pinctrl: uniphier: introduce capability flag
[cascardo/linux.git] / drivers / pinctrl / uniphier / pinctrl-uniphier-core.c
index 7f7274e..ca2562a 100644 (file)
@@ -64,10 +64,10 @@ static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
 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 struct pin_desc *desc = pin_desc_get(pctldev, offset);
        const char *pull_dir, *drv_type;
 
-       switch (uniphier_pin_get_pull_dir(pin->drv_data)) {
+       switch (uniphier_pin_get_pull_dir(desc->drv_data)) {
        case UNIPHIER_PIN_PULL_UP:
                pull_dir = "UP";
                break;
@@ -87,13 +87,16 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
                BUG();
        }
 
-       switch (uniphier_pin_get_drv_type(pin->drv_data)) {
+       switch (uniphier_pin_get_drv_type(desc->drv_data)) {
        case UNIPHIER_PIN_DRV_1BIT:
                drv_type = "4/8(mA)";
                break;
        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;
@@ -126,12 +129,12 @@ static const struct pinctrl_ops uniphier_pctlops = {
 };
 
 static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
-                                     const struct pinctrl_pin_desc *pin,
+                                     const struct pin_desc *desc,
                                      enum pin_config_param param)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
        enum uniphier_pin_pull_dir pull_dir =
-                               uniphier_pin_get_pull_dir(pin->drv_data);
+                               uniphier_pin_get_pull_dir(desc->drv_data);
        unsigned int pupdctrl, reg, shift, val;
        unsigned int expected = 1;
        int ret;
@@ -161,7 +164,7 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
                BUG();
        }
 
-       pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
+       pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
 
        reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
        shift = pupdctrl % 32;
@@ -176,14 +179,15 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
-                                      const struct pinctrl_pin_desc *pin,
+                                      const struct pin_desc *desc,
                                       u16 *strength)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
        enum uniphier_pin_drv_type type =
-                               uniphier_pin_get_drv_type(pin->drv_data);
+                               uniphier_pin_get_drv_type(desc->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;
@@ -211,12 +222,9 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
                return -EINVAL;
        }
 
-       drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
+       drvctrl = uniphier_pin_get_drvctrl(desc->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;
@@ -231,10 +239,10 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
-                                       const struct pinctrl_pin_desc *pin)
+                                             const struct pin_desc *desc)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-       unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
+       unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
        unsigned int val;
        int ret;
 
@@ -253,7 +261,7 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
                                        unsigned pin,
                                        unsigned long *configs)
 {
-       const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
+       const struct pin_desc *desc = pin_desc_get(pctldev, pin);
        enum pin_config_param param = pinconf_to_config_param(*configs);
        bool has_arg = false;
        u16 arg;
@@ -263,14 +271,14 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
        case PIN_CONFIG_BIAS_DISABLE:
        case PIN_CONFIG_BIAS_PULL_UP:
        case PIN_CONFIG_BIAS_PULL_DOWN:
-               ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param);
+               ret = uniphier_conf_pin_bias_get(pctldev, desc, param);
                break;
        case PIN_CONFIG_DRIVE_STRENGTH:
-               ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg);
+               ret = uniphier_conf_pin_drive_get(pctldev, desc, &arg);
                has_arg = true;
                break;
        case PIN_CONFIG_INPUT_ENABLE:
-               ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc);
+               ret = uniphier_conf_pin_input_enable_get(pctldev, desc);
                break;
        default:
                /* unsupported parameter */
@@ -285,13 +293,12 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
-                                     const struct pinctrl_pin_desc *pin,
-                                     enum pin_config_param param,
-                                     u16 arg)
+                                     const struct pin_desc *desc,
+                                     enum pin_config_param param, u16 arg)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
        enum uniphier_pin_pull_dir pull_dir =
-                               uniphier_pin_get_pull_dir(pin->drv_data);
+                               uniphier_pin_get_pull_dir(desc->drv_data);
        unsigned int pupdctrl, reg, shift;
        unsigned int val = 1;
 
@@ -302,8 +309,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
                if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
                    pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
                        dev_err(pctldev->dev,
-                               "can not disable pull register for pin %u (%s)\n",
-                               pin->number, pin->name);
+                               "can not disable pull register for pin %s\n",
+                               desc->name);
                        return -EINVAL;
                }
                val = 0;
@@ -313,8 +320,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
                        return 0;
                if (pull_dir != UNIPHIER_PIN_PULL_UP) {
                        dev_err(pctldev->dev,
-                               "pull-up is unsupported for pin %u (%s)\n",
-                               pin->number, pin->name);
+                               "pull-up is unsupported for pin %s\n",
+                               desc->name);
                        return -EINVAL;
                }
                if (arg == 0) {
@@ -327,8 +334,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
                        return 0;
                if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
                        dev_err(pctldev->dev,
-                               "pull-down is unsupported for pin %u (%s)\n",
-                               pin->number, pin->name);
+                               "pull-down is unsupported for pin %s\n",
+                               desc->name);
                        return -EINVAL;
                }
                if (arg == 0) {
@@ -339,8 +346,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
        case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
                if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
                        dev_err(pctldev->dev,
-                               "pull-up/down is unsupported for pin %u (%s)\n",
-                               pin->number, pin->name);
+                               "pull-up/down is unsupported for pin %s\n",
+                               desc->name);
                        return -EINVAL;
                }
 
