* [PATCH v3 1/4] iio: adc: add NXP LPC18xx ADC driver
2016-03-12 12:30 [PATCH v3 0/4] Support for analog peripherals on LPC18xx familiy Joachim Eastwood
@ 2016-03-12 12:30 ` Joachim Eastwood
2016-03-12 18:14 ` Jonathan Cameron
2016-03-12 12:30 ` [PATCH v3 2/4] dt: document NXP LPC1850 ADC driver bindings Joachim Eastwood
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Joachim Eastwood @ 2016-03-12 12:30 UTC (permalink / raw)
To: jic23
Cc: Joachim Eastwood, knaack.h, lars, pmeerw, linux-iio, robh+dt,
devicetree
Add base support for the 10-bit SAR ADC peripheral found
on NXP LPC18xx/43xx SoCs.
This is a minimal driver that does not support burst mode,
interrupts, DMA or hardware triggers.
User manual with register description can be found on:
LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf
LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
drivers/iio/adc/Kconfig | 10 ++
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/lpc18xx_adc.c | 231 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 242 insertions(+)
create mode 100644 drivers/iio/adc/lpc18xx_adc.c
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a8819a08a828..9ddcd5db039b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -235,6 +235,16 @@ config LP8788_ADC
To compile this driver as a module, choose M here: the module will be
called lp8788_adc.
+config LPC18XX_ADC
+ tristate "NXP LPC18xx ADC driver"
+ depends on ARCH_LPC18XX || COMPILE_TEST
+ depends on OF && HAS_IOMEM
+ help
+ Say yes here to build support for NXP LPC18XX ADC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called lpc18xx_adc.
+
config MAX1027
tristate "Maxim max1027 ADC driver"
depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index b1aa456e6af3..1a4ac4590857 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c
new file mode 100644
index 000000000000..3ef18f4b27f0
--- /dev/null
+++ b/drivers/iio/adc/lpc18xx_adc.c
@@ -0,0 +1,231 @@
+/*
+ * IIO ADC driver for NXP LPC18xx ADC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ * - Hardware triggers
+ * - Burst mode
+ * - Interrupts
+ * - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX ADC registers and bits */
+#define LPC18XX_ADC_CR 0x000
+#define LPC18XX_ADC_CR_CLKDIV_SHIFT 8
+#define LPC18XX_ADC_CR_PDN BIT(21)
+#define LPC18XX_ADC_CR_START_NOW (0x1 << 24)
+#define LPC18XX_ADC_GDR 0x004
+
+/* Data register bits */
+#define LPC18XX_ADC_SAMPLE_SHIFT 6
+#define LPC18XX_ADC_SAMPLE_MASK 0x3ff
+#define LPC18XX_ADC_CONV_DONE BIT(31)
+
+/* Clock should be 4.5 MHz or less */
+#define LPC18XX_ADC_CLK_TARGET 4500000
+
+struct lpc18xx_adc {
+ struct regulator *vref;
+ void __iomem *base;
+ struct device *dev;
+ struct mutex lock;
+ struct clk *clk;
+ u32 cr_reg;
+};
+
+#define LPC18XX_ADC_CHAN(_idx) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = _idx, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
+ LPC18XX_ADC_CHAN(0),
+ LPC18XX_ADC_CHAN(1),
+ LPC18XX_ADC_CHAN(2),
+ LPC18XX_ADC_CHAN(3),
+ LPC18XX_ADC_CHAN(4),
+ LPC18XX_ADC_CHAN(5),
+ LPC18XX_ADC_CHAN(6),
+ LPC18XX_ADC_CHAN(7),
+};
+
+static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
+{
+ int ret;
+ u32 reg;
+
+ reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
+ writel(reg, adc->base + LPC18XX_ADC_CR);
+
+ ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
+ reg & LPC18XX_ADC_CONV_DONE, 3, 9);
+ if (ret) {
+ dev_warn(adc->dev, "adc read timed out\n");
+ return ret;
+ }
+
+ return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
+}
+
+static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&adc->lock);
+ *val = lpc18xx_adc_read_chan(adc, chan->channel);
+ mutex_unlock(&adc->lock);
+ if (*val < 0)
+ return *val;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = regulator_get_voltage(adc->vref) / 1000;
+ *val2 = 10;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_adc_info = {
+ .read_raw = lpc18xx_adc_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_adc_probe(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev;
+ struct lpc18xx_adc *adc;
+ struct resource *res;
+ unsigned int clkdiv;
+ unsigned long rate;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, indio_dev);
+ adc = iio_priv(indio_dev);
+ adc->dev = &pdev->dev;
+ mutex_init(&adc->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ adc->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(adc->base))
+ return PTR_ERR(adc->base);
+
+ adc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(adc->clk)) {
+ dev_err(&pdev->dev, "error getting clock\n");
+ return PTR_ERR(adc->clk);
+ }
+
+ rate = clk_get_rate(adc->clk);
+ clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
+
+ adc->vref = devm_regulator_get(&pdev->dev, "vref");
+ if (IS_ERR(adc->vref)) {
+ dev_err(&pdev->dev, "error getting regulator\n");
+ return PTR_ERR(adc->vref);
+ }
+
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->info = &lpc18xx_adc_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = lpc18xx_adc_iio_channels;
+ indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
+
+ ret = regulator_enable(adc->vref);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable regulator\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(adc->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable clock\n");
+ goto dis_reg;
+ }
+
+ adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
+ LPC18XX_ADC_CR_PDN;
+ writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to register device\n");
+ goto dis_clk;
+ }
+
+ return 0;
+
+dis_clk:
+ writel(0, adc->base + LPC18XX_ADC_CR);
+ clk_disable_unprepare(adc->clk);
+dis_reg:
+ regulator_disable(adc->vref);
+ return ret;
+}
+
+static int lpc18xx_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ writel(0, adc->base + LPC18XX_ADC_CR);
+ clk_disable_unprepare(adc->clk);
+ regulator_disable(adc->vref);
+
+ return 0;
+}
+
+static const struct of_device_id lpc18xx_adc_match[] = {
+ { .compatible = "nxp,lpc1850-adc" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
+
+static struct platform_driver lpc18xx_adc_driver = {
+ .probe = lpc18xx_adc_probe,
+ .remove = lpc18xx_adc_remove,
+ .driver = {
+ .name = "lpc18xx-adc",
+ .of_match_table = lpc18xx_adc_match,
+ },
+};
+module_platform_driver(lpc18xx_adc_driver);
+
+MODULE_DESCRIPTION("LPC18xx ADC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
--
1.8.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v3 1/4] iio: adc: add NXP LPC18xx ADC driver
2016-03-12 12:30 ` [PATCH v3 1/4] iio: adc: add NXP LPC18xx ADC driver Joachim Eastwood
@ 2016-03-12 18:14 ` Jonathan Cameron
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2016-03-12 18:14 UTC (permalink / raw)
To: Joachim Eastwood; +Cc: knaack.h, lars, pmeerw, linux-iio, robh+dt, devicetree
On 12/03/16 12:30, Joachim Eastwood wrote:
> Add base support for the 10-bit SAR ADC peripheral found
> on NXP LPC18xx/43xx SoCs.
>
> This is a minimal driver that does not support burst mode,
> interrupts, DMA or hardware triggers.
>
> User manual with register description can be found on:
> LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf
> LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf
>
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Applied to the togreg branch of iio.git - initially pushed out as
testing for the autobuilders to play with it.
Thanks,
Jonathan
> ---
> drivers/iio/adc/Kconfig | 10 ++
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/lpc18xx_adc.c | 231 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 242 insertions(+)
> create mode 100644 drivers/iio/adc/lpc18xx_adc.c
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index a8819a08a828..9ddcd5db039b 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -235,6 +235,16 @@ config LP8788_ADC
> To compile this driver as a module, choose M here: the module will be
> called lp8788_adc.
>
> +config LPC18XX_ADC
> + tristate "NXP LPC18xx ADC driver"
> + depends on ARCH_LPC18XX || COMPILE_TEST
> + depends on OF && HAS_IOMEM
> + help
> + Say yes here to build support for NXP LPC18XX ADC.
> +
> + To compile this driver as a module, choose M here: the module will be
> + called lpc18xx_adc.
> +
> config MAX1027
> tristate "Maxim max1027 ADC driver"
> depends on SPI
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index b1aa456e6af3..1a4ac4590857 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
> obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
> obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
> obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
> +obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
> obj-$(CONFIG_MAX1027) += max1027.o
> obj-$(CONFIG_MAX1363) += max1363.o
> obj-$(CONFIG_MCP320X) += mcp320x.o
> diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c
> new file mode 100644
> index 000000000000..3ef18f4b27f0
> --- /dev/null
> +++ b/drivers/iio/adc/lpc18xx_adc.c
> @@ -0,0 +1,231 @@
> +/*
> + * IIO ADC driver for NXP LPC18xx ADC
> + *
> + * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * UNSUPPORTED hardware features:
> + * - Hardware triggers
> + * - Burst mode
> + * - Interrupts
> + * - DMA
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/driver.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +/* LPC18XX ADC registers and bits */
> +#define LPC18XX_ADC_CR 0x000
> +#define LPC18XX_ADC_CR_CLKDIV_SHIFT 8
> +#define LPC18XX_ADC_CR_PDN BIT(21)
> +#define LPC18XX_ADC_CR_START_NOW (0x1 << 24)
> +#define LPC18XX_ADC_GDR 0x004
> +
> +/* Data register bits */
> +#define LPC18XX_ADC_SAMPLE_SHIFT 6
> +#define LPC18XX_ADC_SAMPLE_MASK 0x3ff
> +#define LPC18XX_ADC_CONV_DONE BIT(31)
> +
> +/* Clock should be 4.5 MHz or less */
> +#define LPC18XX_ADC_CLK_TARGET 4500000
> +
> +struct lpc18xx_adc {
> + struct regulator *vref;
> + void __iomem *base;
> + struct device *dev;
> + struct mutex lock;
> + struct clk *clk;
> + u32 cr_reg;
> +};
> +
> +#define LPC18XX_ADC_CHAN(_idx) { \
> + .type = IIO_VOLTAGE, \
> + .indexed = 1, \
> + .channel = _idx, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> +}
> +
> +static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
> + LPC18XX_ADC_CHAN(0),
> + LPC18XX_ADC_CHAN(1),
> + LPC18XX_ADC_CHAN(2),
> + LPC18XX_ADC_CHAN(3),
> + LPC18XX_ADC_CHAN(4),
> + LPC18XX_ADC_CHAN(5),
> + LPC18XX_ADC_CHAN(6),
> + LPC18XX_ADC_CHAN(7),
> +};
> +
> +static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
> +{
> + int ret;
> + u32 reg;
> +
> + reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
> + writel(reg, adc->base + LPC18XX_ADC_CR);
> +
> + ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
> + reg & LPC18XX_ADC_CONV_DONE, 3, 9);
> + if (ret) {
> + dev_warn(adc->dev, "adc read timed out\n");
> + return ret;
> + }
> +
> + return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
> +}
> +
> +static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct lpc18xx_adc *adc = iio_priv(indio_dev);
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + mutex_lock(&adc->lock);
> + *val = lpc18xx_adc_read_chan(adc, chan->channel);
> + mutex_unlock(&adc->lock);
> + if (*val < 0)
> + return *val;
> +
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_SCALE:
> + *val = regulator_get_voltage(adc->vref) / 1000;
> + *val2 = 10;
> +
> + return IIO_VAL_FRACTIONAL_LOG2;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static const struct iio_info lpc18xx_adc_info = {
> + .read_raw = lpc18xx_adc_read_raw,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int lpc18xx_adc_probe(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev;
> + struct lpc18xx_adc *adc;
> + struct resource *res;
> + unsigned int clkdiv;
> + unsigned long rate;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, indio_dev);
> + adc = iio_priv(indio_dev);
> + adc->dev = &pdev->dev;
> + mutex_init(&adc->lock);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + adc->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(adc->base))
> + return PTR_ERR(adc->base);
> +
> + adc->clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(adc->clk)) {
> + dev_err(&pdev->dev, "error getting clock\n");
> + return PTR_ERR(adc->clk);
> + }
> +
> + rate = clk_get_rate(adc->clk);
> + clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
> +
> + adc->vref = devm_regulator_get(&pdev->dev, "vref");
> + if (IS_ERR(adc->vref)) {
> + dev_err(&pdev->dev, "error getting regulator\n");
> + return PTR_ERR(adc->vref);
> + }
> +
> + indio_dev->name = dev_name(&pdev->dev);
> + indio_dev->dev.parent = &pdev->dev;
> + indio_dev->info = &lpc18xx_adc_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = lpc18xx_adc_iio_channels;
> + indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
> +
> + ret = regulator_enable(adc->vref);
> + if (ret) {
> + dev_err(&pdev->dev, "unable to enable regulator\n");
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(adc->clk);
> + if (ret) {
> + dev_err(&pdev->dev, "unable to enable clock\n");
> + goto dis_reg;
> + }
> +
> + adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
> + LPC18XX_ADC_CR_PDN;
> + writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "unable to register device\n");
> + goto dis_clk;
> + }
> +
> + return 0;
> +
> +dis_clk:
> + writel(0, adc->base + LPC18XX_ADC_CR);
> + clk_disable_unprepare(adc->clk);
> +dis_reg:
> + regulator_disable(adc->vref);
> + return ret;
> +}
> +
> +static int lpc18xx_adc_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct lpc18xx_adc *adc = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + writel(0, adc->base + LPC18XX_ADC_CR);
> + clk_disable_unprepare(adc->clk);
> + regulator_disable(adc->vref);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id lpc18xx_adc_match[] = {
> + { .compatible = "nxp,lpc1850-adc" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
> +
> +static struct platform_driver lpc18xx_adc_driver = {
> + .probe = lpc18xx_adc_probe,
> + .remove = lpc18xx_adc_remove,
> + .driver = {
> + .name = "lpc18xx-adc",
> + .of_match_table = lpc18xx_adc_match,
> + },
> +};
> +module_platform_driver(lpc18xx_adc_driver);
> +
> +MODULE_DESCRIPTION("LPC18xx ADC driver");
> +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 2/4] dt: document NXP LPC1850 ADC driver bindings
2016-03-12 12:30 [PATCH v3 0/4] Support for analog peripherals on LPC18xx familiy Joachim Eastwood
2016-03-12 12:30 ` [PATCH v3 1/4] iio: adc: add NXP LPC18xx ADC driver Joachim Eastwood
@ 2016-03-12 12:30 ` Joachim Eastwood
2016-03-12 18:15 ` Jonathan Cameron
2016-03-12 12:30 ` [PATCH v3 3/4] iio: dac: add NXP LPC18xx DAC driver Joachim Eastwood
2016-03-12 12:30 ` [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings Joachim Eastwood
3 siblings, 1 reply; 11+ messages in thread
From: Joachim Eastwood @ 2016-03-12 12:30 UTC (permalink / raw)
To: jic23
Cc: Joachim Eastwood, knaack.h, lars, pmeerw, linux-iio, robh+dt,
devicetree
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
.../devicetree/bindings/iio/adc/lpc1850-adc.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
diff --git a/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
new file mode 100644
index 000000000000..0bcae5140bc5
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
@@ -0,0 +1,21 @@
+NXP LPC1850 ADC bindings
+
+Required properties:
+- compatible: Should be "nxp,lpc1850-adc"
+- reg: Offset and length of the register set for the ADC device
+- interrupts: The interrupt number for the ADC device
+- clocks: The root clock of the ADC controller
+- vref-supply: The regulator supply ADC reference voltage
+- resets: phandle to reset controller and line specifier
+
+Example:
+
+adc0: adc@400e3000 {
+ compatible = "nxp,lpc1850-adc";
+ reg = <0x400e3000 0x1000>;
+ interrupts = <17>;
+ clocks = <&ccu1 CLK_APB3_ADC0>;
+ vref-supply = <®_vdda>;
+ resets = <&rgu 40>;
+ status = "disabled";
+};
--
1.8.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v3 2/4] dt: document NXP LPC1850 ADC driver bindings
2016-03-12 12:30 ` [PATCH v3 2/4] dt: document NXP LPC1850 ADC driver bindings Joachim Eastwood
@ 2016-03-12 18:15 ` Jonathan Cameron
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2016-03-12 18:15 UTC (permalink / raw)
To: Joachim Eastwood; +Cc: knaack.h, lars, pmeerw, linux-iio, robh+dt, devicetree
On 12/03/16 12:30, Joachim Eastwood wrote:
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Applied.
> ---
> .../devicetree/bindings/iio/adc/lpc1850-adc.txt | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
> new file mode 100644
> index 000000000000..0bcae5140bc5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
> @@ -0,0 +1,21 @@
> +NXP LPC1850 ADC bindings
> +
> +Required properties:
> +- compatible: Should be "nxp,lpc1850-adc"
> +- reg: Offset and length of the register set for the ADC device
> +- interrupts: The interrupt number for the ADC device
> +- clocks: The root clock of the ADC controller
> +- vref-supply: The regulator supply ADC reference voltage
> +- resets: phandle to reset controller and line specifier
> +
> +Example:
> +
> +adc0: adc@400e3000 {
> + compatible = "nxp,lpc1850-adc";
> + reg = <0x400e3000 0x1000>;
> + interrupts = <17>;
> + clocks = <&ccu1 CLK_APB3_ADC0>;
> + vref-supply = <®_vdda>;
> + resets = <&rgu 40>;
> + status = "disabled";
> +};
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 3/4] iio: dac: add NXP LPC18xx DAC driver
2016-03-12 12:30 [PATCH v3 0/4] Support for analog peripherals on LPC18xx familiy Joachim Eastwood
2016-03-12 12:30 ` [PATCH v3 1/4] iio: adc: add NXP LPC18xx ADC driver Joachim Eastwood
2016-03-12 12:30 ` [PATCH v3 2/4] dt: document NXP LPC1850 ADC driver bindings Joachim Eastwood
@ 2016-03-12 12:30 ` Joachim Eastwood
2016-03-12 18:15 ` Jonathan Cameron
2016-03-12 12:30 ` [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings Joachim Eastwood
3 siblings, 1 reply; 11+ messages in thread
From: Joachim Eastwood @ 2016-03-12 12:30 UTC (permalink / raw)
To: jic23
Cc: Joachim Eastwood, knaack.h, lars, pmeerw, linux-iio, robh+dt,
devicetree
Add base support for the 10-bit DAC peripheral found
on NXP LPC18xx/43xx SoCs.
This is a minimal driver that does not support DMA or
interrupts.
User manual with register description can be found on:
LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf
LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
drivers/iio/dac/Kconfig | 10 ++
drivers/iio/dac/Makefile | 1 +
drivers/iio/dac/lpc18xx_dac.c | 210 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 221 insertions(+)
create mode 100644 drivers/iio/dac/lpc18xx_dac.c
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index a995139f907c..210db81ca144 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -154,6 +154,16 @@ config AD7303
To compile this driver as module choose M here: the module will be called
ad7303.
+config LPC18XX_DAC
+ tristate "NXP LPC18xx DAC driver"
+ depends on ARCH_LPC18XX || COMPILE_TEST
+ depends on OF && HAS_IOMEM
+ help
+ Say yes here to build support for NXP LPC18XX DAC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called lpc18xx_dac.
+
config M62332
tristate "Mitsubishi M62332 DAC driver"
depends on I2C
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 67b48429686d..420a15cdaa53 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
obj-$(CONFIG_M62332) += m62332.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MAX5821) += max5821.o
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
new file mode 100644
index 000000000000..55d1456a059d
--- /dev/null
+++ b/drivers/iio/dac/lpc18xx_dac.c
@@ -0,0 +1,210 @@
+/*
+ * IIO DAC driver for NXP LPC18xx DAC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ * - Interrupts
+ * - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX DAC registers and bits */
+#define LPC18XX_DAC_CR 0x000
+#define LPC18XX_DAC_CR_VALUE_SHIFT 6
+#define LPC18XX_DAC_CR_VALUE_MASK 0x3ff
+#define LPC18XX_DAC_CR_BIAS BIT(16)
+#define LPC18XX_DAC_CTRL 0x004
+#define LPC18XX_DAC_CTRL_DMA_ENA BIT(3)
+
+struct lpc18xx_dac {
+ struct regulator *vref;
+ void __iomem *base;
+ struct mutex lock;
+ struct clk *clk;
+};
+
+static const struct iio_chan_spec lpc18xx_dac_iio_channels[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .output = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static int lpc18xx_dac_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct lpc18xx_dac *dac = iio_priv(indio_dev);
+ u32 reg;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ reg = readl(dac->base + LPC18XX_DAC_CR);
+ *val = reg >> LPC18XX_DAC_CR_VALUE_SHIFT;
+ *val &= LPC18XX_DAC_CR_VALUE_MASK;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = regulator_get_voltage(dac->vref) / 1000;
+ *val2 = 10;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ }
+
+ return -EINVAL;
+}
+
+static int lpc18xx_dac_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct lpc18xx_dac *dac = iio_priv(indio_dev);
+ u32 reg;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (val < 0 || val > LPC18XX_DAC_CR_VALUE_MASK)
+ return -EINVAL;
+
+ reg = LPC18XX_DAC_CR_BIAS;
+ reg |= val << LPC18XX_DAC_CR_VALUE_SHIFT;
+
+ mutex_lock(&dac->lock);
+ writel(reg, dac->base + LPC18XX_DAC_CR);
+ writel(LPC18XX_DAC_CTRL_DMA_ENA, dac->base + LPC18XX_DAC_CTRL);
+ mutex_unlock(&dac->lock);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_dac_info = {
+ .read_raw = lpc18xx_dac_read_raw,
+ .write_raw = lpc18xx_dac_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_dac_probe(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev;
+ struct lpc18xx_dac *dac;
+ struct resource *res;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, indio_dev);
+ dac = iio_priv(indio_dev);
+ mutex_init(&dac->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dac->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dac->base))
+ return PTR_ERR(dac->base);
+
+ dac->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dac->clk)) {
+ dev_err(&pdev->dev, "error getting clock\n");
+ return PTR_ERR(dac->clk);
+ }
+
+ dac->vref = devm_regulator_get(&pdev->dev, "vref");
+ if (IS_ERR(dac->vref)) {
+ dev_err(&pdev->dev, "error getting regulator\n");
+ return PTR_ERR(dac->vref);
+ }
+
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->info = &lpc18xx_dac_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = lpc18xx_dac_iio_channels;
+ indio_dev->num_channels = ARRAY_SIZE(lpc18xx_dac_iio_channels);
+
+ ret = regulator_enable(dac->vref);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable regulator\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(dac->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable clock\n");
+ goto dis_reg;
+ }
+
+ writel(0, dac->base + LPC18XX_DAC_CTRL);
+ writel(0, dac->base + LPC18XX_DAC_CR);
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to register device\n");
+ goto dis_clk;
+ }
+
+ return 0;
+
+dis_clk:
+ clk_disable_unprepare(dac->clk);
+dis_reg:
+ regulator_disable(dac->vref);
+ return ret;
+}
+
+static int lpc18xx_dac_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct lpc18xx_dac *dac = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ writel(0, dac->base + LPC18XX_DAC_CTRL);
+ clk_disable_unprepare(dac->clk);
+ regulator_disable(dac->vref);
+
+ return 0;
+}
+
+static const struct of_device_id lpc18xx_dac_match[] = {
+ { .compatible = "nxp,lpc1850-dac" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
+
+static struct platform_driver lpc18xx_dac_driver = {
+ .probe = lpc18xx_dac_probe,
+ .remove = lpc18xx_dac_remove,
+ .driver = {
+ .name = "lpc18xx-dac",
+ .of_match_table = lpc18xx_dac_match,
+ },
+};
+module_platform_driver(lpc18xx_dac_driver);
+
+MODULE_DESCRIPTION("LPC18xx DAC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
--
1.8.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v3 3/4] iio: dac: add NXP LPC18xx DAC driver
2016-03-12 12:30 ` [PATCH v3 3/4] iio: dac: add NXP LPC18xx DAC driver Joachim Eastwood
@ 2016-03-12 18:15 ` Jonathan Cameron
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2016-03-12 18:15 UTC (permalink / raw)
To: Joachim Eastwood; +Cc: knaack.h, lars, pmeerw, linux-iio, robh+dt, devicetree
On 12/03/16 12:30, Joachim Eastwood wrote:
> Add base support for the 10-bit DAC peripheral found
> on NXP LPC18xx/43xx SoCs.
>
> This is a minimal driver that does not support DMA or
> interrupts.
>
> User manual with register description can be found on:
> LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf
> LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf
>
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Applied.
> ---
> drivers/iio/dac/Kconfig | 10 ++
> drivers/iio/dac/Makefile | 1 +
> drivers/iio/dac/lpc18xx_dac.c | 210 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 221 insertions(+)
> create mode 100644 drivers/iio/dac/lpc18xx_dac.c
>
> diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
> index a995139f907c..210db81ca144 100644
> --- a/drivers/iio/dac/Kconfig
> +++ b/drivers/iio/dac/Kconfig
> @@ -154,6 +154,16 @@ config AD7303
> To compile this driver as module choose M here: the module will be called
> ad7303.
>
> +config LPC18XX_DAC
> + tristate "NXP LPC18xx DAC driver"
> + depends on ARCH_LPC18XX || COMPILE_TEST
> + depends on OF && HAS_IOMEM
> + help
> + Say yes here to build support for NXP LPC18XX DAC.
> +
> + To compile this driver as a module, choose M here: the module will be
> + called lpc18xx_dac.
> +
> config M62332
> tristate "Mitsubishi M62332 DAC driver"
> depends on I2C
> diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
> index 67b48429686d..420a15cdaa53 100644
> --- a/drivers/iio/dac/Makefile
> +++ b/drivers/iio/dac/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
> obj-$(CONFIG_AD5791) += ad5791.o
> obj-$(CONFIG_AD5686) += ad5686.o
> obj-$(CONFIG_AD7303) += ad7303.o
> +obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
> obj-$(CONFIG_M62332) += m62332.o
> obj-$(CONFIG_MAX517) += max517.o
> obj-$(CONFIG_MAX5821) += max5821.o
> diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
> new file mode 100644
> index 000000000000..55d1456a059d
> --- /dev/null
> +++ b/drivers/iio/dac/lpc18xx_dac.c
> @@ -0,0 +1,210 @@
> +/*
> + * IIO DAC driver for NXP LPC18xx DAC
> + *
> + * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * UNSUPPORTED hardware features:
> + * - Interrupts
> + * - DMA
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/driver.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +/* LPC18XX DAC registers and bits */
> +#define LPC18XX_DAC_CR 0x000
> +#define LPC18XX_DAC_CR_VALUE_SHIFT 6
> +#define LPC18XX_DAC_CR_VALUE_MASK 0x3ff
> +#define LPC18XX_DAC_CR_BIAS BIT(16)
> +#define LPC18XX_DAC_CTRL 0x004
> +#define LPC18XX_DAC_CTRL_DMA_ENA BIT(3)
> +
> +struct lpc18xx_dac {
> + struct regulator *vref;
> + void __iomem *base;
> + struct mutex lock;
> + struct clk *clk;
> +};
> +
> +static const struct iio_chan_spec lpc18xx_dac_iio_channels[] = {
> + {
> + .type = IIO_VOLTAGE,
> + .output = 1,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> + BIT(IIO_CHAN_INFO_SCALE),
> + },
> +};
> +
> +static int lpc18xx_dac_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct lpc18xx_dac *dac = iio_priv(indio_dev);
> + u32 reg;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + reg = readl(dac->base + LPC18XX_DAC_CR);
> + *val = reg >> LPC18XX_DAC_CR_VALUE_SHIFT;
> + *val &= LPC18XX_DAC_CR_VALUE_MASK;
> +
> + return IIO_VAL_INT;
> +
> + case IIO_CHAN_INFO_SCALE:
> + *val = regulator_get_voltage(dac->vref) / 1000;
> + *val2 = 10;
> +
> + return IIO_VAL_FRACTIONAL_LOG2;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int lpc18xx_dac_write_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int val, int val2, long mask)
> +{
> + struct lpc18xx_dac *dac = iio_priv(indio_dev);
> + u32 reg;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + if (val < 0 || val > LPC18XX_DAC_CR_VALUE_MASK)
> + return -EINVAL;
> +
> + reg = LPC18XX_DAC_CR_BIAS;
> + reg |= val << LPC18XX_DAC_CR_VALUE_SHIFT;
> +
> + mutex_lock(&dac->lock);
> + writel(reg, dac->base + LPC18XX_DAC_CR);
> + writel(LPC18XX_DAC_CTRL_DMA_ENA, dac->base + LPC18XX_DAC_CTRL);
> + mutex_unlock(&dac->lock);
> +
> + return 0;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static const struct iio_info lpc18xx_dac_info = {
> + .read_raw = lpc18xx_dac_read_raw,
> + .write_raw = lpc18xx_dac_write_raw,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int lpc18xx_dac_probe(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev;
> + struct lpc18xx_dac *dac;
> + struct resource *res;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, indio_dev);
> + dac = iio_priv(indio_dev);
> + mutex_init(&dac->lock);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + dac->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(dac->base))
> + return PTR_ERR(dac->base);
> +
> + dac->clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(dac->clk)) {
> + dev_err(&pdev->dev, "error getting clock\n");
> + return PTR_ERR(dac->clk);
> + }
> +
> + dac->vref = devm_regulator_get(&pdev->dev, "vref");
> + if (IS_ERR(dac->vref)) {
> + dev_err(&pdev->dev, "error getting regulator\n");
> + return PTR_ERR(dac->vref);
> + }
> +
> + indio_dev->name = dev_name(&pdev->dev);
> + indio_dev->dev.parent = &pdev->dev;
> + indio_dev->info = &lpc18xx_dac_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = lpc18xx_dac_iio_channels;
> + indio_dev->num_channels = ARRAY_SIZE(lpc18xx_dac_iio_channels);
> +
> + ret = regulator_enable(dac->vref);
> + if (ret) {
> + dev_err(&pdev->dev, "unable to enable regulator\n");
> + return ret;
> + }
> +
> + ret = clk_prepare_enable(dac->clk);
> + if (ret) {
> + dev_err(&pdev->dev, "unable to enable clock\n");
> + goto dis_reg;
> + }
> +
> + writel(0, dac->base + LPC18XX_DAC_CTRL);
> + writel(0, dac->base + LPC18XX_DAC_CR);
> +
> + ret = iio_device_register(indio_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "unable to register device\n");
> + goto dis_clk;
> + }
> +
> + return 0;
> +
> +dis_clk:
> + clk_disable_unprepare(dac->clk);
> +dis_reg:
> + regulator_disable(dac->vref);
> + return ret;
> +}
> +
> +static int lpc18xx_dac_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct lpc18xx_dac *dac = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + writel(0, dac->base + LPC18XX_DAC_CTRL);
> + clk_disable_unprepare(dac->clk);
> + regulator_disable(dac->vref);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id lpc18xx_dac_match[] = {
> + { .compatible = "nxp,lpc1850-dac" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
> +
> +static struct platform_driver lpc18xx_dac_driver = {
> + .probe = lpc18xx_dac_probe,
> + .remove = lpc18xx_dac_remove,
> + .driver = {
> + .name = "lpc18xx-dac",
> + .of_match_table = lpc18xx_dac_match,
> + },
> +};
> +module_platform_driver(lpc18xx_dac_driver);
> +
> +MODULE_DESCRIPTION("LPC18xx DAC driver");
> +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings
2016-03-12 12:30 [PATCH v3 0/4] Support for analog peripherals on LPC18xx familiy Joachim Eastwood
` (2 preceding siblings ...)
2016-03-12 12:30 ` [PATCH v3 3/4] iio: dac: add NXP LPC18xx DAC driver Joachim Eastwood
@ 2016-03-12 12:30 ` Joachim Eastwood
2016-03-12 18:17 ` Jonathan Cameron
2016-03-18 20:12 ` Rob Herring
3 siblings, 2 replies; 11+ messages in thread
From: Joachim Eastwood @ 2016-03-12 12:30 UTC (permalink / raw)
To: jic23
Cc: Joachim Eastwood, knaack.h, lars, pmeerw, linux-iio, robh+dt,
devicetree
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
.../devicetree/bindings/iio/dac/lpc1850-dac.txt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
diff --git a/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
new file mode 100644
index 000000000000..7d6647d4af5e
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
@@ -0,0 +1,20 @@
+NXP LPC1850 DAC bindings
+
+Required properties:
+- compatible: Should be "nxp,lpc1850-dac"
+- reg: Offset and length of the register set for the ADC device
+- interrupts: The interrupt number for the ADC device
+- clocks: The root clock of the ADC controller
+- vref-supply: The regulator supply ADC reference voltage
+- resets: phandle to reset controller and line specifier
+
+Example:
+dac: dac@400e1000 {
+ compatible = "nxp,lpc1850-dac";
+ reg = <0x400e1000 0x1000>;
+ interrupts = <0>;
+ clocks = <&ccu1 CLK_APB3_DAC>;
+ vref-supply = <®_vdda>;
+ resets = <&rgu 42>;
+ status = "disabled";
+};
--
1.8.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings
2016-03-12 12:30 ` [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings Joachim Eastwood
@ 2016-03-12 18:17 ` Jonathan Cameron
2016-03-12 19:06 ` Joachim Eastwood
2016-03-18 20:12 ` Rob Herring
1 sibling, 1 reply; 11+ messages in thread
From: Jonathan Cameron @ 2016-03-12 18:17 UTC (permalink / raw)
To: Joachim Eastwood; +Cc: knaack.h, lars, pmeerw, linux-iio, robh+dt, devicetree
On 12/03/16 12:30, Joachim Eastwood wrote:
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
A very straight forward binding so I'm happy to apply this without
a devicetree ack (still time if anyone does want to take a look though as
it won't be in my non rebasing tree until probably next weekend now.)
Applied to the togreg branch of iio.git - initially pushed out as testing
for the autobuilders to play with it.
We have unfortunately missed the merge window that will probably open tomorrow
(as IIO stuff must be in a few weeks before that) so this is looking at the
next merge window in 3 months time. Will be in linux-next in about 3-4 weeks
though after I send a pull request to Greg KH post merge window closing.
Thanks,
Jonathan
> ---
> .../devicetree/bindings/iio/dac/lpc1850-dac.txt | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
>
> diff --git a/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
> new file mode 100644
> index 000000000000..7d6647d4af5e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
> @@ -0,0 +1,20 @@
> +NXP LPC1850 DAC bindings
> +
> +Required properties:
> +- compatible: Should be "nxp,lpc1850-dac"
> +- reg: Offset and length of the register set for the ADC device
> +- interrupts: The interrupt number for the ADC device
> +- clocks: The root clock of the ADC controller
> +- vref-supply: The regulator supply ADC reference voltage
> +- resets: phandle to reset controller and line specifier
> +
> +Example:
> +dac: dac@400e1000 {
> + compatible = "nxp,lpc1850-dac";
> + reg = <0x400e1000 0x1000>;
> + interrupts = <0>;
> + clocks = <&ccu1 CLK_APB3_DAC>;
> + vref-supply = <®_vdda>;
> + resets = <&rgu 42>;
> + status = "disabled";
> +};
>
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings
2016-03-12 18:17 ` Jonathan Cameron
@ 2016-03-12 19:06 ` Joachim Eastwood
0 siblings, 0 replies; 11+ messages in thread
From: Joachim Eastwood @ 2016-03-12 19:06 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
linux-iio, Rob Herring, devicetree
Hi Jonathan,
On 12 March 2016 at 19:17, Jonathan Cameron <jic23@kernel.org> wrote:
> On 12/03/16 12:30, Joachim Eastwood wrote:
>> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> A very straight forward binding so I'm happy to apply this without
> a devicetree ack (still time if anyone does want to take a look though as
> it won't be in my non rebasing tree until probably next weekend now.)
>
> Applied to the togreg branch of iio.git - initially pushed out as testing
> for the autobuilders to play with it.
Thanks!
> We have unfortunately missed the merge window that will probably open tomorrow
> (as IIO stuff must be in a few weeks before that) so this is looking at the
> next merge window in 3 months time. Will be in linux-next in about 3-4 weeks
> though after I send a pull request to Greg KH post merge window closing.
I wasn't expecting it to go upstream in the upcoming window. But I
will be good to get it into next after the window closes so I can get
the DT bits for lpc18xx upstream as well.
regards,
Joachim Eastwood
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings
2016-03-12 12:30 ` [PATCH v3 4/4] dt: document NXP LPC1850 DAC driver bindings Joachim Eastwood
2016-03-12 18:17 ` Jonathan Cameron
@ 2016-03-18 20:12 ` Rob Herring
1 sibling, 0 replies; 11+ messages in thread
From: Rob Herring @ 2016-03-18 20:12 UTC (permalink / raw)
To: Joachim Eastwood; +Cc: jic23, knaack.h, lars, pmeerw, linux-iio, devicetree
On Sat, Mar 12, 2016 at 01:30:17PM +0100, Joachim Eastwood wrote:
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> ---
> .../devicetree/bindings/iio/dac/lpc1850-dac.txt | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 11+ messages in thread