Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
[deliverable/linux.git] / drivers / mfd / wm831x-spi.c
CommitLineData
2aa13b9e
MB
1/*
2 * wm831x-spi.c -- SPI access for Wolfson WM831x PMICs
3 *
4 * Copyright 2009,2010 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
87d1906d 17#include <linux/pm.h>
2aa13b9e
MB
18#include <linux/spi/spi.h>
19
20#include <linux/mfd/wm831x/core.h>
21
22static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
23 int bytes, void *dest)
24{
25 u16 tx_val;
26 u16 *d = dest;
27 int r, ret;
28
29 /* Go register at a time */
30 for (r = reg; r < reg + (bytes / 2); r++) {
31 tx_val = r | 0x8000;
32
33 ret = spi_write_then_read(wm831x->control_data,
34 (u8 *)&tx_val, 2, (u8 *)d, 2);
35 if (ret != 0)
36 return ret;
37
38 *d = be16_to_cpu(*d);
39
40 d++;
41 }
42
43 return 0;
44}
45
46static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
47 int bytes, void *src)
48{
49 struct spi_device *spi = wm831x->control_data;
50 u16 *s = src;
51 u16 data[2];
52 int ret, r;
53
54 /* Go register at a time */
55 for (r = reg; r < reg + (bytes / 2); r++) {
56 data[0] = r;
57 data[1] = *s++;
58
59 ret = spi_write(spi, (char *)&data, sizeof(data));
60 if (ret != 0)
61 return ret;
62 }
63
64 return 0;
65}
66
67static int __devinit wm831x_spi_probe(struct spi_device *spi)
68{
69 struct wm831x *wm831x;
70 enum wm831x_parent type;
71
72 /* Currently SPI support for ID tables is unmerged, we're faking it */
73 if (strcmp(spi->modalias, "wm8310") == 0)
74 type = WM8310;
75 else if (strcmp(spi->modalias, "wm8311") == 0)
76 type = WM8311;
77 else if (strcmp(spi->modalias, "wm8312") == 0)
78 type = WM8312;
79 else if (strcmp(spi->modalias, "wm8320") == 0)
80 type = WM8320;
81 else if (strcmp(spi->modalias, "wm8321") == 0)
82 type = WM8321;
83 else if (strcmp(spi->modalias, "wm8325") == 0)
84 type = WM8325;
412dc11d
MB
85 else if (strcmp(spi->modalias, "wm8326") == 0)
86 type = WM8326;
2aa13b9e
MB
87 else {
88 dev_err(&spi->dev, "Unknown device type\n");
89 return -EINVAL;
90 }
91
92 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
93 if (wm831x == NULL)
94 return -ENOMEM;
95
96 spi->bits_per_word = 16;
97 spi->mode = SPI_MODE_0;
98
99 dev_set_drvdata(&spi->dev, wm831x);
100 wm831x->dev = &spi->dev;
101 wm831x->control_data = spi;
102 wm831x->read_dev = wm831x_spi_read_device;
103 wm831x->write_dev = wm831x_spi_write_device;
104
105 return wm831x_device_init(wm831x, type, spi->irq);
106}
107
108static int __devexit wm831x_spi_remove(struct spi_device *spi)
109{
110 struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
111
112 wm831x_device_exit(wm831x);
113
114 return 0;
115}
116
87d1906d 117static int wm831x_spi_suspend(struct device *dev)
2aa13b9e 118{
87d1906d 119 struct wm831x *wm831x = dev_get_drvdata(dev);
2aa13b9e
MB
120
121 return wm831x_device_suspend(wm831x);
122}
123
87d1906d
MB
124static const struct dev_pm_ops wm831x_spi_pm = {
125 .freeze = wm831x_spi_suspend,
126 .suspend = wm831x_spi_suspend,
127};
128
2aa13b9e
MB
129static struct spi_driver wm8310_spi_driver = {
130 .driver = {
131 .name = "wm8310",
132 .bus = &spi_bus_type,
133 .owner = THIS_MODULE,
87d1906d 134 .pm = &wm831x_spi_pm,
2aa13b9e
MB
135 },
136 .probe = wm831x_spi_probe,
137 .remove = __devexit_p(wm831x_spi_remove),
2aa13b9e
MB
138};
139
140static struct spi_driver wm8311_spi_driver = {
141 .driver = {
142 .name = "wm8311",
143 .bus = &spi_bus_type,
144 .owner = THIS_MODULE,
87d1906d 145 .pm = &wm831x_spi_pm,
2aa13b9e
MB
146 },
147 .probe = wm831x_spi_probe,
148 .remove = __devexit_p(wm831x_spi_remove),
2aa13b9e
MB
149};
150
151static struct spi_driver wm8312_spi_driver = {
152 .driver = {
153 .name = "wm8312",
154 .bus = &spi_bus_type,
155 .owner = THIS_MODULE,
87d1906d 156 .pm = &wm831x_spi_pm,
2aa13b9e
MB
157 },
158 .probe = wm831x_spi_probe,
159 .remove = __devexit_p(wm831x_spi_remove),
2aa13b9e
MB
160};
161
162static struct spi_driver wm8320_spi_driver = {
163 .driver = {
164 .name = "wm8320",
165 .bus = &spi_bus_type,
166 .owner = THIS_MODULE,
87d1906d 167 .pm = &wm831x_spi_pm,
2aa13b9e
MB
168 },
169 .probe = wm831x_spi_probe,
170 .remove = __devexit_p(wm831x_spi_remove),
2aa13b9e
MB
171};
172
173static struct spi_driver wm8321_spi_driver = {
174 .driver = {
175 .name = "wm8321",
176 .bus = &spi_bus_type,
177 .owner = THIS_MODULE,
87d1906d 178 .pm = &wm831x_spi_pm,
2aa13b9e
MB
179 },
180 .probe = wm831x_spi_probe,
181 .remove = __devexit_p(wm831x_spi_remove),
2aa13b9e
MB
182};
183
184static struct spi_driver wm8325_spi_driver = {
185 .driver = {
186 .name = "wm8325",
187 .bus = &spi_bus_type,
188 .owner = THIS_MODULE,
87d1906d 189 .pm = &wm831x_spi_pm,
2aa13b9e
MB
190 },
191 .probe = wm831x_spi_probe,
192 .remove = __devexit_p(wm831x_spi_remove),
2aa13b9e
MB
193};
194
412dc11d
MB
195static struct spi_driver wm8326_spi_driver = {
196 .driver = {
197 .name = "wm8326",
198 .bus = &spi_bus_type,
199 .owner = THIS_MODULE,
87d1906d 200 .pm = &wm831x_spi_pm,
412dc11d
MB
201 },
202 .probe = wm831x_spi_probe,
203 .remove = __devexit_p(wm831x_spi_remove),
412dc11d
MB
204};
205
2aa13b9e
MB
206static int __init wm831x_spi_init(void)
207{
208 int ret;
209
210 ret = spi_register_driver(&wm8310_spi_driver);
211 if (ret != 0)
212 pr_err("Failed to register WM8310 SPI driver: %d\n", ret);
213
214 ret = spi_register_driver(&wm8311_spi_driver);
215 if (ret != 0)
216 pr_err("Failed to register WM8311 SPI driver: %d\n", ret);
217
218 ret = spi_register_driver(&wm8312_spi_driver);
219 if (ret != 0)
220 pr_err("Failed to register WM8312 SPI driver: %d\n", ret);
221
222 ret = spi_register_driver(&wm8320_spi_driver);
223 if (ret != 0)
224 pr_err("Failed to register WM8320 SPI driver: %d\n", ret);
225
226 ret = spi_register_driver(&wm8321_spi_driver);
227 if (ret != 0)
228 pr_err("Failed to register WM8321 SPI driver: %d\n", ret);
229
230 ret = spi_register_driver(&wm8325_spi_driver);
231 if (ret != 0)
232 pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
233
412dc11d
MB
234 ret = spi_register_driver(&wm8326_spi_driver);
235 if (ret != 0)
236 pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
237
2aa13b9e
MB
238 return 0;
239}
240subsys_initcall(wm831x_spi_init);
241
242static void __exit wm831x_spi_exit(void)
243{
412dc11d 244 spi_unregister_driver(&wm8326_spi_driver);
2aa13b9e
MB
245 spi_unregister_driver(&wm8325_spi_driver);
246 spi_unregister_driver(&wm8321_spi_driver);
247 spi_unregister_driver(&wm8320_spi_driver);
248 spi_unregister_driver(&wm8312_spi_driver);
249 spi_unregister_driver(&wm8311_spi_driver);
250 spi_unregister_driver(&wm8310_spi_driver);
251}
252module_exit(wm831x_spi_exit);
253
254MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
255MODULE_LICENSE("GPL");
256MODULE_AUTHOR("Mark Brown");
This page took 0.089965 seconds and 5 git commands to generate.