aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/ad525x_dpot-spi.c
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2010-05-24 17:33:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 11:07:04 -0400
commit6c536e4ce8edd61fdc4ab68e19ae164a54fc958f (patch)
tree1d09ef6de4c04a4bd597b060d668fce2eac14681 /drivers/misc/ad525x_dpot-spi.c
parent0c53b9fbcca8870e4f4b248f4ed5fdadd43a01b6 (diff)
ad525x_dpot: add support for SPI parts
Split the bus logic out into separate files so that we can handle I2C and SPI busses independently. The new SPI bus logic brings in support for a lot more parts: AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203, AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235, AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293, AD7376, AD8400, AD8402, AD8403, ADN2850 [randy.dunlap@oracle.com: fix ad525X_dpot build] Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/ad525x_dpot-spi.c')
-rw-r--r--drivers/misc/ad525x_dpot-spi.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
new file mode 100644
index 00000000000..b8c6df9c843
--- /dev/null
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -0,0 +1,172 @@
1/*
2 * Driver for the Analog Devices digital potentiometers (SPI bus)
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/spi/spi.h>
10#include <linux/module.h>
11
12#include "ad525x_dpot.h"
13
14static const struct ad_dpot_id ad_dpot_spi_devlist[] = {
15 {.name = "ad5160", .devid = AD5160_ID},
16 {.name = "ad5161", .devid = AD5161_ID},
17 {.name = "ad5162", .devid = AD5162_ID},
18 {.name = "ad5165", .devid = AD5165_ID},
19 {.name = "ad5200", .devid = AD5200_ID},
20 {.name = "ad5201", .devid = AD5201_ID},
21 {.name = "ad5203", .devid = AD5203_ID},
22 {.name = "ad5204", .devid = AD5204_ID},
23 {.name = "ad5206", .devid = AD5206_ID},
24 {.name = "ad5207", .devid = AD5207_ID},
25 {.name = "ad5231", .devid = AD5231_ID},
26 {.name = "ad5232", .devid = AD5232_ID},
27 {.name = "ad5233", .devid = AD5233_ID},
28 {.name = "ad5235", .devid = AD5235_ID},
29 {.name = "ad5260", .devid = AD5260_ID},
30 {.name = "ad5262", .devid = AD5262_ID},
31 {.name = "ad5263", .devid = AD5263_ID},
32 {.name = "ad5290", .devid = AD5290_ID},
33 {.name = "ad5291", .devid = AD5291_ID},
34 {.name = "ad5292", .devid = AD5292_ID},
35 {.name = "ad5293", .devid = AD5293_ID},
36 {.name = "ad7376", .devid = AD7376_ID},
37 {.name = "ad8400", .devid = AD8400_ID},
38 {.name = "ad8402", .devid = AD8402_ID},
39 {.name = "ad8403", .devid = AD8403_ID},
40 {.name = "adn2850", .devid = ADN2850_ID},
41 {}
42};
43
44/* ------------------------------------------------------------------------- */
45
46/* SPI bus functions */
47static int write8(void *client, u8 val)
48{
49 u8 data = val;
50 return spi_write(client, &data, 1);
51}
52
53static int write16(void *client, u8 reg, u8 val)
54{
55 u8 data[2] = {reg, val};
56 return spi_write(client, data, 1);
57}
58
59static int write24(void *client, u8 reg, u16 val)
60{
61 u8 data[3] = {reg, val >> 8, val};
62 return spi_write(client, data, 1);
63}
64
65static int read8(void *client)
66{
67 int ret;
68 u8 data;
69 ret = spi_read(client, &data, 1);
70 if (ret < 0)
71 return ret;
72
73 return data;
74}
75
76static int read16(void *client, u8 reg)
77{
78 int ret;
79 u8 buf_rx[2];
80
81 write16(client, reg, 0);
82 ret = spi_read(client, buf_rx, 2);
83 if (ret < 0)
84 return ret;
85
86 return (buf_rx[0] << 8) | buf_rx[1];
87}
88
89static int read24(void *client, u8 reg)
90{
91 int ret;
92 u8 buf_rx[3];
93
94 write24(client, reg, 0);
95 ret = spi_read(client, buf_rx, 3);
96 if (ret < 0)
97 return ret;
98
99 return (buf_rx[1] << 8) | buf_rx[2];
100}
101
102static const struct ad_dpot_bus_ops bops = {
103 .read_d8 = read8,
104 .read_r8d8 = read16,
105 .read_r8d16 = read24,
106 .write_d8 = write8,
107 .write_r8d8 = write16,
108 .write_r8d16 = write24,
109};
110
111static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id,
112 char *name)
113{
114 while (id->name && id->name[0]) {
115 if (strcmp(name, id->name) == 0)
116 return id;
117 id++;
118 }
119 return NULL;
120}
121
122static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
123{
124 char *name = spi->dev.platform_data;
125 const struct ad_dpot_id *dpot_id;
126
127 struct ad_dpot_bus_data bdata = {
128 .client = spi,
129 .bops = &bops,
130 };
131
132 dpot_id = dpot_match_id(ad_dpot_spi_devlist, name);
133
134 if (dpot_id == NULL) {
135 dev_err(&spi->dev, "%s not in supported device list", name);
136 return -ENODEV;
137 }
138
139 return ad_dpot_probe(&spi->dev, &bdata, dpot_id);
140}
141
142static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
143{
144 return ad_dpot_remove(&spi->dev);
145}
146
147static struct spi_driver ad_dpot_spi_driver = {
148 .driver = {
149 .name = "ad_dpot",
150 .bus = &spi_bus_type,
151 .owner = THIS_MODULE,
152 },
153 .probe = ad_dpot_spi_probe,
154 .remove = __devexit_p(ad_dpot_spi_remove),
155};
156
157static int __init ad_dpot_spi_init(void)
158{
159 return spi_register_driver(&ad_dpot_spi_driver);
160}
161module_init(ad_dpot_spi_init);
162
163static void __exit ad_dpot_spi_exit(void)
164{
165 spi_unregister_driver(&ad_dpot_spi_driver);
166}
167module_exit(ad_dpot_spi_exit);
168
169MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
170MODULE_DESCRIPTION("digital potentiometer SPI bus driver");
171MODULE_LICENSE("GPL");
172MODULE_ALIAS("spi:ad_dpot");