@@ -351,7 +358,7 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
                BUG();
        }
 
-       pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
+       pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
 
        reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
        shift = pupdctrl % 32;
@@ -360,30 +367,38 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
-                                      const struct pinctrl_pin_desc *pin,
+                                      const struct pin_desc *desc,
                                       u16 strength)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
        enum uniphier_pin_drv_type type =
-                               uniphier_pin_get_drv_type(pin->drv_data);
+                               uniphier_pin_get_drv_type(desc->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",
-                       pin->number, pin->name);
+                       "cannot change drive strength for pin %s\n",
+                       desc->name);
                return -EINVAL;
        }
 
@@ -394,19 +409,16 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 
        if (val == 0) {
                dev_err(pctldev->dev,
-                       "unsupported drive strength %u mA for pin %u (%s)\n",
-                       strength, pin->number, pin->name);
+                       "unsupported drive strength %u mA for pin %s\n",
+                       strength, desc->name);
                return -EINVAL;
        }
 
        val--;
 
-       drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
+       drvctrl = uniphier_pin_get_drvctrl(desc->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;
@@ -416,11 +428,11 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
-                                         const struct pinctrl_pin_desc *pin,
+                                         const struct pin_desc *desc,
                                          u16 enable)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-       unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
+       unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
 
        if (enable == 0) {
                /*
@@ -444,7 +456,7 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
                                        unsigned long *configs,
                                        unsigned num_configs)
 {
-       const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
+       const struct pin_desc *desc = pin_desc_get(pctldev, pin);
        int i, ret;
 
        for (i = 0; i < num_configs; i++) {
@@ -457,16 +469,15 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
                case PIN_CONFIG_BIAS_PULL_UP:
                case PIN_CONFIG_BIAS_PULL_DOWN:
                case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
-                       ret = uniphier_conf_pin_bias_set(pctldev, pin_desc,
+                       ret = uniphier_conf_pin_bias_set(pctldev, desc,
                                                         param, arg);
                        break;
                case PIN_CONFIG_DRIVE_STRENGTH:
-                       ret = uniphier_conf_pin_drive_set(pctldev, pin_desc,
-                                                         arg);
+                       ret = uniphier_conf_pin_drive_set(pctldev, desc, arg);
                        break;
                case PIN_CONFIG_INPUT_ENABLE:
-                       ret = uniphier_conf_pin_input_enable(pctldev,
-                                                            pin_desc, arg);
+                       ret = uniphier_conf_pin_input_enable(pctldev, desc,
+                                                            arg);
                        break;
                default:
                        dev_err(pctldev->dev,
@@ -541,17 +552,36 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
                                    unsigned muxval)
 {
        struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-       unsigned mux_bits = priv->socdata->mux_bits;
-       unsigned reg_stride = priv->socdata->reg_stride;
-       unsigned reg, reg_end, shift, mask;
+       unsigned int mux_bits, reg_stride, reg, reg_end, shift, mask;
+       bool load_pinctrl;
        int ret;
 
        /* some pins need input-enabling */
        ret = uniphier_conf_pin_input_enable(pctldev,
-                                            &pctldev->desc->pins[pin], 1);
+                                            pin_desc_get(pctldev, pin), 1);
        if (ret)
                return ret;
 
+       if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
+               /*
+                *  Mode     reg_offset     bit_position
+                *  Normal    4 * n        shift+3:shift
+                *  Debug     4 * n        shift+7:shift+4
+                */
+               mux_bits = 4;
+               reg_stride = 8;
+               load_pinctrl = true;
+       } else {
+               /*
+                *  Mode     reg_offset     bit_position
+                *  Normal    8 * n        shift+3:shift
+                *  Debug     8 * n + 4    shift+3:shift
+                */
+               mux_bits = 8;
+               reg_stride = 4;
+               load_pinctrl = false;
+       }
+
        reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
        reg_end = reg + reg_stride;
        shift = pin * mux_bits % 32;
@@ -569,7 +599,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
                muxval >>= mux_bits;
        }
 
-       if (priv->socdata->load_pinctrl) {
+       if (load_pinctrl) {
                ret = regmap_write(priv->regmap,
                                   UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
                if (ret)
@@ -647,12 +677,8 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 
        if (!socdata ||
            !socdata->pins || !socdata->npins ||
-           !socdata->groups ||
-           !socdata->groups_count ||
-           !socdata->functions ||
-           !socdata->functions_count ||
-           !socdata->mux_bits ||
-           !socdata->reg_stride) {
+           !socdata->groups || !socdata->groups_count ||
+           !socdata->functions || !socdata->functions_count) {
                dev_err(dev, "pinctrl socdata lacks necessary members\n");
                return -EINVAL;
        }