aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c19
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h16
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c24
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h26
4 files changed, 49 insertions, 36 deletions
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index cf7700ed57b8..b5dbb87800fd 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -34,6 +34,15 @@
34#include "pinctrl-samsung.h" 34#include "pinctrl-samsung.h"
35#include "pinctrl-exynos.h" 35#include "pinctrl-exynos.h"
36 36
37
38static struct samsung_pin_bank_type bank_type_off = {
39 .fld_width = { 4, 1, 2, 2, 2, 2, },
40};
41
42static struct samsung_pin_bank_type bank_type_alive = {
43 .fld_width = { 4, 1, 2, 2, },
44};
45
37/* list of external wakeup controllers supported */ 46/* list of external wakeup controllers supported */
38static const struct of_device_id exynos_wkup_irq_ids[] = { 47static const struct of_device_id exynos_wkup_irq_ids[] = {
39 { .compatible = "samsung,exynos4210-wakeup-eint", }, 48 { .compatible = "samsung,exynos4210-wakeup-eint", },
@@ -76,6 +85,7 @@ static void exynos_gpio_irq_ack(struct irq_data *irqd)
76static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 85static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
77{ 86{
78 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 87 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
88 struct samsung_pin_bank_type *bank_type = bank->type;
79 struct samsung_pinctrl_drv_data *d = bank->drvdata; 89 struct samsung_pinctrl_drv_data *d = bank->drvdata;
80 struct samsung_pin_ctrl *ctrl = d->ctrl; 90 struct samsung_pin_ctrl *ctrl = d->ctrl;
81 unsigned int pin = irqd->hwirq; 91 unsigned int pin = irqd->hwirq;
@@ -117,8 +127,8 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
117 writel(con, d->virt_base + reg_con); 127 writel(con, d->virt_base + reg_con);
118 128
119 reg_con = bank->pctl_offset; 129 reg_con = bank->pctl_offset;
120 shift = pin * bank->func_width; 130 shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
121 mask = (1 << bank->func_width) - 1; 131 mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
122 132
123 spin_lock_irqsave(&bank->slock, flags); 133 spin_lock_irqsave(&bank->slock, flags);
124 134
@@ -259,6 +269,7 @@ static void exynos_wkup_irq_ack(struct irq_data *irqd)
259static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) 269static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
260{ 270{
261 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 271 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
272 struct samsung_pin_bank_type *bank_type = bank->type;
262 struct samsung_pinctrl_drv_data *d = bank->drvdata; 273 struct samsung_pinctrl_drv_data *d = bank->drvdata;
263 unsigned int pin = irqd->hwirq; 274 unsigned int pin = irqd->hwirq;
264 unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset; 275 unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
@@ -299,8 +310,8 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
299 writel(con, d->virt_base + reg_con); 310 writel(con, d->virt_base + reg_con);
300 311
301 reg_con = bank->pctl_offset; 312 reg_con = bank->pctl_offset;
302 shift = pin * bank->func_width; 313 shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
303 mask = (1 << bank->func_width) - 1; 314 mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
304 315
305 spin_lock_irqsave(&bank->slock, flags); 316 spin_lock_irqsave(&bank->slock, flags);
306 317
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 0a708890d8b4..9b1f77a5bf0f 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -48,26 +48,18 @@
48 48
49#define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \ 49#define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \
50 { \ 50 { \
51 .type = &bank_type_off, \
51 .pctl_offset = reg, \ 52 .pctl_offset = reg, \
52 .nr_pins = pins, \ 53 .nr_pins = pins, \
53 .func_width = 4, \
54 .pud_width = 2, \
55 .drv_width = 2, \
56 .conpdn_width = 2, \
57 .pudpdn_width = 2, \
58 .eint_type = EINT_TYPE_NONE, \ 54 .eint_type = EINT_TYPE_NONE, \
59 .name = id \ 55 .name = id \
60 } 56 }
61 57
62#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \ 58#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \
63 { \ 59 { \
60 .type = &bank_type_off, \
64 .pctl_offset = reg, \ 61 .pctl_offset = reg, \
65 .nr_pins = pins, \ 62 .nr_pins = pins, \
66 .func_width = 4, \
67 .pud_width = 2, \
68 .drv_width = 2, \
69 .conpdn_width = 2, \
70 .pudpdn_width = 2, \
71 .eint_type = EINT_TYPE_GPIO, \ 63 .eint_type = EINT_TYPE_GPIO, \
72 .eint_offset = offs, \ 64 .eint_offset = offs, \
73 .name = id \ 65 .name = id \
@@ -75,11 +67,9 @@
75 67
76#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \ 68#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \
77 { \ 69 { \
70 .type = &bank_type_alive, \
78 .pctl_offset = reg, \ 71 .pctl_offset = reg, \
79 .nr_pins = pins, \ 72 .nr_pins = pins, \
80 .func_width = 4, \
81 .pud_width = 2, \
82 .drv_width = 2, \
83 .eint_type = EINT_TYPE_WKUP, \ 73 .eint_type = EINT_TYPE_WKUP, \
84 .eint_offset = offs, \ 74 .eint_offset = offs, \
85 .name = id \ 75 .name = id \
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 0df613134072..97dd56024e33 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -300,10 +300,13 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
300 * pin function number in the config register. 300 * pin function number in the config register.
301 */ 301 */
302 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { 302 for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
303 struct samsung_pin_bank_type *type;
304
303 pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base, 305 pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
304 &reg, &pin_offset, &bank); 306 &reg, &pin_offset, &bank);
305 mask = (1 << bank->func_width) - 1; 307 type = bank->type;
306 shift = pin_offset * bank->func_width; 308 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
309 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
307 310
308 spin_lock_irqsave(&bank->slock, flags); 311 spin_lock_irqsave(&bank->slock, flags);
309 312
@@ -340,6 +343,7 @@ static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
340static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, 343static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
341 struct pinctrl_gpio_range *range, unsigned offset, bool input) 344 struct pinctrl_gpio_range *range, unsigned offset, bool input)
342{ 345{
346 struct samsung_pin_bank_type *type;
343 struct samsung_pin_bank *bank; 347 struct samsung_pin_bank *bank;
344 struct samsung_pinctrl_drv_data *drvdata; 348 struct samsung_pinctrl_drv_data *drvdata;
345 void __iomem *reg; 349 void __iomem *reg;
@@ -347,13 +351,14 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
347 unsigned long flags; 351 unsigned long flags;
348 352
349 bank = gc_to_pin_bank(range->gc); 353 bank = gc_to_pin_bank(range->gc);
354 type = bank->type;
350 drvdata = pinctrl_dev_get_drvdata(pctldev); 355 drvdata = pinctrl_dev_get_drvdata(pctldev);
351 356
352 pin_offset = offset - bank->pin_base; 357 pin_offset = offset - bank->pin_base;
353 reg = drvdata->virt_base + bank->pctl_offset; 358 reg = drvdata->virt_base + bank->pctl_offset;
354 359
355 mask = (1 << bank->func_width) - 1; 360 mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
356 shift = pin_offset * bank->func_width; 361 shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
357 362
358 spin_lock_irqsave(&bank->slock, flags); 363 spin_lock_irqsave(&bank->slock, flags);
359 364
@@ -383,6 +388,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
383 unsigned long *config, bool set) 388 unsigned long *config, bool set)
384{ 389{
385 struct samsung_pinctrl_drv_data *drvdata; 390 struct samsung_pinctrl_drv_data *drvdata;
391 struct samsung_pin_bank_type *type;
386 struct samsung_pin_bank *bank; 392 struct samsung_pin_bank *bank;
387 void __iomem *reg_base; 393 void __iomem *reg_base;
388 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config); 394 enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
@@ -393,22 +399,19 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
393 drvdata = pinctrl_dev_get_drvdata(pctldev); 399 drvdata = pinctrl_dev_get_drvdata(pctldev);
394 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base, 400 pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
395 &pin_offset, &bank); 401 &pin_offset, &bank);
402 type = bank->type;
396 403
397 switch (cfg_type) { 404 switch (cfg_type) {
398 case PINCFG_TYPE_PUD: 405 case PINCFG_TYPE_PUD:
399 width = bank->pud_width;
400 cfg_reg = PUD_REG; 406 cfg_reg = PUD_REG;
401 break; 407 break;
402 case PINCFG_TYPE_DRV: 408 case PINCFG_TYPE_DRV:
403 width = bank->drv_width;
404 cfg_reg = DRV_REG; 409 cfg_reg = DRV_REG;
405 break; 410 break;
406 case PINCFG_TYPE_CON_PDN: 411 case PINCFG_TYPE_CON_PDN:
407 width = bank->conpdn_width;
408 cfg_reg = CONPDN_REG; 412 cfg_reg = CONPDN_REG;
409 break; 413 break;
410 case PINCFG_TYPE_PUD_PDN: 414 case PINCFG_TYPE_PUD_PDN:
411 width = bank->pudpdn_width;
412 cfg_reg = PUDPDN_REG; 415 cfg_reg = PUDPDN_REG;
413 break; 416 break;
414 default: 417 default:
@@ -416,9 +419,11 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
416 return -EINVAL; 419 return -EINVAL;
417 } 420 }
418 421
419 if (!width) 422 if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
420 return -EINVAL; 423 return -EINVAL;
421 424
425 width = type->fld_width[cfg_type];
426
422 spin_lock_irqsave(&bank->slock, flags); 427 spin_lock_irqsave(&bank->slock, flags);
423 428
424 mask = (1 << width) - 1; 429 mask = (1 << width) - 1;
@@ -497,6 +502,7 @@ static const struct pinconf_ops samsung_pinconf_ops = {
497static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 502static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
498{ 503{
499 struct samsung_pin_bank *bank = gc_to_pin_bank(gc); 504 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
505 struct samsung_pin_bank_type *type = bank->type;
500 unsigned long flags; 506 unsigned long flags;
501 void __iomem *reg; 507 void __iomem *reg;
502 u32 data; 508 u32 data;
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index b9dbe7949fab..1c590f7e95dd 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -37,16 +37,22 @@
37 37
38/** 38/**
39 * enum pincfg_type - possible pin configuration types supported. 39 * enum pincfg_type - possible pin configuration types supported.
40 * @PINCFG_TYPE_FUNC: Function configuration.
41 * @PINCFG_TYPE_DAT: Pin value configuration.
40 * @PINCFG_TYPE_PUD: Pull up/down configuration. 42 * @PINCFG_TYPE_PUD: Pull up/down configuration.
41 * @PINCFG_TYPE_DRV: Drive strength configuration. 43 * @PINCFG_TYPE_DRV: Drive strength configuration.
42 * @PINCFG_TYPE_CON_PDN: Pin function in power down mode. 44 * @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
43 * @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode. 45 * @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
44 */ 46 */
45enum pincfg_type { 47enum pincfg_type {
48 PINCFG_TYPE_FUNC,
49 PINCFG_TYPE_DAT,
46 PINCFG_TYPE_PUD, 50 PINCFG_TYPE_PUD,
47 PINCFG_TYPE_DRV, 51 PINCFG_TYPE_DRV,
48 PINCFG_TYPE_CON_PDN, 52 PINCFG_TYPE_CON_PDN,
49 PINCFG_TYPE_PUD_PDN, 53 PINCFG_TYPE_PUD_PDN,
54
55 PINCFG_TYPE_NUM
50}; 56};
51 57
52/* 58/*
@@ -103,15 +109,19 @@ enum eint_type {
103struct samsung_pinctrl_drv_data; 109struct samsung_pinctrl_drv_data;
104 110
105/** 111/**
112 * struct samsung_pin_bank_type: pin bank type description
113 * @fld_width: widths of configuration bitfields (0 if unavailable)
114 */
115struct samsung_pin_bank_type {
116 u8 fld_width[PINCFG_TYPE_NUM];
117};
118
119/**
106 * struct samsung_pin_bank: represent a controller pin-bank. 120 * struct samsung_pin_bank: represent a controller pin-bank.
121 * @type: type of the bank (register offsets and bitfield widths)
107 * @pctl_offset: starting offset of the pin-bank registers. 122 * @pctl_offset: starting offset of the pin-bank registers.
108 * @pin_base: starting pin number of the bank. 123 * @pin_base: starting pin number of the bank.
109 * @nr_pins: number of pins included in this bank. 124 * @nr_pins: number of pins included in this bank.
110 * @func_width: width of the function selector bit field.
111 * @pud_width: width of the pin pull up/down selector bit field.
112 * @drv_width: width of the pin driver strength selector bit field.
113 * @conpdn_width: width of the sleep mode function selector bin field.
114 * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
115 * @eint_type: type of the external interrupt supported by the bank. 125 * @eint_type: type of the external interrupt supported by the bank.
116 * @name: name to be prefixed for each pin in this pin bank. 126 * @name: name to be prefixed for each pin in this pin bank.
117 * @of_node: OF node of the bank. 127 * @of_node: OF node of the bank.
@@ -122,14 +132,10 @@ struct samsung_pinctrl_drv_data;
122 * @slock: spinlock protecting bank registers 132 * @slock: spinlock protecting bank registers
123 */ 133 */
124struct samsung_pin_bank { 134struct samsung_pin_bank {
135 struct samsung_pin_bank_type *type;
125 u32 pctl_offset; 136 u32 pctl_offset;
126 u32 pin_base; 137 u32 pin_base;
127 u8 nr_pins; 138 u8 nr_pins;
128 u8 func_width;
129 u8 pud_width;
130 u8 drv_width;
131 u8 conpdn_width;
132 u8 pudpdn_width;
133 enum eint_type eint_type; 139 enum eint_type eint_type;
134 u32 eint_offset; 140 u32 eint_offset;
135 char *name; 141 char *name;