diff for duplicates of <1669488.HHBBlHNMv1@diego> diff --git a/a/1.txt b/N1/1.txt index 81d2620..c66e8cb 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,80 +1,75 @@ Am Sonntag, 13. Juli 2014, 14:09:48 schrieb Hartmut Knaack: -> Heiko St=FCbner schrieb: -> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation= - +> Heiko St?bner schrieb: +> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation > > Register (SAR) A/D Converter. It uses the supply and ground as its -> > reference and converts the analog input signal into 10-bit binary d= -igital +> > reference and converts the analog input signal into 10-bit binary digital > > codes. -> Is there a datasheet available anywhere, or just under some NDA? I've= - got -> some comments in line, which might be answered by reading the datashe= -et. +> Is there a datasheet available anywhere, or just under some NDA? I've got +> some comments in line, which might be answered by reading the datasheet. Sadly, there is no datasheet available to the public. > > Signed-off-by: Heiko Stuebner <heiko@sntech.de> > > --- -> >=20 +> > > > changes since v2: > > - address more comments from Peter Meerwald -> >=20 +> > > > mainly the missing info_mask_shared_by_type element -> > =20 +> > > > changes since v1: > > - address comments from Peter Meerwald -> >=20 +> > > > drivers/iio/adc/Kconfig | 10 ++ -> >=20 +> > > > drivers/iio/adc/Makefile | 1 + > > drivers/iio/adc/rockchip_saradc.c | 314 > > ++++++++++++++++++++++++++++++++++++++ 3 files changed, 325 > > insertions(+) > > create mode 100644 drivers/iio/adc/rockchip_saradc.c -> >=20 +> > > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > > index a80d236..5d36bdb 100644 > > --- a/drivers/iio/adc/Kconfig > > +++ b/drivers/iio/adc/Kconfig > > @@ -187,6 +187,16 @@ config NAU7802 -> >=20 -> > =09 To compile this driver as a module, choose M here: the -> > =09 module will be called nau7802. -> >=20 +> > +> > To compile this driver as a module, choose M here: the +> > module will be called nau7802. +> > > > +config ROCKCHIP_SARADC -> > +=09tristate "Rockchip SARADC driver" -> > +=09depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST) -> > +=09help -> > +=09 Say yes here to build support for the SARADC found in SoCs fr= -om -> > +=09 Rockchip. +> > + tristate "Rockchip SARADC driver" +> > + depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST) +> > + help +> > + Say yes here to build support for the SARADC found in SoCs from +> > + Rockchip. > > + -> > +=09 To compile this driver as a module, choose M here: the -> > +=09 module will be called rockchip_saradc. +> > + To compile this driver as a module, choose M here: the +> > + module will be called rockchip_saradc. > > + -> >=20 +> > > > config TI_ADC081C -> > =20 -> > =09tristate "Texas Instruments ADC081C021/027" -> > =09depends on I2C -> >=20 +> > +> > tristate "Texas Instruments ADC081C021/027" +> > depends on I2C +> > > > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > > index 9d60f2d..8e2932d 100644 > > --- a/drivers/iio/adc/Makefile > > +++ b/drivers/iio/adc/Makefile -> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) +=3D mcp320x.o -> >=20 -> > obj-$(CONFIG_MCP3422) +=3D mcp3422.o -> > obj-$(CONFIG_MEN_Z188_ADC) +=3D men_z188_adc.o -> > obj-$(CONFIG_NAU7802) +=3D nau7802.o -> >=20 -> > +obj-$(CONFIG_ROCKCHIP_SARADC) +=3D rockchip_saradc.o -> >=20 -> > obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o -> > obj-$(CONFIG_TI_AM335X_ADC) +=3D ti_am335x_adc.o -> > obj-$(CONFIG_TWL4030_MADC) +=3D twl4030-madc.o -> >=20 +> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o +> > +> > obj-$(CONFIG_MCP3422) += mcp3422.o +> > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o +> > obj-$(CONFIG_NAU7802) += nau7802.o +> > +> > +obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o +> > +> > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o +> > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o +> > obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o +> > > > diff --git a/drivers/iio/adc/rockchip_saradc.c > > b/drivers/iio/adc/rockchip_saradc.c new file mode 100644 > > index 0000000..8fc5867 @@ -84,26 +79,21 @@ om > > +/* > > + * Rockchip Successive Approximation Register (SAR) A/D Converter > > + * Copyright (C) 2014 ROCKCHIP, Inc. ->=20 +> > Does this mean, that you are working for Rockchip? -I'm doing consulting on the mainline integration and the code is largel= -y the=20 +I'm doing consulting on the mainline integration and the code is largely the one taken from the upstream tree and only cleaned up in places. ->=20 +> > > + * -> > + * This program is free software; you can redistribute it and/or m= -odify -> > + * it under the terms of the GNU General Public License as publish= -ed by -> > + * the Free Software Foundation; either version 2 of the License, = -or +> > + * 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,= - +> > + * 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. @@ -119,152 +109,141 @@ or > > +#include <linux/regulator/consumer.h> > > +#include <linux/iio/iio.h> > > + -> > +#define SARADC_DATA=09=09=090x00 -> > +#define SARADC_DATA_MASK=09=090x3ff +> > +#define SARADC_DATA 0x00 +> > +#define SARADC_DATA_MASK 0x3ff > > + -> > +#define SARADC_STAS=09=09=090x04 -> > +#define SARADC_STAS_BUSY=09=09BIT(0) +> > +#define SARADC_STAS 0x04 +> > +#define SARADC_STAS_BUSY BIT(0) > > + -> > +#define SARADC_CTRL=09=09=090x08 -> > +#define SARADC_CTRL_IRQ_STATUS=09=09BIT(6) -> > +#define SARADC_CTRL_IRQ_ENABLE=09=09BIT(5) -> > +#define SARADC_CTRL_POWER_CTRL=09=09BIT(3) -> > +#define SARADC_CTRL_CHN_MASK=09=090x7 +> > +#define SARADC_CTRL 0x08 +> > +#define SARADC_CTRL_IRQ_STATUS BIT(6) +> > +#define SARADC_CTRL_IRQ_ENABLE BIT(5) +> > +#define SARADC_CTRL_POWER_CTRL BIT(3) +> > +#define SARADC_CTRL_CHN_MASK 0x7 > > + -> > +#define SARADC_DLY_PU_SOC=09=090x0c -> > +#define SARADC_DLY_PU_SOC_MASK=09=090x3f +> > +#define SARADC_DLY_PU_SOC 0x0c +> > +#define SARADC_DLY_PU_SOC_MASK 0x3f > > + -> > +#define SARADC_BITS=09=09=0910 -> > +#define SARADC_TIMEOUT=09=09=09msecs_to_jiffies(100) +> > +#define SARADC_BITS 10 +> > +#define SARADC_TIMEOUT msecs_to_jiffies(100) > > + > > +struct rockchip_saradc { -> > +=09void __iomem=09=09*regs; -> > +=09struct clk=09=09*pclk; -> > +=09struct clk=09=09*clk; -> > +=09struct completion=09completion; -> > +=09struct regulator=09*vref; -> > +=09int=09=09=09vref_mv; -> > +=09u16=09=09=09last_val; +> > + void __iomem *regs; +> > + struct clk *pclk; +> > + struct clk *clk; +> > + struct completion completion; +> > + struct regulator *vref; +> > + int vref_mv; +> > + u16 last_val; > > +}; > > + > > +static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, -> > +=09=09=09=09 struct iio_chan_spec const *chan, -> > +=09=09=09=09 int *val, int *val2, long mask) +> > + struct iio_chan_spec const *chan, +> > + int *val, int *val2, long mask) > > +{ -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09switch (mask) { -> > +=09case IIO_CHAN_INFO_RAW: -> > +=09=09mutex_lock(&indio_dev->mlock); +> > + switch (mask) { +> > + case IIO_CHAN_INFO_RAW: +> > + mutex_lock(&indio_dev->mlock); > > + -> > +=09=09/* Select the channel to be used and trigger conversion */ -> > +=09=09writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC); ->=20 -> This could need a bit more explanation. Maybe represent the magic val= -ue of +> > + /* Select the channel to be used and trigger conversion */ +> > + writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC); +> +> This could need a bit more explanation. Maybe represent the magic value of > 0x8 with a more self explaining definition. -This actually isn't a magic value, but the "delay between power up and = -start=20 -command" in clock periods. But you're right, this might benefit from a = -better=20 -explaination, as the channel selection and start is done by the setting= - below. +This actually isn't a magic value, but the "delay between power up and start +command" in clock periods. But you're right, this might benefit from a better +explaination, as the channel selection and start is done by the setting below. -> > +=09=09writel(SARADC_CTRL_POWER_CTRL -> > +=09=09=09=09| (chan->channel & SARADC_CTRL_CHN_MASK) -> > +=09=09=09=09| SARADC_CTRL_IRQ_ENABLE, -> > +=09=09 info->regs + SARADC_CTRL); -> > + -> > +=09=09if (!wait_for_completion_timeout(&info->completion, -> > +=09=09=09=09=09=09 SARADC_TIMEOUT)) { -> > +=09=09=09writel_relaxed(0, info->regs + SARADC_CTRL); -> > +=09=09=09mutex_unlock(&indio_dev->mlock); -> > +=09=09=09return -ETIMEDOUT; -> > +=09=09} -> > + -> > +=09=09*val =3D info->last_val; -> > +=09=09mutex_unlock(&indio_dev->mlock); -> > +=09=09return IIO_VAL_INT; -> > +=09case IIO_CHAN_INFO_SCALE: -> > +=09=09*val =3D info->vref_mv; -> > +=09=09*val2 =3D SARADC_BITS; -> > +=09=09return IIO_VAL_FRACTIONAL_LOG2; ->=20 -> Are there only fixed voltage regulators used, or are there chances th= -at -> variable voltage regulators could be used for vref? In the second cas= -e, it +> > + writel(SARADC_CTRL_POWER_CTRL +> > + | (chan->channel & SARADC_CTRL_CHN_MASK) +> > + | SARADC_CTRL_IRQ_ENABLE, +> > + info->regs + SARADC_CTRL); +> > + +> > + if (!wait_for_completion_timeout(&info->completion, +> > + SARADC_TIMEOUT)) { +> > + writel_relaxed(0, info->regs + SARADC_CTRL); +> > + mutex_unlock(&indio_dev->mlock); +> > + return -ETIMEDOUT; +> > + } +> > + +> > + *val = info->last_val; +> > + mutex_unlock(&indio_dev->mlock); +> > + return IIO_VAL_INT; +> > + case IIO_CHAN_INFO_SCALE: +> > + *val = info->vref_mv; +> > + *val2 = SARADC_BITS; +> > + return IIO_VAL_FRACTIONAL_LOG2; +> +> Are there only fixed voltage regulators used, or are there chances that +> variable voltage regulators could be used for vref? In the second case, it > would be better to determine the current regulator voltage here. -The voltage regulators used are generally variable, but set to a fixed = -setting=20 +The voltage regulators used are generally variable, but set to a fixed setting that is not supposed to be changed. -Nevertheless I think you're right and the driver could be prepared for = -the=20 +Nevertheless I think you're right and the driver could be prepared for the case where the voltage might really change. -> > +=09default: -> > +=09=09return -EINVAL; -> > +=09} +> > + default: +> > + return -EINVAL; +> > + } > > +} > > + > > +static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) > > +{ -> > +=09struct rockchip_saradc *info =3D (struct rockchip_saradc *)dev_= -id; +> > + struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id; > > + -> > +=09/* Read value */ -> > +=09info->last_val =3D readl_relaxed(info->regs + SARADC_DATA); -> > +=09info->last_val &=3D SARADC_DATA_MASK; +> > + /* Read value */ +> > + info->last_val = readl_relaxed(info->regs + SARADC_DATA); +> > + info->last_val &= SARADC_DATA_MASK; > > + -> > +=09/* Clear irq & power down adc */ -> > +=09writel_relaxed(0, info->regs + SARADC_CTRL); +> > + /* Clear irq & power down adc */ +> > + writel_relaxed(0, info->regs + SARADC_CTRL); > > + -> > +=09complete(&info->completion); +> > + complete(&info->completion); > > + -> > +=09return IRQ_HANDLED; +> > + return IRQ_HANDLED; > > +} > > + -> > +static const struct iio_info rockchip_saradc_iio_info =3D { -> > +=09.read_raw =3D rockchip_saradc_read_raw, -> > +=09.driver_module =3D THIS_MODULE, +> > +static const struct iio_info rockchip_saradc_iio_info = { +> > + .read_raw = rockchip_saradc_read_raw, +> > + .driver_module = THIS_MODULE, > > +}; > > + -> > +#define ADC_CHANNEL(_index, _id) {=09=09=09=09\ -> > +=09.type =3D IIO_VOLTAGE,=09=09=09=09=09\ -> > +=09.indexed =3D 1,=09=09=09=09=09=09\ -> > +=09.channel =3D _index,=09=09=09=09=09\ -> > +=09.info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW),=09=09\ -> > +=09.info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE),=09\ -> > +=09.datasheet_name =3D _id,=09=09=09=09=09\ +> > +#define ADC_CHANNEL(_index, _id) { \ +> > + .type = IIO_VOLTAGE, \ +> > + .indexed = 1, \ +> > + .channel = _index, \ +> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +> > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +> > + .datasheet_name = _id, \ > > +} > > + -> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] =3D= - { -> > +=09ADC_CHANNEL(0, "adc0"), -> > +=09ADC_CHANNEL(1, "adc1"), -> > +=09ADC_CHANNEL(2, "adc2"), +> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] = { +> > + ADC_CHANNEL(0, "adc0"), +> > + ADC_CHANNEL(1, "adc1"), +> > + ADC_CHANNEL(2, "adc2"), > > +}; > > + > > +static int rockchip_saradc_probe(struct platform_device *pdev) > > +{ -> > +=09struct rockchip_saradc *info =3D NULL; -> > +=09struct device_node *np =3D pdev->dev.of_node; -> > +=09struct iio_dev *indio_dev =3D NULL; -> > +=09struct resource=09*mem; -> > +=09int ret =3D -ENODEV; -> > +=09int irq; -> > +=09u32 rate; -> > + -> > +=09if (!np) -> > +=09=09return ret; ->=20 -> return -ENODEV is usually used, and a bit more obvious. That would al= -so make +> > + struct rockchip_saradc *info = NULL; +> > + struct device_node *np = pdev->dev.of_node; +> > + struct iio_dev *indio_dev = NULL; +> > + struct resource *mem; +> > + int ret = -ENODEV; +> > + int irq; +> > + u32 rate; +> > + +> > + if (!np) +> > + return ret; +> +> return -ENODEV is usually used, and a bit more obvious. That would also make > the initialization of ret obsolete. ok @@ -274,182 +253,179 @@ Thanks for the review Heiko > > + -> > +=09indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(*info));= - -> > +=09if (!indio_dev) { -> > +=09=09dev_err(&pdev->dev, "failed allocating iio device\n"); -> > +=09=09return -ENOMEM; -> > +=09} -> > +=09info =3D iio_priv(indio_dev); -> > + -> > +=09mem =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); -> > +=09info->regs =3D devm_request_and_ioremap(&pdev->dev, mem); -> > +=09if (!info->regs) -> > +=09=09return -ENOMEM; -> > + -> > +=09irq =3D platform_get_irq(pdev, 0); -> > +=09if (irq < 0) { -> > +=09=09dev_err(&pdev->dev, "no irq resource?\n"); -> > +=09=09return irq; -> > +=09} -> > + -> > +=09ret =3D devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, -> > +=09=09=09 0, dev_name(&pdev->dev), info); -> > +=09if (ret < 0) { -> > +=09=09dev_err(&pdev->dev, "failed requesting irq %d\n", irq); -> > +=09=09return ret; -> > +=09} -> > + -> > +=09init_completion(&info->completion); -> > + -> > +=09info->pclk =3D devm_clk_get(&pdev->dev, "apb_pclk"); -> > +=09if (IS_ERR(info->pclk)) { -> > +=09=09dev_err(&pdev->dev, "failed to get pclk\n"); -> > +=09=09return PTR_ERR(info->pclk); -> > +=09} -> > + -> > +=09info->clk =3D devm_clk_get(&pdev->dev, "saradc"); -> > +=09if (IS_ERR(info->clk)) { -> > +=09=09dev_err(&pdev->dev, "failed to get adc clock\n"); -> > +=09=09return PTR_ERR(info->clk); -> > +=09} -> > + -> > +=09info->vref =3D devm_regulator_get(&pdev->dev, "vref"); -> > +=09if (IS_ERR(info->vref)) { -> > +=09=09dev_err(&pdev->dev, "failed to get regulator, %ld\n", -> > +=09=09=09PTR_ERR(info->vref)); -> > +=09=09return PTR_ERR(info->vref); -> > +=09} -> > + -> > +=09/* use a default of 1MHz for the converter clock */ -> > +=09if (of_property_read_u32(np, "clock-frequency", &rate)) -> > +=09=09rate =3D 1000000; -> > + -> > +=09ret =3D clk_set_rate(info->clk, rate); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret)= -; -> > +=09=09return ret; -> > +=09} -> > + -> > +=09ret =3D regulator_enable(info->vref); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable vref regulator\n"); -> > +=09=09return ret; -> > +=09} -> > + -> > +=09ret =3D regulator_get_voltage(info->vref); -> > +=09if (ret < 0) { -> > +=09=09dev_err(&pdev->dev, "failed to get regulator voltage\n"); -> > +=09=09goto err_reg_voltage; -> > +=09} -> > +=09info->vref_mv =3D ret / 1000; -> > + -> > +=09ret =3D clk_prepare_enable(info->pclk); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable pclk\n"); -> > +=09=09goto err_reg_voltage; -> > +=09} -> > + -> > +=09ret =3D clk_prepare_enable(info->clk); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable converter clock\n"); -> > +=09=09goto err_pclk; -> > +=09} -> > + -> > +=09platform_set_drvdata(pdev, indio_dev); -> > + -> > +=09indio_dev->name =3D dev_name(&pdev->dev); -> > +=09indio_dev->dev.parent =3D &pdev->dev; -> > +=09indio_dev->dev.of_node =3D pdev->dev.of_node; -> > +=09indio_dev->info =3D &rockchip_saradc_iio_info; -> > +=09indio_dev->modes =3D INDIO_DIRECT_MODE; -> > + -> > +=09indio_dev->channels =3D rockchip_saradc_iio_channels; -> > +=09indio_dev->num_channels =3D ARRAY_SIZE(rockchip_saradc_iio_chan= -nels); -> > + -> > +=09ret =3D iio_device_register(indio_dev); -> > +=09if (ret) -> > +=09=09goto err_clk; -> > + -> > +=09return 0; +> > + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); +> > + if (!indio_dev) { +> > + dev_err(&pdev->dev, "failed allocating iio device\n"); +> > + return -ENOMEM; +> > + } +> > + info = iio_priv(indio_dev); +> > + +> > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +> > + info->regs = devm_request_and_ioremap(&pdev->dev, mem); +> > + if (!info->regs) +> > + return -ENOMEM; +> > + +> > + irq = platform_get_irq(pdev, 0); +> > + if (irq < 0) { +> > + dev_err(&pdev->dev, "no irq resource?\n"); +> > + return irq; +> > + } +> > + +> > + ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, +> > + 0, dev_name(&pdev->dev), info); +> > + if (ret < 0) { +> > + dev_err(&pdev->dev, "failed requesting irq %d\n", irq); +> > + return ret; +> > + } +> > + +> > + init_completion(&info->completion); +> > + +> > + info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); +> > + if (IS_ERR(info->pclk)) { +> > + dev_err(&pdev->dev, "failed to get pclk\n"); +> > + return PTR_ERR(info->pclk); +> > + } +> > + +> > + info->clk = devm_clk_get(&pdev->dev, "saradc"); +> > + if (IS_ERR(info->clk)) { +> > + dev_err(&pdev->dev, "failed to get adc clock\n"); +> > + return PTR_ERR(info->clk); +> > + } +> > + +> > + info->vref = devm_regulator_get(&pdev->dev, "vref"); +> > + if (IS_ERR(info->vref)) { +> > + dev_err(&pdev->dev, "failed to get regulator, %ld\n", +> > + PTR_ERR(info->vref)); +> > + return PTR_ERR(info->vref); +> > + } +> > + +> > + /* use a default of 1MHz for the converter clock */ +> > + if (of_property_read_u32(np, "clock-frequency", &rate)) +> > + rate = 1000000; +> > + +> > + ret = clk_set_rate(info->clk, rate); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); +> > + return ret; +> > + } +> > + +> > + ret = regulator_enable(info->vref); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable vref regulator\n"); +> > + return ret; +> > + } +> > + +> > + ret = regulator_get_voltage(info->vref); +> > + if (ret < 0) { +> > + dev_err(&pdev->dev, "failed to get regulator voltage\n"); +> > + goto err_reg_voltage; +> > + } +> > + info->vref_mv = ret / 1000; +> > + +> > + ret = clk_prepare_enable(info->pclk); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable pclk\n"); +> > + goto err_reg_voltage; +> > + } +> > + +> > + ret = clk_prepare_enable(info->clk); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable converter clock\n"); +> > + goto err_pclk; +> > + } +> > + +> > + platform_set_drvdata(pdev, indio_dev); +> > + +> > + indio_dev->name = dev_name(&pdev->dev); +> > + indio_dev->dev.parent = &pdev->dev; +> > + indio_dev->dev.of_node = pdev->dev.of_node; +> > + indio_dev->info = &rockchip_saradc_iio_info; +> > + indio_dev->modes = INDIO_DIRECT_MODE; +> > + +> > + indio_dev->channels = rockchip_saradc_iio_channels; +> > + indio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels); +> > + +> > + ret = iio_device_register(indio_dev); +> > + if (ret) +> > + goto err_clk; +> > + +> > + return 0; > > + > > +err_clk: -> > +=09clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->clk); > > +err_pclk: -> > +=09clk_disable_unprepare(info->pclk); +> > + clk_disable_unprepare(info->pclk); > > +err_reg_voltage: -> > +=09regulator_disable(info->vref); -> > +=09return ret; +> > + regulator_disable(info->vref); +> > + return ret; > > +} > > + > > +static int rockchip_saradc_remove(struct platform_device *pdev) > > +{ -> > +=09struct iio_dev *indio_dev =3D platform_get_drvdata(pdev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct iio_dev *indio_dev = platform_get_drvdata(pdev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09iio_device_unregister(indio_dev); -> > +=09clk_disable_unprepare(info->clk); -> > +=09clk_disable_unprepare(info->pclk); -> > +=09regulator_disable(info->vref); +> > + iio_device_unregister(indio_dev); +> > + clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->pclk); +> > + regulator_disable(info->vref); > > + -> > +=09return 0; +> > + return 0; > > +} > > + > > +#ifdef CONFIG_PM_SLEEP > > +static int rockchip_saradc_suspend(struct device *dev) > > +{ -> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct iio_dev *indio_dev = dev_get_drvdata(dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09clk_disable_unprepare(info->clk); -> > +=09clk_disable_unprepare(info->pclk); -> > +=09regulator_disable(info->vref); +> > + clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->pclk); +> > + regulator_disable(info->vref); > > + -> > +=09return 0; +> > + return 0; > > +} > > + > > +static int rockchip_saradc_resume(struct device *dev) > > +{ -> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); -> > +=09int ret; +> > + struct iio_dev *indio_dev = dev_get_drvdata(dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); +> > + int ret; > > + -> > +=09ret =3D regulator_enable(info->vref); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = regulator_enable(info->vref); +> > + if (ret) +> > + return ret; > > + -> > +=09ret =3D clk_prepare_enable(info->pclk); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = clk_prepare_enable(info->pclk); +> > + if (ret) +> > + return ret; > > + -> > +=09ret =3D clk_prepare_enable(info->clk); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = clk_prepare_enable(info->clk); +> > + if (ret) +> > + return ret; > > + -> > +=09return ret; +> > + return ret; > > +} > > +#endif > > + > > +static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, -> > +=09=09=09 rockchip_saradc_suspend, rockchip_saradc_resume); +> > + rockchip_saradc_suspend, rockchip_saradc_resume); > > + -> > +static const struct of_device_id rockchip_saradc_match[] =3D { -> > +=09{ .compatible =3D "rockchip,saradc" }, -> > +=09{}, +> > +static const struct of_device_id rockchip_saradc_match[] = { +> > + { .compatible = "rockchip,saradc" }, +> > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, rockchip_saradc_match); > > + -> > +static struct platform_driver rockchip_saradc_driver =3D { -> > +=09.probe=09=09=3D rockchip_saradc_probe, -> > +=09.remove=09=09=3D rockchip_saradc_remove, -> > +=09.driver=09=09=3D { -> > +=09=09.name=09=3D "rockchip-saradc", -> > +=09=09.owner=09=3D THIS_MODULE, -> > +=09=09.of_match_table =3D rockchip_saradc_match, -> > +=09=09.pm=09=3D &rockchip_saradc_pm_ops, -> > +=09}, +> > +static struct platform_driver rockchip_saradc_driver = { +> > + .probe = rockchip_saradc_probe, +> > + .remove = rockchip_saradc_remove, +> > + .driver = { +> > + .name = "rockchip-saradc", +> > + .owner = THIS_MODULE, +> > + .of_match_table = rockchip_saradc_match, +> > + .pm = &rockchip_saradc_pm_ops, +> > + }, > > +}; > > + > > +module_platform_driver(rockchip_saradc_driver); diff --git a/a/content_digest b/N1/content_digest index 6c89bb6..bc64cc8 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,102 +1,84 @@ "ref\02959154.xc8BQActsn@diego\0" "ref\02263220.rhyqmTfAiL@diego\0" "ref\053C2770C.3050701@gmx.de\0" - "From\0Heiko St\303\274bner <heiko@sntech.de>\0" - "Subject\0Re: [PATCH v3 1/2] iio: adc: add driver for Rockchip saradc\0" + "From\0heiko@sntech.de (Heiko St\303\274bner)\0" + "Subject\0[PATCH v3 1/2] iio: adc: add driver for Rockchip saradc\0" "Date\0Sun, 13 Jul 2014 14:33:19 +0200\0" - "To\0Hartmut Knaack <knaack.h@gmx.de>\0" - "Cc\0Jonathan Cameron <jic23@kernel.org>" - linux-arm-kernel@lists.infradead.org - linux-kernel@vger.kernel.org - linux-iio@vger.kernel.org - devicetree@vger.kernel.org - Rob Herring <robh+dt@kernel.org> - Pawel Moll <pawel.moll@arm.com> - Mark Rutland <mark.rutland@arm.com> - Ian Campbell <ijc+devicetree@hellion.org.uk> - Kumar Gala <galak@codeaurora.org> - " eddie(\350\224\241\346\236\253) <cf@rock-chips.com>" - huangtao@rock-chips.com - " Peter Meerwald <pmeerw@pmeerw.net>\0" + "To\0linux-arm-kernel@lists.infradead.org\0" "\00:1\0" "b\0" "Am Sonntag, 13. Juli 2014, 14:09:48 schrieb Hartmut Knaack:\n" - "> Heiko St=FCbner schrieb:\n" - "> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation=\n" - "\n" + "> Heiko St?bner schrieb:\n" + "> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation\n" "> > Register (SAR) A/D Converter. It uses the supply and ground as its\n" - "> > reference and converts the analog input signal into 10-bit binary d=\n" - "igital\n" + "> > reference and converts the analog input signal into 10-bit binary digital\n" "> > codes.\n" - "> Is there a datasheet available anywhere, or just under some NDA? I've=\n" - " got\n" - "> some comments in line, which might be answered by reading the datashe=\n" - "et.\n" + "> Is there a datasheet available anywhere, or just under some NDA? I've got\n" + "> some comments in line, which might be answered by reading the datasheet.\n" "\n" "Sadly, there is no datasheet available to the public.\n" "\n" "\n" "> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>\n" "> > ---\n" - "> >=20\n" + "> > \n" "> > changes since v2:\n" "> > - address more comments from Peter Meerwald\n" - "> >=20\n" + "> > \n" "> > mainly the missing info_mask_shared_by_type element\n" - "> > =20\n" + "> > \n" "> > changes since v1:\n" "> > - address comments from Peter Meerwald\n" - "> >=20\n" + "> > \n" "> > drivers/iio/adc/Kconfig | 10 ++\n" - "> >=20\n" + "> > \n" "> > drivers/iio/adc/Makefile | 1 +\n" "> > drivers/iio/adc/rockchip_saradc.c | 314\n" "> > ++++++++++++++++++++++++++++++++++++++ 3 files changed, 325\n" "> > insertions(+)\n" "> > create mode 100644 drivers/iio/adc/rockchip_saradc.c\n" - "> >=20\n" + "> > \n" "> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig\n" "> > index a80d236..5d36bdb 100644\n" "> > --- a/drivers/iio/adc/Kconfig\n" "> > +++ b/drivers/iio/adc/Kconfig\n" "> > @@ -187,6 +187,16 @@ config NAU7802\n" - "> >=20\n" - "> > =09 To compile this driver as a module, choose M here: the\n" - "> > =09 module will be called nau7802.\n" - "> >=20\n" + "> > \n" + "> > \t To compile this driver as a module, choose M here: the\n" + "> > \t module will be called nau7802.\n" + "> > \n" "> > +config ROCKCHIP_SARADC\n" - "> > +=09tristate \"Rockchip SARADC driver\"\n" - "> > +=09depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST)\n" - "> > +=09help\n" - "> > +=09 Say yes here to build support for the SARADC found in SoCs fr=\n" - "om\n" - "> > +=09 Rockchip.\n" + "> > +\ttristate \"Rockchip SARADC driver\"\n" + "> > +\tdepends on ARCH_ROCKCHIP || (OF && COMPILE_TEST)\n" + "> > +\thelp\n" + "> > +\t Say yes here to build support for the SARADC found in SoCs from\n" + "> > +\t Rockchip.\n" "> > +\n" - "> > +=09 To compile this driver as a module, choose M here: the\n" - "> > +=09 module will be called rockchip_saradc.\n" + "> > +\t To compile this driver as a module, choose M here: the\n" + "> > +\t module will be called rockchip_saradc.\n" "> > +\n" - "> >=20\n" + "> > \n" "> > config TI_ADC081C\n" - "> > =20\n" - "> > =09tristate \"Texas Instruments ADC081C021/027\"\n" - "> > =09depends on I2C\n" - "> >=20\n" + "> > \n" + "> > \ttristate \"Texas Instruments ADC081C021/027\"\n" + "> > \tdepends on I2C\n" + "> > \n" "> > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile\n" "> > index 9d60f2d..8e2932d 100644\n" "> > --- a/drivers/iio/adc/Makefile\n" "> > +++ b/drivers/iio/adc/Makefile\n" - "> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) +=3D mcp320x.o\n" - "> >=20\n" - "> > obj-$(CONFIG_MCP3422) +=3D mcp3422.o\n" - "> > obj-$(CONFIG_MEN_Z188_ADC) +=3D men_z188_adc.o\n" - "> > obj-$(CONFIG_NAU7802) +=3D nau7802.o\n" - "> >=20\n" - "> > +obj-$(CONFIG_ROCKCHIP_SARADC) +=3D rockchip_saradc.o\n" - "> >=20\n" - "> > obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o\n" - "> > obj-$(CONFIG_TI_AM335X_ADC) +=3D ti_am335x_adc.o\n" - "> > obj-$(CONFIG_TWL4030_MADC) +=3D twl4030-madc.o\n" - "> >=20\n" + "> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o\n" + "> > \n" + "> > obj-$(CONFIG_MCP3422) += mcp3422.o\n" + "> > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o\n" + "> > obj-$(CONFIG_NAU7802) += nau7802.o\n" + "> > \n" + "> > +obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o\n" + "> > \n" + "> > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o\n" + "> > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o\n" + "> > obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o\n" + "> > \n" "> > diff --git a/drivers/iio/adc/rockchip_saradc.c\n" "> > b/drivers/iio/adc/rockchip_saradc.c new file mode 100644\n" "> > index 0000000..8fc5867\n" @@ -106,26 +88,21 @@ "> > +/*\n" "> > + * Rockchip Successive Approximation Register (SAR) A/D Converter\n" "> > + * Copyright (C) 2014 ROCKCHIP, Inc.\n" - ">=20\n" + "> \n" "> Does this mean, that you are working for Rockchip?\n" "\n" - "I'm doing consulting on the mainline integration and the code is largel=\n" - "y the=20\n" + "I'm doing consulting on the mainline integration and the code is largely the \n" "one taken from the upstream tree and only cleaned up in places.\n" "\n" "\n" - ">=20\n" + "> \n" "> > + *\n" - "> > + * This program is free software; you can redistribute it and/or m=\n" - "odify\n" - "> > + * it under the terms of the GNU General Public License as publish=\n" - "ed by\n" - "> > + * the Free Software Foundation; either version 2 of the License, =\n" - "or\n" + "> > + * This program is free software; you can redistribute it and/or modify\n" + "> > + * it under the terms of the GNU General Public License as published by\n" + "> > + * the Free Software Foundation; either version 2 of the License, or\n" "> > + * (at your option) any later version.\n" "> > + *\n" - "> > + * This program is distributed in the hope that it will be useful,=\n" - "\n" + "> > + * This program is distributed in the hope that it will be useful,\n" "> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "> > + * GNU General Public License for more details.\n" @@ -141,152 +118,141 @@ "> > +#include <linux/regulator/consumer.h>\n" "> > +#include <linux/iio/iio.h>\n" "> > +\n" - "> > +#define SARADC_DATA=09=09=090x00\n" - "> > +#define SARADC_DATA_MASK=09=090x3ff\n" + "> > +#define SARADC_DATA\t\t\t0x00\n" + "> > +#define SARADC_DATA_MASK\t\t0x3ff\n" "> > +\n" - "> > +#define SARADC_STAS=09=09=090x04\n" - "> > +#define SARADC_STAS_BUSY=09=09BIT(0)\n" + "> > +#define SARADC_STAS\t\t\t0x04\n" + "> > +#define SARADC_STAS_BUSY\t\tBIT(0)\n" "> > +\n" - "> > +#define SARADC_CTRL=09=09=090x08\n" - "> > +#define SARADC_CTRL_IRQ_STATUS=09=09BIT(6)\n" - "> > +#define SARADC_CTRL_IRQ_ENABLE=09=09BIT(5)\n" - "> > +#define SARADC_CTRL_POWER_CTRL=09=09BIT(3)\n" - "> > +#define SARADC_CTRL_CHN_MASK=09=090x7\n" + "> > +#define SARADC_CTRL\t\t\t0x08\n" + "> > +#define SARADC_CTRL_IRQ_STATUS\t\tBIT(6)\n" + "> > +#define SARADC_CTRL_IRQ_ENABLE\t\tBIT(5)\n" + "> > +#define SARADC_CTRL_POWER_CTRL\t\tBIT(3)\n" + "> > +#define SARADC_CTRL_CHN_MASK\t\t0x7\n" "> > +\n" - "> > +#define SARADC_DLY_PU_SOC=09=090x0c\n" - "> > +#define SARADC_DLY_PU_SOC_MASK=09=090x3f\n" + "> > +#define SARADC_DLY_PU_SOC\t\t0x0c\n" + "> > +#define SARADC_DLY_PU_SOC_MASK\t\t0x3f\n" "> > +\n" - "> > +#define SARADC_BITS=09=09=0910\n" - "> > +#define SARADC_TIMEOUT=09=09=09msecs_to_jiffies(100)\n" + "> > +#define SARADC_BITS\t\t\t10\n" + "> > +#define SARADC_TIMEOUT\t\t\tmsecs_to_jiffies(100)\n" "> > +\n" "> > +struct rockchip_saradc {\n" - "> > +=09void __iomem=09=09*regs;\n" - "> > +=09struct clk=09=09*pclk;\n" - "> > +=09struct clk=09=09*clk;\n" - "> > +=09struct completion=09completion;\n" - "> > +=09struct regulator=09*vref;\n" - "> > +=09int=09=09=09vref_mv;\n" - "> > +=09u16=09=09=09last_val;\n" + "> > +\tvoid __iomem\t\t*regs;\n" + "> > +\tstruct clk\t\t*pclk;\n" + "> > +\tstruct clk\t\t*clk;\n" + "> > +\tstruct completion\tcompletion;\n" + "> > +\tstruct regulator\t*vref;\n" + "> > +\tint\t\t\tvref_mv;\n" + "> > +\tu16\t\t\tlast_val;\n" "> > +};\n" "> > +\n" "> > +static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,\n" - "> > +=09=09=09=09 struct iio_chan_spec const *chan,\n" - "> > +=09=09=09=09 int *val, int *val2, long mask)\n" + "> > +\t\t\t\t struct iio_chan_spec const *chan,\n" + "> > +\t\t\t\t int *val, int *val2, long mask)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09switch (mask) {\n" - "> > +=09case IIO_CHAN_INFO_RAW:\n" - "> > +=09=09mutex_lock(&indio_dev->mlock);\n" + "> > +\tswitch (mask) {\n" + "> > +\tcase IIO_CHAN_INFO_RAW:\n" + "> > +\t\tmutex_lock(&indio_dev->mlock);\n" "> > +\n" - "> > +=09=09/* Select the channel to be used and trigger conversion */\n" - "> > +=09=09writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC);\n" - ">=20\n" - "> This could need a bit more explanation. Maybe represent the magic val=\n" - "ue of\n" + "> > +\t\t/* Select the channel to be used and trigger conversion */\n" + "> > +\t\twritel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC);\n" + "> \n" + "> This could need a bit more explanation. Maybe represent the magic value of\n" "> 0x8 with a more self explaining definition.\n" "\n" - "This actually isn't a magic value, but the \"delay between power up and =\n" - "start=20\n" - "command\" in clock periods. But you're right, this might benefit from a =\n" - "better=20\n" - "explaination, as the channel selection and start is done by the setting=\n" - " below.\n" + "This actually isn't a magic value, but the \"delay between power up and start \n" + "command\" in clock periods. But you're right, this might benefit from a better \n" + "explaination, as the channel selection and start is done by the setting below.\n" "\n" "\n" - "> > +=09=09writel(SARADC_CTRL_POWER_CTRL\n" - "> > +=09=09=09=09| (chan->channel & SARADC_CTRL_CHN_MASK)\n" - "> > +=09=09=09=09| SARADC_CTRL_IRQ_ENABLE,\n" - "> > +=09=09 info->regs + SARADC_CTRL);\n" - "> > +\n" - "> > +=09=09if (!wait_for_completion_timeout(&info->completion,\n" - "> > +=09=09=09=09=09=09 SARADC_TIMEOUT)) {\n" - "> > +=09=09=09writel_relaxed(0, info->regs + SARADC_CTRL);\n" - "> > +=09=09=09mutex_unlock(&indio_dev->mlock);\n" - "> > +=09=09=09return -ETIMEDOUT;\n" - "> > +=09=09}\n" - "> > +\n" - "> > +=09=09*val =3D info->last_val;\n" - "> > +=09=09mutex_unlock(&indio_dev->mlock);\n" - "> > +=09=09return IIO_VAL_INT;\n" - "> > +=09case IIO_CHAN_INFO_SCALE:\n" - "> > +=09=09*val =3D info->vref_mv;\n" - "> > +=09=09*val2 =3D SARADC_BITS;\n" - "> > +=09=09return IIO_VAL_FRACTIONAL_LOG2;\n" - ">=20\n" - "> Are there only fixed voltage regulators used, or are there chances th=\n" - "at\n" - "> variable voltage regulators could be used for vref? In the second cas=\n" - "e, it\n" + "> > +\t\twritel(SARADC_CTRL_POWER_CTRL\n" + "> > +\t\t\t\t| (chan->channel & SARADC_CTRL_CHN_MASK)\n" + "> > +\t\t\t\t| SARADC_CTRL_IRQ_ENABLE,\n" + "> > +\t\t info->regs + SARADC_CTRL);\n" + "> > +\n" + "> > +\t\tif (!wait_for_completion_timeout(&info->completion,\n" + "> > +\t\t\t\t\t\t SARADC_TIMEOUT)) {\n" + "> > +\t\t\twritel_relaxed(0, info->regs + SARADC_CTRL);\n" + "> > +\t\t\tmutex_unlock(&indio_dev->mlock);\n" + "> > +\t\t\treturn -ETIMEDOUT;\n" + "> > +\t\t}\n" + "> > +\n" + "> > +\t\t*val = info->last_val;\n" + "> > +\t\tmutex_unlock(&indio_dev->mlock);\n" + "> > +\t\treturn IIO_VAL_INT;\n" + "> > +\tcase IIO_CHAN_INFO_SCALE:\n" + "> > +\t\t*val = info->vref_mv;\n" + "> > +\t\t*val2 = SARADC_BITS;\n" + "> > +\t\treturn IIO_VAL_FRACTIONAL_LOG2;\n" + "> \n" + "> Are there only fixed voltage regulators used, or are there chances that\n" + "> variable voltage regulators could be used for vref? In the second case, it\n" "> would be better to determine the current regulator voltage here.\n" "\n" - "The voltage regulators used are generally variable, but set to a fixed =\n" - "setting=20\n" + "The voltage regulators used are generally variable, but set to a fixed setting \n" "that is not supposed to be changed.\n" "\n" - "Nevertheless I think you're right and the driver could be prepared for =\n" - "the=20\n" + "Nevertheless I think you're right and the driver could be prepared for the \n" "case where the voltage might really change.\n" "\n" "\n" - "> > +=09default:\n" - "> > +=09=09return -EINVAL;\n" - "> > +=09}\n" + "> > +\tdefault:\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\t}\n" "> > +}\n" "> > +\n" "> > +static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D (struct rockchip_saradc *)dev_=\n" - "id;\n" + "> > +\tstruct rockchip_saradc *info = (struct rockchip_saradc *)dev_id;\n" "> > +\n" - "> > +=09/* Read value */\n" - "> > +=09info->last_val =3D readl_relaxed(info->regs + SARADC_DATA);\n" - "> > +=09info->last_val &=3D SARADC_DATA_MASK;\n" + "> > +\t/* Read value */\n" + "> > +\tinfo->last_val = readl_relaxed(info->regs + SARADC_DATA);\n" + "> > +\tinfo->last_val &= SARADC_DATA_MASK;\n" "> > +\n" - "> > +=09/* Clear irq & power down adc */\n" - "> > +=09writel_relaxed(0, info->regs + SARADC_CTRL);\n" + "> > +\t/* Clear irq & power down adc */\n" + "> > +\twritel_relaxed(0, info->regs + SARADC_CTRL);\n" "> > +\n" - "> > +=09complete(&info->completion);\n" + "> > +\tcomplete(&info->completion);\n" "> > +\n" - "> > +=09return IRQ_HANDLED;\n" + "> > +\treturn IRQ_HANDLED;\n" "> > +}\n" "> > +\n" - "> > +static const struct iio_info rockchip_saradc_iio_info =3D {\n" - "> > +=09.read_raw =3D rockchip_saradc_read_raw,\n" - "> > +=09.driver_module =3D THIS_MODULE,\n" + "> > +static const struct iio_info rockchip_saradc_iio_info = {\n" + "> > +\t.read_raw = rockchip_saradc_read_raw,\n" + "> > +\t.driver_module = THIS_MODULE,\n" "> > +};\n" "> > +\n" - "> > +#define ADC_CHANNEL(_index, _id) {=09=09=09=09\\\n" - "> > +=09.type =3D IIO_VOLTAGE,=09=09=09=09=09\\\n" - "> > +=09.indexed =3D 1,=09=09=09=09=09=09\\\n" - "> > +=09.channel =3D _index,=09=09=09=09=09\\\n" - "> > +=09.info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW),=09=09\\\n" - "> > +=09.info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE),=09\\\n" - "> > +=09.datasheet_name =3D _id,=09=09=09=09=09\\\n" + "> > +#define ADC_CHANNEL(_index, _id) {\t\t\t\t\\\n" + "> > +\t.type = IIO_VOLTAGE,\t\t\t\t\t\\\n" + "> > +\t.indexed = 1,\t\t\t\t\t\t\\\n" + "> > +\t.channel = _index,\t\t\t\t\t\\\n" + "> > +\t.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),\t\t\\\n" + "> > +\t.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\t\\\n" + "> > +\t.datasheet_name = _id,\t\t\t\t\t\\\n" "> > +}\n" "> > +\n" - "> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] =3D=\n" - " {\n" - "> > +=09ADC_CHANNEL(0, \"adc0\"),\n" - "> > +=09ADC_CHANNEL(1, \"adc1\"),\n" - "> > +=09ADC_CHANNEL(2, \"adc2\"),\n" + "> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {\n" + "> > +\tADC_CHANNEL(0, \"adc0\"),\n" + "> > +\tADC_CHANNEL(1, \"adc1\"),\n" + "> > +\tADC_CHANNEL(2, \"adc2\"),\n" "> > +};\n" "> > +\n" "> > +static int rockchip_saradc_probe(struct platform_device *pdev)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D NULL;\n" - "> > +=09struct device_node *np =3D pdev->dev.of_node;\n" - "> > +=09struct iio_dev *indio_dev =3D NULL;\n" - "> > +=09struct resource=09*mem;\n" - "> > +=09int ret =3D -ENODEV;\n" - "> > +=09int irq;\n" - "> > +=09u32 rate;\n" - "> > +\n" - "> > +=09if (!np)\n" - "> > +=09=09return ret;\n" - ">=20\n" - "> return -ENODEV is usually used, and a bit more obvious. That would al=\n" - "so make\n" + "> > +\tstruct rockchip_saradc *info = NULL;\n" + "> > +\tstruct device_node *np = pdev->dev.of_node;\n" + "> > +\tstruct iio_dev *indio_dev = NULL;\n" + "> > +\tstruct resource\t*mem;\n" + "> > +\tint ret = -ENODEV;\n" + "> > +\tint irq;\n" + "> > +\tu32 rate;\n" + "> > +\n" + "> > +\tif (!np)\n" + "> > +\t\treturn ret;\n" + "> \n" + "> return -ENODEV is usually used, and a bit more obvious. That would also make\n" "> the initialization of ret obsolete.\n" "\n" "ok\n" @@ -296,184 +262,181 @@ "Heiko\n" "\n" "> > +\n" - "> > +=09indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(*info));=\n" - "\n" - "> > +=09if (!indio_dev) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed allocating iio device\\n\");\n" - "> > +=09=09return -ENOMEM;\n" - "> > +=09}\n" - "> > +=09info =3D iio_priv(indio_dev);\n" - "> > +\n" - "> > +=09mem =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" - "> > +=09info->regs =3D devm_request_and_ioremap(&pdev->dev, mem);\n" - "> > +=09if (!info->regs)\n" - "> > +=09=09return -ENOMEM;\n" - "> > +\n" - "> > +=09irq =3D platform_get_irq(pdev, 0);\n" - "> > +=09if (irq < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"no irq resource?\\n\");\n" - "> > +=09=09return irq;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,\n" - "> > +=09=09=09 0, dev_name(&pdev->dev), info);\n" - "> > +=09if (ret < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed requesting irq %d\\n\", irq);\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09init_completion(&info->completion);\n" - "> > +\n" - "> > +=09info->pclk =3D devm_clk_get(&pdev->dev, \"apb_pclk\");\n" - "> > +=09if (IS_ERR(info->pclk)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get pclk\\n\");\n" - "> > +=09=09return PTR_ERR(info->pclk);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09info->clk =3D devm_clk_get(&pdev->dev, \"saradc\");\n" - "> > +=09if (IS_ERR(info->clk)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get adc clock\\n\");\n" - "> > +=09=09return PTR_ERR(info->clk);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09info->vref =3D devm_regulator_get(&pdev->dev, \"vref\");\n" - "> > +=09if (IS_ERR(info->vref)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get regulator, %ld\\n\",\n" - "> > +=09=09=09PTR_ERR(info->vref));\n" - "> > +=09=09return PTR_ERR(info->vref);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09/* use a default of 1MHz for the converter clock */\n" - "> > +=09if (of_property_read_u32(np, \"clock-frequency\", &rate))\n" - "> > +=09=09rate =3D 1000000;\n" - "> > +\n" - "> > +=09ret =3D clk_set_rate(info->clk, rate);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to set adc clk rate, %d\\n\", ret)=\n" - ";\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D regulator_enable(info->vref);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable vref regulator\\n\");\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D regulator_get_voltage(info->vref);\n" - "> > +=09if (ret < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get regulator voltage\\n\");\n" - "> > +=09=09goto err_reg_voltage;\n" - "> > +=09}\n" - "> > +=09info->vref_mv =3D ret / 1000;\n" - "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->pclk);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable pclk\\n\");\n" - "> > +=09=09goto err_reg_voltage;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->clk);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable converter clock\\n\");\n" - "> > +=09=09goto err_pclk;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09platform_set_drvdata(pdev, indio_dev);\n" - "> > +\n" - "> > +=09indio_dev->name =3D dev_name(&pdev->dev);\n" - "> > +=09indio_dev->dev.parent =3D &pdev->dev;\n" - "> > +=09indio_dev->dev.of_node =3D pdev->dev.of_node;\n" - "> > +=09indio_dev->info =3D &rockchip_saradc_iio_info;\n" - "> > +=09indio_dev->modes =3D INDIO_DIRECT_MODE;\n" - "> > +\n" - "> > +=09indio_dev->channels =3D rockchip_saradc_iio_channels;\n" - "> > +=09indio_dev->num_channels =3D ARRAY_SIZE(rockchip_saradc_iio_chan=\n" - "nels);\n" - "> > +\n" - "> > +=09ret =3D iio_device_register(indio_dev);\n" - "> > +=09if (ret)\n" - "> > +=09=09goto err_clk;\n" - "> > +\n" - "> > +=09return 0;\n" + "> > +\tindio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));\n" + "> > +\tif (!indio_dev) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed allocating iio device\\n\");\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\t}\n" + "> > +\tinfo = iio_priv(indio_dev);\n" + "> > +\n" + "> > +\tmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" + "> > +\tinfo->regs = devm_request_and_ioremap(&pdev->dev, mem);\n" + "> > +\tif (!info->regs)\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\n" + "> > +\tirq = platform_get_irq(pdev, 0);\n" + "> > +\tif (irq < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"no irq resource?\\n\");\n" + "> > +\t\treturn irq;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,\n" + "> > +\t\t\t 0, dev_name(&pdev->dev), info);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed requesting irq %d\\n\", irq);\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinit_completion(&info->completion);\n" + "> > +\n" + "> > +\tinfo->pclk = devm_clk_get(&pdev->dev, \"apb_pclk\");\n" + "> > +\tif (IS_ERR(info->pclk)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get pclk\\n\");\n" + "> > +\t\treturn PTR_ERR(info->pclk);\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinfo->clk = devm_clk_get(&pdev->dev, \"saradc\");\n" + "> > +\tif (IS_ERR(info->clk)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get adc clock\\n\");\n" + "> > +\t\treturn PTR_ERR(info->clk);\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinfo->vref = devm_regulator_get(&pdev->dev, \"vref\");\n" + "> > +\tif (IS_ERR(info->vref)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get regulator, %ld\\n\",\n" + "> > +\t\t\tPTR_ERR(info->vref));\n" + "> > +\t\treturn PTR_ERR(info->vref);\n" + "> > +\t}\n" + "> > +\n" + "> > +\t/* use a default of 1MHz for the converter clock */\n" + "> > +\tif (of_property_read_u32(np, \"clock-frequency\", &rate))\n" + "> > +\t\trate = 1000000;\n" + "> > +\n" + "> > +\tret = clk_set_rate(info->clk, rate);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to set adc clk rate, %d\\n\", ret);\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = regulator_enable(info->vref);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable vref regulator\\n\");\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = regulator_get_voltage(info->vref);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get regulator voltage\\n\");\n" + "> > +\t\tgoto err_reg_voltage;\n" + "> > +\t}\n" + "> > +\tinfo->vref_mv = ret / 1000;\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(info->pclk);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable pclk\\n\");\n" + "> > +\t\tgoto err_reg_voltage;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(info->clk);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable converter clock\\n\");\n" + "> > +\t\tgoto err_pclk;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tplatform_set_drvdata(pdev, indio_dev);\n" + "> > +\n" + "> > +\tindio_dev->name = dev_name(&pdev->dev);\n" + "> > +\tindio_dev->dev.parent = &pdev->dev;\n" + "> > +\tindio_dev->dev.of_node = pdev->dev.of_node;\n" + "> > +\tindio_dev->info = &rockchip_saradc_iio_info;\n" + "> > +\tindio_dev->modes = INDIO_DIRECT_MODE;\n" + "> > +\n" + "> > +\tindio_dev->channels = rockchip_saradc_iio_channels;\n" + "> > +\tindio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels);\n" + "> > +\n" + "> > +\tret = iio_device_register(indio_dev);\n" + "> > +\tif (ret)\n" + "> > +\t\tgoto err_clk;\n" + "> > +\n" + "> > +\treturn 0;\n" "> > +\n" "> > +err_clk:\n" - "> > +=09clk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" "> > +err_pclk:\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" "> > +err_reg_voltage:\n" - "> > +=09regulator_disable(info->vref);\n" - "> > +=09return ret;\n" + "> > +\tregulator_disable(info->vref);\n" + "> > +\treturn ret;\n" "> > +}\n" "> > +\n" "> > +static int rockchip_saradc_remove(struct platform_device *pdev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D platform_get_drvdata(pdev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct iio_dev *indio_dev = platform_get_drvdata(pdev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09iio_device_unregister(indio_dev);\n" - "> > +=09clk_disable_unprepare(info->clk);\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" - "> > +=09regulator_disable(info->vref);\n" + "> > +\tiio_device_unregister(indio_dev);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" + "> > +\tregulator_disable(info->vref);\n" "> > +\n" - "> > +=09return 0;\n" + "> > +\treturn 0;\n" "> > +}\n" "> > +\n" "> > +#ifdef CONFIG_PM_SLEEP\n" "> > +static int rockchip_saradc_suspend(struct device *dev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct iio_dev *indio_dev = dev_get_drvdata(dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09clk_disable_unprepare(info->clk);\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" - "> > +=09regulator_disable(info->vref);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" + "> > +\tregulator_disable(info->vref);\n" "> > +\n" - "> > +=09return 0;\n" + "> > +\treturn 0;\n" "> > +}\n" "> > +\n" "> > +static int rockchip_saradc_resume(struct device *dev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" - "> > +=09int ret;\n" + "> > +\tstruct iio_dev *indio_dev = dev_get_drvdata(dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" + "> > +\tint ret;\n" "> > +\n" - "> > +=09ret =3D regulator_enable(info->vref);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = regulator_enable(info->vref);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->pclk);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = clk_prepare_enable(info->pclk);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->clk);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = clk_prepare_enable(info->clk);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09return ret;\n" + "> > +\treturn ret;\n" "> > +}\n" "> > +#endif\n" "> > +\n" "> > +static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,\n" - "> > +=09=09=09 rockchip_saradc_suspend, rockchip_saradc_resume);\n" + "> > +\t\t\t rockchip_saradc_suspend, rockchip_saradc_resume);\n" "> > +\n" - "> > +static const struct of_device_id rockchip_saradc_match[] =3D {\n" - "> > +=09{ .compatible =3D \"rockchip,saradc\" },\n" - "> > +=09{},\n" + "> > +static const struct of_device_id rockchip_saradc_match[] = {\n" + "> > +\t{ .compatible = \"rockchip,saradc\" },\n" + "> > +\t{},\n" "> > +};\n" "> > +MODULE_DEVICE_TABLE(of, rockchip_saradc_match);\n" "> > +\n" - "> > +static struct platform_driver rockchip_saradc_driver =3D {\n" - "> > +=09.probe=09=09=3D rockchip_saradc_probe,\n" - "> > +=09.remove=09=09=3D rockchip_saradc_remove,\n" - "> > +=09.driver=09=09=3D {\n" - "> > +=09=09.name=09=3D \"rockchip-saradc\",\n" - "> > +=09=09.owner=09=3D THIS_MODULE,\n" - "> > +=09=09.of_match_table =3D rockchip_saradc_match,\n" - "> > +=09=09.pm=09=3D &rockchip_saradc_pm_ops,\n" - "> > +=09},\n" + "> > +static struct platform_driver rockchip_saradc_driver = {\n" + "> > +\t.probe\t\t= rockchip_saradc_probe,\n" + "> > +\t.remove\t\t= rockchip_saradc_remove,\n" + "> > +\t.driver\t\t= {\n" + "> > +\t\t.name\t= \"rockchip-saradc\",\n" + "> > +\t\t.owner\t= THIS_MODULE,\n" + "> > +\t\t.of_match_table = rockchip_saradc_match,\n" + "> > +\t\t.pm\t= &rockchip_saradc_pm_ops,\n" + "> > +\t},\n" "> > +};\n" "> > +\n" > > +module_platform_driver(rockchip_saradc_driver); -0e5ea159e619b9e530c8290dde81e56be4a7a3be243f436452570055a638eb61 +1ac983c980931bc0300e4661585823ebb3284078c8d364c41925ea513d0fae17
diff --git a/a/1.txt b/N2/1.txt index 81d2620..b4e8e80 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -1,80 +1,75 @@ Am Sonntag, 13. Juli 2014, 14:09:48 schrieb Hartmut Knaack: -> Heiko St=FCbner schrieb: -> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation= - +> Heiko Stübner schrieb: +> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation > > Register (SAR) A/D Converter. It uses the supply and ground as its -> > reference and converts the analog input signal into 10-bit binary d= -igital +> > reference and converts the analog input signal into 10-bit binary digital > > codes. -> Is there a datasheet available anywhere, or just under some NDA? I've= - got -> some comments in line, which might be answered by reading the datashe= -et. +> Is there a datasheet available anywhere, or just under some NDA? I've got +> some comments in line, which might be answered by reading the datasheet. Sadly, there is no datasheet available to the public. -> > Signed-off-by: Heiko Stuebner <heiko@sntech.de> +> > Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org> > > --- -> >=20 +> > > > changes since v2: > > - address more comments from Peter Meerwald -> >=20 +> > > > mainly the missing info_mask_shared_by_type element -> > =20 +> > > > changes since v1: > > - address comments from Peter Meerwald -> >=20 +> > > > drivers/iio/adc/Kconfig | 10 ++ -> >=20 +> > > > drivers/iio/adc/Makefile | 1 + > > drivers/iio/adc/rockchip_saradc.c | 314 > > ++++++++++++++++++++++++++++++++++++++ 3 files changed, 325 > > insertions(+) > > create mode 100644 drivers/iio/adc/rockchip_saradc.c -> >=20 +> > > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > > index a80d236..5d36bdb 100644 > > --- a/drivers/iio/adc/Kconfig > > +++ b/drivers/iio/adc/Kconfig > > @@ -187,6 +187,16 @@ config NAU7802 -> >=20 -> > =09 To compile this driver as a module, choose M here: the -> > =09 module will be called nau7802. -> >=20 +> > +> > To compile this driver as a module, choose M here: the +> > module will be called nau7802. +> > > > +config ROCKCHIP_SARADC -> > +=09tristate "Rockchip SARADC driver" -> > +=09depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST) -> > +=09help -> > +=09 Say yes here to build support for the SARADC found in SoCs fr= -om -> > +=09 Rockchip. +> > + tristate "Rockchip SARADC driver" +> > + depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST) +> > + help +> > + Say yes here to build support for the SARADC found in SoCs from +> > + Rockchip. > > + -> > +=09 To compile this driver as a module, choose M here: the -> > +=09 module will be called rockchip_saradc. +> > + To compile this driver as a module, choose M here: the +> > + module will be called rockchip_saradc. > > + -> >=20 +> > > > config TI_ADC081C -> > =20 -> > =09tristate "Texas Instruments ADC081C021/027" -> > =09depends on I2C -> >=20 +> > +> > tristate "Texas Instruments ADC081C021/027" +> > depends on I2C +> > > > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > > index 9d60f2d..8e2932d 100644 > > --- a/drivers/iio/adc/Makefile > > +++ b/drivers/iio/adc/Makefile -> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) +=3D mcp320x.o -> >=20 -> > obj-$(CONFIG_MCP3422) +=3D mcp3422.o -> > obj-$(CONFIG_MEN_Z188_ADC) +=3D men_z188_adc.o -> > obj-$(CONFIG_NAU7802) +=3D nau7802.o -> >=20 -> > +obj-$(CONFIG_ROCKCHIP_SARADC) +=3D rockchip_saradc.o -> >=20 -> > obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o -> > obj-$(CONFIG_TI_AM335X_ADC) +=3D ti_am335x_adc.o -> > obj-$(CONFIG_TWL4030_MADC) +=3D twl4030-madc.o -> >=20 +> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o +> > +> > obj-$(CONFIG_MCP3422) += mcp3422.o +> > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o +> > obj-$(CONFIG_NAU7802) += nau7802.o +> > +> > +obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o +> > +> > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o +> > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o +> > obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o +> > > > diff --git a/drivers/iio/adc/rockchip_saradc.c > > b/drivers/iio/adc/rockchip_saradc.c new file mode 100644 > > index 0000000..8fc5867 @@ -84,26 +79,21 @@ om > > +/* > > + * Rockchip Successive Approximation Register (SAR) A/D Converter > > + * Copyright (C) 2014 ROCKCHIP, Inc. ->=20 +> > Does this mean, that you are working for Rockchip? -I'm doing consulting on the mainline integration and the code is largel= -y the=20 +I'm doing consulting on the mainline integration and the code is largely the one taken from the upstream tree and only cleaned up in places. ->=20 +> > > + * -> > + * This program is free software; you can redistribute it and/or m= -odify -> > + * it under the terms of the GNU General Public License as publish= -ed by -> > + * the Free Software Foundation; either version 2 of the License, = -or +> > + * 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,= - +> > + * 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. @@ -119,152 +109,141 @@ or > > +#include <linux/regulator/consumer.h> > > +#include <linux/iio/iio.h> > > + -> > +#define SARADC_DATA=09=09=090x00 -> > +#define SARADC_DATA_MASK=09=090x3ff +> > +#define SARADC_DATA 0x00 +> > +#define SARADC_DATA_MASK 0x3ff > > + -> > +#define SARADC_STAS=09=09=090x04 -> > +#define SARADC_STAS_BUSY=09=09BIT(0) +> > +#define SARADC_STAS 0x04 +> > +#define SARADC_STAS_BUSY BIT(0) > > + -> > +#define SARADC_CTRL=09=09=090x08 -> > +#define SARADC_CTRL_IRQ_STATUS=09=09BIT(6) -> > +#define SARADC_CTRL_IRQ_ENABLE=09=09BIT(5) -> > +#define SARADC_CTRL_POWER_CTRL=09=09BIT(3) -> > +#define SARADC_CTRL_CHN_MASK=09=090x7 +> > +#define SARADC_CTRL 0x08 +> > +#define SARADC_CTRL_IRQ_STATUS BIT(6) +> > +#define SARADC_CTRL_IRQ_ENABLE BIT(5) +> > +#define SARADC_CTRL_POWER_CTRL BIT(3) +> > +#define SARADC_CTRL_CHN_MASK 0x7 > > + -> > +#define SARADC_DLY_PU_SOC=09=090x0c -> > +#define SARADC_DLY_PU_SOC_MASK=09=090x3f +> > +#define SARADC_DLY_PU_SOC 0x0c +> > +#define SARADC_DLY_PU_SOC_MASK 0x3f > > + -> > +#define SARADC_BITS=09=09=0910 -> > +#define SARADC_TIMEOUT=09=09=09msecs_to_jiffies(100) +> > +#define SARADC_BITS 10 +> > +#define SARADC_TIMEOUT msecs_to_jiffies(100) > > + > > +struct rockchip_saradc { -> > +=09void __iomem=09=09*regs; -> > +=09struct clk=09=09*pclk; -> > +=09struct clk=09=09*clk; -> > +=09struct completion=09completion; -> > +=09struct regulator=09*vref; -> > +=09int=09=09=09vref_mv; -> > +=09u16=09=09=09last_val; +> > + void __iomem *regs; +> > + struct clk *pclk; +> > + struct clk *clk; +> > + struct completion completion; +> > + struct regulator *vref; +> > + int vref_mv; +> > + u16 last_val; > > +}; > > + > > +static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, -> > +=09=09=09=09 struct iio_chan_spec const *chan, -> > +=09=09=09=09 int *val, int *val2, long mask) +> > + struct iio_chan_spec const *chan, +> > + int *val, int *val2, long mask) > > +{ -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09switch (mask) { -> > +=09case IIO_CHAN_INFO_RAW: -> > +=09=09mutex_lock(&indio_dev->mlock); +> > + switch (mask) { +> > + case IIO_CHAN_INFO_RAW: +> > + mutex_lock(&indio_dev->mlock); > > + -> > +=09=09/* Select the channel to be used and trigger conversion */ -> > +=09=09writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC); ->=20 -> This could need a bit more explanation. Maybe represent the magic val= -ue of +> > + /* Select the channel to be used and trigger conversion */ +> > + writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC); +> +> This could need a bit more explanation. Maybe represent the magic value of > 0x8 with a more self explaining definition. -This actually isn't a magic value, but the "delay between power up and = -start=20 -command" in clock periods. But you're right, this might benefit from a = -better=20 -explaination, as the channel selection and start is done by the setting= - below. +This actually isn't a magic value, but the "delay between power up and start +command" in clock periods. But you're right, this might benefit from a better +explaination, as the channel selection and start is done by the setting below. -> > +=09=09writel(SARADC_CTRL_POWER_CTRL -> > +=09=09=09=09| (chan->channel & SARADC_CTRL_CHN_MASK) -> > +=09=09=09=09| SARADC_CTRL_IRQ_ENABLE, -> > +=09=09 info->regs + SARADC_CTRL); -> > + -> > +=09=09if (!wait_for_completion_timeout(&info->completion, -> > +=09=09=09=09=09=09 SARADC_TIMEOUT)) { -> > +=09=09=09writel_relaxed(0, info->regs + SARADC_CTRL); -> > +=09=09=09mutex_unlock(&indio_dev->mlock); -> > +=09=09=09return -ETIMEDOUT; -> > +=09=09} -> > + -> > +=09=09*val =3D info->last_val; -> > +=09=09mutex_unlock(&indio_dev->mlock); -> > +=09=09return IIO_VAL_INT; -> > +=09case IIO_CHAN_INFO_SCALE: -> > +=09=09*val =3D info->vref_mv; -> > +=09=09*val2 =3D SARADC_BITS; -> > +=09=09return IIO_VAL_FRACTIONAL_LOG2; ->=20 -> Are there only fixed voltage regulators used, or are there chances th= -at -> variable voltage regulators could be used for vref? In the second cas= -e, it +> > + writel(SARADC_CTRL_POWER_CTRL +> > + | (chan->channel & SARADC_CTRL_CHN_MASK) +> > + | SARADC_CTRL_IRQ_ENABLE, +> > + info->regs + SARADC_CTRL); +> > + +> > + if (!wait_for_completion_timeout(&info->completion, +> > + SARADC_TIMEOUT)) { +> > + writel_relaxed(0, info->regs + SARADC_CTRL); +> > + mutex_unlock(&indio_dev->mlock); +> > + return -ETIMEDOUT; +> > + } +> > + +> > + *val = info->last_val; +> > + mutex_unlock(&indio_dev->mlock); +> > + return IIO_VAL_INT; +> > + case IIO_CHAN_INFO_SCALE: +> > + *val = info->vref_mv; +> > + *val2 = SARADC_BITS; +> > + return IIO_VAL_FRACTIONAL_LOG2; +> +> Are there only fixed voltage regulators used, or are there chances that +> variable voltage regulators could be used for vref? In the second case, it > would be better to determine the current regulator voltage here. -The voltage regulators used are generally variable, but set to a fixed = -setting=20 +The voltage regulators used are generally variable, but set to a fixed setting that is not supposed to be changed. -Nevertheless I think you're right and the driver could be prepared for = -the=20 +Nevertheless I think you're right and the driver could be prepared for the case where the voltage might really change. -> > +=09default: -> > +=09=09return -EINVAL; -> > +=09} +> > + default: +> > + return -EINVAL; +> > + } > > +} > > + > > +static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) > > +{ -> > +=09struct rockchip_saradc *info =3D (struct rockchip_saradc *)dev_= -id; +> > + struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id; > > + -> > +=09/* Read value */ -> > +=09info->last_val =3D readl_relaxed(info->regs + SARADC_DATA); -> > +=09info->last_val &=3D SARADC_DATA_MASK; +> > + /* Read value */ +> > + info->last_val = readl_relaxed(info->regs + SARADC_DATA); +> > + info->last_val &= SARADC_DATA_MASK; > > + -> > +=09/* Clear irq & power down adc */ -> > +=09writel_relaxed(0, info->regs + SARADC_CTRL); +> > + /* Clear irq & power down adc */ +> > + writel_relaxed(0, info->regs + SARADC_CTRL); > > + -> > +=09complete(&info->completion); +> > + complete(&info->completion); > > + -> > +=09return IRQ_HANDLED; +> > + return IRQ_HANDLED; > > +} > > + -> > +static const struct iio_info rockchip_saradc_iio_info =3D { -> > +=09.read_raw =3D rockchip_saradc_read_raw, -> > +=09.driver_module =3D THIS_MODULE, +> > +static const struct iio_info rockchip_saradc_iio_info = { +> > + .read_raw = rockchip_saradc_read_raw, +> > + .driver_module = THIS_MODULE, > > +}; > > + -> > +#define ADC_CHANNEL(_index, _id) {=09=09=09=09\ -> > +=09.type =3D IIO_VOLTAGE,=09=09=09=09=09\ -> > +=09.indexed =3D 1,=09=09=09=09=09=09\ -> > +=09.channel =3D _index,=09=09=09=09=09\ -> > +=09.info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW),=09=09\ -> > +=09.info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE),=09\ -> > +=09.datasheet_name =3D _id,=09=09=09=09=09\ +> > +#define ADC_CHANNEL(_index, _id) { \ +> > + .type = IIO_VOLTAGE, \ +> > + .indexed = 1, \ +> > + .channel = _index, \ +> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +> > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +> > + .datasheet_name = _id, \ > > +} > > + -> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] =3D= - { -> > +=09ADC_CHANNEL(0, "adc0"), -> > +=09ADC_CHANNEL(1, "adc1"), -> > +=09ADC_CHANNEL(2, "adc2"), +> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] = { +> > + ADC_CHANNEL(0, "adc0"), +> > + ADC_CHANNEL(1, "adc1"), +> > + ADC_CHANNEL(2, "adc2"), > > +}; > > + > > +static int rockchip_saradc_probe(struct platform_device *pdev) > > +{ -> > +=09struct rockchip_saradc *info =3D NULL; -> > +=09struct device_node *np =3D pdev->dev.of_node; -> > +=09struct iio_dev *indio_dev =3D NULL; -> > +=09struct resource=09*mem; -> > +=09int ret =3D -ENODEV; -> > +=09int irq; -> > +=09u32 rate; -> > + -> > +=09if (!np) -> > +=09=09return ret; ->=20 -> return -ENODEV is usually used, and a bit more obvious. That would al= -so make +> > + struct rockchip_saradc *info = NULL; +> > + struct device_node *np = pdev->dev.of_node; +> > + struct iio_dev *indio_dev = NULL; +> > + struct resource *mem; +> > + int ret = -ENODEV; +> > + int irq; +> > + u32 rate; +> > + +> > + if (!np) +> > + return ret; +> +> return -ENODEV is usually used, and a bit more obvious. That would also make > the initialization of ret obsolete. ok @@ -274,182 +253,179 @@ Thanks for the review Heiko > > + -> > +=09indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(*info));= - -> > +=09if (!indio_dev) { -> > +=09=09dev_err(&pdev->dev, "failed allocating iio device\n"); -> > +=09=09return -ENOMEM; -> > +=09} -> > +=09info =3D iio_priv(indio_dev); -> > + -> > +=09mem =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); -> > +=09info->regs =3D devm_request_and_ioremap(&pdev->dev, mem); -> > +=09if (!info->regs) -> > +=09=09return -ENOMEM; -> > + -> > +=09irq =3D platform_get_irq(pdev, 0); -> > +=09if (irq < 0) { -> > +=09=09dev_err(&pdev->dev, "no irq resource?\n"); -> > +=09=09return irq; -> > +=09} -> > + -> > +=09ret =3D devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, -> > +=09=09=09 0, dev_name(&pdev->dev), info); -> > +=09if (ret < 0) { -> > +=09=09dev_err(&pdev->dev, "failed requesting irq %d\n", irq); -> > +=09=09return ret; -> > +=09} -> > + -> > +=09init_completion(&info->completion); -> > + -> > +=09info->pclk =3D devm_clk_get(&pdev->dev, "apb_pclk"); -> > +=09if (IS_ERR(info->pclk)) { -> > +=09=09dev_err(&pdev->dev, "failed to get pclk\n"); -> > +=09=09return PTR_ERR(info->pclk); -> > +=09} -> > + -> > +=09info->clk =3D devm_clk_get(&pdev->dev, "saradc"); -> > +=09if (IS_ERR(info->clk)) { -> > +=09=09dev_err(&pdev->dev, "failed to get adc clock\n"); -> > +=09=09return PTR_ERR(info->clk); -> > +=09} -> > + -> > +=09info->vref =3D devm_regulator_get(&pdev->dev, "vref"); -> > +=09if (IS_ERR(info->vref)) { -> > +=09=09dev_err(&pdev->dev, "failed to get regulator, %ld\n", -> > +=09=09=09PTR_ERR(info->vref)); -> > +=09=09return PTR_ERR(info->vref); -> > +=09} -> > + -> > +=09/* use a default of 1MHz for the converter clock */ -> > +=09if (of_property_read_u32(np, "clock-frequency", &rate)) -> > +=09=09rate =3D 1000000; -> > + -> > +=09ret =3D clk_set_rate(info->clk, rate); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret)= -; -> > +=09=09return ret; -> > +=09} -> > + -> > +=09ret =3D regulator_enable(info->vref); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable vref regulator\n"); -> > +=09=09return ret; -> > +=09} -> > + -> > +=09ret =3D regulator_get_voltage(info->vref); -> > +=09if (ret < 0) { -> > +=09=09dev_err(&pdev->dev, "failed to get regulator voltage\n"); -> > +=09=09goto err_reg_voltage; -> > +=09} -> > +=09info->vref_mv =3D ret / 1000; -> > + -> > +=09ret =3D clk_prepare_enable(info->pclk); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable pclk\n"); -> > +=09=09goto err_reg_voltage; -> > +=09} -> > + -> > +=09ret =3D clk_prepare_enable(info->clk); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable converter clock\n"); -> > +=09=09goto err_pclk; -> > +=09} -> > + -> > +=09platform_set_drvdata(pdev, indio_dev); -> > + -> > +=09indio_dev->name =3D dev_name(&pdev->dev); -> > +=09indio_dev->dev.parent =3D &pdev->dev; -> > +=09indio_dev->dev.of_node =3D pdev->dev.of_node; -> > +=09indio_dev->info =3D &rockchip_saradc_iio_info; -> > +=09indio_dev->modes =3D INDIO_DIRECT_MODE; -> > + -> > +=09indio_dev->channels =3D rockchip_saradc_iio_channels; -> > +=09indio_dev->num_channels =3D ARRAY_SIZE(rockchip_saradc_iio_chan= -nels); -> > + -> > +=09ret =3D iio_device_register(indio_dev); -> > +=09if (ret) -> > +=09=09goto err_clk; -> > + -> > +=09return 0; +> > + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); +> > + if (!indio_dev) { +> > + dev_err(&pdev->dev, "failed allocating iio device\n"); +> > + return -ENOMEM; +> > + } +> > + info = iio_priv(indio_dev); +> > + +> > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +> > + info->regs = devm_request_and_ioremap(&pdev->dev, mem); +> > + if (!info->regs) +> > + return -ENOMEM; +> > + +> > + irq = platform_get_irq(pdev, 0); +> > + if (irq < 0) { +> > + dev_err(&pdev->dev, "no irq resource?\n"); +> > + return irq; +> > + } +> > + +> > + ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, +> > + 0, dev_name(&pdev->dev), info); +> > + if (ret < 0) { +> > + dev_err(&pdev->dev, "failed requesting irq %d\n", irq); +> > + return ret; +> > + } +> > + +> > + init_completion(&info->completion); +> > + +> > + info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); +> > + if (IS_ERR(info->pclk)) { +> > + dev_err(&pdev->dev, "failed to get pclk\n"); +> > + return PTR_ERR(info->pclk); +> > + } +> > + +> > + info->clk = devm_clk_get(&pdev->dev, "saradc"); +> > + if (IS_ERR(info->clk)) { +> > + dev_err(&pdev->dev, "failed to get adc clock\n"); +> > + return PTR_ERR(info->clk); +> > + } +> > + +> > + info->vref = devm_regulator_get(&pdev->dev, "vref"); +> > + if (IS_ERR(info->vref)) { +> > + dev_err(&pdev->dev, "failed to get regulator, %ld\n", +> > + PTR_ERR(info->vref)); +> > + return PTR_ERR(info->vref); +> > + } +> > + +> > + /* use a default of 1MHz for the converter clock */ +> > + if (of_property_read_u32(np, "clock-frequency", &rate)) +> > + rate = 1000000; +> > + +> > + ret = clk_set_rate(info->clk, rate); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); +> > + return ret; +> > + } +> > + +> > + ret = regulator_enable(info->vref); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable vref regulator\n"); +> > + return ret; +> > + } +> > + +> > + ret = regulator_get_voltage(info->vref); +> > + if (ret < 0) { +> > + dev_err(&pdev->dev, "failed to get regulator voltage\n"); +> > + goto err_reg_voltage; +> > + } +> > + info->vref_mv = ret / 1000; +> > + +> > + ret = clk_prepare_enable(info->pclk); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable pclk\n"); +> > + goto err_reg_voltage; +> > + } +> > + +> > + ret = clk_prepare_enable(info->clk); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable converter clock\n"); +> > + goto err_pclk; +> > + } +> > + +> > + platform_set_drvdata(pdev, indio_dev); +> > + +> > + indio_dev->name = dev_name(&pdev->dev); +> > + indio_dev->dev.parent = &pdev->dev; +> > + indio_dev->dev.of_node = pdev->dev.of_node; +> > + indio_dev->info = &rockchip_saradc_iio_info; +> > + indio_dev->modes = INDIO_DIRECT_MODE; +> > + +> > + indio_dev->channels = rockchip_saradc_iio_channels; +> > + indio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels); +> > + +> > + ret = iio_device_register(indio_dev); +> > + if (ret) +> > + goto err_clk; +> > + +> > + return 0; > > + > > +err_clk: -> > +=09clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->clk); > > +err_pclk: -> > +=09clk_disable_unprepare(info->pclk); +> > + clk_disable_unprepare(info->pclk); > > +err_reg_voltage: -> > +=09regulator_disable(info->vref); -> > +=09return ret; +> > + regulator_disable(info->vref); +> > + return ret; > > +} > > + > > +static int rockchip_saradc_remove(struct platform_device *pdev) > > +{ -> > +=09struct iio_dev *indio_dev =3D platform_get_drvdata(pdev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct iio_dev *indio_dev = platform_get_drvdata(pdev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09iio_device_unregister(indio_dev); -> > +=09clk_disable_unprepare(info->clk); -> > +=09clk_disable_unprepare(info->pclk); -> > +=09regulator_disable(info->vref); +> > + iio_device_unregister(indio_dev); +> > + clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->pclk); +> > + regulator_disable(info->vref); > > + -> > +=09return 0; +> > + return 0; > > +} > > + > > +#ifdef CONFIG_PM_SLEEP > > +static int rockchip_saradc_suspend(struct device *dev) > > +{ -> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct iio_dev *indio_dev = dev_get_drvdata(dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09clk_disable_unprepare(info->clk); -> > +=09clk_disable_unprepare(info->pclk); -> > +=09regulator_disable(info->vref); +> > + clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->pclk); +> > + regulator_disable(info->vref); > > + -> > +=09return 0; +> > + return 0; > > +} > > + > > +static int rockchip_saradc_resume(struct device *dev) > > +{ -> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); -> > +=09int ret; +> > + struct iio_dev *indio_dev = dev_get_drvdata(dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); +> > + int ret; > > + -> > +=09ret =3D regulator_enable(info->vref); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = regulator_enable(info->vref); +> > + if (ret) +> > + return ret; > > + -> > +=09ret =3D clk_prepare_enable(info->pclk); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = clk_prepare_enable(info->pclk); +> > + if (ret) +> > + return ret; > > + -> > +=09ret =3D clk_prepare_enable(info->clk); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = clk_prepare_enable(info->clk); +> > + if (ret) +> > + return ret; > > + -> > +=09return ret; +> > + return ret; > > +} > > +#endif > > + > > +static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, -> > +=09=09=09 rockchip_saradc_suspend, rockchip_saradc_resume); +> > + rockchip_saradc_suspend, rockchip_saradc_resume); > > + -> > +static const struct of_device_id rockchip_saradc_match[] =3D { -> > +=09{ .compatible =3D "rockchip,saradc" }, -> > +=09{}, +> > +static const struct of_device_id rockchip_saradc_match[] = { +> > + { .compatible = "rockchip,saradc" }, +> > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, rockchip_saradc_match); > > + -> > +static struct platform_driver rockchip_saradc_driver =3D { -> > +=09.probe=09=09=3D rockchip_saradc_probe, -> > +=09.remove=09=09=3D rockchip_saradc_remove, -> > +=09.driver=09=09=3D { -> > +=09=09.name=09=3D "rockchip-saradc", -> > +=09=09.owner=09=3D THIS_MODULE, -> > +=09=09.of_match_table =3D rockchip_saradc_match, -> > +=09=09.pm=09=3D &rockchip_saradc_pm_ops, -> > +=09}, +> > +static struct platform_driver rockchip_saradc_driver = { +> > + .probe = rockchip_saradc_probe, +> > + .remove = rockchip_saradc_remove, +> > + .driver = { +> > + .name = "rockchip-saradc", +> > + .owner = THIS_MODULE, +> > + .of_match_table = rockchip_saradc_match, +> > + .pm = &rockchip_saradc_pm_ops, +> > + }, > > +}; > > + > > +module_platform_driver(rockchip_saradc_driver); diff --git a/a/content_digest b/N2/content_digest index 6c89bb6..73f82e8 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -1,102 +1,98 @@ "ref\02959154.xc8BQActsn@diego\0" "ref\02263220.rhyqmTfAiL@diego\0" "ref\053C2770C.3050701@gmx.de\0" - "From\0Heiko St\303\274bner <heiko@sntech.de>\0" + "ref\053C2770C.3050701-Mmb7MZpHnFY@public.gmane.org\0" + "From\0Heiko St\303\274bner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>\0" "Subject\0Re: [PATCH v3 1/2] iio: adc: add driver for Rockchip saradc\0" "Date\0Sun, 13 Jul 2014 14:33:19 +0200\0" - "To\0Hartmut Knaack <knaack.h@gmx.de>\0" - "Cc\0Jonathan Cameron <jic23@kernel.org>" - linux-arm-kernel@lists.infradead.org - linux-kernel@vger.kernel.org - linux-iio@vger.kernel.org - devicetree@vger.kernel.org - Rob Herring <robh+dt@kernel.org> - Pawel Moll <pawel.moll@arm.com> - Mark Rutland <mark.rutland@arm.com> - Ian Campbell <ijc+devicetree@hellion.org.uk> - Kumar Gala <galak@codeaurora.org> - " eddie(\350\224\241\346\236\253) <cf@rock-chips.com>" - huangtao@rock-chips.com - " Peter Meerwald <pmeerw@pmeerw.net>\0" + "To\0Hartmut Knaack <knaack.h-Mmb7MZpHnFY@public.gmane.org>\0" + "Cc\0Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>" + linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org + linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org + linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org + devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org + Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> + Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> + Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> + Ian Campbell <ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org> + Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> + " eddie(\350\224\241\346\236\253) <cf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>" + huangtao-TNX95d0MmH7DzftRWevZcw@public.gmane.org + " Peter Meerwald <pmeerw-jW+XmwGofnusTnJN9+BGXg@public.gmane.org>\0" "\00:1\0" "b\0" "Am Sonntag, 13. Juli 2014, 14:09:48 schrieb Hartmut Knaack:\n" - "> Heiko St=FCbner schrieb:\n" - "> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation=\n" - "\n" + "> Heiko St\303\274bner schrieb:\n" + "> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation\n" "> > Register (SAR) A/D Converter. It uses the supply and ground as its\n" - "> > reference and converts the analog input signal into 10-bit binary d=\n" - "igital\n" + "> > reference and converts the analog input signal into 10-bit binary digital\n" "> > codes.\n" - "> Is there a datasheet available anywhere, or just under some NDA? I've=\n" - " got\n" - "> some comments in line, which might be answered by reading the datashe=\n" - "et.\n" + "> Is there a datasheet available anywhere, or just under some NDA? I've got\n" + "> some comments in line, which might be answered by reading the datasheet.\n" "\n" "Sadly, there is no datasheet available to the public.\n" "\n" "\n" - "> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>\n" + "> > Signed-off-by: Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>\n" "> > ---\n" - "> >=20\n" + "> > \n" "> > changes since v2:\n" "> > - address more comments from Peter Meerwald\n" - "> >=20\n" + "> > \n" "> > mainly the missing info_mask_shared_by_type element\n" - "> > =20\n" + "> > \n" "> > changes since v1:\n" "> > - address comments from Peter Meerwald\n" - "> >=20\n" + "> > \n" "> > drivers/iio/adc/Kconfig | 10 ++\n" - "> >=20\n" + "> > \n" "> > drivers/iio/adc/Makefile | 1 +\n" "> > drivers/iio/adc/rockchip_saradc.c | 314\n" "> > ++++++++++++++++++++++++++++++++++++++ 3 files changed, 325\n" "> > insertions(+)\n" "> > create mode 100644 drivers/iio/adc/rockchip_saradc.c\n" - "> >=20\n" + "> > \n" "> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig\n" "> > index a80d236..5d36bdb 100644\n" "> > --- a/drivers/iio/adc/Kconfig\n" "> > +++ b/drivers/iio/adc/Kconfig\n" "> > @@ -187,6 +187,16 @@ config NAU7802\n" - "> >=20\n" - "> > =09 To compile this driver as a module, choose M here: the\n" - "> > =09 module will be called nau7802.\n" - "> >=20\n" + "> > \n" + "> > \t To compile this driver as a module, choose M here: the\n" + "> > \t module will be called nau7802.\n" + "> > \n" "> > +config ROCKCHIP_SARADC\n" - "> > +=09tristate \"Rockchip SARADC driver\"\n" - "> > +=09depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST)\n" - "> > +=09help\n" - "> > +=09 Say yes here to build support for the SARADC found in SoCs fr=\n" - "om\n" - "> > +=09 Rockchip.\n" + "> > +\ttristate \"Rockchip SARADC driver\"\n" + "> > +\tdepends on ARCH_ROCKCHIP || (OF && COMPILE_TEST)\n" + "> > +\thelp\n" + "> > +\t Say yes here to build support for the SARADC found in SoCs from\n" + "> > +\t Rockchip.\n" "> > +\n" - "> > +=09 To compile this driver as a module, choose M here: the\n" - "> > +=09 module will be called rockchip_saradc.\n" + "> > +\t To compile this driver as a module, choose M here: the\n" + "> > +\t module will be called rockchip_saradc.\n" "> > +\n" - "> >=20\n" + "> > \n" "> > config TI_ADC081C\n" - "> > =20\n" - "> > =09tristate \"Texas Instruments ADC081C021/027\"\n" - "> > =09depends on I2C\n" - "> >=20\n" + "> > \n" + "> > \ttristate \"Texas Instruments ADC081C021/027\"\n" + "> > \tdepends on I2C\n" + "> > \n" "> > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile\n" "> > index 9d60f2d..8e2932d 100644\n" "> > --- a/drivers/iio/adc/Makefile\n" "> > +++ b/drivers/iio/adc/Makefile\n" - "> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) +=3D mcp320x.o\n" - "> >=20\n" - "> > obj-$(CONFIG_MCP3422) +=3D mcp3422.o\n" - "> > obj-$(CONFIG_MEN_Z188_ADC) +=3D men_z188_adc.o\n" - "> > obj-$(CONFIG_NAU7802) +=3D nau7802.o\n" - "> >=20\n" - "> > +obj-$(CONFIG_ROCKCHIP_SARADC) +=3D rockchip_saradc.o\n" - "> >=20\n" - "> > obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o\n" - "> > obj-$(CONFIG_TI_AM335X_ADC) +=3D ti_am335x_adc.o\n" - "> > obj-$(CONFIG_TWL4030_MADC) +=3D twl4030-madc.o\n" - "> >=20\n" + "> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o\n" + "> > \n" + "> > obj-$(CONFIG_MCP3422) += mcp3422.o\n" + "> > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o\n" + "> > obj-$(CONFIG_NAU7802) += nau7802.o\n" + "> > \n" + "> > +obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o\n" + "> > \n" + "> > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o\n" + "> > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o\n" + "> > obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o\n" + "> > \n" "> > diff --git a/drivers/iio/adc/rockchip_saradc.c\n" "> > b/drivers/iio/adc/rockchip_saradc.c new file mode 100644\n" "> > index 0000000..8fc5867\n" @@ -106,26 +102,21 @@ "> > +/*\n" "> > + * Rockchip Successive Approximation Register (SAR) A/D Converter\n" "> > + * Copyright (C) 2014 ROCKCHIP, Inc.\n" - ">=20\n" + "> \n" "> Does this mean, that you are working for Rockchip?\n" "\n" - "I'm doing consulting on the mainline integration and the code is largel=\n" - "y the=20\n" + "I'm doing consulting on the mainline integration and the code is largely the \n" "one taken from the upstream tree and only cleaned up in places.\n" "\n" "\n" - ">=20\n" + "> \n" "> > + *\n" - "> > + * This program is free software; you can redistribute it and/or m=\n" - "odify\n" - "> > + * it under the terms of the GNU General Public License as publish=\n" - "ed by\n" - "> > + * the Free Software Foundation; either version 2 of the License, =\n" - "or\n" + "> > + * This program is free software; you can redistribute it and/or modify\n" + "> > + * it under the terms of the GNU General Public License as published by\n" + "> > + * the Free Software Foundation; either version 2 of the License, or\n" "> > + * (at your option) any later version.\n" "> > + *\n" - "> > + * This program is distributed in the hope that it will be useful,=\n" - "\n" + "> > + * This program is distributed in the hope that it will be useful,\n" "> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "> > + * GNU General Public License for more details.\n" @@ -141,152 +132,141 @@ "> > +#include <linux/regulator/consumer.h>\n" "> > +#include <linux/iio/iio.h>\n" "> > +\n" - "> > +#define SARADC_DATA=09=09=090x00\n" - "> > +#define SARADC_DATA_MASK=09=090x3ff\n" + "> > +#define SARADC_DATA\t\t\t0x00\n" + "> > +#define SARADC_DATA_MASK\t\t0x3ff\n" "> > +\n" - "> > +#define SARADC_STAS=09=09=090x04\n" - "> > +#define SARADC_STAS_BUSY=09=09BIT(0)\n" + "> > +#define SARADC_STAS\t\t\t0x04\n" + "> > +#define SARADC_STAS_BUSY\t\tBIT(0)\n" "> > +\n" - "> > +#define SARADC_CTRL=09=09=090x08\n" - "> > +#define SARADC_CTRL_IRQ_STATUS=09=09BIT(6)\n" - "> > +#define SARADC_CTRL_IRQ_ENABLE=09=09BIT(5)\n" - "> > +#define SARADC_CTRL_POWER_CTRL=09=09BIT(3)\n" - "> > +#define SARADC_CTRL_CHN_MASK=09=090x7\n" + "> > +#define SARADC_CTRL\t\t\t0x08\n" + "> > +#define SARADC_CTRL_IRQ_STATUS\t\tBIT(6)\n" + "> > +#define SARADC_CTRL_IRQ_ENABLE\t\tBIT(5)\n" + "> > +#define SARADC_CTRL_POWER_CTRL\t\tBIT(3)\n" + "> > +#define SARADC_CTRL_CHN_MASK\t\t0x7\n" "> > +\n" - "> > +#define SARADC_DLY_PU_SOC=09=090x0c\n" - "> > +#define SARADC_DLY_PU_SOC_MASK=09=090x3f\n" + "> > +#define SARADC_DLY_PU_SOC\t\t0x0c\n" + "> > +#define SARADC_DLY_PU_SOC_MASK\t\t0x3f\n" "> > +\n" - "> > +#define SARADC_BITS=09=09=0910\n" - "> > +#define SARADC_TIMEOUT=09=09=09msecs_to_jiffies(100)\n" + "> > +#define SARADC_BITS\t\t\t10\n" + "> > +#define SARADC_TIMEOUT\t\t\tmsecs_to_jiffies(100)\n" "> > +\n" "> > +struct rockchip_saradc {\n" - "> > +=09void __iomem=09=09*regs;\n" - "> > +=09struct clk=09=09*pclk;\n" - "> > +=09struct clk=09=09*clk;\n" - "> > +=09struct completion=09completion;\n" - "> > +=09struct regulator=09*vref;\n" - "> > +=09int=09=09=09vref_mv;\n" - "> > +=09u16=09=09=09last_val;\n" + "> > +\tvoid __iomem\t\t*regs;\n" + "> > +\tstruct clk\t\t*pclk;\n" + "> > +\tstruct clk\t\t*clk;\n" + "> > +\tstruct completion\tcompletion;\n" + "> > +\tstruct regulator\t*vref;\n" + "> > +\tint\t\t\tvref_mv;\n" + "> > +\tu16\t\t\tlast_val;\n" "> > +};\n" "> > +\n" "> > +static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,\n" - "> > +=09=09=09=09 struct iio_chan_spec const *chan,\n" - "> > +=09=09=09=09 int *val, int *val2, long mask)\n" + "> > +\t\t\t\t struct iio_chan_spec const *chan,\n" + "> > +\t\t\t\t int *val, int *val2, long mask)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09switch (mask) {\n" - "> > +=09case IIO_CHAN_INFO_RAW:\n" - "> > +=09=09mutex_lock(&indio_dev->mlock);\n" + "> > +\tswitch (mask) {\n" + "> > +\tcase IIO_CHAN_INFO_RAW:\n" + "> > +\t\tmutex_lock(&indio_dev->mlock);\n" "> > +\n" - "> > +=09=09/* Select the channel to be used and trigger conversion */\n" - "> > +=09=09writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC);\n" - ">=20\n" - "> This could need a bit more explanation. Maybe represent the magic val=\n" - "ue of\n" + "> > +\t\t/* Select the channel to be used and trigger conversion */\n" + "> > +\t\twritel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC);\n" + "> \n" + "> This could need a bit more explanation. Maybe represent the magic value of\n" "> 0x8 with a more self explaining definition.\n" "\n" - "This actually isn't a magic value, but the \"delay between power up and =\n" - "start=20\n" - "command\" in clock periods. But you're right, this might benefit from a =\n" - "better=20\n" - "explaination, as the channel selection and start is done by the setting=\n" - " below.\n" + "This actually isn't a magic value, but the \"delay between power up and start \n" + "command\" in clock periods. But you're right, this might benefit from a better \n" + "explaination, as the channel selection and start is done by the setting below.\n" "\n" "\n" - "> > +=09=09writel(SARADC_CTRL_POWER_CTRL\n" - "> > +=09=09=09=09| (chan->channel & SARADC_CTRL_CHN_MASK)\n" - "> > +=09=09=09=09| SARADC_CTRL_IRQ_ENABLE,\n" - "> > +=09=09 info->regs + SARADC_CTRL);\n" - "> > +\n" - "> > +=09=09if (!wait_for_completion_timeout(&info->completion,\n" - "> > +=09=09=09=09=09=09 SARADC_TIMEOUT)) {\n" - "> > +=09=09=09writel_relaxed(0, info->regs + SARADC_CTRL);\n" - "> > +=09=09=09mutex_unlock(&indio_dev->mlock);\n" - "> > +=09=09=09return -ETIMEDOUT;\n" - "> > +=09=09}\n" - "> > +\n" - "> > +=09=09*val =3D info->last_val;\n" - "> > +=09=09mutex_unlock(&indio_dev->mlock);\n" - "> > +=09=09return IIO_VAL_INT;\n" - "> > +=09case IIO_CHAN_INFO_SCALE:\n" - "> > +=09=09*val =3D info->vref_mv;\n" - "> > +=09=09*val2 =3D SARADC_BITS;\n" - "> > +=09=09return IIO_VAL_FRACTIONAL_LOG2;\n" - ">=20\n" - "> Are there only fixed voltage regulators used, or are there chances th=\n" - "at\n" - "> variable voltage regulators could be used for vref? In the second cas=\n" - "e, it\n" + "> > +\t\twritel(SARADC_CTRL_POWER_CTRL\n" + "> > +\t\t\t\t| (chan->channel & SARADC_CTRL_CHN_MASK)\n" + "> > +\t\t\t\t| SARADC_CTRL_IRQ_ENABLE,\n" + "> > +\t\t info->regs + SARADC_CTRL);\n" + "> > +\n" + "> > +\t\tif (!wait_for_completion_timeout(&info->completion,\n" + "> > +\t\t\t\t\t\t SARADC_TIMEOUT)) {\n" + "> > +\t\t\twritel_relaxed(0, info->regs + SARADC_CTRL);\n" + "> > +\t\t\tmutex_unlock(&indio_dev->mlock);\n" + "> > +\t\t\treturn -ETIMEDOUT;\n" + "> > +\t\t}\n" + "> > +\n" + "> > +\t\t*val = info->last_val;\n" + "> > +\t\tmutex_unlock(&indio_dev->mlock);\n" + "> > +\t\treturn IIO_VAL_INT;\n" + "> > +\tcase IIO_CHAN_INFO_SCALE:\n" + "> > +\t\t*val = info->vref_mv;\n" + "> > +\t\t*val2 = SARADC_BITS;\n" + "> > +\t\treturn IIO_VAL_FRACTIONAL_LOG2;\n" + "> \n" + "> Are there only fixed voltage regulators used, or are there chances that\n" + "> variable voltage regulators could be used for vref? In the second case, it\n" "> would be better to determine the current regulator voltage here.\n" "\n" - "The voltage regulators used are generally variable, but set to a fixed =\n" - "setting=20\n" + "The voltage regulators used are generally variable, but set to a fixed setting \n" "that is not supposed to be changed.\n" "\n" - "Nevertheless I think you're right and the driver could be prepared for =\n" - "the=20\n" + "Nevertheless I think you're right and the driver could be prepared for the \n" "case where the voltage might really change.\n" "\n" "\n" - "> > +=09default:\n" - "> > +=09=09return -EINVAL;\n" - "> > +=09}\n" + "> > +\tdefault:\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\t}\n" "> > +}\n" "> > +\n" "> > +static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D (struct rockchip_saradc *)dev_=\n" - "id;\n" + "> > +\tstruct rockchip_saradc *info = (struct rockchip_saradc *)dev_id;\n" "> > +\n" - "> > +=09/* Read value */\n" - "> > +=09info->last_val =3D readl_relaxed(info->regs + SARADC_DATA);\n" - "> > +=09info->last_val &=3D SARADC_DATA_MASK;\n" + "> > +\t/* Read value */\n" + "> > +\tinfo->last_val = readl_relaxed(info->regs + SARADC_DATA);\n" + "> > +\tinfo->last_val &= SARADC_DATA_MASK;\n" "> > +\n" - "> > +=09/* Clear irq & power down adc */\n" - "> > +=09writel_relaxed(0, info->regs + SARADC_CTRL);\n" + "> > +\t/* Clear irq & power down adc */\n" + "> > +\twritel_relaxed(0, info->regs + SARADC_CTRL);\n" "> > +\n" - "> > +=09complete(&info->completion);\n" + "> > +\tcomplete(&info->completion);\n" "> > +\n" - "> > +=09return IRQ_HANDLED;\n" + "> > +\treturn IRQ_HANDLED;\n" "> > +}\n" "> > +\n" - "> > +static const struct iio_info rockchip_saradc_iio_info =3D {\n" - "> > +=09.read_raw =3D rockchip_saradc_read_raw,\n" - "> > +=09.driver_module =3D THIS_MODULE,\n" + "> > +static const struct iio_info rockchip_saradc_iio_info = {\n" + "> > +\t.read_raw = rockchip_saradc_read_raw,\n" + "> > +\t.driver_module = THIS_MODULE,\n" "> > +};\n" "> > +\n" - "> > +#define ADC_CHANNEL(_index, _id) {=09=09=09=09\\\n" - "> > +=09.type =3D IIO_VOLTAGE,=09=09=09=09=09\\\n" - "> > +=09.indexed =3D 1,=09=09=09=09=09=09\\\n" - "> > +=09.channel =3D _index,=09=09=09=09=09\\\n" - "> > +=09.info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW),=09=09\\\n" - "> > +=09.info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE),=09\\\n" - "> > +=09.datasheet_name =3D _id,=09=09=09=09=09\\\n" + "> > +#define ADC_CHANNEL(_index, _id) {\t\t\t\t\\\n" + "> > +\t.type = IIO_VOLTAGE,\t\t\t\t\t\\\n" + "> > +\t.indexed = 1,\t\t\t\t\t\t\\\n" + "> > +\t.channel = _index,\t\t\t\t\t\\\n" + "> > +\t.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),\t\t\\\n" + "> > +\t.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\t\\\n" + "> > +\t.datasheet_name = _id,\t\t\t\t\t\\\n" "> > +}\n" "> > +\n" - "> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] =3D=\n" - " {\n" - "> > +=09ADC_CHANNEL(0, \"adc0\"),\n" - "> > +=09ADC_CHANNEL(1, \"adc1\"),\n" - "> > +=09ADC_CHANNEL(2, \"adc2\"),\n" + "> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {\n" + "> > +\tADC_CHANNEL(0, \"adc0\"),\n" + "> > +\tADC_CHANNEL(1, \"adc1\"),\n" + "> > +\tADC_CHANNEL(2, \"adc2\"),\n" "> > +};\n" "> > +\n" "> > +static int rockchip_saradc_probe(struct platform_device *pdev)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D NULL;\n" - "> > +=09struct device_node *np =3D pdev->dev.of_node;\n" - "> > +=09struct iio_dev *indio_dev =3D NULL;\n" - "> > +=09struct resource=09*mem;\n" - "> > +=09int ret =3D -ENODEV;\n" - "> > +=09int irq;\n" - "> > +=09u32 rate;\n" - "> > +\n" - "> > +=09if (!np)\n" - "> > +=09=09return ret;\n" - ">=20\n" - "> return -ENODEV is usually used, and a bit more obvious. That would al=\n" - "so make\n" + "> > +\tstruct rockchip_saradc *info = NULL;\n" + "> > +\tstruct device_node *np = pdev->dev.of_node;\n" + "> > +\tstruct iio_dev *indio_dev = NULL;\n" + "> > +\tstruct resource\t*mem;\n" + "> > +\tint ret = -ENODEV;\n" + "> > +\tint irq;\n" + "> > +\tu32 rate;\n" + "> > +\n" + "> > +\tif (!np)\n" + "> > +\t\treturn ret;\n" + "> \n" + "> return -ENODEV is usually used, and a bit more obvious. That would also make\n" "> the initialization of ret obsolete.\n" "\n" "ok\n" @@ -296,184 +276,181 @@ "Heiko\n" "\n" "> > +\n" - "> > +=09indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(*info));=\n" - "\n" - "> > +=09if (!indio_dev) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed allocating iio device\\n\");\n" - "> > +=09=09return -ENOMEM;\n" - "> > +=09}\n" - "> > +=09info =3D iio_priv(indio_dev);\n" - "> > +\n" - "> > +=09mem =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" - "> > +=09info->regs =3D devm_request_and_ioremap(&pdev->dev, mem);\n" - "> > +=09if (!info->regs)\n" - "> > +=09=09return -ENOMEM;\n" - "> > +\n" - "> > +=09irq =3D platform_get_irq(pdev, 0);\n" - "> > +=09if (irq < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"no irq resource?\\n\");\n" - "> > +=09=09return irq;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,\n" - "> > +=09=09=09 0, dev_name(&pdev->dev), info);\n" - "> > +=09if (ret < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed requesting irq %d\\n\", irq);\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09init_completion(&info->completion);\n" - "> > +\n" - "> > +=09info->pclk =3D devm_clk_get(&pdev->dev, \"apb_pclk\");\n" - "> > +=09if (IS_ERR(info->pclk)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get pclk\\n\");\n" - "> > +=09=09return PTR_ERR(info->pclk);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09info->clk =3D devm_clk_get(&pdev->dev, \"saradc\");\n" - "> > +=09if (IS_ERR(info->clk)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get adc clock\\n\");\n" - "> > +=09=09return PTR_ERR(info->clk);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09info->vref =3D devm_regulator_get(&pdev->dev, \"vref\");\n" - "> > +=09if (IS_ERR(info->vref)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get regulator, %ld\\n\",\n" - "> > +=09=09=09PTR_ERR(info->vref));\n" - "> > +=09=09return PTR_ERR(info->vref);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09/* use a default of 1MHz for the converter clock */\n" - "> > +=09if (of_property_read_u32(np, \"clock-frequency\", &rate))\n" - "> > +=09=09rate =3D 1000000;\n" - "> > +\n" - "> > +=09ret =3D clk_set_rate(info->clk, rate);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to set adc clk rate, %d\\n\", ret)=\n" - ";\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D regulator_enable(info->vref);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable vref regulator\\n\");\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D regulator_get_voltage(info->vref);\n" - "> > +=09if (ret < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get regulator voltage\\n\");\n" - "> > +=09=09goto err_reg_voltage;\n" - "> > +=09}\n" - "> > +=09info->vref_mv =3D ret / 1000;\n" - "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->pclk);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable pclk\\n\");\n" - "> > +=09=09goto err_reg_voltage;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->clk);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable converter clock\\n\");\n" - "> > +=09=09goto err_pclk;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09platform_set_drvdata(pdev, indio_dev);\n" - "> > +\n" - "> > +=09indio_dev->name =3D dev_name(&pdev->dev);\n" - "> > +=09indio_dev->dev.parent =3D &pdev->dev;\n" - "> > +=09indio_dev->dev.of_node =3D pdev->dev.of_node;\n" - "> > +=09indio_dev->info =3D &rockchip_saradc_iio_info;\n" - "> > +=09indio_dev->modes =3D INDIO_DIRECT_MODE;\n" - "> > +\n" - "> > +=09indio_dev->channels =3D rockchip_saradc_iio_channels;\n" - "> > +=09indio_dev->num_channels =3D ARRAY_SIZE(rockchip_saradc_iio_chan=\n" - "nels);\n" - "> > +\n" - "> > +=09ret =3D iio_device_register(indio_dev);\n" - "> > +=09if (ret)\n" - "> > +=09=09goto err_clk;\n" - "> > +\n" - "> > +=09return 0;\n" + "> > +\tindio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));\n" + "> > +\tif (!indio_dev) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed allocating iio device\\n\");\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\t}\n" + "> > +\tinfo = iio_priv(indio_dev);\n" + "> > +\n" + "> > +\tmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" + "> > +\tinfo->regs = devm_request_and_ioremap(&pdev->dev, mem);\n" + "> > +\tif (!info->regs)\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\n" + "> > +\tirq = platform_get_irq(pdev, 0);\n" + "> > +\tif (irq < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"no irq resource?\\n\");\n" + "> > +\t\treturn irq;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,\n" + "> > +\t\t\t 0, dev_name(&pdev->dev), info);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed requesting irq %d\\n\", irq);\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinit_completion(&info->completion);\n" + "> > +\n" + "> > +\tinfo->pclk = devm_clk_get(&pdev->dev, \"apb_pclk\");\n" + "> > +\tif (IS_ERR(info->pclk)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get pclk\\n\");\n" + "> > +\t\treturn PTR_ERR(info->pclk);\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinfo->clk = devm_clk_get(&pdev->dev, \"saradc\");\n" + "> > +\tif (IS_ERR(info->clk)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get adc clock\\n\");\n" + "> > +\t\treturn PTR_ERR(info->clk);\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinfo->vref = devm_regulator_get(&pdev->dev, \"vref\");\n" + "> > +\tif (IS_ERR(info->vref)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get regulator, %ld\\n\",\n" + "> > +\t\t\tPTR_ERR(info->vref));\n" + "> > +\t\treturn PTR_ERR(info->vref);\n" + "> > +\t}\n" + "> > +\n" + "> > +\t/* use a default of 1MHz for the converter clock */\n" + "> > +\tif (of_property_read_u32(np, \"clock-frequency\", &rate))\n" + "> > +\t\trate = 1000000;\n" + "> > +\n" + "> > +\tret = clk_set_rate(info->clk, rate);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to set adc clk rate, %d\\n\", ret);\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = regulator_enable(info->vref);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable vref regulator\\n\");\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = regulator_get_voltage(info->vref);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get regulator voltage\\n\");\n" + "> > +\t\tgoto err_reg_voltage;\n" + "> > +\t}\n" + "> > +\tinfo->vref_mv = ret / 1000;\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(info->pclk);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable pclk\\n\");\n" + "> > +\t\tgoto err_reg_voltage;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(info->clk);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable converter clock\\n\");\n" + "> > +\t\tgoto err_pclk;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tplatform_set_drvdata(pdev, indio_dev);\n" + "> > +\n" + "> > +\tindio_dev->name = dev_name(&pdev->dev);\n" + "> > +\tindio_dev->dev.parent = &pdev->dev;\n" + "> > +\tindio_dev->dev.of_node = pdev->dev.of_node;\n" + "> > +\tindio_dev->info = &rockchip_saradc_iio_info;\n" + "> > +\tindio_dev->modes = INDIO_DIRECT_MODE;\n" + "> > +\n" + "> > +\tindio_dev->channels = rockchip_saradc_iio_channels;\n" + "> > +\tindio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels);\n" + "> > +\n" + "> > +\tret = iio_device_register(indio_dev);\n" + "> > +\tif (ret)\n" + "> > +\t\tgoto err_clk;\n" + "> > +\n" + "> > +\treturn 0;\n" "> > +\n" "> > +err_clk:\n" - "> > +=09clk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" "> > +err_pclk:\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" "> > +err_reg_voltage:\n" - "> > +=09regulator_disable(info->vref);\n" - "> > +=09return ret;\n" + "> > +\tregulator_disable(info->vref);\n" + "> > +\treturn ret;\n" "> > +}\n" "> > +\n" "> > +static int rockchip_saradc_remove(struct platform_device *pdev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D platform_get_drvdata(pdev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct iio_dev *indio_dev = platform_get_drvdata(pdev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09iio_device_unregister(indio_dev);\n" - "> > +=09clk_disable_unprepare(info->clk);\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" - "> > +=09regulator_disable(info->vref);\n" + "> > +\tiio_device_unregister(indio_dev);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" + "> > +\tregulator_disable(info->vref);\n" "> > +\n" - "> > +=09return 0;\n" + "> > +\treturn 0;\n" "> > +}\n" "> > +\n" "> > +#ifdef CONFIG_PM_SLEEP\n" "> > +static int rockchip_saradc_suspend(struct device *dev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct iio_dev *indio_dev = dev_get_drvdata(dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09clk_disable_unprepare(info->clk);\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" - "> > +=09regulator_disable(info->vref);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" + "> > +\tregulator_disable(info->vref);\n" "> > +\n" - "> > +=09return 0;\n" + "> > +\treturn 0;\n" "> > +}\n" "> > +\n" "> > +static int rockchip_saradc_resume(struct device *dev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" - "> > +=09int ret;\n" + "> > +\tstruct iio_dev *indio_dev = dev_get_drvdata(dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" + "> > +\tint ret;\n" "> > +\n" - "> > +=09ret =3D regulator_enable(info->vref);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = regulator_enable(info->vref);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->pclk);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = clk_prepare_enable(info->pclk);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->clk);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = clk_prepare_enable(info->clk);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09return ret;\n" + "> > +\treturn ret;\n" "> > +}\n" "> > +#endif\n" "> > +\n" "> > +static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,\n" - "> > +=09=09=09 rockchip_saradc_suspend, rockchip_saradc_resume);\n" + "> > +\t\t\t rockchip_saradc_suspend, rockchip_saradc_resume);\n" "> > +\n" - "> > +static const struct of_device_id rockchip_saradc_match[] =3D {\n" - "> > +=09{ .compatible =3D \"rockchip,saradc\" },\n" - "> > +=09{},\n" + "> > +static const struct of_device_id rockchip_saradc_match[] = {\n" + "> > +\t{ .compatible = \"rockchip,saradc\" },\n" + "> > +\t{},\n" "> > +};\n" "> > +MODULE_DEVICE_TABLE(of, rockchip_saradc_match);\n" "> > +\n" - "> > +static struct platform_driver rockchip_saradc_driver =3D {\n" - "> > +=09.probe=09=09=3D rockchip_saradc_probe,\n" - "> > +=09.remove=09=09=3D rockchip_saradc_remove,\n" - "> > +=09.driver=09=09=3D {\n" - "> > +=09=09.name=09=3D \"rockchip-saradc\",\n" - "> > +=09=09.owner=09=3D THIS_MODULE,\n" - "> > +=09=09.of_match_table =3D rockchip_saradc_match,\n" - "> > +=09=09.pm=09=3D &rockchip_saradc_pm_ops,\n" - "> > +=09},\n" + "> > +static struct platform_driver rockchip_saradc_driver = {\n" + "> > +\t.probe\t\t= rockchip_saradc_probe,\n" + "> > +\t.remove\t\t= rockchip_saradc_remove,\n" + "> > +\t.driver\t\t= {\n" + "> > +\t\t.name\t= \"rockchip-saradc\",\n" + "> > +\t\t.owner\t= THIS_MODULE,\n" + "> > +\t\t.of_match_table = rockchip_saradc_match,\n" + "> > +\t\t.pm\t= &rockchip_saradc_pm_ops,\n" + "> > +\t},\n" "> > +};\n" "> > +\n" > > +module_platform_driver(rockchip_saradc_driver); -0e5ea159e619b9e530c8290dde81e56be4a7a3be243f436452570055a638eb61 +d21967e9961d8f3098c8b2845761b692f4454de7699e4a94c1d18b08dcfbcd42
diff --git a/a/1.txt b/N3/1.txt index 81d2620..9bc8c76 100644 --- a/a/1.txt +++ b/N3/1.txt @@ -1,80 +1,75 @@ Am Sonntag, 13. Juli 2014, 14:09:48 schrieb Hartmut Knaack: -> Heiko St=FCbner schrieb: -> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation= - +> Heiko Stübner schrieb: +> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation > > Register (SAR) A/D Converter. It uses the supply and ground as its -> > reference and converts the analog input signal into 10-bit binary d= -igital +> > reference and converts the analog input signal into 10-bit binary digital > > codes. -> Is there a datasheet available anywhere, or just under some NDA? I've= - got -> some comments in line, which might be answered by reading the datashe= -et. +> Is there a datasheet available anywhere, or just under some NDA? I've got +> some comments in line, which might be answered by reading the datasheet. Sadly, there is no datasheet available to the public. > > Signed-off-by: Heiko Stuebner <heiko@sntech.de> > > --- -> >=20 +> > > > changes since v2: > > - address more comments from Peter Meerwald -> >=20 +> > > > mainly the missing info_mask_shared_by_type element -> > =20 +> > > > changes since v1: > > - address comments from Peter Meerwald -> >=20 +> > > > drivers/iio/adc/Kconfig | 10 ++ -> >=20 +> > > > drivers/iio/adc/Makefile | 1 + > > drivers/iio/adc/rockchip_saradc.c | 314 > > ++++++++++++++++++++++++++++++++++++++ 3 files changed, 325 > > insertions(+) > > create mode 100644 drivers/iio/adc/rockchip_saradc.c -> >=20 +> > > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > > index a80d236..5d36bdb 100644 > > --- a/drivers/iio/adc/Kconfig > > +++ b/drivers/iio/adc/Kconfig > > @@ -187,6 +187,16 @@ config NAU7802 -> >=20 -> > =09 To compile this driver as a module, choose M here: the -> > =09 module will be called nau7802. -> >=20 +> > +> > To compile this driver as a module, choose M here: the +> > module will be called nau7802. +> > > > +config ROCKCHIP_SARADC -> > +=09tristate "Rockchip SARADC driver" -> > +=09depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST) -> > +=09help -> > +=09 Say yes here to build support for the SARADC found in SoCs fr= -om -> > +=09 Rockchip. +> > + tristate "Rockchip SARADC driver" +> > + depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST) +> > + help +> > + Say yes here to build support for the SARADC found in SoCs from +> > + Rockchip. > > + -> > +=09 To compile this driver as a module, choose M here: the -> > +=09 module will be called rockchip_saradc. +> > + To compile this driver as a module, choose M here: the +> > + module will be called rockchip_saradc. > > + -> >=20 +> > > > config TI_ADC081C -> > =20 -> > =09tristate "Texas Instruments ADC081C021/027" -> > =09depends on I2C -> >=20 +> > +> > tristate "Texas Instruments ADC081C021/027" +> > depends on I2C +> > > > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > > index 9d60f2d..8e2932d 100644 > > --- a/drivers/iio/adc/Makefile > > +++ b/drivers/iio/adc/Makefile -> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) +=3D mcp320x.o -> >=20 -> > obj-$(CONFIG_MCP3422) +=3D mcp3422.o -> > obj-$(CONFIG_MEN_Z188_ADC) +=3D men_z188_adc.o -> > obj-$(CONFIG_NAU7802) +=3D nau7802.o -> >=20 -> > +obj-$(CONFIG_ROCKCHIP_SARADC) +=3D rockchip_saradc.o -> >=20 -> > obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o -> > obj-$(CONFIG_TI_AM335X_ADC) +=3D ti_am335x_adc.o -> > obj-$(CONFIG_TWL4030_MADC) +=3D twl4030-madc.o -> >=20 +> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o +> > +> > obj-$(CONFIG_MCP3422) += mcp3422.o +> > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o +> > obj-$(CONFIG_NAU7802) += nau7802.o +> > +> > +obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o +> > +> > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o +> > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o +> > obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o +> > > > diff --git a/drivers/iio/adc/rockchip_saradc.c > > b/drivers/iio/adc/rockchip_saradc.c new file mode 100644 > > index 0000000..8fc5867 @@ -84,26 +79,21 @@ om > > +/* > > + * Rockchip Successive Approximation Register (SAR) A/D Converter > > + * Copyright (C) 2014 ROCKCHIP, Inc. ->=20 +> > Does this mean, that you are working for Rockchip? -I'm doing consulting on the mainline integration and the code is largel= -y the=20 +I'm doing consulting on the mainline integration and the code is largely the one taken from the upstream tree and only cleaned up in places. ->=20 +> > > + * -> > + * This program is free software; you can redistribute it and/or m= -odify -> > + * it under the terms of the GNU General Public License as publish= -ed by -> > + * the Free Software Foundation; either version 2 of the License, = -or +> > + * 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,= - +> > + * 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. @@ -119,152 +109,141 @@ or > > +#include <linux/regulator/consumer.h> > > +#include <linux/iio/iio.h> > > + -> > +#define SARADC_DATA=09=09=090x00 -> > +#define SARADC_DATA_MASK=09=090x3ff +> > +#define SARADC_DATA 0x00 +> > +#define SARADC_DATA_MASK 0x3ff > > + -> > +#define SARADC_STAS=09=09=090x04 -> > +#define SARADC_STAS_BUSY=09=09BIT(0) +> > +#define SARADC_STAS 0x04 +> > +#define SARADC_STAS_BUSY BIT(0) > > + -> > +#define SARADC_CTRL=09=09=090x08 -> > +#define SARADC_CTRL_IRQ_STATUS=09=09BIT(6) -> > +#define SARADC_CTRL_IRQ_ENABLE=09=09BIT(5) -> > +#define SARADC_CTRL_POWER_CTRL=09=09BIT(3) -> > +#define SARADC_CTRL_CHN_MASK=09=090x7 +> > +#define SARADC_CTRL 0x08 +> > +#define SARADC_CTRL_IRQ_STATUS BIT(6) +> > +#define SARADC_CTRL_IRQ_ENABLE BIT(5) +> > +#define SARADC_CTRL_POWER_CTRL BIT(3) +> > +#define SARADC_CTRL_CHN_MASK 0x7 > > + -> > +#define SARADC_DLY_PU_SOC=09=090x0c -> > +#define SARADC_DLY_PU_SOC_MASK=09=090x3f +> > +#define SARADC_DLY_PU_SOC 0x0c +> > +#define SARADC_DLY_PU_SOC_MASK 0x3f > > + -> > +#define SARADC_BITS=09=09=0910 -> > +#define SARADC_TIMEOUT=09=09=09msecs_to_jiffies(100) +> > +#define SARADC_BITS 10 +> > +#define SARADC_TIMEOUT msecs_to_jiffies(100) > > + > > +struct rockchip_saradc { -> > +=09void __iomem=09=09*regs; -> > +=09struct clk=09=09*pclk; -> > +=09struct clk=09=09*clk; -> > +=09struct completion=09completion; -> > +=09struct regulator=09*vref; -> > +=09int=09=09=09vref_mv; -> > +=09u16=09=09=09last_val; +> > + void __iomem *regs; +> > + struct clk *pclk; +> > + struct clk *clk; +> > + struct completion completion; +> > + struct regulator *vref; +> > + int vref_mv; +> > + u16 last_val; > > +}; > > + > > +static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, -> > +=09=09=09=09 struct iio_chan_spec const *chan, -> > +=09=09=09=09 int *val, int *val2, long mask) +> > + struct iio_chan_spec const *chan, +> > + int *val, int *val2, long mask) > > +{ -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09switch (mask) { -> > +=09case IIO_CHAN_INFO_RAW: -> > +=09=09mutex_lock(&indio_dev->mlock); +> > + switch (mask) { +> > + case IIO_CHAN_INFO_RAW: +> > + mutex_lock(&indio_dev->mlock); > > + -> > +=09=09/* Select the channel to be used and trigger conversion */ -> > +=09=09writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC); ->=20 -> This could need a bit more explanation. Maybe represent the magic val= -ue of +> > + /* Select the channel to be used and trigger conversion */ +> > + writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC); +> +> This could need a bit more explanation. Maybe represent the magic value of > 0x8 with a more self explaining definition. -This actually isn't a magic value, but the "delay between power up and = -start=20 -command" in clock periods. But you're right, this might benefit from a = -better=20 -explaination, as the channel selection and start is done by the setting= - below. +This actually isn't a magic value, but the "delay between power up and start +command" in clock periods. But you're right, this might benefit from a better +explaination, as the channel selection and start is done by the setting below. -> > +=09=09writel(SARADC_CTRL_POWER_CTRL -> > +=09=09=09=09| (chan->channel & SARADC_CTRL_CHN_MASK) -> > +=09=09=09=09| SARADC_CTRL_IRQ_ENABLE, -> > +=09=09 info->regs + SARADC_CTRL); -> > + -> > +=09=09if (!wait_for_completion_timeout(&info->completion, -> > +=09=09=09=09=09=09 SARADC_TIMEOUT)) { -> > +=09=09=09writel_relaxed(0, info->regs + SARADC_CTRL); -> > +=09=09=09mutex_unlock(&indio_dev->mlock); -> > +=09=09=09return -ETIMEDOUT; -> > +=09=09} -> > + -> > +=09=09*val =3D info->last_val; -> > +=09=09mutex_unlock(&indio_dev->mlock); -> > +=09=09return IIO_VAL_INT; -> > +=09case IIO_CHAN_INFO_SCALE: -> > +=09=09*val =3D info->vref_mv; -> > +=09=09*val2 =3D SARADC_BITS; -> > +=09=09return IIO_VAL_FRACTIONAL_LOG2; ->=20 -> Are there only fixed voltage regulators used, or are there chances th= -at -> variable voltage regulators could be used for vref? In the second cas= -e, it +> > + writel(SARADC_CTRL_POWER_CTRL +> > + | (chan->channel & SARADC_CTRL_CHN_MASK) +> > + | SARADC_CTRL_IRQ_ENABLE, +> > + info->regs + SARADC_CTRL); +> > + +> > + if (!wait_for_completion_timeout(&info->completion, +> > + SARADC_TIMEOUT)) { +> > + writel_relaxed(0, info->regs + SARADC_CTRL); +> > + mutex_unlock(&indio_dev->mlock); +> > + return -ETIMEDOUT; +> > + } +> > + +> > + *val = info->last_val; +> > + mutex_unlock(&indio_dev->mlock); +> > + return IIO_VAL_INT; +> > + case IIO_CHAN_INFO_SCALE: +> > + *val = info->vref_mv; +> > + *val2 = SARADC_BITS; +> > + return IIO_VAL_FRACTIONAL_LOG2; +> +> Are there only fixed voltage regulators used, or are there chances that +> variable voltage regulators could be used for vref? In the second case, it > would be better to determine the current regulator voltage here. -The voltage regulators used are generally variable, but set to a fixed = -setting=20 +The voltage regulators used are generally variable, but set to a fixed setting that is not supposed to be changed. -Nevertheless I think you're right and the driver could be prepared for = -the=20 +Nevertheless I think you're right and the driver could be prepared for the case where the voltage might really change. -> > +=09default: -> > +=09=09return -EINVAL; -> > +=09} +> > + default: +> > + return -EINVAL; +> > + } > > +} > > + > > +static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) > > +{ -> > +=09struct rockchip_saradc *info =3D (struct rockchip_saradc *)dev_= -id; +> > + struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id; > > + -> > +=09/* Read value */ -> > +=09info->last_val =3D readl_relaxed(info->regs + SARADC_DATA); -> > +=09info->last_val &=3D SARADC_DATA_MASK; +> > + /* Read value */ +> > + info->last_val = readl_relaxed(info->regs + SARADC_DATA); +> > + info->last_val &= SARADC_DATA_MASK; > > + -> > +=09/* Clear irq & power down adc */ -> > +=09writel_relaxed(0, info->regs + SARADC_CTRL); +> > + /* Clear irq & power down adc */ +> > + writel_relaxed(0, info->regs + SARADC_CTRL); > > + -> > +=09complete(&info->completion); +> > + complete(&info->completion); > > + -> > +=09return IRQ_HANDLED; +> > + return IRQ_HANDLED; > > +} > > + -> > +static const struct iio_info rockchip_saradc_iio_info =3D { -> > +=09.read_raw =3D rockchip_saradc_read_raw, -> > +=09.driver_module =3D THIS_MODULE, +> > +static const struct iio_info rockchip_saradc_iio_info = { +> > + .read_raw = rockchip_saradc_read_raw, +> > + .driver_module = THIS_MODULE, > > +}; > > + -> > +#define ADC_CHANNEL(_index, _id) {=09=09=09=09\ -> > +=09.type =3D IIO_VOLTAGE,=09=09=09=09=09\ -> > +=09.indexed =3D 1,=09=09=09=09=09=09\ -> > +=09.channel =3D _index,=09=09=09=09=09\ -> > +=09.info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW),=09=09\ -> > +=09.info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE),=09\ -> > +=09.datasheet_name =3D _id,=09=09=09=09=09\ +> > +#define ADC_CHANNEL(_index, _id) { \ +> > + .type = IIO_VOLTAGE, \ +> > + .indexed = 1, \ +> > + .channel = _index, \ +> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +> > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +> > + .datasheet_name = _id, \ > > +} > > + -> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] =3D= - { -> > +=09ADC_CHANNEL(0, "adc0"), -> > +=09ADC_CHANNEL(1, "adc1"), -> > +=09ADC_CHANNEL(2, "adc2"), +> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] = { +> > + ADC_CHANNEL(0, "adc0"), +> > + ADC_CHANNEL(1, "adc1"), +> > + ADC_CHANNEL(2, "adc2"), > > +}; > > + > > +static int rockchip_saradc_probe(struct platform_device *pdev) > > +{ -> > +=09struct rockchip_saradc *info =3D NULL; -> > +=09struct device_node *np =3D pdev->dev.of_node; -> > +=09struct iio_dev *indio_dev =3D NULL; -> > +=09struct resource=09*mem; -> > +=09int ret =3D -ENODEV; -> > +=09int irq; -> > +=09u32 rate; -> > + -> > +=09if (!np) -> > +=09=09return ret; ->=20 -> return -ENODEV is usually used, and a bit more obvious. That would al= -so make +> > + struct rockchip_saradc *info = NULL; +> > + struct device_node *np = pdev->dev.of_node; +> > + struct iio_dev *indio_dev = NULL; +> > + struct resource *mem; +> > + int ret = -ENODEV; +> > + int irq; +> > + u32 rate; +> > + +> > + if (!np) +> > + return ret; +> +> return -ENODEV is usually used, and a bit more obvious. That would also make > the initialization of ret obsolete. ok @@ -274,182 +253,179 @@ Thanks for the review Heiko > > + -> > +=09indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(*info));= - -> > +=09if (!indio_dev) { -> > +=09=09dev_err(&pdev->dev, "failed allocating iio device\n"); -> > +=09=09return -ENOMEM; -> > +=09} -> > +=09info =3D iio_priv(indio_dev); -> > + -> > +=09mem =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); -> > +=09info->regs =3D devm_request_and_ioremap(&pdev->dev, mem); -> > +=09if (!info->regs) -> > +=09=09return -ENOMEM; -> > + -> > +=09irq =3D platform_get_irq(pdev, 0); -> > +=09if (irq < 0) { -> > +=09=09dev_err(&pdev->dev, "no irq resource?\n"); -> > +=09=09return irq; -> > +=09} -> > + -> > +=09ret =3D devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, -> > +=09=09=09 0, dev_name(&pdev->dev), info); -> > +=09if (ret < 0) { -> > +=09=09dev_err(&pdev->dev, "failed requesting irq %d\n", irq); -> > +=09=09return ret; -> > +=09} -> > + -> > +=09init_completion(&info->completion); -> > + -> > +=09info->pclk =3D devm_clk_get(&pdev->dev, "apb_pclk"); -> > +=09if (IS_ERR(info->pclk)) { -> > +=09=09dev_err(&pdev->dev, "failed to get pclk\n"); -> > +=09=09return PTR_ERR(info->pclk); -> > +=09} -> > + -> > +=09info->clk =3D devm_clk_get(&pdev->dev, "saradc"); -> > +=09if (IS_ERR(info->clk)) { -> > +=09=09dev_err(&pdev->dev, "failed to get adc clock\n"); -> > +=09=09return PTR_ERR(info->clk); -> > +=09} -> > + -> > +=09info->vref =3D devm_regulator_get(&pdev->dev, "vref"); -> > +=09if (IS_ERR(info->vref)) { -> > +=09=09dev_err(&pdev->dev, "failed to get regulator, %ld\n", -> > +=09=09=09PTR_ERR(info->vref)); -> > +=09=09return PTR_ERR(info->vref); -> > +=09} -> > + -> > +=09/* use a default of 1MHz for the converter clock */ -> > +=09if (of_property_read_u32(np, "clock-frequency", &rate)) -> > +=09=09rate =3D 1000000; -> > + -> > +=09ret =3D clk_set_rate(info->clk, rate); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret)= -; -> > +=09=09return ret; -> > +=09} -> > + -> > +=09ret =3D regulator_enable(info->vref); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable vref regulator\n"); -> > +=09=09return ret; -> > +=09} -> > + -> > +=09ret =3D regulator_get_voltage(info->vref); -> > +=09if (ret < 0) { -> > +=09=09dev_err(&pdev->dev, "failed to get regulator voltage\n"); -> > +=09=09goto err_reg_voltage; -> > +=09} -> > +=09info->vref_mv =3D ret / 1000; -> > + -> > +=09ret =3D clk_prepare_enable(info->pclk); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable pclk\n"); -> > +=09=09goto err_reg_voltage; -> > +=09} -> > + -> > +=09ret =3D clk_prepare_enable(info->clk); -> > +=09if (ret) { -> > +=09=09dev_err(&pdev->dev, "failed to enable converter clock\n"); -> > +=09=09goto err_pclk; -> > +=09} -> > + -> > +=09platform_set_drvdata(pdev, indio_dev); -> > + -> > +=09indio_dev->name =3D dev_name(&pdev->dev); -> > +=09indio_dev->dev.parent =3D &pdev->dev; -> > +=09indio_dev->dev.of_node =3D pdev->dev.of_node; -> > +=09indio_dev->info =3D &rockchip_saradc_iio_info; -> > +=09indio_dev->modes =3D INDIO_DIRECT_MODE; -> > + -> > +=09indio_dev->channels =3D rockchip_saradc_iio_channels; -> > +=09indio_dev->num_channels =3D ARRAY_SIZE(rockchip_saradc_iio_chan= -nels); -> > + -> > +=09ret =3D iio_device_register(indio_dev); -> > +=09if (ret) -> > +=09=09goto err_clk; -> > + -> > +=09return 0; +> > + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); +> > + if (!indio_dev) { +> > + dev_err(&pdev->dev, "failed allocating iio device\n"); +> > + return -ENOMEM; +> > + } +> > + info = iio_priv(indio_dev); +> > + +> > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +> > + info->regs = devm_request_and_ioremap(&pdev->dev, mem); +> > + if (!info->regs) +> > + return -ENOMEM; +> > + +> > + irq = platform_get_irq(pdev, 0); +> > + if (irq < 0) { +> > + dev_err(&pdev->dev, "no irq resource?\n"); +> > + return irq; +> > + } +> > + +> > + ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, +> > + 0, dev_name(&pdev->dev), info); +> > + if (ret < 0) { +> > + dev_err(&pdev->dev, "failed requesting irq %d\n", irq); +> > + return ret; +> > + } +> > + +> > + init_completion(&info->completion); +> > + +> > + info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); +> > + if (IS_ERR(info->pclk)) { +> > + dev_err(&pdev->dev, "failed to get pclk\n"); +> > + return PTR_ERR(info->pclk); +> > + } +> > + +> > + info->clk = devm_clk_get(&pdev->dev, "saradc"); +> > + if (IS_ERR(info->clk)) { +> > + dev_err(&pdev->dev, "failed to get adc clock\n"); +> > + return PTR_ERR(info->clk); +> > + } +> > + +> > + info->vref = devm_regulator_get(&pdev->dev, "vref"); +> > + if (IS_ERR(info->vref)) { +> > + dev_err(&pdev->dev, "failed to get regulator, %ld\n", +> > + PTR_ERR(info->vref)); +> > + return PTR_ERR(info->vref); +> > + } +> > + +> > + /* use a default of 1MHz for the converter clock */ +> > + if (of_property_read_u32(np, "clock-frequency", &rate)) +> > + rate = 1000000; +> > + +> > + ret = clk_set_rate(info->clk, rate); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); +> > + return ret; +> > + } +> > + +> > + ret = regulator_enable(info->vref); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable vref regulator\n"); +> > + return ret; +> > + } +> > + +> > + ret = regulator_get_voltage(info->vref); +> > + if (ret < 0) { +> > + dev_err(&pdev->dev, "failed to get regulator voltage\n"); +> > + goto err_reg_voltage; +> > + } +> > + info->vref_mv = ret / 1000; +> > + +> > + ret = clk_prepare_enable(info->pclk); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable pclk\n"); +> > + goto err_reg_voltage; +> > + } +> > + +> > + ret = clk_prepare_enable(info->clk); +> > + if (ret) { +> > + dev_err(&pdev->dev, "failed to enable converter clock\n"); +> > + goto err_pclk; +> > + } +> > + +> > + platform_set_drvdata(pdev, indio_dev); +> > + +> > + indio_dev->name = dev_name(&pdev->dev); +> > + indio_dev->dev.parent = &pdev->dev; +> > + indio_dev->dev.of_node = pdev->dev.of_node; +> > + indio_dev->info = &rockchip_saradc_iio_info; +> > + indio_dev->modes = INDIO_DIRECT_MODE; +> > + +> > + indio_dev->channels = rockchip_saradc_iio_channels; +> > + indio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels); +> > + +> > + ret = iio_device_register(indio_dev); +> > + if (ret) +> > + goto err_clk; +> > + +> > + return 0; > > + > > +err_clk: -> > +=09clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->clk); > > +err_pclk: -> > +=09clk_disable_unprepare(info->pclk); +> > + clk_disable_unprepare(info->pclk); > > +err_reg_voltage: -> > +=09regulator_disable(info->vref); -> > +=09return ret; +> > + regulator_disable(info->vref); +> > + return ret; > > +} > > + > > +static int rockchip_saradc_remove(struct platform_device *pdev) > > +{ -> > +=09struct iio_dev *indio_dev =3D platform_get_drvdata(pdev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct iio_dev *indio_dev = platform_get_drvdata(pdev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09iio_device_unregister(indio_dev); -> > +=09clk_disable_unprepare(info->clk); -> > +=09clk_disable_unprepare(info->pclk); -> > +=09regulator_disable(info->vref); +> > + iio_device_unregister(indio_dev); +> > + clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->pclk); +> > + regulator_disable(info->vref); > > + -> > +=09return 0; +> > + return 0; > > +} > > + > > +#ifdef CONFIG_PM_SLEEP > > +static int rockchip_saradc_suspend(struct device *dev) > > +{ -> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); +> > + struct iio_dev *indio_dev = dev_get_drvdata(dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); > > + -> > +=09clk_disable_unprepare(info->clk); -> > +=09clk_disable_unprepare(info->pclk); -> > +=09regulator_disable(info->vref); +> > + clk_disable_unprepare(info->clk); +> > + clk_disable_unprepare(info->pclk); +> > + regulator_disable(info->vref); > > + -> > +=09return 0; +> > + return 0; > > +} > > + > > +static int rockchip_saradc_resume(struct device *dev) > > +{ -> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev); -> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev); -> > +=09int ret; +> > + struct iio_dev *indio_dev = dev_get_drvdata(dev); +> > + struct rockchip_saradc *info = iio_priv(indio_dev); +> > + int ret; > > + -> > +=09ret =3D regulator_enable(info->vref); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = regulator_enable(info->vref); +> > + if (ret) +> > + return ret; > > + -> > +=09ret =3D clk_prepare_enable(info->pclk); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = clk_prepare_enable(info->pclk); +> > + if (ret) +> > + return ret; > > + -> > +=09ret =3D clk_prepare_enable(info->clk); -> > +=09if (ret) -> > +=09=09return ret; +> > + ret = clk_prepare_enable(info->clk); +> > + if (ret) +> > + return ret; > > + -> > +=09return ret; +> > + return ret; > > +} > > +#endif > > + > > +static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, -> > +=09=09=09 rockchip_saradc_suspend, rockchip_saradc_resume); +> > + rockchip_saradc_suspend, rockchip_saradc_resume); > > + -> > +static const struct of_device_id rockchip_saradc_match[] =3D { -> > +=09{ .compatible =3D "rockchip,saradc" }, -> > +=09{}, +> > +static const struct of_device_id rockchip_saradc_match[] = { +> > + { .compatible = "rockchip,saradc" }, +> > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, rockchip_saradc_match); > > + -> > +static struct platform_driver rockchip_saradc_driver =3D { -> > +=09.probe=09=09=3D rockchip_saradc_probe, -> > +=09.remove=09=09=3D rockchip_saradc_remove, -> > +=09.driver=09=09=3D { -> > +=09=09.name=09=3D "rockchip-saradc", -> > +=09=09.owner=09=3D THIS_MODULE, -> > +=09=09.of_match_table =3D rockchip_saradc_match, -> > +=09=09.pm=09=3D &rockchip_saradc_pm_ops, -> > +=09}, +> > +static struct platform_driver rockchip_saradc_driver = { +> > + .probe = rockchip_saradc_probe, +> > + .remove = rockchip_saradc_remove, +> > + .driver = { +> > + .name = "rockchip-saradc", +> > + .owner = THIS_MODULE, +> > + .of_match_table = rockchip_saradc_match, +> > + .pm = &rockchip_saradc_pm_ops, +> > + }, > > +}; > > + > > +module_platform_driver(rockchip_saradc_driver); diff --git a/a/content_digest b/N3/content_digest index 6c89bb6..06ab8a5 100644 --- a/a/content_digest +++ b/N3/content_digest @@ -21,82 +21,77 @@ "\00:1\0" "b\0" "Am Sonntag, 13. Juli 2014, 14:09:48 schrieb Hartmut Knaack:\n" - "> Heiko St=FCbner schrieb:\n" - "> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation=\n" - "\n" + "> Heiko St\303\274bner schrieb:\n" + "> > The ADC is a 3-channel signal-ended 10-bit Successive Approximation\n" "> > Register (SAR) A/D Converter. It uses the supply and ground as its\n" - "> > reference and converts the analog input signal into 10-bit binary d=\n" - "igital\n" + "> > reference and converts the analog input signal into 10-bit binary digital\n" "> > codes.\n" - "> Is there a datasheet available anywhere, or just under some NDA? I've=\n" - " got\n" - "> some comments in line, which might be answered by reading the datashe=\n" - "et.\n" + "> Is there a datasheet available anywhere, or just under some NDA? I've got\n" + "> some comments in line, which might be answered by reading the datasheet.\n" "\n" "Sadly, there is no datasheet available to the public.\n" "\n" "\n" "> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>\n" "> > ---\n" - "> >=20\n" + "> > \n" "> > changes since v2:\n" "> > - address more comments from Peter Meerwald\n" - "> >=20\n" + "> > \n" "> > mainly the missing info_mask_shared_by_type element\n" - "> > =20\n" + "> > \n" "> > changes since v1:\n" "> > - address comments from Peter Meerwald\n" - "> >=20\n" + "> > \n" "> > drivers/iio/adc/Kconfig | 10 ++\n" - "> >=20\n" + "> > \n" "> > drivers/iio/adc/Makefile | 1 +\n" "> > drivers/iio/adc/rockchip_saradc.c | 314\n" "> > ++++++++++++++++++++++++++++++++++++++ 3 files changed, 325\n" "> > insertions(+)\n" "> > create mode 100644 drivers/iio/adc/rockchip_saradc.c\n" - "> >=20\n" + "> > \n" "> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig\n" "> > index a80d236..5d36bdb 100644\n" "> > --- a/drivers/iio/adc/Kconfig\n" "> > +++ b/drivers/iio/adc/Kconfig\n" "> > @@ -187,6 +187,16 @@ config NAU7802\n" - "> >=20\n" - "> > =09 To compile this driver as a module, choose M here: the\n" - "> > =09 module will be called nau7802.\n" - "> >=20\n" + "> > \n" + "> > \t To compile this driver as a module, choose M here: the\n" + "> > \t module will be called nau7802.\n" + "> > \n" "> > +config ROCKCHIP_SARADC\n" - "> > +=09tristate \"Rockchip SARADC driver\"\n" - "> > +=09depends on ARCH_ROCKCHIP || (OF && COMPILE_TEST)\n" - "> > +=09help\n" - "> > +=09 Say yes here to build support for the SARADC found in SoCs fr=\n" - "om\n" - "> > +=09 Rockchip.\n" + "> > +\ttristate \"Rockchip SARADC driver\"\n" + "> > +\tdepends on ARCH_ROCKCHIP || (OF && COMPILE_TEST)\n" + "> > +\thelp\n" + "> > +\t Say yes here to build support for the SARADC found in SoCs from\n" + "> > +\t Rockchip.\n" "> > +\n" - "> > +=09 To compile this driver as a module, choose M here: the\n" - "> > +=09 module will be called rockchip_saradc.\n" + "> > +\t To compile this driver as a module, choose M here: the\n" + "> > +\t module will be called rockchip_saradc.\n" "> > +\n" - "> >=20\n" + "> > \n" "> > config TI_ADC081C\n" - "> > =20\n" - "> > =09tristate \"Texas Instruments ADC081C021/027\"\n" - "> > =09depends on I2C\n" - "> >=20\n" + "> > \n" + "> > \ttristate \"Texas Instruments ADC081C021/027\"\n" + "> > \tdepends on I2C\n" + "> > \n" "> > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile\n" "> > index 9d60f2d..8e2932d 100644\n" "> > --- a/drivers/iio/adc/Makefile\n" "> > +++ b/drivers/iio/adc/Makefile\n" - "> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) +=3D mcp320x.o\n" - "> >=20\n" - "> > obj-$(CONFIG_MCP3422) +=3D mcp3422.o\n" - "> > obj-$(CONFIG_MEN_Z188_ADC) +=3D men_z188_adc.o\n" - "> > obj-$(CONFIG_NAU7802) +=3D nau7802.o\n" - "> >=20\n" - "> > +obj-$(CONFIG_ROCKCHIP_SARADC) +=3D rockchip_saradc.o\n" - "> >=20\n" - "> > obj-$(CONFIG_TI_ADC081C) +=3D ti-adc081c.o\n" - "> > obj-$(CONFIG_TI_AM335X_ADC) +=3D ti_am335x_adc.o\n" - "> > obj-$(CONFIG_TWL4030_MADC) +=3D twl4030-madc.o\n" - "> >=20\n" + "> > @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o\n" + "> > \n" + "> > obj-$(CONFIG_MCP3422) += mcp3422.o\n" + "> > obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o\n" + "> > obj-$(CONFIG_NAU7802) += nau7802.o\n" + "> > \n" + "> > +obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o\n" + "> > \n" + "> > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o\n" + "> > obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o\n" + "> > obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o\n" + "> > \n" "> > diff --git a/drivers/iio/adc/rockchip_saradc.c\n" "> > b/drivers/iio/adc/rockchip_saradc.c new file mode 100644\n" "> > index 0000000..8fc5867\n" @@ -106,26 +101,21 @@ "> > +/*\n" "> > + * Rockchip Successive Approximation Register (SAR) A/D Converter\n" "> > + * Copyright (C) 2014 ROCKCHIP, Inc.\n" - ">=20\n" + "> \n" "> Does this mean, that you are working for Rockchip?\n" "\n" - "I'm doing consulting on the mainline integration and the code is largel=\n" - "y the=20\n" + "I'm doing consulting on the mainline integration and the code is largely the \n" "one taken from the upstream tree and only cleaned up in places.\n" "\n" "\n" - ">=20\n" + "> \n" "> > + *\n" - "> > + * This program is free software; you can redistribute it and/or m=\n" - "odify\n" - "> > + * it under the terms of the GNU General Public License as publish=\n" - "ed by\n" - "> > + * the Free Software Foundation; either version 2 of the License, =\n" - "or\n" + "> > + * This program is free software; you can redistribute it and/or modify\n" + "> > + * it under the terms of the GNU General Public License as published by\n" + "> > + * the Free Software Foundation; either version 2 of the License, or\n" "> > + * (at your option) any later version.\n" "> > + *\n" - "> > + * This program is distributed in the hope that it will be useful,=\n" - "\n" + "> > + * This program is distributed in the hope that it will be useful,\n" "> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "> > + * GNU General Public License for more details.\n" @@ -141,152 +131,141 @@ "> > +#include <linux/regulator/consumer.h>\n" "> > +#include <linux/iio/iio.h>\n" "> > +\n" - "> > +#define SARADC_DATA=09=09=090x00\n" - "> > +#define SARADC_DATA_MASK=09=090x3ff\n" + "> > +#define SARADC_DATA\t\t\t0x00\n" + "> > +#define SARADC_DATA_MASK\t\t0x3ff\n" "> > +\n" - "> > +#define SARADC_STAS=09=09=090x04\n" - "> > +#define SARADC_STAS_BUSY=09=09BIT(0)\n" + "> > +#define SARADC_STAS\t\t\t0x04\n" + "> > +#define SARADC_STAS_BUSY\t\tBIT(0)\n" "> > +\n" - "> > +#define SARADC_CTRL=09=09=090x08\n" - "> > +#define SARADC_CTRL_IRQ_STATUS=09=09BIT(6)\n" - "> > +#define SARADC_CTRL_IRQ_ENABLE=09=09BIT(5)\n" - "> > +#define SARADC_CTRL_POWER_CTRL=09=09BIT(3)\n" - "> > +#define SARADC_CTRL_CHN_MASK=09=090x7\n" + "> > +#define SARADC_CTRL\t\t\t0x08\n" + "> > +#define SARADC_CTRL_IRQ_STATUS\t\tBIT(6)\n" + "> > +#define SARADC_CTRL_IRQ_ENABLE\t\tBIT(5)\n" + "> > +#define SARADC_CTRL_POWER_CTRL\t\tBIT(3)\n" + "> > +#define SARADC_CTRL_CHN_MASK\t\t0x7\n" "> > +\n" - "> > +#define SARADC_DLY_PU_SOC=09=090x0c\n" - "> > +#define SARADC_DLY_PU_SOC_MASK=09=090x3f\n" + "> > +#define SARADC_DLY_PU_SOC\t\t0x0c\n" + "> > +#define SARADC_DLY_PU_SOC_MASK\t\t0x3f\n" "> > +\n" - "> > +#define SARADC_BITS=09=09=0910\n" - "> > +#define SARADC_TIMEOUT=09=09=09msecs_to_jiffies(100)\n" + "> > +#define SARADC_BITS\t\t\t10\n" + "> > +#define SARADC_TIMEOUT\t\t\tmsecs_to_jiffies(100)\n" "> > +\n" "> > +struct rockchip_saradc {\n" - "> > +=09void __iomem=09=09*regs;\n" - "> > +=09struct clk=09=09*pclk;\n" - "> > +=09struct clk=09=09*clk;\n" - "> > +=09struct completion=09completion;\n" - "> > +=09struct regulator=09*vref;\n" - "> > +=09int=09=09=09vref_mv;\n" - "> > +=09u16=09=09=09last_val;\n" + "> > +\tvoid __iomem\t\t*regs;\n" + "> > +\tstruct clk\t\t*pclk;\n" + "> > +\tstruct clk\t\t*clk;\n" + "> > +\tstruct completion\tcompletion;\n" + "> > +\tstruct regulator\t*vref;\n" + "> > +\tint\t\t\tvref_mv;\n" + "> > +\tu16\t\t\tlast_val;\n" "> > +};\n" "> > +\n" "> > +static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,\n" - "> > +=09=09=09=09 struct iio_chan_spec const *chan,\n" - "> > +=09=09=09=09 int *val, int *val2, long mask)\n" + "> > +\t\t\t\t struct iio_chan_spec const *chan,\n" + "> > +\t\t\t\t int *val, int *val2, long mask)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09switch (mask) {\n" - "> > +=09case IIO_CHAN_INFO_RAW:\n" - "> > +=09=09mutex_lock(&indio_dev->mlock);\n" + "> > +\tswitch (mask) {\n" + "> > +\tcase IIO_CHAN_INFO_RAW:\n" + "> > +\t\tmutex_lock(&indio_dev->mlock);\n" "> > +\n" - "> > +=09=09/* Select the channel to be used and trigger conversion */\n" - "> > +=09=09writel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC);\n" - ">=20\n" - "> This could need a bit more explanation. Maybe represent the magic val=\n" - "ue of\n" + "> > +\t\t/* Select the channel to be used and trigger conversion */\n" + "> > +\t\twritel_relaxed(0x08, info->regs + SARADC_DLY_PU_SOC);\n" + "> \n" + "> This could need a bit more explanation. Maybe represent the magic value of\n" "> 0x8 with a more self explaining definition.\n" "\n" - "This actually isn't a magic value, but the \"delay between power up and =\n" - "start=20\n" - "command\" in clock periods. But you're right, this might benefit from a =\n" - "better=20\n" - "explaination, as the channel selection and start is done by the setting=\n" - " below.\n" + "This actually isn't a magic value, but the \"delay between power up and start \n" + "command\" in clock periods. But you're right, this might benefit from a better \n" + "explaination, as the channel selection and start is done by the setting below.\n" "\n" "\n" - "> > +=09=09writel(SARADC_CTRL_POWER_CTRL\n" - "> > +=09=09=09=09| (chan->channel & SARADC_CTRL_CHN_MASK)\n" - "> > +=09=09=09=09| SARADC_CTRL_IRQ_ENABLE,\n" - "> > +=09=09 info->regs + SARADC_CTRL);\n" - "> > +\n" - "> > +=09=09if (!wait_for_completion_timeout(&info->completion,\n" - "> > +=09=09=09=09=09=09 SARADC_TIMEOUT)) {\n" - "> > +=09=09=09writel_relaxed(0, info->regs + SARADC_CTRL);\n" - "> > +=09=09=09mutex_unlock(&indio_dev->mlock);\n" - "> > +=09=09=09return -ETIMEDOUT;\n" - "> > +=09=09}\n" - "> > +\n" - "> > +=09=09*val =3D info->last_val;\n" - "> > +=09=09mutex_unlock(&indio_dev->mlock);\n" - "> > +=09=09return IIO_VAL_INT;\n" - "> > +=09case IIO_CHAN_INFO_SCALE:\n" - "> > +=09=09*val =3D info->vref_mv;\n" - "> > +=09=09*val2 =3D SARADC_BITS;\n" - "> > +=09=09return IIO_VAL_FRACTIONAL_LOG2;\n" - ">=20\n" - "> Are there only fixed voltage regulators used, or are there chances th=\n" - "at\n" - "> variable voltage regulators could be used for vref? In the second cas=\n" - "e, it\n" + "> > +\t\twritel(SARADC_CTRL_POWER_CTRL\n" + "> > +\t\t\t\t| (chan->channel & SARADC_CTRL_CHN_MASK)\n" + "> > +\t\t\t\t| SARADC_CTRL_IRQ_ENABLE,\n" + "> > +\t\t info->regs + SARADC_CTRL);\n" + "> > +\n" + "> > +\t\tif (!wait_for_completion_timeout(&info->completion,\n" + "> > +\t\t\t\t\t\t SARADC_TIMEOUT)) {\n" + "> > +\t\t\twritel_relaxed(0, info->regs + SARADC_CTRL);\n" + "> > +\t\t\tmutex_unlock(&indio_dev->mlock);\n" + "> > +\t\t\treturn -ETIMEDOUT;\n" + "> > +\t\t}\n" + "> > +\n" + "> > +\t\t*val = info->last_val;\n" + "> > +\t\tmutex_unlock(&indio_dev->mlock);\n" + "> > +\t\treturn IIO_VAL_INT;\n" + "> > +\tcase IIO_CHAN_INFO_SCALE:\n" + "> > +\t\t*val = info->vref_mv;\n" + "> > +\t\t*val2 = SARADC_BITS;\n" + "> > +\t\treturn IIO_VAL_FRACTIONAL_LOG2;\n" + "> \n" + "> Are there only fixed voltage regulators used, or are there chances that\n" + "> variable voltage regulators could be used for vref? In the second case, it\n" "> would be better to determine the current regulator voltage here.\n" "\n" - "The voltage regulators used are generally variable, but set to a fixed =\n" - "setting=20\n" + "The voltage regulators used are generally variable, but set to a fixed setting \n" "that is not supposed to be changed.\n" "\n" - "Nevertheless I think you're right and the driver could be prepared for =\n" - "the=20\n" + "Nevertheless I think you're right and the driver could be prepared for the \n" "case where the voltage might really change.\n" "\n" "\n" - "> > +=09default:\n" - "> > +=09=09return -EINVAL;\n" - "> > +=09}\n" + "> > +\tdefault:\n" + "> > +\t\treturn -EINVAL;\n" + "> > +\t}\n" "> > +}\n" "> > +\n" "> > +static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D (struct rockchip_saradc *)dev_=\n" - "id;\n" + "> > +\tstruct rockchip_saradc *info = (struct rockchip_saradc *)dev_id;\n" "> > +\n" - "> > +=09/* Read value */\n" - "> > +=09info->last_val =3D readl_relaxed(info->regs + SARADC_DATA);\n" - "> > +=09info->last_val &=3D SARADC_DATA_MASK;\n" + "> > +\t/* Read value */\n" + "> > +\tinfo->last_val = readl_relaxed(info->regs + SARADC_DATA);\n" + "> > +\tinfo->last_val &= SARADC_DATA_MASK;\n" "> > +\n" - "> > +=09/* Clear irq & power down adc */\n" - "> > +=09writel_relaxed(0, info->regs + SARADC_CTRL);\n" + "> > +\t/* Clear irq & power down adc */\n" + "> > +\twritel_relaxed(0, info->regs + SARADC_CTRL);\n" "> > +\n" - "> > +=09complete(&info->completion);\n" + "> > +\tcomplete(&info->completion);\n" "> > +\n" - "> > +=09return IRQ_HANDLED;\n" + "> > +\treturn IRQ_HANDLED;\n" "> > +}\n" "> > +\n" - "> > +static const struct iio_info rockchip_saradc_iio_info =3D {\n" - "> > +=09.read_raw =3D rockchip_saradc_read_raw,\n" - "> > +=09.driver_module =3D THIS_MODULE,\n" + "> > +static const struct iio_info rockchip_saradc_iio_info = {\n" + "> > +\t.read_raw = rockchip_saradc_read_raw,\n" + "> > +\t.driver_module = THIS_MODULE,\n" "> > +};\n" "> > +\n" - "> > +#define ADC_CHANNEL(_index, _id) {=09=09=09=09\\\n" - "> > +=09.type =3D IIO_VOLTAGE,=09=09=09=09=09\\\n" - "> > +=09.indexed =3D 1,=09=09=09=09=09=09\\\n" - "> > +=09.channel =3D _index,=09=09=09=09=09\\\n" - "> > +=09.info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW),=09=09\\\n" - "> > +=09.info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE),=09\\\n" - "> > +=09.datasheet_name =3D _id,=09=09=09=09=09\\\n" + "> > +#define ADC_CHANNEL(_index, _id) {\t\t\t\t\\\n" + "> > +\t.type = IIO_VOLTAGE,\t\t\t\t\t\\\n" + "> > +\t.indexed = 1,\t\t\t\t\t\t\\\n" + "> > +\t.channel = _index,\t\t\t\t\t\\\n" + "> > +\t.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),\t\t\\\n" + "> > +\t.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\t\\\n" + "> > +\t.datasheet_name = _id,\t\t\t\t\t\\\n" "> > +}\n" "> > +\n" - "> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] =3D=\n" - " {\n" - "> > +=09ADC_CHANNEL(0, \"adc0\"),\n" - "> > +=09ADC_CHANNEL(1, \"adc1\"),\n" - "> > +=09ADC_CHANNEL(2, \"adc2\"),\n" + "> > +static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {\n" + "> > +\tADC_CHANNEL(0, \"adc0\"),\n" + "> > +\tADC_CHANNEL(1, \"adc1\"),\n" + "> > +\tADC_CHANNEL(2, \"adc2\"),\n" "> > +};\n" "> > +\n" "> > +static int rockchip_saradc_probe(struct platform_device *pdev)\n" "> > +{\n" - "> > +=09struct rockchip_saradc *info =3D NULL;\n" - "> > +=09struct device_node *np =3D pdev->dev.of_node;\n" - "> > +=09struct iio_dev *indio_dev =3D NULL;\n" - "> > +=09struct resource=09*mem;\n" - "> > +=09int ret =3D -ENODEV;\n" - "> > +=09int irq;\n" - "> > +=09u32 rate;\n" - "> > +\n" - "> > +=09if (!np)\n" - "> > +=09=09return ret;\n" - ">=20\n" - "> return -ENODEV is usually used, and a bit more obvious. That would al=\n" - "so make\n" + "> > +\tstruct rockchip_saradc *info = NULL;\n" + "> > +\tstruct device_node *np = pdev->dev.of_node;\n" + "> > +\tstruct iio_dev *indio_dev = NULL;\n" + "> > +\tstruct resource\t*mem;\n" + "> > +\tint ret = -ENODEV;\n" + "> > +\tint irq;\n" + "> > +\tu32 rate;\n" + "> > +\n" + "> > +\tif (!np)\n" + "> > +\t\treturn ret;\n" + "> \n" + "> return -ENODEV is usually used, and a bit more obvious. That would also make\n" "> the initialization of ret obsolete.\n" "\n" "ok\n" @@ -296,184 +275,181 @@ "Heiko\n" "\n" "> > +\n" - "> > +=09indio_dev =3D devm_iio_device_alloc(&pdev->dev, sizeof(*info));=\n" - "\n" - "> > +=09if (!indio_dev) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed allocating iio device\\n\");\n" - "> > +=09=09return -ENOMEM;\n" - "> > +=09}\n" - "> > +=09info =3D iio_priv(indio_dev);\n" - "> > +\n" - "> > +=09mem =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" - "> > +=09info->regs =3D devm_request_and_ioremap(&pdev->dev, mem);\n" - "> > +=09if (!info->regs)\n" - "> > +=09=09return -ENOMEM;\n" - "> > +\n" - "> > +=09irq =3D platform_get_irq(pdev, 0);\n" - "> > +=09if (irq < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"no irq resource?\\n\");\n" - "> > +=09=09return irq;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,\n" - "> > +=09=09=09 0, dev_name(&pdev->dev), info);\n" - "> > +=09if (ret < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed requesting irq %d\\n\", irq);\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09init_completion(&info->completion);\n" - "> > +\n" - "> > +=09info->pclk =3D devm_clk_get(&pdev->dev, \"apb_pclk\");\n" - "> > +=09if (IS_ERR(info->pclk)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get pclk\\n\");\n" - "> > +=09=09return PTR_ERR(info->pclk);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09info->clk =3D devm_clk_get(&pdev->dev, \"saradc\");\n" - "> > +=09if (IS_ERR(info->clk)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get adc clock\\n\");\n" - "> > +=09=09return PTR_ERR(info->clk);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09info->vref =3D devm_regulator_get(&pdev->dev, \"vref\");\n" - "> > +=09if (IS_ERR(info->vref)) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get regulator, %ld\\n\",\n" - "> > +=09=09=09PTR_ERR(info->vref));\n" - "> > +=09=09return PTR_ERR(info->vref);\n" - "> > +=09}\n" - "> > +\n" - "> > +=09/* use a default of 1MHz for the converter clock */\n" - "> > +=09if (of_property_read_u32(np, \"clock-frequency\", &rate))\n" - "> > +=09=09rate =3D 1000000;\n" - "> > +\n" - "> > +=09ret =3D clk_set_rate(info->clk, rate);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to set adc clk rate, %d\\n\", ret)=\n" - ";\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D regulator_enable(info->vref);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable vref regulator\\n\");\n" - "> > +=09=09return ret;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D regulator_get_voltage(info->vref);\n" - "> > +=09if (ret < 0) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to get regulator voltage\\n\");\n" - "> > +=09=09goto err_reg_voltage;\n" - "> > +=09}\n" - "> > +=09info->vref_mv =3D ret / 1000;\n" - "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->pclk);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable pclk\\n\");\n" - "> > +=09=09goto err_reg_voltage;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->clk);\n" - "> > +=09if (ret) {\n" - "> > +=09=09dev_err(&pdev->dev, \"failed to enable converter clock\\n\");\n" - "> > +=09=09goto err_pclk;\n" - "> > +=09}\n" - "> > +\n" - "> > +=09platform_set_drvdata(pdev, indio_dev);\n" - "> > +\n" - "> > +=09indio_dev->name =3D dev_name(&pdev->dev);\n" - "> > +=09indio_dev->dev.parent =3D &pdev->dev;\n" - "> > +=09indio_dev->dev.of_node =3D pdev->dev.of_node;\n" - "> > +=09indio_dev->info =3D &rockchip_saradc_iio_info;\n" - "> > +=09indio_dev->modes =3D INDIO_DIRECT_MODE;\n" - "> > +\n" - "> > +=09indio_dev->channels =3D rockchip_saradc_iio_channels;\n" - "> > +=09indio_dev->num_channels =3D ARRAY_SIZE(rockchip_saradc_iio_chan=\n" - "nels);\n" - "> > +\n" - "> > +=09ret =3D iio_device_register(indio_dev);\n" - "> > +=09if (ret)\n" - "> > +=09=09goto err_clk;\n" - "> > +\n" - "> > +=09return 0;\n" + "> > +\tindio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));\n" + "> > +\tif (!indio_dev) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed allocating iio device\\n\");\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\t}\n" + "> > +\tinfo = iio_priv(indio_dev);\n" + "> > +\n" + "> > +\tmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" + "> > +\tinfo->regs = devm_request_and_ioremap(&pdev->dev, mem);\n" + "> > +\tif (!info->regs)\n" + "> > +\t\treturn -ENOMEM;\n" + "> > +\n" + "> > +\tirq = platform_get_irq(pdev, 0);\n" + "> > +\tif (irq < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"no irq resource?\\n\");\n" + "> > +\t\treturn irq;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,\n" + "> > +\t\t\t 0, dev_name(&pdev->dev), info);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed requesting irq %d\\n\", irq);\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinit_completion(&info->completion);\n" + "> > +\n" + "> > +\tinfo->pclk = devm_clk_get(&pdev->dev, \"apb_pclk\");\n" + "> > +\tif (IS_ERR(info->pclk)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get pclk\\n\");\n" + "> > +\t\treturn PTR_ERR(info->pclk);\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinfo->clk = devm_clk_get(&pdev->dev, \"saradc\");\n" + "> > +\tif (IS_ERR(info->clk)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get adc clock\\n\");\n" + "> > +\t\treturn PTR_ERR(info->clk);\n" + "> > +\t}\n" + "> > +\n" + "> > +\tinfo->vref = devm_regulator_get(&pdev->dev, \"vref\");\n" + "> > +\tif (IS_ERR(info->vref)) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get regulator, %ld\\n\",\n" + "> > +\t\t\tPTR_ERR(info->vref));\n" + "> > +\t\treturn PTR_ERR(info->vref);\n" + "> > +\t}\n" + "> > +\n" + "> > +\t/* use a default of 1MHz for the converter clock */\n" + "> > +\tif (of_property_read_u32(np, \"clock-frequency\", &rate))\n" + "> > +\t\trate = 1000000;\n" + "> > +\n" + "> > +\tret = clk_set_rate(info->clk, rate);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to set adc clk rate, %d\\n\", ret);\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = regulator_enable(info->vref);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable vref regulator\\n\");\n" + "> > +\t\treturn ret;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = regulator_get_voltage(info->vref);\n" + "> > +\tif (ret < 0) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to get regulator voltage\\n\");\n" + "> > +\t\tgoto err_reg_voltage;\n" + "> > +\t}\n" + "> > +\tinfo->vref_mv = ret / 1000;\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(info->pclk);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable pclk\\n\");\n" + "> > +\t\tgoto err_reg_voltage;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tret = clk_prepare_enable(info->clk);\n" + "> > +\tif (ret) {\n" + "> > +\t\tdev_err(&pdev->dev, \"failed to enable converter clock\\n\");\n" + "> > +\t\tgoto err_pclk;\n" + "> > +\t}\n" + "> > +\n" + "> > +\tplatform_set_drvdata(pdev, indio_dev);\n" + "> > +\n" + "> > +\tindio_dev->name = dev_name(&pdev->dev);\n" + "> > +\tindio_dev->dev.parent = &pdev->dev;\n" + "> > +\tindio_dev->dev.of_node = pdev->dev.of_node;\n" + "> > +\tindio_dev->info = &rockchip_saradc_iio_info;\n" + "> > +\tindio_dev->modes = INDIO_DIRECT_MODE;\n" + "> > +\n" + "> > +\tindio_dev->channels = rockchip_saradc_iio_channels;\n" + "> > +\tindio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels);\n" + "> > +\n" + "> > +\tret = iio_device_register(indio_dev);\n" + "> > +\tif (ret)\n" + "> > +\t\tgoto err_clk;\n" + "> > +\n" + "> > +\treturn 0;\n" "> > +\n" "> > +err_clk:\n" - "> > +=09clk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" "> > +err_pclk:\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" "> > +err_reg_voltage:\n" - "> > +=09regulator_disable(info->vref);\n" - "> > +=09return ret;\n" + "> > +\tregulator_disable(info->vref);\n" + "> > +\treturn ret;\n" "> > +}\n" "> > +\n" "> > +static int rockchip_saradc_remove(struct platform_device *pdev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D platform_get_drvdata(pdev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct iio_dev *indio_dev = platform_get_drvdata(pdev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09iio_device_unregister(indio_dev);\n" - "> > +=09clk_disable_unprepare(info->clk);\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" - "> > +=09regulator_disable(info->vref);\n" + "> > +\tiio_device_unregister(indio_dev);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" + "> > +\tregulator_disable(info->vref);\n" "> > +\n" - "> > +=09return 0;\n" + "> > +\treturn 0;\n" "> > +}\n" "> > +\n" "> > +#ifdef CONFIG_PM_SLEEP\n" "> > +static int rockchip_saradc_suspend(struct device *dev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" + "> > +\tstruct iio_dev *indio_dev = dev_get_drvdata(dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" "> > +\n" - "> > +=09clk_disable_unprepare(info->clk);\n" - "> > +=09clk_disable_unprepare(info->pclk);\n" - "> > +=09regulator_disable(info->vref);\n" + "> > +\tclk_disable_unprepare(info->clk);\n" + "> > +\tclk_disable_unprepare(info->pclk);\n" + "> > +\tregulator_disable(info->vref);\n" "> > +\n" - "> > +=09return 0;\n" + "> > +\treturn 0;\n" "> > +}\n" "> > +\n" "> > +static int rockchip_saradc_resume(struct device *dev)\n" "> > +{\n" - "> > +=09struct iio_dev *indio_dev =3D dev_get_drvdata(dev);\n" - "> > +=09struct rockchip_saradc *info =3D iio_priv(indio_dev);\n" - "> > +=09int ret;\n" + "> > +\tstruct iio_dev *indio_dev = dev_get_drvdata(dev);\n" + "> > +\tstruct rockchip_saradc *info = iio_priv(indio_dev);\n" + "> > +\tint ret;\n" "> > +\n" - "> > +=09ret =3D regulator_enable(info->vref);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = regulator_enable(info->vref);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->pclk);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = clk_prepare_enable(info->pclk);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09ret =3D clk_prepare_enable(info->clk);\n" - "> > +=09if (ret)\n" - "> > +=09=09return ret;\n" + "> > +\tret = clk_prepare_enable(info->clk);\n" + "> > +\tif (ret)\n" + "> > +\t\treturn ret;\n" "> > +\n" - "> > +=09return ret;\n" + "> > +\treturn ret;\n" "> > +}\n" "> > +#endif\n" "> > +\n" "> > +static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,\n" - "> > +=09=09=09 rockchip_saradc_suspend, rockchip_saradc_resume);\n" + "> > +\t\t\t rockchip_saradc_suspend, rockchip_saradc_resume);\n" "> > +\n" - "> > +static const struct of_device_id rockchip_saradc_match[] =3D {\n" - "> > +=09{ .compatible =3D \"rockchip,saradc\" },\n" - "> > +=09{},\n" + "> > +static const struct of_device_id rockchip_saradc_match[] = {\n" + "> > +\t{ .compatible = \"rockchip,saradc\" },\n" + "> > +\t{},\n" "> > +};\n" "> > +MODULE_DEVICE_TABLE(of, rockchip_saradc_match);\n" "> > +\n" - "> > +static struct platform_driver rockchip_saradc_driver =3D {\n" - "> > +=09.probe=09=09=3D rockchip_saradc_probe,\n" - "> > +=09.remove=09=09=3D rockchip_saradc_remove,\n" - "> > +=09.driver=09=09=3D {\n" - "> > +=09=09.name=09=3D \"rockchip-saradc\",\n" - "> > +=09=09.owner=09=3D THIS_MODULE,\n" - "> > +=09=09.of_match_table =3D rockchip_saradc_match,\n" - "> > +=09=09.pm=09=3D &rockchip_saradc_pm_ops,\n" - "> > +=09},\n" + "> > +static struct platform_driver rockchip_saradc_driver = {\n" + "> > +\t.probe\t\t= rockchip_saradc_probe,\n" + "> > +\t.remove\t\t= rockchip_saradc_remove,\n" + "> > +\t.driver\t\t= {\n" + "> > +\t\t.name\t= \"rockchip-saradc\",\n" + "> > +\t\t.owner\t= THIS_MODULE,\n" + "> > +\t\t.of_match_table = rockchip_saradc_match,\n" + "> > +\t\t.pm\t= &rockchip_saradc_pm_ops,\n" + "> > +\t},\n" "> > +};\n" "> > +\n" > > +module_platform_driver(rockchip_saradc_driver); -0e5ea159e619b9e530c8290dde81e56be4a7a3be243f436452570055a638eb61 +4ab39df506a45bc2ad2cbeed58fe0bbdf067a9ac1445a9aaed61549e121dd901
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.