0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/completion.h>
0010 #include <linux/err.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/io.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mod_devicetable.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regulator/consumer.h>
0018
0019 #include <linux/iio/iio.h>
0020 #include <linux/iio/driver.h>
0021 #include <linux/iio/sysfs.h>
0022
0023
0024 #define IMX7D_REG_ADC_CH_A_CFG1 0x00
0025 #define IMX7D_REG_ADC_CH_A_CFG2 0x10
0026 #define IMX7D_REG_ADC_CH_B_CFG1 0x20
0027 #define IMX7D_REG_ADC_CH_B_CFG2 0x30
0028 #define IMX7D_REG_ADC_CH_C_CFG1 0x40
0029 #define IMX7D_REG_ADC_CH_C_CFG2 0x50
0030 #define IMX7D_REG_ADC_CH_D_CFG1 0x60
0031 #define IMX7D_REG_ADC_CH_D_CFG2 0x70
0032 #define IMX7D_REG_ADC_CH_SW_CFG 0x80
0033 #define IMX7D_REG_ADC_TIMER_UNIT 0x90
0034 #define IMX7D_REG_ADC_DMA_FIFO 0xa0
0035 #define IMX7D_REG_ADC_FIFO_STATUS 0xb0
0036 #define IMX7D_REG_ADC_INT_SIG_EN 0xc0
0037 #define IMX7D_REG_ADC_INT_EN 0xd0
0038 #define IMX7D_REG_ADC_INT_STATUS 0xe0
0039 #define IMX7D_REG_ADC_CHA_B_CNV_RSLT 0xf0
0040 #define IMX7D_REG_ADC_CHC_D_CNV_RSLT 0x100
0041 #define IMX7D_REG_ADC_CH_SW_CNV_RSLT 0x110
0042 #define IMX7D_REG_ADC_DMA_FIFO_DAT 0x120
0043 #define IMX7D_REG_ADC_ADC_CFG 0x130
0044
0045 #define IMX7D_REG_ADC_CHANNEL_CFG2_BASE 0x10
0046 #define IMX7D_EACH_CHANNEL_REG_OFFSET 0x20
0047
0048 #define IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN (0x1 << 31)
0049 #define IMX7D_REG_ADC_CH_CFG1_CHANNEL_SINGLE BIT(30)
0050 #define IMX7D_REG_ADC_CH_CFG1_CHANNEL_AVG_EN BIT(29)
0051 #define IMX7D_REG_ADC_CH_CFG1_CHANNEL_SEL(x) ((x) << 24)
0052
0053 #define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_4 (0x0 << 12)
0054 #define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_8 (0x1 << 12)
0055 #define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_16 (0x2 << 12)
0056 #define IMX7D_REG_ADC_CH_CFG2_AVG_NUM_32 (0x3 << 12)
0057
0058 #define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_4 (0x0 << 29)
0059 #define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_8 (0x1 << 29)
0060 #define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_16 (0x2 << 29)
0061 #define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_32 (0x3 << 29)
0062 #define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_64 (0x4 << 29)
0063 #define IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_128 (0x5 << 29)
0064
0065 #define IMX7D_REG_ADC_ADC_CFG_ADC_CLK_DOWN BIT(31)
0066 #define IMX7D_REG_ADC_ADC_CFG_ADC_POWER_DOWN BIT(1)
0067 #define IMX7D_REG_ADC_ADC_CFG_ADC_EN BIT(0)
0068
0069 #define IMX7D_REG_ADC_INT_CHA_COV_INT_EN BIT(8)
0070 #define IMX7D_REG_ADC_INT_CHB_COV_INT_EN BIT(9)
0071 #define IMX7D_REG_ADC_INT_CHC_COV_INT_EN BIT(10)
0072 #define IMX7D_REG_ADC_INT_CHD_COV_INT_EN BIT(11)
0073 #define IMX7D_REG_ADC_INT_CHANNEL_INT_EN \
0074 (IMX7D_REG_ADC_INT_CHA_COV_INT_EN | \
0075 IMX7D_REG_ADC_INT_CHB_COV_INT_EN | \
0076 IMX7D_REG_ADC_INT_CHC_COV_INT_EN | \
0077 IMX7D_REG_ADC_INT_CHD_COV_INT_EN)
0078 #define IMX7D_REG_ADC_INT_STATUS_CHANNEL_INT_STATUS 0xf00
0079 #define IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT 0xf0000
0080
0081 #define IMX7D_ADC_TIMEOUT msecs_to_jiffies(100)
0082 #define IMX7D_ADC_INPUT_CLK 24000000
0083
0084 enum imx7d_adc_clk_pre_div {
0085 IMX7D_ADC_ANALOG_CLK_PRE_DIV_4,
0086 IMX7D_ADC_ANALOG_CLK_PRE_DIV_8,
0087 IMX7D_ADC_ANALOG_CLK_PRE_DIV_16,
0088 IMX7D_ADC_ANALOG_CLK_PRE_DIV_32,
0089 IMX7D_ADC_ANALOG_CLK_PRE_DIV_64,
0090 IMX7D_ADC_ANALOG_CLK_PRE_DIV_128,
0091 };
0092
0093 enum imx7d_adc_average_num {
0094 IMX7D_ADC_AVERAGE_NUM_4,
0095 IMX7D_ADC_AVERAGE_NUM_8,
0096 IMX7D_ADC_AVERAGE_NUM_16,
0097 IMX7D_ADC_AVERAGE_NUM_32,
0098 };
0099
0100 struct imx7d_adc_feature {
0101 enum imx7d_adc_clk_pre_div clk_pre_div;
0102 enum imx7d_adc_average_num avg_num;
0103
0104 u32 core_time_unit;
0105 };
0106
0107 struct imx7d_adc {
0108 struct device *dev;
0109 void __iomem *regs;
0110 struct clk *clk;
0111
0112 u32 vref_uv;
0113 u32 value;
0114 u32 channel;
0115 u32 pre_div_num;
0116
0117 struct regulator *vref;
0118 struct imx7d_adc_feature adc_feature;
0119
0120 struct completion completion;
0121 };
0122
0123 struct imx7d_adc_analogue_core_clk {
0124 u32 pre_div;
0125 u32 reg_config;
0126 };
0127
0128 #define IMX7D_ADC_ANALOGUE_CLK_CONFIG(_pre_div, _reg_conf) { \
0129 .pre_div = (_pre_div), \
0130 .reg_config = (_reg_conf), \
0131 }
0132
0133 static const struct imx7d_adc_analogue_core_clk imx7d_adc_analogue_clk[] = {
0134 IMX7D_ADC_ANALOGUE_CLK_CONFIG(4, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_4),
0135 IMX7D_ADC_ANALOGUE_CLK_CONFIG(8, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_8),
0136 IMX7D_ADC_ANALOGUE_CLK_CONFIG(16, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_16),
0137 IMX7D_ADC_ANALOGUE_CLK_CONFIG(32, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_32),
0138 IMX7D_ADC_ANALOGUE_CLK_CONFIG(64, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_64),
0139 IMX7D_ADC_ANALOGUE_CLK_CONFIG(128, IMX7D_REG_ADC_TIMER_UNIT_PRE_DIV_128),
0140 };
0141
0142 #define IMX7D_ADC_CHAN(_idx) { \
0143 .type = IIO_VOLTAGE, \
0144 .indexed = 1, \
0145 .channel = (_idx), \
0146 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0147 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
0148 BIT(IIO_CHAN_INFO_SAMP_FREQ), \
0149 }
0150
0151 static const struct iio_chan_spec imx7d_adc_iio_channels[] = {
0152 IMX7D_ADC_CHAN(0),
0153 IMX7D_ADC_CHAN(1),
0154 IMX7D_ADC_CHAN(2),
0155 IMX7D_ADC_CHAN(3),
0156 IMX7D_ADC_CHAN(4),
0157 IMX7D_ADC_CHAN(5),
0158 IMX7D_ADC_CHAN(6),
0159 IMX7D_ADC_CHAN(7),
0160 IMX7D_ADC_CHAN(8),
0161 IMX7D_ADC_CHAN(9),
0162 IMX7D_ADC_CHAN(10),
0163 IMX7D_ADC_CHAN(11),
0164 IMX7D_ADC_CHAN(12),
0165 IMX7D_ADC_CHAN(13),
0166 IMX7D_ADC_CHAN(14),
0167 IMX7D_ADC_CHAN(15),
0168 };
0169
0170 static const u32 imx7d_adc_average_num[] = {
0171 IMX7D_REG_ADC_CH_CFG2_AVG_NUM_4,
0172 IMX7D_REG_ADC_CH_CFG2_AVG_NUM_8,
0173 IMX7D_REG_ADC_CH_CFG2_AVG_NUM_16,
0174 IMX7D_REG_ADC_CH_CFG2_AVG_NUM_32,
0175 };
0176
0177 static void imx7d_adc_feature_config(struct imx7d_adc *info)
0178 {
0179 info->adc_feature.clk_pre_div = IMX7D_ADC_ANALOG_CLK_PRE_DIV_4;
0180 info->adc_feature.avg_num = IMX7D_ADC_AVERAGE_NUM_32;
0181 info->adc_feature.core_time_unit = 1;
0182 }
0183
0184 static void imx7d_adc_sample_rate_set(struct imx7d_adc *info)
0185 {
0186 struct imx7d_adc_feature *adc_feature = &info->adc_feature;
0187 struct imx7d_adc_analogue_core_clk adc_analogure_clk;
0188 u32 i;
0189 u32 tmp_cfg1;
0190 u32 sample_rate = 0;
0191
0192
0193
0194
0195
0196 for (i = 0; i < 4; i++) {
0197 tmp_cfg1 =
0198 readl(info->regs + i * IMX7D_EACH_CHANNEL_REG_OFFSET);
0199 tmp_cfg1 &= ~IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN;
0200 writel(tmp_cfg1,
0201 info->regs + i * IMX7D_EACH_CHANNEL_REG_OFFSET);
0202 }
0203
0204 adc_analogure_clk = imx7d_adc_analogue_clk[adc_feature->clk_pre_div];
0205 sample_rate |= adc_analogure_clk.reg_config;
0206 info->pre_div_num = adc_analogure_clk.pre_div;
0207
0208 sample_rate |= adc_feature->core_time_unit;
0209 writel(sample_rate, info->regs + IMX7D_REG_ADC_TIMER_UNIT);
0210 }
0211
0212 static void imx7d_adc_hw_init(struct imx7d_adc *info)
0213 {
0214 u32 cfg;
0215
0216
0217 cfg = readl(info->regs + IMX7D_REG_ADC_ADC_CFG);
0218 cfg &= ~(IMX7D_REG_ADC_ADC_CFG_ADC_CLK_DOWN |
0219 IMX7D_REG_ADC_ADC_CFG_ADC_POWER_DOWN);
0220 cfg |= IMX7D_REG_ADC_ADC_CFG_ADC_EN;
0221 writel(cfg, info->regs + IMX7D_REG_ADC_ADC_CFG);
0222
0223
0224 writel(IMX7D_REG_ADC_INT_CHANNEL_INT_EN,
0225 info->regs + IMX7D_REG_ADC_INT_SIG_EN);
0226 writel(IMX7D_REG_ADC_INT_CHANNEL_INT_EN,
0227 info->regs + IMX7D_REG_ADC_INT_EN);
0228
0229 imx7d_adc_sample_rate_set(info);
0230 }
0231
0232 static void imx7d_adc_channel_set(struct imx7d_adc *info)
0233 {
0234 u32 cfg1 = 0;
0235 u32 cfg2;
0236 u32 channel;
0237
0238 channel = info->channel;
0239
0240
0241 cfg1 |= (IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN |
0242 IMX7D_REG_ADC_CH_CFG1_CHANNEL_SINGLE |
0243 IMX7D_REG_ADC_CH_CFG1_CHANNEL_AVG_EN);
0244
0245
0246
0247
0248
0249
0250
0251 cfg1 |= IMX7D_REG_ADC_CH_CFG1_CHANNEL_SEL(channel);
0252
0253
0254
0255
0256
0257 cfg2 = readl(info->regs + IMX7D_EACH_CHANNEL_REG_OFFSET * channel +
0258 IMX7D_REG_ADC_CHANNEL_CFG2_BASE);
0259
0260 cfg2 |= imx7d_adc_average_num[info->adc_feature.avg_num];
0261
0262
0263
0264
0265
0266 writel(cfg2, info->regs + IMX7D_EACH_CHANNEL_REG_OFFSET * channel +
0267 IMX7D_REG_ADC_CHANNEL_CFG2_BASE);
0268 writel(cfg1, info->regs + IMX7D_EACH_CHANNEL_REG_OFFSET * channel);
0269 }
0270
0271 static u32 imx7d_adc_get_sample_rate(struct imx7d_adc *info)
0272 {
0273 u32 analogue_core_clk;
0274 u32 core_time_unit = info->adc_feature.core_time_unit;
0275 u32 tmp;
0276
0277 analogue_core_clk = IMX7D_ADC_INPUT_CLK / info->pre_div_num;
0278 tmp = (core_time_unit + 1) * 6;
0279
0280 return analogue_core_clk / tmp;
0281 }
0282
0283 static int imx7d_adc_read_raw(struct iio_dev *indio_dev,
0284 struct iio_chan_spec const *chan,
0285 int *val,
0286 int *val2,
0287 long mask)
0288 {
0289 struct imx7d_adc *info = iio_priv(indio_dev);
0290
0291 u32 channel;
0292 long ret;
0293
0294 switch (mask) {
0295 case IIO_CHAN_INFO_RAW:
0296 mutex_lock(&indio_dev->mlock);
0297 reinit_completion(&info->completion);
0298
0299 channel = chan->channel & 0x03;
0300 info->channel = channel;
0301 imx7d_adc_channel_set(info);
0302
0303 ret = wait_for_completion_interruptible_timeout
0304 (&info->completion, IMX7D_ADC_TIMEOUT);
0305 if (ret == 0) {
0306 mutex_unlock(&indio_dev->mlock);
0307 return -ETIMEDOUT;
0308 }
0309 if (ret < 0) {
0310 mutex_unlock(&indio_dev->mlock);
0311 return ret;
0312 }
0313
0314 *val = info->value;
0315 mutex_unlock(&indio_dev->mlock);
0316 return IIO_VAL_INT;
0317
0318 case IIO_CHAN_INFO_SCALE:
0319 info->vref_uv = regulator_get_voltage(info->vref);
0320 *val = info->vref_uv / 1000;
0321 *val2 = 12;
0322 return IIO_VAL_FRACTIONAL_LOG2;
0323
0324 case IIO_CHAN_INFO_SAMP_FREQ:
0325 *val = imx7d_adc_get_sample_rate(info);
0326 return IIO_VAL_INT;
0327
0328 default:
0329 return -EINVAL;
0330 }
0331 }
0332
0333 static int imx7d_adc_read_data(struct imx7d_adc *info)
0334 {
0335 u32 channel;
0336 u32 value;
0337
0338 channel = info->channel & 0x03;
0339
0340
0341
0342
0343
0344
0345
0346 if (channel < 2)
0347 value = readl(info->regs + IMX7D_REG_ADC_CHA_B_CNV_RSLT);
0348 else
0349 value = readl(info->regs + IMX7D_REG_ADC_CHC_D_CNV_RSLT);
0350 if (channel & 0x1)
0351 value = (value >> 16) & 0xFFF;
0352 else
0353 value &= 0xFFF;
0354
0355 return value;
0356 }
0357
0358 static irqreturn_t imx7d_adc_isr(int irq, void *dev_id)
0359 {
0360 struct imx7d_adc *info = dev_id;
0361 int status;
0362
0363 status = readl(info->regs + IMX7D_REG_ADC_INT_STATUS);
0364 if (status & IMX7D_REG_ADC_INT_STATUS_CHANNEL_INT_STATUS) {
0365 info->value = imx7d_adc_read_data(info);
0366 complete(&info->completion);
0367
0368
0369
0370
0371
0372
0373
0374 status &= ~IMX7D_REG_ADC_INT_STATUS_CHANNEL_INT_STATUS;
0375 writel(status, info->regs + IMX7D_REG_ADC_INT_STATUS);
0376 }
0377
0378
0379
0380
0381
0382 if (status & IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT) {
0383 dev_err(info->dev,
0384 "ADC got conversion time out interrupt: 0x%08x\n",
0385 status);
0386 status &= ~IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT;
0387 writel(status, info->regs + IMX7D_REG_ADC_INT_STATUS);
0388 }
0389
0390 return IRQ_HANDLED;
0391 }
0392
0393 static int imx7d_adc_reg_access(struct iio_dev *indio_dev,
0394 unsigned reg, unsigned writeval,
0395 unsigned *readval)
0396 {
0397 struct imx7d_adc *info = iio_priv(indio_dev);
0398
0399 if (!readval || reg % 4 || reg > IMX7D_REG_ADC_ADC_CFG)
0400 return -EINVAL;
0401
0402 *readval = readl(info->regs + reg);
0403
0404 return 0;
0405 }
0406
0407 static const struct iio_info imx7d_adc_iio_info = {
0408 .read_raw = &imx7d_adc_read_raw,
0409 .debugfs_reg_access = &imx7d_adc_reg_access,
0410 };
0411
0412 static const struct of_device_id imx7d_adc_match[] = {
0413 { .compatible = "fsl,imx7d-adc", },
0414 { }
0415 };
0416 MODULE_DEVICE_TABLE(of, imx7d_adc_match);
0417
0418 static void imx7d_adc_power_down(struct imx7d_adc *info)
0419 {
0420 u32 adc_cfg;
0421
0422 adc_cfg = readl(info->regs + IMX7D_REG_ADC_ADC_CFG);
0423 adc_cfg |= IMX7D_REG_ADC_ADC_CFG_ADC_CLK_DOWN |
0424 IMX7D_REG_ADC_ADC_CFG_ADC_POWER_DOWN;
0425 adc_cfg &= ~IMX7D_REG_ADC_ADC_CFG_ADC_EN;
0426 writel(adc_cfg, info->regs + IMX7D_REG_ADC_ADC_CFG);
0427 }
0428
0429 static int imx7d_adc_enable(struct device *dev)
0430 {
0431 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0432 struct imx7d_adc *info = iio_priv(indio_dev);
0433 int ret;
0434
0435 ret = regulator_enable(info->vref);
0436 if (ret) {
0437 dev_err(info->dev,
0438 "Can't enable adc reference top voltage, err = %d\n",
0439 ret);
0440 return ret;
0441 }
0442
0443 ret = clk_prepare_enable(info->clk);
0444 if (ret) {
0445 dev_err(info->dev,
0446 "Could not prepare or enable clock.\n");
0447 regulator_disable(info->vref);
0448 return ret;
0449 }
0450
0451 imx7d_adc_hw_init(info);
0452
0453 return 0;
0454 }
0455
0456 static int imx7d_adc_disable(struct device *dev)
0457 {
0458 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0459 struct imx7d_adc *info = iio_priv(indio_dev);
0460
0461 imx7d_adc_power_down(info);
0462
0463 clk_disable_unprepare(info->clk);
0464 regulator_disable(info->vref);
0465
0466 return 0;
0467 }
0468
0469 static void __imx7d_adc_disable(void *data)
0470 {
0471 imx7d_adc_disable(data);
0472 }
0473
0474 static int imx7d_adc_probe(struct platform_device *pdev)
0475 {
0476 struct imx7d_adc *info;
0477 struct iio_dev *indio_dev;
0478 struct device *dev = &pdev->dev;
0479 int irq;
0480 int ret;
0481
0482 indio_dev = devm_iio_device_alloc(dev, sizeof(*info));
0483 if (!indio_dev) {
0484 dev_err(&pdev->dev, "Failed allocating iio device\n");
0485 return -ENOMEM;
0486 }
0487
0488 info = iio_priv(indio_dev);
0489 info->dev = dev;
0490
0491 info->regs = devm_platform_ioremap_resource(pdev, 0);
0492 if (IS_ERR(info->regs))
0493 return PTR_ERR(info->regs);
0494
0495 irq = platform_get_irq(pdev, 0);
0496 if (irq < 0)
0497 return dev_err_probe(dev, irq, "Failed getting irq\n");
0498
0499 info->clk = devm_clk_get(dev, "adc");
0500 if (IS_ERR(info->clk))
0501 return dev_err_probe(dev, PTR_ERR(info->clk), "Failed getting clock\n");
0502
0503 info->vref = devm_regulator_get(dev, "vref");
0504 if (IS_ERR(info->vref))
0505 return dev_err_probe(dev, PTR_ERR(info->vref),
0506 "Failed getting reference voltage\n");
0507
0508 platform_set_drvdata(pdev, indio_dev);
0509
0510 init_completion(&info->completion);
0511
0512 indio_dev->name = dev_name(dev);
0513 indio_dev->info = &imx7d_adc_iio_info;
0514 indio_dev->modes = INDIO_DIRECT_MODE;
0515 indio_dev->channels = imx7d_adc_iio_channels;
0516 indio_dev->num_channels = ARRAY_SIZE(imx7d_adc_iio_channels);
0517
0518 ret = devm_request_irq(dev, irq, imx7d_adc_isr, 0, dev_name(dev), info);
0519 if (ret < 0) {
0520 dev_err(dev, "Failed requesting irq, irq = %d\n", irq);
0521 return ret;
0522 }
0523
0524 imx7d_adc_feature_config(info);
0525
0526 ret = imx7d_adc_enable(dev);
0527 if (ret)
0528 return ret;
0529
0530 ret = devm_add_action_or_reset(dev, __imx7d_adc_disable, dev);
0531 if (ret)
0532 return ret;
0533
0534 ret = devm_iio_device_register(dev, indio_dev);
0535 if (ret) {
0536 dev_err(&pdev->dev, "Couldn't register the device.\n");
0537 return ret;
0538 }
0539
0540 return 0;
0541 }
0542
0543 static DEFINE_SIMPLE_DEV_PM_OPS(imx7d_adc_pm_ops, imx7d_adc_disable,
0544 imx7d_adc_enable);
0545
0546 static struct platform_driver imx7d_adc_driver = {
0547 .probe = imx7d_adc_probe,
0548 .driver = {
0549 .name = "imx7d_adc",
0550 .of_match_table = imx7d_adc_match,
0551 .pm = pm_sleep_ptr(&imx7d_adc_pm_ops),
0552 },
0553 };
0554
0555 module_platform_driver(imx7d_adc_driver);
0556
0557 MODULE_AUTHOR("Haibo Chen <haibo.chen@freescale.com>");
0558 MODULE_DESCRIPTION("Freescale IMX7D ADC driver");
0559 MODULE_LICENSE("GPL v2");