1 /* 2 * Rockchip Successive Approximation Register (SAR) A/D Converter 3 * Copyright (C) 2014 ROCKCHIP, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/module.h> 17 #include <linux/platform_device.h> 18 #include <linux/interrupt.h> 19 #include <linux/io.h> 20 #include <linux/of.h> 21 #include <linux/clk.h> 22 #include <linux/completion.h> 23 #include <linux/regulator/consumer.h> 24 #include <linux/iio/iio.h> 25 26 #define SARADC_DATA 0x00 27 #define SARADC_DATA_MASK 0x3ff 28 29 #define SARADC_STAS 0x04 30 #define SARADC_STAS_BUSY BIT(0) 31 32 #define SARADC_CTRL 0x08 33 #define SARADC_CTRL_IRQ_STATUS BIT(6) 34 #define SARADC_CTRL_IRQ_ENABLE BIT(5) 35 #define SARADC_CTRL_POWER_CTRL BIT(3) 36 #define SARADC_CTRL_CHN_MASK 0x7 37 38 #define SARADC_DLY_PU_SOC 0x0c 39 #define SARADC_DLY_PU_SOC_MASK 0x3f 40 41 #define SARADC_BITS 10 42 #define SARADC_TIMEOUT msecs_to_jiffies(100) 43 44 struct rockchip_saradc { 45 void __iomem *regs; 46 struct clk *pclk; 47 struct clk *clk; 48 struct completion completion; 49 struct regulator *vref; 50 u16 last_val; 51 }; 52 53 static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, 54 struct iio_chan_spec const *chan, 55 int *val, int *val2, long mask) 56 { 57 struct rockchip_saradc *info = iio_priv(indio_dev); 58 int ret; 59 60 switch (mask) { 61 case IIO_CHAN_INFO_RAW: 62 mutex_lock(&indio_dev->mlock); 63 64 reinit_completion(&info->completion); 65 66 /* 8 clock periods as delay between power up and start cmd */ 67 writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); 68 69 /* Select the channel to be used and trigger conversion */ 70 writel(SARADC_CTRL_POWER_CTRL 71 | (chan->channel & SARADC_CTRL_CHN_MASK) 72 | SARADC_CTRL_IRQ_ENABLE, 73 info->regs + SARADC_CTRL); 74 75 if (!wait_for_completion_timeout(&info->completion, 76 SARADC_TIMEOUT)) { 77 writel_relaxed(0, info->regs + SARADC_CTRL); 78 mutex_unlock(&indio_dev->mlock); 79 return -ETIMEDOUT; 80 } 81 82 *val = info->last_val; 83 mutex_unlock(&indio_dev->mlock); 84 return IIO_VAL_INT; 85 case IIO_CHAN_INFO_SCALE: 86 ret = regulator_get_voltage(info->vref); 87 if (ret < 0) { 88 dev_err(&indio_dev->dev, "failed to get voltage\n"); 89 return ret; 90 } 91 92 *val = ret / 1000; 93 *val2 = SARADC_BITS; 94 return IIO_VAL_FRACTIONAL_LOG2; 95 default: 96 return -EINVAL; 97 } 98 } 99 100 static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) 101 { 102 struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id; 103 104 /* Read value */ 105 info->last_val = readl_relaxed(info->regs + SARADC_DATA); 106 info->last_val &= SARADC_DATA_MASK; 107 108 /* Clear irq & power down adc */ 109 writel_relaxed(0, info->regs + SARADC_CTRL); 110 111 complete(&info->completion); 112 113 return IRQ_HANDLED; 114 } 115 116 static const struct iio_info rockchip_saradc_iio_info = { 117 .read_raw = rockchip_saradc_read_raw, 118 .driver_module = THIS_MODULE, 119 }; 120 121 #define ADC_CHANNEL(_index, _id) { \ 122 .type = IIO_VOLTAGE, \ 123 .indexed = 1, \ 124 .channel = _index, \ 125 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 126 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 127 .datasheet_name = _id, \ 128 } 129 130 static const struct iio_chan_spec rockchip_saradc_iio_channels[] = { 131 ADC_CHANNEL(0, "adc0"), 132 ADC_CHANNEL(1, "adc1"), 133 ADC_CHANNEL(2, "adc2"), 134 }; 135 136 static int rockchip_saradc_probe(struct platform_device *pdev) 137 { 138 struct rockchip_saradc *info = NULL; 139 struct device_node *np = pdev->dev.of_node; 140 struct iio_dev *indio_dev = NULL; 141 struct resource *mem; 142 int ret; 143 int irq; 144 145 if (!np) 146 return -ENODEV; 147 148 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); 149 if (!indio_dev) { 150 dev_err(&pdev->dev, "failed allocating iio device\n"); 151 return -ENOMEM; 152 } 153 info = iio_priv(indio_dev); 154 155 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 156 info->regs = devm_ioremap_resource(&pdev->dev, mem); 157 if (IS_ERR(info->regs)) 158 return PTR_ERR(info->regs); 159 160 init_completion(&info->completion); 161 162 irq = platform_get_irq(pdev, 0); 163 if (irq < 0) { 164 dev_err(&pdev->dev, "no irq resource?\n"); 165 return irq; 166 } 167 168 ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, 169 0, dev_name(&pdev->dev), info); 170 if (ret < 0) { 171 dev_err(&pdev->dev, "failed requesting irq %d\n", irq); 172 return ret; 173 } 174 175 info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); 176 if (IS_ERR(info->pclk)) { 177 dev_err(&pdev->dev, "failed to get pclk\n"); 178 return PTR_ERR(info->pclk); 179 } 180 181 info->clk = devm_clk_get(&pdev->dev, "saradc"); 182 if (IS_ERR(info->clk)) { 183 dev_err(&pdev->dev, "failed to get adc clock\n"); 184 return PTR_ERR(info->clk); 185 } 186 187 info->vref = devm_regulator_get(&pdev->dev, "vref"); 188 if (IS_ERR(info->vref)) { 189 dev_err(&pdev->dev, "failed to get regulator, %ld\n", 190 PTR_ERR(info->vref)); 191 return PTR_ERR(info->vref); 192 } 193 194 /* 195 * Use a default of 1MHz for the converter clock. 196 * This may become user-configurable in the future. 197 */ 198 ret = clk_set_rate(info->clk, 1000000); 199 if (ret < 0) { 200 dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); 201 return ret; 202 } 203 204 ret = regulator_enable(info->vref); 205 if (ret < 0) { 206 dev_err(&pdev->dev, "failed to enable vref regulator\n"); 207 return ret; 208 } 209 210 ret = clk_prepare_enable(info->pclk); 211 if (ret < 0) { 212 dev_err(&pdev->dev, "failed to enable pclk\n"); 213 goto err_reg_voltage; 214 } 215 216 ret = clk_prepare_enable(info->clk); 217 if (ret < 0) { 218 dev_err(&pdev->dev, "failed to enable converter clock\n"); 219 goto err_pclk; 220 } 221 222 platform_set_drvdata(pdev, indio_dev); 223 224 indio_dev->name = dev_name(&pdev->dev); 225 indio_dev->dev.parent = &pdev->dev; 226 indio_dev->dev.of_node = pdev->dev.of_node; 227 indio_dev->info = &rockchip_saradc_iio_info; 228 indio_dev->modes = INDIO_DIRECT_MODE; 229 230 indio_dev->channels = rockchip_saradc_iio_channels; 231 indio_dev->num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels); 232 233 ret = iio_device_register(indio_dev); 234 if (ret) 235 goto err_clk; 236 237 return 0; 238 239 err_clk: 240 clk_disable_unprepare(info->clk); 241 err_pclk: 242 clk_disable_unprepare(info->pclk); 243 err_reg_voltage: 244 regulator_disable(info->vref); 245 return ret; 246 } 247 248 static int rockchip_saradc_remove(struct platform_device *pdev) 249 { 250 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 251 struct rockchip_saradc *info = iio_priv(indio_dev); 252 253 iio_device_unregister(indio_dev); 254 clk_disable_unprepare(info->clk); 255 clk_disable_unprepare(info->pclk); 256 regulator_disable(info->vref); 257 258 return 0; 259 } 260 261 #ifdef CONFIG_PM_SLEEP 262 static int rockchip_saradc_suspend(struct device *dev) 263 { 264 struct iio_dev *indio_dev = dev_get_drvdata(dev); 265 struct rockchip_saradc *info = iio_priv(indio_dev); 266 267 clk_disable_unprepare(info->clk); 268 clk_disable_unprepare(info->pclk); 269 regulator_disable(info->vref); 270 271 return 0; 272 } 273 274 static int rockchip_saradc_resume(struct device *dev) 275 { 276 struct iio_dev *indio_dev = dev_get_drvdata(dev); 277 struct rockchip_saradc *info = iio_priv(indio_dev); 278 int ret; 279 280 ret = regulator_enable(info->vref); 281 if (ret) 282 return ret; 283 284 ret = clk_prepare_enable(info->pclk); 285 if (ret) 286 return ret; 287 288 ret = clk_prepare_enable(info->clk); 289 if (ret) 290 return ret; 291 292 return ret; 293 } 294 #endif 295 296 static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, 297 rockchip_saradc_suspend, rockchip_saradc_resume); 298 299 static const struct of_device_id rockchip_saradc_match[] = { 300 { .compatible = "rockchip,saradc" }, 301 {}, 302 }; 303 MODULE_DEVICE_TABLE(of, rockchip_saradc_match); 304 305 static struct platform_driver rockchip_saradc_driver = { 306 .probe = rockchip_saradc_probe, 307 .remove = rockchip_saradc_remove, 308 .driver = { 309 .name = "rockchip-saradc", 310 .owner = THIS_MODULE, 311 .of_match_table = rockchip_saradc_match, 312 .pm = &rockchip_saradc_pm_ops, 313 }, 314 }; 315 316 module_platform_driver(rockchip_saradc_driver); 317