summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2019-04-29 02:43:07 -0400
committerOlof Johansson <olof@lixom.net>2019-04-29 02:43:07 -0400
commit1895ef4ef229ec1873a78ce31fe50b38cfd2b58a (patch)
tree0db44f6e89cfa0bb732a262362d9748a27788b5b /drivers/gpio
parent6a508f98d95e355a40064e23643756773f4092bd (diff)
parent1fae0ad1e2032a603f93d4ad752bfa6fe7c9b887 (diff)
Merge tag 'ixp4xx-for-armsoc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik into arm/soc
This modernizes the IXP4xx platform and adds initial Device Tree Support. We migrate to MULTI_IRQ_HANDLER, bumps the IRQs to offset 16, converts to SPARSE_IRQ, then we add proper subsystem drivers in each subsystem for irqchip, GPIO and clocksource and switch over to using these new drivers. Next we modernize the NPE and QMGR drivers and push them down into drivers/soc. This has been tested on the IXP4xx NSLU2 and the Gateworks GW2358-4. * tag 'ixp4xx-for-armsoc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik: (31 commits) ARM: dts: Add queue manager and NPE to the IXP4xx DTSI soc: ixp4xx: qmgr: Add DT probe code soc: ixp4xx: qmgr: Add DT bindings for IXP4xx qmgr soc: ixp4xx: npe: Add DT probe code soc: ixp4xx: Add DT bindings for IXP4xx NPE soc: ixp4xx: qmgr: Pass resources soc: ixp4xx: Remove unused functions soc: ixp4xx: Uninline several functions soc: ixp4xx: npe: Pass addresses as resources ARM: ixp4xx: Turn the QMGR into a platform device ARM: ixp4xx: Turn the NPE into a platform device ARM: ixp4xx: Move IXP4xx QMGR and NPE headers ARM: ixp4xx: Move NPE and QMGR to drivers/soc ARM: dts: Add some initial IXP4xx device trees ARM: ixp4xx: Add device tree boot support ARM: ixp4xx: Add DT bindings gpio: ixp4xx: Add OF probing support gpio: ixp4xx: Add DT bindings clocksource/drivers/ixp4xx: Add OF initialization support clocksource/drivers/ixp4xx: Add DT bindings ... Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig13
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-ixp4xx.c474
3 files changed, 488 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3f50526a771f..a77b3b25a779 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -287,6 +287,19 @@ config GPIO_IOP
287 287
288 If unsure, say N. 288 If unsure, say N.
289 289
290config GPIO_IXP4XX
291 bool "Intel IXP4xx GPIO"
292 depends on ARM # For <asm/mach-types.h>
293 depends on ARCH_IXP4XX
294 select GPIO_GENERIC
295 select IRQ_DOMAIN
296 select IRQ_DOMAIN_HIERARCHY
297 help
298 Say yes here to support the GPIO functionality of a number of Intel
299 IXP4xx series of chips.
300
301 If unsure, say N.
302
290config GPIO_LOONGSON 303config GPIO_LOONGSON
291 bool "Loongson-2/3 GPIO support" 304 bool "Loongson-2/3 GPIO support"
292 depends on CPU_LOONGSON2 || CPU_LOONGSON3 305 depends on CPU_LOONGSON2 || CPU_LOONGSON3
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 54d55274b93a..1ee5dab9c3cf 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
61obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o 61obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
62obj-$(CONFIG_GPIO_ICH) += gpio-ich.o 62obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
63obj-$(CONFIG_GPIO_IOP) += gpio-iop.o 63obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
64obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
64obj-$(CONFIG_GPIO_IT87) += gpio-it87.o 65obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
65obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o 66obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
66obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o 67obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
new file mode 100644
index 000000000000..4b1cf7ea858d
--- /dev/null
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -0,0 +1,474 @@
1// SPDX-License-Identifier: GPL-2.0
2//
3// IXP4 GPIO driver
4// Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
5//
6// based on previous work and know-how from:
7// Deepak Saxena <dsaxena@plexity.net>
8
9#include <linux/gpio/driver.h>
10#include <linux/io.h>
11#include <linux/irq.h>
12#include <linux/irqdomain.h>
13#include <linux/irqchip.h>
14#include <linux/of_irq.h>
15#include <linux/platform_device.h>
16#include <linux/bitops.h>
17/* Include that go away with DT transition */
18#include <linux/irqchip/irq-ixp4xx.h>
19
20#include <asm/mach-types.h>
21
22#define IXP4XX_REG_GPOUT 0x00
23#define IXP4XX_REG_GPOE 0x04
24#define IXP4XX_REG_GPIN 0x08
25#define IXP4XX_REG_GPIS 0x0C
26#define IXP4XX_REG_GPIT1 0x10
27#define IXP4XX_REG_GPIT2 0x14
28#define IXP4XX_REG_GPCLK 0x18
29#define IXP4XX_REG_GPDBSEL 0x1C
30
31/*
32 * The hardware uses 3 bits to indicate interrupt "style".
33 * we clear and set these three bits accordingly. The lower 24
34 * bits in two registers (GPIT1 and GPIT2) are used to set up
35 * the style for 8 lines each for a total of 16 GPIO lines.
36 */
37#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH 0x0
38#define IXP4XX_GPIO_STYLE_ACTIVE_LOW 0x1
39#define IXP4XX_GPIO_STYLE_RISING_EDGE 0x2
40#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3
41#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4
42#define IXP4XX_GPIO_STYLE_MASK GENMASK(2, 0)
43#define IXP4XX_GPIO_STYLE_SIZE 3
44
45/**
46 * struct ixp4xx_gpio - IXP4 GPIO state container
47 * @dev: containing device for this instance
48 * @fwnode: the fwnode for this GPIO chip
49 * @gc: gpiochip for this instance
50 * @domain: irqdomain for this chip instance
51 * @base: remapped I/O-memory base
52 * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
53 * 0: level triggered
54 */
55struct ixp4xx_gpio {
56 struct device *dev;
57 struct fwnode_handle *fwnode;
58 struct gpio_chip gc;
59 struct irq_domain *domain;
60 void __iomem *base;
61 unsigned long long irq_edge;
62};
63
64/**
65 * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map
66 * @gpio_offset: offset of the IXP4 GPIO line
67 * @parent_hwirq: hwirq on the parent IRQ controller
68 */
69struct ixp4xx_gpio_map {
70 int gpio_offset;
71 int parent_hwirq;
72};
73
74/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */
75const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = {
76 { .gpio_offset = 0, .parent_hwirq = 6 },
77 { .gpio_offset = 1, .parent_hwirq = 7 },
78 { .gpio_offset = 2, .parent_hwirq = 19 },
79 { .gpio_offset = 3, .parent_hwirq = 20 },
80 { .gpio_offset = 4, .parent_hwirq = 21 },
81 { .gpio_offset = 5, .parent_hwirq = 22 },
82 { .gpio_offset = 6, .parent_hwirq = 23 },
83 { .gpio_offset = 7, .parent_hwirq = 24 },
84 { .gpio_offset = 8, .parent_hwirq = 25 },
85 { .gpio_offset = 9, .parent_hwirq = 26 },
86 { .gpio_offset = 10, .parent_hwirq = 27 },
87 { .gpio_offset = 11, .parent_hwirq = 28 },
88 { .gpio_offset = 12, .parent_hwirq = 29 },
89};
90
91static void ixp4xx_gpio_irq_ack(struct irq_data *d)
92{
93 struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
94
95 __raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);
96}
97
98static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
99{
100 struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
101
102 /* ACK when unmasking if not edge-triggered */
103 if (!(g->irq_edge & BIT(d->hwirq)))
104 ixp4xx_gpio_irq_ack(d);
105
106 irq_chip_unmask_parent(d);
107}
108
109static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
110{
111 struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
112 int line = d->hwirq;
113 unsigned long flags;
114 u32 int_style;
115 u32 int_reg;
116 u32 val;
117
118 switch (type) {
119 case IRQ_TYPE_EDGE_BOTH:
120 irq_set_handler_locked(d, handle_edge_irq);
121 int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
122 g->irq_edge |= BIT(d->hwirq);
123 break;
124 case IRQ_TYPE_EDGE_RISING:
125 irq_set_handler_locked(d, handle_edge_irq);
126 int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
127 g->irq_edge |= BIT(d->hwirq);
128 break;
129 case IRQ_TYPE_EDGE_FALLING:
130 irq_set_handler_locked(d, handle_edge_irq);
131 int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
132 g->irq_edge |= BIT(d->hwirq);
133 break;
134 case IRQ_TYPE_LEVEL_HIGH:
135 irq_set_handler_locked(d, handle_level_irq);
136 int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
137 g->irq_edge &= ~BIT(d->hwirq);
138 break;
139 case IRQ_TYPE_LEVEL_LOW:
140 irq_set_handler_locked(d, handle_level_irq);
141 int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
142 g->irq_edge &= ~BIT(d->hwirq);
143 break;
144 default:
145 return -EINVAL;
146 }
147
148 if (line >= 8) {
149 /* pins 8-15 */
150 line -= 8;
151 int_reg = IXP4XX_REG_GPIT2;
152 } else {
153 /* pins 0-7 */
154 int_reg = IXP4XX_REG_GPIT1;
155 }
156
157 spin_lock_irqsave(&g->gc.bgpio_lock, flags);
158
159 /* Clear the style for the appropriate pin */
160 val = __raw_readl(g->base + int_reg);
161 val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));
162 __raw_writel(val, g->base + int_reg);
163
164 __raw_writel(BIT(line), g->base + IXP4XX_REG_GPIS);
165
166 /* Set the new style */
167 val = __raw_readl(g->base + int_reg);
168 val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
169 __raw_writel(val, g->base + int_reg);
170
171 /* Force-configure this line as an input */
172 val = __raw_readl(g->base + IXP4XX_REG_GPOE);
173 val |= BIT(d->hwirq);
174 __raw_writel(val, g->base + IXP4XX_REG_GPOE);
175
176 spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);
177
178 /* This parent only accept level high (asserted) */
179 return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
180}
181
182static struct irq_chip ixp4xx_gpio_irqchip = {
183 .name = "IXP4GPIO",
184 .irq_ack = ixp4xx_gpio_irq_ack,
185 .irq_mask = irq_chip_mask_parent,
186 .irq_unmask = ixp4xx_gpio_irq_unmask,
187 .irq_set_type = ixp4xx_gpio_irq_set_type,
188};
189
190static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
191{
192 struct ixp4xx_gpio *g = gpiochip_get_data(gc);
193 struct irq_fwspec fwspec;
194
195 fwspec.fwnode = g->fwnode;
196 fwspec.param_count = 2;
197 fwspec.param[0] = offset;
198 fwspec.param[1] = IRQ_TYPE_NONE;
199
200 return irq_create_fwspec_mapping(&fwspec);
201}
202
203static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain,
204 struct irq_fwspec *fwspec,
205 unsigned long *hwirq,
206 unsigned int *type)
207{
208
209 /* We support standard DT translation */
210 if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
211 *hwirq = fwspec->param[0];
212 *type = fwspec->param[1];
213 return 0;
214 }
215
216 /* This goes away when we transition to DT */
217 if (is_fwnode_irqchip(fwspec->fwnode)) {
218 if (fwspec->param_count != 2)
219 return -EINVAL;
220 *hwirq = fwspec->param[0];
221 *type = fwspec->param[1];
222 WARN_ON(*type == IRQ_TYPE_NONE);
223 return 0;
224 }
225 return -EINVAL;
226}
227
228static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d,
229 unsigned int irq, unsigned int nr_irqs,
230 void *data)
231{
232 struct ixp4xx_gpio *g = d->host_data;
233 irq_hw_number_t hwirq;
234 unsigned int type = IRQ_TYPE_NONE;
235 struct irq_fwspec *fwspec = data;
236 int ret;
237 int i;
238
239 ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type);
240 if (ret)
241 return ret;
242
243 dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n",
244 irq, irq + nr_irqs - 1,
245 hwirq, hwirq + nr_irqs - 1);
246
247 for (i = 0; i < nr_irqs; i++) {
248 struct irq_fwspec parent_fwspec;
249 const struct ixp4xx_gpio_map *map;
250 int j;
251
252 /* Not all lines support IRQs */
253 for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) {
254 map = &ixp4xx_gpiomap[j];
255 if (map->gpio_offset == hwirq)
256 break;
257 }
258 if (j == ARRAY_SIZE(ixp4xx_gpiomap)) {
259 dev_err(g->dev, "can't look up hwirq %lu\n", hwirq);
260 return -EINVAL;
261 }
262 dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq);
263
264 /*
265 * We set handle_bad_irq because the .set_type() should
266 * always be invoked and set the right type of handler.
267 */
268 irq_domain_set_info(d,
269 irq + i,
270 hwirq + i,
271 &ixp4xx_gpio_irqchip,
272 g,
273 handle_bad_irq,
274 NULL, NULL);
275 irq_set_probe(irq + i);
276
277 /*
278 * Create a IRQ fwspec to send up to the parent irqdomain:
279 * specify the hwirq we address on the parent and tie it
280 * all together up the chain.
281 */
282 parent_fwspec.fwnode = d->parent->fwnode;
283 parent_fwspec.param_count = 2;
284 parent_fwspec.param[0] = map->parent_hwirq;
285 /* This parent only handles asserted level IRQs */
286 parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
287 dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n",
288 irq + i, map->parent_hwirq);
289 ret = irq_domain_alloc_irqs_parent(d, irq + i, 1,
290 &parent_fwspec);
291 if (ret)
292 dev_err(g->dev,
293 "failed to allocate parent hwirq %d for hwirq %lu\n",
294 map->parent_hwirq, hwirq);
295 }
296
297 return 0;
298}
299
300static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = {
301 .translate = ixp4xx_gpio_irq_domain_translate,
302 .alloc = ixp4xx_gpio_irq_domain_alloc,
303 .free = irq_domain_free_irqs_common,
304};
305
306static int ixp4xx_gpio_probe(struct platform_device *pdev)
307{
308 unsigned long flags;
309 struct device *dev = &pdev->dev;
310 struct device_node *np = dev->of_node;
311 struct irq_domain *parent;
312 struct resource *res;
313 struct ixp4xx_gpio *g;
314 int ret;
315 int i;
316
317 g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
318 if (!g)
319 return -ENOMEM;
320 g->dev = dev;
321
322 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
323 g->base = devm_ioremap_resource(dev, res);
324 if (IS_ERR(g->base)) {
325 dev_err(dev, "ioremap error\n");
326 return PTR_ERR(g->base);
327 }
328
329 /*
330 * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
331 * specific machines.
332 */
333 if (machine_is_dsmg600() || machine_is_nas100d())
334 __raw_writel(0x0, g->base + IXP4XX_REG_GPCLK);
335
336 /*
337 * This is a very special big-endian ARM issue: when the IXP4xx is
338 * run in big endian mode, all registers in the machine are switched
339 * around to the CPU-native endianness. As you see mostly in the
340 * driver we use __raw_readl()/__raw_writel() to access the registers
341 * in the appropriate order. With the GPIO library we need to specify
342 * byte order explicitly, so this flag needs to be set when compiling
343 * for big endian.
344 */
345#if defined(CONFIG_CPU_BIG_ENDIAN)
346 flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
347#else
348 flags = 0;
349#endif
350
351 /* Populate and register gpio chip */
352 ret = bgpio_init(&g->gc, dev, 4,
353 g->base + IXP4XX_REG_GPIN,
354 g->base + IXP4XX_REG_GPOUT,
355 NULL,
356 NULL,
357 g->base + IXP4XX_REG_GPOE,
358 flags);
359 if (ret) {
360 dev_err(dev, "unable to init generic GPIO\n");
361 return ret;
362 }
363 g->gc.to_irq = ixp4xx_gpio_to_irq;
364 g->gc.ngpio = 16;
365 g->gc.label = "IXP4XX_GPIO_CHIP";
366 /*
367 * TODO: when we have migrated to device tree and all GPIOs
368 * are fetched using phandles, set this to -1 to get rid of
369 * the fixed gpiochip base.
370 */
371 g->gc.base = 0;
372 g->gc.parent = &pdev->dev;
373 g->gc.owner = THIS_MODULE;
374
375 ret = devm_gpiochip_add_data(dev, &g->gc, g);
376 if (ret) {
377 dev_err(dev, "failed to add SoC gpiochip\n");
378 return ret;
379 }
380
381 /*
382 * When we convert to device tree we will simply look up the
383 * parent irqdomain using irq_find_host(parent) as parent comes
384 * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
385 * the fwnode. For now we need this boardfile style code.
386 */
387 if (np) {
388 struct device_node *irq_parent;
389
390 irq_parent = of_irq_find_parent(np);
391 if (!irq_parent) {
392 dev_err(dev, "no IRQ parent node\n");
393 return -ENODEV;
394 }
395 parent = irq_find_host(irq_parent);
396 if (!parent) {
397 dev_err(dev, "no IRQ parent domain\n");
398 return -ENODEV;
399 }
400 g->fwnode = of_node_to_fwnode(np);
401 } else {
402 parent = ixp4xx_get_irq_domain();
403 g->fwnode = irq_domain_alloc_fwnode(g->base);
404 if (!g->fwnode) {
405 dev_err(dev, "no domain base\n");
406 return -ENODEV;
407 }
408 }
409 g->domain = irq_domain_create_hierarchy(parent,
410 IRQ_DOMAIN_FLAG_HIERARCHY,
411 ARRAY_SIZE(ixp4xx_gpiomap),
412 g->fwnode,
413 &ixp4xx_gpio_irqdomain_ops,
414 g);
415 if (!g->domain) {
416 irq_domain_free_fwnode(g->fwnode);
417 dev_err(dev, "no hierarchical irq domain\n");
418 return ret;
419 }
420
421 /*
422 * After adding OF support, this is no longer needed: irqs
423 * will be allocated for the respective fwnodes.
424 */
425 if (!np) {
426 for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
427 const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
428 struct irq_fwspec fwspec;
429
430 fwspec.fwnode = g->fwnode;
431 /* This is the hwirq for the GPIO line side of things */
432 fwspec.param[0] = map->gpio_offset;
433 fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
434 fwspec.param_count = 2;
435 ret = __irq_domain_alloc_irqs(g->domain,
436 -1, /* just pick something */
437 1,
438 NUMA_NO_NODE,
439 &fwspec,
440 false,
441 NULL);
442 if (ret < 0) {
443 irq_domain_free_fwnode(g->fwnode);
444 dev_err(dev,
445 "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
446 map->gpio_offset, map->parent_hwirq,
447 ret);
448 return ret;
449 }
450 }
451 }
452
453 platform_set_drvdata(pdev, g);
454 dev_info(dev, "IXP4 GPIO @%p registered\n", g->base);
455
456 return 0;
457}
458
459static const struct of_device_id ixp4xx_gpio_of_match[] = {
460 {
461 .compatible = "intel,ixp4xx-gpio",
462 },
463 {},
464};
465
466
467static struct platform_driver ixp4xx_gpio_driver = {
468 .driver = {
469 .name = "ixp4xx-gpio",
470 .of_match_table = of_match_ptr(ixp4xx_gpio_of_match),
471 },
472 .probe = ixp4xx_gpio_probe,
473};
474builtin_platform_driver(ixp4xx_gpio_driver);