summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl-ocelot.c
diff options
context:
space:
mode:
authorColin Foster <colin.foster@in-advantage.com>2021-11-19 22:59:27 +0300
committerLinus Walleij <linus.walleij@linaro.org>2021-11-22 03:07:02 +0300
commit076d9e71bcf8a80c94bf1d46c424977472c97078 (patch)
tree87a4af449b73d5f936b5101b44093d2925ce8105 /drivers/pinctrl/pinctrl-ocelot.c
parenta159c2b4cb7517fe11f3ce698f792126e964fc7a (diff)
downloadlinux-076d9e71bcf8a80c94bf1d46c424977472c97078.tar.xz
pinctrl: ocelot: convert pinctrl to regmap
In order to allow external control via SPI, memory-mapped areas must be changed to use the generic regmap interface. This is step 1, and is followed by an implementation that allows a custom regmap. Signed-off-by: Colin Foster <colin.foster@in-advantage.com> Link: https://lore.kernel.org/r/20211119195928.2498441-4-colin.foster@in-advantage.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-ocelot.c')
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
index d59d684d3496..42aab9ba049a 100644
--- a/drivers/pinctrl/pinctrl-ocelot.c
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -317,7 +317,7 @@ struct ocelot_pinctrl {
struct pinctrl_dev *pctl;
struct gpio_chip gpio_chip;
struct regmap *map;
- void __iomem *pincfg;
+ struct regmap *pincfg;
struct pinctrl_desc *desc;
struct ocelot_pmx_func func[FUNC_MAX];
u8 stride;
@@ -1224,7 +1224,11 @@ static int ocelot_hw_get_value(struct ocelot_pinctrl *info,
int ret = -EOPNOTSUPP;
if (info->pincfg) {
- u32 regcfg = readl(info->pincfg + (pin * sizeof(u32)));
+ u32 regcfg;
+
+ ret = regmap_read(info->pincfg, pin, &regcfg);
+ if (ret)
+ return ret;
ret = 0;
switch (reg) {
@@ -1248,6 +1252,24 @@ static int ocelot_hw_get_value(struct ocelot_pinctrl *info,
return ret;
}
+static int ocelot_pincfg_clrsetbits(struct ocelot_pinctrl *info, u32 regaddr,
+ u32 clrbits, u32 setbits)
+{
+ u32 val;
+ int ret;
+
+ ret = regmap_read(info->pincfg, regaddr, &val);
+ if (ret)
+ return ret;
+
+ val &= ~clrbits;
+ val |= setbits;
+
+ ret = regmap_write(info->pincfg, regaddr, val);
+
+ return ret;
+}
+
static int ocelot_hw_set_value(struct ocelot_pinctrl *info,
unsigned int pin,
unsigned int reg,
@@ -1256,21 +1278,23 @@ static int ocelot_hw_set_value(struct ocelot_pinctrl *info,
int ret = -EOPNOTSUPP;
if (info->pincfg) {
- void __iomem *regaddr = info->pincfg + (pin * sizeof(u32));
ret = 0;
switch (reg) {
case PINCONF_BIAS:
- ocelot_clrsetbits(regaddr, BIAS_BITS, val);
+ ret = ocelot_pincfg_clrsetbits(info, pin, BIAS_BITS,
+ val);
break;
case PINCONF_SCHMITT:
- ocelot_clrsetbits(regaddr, SCHMITT_BIT, val);
+ ret = ocelot_pincfg_clrsetbits(info, pin, SCHMITT_BIT,
+ val);
break;
case PINCONF_DRIVE_STRENGTH:
if (val <= 3)
- ocelot_clrsetbits(regaddr, DRIVE_BITS, val);
+ ret = ocelot_pincfg_clrsetbits(info, pin,
+ DRIVE_BITS, val);
else
ret = -EINVAL;
break;
@@ -1756,10 +1780,31 @@ static const struct of_device_id ocelot_pinctrl_of_match[] = {
{},
};
+static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev)
+{
+ void __iomem *base;
+
+ const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 32,
+ };
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base)) {
+ dev_dbg(&pdev->dev, "Failed to ioremap config registers (no extended pinconf)\n");
+ return NULL;
+ }
+
+ return devm_regmap_init_mmio(&pdev->dev, base, &regmap_config);
+}
+
static int ocelot_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ocelot_pinctrl *info;
+ struct regmap *pincfg;
void __iomem *base;
int ret;
struct regmap_config regmap_config = {
@@ -1793,11 +1838,11 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
/* Pinconf registers */
if (info->desc->confops) {
- base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base))
- dev_dbg(dev, "Failed to ioremap config registers (no extended pinconf)\n");
+ pincfg = ocelot_pinctrl_create_pincfg(pdev);
+ if (IS_ERR(pincfg))
+ dev_dbg(dev, "Failed to create pincfg regmap\n");
else
- info->pincfg = base;
+ info->pincfg = pincfg;
}
ret = ocelot_pinctrl_register(pdev, info);