diff options
| author | Wolfram Sang <wsa+renesas@sang-engineering.com> | 2016-06-06 12:08:25 -0400 |
|---|---|---|
| committer | Geert Uytterhoeven <geert+renesas@glider.be> | 2016-06-10 03:00:19 -0400 |
| commit | 8775306dcf48092ff9520463699f8fb373ceb57e (patch) | |
| tree | 0eb508dcb23e771a0a3234539fb0332341c49d3f /drivers/pinctrl/sh-pfc | |
| parent | 1a695a905c18548062509178b98bc91e67510864 (diff) | |
pinctrl: sh-pfc: refactor voltage setting
All known hardware being able to switch voltages has the same POCCTRL
register. So, factor out the common code to the core and keep only
the pin-to-bit mapping SoC specific. Convert the only user, r8a7790.
In case POCCTRL should ever get more complex (more voltages to select?),
we should probably switch over to a describing array like drive strength
does currently.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Diffstat (limited to 'drivers/pinctrl/sh-pfc')
| -rw-r--r-- | drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 58 | ||||
| -rw-r--r-- | drivers/pinctrl/sh-pfc/pinctrl.c | 41 | ||||
| -rw-r--r-- | drivers/pinctrl/sh-pfc/sh_pfc.h | 4 |
3 files changed, 40 insertions, 63 deletions
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index eed8daa464cc..1537a0779399 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c | |||
| @@ -4696,47 +4696,6 @@ static const char * const vin3_groups[] = { | |||
| 4696 | "vin3_clk", | 4696 | "vin3_clk", |
| 4697 | }; | 4697 | }; |
| 4698 | 4698 | ||
| 4699 | #define IOCTRL6 0x8c | ||
| 4700 | |||
| 4701 | static int r8a7790_get_io_voltage(struct sh_pfc *pfc, unsigned int pin) | ||
| 4702 | { | ||
| 4703 | u32 data, mask; | ||
| 4704 | |||
| 4705 | if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin)) | ||
| 4706 | return -EINVAL; | ||
| 4707 | |||
| 4708 | data = ioread32(pfc->windows->virt + IOCTRL6), | ||
| 4709 | /* Bits in IOCTRL6 are numbered in opposite order to pins */ | ||
| 4710 | mask = 0x80000000 >> (pin & 0x1f); | ||
| 4711 | |||
| 4712 | return (data & mask) ? 3300 : 1800; | ||
| 4713 | } | ||
| 4714 | |||
| 4715 | static int r8a7790_set_io_voltage(struct sh_pfc *pfc, unsigned int pin, u16 mV) | ||
| 4716 | { | ||
| 4717 | u32 data, mask; | ||
| 4718 | |||
| 4719 | if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin)) | ||
| 4720 | return -EINVAL; | ||
| 4721 | |||
| 4722 | if (mV != 1800 && mV != 3300) | ||
| 4723 | return -EINVAL; | ||
| 4724 | |||
| 4725 | data = ioread32(pfc->windows->virt + IOCTRL6); | ||
| 4726 | /* Bits in IOCTRL6 are numbered in opposite order to pins */ | ||
| 4727 | mask = 0x80000000 >> (pin & 0x1f); | ||
| 4728 | |||
| 4729 | if (mV == 3300) | ||
| 4730 | data |= mask; | ||
| 4731 | else | ||
| 4732 | data &= ~mask; | ||
| 4733 | |||
| 4734 | iowrite32(~data, pfc->windows->virt); /* unlock reg */ | ||
| 4735 | iowrite32(data, pfc->windows->virt + IOCTRL6); | ||
| 4736 | |||
| 4737 | return 0; | ||
| 4738 | } | ||
| 4739 | |||
| 4740 | static const struct sh_pfc_function pinmux_functions[] = { | 4699 | static const struct sh_pfc_function pinmux_functions[] = { |
| 4741 | SH_PFC_FUNCTION(audio_clk), | 4700 | SH_PFC_FUNCTION(audio_clk), |
| 4742 | SH_PFC_FUNCTION(avb), | 4701 | SH_PFC_FUNCTION(avb), |
| @@ -5736,14 +5695,23 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { | |||
| 5736 | { }, | 5695 | { }, |
| 5737 | }; | 5696 | }; |
| 5738 | 5697 | ||
| 5739 | static const struct sh_pfc_soc_operations pinmux_ops = { | 5698 | static int r8a7790_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl) |
| 5740 | .get_io_voltage = r8a7790_get_io_voltage, | 5699 | { |
| 5741 | .set_io_voltage = r8a7790_set_io_voltage, | 5700 | if (pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31)) |
| 5701 | return -EINVAL; | ||
| 5702 | |||
| 5703 | *pocctrl = 0xe606008c; | ||
| 5704 | |||
| 5705 | return 31 - (pin & 0x1f); | ||
| 5706 | } | ||
| 5707 | |||
| 5708 | static const struct sh_pfc_soc_operations r8a7790_pinmux_ops = { | ||
| 5709 | .pin_to_pocctrl = r8a7790_pin_to_pocctrl, | ||
| 5742 | }; | 5710 | }; |
| 5743 | 5711 | ||
| 5744 | const struct sh_pfc_soc_info r8a7790_pinmux_info = { | 5712 | const struct sh_pfc_soc_info r8a7790_pinmux_info = { |
| 5745 | .name = "r8a77900_pfc", | 5713 | .name = "r8a77900_pfc", |
| 5746 | .ops = &pinmux_ops, | 5714 | .ops = &r8a7790_pinmux_ops, |
| 5747 | .unlock_reg = 0xe6060000, /* PMMR */ | 5715 | .unlock_reg = 0xe6060000, /* PMMR */ |
| 5748 | 5716 | ||
| 5749 | .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, | 5717 | .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, |
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index fdb445d68b9a..d4e65bc7dacd 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c | |||
| @@ -632,19 +632,21 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, | |||
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | case PIN_CONFIG_POWER_SOURCE: { | 634 | case PIN_CONFIG_POWER_SOURCE: { |
| 635 | int ret; | 635 | u32 pocctrl, val; |
| 636 | int bit; | ||
| 636 | 637 | ||
| 637 | if (!pfc->info->ops || !pfc->info->ops->get_io_voltage) | 638 | if (!pfc->info->ops || !pfc->info->ops->pin_to_pocctrl) |
| 638 | return -ENOTSUPP; | 639 | return -ENOTSUPP; |
| 639 | 640 | ||
| 641 | bit = pfc->info->ops->pin_to_pocctrl(pfc, _pin, &pocctrl); | ||
| 642 | if (WARN(bit < 0, "invalid pin %#x", _pin)) | ||
| 643 | return bit; | ||
| 644 | |||
| 640 | spin_lock_irqsave(&pfc->lock, flags); | 645 | spin_lock_irqsave(&pfc->lock, flags); |
| 641 | ret = pfc->info->ops->get_io_voltage(pfc, _pin); | 646 | val = sh_pfc_read_reg(pfc, pocctrl, 32); |
| 642 | spin_unlock_irqrestore(&pfc->lock, flags); | 647 | spin_unlock_irqrestore(&pfc->lock, flags); |
| 643 | 648 | ||
| 644 | if (ret < 0) | 649 | *config = (val & BIT(bit)) ? 3300 : 1800; |
| 645 | return ret; | ||
| 646 | |||
| 647 | *config = ret; | ||
| 648 | break; | 650 | break; |
| 649 | } | 651 | } |
| 650 | 652 | ||
| @@ -696,20 +698,29 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin, | |||
| 696 | } | 698 | } |
| 697 | 699 | ||
| 698 | case PIN_CONFIG_POWER_SOURCE: { | 700 | case PIN_CONFIG_POWER_SOURCE: { |
| 699 | unsigned int arg = | 701 | unsigned int mV = pinconf_to_config_argument(configs[i]); |
| 700 | pinconf_to_config_argument(configs[i]); | 702 | u32 pocctrl, val; |
| 701 | int ret; | 703 | int bit; |
| 702 | 704 | ||
| 703 | if (!pfc->info->ops || !pfc->info->ops->set_io_voltage) | 705 | if (!pfc->info->ops || !pfc->info->ops->pin_to_pocctrl) |
| 704 | return -ENOTSUPP; | 706 | return -ENOTSUPP; |
| 705 | 707 | ||
| 708 | bit = pfc->info->ops->pin_to_pocctrl(pfc, _pin, &pocctrl); | ||
| 709 | if (WARN(bit < 0, "invalid pin %#x", _pin)) | ||
| 710 | return bit; | ||
| 711 | |||
| 712 | if (mV != 1800 && mV != 3300) | ||
| 713 | return -EINVAL; | ||
| 714 | |||
| 706 | spin_lock_irqsave(&pfc->lock, flags); | 715 | spin_lock_irqsave(&pfc->lock, flags); |
| 707 | ret = pfc->info->ops->set_io_voltage(pfc, _pin, arg); | 716 | val = sh_pfc_read_reg(pfc, pocctrl, 32); |
| 717 | if (mV == 3300) | ||
| 718 | val |= BIT(bit); | ||
| 719 | else | ||
| 720 | val &= ~BIT(bit); | ||
| 721 | sh_pfc_write_reg(pfc, pocctrl, 32, val); | ||
| 708 | spin_unlock_irqrestore(&pfc->lock, flags); | 722 | spin_unlock_irqrestore(&pfc->lock, flags); |
| 709 | 723 | ||
| 710 | if (ret) | ||
| 711 | return ret; | ||
| 712 | |||
| 713 | break; | 724 | break; |
| 714 | } | 725 | } |
| 715 | 726 | ||
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 656ea32f776c..ea3a52751455 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h | |||
| @@ -189,9 +189,7 @@ struct sh_pfc_soc_operations { | |||
| 189 | unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin); | 189 | unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin); |
| 190 | void (*set_bias)(struct sh_pfc *pfc, unsigned int pin, | 190 | void (*set_bias)(struct sh_pfc *pfc, unsigned int pin, |
| 191 | unsigned int bias); | 191 | unsigned int bias); |
| 192 | int (*get_io_voltage)(struct sh_pfc *pfc, unsigned int pin); | 192 | int (*pin_to_pocctrl)(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl); |
| 193 | int (*set_io_voltage)(struct sh_pfc *pfc, unsigned int pin, | ||
| 194 | u16 voltage_mV); | ||
| 195 | }; | 193 | }; |
| 196 | 194 | ||
| 197 | struct sh_pfc_soc_info { | 195 | struct sh_pfc_soc_info { |
