linux/drivers/staging/iio/dds/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
  18#include "../iio.h"
  19#include "../sysfs.h"
  20
  21#define DRV_NAME "ad9850"
  22
  23#define value_mask (u16)0xf000
  24#define addr_shift 12
  25
  26/* Register format: 4 bits addr + 12 bits value */
  27struct ad9850_config {
  28        u8 control[5];
  29};
  30
  31struct ad9850_state {
  32        struct mutex lock;
  33        struct iio_dev *idev;
  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_get_drvdata(dev);
  47        struct ad9850_state *st = idev->dev_data;
  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        .name = DRV_NAME,
  73        .attrs = ad9850_attributes,
  74};
  75
  76static int __devinit ad9850_probe(struct spi_device *spi)
  77{
  78        struct ad9850_state *st;
  79        int ret = 0;
  80
  81        st = kzalloc(sizeof(*st), GFP_KERNEL);
  82        if (st == NULL) {
  83                ret = -ENOMEM;
  84                goto error_ret;
  85        }
  86        spi_set_drvdata(spi, st);
  87
  88        mutex_init(&st->lock);
  89        st->sdev = spi;
  90
  91        st->idev = iio_allocate_device();
  92        if (st->idev == NULL) {
  93                ret = -ENOMEM;
  94                goto error_free_st;
  95        }
  96        st->idev->dev.parent = &spi->dev;
  97        st->idev->num_interrupt_lines = 0;
  98        st->idev->event_attrs = NULL;
  99
 100        st->idev->attrs = &ad9850_attribute_group;
 101        st->idev->dev_data = (void *)(st);
 102        st->idev->driver_module = THIS_MODULE;
 103        st->idev->modes = INDIO_DIRECT_MODE;
 104
 105        ret = iio_device_register(st->idev);
 106        if (ret)
 107                goto error_free_dev;
 108        spi->max_speed_hz = 2000000;
 109        spi->mode = SPI_MODE_3;
 110        spi->bits_per_word = 16;
 111        spi_setup(spi);
 112
 113        return 0;
 114
 115error_free_dev:
 116        iio_free_device(st->idev);
 117error_free_st:
 118        kfree(st);
 119error_ret:
 120        return ret;
 121}
 122
 123static int __devexit ad9850_remove(struct spi_device *spi)
 124{
 125        struct ad9850_state *st = spi_get_drvdata(spi);
 126
 127        iio_device_unregister(st->idev);
 128        kfree(st);
 129
 130        return 0;
 131}
 132
 133static struct spi_driver ad9850_driver = {
 134        .driver = {
 135                .name = DRV_NAME,
 136                .owner = THIS_MODULE,
 137        },
 138        .probe = ad9850_probe,
 139        .remove = __devexit_p(ad9850_remove),
 140};
 141
 142static __init int ad9850_spi_init(void)
 143{
 144        return spi_register_driver(&ad9850_driver);
 145}
 146module_init(ad9850_spi_init);
 147
 148static __exit void ad9850_spi_exit(void)
 149{
 150        spi_unregister_driver(&ad9850_driver);
 151}
 152module_exit(ad9850_spi_exit);
 153
 154MODULE_AUTHOR("Cliff Cai");
 155MODULE_DESCRIPTION("Analog Devices ad9850 driver");
 156MODULE_LICENSE("GPL v2");
 157