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 | |
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(timer: &psw->debounce, expires: jiffies + 50); |
37 | ret = 1; |
38 | } |
39 | |
40 | out: |
41 | /* Clear the switch IRQs */ |
42 | __raw_writeb(val: 0x00, addr: 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 | |
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 | |