PageRenderTime 83ms CodeModel.GetById 30ms app.highlight 11ms RepoModel.GetById 40ms app.codeStats 0ms

/drivers/staging/iio/resolver/ad2s120x.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 177 lines | 136 code | 26 blank | 15 comment | 9 complexity | b6cfebde4352d3323edb33e28910a036 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/*
  2 * ad2s120x.c simple support for the ADI Resolver to Digital Converters: AD2S1200/1205
  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/delay.h>
 18#include <linux/gpio.h>
 19
 20#include "../iio.h"
 21#include "../sysfs.h"
 22
 23#define DRV_NAME "ad2s120x"
 24
 25/* input pin sample and rdvel is controlled by driver */
 26#define AD2S120X_PN	2
 27
 28/* input clock on serial interface */
 29#define AD2S120X_HZ	8192000
 30/* clock period in nano second */
 31#define AD2S120X_TSCLK	(1000000000/AD2S120X_HZ)
 32
 33struct ad2s120x_state {
 34	struct mutex lock;
 35	struct spi_device *sdev;
 36	int sample;
 37	int rdvel;
 38	u8 rx[2] ____cacheline_aligned;
 39};
 40
 41static ssize_t ad2s120x_show_val(struct device *dev,
 42			struct device_attribute *attr, char *buf)
 43{
 44	int ret = 0;
 45	ssize_t len = 0;
 46	u16 pos;
 47	s16 vel;
 48	u8 status;
 49	struct ad2s120x_state *st = iio_priv(dev_get_drvdata(dev));
 50	struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
 51
 52	mutex_lock(&st->lock);
 53
 54	gpio_set_value(st->sample, 0);
 55	/* delay (6 * AD2S120X_TSCLK + 20) nano seconds */
 56	udelay(1);
 57	gpio_set_value(st->sample, 1);
 58	gpio_set_value(st->rdvel, iattr->address);
 59	ret = spi_read(st->sdev, st->rx, 2);
 60	if (ret < 0)
 61		goto error_ret;
 62	status = st->rx[1];
 63	if (iattr->address)
 64		pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
 65	else {
 66		vel = (st->rx[0] & 0x80) ? 0xf000 : 0;
 67		vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
 68	}
 69	len = sprintf(buf, "%d %c%c%c%c ", iattr->address ? pos : vel,
 70				(status & 0x8) ? 'P' : 'V',
 71				(status & 0x4) ? 'd' : '_',
 72				(status & 0x2) ? 'l' : '_',
 73				(status & 0x1) ? '1' : '0');
 74error_ret:
 75	/* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */
 76	udelay(1);
 77	mutex_unlock(&st->lock);
 78
 79	return ret ? ret : len;
 80}
 81
 82static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s120x_show_val, NULL, 1);
 83static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s120x_show_val, NULL, 0);
 84
 85static struct attribute *ad2s120x_attributes[] = {
 86	&iio_dev_attr_pos.dev_attr.attr,
 87	&iio_dev_attr_vel.dev_attr.attr,
 88	NULL,
 89};
 90
 91static const struct attribute_group ad2s120x_attribute_group = {
 92	.attrs = ad2s120x_attributes,
 93};
 94
 95static const struct iio_info ad2s120x_info = {
 96	.attrs = &ad2s120x_attribute_group,
 97	.driver_module = THIS_MODULE,
 98};
 99
100static int __devinit ad2s120x_probe(struct spi_device *spi)
101{
102	struct ad2s120x_state *st;
103	struct iio_dev *indio_dev;
104	int pn, ret = 0;
105	unsigned short *pins = spi->dev.platform_data;
106
107	for (pn = 0; pn < AD2S120X_PN; pn++)
108		if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) {
109			pr_err("%s: request gpio pin %d failed\n",
110						DRV_NAME, pins[pn]);
111			goto error_ret;
112		}
113	indio_dev = iio_allocate_device(sizeof(*st));
114	if (indio_dev == NULL) {
115		ret = -ENOMEM;
116		goto error_ret;
117	}
118	spi_set_drvdata(spi, indio_dev);
119	st = iio_priv(indio_dev);
120	mutex_init(&st->lock);
121	st->sdev = spi;
122	st->sample = pins[0];
123	st->rdvel = pins[1];
124
125	indio_dev->dev.parent = &spi->dev;
126	indio_dev->info = &ad2s120x_info;
127	indio_dev->modes = INDIO_DIRECT_MODE;
128
129	ret = iio_device_register(indio_dev);
130	if (ret)
131		goto error_free_dev;
132
133	spi->max_speed_hz = AD2S120X_HZ;
134	spi->mode = SPI_MODE_3;
135	spi_setup(spi);
136
137	return 0;
138
139error_free_dev:
140	iio_free_device(indio_dev);
141error_ret:
142	for (--pn; pn >= 0; pn--)
143		gpio_free(pins[pn]);
144	return ret;
145}
146
147static int __devexit ad2s120x_remove(struct spi_device *spi)
148{
149	iio_device_unregister(spi_get_drvdata(spi));
150
151	return 0;
152}
153
154static struct spi_driver ad2s120x_driver = {
155	.driver = {
156		.name = DRV_NAME,
157		.owner = THIS_MODULE,
158	},
159	.probe = ad2s120x_probe,
160	.remove = __devexit_p(ad2s120x_remove),
161};
162
163static __init int ad2s120x_spi_init(void)
164{
165	return spi_register_driver(&ad2s120x_driver);
166}
167module_init(ad2s120x_spi_init);
168
169static __exit void ad2s120x_spi_exit(void)
170{
171	spi_unregister_driver(&ad2s120x_driver);
172}
173module_exit(ad2s120x_spi_exit);
174
175MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>");
176MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver");
177MODULE_LICENSE("GPL v2");