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