|
@@ -14,6 +14,7 @@
|
|
|
|
|
|
#include <linux/export.h>
|
|
|
#include <linux/mfd/syscon.h>
|
|
|
+#include <linux/of.h>
|
|
|
#include <linux/pinctrl/pinconf.h>
|
|
|
#include <linux/pinctrl/pinconf-generic.h>
|
|
|
#include <linux/pinctrl/pinctrl.h>
|
|
@@ -29,6 +30,7 @@ struct uniphier_pinctrl_priv {
|
|
|
struct pinctrl_desc pctldesc;
|
|
|
struct pinctrl_dev *pctldev;
|
|
|
struct regmap *regmap;
|
|
|
+ unsigned int regbase;
|
|
|
struct uniphier_pinctrl_socdata *socdata;
|
|
|
};
|
|
|
|
|
@@ -169,7 +171,7 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
|
|
|
reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
|
|
|
shift = pupdctrl % 32;
|
|
|
|
|
|
- ret = regmap_read(priv->regmap, reg, &val);
|
|
|
+ ret = regmap_read(priv->regmap, priv->regbase + reg, &val);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -229,7 +231,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
|
|
|
shift = drvctrl % 32;
|
|
|
mask = (1U << width) - 1;
|
|
|
|
|
|
- ret = regmap_read(priv->regmap, reg, &val);
|
|
|
+ ret = regmap_read(priv->regmap, priv->regbase + reg, &val);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -250,7 +252,8 @@ static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
|
|
|
/* This pin is always input-enabled. */
|
|
|
return 0;
|
|
|
|
|
|
- ret = regmap_read(priv->regmap, UNIPHIER_PINCTRL_IECTRL, &val);
|
|
|
+ ret = regmap_read(priv->regmap,
|
|
|
+ priv->regbase + UNIPHIER_PINCTRL_IECTRL, &val);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -363,7 +366,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
|
|
|
reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
|
|
|
shift = pupdctrl % 32;
|
|
|
|
|
|
- return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);
|
|
|
+ return regmap_update_bits(priv->regmap, priv->regbase + reg,
|
|
|
+ 1 << shift, val << shift);
|
|
|
}
|
|
|
|
|
|
static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
|
|
@@ -423,7 +427,7 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
|
|
|
shift = drvctrl % 32;
|
|
|
mask = (1U << width) - 1;
|
|
|
|
|
|
- return regmap_update_bits(priv->regmap, reg,
|
|
|
+ return regmap_update_bits(priv->regmap, priv->regbase + reg,
|
|
|
mask << shift, val << shift);
|
|
|
}
|
|
|
|
|
@@ -447,7 +451,7 @@ static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
|
|
|
if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
|
|
|
return enable ? 0 : -EINVAL;
|
|
|
|
|
|
- reg = UNIPHIER_PINCTRL_IECTRL + iectrl / 32 * 4;
|
|
|
+ reg = priv->regbase + UNIPHIER_PINCTRL_IECTRL + iectrl / 32 * 4;
|
|
|
mask = BIT(iectrl % 32);
|
|
|
|
|
|
return regmap_update_bits(priv->regmap, reg, mask, enable ? mask : 0);
|
|
@@ -597,7 +601,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
|
|
|
* stored in the offset+4.
|
|
|
*/
|
|
|
for (; reg < reg_end; reg += 4) {
|
|
|
- ret = regmap_update_bits(priv->regmap, reg,
|
|
|
+ ret = regmap_update_bits(priv->regmap, priv->regbase + reg,
|
|
|
mask << shift, muxval << shift);
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -606,7 +610,8 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
|
|
|
|
|
|
if (load_pinctrl) {
|
|
|
ret = regmap_write(priv->regmap,
|
|
|
- UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
|
|
|
+ priv->regbase + UNIPHIER_PINCTRL_LOAD_PINMUX,
|
|
|
+ 1);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
}
|
|
@@ -679,6 +684,7 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
|
|
|
{
|
|
|
struct device *dev = &pdev->dev;
|
|
|
struct uniphier_pinctrl_priv *priv;
|
|
|
+ struct device_node *parent;
|
|
|
|
|
|
if (!socdata ||
|
|
|
!socdata->pins || !socdata->npins ||
|
|
@@ -692,7 +698,21 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
|
|
|
if (!priv)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- priv->regmap = syscon_node_to_regmap(dev->of_node);
|
|
|
+ if (of_device_is_compatible(dev->of_node, "socionext,ph1-ld4-pinctrl") ||
|
|
|
+ of_device_is_compatible(dev->of_node, "socionext,ph1-pro4-pinctrl") ||
|
|
|
+ of_device_is_compatible(dev->of_node, "socionext,ph1-sld8-pinctrl") ||
|
|
|
+ of_device_is_compatible(dev->of_node, "socionext,ph1-pro5-pinctrl") ||
|
|
|
+ of_device_is_compatible(dev->of_node, "socionext,proxstream2-pinctrl") ||
|
|
|
+ of_device_is_compatible(dev->of_node, "socionext,ph1-ld6b-pinctrl")) {
|
|
|
+ /* old binding */
|
|
|
+ priv->regmap = syscon_node_to_regmap(dev->of_node);
|
|
|
+ } else {
|
|
|
+ priv->regbase = 0x1000;
|
|
|
+ parent = of_get_parent(dev->of_node);
|
|
|
+ priv->regmap = syscon_node_to_regmap(parent);
|
|
|
+ of_node_put(parent);
|
|
|
+ }
|
|
|
+
|
|
|
if (IS_ERR(priv->regmap)) {
|
|
|
dev_err(dev, "failed to get regmap\n");
|
|
|
return PTR_ERR(priv->regmap);
|