aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c6
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c37
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h9
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
38static struct samsung_pin_bank_type bank_type_off = { 38static 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
42static struct samsung_pin_bank_type bank_type_alive = { 43static 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 */
115struct samsung_pin_bank_type { 109struct 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/**