pinctrl/pinconfig: add debug interface
[deliverable/linux.git] / drivers / pinctrl / pinctrl-s3c64xx.c
CommitLineData
61dd7261
TF
1/*
2 * S3C64xx specific support for pinctrl-samsung driver.
3 *
4 * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
5 *
6 * Based on pinctrl-exynos.c, please see the file for original copyrights.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This file contains the Samsung S3C64xx specific information required by the
14 * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
15 * external gpio and wakeup interrupt support.
16 */
17
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/interrupt.h>
21#include <linux/irqdomain.h>
22#include <linux/irq.h>
23#include <linux/of_irq.h>
24#include <linux/io.h>
25#include <linux/slab.h>
26#include <linux/err.h>
27
28#include <asm/mach/irq.h>
29
30#include "pinctrl-samsung.h"
31
32#define NUM_EINT0 28
33#define NUM_EINT0_IRQ 4
34#define EINT_MAX_PER_REG 16
35#define EINT_MAX_PER_GROUP 16
36
37/* External GPIO and wakeup interrupt related definitions */
38#define SVC_GROUP_SHIFT 4
39#define SVC_GROUP_MASK 0xf
40#define SVC_NUM_MASK 0xf
41#define SVC_GROUP(x) ((x >> SVC_GROUP_SHIFT) & \
42 SVC_GROUP_MASK)
43
44#define EINT12CON_REG 0x200
45#define EINT12MASK_REG 0x240
46#define EINT12PEND_REG 0x260
47
48#define EINT_OFFS(i) ((i) % (2 * EINT_MAX_PER_GROUP))
49#define EINT_GROUP(i) ((i) / EINT_MAX_PER_GROUP)
50#define EINT_REG(g) (4 * ((g) / 2))
51
52#define EINTCON_REG(i) (EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
53#define EINTMASK_REG(i) (EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
54#define EINTPEND_REG(i) (EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
55
56#define SERVICE_REG 0x284
57#define SERVICEPEND_REG 0x288
58
59#define EINT0CON0_REG 0x900
60#define EINT0MASK_REG 0x920
61#define EINT0PEND_REG 0x924
62
63/* S3C64xx specific external interrupt trigger types */
64#define EINT_LEVEL_LOW 0
65#define EINT_LEVEL_HIGH 1
66#define EINT_EDGE_FALLING 2
67#define EINT_EDGE_RISING 4
68#define EINT_EDGE_BOTH 6
69#define EINT_CON_MASK 0xF
70#define EINT_CON_LEN 4
71
72static struct samsung_pin_bank_type bank_type_4bit_off = {
73 .fld_width = { 4, 1, 2, 0, 2, 2, },
74 .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
75};
76
77static struct samsung_pin_bank_type bank_type_4bit_alive = {
78 .fld_width = { 4, 1, 2, },
79 .reg_offset = { 0x00, 0x04, 0x08, },
80};
81
82static struct samsung_pin_bank_type bank_type_4bit2_off = {
83 .fld_width = { 4, 1, 2, 0, 2, 2, },
84 .reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
85};
86
87static struct samsung_pin_bank_type bank_type_4bit2_alive = {
88 .fld_width = { 4, 1, 2, },
89 .reg_offset = { 0x00, 0x08, 0x0c, },
90};
91
92static struct samsung_pin_bank_type bank_type_2bit_off = {
93 .fld_width = { 2, 1, 2, 0, 2, 2, },
94 .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
95};
96
97static struct samsung_pin_bank_type bank_type_2bit_alive = {
98 .fld_width = { 2, 1, 2, },
99 .reg_offset = { 0x00, 0x04, 0x08, },
100};
101
102#define PIN_BANK_4BIT(pins, reg, id) \
103 { \
104 .type = &bank_type_4bit_off, \
105 .pctl_offset = reg, \
106 .nr_pins = pins, \
107 .eint_type = EINT_TYPE_NONE, \
108 .name = id \
109 }
110
111#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs) \
112 { \
113 .type = &bank_type_4bit_off, \
114 .pctl_offset = reg, \
115 .nr_pins = pins, \
116 .eint_type = EINT_TYPE_GPIO, \
117 .eint_func = 7, \
118 .eint_mask = (1 << (pins)) - 1, \
119 .eint_offset = eoffs, \
120 .name = id \
121 }
122
123#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
124 { \
125 .type = &bank_type_4bit_alive,\
126 .pctl_offset = reg, \
127 .nr_pins = pins, \
128 .eint_type = EINT_TYPE_WKUP, \
129 .eint_func = 3, \
130 .eint_mask = emask, \
131 .eint_offset = eoffs, \
132 .name = id \
133 }
134
135#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs) \
136 { \
137 .type = &bank_type_4bit2_off, \
138 .pctl_offset = reg, \
139 .nr_pins = pins, \
140 .eint_type = EINT_TYPE_GPIO, \
141 .eint_func = 7, \
142 .eint_mask = (1 << (pins)) - 1, \
143 .eint_offset = eoffs, \
144 .name = id \
145 }
146
147#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
148 { \
149 .type = &bank_type_4bit2_alive,\
150 .pctl_offset = reg, \
151 .nr_pins = pins, \
152 .eint_type = EINT_TYPE_WKUP, \
153 .eint_func = 3, \
154 .eint_mask = emask, \
155 .eint_offset = eoffs, \
156 .name = id \
157 }
158
159#define PIN_BANK_4BIT2_ALIVE(pins, reg, id) \
160 { \
161 .type = &bank_type_4bit2_alive,\
162 .pctl_offset = reg, \
163 .nr_pins = pins, \
164 .eint_type = EINT_TYPE_NONE, \
165 .name = id \
166 }
167
168#define PIN_BANK_2BIT(pins, reg, id) \
169 { \
170 .type = &bank_type_2bit_off, \
171 .pctl_offset = reg, \
172 .nr_pins = pins, \
173 .eint_type = EINT_TYPE_NONE, \
174 .name = id \
175 }
176
177#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
178 { \
179 .type = &bank_type_2bit_off, \
180 .pctl_offset = reg, \
181 .nr_pins = pins, \
182 .eint_type = EINT_TYPE_GPIO, \
183 .eint_func = 3, \
184 .eint_mask = emask, \
185 .eint_offset = eoffs, \
186 .name = id \
187 }
188
189#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs) \
190 { \
191 .type = &bank_type_2bit_alive,\
192 .pctl_offset = reg, \
193 .nr_pins = pins, \
194 .eint_type = EINT_TYPE_WKUP, \
195 .eint_func = 2, \
196 .eint_mask = (1 << (pins)) - 1, \
197 .eint_offset = eoffs, \
198 .name = id \
199 }
200
201/**
202 * struct s3c64xx_eint0_data: EINT0 common data
203 * @drvdata: pin controller driver data
204 * @domains: IRQ domains of particular EINT0 interrupts
205 * @pins: pin offsets inside of banks of particular EINT0 interrupts
206 */
207struct s3c64xx_eint0_data {
208 struct samsung_pinctrl_drv_data *drvdata;
209 struct irq_domain *domains[NUM_EINT0];
210 u8 pins[NUM_EINT0];
211};
212
213/**
214 * struct s3c64xx_eint0_domain_data: EINT0 per-domain data
215 * @bank: pin bank related to the domain
216 * @eints: EINT0 interrupts related to the domain
217 */
218struct s3c64xx_eint0_domain_data {
219 struct samsung_pin_bank *bank;
220 u8 eints[];
221};
222
223/**
224 * struct s3c64xx_eint_gpio_data: GPIO EINT data
225 * @drvdata: pin controller driver data
226 * @domains: array of domains related to EINT interrupt groups
227 */
228struct s3c64xx_eint_gpio_data {
229 struct samsung_pinctrl_drv_data *drvdata;
230 struct irq_domain *domains[];
231};
232
233/*
234 * Common functions for S3C64xx EINT configuration
235 */
236
237static int s3c64xx_irq_get_trigger(unsigned int type)
238{
239 int trigger;
240
241 switch (type) {
242 case IRQ_TYPE_EDGE_RISING:
243 trigger = EINT_EDGE_RISING;
244 break;
245 case IRQ_TYPE_EDGE_FALLING:
246 trigger = EINT_EDGE_FALLING;
247 break;
248 case IRQ_TYPE_EDGE_BOTH:
249 trigger = EINT_EDGE_BOTH;
250 break;
251 case IRQ_TYPE_LEVEL_HIGH:
252 trigger = EINT_LEVEL_HIGH;
253 break;
254 case IRQ_TYPE_LEVEL_LOW:
255 trigger = EINT_LEVEL_LOW;
256 break;
257 default:
258 return -EINVAL;
259 }
260
261 return trigger;
262}
263
264static void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type)
265{
266 /* Edge- and level-triggered interrupts need different handlers */
267 if (type & IRQ_TYPE_EDGE_BOTH)
268 __irq_set_handler_locked(irq, handle_edge_irq);
269 else
270 __irq_set_handler_locked(irq, handle_level_irq);
271}
272
273static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
274 struct samsung_pin_bank *bank, int pin)
275{
276 struct samsung_pin_bank_type *bank_type = bank->type;
277 unsigned long flags;
278 void __iomem *reg;
279 u8 shift;
280 u32 mask;
281 u32 val;
282
283 /* Make sure that pin is configured as interrupt */
284 reg = d->virt_base + bank->pctl_offset;
285 shift = pin;
286 if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
287 /* 4-bit bank type with 2 con regs */
288 reg += 4;
289 shift -= 8;
290 }
291
292 shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
293 mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
294
295 spin_lock_irqsave(&bank->slock, flags);
296
297 val = readl(reg);
298 val &= ~(mask << shift);
299 val |= bank->eint_func << shift;
300 writel(val, reg);
301
302 spin_unlock_irqrestore(&bank->slock, flags);
303}
304
305/*
306 * Functions for EINT GPIO configuration (EINT groups 1-9)
307 */
308
309static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
310{
311 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
312 struct samsung_pinctrl_drv_data *d = bank->drvdata;
313 unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
314 void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
315 u32 val;
316
317 val = readl(reg);
318 if (mask)
319 val |= 1 << index;
320 else
321 val &= ~(1 << index);
322 writel(val, reg);
323}
324
325static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
326{
327 s3c64xx_gpio_irq_set_mask(irqd, false);
328}
329
330static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
331{
332 s3c64xx_gpio_irq_set_mask(irqd, true);
333}
334
335static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
336{
337 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
338 struct samsung_pinctrl_drv_data *d = bank->drvdata;
339 unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
340 void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
341
342 writel(1 << index, reg);
343}
344
345static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
346{
347 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
348 struct samsung_pinctrl_drv_data *d = bank->drvdata;
349 void __iomem *reg;
350 int trigger;
351 u8 shift;
352 u32 val;
353
354 trigger = s3c64xx_irq_get_trigger(type);
355 if (trigger < 0) {
356 pr_err("unsupported external interrupt type\n");
357 return -EINVAL;
358 }
359
360 s3c64xx_irq_set_handler(irqd->irq, type);
361
362 /* Set up interrupt trigger */
363 reg = d->virt_base + EINTCON_REG(bank->eint_offset);
364 shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
365 shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
366
367 val = readl(reg);
368 val &= ~(EINT_CON_MASK << shift);
369 val |= trigger << shift;
370 writel(val, reg);
371
372 s3c64xx_irq_set_function(d, bank, irqd->hwirq);
373
374 return 0;
375}
376
377/*
378 * irq_chip for gpio interrupts.
379 */
380static struct irq_chip s3c64xx_gpio_irq_chip = {
381 .name = "GPIO",
382 .irq_unmask = s3c64xx_gpio_irq_unmask,
383 .irq_mask = s3c64xx_gpio_irq_mask,
384 .irq_ack = s3c64xx_gpio_irq_ack,
385 .irq_set_type = s3c64xx_gpio_irq_set_type,
386};
387
388static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
389 irq_hw_number_t hw)
390{
391 struct samsung_pin_bank *bank = h->host_data;
392
393 if (!(bank->eint_mask & (1 << hw)))
394 return -EINVAL;
395
396 irq_set_chip_and_handler(virq,
397 &s3c64xx_gpio_irq_chip, handle_level_irq);
398 irq_set_chip_data(virq, bank);
399 set_irq_flags(virq, IRQF_VALID);
400
401 return 0;
402}
403
404/*
405 * irq domain callbacks for external gpio interrupt controller.
406 */
407static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
408 .map = s3c64xx_gpio_irq_map,
409 .xlate = irq_domain_xlate_twocell,
410};
411
412static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
413{
414 struct irq_chip *chip = irq_get_chip(irq);
415 struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
416 struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
417
418 chained_irq_enter(chip, desc);
419
420 do {
421 unsigned int svc;
422 unsigned int group;
423 unsigned int pin;
424 unsigned int virq;
425
426 svc = readl(drvdata->virt_base + SERVICE_REG);
427 group = SVC_GROUP(svc);
428 pin = svc & SVC_NUM_MASK;
429
430 if (!group)
431 break;
432
433 /* Group 1 is used for two pin banks */
434 if (group == 1) {
435 if (pin < 8)
436 group = 0;
437 else
438 pin -= 8;
439 }
440
441 virq = irq_linear_revmap(data->domains[group], pin);
442 /*
443 * Something must be really wrong if an unmapped EINT
444 * was unmasked...
445 */
446 BUG_ON(!virq);
447
448 generic_handle_irq(virq);
449 } while (1);
450
451 chained_irq_exit(chip, desc);
452}
453
454/**
455 * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
456 * @d: driver data of samsung pinctrl driver.
457 */
458static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
459{
460 struct s3c64xx_eint_gpio_data *data;
461 struct samsung_pin_bank *bank;
462 struct device *dev = d->dev;
463 unsigned int nr_domains;
464 unsigned int i;
465
466 if (!d->irq) {
467 dev_err(dev, "irq number not available\n");
468 return -EINVAL;
469 }
470
471 nr_domains = 0;
472 bank = d->ctrl->pin_banks;
473 for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
474 unsigned int nr_eints;
475 unsigned int mask;
476
477 if (bank->eint_type != EINT_TYPE_GPIO)
478 continue;
479
480 mask = bank->eint_mask;
481 nr_eints = fls(mask);
482
483 bank->irq_domain = irq_domain_add_linear(bank->of_node,
484 nr_eints, &s3c64xx_gpio_irqd_ops, bank);
485 if (!bank->irq_domain) {
486 dev_err(dev, "gpio irq domain add failed\n");
487 return -ENXIO;
488 }
489
490 ++nr_domains;
491 }
492
493 data = devm_kzalloc(dev, sizeof(*data)
494 + nr_domains * sizeof(*data->domains), GFP_KERNEL);
495 if (!data) {
496 dev_err(dev, "failed to allocate handler data\n");
497 return -ENOMEM;
498 }
499 data->drvdata = d;
500
501 bank = d->ctrl->pin_banks;
502 nr_domains = 0;
503 for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
504 if (bank->eint_type != EINT_TYPE_GPIO)
505 continue;
506
507 data->domains[nr_domains++] = bank->irq_domain;
508 }
509
510 irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
511 irq_set_handler_data(d->irq, data);
512
513 return 0;
514}
515
516/*
517 * Functions for configuration of EINT0 wake-up interrupts
518 */
519
520static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
521{
522 struct s3c64xx_eint0_domain_data *ddata =
523 irq_data_get_irq_chip_data(irqd);
524 struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
525 u32 val;
526
527 val = readl(d->virt_base + EINT0MASK_REG);
528 if (mask)
529 val |= 1 << ddata->eints[irqd->hwirq];
530 else
531 val &= ~(1 << ddata->eints[irqd->hwirq]);
532 writel(val, d->virt_base + EINT0MASK_REG);
533}
534
535static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
536{
537 s3c64xx_eint0_irq_set_mask(irqd, false);
538}
539
540static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
541{
542 s3c64xx_eint0_irq_set_mask(irqd, true);
543}
544
545static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
546{
547 struct s3c64xx_eint0_domain_data *ddata =
548 irq_data_get_irq_chip_data(irqd);
549 struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
550
551 writel(1 << ddata->eints[irqd->hwirq],
552 d->virt_base + EINT0PEND_REG);
553}
554
555static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
556{
557 struct s3c64xx_eint0_domain_data *ddata =
558 irq_data_get_irq_chip_data(irqd);
559 struct samsung_pin_bank *bank = ddata->bank;
560 struct samsung_pinctrl_drv_data *d = bank->drvdata;
561 void __iomem *reg;
562 int trigger;
563 u8 shift;
564 u32 val;
565
566 trigger = s3c64xx_irq_get_trigger(type);
567 if (trigger < 0) {
568 pr_err("unsupported external interrupt type\n");
569 return -EINVAL;
570 }
571
572 s3c64xx_irq_set_handler(irqd->irq, type);
573
574 /* Set up interrupt trigger */
575 reg = d->virt_base + EINT0CON0_REG;
576 shift = ddata->eints[irqd->hwirq];
577 if (shift >= EINT_MAX_PER_REG) {
578 reg += 4;
579 shift -= EINT_MAX_PER_REG;
580 }
581 shift = EINT_CON_LEN * (shift / 2);
582
583 val = readl(reg);
584 val &= ~(EINT_CON_MASK << shift);
585 val |= trigger << shift;
586 writel(val, reg);
587
588 s3c64xx_irq_set_function(d, bank, irqd->hwirq);
589
590 return 0;
591}
592
593/*
594 * irq_chip for wakeup interrupts
595 */
596static struct irq_chip s3c64xx_eint0_irq_chip = {
597 .name = "EINT0",
598 .irq_unmask = s3c64xx_eint0_irq_unmask,
599 .irq_mask = s3c64xx_eint0_irq_mask,
600 .irq_ack = s3c64xx_eint0_irq_ack,
601 .irq_set_type = s3c64xx_eint0_irq_set_type,
602};
603
604static inline void s3c64xx_irq_demux_eint(unsigned int irq,
605 struct irq_desc *desc, u32 range)
606{
607 struct irq_chip *chip = irq_get_chip(irq);
608 struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
609 struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
610 unsigned int pend, mask;
611
612 chained_irq_enter(chip, desc);
613
614 pend = readl(drvdata->virt_base + EINT0PEND_REG);
615 mask = readl(drvdata->virt_base + EINT0MASK_REG);
616
617 pend = pend & range & ~mask;
618 pend &= range;
619
620 while (pend) {
621 unsigned int virq;
622
623 irq = fls(pend) - 1;
624 pend &= ~(1 << irq);
625
626 virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
627 /*
628 * Something must be really wrong if an unmapped EINT
629 * was unmasked...
630 */
631 BUG_ON(!virq);
632
633 generic_handle_irq(virq);
634 }
635
636 chained_irq_exit(chip, desc);
637}
638
639static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
640{
641 s3c64xx_irq_demux_eint(irq, desc, 0xf);
642}
643
644static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
645{
646 s3c64xx_irq_demux_eint(irq, desc, 0xff0);
647}
648
649static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
650{
651 s3c64xx_irq_demux_eint(irq, desc, 0xff000);
652}
653
654static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
655{
656 s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
657}
658
659static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
660 s3c64xx_demux_eint0_3,
661 s3c64xx_demux_eint4_11,
662 s3c64xx_demux_eint12_19,
663 s3c64xx_demux_eint20_27,
664};
665
666static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
667 irq_hw_number_t hw)
668{
669 struct s3c64xx_eint0_domain_data *ddata = h->host_data;
670 struct samsung_pin_bank *bank = ddata->bank;
671
672 if (!(bank->eint_mask & (1 << hw)))
673 return -EINVAL;
674
675 irq_set_chip_and_handler(virq,
676 &s3c64xx_eint0_irq_chip, handle_level_irq);
677 irq_set_chip_data(virq, ddata);
678 set_irq_flags(virq, IRQF_VALID);
679
680 return 0;
681}
682
683/*
684 * irq domain callbacks for external wakeup interrupt controller.
685 */
686static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
687 .map = s3c64xx_eint0_irq_map,
688 .xlate = irq_domain_xlate_twocell,
689};
690
691/* list of external wakeup controllers supported */
692static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
693 { .compatible = "samsung,s3c64xx-wakeup-eint", },
694 { }
695};
696
697/**
698 * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
699 * @d: driver data of samsung pinctrl driver.
700 */
701static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
702{
703 struct device *dev = d->dev;
704 struct device_node *eint0_np = NULL;
705 struct device_node *np;
706 struct samsung_pin_bank *bank;
707 struct s3c64xx_eint0_data *data;
708 unsigned int i;
709
710 for_each_child_of_node(dev->of_node, np) {
711 if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
712 eint0_np = np;
713 break;
714 }
715 }
716 if (!eint0_np)
717 return -ENODEV;
718
719 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
720 if (!data) {
721 dev_err(dev, "could not allocate memory for wkup eint data\n");
722 return -ENOMEM;
723 }
724 data->drvdata = d;
725
726 for (i = 0; i < NUM_EINT0_IRQ; ++i) {
727 unsigned int irq;
728
729 irq = irq_of_parse_and_map(eint0_np, i);
730 if (!irq) {
731 dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
732 return -ENXIO;
733 }
734
735 irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
736 irq_set_handler_data(irq, data);
737 }
738
739 bank = d->ctrl->pin_banks;
740 for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
741 struct s3c64xx_eint0_domain_data *ddata;
742 unsigned int nr_eints;
743 unsigned int mask;
744 unsigned int irq;
745 unsigned int pin;
746
747 if (bank->eint_type != EINT_TYPE_WKUP)
748 continue;
749
750 mask = bank->eint_mask;
751 nr_eints = fls(mask);
752
753 ddata = devm_kzalloc(dev,
754 sizeof(*ddata) + nr_eints, GFP_KERNEL);
755 if (!ddata) {
756 dev_err(dev, "failed to allocate domain data\n");
757 return -ENOMEM;
758 }
759 ddata->bank = bank;
760
761 bank->irq_domain = irq_domain_add_linear(bank->of_node,
762 nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
763 if (!bank->irq_domain) {
764 dev_err(dev, "wkup irq domain add failed\n");
765 return -ENXIO;
766 }
767
768 irq = bank->eint_offset;
769 mask = bank->eint_mask;
770 for (pin = 0; mask; ++pin, mask >>= 1) {
771 if (!(mask & 1))
772 continue;
773 data->domains[irq] = bank->irq_domain;
774 data->pins[irq] = pin;
775 ddata->eints[pin] = irq;
776 ++irq;
777 }
778 }
779
780 return 0;
781}
782
783/* pin banks of s3c64xx pin-controller 0 */
784static struct samsung_pin_bank s3c64xx_pin_banks0[] = {
785 PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
786 PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
787 PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
788 PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
789 PIN_BANK_4BIT(5, 0x080, "gpe"),
790 PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
791 PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
792 PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
793 PIN_BANK_2BIT(16, 0x100, "gpi"),
794 PIN_BANK_2BIT(12, 0x120, "gpj"),
795 PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
796 PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
797 PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
798 PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
799 PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
800 PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
801 PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
802};
803
804/*
805 * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
806 * one gpio/pin-mux/pinconfig controller.
807 */
808struct samsung_pin_ctrl s3c64xx_pin_ctrl[] = {
809 {
810 /* pin-controller instance 1 data */
811 .pin_banks = s3c64xx_pin_banks0,
812 .nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0),
813 .eint_gpio_init = s3c64xx_eint_gpio_init,
814 .eint_wkup_init = s3c64xx_eint_eint0_init,
815 .label = "S3C64xx-GPIO",
816 },
817};
This page took 0.052518 seconds and 5 git commands to generate.