Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/misc/ad525x_dpot-spi.c
15109 views
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
14
static 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
{.name = "ad5270", .devid = AD5270_ID},
42
{.name = "ad5271", .devid = AD5271_ID},
43
{}
44
};
45
46
/* ------------------------------------------------------------------------- */
47
48
/* SPI bus functions */
49
static int write8(void *client, u8 val)
50
{
51
u8 data = val;
52
return spi_write(client, &data, 1);
53
}
54
55
static int write16(void *client, u8 reg, u8 val)
56
{
57
u8 data[2] = {reg, val};
58
return spi_write(client, data, 2);
59
}
60
61
static int write24(void *client, u8 reg, u16 val)
62
{
63
u8 data[3] = {reg, val >> 8, val};
64
return spi_write(client, data, 3);
65
}
66
67
static int read8(void *client)
68
{
69
int ret;
70
u8 data;
71
ret = spi_read(client, &data, 1);
72
if (ret < 0)
73
return ret;
74
75
return data;
76
}
77
78
static int read16(void *client, u8 reg)
79
{
80
int ret;
81
u8 buf_rx[2];
82
83
write16(client, reg, 0);
84
ret = spi_read(client, buf_rx, 2);
85
if (ret < 0)
86
return ret;
87
88
return (buf_rx[0] << 8) | buf_rx[1];
89
}
90
91
static int read24(void *client, u8 reg)
92
{
93
int ret;
94
u8 buf_rx[3];
95
96
write24(client, reg, 0);
97
ret = spi_read(client, buf_rx, 3);
98
if (ret < 0)
99
return ret;
100
101
return (buf_rx[1] << 8) | buf_rx[2];
102
}
103
104
static const struct ad_dpot_bus_ops bops = {
105
.read_d8 = read8,
106
.read_r8d8 = read16,
107
.read_r8d16 = read24,
108
.write_d8 = write8,
109
.write_r8d8 = write16,
110
.write_r8d16 = write24,
111
};
112
113
static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id,
114
char *name)
115
{
116
while (id->name && id->name[0]) {
117
if (strcmp(name, id->name) == 0)
118
return id;
119
id++;
120
}
121
return NULL;
122
}
123
124
static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
125
{
126
char *name = spi->dev.platform_data;
127
const struct ad_dpot_id *dpot_id;
128
129
struct ad_dpot_bus_data bdata = {
130
.client = spi,
131
.bops = &bops,
132
};
133
134
dpot_id = dpot_match_id(ad_dpot_spi_devlist, name);
135
136
if (dpot_id == NULL) {
137
dev_err(&spi->dev, "%s not in supported device list", name);
138
return -ENODEV;
139
}
140
141
return ad_dpot_probe(&spi->dev, &bdata, dpot_id);
142
}
143
144
static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
145
{
146
return ad_dpot_remove(&spi->dev);
147
}
148
149
static struct spi_driver ad_dpot_spi_driver = {
150
.driver = {
151
.name = "ad_dpot",
152
.bus = &spi_bus_type,
153
.owner = THIS_MODULE,
154
},
155
.probe = ad_dpot_spi_probe,
156
.remove = __devexit_p(ad_dpot_spi_remove),
157
};
158
159
static int __init ad_dpot_spi_init(void)
160
{
161
return spi_register_driver(&ad_dpot_spi_driver);
162
}
163
module_init(ad_dpot_spi_init);
164
165
static void __exit ad_dpot_spi_exit(void)
166
{
167
spi_unregister_driver(&ad_dpot_spi_driver);
168
}
169
module_exit(ad_dpot_spi_exit);
170
171
MODULE_AUTHOR("Michael Hennerich <[email protected]>");
172
MODULE_DESCRIPTION("digital potentiometer SPI bus driver");
173
MODULE_LICENSE("GPL");
174
MODULE_ALIAS("spi:ad_dpot");
175
176