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