Commit 72e5706a authored by Masahiro Yamada's avatar Masahiro Yamada Committed by Linus Walleij

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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 9eaa98a6
...@@ -94,6 +94,9 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, ...@@ -94,6 +94,9 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
case UNIPHIER_PIN_DRV_2BIT: case UNIPHIER_PIN_DRV_2BIT:
drv_type = "8/12/16/20(mA)"; drv_type = "8/12/16/20(mA)";
break; break;
case UNIPHIER_PIN_DRV_3BIT:
drv_type = "4/5/7/9/11/12/14/16(mA)";
break;
case UNIPHIER_PIN_DRV_FIXED4: case UNIPHIER_PIN_DRV_FIXED4:
drv_type = "4(mA)"; drv_type = "4(mA)";
break; break;
...@@ -184,6 +187,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, ...@@ -184,6 +187,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
uniphier_pin_get_drv_type(pin->drv_data); uniphier_pin_get_drv_type(pin->drv_data);
const unsigned int strength_1bit[] = {4, 8}; const unsigned int strength_1bit[] = {4, 8};
const unsigned int strength_2bit[] = {8, 12, 16, 20}; 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; const unsigned int *supported_strength;
unsigned int drvctrl, reg, shift, mask, width, val; unsigned int drvctrl, reg, shift, mask, width, val;
int ret; int ret;
...@@ -191,12 +195,19 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, ...@@ -191,12 +195,19 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
switch (type) { switch (type) {
case UNIPHIER_PIN_DRV_1BIT: case UNIPHIER_PIN_DRV_1BIT:
supported_strength = strength_1bit; supported_strength = strength_1bit;
reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
width = 1; width = 1;
break; break;
case UNIPHIER_PIN_DRV_2BIT: case UNIPHIER_PIN_DRV_2BIT:
supported_strength = strength_2bit; supported_strength = strength_2bit;
reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
width = 2; width = 2;
break; break;
case UNIPHIER_PIN_DRV_3BIT:
supported_strength = strength_3bit;
reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
width = 4;
break;
case UNIPHIER_PIN_DRV_FIXED4: case UNIPHIER_PIN_DRV_FIXED4:
*strength = 4; *strength = 4;
return 0; return 0;
...@@ -214,9 +225,6 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, ...@@ -214,9 +225,6 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
drvctrl *= width; drvctrl *= width;
reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
UNIPHIER_PINCTRL_DRVCTRL_BASE;
reg += drvctrl / 32 * 4; reg += drvctrl / 32 * 4;
shift = drvctrl % 32; shift = drvctrl % 32;
mask = (1U << width) - 1; mask = (1U << width) - 1;
...@@ -368,18 +376,26 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev, ...@@ -368,18 +376,26 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
uniphier_pin_get_drv_type(pin->drv_data); uniphier_pin_get_drv_type(pin->drv_data);
const unsigned int strength_1bit[] = {4, 8, -1}; const unsigned int strength_1bit[] = {4, 8, -1};
const unsigned int strength_2bit[] = {8, 12, 16, 20, -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; const unsigned int *supported_strength;
unsigned int drvctrl, reg, shift, mask, width, val; unsigned int drvctrl, reg, shift, mask, width, val;
switch (type) { switch (type) {
case UNIPHIER_PIN_DRV_1BIT: case UNIPHIER_PIN_DRV_1BIT:
supported_strength = strength_1bit; supported_strength = strength_1bit;
reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
width = 1; width = 1;
break; break;
case UNIPHIER_PIN_DRV_2BIT: case UNIPHIER_PIN_DRV_2BIT:
supported_strength = strength_2bit; supported_strength = strength_2bit;
reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
width = 2; width = 2;
break; break;
case UNIPHIER_PIN_DRV_3BIT:
supported_strength = strength_3bit;
reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
width = 4;
break;
default: default:
dev_err(pctldev->dev, dev_err(pctldev->dev,
"cannot change drive strength for pin %u (%s)\n", "cannot change drive strength for pin %u (%s)\n",
...@@ -404,9 +420,6 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev, ...@@ -404,9 +420,6 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
drvctrl *= width; drvctrl *= width;
reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
UNIPHIER_PINCTRL_DRVCTRL_BASE;
reg += drvctrl / 32 * 4; reg += drvctrl / 32 * 4;
shift = drvctrl % 32; shift = drvctrl % 32;
mask = (1U << width) - 1; mask = (1U << width) - 1;
......
...@@ -25,6 +25,7 @@ struct platform_device; ...@@ -25,6 +25,7 @@ struct platform_device;
#define UNIPHIER_PINCTRL_LOAD_PINMUX 0x700 #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x700
#define UNIPHIER_PINCTRL_DRVCTRL_BASE 0x800 #define UNIPHIER_PINCTRL_DRVCTRL_BASE 0x800
#define UNIPHIER_PINCTRL_DRV2CTRL_BASE 0x900 #define UNIPHIER_PINCTRL_DRV2CTRL_BASE 0x900
#define UNIPHIER_PINCTRL_DRV3CTRL_BASE 0x980
#define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0xa00 #define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0xa00
#define UNIPHIER_PINCTRL_IECTRL 0xd00 #define UNIPHIER_PINCTRL_IECTRL 0xd00
...@@ -72,6 +73,7 @@ struct platform_device; ...@@ -72,6 +73,7 @@ struct platform_device;
enum uniphier_pin_drv_type { enum uniphier_pin_drv_type {
UNIPHIER_PIN_DRV_1BIT, /* 2 level control: 4/8 mA */ 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_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_FIXED4, /* fixed to 4mA */
UNIPHIER_PIN_DRV_FIXED5, /* fixed to 5mA */ UNIPHIER_PIN_DRV_FIXED5, /* fixed to 5mA */
UNIPHIER_PIN_DRV_FIXED8, /* fixed to 8mA */ UNIPHIER_PIN_DRV_FIXED8, /* fixed to 8mA */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment