linux/drivers/staging/iio/frequency/ad9834.c
<<
>>
Prefs
   1/*
   2 * AD9833/AD9834/AD9837/AD9838 SPI DDS driver
   3 *
   4 * Copyright 2010-2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/workqueue.h>
  11#include <linux/device.h>
  12#include <linux/kernel.h>
  13#include <linux/slab.h>
  14#include <linux/sysfs.h>
  15#include <linux/list.h>
  16#include <linux/spi/spi.h>
  17#include <linux/regulator/consumer.h>
  18#include <linux/err.h>
  19#include <linux/module.h>
  20#include <asm/div64.h>
  21
  22#include <linux/iio/iio.h>
  23#include <linux/iio/sysfs.h>
  24#include "dds.h"
  25
  26#include "ad9834.h"
  27
  28static unsigned int ad9834_calc_freqreg(unsigned long mclk, unsigned long fout)
  29{
  30        unsigned long long freqreg = (u64)fout * (u64)BIT(AD9834_FREQ_BITS);
  31
  32        do_div(freqreg, mclk);
  33        return freqreg;
  34}
  35
  36static int ad9834_write_frequency(struct ad9834_state *st,
  37                                  unsigned long addr, unsigned long fout)
  38{
  39        unsigned long regval;
  40
  41        if (fout > (st->mclk / 2))
  42                return -EINVAL;
  43
  44        regval = ad9834_calc_freqreg(st->mclk, fout);
  45
  46        st->freq_data[0] = cpu_to_be16(addr | (regval &
  47                                       RES_MASK(AD9834_FREQ_BITS / 2)));
  48        st->freq_data[1] = cpu_to_be16(addr | ((regval >>
  49                                       (AD9834_FREQ_BITS / 2)) &
  50                                       RES_MASK(AD9834_FREQ_BITS / 2)));
  51
  52        return spi_sync(st->spi, &st->freq_msg);
  53}
  54
  55static int ad9834_write_phase(struct ad9834_state *st,
  56                              unsigned long addr, unsigned long phase)
  57{
  58        if (phase > BIT(AD9834_PHASE_BITS))
  59                return -EINVAL;
  60        st->data = cpu_to_be16(addr | phase);
  61
  62        return spi_sync(st->spi, &st->msg);
  63}
  64
  65static ssize_t ad9834_write(struct device *dev,
  66                            struct device_attribute *attr,
  67                            const char *buf,
  68                            size_t len)
  69{
  70        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  71        struct ad9834_state *st = iio_priv(indio_dev);
  72        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
  73        int ret;
  74        unsigned long val;
  75
  76        ret = kstrtoul(buf, 10, &val);
  77        if (ret)
  78                goto error_ret;
  79
  80        mutex_lock(&indio_dev->mlock);
  81        switch ((u32)this_attr->address) {
  82        case AD9834_REG_FREQ0:
  83        case AD9834_REG_FREQ1:
  84                ret = ad9834_write_frequency(st, this_attr->address, val);
  85                break;
  86        case AD9834_REG_PHASE0:
  87        case AD9834_REG_PHASE1:
  88                ret = ad9834_write_phase(st, this_attr->address, val);
  89                break;
  90        case AD9834_OPBITEN:
  91                if (st->control & AD9834_MODE) {
  92                        ret = -EINVAL;  /* AD9843 reserved mode */
  93                        break;
  94                }
  95
  96                if (val)
  97                        st->control |= AD9834_OPBITEN;
  98                else
  99                        st->control &= ~AD9834_OPBITEN;
 100
 101                st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
 102                ret = spi_sync(st->spi, &st->msg);
 103                break;
 104        case AD9834_PIN_SW:
 105                if (val)
 106                        st->control |= AD9834_PIN_SW;
 107                else
 108                        st->control &= ~AD9834_PIN_SW;
 109                st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
 110                ret = spi_sync(st->spi, &st->msg);
 111                break;
 112        case AD9834_FSEL:
 113        case AD9834_PSEL:
 114                if (!val) {
 115                        st->control &= ~(this_attr->address | AD9834_PIN_SW);
 116                } else if (val == 1) {
 117                        st->control |= this_attr->address;
 118                        st->control &= ~AD9834_PIN_SW;
 119                } else {
 120                        ret = -EINVAL;
 121                        break;
 122                }
 123                st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
 124                ret = spi_sync(st->spi, &st->msg);
 125                break;
 126        case AD9834_RESET:
 127                if (val)
 128                        st->control &= ~AD9834_RESET;
 129                else
 130                        st->control |= AD9834_RESET;
 131
 132                st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
 133                ret = spi_sync(st->spi, &st->msg);
 134                break;
 135        default:
 136                ret = -ENODEV;
 137        }
 138        mutex_unlock(&indio_dev->mlock);
 139
 140error_ret:
 141        return ret ? ret : len;
 142}
 143
 144static ssize_t ad9834_store_wavetype(struct device *dev,
 145                                     struct device_attribute *attr,
 146                                     const char *buf,
 147                                     size_t len)
 148{
 149        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 150        struct ad9834_state *st = iio_priv(indio_dev);
 151        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 152        int ret = 0;
 153        bool is_ad9833_7 = (st->devid == ID_AD9833) || (st->devid == ID_AD9837);
 154
 155        mutex_lock(&indio_dev->mlock);
 156
 157        switch ((u32)this_attr->address) {
 158        case 0:
 159                if (sysfs_streq(buf, "sine")) {
 160                        st->control &= ~AD9834_MODE;
 161                        if (is_ad9833_7)
 162                                st->control &= ~AD9834_OPBITEN;
 163                } else if (sysfs_streq(buf, "triangle")) {
 164                        if (is_ad9833_7) {
 165                                st->control &= ~AD9834_OPBITEN;
 166                                st->control |= AD9834_MODE;
 167                        } else if (st->control & AD9834_OPBITEN) {
 168                                ret = -EINVAL;  /* AD9843 reserved mode */
 169                        } else {
 170                                st->control |= AD9834_MODE;
 171                        }
 172                } else if (is_ad9833_7 && sysfs_streq(buf, "square")) {
 173                        st->control &= ~AD9834_MODE;
 174                        st->control |= AD9834_OPBITEN;
 175                } else {
 176                        ret = -EINVAL;
 177                }
 178
 179                break;
 180        case 1:
 181                if (sysfs_streq(buf, "square") &&
 182                    !(st->control & AD9834_MODE)) {
 183                        st->control &= ~AD9834_MODE;
 184                        st->control |= AD9834_OPBITEN;
 185                } else {
 186                        ret = -EINVAL;
 187                }
 188                break;
 189        default:
 190                ret = -EINVAL;
 191                break;
 192        }
 193
 194        if (!ret) {
 195                st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
 196                ret = spi_sync(st->spi, &st->msg);
 197        }
 198        mutex_unlock(&indio_dev->mlock);
 199
 200        return ret ? ret : len;
 201}
 202
 203static
 204ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
 205                                            struct device_attribute *attr,
 206                                            char *buf)
 207{
 208        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 209        struct ad9834_state *st = iio_priv(indio_dev);
 210        char *str;
 211
 212        if ((st->devid == ID_AD9833) || (st->devid == ID_AD9837))
 213                str = "sine triangle square";
 214        else if (st->control & AD9834_OPBITEN)
 215                str = "sine";
 216        else
 217                str = "sine triangle";
 218
 219        return sprintf(buf, "%s\n", str);
 220}
 221
 222static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO,
 223                       ad9834_show_out0_wavetype_available, NULL, 0);
 224
 225static
 226ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
 227                                            struct device_attribute *attr,
 228                                            char *buf)
 229{
 230        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 231        struct ad9834_state *st = iio_priv(indio_dev);
 232        char *str;
 233
 234        if (st->control & AD9834_MODE)
 235                str = "";
 236        else
 237                str = "square";
 238
 239        return sprintf(buf, "%s\n", str);
 240}
 241
 242static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, S_IRUGO,
 243                       ad9834_show_out1_wavetype_available, NULL, 0);
 244
 245/**
 246 * see dds.h for further information
 247 */
 248
 249static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ0);
 250static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ1);
 251static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_FSEL);
 252static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */
 253
 254static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE0);
 255static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE1);
 256static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_PSEL);
 257static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/
 258
 259static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL,
 260        ad9834_write, AD9834_PIN_SW);
 261static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, ad9834_write, AD9834_RESET);
 262static IIO_DEV_ATTR_OUTY_ENABLE(0, 1, S_IWUSR, NULL,
 263        ad9834_write, AD9834_OPBITEN);
 264static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0);
 265static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1);
 266
 267static struct attribute *ad9834_attributes[] = {
 268        &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr,
 269        &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr,
 270        &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr,
 271        &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr,
 272        &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr,
 273        &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr,
 274        &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr,
 275        &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr,
 276        &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr,
 277        &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr,
 278        &iio_dev_attr_out_altvoltage0_out1_enable.dev_attr.attr,
 279        &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr,
 280        &iio_dev_attr_out_altvoltage0_out1_wavetype.dev_attr.attr,
 281        &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr,
 282        &iio_dev_attr_out_altvoltage0_out1_wavetype_available.dev_attr.attr,
 283        NULL,
 284};
 285
 286static struct attribute *ad9833_attributes[] = {
 287        &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr,
 288        &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr,
 289        &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr,
 290        &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr,
 291        &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr,
 292        &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr,
 293        &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr,
 294        &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr,
 295        &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr,
 296        &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr,
 297        &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr,
 298        NULL,
 299};
 300
 301static const struct attribute_group ad9834_attribute_group = {
 302        .attrs = ad9834_attributes,
 303};
 304
 305static const struct attribute_group ad9833_attribute_group = {
 306        .attrs = ad9833_attributes,
 307};
 308
 309static const struct iio_info ad9834_info = {
 310        .attrs = &ad9834_attribute_group,
 311        .driver_module = THIS_MODULE,
 312};
 313
 314static const struct iio_info ad9833_info = {
 315        .attrs = &ad9833_attribute_group,
 316        .driver_module = THIS_MODULE,
 317};
 318
 319static int ad9834_probe(struct spi_device *spi)
 320{
 321        struct ad9834_platform_data *pdata = dev_get_platdata(&spi->dev);
 322        struct ad9834_state *st;
 323        struct iio_dev *indio_dev;
 324        struct regulator *reg;
 325        int ret;
 326
 327        if (!pdata) {
 328                dev_dbg(&spi->dev, "no platform data?\n");
 329                return -ENODEV;
 330        }
 331
 332        reg = devm_regulator_get(&spi->dev, "vcc");
 333        if (!IS_ERR(reg)) {
 334                ret = regulator_enable(reg);
 335                if (ret)
 336                        return ret;
 337        }
 338
 339        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 340        if (!indio_dev) {
 341                ret = -ENOMEM;
 342                goto error_disable_reg;
 343        }
 344        spi_set_drvdata(spi, indio_dev);
 345        st = iio_priv(indio_dev);
 346        st->mclk = pdata->mclk;
 347        st->spi = spi;
 348        st->devid = spi_get_device_id(spi)->driver_data;
 349        st->reg = reg;
 350        indio_dev->dev.parent = &spi->dev;
 351        indio_dev->name = spi_get_device_id(spi)->name;
 352        switch (st->devid) {
 353        case ID_AD9833:
 354        case ID_AD9837:
 355                indio_dev->info = &ad9833_info;
 356                break;
 357        default:
 358                indio_dev->info = &ad9834_info;
 359                break;
 360        }
 361        indio_dev->modes = INDIO_DIRECT_MODE;
 362
 363        /* Setup default messages */
 364
 365        st->xfer.tx_buf = &st->data;
 366        st->xfer.len = 2;
 367
 368        spi_message_init(&st->msg);
 369        spi_message_add_tail(&st->xfer, &st->msg);
 370
 371        st->freq_xfer[0].tx_buf = &st->freq_data[0];
 372        st->freq_xfer[0].len = 2;
 373        st->freq_xfer[0].cs_change = 1;
 374        st->freq_xfer[1].tx_buf = &st->freq_data[1];
 375        st->freq_xfer[1].len = 2;
 376
 377        spi_message_init(&st->freq_msg);
 378        spi_message_add_tail(&st->freq_xfer[0], &st->freq_msg);
 379        spi_message_add_tail(&st->freq_xfer[1], &st->freq_msg);
 380
 381        st->control = AD9834_B28 | AD9834_RESET;
 382
 383        if (!pdata->en_div2)
 384                st->control |= AD9834_DIV2;
 385
 386        if (!pdata->en_signbit_msb_out && (st->devid == ID_AD9834))
 387                st->control |= AD9834_SIGN_PIB;
 388
 389        st->data = cpu_to_be16(AD9834_REG_CMD | st->control);
 390        ret = spi_sync(st->spi, &st->msg);
 391        if (ret) {
 392                dev_err(&spi->dev, "device init failed\n");
 393                goto error_disable_reg;
 394        }
 395
 396        ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, pdata->freq0);
 397        if (ret)
 398                goto error_disable_reg;
 399
 400        ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, pdata->freq1);
 401        if (ret)
 402                goto error_disable_reg;
 403
 404        ret = ad9834_write_phase(st, AD9834_REG_PHASE0, pdata->phase0);
 405        if (ret)
 406                goto error_disable_reg;
 407
 408        ret = ad9834_write_phase(st, AD9834_REG_PHASE1, pdata->phase1);
 409        if (ret)
 410                goto error_disable_reg;
 411
 412        ret = iio_device_register(indio_dev);
 413        if (ret)
 414                goto error_disable_reg;
 415
 416        return 0;
 417
 418error_disable_reg:
 419        if (!IS_ERR(reg))
 420                regulator_disable(reg);
 421
 422        return ret;
 423}
 424
 425static int ad9834_remove(struct spi_device *spi)
 426{
 427        struct iio_dev *indio_dev = spi_get_drvdata(spi);
 428        struct ad9834_state *st = iio_priv(indio_dev);
 429
 430        iio_device_unregister(indio_dev);
 431        if (!IS_ERR(st->reg))
 432                regulator_disable(st->reg);
 433
 434        return 0;
 435}
 436
 437static const struct spi_device_id ad9834_id[] = {
 438        {"ad9833", ID_AD9833},
 439        {"ad9834", ID_AD9834},
 440        {"ad9837", ID_AD9837},
 441        {"ad9838", ID_AD9838},
 442        {}
 443};
 444MODULE_DEVICE_TABLE(spi, ad9834_id);
 445
 446static struct spi_driver ad9834_driver = {
 447        .driver = {
 448                .name   = "ad9834",
 449        },
 450        .probe          = ad9834_probe,
 451        .remove         = ad9834_remove,
 452        .id_table       = ad9834_id,
 453};
 454module_spi_driver(ad9834_driver);
 455
 456MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 457MODULE_DESCRIPTION("Analog Devices AD9833/AD9834/AD9837/AD9838 DDS");
 458MODULE_LICENSE("GPL v2");
 459