diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2017-01-13 14:03:35 +0300 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-01-18 11:58:04 +0300 |
commit | d068b0988a48418a1b6679f5b7d650400846d17f (patch) | |
tree | 4919ca6853a15e6f46f26bbf7861edcca378486d /drivers/pinctrl/mvebu | |
parent | ad9ec4ecee6889321ae1752ce8793524a8cdfa7a (diff) | |
download | linux-d068b0988a48418a1b6679f5b7d650400846d17f.tar.xz |
pinctrl: mvebu: add simple regmap based pinctrl implementation
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>
Diffstat (limited to 'drivers/pinctrl/mvebu')
-rw-r--r-- | drivers/pinctrl/mvebu/pinctrl-mvebu.c | 60 | ||||
-rw-r--r-- | drivers/pinctrl/mvebu/pinctrl-mvebu.h | 16 |
2 files changed, 75 insertions, 1 deletions
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 8415761f4b01..1bdfe770eb5c 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -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); +} diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h index a9304cdc23e2..c90704e74884 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h @@ -16,9 +16,17 @@ /** * 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 |