pinctrl: uniphier: support 3-bit drive strength control
[cascardo/linux.git] / drivers / pinctrl / uniphier / pinctrl-uniphier-core.c
index 9674009..017b84f 100644 (file)
@@ -26,6 +26,7 @@
 #include "pinctrl-uniphier.h"
 
 struct uniphier_pinctrl_priv {
+       struct pinctrl_desc pctldesc;
        struct pinctrl_dev *pctldev;
        struct regmap *regmap;
        struct uniphier_pinctrl_socdata *socdata;
@@ -64,7 +65,7 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
                                       struct seq_file *s, unsigned offset)
 {
        const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset];
-       const char *pull_dir, *drv_str;
+       const char *pull_dir, *drv_type;
 
        switch (uniphier_pin_get_pull_dir(pin->drv_data)) {
        case UNIPHIER_PIN_PULL_UP:
@@ -73,6 +74,12 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
        case UNIPHIER_PIN_PULL_DOWN:
                pull_dir = "DOWN";
                break;
+       case UNIPHIER_PIN_PULL_UP_FIXED:
+               pull_dir = "UP(FIXED)";
+               break;
+       case UNIPHIER_PIN_PULL_DOWN_FIXED:
+               pull_dir = "DOWN(FIXED)";
+               break;
        case UNIPHIER_PIN_PULL_NONE:
                pull_dir = "NONE";
                break;
@@ -80,30 +87,33 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
                BUG();
        }
 
-       switch (uniphier_pin_get_drv_str(pin->drv_data)) {
-       case UNIPHIER_PIN_DRV_4_8:
-               drv_str = "4/8(mA)";
+       switch (uniphier_pin_get_drv_type(pin->drv_data)) {
+       case UNIPHIER_PIN_DRV_1BIT:
+               drv_type = "4/8(mA)";
                break;
-       case UNIPHIER_PIN_DRV_8_12_16_20:
-               drv_str = "8/12/16/20(mA)";
+       case UNIPHIER_PIN_DRV_2BIT:
+               drv_type = "8/12/16/20(mA)";
                break;
-       case UNIPHIER_PIN_DRV_FIXED_4:
-               drv_str = "4(mA)";
+       case UNIPHIER_PIN_DRV_3BIT:
+               drv_type = "4/5/7/9/11/12/14/16(mA)";
                break;
-       case UNIPHIER_PIN_DRV_FIXED_5:
-               drv_str = "5(mA)";
+       case UNIPHIER_PIN_DRV_FIXED4:
+               drv_type = "4(mA)";
                break;
-       case UNIPHIER_PIN_DRV_FIXED_8:
-               drv_str = "8(mA)";
+       case UNIPHIER_PIN_DRV_FIXED5:
+               drv_type = "5(mA)";
+               break;
+       case UNIPHIER_PIN_DRV_FIXED8:
+               drv_type = "8(mA)";
                break;
        case UNIPHIER_PIN_DRV_NONE:
-               drv_str = "NONE";
+               drv_type = "NONE";
                break;
        default:
                BUG();
        }
 
-       seq_printf(s, " PULL_DIR=%s  DRV_STR=%s", pull_dir, drv_str);
+       seq_printf(s, " PULL_DIR=%s  DRV_TYPE=%s", pull_dir, drv_type);
 }
 #endif
 
@@ -173,30 +183,38 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
                                       u16 *strength)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-       enum uniphier_pin_drv_str drv_str =
-                               uniphier_pin_get_drv_str(pin->drv_data);
-       const unsigned int strength_4_8[] = {4, 8};
-       const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20};
+       enum uniphier_pin_drv_type type =
+                               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;
 
-       switch (drv_str) {
-       case UNIPHIER_PIN_DRV_4_8:
-               supported_strength = strength_4_8;
+       switch (type) {
+       case UNIPHIER_PIN_DRV_1BIT:
+               supported_strength = strength_1bit;
+               reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
                width = 1;
                break;
-       case UNIPHIER_PIN_DRV_8_12_16_20:
-               supported_strength = strength_8_12_16_20;
+       case UNIPHIER_PIN_DRV_2BIT:
+               supported_strength = strength_2bit;
+               reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
                width = 2;
                break;
-       case UNIPHIER_PIN_DRV_FIXED_4:
+       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;
-       case UNIPHIER_PIN_DRV_FIXED_5:
+       case UNIPHIER_PIN_DRV_FIXED5:
                *strength = 5;
                return 0;
-       case UNIPHIER_PIN_DRV_FIXED_8:
+       case UNIPHIER_PIN_DRV_FIXED8:
                *strength = 8;
                return 0;
        default:
@@ -207,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;
@@ -357,22 +372,30 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
                                       u16 strength)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-       enum uniphier_pin_drv_str drv_str =
-                               uniphier_pin_get_drv_str(pin->drv_data);
-       const unsigned int strength_4_8[] = {4, 8, -1};
-       const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20, -1};
+       enum uniphier_pin_drv_type type =
+                               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 (drv_str) {
-       case UNIPHIER_PIN_DRV_4_8:
-               supported_strength = strength_4_8;
+       switch (type) {
+       case UNIPHIER_PIN_DRV_1BIT:
+               supported_strength = strength_1bit;
+               reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
                width = 1;
                break;
-       case UNIPHIER_PIN_DRV_8_12_16_20:
-               supported_strength = strength_8_12_16_20;
+       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",
@@ -397,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;
@@ -633,13 +653,13 @@ static const struct pinmux_ops uniphier_pmxops = {
 };
 
 int uniphier_pinctrl_probe(struct platform_device *pdev,
-                          struct pinctrl_desc *desc,
                           struct uniphier_pinctrl_socdata *socdata)
 {
        struct device *dev = &pdev->dev;
        struct uniphier_pinctrl_priv *priv;
 
        if (!socdata ||
+           !socdata->pins || !socdata->npins ||
            !socdata->groups ||
            !socdata->groups_count ||
            !socdata->functions ||
@@ -661,11 +681,15 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
        }
 
        priv->socdata = socdata;
-       desc->pctlops = &uniphier_pctlops;
-       desc->pmxops = &uniphier_pmxops;
-       desc->confops = &uniphier_confops;
-
-       priv->pctldev = devm_pinctrl_register(dev, desc, priv);
+       priv->pctldesc.name = dev->driver->name;
+       priv->pctldesc.pins = socdata->pins;
+       priv->pctldesc.npins = socdata->npins;
+       priv->pctldesc.pctlops = &uniphier_pctlops;
+       priv->pctldesc.pmxops = &uniphier_pmxops;
+       priv->pctldesc.confops = &uniphier_confops;
+       priv->pctldesc.owner = dev->driver->owner;
+
+       priv->pctldev = devm_pinctrl_register(dev, &priv->pctldesc, priv);
        if (IS_ERR(priv->pctldev)) {
                dev_err(dev, "failed to register UniPhier pinctrl driver\n");
                return PTR_ERR(priv->pctldev);