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
  18#include "../iio.h"
  19#include "../sysfs.h"
  20
  21#define DRV_NAME "ad9910"
  22
  23#define CFR1 0x0
  24#define CFR2 0x1
  25#define CFR3 0x2
  26
  27#define AUXDAC 0x3
  28#define IOUPD 0x4
  29#define FTW 0x7
  30#define POW 0x8
  31#define ASF 0x9
  32#define MULTC 0x0A
  33#define DIG_RAMPL 0x0B
  34#define DIG_RAMPS 0x0C
  35#define DIG_RAMPR 0x0D
  36#define SIN_TONEP0 0x0E
  37#define SIN_TONEP1 0x0F
  38#define SIN_TONEP2 0x10
  39#define SIN_TONEP3 0x11
  40#define SIN_TONEP4 0x12
  41#define SIN_TONEP5 0x13
  42#define SIN_TONEP6 0x14
  43#define SIN_TONEP7 0x15
  44
  45#define RAM_ENABLE      (1 << 7)
  46
  47#define MANUAL_OSK      (1 << 7)
  48#define INVSIC          (1 << 6)
  49#define DDS_SINEOP      (1)
  50
  51#define AUTO_OSK        (1)
  52#define OSKEN           (1 << 1)
  53#define LOAD_ARR        (1 << 2)
  54#define CLR_PHA         (1 << 3)
  55#define CLR_DIG         (1 << 4)
  56#define ACLR_PHA        (1 << 5)
  57#define ACLR_DIG        (1 << 6)
  58#define LOAD_LRR        (1 << 7)
  59
  60#define LSB_FST         (1)
  61#define SDIO_IPT        (1 << 1)
  62#define EXT_PWD         (1 << 3)
  63#define ADAC_PWD        (1 << 4)
  64#define REFCLK_PWD      (1 << 5)
  65#define DAC_PWD         (1 << 6)
  66#define DIG_PWD         (1 << 7)
  67
  68#define ENA_AMP         (1)
  69#define READ_FTW        (1)
  70#define DIGR_LOW        (1 << 1)
  71#define DIGR_HIGH       (1 << 2)
  72#define DIGR_ENA        (1 << 3)
  73#define SYNCCLK_ENA     (1 << 6)
  74#define ITER_IOUPD      (1 << 7)
  75
  76#define TX_ENA          (1 << 1)
  77#define PDCLK_INV       (1 << 2)
  78#define PDCLK_ENB       (1 << 3)
  79
  80#define PARA_ENA        (1 << 4)
  81#define SYNC_DIS        (1 << 5)
  82#define DATA_ASS        (1 << 6)
  83#define MATCH_ENA       (1 << 7)
  84
  85#define PLL_ENA         (1)
  86#define PFD_RST         (1 << 2)
  87#define REFCLK_RST      (1 << 6)
  88#define REFCLK_BYP      (1 << 7)
  89
  90/* Register format: 1 byte addr + value */
  91struct ad9910_config {
  92        u8 auxdac[5];
  93        u8 ioupd[5];
  94        u8 ftw[5];
  95        u8 pow[3];
  96        u8 asf[5];
  97        u8 multc[5];
  98        u8 dig_rampl[9];
  99        u8 dig_ramps[9];
 100        u8 dig_rampr[5];
 101        u8 sin_tonep0[9];
 102        u8 sin_tonep1[9];
 103        u8 sin_tonep2[9];
 104        u8 sin_tonep3[9];
 105        u8 sin_tonep4[9];
 106        u8 sin_tonep5[9];
 107        u8 sin_tonep6[9];
 108        u8 sin_tonep7[9];
 109};
 110
 111struct ad9910_state {
 112        struct mutex lock;
 113        struct iio_dev *idev;
 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 = idev->dev_data;
 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        .name = DRV_NAME,
 357        .attrs = ad9910_attributes,
 358};
 359
 360static int __devinit ad9910_probe(struct spi_device *spi)
 361{
 362        struct ad9910_state *st;
 363        int ret = 0;
 364
 365        st = kzalloc(sizeof(*st), GFP_KERNEL);
 366        if (st == NULL) {
 367                ret = -ENOMEM;
 368                goto error_ret;
 369        }
 370        spi_set_drvdata(spi, st);
 371
 372        mutex_init(&st->lock);
 373        st->sdev = spi;
 374
 375        st->idev = iio_allocate_device();
 376        if (st->idev == NULL) {
 377                ret = -ENOMEM;
 378                goto error_free_st;
 379        }
 380        st->idev->dev.parent = &spi->dev;
 381        st->idev->num_interrupt_lines = 0;
 382        st->idev->event_attrs = NULL;
 383
 384        st->idev->attrs = &ad9910_attribute_group;
 385        st->idev->dev_data = (void *)(st);
 386        st->idev->driver_module = THIS_MODULE;
 387        st->idev->modes = INDIO_DIRECT_MODE;
 388
 389        ret = iio_device_register(st->idev);
 390        if (ret)
 391                goto error_free_dev;
 392        spi->max_speed_hz = 2000000;
 393        spi->mode = SPI_MODE_3;
 394        spi->bits_per_word = 8;
 395        spi_setup(spi);
 396        ad9910_init(st);
 397        return 0;
 398
 399error_free_dev:
 400        iio_free_device(st->idev);
 401error_free_st:
 402        kfree(st);
 403error_ret:
 404        return ret;
 405}
 406
 407static int __devexit ad9910_remove(struct spi_device *spi)
 408{
 409        struct ad9910_state *st = spi_get_drvdata(spi);
 410
 411        iio_device_unregister(st->idev);
 412        kfree(st);
 413
 414        return 0;
 415}
 416
 417static struct spi_driver ad9910_driver = {
 418        .driver = {
 419                .name = DRV_NAME,
 420                .owner = THIS_MODULE,
 421        },
 422        .probe = ad9910_probe,
 423        .remove = __devexit_p(ad9910_remove),
 424};
 425
 426static __init int ad9910_spi_init(void)
 427{
 428        return spi_register_driver(&ad9910_driver);
 429}
 430module_init(ad9910_spi_init);
 431
 432static __exit void ad9910_spi_exit(void)
 433{
 434        spi_unregister_driver(&ad9910_driver);
 435}
 436module_exit(ad9910_spi_exit);
 437
 438MODULE_AUTHOR("Cliff Cai");
 439MODULE_DESCRIPTION("Analog Devices ad9910 driver");
 440MODULE_LICENSE("GPL v2");
 441