Commit | Line | Data |
---|---|---|
e9a03add SZ |
1 | /* |
2 | * Pinctrl Driver for ADI GPIO2 controller | |
3 | * | |
4 | * Copyright 2007-2013 Analog Devices Inc. | |
5 | * | |
6 | * Licensed under the GPLv2 or later | |
7 | */ | |
8 | ||
9 | #include <linux/bitops.h> | |
10 | #include <linux/delay.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/err.h> | |
13 | #include <linux/debugfs.h> | |
14 | #include <linux/seq_file.h> | |
15 | #include <linux/irq.h> | |
16 | #include <linux/platform_data/pinctrl-adi2.h> | |
17 | #include <linux/irqdomain.h> | |
18 | #include <linux/irqchip/chained_irq.h> | |
19 | #include <linux/pinctrl/pinctrl.h> | |
20 | #include <linux/pinctrl/pinmux.h> | |
21 | #include <linux/pinctrl/consumer.h> | |
22 | #include <linux/pinctrl/machine.h> | |
23 | #include <linux/syscore_ops.h> | |
24 | #include <linux/gpio.h> | |
25 | #include <asm/portmux.h> | |
26 | #include "pinctrl-adi2.h" | |
27 | #include "core.h" | |
28 | ||
29 | /* | |
30 | According to the BF54x HRM, pint means "pin interrupt". | |
31 | http://www.analog.com/static/imported-files/processor_manuals/ADSP-BF54x_hwr_rev1.2.pdf | |
32 | ||
33 | ADSP-BF54x processor Blackfin processors have four SIC interrupt chan- | |
34 | nels dedicated to pin interrupt purposes. These channels are managed by | |
35 | four hardware blocks, called PINT0, PINT1, PINT2, and PINT3. Every PINTx | |
36 | block can sense to up to 32 pins. While PINT0 and PINT1 can sense the | |
37 | pins of port A and port B, PINT2 and PINT3 manage all the pins from port | |
38 | C to port J as shown in Figure 9-2. | |
39 | ||
40 | n BF54x HRM: | |
41 | The ten GPIO ports are subdivided into 8-bit half ports, resulting in lower and | |
42 | upper half 8-bit units. The PINTx_ASSIGN registers control the 8-bit multi- | |
43 | plexers shown in Figure 9-3. Lower half units of eight pins can be | |
44 | forwarded to either byte 0 or byte 2 of either associated PINTx block. | |
45 | Upper half units can be forwarded to either byte 1 or byte 3 of the pin | |
46 | interrupt blocks, without further restrictions. | |
47 | ||
48 | All MMR registers in the pin interrupt module are 32 bits wide. To simply the | |
49 | mapping logic, this driver only maps a 16-bit gpio port to the upper or lower | |
50 | 16 bits of a PINTx block. You can find the Figure 9-3 on page 583. | |
51 | ||
52 | Each IRQ domain is binding to a GPIO bank device. 2 GPIO bank devices can map | |
53 | to one PINT device. Two in "struct gpio_pint" are used to ease the PINT | |
54 | interrupt handler. | |
55 | ||
56 | The GPIO bank mapping to the lower 16 bits of the PINT device set its IRQ | |
57 | domain pointer in domain[0]. The IRQ domain pointer of the other bank is set | |
58 | to domain[1]. PINT interrupt handler adi_gpio_handle_pint_irq() finds out | |
59 | the current domain pointer according to whether the interrupt request mask | |
60 | is in lower 16 bits (domain[0]) or upper 16bits (domain[1]). | |
61 | ||
62 | A PINT device is not part of a GPIO port device in Blackfin. Multiple GPIO | |
63 | port devices can be mapped to the same PINT device. | |
64 | ||
65 | */ | |
66 | ||
67 | static LIST_HEAD(adi_pint_list); | |
68 | static LIST_HEAD(adi_gpio_port_list); | |
69 | ||
70 | #define DRIVER_NAME "pinctrl-adi2" | |
71 | ||
72 | #define PINT_HI_OFFSET 16 | |
73 | ||
74 | /** | |
75 | * struct gpio_port_saved - GPIO port registers that should be saved between | |
76 | * power suspend and resume operations. | |
77 | * | |
78 | * @fer: PORTx_FER register | |
79 | * @data: PORTx_DATA register | |
80 | * @dir: PORTx_DIR register | |
81 | * @inen: PORTx_INEN register | |
82 | * @mux: PORTx_MUX register | |
83 | */ | |
84 | struct gpio_port_saved { | |
85 | u16 fer; | |
86 | u16 data; | |
87 | u16 dir; | |
88 | u16 inen; | |
89 | u32 mux; | |
90 | }; | |
91 | ||
1e6f8e3c SZ |
92 | /* |
93 | * struct gpio_pint_saved - PINT registers saved in PM operations | |
94 | * | |
95 | * @assign: ASSIGN register | |
96 | * @edge_set: EDGE_SET register | |
97 | * @invert_set: INVERT_SET register | |
98 | */ | |
99 | struct gpio_pint_saved { | |
100 | u32 assign; | |
101 | u32 edge_set; | |
102 | u32 invert_set; | |
103 | }; | |
104 | ||
e9a03add SZ |
105 | /** |
106 | * struct gpio_pint - Pin interrupt controller device. Multiple ADI GPIO | |
107 | * banks can be mapped into one Pin interrupt controller. | |
108 | * | |
109 | * @node: All gpio_pint instances are added to a global list. | |
110 | * @base: PINT device register base address | |
111 | * @irq: IRQ of the PINT device, it is the parent IRQ of all | |
112 | * GPIO IRQs mapping to this device. | |
113 | * @domain: [0] irq domain of the gpio port, whose hardware interrupts are | |
114 | * mapping to the low 16-bit of the pint registers. | |
115 | * [1] irq domain of the gpio port, whose hardware interrupts are | |
116 | * mapping to the high 16-bit of the pint registers. | |
117 | * @regs: address pointer to the PINT device | |
118 | * @map_count: No more than 2 GPIO banks can be mapped to this PINT device. | |
119 | * @lock: This lock make sure the irq_chip operations to one PINT device | |
120 | * for different GPIO interrrupts are atomic. | |
121 | * @pint_map_port: Set up the mapping between one PINT device and | |
122 | * multiple GPIO banks. | |
123 | */ | |
124 | struct gpio_pint { | |
125 | struct list_head node; | |
126 | void __iomem *base; | |
127 | int irq; | |
128 | struct irq_domain *domain[2]; | |
129 | struct gpio_pint_regs *regs; | |
1e6f8e3c | 130 | struct gpio_pint_saved saved_data; |
e9a03add SZ |
131 | int map_count; |
132 | spinlock_t lock; | |
133 | ||
134 | int (*pint_map_port)(struct gpio_pint *pint, bool assign, | |
135 | u8 map, struct irq_domain *domain); | |
136 | }; | |
137 | ||
138 | /** | |
139 | * ADI pin controller | |
140 | * | |
141 | * @dev: a pointer back to containing device | |
142 | * @pctl: the pinctrl device | |
143 | * @soc: SoC data for this specific chip | |
144 | */ | |
145 | struct adi_pinctrl { | |
146 | struct device *dev; | |
147 | struct pinctrl_dev *pctl; | |
148 | const struct adi_pinctrl_soc_data *soc; | |
149 | }; | |
150 | ||
151 | /** | |
152 | * struct gpio_port - GPIO bank device. Multiple ADI GPIO banks can be mapped | |
153 | * into one pin interrupt controller. | |
154 | * | |
155 | * @node: All gpio_port instances are added to a list. | |
156 | * @base: GPIO bank device register base address | |
157 | * @irq_base: base IRQ of the GPIO bank device | |
158 | * @width: PIN number of the GPIO bank device | |
159 | * @regs: address pointer to the GPIO bank device | |
160 | * @saved_data: registers that should be saved between PM operations. | |
161 | * @dev: device structure of this GPIO bank | |
162 | * @pint: GPIO PINT device that this GPIO bank mapped to | |
163 | * @pint_map: GIOP bank mapping code in PINT device | |
164 | * @pint_assign: The 32-bit PINT registers can be divided into 2 parts. A | |
165 | * GPIO bank can be mapped into either low 16 bits[0] or high 16 | |
166 | * bits[1] of each PINT register. | |
167 | * @lock: This lock make sure the irq_chip operations to one PINT device | |
168 | * for different GPIO interrrupts are atomic. | |
169 | * @chip: abstract a GPIO controller | |
170 | * @domain: The irq domain owned by the GPIO port. | |
171 | * @rsvmap: Reservation map array for each pin in the GPIO bank | |
172 | */ | |
173 | struct gpio_port { | |
174 | struct list_head node; | |
175 | void __iomem *base; | |
b4eef7b2 | 176 | int irq_base; |
e9a03add SZ |
177 | unsigned int width; |
178 | struct gpio_port_t *regs; | |
179 | struct gpio_port_saved saved_data; | |
180 | struct device *dev; | |
181 | ||
182 | struct gpio_pint *pint; | |
183 | u8 pint_map; | |
184 | bool pint_assign; | |
185 | ||
186 | spinlock_t lock; | |
187 | struct gpio_chip chip; | |
188 | struct irq_domain *domain; | |
189 | }; | |
190 | ||
191 | static inline u8 pin_to_offset(struct pinctrl_gpio_range *range, unsigned pin) | |
192 | { | |
193 | return pin - range->pin_base; | |
194 | } | |
195 | ||
196 | static inline u32 hwirq_to_pintbit(struct gpio_port *port, int hwirq) | |
197 | { | |
198 | return port->pint_assign ? BIT(hwirq) << PINT_HI_OFFSET : BIT(hwirq); | |
199 | } | |
200 | ||
201 | static struct gpio_pint *find_gpio_pint(unsigned id) | |
202 | { | |
203 | struct gpio_pint *pint; | |
204 | int i = 0; | |
205 | ||
206 | list_for_each_entry(pint, &adi_pint_list, node) { | |
207 | if (id == i) | |
208 | return pint; | |
209 | i++; | |
210 | } | |
211 | ||
212 | return NULL; | |
213 | } | |
214 | ||
215 | static inline void port_setup(struct gpio_port *port, unsigned offset, | |
216 | bool use_for_gpio) | |
217 | { | |
218 | struct gpio_port_t *regs = port->regs; | |
219 | ||
220 | if (use_for_gpio) | |
221 | writew(readw(®s->port_fer) & ~BIT(offset), | |
222 | ®s->port_fer); | |
223 | else | |
224 | writew(readw(®s->port_fer) | BIT(offset), ®s->port_fer); | |
225 | } | |
226 | ||
227 | static inline void portmux_setup(struct gpio_port *port, unsigned offset, | |
228 | unsigned short function) | |
229 | { | |
230 | struct gpio_port_t *regs = port->regs; | |
231 | u32 pmux; | |
232 | ||
233 | pmux = readl(®s->port_mux); | |
234 | ||
235 | /* The function field of each pin has 2 consecutive bits in | |
236 | * the mux register. | |
237 | */ | |
238 | pmux &= ~(0x3 << (2 * offset)); | |
239 | pmux |= (function & 0x3) << (2 * offset); | |
240 | ||
241 | writel(pmux, ®s->port_mux); | |
242 | } | |
243 | ||
244 | static inline u16 get_portmux(struct gpio_port *port, unsigned offset) | |
245 | { | |
246 | struct gpio_port_t *regs = port->regs; | |
247 | u32 pmux = readl(®s->port_mux); | |
248 | ||
249 | /* The function field of each pin has 2 consecutive bits in | |
250 | * the mux register. | |
251 | */ | |
252 | return pmux >> (2 * offset) & 0x3; | |
253 | } | |
254 | ||
255 | static void adi_gpio_ack_irq(struct irq_data *d) | |
256 | { | |
257 | unsigned long flags; | |
258 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
259 | struct gpio_pint_regs *regs = port->pint->regs; | |
260 | unsigned pintbit = hwirq_to_pintbit(port, d->hwirq); | |
261 | ||
262 | spin_lock_irqsave(&port->lock, flags); | |
010c51e1 | 263 | spin_lock(&port->pint->lock); |
e9a03add SZ |
264 | |
265 | if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { | |
266 | if (readl(®s->invert_set) & pintbit) | |
267 | writel(pintbit, ®s->invert_clear); | |
268 | else | |
269 | writel(pintbit, ®s->invert_set); | |
270 | } | |
271 | ||
272 | writel(pintbit, ®s->request); | |
273 | ||
010c51e1 | 274 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
275 | spin_unlock_irqrestore(&port->lock, flags); |
276 | } | |
277 | ||
278 | static void adi_gpio_mask_ack_irq(struct irq_data *d) | |
279 | { | |
280 | unsigned long flags; | |
281 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
282 | struct gpio_pint_regs *regs = port->pint->regs; | |
283 | unsigned pintbit = hwirq_to_pintbit(port, d->hwirq); | |
284 | ||
285 | spin_lock_irqsave(&port->lock, flags); | |
010c51e1 | 286 | spin_lock(&port->pint->lock); |
e9a03add SZ |
287 | |
288 | if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { | |
289 | if (readl(®s->invert_set) & pintbit) | |
290 | writel(pintbit, ®s->invert_clear); | |
291 | else | |
292 | writel(pintbit, ®s->invert_set); | |
293 | } | |
294 | ||
295 | writel(pintbit, ®s->request); | |
296 | writel(pintbit, ®s->mask_clear); | |
297 | ||
010c51e1 | 298 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
299 | spin_unlock_irqrestore(&port->lock, flags); |
300 | } | |
301 | ||
302 | static void adi_gpio_mask_irq(struct irq_data *d) | |
303 | { | |
304 | unsigned long flags; | |
305 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
306 | struct gpio_pint_regs *regs = port->pint->regs; | |
307 | ||
308 | spin_lock_irqsave(&port->lock, flags); | |
010c51e1 | 309 | spin_lock(&port->pint->lock); |
e9a03add SZ |
310 | |
311 | writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_clear); | |
312 | ||
010c51e1 | 313 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
314 | spin_unlock_irqrestore(&port->lock, flags); |
315 | } | |
316 | ||
317 | static void adi_gpio_unmask_irq(struct irq_data *d) | |
318 | { | |
319 | unsigned long flags; | |
320 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
321 | struct gpio_pint_regs *regs = port->pint->regs; | |
322 | ||
323 | spin_lock_irqsave(&port->lock, flags); | |
010c51e1 | 324 | spin_lock(&port->pint->lock); |
e9a03add SZ |
325 | |
326 | writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_set); | |
327 | ||
010c51e1 | 328 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
329 | spin_unlock_irqrestore(&port->lock, flags); |
330 | } | |
331 | ||
332 | static unsigned int adi_gpio_irq_startup(struct irq_data *d) | |
333 | { | |
334 | unsigned long flags; | |
335 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
010c51e1 | 336 | struct gpio_pint_regs *regs; |
e9a03add SZ |
337 | |
338 | if (!port) { | |
010c51e1 | 339 | pr_err("GPIO IRQ %d :Not exist\n", d->irq); |
57ef0428 | 340 | /* FIXME: negative return code will be ignored */ |
e9a03add SZ |
341 | return -ENODEV; |
342 | } | |
343 | ||
010c51e1 SZ |
344 | regs = port->pint->regs; |
345 | ||
e9a03add | 346 | spin_lock_irqsave(&port->lock, flags); |
010c51e1 | 347 | spin_lock(&port->pint->lock); |
e9a03add SZ |
348 | |
349 | port_setup(port, d->hwirq, true); | |
350 | writew(BIT(d->hwirq), &port->regs->dir_clear); | |
351 | writew(readw(&port->regs->inen) | BIT(d->hwirq), &port->regs->inen); | |
352 | ||
353 | writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_set); | |
354 | ||
010c51e1 | 355 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
356 | spin_unlock_irqrestore(&port->lock, flags); |
357 | ||
358 | return 0; | |
359 | } | |
360 | ||
361 | static void adi_gpio_irq_shutdown(struct irq_data *d) | |
362 | { | |
363 | unsigned long flags; | |
364 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
365 | struct gpio_pint_regs *regs = port->pint->regs; | |
366 | ||
367 | spin_lock_irqsave(&port->lock, flags); | |
010c51e1 | 368 | spin_lock(&port->pint->lock); |
e9a03add SZ |
369 | |
370 | writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_clear); | |
371 | ||
010c51e1 | 372 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
373 | spin_unlock_irqrestore(&port->lock, flags); |
374 | } | |
375 | ||
376 | static int adi_gpio_irq_type(struct irq_data *d, unsigned int type) | |
377 | { | |
378 | unsigned long flags; | |
379 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
010c51e1 | 380 | struct gpio_pint_regs *pint_regs; |
e9a03add SZ |
381 | unsigned pintmask; |
382 | unsigned int irq = d->irq; | |
383 | int ret = 0; | |
384 | char buf[16]; | |
385 | ||
386 | if (!port) { | |
010c51e1 | 387 | pr_err("GPIO IRQ %d :Not exist\n", d->irq); |
e9a03add SZ |
388 | return -ENODEV; |
389 | } | |
390 | ||
010c51e1 SZ |
391 | pint_regs = port->pint->regs; |
392 | ||
e9a03add SZ |
393 | pintmask = hwirq_to_pintbit(port, d->hwirq); |
394 | ||
395 | spin_lock_irqsave(&port->lock, flags); | |
010c51e1 | 396 | spin_lock(&port->pint->lock); |
e9a03add SZ |
397 | |
398 | /* In case of interrupt autodetect, set irq type to edge sensitive. */ | |
399 | if (type == IRQ_TYPE_PROBE) | |
400 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | |
401 | ||
402 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | | |
403 | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | |
719e231b | 404 | snprintf(buf, 16, "gpio-irq%u", irq); |
e9a03add SZ |
405 | port_setup(port, d->hwirq, true); |
406 | } else | |
407 | goto out; | |
408 | ||
409 | /* The GPIO interrupt is triggered only when its input value | |
410 | * transfer from 0 to 1. So, invert the input value if the | |
411 | * irq type is low or falling | |
412 | */ | |
413 | if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) | |
414 | writel(pintmask, &pint_regs->invert_set); | |
415 | else | |
416 | writel(pintmask, &pint_regs->invert_clear); | |
417 | ||
418 | /* In edge sensitive case, if the input value of the requested irq | |
419 | * is already 1, invert it. | |
420 | */ | |
421 | if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { | |
422 | if (gpio_get_value(port->chip.base + d->hwirq)) | |
423 | writel(pintmask, &pint_regs->invert_set); | |
424 | else | |
425 | writel(pintmask, &pint_regs->invert_clear); | |
426 | } | |
427 | ||
428 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | |
429 | writel(pintmask, &pint_regs->edge_set); | |
e0d6a2c6 | 430 | irq_set_handler_locked(d, handle_edge_irq); |
e9a03add SZ |
431 | } else { |
432 | writel(pintmask, &pint_regs->edge_clear); | |
e0d6a2c6 | 433 | irq_set_handler_locked(d, handle_level_irq); |
e9a03add SZ |
434 | } |
435 | ||
436 | out: | |
010c51e1 | 437 | spin_unlock(&port->pint->lock); |
e9a03add SZ |
438 | spin_unlock_irqrestore(&port->lock, flags); |
439 | ||
440 | return ret; | |
441 | } | |
442 | ||
443 | #ifdef CONFIG_PM | |
444 | static int adi_gpio_set_wake(struct irq_data *d, unsigned int state) | |
445 | { | |
446 | struct gpio_port *port = irq_data_get_irq_chip_data(d); | |
447 | ||
448 | if (!port || !port->pint || port->pint->irq != d->irq) | |
449 | return -EINVAL; | |
450 | ||
451 | #ifndef SEC_GCTL | |
452 | adi_internal_set_wake(port->pint->irq, state); | |
453 | #endif | |
454 | ||
455 | return 0; | |
456 | } | |
457 | ||
458 | static int adi_pint_suspend(void) | |
459 | { | |
460 | struct gpio_pint *pint; | |
461 | ||
462 | list_for_each_entry(pint, &adi_pint_list, node) { | |
463 | writel(0xffffffff, &pint->regs->mask_clear); | |
464 | pint->saved_data.assign = readl(&pint->regs->assign); | |
465 | pint->saved_data.edge_set = readl(&pint->regs->edge_set); | |
466 | pint->saved_data.invert_set = readl(&pint->regs->invert_set); | |
467 | } | |
468 | ||
469 | return 0; | |
470 | } | |
471 | ||
472 | static void adi_pint_resume(void) | |
473 | { | |
474 | struct gpio_pint *pint; | |
475 | ||
476 | list_for_each_entry(pint, &adi_pint_list, node) { | |
477 | writel(pint->saved_data.assign, &pint->regs->assign); | |
478 | writel(pint->saved_data.edge_set, &pint->regs->edge_set); | |
479 | writel(pint->saved_data.invert_set, &pint->regs->invert_set); | |
480 | } | |
481 | } | |
482 | ||
483 | static int adi_gpio_suspend(void) | |
484 | { | |
485 | struct gpio_port *port; | |
486 | ||
487 | list_for_each_entry(port, &adi_gpio_port_list, node) { | |
488 | port->saved_data.fer = readw(&port->regs->port_fer); | |
489 | port->saved_data.mux = readl(&port->regs->port_mux); | |
490 | port->saved_data.data = readw(&port->regs->data); | |
491 | port->saved_data.inen = readw(&port->regs->inen); | |
492 | port->saved_data.dir = readw(&port->regs->dir_set); | |
493 | } | |
494 | ||
495 | return adi_pint_suspend(); | |
496 | } | |
497 | ||
498 | static void adi_gpio_resume(void) | |
499 | { | |
500 | struct gpio_port *port; | |
501 | ||
502 | adi_pint_resume(); | |
503 | ||
504 | list_for_each_entry(port, &adi_gpio_port_list, node) { | |
505 | writel(port->saved_data.mux, &port->regs->port_mux); | |
506 | writew(port->saved_data.fer, &port->regs->port_fer); | |
507 | writew(port->saved_data.inen, &port->regs->inen); | |
508 | writew(port->saved_data.data & port->saved_data.dir, | |
509 | &port->regs->data_set); | |
510 | writew(port->saved_data.dir, &port->regs->dir_set); | |
511 | } | |
512 | ||
513 | } | |
514 | ||
515 | static struct syscore_ops gpio_pm_syscore_ops = { | |
516 | .suspend = adi_gpio_suspend, | |
517 | .resume = adi_gpio_resume, | |
518 | }; | |
519 | #else /* CONFIG_PM */ | |
520 | #define adi_gpio_set_wake NULL | |
521 | #endif /* CONFIG_PM */ | |
522 | ||
523 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | |
524 | static inline void preflow_handler(struct irq_desc *desc) | |
525 | { | |
526 | if (desc->preflow_handler) | |
527 | desc->preflow_handler(&desc->irq_data); | |
528 | } | |
529 | #else | |
530 | static inline void preflow_handler(struct irq_desc *desc) { } | |
531 | #endif | |
532 | ||
bd0b9ac4 | 533 | static void adi_gpio_handle_pint_irq(struct irq_desc *desc) |
e9a03add SZ |
534 | { |
535 | u32 request; | |
536 | u32 level_mask, hwirq; | |
537 | bool umask = false; | |
538 | struct gpio_pint *pint = irq_desc_get_handler_data(desc); | |
539 | struct irq_chip *chip = irq_desc_get_chip(desc); | |
540 | struct gpio_pint_regs *regs = pint->regs; | |
541 | struct irq_domain *domain; | |
542 | ||
543 | preflow_handler(desc); | |
544 | chained_irq_enter(chip, desc); | |
545 | ||
546 | request = readl(®s->request); | |
547 | level_mask = readl(®s->edge_set) & request; | |
548 | ||
549 | hwirq = 0; | |
550 | domain = pint->domain[0]; | |
551 | while (request) { | |
552 | /* domain pointer need to be changed only once at IRQ 16 when | |
553 | * we go through IRQ requests from bit 0 to bit 31. | |
554 | */ | |
555 | if (hwirq == PINT_HI_OFFSET) | |
556 | domain = pint->domain[1]; | |
557 | ||
558 | if (request & 1) { | |
559 | if (level_mask & BIT(hwirq)) { | |
560 | umask = true; | |
561 | chained_irq_exit(chip, desc); | |
562 | } | |
563 | generic_handle_irq(irq_find_mapping(domain, | |
564 | hwirq % PINT_HI_OFFSET)); | |
565 | } | |
566 | ||
567 | hwirq++; | |
568 | request >>= 1; | |
569 | } | |
570 | ||
571 | if (!umask) | |
572 | chained_irq_exit(chip, desc); | |
573 | } | |
574 | ||
575 | static struct irq_chip adi_gpio_irqchip = { | |
576 | .name = "GPIO", | |
577 | .irq_ack = adi_gpio_ack_irq, | |
578 | .irq_mask = adi_gpio_mask_irq, | |
579 | .irq_mask_ack = adi_gpio_mask_ack_irq, | |
580 | .irq_unmask = adi_gpio_unmask_irq, | |
581 | .irq_disable = adi_gpio_mask_irq, | |
582 | .irq_enable = adi_gpio_unmask_irq, | |
583 | .irq_set_type = adi_gpio_irq_type, | |
584 | .irq_startup = adi_gpio_irq_startup, | |
585 | .irq_shutdown = adi_gpio_irq_shutdown, | |
586 | .irq_set_wake = adi_gpio_set_wake, | |
587 | }; | |
588 | ||
589 | static int adi_get_groups_count(struct pinctrl_dev *pctldev) | |
590 | { | |
591 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
592 | ||
593 | return pinctrl->soc->ngroups; | |
594 | } | |
595 | ||
596 | static const char *adi_get_group_name(struct pinctrl_dev *pctldev, | |
597 | unsigned selector) | |
598 | { | |
599 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
600 | ||
601 | return pinctrl->soc->groups[selector].name; | |
602 | } | |
603 | ||
604 | static int adi_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, | |
605 | const unsigned **pins, | |
606 | unsigned *num_pins) | |
607 | { | |
608 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
609 | ||
610 | *pins = pinctrl->soc->groups[selector].pins; | |
611 | *num_pins = pinctrl->soc->groups[selector].num; | |
612 | return 0; | |
613 | } | |
614 | ||
615 | static struct pinctrl_ops adi_pctrl_ops = { | |
616 | .get_groups_count = adi_get_groups_count, | |
617 | .get_group_name = adi_get_group_name, | |
618 | .get_group_pins = adi_get_group_pins, | |
619 | }; | |
620 | ||
03e9f0ca LW |
621 | static int adi_pinmux_set(struct pinctrl_dev *pctldev, unsigned func_id, |
622 | unsigned group_id) | |
e9a03add SZ |
623 | { |
624 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
625 | struct gpio_port *port; | |
626 | struct pinctrl_gpio_range *range; | |
627 | unsigned long flags; | |
628 | unsigned short *mux, pin; | |
629 | ||
e3653749 | 630 | mux = (unsigned short *)pinctrl->soc->groups[group_id].mux; |
e9a03add SZ |
631 | |
632 | while (*mux) { | |
633 | pin = P_IDENT(*mux); | |
634 | ||
635 | range = pinctrl_find_gpio_range_from_pin(pctldev, pin); | |
636 | if (range == NULL) /* should not happen */ | |
637 | return -ENODEV; | |
638 | ||
639 | port = container_of(range->gc, struct gpio_port, chip); | |
640 | ||
641 | spin_lock_irqsave(&port->lock, flags); | |
642 | ||
643 | portmux_setup(port, pin_to_offset(range, pin), | |
b81e57e6 | 644 | P_FUNCT2MUX(*mux)); |
e9a03add SZ |
645 | port_setup(port, pin_to_offset(range, pin), false); |
646 | mux++; | |
647 | ||
648 | spin_unlock_irqrestore(&port->lock, flags); | |
649 | } | |
650 | ||
651 | return 0; | |
652 | } | |
653 | ||
e9a03add SZ |
654 | static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) |
655 | { | |
656 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
657 | ||
658 | return pinctrl->soc->nfunctions; | |
659 | } | |
660 | ||
661 | static const char *adi_pinmux_get_func_name(struct pinctrl_dev *pctldev, | |
662 | unsigned selector) | |
663 | { | |
664 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
665 | ||
666 | return pinctrl->soc->functions[selector].name; | |
667 | } | |
668 | ||
669 | static int adi_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector, | |
670 | const char * const **groups, | |
671 | unsigned * const num_groups) | |
672 | { | |
673 | struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); | |
674 | ||
675 | *groups = pinctrl->soc->functions[selector].groups; | |
676 | *num_groups = pinctrl->soc->functions[selector].num_groups; | |
677 | return 0; | |
678 | } | |
679 | ||
680 | static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev, | |
681 | struct pinctrl_gpio_range *range, unsigned pin) | |
682 | { | |
683 | struct gpio_port *port; | |
684 | unsigned long flags; | |
685 | u8 offset; | |
686 | ||
687 | port = container_of(range->gc, struct gpio_port, chip); | |
688 | offset = pin_to_offset(range, pin); | |
689 | ||
690 | spin_lock_irqsave(&port->lock, flags); | |
691 | ||
692 | port_setup(port, offset, true); | |
693 | ||
694 | spin_unlock_irqrestore(&port->lock, flags); | |
695 | ||
696 | return 0; | |
697 | } | |
698 | ||
699 | static struct pinmux_ops adi_pinmux_ops = { | |
03e9f0ca | 700 | .set_mux = adi_pinmux_set, |
e9a03add SZ |
701 | .get_functions_count = adi_pinmux_get_funcs_count, |
702 | .get_function_name = adi_pinmux_get_func_name, | |
703 | .get_function_groups = adi_pinmux_get_groups, | |
704 | .gpio_request_enable = adi_pinmux_request_gpio, | |
8c4c2016 | 705 | .strict = true, |
e9a03add SZ |
706 | }; |
707 | ||
708 | ||
709 | static struct pinctrl_desc adi_pinmux_desc = { | |
710 | .name = DRIVER_NAME, | |
711 | .pctlops = &adi_pctrl_ops, | |
712 | .pmxops = &adi_pinmux_ops, | |
713 | .owner = THIS_MODULE, | |
714 | }; | |
715 | ||
e9a03add SZ |
716 | static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
717 | { | |
718 | struct gpio_port *port; | |
719 | unsigned long flags; | |
720 | ||
721 | port = container_of(chip, struct gpio_port, chip); | |
722 | ||
723 | spin_lock_irqsave(&port->lock, flags); | |
724 | ||
725 | writew(BIT(offset), &port->regs->dir_clear); | |
726 | writew(readw(&port->regs->inen) | BIT(offset), &port->regs->inen); | |
727 | ||
728 | spin_unlock_irqrestore(&port->lock, flags); | |
729 | ||
730 | return 0; | |
731 | } | |
732 | ||
733 | static void adi_gpio_set_value(struct gpio_chip *chip, unsigned offset, | |
734 | int value) | |
735 | { | |
736 | struct gpio_port *port = container_of(chip, struct gpio_port, chip); | |
737 | struct gpio_port_t *regs = port->regs; | |
738 | unsigned long flags; | |
739 | ||
740 | spin_lock_irqsave(&port->lock, flags); | |
741 | ||
742 | if (value) | |
d3224ed1 | 743 | writew(BIT(offset), ®s->data_set); |
e9a03add | 744 | else |
d3224ed1 | 745 | writew(BIT(offset), ®s->data_clear); |
e9a03add SZ |
746 | |
747 | spin_unlock_irqrestore(&port->lock, flags); | |
748 | } | |
749 | ||
750 | static int adi_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | |
751 | int value) | |
752 | { | |
753 | struct gpio_port *port = container_of(chip, struct gpio_port, chip); | |
754 | struct gpio_port_t *regs = port->regs; | |
755 | unsigned long flags; | |
756 | ||
757 | spin_lock_irqsave(&port->lock, flags); | |
758 | ||
d3224ed1 SZ |
759 | writew(readw(®s->inen) & ~BIT(offset), ®s->inen); |
760 | if (value) | |
761 | writew(BIT(offset), ®s->data_set); | |
762 | else | |
763 | writew(BIT(offset), ®s->data_clear); | |
764 | writew(BIT(offset), ®s->dir_set); | |
e9a03add SZ |
765 | |
766 | spin_unlock_irqrestore(&port->lock, flags); | |
767 | ||
768 | return 0; | |
769 | } | |
770 | ||
771 | static int adi_gpio_get_value(struct gpio_chip *chip, unsigned offset) | |
772 | { | |
773 | struct gpio_port *port = container_of(chip, struct gpio_port, chip); | |
774 | struct gpio_port_t *regs = port->regs; | |
775 | unsigned long flags; | |
776 | int ret; | |
777 | ||
778 | spin_lock_irqsave(&port->lock, flags); | |
779 | ||
780 | ret = !!(readw(®s->data) & BIT(offset)); | |
781 | ||
782 | spin_unlock_irqrestore(&port->lock, flags); | |
783 | ||
784 | return ret; | |
785 | } | |
786 | ||
787 | static int adi_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |
788 | { | |
789 | struct gpio_port *port = container_of(chip, struct gpio_port, chip); | |
790 | ||
791 | if (port->irq_base >= 0) | |
792 | return irq_find_mapping(port->domain, offset); | |
793 | else | |
794 | return irq_create_mapping(port->domain, offset); | |
795 | } | |
796 | ||
797 | static int adi_pint_map_port(struct gpio_pint *pint, bool assign, u8 map, | |
798 | struct irq_domain *domain) | |
799 | { | |
800 | struct gpio_pint_regs *regs = pint->regs; | |
801 | u32 map_mask; | |
802 | ||
803 | if (pint->map_count > 1) | |
804 | return -EINVAL; | |
805 | ||
806 | pint->map_count++; | |
807 | ||
808 | /* The map_mask of each gpio port is a 16-bit duplicate | |
809 | * of the 8-bit map. It can be set to either high 16 bits or low | |
810 | * 16 bits of the pint assignment register. | |
811 | */ | |
812 | map_mask = (map << 8) | map; | |
813 | if (assign) { | |
814 | map_mask <<= PINT_HI_OFFSET; | |
815 | writel((readl(®s->assign) & 0xFFFF) | map_mask, | |
816 | ®s->assign); | |
817 | } else | |
818 | writel((readl(®s->assign) & 0xFFFF0000) | map_mask, | |
819 | ®s->assign); | |
820 | ||
821 | pint->domain[assign] = domain; | |
822 | ||
823 | return 0; | |
824 | } | |
825 | ||
826 | static int adi_gpio_pint_probe(struct platform_device *pdev) | |
827 | { | |
828 | struct device *dev = &pdev->dev; | |
829 | struct resource *res; | |
830 | struct gpio_pint *pint; | |
831 | ||
832 | pint = devm_kzalloc(dev, sizeof(struct gpio_pint), GFP_KERNEL); | |
833 | if (!pint) { | |
834 | dev_err(dev, "Memory alloc failed\n"); | |
835 | return -ENOMEM; | |
836 | } | |
837 | ||
838 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
c8690d6d AL |
839 | pint->base = devm_ioremap_resource(dev, res); |
840 | if (IS_ERR(pint->base)) | |
841 | return PTR_ERR(pint->base); | |
e9a03add SZ |
842 | |
843 | pint->regs = (struct gpio_pint_regs *)pint->base; | |
844 | ||
845 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
846 | if (!res) { | |
847 | dev_err(dev, "Invalid IRQ resource\n"); | |
848 | return -ENODEV; | |
849 | } | |
850 | ||
851 | spin_lock_init(&pint->lock); | |
852 | ||
853 | pint->irq = res->start; | |
854 | pint->pint_map_port = adi_pint_map_port; | |
855 | platform_set_drvdata(pdev, pint); | |
856 | ||
bb6d6dd3 TG |
857 | irq_set_chained_handler_and_data(pint->irq, adi_gpio_handle_pint_irq, |
858 | pint); | |
e9a03add SZ |
859 | |
860 | list_add_tail(&pint->node, &adi_pint_list); | |
861 | ||
862 | return 0; | |
863 | } | |
864 | ||
865 | static int adi_gpio_pint_remove(struct platform_device *pdev) | |
866 | { | |
867 | struct gpio_pint *pint = platform_get_drvdata(pdev); | |
868 | ||
869 | list_del(&pint->node); | |
870 | irq_set_handler(pint->irq, handle_simple_irq); | |
871 | ||
872 | return 0; | |
873 | } | |
874 | ||
875 | static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq, | |
876 | irq_hw_number_t hwirq) | |
877 | { | |
878 | struct gpio_port *port = d->host_data; | |
879 | ||
880 | if (!port) | |
881 | return -EINVAL; | |
882 | ||
883 | irq_set_chip_data(irq, port); | |
884 | irq_set_chip_and_handler(irq, &adi_gpio_irqchip, | |
885 | handle_level_irq); | |
886 | ||
887 | return 0; | |
888 | } | |
889 | ||
f77329d1 | 890 | static const struct irq_domain_ops adi_gpio_irq_domain_ops = { |
e9a03add SZ |
891 | .map = adi_gpio_irq_map, |
892 | .xlate = irq_domain_xlate_onecell, | |
893 | }; | |
894 | ||
895 | static int adi_gpio_init_int(struct gpio_port *port) | |
896 | { | |
897 | struct device_node *node = port->dev->of_node; | |
898 | struct gpio_pint *pint = port->pint; | |
899 | int ret; | |
900 | ||
901 | port->domain = irq_domain_add_linear(node, port->width, | |
902 | &adi_gpio_irq_domain_ops, port); | |
903 | if (!port->domain) { | |
904 | dev_err(port->dev, "Failed to create irqdomain\n"); | |
905 | return -ENOSYS; | |
906 | } | |
907 | ||
908 | /* According to BF54x and BF60x HRM, pin interrupt devices are not | |
909 | * part of the GPIO port device. in GPIO interrupt mode, the GPIO | |
910 | * pins of multiple port devices can be routed into one pin interrupt | |
911 | * device. The mapping can be configured by setting pint assignment | |
912 | * register with the mapping value of different GPIO port. This is | |
913 | * done via function pint_map_port(). | |
914 | */ | |
915 | ret = pint->pint_map_port(port->pint, port->pint_assign, | |
916 | port->pint_map, port->domain); | |
917 | if (ret) | |
918 | return ret; | |
919 | ||
920 | if (port->irq_base >= 0) { | |
921 | ret = irq_create_strict_mappings(port->domain, port->irq_base, | |
922 | 0, port->width); | |
923 | if (ret) { | |
924 | dev_err(port->dev, "Couldn't associate to domain\n"); | |
925 | return ret; | |
926 | } | |
927 | } | |
928 | ||
929 | return 0; | |
930 | } | |
931 | ||
932 | #define DEVNAME_SIZE 16 | |
933 | ||
934 | static int adi_gpio_probe(struct platform_device *pdev) | |
935 | { | |
936 | struct device *dev = &pdev->dev; | |
937 | const struct adi_pinctrl_gpio_platform_data *pdata; | |
938 | struct resource *res; | |
939 | struct gpio_port *port; | |
940 | char pinctrl_devname[DEVNAME_SIZE]; | |
941 | static int gpio; | |
b4e7c55d | 942 | int ret = 0; |
e9a03add SZ |
943 | |
944 | pdata = dev->platform_data; | |
945 | if (!pdata) | |
946 | return -EINVAL; | |
947 | ||
948 | port = devm_kzalloc(dev, sizeof(struct gpio_port), GFP_KERNEL); | |
949 | if (!port) { | |
950 | dev_err(dev, "Memory alloc failed\n"); | |
951 | return -ENOMEM; | |
952 | } | |
953 | ||
954 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
c8690d6d AL |
955 | port->base = devm_ioremap_resource(dev, res); |
956 | if (IS_ERR(port->base)) | |
957 | return PTR_ERR(port->base); | |
e9a03add SZ |
958 | |
959 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
960 | if (!res) | |
961 | port->irq_base = -1; | |
962 | else | |
963 | port->irq_base = res->start; | |
964 | ||
965 | port->width = pdata->port_width; | |
966 | port->dev = dev; | |
967 | port->regs = (struct gpio_port_t *)port->base; | |
968 | port->pint_assign = pdata->pint_assign; | |
969 | port->pint_map = pdata->pint_map; | |
970 | ||
971 | port->pint = find_gpio_pint(pdata->pint_id); | |
972 | if (port->pint) { | |
973 | ret = adi_gpio_init_int(port); | |
974 | if (ret) | |
975 | return ret; | |
976 | } | |
977 | ||
978 | spin_lock_init(&port->lock); | |
979 | ||
980 | platform_set_drvdata(pdev, port); | |
981 | ||
982 | port->chip.label = "adi-gpio"; | |
983 | port->chip.direction_input = adi_gpio_direction_input; | |
984 | port->chip.get = adi_gpio_get_value; | |
985 | port->chip.direction_output = adi_gpio_direction_output; | |
986 | port->chip.set = adi_gpio_set_value; | |
98c85d58 JG |
987 | port->chip.request = gpiochip_generic_request, |
988 | port->chip.free = gpiochip_generic_free, | |
e9a03add SZ |
989 | port->chip.to_irq = adi_gpio_to_irq; |
990 | if (pdata->port_gpio_base > 0) | |
991 | port->chip.base = pdata->port_gpio_base; | |
992 | else | |
993 | port->chip.base = gpio; | |
994 | port->chip.ngpio = port->width; | |
995 | gpio = port->chip.base + port->width; | |
996 | ||
997 | ret = gpiochip_add(&port->chip); | |
998 | if (ret) { | |
999 | dev_err(&pdev->dev, "Fail to add GPIO chip.\n"); | |
1000 | goto out_remove_domain; | |
1001 | } | |
1002 | ||
1003 | /* Add gpio pin range */ | |
1004 | snprintf(pinctrl_devname, DEVNAME_SIZE, "pinctrl-adi2.%d", | |
1005 | pdata->pinctrl_id); | |
1006 | pinctrl_devname[DEVNAME_SIZE - 1] = 0; | |
1007 | ret = gpiochip_add_pin_range(&port->chip, pinctrl_devname, | |
1008 | 0, pdata->port_pin_base, port->width); | |
1009 | if (ret) { | |
1010 | dev_err(&pdev->dev, "Fail to add pin range to %s.\n", | |
1011 | pinctrl_devname); | |
1012 | goto out_remove_gpiochip; | |
1013 | } | |
1014 | ||
1015 | list_add_tail(&port->node, &adi_gpio_port_list); | |
1016 | ||
1017 | return 0; | |
1018 | ||
1019 | out_remove_gpiochip: | |
b4e7c55d | 1020 | gpiochip_remove(&port->chip); |
e9a03add SZ |
1021 | out_remove_domain: |
1022 | if (port->pint) | |
1023 | irq_domain_remove(port->domain); | |
1024 | ||
1025 | return ret; | |
1026 | } | |
1027 | ||
1028 | static int adi_gpio_remove(struct platform_device *pdev) | |
1029 | { | |
1030 | struct gpio_port *port = platform_get_drvdata(pdev); | |
e9a03add SZ |
1031 | u8 offset; |
1032 | ||
1033 | list_del(&port->node); | |
b4e7c55d | 1034 | gpiochip_remove(&port->chip); |
e9a03add SZ |
1035 | if (port->pint) { |
1036 | for (offset = 0; offset < port->width; offset++) | |
1037 | irq_dispose_mapping(irq_find_mapping(port->domain, | |
1038 | offset)); | |
1039 | irq_domain_remove(port->domain); | |
1040 | } | |
1041 | ||
b4e7c55d | 1042 | return 0; |
e9a03add SZ |
1043 | } |
1044 | ||
1045 | static int adi_pinctrl_probe(struct platform_device *pdev) | |
1046 | { | |
1047 | struct adi_pinctrl *pinctrl; | |
1048 | ||
1049 | pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL); | |
1050 | if (!pinctrl) | |
1051 | return -ENOMEM; | |
1052 | ||
1053 | pinctrl->dev = &pdev->dev; | |
1054 | ||
1055 | adi_pinctrl_soc_init(&pinctrl->soc); | |
1056 | ||
1057 | adi_pinmux_desc.pins = pinctrl->soc->pins; | |
1058 | adi_pinmux_desc.npins = pinctrl->soc->npins; | |
1059 | ||
1060 | /* Now register the pin controller and all pins it handles */ | |
1061 | pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl); | |
323de9ef | 1062 | if (IS_ERR(pinctrl->pctl)) { |
e9a03add | 1063 | dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n"); |
323de9ef | 1064 | return PTR_ERR(pinctrl->pctl); |
e9a03add SZ |
1065 | } |
1066 | ||
1067 | platform_set_drvdata(pdev, pinctrl); | |
1068 | ||
1069 | return 0; | |
1070 | } | |
1071 | ||
1072 | static int adi_pinctrl_remove(struct platform_device *pdev) | |
1073 | { | |
1074 | struct adi_pinctrl *pinctrl = platform_get_drvdata(pdev); | |
1075 | ||
1076 | pinctrl_unregister(pinctrl->pctl); | |
1077 | ||
1078 | return 0; | |
1079 | } | |
1080 | ||
1081 | static struct platform_driver adi_pinctrl_driver = { | |
1082 | .probe = adi_pinctrl_probe, | |
1083 | .remove = adi_pinctrl_remove, | |
1084 | .driver = { | |
1085 | .name = DRIVER_NAME, | |
1086 | }, | |
1087 | }; | |
1088 | ||
1089 | static struct platform_driver adi_gpio_pint_driver = { | |
1090 | .probe = adi_gpio_pint_probe, | |
1091 | .remove = adi_gpio_pint_remove, | |
1092 | .driver = { | |
1093 | .name = "adi-gpio-pint", | |
1094 | }, | |
1095 | }; | |
1096 | ||
1097 | static struct platform_driver adi_gpio_driver = { | |
1098 | .probe = adi_gpio_probe, | |
1099 | .remove = adi_gpio_remove, | |
1100 | .driver = { | |
1101 | .name = "adi-gpio", | |
1102 | }, | |
1103 | }; | |
1104 | ||
1105 | static int __init adi_pinctrl_setup(void) | |
1106 | { | |
1107 | int ret; | |
1108 | ||
1109 | ret = platform_driver_register(&adi_pinctrl_driver); | |
1110 | if (ret) | |
1111 | return ret; | |
1112 | ||
1113 | ret = platform_driver_register(&adi_gpio_pint_driver); | |
1114 | if (ret) | |
1115 | goto pint_error; | |
1116 | ||
1117 | ret = platform_driver_register(&adi_gpio_driver); | |
1118 | if (ret) | |
1119 | goto gpio_error; | |
1120 | ||
1121 | #ifdef CONFIG_PM | |
1122 | register_syscore_ops(&gpio_pm_syscore_ops); | |
1123 | #endif | |
1124 | return ret; | |
1125 | gpio_error: | |
1126 | platform_driver_unregister(&adi_gpio_pint_driver); | |
1127 | pint_error: | |
1128 | platform_driver_unregister(&adi_pinctrl_driver); | |
1129 | ||
1130 | return ret; | |
1131 | } | |
1132 | arch_initcall(adi_pinctrl_setup); | |
1133 | ||
1134 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); | |
1135 | MODULE_DESCRIPTION("ADI gpio2 pin control driver"); | |
1136 | MODULE_LICENSE("GPL"); |