* [PATCH v4 2/2] Regulator: Add Anatop regulator driver
2012-02-08 20:51 ` [PATCH v4 1/2] mfd: Add anatop mfd driver Ying-Chun Liu (PaulLiu)
@ 2012-02-08 20:51 ` Ying-Chun Liu (PaulLiu)
2012-02-09 11:24 ` Mark Brown
2012-02-11 6:36 ` Shawn Guo
2012-02-11 6:05 ` [PATCH v4 1/2] mfd: Add anatop mfd driver Shawn Guo
` (2 subsequent siblings)
3 siblings, 2 replies; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-02-08 20:51 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Anatop is an integrated regulator inside i.MX6 SoC.
There are 3 digital regulators which controls PU, CORE (ARM), and SOC.
And 3 analog regulators which controls 1P1, 2P5, 3P0 (USB).
This patch adds the Anatop regulator driver.
Signed-off-by: Nancy Chen <Nancy.Chen@freescale.com>
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@ti.com>
---
drivers/regulator/Kconfig | 6 +
drivers/regulator/Makefile | 1 +
drivers/regulator/anatop-regulator.c | 204 ++++++++++++++++++++++++++++
include/linux/regulator/anatop-regulator.h | 49 +++++++
4 files changed, 260 insertions(+), 0 deletions(-)
create mode 100644 drivers/regulator/anatop-regulator.c
create mode 100644 include/linux/regulator/anatop-regulator.h
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7a61b17..5fbcda2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -335,5 +335,11 @@ config REGULATOR_AAT2870
If you have a AnalogicTech AAT2870 say Y to enable the
regulator driver.
+config REGULATOR_ANATOP
+ tristate "ANATOP LDO regulators"
+ depends on MFD_ANATOP
+ help
+ Say y here to support ANATOP LDOs regulators.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 503bac8..8440871 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,5 +48,6 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
+obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
new file mode 100644
index 0000000..d800c88
--- /dev/null
+++ b/drivers/regulator/anatop-regulator.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regulator/of_regulator.h>
+
+static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ u32 val, sel;
+ int uv;
+
+ uv = min_uV;
+ pr_debug("%s: uv %d, min %d, max %d\n", __func__,
+ uv, anatop_reg->rdata->min_voltage,
+ anatop_reg->rdata->max_voltage);
+
+ if (uv < anatop_reg->rdata->min_voltage
+ || uv > anatop_reg->rdata->max_voltage) {
+ if (max_uV > anatop_reg->rdata->min_voltage)
+ uv = anatop_reg->rdata->min_voltage;
+ else
+ return -EINVAL;
+ }
+
+ if (anatop_reg->rdata->control_reg) {
+ sel = (uv - anatop_reg->rdata->min_voltage) / 25000;
+ val = anatop_reg->rdata->min_bit_val + sel;
+ *selector = sel;
+ pr_debug("%s: calculated val %d\n", __func__, val);
+ anatop_reg->rdata->mfd->write(anatop_reg->rdata->mfd,
+ anatop_reg->rdata->control_reg,
+ anatop_reg->rdata->vol_bit_shift,
+ anatop_reg->rdata->vol_bit_size,
+ val);
+ return 0;
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int anatop_get_voltage_sel(struct regulator_dev *reg)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ int selector;
+ struct anatop_regulator_data *rdata = anatop_reg->rdata;
+
+ if (rdata->control_reg) {
+ u32 val = rdata->mfd->read(rdata->mfd,
+ rdata->control_reg,
+ rdata->vol_bit_shift,
+ rdata->vol_bit_size);
+ selector = val - rdata->min_bit_val;
+ return selector;
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int anatop_list_voltage(struct regulator_dev *dev, unsigned selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(dev);
+ int uv;
+ struct anatop_regulator_data *rdata = anatop_reg->rdata;
+
+ uv = rdata->min_voltage + selector * 25000;
+ pr_debug("vddio = %d, selector = %u\n", uv, selector);
+ return uv;
+}
+
+static struct regulator_ops anatop_rops = {
+ .set_voltage = anatop_set_voltage,
+ .get_voltage_sel = anatop_get_voltage_sel,
+ .list_voltage = anatop_list_voltage,
+};
+
+int anatop_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regulator_desc *rdesc;
+ struct regulator_dev *rdev;
+ struct anatop_regulator *sreg;
+ struct regulator_init_data *initdata;
+ struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
+ const __be32 *rval;
+ u64 ofsize;
+
+ initdata = of_get_regulator_init_data(dev, dev->of_node);
+ sreg = devm_kzalloc(dev, sizeof(struct anatop_regulator), GFP_KERNEL);
+ if (!sreg)
+ return -EINVAL;
+ rdesc = devm_kzalloc(dev, sizeof(struct regulator_desc), GFP_KERNEL);
+ if (!rdesc)
+ return -EINVAL;
+ sreg->initdata = initdata;
+ sreg->regulator = rdesc;
+ memset(rdesc, 0, sizeof(struct regulator_desc));
+ rdesc->name = kstrdup(of_get_property(np, "regulator-name", NULL),
+ GFP_KERNEL);
+ rdesc->ops = &anatop_rops;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->owner = THIS_MODULE;
+ sreg->rdata = devm_kzalloc(dev,
+ sizeof(struct anatop_regulator_data),
+ GFP_KERNEL);
+ sreg->rdata->name = kstrdup(rdesc->name, GFP_KERNEL);
+ rval = of_get_address(np, 0, &ofsize, NULL);
+ if (rval) {
+ sreg->rdata->control_reg = be32_to_cpu(rval[0]);
+ sreg->rdata->vol_bit_shift = be32_to_cpu(rval[1]);
+ }
+ sreg->rdata->mfd = anatopmfd;
+ sreg->rdata->vol_bit_size = (int)ofsize;
+ rval = of_get_property(np, "min-bit-val", NULL);
+ if (rval)
+ sreg->rdata->min_bit_val = be32_to_cpu(*rval);
+ rval = of_get_property(np, "min-voltage", NULL);
+ if (rval)
+ sreg->rdata->min_voltage = be32_to_cpu(*rval);
+ rval = of_get_property(np, "max-voltage", NULL);
+ if (rval)
+ sreg->rdata->max_voltage = be32_to_cpu(*rval);
+
+ /* register regulator */
+ rdev = regulator_register(rdesc, &pdev->dev,
+ initdata, sreg, pdev->dev.of_node);
+ platform_set_drvdata(pdev, rdev);
+
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ rdesc->name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+int anatop_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ regulator_unregister(rdev);
+ return 0;
+}
+
+struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { /* end */ }
+};
+
+
+struct platform_driver anatop_regulator = {
+ .driver = {
+ .name = "anatop_regulator",
+ .owner = THIS_MODULE,
+ .of_match_table = of_anatop_regulator_match_tbl,
+ },
+ .probe = anatop_regulator_probe,
+ .remove = anatop_regulator_remove,
+};
+
+int anatop_regulator_init(void)
+{
+ return platform_driver_register(&anatop_regulator);
+}
+
+void anatop_regulator_exit(void)
+{
+ platform_driver_unregister(&anatop_regulator);
+}
+
+postcore_initcall(anatop_regulator_init);
+module_exit(anatop_regulator_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("ANATOP Regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/regulator/anatop-regulator.h b/include/linux/regulator/anatop-regulator.h
new file mode 100644
index 0000000..089d519
--- /dev/null
+++ b/include/linux/regulator/anatop-regulator.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ANATOP_REGULATOR_H
+#define __ANATOP_REGULATOR_H
+#include <linux/regulator/driver.h>
+#include <linux/mfd/anatop.h>
+
+struct anatop_regulator {
+ struct regulator_desc *regulator;
+ struct regulator_init_data *initdata;
+ struct anatop_regulator_data *rdata;
+};
+
+
+struct anatop_regulator_data {
+ const char *name;
+
+ u32 control_reg;
+ struct anatop *mfd;
+ int vol_bit_shift;
+ int vol_bit_size;
+ int min_bit_val;
+ int min_voltage;
+ int max_voltage;
+};
+
+int anatop_register_regulator(
+ struct anatop_regulator *reg_data, int reg,
+ struct regulator_init_data *initdata);
+
+#endif /* __ANATOP_REGULATOR_H */
--
1.7.8.3
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v4 2/2] Regulator: Add Anatop regulator driver
2012-02-08 20:51 ` [PATCH v4 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
@ 2012-02-09 11:24 ` Mark Brown
2012-02-11 6:36 ` Shawn Guo
1 sibling, 0 replies; 25+ messages in thread
From: Mark Brown @ 2012-02-09 11:24 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Feb 09, 2012 at 04:51:26AM +0800, Ying-Chun Liu (PaulLiu) wrote:
Overall this is looking pretty good, a few issues but relatively minor.
> + if (uv < anatop_reg->rdata->min_voltage
> + || uv > anatop_reg->rdata->max_voltage) {
> + if (max_uV > anatop_reg->rdata->min_voltage)
> + uv = anatop_reg->rdata->min_voltage;
> + else
> + return -EINVAL;
> + }
This looks buggy (and is quite hard to follow). The check for the
voltage being above the minimum voltage is fine but surely if the
voltage is too high then the first if statement will be true and max_uV
will be greater than the minimum voltage so the second if will be true.
This will cause us to choose the minimum voltage that the regulator can
do which is less than the minimum voltage requested.
You probably shouldn't be checking for the upper end of the range at all
here...
> + if (anatop_reg->rdata->control_reg) {
> + sel = (uv - anatop_reg->rdata->min_voltage) / 25000;
> + val = anatop_reg->rdata->min_bit_val + sel;
> + *selector = sel;
> + pr_debug("%s: calculated val %d\n", __func__, val);
...instead check that selector is in range here.
> + anatop_reg->rdata->mfd->write(anatop_reg->rdata->mfd,
> + anatop_reg->rdata->control_reg,
> + anatop_reg->rdata->vol_bit_shift,
> + anatop_reg->rdata->vol_bit_size,
> + val);
Just have a write() function in the MFD.
> + memset(rdesc, 0, sizeof(struct regulator_desc));
> + rdesc->name = kstrdup(of_get_property(np, "regulator-name", NULL),
> + GFP_KERNEL);
You should add binding documentation for the device since it's OF based.
> + sreg->rdata->name = kstrdup(rdesc->name, GFP_KERNEL);
Can't you just point to rdesc->name?
> + if (IS_ERR(rdev)) {
> + dev_err(&pdev->dev, "failed to register %s\n",
> + rdesc->name);
> + return PTR_ERR(rdev);
> + }
All your kstrdup()s need to be unwound in error and free cases.
> +int anatop_regulator_init(void)
> +{
> + return platform_driver_register(&anatop_regulator);
> +}
> +
> +void anatop_regulator_exit(void)
> +{
> + platform_driver_unregister(&anatop_regulator);
> +}
> +
> +postcore_initcall(anatop_regulator_init);
> +module_exit(anatop_regulator_exit);
These should be adjacent to the functions.
> +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
Either omit this or put one or more humans as the author.
> +struct anatop_regulator {
> + struct regulator_desc *regulator;
> + struct regulator_init_data *initdata;
> + struct anatop_regulator_data *rdata;
> +};
May as well just merge the regulator data in here - it's not ever used
except with a 1:1 relationship between them. Could also directly
embed the desc and init_data, then you just have one allocation for the
data rather than a series to error check.
> +int anatop_register_regulator(
> + struct anatop_regulator *reg_data, int reg,
> + struct regulator_init_data *initdata);
This looks like it's not defined any more so could be removed and since
you only appear to support OF the entire header could be merged into the
driver.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120209/06f638d6/attachment.sig>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v4 2/2] Regulator: Add Anatop regulator driver
2012-02-08 20:51 ` [PATCH v4 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
2012-02-09 11:24 ` Mark Brown
@ 2012-02-11 6:36 ` Shawn Guo
2012-02-11 13:17 ` Mark Brown
1 sibling, 1 reply; 25+ messages in thread
From: Shawn Guo @ 2012-02-11 6:36 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Feb 09, 2012 at 04:51:26AM +0800, Ying-Chun Liu (PaulLiu) wrote:
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is an integrated regulator inside i.MX6 SoC.
> There are 3 digital regulators which controls PU, CORE (ARM), and SOC.
> And 3 analog regulators which controls 1P1, 2P5, 3P0 (USB).
> This patch adds the Anatop regulator driver.
>
> Signed-off-by: Nancy Chen <Nancy.Chen@freescale.com>
> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@ti.com>
> ---
> drivers/regulator/Kconfig | 6 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/anatop-regulator.c | 204 ++++++++++++++++++++++++++++
> include/linux/regulator/anatop-regulator.h | 49 +++++++
> 4 files changed, 260 insertions(+), 0 deletions(-)
> create mode 100644 drivers/regulator/anatop-regulator.c
> create mode 100644 include/linux/regulator/anatop-regulator.h
>
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index 7a61b17..5fbcda2 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -335,5 +335,11 @@ config REGULATOR_AAT2870
> If you have a AnalogicTech AAT2870 say Y to enable the
> regulator driver.
>
> +config REGULATOR_ANATOP
> + tristate "ANATOP LDO regulators"
> + depends on MFD_ANATOP
> + help
> + Say y here to support ANATOP LDOs regulators.
> +
> endif
>
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index 503bac8..8440871 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -48,5 +48,6 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
> obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
> obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
> obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
> +obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
>
> ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
> diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
> new file mode 100644
> index 0000000..d800c88
> --- /dev/null
> +++ b/drivers/regulator/anatop-regulator.c
> @@ -0,0 +1,204 @@
> +/*
> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/anatop-regulator.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/regulator/of_regulator.h>
> +
> +static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
> + int max_uV, unsigned *selector)
> +{
> + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
> + u32 val, sel;
> + int uv;
> +
> + uv = min_uV;
> + pr_debug("%s: uv %d, min %d, max %d\n", __func__,
I would suggest dev_dbg in device driver.
> + uv, anatop_reg->rdata->min_voltage,
> + anatop_reg->rdata->max_voltage);
> +
> + if (uv < anatop_reg->rdata->min_voltage
> + || uv > anatop_reg->rdata->max_voltage) {
> + if (max_uV > anatop_reg->rdata->min_voltage)
> + uv = anatop_reg->rdata->min_voltage;
> + else
> + return -EINVAL;
> + }
> +
> + if (anatop_reg->rdata->control_reg) {
> + sel = (uv - anatop_reg->rdata->min_voltage) / 25000;
> + val = anatop_reg->rdata->min_bit_val + sel;
> + *selector = sel;
> + pr_debug("%s: calculated val %d\n", __func__, val);
> + anatop_reg->rdata->mfd->write(anatop_reg->rdata->mfd,
> + anatop_reg->rdata->control_reg,
> + anatop_reg->rdata->vol_bit_shift,
> + anatop_reg->rdata->vol_bit_size,
> + val);
> + return 0;
> + } else {
> + return -ENOTSUPP;
> + }
> +}
> +
> +static int anatop_get_voltage_sel(struct regulator_dev *reg)
> +{
> + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
> + int selector;
> + struct anatop_regulator_data *rdata = anatop_reg->rdata;
> +
> + if (rdata->control_reg) {
> + u32 val = rdata->mfd->read(rdata->mfd,
> + rdata->control_reg,
> + rdata->vol_bit_shift,
> + rdata->vol_bit_size);
> + selector = val - rdata->min_bit_val;
> + return selector;
> + } else {
> + return -ENOTSUPP;
> + }
> +}
> +
> +static int anatop_list_voltage(struct regulator_dev *dev, unsigned selector)
> +{
> + struct anatop_regulator *anatop_reg = rdev_get_drvdata(dev);
> + int uv;
> + struct anatop_regulator_data *rdata = anatop_reg->rdata;
> +
> + uv = rdata->min_voltage + selector * 25000;
> + pr_debug("vddio = %d, selector = %u\n", uv, selector);
> + return uv;
> +}
> +
> +static struct regulator_ops anatop_rops = {
> + .set_voltage = anatop_set_voltage,
> + .get_voltage_sel = anatop_get_voltage_sel,
> + .list_voltage = anatop_list_voltage,
> +};
> +
> +int anatop_regulator_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct regulator_desc *rdesc;
> + struct regulator_dev *rdev;
> + struct anatop_regulator *sreg;
> + struct regulator_init_data *initdata;
> + struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
> + const __be32 *rval;
> + u64 ofsize;
> +
> + initdata = of_get_regulator_init_data(dev, dev->of_node);
> + sreg = devm_kzalloc(dev, sizeof(struct anatop_regulator), GFP_KERNEL);
> + if (!sreg)
> + return -EINVAL;
> + rdesc = devm_kzalloc(dev, sizeof(struct regulator_desc), GFP_KERNEL);
> + if (!rdesc)
> + return -EINVAL;
> + sreg->initdata = initdata;
> + sreg->regulator = rdesc;
> + memset(rdesc, 0, sizeof(struct regulator_desc));
> + rdesc->name = kstrdup(of_get_property(np, "regulator-name", NULL),
> + GFP_KERNEL);
We can probably reuse the regulator's node name here to save property
regulator-name.
> + rdesc->ops = &anatop_rops;
> + rdesc->type = REGULATOR_VOLTAGE;
> + rdesc->owner = THIS_MODULE;
> + sreg->rdata = devm_kzalloc(dev,
> + sizeof(struct anatop_regulator_data),
> + GFP_KERNEL);
> + sreg->rdata->name = kstrdup(rdesc->name, GFP_KERNEL);
> + rval = of_get_address(np, 0, &ofsize, NULL);
> + if (rval) {
> + sreg->rdata->control_reg = be32_to_cpu(rval[0]);
> + sreg->rdata->vol_bit_shift = be32_to_cpu(rval[1]);
I'm not sure you can (ab)use 'reg' property for bit shift. We may
need to have a property for it.
> + }
> + sreg->rdata->mfd = anatopmfd;
> + sreg->rdata->vol_bit_size = (int)ofsize;
> + rval = of_get_property(np, "min-bit-val", NULL);
> + if (rval)
> + sreg->rdata->min_bit_val = be32_to_cpu(*rval);
> + rval = of_get_property(np, "min-voltage", NULL);
> + if (rval)
> + sreg->rdata->min_voltage = be32_to_cpu(*rval);
> + rval = of_get_property(np, "max-voltage", NULL);
> + if (rval)
> + sreg->rdata->max_voltage = be32_to_cpu(*rval);
We need a sensible binding document to understand those. But at least,
shouldn't min-voltage and max-voltage be retrieved as the common
regulator binding documented in
Documentation/devicetree/bindings/regulator/regulator.txt?
> +
> + /* register regulator */
> + rdev = regulator_register(rdesc, &pdev->dev,
> + initdata, sreg, pdev->dev.of_node);
> + platform_set_drvdata(pdev, rdev);
> +
> + if (IS_ERR(rdev)) {
> + dev_err(&pdev->dev, "failed to register %s\n",
> + rdesc->name);
> + return PTR_ERR(rdev);
> + }
> +
> + return 0;
> +}
> +
> +int anatop_regulator_remove(struct platform_device *pdev)
> +{
> + struct regulator_dev *rdev = platform_get_drvdata(pdev);
> + regulator_unregister(rdev);
> + return 0;
> +}
> +
> +struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
> + { .compatible = "fsl,anatop-regulator", },
> + { /* end */ }
> +};
> +
> +
One blank line is enough.
> +struct platform_driver anatop_regulator = {
> + .driver = {
> + .name = "anatop_regulator",
> + .owner = THIS_MODULE,
> + .of_match_table = of_anatop_regulator_match_tbl,
> + },
> + .probe = anatop_regulator_probe,
> + .remove = anatop_regulator_remove,
> +};
> +
> +int anatop_regulator_init(void)
> +{
> + return platform_driver_register(&anatop_regulator);
> +}
> +
> +void anatop_regulator_exit(void)
> +{
> + platform_driver_unregister(&anatop_regulator);
> +}
> +
> +postcore_initcall(anatop_regulator_init);
> +module_exit(anatop_regulator_exit);
> +
> +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
> +MODULE_DESCRIPTION("ANATOP Regulator driver");
> +MODULE_LICENSE("GPL");
"GPL v2"?
> diff --git a/include/linux/regulator/anatop-regulator.h b/include/linux/regulator/anatop-regulator.h
> new file mode 100644
> index 0000000..089d519
> --- /dev/null
> +++ b/include/linux/regulator/anatop-regulator.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#ifndef __ANATOP_REGULATOR_H
> +#define __ANATOP_REGULATOR_H
Have a blank line here.
> +#include <linux/regulator/driver.h>
> +#include <linux/mfd/anatop.h>
> +
> +struct anatop_regulator {
> + struct regulator_desc *regulator;
> + struct regulator_init_data *initdata;
> + struct anatop_regulator_data *rdata;
> +};
> +
> +
Drop one blank line here.
> +struct anatop_regulator_data {
> + const char *name;
> +
Nit: drop this blank line.
> + u32 control_reg;
> + struct anatop *mfd;
> + int vol_bit_shift;
> + int vol_bit_size;
> + int min_bit_val;
> + int min_voltage;
> + int max_voltage;
> +};
> +
It seems to me that anatop_regulator_data should be put before
anatop_regulator.
Regards,
Shawn
> +int anatop_register_regulator(
> + struct anatop_regulator *reg_data, int reg,
> + struct regulator_init_data *initdata);
> +
> +#endif /* __ANATOP_REGULATOR_H */
> --
> 1.7.8.3
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v4 2/2] Regulator: Add Anatop regulator driver
2012-02-11 6:36 ` Shawn Guo
@ 2012-02-11 13:17 ` Mark Brown
0 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2012-02-11 13:17 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Feb 10, 2012 at 10:36:38PM -0800, Shawn Guo wrote:
> On Thu, Feb 09, 2012 at 04:51:26AM +0800, Ying-Chun Liu (PaulLiu) wrote:
> > + rval = of_get_property(np, "min-voltage", NULL);
> > + if (rval)
> > + sreg->rdata->min_voltage = be32_to_cpu(*rval);
> > + rval = of_get_property(np, "max-voltage", NULL);
> > + if (rval)
> > + sreg->rdata->max_voltage = be32_to_cpu(*rval);
> We need a sensible binding document to understand those. But at least,
> shouldn't min-voltage and max-voltage be retrieved as the common
> regulator binding documented in
> Documentation/devicetree/bindings/regulator/regulator.txt?
Normally this would be a bad idea as the set of voltages that can safely
be used on a given board might differ from those which are supported by
the device. However in this case you might be OK as this is all
internal to the SoC and so presumably won't vary from board to board.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120211/f42da0ce/attachment.sig>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v4 1/2] mfd: Add anatop mfd driver
2012-02-08 20:51 ` [PATCH v4 1/2] mfd: Add anatop mfd driver Ying-Chun Liu (PaulLiu)
2012-02-08 20:51 ` [PATCH v4 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
@ 2012-02-11 6:05 ` Shawn Guo
2012-02-21 11:17 ` Samuel Ortiz
2012-03-01 9:10 ` [PATCH v5 " Ying-Chun Liu (PaulLiu)
3 siblings, 0 replies; 25+ messages in thread
From: Shawn Guo @ 2012-02-11 6:05 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Feb 09, 2012 at 04:51:25AM +0800, Ying-Chun Liu (PaulLiu) wrote:
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
> Anatop provides regulators and thermal.
> This driver handles the address space and the operation of the mfd device.
>
> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> ---
> drivers/mfd/Kconfig | 6 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/anatop-mfd.c | 152 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/anatop.h | 39 +++++++++++
> 4 files changed, 198 insertions(+), 0 deletions(-)
> create mode 100644 drivers/mfd/anatop-mfd.c
> create mode 100644 include/linux/mfd/anatop.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index cd13e9f..4f71627 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
> Passage) chip. This chip embeds audio, battery, GPIO, etc.
> devices used in Intel Medfield platforms.
>
> +config MFD_ANATOP
> + bool "Support for Anatop"
> + depends on SOC_IMX6Q
> + help
> + Select this option to enable Anatop MFD driver.
> +
> endmenu
> endif
>
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index b953bab..8e11060 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -112,3 +112,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
> obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
> obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
> obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
> +obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
> diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
> new file mode 100644
> index 0000000..58c6054
> --- /dev/null
> +++ b/drivers/mfd/anatop-mfd.c
> @@ -0,0 +1,152 @@
> +/*
> + * Anatop MFD driver
> + *
> + * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> + * Copyright (C) 2012 Linaro
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/mfd/anatop.h>
> +
> +static u32 anatop_read(struct anatop *adata, u32 addr, int bit_shift, int bits)
> +{
> + u32 val;
> + int mask;
Nit: it may be nice to put a blank line here.
> + if (bits == 32)
> + mask = 0xff;
Shouldn't it be ~0?
> + else
> + mask = (1 << bits) - 1;
> +
> + val = ioread32(adata->ioreg+addr);
Why not just readl()? Nit: put space before and after '+'.
> + val = (val >> bit_shift) & mask;
Nit: it may be nice to put a blank line here.
> + return val;
> +}
> +
> +static void anatop_write(struct anatop *adata, u32 addr, int bit_shift,
> + int bits, u32 data)
> +{
> + u32 val;
> + int mask;
> + if (bits == 32)
> + mask = 0xff;
> + else
> + mask = (1 << bits) - 1;
> +
> + val = ioread32(adata->ioreg+addr) & ~(mask << bit_shift);
> + iowrite32((data << bit_shift) | val, adata->ioreg);
Same comments on anatop_read apply on anatop_write here.
> +}
> +
> +static const struct of_device_id of_anatop_regulator_match[] = {
A better naming of of_anatop_regulator_match, since it covers not only
regulator but also thermal as below?
> + {
> + .compatible = "fsl,anatop-regulator",
> + },
Nit: since you only have one line here, it could be just:
{ .compatible = "fsl,anatop-regulator", },
> + {
> + .compatible = "fsl,anatop-thermal",
> + },
> + { },
> +};
> +
> +static int of_anatop_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + u64 ofaddr;
> + u64 ofsize;
> + void *ioreg;
> + struct anatop *drvdata;
> + int ret = 0;
> + const __be32 *rval;
> +
---
> + rval = of_get_address(np, 0, &ofsize, NULL);
> + if (rval)
> + ofaddr = be32_to_cpu(*rval);
> + else
> + return -EINVAL;
> +
> + ioreg = ioremap(ofaddr, ofsize);
---
Above lines can just be of_iomap(np, 0);
> + if (!ioreg)
> + return -EINVAL;
> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
> + if (!drvdata)
> + return -EINVAL;
> + drvdata->ioreg = ioreg;
> + drvdata->read = anatop_read;
> + drvdata->write = anatop_write;
> + platform_set_drvdata(pdev, drvdata);
> + of_platform_bus_probe(np, of_anatop_regulator_match, dev);
Nit: it may be nice to put a blank line here.
> + return ret;
The 'ret' is used nowhere, so the above line can just be:
return 0;
> +}
> +
> +static int of_anatop_remove(struct platform_device *pdev)
> +{
Nothing to do here? At least iounmap?
> + return 0;
> +}
> +
> +static const struct of_device_id of_anatop_match[] = {
> + {
> + .compatible = "fsl,imx6q-anatop",
> + },
{ .compatible = "fsl,imx6q-anatop", },
> + { },
> +};
> +
> +static struct platform_driver anatop_of_driver = {
> + .driver = {
> + .name = "anatop-mfd",
> + .owner = THIS_MODULE,
> + .of_match_table = of_anatop_match,
> + },
> + .probe = of_anatop_probe,
> + .remove = of_anatop_remove,
> +};
> +
> +static int __init anatop_init(void)
> +{
> + int ret;
> + ret = platform_driver_register(&anatop_of_driver);
> + return ret;
return platform_driver_register(&anatop_of_driver);
> +}
> +
> +static void __exit anatop_exit(void)
> +{
> + platform_driver_unregister(&anatop_of_driver);
> +}
> +
> +postcore_initcall(anatop_init);
> +module_exit(anatop_exit);
> +
> +MODULE_AUTHOR("Ying-Chun Liu (PaulLiu)");
Missing your email address here.
> +MODULE_DESCRIPTION("ANATOP MFD driver");
> +MODULE_LICENSE("GPL");
"GPL v2" for better?
> diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
> new file mode 100644
> index 0000000..4425538
> --- /dev/null
> +++ b/include/linux/mfd/anatop.h
> @@ -0,0 +1,39 @@
> +/*
> + * anatop.h - Anatop MFD driver
> + *
> + * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paulliu@debian.org>
It would nice to use a consistent email address through the patch.
Regards,
Shawn
> + * Copyright (C) 2012 Linaro
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#ifndef __LINUX_MFD_ANATOP_H
> +#define __LINUX_MFD_ANATOP_H
> +
> +/**
> + * anatop - MFD data
> + * @ioreg: ioremap register
> + * @read: function to read bits from the device
> + * @write: function to write bits to the device
> + */
> +struct anatop {
> + void *ioreg;
> + u32 (*read) (struct anatop *adata, u32 addr, int bit_shift, int bits);
> + void (*write) (struct anatop *adata, u32 addr, int bit_shift,
> + int bits, u32 data);
> +
> +};
> +
> +#endif /* __LINUX_MFD_ANATOP_H */
> --
> 1.7.8.3
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v4 1/2] mfd: Add anatop mfd driver
2012-02-08 20:51 ` [PATCH v4 1/2] mfd: Add anatop mfd driver Ying-Chun Liu (PaulLiu)
2012-02-08 20:51 ` [PATCH v4 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
2012-02-11 6:05 ` [PATCH v4 1/2] mfd: Add anatop mfd driver Shawn Guo
@ 2012-02-21 11:17 ` Samuel Ortiz
2012-03-01 9:19 ` Ying-Chun Liu (PaulLiu)
2012-03-01 9:10 ` [PATCH v5 " Ying-Chun Liu (PaulLiu)
3 siblings, 1 reply; 25+ messages in thread
From: Samuel Ortiz @ 2012-02-21 11:17 UTC (permalink / raw)
To: linux-arm-kernel
Hi Paul,
I didn't get patch #2, so I don't get to see how the read/write functions ar
eused for example.
On Thu, Feb 09, 2012 at 04:51:25AM +0800, Ying-Chun Liu (PaulLiu) wrote:
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
> Anatop provides regulators and thermal.
> This driver handles the address space and the operation of the mfd device.
A few comments here:
> +static u32 anatop_read(struct anatop *adata, u32 addr, int bit_shift, int bits)
> +{
> + u32 val;
> + int mask;
> + if (bits == 32)
> + mask = 0xff;
> + else
> + mask = (1 << bits) - 1;
> +
> + val = ioread32(adata->ioreg+addr);
> + val = (val >> bit_shift) & mask;
> + return val;
> +}
> +
> +static void anatop_write(struct anatop *adata, u32 addr, int bit_shift,
> + int bits, u32 data)
> +{
> + u32 val;
> + int mask;
> + if (bits == 32)
> + mask = 0xff;
> + else
> + mask = (1 << bits) - 1;
> +
> + val = ioread32(adata->ioreg+addr) & ~(mask << bit_shift);
> + iowrite32((data << bit_shift) | val, adata->ioreg);
> +}
Don't you need some sort of read/write atomic routine as well ? Locking would
be needed then...
> +static const struct of_device_id of_anatop_regulator_match[] = {
> + {
> + .compatible = "fsl,anatop-regulator",
> + },
> + {
> + .compatible = "fsl,anatop-thermal",
> + },
> + { },
> +};
> +
> +static int of_anatop_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + u64 ofaddr;
> + u64 ofsize;
> + void *ioreg;
> + struct anatop *drvdata;
> + int ret = 0;
> + const __be32 *rval;
> +
> + rval = of_get_address(np, 0, &ofsize, NULL);
> + if (rval)
> + ofaddr = be32_to_cpu(*rval);
> + else
> + return -EINVAL;
> +
> + ioreg = ioremap(ofaddr, ofsize);
> + if (!ioreg)
> + return -EINVAL;
> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
> + if (!drvdata)
> + return -EINVAL;
> + drvdata->ioreg = ioreg;
> + drvdata->read = anatop_read;
> + drvdata->write = anatop_write;
> + platform_set_drvdata(pdev, drvdata);
> + of_platform_bus_probe(np, of_anatop_regulator_match, dev);
> + return ret;
> +}
So it seems that your driver here does nothing but extending your device tree
definition. Correct me if I'm wrong, aren't you trying to fix a broken device
tree definition here ?
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v4 1/2] mfd: Add anatop mfd driver
2012-02-21 11:17 ` Samuel Ortiz
@ 2012-03-01 9:19 ` Ying-Chun Liu (PaulLiu)
0 siblings, 0 replies; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-01 9:19 UTC (permalink / raw)
To: linux-arm-kernel
(2012?02?21? 19:17), Samuel Ortiz wrote:
> Hi Paul,
>
> I didn't get patch #2, so I don't get to see how the read/write functions ar
> eused for example.
>
Hi Samuel,
Sorry for late reply.
I've sent out v5 today.
>> + ioreg = ioremap(ofaddr, ofsize);
>> + if (!ioreg)
>> + return -EINVAL;
>> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
>> + if (!drvdata)
>> + return -EINVAL;
>> + drvdata->ioreg = ioreg;
>> + drvdata->read = anatop_read;
>> + drvdata->write = anatop_write;
>> + platform_set_drvdata(pdev, drvdata);
>> + of_platform_bus_probe(np, of_anatop_regulator_match, dev);
>> + return ret;
>> +}
> So it seems that your driver here does nothing but extending your device tree
> definition. Correct me if I'm wrong, aren't you trying to fix a broken device
> tree definition here ?
>
The driver here ioremap the addresses for anatop chip in i.MX6Q SoC. The
addresses are shared by several regulators. Also thermal drivers are
also in the same range.
Here are examples of the anatop description in dts file
anatop at 020c8000 {
compatible = "fsl,imx6q-anatop";
reg = <0x020c8000 0x1000>;
interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
#address-cells = <1>;
#size-cells = <1>;
reg_vddpu: regulator-vddpu at 140 {
compatible = "fsl,anatop-regulator";
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
reg = <0x140 1>;
vol-bit-shift = <9>;
vol-bit-size = <5>;
min-bit-val = <1>;
min-voltage = <725000>;
max-voltage = <1300000>;
};
reg_vddcore: regulator-vddcore at 140 {
compatible = "fsl,anatop-regulator";
regulator-name = "vddcore";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
reg = <0x140 1>;
vol-bit-shift = <0>;
vol-bit-size = <5>;
min-bit-val = <1>;
min-voltage = <725000>;
max-voltage = <1300000>;
};
...
So both reg_vddpu and reg_vddcore are using the same address.
Yours Sincerely,
Paul
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v5 1/2] mfd: Add anatop mfd driver
2012-02-08 20:51 ` [PATCH v4 1/2] mfd: Add anatop mfd driver Ying-Chun Liu (PaulLiu)
` (2 preceding siblings ...)
2012-02-21 11:17 ` Samuel Ortiz
@ 2012-03-01 9:10 ` Ying-Chun Liu (PaulLiu)
2012-03-01 9:10 ` [PATCH v5 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
` (2 more replies)
3 siblings, 3 replies; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-01 9:10 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
Anatop provides regulators and thermal.
This driver handles the address space and the operation of the mfd device.
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mfd/Kconfig | 6 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/anatop-mfd.c | 144 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/anatop.h | 40 ++++++++++++
4 files changed, 191 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/anatop-mfd.c
create mode 100644 include/linux/mfd/anatop.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f147395..f787d17 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
Passage) chip. This chip embeds audio, battery, GPIO, etc.
devices used in Intel Medfield platforms.
+config MFD_ANATOP
+ bool "Support for Anatop"
+ depends on SOC_IMX6Q
+ help
+ Select this option to enable Anatop MFD driver.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b953bab..8e11060 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -112,3 +112,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
+obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
new file mode 100644
index 0000000..86e2b8e
--- /dev/null
+++ b/drivers/mfd/anatop-mfd.c
@@ -0,0 +1,144 @@
+/*
+ * Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/mfd/anatop.h>
+
+u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, int bits)
+{
+ u32 val;
+ int mask;
+
+ if (bits == 32)
+ mask = ~0;
+ else
+ mask = (1 << bits) - 1;
+
+ spin_lock(&adata->reglock);
+ val = readl(adata->ioreg + addr);
+ spin_unlock(&adata->reglock);
+ val = (val >> bit_shift) & mask;
+
+ return val;
+}
+EXPORT_SYMBOL(anatop_get_bits);
+
+void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
+ int bits, u32 data)
+{
+ u32 val;
+ int mask;
+ if (bits == 32)
+ mask = ~0;
+ else
+ mask = (1 << bits) - 1;
+
+ spin_lock(&adata->reglock);
+ val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
+ writel((data << bit_shift) | val, adata->ioreg);
+ spin_unlock(&adata->reglock);
+}
+EXPORT_SYMBOL(anatop_set_bits);
+
+static const struct of_device_id of_anatop_subdevice_match[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { .compatible = "fsl,anatop-thermal", },
+ { },
+};
+
+static int of_anatop_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void *ioreg;
+ struct anatop *drvdata;
+
+ ioreg = of_iomap(np, 0);
+ if (!ioreg)
+ return -EINVAL;
+ drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
+ if (!drvdata)
+ return -EINVAL;
+ drvdata->ioreg = ioreg;
+ spin_lock_init(&drvdata->reglock);
+ platform_set_drvdata(pdev, drvdata);
+ of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
+
+ return 0;
+}
+
+static int of_anatop_remove(struct platform_device *pdev)
+{
+ struct anatop *drvdata;
+ drvdata = platform_get_drvdata(pdev);
+ iounmap(drvdata->ioreg);
+ return 0;
+}
+
+static const struct of_device_id of_anatop_match[] = {
+ { .compatible = "fsl,imx6q-anatop", },
+ { },
+};
+
+static struct platform_driver anatop_of_driver = {
+ .driver = {
+ .name = "anatop-mfd",
+ .owner = THIS_MODULE,
+ .of_match_table = of_anatop_match,
+ },
+ .probe = of_anatop_probe,
+ .remove = of_anatop_remove,
+};
+
+static int __init anatop_init(void)
+{
+ return platform_driver_register(&anatop_of_driver);
+}
+postcore_initcall(anatop_init);
+
+static void __exit anatop_exit(void)
+{
+ platform_driver_unregister(&anatop_of_driver);
+}
+module_exit(anatop_exit);
+
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_DESCRIPTION("ANATOP MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
new file mode 100644
index 0000000..22c1007
--- /dev/null
+++ b/include/linux/mfd/anatop.h
@@ -0,0 +1,40 @@
+/*
+ * anatop.h - Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_MFD_ANATOP_H
+#define __LINUX_MFD_ANATOP_H
+
+#include <linux/spinlock.h>
+
+/**
+ * anatop - MFD data
+ * @ioreg: ioremap register
+ * @reglock: spinlock for register read/write
+ */
+struct anatop {
+ void *ioreg;
+ spinlock_t reglock;
+};
+
+extern u32 anatop_get_bits(struct anatop *, u32, int, int);
+extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
+
+#endif /* __LINUX_MFD_ANATOP_H */
--
1.7.9
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v5 2/2] Regulator: Add Anatop regulator driver
2012-03-01 9:10 ` [PATCH v5 " Ying-Chun Liu (PaulLiu)
@ 2012-03-01 9:10 ` Ying-Chun Liu (PaulLiu)
2012-03-01 11:17 ` Mark Brown
2012-03-01 11:30 ` [PATCH v5 1/2] mfd: Add anatop mfd driver Mark Brown
2012-03-02 7:00 ` [PATCH v6 " Ying-Chun Liu (PaulLiu)
2 siblings, 1 reply; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-01 9:10 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Anatop is an integrated regulator inside i.MX6 SoC.
There are 3 digital regulators which controls PU, CORE (ARM), and SOC.
And 3 analog regulators which controls 1P1, 2P5, 3P0 (USB).
This patch adds the Anatop regulator driver.
Signed-off-by: Nancy Chen <Nancy.Chen@freescale.com>
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@ti.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
---
.../bindings/regulator/anatop-regulator.txt | 28 +++
drivers/regulator/Kconfig | 6 +
drivers/regulator/Makefile | 1 +
drivers/regulator/anatop-regulator.c | 203 ++++++++++++++++++++
include/linux/regulator/anatop-regulator.h | 40 ++++
5 files changed, 278 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/regulator/anatop-regulator.txt
create mode 100644 drivers/regulator/anatop-regulator.c
create mode 100644 include/linux/regulator/anatop-regulator.h
diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
new file mode 100644
index 0000000..9ed7326
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
@@ -0,0 +1,28 @@
+Anatop Voltage regulators
+
+Required properties:
+- compatible: Must be "fsl,anatop-regulator"
+- vol-bit-shift: Bit shift for the register
+- vol-bit-size: Number of bits used in the register
+- min-bit-val: Minimum value of this register
+- min-voltage: Minimum voltage of this regulator
+- max-voltage: Maximum voltage of this regulator
+
+Any property defined as part of the core regulator
+binding, defined in regulator.txt, can also be used.
+
+Example:
+
+ reg_vddpu: regulator-vddpu at 140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddpu";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ reg = <0x140>;
+ vol-bit-shift = <9>;
+ vol-bit-size = <5>;
+ min-bit-val = <1>;
+ min-voltage = <725000>;
+ max-voltage = <1300000>;
+ };
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7a61b17..5fbcda2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -335,5 +335,11 @@ config REGULATOR_AAT2870
If you have a AnalogicTech AAT2870 say Y to enable the
regulator driver.
+config REGULATOR_ANATOP
+ tristate "ANATOP LDO regulators"
+ depends on MFD_ANATOP
+ help
+ Say y here to support ANATOP LDOs regulators.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 503bac8..8440871 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,5 +48,6 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
+obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
new file mode 100644
index 0000000..1f3a878
--- /dev/null
+++ b/drivers/regulator/anatop-regulator.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regulator/of_regulator.h>
+
+static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ u32 val, sel;
+ int uv;
+
+ uv = min_uV;
+ dev_dbg(®->dev, "%s: uv %d, min %d, max %d\n", __func__,
+ uv, anatop_reg->min_voltage,
+ anatop_reg->max_voltage);
+
+ if (uv < anatop_reg->min_voltage) {
+ if (max_uV > anatop_reg->min_voltage)
+ uv = anatop_reg->min_voltage;
+ else
+ return -EINVAL;
+ }
+
+ if (anatop_reg->control_reg) {
+ sel = (uv - anatop_reg->min_voltage) / 25000;
+ if (sel * 25000 + anatop_reg->min_voltage
+ > anatop_reg->max_voltage)
+ return -EINVAL;
+ val = anatop_reg->min_bit_val + sel;
+ *selector = sel;
+ dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val);
+ anatop_set_bits(anatop_reg->mfd,
+ anatop_reg->control_reg,
+ anatop_reg->vol_bit_shift,
+ anatop_reg->vol_bit_size,
+ val);
+ return 0;
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int anatop_get_voltage_sel(struct regulator_dev *reg)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ int selector;
+
+ if (anatop_reg->control_reg) {
+ u32 val = anatop_get_bits(anatop_reg->mfd,
+ anatop_reg->control_reg,
+ anatop_reg->vol_bit_shift,
+ anatop_reg->vol_bit_size);
+ selector = val - anatop_reg->min_bit_val;
+ return selector;
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ int uv;
+
+ uv = anatop_reg->min_voltage + selector * 25000;
+ dev_dbg(®->dev, "vddio = %d, selector = %u\n", uv, selector);
+
+ return uv;
+}
+
+static struct regulator_ops anatop_rops = {
+ .set_voltage = anatop_set_voltage,
+ .get_voltage_sel = anatop_get_voltage_sel,
+ .list_voltage = anatop_list_voltage,
+};
+
+int anatop_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regulator_desc *rdesc;
+ struct regulator_dev *rdev;
+ struct anatop_regulator *sreg;
+ struct regulator_init_data *initdata;
+ struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
+ const __be32 *rval;
+ u64 ofsize;
+
+ initdata = of_get_regulator_init_data(dev, dev->of_node);
+ sreg = devm_kzalloc(dev, sizeof(struct anatop_regulator), GFP_KERNEL);
+ if (!sreg)
+ return -EINVAL;
+ rdesc = devm_kzalloc(dev, sizeof(struct regulator_desc), GFP_KERNEL);
+ if (!rdesc)
+ return -EINVAL;
+ sreg->initdata = initdata;
+ sreg->regulator = rdesc;
+ memset(rdesc, 0, sizeof(struct regulator_desc));
+ rdesc->name = kstrdup(of_get_property(np, "regulator-name", NULL),
+ GFP_KERNEL);
+ rdesc->ops = &anatop_rops;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->owner = THIS_MODULE;
+ sreg->name = rdesc->name;
+ sreg->mfd = anatopmfd;
+ rval = of_get_address(np, 0, &ofsize, NULL);
+ if (rval)
+ sreg->control_reg = be32_to_cpu(*rval);
+ rval = of_get_property(np, "vol-bit-size", NULL);
+ if (rval)
+ sreg->vol_bit_size = be32_to_cpu(*rval);
+ rval = of_get_property(np, "vol-bit-shift", NULL);
+ if (rval)
+ sreg->vol_bit_shift = be32_to_cpu(*rval);
+ rval = of_get_property(np, "min-bit-val", NULL);
+ if (rval)
+ sreg->min_bit_val = be32_to_cpu(*rval);
+ rval = of_get_property(np, "min-voltage", NULL);
+ if (rval)
+ sreg->min_voltage = be32_to_cpu(*rval);
+ rval = of_get_property(np, "max-voltage", NULL);
+ if (rval)
+ sreg->max_voltage = be32_to_cpu(*rval);
+
+ /* register regulator */
+ rdev = regulator_register(rdesc, &pdev->dev,
+ initdata, sreg, pdev->dev.of_node);
+ platform_set_drvdata(pdev, rdev);
+
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ rdesc->name);
+ kfree(rdesc->name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+int anatop_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ regulator_unregister(rdev);
+ return 0;
+}
+
+struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { /* end */ }
+};
+
+struct platform_driver anatop_regulator = {
+ .driver = {
+ .name = "anatop_regulator",
+ .owner = THIS_MODULE,
+ .of_match_table = of_anatop_regulator_match_tbl,
+ },
+ .probe = anatop_regulator_probe,
+ .remove = anatop_regulator_remove,
+};
+
+int anatop_regulator_init(void)
+{
+ return platform_driver_register(&anatop_regulator);
+}
+postcore_initcall(anatop_regulator_init);
+
+void anatop_regulator_exit(void)
+{
+ platform_driver_unregister(&anatop_regulator);
+}
+module_exit(anatop_regulator_exit);
+
+MODULE_DESCRIPTION("ANATOP Regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/regulator/anatop-regulator.h b/include/linux/regulator/anatop-regulator.h
new file mode 100644
index 0000000..7a9a05b
--- /dev/null
+++ b/include/linux/regulator/anatop-regulator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ANATOP_REGULATOR_H
+#define __ANATOP_REGULATOR_H
+
+#include <linux/regulator/driver.h>
+#include <linux/mfd/anatop.h>
+
+struct anatop_regulator {
+ struct regulator_desc *regulator;
+ struct regulator_init_data *initdata;
+ const char *name;
+ u32 control_reg;
+ struct anatop *mfd;
+ int vol_bit_shift;
+ int vol_bit_size;
+ int min_bit_val;
+ int min_voltage;
+ int max_voltage;
+};
+
+#endif /* __ANATOP_REGULATOR_H */
--
1.7.9
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v5 1/2] mfd: Add anatop mfd driver
2012-03-01 9:10 ` [PATCH v5 " Ying-Chun Liu (PaulLiu)
2012-03-01 9:10 ` [PATCH v5 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
@ 2012-03-01 11:30 ` Mark Brown
2012-03-02 7:00 ` [PATCH v6 " Ying-Chun Liu (PaulLiu)
2 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2012-03-01 11:30 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 01, 2012 at 05:10:51PM +0800, Ying-Chun Liu (PaulLiu) wrote:
> + spin_lock(&adata->reglock);
> + val = readl(adata->ioreg + addr);
> + spin_unlock(&adata->reglock);
Do you really need to take a lock for a single read operation from a
memory mapped register? I'd expect this to be atomic in itself. You
need to lock on read/modify/write cycles to make sure that you don't get
a read/read/modify/modify/write/write and misplace one of the modifies
but that's not an issue for an isolated read.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120301/65ce9750/attachment.sig>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v6 1/2] mfd: Add anatop mfd driver
2012-03-01 9:10 ` [PATCH v5 " Ying-Chun Liu (PaulLiu)
2012-03-01 9:10 ` [PATCH v5 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
2012-03-01 11:30 ` [PATCH v5 1/2] mfd: Add anatop mfd driver Mark Brown
@ 2012-03-02 7:00 ` Ying-Chun Liu (PaulLiu)
2012-03-02 7:00 ` [PATCH v6 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
` (3 more replies)
2 siblings, 4 replies; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-02 7:00 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
Anatop provides regulators and thermal.
This driver handles the address space and the operation of the mfd device.
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mfd/Kconfig | 6 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/anatop-mfd.c | 142 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/anatop.h | 40 ++++++++++++
4 files changed, 189 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/anatop-mfd.c
create mode 100644 include/linux/mfd/anatop.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f147395..f787d17 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
Passage) chip. This chip embeds audio, battery, GPIO, etc.
devices used in Intel Medfield platforms.
+config MFD_ANATOP
+ bool "Support for Anatop"
+ depends on SOC_IMX6Q
+ help
+ Select this option to enable Anatop MFD driver.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b953bab..8e11060 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -112,3 +112,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
+obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
new file mode 100644
index 0000000..0307051
--- /dev/null
+++ b/drivers/mfd/anatop-mfd.c
@@ -0,0 +1,142 @@
+/*
+ * Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/mfd/anatop.h>
+
+u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, int bits)
+{
+ u32 val;
+ int mask;
+
+ if (bits == 32)
+ mask = ~0;
+ else
+ mask = (1 << bits) - 1;
+
+ val = readl(adata->ioreg + addr);
+ val = (val >> bit_shift) & mask;
+
+ return val;
+}
+EXPORT_SYMBOL(anatop_get_bits);
+
+void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
+ int bits, u32 data)
+{
+ u32 val;
+ int mask;
+ if (bits == 32)
+ mask = ~0;
+ else
+ mask = (1 << bits) - 1;
+
+ spin_lock(&adata->reglock);
+ val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
+ writel((data << bit_shift) | val, adata->ioreg);
+ spin_unlock(&adata->reglock);
+}
+EXPORT_SYMBOL(anatop_set_bits);
+
+static const struct of_device_id of_anatop_subdevice_match[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { .compatible = "fsl,anatop-thermal", },
+ { },
+};
+
+static int of_anatop_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void *ioreg;
+ struct anatop *drvdata;
+
+ ioreg = of_iomap(np, 0);
+ if (!ioreg)
+ return -EINVAL;
+ drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
+ if (!drvdata)
+ return -EINVAL;
+ drvdata->ioreg = ioreg;
+ spin_lock_init(&drvdata->reglock);
+ platform_set_drvdata(pdev, drvdata);
+ of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
+
+ return 0;
+}
+
+static int of_anatop_remove(struct platform_device *pdev)
+{
+ struct anatop *drvdata;
+ drvdata = platform_get_drvdata(pdev);
+ iounmap(drvdata->ioreg);
+ return 0;
+}
+
+static const struct of_device_id of_anatop_match[] = {
+ { .compatible = "fsl,imx6q-anatop", },
+ { },
+};
+
+static struct platform_driver anatop_of_driver = {
+ .driver = {
+ .name = "anatop-mfd",
+ .owner = THIS_MODULE,
+ .of_match_table = of_anatop_match,
+ },
+ .probe = of_anatop_probe,
+ .remove = of_anatop_remove,
+};
+
+static int __init anatop_init(void)
+{
+ return platform_driver_register(&anatop_of_driver);
+}
+postcore_initcall(anatop_init);
+
+static void __exit anatop_exit(void)
+{
+ platform_driver_unregister(&anatop_of_driver);
+}
+module_exit(anatop_exit);
+
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_DESCRIPTION("ANATOP MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
new file mode 100644
index 0000000..22c1007
--- /dev/null
+++ b/include/linux/mfd/anatop.h
@@ -0,0 +1,40 @@
+/*
+ * anatop.h - Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_MFD_ANATOP_H
+#define __LINUX_MFD_ANATOP_H
+
+#include <linux/spinlock.h>
+
+/**
+ * anatop - MFD data
+ * @ioreg: ioremap register
+ * @reglock: spinlock for register read/write
+ */
+struct anatop {
+ void *ioreg;
+ spinlock_t reglock;
+};
+
+extern u32 anatop_get_bits(struct anatop *, u32, int, int);
+extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
+
+#endif /* __LINUX_MFD_ANATOP_H */
--
1.7.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 2/2] Regulator: Add Anatop regulator driver
2012-03-02 7:00 ` [PATCH v6 " Ying-Chun Liu (PaulLiu)
@ 2012-03-02 7:00 ` Ying-Chun Liu (PaulLiu)
2012-03-04 6:51 ` Shawn Guo
2012-03-02 7:07 ` [PATCH v6 1/2] mfd: Add anatop mfd driver Venu Byravarasu
` (2 subsequent siblings)
3 siblings, 1 reply; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-02 7:00 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Anatop is an integrated regulator inside i.MX6 SoC.
There are 3 digital regulators which controls PU, CORE (ARM), and SOC.
And 3 analog regulators which controls 1P1, 2P5, 3P0 (USB).
This patch adds the Anatop regulator driver.
Signed-off-by: Nancy Chen <Nancy.Chen@freescale.com>
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@ti.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
---
.../bindings/regulator/anatop-regulator.txt | 28 +++
drivers/regulator/Kconfig | 6 +
drivers/regulator/Makefile | 1 +
drivers/regulator/anatop-regulator.c | 205 ++++++++++++++++++++
include/linux/regulator/anatop-regulator.h | 40 ++++
5 files changed, 280 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/regulator/anatop-regulator.txt
create mode 100644 drivers/regulator/anatop-regulator.c
create mode 100644 include/linux/regulator/anatop-regulator.h
diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
new file mode 100644
index 0000000..f19cfea
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
@@ -0,0 +1,28 @@
+Anatop Voltage regulators
+
+Required properties:
+- compatible: Must be "fsl,anatop-regulator"
+- vol-bit-shift: Bit shift for the register
+- vol-bit-size: Number of bits used in the register
+- min-bit-val: Minimum value of this register
+- min-voltage: Minimum voltage of this regulator
+- max-voltage: Maximum voltage of this regulator
+
+Any property defined as part of the core regulator
+binding, defined in regulator.txt, can also be used.
+
+Example:
+
+ reg_vddpu: regulator-vddpu at 140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddpu";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ reg = <0x140 1>;
+ vol-bit-shift = <9>;
+ vol-bit-size = <5>;
+ min-bit-val = <1>;
+ min-voltage = <725000>;
+ max-voltage = <1300000>;
+ };
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7a61b17..5fbcda2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -335,5 +335,11 @@ config REGULATOR_AAT2870
If you have a AnalogicTech AAT2870 say Y to enable the
regulator driver.
+config REGULATOR_ANATOP
+ tristate "ANATOP LDO regulators"
+ depends on MFD_ANATOP
+ help
+ Say y here to support ANATOP LDOs regulators.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 503bac8..8440871 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,5 +48,6 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
+obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
new file mode 100644
index 0000000..84d8f50
--- /dev/null
+++ b/drivers/regulator/anatop-regulator.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regulator/of_regulator.h>
+
+static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ u32 val, sel;
+ int uv;
+
+ uv = min_uV;
+ dev_dbg(®->dev, "%s: uv %d, min %d, max %d\n", __func__,
+ uv, anatop_reg->min_voltage,
+ anatop_reg->max_voltage);
+
+ if (uv < anatop_reg->min_voltage) {
+ if (max_uV > anatop_reg->min_voltage)
+ uv = anatop_reg->min_voltage;
+ else
+ return -EINVAL;
+ }
+
+ if (anatop_reg->control_reg) {
+ sel = (uv - anatop_reg->min_voltage) / 25000;
+ if (sel * 25000 + anatop_reg->min_voltage
+ > anatop_reg->max_voltage)
+ return -EINVAL;
+ val = anatop_reg->min_bit_val + sel;
+ *selector = sel;
+ dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val);
+ anatop_set_bits(anatop_reg->mfd,
+ anatop_reg->control_reg,
+ anatop_reg->vol_bit_shift,
+ anatop_reg->vol_bit_size,
+ val);
+ return 0;
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int anatop_get_voltage_sel(struct regulator_dev *reg)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ int selector;
+
+ if (anatop_reg->control_reg) {
+ u32 val = anatop_get_bits(anatop_reg->mfd,
+ anatop_reg->control_reg,
+ anatop_reg->vol_bit_shift,
+ anatop_reg->vol_bit_size);
+ selector = val - anatop_reg->min_bit_val;
+ return selector;
+ } else {
+ return -ENOTSUPP;
+ }
+}
+
+static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+ int uv;
+
+ uv = anatop_reg->min_voltage + selector * 25000;
+ dev_dbg(®->dev, "vddio = %d, selector = %u\n", uv, selector);
+
+ return uv;
+}
+
+static struct regulator_ops anatop_rops = {
+ .set_voltage = anatop_set_voltage,
+ .get_voltage_sel = anatop_get_voltage_sel,
+ .list_voltage = anatop_list_voltage,
+};
+
+int anatop_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regulator_desc *rdesc;
+ struct regulator_dev *rdev;
+ struct anatop_regulator *sreg;
+ struct regulator_init_data *initdata;
+ struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
+ const __be32 *rval;
+ u64 ofsize;
+
+ initdata = of_get_regulator_init_data(dev, dev->of_node);
+ sreg = devm_kzalloc(dev, sizeof(struct anatop_regulator), GFP_KERNEL);
+ if (!sreg)
+ return -EINVAL;
+ rdesc = devm_kzalloc(dev, sizeof(struct regulator_desc), GFP_KERNEL);
+ if (!rdesc)
+ return -EINVAL;
+ sreg->initdata = initdata;
+ sreg->name = kstrdup(of_get_property(np, "regulator-name", NULL),
+ GFP_KERNEL);
+ sreg->regulator = rdesc;
+ memset(rdesc, 0, sizeof(struct regulator_desc));
+ rdesc->name = sreg->name;
+ rdesc->ops = &anatop_rops;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->owner = THIS_MODULE;
+ sreg->mfd = anatopmfd;
+ rval = of_get_address(np, 0, &ofsize, NULL);
+ if (rval)
+ sreg->control_reg = be32_to_cpu(*rval);
+ rval = of_get_property(np, "vol-bit-size", NULL);
+ if (rval)
+ sreg->vol_bit_size = be32_to_cpu(*rval);
+ rval = of_get_property(np, "vol-bit-shift", NULL);
+ if (rval)
+ sreg->vol_bit_shift = be32_to_cpu(*rval);
+ rval = of_get_property(np, "min-bit-val", NULL);
+ if (rval)
+ sreg->min_bit_val = be32_to_cpu(*rval);
+ rval = of_get_property(np, "min-voltage", NULL);
+ if (rval)
+ sreg->min_voltage = be32_to_cpu(*rval);
+ rval = of_get_property(np, "max-voltage", NULL);
+ if (rval)
+ sreg->max_voltage = be32_to_cpu(*rval);
+
+ /* register regulator */
+ rdev = regulator_register(rdesc, &pdev->dev,
+ initdata, sreg, pdev->dev.of_node);
+ platform_set_drvdata(pdev, rdev);
+
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ rdesc->name);
+ kfree(sreg->name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+int anatop_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
+ kfree(sreg->name);
+ regulator_unregister(rdev);
+ return 0;
+}
+
+struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { /* end */ }
+};
+
+struct platform_driver anatop_regulator = {
+ .driver = {
+ .name = "anatop_regulator",
+ .owner = THIS_MODULE,
+ .of_match_table = of_anatop_regulator_match_tbl,
+ },
+ .probe = anatop_regulator_probe,
+ .remove = anatop_regulator_remove,
+};
+
+int anatop_regulator_init(void)
+{
+ return platform_driver_register(&anatop_regulator);
+}
+postcore_initcall(anatop_regulator_init);
+
+void anatop_regulator_exit(void)
+{
+ platform_driver_unregister(&anatop_regulator);
+}
+module_exit(anatop_regulator_exit);
+
+MODULE_DESCRIPTION("ANATOP Regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/regulator/anatop-regulator.h b/include/linux/regulator/anatop-regulator.h
new file mode 100644
index 0000000..7a9a05b
--- /dev/null
+++ b/include/linux/regulator/anatop-regulator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ANATOP_REGULATOR_H
+#define __ANATOP_REGULATOR_H
+
+#include <linux/regulator/driver.h>
+#include <linux/mfd/anatop.h>
+
+struct anatop_regulator {
+ struct regulator_desc *regulator;
+ struct regulator_init_data *initdata;
+ const char *name;
+ u32 control_reg;
+ struct anatop *mfd;
+ int vol_bit_shift;
+ int vol_bit_size;
+ int min_bit_val;
+ int min_voltage;
+ int max_voltage;
+};
+
+#endif /* __ANATOP_REGULATOR_H */
--
1.7.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v6 2/2] Regulator: Add Anatop regulator driver
2012-03-02 7:00 ` [PATCH v6 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
@ 2012-03-04 6:51 ` Shawn Guo
2012-03-04 13:29 ` Mark Brown
0 siblings, 1 reply; 25+ messages in thread
From: Shawn Guo @ 2012-03-04 6:51 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Mar 02, 2012 at 03:00:41PM +0800, Ying-Chun Liu (PaulLiu) wrote:
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is an integrated regulator inside i.MX6 SoC.
> There are 3 digital regulators which controls PU, CORE (ARM), and SOC.
> And 3 analog regulators which controls 1P1, 2P5, 3P0 (USB).
> This patch adds the Anatop regulator driver.
>
> Signed-off-by: Nancy Chen <Nancy.Chen@freescale.com>
> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@ti.com>
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> ---
> .../bindings/regulator/anatop-regulator.txt | 28 +++
> drivers/regulator/Kconfig | 6 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/anatop-regulator.c | 205 ++++++++++++++++++++
> include/linux/regulator/anatop-regulator.h | 40 ++++
> 5 files changed, 280 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/regulator/anatop-regulator.txt
> create mode 100644 drivers/regulator/anatop-regulator.c
> create mode 100644 include/linux/regulator/anatop-regulator.h
>
> diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
> new file mode 100644
> index 0000000..f19cfea
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
> @@ -0,0 +1,28 @@
> +Anatop Voltage regulators
> +
> +Required properties:
> +- compatible: Must be "fsl,anatop-regulator"
> +- vol-bit-shift: Bit shift for the register
> +- vol-bit-size: Number of bits used in the register
A better name might be vol-bit-width, considering shift and width
are generally a couple.
> +- min-bit-val: Minimum value of this register
> +- min-voltage: Minimum voltage of this regulator
> +- max-voltage: Maximum voltage of this regulator
> +
> +Any property defined as part of the core regulator
> +binding, defined in regulator.txt, can also be used.
> +
> +Example:
> +
> + reg_vddpu: regulator-vddpu at 140 {
> + compatible = "fsl,anatop-regulator";
> + regulator-name = "vddpu";
> + regulator-min-microvolt = <725000>;
> + regulator-max-microvolt = <1300000>;
> + regulator-always-on;
> + reg = <0x140 1>;
The size cell is useless and confusing here. I think we can just have
it like "reg = <0x140>;".
> + vol-bit-shift = <9>;
> + vol-bit-size = <5>;
> + min-bit-val = <1>;
> + min-voltage = <725000>;
> + max-voltage = <1300000>;
> + };
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index 7a61b17..5fbcda2 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -335,5 +335,11 @@ config REGULATOR_AAT2870
> If you have a AnalogicTech AAT2870 say Y to enable the
> regulator driver.
>
> +config REGULATOR_ANATOP
> + tristate "ANATOP LDO regulators"
A more descriptive prompt?
> + depends on MFD_ANATOP
> + help
> + Say y here to support ANATOP LDOs regulators.
Ditto.
> +
> endif
>
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index 503bac8..8440871 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -48,5 +48,6 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
> obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
> obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
> obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
> +obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
>
> ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
> diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
> new file mode 100644
> index 0000000..84d8f50
> --- /dev/null
> +++ b/drivers/regulator/anatop-regulator.c
> @@ -0,0 +1,205 @@
> +/*
> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/anatop-regulator.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/regulator/of_regulator.h>
It may be good to have <linux/regulator/*> headers grouped/sorted
together, something like:
#include <linux/regulator/anatop-regulator.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
> +
> +static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
> + int max_uV, unsigned *selector)
> +{
> + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
> + u32 val, sel;
> + int uv;
> +
> + uv = min_uV;
> + dev_dbg(®->dev, "%s: uv %d, min %d, max %d\n", __func__,
> + uv, anatop_reg->min_voltage,
> + anatop_reg->max_voltage);
> +
> + if (uv < anatop_reg->min_voltage) {
> + if (max_uV > anatop_reg->min_voltage)
> + uv = anatop_reg->min_voltage;
> + else
> + return -EINVAL;
> + }
> +
> + if (anatop_reg->control_reg) {
> + sel = (uv - anatop_reg->min_voltage) / 25000;
> + if (sel * 25000 + anatop_reg->min_voltage
> + > anatop_reg->max_voltage)
> + return -EINVAL;
> + val = anatop_reg->min_bit_val + sel;
> + *selector = sel;
> + dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val);
> + anatop_set_bits(anatop_reg->mfd,
> + anatop_reg->control_reg,
> + anatop_reg->vol_bit_shift,
> + anatop_reg->vol_bit_size,
> + val);
> + return 0;
> + } else {
> + return -ENOTSUPP;
> + }
> +}
> +
> +static int anatop_get_voltage_sel(struct regulator_dev *reg)
> +{
> + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
> + int selector;
> +
> + if (anatop_reg->control_reg) {
> + u32 val = anatop_get_bits(anatop_reg->mfd,
> + anatop_reg->control_reg,
> + anatop_reg->vol_bit_shift,
> + anatop_reg->vol_bit_size);
> + selector = val - anatop_reg->min_bit_val;
> + return selector;
> + } else {
> + return -ENOTSUPP;
> + }
> +}
> +
> +static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
> +{
> + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
> + int uv;
> +
> + uv = anatop_reg->min_voltage + selector * 25000;
> + dev_dbg(®->dev, "vddio = %d, selector = %u\n", uv, selector);
> +
> + return uv;
> +}
> +
> +static struct regulator_ops anatop_rops = {
> + .set_voltage = anatop_set_voltage,
> + .get_voltage_sel = anatop_get_voltage_sel,
> + .list_voltage = anatop_list_voltage,
> +};
> +
> +int anatop_regulator_probe(struct platform_device *pdev)
static int __devinit
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct regulator_desc *rdesc;
> + struct regulator_dev *rdev;
> + struct anatop_regulator *sreg;
> + struct regulator_init_data *initdata;
> + struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
> + const __be32 *rval;
> + u64 ofsize;
> +
> + initdata = of_get_regulator_init_data(dev, dev->of_node);
You already have a variable np being dev->of_node.
> + sreg = devm_kzalloc(dev, sizeof(struct anatop_regulator), GFP_KERNEL);
> + if (!sreg)
> + return -EINVAL;
> + rdesc = devm_kzalloc(dev, sizeof(struct regulator_desc), GFP_KERNEL);
> + if (!rdesc)
> + return -EINVAL;
Would something like the following be better?
sreg = devm_kzalloc(dev, sizeof(*sreg) + sizeof(*rdesc), GFP_KERNEL);
if (!sreg)
return -ENOMEM;
rdesc = (struct regulator_desc *)(sreg + 1);
> + sreg->initdata = initdata;
> + sreg->name = kstrdup(of_get_property(np, "regulator-name", NULL),
> + GFP_KERNEL);
> + sreg->regulator = rdesc;
> + memset(rdesc, 0, sizeof(struct regulator_desc));
sizeof(*rdesc)
> + rdesc->name = sreg->name;
> + rdesc->ops = &anatop_rops;
> + rdesc->type = REGULATOR_VOLTAGE;
> + rdesc->owner = THIS_MODULE;
> + sreg->mfd = anatopmfd;
> + rval = of_get_address(np, 0, &ofsize, NULL);
> + if (rval)
> + sreg->control_reg = be32_to_cpu(*rval);
With size cell removed, we can just read the "reg" property as an u32
with helper function of_property_read_u32().
> + rval = of_get_property(np, "vol-bit-size", NULL);
> + if (rval)
> + sreg->vol_bit_size = be32_to_cpu(*rval);
> + rval = of_get_property(np, "vol-bit-shift", NULL);
> + if (rval)
> + sreg->vol_bit_shift = be32_to_cpu(*rval);
> + rval = of_get_property(np, "min-bit-val", NULL);
> + if (rval)
> + sreg->min_bit_val = be32_to_cpu(*rval);
> + rval = of_get_property(np, "min-voltage", NULL);
> + if (rval)
> + sreg->min_voltage = be32_to_cpu(*rval);
> + rval = of_get_property(np, "max-voltage", NULL);
> + if (rval)
> + sreg->max_voltage = be32_to_cpu(*rval);
All above can just use of_property_read_u32().
> +
> + /* register regulator */
> + rdev = regulator_register(rdesc, &pdev->dev,
> + initdata, sreg, pdev->dev.of_node);
> + platform_set_drvdata(pdev, rdev);
> +
> + if (IS_ERR(rdev)) {
> + dev_err(&pdev->dev, "failed to register %s\n",
> + rdesc->name);
> + kfree(sreg->name);
> + return PTR_ERR(rdev);
> + }
Shouldn't the error checking go right after regulator_register() call?
> +
> + return 0;
> +}
> +
> +int anatop_regulator_remove(struct platform_device *pdev)
static int __devexit
> +{
> + struct regulator_dev *rdev = platform_get_drvdata(pdev);
> + struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
> + kfree(sreg->name);
> + regulator_unregister(rdev);
> + return 0;
> +}
> +
> +struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
static
> + { .compatible = "fsl,anatop-regulator", },
> + { /* end */ }
> +};
> +
> +struct platform_driver anatop_regulator = {
static
> + .driver = {
> + .name = "anatop_regulator",
> + .owner = THIS_MODULE,
> + .of_match_table = of_anatop_regulator_match_tbl,
> + },
> + .probe = anatop_regulator_probe,
> + .remove = anatop_regulator_remove,
> +};
> +
> +int anatop_regulator_init(void)
static int __init
> +{
> + return platform_driver_register(&anatop_regulator);
> +}
> +postcore_initcall(anatop_regulator_init);
> +
> +void anatop_regulator_exit(void)
static void __exit
> +{
> + platform_driver_unregister(&anatop_regulator);
> +}
> +module_exit(anatop_regulator_exit);
> +
> +MODULE_DESCRIPTION("ANATOP Regulator driver");
> +MODULE_LICENSE("GPL v2");
MODULE_AUTHOR? Multiple people can be listed there.
> diff --git a/include/linux/regulator/anatop-regulator.h b/include/linux/regulator/anatop-regulator.h
> new file mode 100644
> index 0000000..7a9a05b
> --- /dev/null
> +++ b/include/linux/regulator/anatop-regulator.h
> @@ -0,0 +1,40 @@
> +/*
> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> +
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#ifndef __ANATOP_REGULATOR_H
> +#define __ANATOP_REGULATOR_H
> +
> +#include <linux/regulator/driver.h>
> +#include <linux/mfd/anatop.h>
> +
> +struct anatop_regulator {
> + struct regulator_desc *regulator;
> + struct regulator_init_data *initdata;
> + const char *name;
> + u32 control_reg;
> + struct anatop *mfd;
> + int vol_bit_shift;
> + int vol_bit_size;
> + int min_bit_val;
> + int min_voltage;
> + int max_voltage;
> +};
Does this structure really need to be public?
> +
> +#endif /* __ANATOP_REGULATOR_H */
> --
> 1.7.9.1
>
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v6 2/2] Regulator: Add Anatop regulator driver
2012-03-04 6:51 ` Shawn Guo
@ 2012-03-04 13:29 ` Mark Brown
0 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2012-03-04 13:29 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Mar 04, 2012 at 02:51:48PM +0800, Shawn Guo wrote:
> > + sreg = devm_kzalloc(dev, sizeof(struct anatop_regulator), GFP_KERNEL);
> > + if (!sreg)
> > + return -EINVAL;
> > + rdesc = devm_kzalloc(dev, sizeof(struct regulator_desc), GFP_KERNEL);
> > + if (!rdesc)
> > + return -EINVAL;
> Would something like the following be better?
> sreg = devm_kzalloc(dev, sizeof(*sreg) + sizeof(*rdesc), GFP_KERNEL);
> if (!sreg)
> return -ENOMEM;
> rdesc = (struct regulator_desc *)(sreg + 1);
No, that sort of pointer arithmetic would be much worse - it's harder to
read and more likely to break. However, embedding the regulator_desc in
sreg would achieve the same result without the legibility issues.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120304/81dfb3ad/attachment.sig>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v6 1/2] mfd: Add anatop mfd driver
2012-03-02 7:00 ` [PATCH v6 " Ying-Chun Liu (PaulLiu)
2012-03-02 7:00 ` [PATCH v6 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
@ 2012-03-02 7:07 ` Venu Byravarasu
2012-03-02 7:51 ` Ying-Chun Liu (PaulLiu)
2012-03-02 14:00 ` Peter Korsgaard
2012-03-03 17:39 ` [PATCH v7 " Ying-Chun Liu (PaulLiu)
3 siblings, 1 reply; 25+ messages in thread
From: Venu Byravarasu @ 2012-03-02 7:07 UTC (permalink / raw)
To: linux-arm-kernel
Why you did not made use of regmap?
> -----Original Message-----
> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
> owner at vger.kernel.org] On Behalf Of Ying-Chun Liu (PaulLiu)
> Sent: Friday, March 02, 2012 12:31 PM
> To: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org; linaro-dev at lists.linaro.org;
> patches at linaro.org; Ying-Chun Liu (PaulLiu); Samuel Ortiz; Mark Brown; Shawn
> Guo
> Subject: [PATCH v6 1/2] mfd: Add anatop mfd driver
>
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
> Anatop provides regulators and thermal.
> This driver handles the address space and the operation of the mfd device.
>
> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> ---
> drivers/mfd/Kconfig | 6 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/anatop-mfd.c | 142
> ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/anatop.h | 40 ++++++++++++
> 4 files changed, 189 insertions(+), 0 deletions(-)
> create mode 100644 drivers/mfd/anatop-mfd.c
> create mode 100644 include/linux/mfd/anatop.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index f147395..f787d17 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
> Passage) chip. This chip embeds audio, battery, GPIO, etc.
> devices used in Intel Medfield platforms.
>
> +config MFD_ANATOP
> + bool "Support for Anatop"
> + depends on SOC_IMX6Q
> + help
> + Select this option to enable Anatop MFD driver.
> +
> endmenu
> endif
>
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index b953bab..8e11060 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -112,3 +112,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) +=
> tps65911-comparator.o
> obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
> obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
> obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
> +obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
> diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
> new file mode 100644
> index 0000000..0307051
> --- /dev/null
> +++ b/drivers/mfd/anatop-mfd.c
> @@ -0,0 +1,142 @@
> +/*
> + * Anatop MFD driver
> + *
> + * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> + * Copyright (C) 2012 Linaro
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/mfd/anatop.h>
> +
> +u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, int bits)
> +{
> + u32 val;
> + int mask;
> +
> + if (bits == 32)
> + mask = ~0;
> + else
> + mask = (1 << bits) - 1;
> +
> + val = readl(adata->ioreg + addr);
> + val = (val >> bit_shift) & mask;
> +
> + return val;
> +}
> +EXPORT_SYMBOL(anatop_get_bits);
> +
> +void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
> + int bits, u32 data)
> +{
> + u32 val;
> + int mask;
> + if (bits == 32)
> + mask = ~0;
> + else
> + mask = (1 << bits) - 1;
> +
> + spin_lock(&adata->reglock);
> + val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
> + writel((data << bit_shift) | val, adata->ioreg);
> + spin_unlock(&adata->reglock);
> +}
> +EXPORT_SYMBOL(anatop_set_bits);
> +
> +static const struct of_device_id of_anatop_subdevice_match[] = {
> + { .compatible = "fsl,anatop-regulator", },
> + { .compatible = "fsl,anatop-thermal", },
> + { },
> +};
> +
> +static int of_anatop_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + void *ioreg;
> + struct anatop *drvdata;
> +
> + ioreg = of_iomap(np, 0);
> + if (!ioreg)
> + return -EINVAL;
> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
> + if (!drvdata)
> + return -EINVAL;
> + drvdata->ioreg = ioreg;
> + spin_lock_init(&drvdata->reglock);
> + platform_set_drvdata(pdev, drvdata);
> + of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
> +
> + return 0;
> +}
> +
> +static int of_anatop_remove(struct platform_device *pdev)
> +{
> + struct anatop *drvdata;
> + drvdata = platform_get_drvdata(pdev);
> + iounmap(drvdata->ioreg);
> + return 0;
> +}
> +
> +static const struct of_device_id of_anatop_match[] = {
> + { .compatible = "fsl,imx6q-anatop", },
> + { },
> +};
> +
> +static struct platform_driver anatop_of_driver = {
> + .driver = {
> + .name = "anatop-mfd",
> + .owner = THIS_MODULE,
> + .of_match_table = of_anatop_match,
> + },
> + .probe = of_anatop_probe,
> + .remove = of_anatop_remove,
> +};
> +
> +static int __init anatop_init(void)
> +{
> + return platform_driver_register(&anatop_of_driver);
> +}
> +postcore_initcall(anatop_init);
> +
> +static void __exit anatop_exit(void)
> +{
> + platform_driver_unregister(&anatop_of_driver);
> +}
> +module_exit(anatop_exit);
> +
> +MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
> +MODULE_DESCRIPTION("ANATOP MFD driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
> new file mode 100644
> index 0000000..22c1007
> --- /dev/null
> +++ b/include/linux/mfd/anatop.h
> @@ -0,0 +1,40 @@
> +/*
> + * anatop.h - Anatop MFD driver
> + *
> + * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> + * Copyright (C) 2012 Linaro
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#ifndef __LINUX_MFD_ANATOP_H
> +#define __LINUX_MFD_ANATOP_H
> +
> +#include <linux/spinlock.h>
> +
> +/**
> + * anatop - MFD data
> + * @ioreg: ioremap register
> + * @reglock: spinlock for register read/write
> + */
> +struct anatop {
> + void *ioreg;
> + spinlock_t reglock;
> +};
> +
> +extern u32 anatop_get_bits(struct anatop *, u32, int, int);
> +extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
> +
> +#endif /* __LINUX_MFD_ANATOP_H */
> --
> 1.7.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v6 1/2] mfd: Add anatop mfd driver
2012-03-02 7:07 ` [PATCH v6 1/2] mfd: Add anatop mfd driver Venu Byravarasu
@ 2012-03-02 7:51 ` Ying-Chun Liu (PaulLiu)
2012-03-02 8:02 ` Venu Byravarasu
0 siblings, 1 reply; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-02 7:51 UTC (permalink / raw)
To: linux-arm-kernel
(2012?03?02? 15:07), Venu Byravarasu wrote:
> Why you did not made use of regmap?
>
Hi Venu,
I cannot fully understand. Anatop is not SPI or I2C device. It is
internally embedded into the SoC. It is directly accessed by memory I/O.
Do you mean I should implement a regmap_bus which uses memory I/O and
then use regmap?
Regards,
Paul
>> -----Original Message-----
>> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
>> owner at vger.kernel.org] On Behalf Of Ying-Chun Liu (PaulLiu)
>> Sent: Friday, March 02, 2012 12:31 PM
>> To: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org; linaro-dev at lists.linaro.org;
>> patches at linaro.org; Ying-Chun Liu (PaulLiu); Samuel Ortiz; Mark Brown; Shawn
>> Guo
>> Subject: [PATCH v6 1/2] mfd: Add anatop mfd driver
>>
>> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>>
>> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
>> Anatop provides regulators and thermal.
>> This driver handles the address space and the operation of the mfd device.
>>
>> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
>> Cc: Samuel Ortiz <sameo@linux.intel.com>
>> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Cc: Shawn Guo <shawn.guo@linaro.org>
>> ---
>> drivers/mfd/Kconfig | 6 ++
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v6 1/2] mfd: Add anatop mfd driver
2012-03-02 7:00 ` [PATCH v6 " Ying-Chun Liu (PaulLiu)
2012-03-02 7:00 ` [PATCH v6 2/2] Regulator: Add Anatop regulator driver Ying-Chun Liu (PaulLiu)
2012-03-02 7:07 ` [PATCH v6 1/2] mfd: Add anatop mfd driver Venu Byravarasu
@ 2012-03-02 14:00 ` Peter Korsgaard
2012-03-03 17:39 ` [PATCH v7 " Ying-Chun Liu (PaulLiu)
3 siblings, 0 replies; 25+ messages in thread
From: Peter Korsgaard @ 2012-03-02 14:00 UTC (permalink / raw)
To: linux-arm-kernel
>>>>> "Y" == Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org> writes:
Hi,
Y> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Y> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
Y> Anatop provides regulators and thermal.
Y> This driver handles the address space and the operation of the mfd device.
Y> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Y> Cc: Samuel Ortiz <sameo@linux.intel.com>
Y> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Y> Cc: Shawn Guo <shawn.guo@linaro.org>
Y> ---
Y> drivers/mfd/Kconfig | 6 ++
Y> drivers/mfd/Makefile | 1 +
Y> drivers/mfd/anatop-mfd.c | 142 ++++++++++++++++++++++++++++++++++++++++++++
Y> include/linux/mfd/anatop.h | 40 ++++++++++++
Y> 4 files changed, 189 insertions(+), 0 deletions(-)
Y> create mode 100644 drivers/mfd/anatop-mfd.c
Y> create mode 100644 include/linux/mfd/anatop.h
Y> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
Y> index f147395..f787d17 100644
Y> --- a/drivers/mfd/Kconfig
Y> +++ b/drivers/mfd/Kconfig
Y> @@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
Y> Passage) chip. This chip embeds audio, battery, GPIO, etc.
Y> devices used in Intel Medfield platforms.
Y> +config MFD_ANATOP
Y> + bool "Support for Anatop"
Y> + depends on SOC_IMX6Q
The bool line should be indented with a <tab>, not spaces.
--
Bye, Peter Korsgaard
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v7 1/2] mfd: Add anatop mfd driver
2012-03-02 7:00 ` [PATCH v6 " Ying-Chun Liu (PaulLiu)
` (2 preceding siblings ...)
2012-03-02 14:00 ` Peter Korsgaard
@ 2012-03-03 17:39 ` Ying-Chun Liu (PaulLiu)
2012-03-03 17:58 ` Mark Brown
` (3 more replies)
3 siblings, 4 replies; 25+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2012-03-03 17:39 UTC (permalink / raw)
To: linux-arm-kernel
From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
Anatop provides regulators and thermal.
This driver handles the address space and the operation of the mfd device.
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Venu Byravarasu <vbyravarasu@nvidia.com>
Cc: Peter Korsgaard <jacmet@sunsite.dk>
---
drivers/mfd/Kconfig | 6 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/anatop-mfd.c | 142 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/anatop.h | 40 ++++++++++++
4 files changed, 189 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/anatop-mfd.c
create mode 100644 include/linux/mfd/anatop.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f147395..78593e8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
Passage) chip. This chip embeds audio, battery, GPIO, etc.
devices used in Intel Medfield platforms.
+config MFD_ANATOP
+ bool "Support for Anatop"
+ depends on SOC_IMX6Q
+ help
+ Select this option to enable Anatop MFD driver.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b953bab..8e11060 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -112,3 +112,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
+obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
new file mode 100644
index 0000000..0307051
--- /dev/null
+++ b/drivers/mfd/anatop-mfd.c
@@ -0,0 +1,142 @@
+/*
+ * Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/mfd/anatop.h>
+
+u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, int bits)
+{
+ u32 val;
+ int mask;
+
+ if (bits == 32)
+ mask = ~0;
+ else
+ mask = (1 << bits) - 1;
+
+ val = readl(adata->ioreg + addr);
+ val = (val >> bit_shift) & mask;
+
+ return val;
+}
+EXPORT_SYMBOL(anatop_get_bits);
+
+void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
+ int bits, u32 data)
+{
+ u32 val;
+ int mask;
+ if (bits == 32)
+ mask = ~0;
+ else
+ mask = (1 << bits) - 1;
+
+ spin_lock(&adata->reglock);
+ val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
+ writel((data << bit_shift) | val, adata->ioreg);
+ spin_unlock(&adata->reglock);
+}
+EXPORT_SYMBOL(anatop_set_bits);
+
+static const struct of_device_id of_anatop_subdevice_match[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { .compatible = "fsl,anatop-thermal", },
+ { },
+};
+
+static int of_anatop_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void *ioreg;
+ struct anatop *drvdata;
+
+ ioreg = of_iomap(np, 0);
+ if (!ioreg)
+ return -EINVAL;
+ drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
+ if (!drvdata)
+ return -EINVAL;
+ drvdata->ioreg = ioreg;
+ spin_lock_init(&drvdata->reglock);
+ platform_set_drvdata(pdev, drvdata);
+ of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
+
+ return 0;
+}
+
+static int of_anatop_remove(struct platform_device *pdev)
+{
+ struct anatop *drvdata;
+ drvdata = platform_get_drvdata(pdev);
+ iounmap(drvdata->ioreg);
+ return 0;
+}
+
+static const struct of_device_id of_anatop_match[] = {
+ { .compatible = "fsl,imx6q-anatop", },
+ { },
+};
+
+static struct platform_driver anatop_of_driver = {
+ .driver = {
+ .name = "anatop-mfd",
+ .owner = THIS_MODULE,
+ .of_match_table = of_anatop_match,
+ },
+ .probe = of_anatop_probe,
+ .remove = of_anatop_remove,
+};
+
+static int __init anatop_init(void)
+{
+ return platform_driver_register(&anatop_of_driver);
+}
+postcore_initcall(anatop_init);
+
+static void __exit anatop_exit(void)
+{
+ platform_driver_unregister(&anatop_of_driver);
+}
+module_exit(anatop_exit);
+
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_DESCRIPTION("ANATOP MFD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
new file mode 100644
index 0000000..22c1007
--- /dev/null
+++ b/include/linux/mfd/anatop.h
@@ -0,0 +1,40 @@
+/*
+ * anatop.h - Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_MFD_ANATOP_H
+#define __LINUX_MFD_ANATOP_H
+
+#include <linux/spinlock.h>
+
+/**
+ * anatop - MFD data
+ * @ioreg: ioremap register
+ * @reglock: spinlock for register read/write
+ */
+struct anatop {
+ void *ioreg;
+ spinlock_t reglock;
+};
+
+extern u32 anatop_get_bits(struct anatop *, u32, int, int);
+extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
+
+#endif /* __LINUX_MFD_ANATOP_H */
--
1.7.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v7 1/2] mfd: Add anatop mfd driver
2012-03-03 17:39 ` [PATCH v7 " Ying-Chun Liu (PaulLiu)
@ 2012-03-03 17:58 ` Mark Brown
2012-03-04 5:25 ` Shawn Guo
` (2 subsequent siblings)
3 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2012-03-03 17:58 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Mar 04, 2012 at 01:39:12AM +0800, Ying-Chun Liu (PaulLiu) wrote:
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
> Anatop provides regulators and thermal.
> This driver handles the address space and the operation of the mfd device.
Please stop sending new patches as followups to old versions, it tends
not to do the right thing in mail software.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120303/443de74e/attachment.sig>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v7 1/2] mfd: Add anatop mfd driver
2012-03-03 17:39 ` [PATCH v7 " Ying-Chun Liu (PaulLiu)
2012-03-03 17:58 ` Mark Brown
@ 2012-03-04 5:25 ` Shawn Guo
2012-03-04 5:42 ` Shawn Guo
2012-03-04 5:55 ` Shawn Guo
3 siblings, 0 replies; 25+ messages in thread
From: Shawn Guo @ 2012-03-04 5:25 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Mar 04, 2012 at 01:39:12AM +0800, Ying-Chun Liu (PaulLiu) wrote:
> From: "Ying-Chun Liu (PaulLiu)" <paul.liu@linaro.org>
>
> Anatop is a mfd chip embedded in Freescale i.MX6Q SoC.
> Anatop provides regulators and thermal.
> This driver handles the address space and the operation of the mfd device.
>
> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Shawn Guo <shawn.guo@linaro.org>
A few trivial comments below, otherwise
Acked-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Venu Byravarasu <vbyravarasu@nvidia.com>
> Cc: Peter Korsgaard <jacmet@sunsite.dk>
> ---
> drivers/mfd/Kconfig | 6 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/anatop-mfd.c | 142 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/anatop.h | 40 ++++++++++++
> 4 files changed, 189 insertions(+), 0 deletions(-)
> create mode 100644 drivers/mfd/anatop-mfd.c
> create mode 100644 include/linux/mfd/anatop.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index f147395..78593e8 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -830,6 +830,12 @@ config MFD_INTEL_MSIC
> Passage) chip. This chip embeds audio, battery, GPIO, etc.
> devices used in Intel Medfield platforms.
>
> +config MFD_ANATOP
> + bool "Support for Anatop"
It might worth a more descriptive prompt, something like
"Support Freescale i.MX on-chip ANATOP controller"?
> + depends on SOC_IMX6Q
> + help
> + Select this option to enable Anatop MFD driver.
Ditto, a more descriptive help?
> +
> endmenu
> endif
>
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index b953bab..8e11060 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -112,3 +112,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
> obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
> obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
> obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
> +obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o
> diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
> new file mode 100644
> index 0000000..0307051
> --- /dev/null
> +++ b/drivers/mfd/anatop-mfd.c
> @@ -0,0 +1,142 @@
> +/*
> + * Anatop MFD driver
> + *
> + * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> + * Copyright (C) 2012 Linaro
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/mfd/anatop.h>
> +
> +u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift, int bits)
> +{
> + u32 val;
> + int mask;
Shouldn't mask be also u32? Then "u32 val, mask;"?
> +
> + if (bits == 32)
> + mask = ~0;
> + else
> + mask = (1 << bits) - 1;
> +
> + val = readl(adata->ioreg + addr);
> + val = (val >> bit_shift) & mask;
> +
> + return val;
> +}
> +EXPORT_SYMBOL(anatop_get_bits);
> +
> +void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
> + int bits, u32 data)
> +{
> + u32 val;
> + int mask;
Ditto, with a blank line to be consistent with above function.
> + if (bits == 32)
> + mask = ~0;
> + else
> + mask = (1 << bits) - 1;
> +
> + spin_lock(&adata->reglock);
> + val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
> + writel((data << bit_shift) | val, adata->ioreg);
> + spin_unlock(&adata->reglock);
> +}
> +EXPORT_SYMBOL(anatop_set_bits);
> +
> +static const struct of_device_id of_anatop_subdevice_match[] = {
> + { .compatible = "fsl,anatop-regulator", },
> + { .compatible = "fsl,anatop-thermal", },
> + { },
> +};
> +
> +static int of_anatop_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + void *ioreg;
> + struct anatop *drvdata;
> +
> + ioreg = of_iomap(np, 0);
> + if (!ioreg)
> + return -EINVAL;
return -EADDRNOTAVAIL;
> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
> + if (!drvdata)
> + return -EINVAL;
return -ENOMEM;
The bonus point is we can know the failure cause from error number,
with no need of error message.
Regards,
Shawn
> + drvdata->ioreg = ioreg;
> + spin_lock_init(&drvdata->reglock);
> + platform_set_drvdata(pdev, drvdata);
> + of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
> +
> + return 0;
> +}
> +
> +static int of_anatop_remove(struct platform_device *pdev)
> +{
> + struct anatop *drvdata;
> + drvdata = platform_get_drvdata(pdev);
> + iounmap(drvdata->ioreg);
> + return 0;
> +}
> +
> +static const struct of_device_id of_anatop_match[] = {
> + { .compatible = "fsl,imx6q-anatop", },
> + { },
> +};
> +
> +static struct platform_driver anatop_of_driver = {
> + .driver = {
> + .name = "anatop-mfd",
> + .owner = THIS_MODULE,
> + .of_match_table = of_anatop_match,
> + },
> + .probe = of_anatop_probe,
> + .remove = of_anatop_remove,
> +};
> +
> +static int __init anatop_init(void)
> +{
> + return platform_driver_register(&anatop_of_driver);
> +}
> +postcore_initcall(anatop_init);
> +
> +static void __exit anatop_exit(void)
> +{
> + platform_driver_unregister(&anatop_of_driver);
> +}
> +module_exit(anatop_exit);
> +
> +MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
> +MODULE_DESCRIPTION("ANATOP MFD driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
> new file mode 100644
> index 0000000..22c1007
> --- /dev/null
> +++ b/include/linux/mfd/anatop.h
> @@ -0,0 +1,40 @@
> +/*
> + * anatop.h - Anatop MFD driver
> + *
> + * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> + * Copyright (C) 2012 Linaro
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#ifndef __LINUX_MFD_ANATOP_H
> +#define __LINUX_MFD_ANATOP_H
> +
> +#include <linux/spinlock.h>
> +
> +/**
> + * anatop - MFD data
> + * @ioreg: ioremap register
> + * @reglock: spinlock for register read/write
> + */
> +struct anatop {
> + void *ioreg;
> + spinlock_t reglock;
> +};
> +
> +extern u32 anatop_get_bits(struct anatop *, u32, int, int);
> +extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
> +
> +#endif /* __LINUX_MFD_ANATOP_H */
> --
> 1.7.9.1
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v7 1/2] mfd: Add anatop mfd driver
2012-03-03 17:39 ` [PATCH v7 " Ying-Chun Liu (PaulLiu)
2012-03-03 17:58 ` Mark Brown
2012-03-04 5:25 ` Shawn Guo
@ 2012-03-04 5:42 ` Shawn Guo
2012-03-04 5:55 ` Shawn Guo
3 siblings, 0 replies; 25+ messages in thread
From: Shawn Guo @ 2012-03-04 5:42 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Mar 04, 2012 at 01:39:12AM +0800, Ying-Chun Liu (PaulLiu) wrote:
...
> +static int of_anatop_probe(struct platform_device *pdev)
__devinit
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + void *ioreg;
> + struct anatop *drvdata;
> +
> + ioreg = of_iomap(np, 0);
> + if (!ioreg)
> + return -EINVAL;
> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
> + if (!drvdata)
> + return -EINVAL;
> + drvdata->ioreg = ioreg;
> + spin_lock_init(&drvdata->reglock);
> + platform_set_drvdata(pdev, drvdata);
> + of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
> +
> + return 0;
> +}
> +
> +static int of_anatop_remove(struct platform_device *pdev)
__devexit
> +{
> + struct anatop *drvdata;
> + drvdata = platform_get_drvdata(pdev);
> + iounmap(drvdata->ioreg);
> + return 0;
> +}
> +
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v7 1/2] mfd: Add anatop mfd driver
2012-03-03 17:39 ` [PATCH v7 " Ying-Chun Liu (PaulLiu)
` (2 preceding siblings ...)
2012-03-04 5:42 ` Shawn Guo
@ 2012-03-04 5:55 ` Shawn Guo
3 siblings, 0 replies; 25+ messages in thread
From: Shawn Guo @ 2012-03-04 5:55 UTC (permalink / raw)
To: linux-arm-kernel
Sorry, one more missing ...
On Sun, Mar 04, 2012 at 01:39:12AM +0800, Ying-Chun Liu (PaulLiu) wrote:
...
> +static int of_anatop_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + void *ioreg;
> + struct anatop *drvdata;
> +
> + ioreg = of_iomap(np, 0);
> + if (!ioreg)
> + return -EINVAL;
> + drvdata = devm_kzalloc(dev, sizeof(struct anatop), GFP_KERNEL);
sizeof(*drvdata) please.
Documentation/CodingStyle, Chapter 14:
The preferred form for passing a size of a struct is the following:
p = kmalloc(sizeof(*p), ...);
The alternative form where struct name is spelled out hurts readability and
introduces an opportunity for a bug when the pointer variable type is changed
but the corresponding sizeof that is passed to a memory allocator is not.
> + if (!drvdata)
> + return -EINVAL;
> + drvdata->ioreg = ioreg;
> + spin_lock_init(&drvdata->reglock);
> + platform_set_drvdata(pdev, drvdata);
> + of_platform_bus_probe(np, of_anatop_subdevice_match, dev);
> +
> + return 0;
> +}
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 25+ messages in thread