linux/drivers/staging/iio/frequency/ad9852.c
<<
>>
Prefs
   1/*
   2 * Driver for ADI Direct Digital Synthesis ad9852
   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 <linux/iio/iio.h>
  20#include <linux/iio/sysfs.h>
  21
  22#define DRV_NAME "ad9852"
  23
  24#define addr_phaad1 0x0
  25#define addr_phaad2 0x1
  26#define addr_fretu1 0x2
  27#define addr_fretu2 0x3
  28#define addr_delfre 0x4
  29#define addr_updclk 0x5
  30#define addr_ramclk 0x6
  31#define addr_contrl 0x7
  32#define addr_optskm 0x8
  33#define addr_optskr 0xa
  34#define addr_dacctl 0xb
  35
  36#define COMPPD          (1 << 4)
  37#define REFMULT2        (1 << 2)
  38#define BYPPLL          (1 << 5)
  39#define PLLRANG         (1 << 6)
  40#define IEUPCLK         (1)
  41#define OSKEN           (1 << 5)
  42
  43#define read_bit        (1 << 7)
  44
  45/* Register format: 1 byte addr + value */
  46struct ad9852_config {
  47        u8 phajst0[3];
  48        u8 phajst1[3];
  49        u8 fretun1[6];
  50        u8 fretun2[6];
  51        u8 dltafre[6];
  52        u8 updtclk[5];
  53        u8 ramprat[4];
  54        u8 control[5];
  55        u8 outpskm[3];
  56        u8 outpskr[2];
  57        u8 daccntl[3];
  58};
  59
  60struct ad9852_state {
  61        struct mutex lock;
  62        struct spi_device *sdev;
  63};
  64
  65static ssize_t ad9852_set_parameter(struct device *dev,
  66                                        struct device_attribute *attr,
  67                                        const char *buf,
  68                                        size_t len)
  69{
  70        struct spi_message msg;
  71        struct spi_transfer xfer;
  72        int ret;
  73        struct ad9852_config *config = (struct ad9852_config *)buf;
  74        struct iio_dev *idev = dev_to_iio_dev(dev);
  75        struct ad9852_state *st = iio_priv(idev);
  76
  77        xfer.len = 3;
  78        xfer.tx_buf = &config->phajst0[0];
  79        mutex_lock(&st->lock);
  80
  81        spi_message_init(&msg);
  82        spi_message_add_tail(&xfer, &msg);
  83        ret = spi_sync(st->sdev, &msg);
  84        if (ret)
  85                goto error_ret;
  86
  87        xfer.len = 3;
  88        xfer.tx_buf = &config->phajst1[0];
  89
  90        spi_message_init(&msg);
  91        spi_message_add_tail(&xfer, &msg);
  92        ret = spi_sync(st->sdev, &msg);
  93        if (ret)
  94                goto error_ret;
  95
  96        xfer.len = 6;
  97        xfer.tx_buf = &config->fretun1[0];
  98
  99        spi_message_init(&msg);
 100        spi_message_add_tail(&xfer, &msg);
 101        ret = spi_sync(st->sdev, &msg);
 102        if (ret)
 103                goto error_ret;
 104
 105        xfer.len = 6;
 106        xfer.tx_buf = &config->fretun2[0];
 107
 108        spi_message_init(&msg);
 109        spi_message_add_tail(&xfer, &msg);
 110        ret = spi_sync(st->sdev, &msg);
 111        if (ret)
 112                goto error_ret;
 113
 114        xfer.len = 6;
 115        xfer.tx_buf = &config->dltafre[0];
 116
 117        spi_message_init(&msg);
 118        spi_message_add_tail(&xfer, &msg);
 119        ret = spi_sync(st->sdev, &msg);
 120        if (ret)
 121                goto error_ret;
 122
 123        xfer.len = 5;
 124        xfer.tx_buf = &config->updtclk[0];
 125
 126        spi_message_init(&msg);
 127        spi_message_add_tail(&xfer, &msg);
 128        ret = spi_sync(st->sdev, &msg);
 129        if (ret)
 130                goto error_ret;
 131
 132        xfer.len = 4;
 133        xfer.tx_buf = &config->ramprat[0];
 134
 135        spi_message_init(&msg);
 136        spi_message_add_tail(&xfer, &msg);
 137        ret = spi_sync(st->sdev, &msg);
 138        if (ret)
 139                goto error_ret;
 140
 141        xfer.len = 5;
 142        xfer.tx_buf = &config->control[0];
 143
 144        spi_message_init(&msg);
 145        spi_message_add_tail(&xfer, &msg);
 146        ret = spi_sync(st->sdev, &msg);
 147        if (ret)
 148                goto error_ret;
 149
 150        xfer.len = 3;
 151        xfer.tx_buf = &config->outpskm[0];
 152
 153        spi_message_init(&msg);
 154        spi_message_add_tail(&xfer, &msg);
 155        ret = spi_sync(st->sdev, &msg);
 156        if (ret)
 157                goto error_ret;
 158
 159        xfer.len = 2;
 160        xfer.tx_buf = &config->outpskr[0];
 161
 162        spi_message_init(&msg);
 163        spi_message_add_tail(&xfer, &msg);
 164        ret = spi_sync(st->sdev, &msg);
 165        if (ret)
 166                goto error_ret;
 167
 168        xfer.len = 3;
 169        xfer.tx_buf = &config->daccntl[0];
 170
 171        spi_message_init(&msg);
 172        spi_message_add_tail(&xfer, &msg);
 173        ret = spi_sync(st->sdev, &msg);
 174        if (ret)
 175                goto error_ret;
 176error_ret:
 177        mutex_unlock(&st->lock);
 178
 179        return ret ? ret : len;
 180}
 181
 182static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0);
 183
 184static void ad9852_init(struct ad9852_state *st)
 185{
 186        struct spi_transfer xfer;
 187        int ret;
 188        u8 config[5];
 189
 190        config[0] = addr_contrl;
 191        config[1] = COMPPD;
 192        config[2] = REFMULT2 | BYPPLL | PLLRANG;
 193        config[3] = IEUPCLK;
 194        config[4] = OSKEN;
 195
 196        mutex_lock(&st->lock);
 197
 198        xfer.len = 5;
 199        xfer.tx_buf = &config;
 200
 201        ret = spi_sync_transfer(st->sdev, &xfer, 1);
 202        if (ret)
 203                goto error_ret;
 204
 205error_ret:
 206        mutex_unlock(&st->lock);
 207
 208
 209
 210}
 211
 212static struct attribute *ad9852_attributes[] = {
 213        &iio_dev_attr_dds.dev_attr.attr,
 214        NULL,
 215};
 216
 217static const struct attribute_group ad9852_attribute_group = {
 218        .attrs = ad9852_attributes,
 219};
 220
 221static const struct iio_info ad9852_info = {
 222        .attrs = &ad9852_attribute_group,
 223        .driver_module = THIS_MODULE,
 224};
 225
 226static int ad9852_probe(struct spi_device *spi)
 227{
 228        struct ad9852_state *st;
 229        struct iio_dev *idev;
 230        int ret = 0;
 231
 232        idev = iio_device_alloc(sizeof(*st));
 233        if (idev == NULL) {
 234                ret = -ENOMEM;
 235                goto error_ret;
 236        }
 237        st = iio_priv(idev);
 238        spi_set_drvdata(spi, idev);
 239        mutex_init(&st->lock);
 240        st->sdev = spi;
 241
 242        idev->dev.parent = &spi->dev;
 243        idev->info = &ad9852_info;
 244        idev->modes = INDIO_DIRECT_MODE;
 245
 246        ret = iio_device_register(idev);
 247        if (ret)
 248                goto error_free_dev;
 249        spi->max_speed_hz = 2000000;
 250        spi->mode = SPI_MODE_3;
 251        spi->bits_per_word = 8;
 252        spi_setup(spi);
 253        ad9852_init(st);
 254
 255        return 0;
 256
 257error_free_dev:
 258        iio_device_free(idev);
 259
 260error_ret:
 261        return ret;
 262}
 263
 264static int ad9852_remove(struct spi_device *spi)
 265{
 266        iio_device_unregister(spi_get_drvdata(spi));
 267        iio_device_free(spi_get_drvdata(spi));
 268
 269        return 0;
 270}
 271
 272static struct spi_driver ad9852_driver = {
 273        .driver = {
 274                .name = DRV_NAME,
 275                .owner = THIS_MODULE,
 276        },
 277        .probe = ad9852_probe,
 278        .remove = ad9852_remove,
 279};
 280module_spi_driver(ad9852_driver);
 281
 282MODULE_AUTHOR("Cliff Cai");
 283MODULE_DESCRIPTION("Analog Devices ad9852 driver");
 284MODULE_LICENSE("GPL v2");
 285MODULE_ALIAS("spi:" DRV_NAME);
 286