]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpio/gpio-etraxfs.c
xfrm: dst_entries_init() per-net dst_ops
[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 unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc)
180 {
181         return gc->label[0] - 'A';
182 }
183
184 static int etraxfs_gpio_of_xlate(struct gpio_chip *gc,
185                                const struct of_phandle_args *gpiospec,
186                                u32 *flags)
187 {
188         /*
189          * Port numbers are A to E, and the properties are integers, so we
190          * specify them as 0xA - 0xE.
191          */
192         if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2])
193                 return -EINVAL;
194
195         return of_gpio_simple_xlate(gc, gpiospec, flags);
196 }
197
198 static const struct of_device_id etraxfs_gpio_of_table[] = {
199         {
200                 .compatible = "axis,etraxfs-gio",
201                 .data = &etraxfs_gpio_etraxfs,
202         },
203         {
204                 .compatible = "axis,artpec3-gio",
205                 .data = &etraxfs_gpio_artpec3,
206         },
207         {},
208 };
209
210 static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio)
211 {
212         return gpio % 8;
213 }
214
215 static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip,
216                                               unsigned int gpio)
217 {
218         return 4 * etraxfs_gpio_chip_to_port(&chip->bgc.gc) + gpio / 8;
219 }
220
221 static void etraxfs_gpio_irq_ack(struct irq_data *d)
222 {
223         struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
224         struct etraxfs_gpio_block *block = chip->block;
225         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
226
227         writel(BIT(grpirq), block->regs + block->info->rw_ack_intr);
228 }
229
230 static void etraxfs_gpio_irq_mask(struct irq_data *d)
231 {
232         struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
233         struct etraxfs_gpio_block *block = chip->block;
234         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
235
236         spin_lock(&block->lock);
237         block->mask &= ~BIT(grpirq);
238         writel(block->mask, block->regs + block->info->rw_intr_mask);
239         spin_unlock(&block->lock);
240 }
241
242 static void etraxfs_gpio_irq_unmask(struct irq_data *d)
243 {
244         struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
245         struct etraxfs_gpio_block *block = chip->block;
246         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
247
248         spin_lock(&block->lock);
249         block->mask |= BIT(grpirq);
250         writel(block->mask, block->regs + block->info->rw_intr_mask);
251         spin_unlock(&block->lock);
252 }
253
254 static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
255 {
256         struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
257         struct etraxfs_gpio_block *block = chip->block;
258         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
259         u32 cfg;
260
261         switch (type) {
262         case IRQ_TYPE_EDGE_RISING:
263                 cfg = GIO_CFG_POSEDGE;
264                 break;
265         case IRQ_TYPE_EDGE_FALLING:
266                 cfg = GIO_CFG_NEGEDGE;
267                 break;
268         case IRQ_TYPE_EDGE_BOTH:
269                 cfg = GIO_CFG_ANYEDGE;
270                 break;
271         case IRQ_TYPE_LEVEL_LOW:
272                 cfg = GIO_CFG_LO;
273                 break;
274         case IRQ_TYPE_LEVEL_HIGH:
275                 cfg = GIO_CFG_HI;
276                 break;
277         default:
278                 return -EINVAL;
279         }
280
281         spin_lock(&block->lock);
282         block->cfg &= ~(0x7 << (grpirq * 3));
283         block->cfg |= (cfg << (grpirq * 3));
284         writel(block->cfg, block->regs + block->info->rw_intr_cfg);
285         spin_unlock(&block->lock);
286
287         return 0;
288 }
289
290 static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
291 {
292         struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
293         struct etraxfs_gpio_block *block = chip->block;
294         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
295         int ret = -EBUSY;
296
297         spin_lock(&block->lock);
298         if (block->group[grpirq])
299                 goto out;
300
301         ret = gpiochip_lock_as_irq(&chip->bgc.gc, d->hwirq);
302         if (ret)
303                 goto out;
304
305         block->group[grpirq] = d->irq;
306         if (block->info->rw_intr_pins) {
307                 unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq);
308
309                 block->pins &= ~(0xf << (grpirq * 4));
310                 block->pins |= (pin << (grpirq * 4));
311
312                 writel(block->pins, block->regs + block->info->rw_intr_pins);
313         }
314
315 out:
316         spin_unlock(&block->lock);
317         return ret;
318 }
319
320 static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
321 {
322         struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
323         struct etraxfs_gpio_block *block = chip->block;
324         unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
325
326         spin_lock(&block->lock);
327         block->group[grpirq] = 0;
328         gpiochip_unlock_as_irq(&chip->bgc.gc, d->hwirq);
329         spin_unlock(&block->lock);
330 }
331
332 static struct irq_chip etraxfs_gpio_irq_chip = {
333         .name           = "gpio-etraxfs",
334         .irq_ack        = etraxfs_gpio_irq_ack,
335         .irq_mask       = etraxfs_gpio_irq_mask,
336         .irq_unmask     = etraxfs_gpio_irq_unmask,
337         .irq_set_type   = etraxfs_gpio_irq_set_type,
338         .irq_request_resources = etraxfs_gpio_irq_request_resources,
339         .irq_release_resources = etraxfs_gpio_irq_release_resources,
340 };
341
342 static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id)
343 {
344         struct etraxfs_gpio_block *block = dev_id;
345         unsigned long intr = readl(block->regs + block->info->r_masked_intr);
346         int bit;
347
348         for_each_set_bit(bit, &intr, 8)
349                 generic_handle_irq(block->group[bit]);
350
351         return IRQ_RETVAL(intr & 0xff);
352 }
353
354 static int etraxfs_gpio_probe(struct platform_device *pdev)
355 {
356         struct device *dev = &pdev->dev;
357         const struct etraxfs_gpio_info *info;
358         const struct of_device_id *match;
359         struct etraxfs_gpio_block *block;
360         struct etraxfs_gpio_chip *chips;
361         struct resource *res, *irq;
362         bool allportsirq = false;
363         void __iomem *regs;
364         int ret;
365         int i;
366
367         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
368         regs = devm_ioremap_resource(dev, res);
369         if (IS_ERR(regs))
370                 return PTR_ERR(regs);
371
372         match = of_match_node(etraxfs_gpio_of_table, dev->of_node);
373         if (!match)
374                 return -EINVAL;
375
376         info = match->data;
377
378         chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL);
379         if (!chips)
380                 return -ENOMEM;
381
382         irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
383         if (!irq)
384                 return -EINVAL;
385
386         block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL);
387         if (!block)
388                 return -ENOMEM;
389
390         spin_lock_init(&block->lock);
391
392         block->regs = regs;
393         block->info = info;
394
395         writel(0, block->regs + info->rw_intr_mask);
396         writel(0, block->regs + info->rw_intr_cfg);
397         if (info->rw_intr_pins) {
398                 allportsirq = true;
399                 writel(0, block->regs + info->rw_intr_pins);
400         }
401
402         ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt,
403                                IRQF_SHARED, dev_name(dev), block);
404         if (ret) {
405                 dev_err(dev, "Unable to request irq %d\n", ret);
406                 return ret;
407         }
408
409         for (i = 0; i < info->num_ports; i++) {
410                 struct etraxfs_gpio_chip *chip = &chips[i];
411                 struct bgpio_chip *bgc = &chip->bgc;
412                 const struct etraxfs_gpio_port *port = &info->ports[i];
413                 unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET;
414                 void __iomem *dat = regs + port->din;
415                 void __iomem *set = regs + port->dout;
416                 void __iomem *dirout = regs + port->oe;
417
418                 chip->block = block;
419
420                 if (dirout == set) {
421                         dirout = set = NULL;
422                         flags = BGPIOF_NO_OUTPUT;
423                 }
424
425                 ret = bgpio_init(bgc, dev, 4,
426                                  dat, set, NULL, dirout, NULL,
427                                  flags);
428                 if (ret) {
429                         dev_err(dev, "Unable to init port %s\n",
430                                 port->label);
431                         continue;
432                 }
433
434                 bgc->gc.ngpio = port->ngpio;
435                 bgc->gc.label = port->label;
436
437                 bgc->gc.of_node = dev->of_node;
438                 bgc->gc.of_gpio_n_cells = 3;
439                 bgc->gc.of_xlate = etraxfs_gpio_of_xlate;
440
441                 ret = gpiochip_add(&bgc->gc);
442                 if (ret) {
443                         dev_err(dev, "Unable to register port %s\n",
444                                 bgc->gc.label);
445                         continue;
446                 }
447
448                 if (i > 0 && !allportsirq)
449                         continue;
450
451                 ret = gpiochip_irqchip_add(&bgc->gc, &etraxfs_gpio_irq_chip, 0,
452                                            handle_level_irq, IRQ_TYPE_NONE);
453                 if (ret) {
454                         dev_err(dev, "Unable to add irqchip to port %s\n",
455                                 bgc->gc.label);
456                 }
457         }
458
459         return 0;
460 }
461
462 static struct platform_driver etraxfs_gpio_driver = {
463         .driver = {
464                 .name           = "etraxfs-gpio",
465                 .of_match_table = of_match_ptr(etraxfs_gpio_of_table),
466         },
467         .probe  = etraxfs_gpio_probe,
468 };
469
470 static int __init etraxfs_gpio_init(void)
471 {
472         return platform_driver_register(&etraxfs_gpio_driver);
473 }
474
475 device_initcall(etraxfs_gpio_init);