1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * GPIO driver for the IP block found in the Nomadik SoC; it is an AMBA device, |
4 | * managing 32 pins with alternate functions. It can also handle the STA2X11 |
5 | * block from ST. |
6 | * |
7 | * The GPIO chips are shared with pinctrl-nomadik if used; it needs access for |
8 | * pinmuxing functionality and others. |
9 | * |
10 | * This driver also handles the mobileye,eyeq5-gpio compatible. It is an STA2X11 |
11 | * but with only data, direction and interrupts register active. We want to |
12 | * avoid touching SLPM, RWIMSC, FWIMSC, AFSLA and AFSLB registers; that is, |
13 | * wake and alternate function registers. It is NOT compatible with |
14 | * pinctrl-nomadik. |
15 | * |
16 | * Copyright (C) 2008,2009 STMicroelectronics |
17 | * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> |
18 | * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> |
19 | * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org> |
20 | */ |
21 | #include <linux/cleanup.h> |
22 | #include <linux/clk.h> |
23 | #include <linux/gpio/driver.h> |
24 | #include <linux/interrupt.h> |
25 | #include <linux/kernel.h> |
26 | #include <linux/mod_devicetable.h> |
27 | #include <linux/pinctrl/pinctrl.h> |
28 | #include <linux/platform_device.h> |
29 | #include <linux/property.h> |
30 | #include <linux/reset.h> |
31 | #include <linux/seq_file.h> |
32 | #include <linux/slab.h> |
33 | #include <linux/types.h> |
34 | |
35 | #include <linux/gpio/gpio-nomadik.h> |
36 | |
37 | #ifndef CONFIG_PINCTRL_NOMADIK |
38 | static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); |
39 | #endif |
40 | |
41 | void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, unsigned int offset, |
42 | enum nmk_gpio_slpm mode) |
43 | { |
44 | u32 slpm; |
45 | |
46 | /* We should NOT have been called. */ |
47 | if (WARN_ON(nmk_chip->is_mobileye_soc)) |
48 | return; |
49 | |
50 | slpm = readl(addr: nmk_chip->addr + NMK_GPIO_SLPC); |
51 | if (mode == NMK_GPIO_SLPM_NOCHANGE) |
52 | slpm |= BIT(offset); |
53 | else |
54 | slpm &= ~BIT(offset); |
55 | writel(val: slpm, addr: nmk_chip->addr + NMK_GPIO_SLPC); |
56 | } |
57 | |
58 | static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip, |
59 | unsigned int offset, int val) |
60 | { |
61 | if (val) |
62 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DATS); |
63 | else |
64 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DATC); |
65 | } |
66 | |
67 | void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, |
68 | unsigned int offset, int val) |
69 | { |
70 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DIRS); |
71 | __nmk_gpio_set_output(nmk_chip, offset, val); |
72 | } |
73 | |
74 | /* IRQ functions */ |
75 | |
76 | static void nmk_gpio_irq_ack(struct irq_data *d) |
77 | { |
78 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
79 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
80 | |
81 | clk_enable(clk: nmk_chip->clk); |
82 | writel(BIT(d->hwirq), addr: nmk_chip->addr + NMK_GPIO_IC); |
83 | clk_disable(clk: nmk_chip->clk); |
84 | } |
85 | |
86 | enum nmk_gpio_irq_type { |
87 | NORMAL, |
88 | WAKE, |
89 | }; |
90 | |
91 | static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, |
92 | int offset, enum nmk_gpio_irq_type which, |
93 | bool enable) |
94 | { |
95 | u32 *rimscval; |
96 | u32 *fimscval; |
97 | u32 rimscreg; |
98 | u32 fimscreg; |
99 | |
100 | if (which == NORMAL) { |
101 | rimscreg = NMK_GPIO_RIMSC; |
102 | fimscreg = NMK_GPIO_FIMSC; |
103 | rimscval = &nmk_chip->rimsc; |
104 | fimscval = &nmk_chip->fimsc; |
105 | } else { |
106 | /* We should NOT have been called. */ |
107 | if (WARN_ON(nmk_chip->is_mobileye_soc)) |
108 | return; |
109 | rimscreg = NMK_GPIO_RWIMSC; |
110 | fimscreg = NMK_GPIO_FWIMSC; |
111 | rimscval = &nmk_chip->rwimsc; |
112 | fimscval = &nmk_chip->fwimsc; |
113 | } |
114 | |
115 | /* we must individually set/clear the two edges */ |
116 | if (nmk_chip->edge_rising & BIT(offset)) { |
117 | if (enable) |
118 | *rimscval |= BIT(offset); |
119 | else |
120 | *rimscval &= ~BIT(offset); |
121 | writel(val: *rimscval, addr: nmk_chip->addr + rimscreg); |
122 | } |
123 | if (nmk_chip->edge_falling & BIT(offset)) { |
124 | if (enable) |
125 | *fimscval |= BIT(offset); |
126 | else |
127 | *fimscval &= ~BIT(offset); |
128 | writel(val: *fimscval, addr: nmk_chip->addr + fimscreg); |
129 | } |
130 | } |
131 | |
132 | static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, |
133 | int offset, bool on) |
134 | { |
135 | /* We should NOT have been called. */ |
136 | if (WARN_ON(nmk_chip->is_mobileye_soc)) |
137 | return; |
138 | |
139 | /* |
140 | * Ensure WAKEUP_ENABLE is on. No need to disable it if wakeup is |
141 | * disabled, since setting SLPM to 1 increases power consumption, and |
142 | * wakeup is anyhow controlled by the RIMSC and FIMSC registers. |
143 | */ |
144 | if (nmk_chip->sleepmode && on) { |
145 | __nmk_gpio_set_slpm(nmk_chip, offset, |
146 | mode: NMK_GPIO_SLPM_WAKEUP_ENABLE); |
147 | } |
148 | |
149 | __nmk_gpio_irq_modify(nmk_chip, offset, which: WAKE, enable: on); |
150 | } |
151 | |
152 | static void nmk_gpio_irq_maskunmask(struct nmk_gpio_chip *nmk_chip, |
153 | struct irq_data *d, bool enable) |
154 | { |
155 | unsigned long flags; |
156 | |
157 | clk_enable(clk: nmk_chip->clk); |
158 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
159 | spin_lock(lock: &nmk_chip->lock); |
160 | |
161 | __nmk_gpio_irq_modify(nmk_chip, offset: d->hwirq, which: NORMAL, enable); |
162 | |
163 | if (!nmk_chip->is_mobileye_soc && !(nmk_chip->real_wake & BIT(d->hwirq))) |
164 | __nmk_gpio_set_wake(nmk_chip, offset: d->hwirq, on: enable); |
165 | |
166 | spin_unlock(lock: &nmk_chip->lock); |
167 | spin_unlock_irqrestore(lock: &nmk_gpio_slpm_lock, flags); |
168 | clk_disable(clk: nmk_chip->clk); |
169 | } |
170 | |
171 | static void nmk_gpio_irq_mask(struct irq_data *d) |
172 | { |
173 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
174 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
175 | |
176 | nmk_gpio_irq_maskunmask(nmk_chip, d, enable: false); |
177 | gpiochip_disable_irq(gc, offset: irqd_to_hwirq(d)); |
178 | } |
179 | |
180 | static void nmk_gpio_irq_unmask(struct irq_data *d) |
181 | { |
182 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
183 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
184 | |
185 | gpiochip_enable_irq(gc, offset: irqd_to_hwirq(d)); |
186 | nmk_gpio_irq_maskunmask(nmk_chip, d, enable: true); |
187 | } |
188 | |
189 | static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) |
190 | { |
191 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
192 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
193 | unsigned long flags; |
194 | |
195 | /* Handler is registered in all cases. */ |
196 | if (nmk_chip->is_mobileye_soc) |
197 | return -ENXIO; |
198 | |
199 | clk_enable(clk: nmk_chip->clk); |
200 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
201 | spin_lock(lock: &nmk_chip->lock); |
202 | |
203 | if (irqd_irq_disabled(d)) |
204 | __nmk_gpio_set_wake(nmk_chip, offset: d->hwirq, on); |
205 | |
206 | if (on) |
207 | nmk_chip->real_wake |= BIT(d->hwirq); |
208 | else |
209 | nmk_chip->real_wake &= ~BIT(d->hwirq); |
210 | |
211 | spin_unlock(lock: &nmk_chip->lock); |
212 | spin_unlock_irqrestore(lock: &nmk_gpio_slpm_lock, flags); |
213 | clk_disable(clk: nmk_chip->clk); |
214 | |
215 | return 0; |
216 | } |
217 | |
218 | static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
219 | { |
220 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
221 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
222 | bool enabled = !irqd_irq_disabled(d); |
223 | bool wake = irqd_is_wakeup_set(d); |
224 | unsigned long flags; |
225 | |
226 | if (type & IRQ_TYPE_LEVEL_HIGH) |
227 | return -EINVAL; |
228 | if (type & IRQ_TYPE_LEVEL_LOW) |
229 | return -EINVAL; |
230 | |
231 | clk_enable(clk: nmk_chip->clk); |
232 | spin_lock_irqsave(&nmk_chip->lock, flags); |
233 | |
234 | if (enabled) |
235 | __nmk_gpio_irq_modify(nmk_chip, offset: d->hwirq, which: NORMAL, enable: false); |
236 | |
237 | if (!nmk_chip->is_mobileye_soc && (enabled || wake)) |
238 | __nmk_gpio_irq_modify(nmk_chip, offset: d->hwirq, which: WAKE, enable: false); |
239 | |
240 | nmk_chip->edge_rising &= ~BIT(d->hwirq); |
241 | if (type & IRQ_TYPE_EDGE_RISING) |
242 | nmk_chip->edge_rising |= BIT(d->hwirq); |
243 | |
244 | nmk_chip->edge_falling &= ~BIT(d->hwirq); |
245 | if (type & IRQ_TYPE_EDGE_FALLING) |
246 | nmk_chip->edge_falling |= BIT(d->hwirq); |
247 | |
248 | if (enabled) |
249 | __nmk_gpio_irq_modify(nmk_chip, offset: d->hwirq, which: NORMAL, enable: true); |
250 | |
251 | if (!nmk_chip->is_mobileye_soc && (enabled || wake)) |
252 | __nmk_gpio_irq_modify(nmk_chip, offset: d->hwirq, which: WAKE, enable: true); |
253 | |
254 | spin_unlock_irqrestore(lock: &nmk_chip->lock, flags); |
255 | clk_disable(clk: nmk_chip->clk); |
256 | |
257 | return 0; |
258 | } |
259 | |
260 | static unsigned int nmk_gpio_irq_startup(struct irq_data *d) |
261 | { |
262 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
263 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
264 | |
265 | clk_enable(clk: nmk_chip->clk); |
266 | nmk_gpio_irq_unmask(d); |
267 | return 0; |
268 | } |
269 | |
270 | static void nmk_gpio_irq_shutdown(struct irq_data *d) |
271 | { |
272 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
273 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
274 | |
275 | nmk_gpio_irq_mask(d); |
276 | clk_disable(clk: nmk_chip->clk); |
277 | } |
278 | |
279 | static irqreturn_t nmk_gpio_irq_handler(int irq, void *dev_id) |
280 | { |
281 | struct nmk_gpio_chip *nmk_chip = dev_id; |
282 | struct gpio_chip *chip = &nmk_chip->chip; |
283 | unsigned long mask = GENMASK(chip->ngpio - 1, 0); |
284 | unsigned long status; |
285 | int bit; |
286 | |
287 | clk_enable(clk: nmk_chip->clk); |
288 | |
289 | status = readl(addr: nmk_chip->addr + NMK_GPIO_IS); |
290 | |
291 | /* Ensure we cannot leave pending bits; this should never occur. */ |
292 | if (unlikely(status & ~mask)) |
293 | writel(val: status & ~mask, addr: nmk_chip->addr + NMK_GPIO_IC); |
294 | |
295 | clk_disable(clk: nmk_chip->clk); |
296 | |
297 | for_each_set_bit(bit, &status, chip->ngpio) |
298 | generic_handle_domain_irq_safe(domain: chip->irq.domain, hwirq: bit); |
299 | |
300 | return IRQ_RETVAL((status & mask) != 0); |
301 | } |
302 | |
303 | /* I/O Functions */ |
304 | |
305 | static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned int offset) |
306 | { |
307 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc: chip); |
308 | int dir; |
309 | |
310 | clk_enable(clk: nmk_chip->clk); |
311 | |
312 | dir = readl(addr: nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset); |
313 | |
314 | clk_disable(clk: nmk_chip->clk); |
315 | |
316 | if (dir) |
317 | return GPIO_LINE_DIRECTION_OUT; |
318 | |
319 | return GPIO_LINE_DIRECTION_IN; |
320 | } |
321 | |
322 | static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned int offset) |
323 | { |
324 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc: chip); |
325 | |
326 | clk_enable(clk: nmk_chip->clk); |
327 | |
328 | writel(BIT(offset), addr: nmk_chip->addr + NMK_GPIO_DIRC); |
329 | |
330 | clk_disable(clk: nmk_chip->clk); |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned int offset) |
336 | { |
337 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc: chip); |
338 | int value; |
339 | |
340 | clk_enable(clk: nmk_chip->clk); |
341 | |
342 | value = !!(readl(addr: nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset)); |
343 | |
344 | clk_disable(clk: nmk_chip->clk); |
345 | |
346 | return value; |
347 | } |
348 | |
349 | static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned int offset, |
350 | int val) |
351 | { |
352 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc: chip); |
353 | |
354 | clk_enable(clk: nmk_chip->clk); |
355 | |
356 | __nmk_gpio_set_output(nmk_chip, offset, val); |
357 | |
358 | clk_disable(clk: nmk_chip->clk); |
359 | } |
360 | |
361 | static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned int offset, |
362 | int val) |
363 | { |
364 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc: chip); |
365 | |
366 | clk_enable(clk: nmk_chip->clk); |
367 | |
368 | __nmk_gpio_make_output(nmk_chip, offset, val); |
369 | |
370 | clk_disable(clk: nmk_chip->clk); |
371 | |
372 | return 0; |
373 | } |
374 | |
375 | #ifdef CONFIG_DEBUG_FS |
376 | |
377 | static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset) |
378 | { |
379 | u32 afunc, bfunc; |
380 | |
381 | /* We don't support modes. */ |
382 | if (nmk_chip->is_mobileye_soc) |
383 | return NMK_GPIO_ALT_GPIO; |
384 | |
385 | clk_enable(clk: nmk_chip->clk); |
386 | |
387 | afunc = readl(addr: nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset); |
388 | bfunc = readl(addr: nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset); |
389 | |
390 | clk_disable(clk: nmk_chip->clk); |
391 | |
392 | return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); |
393 | } |
394 | |
395 | void nmk_gpio_dbg_show_one(struct seq_file *s, struct pinctrl_dev *pctldev, |
396 | struct gpio_chip *chip, unsigned int offset, |
397 | unsigned int gpio) |
398 | { |
399 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc: chip); |
400 | int mode; |
401 | bool is_out; |
402 | bool data_out; |
403 | bool pull; |
404 | static const char * const modes[] = { |
405 | [NMK_GPIO_ALT_GPIO] = "gpio" , |
406 | [NMK_GPIO_ALT_A] = "altA" , |
407 | [NMK_GPIO_ALT_B] = "altB" , |
408 | [NMK_GPIO_ALT_C] = "altC" , |
409 | [NMK_GPIO_ALT_C + 1] = "altC1" , |
410 | [NMK_GPIO_ALT_C + 2] = "altC2" , |
411 | [NMK_GPIO_ALT_C + 3] = "altC3" , |
412 | [NMK_GPIO_ALT_C + 4] = "altC4" , |
413 | }; |
414 | |
415 | char *label = gpiochip_dup_line_label(gc: chip, offset); |
416 | if (IS_ERR(ptr: label)) |
417 | return; |
418 | |
419 | clk_enable(clk: nmk_chip->clk); |
420 | is_out = !!(readl(addr: nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset)); |
421 | pull = !(readl(addr: nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset)); |
422 | data_out = !!(readl(addr: nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset)); |
423 | mode = nmk_gpio_get_mode(nmk_chip, offset); |
424 | #ifdef CONFIG_PINCTRL_NOMADIK |
425 | if (mode == NMK_GPIO_ALT_C && pctldev) |
426 | mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio); |
427 | #endif |
428 | |
429 | if (is_out) { |
430 | seq_printf(m: s, fmt: " gpio-%-3d (%-20.20s) out %s %s" , |
431 | gpio, |
432 | label ?: "(none)" , |
433 | data_out ? "hi" : "lo" , |
434 | (mode < 0) ? "unknown" : modes[mode]); |
435 | } else { |
436 | int irq = chip->to_irq(chip, offset); |
437 | const int pullidx = pull ? 1 : 0; |
438 | int val; |
439 | static const char * const pulls[] = { |
440 | "none " , |
441 | "pull enabled" , |
442 | }; |
443 | |
444 | seq_printf(m: s, fmt: " gpio-%-3d (%-20.20s) in %s %s" , |
445 | gpio, |
446 | label ?: "(none)" , |
447 | pulls[pullidx], |
448 | (mode < 0) ? "unknown" : modes[mode]); |
449 | |
450 | val = nmk_gpio_get_input(chip, offset); |
451 | seq_printf(m: s, fmt: " VAL %d" , val); |
452 | |
453 | /* |
454 | * This races with request_irq(), set_irq_type(), |
455 | * and set_irq_wake() ... but those are "rare". |
456 | */ |
457 | if (irq > 0 && irq_has_action(irq)) { |
458 | char *trigger; |
459 | bool wake; |
460 | |
461 | if (nmk_chip->edge_rising & BIT(offset)) |
462 | trigger = "edge-rising" ; |
463 | else if (nmk_chip->edge_falling & BIT(offset)) |
464 | trigger = "edge-falling" ; |
465 | else |
466 | trigger = "edge-undefined" ; |
467 | |
468 | wake = !!(nmk_chip->real_wake & BIT(offset)); |
469 | |
470 | seq_printf(m: s, fmt: " irq-%d %s%s" , |
471 | irq, trigger, wake ? " wakeup" : "" ); |
472 | } |
473 | } |
474 | clk_disable(clk: nmk_chip->clk); |
475 | } |
476 | |
477 | static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
478 | { |
479 | unsigned int i, gpio = chip->base; |
480 | |
481 | for (i = 0; i < chip->ngpio; i++, gpio++) { |
482 | nmk_gpio_dbg_show_one(s, NULL, chip, offset: i, gpio); |
483 | seq_puts(m: s, s: "\n" ); |
484 | } |
485 | } |
486 | |
487 | #else |
488 | |
489 | #define nmk_gpio_dbg_show NULL |
490 | |
491 | #endif |
492 | |
493 | /* |
494 | * We will allocate memory for the state container using devm* allocators |
495 | * binding to the first device reaching this point, it doesn't matter if |
496 | * it is the pin controller or GPIO driver. However we need to use the right |
497 | * platform device when looking up resources so pay attention to pdev. |
498 | */ |
499 | struct nmk_gpio_chip *nmk_gpio_populate_chip(struct fwnode_handle *fwnode, |
500 | struct platform_device *pdev) |
501 | { |
502 | struct nmk_gpio_chip *nmk_chip; |
503 | struct platform_device *gpio_pdev; |
504 | struct device *dev = &pdev->dev; |
505 | struct reset_control *reset; |
506 | struct device *gpio_dev; |
507 | struct gpio_chip *chip; |
508 | struct resource *res; |
509 | struct clk *clk; |
510 | void __iomem *base; |
511 | u32 id, ngpio; |
512 | int ret; |
513 | |
514 | gpio_dev = bus_find_device_by_fwnode(bus: &platform_bus_type, fwnode); |
515 | if (!gpio_dev) { |
516 | dev_err(dev, "populate \"%pfwP\": device not found\n" , fwnode); |
517 | return ERR_PTR(error: -ENODEV); |
518 | } |
519 | gpio_pdev = to_platform_device(gpio_dev); |
520 | |
521 | if (device_property_read_u32(dev: gpio_dev, propname: "gpio-bank" , val: &id)) { |
522 | dev_err(dev, "populate: gpio-bank property not found\n" ); |
523 | platform_device_put(pdev: gpio_pdev); |
524 | return ERR_PTR(error: -EINVAL); |
525 | } |
526 | |
527 | #ifdef CONFIG_PINCTRL_NOMADIK |
528 | if (id >= ARRAY_SIZE(nmk_gpio_chips)) { |
529 | dev_err(dev, "populate: invalid id: %u\n" , id); |
530 | platform_device_put(pdev: gpio_pdev); |
531 | return ERR_PTR(error: -EINVAL); |
532 | } |
533 | /* Already populated? */ |
534 | nmk_chip = nmk_gpio_chips[id]; |
535 | if (nmk_chip) { |
536 | platform_device_put(pdev: gpio_pdev); |
537 | return nmk_chip; |
538 | } |
539 | #endif |
540 | |
541 | nmk_chip = devm_kzalloc(dev, size: sizeof(*nmk_chip), GFP_KERNEL); |
542 | if (!nmk_chip) { |
543 | platform_device_put(pdev: gpio_pdev); |
544 | return ERR_PTR(error: -ENOMEM); |
545 | } |
546 | |
547 | if (device_property_read_u32(dev: gpio_dev, propname: "ngpios" , val: &ngpio)) { |
548 | ngpio = NMK_GPIO_PER_CHIP; |
549 | dev_dbg(dev, "populate: using default ngpio (%u)\n" , ngpio); |
550 | } |
551 | |
552 | nmk_chip->is_mobileye_soc = device_is_compatible(dev: gpio_dev, |
553 | compat: "mobileye,eyeq5-gpio" ); |
554 | nmk_chip->bank = id; |
555 | chip = &nmk_chip->chip; |
556 | chip->base = -1; |
557 | chip->ngpio = ngpio; |
558 | chip->label = dev_name(dev: gpio_dev); |
559 | chip->parent = gpio_dev; |
560 | |
561 | /* NOTE: different devices! No devm_platform_ioremap_resource() here! */ |
562 | res = platform_get_resource(gpio_pdev, IORESOURCE_MEM, 0); |
563 | base = devm_ioremap_resource(dev, res); |
564 | if (IS_ERR(ptr: base)) { |
565 | platform_device_put(pdev: gpio_pdev); |
566 | return ERR_CAST(ptr: base); |
567 | } |
568 | nmk_chip->addr = base; |
569 | |
570 | /* NOTE: do not use devm_ here! */ |
571 | clk = clk_get_optional(dev: gpio_dev, NULL); |
572 | if (IS_ERR(ptr: clk)) { |
573 | platform_device_put(pdev: gpio_pdev); |
574 | return ERR_CAST(ptr: clk); |
575 | } |
576 | clk_prepare(clk); |
577 | nmk_chip->clk = clk; |
578 | |
579 | /* NOTE: do not use devm_ here! */ |
580 | reset = reset_control_get_optional_shared(dev: gpio_dev, NULL); |
581 | if (IS_ERR(ptr: reset)) { |
582 | clk_unprepare(clk); |
583 | clk_put(clk); |
584 | platform_device_put(pdev: gpio_pdev); |
585 | dev_err(dev, "failed getting reset control: %pe\n" , |
586 | reset); |
587 | return ERR_CAST(ptr: reset); |
588 | } |
589 | |
590 | /* |
591 | * Reset might be shared and asserts/deasserts calls are unbalanced. We |
592 | * only support sharing this reset with other gpio-nomadik devices that |
593 | * use this reset to ensure deassertion at probe. |
594 | */ |
595 | ret = reset_control_deassert(rstc: reset); |
596 | if (ret) { |
597 | reset_control_put(rstc: reset); |
598 | clk_unprepare(clk); |
599 | clk_put(clk); |
600 | platform_device_put(pdev: gpio_pdev); |
601 | dev_err(dev, "failed reset deassert: %d\n" , ret); |
602 | return ERR_PTR(error: ret); |
603 | } |
604 | |
605 | #ifdef CONFIG_PINCTRL_NOMADIK |
606 | nmk_gpio_chips[id] = nmk_chip; |
607 | #endif |
608 | return nmk_chip; |
609 | } |
610 | |
611 | static void nmk_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) |
612 | { |
613 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
614 | struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(gc); |
615 | |
616 | seq_printf(m: p, fmt: "nmk%u-%u-%u" , nmk_chip->bank, |
617 | gc->base, gc->base + gc->ngpio - 1); |
618 | } |
619 | |
620 | static const struct irq_chip nmk_irq_chip = { |
621 | .irq_ack = nmk_gpio_irq_ack, |
622 | .irq_mask = nmk_gpio_irq_mask, |
623 | .irq_unmask = nmk_gpio_irq_unmask, |
624 | .irq_set_type = nmk_gpio_irq_set_type, |
625 | .irq_set_wake = nmk_gpio_irq_set_wake, |
626 | .irq_startup = nmk_gpio_irq_startup, |
627 | .irq_shutdown = nmk_gpio_irq_shutdown, |
628 | .irq_print_chip = nmk_gpio_irq_print_chip, |
629 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, |
630 | GPIOCHIP_IRQ_RESOURCE_HELPERS, |
631 | }; |
632 | |
633 | static int nmk_gpio_probe(struct platform_device *pdev) |
634 | { |
635 | struct device *dev = &pdev->dev; |
636 | struct nmk_gpio_chip *nmk_chip; |
637 | struct gpio_irq_chip *girq; |
638 | bool supports_sleepmode; |
639 | struct gpio_chip *chip; |
640 | int irq; |
641 | int ret; |
642 | |
643 | nmk_chip = nmk_gpio_populate_chip(dev_fwnode(dev), pdev); |
644 | if (IS_ERR(ptr: nmk_chip)) { |
645 | dev_err(dev, "could not populate nmk chip struct\n" ); |
646 | return PTR_ERR(ptr: nmk_chip); |
647 | } |
648 | |
649 | supports_sleepmode = |
650 | device_property_read_bool(dev, propname: "st,supports-sleepmode" ); |
651 | |
652 | /* Correct platform device ID */ |
653 | pdev->id = nmk_chip->bank; |
654 | |
655 | irq = platform_get_irq(pdev, 0); |
656 | if (irq < 0) |
657 | return irq; |
658 | |
659 | /* |
660 | * The virt address in nmk_chip->addr is in the nomadik register space, |
661 | * so we can simply convert the resource address, without remapping |
662 | */ |
663 | nmk_chip->sleepmode = supports_sleepmode; |
664 | spin_lock_init(&nmk_chip->lock); |
665 | |
666 | chip = &nmk_chip->chip; |
667 | chip->parent = dev; |
668 | chip->request = gpiochip_generic_request; |
669 | chip->free = gpiochip_generic_free; |
670 | chip->get_direction = nmk_gpio_get_dir; |
671 | chip->direction_input = nmk_gpio_make_input; |
672 | chip->get = nmk_gpio_get_input; |
673 | chip->direction_output = nmk_gpio_make_output; |
674 | chip->set = nmk_gpio_set_output; |
675 | chip->dbg_show = nmk_gpio_dbg_show; |
676 | chip->can_sleep = false; |
677 | chip->owner = THIS_MODULE; |
678 | |
679 | girq = &chip->irq; |
680 | gpio_irq_chip_set_chip(girq, chip: &nmk_irq_chip); |
681 | girq->parent_handler = NULL; |
682 | girq->num_parents = 0; |
683 | girq->parents = NULL; |
684 | girq->default_type = IRQ_TYPE_NONE; |
685 | girq->handler = handle_edge_irq; |
686 | |
687 | ret = devm_request_irq(dev, irq, handler: nmk_gpio_irq_handler, IRQF_SHARED, |
688 | devname: dev_name(dev), dev_id: nmk_chip); |
689 | if (ret) { |
690 | dev_err(dev, "failed requesting IRQ\n" ); |
691 | return ret; |
692 | } |
693 | |
694 | if (!nmk_chip->is_mobileye_soc) { |
695 | clk_enable(clk: nmk_chip->clk); |
696 | nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); |
697 | clk_disable(clk: nmk_chip->clk); |
698 | } |
699 | |
700 | ret = gpiochip_add_data(chip, nmk_chip); |
701 | if (ret) |
702 | return ret; |
703 | |
704 | platform_set_drvdata(pdev, data: nmk_chip); |
705 | |
706 | dev_info(dev, "chip registered\n" ); |
707 | |
708 | return 0; |
709 | } |
710 | |
711 | static const struct of_device_id nmk_gpio_match[] = { |
712 | { .compatible = "st,nomadik-gpio" , }, |
713 | { .compatible = "mobileye,eyeq5-gpio" , }, |
714 | {} |
715 | }; |
716 | |
717 | static struct platform_driver nmk_gpio_driver = { |
718 | .driver = { |
719 | .name = "nomadik-gpio" , |
720 | .of_match_table = nmk_gpio_match, |
721 | .suppress_bind_attrs = true, |
722 | }, |
723 | .probe = nmk_gpio_probe, |
724 | }; |
725 | |
726 | static int __init nmk_gpio_init(void) |
727 | { |
728 | return platform_driver_register(&nmk_gpio_driver); |
729 | } |
730 | subsys_initcall(nmk_gpio_init); |
731 | |