linux/drivers/staging/iio/frequency/ad9850.c
<<
>>
Prefs
   1/*
   2 * Driver for ADI Direct Digital Synthesis ad9850
   3 *
   4 * Copyright (c) 2010-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 "ad9850"
  23
  24#define value_mask (u16)0xf000
  25#define addr_shift 12
  26
  27/* Register format: 4 bits addr + 12 bits value */
  28struct ad9850_config {
  29        u8 control[5];
  30};
  31
  32struct ad9850_state {
  33        struct mutex lock;
  34        struct spi_device *sdev;
  35};
  36
  37static ssize_t ad9850_set_parameter(struct device *dev,
  38                                        struct device_attribute *attr,
  39                                        const char *buf,
  40                                        size_t len)
  41{
  42        struct spi_message msg;
  43        struct spi_transfer xfer;
  44        int ret;
  45        struct ad9850_config *config = (struct ad9850_config *)buf;
  46        struct iio_dev *idev = dev_to_iio_dev(dev);
  47        struct ad9850_state *st = iio_priv(idev);
  48
  49        xfer.len = len;
  50        xfer.tx_buf = config;
  51        mutex_lock(&st->lock);
  52
  53        spi_message_init(&msg);
  54        spi_message_add_tail(&xfer, &msg);
  55        ret = spi_sync(st->sdev, &msg);
  56        if (ret)
  57                goto error_ret;
  58error_ret:
  59        mutex_unlock(&st->lock);
  60
  61        return ret ? ret : len;
  62}
  63
  64static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9850_set_parameter, 0);
  65
  66static struct attribute *ad9850_attributes[] = {
  67        &iio_dev_attr_dds.dev_attr.attr,
  68        NULL,
  69};
  70
  71static const struct attribute_group ad9850_attribute_group = {
  72        .attrs = ad9850_attributes,
  73};
  74
  75static const struct iio_info ad9850_info = {
  76        .attrs = &ad9850_attribute_group,
  77        .driver_module = THIS_MODULE,
  78};
  79
  80static int __devinit ad9850_probe(struct spi_device *spi)
  81{
  82        struct ad9850_state *st;
  83        struct iio_dev *idev;
  84        int ret = 0;
  85
  86        idev = iio_device_alloc(sizeof(*st));
  87        if (idev == NULL) {
  88                ret = -ENOMEM;
  89                goto error_ret;
  90        }
  91        spi_set_drvdata(spi, idev);
  92        st = iio_priv(idev);
  93        mutex_init(&st->lock);
  94        st->sdev = spi;
  95
  96        idev->dev.parent = &spi->dev;
  97        idev->info = &ad9850_info;
  98        idev->modes = INDIO_DIRECT_MODE;
  99
 100        ret = iio_device_register(idev);
 101        if (ret)
 102                goto error_free_dev;
 103        spi->max_speed_hz = 2000000;
 104        spi->mode = SPI_MODE_3;
 105        spi->bits_per_word = 16;
 106        spi_setup(spi);
 107
 108        return 0;
 109
 110error_free_dev:
 111        iio_device_free(idev);
 112error_ret:
 113        return ret;
 114}
 115
 116static int __devexit ad9850_remove(struct spi_device *spi)
 117{
 118        iio_device_unregister(spi_get_drvdata(spi));
 119        iio_device_free(spi_get_drvdata(spi));
 120
 121        return 0;
 122}
 123
 124static struct spi_driver ad9850_driver = {
 125        .driver = {
 126                .name = DRV_NAME,
 127                .owner = THIS_MODULE,
 128        },
 129        .probe = ad9850_probe,
 130        .remove = __devexit_p(ad9850_remove),
 131};
 132module_spi_driver(ad9850_driver);
 133
 134MODULE_AUTHOR("Cliff Cai");
 135MODULE_DESCRIPTION("Analog Devices ad9850 driver");
 136MODULE_LICENSE("GPL v2");
 137MODULE_ALIAS("spi:" DRV_NAME);
 138