Merge tag 'metag-for-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan...
[deliverable/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);
This page took 0.047622 seconds and 6 git commands to generate.