Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
[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 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);
This page took 0.047981 seconds and 5 git commands to generate.