1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Sophgo CV1800B SARADC Driver 4 * 5 * Copyright (C) Bootlin 2024 6 * Author: Thomas Bonnefille <thomas.bonnefille@bootlin.com> 7 */ 8 9 #include <linux/array_size.h> 10 #include <linux/bitfield.h> 11 #include <linux/bits.h> 12 #include <linux/cleanup.h> 13 #include <linux/clk.h> 14 #include <linux/completion.h> 15 #include <linux/err.h> 16 #include <linux/interrupt.h> 17 #include <linux/iopoll.h> 18 #include <linux/mod_devicetable.h> 19 #include <linux/module.h> 20 #include <linux/mutex.h> 21 #include <linux/platform_device.h> 22 #include <linux/types.h> 23 24 #include <linux/iio/iio.h> 25 26 #define CV1800B_ADC_CTRL_REG 0x04 27 #define CV1800B_ADC_EN BIT(0) 28 #define CV1800B_ADC_SEL(x) BIT((x) + 5) 29 #define CV1800B_ADC_STATUS_REG 0x08 30 #define CV1800B_ADC_BUSY BIT(0) 31 #define CV1800B_ADC_CYC_SET_REG 0x0C 32 #define CV1800B_MASK_STARTUP_CYCLE GENMASK(4, 0) 33 #define CV1800B_MASK_SAMPLE_WINDOW GENMASK(11, 8) 34 #define CV1800B_MASK_CLKDIV GENMASK(15, 12) 35 #define CV1800B_MASK_COMPARE_CYCLE GENMASK(19, 16) 36 #define CV1800B_ADC_CH_RESULT_REG(x) (0x14 + 4 * (x)) 37 #define CV1800B_ADC_CH_RESULT GENMASK(11, 0) 38 #define CV1800B_ADC_CH_VALID BIT(15) 39 #define CV1800B_ADC_INTR_EN_REG 0x20 40 #define CV1800B_ADC_INTR_CLR_REG 0x24 41 #define CV1800B_ADC_INTR_CLR_BIT BIT(0) 42 #define CV1800B_ADC_INTR_STA_REG 0x28 43 #define CV1800B_ADC_INTR_STA_BIT BIT(0) 44 #define CV1800B_READ_TIMEOUT_MS 1000 45 #define CV1800B_READ_TIMEOUT_US (CV1800B_READ_TIMEOUT_MS * 1000) 46 47 #define CV1800B_ADC_CHANNEL(index) \ 48 { \ 49 .type = IIO_VOLTAGE, \ 50 .indexed = 1, \ 51 .channel = index, \ 52 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 53 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 54 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ 55 .scan_index = index, \ 56 } 57 58 struct cv1800b_adc { 59 struct completion completion; 60 void __iomem *regs; 61 struct mutex lock; /* ADC Control and Result register */ 62 struct clk *clk; 63 int irq; 64 }; 65 66 static const struct iio_chan_spec sophgo_channels[] = { 67 CV1800B_ADC_CHANNEL(0), 68 CV1800B_ADC_CHANNEL(1), 69 CV1800B_ADC_CHANNEL(2), 70 }; 71 72 static void cv1800b_adc_start_measurement(struct cv1800b_adc *saradc, 73 int channel) 74 { 75 writel(0, saradc->regs + CV1800B_ADC_CTRL_REG); 76 writel(CV1800B_ADC_SEL(channel) | CV1800B_ADC_EN, 77 saradc->regs + CV1800B_ADC_CTRL_REG); 78 } 79 80 static int cv1800b_adc_wait(struct cv1800b_adc *saradc) 81 { 82 if (saradc->irq < 0) { 83 u32 reg; 84 85 return readl_poll_timeout(saradc->regs + CV1800B_ADC_STATUS_REG, 86 reg, !(reg & CV1800B_ADC_BUSY), 87 500, CV1800B_READ_TIMEOUT_US); 88 } 89 90 return wait_for_completion_timeout(&saradc->completion, 91 msecs_to_jiffies(CV1800B_READ_TIMEOUT_MS)) > 0 ? 92 0 : -ETIMEDOUT; 93 } 94 95 static int cv1800b_adc_read_raw(struct iio_dev *indio_dev, 96 struct iio_chan_spec const *chan, 97 int *val, int *val2, long mask) 98 { 99 struct cv1800b_adc *saradc = iio_priv(indio_dev); 100 101 switch (mask) { 102 case IIO_CHAN_INFO_RAW: { 103 u32 sample; 104 105 scoped_guard(mutex, &saradc->lock) { 106 int ret; 107 108 cv1800b_adc_start_measurement(saradc, chan->scan_index); 109 ret = cv1800b_adc_wait(saradc); 110 if (ret < 0) 111 return ret; 112 113 sample = readl(saradc->regs + CV1800B_ADC_CH_RESULT_REG(chan->scan_index)); 114 } 115 if (!(sample & CV1800B_ADC_CH_VALID)) 116 return -ENODATA; 117 118 *val = sample & CV1800B_ADC_CH_RESULT; 119 return IIO_VAL_INT; 120 } 121 case IIO_CHAN_INFO_SCALE: 122 *val = 3300; 123 *val2 = 12; 124 return IIO_VAL_FRACTIONAL_LOG2; 125 case IIO_CHAN_INFO_SAMP_FREQ: { 126 u32 status_reg = readl(saradc->regs + CV1800B_ADC_CYC_SET_REG); 127 unsigned int clk_div = (1 + FIELD_GET(CV1800B_MASK_CLKDIV, status_reg)); 128 unsigned int freq = clk_get_rate(saradc->clk) / clk_div; 129 unsigned int nb_startup_cycle = 1 + FIELD_GET(CV1800B_MASK_STARTUP_CYCLE, status_reg); 130 unsigned int nb_sample_cycle = 1 + FIELD_GET(CV1800B_MASK_SAMPLE_WINDOW, status_reg); 131 unsigned int nb_compare_cycle = 1 + FIELD_GET(CV1800B_MASK_COMPARE_CYCLE, status_reg); 132 133 *val = freq / (nb_startup_cycle + nb_sample_cycle + nb_compare_cycle); 134 return IIO_VAL_INT; 135 } 136 default: 137 return -EINVAL; 138 } 139 } 140 141 static irqreturn_t cv1800b_adc_interrupt_handler(int irq, void *private) 142 { 143 struct cv1800b_adc *saradc = private; 144 u32 reg = readl(saradc->regs + CV1800B_ADC_INTR_STA_REG); 145 146 if (!(FIELD_GET(CV1800B_ADC_INTR_STA_BIT, reg))) 147 return IRQ_NONE; 148 149 writel(CV1800B_ADC_INTR_CLR_BIT, saradc->regs + CV1800B_ADC_INTR_CLR_REG); 150 complete(&saradc->completion); 151 152 return IRQ_HANDLED; 153 } 154 155 static const struct iio_info cv1800b_adc_info = { 156 .read_raw = &cv1800b_adc_read_raw, 157 }; 158 159 static int cv1800b_adc_probe(struct platform_device *pdev) 160 { 161 struct device *dev = &pdev->dev; 162 struct cv1800b_adc *saradc; 163 struct iio_dev *indio_dev; 164 int ret; 165 166 indio_dev = devm_iio_device_alloc(dev, sizeof(*saradc)); 167 if (!indio_dev) 168 return -ENOMEM; 169 170 saradc = iio_priv(indio_dev); 171 indio_dev->name = "sophgo-cv1800b-adc"; 172 indio_dev->modes = INDIO_DIRECT_MODE; 173 indio_dev->info = &cv1800b_adc_info; 174 indio_dev->num_channels = ARRAY_SIZE(sophgo_channels); 175 indio_dev->channels = sophgo_channels; 176 177 saradc->clk = devm_clk_get_enabled(dev, NULL); 178 if (IS_ERR(saradc->clk)) 179 return PTR_ERR(saradc->clk); 180 181 saradc->regs = devm_platform_ioremap_resource(pdev, 0); 182 if (IS_ERR(saradc->regs)) 183 return PTR_ERR(saradc->regs); 184 185 saradc->irq = platform_get_irq_optional(pdev, 0); 186 if (saradc->irq > 0) { 187 init_completion(&saradc->completion); 188 ret = devm_request_irq(dev, saradc->irq, 189 cv1800b_adc_interrupt_handler, 0, 190 dev_name(dev), saradc); 191 if (ret) 192 return ret; 193 194 writel(1, saradc->regs + CV1800B_ADC_INTR_EN_REG); 195 } 196 197 ret = devm_mutex_init(dev, &saradc->lock); 198 if (ret) 199 return ret; 200 201 writel(FIELD_PREP(CV1800B_MASK_STARTUP_CYCLE, 15) | 202 FIELD_PREP(CV1800B_MASK_SAMPLE_WINDOW, 15) | 203 FIELD_PREP(CV1800B_MASK_CLKDIV, 1) | 204 FIELD_PREP(CV1800B_MASK_COMPARE_CYCLE, 15), 205 saradc->regs + CV1800B_ADC_CYC_SET_REG); 206 207 return devm_iio_device_register(dev, indio_dev); 208 } 209 210 static const struct of_device_id cv1800b_adc_match[] = { 211 { .compatible = "sophgo,cv1800b-saradc", }, 212 { } 213 }; 214 MODULE_DEVICE_TABLE(of, cv1800b_adc_match); 215 216 static struct platform_driver cv1800b_adc_driver = { 217 .driver = { 218 .name = "sophgo-cv1800b-saradc", 219 .of_match_table = cv1800b_adc_match, 220 }, 221 .probe = cv1800b_adc_probe, 222 }; 223 module_platform_driver(cv1800b_adc_driver); 224 225 MODULE_AUTHOR("Thomas Bonnefille <thomas.bonnefille@bootlin.com>"); 226 MODULE_DESCRIPTION("Sophgo CV1800B SARADC driver"); 227 MODULE_LICENSE("GPL"); 228