diff options
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 19 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.h | 16 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-samsung.c | 24 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-samsung.h | 26 |
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 | |||
38 | static struct samsung_pin_bank_type bank_type_off = { | ||
39 | .fld_width = { 4, 1, 2, 2, 2, 2, }, | ||
40 | }; | ||
41 | |||
42 | static 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 */ |
38 | static const struct of_device_id exynos_wkup_irq_ids[] = { | 47 | static 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) | |||
76 | static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) | 85 | static 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) | |||
259 | static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) | 269 | static 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 | ®, &pin_offset, &bank); | 306 | ®, &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, | |||
340 | static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, | 343 | static 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, ®_base, | 400 | pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, ®_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 = { | |||
497 | static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | 502 | static 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 | */ |
45 | enum pincfg_type { | 47 | enum 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 { | |||
103 | struct samsung_pinctrl_drv_data; | 109 | struct 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 | */ | ||
115 | struct 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 | */ |
124 | struct samsung_pin_bank { | 134 | struct 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; |