linux/drivers/staging/iio/dds/ad9910.c
<<
>>
Prefs
   1/*
   2 * Driver for ADI Direct Digital Synthesis ad9910
   3 *
   4 * Copyright (c) 2010 Analog Devices Inc.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11#include <linux/types.h>
  12#include <linux/mutex.h>
  13#include <linux/device.h>
  14#include <linux/spi/spi.h>
  15#include <linux/slab.h>
  16#include <linux/sysfs.h>
  17#include <linux/module.h>
  18
  19#include "../iio.h"
  20#include "../sysfs.h"
  21
  22#define DRV_NAME "ad9910"
  23
  24#define CFR1 0x0
  25#define CFR2 0x1
  26#define CFR3 0x2
  27
  28#define AUXDAC 0x3
  29#define IOUPD 0x4
  30#define FTW 0x7
  31#define POW 0x8
  32#define ASF 0x9
  33#define MULTC 0x0A
  34#define DIG_RAMPL 0x0B
  35#define DIG_RAMPS 0x0C
  36#define DIG_RAMPR 0x0D
  37#define SIN_TONEP0 0x0E
  38#define SIN_TONEP1 0x0F
  39#define SIN_TONEP2 0x10
  40#define SIN_TONEP3 0x11
  41#define SIN_TONEP4 0x12
  42#define SIN_TONEP5 0x13
  43#define SIN_TONEP6 0x14
  44#define SIN_TONEP7 0x15
  45
  46#define RAM_ENABLE      (1 << 7)
  47
  48#define MANUAL_OSK      (1 << 7)
  49#define INVSIC          (1 << 6)
  50#define DDS_SINEOP      (1)
  51
  52#define AUTO_OSK        (1)
  53#define OSKEN           (1 << 1)
  54#define LOAD_ARR        (1 << 2)
  55#define CLR_PHA         (1 << 3)
  56#define CLR_DIG         (1 << 4)
  57#define ACLR_PHA        (1 << 5)
  58#define ACLR_DIG        (1 << 6)
  59#define LOAD_LRR        (1 << 7)
  60
  61#define LSB_FST         (1)
  62#define SDIO_IPT        (1 << 1)
  63#define EXT_PWD         (1 << 3)
  64#define ADAC_PWD        (1 << 4)
  65#define REFCLK_PWD      (1 << 5)
  66#define DAC_PWD         (1 << 6)
  67#define DIG_PWD         (1 << 7)
  68
  69#define ENA_AMP         (1)
  70#define READ_FTW        (1)
  71#define DIGR_LOW        (1 << 1)
  72#define DIGR_HIGH       (1 << 2)
  73#define DIGR_ENA        (1 << 3)
  74#define SYNCCLK_ENA     (1 << 6)
  75#define ITER_IOUPD      (1 << 7)
  76
  77#define TX_ENA          (1 << 1)
  78#define PDCLK_INV       (1 << 2)
  79#define PDCLK_ENB       (1 << 3)
  80
  81#define PARA_ENA        (1 << 4)
  82#define SYNC_DIS        (1 << 5)
  83#define DATA_ASS        (1 << 6)
  84#define MATCH_ENA       (1 << 7)
  85
  86#define PLL_ENA         (1)
  87#define PFD_RST         (1 << 2)
  88#define REFCLK_RST      (1 << 6)
  89#define REFCLK_BYP      (1 << 7)
  90
  91/* Register format: 1 byte addr + value */
  92struct ad9910_config {
  93        u8 auxdac[5];
  94        u8 ioupd[5];
  95        u8 ftw[5];
  96        u8 pow[3];
  97        u8 asf[5];
  98        u8 multc[5];
  99        u8 dig_rampl[9];
 100        u8 dig_ramps[9];
 101        u8 dig_rampr[5];
 102        u8 sin_tonep0[9];
 103        u8 sin_tonep1[9];
 104        u8 sin_tonep2[9];
 105        u8 sin_tonep3[9];
 106        u8 sin_tonep4[9];
 107        u8 sin_tonep5[9];
 108        u8 sin_tonep6[9];
 109        u8 sin_tonep7[9];
 110};
 111
 112struct ad9910_state {
 113        struct mutex lock;
 114        struct spi_device *sdev;
 115};
 116
 117static ssize_t ad9910_set_parameter(struct device *dev,
 118                                        struct device_attribute *attr,
 119                                        const char *buf,
 120                                        size_t len)
 121{
 122        struct spi_message msg;
 123        struct spi_transfer xfer;
 124        int ret;
 125        struct ad9910_config *config = (struct ad9910_config *)buf;
 126        struct iio_dev *idev = dev_get_drvdata(dev);
 127        struct ad9910_state *st = iio_priv(idev);
 128
 129        xfer.len = 5;
 130        xfer.tx_buf = &config->auxdac[0];
 131        mutex_lock(&st->lock);
 132
 133        spi_message_init(&msg);
 134        spi_message_add_tail(&xfer, &msg);
 135        ret = spi_sync(st->sdev, &msg);
 136        if (ret)
 137                goto error_ret;
 138
 139        xfer.len = 5;
 140        xfer.tx_buf = &config->ioupd[0];
 141
 142        spi_message_init(&msg);
 143        spi_message_add_tail(&xfer, &msg);
 144        ret = spi_sync(st->sdev, &msg);
 145        if (ret)
 146                goto error_ret;
 147
 148        xfer.len = 5;
 149        xfer.tx_buf = &config->ftw[0];
 150
 151        spi_message_init(&msg);
 152        spi_message_add_tail(&xfer, &msg);
 153        ret = spi_sync(st->sdev, &msg);
 154        if (ret)
 155                goto error_ret;
 156
 157        xfer.len = 3;
 158        xfer.tx_buf = &config->pow[0];
 159
 160        spi_message_init(&msg);
 161        spi_message_add_tail(&xfer, &msg);
 162        ret = spi_sync(st->sdev, &msg);
 163        if (ret)
 164                goto error_ret;
 165
 166        xfer.len = 5;
 167        xfer.tx_buf = &config->asf[0];
 168
 169        spi_message_init(&msg);
 170        spi_message_add_tail(&xfer, &msg);
 171        ret = spi_sync(st->sdev, &msg);
 172        if (ret)
 173                goto error_ret;
 174
 175        xfer.len = 5;
 176        xfer.tx_buf = &config->multc[0];
 177
 178        spi_message_init(&msg);
 179        spi_message_add_tail(&xfer, &msg);
 180        ret = spi_sync(st->sdev, &msg);
 181        if (ret)
 182                goto error_ret;
 183
 184        xfer.len = 9;
 185        xfer.tx_buf = &config->dig_rampl[0];
 186
 187        spi_message_init(&msg);
 188        spi_message_add_tail(&xfer, &msg);
 189        ret = spi_sync(st->sdev, &msg);
 190        if (ret)
 191                goto error_ret;
 192
 193        xfer.len = 9;
 194        xfer.tx_buf = &config->dig_ramps[0];
 195
 196        spi_message_init(&msg);
 197        spi_message_add_tail(&xfer, &msg);
 198        ret = spi_sync(st->sdev, &msg);
 199        if (ret)
 200                goto error_ret;
 201
 202        xfer.len = 5;
 203        xfer.tx_buf = &config->dig_rampr[0];
 204
 205        spi_message_init(&msg);
 206        spi_message_add_tail(&xfer, &msg);
 207        ret = spi_sync(st->sdev, &msg);
 208        if (ret)
 209                goto error_ret;
 210
 211        xfer.len = 9;
 212        xfer.tx_buf = &config->sin_tonep0[0];
 213
 214        spi_message_init(&msg);
 215        spi_message_add_tail(&xfer, &msg);
 216        ret = spi_sync(st->sdev, &msg);
 217        if (ret)
 218                goto error_ret;
 219
 220        xfer.len = 9;
 221        xfer.tx_buf = &config->sin_tonep1[0];
 222
 223        spi_message_init(&msg);
 224        spi_message_add_tail(&xfer, &msg);
 225        ret = spi_sync(st->sdev, &msg);
 226        if (ret)
 227                goto error_ret;
 228
 229        xfer.len = 9;
 230        xfer.tx_buf = &config->sin_tonep2[0];
 231
 232        spi_message_init(&msg);
 233        spi_message_add_tail(&xfer, &msg);
 234        ret = spi_sync(st->sdev, &msg);
 235        if (ret)
 236                goto error_ret;
 237        xfer.len = 9;
 238        xfer.tx_buf = &config->sin_tonep3[0];
 239
 240        spi_message_init(&msg);
 241        spi_message_add_tail(&xfer, &msg);
 242        ret = spi_sync(st->sdev, &msg);
 243        if (ret)
 244                goto error_ret;
 245
 246        xfer.len = 9;
 247        xfer.tx_buf = &config->sin_tonep4[0];
 248
 249        spi_message_init(&msg);
 250        spi_message_add_tail(&xfer, &msg);
 251        ret = spi_sync(st->sdev, &msg);
 252        if (ret)
 253                goto error_ret;
 254
 255        xfer.len = 9;
 256        xfer.tx_buf = &config->sin_tonep5[0];
 257
 258        spi_message_init(&msg);
 259        spi_message_add_tail(&xfer, &msg);
 260        ret = spi_sync(st->sdev, &msg);
 261        if (ret)
 262                goto error_ret;
 263
 264        xfer.len = 9;
 265        xfer.tx_buf = &config->sin_tonep6[0];
 266
 267        spi_message_init(&msg);
 268        spi_message_add_tail(&xfer, &msg);
 269        ret = spi_sync(st->sdev, &msg);
 270        if (ret)
 271                goto error_ret;
 272
 273        xfer.len = 9;
 274        xfer.tx_buf = &config->sin_tonep7[0];
 275
 276        spi_message_init(&msg);
 277        spi_message_add_tail(&xfer, &msg);
 278        ret = spi_sync(st->sdev, &msg);
 279        if (ret)
 280                goto error_ret;
 281error_ret:
 282        mutex_unlock(&st->lock);
 283
 284        return ret ? ret : len;
 285}
 286
 287static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0);
 288
 289static void ad9910_init(struct ad9910_state *st)
 290{
 291        struct spi_message msg;
 292        struct spi_transfer xfer;
 293        int ret;
 294        u8 cfr[5];
 295
 296        cfr[0] = CFR1;
 297        cfr[1] = 0;
 298        cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP;
 299        cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR;
 300        cfr[4] = 0;
 301
 302        mutex_lock(&st->lock);
 303
 304        xfer.len = 5;
 305        xfer.tx_buf = &cfr;
 306
 307        spi_message_init(&msg);
 308        spi_message_add_tail(&xfer, &msg);
 309        ret = spi_sync(st->sdev, &msg);
 310        if (ret)
 311                goto error_ret;
 312
 313        cfr[0] = CFR2;
 314        cfr[1] = ENA_AMP;
 315        cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD;
 316        cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB;
 317        cfr[4] = PARA_ENA;
 318
 319        xfer.len = 5;
 320        xfer.tx_buf = &cfr;
 321
 322        spi_message_init(&msg);
 323        spi_message_add_tail(&xfer, &msg);
 324        ret = spi_sync(st->sdev, &msg);
 325        if (ret)
 326                goto error_ret;
 327
 328        cfr[0] = CFR3;
 329        cfr[1] = PLL_ENA;
 330        cfr[2] = 0;
 331        cfr[3] = REFCLK_RST | REFCLK_BYP;
 332        cfr[4] = 0;
 333
 334        xfer.len = 5;
 335        xfer.tx_buf = &cfr;
 336
 337        spi_message_init(&msg);
 338        spi_message_add_tail(&xfer, &msg);
 339        ret = spi_sync(st->sdev, &msg);
 340        if (ret)
 341                goto error_ret;
 342
 343error_ret:
 344        mutex_unlock(&st->lock);
 345
 346
 347
 348}
 349
 350static struct attribute *ad9910_attributes[] = {
 351        &iio_dev_attr_dds.dev_attr.attr,
 352        NULL,
 353};
 354
 355static const struct attribute_group ad9910_attribute_group = {
 356        .attrs = ad9910_attributes,
 357};
 358
 359static const struct iio_info ad9910_info = {
 360        .attrs = &ad9910_attribute_group,
 361        .driver_module = THIS_MODULE,
 362};
 363
 364static int __devinit ad9910_probe(struct spi_device *spi)
 365{
 366        struct ad9910_state *st;
 367        struct iio_dev *idev;
 368        int ret = 0;
 369
 370        idev = iio_allocate_device(sizeof(*st));
 371        if (idev == NULL) {
 372                ret = -ENOMEM;
 373                goto error_ret;
 374        }
 375        spi_set_drvdata(spi, idev);
 376        st = iio_priv(idev);
 377        mutex_init(&st->lock);
 378        st->sdev = spi;
 379
 380        idev->dev.parent = &spi->dev;
 381        idev->info = &ad9910_info;
 382        idev->modes = INDIO_DIRECT_MODE;
 383
 384        ret = iio_device_register(idev);
 385        if (ret)
 386                goto error_free_dev;
 387        spi->max_speed_hz = 2000000;
 388        spi->mode = SPI_MODE_3;
 389        spi->bits_per_word = 8;
 390        spi_setup(spi);
 391        ad9910_init(st);
 392        return 0;
 393
 394error_free_dev:
 395        iio_free_device(idev);
 396error_ret:
 397        return ret;
 398}
 399
 400static int __devexit ad9910_remove(struct spi_device *spi)
 401{
 402        iio_device_unregister(spi_get_drvdata(spi));
 403        iio_free_device(spi_get_drvdata(spi));
 404
 405        return 0;
 406}
 407
 408static struct spi_driver ad9910_driver = {
 409        .driver = {
 410                .name = DRV_NAME,
 411                .owner = THIS_MODULE,
 412        },
 413        .probe = ad9910_probe,
 414        .remove = __devexit_p(ad9910_remove),
 415};
 416module_spi_driver(ad9910_driver);
 417
 418MODULE_AUTHOR("Cliff Cai");
 419MODULE_DESCRIPTION("Analog Devices ad9910 driver");
 420MODULE_LICENSE("GPL v2");
 421MODULE_ALIAS("spi:" DRV_NAME);
 422