From fd00c9eece2f45c4692bfb875a2154ff6ec1ffa1 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Mon, 7 Apr 2025 15:56:13 +0800 Subject: [PATCH] iio: adc: rockchip_saradc: add support dma mode Change-Id: I0bac2454c71948d9f753472fb72c3117efa8a16d Signed-off-by: Simon Xue --- drivers/iio/adc/rockchip_saradc.c | 98 ++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 340ba2f7b8f5..c90aeddd5e9f 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -21,6 +21,7 @@ #include #include #include +#include #define SARADC_DATA 0x00 @@ -43,6 +44,7 @@ #define SARADC2_CONV_CON 0x0 #define SARADC_T_PD_SOC 0x4 #define SARADC_T_DAS_SOC 0xc +#define SARADC_T_SEL_SOC 0x10 #define SARADC2_END_INT_EN 0x104 #define SARADC2_ST_CON 0x108 #define SARADC2_STATUS 0x10c @@ -55,6 +57,19 @@ #define SARADC2_CONV_CHANNELS GENMASK(3, 0) +#define SARADC3_AUTO_CH_EN 0x160 +#define SARADC3_FIFO_CON 0x18c +#define SARADC3_PADDR_BASE_H 0x190 +#define SARADC3_PADDR_BASE_L 0x194 +#define SARADC3_PADDR_OFF_MAX 0x198 +#define SARADC3_PADDR_OFF_WK 0x200 + +#define SARADC3_EN_END_MAX_INT BIT(3) +#define SARADC3_AUTO_MODE BIT(6) + +#define SARADC3_PMASTER_EN BIT(3) +#define SARADC3_PADDR_MAX_INT_ST BIT(3) + struct rockchip_saradc; struct rockchip_saradc_data { @@ -82,6 +97,9 @@ struct rockchip_saradc { const struct iio_chan_spec *last_chan; struct notifier_block nb; bool suspended; + bool dma_mode; + void *dma_base; + dma_addr_t dma_phys; #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN bool test; u32 test_chn; @@ -91,6 +109,8 @@ struct rockchip_saradc { #endif }; +#define SARADC3_DMA_SIZE SZ_4K + static void rockchip_saradc_reset_controller(struct reset_control *reset); static void rockchip_saradc_start_v1(struct rockchip_saradc *info, @@ -131,6 +151,53 @@ static void rockchip_saradc_start_v2(struct rockchip_saradc *info, writel(val, info->regs + SARADC2_CONV_CON); } +static void rockchip_saradc_start_v3_dma(struct rockchip_saradc *info, + int chn) +{ + int val; + + if (info->reset) + rockchip_saradc_reset_controller(info->reset); + + writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC); + writel_relaxed(0x11, info->regs + SARADC_T_DAS_SOC); + writel_relaxed(0x0, info->regs + SARADC_T_SEL_SOC); + + val = FIELD_PREP(SARADC3_PMASTER_EN, 1); + val |= SARADC3_PMASTER_EN << 16; + writel_relaxed(val, info->regs + SARADC3_FIFO_CON); + + writel_relaxed((u64)info->dma_phys >> 32, + info->regs + SARADC3_PADDR_BASE_H); + writel_relaxed(((u32)info->dma_phys) >> 2, + info->regs + SARADC3_PADDR_BASE_L); + writel_relaxed((SARADC3_DMA_SIZE >> 2) - 1, + info->regs + SARADC3_PADDR_OFF_MAX); + + val = FIELD_PREP(SARADC3_EN_END_MAX_INT, 1); + val |= SARADC3_EN_END_MAX_INT << 16; + writel_relaxed(val, info->regs + SARADC2_END_INT_EN); + + val = BIT(chn) << 16 | BIT(chn); + writel_relaxed(val, info->regs + SARADC3_AUTO_CH_EN); + + val = FIELD_PREP(SARADC2_START, 1) | + FIELD_PREP(SARADC3_AUTO_MODE, 1) | + FIELD_PREP(SARADC2_CONV_CHANNELS, chn); + val |= (SARADC2_START | SARADC3_AUTO_MODE | SARADC2_CONV_CHANNELS) << 16; + writel(val, info->regs + SARADC2_CONV_CON); +} + +/* V3 is compatible with V2 */ +static void rockchip_saradc_start_v3(struct rockchip_saradc *info, + int chn) +{ + if (info->dma_mode) + rockchip_saradc_start_v3_dma(info, chn); + else + rockchip_saradc_start_v2(info, chn); +} + static void rockchip_saradc_start(struct rockchip_saradc *info, int chn) { @@ -164,6 +231,22 @@ static int rockchip_saradc_read_v2(struct rockchip_saradc *info) return readl_relaxed(info->regs + offset); } +static int rockchip_saradc_read_v3(struct rockchip_saradc *info) +{ + int val; + + /* Clear max int and disable dma write function */ + if (info->dma_mode) { + writel_relaxed(SARADC3_PADDR_MAX_INT_ST, + info->regs + SARADC2_END_INT_ST); + val = FIELD_PREP(SARADC3_PMASTER_EN, 0); + val |= SARADC3_PMASTER_EN << 16; + writel_relaxed(val, info->regs + SARADC3_FIFO_CON); + } + + return rockchip_saradc_read_v2(info); +} + static int rockchip_saradc_read(struct rockchip_saradc *info) { return info->data->read(info); @@ -439,8 +522,8 @@ static const struct rockchip_saradc_data rv1126b_saradc_data = { .channels = rockchip_rv1126b_saradc_iio_channels, .num_channels = ARRAY_SIZE(rockchip_rv1126b_saradc_iio_channels), .clk_rate = 24000000, - .start = rockchip_saradc_start_v2, - .read = rockchip_saradc_read_v2, + .start = rockchip_saradc_start_v3, + .read = rockchip_saradc_read_v3, .das_soc_data = 0x14, }; @@ -819,6 +902,17 @@ static int rockchip_saradc_probe(struct platform_device *pdev) #endif mutex_init(&info->lock); + info->dma_mode = device_property_read_bool(&pdev->dev, "rockchip,dma"); + if (info->dma_mode) { + dma_set_mask_and_coherent(&pdev->dev, 40); + info->dma_base = dmam_alloc_coherent(&pdev->dev, SARADC3_DMA_SIZE, + &info->dma_phys, GFP_KERNEL); + if (!info->dma_base) { + dev_err(&pdev->dev, "failed to alloc memory for dma\n"); + return -ENOMEM; + } + } + irq = platform_get_irq(pdev, 0); if (irq < 0) return dev_err_probe(&pdev->dev, irq, "failed to get irq\n");