1*a583c24dSJoachim Eastwood /* 2*a583c24dSJoachim Eastwood * IIO ADC driver for NXP LPC18xx ADC 3*a583c24dSJoachim Eastwood * 4*a583c24dSJoachim Eastwood * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com> 5*a583c24dSJoachim Eastwood * 6*a583c24dSJoachim Eastwood * This program is free software; you can redistribute it and/or modify 7*a583c24dSJoachim Eastwood * it under the terms of the GNU General Public License version 2 as 8*a583c24dSJoachim Eastwood * published by the Free Software Foundation. 9*a583c24dSJoachim Eastwood * 10*a583c24dSJoachim Eastwood * UNSUPPORTED hardware features: 11*a583c24dSJoachim Eastwood * - Hardware triggers 12*a583c24dSJoachim Eastwood * - Burst mode 13*a583c24dSJoachim Eastwood * - Interrupts 14*a583c24dSJoachim Eastwood * - DMA 15*a583c24dSJoachim Eastwood */ 16*a583c24dSJoachim Eastwood 17*a583c24dSJoachim Eastwood #include <linux/clk.h> 18*a583c24dSJoachim Eastwood #include <linux/err.h> 19*a583c24dSJoachim Eastwood #include <linux/iio/iio.h> 20*a583c24dSJoachim Eastwood #include <linux/iio/driver.h> 21*a583c24dSJoachim Eastwood #include <linux/io.h> 22*a583c24dSJoachim Eastwood #include <linux/iopoll.h> 23*a583c24dSJoachim Eastwood #include <linux/module.h> 24*a583c24dSJoachim Eastwood #include <linux/mutex.h> 25*a583c24dSJoachim Eastwood #include <linux/of.h> 26*a583c24dSJoachim Eastwood #include <linux/of_device.h> 27*a583c24dSJoachim Eastwood #include <linux/platform_device.h> 28*a583c24dSJoachim Eastwood #include <linux/regulator/consumer.h> 29*a583c24dSJoachim Eastwood 30*a583c24dSJoachim Eastwood /* LPC18XX ADC registers and bits */ 31*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CR 0x000 32*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CR_CLKDIV_SHIFT 8 33*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CR_PDN BIT(21) 34*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CR_START_NOW (0x1 << 24) 35*a583c24dSJoachim Eastwood #define LPC18XX_ADC_GDR 0x004 36*a583c24dSJoachim Eastwood 37*a583c24dSJoachim Eastwood /* Data register bits */ 38*a583c24dSJoachim Eastwood #define LPC18XX_ADC_SAMPLE_SHIFT 6 39*a583c24dSJoachim Eastwood #define LPC18XX_ADC_SAMPLE_MASK 0x3ff 40*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CONV_DONE BIT(31) 41*a583c24dSJoachim Eastwood 42*a583c24dSJoachim Eastwood /* Clock should be 4.5 MHz or less */ 43*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CLK_TARGET 4500000 44*a583c24dSJoachim Eastwood 45*a583c24dSJoachim Eastwood struct lpc18xx_adc { 46*a583c24dSJoachim Eastwood struct regulator *vref; 47*a583c24dSJoachim Eastwood void __iomem *base; 48*a583c24dSJoachim Eastwood struct device *dev; 49*a583c24dSJoachim Eastwood struct mutex lock; 50*a583c24dSJoachim Eastwood struct clk *clk; 51*a583c24dSJoachim Eastwood u32 cr_reg; 52*a583c24dSJoachim Eastwood }; 53*a583c24dSJoachim Eastwood 54*a583c24dSJoachim Eastwood #define LPC18XX_ADC_CHAN(_idx) { \ 55*a583c24dSJoachim Eastwood .type = IIO_VOLTAGE, \ 56*a583c24dSJoachim Eastwood .indexed = 1, \ 57*a583c24dSJoachim Eastwood .channel = _idx, \ 58*a583c24dSJoachim Eastwood .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 59*a583c24dSJoachim Eastwood .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 60*a583c24dSJoachim Eastwood } 61*a583c24dSJoachim Eastwood 62*a583c24dSJoachim Eastwood static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = { 63*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(0), 64*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(1), 65*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(2), 66*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(3), 67*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(4), 68*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(5), 69*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(6), 70*a583c24dSJoachim Eastwood LPC18XX_ADC_CHAN(7), 71*a583c24dSJoachim Eastwood }; 72*a583c24dSJoachim Eastwood 73*a583c24dSJoachim Eastwood static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch) 74*a583c24dSJoachim Eastwood { 75*a583c24dSJoachim Eastwood int ret; 76*a583c24dSJoachim Eastwood u32 reg; 77*a583c24dSJoachim Eastwood 78*a583c24dSJoachim Eastwood reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW; 79*a583c24dSJoachim Eastwood writel(reg, adc->base + LPC18XX_ADC_CR); 80*a583c24dSJoachim Eastwood 81*a583c24dSJoachim Eastwood ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg, 82*a583c24dSJoachim Eastwood reg & LPC18XX_ADC_CONV_DONE, 3, 9); 83*a583c24dSJoachim Eastwood if (ret) { 84*a583c24dSJoachim Eastwood dev_warn(adc->dev, "adc read timed out\n"); 85*a583c24dSJoachim Eastwood return ret; 86*a583c24dSJoachim Eastwood } 87*a583c24dSJoachim Eastwood 88*a583c24dSJoachim Eastwood return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK; 89*a583c24dSJoachim Eastwood } 90*a583c24dSJoachim Eastwood 91*a583c24dSJoachim Eastwood static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev, 92*a583c24dSJoachim Eastwood struct iio_chan_spec const *chan, 93*a583c24dSJoachim Eastwood int *val, int *val2, long mask) 94*a583c24dSJoachim Eastwood { 95*a583c24dSJoachim Eastwood struct lpc18xx_adc *adc = iio_priv(indio_dev); 96*a583c24dSJoachim Eastwood 97*a583c24dSJoachim Eastwood switch (mask) { 98*a583c24dSJoachim Eastwood case IIO_CHAN_INFO_RAW: 99*a583c24dSJoachim Eastwood mutex_lock(&adc->lock); 100*a583c24dSJoachim Eastwood *val = lpc18xx_adc_read_chan(adc, chan->channel); 101*a583c24dSJoachim Eastwood mutex_unlock(&adc->lock); 102*a583c24dSJoachim Eastwood if (*val < 0) 103*a583c24dSJoachim Eastwood return *val; 104*a583c24dSJoachim Eastwood 105*a583c24dSJoachim Eastwood return IIO_VAL_INT; 106*a583c24dSJoachim Eastwood 107*a583c24dSJoachim Eastwood case IIO_CHAN_INFO_SCALE: 108*a583c24dSJoachim Eastwood *val = regulator_get_voltage(adc->vref) / 1000; 109*a583c24dSJoachim Eastwood *val2 = 10; 110*a583c24dSJoachim Eastwood 111*a583c24dSJoachim Eastwood return IIO_VAL_FRACTIONAL_LOG2; 112*a583c24dSJoachim Eastwood } 113*a583c24dSJoachim Eastwood 114*a583c24dSJoachim Eastwood return -EINVAL; 115*a583c24dSJoachim Eastwood } 116*a583c24dSJoachim Eastwood 117*a583c24dSJoachim Eastwood static const struct iio_info lpc18xx_adc_info = { 118*a583c24dSJoachim Eastwood .read_raw = lpc18xx_adc_read_raw, 119*a583c24dSJoachim Eastwood .driver_module = THIS_MODULE, 120*a583c24dSJoachim Eastwood }; 121*a583c24dSJoachim Eastwood 122*a583c24dSJoachim Eastwood static int lpc18xx_adc_probe(struct platform_device *pdev) 123*a583c24dSJoachim Eastwood { 124*a583c24dSJoachim Eastwood struct iio_dev *indio_dev; 125*a583c24dSJoachim Eastwood struct lpc18xx_adc *adc; 126*a583c24dSJoachim Eastwood struct resource *res; 127*a583c24dSJoachim Eastwood unsigned int clkdiv; 128*a583c24dSJoachim Eastwood unsigned long rate; 129*a583c24dSJoachim Eastwood int ret; 130*a583c24dSJoachim Eastwood 131*a583c24dSJoachim Eastwood indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); 132*a583c24dSJoachim Eastwood if (!indio_dev) 133*a583c24dSJoachim Eastwood return -ENOMEM; 134*a583c24dSJoachim Eastwood 135*a583c24dSJoachim Eastwood platform_set_drvdata(pdev, indio_dev); 136*a583c24dSJoachim Eastwood adc = iio_priv(indio_dev); 137*a583c24dSJoachim Eastwood adc->dev = &pdev->dev; 138*a583c24dSJoachim Eastwood mutex_init(&adc->lock); 139*a583c24dSJoachim Eastwood 140*a583c24dSJoachim Eastwood res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 141*a583c24dSJoachim Eastwood adc->base = devm_ioremap_resource(&pdev->dev, res); 142*a583c24dSJoachim Eastwood if (IS_ERR(adc->base)) 143*a583c24dSJoachim Eastwood return PTR_ERR(adc->base); 144*a583c24dSJoachim Eastwood 145*a583c24dSJoachim Eastwood adc->clk = devm_clk_get(&pdev->dev, NULL); 146*a583c24dSJoachim Eastwood if (IS_ERR(adc->clk)) { 147*a583c24dSJoachim Eastwood dev_err(&pdev->dev, "error getting clock\n"); 148*a583c24dSJoachim Eastwood return PTR_ERR(adc->clk); 149*a583c24dSJoachim Eastwood } 150*a583c24dSJoachim Eastwood 151*a583c24dSJoachim Eastwood rate = clk_get_rate(adc->clk); 152*a583c24dSJoachim Eastwood clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET); 153*a583c24dSJoachim Eastwood 154*a583c24dSJoachim Eastwood adc->vref = devm_regulator_get(&pdev->dev, "vref"); 155*a583c24dSJoachim Eastwood if (IS_ERR(adc->vref)) { 156*a583c24dSJoachim Eastwood dev_err(&pdev->dev, "error getting regulator\n"); 157*a583c24dSJoachim Eastwood return PTR_ERR(adc->vref); 158*a583c24dSJoachim Eastwood } 159*a583c24dSJoachim Eastwood 160*a583c24dSJoachim Eastwood indio_dev->name = dev_name(&pdev->dev); 161*a583c24dSJoachim Eastwood indio_dev->dev.parent = &pdev->dev; 162*a583c24dSJoachim Eastwood indio_dev->info = &lpc18xx_adc_info; 163*a583c24dSJoachim Eastwood indio_dev->modes = INDIO_DIRECT_MODE; 164*a583c24dSJoachim Eastwood indio_dev->channels = lpc18xx_adc_iio_channels; 165*a583c24dSJoachim Eastwood indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels); 166*a583c24dSJoachim Eastwood 167*a583c24dSJoachim Eastwood ret = regulator_enable(adc->vref); 168*a583c24dSJoachim Eastwood if (ret) { 169*a583c24dSJoachim Eastwood dev_err(&pdev->dev, "unable to enable regulator\n"); 170*a583c24dSJoachim Eastwood return ret; 171*a583c24dSJoachim Eastwood } 172*a583c24dSJoachim Eastwood 173*a583c24dSJoachim Eastwood ret = clk_prepare_enable(adc->clk); 174*a583c24dSJoachim Eastwood if (ret) { 175*a583c24dSJoachim Eastwood dev_err(&pdev->dev, "unable to enable clock\n"); 176*a583c24dSJoachim Eastwood goto dis_reg; 177*a583c24dSJoachim Eastwood } 178*a583c24dSJoachim Eastwood 179*a583c24dSJoachim Eastwood adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) | 180*a583c24dSJoachim Eastwood LPC18XX_ADC_CR_PDN; 181*a583c24dSJoachim Eastwood writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR); 182*a583c24dSJoachim Eastwood 183*a583c24dSJoachim Eastwood ret = iio_device_register(indio_dev); 184*a583c24dSJoachim Eastwood if (ret) { 185*a583c24dSJoachim Eastwood dev_err(&pdev->dev, "unable to register device\n"); 186*a583c24dSJoachim Eastwood goto dis_clk; 187*a583c24dSJoachim Eastwood } 188*a583c24dSJoachim Eastwood 189*a583c24dSJoachim Eastwood return 0; 190*a583c24dSJoachim Eastwood 191*a583c24dSJoachim Eastwood dis_clk: 192*a583c24dSJoachim Eastwood writel(0, adc->base + LPC18XX_ADC_CR); 193*a583c24dSJoachim Eastwood clk_disable_unprepare(adc->clk); 194*a583c24dSJoachim Eastwood dis_reg: 195*a583c24dSJoachim Eastwood regulator_disable(adc->vref); 196*a583c24dSJoachim Eastwood return ret; 197*a583c24dSJoachim Eastwood } 198*a583c24dSJoachim Eastwood 199*a583c24dSJoachim Eastwood static int lpc18xx_adc_remove(struct platform_device *pdev) 200*a583c24dSJoachim Eastwood { 201*a583c24dSJoachim Eastwood struct iio_dev *indio_dev = platform_get_drvdata(pdev); 202*a583c24dSJoachim Eastwood struct lpc18xx_adc *adc = iio_priv(indio_dev); 203*a583c24dSJoachim Eastwood 204*a583c24dSJoachim Eastwood iio_device_unregister(indio_dev); 205*a583c24dSJoachim Eastwood 206*a583c24dSJoachim Eastwood writel(0, adc->base + LPC18XX_ADC_CR); 207*a583c24dSJoachim Eastwood clk_disable_unprepare(adc->clk); 208*a583c24dSJoachim Eastwood regulator_disable(adc->vref); 209*a583c24dSJoachim Eastwood 210*a583c24dSJoachim Eastwood return 0; 211*a583c24dSJoachim Eastwood } 212*a583c24dSJoachim Eastwood 213*a583c24dSJoachim Eastwood static const struct of_device_id lpc18xx_adc_match[] = { 214*a583c24dSJoachim Eastwood { .compatible = "nxp,lpc1850-adc" }, 215*a583c24dSJoachim Eastwood { /* sentinel */ } 216*a583c24dSJoachim Eastwood }; 217*a583c24dSJoachim Eastwood MODULE_DEVICE_TABLE(of, lpc18xx_adc_match); 218*a583c24dSJoachim Eastwood 219*a583c24dSJoachim Eastwood static struct platform_driver lpc18xx_adc_driver = { 220*a583c24dSJoachim Eastwood .probe = lpc18xx_adc_probe, 221*a583c24dSJoachim Eastwood .remove = lpc18xx_adc_remove, 222*a583c24dSJoachim Eastwood .driver = { 223*a583c24dSJoachim Eastwood .name = "lpc18xx-adc", 224*a583c24dSJoachim Eastwood .of_match_table = lpc18xx_adc_match, 225*a583c24dSJoachim Eastwood }, 226*a583c24dSJoachim Eastwood }; 227*a583c24dSJoachim Eastwood module_platform_driver(lpc18xx_adc_driver); 228*a583c24dSJoachim Eastwood 229*a583c24dSJoachim Eastwood MODULE_DESCRIPTION("LPC18xx ADC driver"); 230*a583c24dSJoachim Eastwood MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); 231*a583c24dSJoachim Eastwood MODULE_LICENSE("GPL v2"); 232