From 72e5706aa786f6640b229717b7d9d537058c59cf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 31 May 2016 17:05:14 +0900 Subject: [PATCH] pinctrl: uniphier: support 3-bit drive strength control The new ARMv8 SoC, PH1-LD20, supports more fine-grained drive strength control. Drive strength of some pins are controlled by 3-bit width registers (8-level granularity). Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- .../pinctrl/uniphier/pinctrl-uniphier-core.c | 25 ++++++++++++++----- drivers/pinctrl/uniphier/pinctrl-uniphier.h | 2 ++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index 7f7274eae36a..017b84fd9333 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -94,6 +94,9 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, case UNIPHIER_PIN_DRV_2BIT: drv_type = "8/12/16/20(mA)"; break; + case UNIPHIER_PIN_DRV_3BIT: + drv_type = "4/5/7/9/11/12/14/16(mA)"; + break; case UNIPHIER_PIN_DRV_FIXED4: drv_type = "4(mA)"; break; @@ -184,6 +187,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, uniphier_pin_get_drv_type(pin->drv_data); const unsigned int strength_1bit[] = {4, 8}; const unsigned int strength_2bit[] = {8, 12, 16, 20}; + const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16}; const unsigned int *supported_strength; unsigned int drvctrl, reg, shift, mask, width, val; int ret; @@ -191,12 +195,19 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, switch (type) { case UNIPHIER_PIN_DRV_1BIT: supported_strength = strength_1bit; + reg = UNIPHIER_PINCTRL_DRVCTRL_BASE; width = 1; break; case UNIPHIER_PIN_DRV_2BIT: supported_strength = strength_2bit; + reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE; width = 2; break; + case UNIPHIER_PIN_DRV_3BIT: + supported_strength = strength_3bit; + reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE; + width = 4; + break; case UNIPHIER_PIN_DRV_FIXED4: *strength = 4; return 0; @@ -214,9 +225,6 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); drvctrl *= width; - reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE : - UNIPHIER_PINCTRL_DRVCTRL_BASE; - reg += drvctrl / 32 * 4; shift = drvctrl % 32; mask = (1U << width) - 1; @@ -368,18 +376,26 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev, uniphier_pin_get_drv_type(pin->drv_data); const unsigned int strength_1bit[] = {4, 8, -1}; const unsigned int strength_2bit[] = {8, 12, 16, 20, -1}; + const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16, -1}; const unsigned int *supported_strength; unsigned int drvctrl, reg, shift, mask, width, val; switch (type) { case UNIPHIER_PIN_DRV_1BIT: supported_strength = strength_1bit; + reg = UNIPHIER_PINCTRL_DRVCTRL_BASE; width = 1; break; case UNIPHIER_PIN_DRV_2BIT: supported_strength = strength_2bit; + reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE; width = 2; break; + case UNIPHIER_PIN_DRV_3BIT: + supported_strength = strength_3bit; + reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE; + width = 4; + break; default: dev_err(pctldev->dev, "cannot change drive strength for pin %u (%s)\n", @@ -404,9 +420,6 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev, drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); drvctrl *= width; - reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE : - UNIPHIER_PINCTRL_DRVCTRL_BASE; - reg += drvctrl / 32 * 4; shift = drvctrl % 32; mask = (1U << width) - 1; diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h index 7f3e7ffe0096..eca379a2b976 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h @@ -25,6 +25,7 @@ struct platform_device; #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x700 #define UNIPHIER_PINCTRL_DRVCTRL_BASE 0x800 #define UNIPHIER_PINCTRL_DRV2CTRL_BASE 0x900 +#define UNIPHIER_PINCTRL_DRV3CTRL_BASE 0x980 #define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0xa00 #define UNIPHIER_PINCTRL_IECTRL 0xd00 @@ -72,6 +73,7 @@ struct platform_device; enum uniphier_pin_drv_type { UNIPHIER_PIN_DRV_1BIT, /* 2 level control: 4/8 mA */ UNIPHIER_PIN_DRV_2BIT, /* 4 level control: 8/12/16/20 mA */ + UNIPHIER_PIN_DRV_3BIT, /* 8 level control: 4/5/7/9/11/12/14/16 mA */ UNIPHIER_PIN_DRV_FIXED4, /* fixed to 4mA */ UNIPHIER_PIN_DRV_FIXED5, /* fixed to 5mA */ UNIPHIER_PIN_DRV_FIXED8, /* fixed to 8mA */