diff options
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 6 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-samsung.c | 37 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-samsung.h | 9 |
3 files changed, 15 insertions, 37 deletions
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index b5dbb87800fd..8b10b1ac9071 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c | |||
@@ -37,10 +37,12 @@ | |||
37 | 37 | ||
38 | static struct samsung_pin_bank_type bank_type_off = { | 38 | static struct samsung_pin_bank_type bank_type_off = { |
39 | .fld_width = { 4, 1, 2, 2, 2, 2, }, | 39 | .fld_width = { 4, 1, 2, 2, 2, 2, }, |
40 | .reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, }, | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | static struct samsung_pin_bank_type bank_type_alive = { | 43 | static struct samsung_pin_bank_type bank_type_alive = { |
43 | .fld_width = { 4, 1, 2, 2, }, | 44 | .fld_width = { 4, 1, 2, 2, }, |
45 | .reg_offset = { 0x00, 0x04, 0x08, 0x0c, }, | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | /* list of external wakeup controllers supported */ | 48 | /* list of external wakeup controllers supported */ |
@@ -126,7 +128,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) | |||
126 | con |= trig_type << shift; | 128 | con |= trig_type << shift; |
127 | writel(con, d->virt_base + reg_con); | 129 | writel(con, d->virt_base + reg_con); |
128 | 130 | ||
129 | reg_con = bank->pctl_offset; | 131 | reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC]; |
130 | shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; | 132 | shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; |
131 | mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; | 133 | mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; |
132 | 134 | ||
@@ -309,7 +311,7 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) | |||
309 | con |= trig_type << shift; | 311 | con |= trig_type << shift; |
310 | writel(con, d->virt_base + reg_con); | 312 | writel(con, d->virt_base + reg_con); |
311 | 313 | ||
312 | reg_con = bank->pctl_offset; | 314 | reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC]; |
313 | shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; | 315 | shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; |
314 | mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; | 316 | mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; |
315 | 317 | ||
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 97dd56024e33..b917ed36fb65 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c | |||
@@ -275,10 +275,6 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, | |||
275 | *offset = pin - b->pin_base; | 275 | *offset = pin - b->pin_base; |
276 | if (bank) | 276 | if (bank) |
277 | *bank = b; | 277 | *bank = b; |
278 | |||
279 | /* some banks have two config registers in a single bank */ | ||
280 | if (*offset * b->func_width > BITS_PER_LONG) | ||
281 | *reg += 4; | ||
282 | } | 278 | } |
283 | 279 | ||
284 | /* enable or disable a pinmux function */ | 280 | /* enable or disable a pinmux function */ |
@@ -310,11 +306,11 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, | |||
310 | 306 | ||
311 | spin_lock_irqsave(&bank->slock, flags); | 307 | spin_lock_irqsave(&bank->slock, flags); |
312 | 308 | ||
313 | data = readl(reg); | 309 | data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]); |
314 | data &= ~(mask << shift); | 310 | data &= ~(mask << shift); |
315 | if (enable) | 311 | if (enable) |
316 | data |= drvdata->pin_groups[group].func << shift; | 312 | data |= drvdata->pin_groups[group].func << shift; |
317 | writel(data, reg); | 313 | writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]); |
318 | 314 | ||
319 | spin_unlock_irqrestore(&bank->slock, flags); | 315 | spin_unlock_irqrestore(&bank->slock, flags); |
320 | } | 316 | } |
@@ -355,7 +351,8 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, | |||
355 | drvdata = pinctrl_dev_get_drvdata(pctldev); | 351 | drvdata = pinctrl_dev_get_drvdata(pctldev); |
356 | 352 | ||
357 | pin_offset = offset - bank->pin_base; | 353 | pin_offset = offset - bank->pin_base; |
358 | reg = drvdata->virt_base + bank->pctl_offset; | 354 | reg = drvdata->virt_base + bank->pctl_offset + |
355 | type->reg_offset[PINCFG_TYPE_FUNC]; | ||
359 | 356 | ||
360 | mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1; | 357 | mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1; |
361 | shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC]; | 358 | shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC]; |
@@ -401,28 +398,11 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin, | |||
401 | &pin_offset, &bank); | 398 | &pin_offset, &bank); |
402 | type = bank->type; | 399 | type = bank->type; |
403 | 400 | ||
404 | switch (cfg_type) { | ||
405 | case PINCFG_TYPE_PUD: | ||
406 | cfg_reg = PUD_REG; | ||
407 | break; | ||
408 | case PINCFG_TYPE_DRV: | ||
409 | cfg_reg = DRV_REG; | ||
410 | break; | ||
411 | case PINCFG_TYPE_CON_PDN: | ||
412 | cfg_reg = CONPDN_REG; | ||
413 | break; | ||
414 | case PINCFG_TYPE_PUD_PDN: | ||
415 | cfg_reg = PUDPDN_REG; | ||
416 | break; | ||
417 | default: | ||
418 | WARN_ON(1); | ||
419 | return -EINVAL; | ||
420 | } | ||
421 | |||
422 | if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type]) | 401 | if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type]) |
423 | return -EINVAL; | 402 | return -EINVAL; |
424 | 403 | ||
425 | width = type->fld_width[cfg_type]; | 404 | width = type->fld_width[cfg_type]; |
405 | cfg_reg = type->reg_offset[cfg_type]; | ||
426 | 406 | ||
427 | spin_lock_irqsave(&bank->slock, flags); | 407 | spin_lock_irqsave(&bank->slock, flags); |
428 | 408 | ||
@@ -511,11 +491,11 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | |||
511 | 491 | ||
512 | spin_lock_irqsave(&bank->slock, flags); | 492 | spin_lock_irqsave(&bank->slock, flags); |
513 | 493 | ||
514 | data = readl(reg + DAT_REG); | 494 | data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); |
515 | data &= ~(1 << offset); | 495 | data &= ~(1 << offset); |
516 | if (value) | 496 | if (value) |
517 | data |= 1 << offset; | 497 | data |= 1 << offset; |
518 | writel(data, reg + DAT_REG); | 498 | writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]); |
519 | 499 | ||
520 | spin_unlock_irqrestore(&bank->slock, flags); | 500 | spin_unlock_irqrestore(&bank->slock, flags); |
521 | } | 501 | } |
@@ -526,10 +506,11 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) | |||
526 | void __iomem *reg; | 506 | void __iomem *reg; |
527 | u32 data; | 507 | u32 data; |
528 | struct samsung_pin_bank *bank = gc_to_pin_bank(gc); | 508 | struct samsung_pin_bank *bank = gc_to_pin_bank(gc); |
509 | struct samsung_pin_bank_type *type = bank->type; | ||
529 | 510 | ||
530 | reg = bank->drvdata->virt_base + bank->pctl_offset; | 511 | reg = bank->drvdata->virt_base + bank->pctl_offset; |
531 | 512 | ||
532 | data = readl(reg + DAT_REG); | 513 | data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); |
533 | data >>= offset; | 514 | data >>= offset; |
534 | data &= 1; | 515 | data &= 1; |
535 | return data; | 516 | return data; |
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 1c590f7e95dd..9efeee862e0d 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h | |||
@@ -25,13 +25,6 @@ | |||
25 | 25 | ||
26 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
27 | 27 | ||
28 | /* register offsets within a pin bank */ | ||
29 | #define DAT_REG 0x4 | ||
30 | #define PUD_REG 0x8 | ||
31 | #define DRV_REG 0xC | ||
32 | #define CONPDN_REG 0x10 | ||
33 | #define PUDPDN_REG 0x14 | ||
34 | |||
35 | /* pinmux function number for pin as gpio output line */ | 28 | /* pinmux function number for pin as gpio output line */ |
36 | #define FUNC_OUTPUT 0x1 | 29 | #define FUNC_OUTPUT 0x1 |
37 | 30 | ||
@@ -111,9 +104,11 @@ struct samsung_pinctrl_drv_data; | |||
111 | /** | 104 | /** |
112 | * struct samsung_pin_bank_type: pin bank type description | 105 | * struct samsung_pin_bank_type: pin bank type description |
113 | * @fld_width: widths of configuration bitfields (0 if unavailable) | 106 | * @fld_width: widths of configuration bitfields (0 if unavailable) |
107 | * @reg_offset: offsets of configuration registers (don't care of width is 0) | ||
114 | */ | 108 | */ |
115 | struct samsung_pin_bank_type { | 109 | struct samsung_pin_bank_type { |
116 | u8 fld_width[PINCFG_TYPE_NUM]; | 110 | u8 fld_width[PINCFG_TYPE_NUM]; |
111 | u8 reg_offset[PINCFG_TYPE_NUM]; | ||
117 | }; | 112 | }; |
118 | 113 | ||
119 | /** | 114 | /** |