| // SPDX-License-Identifier: GPL-2.0-only | |
| /* | |
| * NXP SAR-ADC driver (adapted from Freescale Vybrid vf610 ADC driver | |
| * by Fugang Duan <B38611@freescale.com>) | |
| * | |
| * Copyright 2013 Freescale Semiconductor, Inc. | |
| * Copyright 2017, 2020-2025 NXP | |
| * Copyright 2025, Linaro Ltd | |
| */ | |
| #include <linux/bitfield.h> | |
| #include <linux/bitops.h> | |
| #include <linux/circ_buf.h> | |
| #include <linux/cleanup.h> | |
| #include <linux/clk.h> | |
| #include <linux/completion.h> | |
| #include <linux/delay.h> | |
| #include <linux/dma-mapping.h> | |
| #include <linux/dmaengine.h> | |
| #include <linux/err.h> | |
| #include <linux/interrupt.h> | |
| #include <linux/iopoll.h> | |
| #include <linux/math64.h> | |
| #include <linux/minmax.h> | |
| #include <linux/mod_devicetable.h> | |
| #include <linux/module.h> | |
| #include <linux/platform_device.h> | |
| #include <linux/pm.h> | |
| #include <linux/property.h> | |
| #include <linux/slab.h> | |
| #include <linux/spinlock.h> | |
| #include <linux/time.h> | |
| #include <linux/types.h> | |
| #include <linux/units.h> | |
| #include <linux/iio/iio.h> | |
| #include <linux/iio/triggered_buffer.h> | |
| #include <linux/iio/trigger_consumer.h> | |
| /* SAR ADC registers. */ | |
| #define NXP_SAR_ADC_CDR(__base, __channel) (((__base) + 0x100) + ((__channel) * 0x4)) | |
| #define NXP_SAR_ADC_CDR_CDATA_MASK GENMASK(11, 0) | |
| #define NXP_SAR_ADC_CDR_VALID BIT(19) | |
| /* Main Configuration Register */ | |
| #define NXP_SAR_ADC_MCR(__base) ((__base) + 0x00) | |
| #define NXP_SAR_ADC_MCR_PWDN BIT(0) | |
| #define NXP_SAR_ADC_MCR_ACKO BIT(5) | |
| #define NXP_SAR_ADC_MCR_ADCLKSEL BIT(8) | |
| #define NXP_SAR_ADC_MCR_TSAMP_MASK GENMASK(10, 9) | |
| #define NXP_SAR_ADC_MCR_NRSMPL_MASK GENMASK(12, 11) | |
| #define NXP_SAR_ADC_MCR_AVGEN BIT(13) | |
| #define NXP_SAR_ADC_MCR_CALSTART BIT(14) | |
| #define NXP_SAR_ADC_MCR_NSTART BIT(24) | |
| #define NXP_SAR_ADC_MCR_MODE BIT(29) | |
| #define NXP_SAR_ADC_MCR_OWREN BIT(31) | |
| /* Main Status Register */ | |
| #define NXP_SAR_ADC_MSR(__base) ((__base) + 0x04) | |
| #define NXP_SAR_ADC_MSR_CALBUSY BIT(29) | |
| #define NXP_SAR_ADC_MSR_CALFAIL BIT(30) | |
| /* Interrupt Status Register */ | |
| #define NXP_SAR_ADC_ISR(__base) ((__base) + 0x10) | |
| #define NXP_SAR_ADC_ISR_ECH BIT(0) | |
| /* Channel Pending Register */ | |
| #define NXP_SAR_ADC_CEOCFR0(__base) ((__base) + 0x14) | |
| #define NXP_SAR_ADC_CEOCFR1(__base) ((__base) + 0x18) | |
| #define NXP_SAR_ADC_EOC_CH(c) BIT(c) | |
| /* Interrupt Mask Register */ | |
| #define NXP_SAR_ADC_IMR(__base) ((__base) + 0x20) | |
| /* Channel Interrupt Mask Register */ | |
| #define NXP_SAR_ADC_CIMR0(__base) ((__base) + 0x24) | |
| #define NXP_SAR_ADC_CIMR1(__base) ((__base) + 0x28) | |
| /* DMA Setting Register */ | |
| #define NXP_SAR_ADC_DMAE(__base) ((__base) + 0x40) | |
| #define NXP_SAR_ADC_DMAE_DMAEN BIT(0) | |
| #define NXP_SAR_ADC_DMAE_DCLR BIT(1) | |
| /* DMA Control register */ | |
| #define NXP_SAR_ADC_DMAR0(__base) ((__base) + 0x44) | |
| #define NXP_SAR_ADC_DMAR1(__base) ((__base) + 0x48) | |
| /* Conversion Timing Register */ | |
| #define NXP_SAR_ADC_CTR0(__base) ((__base) + 0x94) | |
| #define NXP_SAR_ADC_CTR1(__base) ((__base) + 0x98) | |
| #define NXP_SAR_ADC_CTR_INPSAMP_MIN 0x08 | |
| #define NXP_SAR_ADC_CTR_INPSAMP_MAX 0xff | |
| /* Normal Conversion Mask Register */ | |
| #define NXP_SAR_ADC_NCMR0(__base) ((__base) + 0xa4) | |
| #define NXP_SAR_ADC_NCMR1(__base) ((__base) + 0xa8) | |
| /* Normal Conversion Mask Register field define */ | |
| #define NXP_SAR_ADC_CH_MASK GENMASK(7, 0) | |
| /* Other field define */ | |
| #define NXP_SAR_ADC_CONV_TIMEOUT (msecs_to_jiffies(100)) | |
| #define NXP_SAR_ADC_CAL_TIMEOUT_US (100 * USEC_PER_MSEC) | |
| #define NXP_SAR_ADC_WAIT_US (2 * USEC_PER_MSEC) | |
| #define NXP_SAR_ADC_RESOLUTION 12 | |
| /* Duration of conversion phases */ | |
| #define NXP_SAR_ADC_TPT 2 | |
| #define NXP_SAR_ADC_DP 2 | |
| #define NXP_SAR_ADC_CT ((NXP_SAR_ADC_RESOLUTION + 2) * 4) | |
| #define NXP_SAR_ADC_CONV_TIME (NXP_SAR_ADC_TPT + NXP_SAR_ADC_CT + NXP_SAR_ADC_DP) | |
| #define NXP_SAR_ADC_NR_CHANNELS 8 | |
| #define NXP_PAGE_SIZE SZ_4K | |
| #define NXP_SAR_ADC_DMA_SAMPLE_SZ DMA_SLAVE_BUSWIDTH_4_BYTES | |
| #define NXP_SAR_ADC_DMA_BUFF_SZ (NXP_PAGE_SIZE * NXP_SAR_ADC_DMA_SAMPLE_SZ) | |
| #define NXP_SAR_ADC_DMA_SAMPLE_CNT (NXP_SAR_ADC_DMA_BUFF_SZ / NXP_SAR_ADC_DMA_SAMPLE_SZ) | |
| struct nxp_sar_adc { | |
| void __iomem *regs; | |
| phys_addr_t regs_phys; | |
| u8 current_channel; | |
| u8 channels_used; | |
| u16 value; | |
| u32 vref_mV; | |
| /* Save and restore context. */ | |
| u32 inpsamp; | |
| u32 pwdn; | |
| struct clk *clk; | |
| struct dma_chan *dma_chan; | |
| struct completion completion; | |
| struct circ_buf dma_buf; | |
| dma_addr_t rx_dma_buf; | |
| dma_cookie_t cookie; | |
| /* Protect circular buffers access. */ | |
| spinlock_t lock; | |
| /* Array of enabled channels. */ | |
| u16 buffered_chan[NXP_SAR_ADC_NR_CHANNELS]; | |
| /* Buffer to be filled by the DMA. */ | |
| IIO_DECLARE_BUFFER_WITH_TS(u16, buffer, NXP_SAR_ADC_NR_CHANNELS); | |
| }; | |
| struct nxp_sar_adc_data { | |
| u32 vref_mV; | |
| const char *model; | |
| }; | |
| #define ADC_CHAN(_idx, _chan_type) { \ | |
| .type = (_chan_type), \ | |
| .indexed = 1, \ | |
| .channel = (_idx), \ | |
| .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | |
| BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
| .scan_index = (_idx), \ | |
| .scan_type = { \ | |
| .sign = 'u', \ | |
| .realbits = 12, \ | |
| .storagebits = 16, \ | |
| }, \ | |
| } | |
| static const struct iio_chan_spec nxp_sar_adc_iio_channels[] = { | |
| ADC_CHAN(0, IIO_VOLTAGE), | |
| ADC_CHAN(1, IIO_VOLTAGE), | |
| ADC_CHAN(2, IIO_VOLTAGE), | |
| ADC_CHAN(3, IIO_VOLTAGE), | |
| ADC_CHAN(4, IIO_VOLTAGE), | |
| ADC_CHAN(5, IIO_VOLTAGE), | |
| ADC_CHAN(6, IIO_VOLTAGE), | |
| ADC_CHAN(7, IIO_VOLTAGE), | |
| /* | |
| * The NXP SAR ADC documentation marks the channels 8 to 31 as | |
| * "Reserved". Reflect the same in the driver in case new ADC | |
| * variants comes with more channels. | |
| */ | |
| IIO_CHAN_SOFT_TIMESTAMP(32), | |
| }; | |
| static void nxp_sar_adc_irq_cfg(struct nxp_sar_adc *info, bool enable) | |
| { | |
| if (enable) | |
| writel(NXP_SAR_ADC_ISR_ECH, NXP_SAR_ADC_IMR(info->regs)); | |
| else | |
| writel(0, NXP_SAR_ADC_IMR(info->regs)); | |
| } | |
| static bool nxp_sar_adc_set_enabled(struct nxp_sar_adc *info, bool enable) | |
| { | |
| u32 mcr; | |
| bool pwdn; | |
| mcr = readl(NXP_SAR_ADC_MCR(info->regs)); | |
| /* | |
| * Get the current state and return it later. This is used for | |
| * suspend/resume to get the power state | |
| */ | |
| pwdn = FIELD_GET(NXP_SAR_ADC_MCR_PWDN, mcr); | |
| /* When the enabled flag is not set, we set the power down bit */ | |
| FIELD_MODIFY(NXP_SAR_ADC_MCR_PWDN, &mcr, !enable); | |
| writel(mcr, NXP_SAR_ADC_MCR(info->regs)); | |
| /* | |
| * Ensure there are at least three cycles between the | |
| * configuration of NCMR and the setting of NSTART. | |
| */ | |
| if (enable) | |
| ndelay(div64_u64(NSEC_PER_SEC, clk_get_rate(info->clk) * 3)); | |
| return pwdn; | |
| } | |
| static inline bool nxp_sar_adc_enable(struct nxp_sar_adc *info) | |
| { | |
| return nxp_sar_adc_set_enabled(info, true); | |
| } | |
| static inline bool nxp_sar_adc_disable(struct nxp_sar_adc *info) | |
| { | |
| return nxp_sar_adc_set_enabled(info, false); | |
| } | |
| static inline void nxp_sar_adc_calibration_start(void __iomem *base) | |
| { | |
| u32 mcr = readl(NXP_SAR_ADC_MCR(base)); | |
| FIELD_MODIFY(NXP_SAR_ADC_MCR_CALSTART, &mcr, 0x1); | |
| writel(mcr, NXP_SAR_ADC_MCR(base)); | |
| } | |
| static inline int nxp_sar_adc_calibration_wait(void __iomem *base) | |
| { | |
| u32 msr; | |
| int ret; | |
| ret = readl_poll_timeout(NXP_SAR_ADC_MSR(base), msr, | |
| !FIELD_GET(NXP_SAR_ADC_MSR_CALBUSY, msr), | |
| NXP_SAR_ADC_WAIT_US, | |
| NXP_SAR_ADC_CAL_TIMEOUT_US); | |
| if (ret) | |
| return ret; | |
| if (FIELD_GET(NXP_SAR_ADC_MSR_CALFAIL, msr)) { | |
| /* | |
| * If the calibration fails, the status register bit must be | |
| * cleared. | |
| */ | |
| FIELD_MODIFY(NXP_SAR_ADC_MSR_CALFAIL, &msr, 0x0); | |
| writel(msr, NXP_SAR_ADC_MSR(base)); | |
| return -EAGAIN; | |
| } | |
| return 0; | |
| } | |
| static int nxp_sar_adc_calibration(struct nxp_sar_adc *info) | |
| { | |
| int ret; | |
| /* Calibration works only if the ADC is powered up. */ | |
| nxp_sar_adc_enable(info); | |
| /* The calibration operation starts. */ | |
| nxp_sar_adc_calibration_start(info->regs); | |
| ret = nxp_sar_adc_calibration_wait(info->regs); | |
| /* | |
| * Calibration works only if the ADC is powered up. However | |
| * the calibration is called from the probe function where the | |
| * iio is not enabled, so we disable after the calibration. | |
| */ | |
| nxp_sar_adc_disable(info); | |
| return ret; | |
| } | |
| static void nxp_sar_adc_conversion_timing_set(struct nxp_sar_adc *info, u32 inpsamp) | |
| { | |
| inpsamp = clamp(inpsamp, NXP_SAR_ADC_CTR_INPSAMP_MIN, NXP_SAR_ADC_CTR_INPSAMP_MAX); | |
| writel(inpsamp, NXP_SAR_ADC_CTR0(info->regs)); | |
| } | |
| static u32 nxp_sar_adc_conversion_timing_get(struct nxp_sar_adc *info) | |
| { | |
| return readl(NXP_SAR_ADC_CTR0(info->regs)); | |
| } | |
| static void nxp_sar_adc_read_notify(struct nxp_sar_adc *info) | |
| { | |
| writel(NXP_SAR_ADC_CH_MASK, NXP_SAR_ADC_CEOCFR0(info->regs)); | |
| writel(NXP_SAR_ADC_CH_MASK, NXP_SAR_ADC_CEOCFR1(info->regs)); | |
| } | |
| static int nxp_sar_adc_read_data(struct nxp_sar_adc *info, unsigned int chan) | |
| { | |
| u32 ceocfr, cdr; | |
| ceocfr = readl(NXP_SAR_ADC_CEOCFR0(info->regs)); | |
| /* | |
| * FIELD_GET() can not be used here because EOC_CH is not constant. | |
| * TODO: Switch to field_get() when it will be available. | |
| */ | |
| if (!(NXP_SAR_ADC_EOC_CH(chan) & ceocfr)) | |
| return -EIO; | |
| cdr = readl(NXP_SAR_ADC_CDR(info->regs, chan)); | |
| if (!(FIELD_GET(NXP_SAR_ADC_CDR_VALID, cdr))) | |
| return -EIO; | |
| return FIELD_GET(NXP_SAR_ADC_CDR_CDATA_MASK, cdr); | |
| } | |
| static void nxp_sar_adc_isr_buffer(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| unsigned int i; | |
| int ret; | |
| for (i = 0; i < info->channels_used; i++) { | |
| ret = nxp_sar_adc_read_data(info, info->buffered_chan[i]); | |
| if (ret < 0) { | |
| nxp_sar_adc_read_notify(info); | |
| return; | |
| } | |
| info->buffer[i] = ret; | |
| } | |
| nxp_sar_adc_read_notify(info); | |
| iio_push_to_buffers_with_ts(indio_dev, info->buffer, sizeof(info->buffer), | |
| iio_get_time_ns(indio_dev)); | |
| iio_trigger_notify_done(indio_dev->trig); | |
| } | |
| static void nxp_sar_adc_isr_read_raw(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| int ret; | |
| ret = nxp_sar_adc_read_data(info, info->current_channel); | |
| nxp_sar_adc_read_notify(info); | |
| if (ret < 0) | |
| return; | |
| info->value = ret; | |
| complete(&info->completion); | |
| } | |
| static irqreturn_t nxp_sar_adc_isr(int irq, void *dev_id) | |
| { | |
| struct iio_dev *indio_dev = dev_id; | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| int isr; | |
| isr = readl(NXP_SAR_ADC_ISR(info->regs)); | |
| if (!(FIELD_GET(NXP_SAR_ADC_ISR_ECH, isr))) | |
| return IRQ_NONE; | |
| if (iio_buffer_enabled(indio_dev)) | |
| nxp_sar_adc_isr_buffer(indio_dev); | |
| else | |
| nxp_sar_adc_isr_read_raw(indio_dev); | |
| writel(NXP_SAR_ADC_ISR_ECH, NXP_SAR_ADC_ISR(info->regs)); | |
| return IRQ_HANDLED; | |
| } | |
| static void nxp_sar_adc_channels_disable(struct nxp_sar_adc *info, u32 mask) | |
| { | |
| u32 ncmr, cimr; | |
| ncmr = readl(NXP_SAR_ADC_NCMR0(info->regs)); | |
| cimr = readl(NXP_SAR_ADC_CIMR0(info->regs)); | |
| /* FIELD_MODIFY() can not be used because the mask is not constant */ | |
| ncmr &= ~mask; | |
| cimr &= ~mask; | |
| writel(ncmr, NXP_SAR_ADC_NCMR0(info->regs)); | |
| writel(cimr, NXP_SAR_ADC_CIMR0(info->regs)); | |
| } | |
| static void nxp_sar_adc_channels_enable(struct nxp_sar_adc *info, u32 mask) | |
| { | |
| u32 ncmr, cimr; | |
| ncmr = readl(NXP_SAR_ADC_NCMR0(info->regs)); | |
| cimr = readl(NXP_SAR_ADC_CIMR0(info->regs)); | |
| ncmr |= mask; | |
| cimr |= mask; | |
| writel(ncmr, NXP_SAR_ADC_NCMR0(info->regs)); | |
| writel(cimr, NXP_SAR_ADC_CIMR0(info->regs)); | |
| } | |
| static void nxp_sar_adc_dma_channels_enable(struct nxp_sar_adc *info, u32 mask) | |
| { | |
| u32 dmar; | |
| dmar = readl(NXP_SAR_ADC_DMAR0(info->regs)); | |
| dmar |= mask; | |
| writel(dmar, NXP_SAR_ADC_DMAR0(info->regs)); | |
| } | |
| static void nxp_sar_adc_dma_channels_disable(struct nxp_sar_adc *info, u32 mask) | |
| { | |
| u32 dmar; | |
| dmar = readl(NXP_SAR_ADC_DMAR0(info->regs)); | |
| dmar &= ~mask; | |
| writel(dmar, NXP_SAR_ADC_DMAR0(info->regs)); | |
| } | |
| static void nxp_sar_adc_dma_cfg(struct nxp_sar_adc *info, bool enable) | |
| { | |
| u32 dmae; | |
| dmae = readl(NXP_SAR_ADC_DMAE(info->regs)); | |
| FIELD_MODIFY(NXP_SAR_ADC_DMAE_DMAEN, &dmae, enable); | |
| writel(dmae, NXP_SAR_ADC_DMAE(info->regs)); | |
| } | |
| static void nxp_sar_adc_stop_conversion(struct nxp_sar_adc *info) | |
| { | |
| u32 mcr; | |
| mcr = readl(NXP_SAR_ADC_MCR(info->regs)); | |
| FIELD_MODIFY(NXP_SAR_ADC_MCR_NSTART, &mcr, 0x0); | |
| writel(mcr, NXP_SAR_ADC_MCR(info->regs)); | |
| /* | |
| * On disable, we have to wait for the transaction to finish. | |
| * ADC does not abort the transaction if a chain conversion is | |
| * in progress. Wait for the worst case scenario - 80 ADC clk | |
| * cycles. The clock rate is 80MHz, this routine is called | |
| * only when the capture finishes. The delay will be very | |
| * short, usec-ish, which is acceptable in the atomic context. | |
| */ | |
| ndelay(div64_u64(NSEC_PER_SEC, clk_get_rate(info->clk)) * 80); | |
| } | |
| static int nxp_sar_adc_start_conversion(struct nxp_sar_adc *info, bool raw) | |
| { | |
| u32 mcr; | |
| mcr = readl(NXP_SAR_ADC_MCR(info->regs)); | |
| FIELD_MODIFY(NXP_SAR_ADC_MCR_NSTART, &mcr, 0x1); | |
| FIELD_MODIFY(NXP_SAR_ADC_MCR_MODE, &mcr, raw ? 0 : 1); | |
| writel(mcr, NXP_SAR_ADC_MCR(info->regs)); | |
| return 0; | |
| } | |
| static int nxp_sar_adc_read_channel(struct nxp_sar_adc *info, int channel) | |
| { | |
| int ret; | |
| info->current_channel = channel; | |
| nxp_sar_adc_channels_enable(info, BIT(channel)); | |
| nxp_sar_adc_irq_cfg(info, true); | |
| nxp_sar_adc_enable(info); | |
| reinit_completion(&info->completion); | |
| ret = nxp_sar_adc_start_conversion(info, true); | |
| if (ret < 0) | |
| goto out_disable; | |
| if (!wait_for_completion_interruptible_timeout(&info->completion, | |
| NXP_SAR_ADC_CONV_TIMEOUT)) | |
| ret = -ETIMEDOUT; | |
| nxp_sar_adc_stop_conversion(info); | |
| out_disable: | |
| nxp_sar_adc_channels_disable(info, BIT(channel)); | |
| nxp_sar_adc_irq_cfg(info, false); | |
| nxp_sar_adc_disable(info); | |
| return ret; | |
| } | |
| static int nxp_sar_adc_read_raw(struct iio_dev *indio_dev, | |
| struct iio_chan_spec const *chan, int *val, | |
| int *val2, long mask) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| u32 inpsamp; | |
| int ret; | |
| switch (mask) { | |
| case IIO_CHAN_INFO_RAW: | |
| if (!iio_device_claim_direct(indio_dev)) | |
| return -EBUSY; | |
| ret = nxp_sar_adc_read_channel(info, chan->channel); | |
| iio_device_release_direct(indio_dev); | |
| if (ret) | |
| return ret; | |
| *val = info->value; | |
| return IIO_VAL_INT; | |
| case IIO_CHAN_INFO_SCALE: | |
| *val = info->vref_mV; | |
| *val2 = NXP_SAR_ADC_RESOLUTION; | |
| return IIO_VAL_FRACTIONAL_LOG2; | |
| case IIO_CHAN_INFO_SAMP_FREQ: | |
| inpsamp = nxp_sar_adc_conversion_timing_get(info); | |
| *val = clk_get_rate(info->clk) / (inpsamp + NXP_SAR_ADC_CONV_TIME); | |
| return IIO_VAL_INT; | |
| default: | |
| return -EINVAL; | |
| } | |
| } | |
| static int nxp_sar_adc_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, | |
| int val, int val2, long mask) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| u32 inpsamp; | |
| switch (mask) { | |
| case IIO_CHAN_INFO_SAMP_FREQ: | |
| /* | |
| * Configures the sample period duration in terms of the SAR | |
| * controller clock. The minimum acceptable value is 8. | |
| * Configuring it to a value lower than 8 sets the sample period | |
| * to 8 cycles. We read the clock value and divide by the | |
| * sampling timing which gives us the number of cycles expected. | |
| * The value is 8-bit wide, consequently the max value is 0xFF. | |
| */ | |
| inpsamp = clk_get_rate(info->clk) / val - NXP_SAR_ADC_CONV_TIME; | |
| nxp_sar_adc_conversion_timing_set(info, inpsamp); | |
| return 0; | |
| default: | |
| return -EINVAL; | |
| } | |
| } | |
| static void nxp_sar_adc_dma_cb(void *data) | |
| { | |
| struct iio_dev *indio_dev = data; | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| struct dma_tx_state state; | |
| struct circ_buf *dma_buf; | |
| struct device *dev_dma; | |
| u32 *dma_samples; | |
| s64 timestamp; | |
| int idx, ret; | |
| guard(spinlock_irqsave)(&info->lock); | |
| dma_buf = &info->dma_buf; | |
| dma_samples = (u32 *)dma_buf->buf; | |
| dev_dma = info->dma_chan->device->dev; | |
| /* | |
| * DMA in some corner cases might have already be charged for | |
| * the next transfer. Potentially there can be a race where | |
| * the residue changes while the dma engine updates the | |
| * buffer. That could be handled by using the | |
| * callback_result() instead of callback() because the residue | |
| * will be passed as a parameter to the function. However this | |
| * new callback is pretty new and the backend does not update | |
| * the residue. So let's stick to the version other drivers do | |
| * which has proven running well in production since several | |
| * years. | |
| */ | |
| dmaengine_tx_status(info->dma_chan, info->cookie, &state); | |
| dma_sync_single_for_cpu(dev_dma, info->rx_dma_buf, | |
| NXP_SAR_ADC_DMA_BUFF_SZ, DMA_FROM_DEVICE); | |
| /* Current head position. */ | |
| dma_buf->head = (NXP_SAR_ADC_DMA_BUFF_SZ - state.residue) / | |
| NXP_SAR_ADC_DMA_SAMPLE_SZ; | |
| /* If everything was transferred, avoid an off by one error. */ | |
| if (!state.residue) | |
| dma_buf->head--; | |
| /* Something went wrong and nothing transferred. */ | |
| if (state.residue != NXP_SAR_ADC_DMA_BUFF_SZ) { | |
| /* Make sure that head is multiple of info->channels_used. */ | |
| dma_buf->head -= dma_buf->head % info->channels_used; | |
| /* | |
| * dma_buf->tail != dma_buf->head condition will become false | |
| * because dma_buf->tail will be incremented with 1. | |
| */ | |
| while (dma_buf->tail != dma_buf->head) { | |
| idx = dma_buf->tail % info->channels_used; | |
| info->buffer[idx] = dma_samples[dma_buf->tail]; | |
| dma_buf->tail = (dma_buf->tail + 1) % NXP_SAR_ADC_DMA_SAMPLE_CNT; | |
| if (idx != info->channels_used - 1) | |
| continue; | |
| /* | |
| * iio_push_to_buffers_with_ts() should not be | |
| * called with dma_samples as parameter. The samples | |
| * will be smashed if timestamp is enabled. | |
| */ | |
| timestamp = iio_get_time_ns(indio_dev); | |
| ret = iio_push_to_buffers_with_ts(indio_dev, info->buffer, | |
| sizeof(info->buffer), | |
| timestamp); | |
| if (ret < 0 && ret != -EBUSY) | |
| dev_err_ratelimited(&indio_dev->dev, | |
| "failed to push iio buffer: %d", | |
| ret); | |
| } | |
| dma_buf->tail = dma_buf->head; | |
| } | |
| dma_sync_single_for_device(dev_dma, info->rx_dma_buf, | |
| NXP_SAR_ADC_DMA_BUFF_SZ, DMA_FROM_DEVICE); | |
| } | |
| static int nxp_sar_adc_start_cyclic_dma(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| struct dma_slave_config config; | |
| struct dma_async_tx_descriptor *desc; | |
| int ret; | |
| info->dma_buf.head = 0; | |
| info->dma_buf.tail = 0; | |
| config.direction = DMA_DEV_TO_MEM; | |
| config.src_addr_width = NXP_SAR_ADC_DMA_SAMPLE_SZ; | |
| config.src_addr = NXP_SAR_ADC_CDR(info->regs_phys, info->buffered_chan[0]); | |
| config.src_port_window_size = info->channels_used; | |
| config.src_maxburst = info->channels_used; | |
| ret = dmaengine_slave_config(info->dma_chan, &config); | |
| if (ret < 0) | |
| return ret; | |
| desc = dmaengine_prep_dma_cyclic(info->dma_chan, | |
| info->rx_dma_buf, | |
| NXP_SAR_ADC_DMA_BUFF_SZ, | |
| NXP_SAR_ADC_DMA_BUFF_SZ / 2, | |
| DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); | |
| if (!desc) | |
| return -EINVAL; | |
| desc->callback = nxp_sar_adc_dma_cb; | |
| desc->callback_param = indio_dev; | |
| info->cookie = dmaengine_submit(desc); | |
| ret = dma_submit_error(info->cookie); | |
| if (ret) { | |
| dmaengine_terminate_async(info->dma_chan); | |
| return ret; | |
| } | |
| dma_async_issue_pending(info->dma_chan); | |
| return 0; | |
| } | |
| static void nxp_sar_adc_buffer_software_do_predisable(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| /* | |
| * The ADC DMAEN bit should be cleared before DMA transaction | |
| * is canceled. | |
| */ | |
| nxp_sar_adc_stop_conversion(info); | |
| dmaengine_terminate_sync(info->dma_chan); | |
| nxp_sar_adc_dma_cfg(info, false); | |
| nxp_sar_adc_dma_channels_disable(info, *indio_dev->active_scan_mask); | |
| dma_release_channel(info->dma_chan); | |
| } | |
| static int nxp_sar_adc_buffer_software_do_postenable(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| int ret; | |
| info->dma_chan = dma_request_chan(indio_dev->dev.parent, "rx"); | |
| if (IS_ERR(info->dma_chan)) | |
| return PTR_ERR(info->dma_chan); | |
| nxp_sar_adc_dma_channels_enable(info, *indio_dev->active_scan_mask); | |
| nxp_sar_adc_dma_cfg(info, true); | |
| ret = nxp_sar_adc_start_cyclic_dma(indio_dev); | |
| if (ret) | |
| goto out_dma_channels_disable; | |
| ret = nxp_sar_adc_start_conversion(info, false); | |
| if (ret) | |
| goto out_stop_cyclic_dma; | |
| return 0; | |
| out_stop_cyclic_dma: | |
| dmaengine_terminate_sync(info->dma_chan); | |
| out_dma_channels_disable: | |
| nxp_sar_adc_dma_cfg(info, false); | |
| nxp_sar_adc_dma_channels_disable(info, *indio_dev->active_scan_mask); | |
| dma_release_channel(info->dma_chan); | |
| return ret; | |
| } | |
| static void nxp_sar_adc_buffer_trigger_do_predisable(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| nxp_sar_adc_irq_cfg(info, false); | |
| } | |
| static int nxp_sar_adc_buffer_trigger_do_postenable(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| nxp_sar_adc_irq_cfg(info, true); | |
| return 0; | |
| } | |
| static int nxp_sar_adc_buffer_postenable(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| int current_mode = iio_device_get_current_mode(indio_dev); | |
| unsigned long channel; | |
| int ret; | |
| info->channels_used = 0; | |
| /* | |
| * The SAR-ADC has two groups of channels. | |
| * | |
| * - Group #0: | |
| * * bit 0-7 : channel 0 -> channel 7 | |
| * * bit 8-31 : reserved | |
| * | |
| * - Group #32: | |
| * * bit 0-7 : Internal | |
| * * bit 8-31 : reserved | |
| * | |
| * The 8 channels from group #0 are used in this driver for | |
| * ADC as described when declaring the IIO device and the | |
| * mapping is the same. That means the active_scan_mask can be | |
| * used directly to write the channel interrupt mask. | |
| */ | |
| nxp_sar_adc_channels_enable(info, *indio_dev->active_scan_mask); | |
| for_each_set_bit(channel, indio_dev->active_scan_mask, NXP_SAR_ADC_NR_CHANNELS) | |
| info->buffered_chan[info->channels_used++] = channel; | |
| nxp_sar_adc_enable(info); | |
| if (current_mode == INDIO_BUFFER_SOFTWARE) | |
| ret = nxp_sar_adc_buffer_software_do_postenable(indio_dev); | |
| else | |
| ret = nxp_sar_adc_buffer_trigger_do_postenable(indio_dev); | |
| if (ret) | |
| goto out_postenable; | |
| return 0; | |
| out_postenable: | |
| nxp_sar_adc_disable(info); | |
| nxp_sar_adc_channels_disable(info, *indio_dev->active_scan_mask); | |
| return ret; | |
| } | |
| static int nxp_sar_adc_buffer_predisable(struct iio_dev *indio_dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| int currentmode = iio_device_get_current_mode(indio_dev); | |
| if (currentmode == INDIO_BUFFER_SOFTWARE) | |
| nxp_sar_adc_buffer_software_do_predisable(indio_dev); | |
| else | |
| nxp_sar_adc_buffer_trigger_do_predisable(indio_dev); | |
| nxp_sar_adc_disable(info); | |
| nxp_sar_adc_channels_disable(info, *indio_dev->active_scan_mask); | |
| return 0; | |
| } | |
| static irqreturn_t nxp_sar_adc_trigger_handler(int irq, void *p) | |
| { | |
| struct iio_poll_func *pf = p; | |
| struct iio_dev *indio_dev = pf->indio_dev; | |
| struct nxp_sar_adc *info = iio_priv(indio_dev); | |
| int ret; | |
| ret = nxp_sar_adc_start_conversion(info, true); | |
| if (ret < 0) | |
| dev_dbg(&indio_dev->dev, "Failed to start conversion\n"); | |
| return IRQ_HANDLED; | |
| } | |
| static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { | |
| .postenable = nxp_sar_adc_buffer_postenable, | |
| .predisable = nxp_sar_adc_buffer_predisable, | |
| }; | |
| static const struct iio_info nxp_sar_adc_iio_info = { | |
| .read_raw = nxp_sar_adc_read_raw, | |
| .write_raw = nxp_sar_adc_write_raw, | |
| }; | |
| static int nxp_sar_adc_dma_probe(struct device *dev, struct nxp_sar_adc *info) | |
| { | |
| u8 *rx_buf; | |
| rx_buf = dmam_alloc_coherent(dev, NXP_SAR_ADC_DMA_BUFF_SZ, | |
| &info->rx_dma_buf, GFP_KERNEL); | |
| if (!rx_buf) | |
| return -ENOMEM; | |
| info->dma_buf.buf = rx_buf; | |
| return 0; | |
| } | |
| /* | |
| * The documentation describes the reset values for the registers. | |
| * However some registers do not have these values after a reset. It | |
| * is not a desirable situation. In some other SoC family | |
| * documentation NXP recommends not assuming the default values are | |
| * set and to initialize the registers conforming to the documentation | |
| * reset information to prevent this situation. Assume the same rule | |
| * applies here as there is a discrepancy between what is read from | |
| * the registers at reset time and the documentation. | |
| */ | |
| static void nxp_sar_adc_set_default_values(struct nxp_sar_adc *info) | |
| { | |
| writel(0x00003901, NXP_SAR_ADC_MCR(info->regs)); | |
| writel(0x00000001, NXP_SAR_ADC_MSR(info->regs)); | |
| writel(0x00000014, NXP_SAR_ADC_CTR0(info->regs)); | |
| writel(0x00000014, NXP_SAR_ADC_CTR1(info->regs)); | |
| writel(0x00000000, NXP_SAR_ADC_CIMR0(info->regs)); | |
| writel(0x00000000, NXP_SAR_ADC_CIMR1(info->regs)); | |
| writel(0x00000000, NXP_SAR_ADC_NCMR0(info->regs)); | |
| writel(0x00000000, NXP_SAR_ADC_NCMR1(info->regs)); | |
| } | |
| static int nxp_sar_adc_probe(struct platform_device *pdev) | |
| { | |
| struct device *dev = &pdev->dev; | |
| const struct nxp_sar_adc_data *data = device_get_match_data(dev); | |
| struct nxp_sar_adc *info; | |
| struct iio_dev *indio_dev; | |
| struct resource *mem; | |
| int irq, ret; | |
| indio_dev = devm_iio_device_alloc(dev, sizeof(*info)); | |
| if (!indio_dev) | |
| return -ENOMEM; | |
| info = iio_priv(indio_dev); | |
| info->vref_mV = data->vref_mV; | |
| spin_lock_init(&info->lock); | |
| info->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); | |
| if (IS_ERR(info->regs)) | |
| return dev_err_probe(dev, PTR_ERR(info->regs), | |
| "Failed to get and remap resource"); | |
| info->regs_phys = mem->start; | |
| irq = platform_get_irq(pdev, 0); | |
| if (irq < 0) | |
| return irq; | |
| ret = devm_request_irq(dev, irq, nxp_sar_adc_isr, 0, dev_name(dev), | |
| indio_dev); | |
| if (ret < 0) | |
| return ret; | |
| info->clk = devm_clk_get_enabled(dev, NULL); | |
| if (IS_ERR(info->clk)) | |
| return dev_err_probe(dev, PTR_ERR(info->clk), | |
| "Failed to get the clock\n"); | |
| platform_set_drvdata(pdev, indio_dev); | |
| init_completion(&info->completion); | |
| indio_dev->name = data->model; | |
| indio_dev->info = &nxp_sar_adc_iio_info; | |
| indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; | |
| indio_dev->channels = nxp_sar_adc_iio_channels; | |
| indio_dev->num_channels = ARRAY_SIZE(nxp_sar_adc_iio_channels); | |
| nxp_sar_adc_set_default_values(info); | |
| ret = nxp_sar_adc_calibration(info); | |
| if (ret) | |
| dev_err_probe(dev, ret, "Calibration failed\n"); | |
| ret = nxp_sar_adc_dma_probe(dev, info); | |
| if (ret) | |
| return dev_err_probe(dev, ret, "Failed to initialize the DMA\n"); | |
| ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | |
| &iio_pollfunc_store_time, | |
| &nxp_sar_adc_trigger_handler, | |
| &iio_triggered_buffer_setup_ops); | |
| if (ret < 0) | |
| return dev_err_probe(dev, ret, "Couldn't initialise the buffer\n"); | |
| ret = devm_iio_device_register(dev, indio_dev); | |
| if (ret) | |
| return dev_err_probe(dev, ret, "Couldn't register the device\n"); | |
| return 0; | |
| } | |
| static int nxp_sar_adc_suspend(struct device *dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(dev_get_drvdata(dev)); | |
| info->pwdn = nxp_sar_adc_disable(info); | |
| info->inpsamp = nxp_sar_adc_conversion_timing_get(info); | |
| clk_disable_unprepare(info->clk); | |
| return 0; | |
| } | |
| static int nxp_sar_adc_resume(struct device *dev) | |
| { | |
| struct nxp_sar_adc *info = iio_priv(dev_get_drvdata(dev)); | |
| int ret; | |
| ret = clk_prepare_enable(info->clk); | |
| if (ret) | |
| return ret; | |
| nxp_sar_adc_conversion_timing_set(info, info->inpsamp); | |
| if (!info->pwdn) | |
| nxp_sar_adc_enable(info); | |
| return 0; | |
| } | |
| static DEFINE_SIMPLE_DEV_PM_OPS(nxp_sar_adc_pm_ops, nxp_sar_adc_suspend, | |
| nxp_sar_adc_resume); | |
| static const struct nxp_sar_adc_data s32g2_sar_adc_data = { | |
| .vref_mV = 1800, | |
| .model = "s32g2-sar-adc", | |
| }; | |
| static const struct of_device_id nxp_sar_adc_match[] = { | |
| { .compatible = "nxp,s32g2-sar-adc", .data = &s32g2_sar_adc_data }, | |
| { } | |
| }; | |
| MODULE_DEVICE_TABLE(of, nxp_sar_adc_match); | |
| static struct platform_driver nxp_sar_adc_driver = { | |
| .probe = nxp_sar_adc_probe, | |
| .driver = { | |
| .name = "nxp-sar-adc", | |
| .of_match_table = nxp_sar_adc_match, | |
| .pm = pm_sleep_ptr(&nxp_sar_adc_pm_ops), | |
| }, | |
| }; | |
| module_platform_driver(nxp_sar_adc_driver); | |
| MODULE_AUTHOR("NXP"); | |
| MODULE_DESCRIPTION("NXP SAR-ADC driver"); | |
| MODULE_LICENSE("GPL"); |