aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Figa <tomasz.figa@gmail.com>2013-03-18 17:31:52 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-04-09 03:41:09 -0400
commit499147c9dbceee27c63bf8e6b604aca1737e9e0c (patch)
tree54305db6aac8a73a8e495f98b1f0f82886e3af53
parentd5517bec272ce4732f7e86a72a1bb815834c912c (diff)
pinctrl: samsung: Split pin bank description into two structures
This patch splits pin bank description into two structures, one describing bank type (currently only bitfield widths), which can be shared across multiple banks and second containing bank-specific parameters including a pointer to a bank type struct. It is a prerequisite for further patch removing the statically hardcoded register offsets, making it impossible to support SoCs with different set and order of pin control registers. Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-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;