Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
45528e38 DB |
2 | /* |
3 | * linux/arch/arm/mach-sa1100/gpio.c | |
4 | * | |
5 | * Generic SA-1100 GPIO handling | |
45528e38 | 6 | */ |
827fb6af | 7 | #include <linux/gpio/driver.h> |
45528e38 DB |
8 | #include <linux/init.h> |
9 | #include <linux/module.h> | |
40ca061b | 10 | #include <linux/io.h> |
a0ea298d | 11 | #include <linux/syscore_ops.h> |
9dd4819e | 12 | #include <soc/sa1100/pwer.h> |
a09e64fb | 13 | #include <mach/hardware.h> |
f314f33b | 14 | #include <mach/irqs.h> |
45528e38 | 15 | |
07242b24 RK |
16 | struct sa1100_gpio_chip { |
17 | struct gpio_chip chip; | |
18 | void __iomem *membase; | |
19 | int irqbase; | |
20 | u32 irqmask; | |
21 | u32 irqrising; | |
22 | u32 irqfalling; | |
23 | u32 irqwake; | |
24 | }; | |
25 | ||
26 | #define sa1100_gpio_chip(x) container_of(x, struct sa1100_gpio_chip, chip) | |
27 | ||
28 | enum { | |
29 | R_GPLR = 0x00, | |
30 | R_GPDR = 0x04, | |
31 | R_GPSR = 0x08, | |
32 | R_GPCR = 0x0c, | |
33 | R_GRER = 0x10, | |
34 | R_GFER = 0x14, | |
35 | R_GEDR = 0x18, | |
36 | R_GAFR = 0x1c, | |
37 | }; | |
38 | ||
45528e38 DB |
39 | static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) |
40 | { | |
07242b24 RK |
41 | return readl_relaxed(sa1100_gpio_chip(chip)->membase + R_GPLR) & |
42 | BIT(offset); | |
45528e38 DB |
43 | } |
44 | ||
45 | static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |
46 | { | |
07242b24 RK |
47 | int reg = value ? R_GPSR : R_GPCR; |
48 | ||
49 | writel_relaxed(BIT(offset), sa1100_gpio_chip(chip)->membase + reg); | |
45528e38 DB |
50 | } |
51 | ||
c65d1fd3 RK |
52 | static int sa1100_get_direction(struct gpio_chip *chip, unsigned offset) |
53 | { | |
54 | void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; | |
55 | ||
56 | return !(readl_relaxed(gpdr) & BIT(offset)); | |
57 | } | |
58 | ||
45528e38 DB |
59 | static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) |
60 | { | |
07242b24 | 61 | void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; |
45528e38 DB |
62 | unsigned long flags; |
63 | ||
64 | local_irq_save(flags); | |
07242b24 | 65 | writel_relaxed(readl_relaxed(gpdr) & ~BIT(offset), gpdr); |
45528e38 | 66 | local_irq_restore(flags); |
07242b24 | 67 | |
45528e38 DB |
68 | return 0; |
69 | } | |
70 | ||
71 | static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value) | |
72 | { | |
07242b24 | 73 | void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; |
45528e38 DB |
74 | unsigned long flags; |
75 | ||
76 | local_irq_save(flags); | |
77 | sa1100_gpio_set(chip, offset, value); | |
07242b24 | 78 | writel_relaxed(readl_relaxed(gpdr) | BIT(offset), gpdr); |
45528e38 | 79 | local_irq_restore(flags); |
07242b24 | 80 | |
45528e38 DB |
81 | return 0; |
82 | } | |
83 | ||
f408c985 RK |
84 | static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset) |
85 | { | |
07242b24 | 86 | return sa1100_gpio_chip(chip)->irqbase + offset; |
f408c985 RK |
87 | } |
88 | ||
07242b24 RK |
89 | static struct sa1100_gpio_chip sa1100_gpio_chip = { |
90 | .chip = { | |
91 | .label = "gpio", | |
c65d1fd3 | 92 | .get_direction = sa1100_get_direction, |
07242b24 RK |
93 | .direction_input = sa1100_direction_input, |
94 | .direction_output = sa1100_direction_output, | |
95 | .set = sa1100_gpio_set, | |
96 | .get = sa1100_gpio_get, | |
97 | .to_irq = sa1100_to_irq, | |
98 | .base = 0, | |
99 | .ngpio = GPIO_MAX + 1, | |
100 | }, | |
101 | .membase = (void *)&GPLR, | |
102 | .irqbase = IRQ_GPIO0, | |
45528e38 DB |
103 | }; |
104 | ||
a0ea298d DES |
105 | /* |
106 | * SA1100 GPIO edge detection for IRQs: | |
107 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. | |
108 | * Use this instead of directly setting GRER/GFER. | |
109 | */ | |
07242b24 RK |
110 | static void sa1100_update_edge_regs(struct sa1100_gpio_chip *sgc) |
111 | { | |
112 | void *base = sgc->membase; | |
113 | u32 grer, gfer; | |
114 | ||
115 | grer = sgc->irqrising & sgc->irqmask; | |
116 | gfer = sgc->irqfalling & sgc->irqmask; | |
117 | ||
118 | writel_relaxed(grer, base + R_GRER); | |
119 | writel_relaxed(gfer, base + R_GFER); | |
120 | } | |
a0ea298d DES |
121 | |
122 | static int sa1100_gpio_type(struct irq_data *d, unsigned int type) | |
123 | { | |
07242b24 RK |
124 | struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); |
125 | unsigned int mask = BIT(d->hwirq); | |
a0ea298d DES |
126 | |
127 | if (type == IRQ_TYPE_PROBE) { | |
07242b24 | 128 | if ((sgc->irqrising | sgc->irqfalling) & mask) |
a0ea298d DES |
129 | return 0; |
130 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | |
131 | } | |
132 | ||
133 | if (type & IRQ_TYPE_EDGE_RISING) | |
07242b24 | 134 | sgc->irqrising |= mask; |
a0ea298d | 135 | else |
07242b24 | 136 | sgc->irqrising &= ~mask; |
a0ea298d | 137 | if (type & IRQ_TYPE_EDGE_FALLING) |
07242b24 | 138 | sgc->irqfalling |= mask; |
a0ea298d | 139 | else |
07242b24 | 140 | sgc->irqfalling &= ~mask; |
a0ea298d | 141 | |
07242b24 | 142 | sa1100_update_edge_regs(sgc); |
a0ea298d DES |
143 | |
144 | return 0; | |
145 | } | |
146 | ||
147 | /* | |
148 | * GPIO IRQs must be acknowledged. | |
149 | */ | |
150 | static void sa1100_gpio_ack(struct irq_data *d) | |
151 | { | |
07242b24 RK |
152 | struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); |
153 | ||
154 | writel_relaxed(BIT(d->hwirq), sgc->membase + R_GEDR); | |
a0ea298d DES |
155 | } |
156 | ||
157 | static void sa1100_gpio_mask(struct irq_data *d) | |
158 | { | |
07242b24 | 159 | struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); |
a0ea298d DES |
160 | unsigned int mask = BIT(d->hwirq); |
161 | ||
07242b24 | 162 | sgc->irqmask &= ~mask; |
a0ea298d | 163 | |
07242b24 | 164 | sa1100_update_edge_regs(sgc); |
a0ea298d DES |
165 | } |
166 | ||
167 | static void sa1100_gpio_unmask(struct irq_data *d) | |
168 | { | |
07242b24 | 169 | struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); |
a0ea298d DES |
170 | unsigned int mask = BIT(d->hwirq); |
171 | ||
07242b24 | 172 | sgc->irqmask |= mask; |
a0ea298d | 173 | |
07242b24 | 174 | sa1100_update_edge_regs(sgc); |
a0ea298d DES |
175 | } |
176 | ||
177 | static int sa1100_gpio_wake(struct irq_data *d, unsigned int on) | |
178 | { | |
07242b24 | 179 | struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); |
9dd4819e RK |
180 | int ret = sa11x0_gpio_set_wake(d->hwirq, on); |
181 | if (!ret) { | |
182 | if (on) | |
07242b24 | 183 | sgc->irqwake |= BIT(d->hwirq); |
9dd4819e | 184 | else |
07242b24 | 185 | sgc->irqwake &= ~BIT(d->hwirq); |
9dd4819e RK |
186 | } |
187 | return ret; | |
a0ea298d DES |
188 | } |
189 | ||
190 | /* | |
191 | * This is for GPIO IRQs | |
192 | */ | |
193 | static struct irq_chip sa1100_gpio_irq_chip = { | |
194 | .name = "GPIO", | |
195 | .irq_ack = sa1100_gpio_ack, | |
196 | .irq_mask = sa1100_gpio_mask, | |
197 | .irq_unmask = sa1100_gpio_unmask, | |
198 | .irq_set_type = sa1100_gpio_type, | |
199 | .irq_set_wake = sa1100_gpio_wake, | |
200 | }; | |
201 | ||
202 | static int sa1100_gpio_irqdomain_map(struct irq_domain *d, | |
203 | unsigned int irq, irq_hw_number_t hwirq) | |
204 | { | |
07242b24 RK |
205 | struct sa1100_gpio_chip *sgc = d->host_data; |
206 | ||
207 | irq_set_chip_data(irq, sgc); | |
208 | irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, handle_edge_irq); | |
56beac95 | 209 | irq_set_probe(irq); |
a0ea298d DES |
210 | |
211 | return 0; | |
212 | } | |
213 | ||
0b354dc4 | 214 | static const struct irq_domain_ops sa1100_gpio_irqdomain_ops = { |
a0ea298d DES |
215 | .map = sa1100_gpio_irqdomain_map, |
216 | .xlate = irq_domain_xlate_onetwocell, | |
217 | }; | |
218 | ||
219 | static struct irq_domain *sa1100_gpio_irqdomain; | |
220 | ||
221 | /* | |
222 | * IRQ 0-11 (GPIO) handler. We enter here with the | |
223 | * irq_controller_lock held, and IRQs disabled. Decode the IRQ | |
224 | * and call the handler. | |
225 | */ | |
bd0b9ac4 | 226 | static void sa1100_gpio_handler(struct irq_desc *desc) |
a0ea298d | 227 | { |
07242b24 | 228 | struct sa1100_gpio_chip *sgc = irq_desc_get_handler_data(desc); |
2951a799 | 229 | unsigned int irq, mask; |
07242b24 | 230 | void __iomem *gedr = sgc->membase + R_GEDR; |
a0ea298d | 231 | |
07242b24 | 232 | mask = readl_relaxed(gedr); |
a0ea298d DES |
233 | do { |
234 | /* | |
235 | * clear down all currently active IRQ sources. | |
236 | * We will be processing them all. | |
237 | */ | |
07242b24 | 238 | writel_relaxed(mask, gedr); |
a0ea298d | 239 | |
07242b24 | 240 | irq = sgc->irqbase; |
a0ea298d DES |
241 | do { |
242 | if (mask & 1) | |
243 | generic_handle_irq(irq); | |
244 | mask >>= 1; | |
245 | irq++; | |
246 | } while (mask); | |
247 | ||
07242b24 | 248 | mask = readl_relaxed(gedr); |
a0ea298d DES |
249 | } while (mask); |
250 | } | |
251 | ||
252 | static int sa1100_gpio_suspend(void) | |
253 | { | |
07242b24 RK |
254 | struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip; |
255 | ||
a0ea298d DES |
256 | /* |
257 | * Set the appropriate edges for wakeup. | |
258 | */ | |
07242b24 RK |
259 | writel_relaxed(sgc->irqwake & sgc->irqrising, sgc->membase + R_GRER); |
260 | writel_relaxed(sgc->irqwake & sgc->irqfalling, sgc->membase + R_GFER); | |
a0ea298d DES |
261 | |
262 | /* | |
263 | * Clear any pending GPIO interrupts. | |
264 | */ | |
07242b24 RK |
265 | writel_relaxed(readl_relaxed(sgc->membase + R_GEDR), |
266 | sgc->membase + R_GEDR); | |
a0ea298d DES |
267 | |
268 | return 0; | |
269 | } | |
270 | ||
271 | static void sa1100_gpio_resume(void) | |
272 | { | |
07242b24 | 273 | sa1100_update_edge_regs(&sa1100_gpio_chip); |
a0ea298d DES |
274 | } |
275 | ||
276 | static struct syscore_ops sa1100_gpio_syscore_ops = { | |
277 | .suspend = sa1100_gpio_suspend, | |
278 | .resume = sa1100_gpio_resume, | |
279 | }; | |
280 | ||
281 | static int __init sa1100_gpio_init_devicefs(void) | |
282 | { | |
283 | register_syscore_ops(&sa1100_gpio_syscore_ops); | |
284 | return 0; | |
285 | } | |
286 | ||
287 | device_initcall(sa1100_gpio_init_devicefs); | |
288 | ||
07242b24 RK |
289 | static const int sa1100_gpio_irqs[] __initconst = { |
290 | /* Install handlers for GPIO 0-10 edge detect interrupts */ | |
291 | IRQ_GPIO0_SC, | |
292 | IRQ_GPIO1_SC, | |
293 | IRQ_GPIO2_SC, | |
294 | IRQ_GPIO3_SC, | |
295 | IRQ_GPIO4_SC, | |
296 | IRQ_GPIO5_SC, | |
297 | IRQ_GPIO6_SC, | |
298 | IRQ_GPIO7_SC, | |
299 | IRQ_GPIO8_SC, | |
300 | IRQ_GPIO9_SC, | |
301 | IRQ_GPIO10_SC, | |
302 | /* Install handler for GPIO 11-27 edge detect interrupts */ | |
303 | IRQ_GPIO11_27, | |
304 | }; | |
305 | ||
45528e38 DB |
306 | void __init sa1100_init_gpio(void) |
307 | { | |
07242b24 RK |
308 | struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip; |
309 | int i; | |
310 | ||
a0ea298d | 311 | /* clear all GPIO edge detects */ |
07242b24 RK |
312 | writel_relaxed(0, sgc->membase + R_GFER); |
313 | writel_relaxed(0, sgc->membase + R_GRER); | |
314 | writel_relaxed(-1, sgc->membase + R_GEDR); | |
a0ea298d | 315 | |
07242b24 | 316 | gpiochip_add_data(&sa1100_gpio_chip.chip, NULL); |
a0ea298d DES |
317 | |
318 | sa1100_gpio_irqdomain = irq_domain_add_simple(NULL, | |
319 | 28, IRQ_GPIO0, | |
07242b24 | 320 | &sa1100_gpio_irqdomain_ops, sgc); |
a0ea298d | 321 | |
07242b24 RK |
322 | for (i = 0; i < ARRAY_SIZE(sa1100_gpio_irqs); i++) |
323 | irq_set_chained_handler_and_data(sa1100_gpio_irqs[i], | |
324 | sa1100_gpio_handler, sgc); | |
45528e38 | 325 | } |