diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 07:57:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 07:57:45 -0400 |
commit | 4e7e2a2008f5d8c49791c412849d5b0232d39bb3 (patch) | |
tree | 32c3fa2d5cefb388689cb795225022769bf7b413 /drivers/mfd/wm831x-spi.c | |
parent | 8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22 (diff) | |
parent | 7cccbdc84487616c3dbe493b04bfa1f362f4bc56 (diff) |
Merge branch 'for-linus' of git://opensource.wolfsonmicro.com/regmap
* 'for-linus' of git://opensource.wolfsonmicro.com/regmap: (62 commits)
mfd: Enable rbtree cache for wm831x devices
regmap: Support some block operations on cached devices
regmap: Allow caches for devices with no defaults
regmap: Ensure rbtree syncs registers set to zero properly
regmap: Allow rbtree to cache zero default values
regmap: Warn on raw I/O as well as bulk reads that bypass cache
regmap: Return a sensible error code if we fail to read the cache
regmap: Use bsearch() to search the register defaults
regmap: Fix doc comment
regmap: Optimize the lookup path to use binary search
regmap: Ensure we scream if we enable cache bypass/only at the same time
regmap: Implement regcache_cache_bypass helper function
regmap: Save/restore the bypass state upon syncing
regmap: Lock the sync path, ensure we use the lockless _regmap_write()
regmap: Fix apostrophe usage
regmap: Make _regmap_write() global
regmap: Fix lock used for regcache_cache_only()
regmap: Grab the lock in regcache_cache_only()
regmap: Modify map->cache_bypass directly
regmap: Fix regcache_sync generic implementation
...
Diffstat (limited to 'drivers/mfd/wm831x-spi.c')
-rw-r--r-- | drivers/mfd/wm831x-spi.c | 204 |
1 files changed, 38 insertions, 166 deletions
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index eed8e4f7a5a1..8d6a9a969dbc 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c | |||
@@ -16,78 +16,19 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
19 | #include <linux/regmap.h> | ||
20 | #include <linux/err.h> | ||
19 | 21 | ||
20 | #include <linux/mfd/wm831x/core.h> | 22 | #include <linux/mfd/wm831x/core.h> |
21 | 23 | ||
22 | static 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 | |||
46 | static 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 | |||
67 | static int __devinit wm831x_spi_probe(struct spi_device *spi) | 24 | static int __devinit wm831x_spi_probe(struct spi_device *spi) |
68 | { | 25 | { |
26 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
69 | struct wm831x *wm831x; | 27 | struct wm831x *wm831x; |
70 | enum wm831x_parent type; | 28 | enum wm831x_parent type; |
29 | int ret; | ||
71 | 30 | ||
72 | /* Currently SPI support for ID tables is unmerged, we're faking it */ | 31 | type = (enum wm831x_parent)id->driver_data; |
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; | ||
85 | else if (strcmp(spi->modalias, "wm8326") == 0) | ||
86 | type = WM8326; | ||
87 | else { | ||
88 | dev_err(&spi->dev, "Unknown device type\n"); | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | 32 | ||
92 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | 33 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); |
93 | if (wm831x == NULL) | 34 | if (wm831x == NULL) |
@@ -98,9 +39,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi) | |||
98 | 39 | ||
99 | dev_set_drvdata(&spi->dev, wm831x); | 40 | dev_set_drvdata(&spi->dev, wm831x); |
100 | wm831x->dev = &spi->dev; | 41 | wm831x->dev = &spi->dev; |
101 | wm831x->control_data = spi; | 42 | |
102 | wm831x->read_dev = wm831x_spi_read_device; | 43 | wm831x->regmap = regmap_init_spi(spi, &wm831x_regmap_config); |
103 | wm831x->write_dev = wm831x_spi_write_device; | 44 | if (IS_ERR(wm831x->regmap)) { |
45 | ret = PTR_ERR(wm831x->regmap); | ||
46 | dev_err(wm831x->dev, "Failed to allocate register map: %d\n", | ||
47 | ret); | ||
48 | kfree(wm831x); | ||
49 | return ret; | ||
50 | } | ||
104 | 51 | ||
105 | return wm831x_device_init(wm831x, type, spi->irq); | 52 | return wm831x_device_init(wm831x, type, spi->irq); |
106 | } | 53 | } |
@@ -121,119 +68,50 @@ static int wm831x_spi_suspend(struct device *dev) | |||
121 | return wm831x_device_suspend(wm831x); | 68 | return wm831x_device_suspend(wm831x); |
122 | } | 69 | } |
123 | 70 | ||
71 | static void wm831x_spi_shutdown(struct spi_device *spi) | ||
72 | { | ||
73 | struct wm831x *wm831x = dev_get_drvdata(&spi->dev); | ||
74 | |||
75 | wm831x_device_shutdown(wm831x); | ||
76 | } | ||
77 | |||
124 | static const struct dev_pm_ops wm831x_spi_pm = { | 78 | static const struct dev_pm_ops wm831x_spi_pm = { |
125 | .freeze = wm831x_spi_suspend, | 79 | .freeze = wm831x_spi_suspend, |
126 | .suspend = wm831x_spi_suspend, | 80 | .suspend = wm831x_spi_suspend, |
127 | }; | 81 | }; |
128 | 82 | ||
129 | static struct spi_driver wm8310_spi_driver = { | 83 | static const struct spi_device_id wm831x_spi_ids[] = { |
130 | .driver = { | 84 | { "wm8310", WM8310 }, |
131 | .name = "wm8310", | 85 | { "wm8311", WM8311 }, |
132 | .bus = &spi_bus_type, | 86 | { "wm8312", WM8312 }, |
133 | .owner = THIS_MODULE, | 87 | { "wm8320", WM8320 }, |
134 | .pm = &wm831x_spi_pm, | 88 | { "wm8321", WM8321 }, |
135 | }, | 89 | { "wm8325", WM8325 }, |
136 | .probe = wm831x_spi_probe, | 90 | { "wm8326", WM8326 }, |
137 | .remove = __devexit_p(wm831x_spi_remove), | 91 | { }, |
138 | }; | 92 | }; |
93 | MODULE_DEVICE_TABLE(spi, wm831x_spi_id); | ||
139 | 94 | ||
140 | static struct spi_driver wm8311_spi_driver = { | 95 | static struct spi_driver wm831x_spi_driver = { |
141 | .driver = { | 96 | .driver = { |
142 | .name = "wm8311", | 97 | .name = "wm831x", |
143 | .bus = &spi_bus_type, | ||
144 | .owner = THIS_MODULE, | ||
145 | .pm = &wm831x_spi_pm, | ||
146 | }, | ||
147 | .probe = wm831x_spi_probe, | ||
148 | .remove = __devexit_p(wm831x_spi_remove), | ||
149 | }; | ||
150 | |||
151 | static struct spi_driver wm8312_spi_driver = { | ||
152 | .driver = { | ||
153 | .name = "wm8312", | ||
154 | .bus = &spi_bus_type, | ||
155 | .owner = THIS_MODULE, | ||
156 | .pm = &wm831x_spi_pm, | ||
157 | }, | ||
158 | .probe = wm831x_spi_probe, | ||
159 | .remove = __devexit_p(wm831x_spi_remove), | ||
160 | }; | ||
161 | |||
162 | static struct spi_driver wm8320_spi_driver = { | ||
163 | .driver = { | ||
164 | .name = "wm8320", | ||
165 | .bus = &spi_bus_type, | ||
166 | .owner = THIS_MODULE, | ||
167 | .pm = &wm831x_spi_pm, | ||
168 | }, | ||
169 | .probe = wm831x_spi_probe, | ||
170 | .remove = __devexit_p(wm831x_spi_remove), | ||
171 | }; | ||
172 | |||
173 | static struct spi_driver wm8321_spi_driver = { | ||
174 | .driver = { | ||
175 | .name = "wm8321", | ||
176 | .bus = &spi_bus_type, | ||
177 | .owner = THIS_MODULE, | ||
178 | .pm = &wm831x_spi_pm, | ||
179 | }, | ||
180 | .probe = wm831x_spi_probe, | ||
181 | .remove = __devexit_p(wm831x_spi_remove), | ||
182 | }; | ||
183 | |||
184 | static struct spi_driver wm8325_spi_driver = { | ||
185 | .driver = { | ||
186 | .name = "wm8325", | ||
187 | .bus = &spi_bus_type, | ||
188 | .owner = THIS_MODULE, | ||
189 | .pm = &wm831x_spi_pm, | ||
190 | }, | ||
191 | .probe = wm831x_spi_probe, | ||
192 | .remove = __devexit_p(wm831x_spi_remove), | ||
193 | }; | ||
194 | |||
195 | static struct spi_driver wm8326_spi_driver = { | ||
196 | .driver = { | ||
197 | .name = "wm8326", | ||
198 | .bus = &spi_bus_type, | 98 | .bus = &spi_bus_type, |
199 | .owner = THIS_MODULE, | 99 | .owner = THIS_MODULE, |
200 | .pm = &wm831x_spi_pm, | 100 | .pm = &wm831x_spi_pm, |
201 | }, | 101 | }, |
102 | .id_table = wm831x_spi_ids, | ||
202 | .probe = wm831x_spi_probe, | 103 | .probe = wm831x_spi_probe, |
203 | .remove = __devexit_p(wm831x_spi_remove), | 104 | .remove = __devexit_p(wm831x_spi_remove), |
105 | .shutdown = wm831x_spi_shutdown, | ||
204 | }; | 106 | }; |
205 | 107 | ||
206 | static int __init wm831x_spi_init(void) | 108 | static int __init wm831x_spi_init(void) |
207 | { | 109 | { |
208 | int ret; | 110 | int ret; |
209 | 111 | ||
210 | ret = spi_register_driver(&wm8310_spi_driver); | 112 | ret = spi_register_driver(&wm831x_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 | |||
234 | ret = spi_register_driver(&wm8326_spi_driver); | ||
235 | if (ret != 0) | 113 | if (ret != 0) |
236 | pr_err("Failed to register WM8326 SPI driver: %d\n", ret); | 114 | pr_err("Failed to register WM831x SPI driver: %d\n", ret); |
237 | 115 | ||
238 | return 0; | 116 | return 0; |
239 | } | 117 | } |
@@ -241,13 +119,7 @@ subsys_initcall(wm831x_spi_init); | |||
241 | 119 | ||
242 | static void __exit wm831x_spi_exit(void) | 120 | static void __exit wm831x_spi_exit(void) |
243 | { | 121 | { |
244 | spi_unregister_driver(&wm8326_spi_driver); | 122 | spi_unregister_driver(&wm831x_spi_driver); |
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 | } | 123 | } |
252 | module_exit(wm831x_spi_exit); | 124 | module_exit(wm831x_spi_exit); |
253 | 125 | ||