summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-ixp4xx.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-01-25 15:59:11 -0500
committerLinus Walleij <linus.walleij@linaro.org>2019-04-23 10:02:13 -0400
commit813e7d36f22762f89856048a32446c8972309566 (patch)
tree90cd921732bce88d0726abac72a3e2114ee4d6cd /drivers/gpio/gpio-ixp4xx.c
parent5b978c10665973d8ee7050b03ef6e97013066b03 (diff)
gpio: ixp4xx: Add driver for the IXP4xx GPIO
This adds a driver for the IXP4xx GPIO block found in the Intel XScale IXP4xx systems. The GPIO part of this block is pretty straight-forward and just uses the generic MMIO GPIO library. The irqchip side of this driver is hierarchical where the main irqchip will receive a processed level trigger in response to the edge detector of the GPIO block, so for this reason the v2 version of the irqdomain API is used (as well as in the parent IXP4xx irqchip) and masking, unmasking and setting up the type on IRQ happens on several levels. Currently this GPIO controller will grab the parent irqdomain using a special function, but as the platform move toward device tree probing, this will not be needed: we can just look up the parent irqdomain from the device tree. Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-ixp4xx.c')
-rw-r--r--drivers/gpio/gpio-ixp4xx.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
new file mode 100644
index 000000000000..eaf317f73f75
--- /dev/null
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -0,0 +1,444 @@
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/platform_device.h>
15#include <linux/bitops.h>
16/* Include that go away with DT transition */
17#include <linux/irqchip/irq-ixp4xx.h>
18
19#include <asm/mach-types.h>
20
21#define IXP4XX_REG_GPOUT 0x00
22#define IXP4XX_REG_GPOE 0x04
23#define IXP4XX_REG_GPIN 0x08
24#define IXP4XX_REG_GPIS 0x0C
25#define IXP4XX_REG_GPIT1 0x10
26#define IXP4XX_REG_GPIT2 0x14
27#define IXP4XX_REG_GPCLK 0x18
28#define IXP4XX_REG_GPDBSEL 0x1C
29
30/*
31 * The hardware uses 3 bits to indicate interrupt "style".
32 * we clear and set these three bits accordingly. The lower 24
33 * bits in two registers (GPIT1 and GPIT2) are used to set up
34 * the style for 8 lines each for a total of 16 GPIO lines.
35 */
36#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH 0x0
37#define IXP4XX_GPIO_STYLE_ACTIVE_LOW 0x1
38#define IXP4XX_GPIO_STYLE_RISING_EDGE 0x2
39#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3
40#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4
41#define IXP4XX_GPIO_STYLE_MASK GENMASK(2, 0)
42#define IXP4XX_GPIO_STYLE_SIZE 3
43
44/**
45 * struct ixp4xx_gpio - IXP4 GPIO state container
46 * @dev: containing device for this instance
47 * @fwnode: the fwnode for this GPIO chip
48 * @gc: gpiochip for this instance
49 * @domain: irqdomain for this chip instance
50 * @base: remapped I/O-memory base
51 * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
52 * 0: level triggered
53 */
54struct ixp4xx_gpio {
55 struct device *dev;
56 struct fwnode_handle *fwnode;
57 struct gpio_chip gc;
58 struct irq_domain *domain;
59 void __iomem *base;
60 unsigned long long irq_edge;
61};
62
63/**
64 * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map
65 * @gpio_offset: offset of the IXP4 GPIO line
66 * @parent_hwirq: hwirq on the parent IRQ controller
67 */
68struct ixp4xx_gpio_map {
69 int gpio_offset;
70 int parent_hwirq;
71};
72
73/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */
74const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = {
75 { .gpio_offset = 0, .parent_hwirq = 6 },
76 { .gpio_offset = 1, .parent_hwirq = 7 },
77 { .gpio_offset = 2, .parent_hwirq = 19 },
78 { .gpio_offset = 3, .parent_hwirq = 20 },
79 { .gpio_offset = 4, .parent_hwirq = 21 },
80 { .gpio_offset = 5, .parent_hwirq = 22 },
81 { .gpio_offset = 6, .parent_hwirq = 23 },
82 { .gpio_offset = 7, .parent_hwirq = 24 },
83 { .gpio_offset = 8, .parent_hwirq = 25 },
84 { .gpio_offset = 9, .parent_hwirq = 26 },
85 { .gpio_offset = 10, .parent_hwirq = 27 },
86 { .gpio_offset = 11, .parent_hwirq = 28 },
87 { .gpio_offset = 12, .parent_hwirq = 29 },
88};
89
90static void ixp4xx_gpio_irq_ack(struct irq_data *d)
91{
92 struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
93
94 __raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);
95}
96
97static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
98{
99 struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
100
101 /* ACK when unmasking if not edge-triggered */
102 if (!(g->irq_edge & BIT(d->hwirq)))
103 ixp4xx_gpio_irq_ack(d);
104
105 irq_chip_unmask_parent(d);
106}
107
108static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
109{
110 struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
111 int line = d->hwirq;
112 unsigned long flags;
113 u32 int_style;
114 u32 int_reg;
115 u32 val;
116
117 switch (type) {
118 case IRQ_TYPE_EDGE_BOTH:
119 irq_set_handler_locked(d, handle_edge_irq);
120 int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
121 g->irq_edge |= BIT(d->hwirq);
122 break;
123 case IRQ_TYPE_EDGE_RISING:
124 irq_set_handler_locked(d, handle_edge_irq);
125 int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
126 g->irq_edge |= BIT(d->hwirq);
127 break;
128 case IRQ_TYPE_EDGE_FALLING:
129 irq_set_handler_locked(d, handle_edge_irq);
130 int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
131 g->irq_edge |= BIT(d->hwirq);
132 break;
133 case IRQ_TYPE_LEVEL_HIGH:
134 irq_set_handler_locked(d, handle_level_irq);
135 int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
136 g->irq_edge &= ~BIT(d->hwirq);
137 break;
138 case IRQ_TYPE_LEVEL_LOW:
139 irq_set_handler_locked(d, handle_level_irq);
140 int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
141 g->irq_edge &= ~BIT(d->hwirq);
142 break;
143 default:
144 return -EINVAL;
145 }
146
147 if (line >= 8) {
148 /* pins 8-15 */
149 line -= 8;
150 int_reg = IXP4XX_REG_GPIT2;
151 } else {
152 /* pins 0-7 */
153 int_reg = IXP4XX_REG_GPIT1;
154 }
155
156 spin_lock_irqsave(&g->gc.bgpio_lock, flags);
157
158 /* Clear the style for the appropriate pin */
159 val = __raw_readl(g->base + int_reg);
160 val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));
161 __raw_writel(val, g->base + int_reg);
162
163 __raw_writel(BIT(line), g->base + IXP4XX_REG_GPIS);
164
165 /* Set the new style */
166 val = __raw_readl(g->base + int_reg);
167 val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
168 __raw_writel(val, g->base + int_reg);
169
170 /* Force-configure this line as an input */
171 val = __raw_readl(g->base + IXP4XX_REG_GPOE);
172 val |= BIT(d->hwirq);
173 __raw_writel(val, g->base + IXP4XX_REG_GPOE);
174
175 spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);
176
177 /* This parent only accept level high (asserted) */
178 return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
179}
180
181static struct irq_chip ixp4xx_gpio_irqchip = {
182 .name = "IXP4GPIO",
183 .irq_ack = ixp4xx_gpio_irq_ack,
184 .irq_mask = irq_chip_mask_parent,
185 .irq_unmask = ixp4xx_gpio_irq_unmask,
186 .irq_set_type = ixp4xx_gpio_irq_set_type,
187};
188
189static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
190{
191 struct ixp4xx_gpio *g = gpiochip_get_data(gc);
192 struct irq_fwspec fwspec;
193
194 fwspec.fwnode = g->fwnode;
195 fwspec.param_count = 2;
196 fwspec.param[0] = offset;
197 fwspec.param[1] = IRQ_TYPE_NONE;
198
199 return irq_create_fwspec_mapping(&fwspec);
200}
201
202static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain,
203 struct irq_fwspec *fwspec,
204 unsigned long *hwirq,
205 unsigned int *type)
206{
207
208 /* We support standard DT translation */
209 if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
210 *hwirq = fwspec->param[0];
211 *type = fwspec->param[1];
212 return 0;
213 }
214
215 /* This goes away when we transition to DT */
216 if (is_fwnode_irqchip(fwspec->fwnode)) {
217 if (fwspec->param_count != 2)
218 return -EINVAL;
219 *hwirq = fwspec->param[0];
220 *type = fwspec->param[1];
221 WARN_ON(*type == IRQ_TYPE_NONE);
222 return 0;
223 }
224 return -EINVAL;
225}
226
227static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d,
228 unsigned int irq, unsigned int nr_irqs,
229 void *data)
230{
231 struct ixp4xx_gpio *g = d->host_data;
232 irq_hw_number_t hwirq;
233 unsigned int type = IRQ_TYPE_NONE;
234 struct irq_fwspec *fwspec = data;
235 int ret;
236 int i;
237
238 ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type);
239 if (ret)
240 return ret;
241
242 dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n",
243 irq, irq + nr_irqs - 1,
244 hwirq, hwirq + nr_irqs - 1);
245
246 for (i = 0; i < nr_irqs; i++) {
247 struct irq_fwspec parent_fwspec;
248 const struct ixp4xx_gpio_map *map;
249 int j;
250
251 /* Not all lines support IRQs */
252 for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) {
253 map = &ixp4xx_gpiomap[j];
254 if (map->gpio_offset == hwirq)
255 break;
256 }
257 if (j == ARRAY_SIZE(ixp4xx_gpiomap)) {
258 dev_err(g->dev, "can't look up hwirq %lu\n", hwirq);
259 return -EINVAL;
260 }
261 dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq);
262
263 /*
264 * We set handle_bad_irq because the .set_type() should
265 * always be invoked and set the right type of handler.
266 */
267 irq_domain_set_info(d,
268 irq + i,
269 hwirq + i,
270 &ixp4xx_gpio_irqchip,
271 g,
272 handle_bad_irq,
273 NULL, NULL);
274 irq_set_probe(irq + i);
275
276 /*
277 * Create a IRQ fwspec to send up to the parent irqdomain:
278 * specify the hwirq we address on the parent and tie it
279 * all together up the chain.
280 */
281 parent_fwspec.fwnode = d->parent->fwnode;
282 parent_fwspec.param_count = 2;
283 parent_fwspec.param[0] = map->parent_hwirq;
284 /* This parent only handles asserted level IRQs */
285 parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
286 dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n",
287 irq + i, map->parent_hwirq);
288 ret = irq_domain_alloc_irqs_parent(d, irq + i, 1,
289 &parent_fwspec);
290 if (ret)
291 dev_err(g->dev,
292 "failed to allocate parent hwirq %d for hwirq %lu\n",
293 map->parent_hwirq, hwirq);
294 }
295
296 return 0;
297}
298
299static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = {
300 .translate = ixp4xx_gpio_irq_domain_translate,
301 .alloc = ixp4xx_gpio_irq_domain_alloc,
302 .free = irq_domain_free_irqs_common,
303};
304
305static int ixp4xx_gpio_probe(struct platform_device *pdev)
306{
307 unsigned long flags;
308 struct device *dev = &pdev->dev;
309 struct irq_domain *parent;
310 struct resource *res;
311 struct ixp4xx_gpio *g;
312 int ret;
313 int i;
314
315 g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
316 if (!g)
317 return -ENOMEM;
318 g->dev = dev;
319
320 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
321 g->base = devm_ioremap_resource(dev, res);
322 if (IS_ERR(g->base)) {
323 dev_err(dev, "ioremap error\n");
324 return PTR_ERR(g->base);
325 }
326
327 /*
328 * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
329 * specific machines.
330 */
331 if (machine_is_dsmg600() || machine_is_nas100d())
332 __raw_writel(0x0, g->base + IXP4XX_REG_GPCLK);
333
334 /*
335 * This is a very special big-endian ARM issue: when the IXP4xx is
336 * run in big endian mode, all registers in the machine are switched
337 * around to the CPU-native endianness. As you see mostly in the
338 * driver we use __raw_readl()/__raw_writel() to access the registers
339 * in the appropriate order. With the GPIO library we need to specify
340 * byte order explicitly, so this flag needs to be set when compiling
341 * for big endian.
342 */
343#if defined(CONFIG_CPU_BIG_ENDIAN)
344 flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
345#else
346 flags = 0;
347#endif
348
349 /* Populate and register gpio chip */
350 ret = bgpio_init(&g->gc, dev, 4,
351 g->base + IXP4XX_REG_GPIN,
352 g->base + IXP4XX_REG_GPOUT,
353 NULL,
354 NULL,
355 g->base + IXP4XX_REG_GPOE,
356 flags);
357 if (ret) {
358 dev_err(dev, "unable to init generic GPIO\n");
359 return ret;
360 }
361 g->gc.to_irq = ixp4xx_gpio_to_irq;
362 g->gc.ngpio = 16;
363 g->gc.label = "IXP4XX_GPIO_CHIP";
364 /*
365 * TODO: when we have migrated to device tree and all GPIOs
366 * are fetched using phandles, set this to -1 to get rid of
367 * the fixed gpiochip base.
368 */
369 g->gc.base = 0;
370 g->gc.parent = &pdev->dev;
371 g->gc.owner = THIS_MODULE;
372
373 ret = devm_gpiochip_add_data(dev, &g->gc, g);
374 if (ret) {
375 dev_err(dev, "failed to add SoC gpiochip\n");
376 return ret;
377 }
378
379 /*
380 * When we convert to device tree we will simply look up the
381 * parent irqdomain using irq_find_host(parent) as parent comes
382 * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
383 * the fwnode. For now we need this boardfile style code.
384 */
385 parent = ixp4xx_get_irq_domain();
386 g->fwnode = irq_domain_alloc_fwnode(g->base);
387 if (!g->fwnode) {
388 dev_err(dev, "no domain base\n");
389 return -ENODEV;
390 }
391 g->domain = irq_domain_create_hierarchy(parent,
392 IRQ_DOMAIN_FLAG_HIERARCHY,
393 ARRAY_SIZE(ixp4xx_gpiomap),
394 g->fwnode,
395 &ixp4xx_gpio_irqdomain_ops,
396 g);
397 if (!g->domain) {
398 irq_domain_free_fwnode(g->fwnode);
399 dev_err(dev, "no hierarchical irq domain\n");
400 return ret;
401 }
402
403 /*
404 * After adding OF support, this is no longer needed: irqs
405 * will be allocated for the respective fwnodes.
406 */
407 for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
408 const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
409 struct irq_fwspec fwspec;
410
411 fwspec.fwnode = g->fwnode;
412 /* This is the hwirq for the GPIO line side of things */
413 fwspec.param[0] = map->gpio_offset;
414 fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
415 fwspec.param_count = 2;
416 ret = __irq_domain_alloc_irqs(g->domain,
417 -1, /* just pick something */
418 1,
419 NUMA_NO_NODE,
420 &fwspec,
421 false,
422 NULL);
423 if (ret < 0) {
424 irq_domain_free_fwnode(g->fwnode);
425 dev_err(dev,
426 "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
427 map->gpio_offset, map->parent_hwirq, ret);
428 return ret;
429 }
430 }
431
432 platform_set_drvdata(pdev, g);
433 dev_info(dev, "IXP4 GPIO @%p registered\n", g->base);
434
435 return 0;
436}
437
438static struct platform_driver ixp4xx_gpio_driver = {
439 .driver = {
440 .name = "ixp4xx-gpio",
441 },
442 .probe = ixp4xx_gpio_probe,
443};
444builtin_platform_driver(ixp4xx_gpio_driver);