1// SPDX-License-Identifier: GPL-2.0
2/*
3 * arch/sh/boards/landisk/psw.c
4 *
5 * push switch support for LANDISK and USL-5P
6 *
7 * Copyright (C) 2006-2007  Paul Mundt
8 * Copyright (C) 2007  kogiidena
9 */
10#include <linux/io.h>
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/platform_device.h>
14#include <mach-landisk/mach/iodata_landisk.h>
15#include <asm/push-switch.h>
16
17static irqreturn_t psw_irq_handler(int irq, void *arg)
18{
19	struct platform_device *pdev = arg;
20	struct push_switch *psw = platform_get_drvdata(pdev);
21	struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
22	unsigned int sw_value;
23	int ret = 0;
24
25	sw_value = (0x0ff & (~__raw_readb(PA_STATUS)));
26
27	/* Nothing to do if there's no state change */
28	if (psw->state) {
29		ret = 1;
30		goto out;
31	}
32
33	/* Figure out who raised it */
34	if (sw_value & (1 << psw_info->bit)) {
35		psw->state = 1;
36		mod_timer(&psw->debounce, jiffies + 50);
37		ret = 1;
38	}
39
40out:
41	/* Clear the switch IRQs */
42	__raw_writeb(0x00, PA_PWRINT_CLR);
43
44	return IRQ_RETVAL(ret);
45}
46
47static struct resource psw_power_resources[] = {
48	[0] = {
49		.start = IRQ_POWER,
50		.flags = IORESOURCE_IRQ,
51       },
52};
53
54static struct resource psw_usl5p_resources[] = {
55	[0] = {
56		.start = IRQ_BUTTON,
57		.flags = IORESOURCE_IRQ,
58	},
59};
60
61static struct push_switch_platform_info psw_power_platform_data = {
62	.name		= "psw_power",
63	.bit		= 4,
64	.irq_flags	= IRQF_SHARED,
65	.irq_handler	= psw_irq_handler,
66};
67
68static struct push_switch_platform_info psw1_platform_data = {
69	.name		= "psw1",
70	.bit		= 0,
71	.irq_flags	= IRQF_SHARED,
72	.irq_handler	= psw_irq_handler,
73};
74
75static struct push_switch_platform_info psw2_platform_data = {
76	.name		= "psw2",
77	.bit		= 2,
78	.irq_flags	= IRQF_SHARED,
79	.irq_handler	= psw_irq_handler,
80};
81
82static struct push_switch_platform_info psw3_platform_data = {
83	.name		= "psw3",
84	.bit		= 1,
85	.irq_flags	= IRQF_SHARED,
86	.irq_handler	= psw_irq_handler,
87};
88
89static struct platform_device psw_power_switch_device = {
90	.name		= "push-switch",
91	.id		= 0,
92	.num_resources	= ARRAY_SIZE(psw_power_resources),
93	.resource	= psw_power_resources,
94	.dev		= {
95		.platform_data = &psw_power_platform_data,
96	},
97};
98
99static struct platform_device psw1_switch_device = {
100	.name		= "push-switch",
101	.id		= 1,
102	.num_resources	= ARRAY_SIZE(psw_usl5p_resources),
103	.resource	= psw_usl5p_resources,
104	.dev		= {
105		.platform_data = &psw1_platform_data,
106	},
107};
108
109static struct platform_device psw2_switch_device = {
110	.name		= "push-switch",
111	.id		= 2,
112	.num_resources	= ARRAY_SIZE(psw_usl5p_resources),
113	.resource	= psw_usl5p_resources,
114	.dev		= {
115		.platform_data = &psw2_platform_data,
116	},
117};
118
119static struct platform_device psw3_switch_device = {
120	.name		= "push-switch",
121	.id		= 3,
122	.num_resources	= ARRAY_SIZE(psw_usl5p_resources),
123	.resource	= psw_usl5p_resources,
124	.dev = {
125		.platform_data = &psw3_platform_data,
126	},
127};
128
129static struct platform_device *psw_devices[] = {
130	&psw_power_switch_device,
131	&psw1_switch_device,
132	&psw2_switch_device,
133	&psw3_switch_device,
134};
135
136static int __init psw_init(void)
137{
138	return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
139}
140device_initcall(psw_init);
141