11664f6a5SPhani Movva /* 21664f6a5SPhani Movva * Copyright (c) 2014-2015 Imagination Technologies Ltd. 31664f6a5SPhani Movva * 41664f6a5SPhani Movva * This program is free software; you can redistribute it and/or modify it 51664f6a5SPhani Movva * under the terms of the GNU General Public License version 2 as published by 61664f6a5SPhani Movva * the Free Software Foundation. 71664f6a5SPhani Movva * 81664f6a5SPhani Movva */ 91664f6a5SPhani Movva 101664f6a5SPhani Movva #include <linux/clk.h> 111664f6a5SPhani Movva #include <linux/delay.h> 121664f6a5SPhani Movva #include <linux/err.h> 131664f6a5SPhani Movva #include <linux/kernel.h> 141664f6a5SPhani Movva #include <linux/module.h> 151664f6a5SPhani Movva #include <linux/of.h> 161664f6a5SPhani Movva #include <linux/of_device.h> 171664f6a5SPhani Movva #include <linux/platform_device.h> 181664f6a5SPhani Movva #include <linux/regulator/consumer.h> 191664f6a5SPhani Movva #include <linux/slab.h> 201664f6a5SPhani Movva 211664f6a5SPhani Movva #include <linux/iio/buffer.h> 221664f6a5SPhani Movva #include <linux/iio/iio.h> 231664f6a5SPhani Movva #include <linux/iio/sysfs.h> 241664f6a5SPhani Movva #include <linux/iio/trigger.h> 251664f6a5SPhani Movva #include <linux/iio/trigger_consumer.h> 261664f6a5SPhani Movva #include <linux/iio/triggered_buffer.h> 271664f6a5SPhani Movva 281664f6a5SPhani Movva /* Registers */ 291664f6a5SPhani Movva #define CC10001_ADC_CONFIG 0x00 301664f6a5SPhani Movva #define CC10001_ADC_START_CONV BIT(4) 311664f6a5SPhani Movva #define CC10001_ADC_MODE_SINGLE_CONV BIT(5) 321664f6a5SPhani Movva 331664f6a5SPhani Movva #define CC10001_ADC_DDATA_OUT 0x04 341664f6a5SPhani Movva #define CC10001_ADC_EOC 0x08 351664f6a5SPhani Movva #define CC10001_ADC_EOC_SET BIT(0) 361664f6a5SPhani Movva 371664f6a5SPhani Movva #define CC10001_ADC_CHSEL_SAMPLED 0x0c 38713276eaSNaidu Tellapati #define CC10001_ADC_POWER_DOWN 0x10 39713276eaSNaidu Tellapati #define CC10001_ADC_POWER_DOWN_SET BIT(0) 40713276eaSNaidu Tellapati 411664f6a5SPhani Movva #define CC10001_ADC_DEBUG 0x14 421664f6a5SPhani Movva #define CC10001_ADC_DATA_COUNT 0x20 431664f6a5SPhani Movva 441664f6a5SPhani Movva #define CC10001_ADC_DATA_MASK GENMASK(9, 0) 451664f6a5SPhani Movva #define CC10001_ADC_NUM_CHANNELS 8 461664f6a5SPhani Movva #define CC10001_ADC_CH_MASK GENMASK(2, 0) 471664f6a5SPhani Movva 481664f6a5SPhani Movva #define CC10001_INVALID_SAMPLED 0xffff 491664f6a5SPhani Movva #define CC10001_MAX_POLL_COUNT 20 501664f6a5SPhani Movva 511664f6a5SPhani Movva /* 521664f6a5SPhani Movva * As per device specification, wait six clock cycles after power-up to 531664f6a5SPhani Movva * activate START. Since adding two more clock cycles delay does not 541664f6a5SPhani Movva * impact the performance too much, we are adding two additional cycles delay 551664f6a5SPhani Movva * intentionally here. 561664f6a5SPhani Movva */ 571664f6a5SPhani Movva #define CC10001_WAIT_CYCLES 8 581664f6a5SPhani Movva 591664f6a5SPhani Movva struct cc10001_adc_device { 601664f6a5SPhani Movva void __iomem *reg_base; 611664f6a5SPhani Movva struct clk *adc_clk; 621664f6a5SPhani Movva struct regulator *reg; 631664f6a5SPhani Movva u16 *buf; 641664f6a5SPhani Movva 651664f6a5SPhani Movva struct mutex lock; 661664f6a5SPhani Movva unsigned int start_delay_ns; 671664f6a5SPhani Movva unsigned int eoc_delay_ns; 681664f6a5SPhani Movva }; 691664f6a5SPhani Movva 701664f6a5SPhani Movva static inline void cc10001_adc_write_reg(struct cc10001_adc_device *adc_dev, 711664f6a5SPhani Movva u32 reg, u32 val) 721664f6a5SPhani Movva { 731664f6a5SPhani Movva writel(val, adc_dev->reg_base + reg); 741664f6a5SPhani Movva } 751664f6a5SPhani Movva 761664f6a5SPhani Movva static inline u32 cc10001_adc_read_reg(struct cc10001_adc_device *adc_dev, 771664f6a5SPhani Movva u32 reg) 781664f6a5SPhani Movva { 791664f6a5SPhani Movva return readl(adc_dev->reg_base + reg); 801664f6a5SPhani Movva } 811664f6a5SPhani Movva 82713276eaSNaidu Tellapati static void cc10001_adc_power_up(struct cc10001_adc_device *adc_dev) 83713276eaSNaidu Tellapati { 84713276eaSNaidu Tellapati cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_DOWN, 0); 85713276eaSNaidu Tellapati ndelay(adc_dev->start_delay_ns); 86713276eaSNaidu Tellapati } 87713276eaSNaidu Tellapati 88713276eaSNaidu Tellapati static void cc10001_adc_power_down(struct cc10001_adc_device *adc_dev) 89713276eaSNaidu Tellapati { 90713276eaSNaidu Tellapati cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_DOWN, 91713276eaSNaidu Tellapati CC10001_ADC_POWER_DOWN_SET); 92713276eaSNaidu Tellapati } 93713276eaSNaidu Tellapati 941664f6a5SPhani Movva static void cc10001_adc_start(struct cc10001_adc_device *adc_dev, 951664f6a5SPhani Movva unsigned int channel) 961664f6a5SPhani Movva { 971664f6a5SPhani Movva u32 val; 981664f6a5SPhani Movva 991664f6a5SPhani Movva /* Channel selection and mode of operation */ 1001664f6a5SPhani Movva val = (channel & CC10001_ADC_CH_MASK) | CC10001_ADC_MODE_SINGLE_CONV; 1011664f6a5SPhani Movva cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val); 1021664f6a5SPhani Movva 1031664f6a5SPhani Movva val = cc10001_adc_read_reg(adc_dev, CC10001_ADC_CONFIG); 1041664f6a5SPhani Movva val = val | CC10001_ADC_START_CONV; 1051664f6a5SPhani Movva cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val); 1061664f6a5SPhani Movva } 1071664f6a5SPhani Movva 1081664f6a5SPhani Movva static u16 cc10001_adc_poll_done(struct iio_dev *indio_dev, 1091664f6a5SPhani Movva unsigned int channel, 1101664f6a5SPhani Movva unsigned int delay) 1111664f6a5SPhani Movva { 1121664f6a5SPhani Movva struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); 1131664f6a5SPhani Movva unsigned int poll_count = 0; 1141664f6a5SPhani Movva 1151664f6a5SPhani Movva while (!(cc10001_adc_read_reg(adc_dev, CC10001_ADC_EOC) & 1161664f6a5SPhani Movva CC10001_ADC_EOC_SET)) { 1171664f6a5SPhani Movva 1181664f6a5SPhani Movva ndelay(delay); 1191664f6a5SPhani Movva if (poll_count++ == CC10001_MAX_POLL_COUNT) 1201664f6a5SPhani Movva return CC10001_INVALID_SAMPLED; 1211664f6a5SPhani Movva } 1221664f6a5SPhani Movva 1231664f6a5SPhani Movva poll_count = 0; 1241664f6a5SPhani Movva while ((cc10001_adc_read_reg(adc_dev, CC10001_ADC_CHSEL_SAMPLED) & 1251664f6a5SPhani Movva CC10001_ADC_CH_MASK) != channel) { 1261664f6a5SPhani Movva 1271664f6a5SPhani Movva ndelay(delay); 1281664f6a5SPhani Movva if (poll_count++ == CC10001_MAX_POLL_COUNT) 1291664f6a5SPhani Movva return CC10001_INVALID_SAMPLED; 1301664f6a5SPhani Movva } 1311664f6a5SPhani Movva 1321664f6a5SPhani Movva /* Read the 10 bit output register */ 1331664f6a5SPhani Movva return cc10001_adc_read_reg(adc_dev, CC10001_ADC_DDATA_OUT) & 1341664f6a5SPhani Movva CC10001_ADC_DATA_MASK; 1351664f6a5SPhani Movva } 1361664f6a5SPhani Movva 1371664f6a5SPhani Movva static irqreturn_t cc10001_adc_trigger_h(int irq, void *p) 1381664f6a5SPhani Movva { 1391664f6a5SPhani Movva struct cc10001_adc_device *adc_dev; 1401664f6a5SPhani Movva struct iio_poll_func *pf = p; 1411664f6a5SPhani Movva struct iio_dev *indio_dev; 1421664f6a5SPhani Movva unsigned int delay_ns; 1431664f6a5SPhani Movva unsigned int channel; 14413415a99SNaidu Tellapati unsigned int scan_idx; 1451664f6a5SPhani Movva bool sample_invalid; 1461664f6a5SPhani Movva u16 *data; 1471664f6a5SPhani Movva int i; 1481664f6a5SPhani Movva 1491664f6a5SPhani Movva indio_dev = pf->indio_dev; 1501664f6a5SPhani Movva adc_dev = iio_priv(indio_dev); 1511664f6a5SPhani Movva data = adc_dev->buf; 1521664f6a5SPhani Movva 1531664f6a5SPhani Movva mutex_lock(&adc_dev->lock); 1541664f6a5SPhani Movva 155713276eaSNaidu Tellapati cc10001_adc_power_up(adc_dev); 1561664f6a5SPhani Movva 1571664f6a5SPhani Movva /* Calculate delay step for eoc and sampled data */ 1581664f6a5SPhani Movva delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT; 1591664f6a5SPhani Movva 1601664f6a5SPhani Movva i = 0; 1611664f6a5SPhani Movva sample_invalid = false; 16213415a99SNaidu Tellapati for_each_set_bit(scan_idx, indio_dev->active_scan_mask, 1631664f6a5SPhani Movva indio_dev->masklength) { 1641664f6a5SPhani Movva 16513415a99SNaidu Tellapati channel = indio_dev->channels[scan_idx].channel; 1661664f6a5SPhani Movva cc10001_adc_start(adc_dev, channel); 1671664f6a5SPhani Movva 1681664f6a5SPhani Movva data[i] = cc10001_adc_poll_done(indio_dev, channel, delay_ns); 1691664f6a5SPhani Movva if (data[i] == CC10001_INVALID_SAMPLED) { 1701664f6a5SPhani Movva dev_warn(&indio_dev->dev, 1711664f6a5SPhani Movva "invalid sample on channel %d\n", channel); 1721664f6a5SPhani Movva sample_invalid = true; 1731664f6a5SPhani Movva goto done; 1741664f6a5SPhani Movva } 1751664f6a5SPhani Movva i++; 1761664f6a5SPhani Movva } 1771664f6a5SPhani Movva 1781664f6a5SPhani Movva done: 179713276eaSNaidu Tellapati cc10001_adc_power_down(adc_dev); 1801664f6a5SPhani Movva 1811664f6a5SPhani Movva mutex_unlock(&adc_dev->lock); 1821664f6a5SPhani Movva 1831664f6a5SPhani Movva if (!sample_invalid) 1841664f6a5SPhani Movva iio_push_to_buffers_with_timestamp(indio_dev, data, 1851664f6a5SPhani Movva iio_get_time_ns()); 1861664f6a5SPhani Movva iio_trigger_notify_done(indio_dev->trig); 1871664f6a5SPhani Movva 1881664f6a5SPhani Movva return IRQ_HANDLED; 1891664f6a5SPhani Movva } 1901664f6a5SPhani Movva 1911664f6a5SPhani Movva static u16 cc10001_adc_read_raw_voltage(struct iio_dev *indio_dev, 1921664f6a5SPhani Movva struct iio_chan_spec const *chan) 1931664f6a5SPhani Movva { 1941664f6a5SPhani Movva struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); 1951664f6a5SPhani Movva unsigned int delay_ns; 1961664f6a5SPhani Movva u16 val; 1971664f6a5SPhani Movva 198713276eaSNaidu Tellapati cc10001_adc_power_up(adc_dev); 1991664f6a5SPhani Movva 2001664f6a5SPhani Movva /* Calculate delay step for eoc and sampled data */ 2011664f6a5SPhani Movva delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT; 2021664f6a5SPhani Movva 2031664f6a5SPhani Movva cc10001_adc_start(adc_dev, chan->channel); 2041664f6a5SPhani Movva 2051664f6a5SPhani Movva val = cc10001_adc_poll_done(indio_dev, chan->channel, delay_ns); 2061664f6a5SPhani Movva 207713276eaSNaidu Tellapati cc10001_adc_power_down(adc_dev); 2081664f6a5SPhani Movva 2091664f6a5SPhani Movva return val; 2101664f6a5SPhani Movva } 2111664f6a5SPhani Movva 2121664f6a5SPhani Movva static int cc10001_adc_read_raw(struct iio_dev *indio_dev, 2131664f6a5SPhani Movva struct iio_chan_spec const *chan, 2141664f6a5SPhani Movva int *val, int *val2, long mask) 2151664f6a5SPhani Movva { 2161664f6a5SPhani Movva struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); 2171664f6a5SPhani Movva int ret; 2181664f6a5SPhani Movva 2191664f6a5SPhani Movva switch (mask) { 2201664f6a5SPhani Movva case IIO_CHAN_INFO_RAW: 2211664f6a5SPhani Movva if (iio_buffer_enabled(indio_dev)) 2221664f6a5SPhani Movva return -EBUSY; 2231664f6a5SPhani Movva mutex_lock(&adc_dev->lock); 2241664f6a5SPhani Movva *val = cc10001_adc_read_raw_voltage(indio_dev, chan); 2251664f6a5SPhani Movva mutex_unlock(&adc_dev->lock); 2261664f6a5SPhani Movva 2271664f6a5SPhani Movva if (*val == CC10001_INVALID_SAMPLED) 2281664f6a5SPhani Movva return -EIO; 2291664f6a5SPhani Movva return IIO_VAL_INT; 2301664f6a5SPhani Movva 2311664f6a5SPhani Movva case IIO_CHAN_INFO_SCALE: 2321664f6a5SPhani Movva ret = regulator_get_voltage(adc_dev->reg); 2331664f6a5SPhani Movva if (ret) 2341664f6a5SPhani Movva return ret; 2351664f6a5SPhani Movva 2361664f6a5SPhani Movva *val = ret / 1000; 2371664f6a5SPhani Movva *val2 = chan->scan_type.realbits; 2381664f6a5SPhani Movva return IIO_VAL_FRACTIONAL_LOG2; 2391664f6a5SPhani Movva 2401664f6a5SPhani Movva default: 2411664f6a5SPhani Movva return -EINVAL; 2421664f6a5SPhani Movva } 2431664f6a5SPhani Movva } 2441664f6a5SPhani Movva 2451664f6a5SPhani Movva static int cc10001_update_scan_mode(struct iio_dev *indio_dev, 2461664f6a5SPhani Movva const unsigned long *scan_mask) 2471664f6a5SPhani Movva { 2481664f6a5SPhani Movva struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); 2491664f6a5SPhani Movva 2501664f6a5SPhani Movva kfree(adc_dev->buf); 2511664f6a5SPhani Movva adc_dev->buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); 2521664f6a5SPhani Movva if (!adc_dev->buf) 2531664f6a5SPhani Movva return -ENOMEM; 2541664f6a5SPhani Movva 2551664f6a5SPhani Movva return 0; 2561664f6a5SPhani Movva } 2571664f6a5SPhani Movva 2581664f6a5SPhani Movva static const struct iio_info cc10001_adc_info = { 2591664f6a5SPhani Movva .driver_module = THIS_MODULE, 2601664f6a5SPhani Movva .read_raw = &cc10001_adc_read_raw, 2611664f6a5SPhani Movva .update_scan_mode = &cc10001_update_scan_mode, 2621664f6a5SPhani Movva }; 2631664f6a5SPhani Movva 26413415a99SNaidu Tellapati static int cc10001_adc_channel_init(struct iio_dev *indio_dev, 26513415a99SNaidu Tellapati unsigned long channel_map) 2661664f6a5SPhani Movva { 2671664f6a5SPhani Movva struct iio_chan_spec *chan_array, *timestamp; 2681664f6a5SPhani Movva unsigned int bit, idx = 0; 2691664f6a5SPhani Movva 27013415a99SNaidu Tellapati indio_dev->num_channels = bitmap_weight(&channel_map, 27113415a99SNaidu Tellapati CC10001_ADC_NUM_CHANNELS) + 1; 2721664f6a5SPhani Movva 27313415a99SNaidu Tellapati chan_array = devm_kcalloc(&indio_dev->dev, indio_dev->num_channels, 2741664f6a5SPhani Movva sizeof(struct iio_chan_spec), 2751664f6a5SPhani Movva GFP_KERNEL); 2761664f6a5SPhani Movva if (!chan_array) 2771664f6a5SPhani Movva return -ENOMEM; 2781664f6a5SPhani Movva 27913415a99SNaidu Tellapati for_each_set_bit(bit, &channel_map, CC10001_ADC_NUM_CHANNELS) { 2801664f6a5SPhani Movva struct iio_chan_spec *chan = &chan_array[idx]; 2811664f6a5SPhani Movva 2821664f6a5SPhani Movva chan->type = IIO_VOLTAGE; 2831664f6a5SPhani Movva chan->indexed = 1; 2841664f6a5SPhani Movva chan->channel = bit; 2851664f6a5SPhani Movva chan->scan_index = idx; 2861664f6a5SPhani Movva chan->scan_type.sign = 'u'; 2871664f6a5SPhani Movva chan->scan_type.realbits = 10; 2881664f6a5SPhani Movva chan->scan_type.storagebits = 16; 2891664f6a5SPhani Movva chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); 2901664f6a5SPhani Movva chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 2911664f6a5SPhani Movva idx++; 2921664f6a5SPhani Movva } 2931664f6a5SPhani Movva 2941664f6a5SPhani Movva timestamp = &chan_array[idx]; 2951664f6a5SPhani Movva timestamp->type = IIO_TIMESTAMP; 2961664f6a5SPhani Movva timestamp->channel = -1; 2971664f6a5SPhani Movva timestamp->scan_index = idx; 2981664f6a5SPhani Movva timestamp->scan_type.sign = 's'; 2991664f6a5SPhani Movva timestamp->scan_type.realbits = 64; 3001664f6a5SPhani Movva timestamp->scan_type.storagebits = 64; 3011664f6a5SPhani Movva 3021664f6a5SPhani Movva indio_dev->channels = chan_array; 3031664f6a5SPhani Movva 3041664f6a5SPhani Movva return 0; 3051664f6a5SPhani Movva } 3061664f6a5SPhani Movva 3071664f6a5SPhani Movva static int cc10001_adc_probe(struct platform_device *pdev) 3081664f6a5SPhani Movva { 3091664f6a5SPhani Movva struct device_node *node = pdev->dev.of_node; 3101664f6a5SPhani Movva struct cc10001_adc_device *adc_dev; 3111664f6a5SPhani Movva unsigned long adc_clk_rate; 3121664f6a5SPhani Movva struct resource *res; 3131664f6a5SPhani Movva struct iio_dev *indio_dev; 31413415a99SNaidu Tellapati unsigned long channel_map; 3151664f6a5SPhani Movva int ret; 3161664f6a5SPhani Movva 3171664f6a5SPhani Movva indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev)); 3181664f6a5SPhani Movva if (indio_dev == NULL) 3191664f6a5SPhani Movva return -ENOMEM; 3201664f6a5SPhani Movva 3211664f6a5SPhani Movva adc_dev = iio_priv(indio_dev); 3221664f6a5SPhani Movva 32313415a99SNaidu Tellapati channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0); 3241664f6a5SPhani Movva if (!of_property_read_u32(node, "adc-reserved-channels", &ret)) 32513415a99SNaidu Tellapati channel_map &= ~ret; 3261664f6a5SPhani Movva 3271664f6a5SPhani Movva adc_dev->reg = devm_regulator_get(&pdev->dev, "vref"); 3281664f6a5SPhani Movva if (IS_ERR(adc_dev->reg)) 3291664f6a5SPhani Movva return PTR_ERR(adc_dev->reg); 3301664f6a5SPhani Movva 3311664f6a5SPhani Movva ret = regulator_enable(adc_dev->reg); 3321664f6a5SPhani Movva if (ret) 3331664f6a5SPhani Movva return ret; 3341664f6a5SPhani Movva 3351664f6a5SPhani Movva indio_dev->dev.parent = &pdev->dev; 3361664f6a5SPhani Movva indio_dev->name = dev_name(&pdev->dev); 3371664f6a5SPhani Movva indio_dev->info = &cc10001_adc_info; 3381664f6a5SPhani Movva indio_dev->modes = INDIO_DIRECT_MODE; 3391664f6a5SPhani Movva 3401664f6a5SPhani Movva res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3411664f6a5SPhani Movva adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res); 3421664f6a5SPhani Movva if (IS_ERR(adc_dev->reg_base)) { 3431664f6a5SPhani Movva ret = PTR_ERR(adc_dev->reg_base); 3441664f6a5SPhani Movva goto err_disable_reg; 3451664f6a5SPhani Movva } 3461664f6a5SPhani Movva 3471664f6a5SPhani Movva adc_dev->adc_clk = devm_clk_get(&pdev->dev, "adc"); 3481664f6a5SPhani Movva if (IS_ERR(adc_dev->adc_clk)) { 3491664f6a5SPhani Movva dev_err(&pdev->dev, "failed to get the clock\n"); 3501664f6a5SPhani Movva ret = PTR_ERR(adc_dev->adc_clk); 3511664f6a5SPhani Movva goto err_disable_reg; 3521664f6a5SPhani Movva } 3531664f6a5SPhani Movva 3541664f6a5SPhani Movva ret = clk_prepare_enable(adc_dev->adc_clk); 3551664f6a5SPhani Movva if (ret) { 3561664f6a5SPhani Movva dev_err(&pdev->dev, "failed to enable the clock\n"); 3571664f6a5SPhani Movva goto err_disable_reg; 3581664f6a5SPhani Movva } 3591664f6a5SPhani Movva 3601664f6a5SPhani Movva adc_clk_rate = clk_get_rate(adc_dev->adc_clk); 3611664f6a5SPhani Movva if (!adc_clk_rate) { 3621664f6a5SPhani Movva ret = -EINVAL; 3631664f6a5SPhani Movva dev_err(&pdev->dev, "null clock rate!\n"); 3641664f6a5SPhani Movva goto err_disable_clk; 3651664f6a5SPhani Movva } 3661664f6a5SPhani Movva 3671664f6a5SPhani Movva adc_dev->eoc_delay_ns = NSEC_PER_SEC / adc_clk_rate; 3681664f6a5SPhani Movva adc_dev->start_delay_ns = adc_dev->eoc_delay_ns * CC10001_WAIT_CYCLES; 3691664f6a5SPhani Movva 3701664f6a5SPhani Movva /* Setup the ADC channels available on the device */ 37113415a99SNaidu Tellapati ret = cc10001_adc_channel_init(indio_dev, channel_map); 3721664f6a5SPhani Movva if (ret < 0) 3731664f6a5SPhani Movva goto err_disable_clk; 3741664f6a5SPhani Movva 3751664f6a5SPhani Movva mutex_init(&adc_dev->lock); 3761664f6a5SPhani Movva 3771664f6a5SPhani Movva ret = iio_triggered_buffer_setup(indio_dev, NULL, 3781664f6a5SPhani Movva &cc10001_adc_trigger_h, NULL); 3791664f6a5SPhani Movva if (ret < 0) 3801664f6a5SPhani Movva goto err_disable_clk; 3811664f6a5SPhani Movva 3821664f6a5SPhani Movva ret = iio_device_register(indio_dev); 3831664f6a5SPhani Movva if (ret < 0) 3841664f6a5SPhani Movva goto err_cleanup_buffer; 3851664f6a5SPhani Movva 3861664f6a5SPhani Movva platform_set_drvdata(pdev, indio_dev); 3871664f6a5SPhani Movva 3881664f6a5SPhani Movva return 0; 3891664f6a5SPhani Movva 3901664f6a5SPhani Movva err_cleanup_buffer: 3911664f6a5SPhani Movva iio_triggered_buffer_cleanup(indio_dev); 3921664f6a5SPhani Movva err_disable_clk: 3931664f6a5SPhani Movva clk_disable_unprepare(adc_dev->adc_clk); 3941664f6a5SPhani Movva err_disable_reg: 3951664f6a5SPhani Movva regulator_disable(adc_dev->reg); 3961664f6a5SPhani Movva return ret; 3971664f6a5SPhani Movva } 3981664f6a5SPhani Movva 3991664f6a5SPhani Movva static int cc10001_adc_remove(struct platform_device *pdev) 4001664f6a5SPhani Movva { 4011664f6a5SPhani Movva struct iio_dev *indio_dev = platform_get_drvdata(pdev); 4021664f6a5SPhani Movva struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); 4031664f6a5SPhani Movva 4041664f6a5SPhani Movva iio_device_unregister(indio_dev); 4051664f6a5SPhani Movva iio_triggered_buffer_cleanup(indio_dev); 4061664f6a5SPhani Movva clk_disable_unprepare(adc_dev->adc_clk); 4071664f6a5SPhani Movva regulator_disable(adc_dev->reg); 4081664f6a5SPhani Movva 4091664f6a5SPhani Movva return 0; 4101664f6a5SPhani Movva } 4111664f6a5SPhani Movva 4121664f6a5SPhani Movva static const struct of_device_id cc10001_adc_dt_ids[] = { 4131664f6a5SPhani Movva { .compatible = "cosmic,10001-adc", }, 4141664f6a5SPhani Movva { } 4151664f6a5SPhani Movva }; 4161664f6a5SPhani Movva MODULE_DEVICE_TABLE(of, cc10001_adc_dt_ids); 4171664f6a5SPhani Movva 4181664f6a5SPhani Movva static struct platform_driver cc10001_adc_driver = { 4191664f6a5SPhani Movva .driver = { 4201664f6a5SPhani Movva .name = "cc10001-adc", 4211664f6a5SPhani Movva .of_match_table = cc10001_adc_dt_ids, 4221664f6a5SPhani Movva }, 4231664f6a5SPhani Movva .probe = cc10001_adc_probe, 4241664f6a5SPhani Movva .remove = cc10001_adc_remove, 4251664f6a5SPhani Movva }; 4261664f6a5SPhani Movva module_platform_driver(cc10001_adc_driver); 4271664f6a5SPhani Movva 4281664f6a5SPhani Movva MODULE_AUTHOR("Phani Movva <Phani.Movva@imgtec.com>"); 4291664f6a5SPhani Movva MODULE_DESCRIPTION("Cosmic Circuits ADC driver"); 4301664f6a5SPhani Movva MODULE_LICENSE("GPL v2"); 431