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 
psw_irq_handler(int irq,void * arg)17 static 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 
40 out:
41 	/* Clear the switch IRQs */
42 	__raw_writeb(0x00, PA_PWRINT_CLR);
43 
44 	return IRQ_RETVAL(ret);
45 }
46 
47 static struct resource psw_power_resources[] = {
48 	[0] = {
49 		.start = IRQ_POWER,
50 		.flags = IORESOURCE_IRQ,
51        },
52 };
53 
54 static struct resource psw_usl5p_resources[] = {
55 	[0] = {
56 		.start = IRQ_BUTTON,
57 		.flags = IORESOURCE_IRQ,
58 	},
59 };
60 
61 static 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 
68 static 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 
75 static 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 
82 static 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 
89 static 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 
99 static 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 
109 static 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 
119 static 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 
129 static struct platform_device *psw_devices[] = {
130 	&psw_power_switch_device,
131 	&psw1_switch_device,
132 	&psw2_switch_device,
133 	&psw3_switch_device,
134 };
135 
psw_init(void)136 static int __init psw_init(void)
137 {
138 	return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
139 }
140 device_initcall(psw_init);
141