linux/drivers/staging/iio/adc/spear_adc.c
<<
>>
Prefs
   1/*
   2 * ST SPEAr ADC driver
   3 *
   4 * Copyright 2012 Stefan Roese <sr@denx.de>
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/platform_device.h>
  11#include <linux/interrupt.h>
  12#include <linux/device.h>
  13#include <linux/kernel.h>
  14#include <linux/slab.h>
  15#include <linux/io.h>
  16#include <linux/clk.h>
  17#include <linux/err.h>
  18#include <linux/completion.h>
  19#include <linux/of.h>
  20#include <linux/of_address.h>
  21
  22#include <linux/iio/iio.h>
  23#include <linux/iio/sysfs.h>
  24
  25/*
  26 * SPEAR registers definitions
  27 */
  28
  29#define SCAN_RATE_LO(x)         ((x) & 0xFFFF)
  30#define SCAN_RATE_HI(x)         (((x) >> 0x10) & 0xFFFF)
  31#define CLK_LOW(x)              (((x) & 0xf) << 0)
  32#define CLK_HIGH(x)             (((x) & 0xf) << 4)
  33
  34/* Bit definitions for SPEAR_ADC_STATUS */
  35#define START_CONVERSION        (1 << 0)
  36#define CHANNEL_NUM(x)          ((x) << 1)
  37#define ADC_ENABLE              (1 << 4)
  38#define AVG_SAMPLE(x)           ((x) << 5)
  39#define VREF_INTERNAL           (1 << 9)
  40
  41#define DATA_MASK               0x03ff
  42#define DATA_BITS               10
  43
  44#define MOD_NAME "spear-adc"
  45
  46#define ADC_CHANNEL_NUM         8
  47
  48#define CLK_MIN                 2500000
  49#define CLK_MAX                 20000000
  50
  51struct adc_regs_spear3xx {
  52        u32 status;
  53        u32 average;
  54        u32 scan_rate;
  55        u32 clk;        /* Not avail for 1340 & 1310 */
  56        u32 ch_ctrl[ADC_CHANNEL_NUM];
  57        u32 ch_data[ADC_CHANNEL_NUM];
  58};
  59
  60struct chan_data {
  61        u32 lsb;
  62        u32 msb;
  63};
  64
  65struct adc_regs_spear6xx {
  66        u32 status;
  67        u32 pad[2];
  68        u32 clk;
  69        u32 ch_ctrl[ADC_CHANNEL_NUM];
  70        struct chan_data ch_data[ADC_CHANNEL_NUM];
  71        u32 scan_rate_lo;
  72        u32 scan_rate_hi;
  73        struct chan_data average;
  74};
  75
  76struct spear_adc_info {
  77        struct device_node *np;
  78        struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
  79        struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
  80        struct clk *clk;
  81        struct completion completion;
  82        u32 current_clk;
  83        u32 sampling_freq;
  84        u32 avg_samples;
  85        u32 vref_external;
  86        u32 value;
  87};
  88
  89/*
  90 * Functions to access some SPEAr ADC register. Abstracted into
  91 * static inline functions, because of different register offsets
  92 * on different SoC variants (SPEAr300 vs SPEAr600 etc).
  93 */
  94static void spear_adc_set_status(struct spear_adc_info *info, u32 val)
  95{
  96        __raw_writel(val, &info->adc_base_spear6xx->status);
  97}
  98
  99static void spear_adc_set_clk(struct spear_adc_info *info, u32 val)
 100{
 101        u32 clk_high, clk_low, count;
 102        u32 apb_clk = clk_get_rate(info->clk);
 103
 104        count = (apb_clk + val - 1) / val;
 105        clk_low = count / 2;
 106        clk_high = count - clk_low;
 107        info->current_clk = apb_clk / count;
 108
 109        __raw_writel(CLK_LOW(clk_low) | CLK_HIGH(clk_high),
 110                     &info->adc_base_spear6xx->clk);
 111}
 112
 113static void spear_adc_set_ctrl(struct spear_adc_info *info, int n,
 114                               u32 val)
 115{
 116        __raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]);
 117}
 118
 119static u32 spear_adc_get_average(struct spear_adc_info *info)
 120{
 121        if (of_device_is_compatible(info->np, "st,spear600-adc")) {
 122                return __raw_readl(&info->adc_base_spear6xx->average.msb) &
 123                        DATA_MASK;
 124        } else {
 125                return __raw_readl(&info->adc_base_spear3xx->average) &
 126                        DATA_MASK;
 127        }
 128}
 129
 130static void spear_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
 131{
 132        if (of_device_is_compatible(info->np, "st,spear600-adc")) {
 133                __raw_writel(SCAN_RATE_LO(rate),
 134                             &info->adc_base_spear6xx->scan_rate_lo);
 135                __raw_writel(SCAN_RATE_HI(rate),
 136                             &info->adc_base_spear6xx->scan_rate_hi);
 137        } else {
 138                __raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
 139        }
 140}
 141
 142static int spear_read_raw(struct iio_dev *indio_dev,
 143                          struct iio_chan_spec const *chan,
 144                          int *val,
 145                          int *val2,
 146                          long mask)
 147{
 148        struct spear_adc_info *info = iio_priv(indio_dev);
 149        u32 scale_mv;
 150        u32 status;
 151
 152        switch (mask) {
 153        case IIO_CHAN_INFO_RAW:
 154                mutex_lock(&indio_dev->mlock);
 155
 156                status = CHANNEL_NUM(chan->channel) |
 157                        AVG_SAMPLE(info->avg_samples) |
 158                        START_CONVERSION | ADC_ENABLE;
 159                if (info->vref_external == 0)
 160                        status |= VREF_INTERNAL;
 161
 162                spear_adc_set_status(info, status);
 163                wait_for_completion(&info->completion); /* set by ISR */
 164                *val = info->value;
 165
 166                mutex_unlock(&indio_dev->mlock);
 167
 168                return IIO_VAL_INT;
 169
 170        case IIO_CHAN_INFO_SCALE:
 171                scale_mv = (info->vref_external * 1000) >> DATA_BITS;
 172                *val =  scale_mv / 1000;
 173                *val2 = (scale_mv % 1000) * 1000;
 174                return IIO_VAL_INT_PLUS_MICRO;
 175        }
 176
 177        return -EINVAL;
 178}
 179
 180#define SPEAR_ADC_CHAN(idx) {                           \
 181        .type = IIO_VOLTAGE,                            \
 182        .indexed = 1,                                   \
 183        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
 184        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
 185        .channel = idx,                                 \
 186        .scan_type = {                                  \
 187                .sign = 'u',                            \
 188                .storagebits = 16,                      \
 189        },                                              \
 190}
 191
 192static const struct iio_chan_spec spear_adc_iio_channels[] = {
 193        SPEAR_ADC_CHAN(0),
 194        SPEAR_ADC_CHAN(1),
 195        SPEAR_ADC_CHAN(2),
 196        SPEAR_ADC_CHAN(3),
 197        SPEAR_ADC_CHAN(4),
 198        SPEAR_ADC_CHAN(5),
 199        SPEAR_ADC_CHAN(6),
 200        SPEAR_ADC_CHAN(7),
 201};
 202
 203static irqreturn_t spear_adc_isr(int irq, void *dev_id)
 204{
 205        struct spear_adc_info *info = (struct spear_adc_info *)dev_id;
 206
 207        /* Read value to clear IRQ */
 208        info->value = spear_adc_get_average(info);
 209        complete(&info->completion);
 210
 211        return IRQ_HANDLED;
 212}
 213
 214static int spear_adc_configure(struct spear_adc_info *info)
 215{
 216        int i;
 217
 218        /* Reset ADC core */
 219        spear_adc_set_status(info, 0);
 220        __raw_writel(0, &info->adc_base_spear6xx->clk);
 221        for (i = 0; i < 8; i++)
 222                spear_adc_set_ctrl(info, i, 0);
 223        spear_adc_set_scanrate(info, 0);
 224
 225        spear_adc_set_clk(info, info->sampling_freq);
 226
 227        return 0;
 228}
 229
 230static ssize_t spear_adc_read_frequency(struct device *dev,
 231                                        struct device_attribute *attr,
 232                                        char *buf)
 233{
 234        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 235        struct spear_adc_info *info = iio_priv(indio_dev);
 236
 237        return sprintf(buf, "%d\n", info->current_clk);
 238}
 239
 240static ssize_t spear_adc_write_frequency(struct device *dev,
 241                                         struct device_attribute *attr,
 242                                         const char *buf,
 243                                         size_t len)
 244{
 245        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 246        struct spear_adc_info *info = iio_priv(indio_dev);
 247        u32 clk_high, clk_low, count;
 248        u32 apb_clk = clk_get_rate(info->clk);
 249        unsigned long lval;
 250        int ret;
 251
 252        ret = kstrtoul(buf, 10, &lval);
 253        if (ret)
 254                return ret;
 255
 256        mutex_lock(&indio_dev->mlock);
 257
 258        if ((lval < CLK_MIN) || (lval > CLK_MAX)) {
 259                ret = -EINVAL;
 260                goto out;
 261        }
 262
 263        count = (apb_clk + lval - 1) / lval;
 264        clk_low = count / 2;
 265        clk_high = count - clk_low;
 266        info->current_clk = apb_clk / count;
 267        spear_adc_set_clk(info, lval);
 268
 269out:
 270        mutex_unlock(&indio_dev->mlock);
 271
 272        return ret ? ret : len;
 273}
 274
 275static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 276                              spear_adc_read_frequency,
 277                              spear_adc_write_frequency);
 278
 279static struct attribute *spear_attributes[] = {
 280        &iio_dev_attr_sampling_frequency.dev_attr.attr,
 281        NULL
 282};
 283
 284static const struct attribute_group spear_attribute_group = {
 285        .attrs = spear_attributes,
 286};
 287
 288static const struct iio_info spear_adc_iio_info = {
 289        .read_raw = &spear_read_raw,
 290        .attrs = &spear_attribute_group,
 291        .driver_module = THIS_MODULE,
 292};
 293
 294static int spear_adc_probe(struct platform_device *pdev)
 295{
 296        struct device_node *np = pdev->dev.of_node;
 297        struct device *dev = &pdev->dev;
 298        struct spear_adc_info *info;
 299        struct iio_dev *iodev = NULL;
 300        int ret = -ENODEV;
 301        int irq;
 302
 303        iodev = iio_device_alloc(sizeof(struct spear_adc_info));
 304        if (!iodev) {
 305                dev_err(dev, "failed allocating iio device\n");
 306                ret = -ENOMEM;
 307                goto errout1;
 308        }
 309
 310        info = iio_priv(iodev);
 311        info->np = np;
 312
 313        /*
 314         * SPEAr600 has a different register layout than other SPEAr SoC's
 315         * (e.g. SPEAr3xx). Let's provide two register base addresses
 316         * to support multi-arch kernels.
 317         */
 318        info->adc_base_spear6xx = of_iomap(np, 0);
 319        if (!info->adc_base_spear6xx) {
 320                dev_err(dev, "failed mapping memory\n");
 321                ret = -ENOMEM;
 322                goto errout2;
 323        }
 324        info->adc_base_spear3xx =
 325                (struct adc_regs_spear3xx *)info->adc_base_spear6xx;
 326
 327        info->clk = clk_get(dev, NULL);
 328        if (IS_ERR(info->clk)) {
 329                dev_err(dev, "failed getting clock\n");
 330                goto errout3;
 331        }
 332
 333        ret = clk_prepare_enable(info->clk);
 334        if (ret) {
 335                dev_err(dev, "failed enabling clock\n");
 336                goto errout4;
 337        }
 338
 339        irq = platform_get_irq(pdev, 0);
 340        if ((irq < 0) || (irq >= NR_IRQS)) {
 341                dev_err(dev, "failed getting interrupt resource\n");
 342                ret = -EINVAL;
 343                goto errout5;
 344        }
 345
 346        ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info);
 347        if (ret < 0) {
 348                dev_err(dev, "failed requesting interrupt\n");
 349                goto errout5;
 350        }
 351
 352        if (of_property_read_u32(np, "sampling-frequency",
 353                                 &info->sampling_freq)) {
 354                dev_err(dev, "sampling-frequency missing in DT\n");
 355                ret = -EINVAL;
 356                goto errout5;
 357        }
 358
 359        /*
 360         * Optional avg_samples defaults to 0, resulting in single data
 361         * conversion
 362         */
 363        of_property_read_u32(np, "average-samples", &info->avg_samples);
 364
 365        /*
 366         * Optional vref_external defaults to 0, resulting in internal vref
 367         * selection
 368         */
 369        of_property_read_u32(np, "vref-external", &info->vref_external);
 370
 371        spear_adc_configure(info);
 372
 373        platform_set_drvdata(pdev, iodev);
 374
 375        init_completion(&info->completion);
 376
 377        iodev->name = MOD_NAME;
 378        iodev->dev.parent = dev;
 379        iodev->info = &spear_adc_iio_info;
 380        iodev->modes = INDIO_DIRECT_MODE;
 381        iodev->channels = spear_adc_iio_channels;
 382        iodev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
 383
 384        ret = iio_device_register(iodev);
 385        if (ret)
 386                goto errout5;
 387
 388        dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
 389
 390        return 0;
 391
 392errout5:
 393        clk_disable_unprepare(info->clk);
 394errout4:
 395        clk_put(info->clk);
 396errout3:
 397        iounmap(info->adc_base_spear6xx);
 398errout2:
 399        iio_device_free(iodev);
 400errout1:
 401        return ret;
 402}
 403
 404static int spear_adc_remove(struct platform_device *pdev)
 405{
 406        struct iio_dev *iodev = platform_get_drvdata(pdev);
 407        struct spear_adc_info *info = iio_priv(iodev);
 408
 409        iio_device_unregister(iodev);
 410        platform_set_drvdata(pdev, NULL);
 411        clk_disable_unprepare(info->clk);
 412        clk_put(info->clk);
 413        iounmap(info->adc_base_spear6xx);
 414        iio_device_free(iodev);
 415
 416        return 0;
 417}
 418
 419static const struct of_device_id spear_adc_dt_ids[] = {
 420        { .compatible = "st,spear600-adc", },
 421        { /* sentinel */ }
 422};
 423MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
 424
 425static struct platform_driver spear_adc_driver = {
 426        .probe          = spear_adc_probe,
 427        .remove         = spear_adc_remove,
 428        .driver         = {
 429                .name   = MOD_NAME,
 430                .owner  = THIS_MODULE,
 431                .of_match_table = of_match_ptr(spear_adc_dt_ids),
 432        },
 433};
 434
 435module_platform_driver(spear_adc_driver);
 436
 437MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
 438MODULE_DESCRIPTION("SPEAr ADC driver");
 439MODULE_LICENSE("GPL");
 440