pinctrl: mvebu: add simple regmap based pinctrl implementation
authorRussell King <rmk+kernel@armlinux.org.uk>
Fri, 13 Jan 2017 11:03:35 +0000 (11:03 +0000)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 18 Jan 2017 08:58:04 +0000 (09:58 +0100)
Add a simple regmap based pinctrl implementation for mvebu, for syscon
based regmap drivers.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/mvebu/pinctrl-mvebu.c
drivers/pinctrl/mvebu/pinctrl-mvebu.h

index 8415761f4b0189566f9f7d2d91cb22b73c43996b..1bdfe770eb5cb51bae7ce47725cb951acb2b260b 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include "pinctrl-mvebu.h"
 
@@ -780,3 +782,61 @@ int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev)
 
        return mvebu_pinctrl_probe(pdev);
 }
+
+int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+                             unsigned int pid, unsigned long *config)
+{
+       unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+       unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+       unsigned int val;
+       int err;
+
+       err = regmap_read(data->regmap.map, data->regmap.offset + off, &val);
+       if (err)
+               return err;
+
+       *config = (val >> shift) & MVEBU_MPP_MASK;
+
+       return 0;
+}
+
+int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+                             unsigned int pid, unsigned long config)
+{
+       unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+       unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+
+       return regmap_update_bits(data->regmap.map, data->regmap.offset + off,
+                                 MVEBU_MPP_MASK << shift, config << shift);
+}
+
+int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,
+                                     struct device *syscon_dev)
+{
+       struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
+       struct mvebu_mpp_ctrl_data *mpp_data;
+       struct regmap *regmap;
+       u32 offset;
+       int i;
+
+       regmap = syscon_node_to_regmap(syscon_dev->of_node);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       if (of_property_read_u32(pdev->dev.of_node, "offset", &offset))
+               return -EINVAL;
+
+       mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),
+                               GFP_KERNEL);
+       if (!mpp_data)
+               return -ENOMEM;
+
+       for (i = 0; i < soc->ncontrols; i++) {
+               mpp_data[i].regmap.map = regmap;
+               mpp_data[i].regmap.offset = offset;
+       }
+
+       soc->control_data = mpp_data;
+
+       return mvebu_pinctrl_probe(pdev);
+}
index a9304cdc23e204a3b16355fb57e1b9c199031d7c..c90704e74884c525fffd21fd921f768bb5455dd2 100644 (file)
 /**
  * struct mvebu_mpp_ctrl_data - private data for the mpp ctrl operations
  * @base: base address of pinctrl hardware
+ * @regmap.map: regmap structure
+ * @regmap.offset: regmap offset
  */
 struct mvebu_mpp_ctrl_data {
-       void __iomem *base;
+       union {
+               void __iomem *base;
+               struct {
+                       struct regmap *map;
+                       u32 offset;
+               } regmap;
+       };
 };
 
 /**
@@ -194,8 +202,14 @@ int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
                               unsigned long *config);
 int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
                               unsigned long config);
+int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+                             unsigned long *config);
+int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+                             unsigned long config);
 
 int mvebu_pinctrl_probe(struct platform_device *pdev);
 int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev);
+int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,
+                                     struct device *syscon_dev);
 
 #endif