pinctrl: uniphier: support 3-bit drive strength control
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Tue, 31 May 2016 08:05:14 +0000 (17:05 +0900)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 31 May 2016 10:46:18 +0000 (12:46 +0200)
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 <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
drivers/pinctrl/uniphier/pinctrl-uniphier.h

index 7f7274e..017b84f 100644 (file)
@@ -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;
index 7f3e7ff..eca379a 100644 (file)
@@ -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 */