]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpio/gpio-etraxfs.c
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
[karo-tx-linux.git] / drivers / gpio / gpio-etraxfs.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/gpio.h>
4 #include <linux/gpio/driver.h>
5 #include <linux/of_gpio.h>
6 #include <linux/io.h>
7 #include <linux/interrupt.h>
8 #include <linux/platform_device.h>
9 #include <linux/basic_mmio_gpio.h>
10
11 #define ETRAX_FS_rw_pa_dout     0
12 #define ETRAX_FS_r_pa_din       4
13 #define ETRAX_FS_rw_pa_oe       8
14 #define ETRAX_FS_rw_intr_cfg    12
15 #define ETRAX_FS_rw_intr_mask   16
16 #define ETRAX_FS_rw_ack_intr    20
17 #define ETRAX_FS_r_intr         24
18 #define ETRAX_FS_r_masked_intr  28
19 #define ETRAX_FS_rw_pb_dout     32
20 #define ETRAX_FS_r_pb_din       36
21 #define ETRAX_FS_rw_pb_oe       40
22 #define ETRAX_FS_rw_pc_dout     48
23 #define ETRAX_FS_r_pc_din       52
24 #define ETRAX_FS_rw_pc_oe       56
25 #define ETRAX_FS_rw_pd_dout     64
26 #define ETRAX_FS_r_pd_din       68
27 #define ETRAX_FS_rw_pd_oe       72
28 #define ETRAX_FS_rw_pe_dout     80
29 #define ETRAX_FS_r_pe_din       84
30 #define ETRAX_FS_rw_pe_oe       88
31
32 #define ARTPEC3_r_pa_din        0
33 #define ARTPEC3_rw_pa_dout      4
34 #define ARTPEC3_rw_pa_oe        8
35 #define ARTPEC3_r_pb_din        44
36 #define ARTPEC3_rw_pb_dout      48
37 #define ARTPEC3_rw_pb_oe        52
38 #define ARTPEC3_r_pc_din        88
39 #define ARTPEC3_rw_pc_dout      92
40 #define ARTPEC3_rw_pc_oe        96
41 #define ARTPEC3_r_pd_din        116
42 #define ARTPEC3_rw_intr_cfg     120
43 #define ARTPEC3_rw_intr_pins    124
44 #define ARTPEC3_rw_intr_mask    128
45 #define ARTPEC3_rw_ack_intr     132
46 #define ARTPEC3_r_masked_intr   140
47
48 #define GIO_CFG_OFF             0
49 #define GIO_CFG_HI              1
50 #define GIO_CFG_LO              2
51 #define GIO_CFG_SET             3
52 #define GIO_CFG_POSEDGE         5
53 #define GIO_CFG_NEGEDGE         6
54 #define GIO_CFG_ANYEDGE         7
55
56 struct etraxfs_gpio_info;
57
58 struct etraxfs_gpio_block {
59         spinlock_t lock;
60         u32 mask;
61         u32 cfg;
62         u32 pins;
63         unsigned int group[8];
64
65         void __iomem *regs;
66         const struct etraxfs_gpio_info *info;
67 };
68
69 struct etraxfs_gpio_chip {
70         struct bgpio_chip bgc;
71         struct etraxfs_gpio_block *block;
72 };
73
74 struct etraxfs_gpio_port {
75         const char *label;
76         unsigned int oe;
77         unsigned int dout;
78         unsigned int din;
79         unsigned int ngpio;
80 };
81
82 struct etraxfs_gpio_info {
83         unsigned int num_ports;
84         const struct etraxfs_gpio_port *ports;
85
86         unsigned int rw_ack_intr;
87         unsigned int rw_intr_mask;
88         unsigned int rw_intr_cfg;
89         unsigned int rw_intr_pins;
90         unsigned int r_masked_intr;
91 };
92
93 static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = {
94         {
95                 .label  = "A",
96                 .ngpio  = 8,
97                 .oe     = ETRAX_FS_rw_pa_oe,
98                 .dout   = ETRAX_FS_rw_pa_dout,
99                 .din    = ETRAX_FS_r_pa_din,
100         },
101         {
102                 .label  = "B",
103                 .ngpio  = 18,
104                 .oe     = ETRAX_FS_rw_pb_oe,
105                 .dout   = ETRAX_FS_rw_pb_dout,
106                 .din    = ETRAX_FS_r_pb_din,
107         },
108         {
109                 .label  = "C",
110                 .ngpio  = 18,
111                 .oe     = ETRAX_FS_rw_pc_oe,
112                 .dout   = ETRAX_FS_rw_pc_dout,
113                 .din    = ETRAX_FS_r_pc_din,
114         },
115         {
116                 .label  = "D",
117                 .ngpio  = 18,
118                 .oe     = ETRAX_FS_rw_pd_oe,
119                 .dout   = ETRAX_FS_rw_pd_dout,
120                 .din    = ETRAX_FS_r_pd_din,
121         },
122         {
123                 .label  = "E",
124                 .ngpio  = 18,
125                 .oe     = ETRAX_FS_rw_pe_oe,
126                 .dout   = ETRAX_FS_rw_pe_dout,
127                 .din    = ETRAX_FS_r_pe_din,
128         },
129 };
130
131 static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = {
132         .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports),
133         .ports = etraxfs_gpio_etraxfs_ports,
134         .rw_ack_intr    = ETRAX_FS_rw_ack_intr,
135         .rw_intr_mask   = ETRAX_FS_rw_intr_mask,
136         .rw_intr_cfg    = ETRAX_FS_rw_intr_cfg,
137         .r_masked_intr  = ETRAX_FS_r_masked_intr,
138 };
139
140 static const struct etraxfs_gpio_port etraxfs_gpio_artpec3_ports[] = {
141         {
142                 .label  = "A",
143                 .ngpio  = 32,
144                 .oe     = ARTPEC3_rw_pa_oe,
145                 .dout   = ARTPEC3_rw_pa_dout,
146                 .din    = ARTPEC3_r_pa_din,
147         },
148         {
149                 .label  = "B",
150                 .ngpio  = 32,
151                 .oe     = ARTPEC3_rw_pb_oe,
152                 .dout   = ARTPEC3_rw_pb_dout,
153                 .din    = ARTPEC3_r_pb_din,
154         },
155         {
156                 .label  = "C",
157                 .ngpio  = 16,
158                 .oe     = ARTPEC3_rw_pc_oe,
159                 .dout   = ARTPEC3_rw_pc_dout,
160                 .din    = ARTPEC3_r_pc_din,
161         },
162         {
163                 .label  = "D",
164                 .ngpio  = 32,
165                 .din    = ARTPEC3_r_pd_din,
166         },
167 };
168
169 static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = {
170         .num_ports = ARRAY_SIZE(etraxfs_gpio_artpec3_ports),
171         .ports = etraxfs_gpio_artpec3_ports,
172         .rw_ack_intr    = ARTPEC3_rw_ack_intr,
173         .rw_intr_mask   = ARTPEC3_rw_intr_mask,
174         .rw_intr_cfg    = ARTPEC3_rw_intr_cfg,
175         .r_masked_intr  = ARTPEC3_r_masked_intr,
176         .rw_intr_pins   = ARTPEC3_rw_intr_pins,
177 };
178
179 static struct etraxfs_gpio_chip *to_etraxfs(struct gpio_chip *gc)
180 {
181         return container_of(gc, struct etraxfs_gpio_chip, bgc.gc);
182 }
183
184 static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc)
185 {
186         return gc->label[0] - 'A';
187 }
188
189 static int etraxfs_gpio_of_xlate(struct gpio_chip *gc,
190                                const struct of_phandle_args *gpiospec,
191                                u32 *flags)
192 {
193         /*
194          * Port numbers are A to E, and the properties are integers, so we
195          * specify them as 0xA - 0xE.
196          */
197         if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2])
198                 return -EINVAL;
199
200         return of_gpio_simple_xlate(gc, gpiospec, flags);
201 }
202
203 static const struct of_device_id etraxfs_gpio_of_table[] = {
204         {
205                 .compatible = "axis,etraxfs-gio",
206                 .data = &etraxfs_gpio_etraxfs,
207         },
208         {
209                 .compatible = "axis,artpec3-gio",
210                 .data = &etraxfs_gpio_artpec3,
211         },
212         {},
213 };
214
215 static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio)
216 {
217         return gpio % 8;
218 }
219
220 static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip,
221                                               unsigned int gpio)
222 {
223         return 4 * etraxfs_gpio_chip_to_port(&chip->bgc.gc) + gpio / 8;
224 }
225
226 static void etraxfs_gpio_irq_ack(struct irq_data *d)
227 {
228         struct etraxfs_gpio_chip *chip =
229                 to_etraxfs(irq_data_get_irq_chip_data(d));
230         struct etraxfs_gpio_block *block = chip->block;
231         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
232
233         writel(BIT(grpirq), block->regs + block->info->rw_ack_intr);
234 }
235
236 static void etraxfs_gpio_irq_mask(struct irq_data *d)
237 {
238         struct etraxfs_gpio_chip *chip =
239                 to_etraxfs(irq_data_get_irq_chip_data(d));
240         struct etraxfs_gpio_block *block = chip->block;
241         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
242
243         spin_lock(&block->lock);
244         block->mask &= ~BIT(grpirq);
245         writel(block->mask, block->regs + block->info->rw_intr_mask);
246         spin_unlock(&block->lock);
247 }
248
249 static void etraxfs_gpio_irq_unmask(struct irq_data *d)
250 {
251         struct etraxfs_gpio_chip *chip =
252                 to_etraxfs(irq_data_get_irq_chip_data(d));
253         struct etraxfs_gpio_block *block = chip->block;
254         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
255
256         spin_lock(&block->lock);
257         block->mask |= BIT(grpirq);
258         writel(block->mask, block->regs + block->info->rw_intr_mask);
259         spin_unlock(&block->lock);
260 }
261
262 static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
263 {
264         struct etraxfs_gpio_chip *chip =
265                 to_etraxfs(irq_data_get_irq_chip_data(d));
266         struct etraxfs_gpio_block *block = chip->block;
267         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
268         u32 cfg;
269
270         switch (type) {
271         case IRQ_TYPE_EDGE_RISING:
272                 cfg = GIO_CFG_POSEDGE;
273                 break;
274         case IRQ_TYPE_EDGE_FALLING:
275                 cfg = GIO_CFG_NEGEDGE;
276                 break;
277         case IRQ_TYPE_EDGE_BOTH:
278                 cfg = GIO_CFG_ANYEDGE;
279                 break;
280         case IRQ_TYPE_LEVEL_LOW:
281                 cfg = GIO_CFG_LO;
282                 break;
283         case IRQ_TYPE_LEVEL_HIGH:
284                 cfg = GIO_CFG_HI;
285                 break;
286         default:
287                 return -EINVAL;
288         }
289
290         spin_lock(&block->lock);
291         block->cfg &= ~(0x7 << (grpirq * 3));
292         block->cfg |= (cfg << (grpirq * 3));
293         writel(block->cfg, block->regs + block->info->rw_intr_cfg);
294         spin_unlock(&block->lock);
295
296         return 0;
297 }
298
299 static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
300 {
301         struct etraxfs_gpio_chip *chip =
302                 to_etraxfs(irq_data_get_irq_chip_data(d));
303         struct etraxfs_gpio_block *block = chip->block;
304         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
305         int ret = -EBUSY;
306
307         spin_lock(&block->lock);
308         if (block->group[grpirq])
309                 goto out;
310
311         ret = gpiochip_lock_as_irq(&chip->bgc.gc, d->hwirq);
312         if (ret)
313                 goto out;
314
315         block->group[grpirq] = d->irq;
316         if (block->info->rw_intr_pins) {
317                 unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq);
318
319                 block->pins &= ~(0xf << (grpirq * 4));
320                 block->pins |= (pin << (grpirq * 4));
321
322                 writel(block->pins, block->regs + block->info->rw_intr_pins);
323         }
324
325 out:
326         spin_unlock(&block->lock);
327         return ret;
328 }
329
330 static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
331 {
332         struct etraxfs_gpio_chip *chip =
333                 to_etraxfs(irq_data_get_irq_chip_data(d));
334         struct etraxfs_gpio_block *block = chip->block;
335         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
336
337         spin_lock(&block->lock);
338         block->group[grpirq] = 0;
339         gpiochip_unlock_as_irq(&chip->bgc.gc, d->hwirq);
340         spin_unlock(&block->lock);
341 }
342
343 static struct irq_chip etraxfs_gpio_irq_chip = {
344         .name           = "gpio-etraxfs",
345         .irq_ack        = etraxfs_gpio_irq_ack,
346         .irq_mask       = etraxfs_gpio_irq_mask,
347         .irq_unmask     = etraxfs_gpio_irq_unmask,
348         .irq_set_type   = etraxfs_gpio_irq_set_type,
349         .irq_request_resources = etraxfs_gpio_irq_request_resources,
350         .irq_release_resources = etraxfs_gpio_irq_release_resources,
351 };
352
353 static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id)
354 {
355         struct etraxfs_gpio_block *block = dev_id;
356         unsigned long intr = readl(block->regs + block->info->r_masked_intr);
357         int bit;
358
359         for_each_set_bit(bit, &intr, 8)
360                 generic_handle_irq(block->group[bit]);
361
362         return IRQ_RETVAL(intr & 0xff);
363 }
364
365 static int etraxfs_gpio_probe(struct platform_device *pdev)
366 {
367         struct device *dev = &pdev->dev;
368         const struct etraxfs_gpio_info *info;
369         const struct of_device_id *match;
370         struct etraxfs_gpio_block *block;
371         struct etraxfs_gpio_chip *chips;
372         struct resource *res, *irq;
373         bool allportsirq = false;
374         void __iomem *regs;
375         int ret;
376         int i;
377
378         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
379         regs = devm_ioremap_resource(dev, res);
380         if (IS_ERR(regs))
381                 return PTR_ERR(regs);
382
383         match = of_match_node(etraxfs_gpio_of_table, dev->of_node);
384         if (!match)
385                 return -EINVAL;
386
387         info = match->data;
388
389         chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL);
390         if (!chips)
391                 return -ENOMEM;
392
393         irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
394         if (!irq)
395                 return -EINVAL;
396
397         block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL);
398         if (!block)
399                 return -ENOMEM;
400
401         spin_lock_init(&block->lock);
402
403         block->regs = regs;
404         block->info = info;
405
406         writel(0, block->regs + info->rw_intr_mask);
407         writel(0, block->regs + info->rw_intr_cfg);
408         if (info->rw_intr_pins) {
409                 allportsirq = true;
410                 writel(0, block->regs + info->rw_intr_pins);
411         }
412
413         ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt,
414                                IRQF_SHARED, dev_name(dev), block);
415         if (ret) {
416                 dev_err(dev, "Unable to request irq %d\n", ret);
417                 return ret;
418         }
419
420         for (i = 0; i < info->num_ports; i++) {
421                 struct etraxfs_gpio_chip *chip = &chips[i];
422                 struct bgpio_chip *bgc = &chip->bgc;
423                 const struct etraxfs_gpio_port *port = &info->ports[i];
424                 unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET;
425                 void __iomem *dat = regs + port->din;
426                 void __iomem *set = regs + port->dout;
427                 void __iomem *dirout = regs + port->oe;
428
429                 chip->block = block;
430
431                 if (dirout == set) {
432                         dirout = set = NULL;
433                         flags = BGPIOF_NO_OUTPUT;
434                 }
435
436                 ret = bgpio_init(bgc, dev, 4,
437                                  dat, set, NULL, dirout, NULL,
438                                  flags);
439                 if (ret) {
440                         dev_err(dev, "Unable to init port %s\n",
441                                 port->label);
442                         continue;
443                 }
444
445                 bgc->gc.ngpio = port->ngpio;
446                 bgc->gc.label = port->label;
447
448                 bgc->gc.of_node = dev->of_node;
449                 bgc->gc.of_gpio_n_cells = 3;
450                 bgc->gc.of_xlate = etraxfs_gpio_of_xlate;
451
452                 ret = gpiochip_add(&bgc->gc);
453                 if (ret) {
454                         dev_err(dev, "Unable to register port %s\n",
455                                 bgc->gc.label);
456                         continue;
457                 }
458
459                 if (i > 0 && !allportsirq)
460                         continue;
461
462                 ret = gpiochip_irqchip_add(&bgc->gc, &etraxfs_gpio_irq_chip, 0,
463                                            handle_level_irq, IRQ_TYPE_NONE);
464                 if (ret) {
465                         dev_err(dev, "Unable to add irqchip to port %s\n",
466                                 bgc->gc.label);
467                 }
468         }
469
470         return 0;
471 }
472
473 static struct platform_driver etraxfs_gpio_driver = {
474         .driver = {
475                 .name           = "etraxfs-gpio",
476                 .of_match_table = of_match_ptr(etraxfs_gpio_of_table),
477         },
478         .probe  = etraxfs_gpio_probe,
479 };
480
481 static int __init etraxfs_gpio_init(void)
482 {
483         return platform_driver_register(&etraxfs_gpio_driver);
484 }
485
486 device_initcall(etraxfs_gpio_init);