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