aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorThomas Abraham <thomas.abraham@linaro.org>2012-09-06 17:07:19 -0400
committerKukjin Kim <kgene.kim@samsung.com>2012-09-06 17:07:19 -0400
commit43b169db184184e1df8dea198d454a06602c5150 (patch)
tree48cb4bcd88dafdf3565b5831d98bcb3767846d52 /drivers/pinctrl
parent30574f0db1b16fedf705cb792099f8a3171598eb (diff)
pinctrl: add exynos4210 specific extensions for samsung pinctrl driver
Add information about the Exynos4210 pin banks and driver data which is used by the Samsung pinctrl driver. In addition to this, the support for external gpio and wakeup interrupt support is included and hooked up with the Samsung pinctrl driver. Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/Kconfig4
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c560
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h217
4 files changed, 782 insertions, 0 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ffed467422e7..34e94c7f68ca 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -150,6 +150,10 @@ config PINCTRL_SAMSUNG
150 select PINMUX 150 select PINMUX
151 select PINCONF 151 select PINCONF
152 152
153config PINCTRL_EXYNOS4
154 bool "Pinctrl driver data for Exynos4 SoC"
155 select PINCTRL_SAMSUNG
156
153source "drivers/pinctrl/spear/Kconfig" 157source "drivers/pinctrl/spear/Kconfig"
154 158
155endmenu 159endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 656ed83372cf..6a88113e11d9 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -30,5 +30,6 @@ obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
30obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o 30obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
31obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o 31obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
32obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o 32obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
33obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o
33 34
34obj-$(CONFIG_PLAT_SPEAR) += spear/ 35obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
new file mode 100644
index 000000000000..447818d9851b
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -0,0 +1,560 @@
1/*
2 * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2012 Linaro Ltd
7 * http://www.linaro.org
8 *
9 * Author: Thomas Abraham <thomas.ab@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This file contains the Samsung Exynos specific information required by the
17 * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
18 * external gpio and wakeup interrupt support.
19 */
20
21#include <linux/module.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
24#include <linux/irqdomain.h>
25#include <linux/irq.h>
26#include <linux/of_irq.h>
27#include <linux/io.h>
28#include <linux/slab.h>
29#include <linux/err.h>
30
31#include <asm/mach/irq.h>
32
33#include "pinctrl-samsung.h"
34#include "pinctrl-exynos.h"
35
36/* list of external wakeup controllers supported */
37static const struct of_device_id exynos_wkup_irq_ids[] = {
38 { .compatible = "samsung,exynos4210-wakeup-eint", },
39};
40
41static void exynos_gpio_irq_unmask(struct irq_data *irqd)
42{
43 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
44 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
45 unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
46 unsigned long mask;
47
48 mask = readl(d->virt_base + reg_mask);
49 mask &= ~(1 << edata->pin);
50 writel(mask, d->virt_base + reg_mask);
51}
52
53static void exynos_gpio_irq_mask(struct irq_data *irqd)
54{
55 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
56 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
57 unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
58 unsigned long mask;
59
60 mask = readl(d->virt_base + reg_mask);
61 mask |= ~(1 << edata->pin);
62 writel(mask, d->virt_base + reg_mask);
63}
64
65static void exynos_gpio_irq_ack(struct irq_data *irqd)
66{
67 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
68 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
69 unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
70
71 writel(1 << edata->pin, d->virt_base + reg_pend);
72}
73
74static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
75{
76 struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
77 struct samsung_pin_ctrl *ctrl = d->ctrl;
78 struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
79 unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
80 unsigned int con, trig_type;
81 unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
82
83 switch (type) {
84 case IRQ_TYPE_EDGE_RISING:
85 trig_type = EXYNOS_EINT_EDGE_RISING;
86 break;
87 case IRQ_TYPE_EDGE_FALLING:
88 trig_type = EXYNOS_EINT_EDGE_FALLING;
89 break;
90 case IRQ_TYPE_EDGE_BOTH:
91 trig_type = EXYNOS_EINT_EDGE_BOTH;
92 break;
93 case IRQ_TYPE_LEVEL_HIGH:
94 trig_type = EXYNOS_EINT_LEVEL_HIGH;
95 break;
96 case IRQ_TYPE_LEVEL_LOW:
97 trig_type = EXYNOS_EINT_LEVEL_LOW;
98 break;
99 default:
100 pr_err("unsupported external interrupt type\n");
101 return -EINVAL;
102 }
103
104 if (type & IRQ_TYPE_EDGE_BOTH)
105 __irq_set_handler_locked(irqd->irq, handle_edge_irq);
106 else
107 __irq_set_handler_locked(irqd->irq, handle_level_irq);
108
109 con = readl(d->virt_base + reg_con);
110 con &= ~(EXYNOS_EINT_CON_MASK << shift);
111 con |= trig_type << shift;
112 writel(con, d->virt_base + reg_con);
113 return 0;
114}
115
116/*
117 * irq_chip for gpio interrupts.
118 */
119static struct irq_chip exynos_gpio_irq_chip = {
120 .name = "exynos_gpio_irq_chip",
121 .irq_unmask = exynos_gpio_irq_unmask,
122 .irq_mask = exynos_gpio_irq_mask,
123 .irq_ack = exynos_gpio_irq_ack,
124 .irq_set_type = exynos_gpio_irq_set_type,
125};
126
127/*
128 * given a controller-local external gpio interrupt number, prepare the handler
129 * data for it.
130 */
131static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
132 struct samsung_pinctrl_drv_data *d)
133{
134 struct samsung_pin_bank *bank = d->ctrl->pin_banks;
135 struct exynos_geint_data *eint_data;
136 unsigned int nr_banks = d->ctrl->nr_banks, idx;
137 unsigned int irq_base = 0, eint_offset = 0;
138
139 if (hw >= d->ctrl->nr_gint) {
140 dev_err(d->dev, "unsupported ext-gpio interrupt\n");
141 return NULL;
142 }
143
144 for (idx = 0; idx < nr_banks; idx++, bank++) {
145 if (bank->eint_type != EINT_TYPE_GPIO)
146 continue;
147 if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
148 break;
149 irq_base += bank->nr_pins;
150 eint_offset += 4;
151 }
152
153 if (idx == nr_banks) {
154 dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
155 return NULL;
156 }
157
158 eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
159 if (!eint_data) {
160 dev_err(d->dev, "no memory for eint-gpio data\n");
161 return NULL;
162 }
163
164 eint_data->bank = bank;
165 eint_data->pin = hw - irq_base;
166 eint_data->eint_offset = eint_offset;
167 return eint_data;
168}
169
170static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
171 irq_hw_number_t hw)
172{
173 struct samsung_pinctrl_drv_data *d = h->host_data;
174 struct exynos_geint_data *eint_data;
175
176 eint_data = exynos_get_eint_data(hw, d);
177 if (!eint_data)
178 return -EINVAL;
179
180 irq_set_handler_data(virq, eint_data);
181 irq_set_chip_data(virq, h->host_data);
182 irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
183 handle_level_irq);
184 set_irq_flags(virq, IRQF_VALID);
185 return 0;
186}
187
188static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
189{
190 struct samsung_pinctrl_drv_data *d = h->host_data;
191 struct exynos_geint_data *eint_data;
192
193 eint_data = irq_get_handler_data(virq);
194 devm_kfree(d->dev, eint_data);
195}
196
197/*
198 * irq domain callbacks for external gpio interrupt controller.
199 */
200static const struct irq_domain_ops exynos_gpio_irqd_ops = {
201 .map = exynos_gpio_irq_map,
202 .unmap = exynos_gpio_irq_unmap,
203 .xlate = irq_domain_xlate_twocell,
204};
205
206static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
207{
208 struct samsung_pinctrl_drv_data *d = data;
209 struct samsung_pin_ctrl *ctrl = d->ctrl;
210 struct samsung_pin_bank *bank = ctrl->pin_banks;
211 unsigned int svc, group, pin, virq;
212
213 svc = readl(d->virt_base + ctrl->svc);
214 group = EXYNOS_SVC_GROUP(svc);
215 pin = svc & EXYNOS_SVC_NUM_MASK;
216
217 if (!group)
218 return IRQ_HANDLED;
219 bank += (group - 1);
220
221 virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
222 if (!virq)
223 return IRQ_NONE;
224 generic_handle_irq(virq);
225 return IRQ_HANDLED;
226}
227
228/*
229 * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
230 * @d: driver data of samsung pinctrl driver.
231 */
232static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
233{
234 struct device *dev = d->dev;
235 unsigned int ret;
236
237 if (!d->irq) {
238 dev_err(dev, "irq number not available\n");
239 return -EINVAL;
240 }
241
242 ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
243 0, dev_name(dev), d);
244 if (ret) {
245 dev_err(dev, "irq request failed\n");
246 return -ENXIO;
247 }
248
249 d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
250 &exynos_gpio_irqd_ops, d);
251 if (!d->gpio_irqd) {
252 dev_err(dev, "gpio irq domain allocation failed\n");
253 return -ENXIO;
254 }
255
256 return 0;
257}
258
259static void exynos_wkup_irq_unmask(struct irq_data *irqd)
260{
261 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
262 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
263 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
264 unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
265 unsigned long mask;
266
267 mask = readl(d->virt_base + reg_mask);
268 mask &= ~(1 << pin);
269 writel(mask, d->virt_base + reg_mask);
270}
271
272static void exynos_wkup_irq_mask(struct irq_data *irqd)
273{
274 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
275 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
276 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
277 unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
278 unsigned long mask;
279
280 mask = readl(d->virt_base + reg_mask);
281 mask &= ~(1 << pin);
282 writel(mask, d->virt_base + reg_mask);
283}
284
285static void exynos_wkup_irq_ack(struct irq_data *irqd)
286{
287 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
288 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
289 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
290 unsigned long pend = d->ctrl->weint_pend + (bank << 2);
291
292 writel(1 << pin, d->virt_base + pend);
293}
294
295static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
296{
297 struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
298 unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
299 unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
300 unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
301 unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
302 unsigned long con, trig_type;
303
304 switch (type) {
305 case IRQ_TYPE_EDGE_RISING:
306 trig_type = EXYNOS_EINT_EDGE_RISING;
307 break;
308 case IRQ_TYPE_EDGE_FALLING:
309 trig_type = EXYNOS_EINT_EDGE_FALLING;
310 break;
311 case IRQ_TYPE_EDGE_BOTH:
312 trig_type = EXYNOS_EINT_EDGE_BOTH;
313 break;
314 case IRQ_TYPE_LEVEL_HIGH:
315 trig_type = EXYNOS_EINT_LEVEL_HIGH;
316 break;
317 case IRQ_TYPE_LEVEL_LOW:
318 trig_type = EXYNOS_EINT_LEVEL_LOW;
319 break;
320 default:
321 pr_err("unsupported external interrupt type\n");
322 return -EINVAL;
323 }
324
325 if (type & IRQ_TYPE_EDGE_BOTH)
326 __irq_set_handler_locked(irqd->irq, handle_edge_irq);
327 else
328 __irq_set_handler_locked(irqd->irq, handle_level_irq);
329
330 con = readl(d->virt_base + reg_con);
331 con &= ~(EXYNOS_EINT_CON_MASK << shift);
332 con |= trig_type << shift;
333 writel(con, d->virt_base + reg_con);
334 return 0;
335}
336
337/*
338 * irq_chip for wakeup interrupts
339 */
340static struct irq_chip exynos_wkup_irq_chip = {
341 .name = "exynos_wkup_irq_chip",
342 .irq_unmask = exynos_wkup_irq_unmask,
343 .irq_mask = exynos_wkup_irq_mask,
344 .irq_ack = exynos_wkup_irq_ack,
345 .irq_set_type = exynos_wkup_irq_set_type,
346};
347
348/* interrupt handler for wakeup interrupts 0..15 */
349static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
350{
351 struct exynos_weint_data *eintd = irq_get_handler_data(irq);
352 struct irq_chip *chip = irq_get_chip(irq);
353 int eint_irq;
354
355 chained_irq_enter(chip, desc);
356 chip->irq_mask(&desc->irq_data);
357
358 if (chip->irq_ack)
359 chip->irq_ack(&desc->irq_data);
360
361 eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
362 generic_handle_irq(eint_irq);
363 chip->irq_unmask(&desc->irq_data);
364 chained_irq_exit(chip, desc);
365}
366
367static void exynos_irq_demux_eint(int irq_base, unsigned long pend,
368 struct irq_domain *domain)
369{
370 unsigned int irq;
371
372 while (pend) {
373 irq = fls(pend) - 1;
374 generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
375 pend &= ~(1 << irq);
376 }
377}
378
379/* interrupt handler for wakeup interrupt 16 */
380static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
381{
382 struct irq_chip *chip = irq_get_chip(irq);
383 struct exynos_weint_data *eintd = irq_get_handler_data(irq);
384 struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
385 unsigned long pend;
386
387 chained_irq_enter(chip, desc);
388 pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
389 exynos_irq_demux_eint(16, pend, eintd->domain);
390 pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
391 exynos_irq_demux_eint(24, pend, eintd->domain);
392 chained_irq_exit(chip, desc);
393}
394
395static int exynos_wkup_irq_map(struct irq_domain *h, unsigned int virq,
396 irq_hw_number_t hw)
397{
398 irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip, handle_level_irq);
399 irq_set_chip_data(virq, h->host_data);
400 set_irq_flags(virq, IRQF_VALID);
401 return 0;
402}
403
404/*
405 * irq domain callbacks for external wakeup interrupt controller.
406 */
407static const struct irq_domain_ops exynos_wkup_irqd_ops = {
408 .map = exynos_wkup_irq_map,
409 .xlate = irq_domain_xlate_twocell,
410};
411
412/*
413 * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
414 * @d: driver data of samsung pinctrl driver.
415 */
416static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
417{
418 struct device *dev = d->dev;
419 struct device_node *wkup_np;
420 struct exynos_weint_data *weint_data;
421 int idx, irq;
422
423 wkup_np = of_find_matching_node(dev->of_node, exynos_wkup_irq_ids);
424 if (!wkup_np) {
425 dev_err(dev, "wakeup controller node not found\n");
426 return -ENODEV;
427 }
428
429 d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
430 &exynos_wkup_irqd_ops, d);
431 if (!d->gpio_irqd) {
432 dev_err(dev, "wakeup irq domain allocation failed\n");
433 return -ENXIO;
434 }
435
436 weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
437 if (!weint_data) {
438 dev_err(dev, "could not allocate memory for weint_data\n");
439 return -ENOMEM;
440 }
441
442 irq = irq_of_parse_and_map(wkup_np, 16);
443 if (irq) {
444 weint_data[16].domain = d->wkup_irqd;
445 irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
446 irq_set_handler_data(irq, &weint_data[16]);
447 } else {
448 dev_err(dev, "irq number for EINT16-32 not found\n");
449 }
450
451 for (idx = 0; idx < 16; idx++) {
452 weint_data[idx].domain = d->wkup_irqd;
453 weint_data[idx].irq = idx;
454
455 irq = irq_of_parse_and_map(wkup_np, idx);
456 if (irq) {
457 irq_set_handler_data(irq, &weint_data[idx]);
458 irq_set_chained_handler(irq, exynos_irq_eint0_15);
459 } else {
460 dev_err(dev, "irq number for eint-%x not found\n", idx);
461 }
462 }
463 return 0;
464}
465
466/* pin banks of exynos4210 pin-controller 0 */
467static struct samsung_pin_bank exynos4210_pin_banks0[] = {
468 EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"),
469 EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"),
470 EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"),
471 EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"),
472 EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"),
473 EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"),
474 EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"),
475 EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"),
476 EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"),
477 EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"),
478 EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"),
479 EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"),
480 EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"),
481 EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"),
482 EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"),
483 EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"),
484};
485
486/* pin banks of exynos4210 pin-controller 1 */
487static struct samsung_pin_bank exynos4210_pin_banks1[] = {
488 EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"),
489 EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"),
490 EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"),
491 EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"),
492 EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"),
493 EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"),
494 EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"),
495 EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"),
496 EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"),
497 EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"),
498 EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"),
499 EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"),
500 EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"),
501 EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"),
502 EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"),
503 EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"),
504 EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"),
505 EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"),
506 EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"),
507 EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"),
508};
509
510/* pin banks of exynos4210 pin-controller 2 */
511static struct samsung_pin_bank exynos4210_pin_banks2[] = {
512 EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"),
513};
514
515/*
516 * Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
517 * three gpio/pin-mux/pinconfig controllers.
518 */
519struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
520 {
521 /* pin-controller instance 0 data */
522 .pin_banks = exynos4210_pin_banks0,
523 .nr_banks = ARRAY_SIZE(exynos4210_pin_banks0),
524 .base = EXYNOS4210_GPIO_A0_START,
525 .nr_pins = EXYNOS4210_GPIOA_NR_PINS,
526 .nr_gint = EXYNOS4210_GPIOA_NR_GINT,
527 .geint_con = EXYNOS_GPIO_ECON_OFFSET,
528 .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
529 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
530 .svc = EXYNOS_SVC_OFFSET,
531 .eint_gpio_init = exynos_eint_gpio_init,
532 .label = "exynos4210-gpio-ctrl0",
533 }, {
534 /* pin-controller instance 1 data */
535 .pin_banks = exynos4210_pin_banks1,
536 .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1),
537 .base = EXYNOS4210_GPIOA_NR_PINS,
538 .nr_pins = EXYNOS4210_GPIOB_NR_PINS,
539 .nr_gint = EXYNOS4210_GPIOB_NR_GINT,
540 .nr_wint = 32,
541 .geint_con = EXYNOS_GPIO_ECON_OFFSET,
542 .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
543 .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
544 .weint_con = EXYNOS_WKUP_ECON_OFFSET,
545 .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
546 .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
547 .svc = EXYNOS_SVC_OFFSET,
548 .eint_gpio_init = exynos_eint_gpio_init,
549 .eint_wkup_init = exynos_eint_wkup_init,
550 .label = "exynos4210-gpio-ctrl1",
551 }, {
552 /* pin-controller instance 2 data */
553 .pin_banks = exynos4210_pin_banks2,
554 .nr_banks = ARRAY_SIZE(exynos4210_pin_banks2),
555 .base = EXYNOS4210_GPIOA_NR_PINS +
556 EXYNOS4210_GPIOB_NR_PINS,
557 .nr_pins = EXYNOS4210_GPIOC_NR_PINS,
558 .label = "exynos4210-gpio-ctrl2",
559 },
560};
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
new file mode 100644
index 000000000000..5f27ba974a3a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -0,0 +1,217 @@
1/*
2 * Exynos specific definitions for Samsung pinctrl and gpiolib driver.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 * Copyright (c) 2012 Linaro Ltd
7 * http://www.linaro.org
8 *
9 * This file contains the Exynos specific definitions for the Samsung
10 * pinctrl/gpiolib interface drivers.
11 *
12 * Author: Thomas Abraham <thomas.ab@samsung.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 */
19
20#define EXYNOS_GPIO_START(__gpio) ((__gpio##_START) + (__gpio##_NR))
21
22#define EXYNOS4210_GPIO_A0_NR (8)
23#define EXYNOS4210_GPIO_A1_NR (6)
24#define EXYNOS4210_GPIO_B_NR (8)
25#define EXYNOS4210_GPIO_C0_NR (5)
26#define EXYNOS4210_GPIO_C1_NR (5)
27#define EXYNOS4210_GPIO_D0_NR (4)
28#define EXYNOS4210_GPIO_D1_NR (4)
29#define EXYNOS4210_GPIO_E0_NR (5)
30#define EXYNOS4210_GPIO_E1_NR (8)
31#define EXYNOS4210_GPIO_E2_NR (6)
32#define EXYNOS4210_GPIO_E3_NR (8)
33#define EXYNOS4210_GPIO_E4_NR (8)
34#define EXYNOS4210_GPIO_F0_NR (8)
35#define EXYNOS4210_GPIO_F1_NR (8)
36#define EXYNOS4210_GPIO_F2_NR (8)
37#define EXYNOS4210_GPIO_F3_NR (6)
38#define EXYNOS4210_GPIO_J0_NR (8)
39#define EXYNOS4210_GPIO_J1_NR (5)
40#define EXYNOS4210_GPIO_K0_NR (7)
41#define EXYNOS4210_GPIO_K1_NR (7)
42#define EXYNOS4210_GPIO_K2_NR (7)
43#define EXYNOS4210_GPIO_K3_NR (7)
44#define EXYNOS4210_GPIO_L0_NR (8)
45#define EXYNOS4210_GPIO_L1_NR (3)
46#define EXYNOS4210_GPIO_L2_NR (8)
47#define EXYNOS4210_GPIO_Y0_NR (6)
48#define EXYNOS4210_GPIO_Y1_NR (4)
49#define EXYNOS4210_GPIO_Y2_NR (6)
50#define EXYNOS4210_GPIO_Y3_NR (8)
51#define EXYNOS4210_GPIO_Y4_NR (8)
52#define EXYNOS4210_GPIO_Y5_NR (8)
53#define EXYNOS4210_GPIO_Y6_NR (8)
54#define EXYNOS4210_GPIO_X0_NR (8)
55#define EXYNOS4210_GPIO_X1_NR (8)
56#define EXYNOS4210_GPIO_X2_NR (8)
57#define EXYNOS4210_GPIO_X3_NR (8)
58#define EXYNOS4210_GPIO_Z_NR (7)
59
60enum exynos4210_gpio_xa_start {
61 EXYNOS4210_GPIO_A0_START = 0,
62 EXYNOS4210_GPIO_A1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0),
63 EXYNOS4210_GPIO_B_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1),
64 EXYNOS4210_GPIO_C0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_B),
65 EXYNOS4210_GPIO_C1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0),
66 EXYNOS4210_GPIO_D0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1),
67 EXYNOS4210_GPIO_D1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0),
68 EXYNOS4210_GPIO_E0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1),
69 EXYNOS4210_GPIO_E1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0),
70 EXYNOS4210_GPIO_E2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1),
71 EXYNOS4210_GPIO_E3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2),
72 EXYNOS4210_GPIO_E4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3),
73 EXYNOS4210_GPIO_F0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4),
74 EXYNOS4210_GPIO_F1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0),
75 EXYNOS4210_GPIO_F2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1),
76 EXYNOS4210_GPIO_F3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2),
77};
78
79enum exynos4210_gpio_xb_start {
80 EXYNOS4210_GPIO_J0_START = 0,
81 EXYNOS4210_GPIO_J1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0),
82 EXYNOS4210_GPIO_K0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1),
83 EXYNOS4210_GPIO_K1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0),
84 EXYNOS4210_GPIO_K2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1),
85 EXYNOS4210_GPIO_K3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2),
86 EXYNOS4210_GPIO_L0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3),
87 EXYNOS4210_GPIO_L1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0),
88 EXYNOS4210_GPIO_L2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1),
89 EXYNOS4210_GPIO_Y0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2),
90 EXYNOS4210_GPIO_Y1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0),
91 EXYNOS4210_GPIO_Y2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1),
92 EXYNOS4210_GPIO_Y3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2),
93 EXYNOS4210_GPIO_Y4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3),
94 EXYNOS4210_GPIO_Y5_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4),
95 EXYNOS4210_GPIO_Y6_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5),
96 EXYNOS4210_GPIO_X0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6),
97 EXYNOS4210_GPIO_X1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0),
98 EXYNOS4210_GPIO_X2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1),
99 EXYNOS4210_GPIO_X3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2),
100};
101
102enum exynos4210_gpio_xc_start {
103 EXYNOS4210_GPIO_Z_START = 0,
104};
105
106#define EXYNOS4210_GPIO_A0_IRQ EXYNOS4210_GPIO_A0_START
107#define EXYNOS4210_GPIO_A1_IRQ EXYNOS4210_GPIO_A1_START
108#define EXYNOS4210_GPIO_B_IRQ EXYNOS4210_GPIO_B_START
109#define EXYNOS4210_GPIO_C0_IRQ EXYNOS4210_GPIO_C0_START
110#define EXYNOS4210_GPIO_C1_IRQ EXYNOS4210_GPIO_C1_START
111#define EXYNOS4210_GPIO_D0_IRQ EXYNOS4210_GPIO_D0_START
112#define EXYNOS4210_GPIO_D1_IRQ EXYNOS4210_GPIO_D1_START
113#define EXYNOS4210_GPIO_E0_IRQ EXYNOS4210_GPIO_E0_START
114#define EXYNOS4210_GPIO_E1_IRQ EXYNOS4210_GPIO_E1_START
115#define EXYNOS4210_GPIO_E2_IRQ EXYNOS4210_GPIO_E2_START
116#define EXYNOS4210_GPIO_E3_IRQ EXYNOS4210_GPIO_E3_START
117#define EXYNOS4210_GPIO_E4_IRQ EXYNOS4210_GPIO_E4_START
118#define EXYNOS4210_GPIO_F0_IRQ EXYNOS4210_GPIO_F0_START
119#define EXYNOS4210_GPIO_F1_IRQ EXYNOS4210_GPIO_F1_START
120#define EXYNOS4210_GPIO_F2_IRQ EXYNOS4210_GPIO_F2_START
121#define EXYNOS4210_GPIO_F3_IRQ EXYNOS4210_GPIO_F3_START
122#define EXYNOS4210_GPIO_J0_IRQ EXYNOS4210_GPIO_J0_START
123#define EXYNOS4210_GPIO_J1_IRQ EXYNOS4210_GPIO_J1_START
124#define EXYNOS4210_GPIO_K0_IRQ EXYNOS4210_GPIO_K0_START
125#define EXYNOS4210_GPIO_K1_IRQ EXYNOS4210_GPIO_K1_START
126#define EXYNOS4210_GPIO_K2_IRQ EXYNOS4210_GPIO_K2_START
127#define EXYNOS4210_GPIO_K3_IRQ EXYNOS4210_GPIO_K3_START
128#define EXYNOS4210_GPIO_L0_IRQ EXYNOS4210_GPIO_L0_START
129#define EXYNOS4210_GPIO_L1_IRQ EXYNOS4210_GPIO_L1_START
130#define EXYNOS4210_GPIO_L2_IRQ EXYNOS4210_GPIO_L2_START
131#define EXYNOS4210_GPIO_Z_IRQ EXYNOS4210_GPIO_Z_START
132
133#define EXYNOS4210_GPIOA_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
134#define EXYNOS4210_GPIOA_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
135#define EXYNOS4210_GPIOB_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
136#define EXYNOS4210_GPIOB_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
137#define EXYNOS4210_GPIOC_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
138
139/* External GPIO and wakeup interrupt related definitions */
140#define EXYNOS_GPIO_ECON_OFFSET 0x700
141#define EXYNOS_GPIO_EMASK_OFFSET 0x900
142#define EXYNOS_GPIO_EPEND_OFFSET 0xA00
143#define EXYNOS_WKUP_ECON_OFFSET 0xE00
144#define EXYNOS_WKUP_EMASK_OFFSET 0xF00
145#define EXYNOS_WKUP_EPEND_OFFSET 0xF40
146#define EXYNOS_SVC_OFFSET 0xB08
147
148/* helpers to access interrupt service register */
149#define EXYNOS_SVC_GROUP_SHIFT 3
150#define EXYNOS_SVC_GROUP_MASK 0x1f
151#define EXYNOS_SVC_NUM_MASK 7
152#define EXYNOS_SVC_GROUP(x) ((x >> EXYNOS_SVC_GROUP_SHIFT) & \
153 EXYNOS_SVC_GROUP_MASK)
154
155/* Exynos specific external interrupt trigger types */
156#define EXYNOS_EINT_LEVEL_LOW 0
157#define EXYNOS_EINT_LEVEL_HIGH 1
158#define EXYNOS_EINT_EDGE_FALLING 2
159#define EXYNOS_EINT_EDGE_RISING 3
160#define EXYNOS_EINT_EDGE_BOTH 4
161#define EXYNOS_EINT_CON_MASK 0xF
162#define EXYNOS_EINT_CON_LEN 4
163
164#define EXYNOS_EINT_MAX_PER_BANK 8
165#define EXYNOS_EINT_NR_WKUP_EINT
166
167#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id) \
168 { \
169 .pctl_offset = reg, \
170 .pin_base = (__gpio##_START), \
171 .nr_pins = (__gpio##_NR), \
172 .func_width = 4, \
173 .pud_width = 2, \
174 .drv_width = 2, \
175 .conpdn_width = 2, \
176 .pudpdn_width = 2, \
177 .eint_type = EINT_TYPE_NONE, \
178 .name = id \
179 }
180
181#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id) \
182 { \
183 .pctl_offset = reg, \
184 .pin_base = (__gpio##_START), \
185 .nr_pins = (__gpio##_NR), \
186 .func_width = 4, \
187 .pud_width = 2, \
188 .drv_width = 2, \
189 .conpdn_width = 2, \
190 .pudpdn_width = 2, \
191 .eint_type = EINT_TYPE_GPIO, \
192 .irq_base = (__gpio##_IRQ), \
193 .name = id \
194 }
195
196/**
197 * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
198 * @bank: pin bank from which this gpio interrupt originates.
199 * @pin: pin number within the bank.
200 * @eint_offset: offset to be added to the con/pend/mask register bank base.
201 */
202struct exynos_geint_data {
203 struct samsung_pin_bank *bank;
204 u32 pin;
205 u32 eint_offset;
206};
207
208/**
209 * struct exynos_weint_data: irq specific data for all the wakeup interrupts
210 * generated by the external wakeup interrupt controller.
211 * @domain: irq domain representing the external wakeup interrupts
212 * @irq: interrupt number within the domain.
213 */
214struct exynos_weint_data {
215 struct irq_domain *domain;
216 u32 irq;
217};