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/of_device.h> 22#include <linux/clk.h> 23#include <linux/completion.h> 24#include <linux/regulator/consumer.h> 25#include <linux/iio/iio.h> 26 27#define SARADC_DATA 0x00 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_TIMEOUT msecs_to_jiffies(100) 42 43struct rockchip_saradc_data { 44 int num_bits; 45 const struct iio_chan_spec *channels; 46 int num_channels; 47 unsigned long clk_rate; 48}; 49 50struct rockchip_saradc { 51 void __iomem *regs; 52 struct clk *pclk; 53 struct clk *clk; 54 struct completion completion; 55 struct regulator *vref; 56 const struct rockchip_saradc_data *data; 57 u16 last_val; 58}; 59 60static int rockchip_saradc_read_raw(struct iio_dev *indio_dev, 61 struct iio_chan_spec const *chan, 62 int *val, int *val2, long mask) 63{ 64 struct rockchip_saradc *info = iio_priv(indio_dev); 65 int ret; 66 67 switch (mask) { 68 case IIO_CHAN_INFO_RAW: 69 mutex_lock(&indio_dev->mlock); 70 71 reinit_completion(&info->completion); 72 73 /* 8 clock periods as delay between power up and start cmd */ 74 writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); 75 76 /* Select the channel to be used and trigger conversion */ 77 writel(SARADC_CTRL_POWER_CTRL 78 | (chan->channel & SARADC_CTRL_CHN_MASK) 79 | SARADC_CTRL_IRQ_ENABLE, 80 info->regs + SARADC_CTRL); 81 82 if (!wait_for_completion_timeout(&info->completion, 83 SARADC_TIMEOUT)) { 84 writel_relaxed(0, info->regs + SARADC_CTRL); 85 mutex_unlock(&indio_dev->mlock); 86 return -ETIMEDOUT; 87 } 88 89 *val = info->last_val; 90 mutex_unlock(&indio_dev->mlock); 91 return IIO_VAL_INT; 92 case IIO_CHAN_INFO_SCALE: 93 ret = regulator_get_voltage(info->vref); 94 if (ret < 0) { 95 dev_err(&indio_dev->dev, "failed to get voltage\n"); 96 return ret; 97 } 98 99 *val = ret / 1000; 100 *val2 = info->data->num_bits; 101 return IIO_VAL_FRACTIONAL_LOG2; 102 default: 103 return -EINVAL; 104 } 105} 106 107static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) 108{ 109 struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id; 110 111 /* Read value */ 112 info->last_val = readl_relaxed(info->regs + SARADC_DATA); 113 info->last_val &= GENMASK(info->data->num_bits - 1, 0); 114 115 /* Clear irq & power down adc */ 116 writel_relaxed(0, info->regs + SARADC_CTRL); 117 118 complete(&info->completion); 119 120 return IRQ_HANDLED; 121} 122 123static const struct iio_info rockchip_saradc_iio_info = { 124 .read_raw = rockchip_saradc_read_raw, 125 .driver_module = THIS_MODULE, 126}; 127 128#define ADC_CHANNEL(_index, _id) { \ 129 .type = IIO_VOLTAGE, \ 130 .indexed = 1, \ 131 .channel = _index, \ 132 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 133 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 134 .datasheet_name = _id, \ 135} 136 137static const struct iio_chan_spec rockchip_saradc_iio_channels[] = { 138 ADC_CHANNEL(0, "adc0"), 139 ADC_CHANNEL(1, "adc1"), 140 ADC_CHANNEL(2, "adc2"), 141}; 142 143static const struct rockchip_saradc_data saradc_data = { 144 .num_bits = 10, 145 .channels = rockchip_saradc_iio_channels, 146 .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels), 147 .clk_rate = 1000000, 148}; 149 150static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = { 151 ADC_CHANNEL(0, "adc0"), 152 ADC_CHANNEL(1, "adc1"), 153}; 154 155static const struct rockchip_saradc_data rk3066_tsadc_data = { 156 .num_bits = 12, 157 .channels = rockchip_rk3066_tsadc_iio_channels, 158 .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels), 159 .clk_rate = 50000, 160}; 161 162static const struct of_device_id rockchip_saradc_match[] = { 163 { 164 .compatible = "rockchip,saradc", 165 .data = &saradc_data, 166 }, { 167 .compatible = "rockchip,rk3066-tsadc", 168 .data = &rk3066_tsadc_data, 169 }, 170 {}, 171}; 172MODULE_DEVICE_TABLE(of, rockchip_saradc_match); 173 174static int rockchip_saradc_probe(struct platform_device *pdev) 175{ 176 struct rockchip_saradc *info = NULL; 177 struct device_node *np = pdev->dev.of_node; 178 struct iio_dev *indio_dev = NULL; 179 struct resource *mem; 180 const struct of_device_id *match; 181 int ret; 182 int irq; 183 184 if (!np) 185 return -ENODEV; 186 187 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); 188 if (!indio_dev) { 189 dev_err(&pdev->dev, "failed allocating iio device\n"); 190 return -ENOMEM; 191 } 192 info = iio_priv(indio_dev); 193 194 match = of_match_device(rockchip_saradc_match, &pdev->dev); 195 info->data = match->data; 196 197 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 198 info->regs = devm_ioremap_resource(&pdev->dev, mem); 199 if (IS_ERR(info->regs)) 200 return PTR_ERR(info->regs); 201 202 init_completion(&info->completion); 203 204 irq = platform_get_irq(pdev, 0); 205 if (irq < 0) { 206 dev_err(&pdev->dev, "no irq resource?\n"); 207 return irq; 208 } 209 210 ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, 211 0, dev_name(&pdev->dev), info); 212 if (ret < 0) { 213 dev_err(&pdev->dev, "failed requesting irq %d\n", irq); 214 return ret; 215 } 216 217 info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); 218 if (IS_ERR(info->pclk)) { 219 dev_err(&pdev->dev, "failed to get pclk\n"); 220 return PTR_ERR(info->pclk); 221 } 222 223 info->clk = devm_clk_get(&pdev->dev, "saradc"); 224 if (IS_ERR(info->clk)) { 225 dev_err(&pdev->dev, "failed to get adc clock\n"); 226 return PTR_ERR(info->clk); 227 } 228 229 info->vref = devm_regulator_get(&pdev->dev, "vref"); 230 if (IS_ERR(info->vref)) { 231 dev_err(&pdev->dev, "failed to get regulator, %ld\n", 232 PTR_ERR(info->vref)); 233 return PTR_ERR(info->vref); 234 } 235 236 /* 237 * Use a default value for the converter clock. 238 * This may become user-configurable in the future. 239 */ 240 ret = clk_set_rate(info->clk, info->data->clk_rate); 241 if (ret < 0) { 242 dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); 243 return ret; 244 } 245 246 ret = regulator_enable(info->vref); 247 if (ret < 0) { 248 dev_err(&pdev->dev, "failed to enable vref regulator\n"); 249 return ret; 250 } 251 252 ret = clk_prepare_enable(info->pclk); 253 if (ret < 0) { 254 dev_err(&pdev->dev, "failed to enable pclk\n"); 255 goto err_reg_voltage; 256 } 257 258 ret = clk_prepare_enable(info->clk); 259 if (ret < 0) { 260 dev_err(&pdev->dev, "failed to enable converter clock\n"); 261 goto err_pclk; 262 } 263 264 platform_set_drvdata(pdev, indio_dev); 265 266 indio_dev->name = dev_name(&pdev->dev); 267 indio_dev->dev.parent = &pdev->dev; 268 indio_dev->dev.of_node = pdev->dev.of_node; 269 indio_dev->info = &rockchip_saradc_iio_info; 270 indio_dev->modes = INDIO_DIRECT_MODE; 271 272 indio_dev->channels = info->data->channels; 273 indio_dev->num_channels = info->data->num_channels; 274 275 ret = iio_device_register(indio_dev); 276 if (ret) 277 goto err_clk; 278 279 return 0; 280 281err_clk: 282 clk_disable_unprepare(info->clk); 283err_pclk: 284 clk_disable_unprepare(info->pclk); 285err_reg_voltage: 286 regulator_disable(info->vref); 287 return ret; 288} 289 290static int rockchip_saradc_remove(struct platform_device *pdev) 291{ 292 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 293 struct rockchip_saradc *info = iio_priv(indio_dev); 294 295 iio_device_unregister(indio_dev); 296 clk_disable_unprepare(info->clk); 297 clk_disable_unprepare(info->pclk); 298 regulator_disable(info->vref); 299 300 return 0; 301} 302 303#ifdef CONFIG_PM_SLEEP 304static int rockchip_saradc_suspend(struct device *dev) 305{ 306 struct iio_dev *indio_dev = dev_get_drvdata(dev); 307 struct rockchip_saradc *info = iio_priv(indio_dev); 308 309 clk_disable_unprepare(info->clk); 310 clk_disable_unprepare(info->pclk); 311 regulator_disable(info->vref); 312 313 return 0; 314} 315 316static int rockchip_saradc_resume(struct device *dev) 317{ 318 struct iio_dev *indio_dev = dev_get_drvdata(dev); 319 struct rockchip_saradc *info = iio_priv(indio_dev); 320 int ret; 321 322 ret = regulator_enable(info->vref); 323 if (ret) 324 return ret; 325 326 ret = clk_prepare_enable(info->pclk); 327 if (ret) 328 return ret; 329 330 ret = clk_prepare_enable(info->clk); 331 if (ret) 332 return ret; 333 334 return ret; 335} 336#endif 337 338static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, 339 rockchip_saradc_suspend, rockchip_saradc_resume); 340 341static struct platform_driver rockchip_saradc_driver = { 342 .probe = rockchip_saradc_probe, 343 .remove = rockchip_saradc_remove, 344 .driver = { 345 .name = "rockchip-saradc", 346 .of_match_table = rockchip_saradc_match, 347 .pm = &rockchip_saradc_pm_ops, 348 }, 349}; 350 351module_platform_driver(rockchip_saradc_driver); 352 353MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 354MODULE_DESCRIPTION("Rockchip SARADC driver"); 355MODULE_LICENSE("GPL v2"); 356