]>
Commit | Line | Data |
---|---|---|
fefe7b09 TP |
1 | /* |
2 | * GPIO driver for Marvell SoCs | |
3 | * | |
4 | * Copyright (C) 2012 Marvell | |
5 | * | |
6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | |
7 | * Andrew Lunn <andrew@lunn.ch> | |
8 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | |
9 | * | |
10 | * This file is licensed under the terms of the GNU General Public | |
11 | * License version 2. This program is licensed "as is" without any | |
12 | * warranty of any kind, whether express or implied. | |
13 | * | |
14 | * This driver is a fairly straightforward GPIO driver for the | |
15 | * complete family of Marvell EBU SoC platforms (Orion, Dove, | |
16 | * Kirkwood, Discovery, Armada 370/XP). The only complexity of this | |
17 | * driver is the different register layout that exists between the | |
18 | * non-SMP platforms (Orion, Dove, Kirkwood, Armada 370) and the SMP | |
19 | * platforms (MV78200 from the Discovery family and the Armada | |
20 | * XP). Therefore, this driver handles three variants of the GPIO | |
21 | * block: | |
22 | * - the basic variant, called "orion-gpio", with the simplest | |
23 | * register set. Used on Orion, Dove, Kirkwoord, Armada 370 and | |
24 | * non-SMP Discovery systems | |
25 | * - the mv78200 variant for MV78200 Discovery systems. This variant | |
26 | * turns the edge mask and level mask registers into CPU0 edge | |
27 | * mask/level mask registers, and adds CPU1 edge mask/level mask | |
28 | * registers. | |
29 | * - the armadaxp variant for Armada XP systems. This variant keeps | |
30 | * the normal cause/edge mask/level mask registers when the global | |
31 | * interrupts are used, but adds per-CPU cause/edge mask/level mask | |
32 | * registers n a separate memory area for the per-CPU GPIO | |
33 | * interrupts. | |
34 | */ | |
35 | ||
641d0342 | 36 | #include <linux/err.h> |
ed329f3a | 37 | #include <linux/init.h> |
fefe7b09 TP |
38 | #include <linux/gpio.h> |
39 | #include <linux/irq.h> | |
40 | #include <linux/slab.h> | |
41 | #include <linux/irqdomain.h> | |
42 | #include <linux/io.h> | |
43 | #include <linux/of_irq.h> | |
44 | #include <linux/of_device.h> | |
757642f9 | 45 | #include <linux/pwm.h> |
de88747f | 46 | #include <linux/clk.h> |
fefe7b09 | 47 | #include <linux/pinctrl/consumer.h> |
01ca59f1 | 48 | #include <linux/irqchip/chained_irq.h> |
757642f9 | 49 | #include <linux/platform_device.h> |
d2cabc4a | 50 | #include <linux/bitops.h> |
fefe7b09 | 51 | |
757642f9 AL |
52 | #include "gpiolib.h" |
53 | ||
fefe7b09 TP |
54 | /* |
55 | * GPIO unit register offsets. | |
56 | */ | |
757642f9 AL |
57 | #define GPIO_OUT_OFF 0x0000 |
58 | #define GPIO_IO_CONF_OFF 0x0004 | |
59 | #define GPIO_BLINK_EN_OFF 0x0008 | |
60 | #define GPIO_IN_POL_OFF 0x000c | |
61 | #define GPIO_DATA_IN_OFF 0x0010 | |
62 | #define GPIO_EDGE_CAUSE_OFF 0x0014 | |
63 | #define GPIO_EDGE_MASK_OFF 0x0018 | |
64 | #define GPIO_LEVEL_MASK_OFF 0x001c | |
65 | #define GPIO_BLINK_CNT_SELECT_OFF 0x0020 | |
66 | ||
67 | /* | |
68 | * PWM register offsets. | |
69 | */ | |
70 | #define PWM_BLINK_ON_DURATION_OFF 0x0 | |
71 | #define PWM_BLINK_OFF_DURATION_OFF 0x4 | |
72 | ||
fefe7b09 TP |
73 | |
74 | /* The MV78200 has per-CPU registers for edge mask and level mask */ | |
a4319a61 | 75 | #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) |
fefe7b09 TP |
76 | #define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C) |
77 | ||
7077f4cc RS |
78 | /* |
79 | * The Armada XP has per-CPU registers for interrupt cause, interrupt | |
fefe7b09 | 80 | * mask and interrupt level mask. Those are relative to the |
7077f4cc RS |
81 | * percpu_membase. |
82 | */ | |
fefe7b09 TP |
83 | #define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4) |
84 | #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4) | |
85 | #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4) | |
86 | ||
a4319a61 AL |
87 | #define MVEBU_GPIO_SOC_VARIANT_ORION 0x1 |
88 | #define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2 | |
fefe7b09 TP |
89 | #define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3 |
90 | ||
a4319a61 | 91 | #define MVEBU_MAX_GPIO_PER_BANK 32 |
fefe7b09 | 92 | |
757642f9 AL |
93 | struct mvebu_pwm { |
94 | void __iomem *membase; | |
95 | unsigned long clk_rate; | |
96 | struct gpio_desc *gpiod; | |
97 | struct pwm_chip chip; | |
98 | spinlock_t lock; | |
99 | struct mvebu_gpio_chip *mvchip; | |
100 | ||
101 | /* Used to preserve GPIO/PWM registers across suspend/resume */ | |
102 | u32 blink_select; | |
103 | u32 blink_on_duration; | |
104 | u32 blink_off_duration; | |
105 | }; | |
106 | ||
fefe7b09 TP |
107 | struct mvebu_gpio_chip { |
108 | struct gpio_chip chip; | |
109 | spinlock_t lock; | |
110 | void __iomem *membase; | |
111 | void __iomem *percpu_membase; | |
d5359226 | 112 | int irqbase; |
fefe7b09 | 113 | struct irq_domain *domain; |
a4319a61 | 114 | int soc_variant; |
b5b7b487 | 115 | |
757642f9 AL |
116 | /* Used for PWM support */ |
117 | struct clk *clk; | |
118 | struct mvebu_pwm *mvpwm; | |
119 | ||
a4319a61 | 120 | /* Used to preserve GPIO registers across suspend/resume */ |
f4c240ca RS |
121 | u32 out_reg; |
122 | u32 io_conf_reg; | |
123 | u32 blink_en_reg; | |
124 | u32 in_pol_reg; | |
125 | u32 edge_mask_regs[4]; | |
126 | u32 level_mask_regs[4]; | |
fefe7b09 TP |
127 | }; |
128 | ||
129 | /* | |
130 | * Functions returning addresses of individual registers for a given | |
131 | * GPIO controller. | |
132 | */ | |
f07708c4 | 133 | static void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) |
fefe7b09 TP |
134 | { |
135 | return mvchip->membase + GPIO_OUT_OFF; | |
136 | } | |
137 | ||
f07708c4 | 138 | static void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) |
e9133760 JL |
139 | { |
140 | return mvchip->membase + GPIO_BLINK_EN_OFF; | |
141 | } | |
142 | ||
757642f9 AL |
143 | static void __iomem *mvebu_gpioreg_blink_counter_select(struct mvebu_gpio_chip |
144 | *mvchip) | |
145 | { | |
146 | return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF; | |
147 | } | |
148 | ||
f07708c4 | 149 | static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) |
fefe7b09 TP |
150 | { |
151 | return mvchip->membase + GPIO_IO_CONF_OFF; | |
152 | } | |
153 | ||
f07708c4 | 154 | static void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip) |
fefe7b09 TP |
155 | { |
156 | return mvchip->membase + GPIO_IN_POL_OFF; | |
157 | } | |
158 | ||
f07708c4 | 159 | static void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) |
fefe7b09 TP |
160 | { |
161 | return mvchip->membase + GPIO_DATA_IN_OFF; | |
162 | } | |
163 | ||
f07708c4 | 164 | static void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) |
fefe7b09 TP |
165 | { |
166 | int cpu; | |
167 | ||
f4dcd2d9 | 168 | switch (mvchip->soc_variant) { |
fefe7b09 TP |
169 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
170 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | |
171 | return mvchip->membase + GPIO_EDGE_CAUSE_OFF; | |
172 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | |
173 | cpu = smp_processor_id(); | |
a4319a61 AL |
174 | return mvchip->percpu_membase + |
175 | GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu); | |
fefe7b09 TP |
176 | default: |
177 | BUG(); | |
178 | } | |
179 | } | |
180 | ||
f07708c4 | 181 | static void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) |
fefe7b09 TP |
182 | { |
183 | int cpu; | |
184 | ||
f4dcd2d9 | 185 | switch (mvchip->soc_variant) { |
fefe7b09 TP |
186 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
187 | return mvchip->membase + GPIO_EDGE_MASK_OFF; | |
188 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | |
189 | cpu = smp_processor_id(); | |
190 | return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu); | |
191 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | |
192 | cpu = smp_processor_id(); | |
a4319a61 AL |
193 | return mvchip->percpu_membase + |
194 | GPIO_EDGE_MASK_ARMADAXP_OFF(cpu); | |
fefe7b09 TP |
195 | default: |
196 | BUG(); | |
197 | } | |
198 | } | |
199 | ||
200 | static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) | |
201 | { | |
202 | int cpu; | |
203 | ||
f4dcd2d9 | 204 | switch (mvchip->soc_variant) { |
fefe7b09 TP |
205 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
206 | return mvchip->membase + GPIO_LEVEL_MASK_OFF; | |
207 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | |
208 | cpu = smp_processor_id(); | |
209 | return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu); | |
210 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | |
211 | cpu = smp_processor_id(); | |
a4319a61 AL |
212 | return mvchip->percpu_membase + |
213 | GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu); | |
fefe7b09 TP |
214 | default: |
215 | BUG(); | |
216 | } | |
217 | } | |
218 | ||
757642f9 AL |
219 | /* |
220 | * Functions returning addresses of individual registers for a given | |
221 | * PWM controller. | |
222 | */ | |
223 | static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm) | |
224 | { | |
225 | return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF; | |
226 | } | |
227 | ||
228 | static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm) | |
229 | { | |
230 | return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF; | |
231 | } | |
232 | ||
fefe7b09 TP |
233 | /* |
234 | * Functions implementing the gpio_chip methods | |
235 | */ | |
d276de70 | 236 | static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value) |
fefe7b09 | 237 | { |
bbe76004 | 238 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
fefe7b09 TP |
239 | unsigned long flags; |
240 | u32 u; | |
241 | ||
242 | spin_lock_irqsave(&mvchip->lock, flags); | |
243 | u = readl_relaxed(mvebu_gpioreg_out(mvchip)); | |
244 | if (value) | |
d2cabc4a | 245 | u |= BIT(pin); |
fefe7b09 | 246 | else |
d2cabc4a | 247 | u &= ~BIT(pin); |
fefe7b09 TP |
248 | writel_relaxed(u, mvebu_gpioreg_out(mvchip)); |
249 | spin_unlock_irqrestore(&mvchip->lock, flags); | |
250 | } | |
251 | ||
d276de70 | 252 | static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin) |
fefe7b09 | 253 | { |
bbe76004 | 254 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
fefe7b09 TP |
255 | u32 u; |
256 | ||
d2cabc4a | 257 | if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin)) { |
fefe7b09 TP |
258 | u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^ |
259 | readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | |
260 | } else { | |
261 | u = readl_relaxed(mvebu_gpioreg_out(mvchip)); | |
262 | } | |
263 | ||
264 | return (u >> pin) & 1; | |
265 | } | |
266 | ||
d276de70 RS |
267 | static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned int pin, |
268 | int value) | |
e9133760 | 269 | { |
bbe76004 | 270 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
e9133760 JL |
271 | unsigned long flags; |
272 | u32 u; | |
273 | ||
274 | spin_lock_irqsave(&mvchip->lock, flags); | |
275 | u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); | |
276 | if (value) | |
d2cabc4a | 277 | u |= BIT(pin); |
e9133760 | 278 | else |
d2cabc4a | 279 | u &= ~BIT(pin); |
e9133760 JL |
280 | writel_relaxed(u, mvebu_gpioreg_blink(mvchip)); |
281 | spin_unlock_irqrestore(&mvchip->lock, flags); | |
282 | } | |
283 | ||
d276de70 | 284 | static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin) |
fefe7b09 | 285 | { |
bbe76004 | 286 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
fefe7b09 TP |
287 | unsigned long flags; |
288 | int ret; | |
289 | u32 u; | |
290 | ||
7077f4cc RS |
291 | /* |
292 | * Check with the pinctrl driver whether this pin is usable as | |
293 | * an input GPIO | |
294 | */ | |
fefe7b09 TP |
295 | ret = pinctrl_gpio_direction_input(chip->base + pin); |
296 | if (ret) | |
297 | return ret; | |
298 | ||
299 | spin_lock_irqsave(&mvchip->lock, flags); | |
300 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); | |
d2cabc4a | 301 | u |= BIT(pin); |
fefe7b09 TP |
302 | writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip)); |
303 | spin_unlock_irqrestore(&mvchip->lock, flags); | |
304 | ||
305 | return 0; | |
306 | } | |
307 | ||
d276de70 | 308 | static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, |
fefe7b09 TP |
309 | int value) |
310 | { | |
bbe76004 | 311 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
fefe7b09 TP |
312 | unsigned long flags; |
313 | int ret; | |
314 | u32 u; | |
315 | ||
7077f4cc RS |
316 | /* |
317 | * Check with the pinctrl driver whether this pin is usable as | |
318 | * an output GPIO | |
319 | */ | |
fefe7b09 TP |
320 | ret = pinctrl_gpio_direction_output(chip->base + pin); |
321 | if (ret) | |
322 | return ret; | |
323 | ||
e9133760 | 324 | mvebu_gpio_blink(chip, pin, 0); |
c57d75c0 TP |
325 | mvebu_gpio_set(chip, pin, value); |
326 | ||
fefe7b09 TP |
327 | spin_lock_irqsave(&mvchip->lock, flags); |
328 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); | |
d2cabc4a | 329 | u &= ~BIT(pin); |
fefe7b09 TP |
330 | writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip)); |
331 | spin_unlock_irqrestore(&mvchip->lock, flags); | |
332 | ||
333 | return 0; | |
334 | } | |
335 | ||
d276de70 | 336 | static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin) |
fefe7b09 | 337 | { |
bbe76004 | 338 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
163ad364 | 339 | |
fefe7b09 TP |
340 | return irq_create_mapping(mvchip->domain, pin); |
341 | } | |
342 | ||
343 | /* | |
344 | * Functions implementing the irq_chip methods | |
345 | */ | |
346 | static void mvebu_gpio_irq_ack(struct irq_data *d) | |
347 | { | |
348 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
349 | struct mvebu_gpio_chip *mvchip = gc->private; | |
812d4788 | 350 | u32 mask = d->mask; |
fefe7b09 TP |
351 | |
352 | irq_gc_lock(gc); | |
812d4788 | 353 | writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip)); |
fefe7b09 TP |
354 | irq_gc_unlock(gc); |
355 | } | |
356 | ||
357 | static void mvebu_gpio_edge_irq_mask(struct irq_data *d) | |
358 | { | |
359 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
360 | struct mvebu_gpio_chip *mvchip = gc->private; | |
61819549 | 361 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
812d4788 | 362 | u32 mask = d->mask; |
fefe7b09 TP |
363 | |
364 | irq_gc_lock(gc); | |
61819549 GC |
365 | ct->mask_cache_priv &= ~mask; |
366 | ||
367 | writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); | |
fefe7b09 TP |
368 | irq_gc_unlock(gc); |
369 | } | |
370 | ||
371 | static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) | |
372 | { | |
373 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
374 | struct mvebu_gpio_chip *mvchip = gc->private; | |
61819549 | 375 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
812d4788 | 376 | u32 mask = d->mask; |
fefe7b09 TP |
377 | |
378 | irq_gc_lock(gc); | |
61819549 GC |
379 | ct->mask_cache_priv |= mask; |
380 | writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); | |
fefe7b09 TP |
381 | irq_gc_unlock(gc); |
382 | } | |
383 | ||
384 | static void mvebu_gpio_level_irq_mask(struct irq_data *d) | |
385 | { | |
386 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
387 | struct mvebu_gpio_chip *mvchip = gc->private; | |
61819549 | 388 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
812d4788 | 389 | u32 mask = d->mask; |
fefe7b09 TP |
390 | |
391 | irq_gc_lock(gc); | |
61819549 GC |
392 | ct->mask_cache_priv &= ~mask; |
393 | writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); | |
fefe7b09 TP |
394 | irq_gc_unlock(gc); |
395 | } | |
396 | ||
397 | static void mvebu_gpio_level_irq_unmask(struct irq_data *d) | |
398 | { | |
399 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
400 | struct mvebu_gpio_chip *mvchip = gc->private; | |
61819549 | 401 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
812d4788 | 402 | u32 mask = d->mask; |
fefe7b09 TP |
403 | |
404 | irq_gc_lock(gc); | |
61819549 GC |
405 | ct->mask_cache_priv |= mask; |
406 | writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); | |
fefe7b09 TP |
407 | irq_gc_unlock(gc); |
408 | } | |
409 | ||
410 | /***************************************************************************** | |
411 | * MVEBU GPIO IRQ | |
412 | * | |
413 | * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same | |
414 | * value of the line or the opposite value. | |
415 | * | |
416 | * Level IRQ handlers: DATA_IN is used directly as cause register. | |
a4319a61 | 417 | * Interrupt are masked by LEVEL_MASK registers. |
fefe7b09 | 418 | * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. |
a4319a61 | 419 | * Interrupt are masked by EDGE_MASK registers. |
fefe7b09 | 420 | * Both-edge handlers: Similar to regular Edge handlers, but also swaps |
a4319a61 AL |
421 | * the polarity to catch the next line transaction. |
422 | * This is a race condition that might not perfectly | |
423 | * work on some use cases. | |
fefe7b09 TP |
424 | * |
425 | * Every eight GPIO lines are grouped (OR'ed) before going up to main | |
426 | * cause register. | |
427 | * | |
a4319a61 AL |
428 | * EDGE cause mask |
429 | * data-in /--------| |-----| |----\ | |
430 | * -----| |----- ---- to main cause reg | |
431 | * X \----------------| |----/ | |
432 | * polarity LEVEL mask | |
fefe7b09 TP |
433 | * |
434 | ****************************************************************************/ | |
435 | ||
436 | static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |
437 | { | |
438 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
439 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | |
440 | struct mvebu_gpio_chip *mvchip = gc->private; | |
441 | int pin; | |
442 | u32 u; | |
443 | ||
444 | pin = d->hwirq; | |
445 | ||
d2cabc4a | 446 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin); |
a4319a61 | 447 | if (!u) |
fefe7b09 | 448 | return -EINVAL; |
fefe7b09 TP |
449 | |
450 | type &= IRQ_TYPE_SENSE_MASK; | |
451 | if (type == IRQ_TYPE_NONE) | |
452 | return -EINVAL; | |
453 | ||
454 | /* Check if we need to change chip and handler */ | |
455 | if (!(ct->type & type)) | |
456 | if (irq_setup_alt_chip(d, type)) | |
457 | return -EINVAL; | |
458 | ||
459 | /* | |
460 | * Configure interrupt polarity. | |
461 | */ | |
f4dcd2d9 | 462 | switch (type) { |
fefe7b09 TP |
463 | case IRQ_TYPE_EDGE_RISING: |
464 | case IRQ_TYPE_LEVEL_HIGH: | |
465 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | |
d2cabc4a | 466 | u &= ~BIT(pin); |
fefe7b09 | 467 | writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); |
7cf8c9f7 | 468 | break; |
fefe7b09 TP |
469 | case IRQ_TYPE_EDGE_FALLING: |
470 | case IRQ_TYPE_LEVEL_LOW: | |
471 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | |
d2cabc4a | 472 | u |= BIT(pin); |
fefe7b09 | 473 | writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); |
7cf8c9f7 | 474 | break; |
fefe7b09 TP |
475 | case IRQ_TYPE_EDGE_BOTH: { |
476 | u32 v; | |
477 | ||
478 | v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^ | |
479 | readl_relaxed(mvebu_gpioreg_data_in(mvchip)); | |
480 | ||
481 | /* | |
482 | * set initial polarity based on current input level | |
483 | */ | |
484 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | |
d2cabc4a RS |
485 | if (v & BIT(pin)) |
486 | u |= BIT(pin); /* falling */ | |
fefe7b09 | 487 | else |
d2cabc4a | 488 | u &= ~BIT(pin); /* rising */ |
fefe7b09 | 489 | writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); |
7cf8c9f7 | 490 | break; |
fefe7b09 TP |
491 | } |
492 | } | |
493 | return 0; | |
494 | } | |
495 | ||
bd0b9ac4 | 496 | static void mvebu_gpio_irq_handler(struct irq_desc *desc) |
fefe7b09 | 497 | { |
476f8b4c | 498 | struct mvebu_gpio_chip *mvchip = irq_desc_get_handler_data(desc); |
01ca59f1 | 499 | struct irq_chip *chip = irq_desc_get_chip(desc); |
fefe7b09 TP |
500 | u32 cause, type; |
501 | int i; | |
502 | ||
503 | if (mvchip == NULL) | |
504 | return; | |
505 | ||
01ca59f1 TP |
506 | chained_irq_enter(chip, desc); |
507 | ||
fefe7b09 TP |
508 | cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) & |
509 | readl_relaxed(mvebu_gpioreg_level_mask(mvchip)); | |
510 | cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) & | |
511 | readl_relaxed(mvebu_gpioreg_edge_mask(mvchip)); | |
512 | ||
513 | for (i = 0; i < mvchip->chip.ngpio; i++) { | |
514 | int irq; | |
515 | ||
812d4788 | 516 | irq = irq_find_mapping(mvchip->domain, i); |
fefe7b09 | 517 | |
d2cabc4a | 518 | if (!(cause & BIT(i))) |
fefe7b09 TP |
519 | continue; |
520 | ||
fb90c22a | 521 | type = irq_get_trigger_type(irq); |
fefe7b09 TP |
522 | if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { |
523 | /* Swap polarity (race with GPIO line) */ | |
524 | u32 polarity; | |
525 | ||
526 | polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | |
d2cabc4a | 527 | polarity ^= BIT(i); |
fefe7b09 TP |
528 | writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip)); |
529 | } | |
01ca59f1 | 530 | |
fefe7b09 TP |
531 | generic_handle_irq(irq); |
532 | } | |
01ca59f1 TP |
533 | |
534 | chained_irq_exit(chip, desc); | |
fefe7b09 TP |
535 | } |
536 | ||
757642f9 AL |
537 | /* |
538 | * Functions implementing the pwm_chip methods | |
539 | */ | |
540 | static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip) | |
541 | { | |
542 | return container_of(chip, struct mvebu_pwm, chip); | |
543 | } | |
544 | ||
545 | static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | |
546 | { | |
547 | struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); | |
548 | struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; | |
549 | struct gpio_desc *desc; | |
550 | unsigned long flags; | |
551 | int ret = 0; | |
552 | ||
553 | spin_lock_irqsave(&mvpwm->lock, flags); | |
554 | ||
555 | if (mvpwm->gpiod) { | |
556 | ret = -EBUSY; | |
557 | } else { | |
558 | desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm); | |
559 | if (!desc) { | |
560 | ret = -ENODEV; | |
561 | goto out; | |
562 | } | |
563 | ||
564 | ret = gpiod_request(desc, "mvebu-pwm"); | |
565 | if (ret) | |
566 | goto out; | |
567 | ||
568 | ret = gpiod_direction_output(desc, 0); | |
569 | if (ret) { | |
570 | gpiod_free(desc); | |
571 | goto out; | |
572 | } | |
573 | ||
574 | mvpwm->gpiod = desc; | |
575 | } | |
576 | out: | |
577 | spin_unlock_irqrestore(&mvpwm->lock, flags); | |
578 | return ret; | |
579 | } | |
580 | ||
581 | static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | |
582 | { | |
583 | struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); | |
584 | unsigned long flags; | |
585 | ||
586 | spin_lock_irqsave(&mvpwm->lock, flags); | |
587 | gpiod_free(mvpwm->gpiod); | |
588 | mvpwm->gpiod = NULL; | |
589 | spin_unlock_irqrestore(&mvpwm->lock, flags); | |
590 | } | |
591 | ||
592 | static void mvebu_pwm_get_state(struct pwm_chip *chip, | |
593 | struct pwm_device *pwm, | |
594 | struct pwm_state *state) { | |
595 | ||
596 | struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); | |
597 | struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; | |
598 | unsigned long long val; | |
599 | unsigned long flags; | |
600 | u32 u; | |
601 | ||
602 | spin_lock_irqsave(&mvpwm->lock, flags); | |
603 | ||
604 | val = (unsigned long long) | |
605 | readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); | |
606 | val *= NSEC_PER_SEC; | |
607 | do_div(val, mvpwm->clk_rate); | |
608 | if (val > UINT_MAX) | |
609 | state->duty_cycle = UINT_MAX; | |
610 | else if (val) | |
611 | state->duty_cycle = val; | |
612 | else | |
613 | state->duty_cycle = 1; | |
614 | ||
615 | val = (unsigned long long) | |
616 | readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); | |
617 | val *= NSEC_PER_SEC; | |
618 | do_div(val, mvpwm->clk_rate); | |
619 | if (val < state->duty_cycle) { | |
620 | state->period = 1; | |
621 | } else { | |
622 | val -= state->duty_cycle; | |
623 | if (val > UINT_MAX) | |
624 | state->period = UINT_MAX; | |
625 | else if (val) | |
626 | state->period = val; | |
627 | else | |
628 | state->period = 1; | |
629 | } | |
630 | ||
631 | u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); | |
632 | if (u) | |
633 | state->enabled = true; | |
634 | else | |
635 | state->enabled = false; | |
636 | ||
637 | spin_unlock_irqrestore(&mvpwm->lock, flags); | |
638 | } | |
639 | ||
640 | static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |
641 | struct pwm_state *state) | |
642 | { | |
643 | struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); | |
644 | struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; | |
645 | unsigned long long val; | |
646 | unsigned long flags; | |
647 | unsigned int on, off; | |
648 | ||
649 | val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle; | |
650 | do_div(val, NSEC_PER_SEC); | |
651 | if (val > UINT_MAX) | |
652 | return -EINVAL; | |
653 | if (val) | |
654 | on = val; | |
655 | else | |
656 | on = 1; | |
657 | ||
658 | val = (unsigned long long) mvpwm->clk_rate * | |
659 | (state->period - state->duty_cycle); | |
660 | do_div(val, NSEC_PER_SEC); | |
661 | if (val > UINT_MAX) | |
662 | return -EINVAL; | |
663 | if (val) | |
664 | off = val; | |
665 | else | |
666 | off = 1; | |
667 | ||
668 | spin_lock_irqsave(&mvpwm->lock, flags); | |
669 | ||
670 | writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm)); | |
671 | writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm)); | |
672 | if (state->enabled) | |
673 | mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1); | |
674 | else | |
675 | mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0); | |
676 | ||
677 | spin_unlock_irqrestore(&mvpwm->lock, flags); | |
678 | ||
679 | return 0; | |
680 | } | |
681 | ||
682 | static const struct pwm_ops mvebu_pwm_ops = { | |
683 | .request = mvebu_pwm_request, | |
684 | .free = mvebu_pwm_free, | |
685 | .get_state = mvebu_pwm_get_state, | |
686 | .apply = mvebu_pwm_apply, | |
687 | .owner = THIS_MODULE, | |
688 | }; | |
689 | ||
690 | static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) | |
691 | { | |
692 | struct mvebu_pwm *mvpwm = mvchip->mvpwm; | |
693 | ||
694 | mvpwm->blink_select = | |
695 | readl_relaxed(mvebu_gpioreg_blink_counter_select(mvchip)); | |
696 | mvpwm->blink_on_duration = | |
697 | readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); | |
698 | mvpwm->blink_off_duration = | |
699 | readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); | |
700 | } | |
701 | ||
702 | static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) | |
703 | { | |
704 | struct mvebu_pwm *mvpwm = mvchip->mvpwm; | |
705 | ||
706 | writel_relaxed(mvpwm->blink_select, | |
707 | mvebu_gpioreg_blink_counter_select(mvchip)); | |
708 | writel_relaxed(mvpwm->blink_on_duration, | |
709 | mvebu_pwmreg_blink_on_duration(mvpwm)); | |
710 | writel_relaxed(mvpwm->blink_off_duration, | |
711 | mvebu_pwmreg_blink_off_duration(mvpwm)); | |
712 | } | |
713 | ||
714 | static int mvebu_pwm_probe(struct platform_device *pdev, | |
715 | struct mvebu_gpio_chip *mvchip, | |
716 | int id) | |
717 | { | |
718 | struct device *dev = &pdev->dev; | |
719 | struct mvebu_pwm *mvpwm; | |
720 | struct resource *res; | |
721 | u32 set; | |
722 | ||
723 | if (!of_device_is_compatible(mvchip->chip.of_node, | |
6c7515c6 | 724 | "marvell,armada-370-gpio")) |
757642f9 AL |
725 | return 0; |
726 | ||
727 | if (IS_ERR(mvchip->clk)) | |
728 | return PTR_ERR(mvchip->clk); | |
729 | ||
730 | /* | |
731 | * There are only two sets of PWM configuration registers for | |
732 | * all the GPIO lines on those SoCs which this driver reserves | |
733 | * for the first two GPIO chips. So if the resource is missing | |
734 | * we can't treat it as an error. | |
735 | */ | |
736 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"); | |
737 | if (!res) | |
738 | return 0; | |
739 | ||
740 | /* | |
741 | * Use set A for lines of GPIO chip with id 0, B for GPIO chip | |
742 | * with id 1. Don't allow further GPIO chips to be used for PWM. | |
743 | */ | |
744 | if (id == 0) | |
745 | set = 0; | |
746 | else if (id == 1) | |
747 | set = U32_MAX; | |
748 | else | |
749 | return -EINVAL; | |
c528eb27 | 750 | writel_relaxed(set, mvebu_gpioreg_blink_counter_select(mvchip)); |
757642f9 AL |
751 | |
752 | mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL); | |
753 | if (!mvpwm) | |
754 | return -ENOMEM; | |
755 | mvchip->mvpwm = mvpwm; | |
756 | mvpwm->mvchip = mvchip; | |
757 | ||
758 | mvpwm->membase = devm_ioremap_resource(dev, res); | |
759 | if (IS_ERR(mvpwm->membase)) | |
760 | return PTR_ERR(mvpwm->membase); | |
761 | ||
762 | mvpwm->clk_rate = clk_get_rate(mvchip->clk); | |
763 | if (!mvpwm->clk_rate) { | |
764 | dev_err(dev, "failed to get clock rate\n"); | |
765 | return -EINVAL; | |
766 | } | |
767 | ||
768 | mvpwm->chip.dev = dev; | |
769 | mvpwm->chip.ops = &mvebu_pwm_ops; | |
770 | mvpwm->chip.npwm = mvchip->chip.ngpio; | |
fc7a9068 RG |
771 | /* |
772 | * There may already be some PWM allocated, so we can't force | |
773 | * mvpwm->chip.base to a fixed point like mvchip->chip.base. | |
774 | * So, we let pwmchip_add() do the numbering and take the next free | |
775 | * region. | |
776 | */ | |
777 | mvpwm->chip.base = -1; | |
757642f9 AL |
778 | |
779 | spin_lock_init(&mvpwm->lock); | |
780 | ||
781 | return pwmchip_add(&mvpwm->chip); | |
782 | } | |
783 | ||
a4ba5e1b SG |
784 | #ifdef CONFIG_DEBUG_FS |
785 | #include <linux/seq_file.h> | |
786 | ||
787 | static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |
788 | { | |
bbe76004 | 789 | struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); |
a4ba5e1b SG |
790 | u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk; |
791 | int i; | |
792 | ||
793 | out = readl_relaxed(mvebu_gpioreg_out(mvchip)); | |
794 | io_conf = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); | |
795 | blink = readl_relaxed(mvebu_gpioreg_blink(mvchip)); | |
796 | in_pol = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | |
797 | data_in = readl_relaxed(mvebu_gpioreg_data_in(mvchip)); | |
798 | cause = readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)); | |
799 | edg_msk = readl_relaxed(mvebu_gpioreg_edge_mask(mvchip)); | |
800 | lvl_msk = readl_relaxed(mvebu_gpioreg_level_mask(mvchip)); | |
801 | ||
802 | for (i = 0; i < chip->ngpio; i++) { | |
803 | const char *label; | |
804 | u32 msk; | |
805 | bool is_out; | |
806 | ||
807 | label = gpiochip_is_requested(chip, i); | |
808 | if (!label) | |
809 | continue; | |
810 | ||
d2cabc4a | 811 | msk = BIT(i); |
a4ba5e1b SG |
812 | is_out = !(io_conf & msk); |
813 | ||
814 | seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label); | |
815 | ||
816 | if (is_out) { | |
817 | seq_printf(s, " out %s %s\n", | |
818 | out & msk ? "hi" : "lo", | |
819 | blink & msk ? "(blink )" : ""); | |
820 | continue; | |
821 | } | |
822 | ||
823 | seq_printf(s, " in %s (act %s) - IRQ", | |
824 | (data_in ^ in_pol) & msk ? "hi" : "lo", | |
825 | in_pol & msk ? "lo" : "hi"); | |
826 | if (!((edg_msk | lvl_msk) & msk)) { | |
a4319a61 | 827 | seq_puts(s, " disabled\n"); |
a4ba5e1b SG |
828 | continue; |
829 | } | |
830 | if (edg_msk & msk) | |
a4319a61 | 831 | seq_puts(s, " edge "); |
a4ba5e1b | 832 | if (lvl_msk & msk) |
a4319a61 | 833 | seq_puts(s, " level"); |
a4ba5e1b SG |
834 | seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); |
835 | } | |
836 | } | |
837 | #else | |
838 | #define mvebu_gpio_dbg_show NULL | |
839 | #endif | |
840 | ||
271b17b6 | 841 | static const struct of_device_id mvebu_gpio_of_match[] = { |
fefe7b09 TP |
842 | { |
843 | .compatible = "marvell,orion-gpio", | |
a4319a61 | 844 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, |
fefe7b09 TP |
845 | }, |
846 | { | |
847 | .compatible = "marvell,mv78200-gpio", | |
a4319a61 | 848 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_MV78200, |
fefe7b09 TP |
849 | }, |
850 | { | |
851 | .compatible = "marvell,armadaxp-gpio", | |
a4319a61 | 852 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, |
fefe7b09 | 853 | }, |
757642f9 | 854 | { |
6c7515c6 | 855 | .compatible = "marvell,armada-370-gpio", |
757642f9 AL |
856 | .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, |
857 | }, | |
fefe7b09 TP |
858 | { |
859 | /* sentinel */ | |
860 | }, | |
861 | }; | |
fefe7b09 | 862 | |
b5b7b487 TP |
863 | static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) |
864 | { | |
865 | struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev); | |
866 | int i; | |
867 | ||
868 | mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip)); | |
869 | mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip)); | |
870 | mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip)); | |
871 | mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip)); | |
872 | ||
873 | switch (mvchip->soc_variant) { | |
874 | case MVEBU_GPIO_SOC_VARIANT_ORION: | |
875 | mvchip->edge_mask_regs[0] = | |
876 | readl(mvchip->membase + GPIO_EDGE_MASK_OFF); | |
877 | mvchip->level_mask_regs[0] = | |
878 | readl(mvchip->membase + GPIO_LEVEL_MASK_OFF); | |
879 | break; | |
880 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | |
881 | for (i = 0; i < 2; i++) { | |
882 | mvchip->edge_mask_regs[i] = | |
883 | readl(mvchip->membase + | |
884 | GPIO_EDGE_MASK_MV78200_OFF(i)); | |
885 | mvchip->level_mask_regs[i] = | |
886 | readl(mvchip->membase + | |
887 | GPIO_LEVEL_MASK_MV78200_OFF(i)); | |
888 | } | |
889 | break; | |
890 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | |
891 | for (i = 0; i < 4; i++) { | |
892 | mvchip->edge_mask_regs[i] = | |
893 | readl(mvchip->membase + | |
894 | GPIO_EDGE_MASK_ARMADAXP_OFF(i)); | |
895 | mvchip->level_mask_regs[i] = | |
896 | readl(mvchip->membase + | |
897 | GPIO_LEVEL_MASK_ARMADAXP_OFF(i)); | |
898 | } | |
899 | break; | |
900 | default: | |
901 | BUG(); | |
902 | } | |
903 | ||
757642f9 AL |
904 | if (IS_ENABLED(CONFIG_PWM)) |
905 | mvebu_pwm_suspend(mvchip); | |
906 | ||
b5b7b487 TP |
907 | return 0; |
908 | } | |
909 | ||
910 | static int mvebu_gpio_resume(struct platform_device *pdev) | |
911 | { | |
912 | struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev); | |
913 | int i; | |
914 | ||
915 | writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip)); | |
916 | writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip)); | |
917 | writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip)); | |
918 | writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip)); | |
919 | ||
920 | switch (mvchip->soc_variant) { | |
921 | case MVEBU_GPIO_SOC_VARIANT_ORION: | |
922 | writel(mvchip->edge_mask_regs[0], | |
923 | mvchip->membase + GPIO_EDGE_MASK_OFF); | |
924 | writel(mvchip->level_mask_regs[0], | |
925 | mvchip->membase + GPIO_LEVEL_MASK_OFF); | |
926 | break; | |
927 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | |
928 | for (i = 0; i < 2; i++) { | |
929 | writel(mvchip->edge_mask_regs[i], | |
930 | mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i)); | |
931 | writel(mvchip->level_mask_regs[i], | |
932 | mvchip->membase + | |
933 | GPIO_LEVEL_MASK_MV78200_OFF(i)); | |
934 | } | |
935 | break; | |
936 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | |
937 | for (i = 0; i < 4; i++) { | |
938 | writel(mvchip->edge_mask_regs[i], | |
939 | mvchip->membase + | |
940 | GPIO_EDGE_MASK_ARMADAXP_OFF(i)); | |
941 | writel(mvchip->level_mask_regs[i], | |
942 | mvchip->membase + | |
943 | GPIO_LEVEL_MASK_ARMADAXP_OFF(i)); | |
944 | } | |
945 | break; | |
946 | default: | |
947 | BUG(); | |
948 | } | |
949 | ||
757642f9 AL |
950 | if (IS_ENABLED(CONFIG_PWM)) |
951 | mvebu_pwm_resume(mvchip); | |
952 | ||
b5b7b487 TP |
953 | return 0; |
954 | } | |
955 | ||
3836309d | 956 | static int mvebu_gpio_probe(struct platform_device *pdev) |
fefe7b09 TP |
957 | { |
958 | struct mvebu_gpio_chip *mvchip; | |
959 | const struct of_device_id *match; | |
960 | struct device_node *np = pdev->dev.of_node; | |
961 | struct resource *res; | |
962 | struct irq_chip_generic *gc; | |
963 | struct irq_chip_type *ct; | |
964 | unsigned int ngpios; | |
812d4788 | 965 | bool have_irqs; |
fefe7b09 TP |
966 | int soc_variant; |
967 | int i, cpu, id; | |
f1d2d081 | 968 | int err; |
fefe7b09 TP |
969 | |
970 | match = of_match_device(mvebu_gpio_of_match, &pdev->dev); | |
971 | if (match) | |
f0d50460 | 972 | soc_variant = (unsigned long) match->data; |
fefe7b09 TP |
973 | else |
974 | soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; | |
975 | ||
812d4788 JG |
976 | /* Some gpio controllers do not provide irq support */ |
977 | have_irqs = of_irq_count(np) != 0; | |
978 | ||
a4319a61 AL |
979 | mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), |
980 | GFP_KERNEL); | |
6c8365f6 | 981 | if (!mvchip) |
fefe7b09 | 982 | return -ENOMEM; |
fefe7b09 | 983 | |
b5b7b487 TP |
984 | platform_set_drvdata(pdev, mvchip); |
985 | ||
fefe7b09 TP |
986 | if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { |
987 | dev_err(&pdev->dev, "Missing ngpios OF property\n"); | |
988 | return -ENODEV; | |
989 | } | |
990 | ||
991 | id = of_alias_get_id(pdev->dev.of_node, "gpio"); | |
992 | if (id < 0) { | |
993 | dev_err(&pdev->dev, "Couldn't get OF id\n"); | |
994 | return id; | |
995 | } | |
996 | ||
757642f9 | 997 | mvchip->clk = devm_clk_get(&pdev->dev, NULL); |
de88747f | 998 | /* Not all SoCs require a clock.*/ |
757642f9 AL |
999 | if (!IS_ERR(mvchip->clk)) |
1000 | clk_prepare_enable(mvchip->clk); | |
de88747f | 1001 | |
fefe7b09 TP |
1002 | mvchip->soc_variant = soc_variant; |
1003 | mvchip->chip.label = dev_name(&pdev->dev); | |
58383c78 | 1004 | mvchip->chip.parent = &pdev->dev; |
203f0daa JG |
1005 | mvchip->chip.request = gpiochip_generic_request; |
1006 | mvchip->chip.free = gpiochip_generic_free; | |
fefe7b09 TP |
1007 | mvchip->chip.direction_input = mvebu_gpio_direction_input; |
1008 | mvchip->chip.get = mvebu_gpio_get; | |
1009 | mvchip->chip.direction_output = mvebu_gpio_direction_output; | |
1010 | mvchip->chip.set = mvebu_gpio_set; | |
812d4788 JG |
1011 | if (have_irqs) |
1012 | mvchip->chip.to_irq = mvebu_gpio_to_irq; | |
fefe7b09 TP |
1013 | mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; |
1014 | mvchip->chip.ngpio = ngpios; | |
9fb1f39e | 1015 | mvchip->chip.can_sleep = false; |
fefe7b09 | 1016 | mvchip->chip.of_node = np; |
a4ba5e1b | 1017 | mvchip->chip.dbg_show = mvebu_gpio_dbg_show; |
fefe7b09 TP |
1018 | |
1019 | spin_lock_init(&mvchip->lock); | |
08a67a58 | 1020 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
641d0342 | 1021 | mvchip->membase = devm_ioremap_resource(&pdev->dev, res); |
422d26b6 | 1022 | if (IS_ERR(mvchip->membase)) |
641d0342 | 1023 | return PTR_ERR(mvchip->membase); |
fefe7b09 | 1024 | |
7077f4cc RS |
1025 | /* |
1026 | * The Armada XP has a second range of registers for the | |
1027 | * per-CPU registers | |
1028 | */ | |
fefe7b09 TP |
1029 | if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) { |
1030 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
641d0342 TR |
1031 | mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev, |
1032 | res); | |
f4dcd2d9 | 1033 | if (IS_ERR(mvchip->percpu_membase)) |
641d0342 | 1034 | return PTR_ERR(mvchip->percpu_membase); |
fefe7b09 TP |
1035 | } |
1036 | ||
1037 | /* | |
1038 | * Mask and clear GPIO interrupts. | |
1039 | */ | |
f4dcd2d9 | 1040 | switch (soc_variant) { |
fefe7b09 TP |
1041 | case MVEBU_GPIO_SOC_VARIANT_ORION: |
1042 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | |
1043 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF); | |
1044 | writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF); | |
1045 | break; | |
1046 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | |
1047 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | |
1048 | for (cpu = 0; cpu < 2; cpu++) { | |
1049 | writel_relaxed(0, mvchip->membase + | |
1050 | GPIO_EDGE_MASK_MV78200_OFF(cpu)); | |
1051 | writel_relaxed(0, mvchip->membase + | |
1052 | GPIO_LEVEL_MASK_MV78200_OFF(cpu)); | |
1053 | } | |
1054 | break; | |
1055 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | |
1056 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | |
1057 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF); | |
1058 | writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF); | |
1059 | for (cpu = 0; cpu < 4; cpu++) { | |
1060 | writel_relaxed(0, mvchip->percpu_membase + | |
1061 | GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu)); | |
1062 | writel_relaxed(0, mvchip->percpu_membase + | |
1063 | GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)); | |
1064 | writel_relaxed(0, mvchip->percpu_membase + | |
1065 | GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu)); | |
1066 | } | |
1067 | break; | |
1068 | default: | |
1069 | BUG(); | |
1070 | } | |
1071 | ||
00b9ab4a | 1072 | devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip); |
fefe7b09 TP |
1073 | |
1074 | /* Some gpio controllers do not provide irq support */ | |
812d4788 | 1075 | if (!have_irqs) |
fefe7b09 TP |
1076 | return 0; |
1077 | ||
812d4788 JG |
1078 | mvchip->domain = |
1079 | irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL); | |
1080 | if (!mvchip->domain) { | |
1081 | dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", | |
1082 | mvchip->chip.label); | |
1083 | return -ENODEV; | |
fefe7b09 TP |
1084 | } |
1085 | ||
812d4788 JG |
1086 | err = irq_alloc_domain_generic_chips( |
1087 | mvchip->domain, ngpios, 2, np->name, handle_level_irq, | |
1088 | IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0); | |
1089 | if (err) { | |
1090 | dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n", | |
1091 | mvchip->chip.label); | |
1092 | goto err_domain; | |
fefe7b09 TP |
1093 | } |
1094 | ||
899c37ed RS |
1095 | /* |
1096 | * NOTE: The common accessors cannot be used because of the percpu | |
812d4788 JG |
1097 | * access to the mask registers |
1098 | */ | |
1099 | gc = irq_get_domain_generic_chip(mvchip->domain, 0); | |
fefe7b09 TP |
1100 | gc->private = mvchip; |
1101 | ct = &gc->chip_types[0]; | |
1102 | ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; | |
1103 | ct->chip.irq_mask = mvebu_gpio_level_irq_mask; | |
1104 | ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask; | |
1105 | ct->chip.irq_set_type = mvebu_gpio_irq_set_type; | |
1106 | ct->chip.name = mvchip->chip.label; | |
1107 | ||
1108 | ct = &gc->chip_types[1]; | |
1109 | ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | |
1110 | ct->chip.irq_ack = mvebu_gpio_irq_ack; | |
1111 | ct->chip.irq_mask = mvebu_gpio_edge_irq_mask; | |
1112 | ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask; | |
1113 | ct->chip.irq_set_type = mvebu_gpio_irq_set_type; | |
1114 | ct->handler = handle_edge_irq; | |
1115 | ct->chip.name = mvchip->chip.label; | |
1116 | ||
899c37ed RS |
1117 | /* |
1118 | * Setup the interrupt handlers. Each chip can have up to 4 | |
812d4788 JG |
1119 | * interrupt handlers, with each handler dealing with 8 GPIO |
1120 | * pins. | |
1121 | */ | |
1122 | for (i = 0; i < 4; i++) { | |
1123 | int irq = platform_get_irq(pdev, i); | |
fefe7b09 | 1124 | |
812d4788 JG |
1125 | if (irq < 0) |
1126 | continue; | |
1127 | irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler, | |
1128 | mvchip); | |
fefe7b09 TP |
1129 | } |
1130 | ||
6c7515c6 | 1131 | /* Some MVEBU SoCs have simple PWM support for GPIO lines */ |
757642f9 AL |
1132 | if (IS_ENABLED(CONFIG_PWM)) |
1133 | return mvebu_pwm_probe(pdev, mvchip, id); | |
1134 | ||
fefe7b09 | 1135 | return 0; |
f1d2d081 | 1136 | |
812d4788 JG |
1137 | err_domain: |
1138 | irq_domain_remove(mvchip->domain); | |
f1d2d081 | 1139 | |
f1d2d081 | 1140 | return err; |
fefe7b09 TP |
1141 | } |
1142 | ||
1143 | static struct platform_driver mvebu_gpio_driver = { | |
1144 | .driver = { | |
a4319a61 | 1145 | .name = "mvebu-gpio", |
fefe7b09 TP |
1146 | .of_match_table = mvebu_gpio_of_match, |
1147 | }, | |
1148 | .probe = mvebu_gpio_probe, | |
b5b7b487 TP |
1149 | .suspend = mvebu_gpio_suspend, |
1150 | .resume = mvebu_gpio_resume, | |
fefe7b09 | 1151 | }; |
ed329f3a | 1152 | builtin_platform_driver(mvebu_gpio_driver); |