Re: [PATCH v2 2/2] iio: adc: add NPCM ADC driver

2019-01-12 Thread Jonathan Cameron
On Wed,  9 Jan 2019 18:43:43 +0200
Tomer Maimon  wrote:

> Add Nuvoton NPCM BMC Analog-to-Digital Converter(ADC) driver.
> 
> The NPCM ADC is a 10-bit converter for eight channel inputs.
> 
> Signed-off-by: Tomer Maimon 
Hi Tomer,

Only remaining element I think needs tidying up is the relative
ordering of probe vs remove and the interaction with devm managed
cleanup.

I really like to see the two elements being as near as possible
to opposite in order. It's a lot harder to review if they aren't.
Chances are there isn't a race condition in here, but if they are
in the 'right' order it becomes much more obvious that there isn't!

Thanks,

Jonathan

> ---
>  drivers/iio/adc/Kconfig|  10 ++
>  drivers/iio/adc/Makefile   |   1 +
>  drivers/iio/adc/npcm_adc.c | 338 
> +
>  3 files changed, 349 insertions(+)
>  create mode 100644 drivers/iio/adc/npcm_adc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 7a3ca4ec0cb7..2d1e70a7d5c4 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -576,6 +576,16 @@ config NAU7802
> To compile this driver as a module, choose M here: the
> module will be called nau7802.
>  
> +config NPCM_ADC
> + tristate "Nuvoton NPCM ADC driver"
> + depends on ARCH_NPCM || COMPILE_TEST
> + depends on HAS_IOMEM
> + help
> +   Say yes here to build support for Nuvoton NPCM ADC.
> +
> +   This driver can also be built as a module. If so, the module
> +   will be called npcm_adc.
> +
>  config PALMAS_GPADC
>   tristate "TI Palmas General Purpose ADC"
>   depends on MFD_PALMAS
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 07df37f621bd..3337eb1f4c30 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -55,6 +55,7 @@ obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
>  obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
>  obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
>  obj-$(CONFIG_NAU7802) += nau7802.o
> +obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
>  obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
>  obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
>  obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
> diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
> new file mode 100644
> index ..c364f2dbd702
> --- /dev/null
> +++ b/drivers/iio/adc/npcm_adc.c
> @@ -0,0 +1,338 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2019 Nuvoton Technology corporation.
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +struct npcm_adc {
> + bool int_status;
> + u32 adc_sample_hz;
> + struct device *dev;
> + void __iomem *regs;
> + struct clk *adc_clk;
> + wait_queue_head_t wq;
> + struct regulator *vref;
> + struct regmap *rst_regmap;
> +};
> +
> +/* NPCM7xx reset module */
> +#define NPCM7XX_IPSRST1_OFFSET   0x020
> +#define NPCM7XX_IPSRST1_ADC_RST  BIT(27)
> +
> +/* ADC registers */
> +#define NPCM_ADCCON   0x00
> +#define NPCM_ADCDATA  0x04
> +
> +/* ADCCON Register Bits */
> +#define NPCM_ADCCON_ADC_INT_EN   BIT(21)
> +#define NPCM_ADCCON_REFSEL   BIT(19)
> +#define NPCM_ADCCON_ADC_INT_ST   BIT(18)
> +#define NPCM_ADCCON_ADC_EN   BIT(17)
> +#define NPCM_ADCCON_ADC_RST  BIT(16)
> +#define NPCM_ADCCON_ADC_CONV BIT(13)
> +
> +#define NPCM_ADCCON_CH_MASK  GENMASK(27, 24)
> +#define NPCM_ADCCON_CH(x)((x) << 24)
> +#define NPCM_ADCCON_DIV_SHIFT1
> +#define NPCM_ADCCON_DIV_MASK GENMASK(8, 1)
> +#define NPCM_ADC_DATA_MASK(x)((x) & GENMASK(9, 0))
> +
> +#define NPCM_ADC_ENABLE  (NPCM_ADCCON_ADC_EN | 
> NPCM_ADCCON_ADC_INT_EN)
> +
> +/* ADC General Definition */
> +#define NPCM_RESOLUTION_BITS 10
> +#define NPCM_ADC_DEFAULT_SAMPLE_RATE 1250
> +#define NPCM_INT_VREF_MV 2000
> +
> +#define NPCM_ADC_CHAN(ch) {  \
> + .type = IIO_VOLTAGE,\
> + .indexed = 1,   \
> + .channel = ch,  \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
> + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
> +}
> +
> +static const struct iio_chan_spec npcm_adc_iio_channels[] = {
> + NPCM_ADC_CHAN(0),
> + NPCM_ADC_CHAN(1),
> + NPCM_ADC_CHAN(2),
> + NPCM_ADC_CHAN(3),
> + NPCM_ADC_CHAN(4),
> + NPCM_ADC_CHAN(5),
> + NPCM_ADC_CHAN(6),
> + NPCM_ADC_CHAN(7),
> +};
> +
> +static irqreturn_t npcm_adc_isr(int irq, void *data)
> +{
> + u32 regtemp;
> + struct iio_dev *indio_dev = data;
> + struct npcm_adc *info = ii

[PATCH v2 2/2] iio: adc: add NPCM ADC driver

2019-01-09 Thread Tomer Maimon
Add Nuvoton NPCM BMC Analog-to-Digital Converter(ADC) driver.

The NPCM ADC is a 10-bit converter for eight channel inputs.

Signed-off-by: Tomer Maimon 
---
 drivers/iio/adc/Kconfig|  10 ++
 drivers/iio/adc/Makefile   |   1 +
 drivers/iio/adc/npcm_adc.c | 338 +
 3 files changed, 349 insertions(+)
 create mode 100644 drivers/iio/adc/npcm_adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7a3ca4ec0cb7..2d1e70a7d5c4 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -576,6 +576,16 @@ config NAU7802
  To compile this driver as a module, choose M here: the
  module will be called nau7802.
 
+config NPCM_ADC
+   tristate "Nuvoton NPCM ADC driver"
+   depends on ARCH_NPCM || COMPILE_TEST
+   depends on HAS_IOMEM
+   help
+ Say yes here to build support for Nuvoton NPCM ADC.
+
+ This driver can also be built as a module. If so, the module
+ will be called npcm_adc.
+
 config PALMAS_GPADC
tristate "TI Palmas General Purpose ADC"
depends on MFD_PALMAS
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 07df37f621bd..3337eb1f4c30 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
 obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
 obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
 obj-$(CONFIG_NAU7802) += nau7802.o
+obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
 obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
 obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
 obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
new file mode 100644
index ..c364f2dbd702
--- /dev/null
+++ b/drivers/iio/adc/npcm_adc.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019 Nuvoton Technology corporation.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct npcm_adc {
+   bool int_status;
+   u32 adc_sample_hz;
+   struct device *dev;
+   void __iomem *regs;
+   struct clk *adc_clk;
+   wait_queue_head_t wq;
+   struct regulator *vref;
+   struct regmap *rst_regmap;
+};
+
+/* NPCM7xx reset module */
+#define NPCM7XX_IPSRST1_OFFSET 0x020
+#define NPCM7XX_IPSRST1_ADC_RSTBIT(27)
+
+/* ADC registers */
+#define NPCM_ADCCON 0x00
+#define NPCM_ADCDATA0x04
+
+/* ADCCON Register Bits */
+#define NPCM_ADCCON_ADC_INT_EN BIT(21)
+#define NPCM_ADCCON_REFSEL BIT(19)
+#define NPCM_ADCCON_ADC_INT_ST BIT(18)
+#define NPCM_ADCCON_ADC_EN BIT(17)
+#define NPCM_ADCCON_ADC_RSTBIT(16)
+#define NPCM_ADCCON_ADC_CONV   BIT(13)
+
+#define NPCM_ADCCON_CH_MASKGENMASK(27, 24)
+#define NPCM_ADCCON_CH(x)  ((x) << 24)
+#define NPCM_ADCCON_DIV_SHIFT  1
+#define NPCM_ADCCON_DIV_MASK   GENMASK(8, 1)
+#define NPCM_ADC_DATA_MASK(x)  ((x) & GENMASK(9, 0))
+
+#define NPCM_ADC_ENABLE(NPCM_ADCCON_ADC_EN | 
NPCM_ADCCON_ADC_INT_EN)
+
+/* ADC General Definition */
+#define NPCM_RESOLUTION_BITS   10
+#define NPCM_ADC_DEFAULT_SAMPLE_RATE   1250
+#define NPCM_INT_VREF_MV   2000
+
+#define NPCM_ADC_CHAN(ch) {\
+   .type = IIO_VOLTAGE,\
+   .indexed = 1,   \
+   .channel = ch,  \
+   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
+   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+}
+
+static const struct iio_chan_spec npcm_adc_iio_channels[] = {
+   NPCM_ADC_CHAN(0),
+   NPCM_ADC_CHAN(1),
+   NPCM_ADC_CHAN(2),
+   NPCM_ADC_CHAN(3),
+   NPCM_ADC_CHAN(4),
+   NPCM_ADC_CHAN(5),
+   NPCM_ADC_CHAN(6),
+   NPCM_ADC_CHAN(7),
+};
+
+static irqreturn_t npcm_adc_isr(int irq, void *data)
+{
+   u32 regtemp;
+   struct iio_dev *indio_dev = data;
+   struct npcm_adc *info = iio_priv(indio_dev);
+
+   regtemp = ioread32(info->regs + NPCM_ADCCON);
+   if (regtemp & NPCM_ADCCON_ADC_INT_ST) {
+   iowrite32(regtemp, info->regs + NPCM_ADCCON);
+   wake_up_interruptible(&info->wq);
+   info->int_status = true;
+   }
+
+   return IRQ_HANDLED;
+}
+
+static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
+{
+   int ret;
+   u32 regtemp;
+
+   /* Select ADC channel */
+   regtemp = ioread32(info->regs + NPCM_ADCCON);
+   regtemp &= ~NPCM_ADCCON_CH_MASK;
+   info->int_status = false;
+   iowrite32(regtemp | NPCM_ADCCON_CH(channel) |
+ NPCM_ADCCON_ADC_CONV,