Commit 18bf50a374a46aec83652f48006a6fac764c635d
Committed by
Samuel Ortiz
1 parent
f78d29f166
Exists in
master
and in
6 other branches
mfd: Store wm8350 struct in core device driver data
This will allow us to move to a more idiomatic MFD model as drivers will be able to get the struct by looking at their parent device. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 1 changed file with 2 additions and 0 deletions Inline Diff
drivers/mfd/wm8350-core.c
1 | /* | 1 | /* |
2 | * wm8350-core.c -- Device access for Wolfson WM8350 | 2 | * wm8350-core.c -- Device access for Wolfson WM8350 |
3 | * | 3 | * |
4 | * Copyright 2007, 2008 Wolfson Microelectronics PLC. | 4 | * Copyright 2007, 2008 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * Author: Liam Girdwood, Mark Brown | 6 | * Author: Liam Girdwood, Mark Brown |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 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 | 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 | 10 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. | 11 | * option) any later version. |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/bug.h> | 19 | #include <linux/bug.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | 24 | ||
25 | #include <linux/mfd/wm8350/core.h> | 25 | #include <linux/mfd/wm8350/core.h> |
26 | #include <linux/mfd/wm8350/audio.h> | 26 | #include <linux/mfd/wm8350/audio.h> |
27 | #include <linux/mfd/wm8350/comparator.h> | 27 | #include <linux/mfd/wm8350/comparator.h> |
28 | #include <linux/mfd/wm8350/gpio.h> | 28 | #include <linux/mfd/wm8350/gpio.h> |
29 | #include <linux/mfd/wm8350/pmic.h> | 29 | #include <linux/mfd/wm8350/pmic.h> |
30 | #include <linux/mfd/wm8350/rtc.h> | 30 | #include <linux/mfd/wm8350/rtc.h> |
31 | #include <linux/mfd/wm8350/supply.h> | 31 | #include <linux/mfd/wm8350/supply.h> |
32 | #include <linux/mfd/wm8350/wdt.h> | 32 | #include <linux/mfd/wm8350/wdt.h> |
33 | 33 | ||
34 | #define WM8350_UNLOCK_KEY 0x0013 | 34 | #define WM8350_UNLOCK_KEY 0x0013 |
35 | #define WM8350_LOCK_KEY 0x0000 | 35 | #define WM8350_LOCK_KEY 0x0000 |
36 | 36 | ||
37 | #define WM8350_CLOCK_CONTROL_1 0x28 | 37 | #define WM8350_CLOCK_CONTROL_1 0x28 |
38 | #define WM8350_AIF_TEST 0x74 | 38 | #define WM8350_AIF_TEST 0x74 |
39 | 39 | ||
40 | /* debug */ | 40 | /* debug */ |
41 | #define WM8350_BUS_DEBUG 0 | 41 | #define WM8350_BUS_DEBUG 0 |
42 | #if WM8350_BUS_DEBUG | 42 | #if WM8350_BUS_DEBUG |
43 | #define dump(regs, src) do { \ | 43 | #define dump(regs, src) do { \ |
44 | int i_; \ | 44 | int i_; \ |
45 | u16 *src_ = src; \ | 45 | u16 *src_ = src; \ |
46 | printk(KERN_DEBUG); \ | 46 | printk(KERN_DEBUG); \ |
47 | for (i_ = 0; i_ < regs; i_++) \ | 47 | for (i_ = 0; i_ < regs; i_++) \ |
48 | printk(" 0x%4.4x", *src_++); \ | 48 | printk(" 0x%4.4x", *src_++); \ |
49 | printk("\n"); \ | 49 | printk("\n"); \ |
50 | } while (0); | 50 | } while (0); |
51 | #else | 51 | #else |
52 | #define dump(bytes, src) | 52 | #define dump(bytes, src) |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | #define WM8350_LOCK_DEBUG 0 | 55 | #define WM8350_LOCK_DEBUG 0 |
56 | #if WM8350_LOCK_DEBUG | 56 | #if WM8350_LOCK_DEBUG |
57 | #define ldbg(format, arg...) printk(format, ## arg) | 57 | #define ldbg(format, arg...) printk(format, ## arg) |
58 | #else | 58 | #else |
59 | #define ldbg(format, arg...) | 59 | #define ldbg(format, arg...) |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * WM8350 Device IO | 63 | * WM8350 Device IO |
64 | */ | 64 | */ |
65 | static DEFINE_MUTEX(io_mutex); | 65 | static DEFINE_MUTEX(io_mutex); |
66 | static DEFINE_MUTEX(reg_lock_mutex); | 66 | static DEFINE_MUTEX(reg_lock_mutex); |
67 | 67 | ||
68 | /* Perform a physical read from the device. | 68 | /* Perform a physical read from the device. |
69 | */ | 69 | */ |
70 | static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs, | 70 | static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs, |
71 | u16 *dest) | 71 | u16 *dest) |
72 | { | 72 | { |
73 | int i, ret; | 73 | int i, ret; |
74 | int bytes = num_regs * 2; | 74 | int bytes = num_regs * 2; |
75 | 75 | ||
76 | dev_dbg(wm8350->dev, "volatile read\n"); | 76 | dev_dbg(wm8350->dev, "volatile read\n"); |
77 | ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest); | 77 | ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest); |
78 | 78 | ||
79 | for (i = reg; i < reg + num_regs; i++) { | 79 | for (i = reg; i < reg + num_regs; i++) { |
80 | /* Cache is CPU endian */ | 80 | /* Cache is CPU endian */ |
81 | dest[i - reg] = be16_to_cpu(dest[i - reg]); | 81 | dest[i - reg] = be16_to_cpu(dest[i - reg]); |
82 | 82 | ||
83 | /* Mask out non-readable bits */ | 83 | /* Mask out non-readable bits */ |
84 | dest[i - reg] &= wm8350_reg_io_map[i].readable; | 84 | dest[i - reg] &= wm8350_reg_io_map[i].readable; |
85 | } | 85 | } |
86 | 86 | ||
87 | dump(num_regs, dest); | 87 | dump(num_regs, dest); |
88 | 88 | ||
89 | return ret; | 89 | return ret; |
90 | } | 90 | } |
91 | 91 | ||
92 | static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest) | 92 | static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest) |
93 | { | 93 | { |
94 | int i; | 94 | int i; |
95 | int end = reg + num_regs; | 95 | int end = reg + num_regs; |
96 | int ret = 0; | 96 | int ret = 0; |
97 | int bytes = num_regs * 2; | 97 | int bytes = num_regs * 2; |
98 | 98 | ||
99 | if (wm8350->read_dev == NULL) | 99 | if (wm8350->read_dev == NULL) |
100 | return -ENODEV; | 100 | return -ENODEV; |
101 | 101 | ||
102 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { | 102 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { |
103 | dev_err(wm8350->dev, "invalid reg %x\n", | 103 | dev_err(wm8350->dev, "invalid reg %x\n", |
104 | reg + num_regs - 1); | 104 | reg + num_regs - 1); |
105 | return -EINVAL; | 105 | return -EINVAL; |
106 | } | 106 | } |
107 | 107 | ||
108 | dev_dbg(wm8350->dev, | 108 | dev_dbg(wm8350->dev, |
109 | "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs); | 109 | "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs); |
110 | 110 | ||
111 | #if WM8350_BUS_DEBUG | 111 | #if WM8350_BUS_DEBUG |
112 | /* we can _safely_ read any register, but warn if read not supported */ | 112 | /* we can _safely_ read any register, but warn if read not supported */ |
113 | for (i = reg; i < end; i++) { | 113 | for (i = reg; i < end; i++) { |
114 | if (!wm8350_reg_io_map[i].readable) | 114 | if (!wm8350_reg_io_map[i].readable) |
115 | dev_warn(wm8350->dev, | 115 | dev_warn(wm8350->dev, |
116 | "reg R%d is not readable\n", i); | 116 | "reg R%d is not readable\n", i); |
117 | } | 117 | } |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | /* if any volatile registers are required, then read back all */ | 120 | /* if any volatile registers are required, then read back all */ |
121 | for (i = reg; i < end; i++) | 121 | for (i = reg; i < end; i++) |
122 | if (wm8350_reg_io_map[i].vol) | 122 | if (wm8350_reg_io_map[i].vol) |
123 | return wm8350_phys_read(wm8350, reg, num_regs, dest); | 123 | return wm8350_phys_read(wm8350, reg, num_regs, dest); |
124 | 124 | ||
125 | /* no volatiles, then cache is good */ | 125 | /* no volatiles, then cache is good */ |
126 | dev_dbg(wm8350->dev, "cache read\n"); | 126 | dev_dbg(wm8350->dev, "cache read\n"); |
127 | memcpy(dest, &wm8350->reg_cache[reg], bytes); | 127 | memcpy(dest, &wm8350->reg_cache[reg], bytes); |
128 | dump(num_regs, dest); | 128 | dump(num_regs, dest); |
129 | return ret; | 129 | return ret; |
130 | } | 130 | } |
131 | 131 | ||
132 | static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) | 132 | static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) |
133 | { | 133 | { |
134 | if (reg == WM8350_SECURITY || | 134 | if (reg == WM8350_SECURITY || |
135 | wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) | 135 | wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) |
136 | return 0; | 136 | return 0; |
137 | 137 | ||
138 | if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && | 138 | if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && |
139 | reg <= WM8350_GPIO_FUNCTION_SELECT_4) || | 139 | reg <= WM8350_GPIO_FUNCTION_SELECT_4) || |
140 | (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && | 140 | (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && |
141 | reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) | 141 | reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) |
142 | return 1; | 142 | return 1; |
143 | return 0; | 143 | return 0; |
144 | } | 144 | } |
145 | 145 | ||
146 | static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) | 146 | static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) |
147 | { | 147 | { |
148 | int i; | 148 | int i; |
149 | int end = reg + num_regs; | 149 | int end = reg + num_regs; |
150 | int bytes = num_regs * 2; | 150 | int bytes = num_regs * 2; |
151 | 151 | ||
152 | if (wm8350->write_dev == NULL) | 152 | if (wm8350->write_dev == NULL) |
153 | return -ENODEV; | 153 | return -ENODEV; |
154 | 154 | ||
155 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { | 155 | if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { |
156 | dev_err(wm8350->dev, "invalid reg %x\n", | 156 | dev_err(wm8350->dev, "invalid reg %x\n", |
157 | reg + num_regs - 1); | 157 | reg + num_regs - 1); |
158 | return -EINVAL; | 158 | return -EINVAL; |
159 | } | 159 | } |
160 | 160 | ||
161 | /* it's generally not a good idea to write to RO or locked registers */ | 161 | /* it's generally not a good idea to write to RO or locked registers */ |
162 | for (i = reg; i < end; i++) { | 162 | for (i = reg; i < end; i++) { |
163 | if (!wm8350_reg_io_map[i].writable) { | 163 | if (!wm8350_reg_io_map[i].writable) { |
164 | dev_err(wm8350->dev, | 164 | dev_err(wm8350->dev, |
165 | "attempted write to read only reg R%d\n", i); | 165 | "attempted write to read only reg R%d\n", i); |
166 | return -EINVAL; | 166 | return -EINVAL; |
167 | } | 167 | } |
168 | 168 | ||
169 | if (is_reg_locked(wm8350, i)) { | 169 | if (is_reg_locked(wm8350, i)) { |
170 | dev_err(wm8350->dev, | 170 | dev_err(wm8350->dev, |
171 | "attempted write to locked reg R%d\n", i); | 171 | "attempted write to locked reg R%d\n", i); |
172 | return -EINVAL; | 172 | return -EINVAL; |
173 | } | 173 | } |
174 | 174 | ||
175 | src[i - reg] &= wm8350_reg_io_map[i].writable; | 175 | src[i - reg] &= wm8350_reg_io_map[i].writable; |
176 | 176 | ||
177 | wm8350->reg_cache[i] = | 177 | wm8350->reg_cache[i] = |
178 | (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) | 178 | (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) |
179 | | src[i - reg]; | 179 | | src[i - reg]; |
180 | 180 | ||
181 | src[i - reg] = cpu_to_be16(src[i - reg]); | 181 | src[i - reg] = cpu_to_be16(src[i - reg]); |
182 | } | 182 | } |
183 | 183 | ||
184 | /* Actually write it out */ | 184 | /* Actually write it out */ |
185 | return wm8350->write_dev(wm8350, reg, bytes, (char *)src); | 185 | return wm8350->write_dev(wm8350, reg, bytes, (char *)src); |
186 | } | 186 | } |
187 | 187 | ||
188 | /* | 188 | /* |
189 | * Safe read, modify, write methods | 189 | * Safe read, modify, write methods |
190 | */ | 190 | */ |
191 | int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) | 191 | int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) |
192 | { | 192 | { |
193 | u16 data; | 193 | u16 data; |
194 | int err; | 194 | int err; |
195 | 195 | ||
196 | mutex_lock(&io_mutex); | 196 | mutex_lock(&io_mutex); |
197 | err = wm8350_read(wm8350, reg, 1, &data); | 197 | err = wm8350_read(wm8350, reg, 1, &data); |
198 | if (err) { | 198 | if (err) { |
199 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | 199 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); |
200 | goto out; | 200 | goto out; |
201 | } | 201 | } |
202 | 202 | ||
203 | data &= ~mask; | 203 | data &= ~mask; |
204 | err = wm8350_write(wm8350, reg, 1, &data); | 204 | err = wm8350_write(wm8350, reg, 1, &data); |
205 | if (err) | 205 | if (err) |
206 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | 206 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); |
207 | out: | 207 | out: |
208 | mutex_unlock(&io_mutex); | 208 | mutex_unlock(&io_mutex); |
209 | return err; | 209 | return err; |
210 | } | 210 | } |
211 | EXPORT_SYMBOL_GPL(wm8350_clear_bits); | 211 | EXPORT_SYMBOL_GPL(wm8350_clear_bits); |
212 | 212 | ||
213 | int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) | 213 | int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) |
214 | { | 214 | { |
215 | u16 data; | 215 | u16 data; |
216 | int err; | 216 | int err; |
217 | 217 | ||
218 | mutex_lock(&io_mutex); | 218 | mutex_lock(&io_mutex); |
219 | err = wm8350_read(wm8350, reg, 1, &data); | 219 | err = wm8350_read(wm8350, reg, 1, &data); |
220 | if (err) { | 220 | if (err) { |
221 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | 221 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); |
222 | goto out; | 222 | goto out; |
223 | } | 223 | } |
224 | 224 | ||
225 | data |= mask; | 225 | data |= mask; |
226 | err = wm8350_write(wm8350, reg, 1, &data); | 226 | err = wm8350_write(wm8350, reg, 1, &data); |
227 | if (err) | 227 | if (err) |
228 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | 228 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); |
229 | out: | 229 | out: |
230 | mutex_unlock(&io_mutex); | 230 | mutex_unlock(&io_mutex); |
231 | return err; | 231 | return err; |
232 | } | 232 | } |
233 | EXPORT_SYMBOL_GPL(wm8350_set_bits); | 233 | EXPORT_SYMBOL_GPL(wm8350_set_bits); |
234 | 234 | ||
235 | u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) | 235 | u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) |
236 | { | 236 | { |
237 | u16 data; | 237 | u16 data; |
238 | int err; | 238 | int err; |
239 | 239 | ||
240 | mutex_lock(&io_mutex); | 240 | mutex_lock(&io_mutex); |
241 | err = wm8350_read(wm8350, reg, 1, &data); | 241 | err = wm8350_read(wm8350, reg, 1, &data); |
242 | if (err) | 242 | if (err) |
243 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); | 243 | dev_err(wm8350->dev, "read from reg R%d failed\n", reg); |
244 | 244 | ||
245 | mutex_unlock(&io_mutex); | 245 | mutex_unlock(&io_mutex); |
246 | return data; | 246 | return data; |
247 | } | 247 | } |
248 | EXPORT_SYMBOL_GPL(wm8350_reg_read); | 248 | EXPORT_SYMBOL_GPL(wm8350_reg_read); |
249 | 249 | ||
250 | int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) | 250 | int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) |
251 | { | 251 | { |
252 | int ret; | 252 | int ret; |
253 | u16 data = val; | 253 | u16 data = val; |
254 | 254 | ||
255 | mutex_lock(&io_mutex); | 255 | mutex_lock(&io_mutex); |
256 | ret = wm8350_write(wm8350, reg, 1, &data); | 256 | ret = wm8350_write(wm8350, reg, 1, &data); |
257 | if (ret) | 257 | if (ret) |
258 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); | 258 | dev_err(wm8350->dev, "write to reg R%d failed\n", reg); |
259 | mutex_unlock(&io_mutex); | 259 | mutex_unlock(&io_mutex); |
260 | return ret; | 260 | return ret; |
261 | } | 261 | } |
262 | EXPORT_SYMBOL_GPL(wm8350_reg_write); | 262 | EXPORT_SYMBOL_GPL(wm8350_reg_write); |
263 | 263 | ||
264 | int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs, | 264 | int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs, |
265 | u16 *dest) | 265 | u16 *dest) |
266 | { | 266 | { |
267 | int err = 0; | 267 | int err = 0; |
268 | 268 | ||
269 | mutex_lock(&io_mutex); | 269 | mutex_lock(&io_mutex); |
270 | err = wm8350_read(wm8350, start_reg, regs, dest); | 270 | err = wm8350_read(wm8350, start_reg, regs, dest); |
271 | if (err) | 271 | if (err) |
272 | dev_err(wm8350->dev, "block read starting from R%d failed\n", | 272 | dev_err(wm8350->dev, "block read starting from R%d failed\n", |
273 | start_reg); | 273 | start_reg); |
274 | mutex_unlock(&io_mutex); | 274 | mutex_unlock(&io_mutex); |
275 | return err; | 275 | return err; |
276 | } | 276 | } |
277 | EXPORT_SYMBOL_GPL(wm8350_block_read); | 277 | EXPORT_SYMBOL_GPL(wm8350_block_read); |
278 | 278 | ||
279 | int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, | 279 | int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, |
280 | u16 *src) | 280 | u16 *src) |
281 | { | 281 | { |
282 | int ret = 0; | 282 | int ret = 0; |
283 | 283 | ||
284 | mutex_lock(&io_mutex); | 284 | mutex_lock(&io_mutex); |
285 | ret = wm8350_write(wm8350, start_reg, regs, src); | 285 | ret = wm8350_write(wm8350, start_reg, regs, src); |
286 | if (ret) | 286 | if (ret) |
287 | dev_err(wm8350->dev, "block write starting at R%d failed\n", | 287 | dev_err(wm8350->dev, "block write starting at R%d failed\n", |
288 | start_reg); | 288 | start_reg); |
289 | mutex_unlock(&io_mutex); | 289 | mutex_unlock(&io_mutex); |
290 | return ret; | 290 | return ret; |
291 | } | 291 | } |
292 | EXPORT_SYMBOL_GPL(wm8350_block_write); | 292 | EXPORT_SYMBOL_GPL(wm8350_block_write); |
293 | 293 | ||
294 | /** | 294 | /** |
295 | * wm8350_reg_lock() | 295 | * wm8350_reg_lock() |
296 | * | 296 | * |
297 | * The WM8350 has a hardware lock which can be used to prevent writes to | 297 | * The WM8350 has a hardware lock which can be used to prevent writes to |
298 | * some registers (generally those which can cause particularly serious | 298 | * some registers (generally those which can cause particularly serious |
299 | * problems if misused). This function enables that lock. | 299 | * problems if misused). This function enables that lock. |
300 | */ | 300 | */ |
301 | int wm8350_reg_lock(struct wm8350 *wm8350) | 301 | int wm8350_reg_lock(struct wm8350 *wm8350) |
302 | { | 302 | { |
303 | u16 key = WM8350_LOCK_KEY; | 303 | u16 key = WM8350_LOCK_KEY; |
304 | int ret; | 304 | int ret; |
305 | 305 | ||
306 | ldbg(__func__); | 306 | ldbg(__func__); |
307 | mutex_lock(&io_mutex); | 307 | mutex_lock(&io_mutex); |
308 | ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); | 308 | ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); |
309 | if (ret) | 309 | if (ret) |
310 | dev_err(wm8350->dev, "lock failed\n"); | 310 | dev_err(wm8350->dev, "lock failed\n"); |
311 | mutex_unlock(&io_mutex); | 311 | mutex_unlock(&io_mutex); |
312 | return ret; | 312 | return ret; |
313 | } | 313 | } |
314 | EXPORT_SYMBOL_GPL(wm8350_reg_lock); | 314 | EXPORT_SYMBOL_GPL(wm8350_reg_lock); |
315 | 315 | ||
316 | /** | 316 | /** |
317 | * wm8350_reg_unlock() | 317 | * wm8350_reg_unlock() |
318 | * | 318 | * |
319 | * The WM8350 has a hardware lock which can be used to prevent writes to | 319 | * The WM8350 has a hardware lock which can be used to prevent writes to |
320 | * some registers (generally those which can cause particularly serious | 320 | * some registers (generally those which can cause particularly serious |
321 | * problems if misused). This function disables that lock so updates | 321 | * problems if misused). This function disables that lock so updates |
322 | * can be performed. For maximum safety this should be done only when | 322 | * can be performed. For maximum safety this should be done only when |
323 | * required. | 323 | * required. |
324 | */ | 324 | */ |
325 | int wm8350_reg_unlock(struct wm8350 *wm8350) | 325 | int wm8350_reg_unlock(struct wm8350 *wm8350) |
326 | { | 326 | { |
327 | u16 key = WM8350_UNLOCK_KEY; | 327 | u16 key = WM8350_UNLOCK_KEY; |
328 | int ret; | 328 | int ret; |
329 | 329 | ||
330 | ldbg(__func__); | 330 | ldbg(__func__); |
331 | mutex_lock(&io_mutex); | 331 | mutex_lock(&io_mutex); |
332 | ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); | 332 | ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); |
333 | if (ret) | 333 | if (ret) |
334 | dev_err(wm8350->dev, "unlock failed\n"); | 334 | dev_err(wm8350->dev, "unlock failed\n"); |
335 | mutex_unlock(&io_mutex); | 335 | mutex_unlock(&io_mutex); |
336 | return ret; | 336 | return ret; |
337 | } | 337 | } |
338 | EXPORT_SYMBOL_GPL(wm8350_reg_unlock); | 338 | EXPORT_SYMBOL_GPL(wm8350_reg_unlock); |
339 | 339 | ||
340 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | 340 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) |
341 | { | 341 | { |
342 | u16 reg, result = 0; | 342 | u16 reg, result = 0; |
343 | 343 | ||
344 | if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) | 344 | if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) |
345 | return -EINVAL; | 345 | return -EINVAL; |
346 | if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP | 346 | if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP |
347 | && (scale != 0 || vref != 0)) | 347 | && (scale != 0 || vref != 0)) |
348 | return -EINVAL; | 348 | return -EINVAL; |
349 | 349 | ||
350 | mutex_lock(&wm8350->auxadc_mutex); | 350 | mutex_lock(&wm8350->auxadc_mutex); |
351 | 351 | ||
352 | /* Turn on the ADC */ | 352 | /* Turn on the ADC */ |
353 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | 353 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); |
354 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA); | 354 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA); |
355 | 355 | ||
356 | if (scale || vref) { | 356 | if (scale || vref) { |
357 | reg = scale << 13; | 357 | reg = scale << 13; |
358 | reg |= vref << 12; | 358 | reg |= vref << 12; |
359 | wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg); | 359 | wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg); |
360 | } | 360 | } |
361 | 361 | ||
362 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | 362 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); |
363 | reg |= 1 << channel | WM8350_AUXADC_POLL; | 363 | reg |= 1 << channel | WM8350_AUXADC_POLL; |
364 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); | 364 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); |
365 | 365 | ||
366 | /* If a late IRQ left the completion signalled then consume | 366 | /* If a late IRQ left the completion signalled then consume |
367 | * the completion. */ | 367 | * the completion. */ |
368 | try_wait_for_completion(&wm8350->auxadc_done); | 368 | try_wait_for_completion(&wm8350->auxadc_done); |
369 | 369 | ||
370 | /* We ignore the result of the completion and just check for a | 370 | /* We ignore the result of the completion and just check for a |
371 | * conversion result, allowing us to soldier on if the IRQ | 371 | * conversion result, allowing us to soldier on if the IRQ |
372 | * infrastructure is not set up for the chip. */ | 372 | * infrastructure is not set up for the chip. */ |
373 | wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5)); | 373 | wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5)); |
374 | 374 | ||
375 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | 375 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); |
376 | if (reg & WM8350_AUXADC_POLL) | 376 | if (reg & WM8350_AUXADC_POLL) |
377 | dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); | 377 | dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); |
378 | else | 378 | else |
379 | result = wm8350_reg_read(wm8350, | 379 | result = wm8350_reg_read(wm8350, |
380 | WM8350_AUX1_READBACK + channel); | 380 | WM8350_AUX1_READBACK + channel); |
381 | 381 | ||
382 | /* Turn off the ADC */ | 382 | /* Turn off the ADC */ |
383 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | 383 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); |
384 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, | 384 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, |
385 | reg & ~WM8350_AUXADC_ENA); | 385 | reg & ~WM8350_AUXADC_ENA); |
386 | 386 | ||
387 | mutex_unlock(&wm8350->auxadc_mutex); | 387 | mutex_unlock(&wm8350->auxadc_mutex); |
388 | 388 | ||
389 | return result & WM8350_AUXADC_DATA1_MASK; | 389 | return result & WM8350_AUXADC_DATA1_MASK; |
390 | } | 390 | } |
391 | EXPORT_SYMBOL_GPL(wm8350_read_auxadc); | 391 | EXPORT_SYMBOL_GPL(wm8350_read_auxadc); |
392 | 392 | ||
393 | static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) | 393 | static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) |
394 | { | 394 | { |
395 | struct wm8350 *wm8350 = irq_data; | 395 | struct wm8350 *wm8350 = irq_data; |
396 | 396 | ||
397 | complete(&wm8350->auxadc_done); | 397 | complete(&wm8350->auxadc_done); |
398 | 398 | ||
399 | return IRQ_HANDLED; | 399 | return IRQ_HANDLED; |
400 | } | 400 | } |
401 | 401 | ||
402 | /* | 402 | /* |
403 | * Cache is always host endian. | 403 | * Cache is always host endian. |
404 | */ | 404 | */ |
405 | static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | 405 | static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) |
406 | { | 406 | { |
407 | int i, ret = 0; | 407 | int i, ret = 0; |
408 | u16 value; | 408 | u16 value; |
409 | const u16 *reg_map; | 409 | const u16 *reg_map; |
410 | 410 | ||
411 | switch (type) { | 411 | switch (type) { |
412 | case 0: | 412 | case 0: |
413 | switch (mode) { | 413 | switch (mode) { |
414 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 | 414 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 |
415 | case 0: | 415 | case 0: |
416 | reg_map = wm8350_mode0_defaults; | 416 | reg_map = wm8350_mode0_defaults; |
417 | break; | 417 | break; |
418 | #endif | 418 | #endif |
419 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 | 419 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 |
420 | case 1: | 420 | case 1: |
421 | reg_map = wm8350_mode1_defaults; | 421 | reg_map = wm8350_mode1_defaults; |
422 | break; | 422 | break; |
423 | #endif | 423 | #endif |
424 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 | 424 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 |
425 | case 2: | 425 | case 2: |
426 | reg_map = wm8350_mode2_defaults; | 426 | reg_map = wm8350_mode2_defaults; |
427 | break; | 427 | break; |
428 | #endif | 428 | #endif |
429 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 | 429 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 |
430 | case 3: | 430 | case 3: |
431 | reg_map = wm8350_mode3_defaults; | 431 | reg_map = wm8350_mode3_defaults; |
432 | break; | 432 | break; |
433 | #endif | 433 | #endif |
434 | default: | 434 | default: |
435 | dev_err(wm8350->dev, | 435 | dev_err(wm8350->dev, |
436 | "WM8350 configuration mode %d not supported\n", | 436 | "WM8350 configuration mode %d not supported\n", |
437 | mode); | 437 | mode); |
438 | return -EINVAL; | 438 | return -EINVAL; |
439 | } | 439 | } |
440 | break; | 440 | break; |
441 | 441 | ||
442 | case 1: | 442 | case 1: |
443 | switch (mode) { | 443 | switch (mode) { |
444 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 | 444 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 |
445 | case 0: | 445 | case 0: |
446 | reg_map = wm8351_mode0_defaults; | 446 | reg_map = wm8351_mode0_defaults; |
447 | break; | 447 | break; |
448 | #endif | 448 | #endif |
449 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 | 449 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 |
450 | case 1: | 450 | case 1: |
451 | reg_map = wm8351_mode1_defaults; | 451 | reg_map = wm8351_mode1_defaults; |
452 | break; | 452 | break; |
453 | #endif | 453 | #endif |
454 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 | 454 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 |
455 | case 2: | 455 | case 2: |
456 | reg_map = wm8351_mode2_defaults; | 456 | reg_map = wm8351_mode2_defaults; |
457 | break; | 457 | break; |
458 | #endif | 458 | #endif |
459 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 | 459 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 |
460 | case 3: | 460 | case 3: |
461 | reg_map = wm8351_mode3_defaults; | 461 | reg_map = wm8351_mode3_defaults; |
462 | break; | 462 | break; |
463 | #endif | 463 | #endif |
464 | default: | 464 | default: |
465 | dev_err(wm8350->dev, | 465 | dev_err(wm8350->dev, |
466 | "WM8351 configuration mode %d not supported\n", | 466 | "WM8351 configuration mode %d not supported\n", |
467 | mode); | 467 | mode); |
468 | return -EINVAL; | 468 | return -EINVAL; |
469 | } | 469 | } |
470 | break; | 470 | break; |
471 | 471 | ||
472 | case 2: | 472 | case 2: |
473 | switch (mode) { | 473 | switch (mode) { |
474 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 | 474 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 |
475 | case 0: | 475 | case 0: |
476 | reg_map = wm8352_mode0_defaults; | 476 | reg_map = wm8352_mode0_defaults; |
477 | break; | 477 | break; |
478 | #endif | 478 | #endif |
479 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 | 479 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 |
480 | case 1: | 480 | case 1: |
481 | reg_map = wm8352_mode1_defaults; | 481 | reg_map = wm8352_mode1_defaults; |
482 | break; | 482 | break; |
483 | #endif | 483 | #endif |
484 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 | 484 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 |
485 | case 2: | 485 | case 2: |
486 | reg_map = wm8352_mode2_defaults; | 486 | reg_map = wm8352_mode2_defaults; |
487 | break; | 487 | break; |
488 | #endif | 488 | #endif |
489 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 | 489 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 |
490 | case 3: | 490 | case 3: |
491 | reg_map = wm8352_mode3_defaults; | 491 | reg_map = wm8352_mode3_defaults; |
492 | break; | 492 | break; |
493 | #endif | 493 | #endif |
494 | default: | 494 | default: |
495 | dev_err(wm8350->dev, | 495 | dev_err(wm8350->dev, |
496 | "WM8352 configuration mode %d not supported\n", | 496 | "WM8352 configuration mode %d not supported\n", |
497 | mode); | 497 | mode); |
498 | return -EINVAL; | 498 | return -EINVAL; |
499 | } | 499 | } |
500 | break; | 500 | break; |
501 | 501 | ||
502 | default: | 502 | default: |
503 | dev_err(wm8350->dev, | 503 | dev_err(wm8350->dev, |
504 | "WM835x configuration mode %d not supported\n", | 504 | "WM835x configuration mode %d not supported\n", |
505 | mode); | 505 | mode); |
506 | return -EINVAL; | 506 | return -EINVAL; |
507 | } | 507 | } |
508 | 508 | ||
509 | wm8350->reg_cache = | 509 | wm8350->reg_cache = |
510 | kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); | 510 | kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); |
511 | if (wm8350->reg_cache == NULL) | 511 | if (wm8350->reg_cache == NULL) |
512 | return -ENOMEM; | 512 | return -ENOMEM; |
513 | 513 | ||
514 | /* Read the initial cache state back from the device - this is | 514 | /* Read the initial cache state back from the device - this is |
515 | * a PMIC so the device many not be in a virgin state and we | 515 | * a PMIC so the device many not be in a virgin state and we |
516 | * can't rely on the silicon values. | 516 | * can't rely on the silicon values. |
517 | */ | 517 | */ |
518 | ret = wm8350->read_dev(wm8350, 0, | 518 | ret = wm8350->read_dev(wm8350, 0, |
519 | sizeof(u16) * (WM8350_MAX_REGISTER + 1), | 519 | sizeof(u16) * (WM8350_MAX_REGISTER + 1), |
520 | wm8350->reg_cache); | 520 | wm8350->reg_cache); |
521 | if (ret < 0) { | 521 | if (ret < 0) { |
522 | dev_err(wm8350->dev, | 522 | dev_err(wm8350->dev, |
523 | "failed to read initial cache values\n"); | 523 | "failed to read initial cache values\n"); |
524 | goto out; | 524 | goto out; |
525 | } | 525 | } |
526 | 526 | ||
527 | /* Mask out uncacheable/unreadable bits and the audio. */ | 527 | /* Mask out uncacheable/unreadable bits and the audio. */ |
528 | for (i = 0; i < WM8350_MAX_REGISTER; i++) { | 528 | for (i = 0; i < WM8350_MAX_REGISTER; i++) { |
529 | if (wm8350_reg_io_map[i].readable && | 529 | if (wm8350_reg_io_map[i].readable && |
530 | (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { | 530 | (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { |
531 | value = be16_to_cpu(wm8350->reg_cache[i]); | 531 | value = be16_to_cpu(wm8350->reg_cache[i]); |
532 | value &= wm8350_reg_io_map[i].readable; | 532 | value &= wm8350_reg_io_map[i].readable; |
533 | wm8350->reg_cache[i] = value; | 533 | wm8350->reg_cache[i] = value; |
534 | } else | 534 | } else |
535 | wm8350->reg_cache[i] = reg_map[i]; | 535 | wm8350->reg_cache[i] = reg_map[i]; |
536 | } | 536 | } |
537 | 537 | ||
538 | out: | 538 | out: |
539 | kfree(wm8350->reg_cache); | 539 | kfree(wm8350->reg_cache); |
540 | return ret; | 540 | return ret; |
541 | } | 541 | } |
542 | 542 | ||
543 | /* | 543 | /* |
544 | * Register a client device. This is non-fatal since there is no need to | 544 | * Register a client device. This is non-fatal since there is no need to |
545 | * fail the entire device init due to a single platform device failing. | 545 | * fail the entire device init due to a single platform device failing. |
546 | */ | 546 | */ |
547 | static void wm8350_client_dev_register(struct wm8350 *wm8350, | 547 | static void wm8350_client_dev_register(struct wm8350 *wm8350, |
548 | const char *name, | 548 | const char *name, |
549 | struct platform_device **pdev) | 549 | struct platform_device **pdev) |
550 | { | 550 | { |
551 | int ret; | 551 | int ret; |
552 | 552 | ||
553 | *pdev = platform_device_alloc(name, -1); | 553 | *pdev = platform_device_alloc(name, -1); |
554 | if (*pdev == NULL) { | 554 | if (*pdev == NULL) { |
555 | dev_err(wm8350->dev, "Failed to allocate %s\n", name); | 555 | dev_err(wm8350->dev, "Failed to allocate %s\n", name); |
556 | return; | 556 | return; |
557 | } | 557 | } |
558 | 558 | ||
559 | (*pdev)->dev.parent = wm8350->dev; | 559 | (*pdev)->dev.parent = wm8350->dev; |
560 | platform_set_drvdata(*pdev, wm8350); | 560 | platform_set_drvdata(*pdev, wm8350); |
561 | ret = platform_device_add(*pdev); | 561 | ret = platform_device_add(*pdev); |
562 | if (ret != 0) { | 562 | if (ret != 0) { |
563 | dev_err(wm8350->dev, "Failed to register %s: %d\n", name, ret); | 563 | dev_err(wm8350->dev, "Failed to register %s: %d\n", name, ret); |
564 | platform_device_put(*pdev); | 564 | platform_device_put(*pdev); |
565 | *pdev = NULL; | 565 | *pdev = NULL; |
566 | } | 566 | } |
567 | } | 567 | } |
568 | 568 | ||
569 | int wm8350_device_init(struct wm8350 *wm8350, int irq, | 569 | int wm8350_device_init(struct wm8350 *wm8350, int irq, |
570 | struct wm8350_platform_data *pdata) | 570 | struct wm8350_platform_data *pdata) |
571 | { | 571 | { |
572 | int ret; | 572 | int ret; |
573 | u16 id1, id2, mask_rev; | 573 | u16 id1, id2, mask_rev; |
574 | u16 cust_id, mode, chip_rev; | 574 | u16 cust_id, mode, chip_rev; |
575 | 575 | ||
576 | dev_set_drvdata(wm8350->dev, wm8350); | ||
577 | |||
576 | /* get WM8350 revision and config mode */ | 578 | /* get WM8350 revision and config mode */ |
577 | ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1); | 579 | ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1); |
578 | if (ret != 0) { | 580 | if (ret != 0) { |
579 | dev_err(wm8350->dev, "Failed to read ID: %d\n", ret); | 581 | dev_err(wm8350->dev, "Failed to read ID: %d\n", ret); |
580 | goto err; | 582 | goto err; |
581 | } | 583 | } |
582 | 584 | ||
583 | ret = wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2); | 585 | ret = wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2); |
584 | if (ret != 0) { | 586 | if (ret != 0) { |
585 | dev_err(wm8350->dev, "Failed to read ID: %d\n", ret); | 587 | dev_err(wm8350->dev, "Failed to read ID: %d\n", ret); |
586 | goto err; | 588 | goto err; |
587 | } | 589 | } |
588 | 590 | ||
589 | ret = wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), | 591 | ret = wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), |
590 | &mask_rev); | 592 | &mask_rev); |
591 | if (ret != 0) { | 593 | if (ret != 0) { |
592 | dev_err(wm8350->dev, "Failed to read revision: %d\n", ret); | 594 | dev_err(wm8350->dev, "Failed to read revision: %d\n", ret); |
593 | goto err; | 595 | goto err; |
594 | } | 596 | } |
595 | 597 | ||
596 | id1 = be16_to_cpu(id1); | 598 | id1 = be16_to_cpu(id1); |
597 | id2 = be16_to_cpu(id2); | 599 | id2 = be16_to_cpu(id2); |
598 | mask_rev = be16_to_cpu(mask_rev); | 600 | mask_rev = be16_to_cpu(mask_rev); |
599 | 601 | ||
600 | if (id1 != 0x6143) { | 602 | if (id1 != 0x6143) { |
601 | dev_err(wm8350->dev, | 603 | dev_err(wm8350->dev, |
602 | "Device with ID %x is not a WM8350\n", id1); | 604 | "Device with ID %x is not a WM8350\n", id1); |
603 | ret = -ENODEV; | 605 | ret = -ENODEV; |
604 | goto err; | 606 | goto err; |
605 | } | 607 | } |
606 | 608 | ||
607 | mode = id2 & WM8350_CONF_STS_MASK >> 10; | 609 | mode = id2 & WM8350_CONF_STS_MASK >> 10; |
608 | cust_id = id2 & WM8350_CUST_ID_MASK; | 610 | cust_id = id2 & WM8350_CUST_ID_MASK; |
609 | chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12; | 611 | chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12; |
610 | dev_info(wm8350->dev, | 612 | dev_info(wm8350->dev, |
611 | "CONF_STS %d, CUST_ID %d, MASK_REV %d, CHIP_REV %d\n", | 613 | "CONF_STS %d, CUST_ID %d, MASK_REV %d, CHIP_REV %d\n", |
612 | mode, cust_id, mask_rev, chip_rev); | 614 | mode, cust_id, mask_rev, chip_rev); |
613 | 615 | ||
614 | if (cust_id != 0) { | 616 | if (cust_id != 0) { |
615 | dev_err(wm8350->dev, "Unsupported CUST_ID\n"); | 617 | dev_err(wm8350->dev, "Unsupported CUST_ID\n"); |
616 | ret = -ENODEV; | 618 | ret = -ENODEV; |
617 | goto err; | 619 | goto err; |
618 | } | 620 | } |
619 | 621 | ||
620 | switch (mask_rev) { | 622 | switch (mask_rev) { |
621 | case 0: | 623 | case 0: |
622 | wm8350->pmic.max_dcdc = WM8350_DCDC_6; | 624 | wm8350->pmic.max_dcdc = WM8350_DCDC_6; |
623 | wm8350->pmic.max_isink = WM8350_ISINK_B; | 625 | wm8350->pmic.max_isink = WM8350_ISINK_B; |
624 | 626 | ||
625 | switch (chip_rev) { | 627 | switch (chip_rev) { |
626 | case WM8350_REV_E: | 628 | case WM8350_REV_E: |
627 | dev_info(wm8350->dev, "WM8350 Rev E\n"); | 629 | dev_info(wm8350->dev, "WM8350 Rev E\n"); |
628 | break; | 630 | break; |
629 | case WM8350_REV_F: | 631 | case WM8350_REV_F: |
630 | dev_info(wm8350->dev, "WM8350 Rev F\n"); | 632 | dev_info(wm8350->dev, "WM8350 Rev F\n"); |
631 | break; | 633 | break; |
632 | case WM8350_REV_G: | 634 | case WM8350_REV_G: |
633 | dev_info(wm8350->dev, "WM8350 Rev G\n"); | 635 | dev_info(wm8350->dev, "WM8350 Rev G\n"); |
634 | wm8350->power.rev_g_coeff = 1; | 636 | wm8350->power.rev_g_coeff = 1; |
635 | break; | 637 | break; |
636 | case WM8350_REV_H: | 638 | case WM8350_REV_H: |
637 | dev_info(wm8350->dev, "WM8350 Rev H\n"); | 639 | dev_info(wm8350->dev, "WM8350 Rev H\n"); |
638 | wm8350->power.rev_g_coeff = 1; | 640 | wm8350->power.rev_g_coeff = 1; |
639 | break; | 641 | break; |
640 | default: | 642 | default: |
641 | /* For safety we refuse to run on unknown hardware */ | 643 | /* For safety we refuse to run on unknown hardware */ |
642 | dev_err(wm8350->dev, "Unknown WM8350 CHIP_REV\n"); | 644 | dev_err(wm8350->dev, "Unknown WM8350 CHIP_REV\n"); |
643 | ret = -ENODEV; | 645 | ret = -ENODEV; |
644 | goto err; | 646 | goto err; |
645 | } | 647 | } |
646 | break; | 648 | break; |
647 | 649 | ||
648 | case 1: | 650 | case 1: |
649 | wm8350->pmic.max_dcdc = WM8350_DCDC_4; | 651 | wm8350->pmic.max_dcdc = WM8350_DCDC_4; |
650 | wm8350->pmic.max_isink = WM8350_ISINK_A; | 652 | wm8350->pmic.max_isink = WM8350_ISINK_A; |
651 | 653 | ||
652 | switch (chip_rev) { | 654 | switch (chip_rev) { |
653 | case 0: | 655 | case 0: |
654 | dev_info(wm8350->dev, "WM8351 Rev A\n"); | 656 | dev_info(wm8350->dev, "WM8351 Rev A\n"); |
655 | wm8350->power.rev_g_coeff = 1; | 657 | wm8350->power.rev_g_coeff = 1; |
656 | break; | 658 | break; |
657 | 659 | ||
658 | case 1: | 660 | case 1: |
659 | dev_info(wm8350->dev, "WM8351 Rev B\n"); | 661 | dev_info(wm8350->dev, "WM8351 Rev B\n"); |
660 | wm8350->power.rev_g_coeff = 1; | 662 | wm8350->power.rev_g_coeff = 1; |
661 | break; | 663 | break; |
662 | 664 | ||
663 | default: | 665 | default: |
664 | dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n"); | 666 | dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n"); |
665 | ret = -ENODEV; | 667 | ret = -ENODEV; |
666 | goto err; | 668 | goto err; |
667 | } | 669 | } |
668 | break; | 670 | break; |
669 | 671 | ||
670 | case 2: | 672 | case 2: |
671 | wm8350->pmic.max_dcdc = WM8350_DCDC_6; | 673 | wm8350->pmic.max_dcdc = WM8350_DCDC_6; |
672 | wm8350->pmic.max_isink = WM8350_ISINK_B; | 674 | wm8350->pmic.max_isink = WM8350_ISINK_B; |
673 | 675 | ||
674 | switch (chip_rev) { | 676 | switch (chip_rev) { |
675 | case 0: | 677 | case 0: |
676 | dev_info(wm8350->dev, "WM8352 Rev A\n"); | 678 | dev_info(wm8350->dev, "WM8352 Rev A\n"); |
677 | wm8350->power.rev_g_coeff = 1; | 679 | wm8350->power.rev_g_coeff = 1; |
678 | break; | 680 | break; |
679 | 681 | ||
680 | default: | 682 | default: |
681 | dev_err(wm8350->dev, "Unknown WM8352 CHIP_REV\n"); | 683 | dev_err(wm8350->dev, "Unknown WM8352 CHIP_REV\n"); |
682 | ret = -ENODEV; | 684 | ret = -ENODEV; |
683 | goto err; | 685 | goto err; |
684 | } | 686 | } |
685 | break; | 687 | break; |
686 | 688 | ||
687 | default: | 689 | default: |
688 | dev_err(wm8350->dev, "Unknown MASK_REV\n"); | 690 | dev_err(wm8350->dev, "Unknown MASK_REV\n"); |
689 | ret = -ENODEV; | 691 | ret = -ENODEV; |
690 | goto err; | 692 | goto err; |
691 | } | 693 | } |
692 | 694 | ||
693 | ret = wm8350_create_cache(wm8350, mask_rev, mode); | 695 | ret = wm8350_create_cache(wm8350, mask_rev, mode); |
694 | if (ret < 0) { | 696 | if (ret < 0) { |
695 | dev_err(wm8350->dev, "Failed to create register cache\n"); | 697 | dev_err(wm8350->dev, "Failed to create register cache\n"); |
696 | return ret; | 698 | return ret; |
697 | } | 699 | } |
698 | 700 | ||
699 | mutex_init(&wm8350->auxadc_mutex); | 701 | mutex_init(&wm8350->auxadc_mutex); |
700 | init_completion(&wm8350->auxadc_done); | 702 | init_completion(&wm8350->auxadc_done); |
701 | 703 | ||
702 | ret = wm8350_irq_init(wm8350, irq, pdata); | 704 | ret = wm8350_irq_init(wm8350, irq, pdata); |
703 | if (ret < 0) | 705 | if (ret < 0) |
704 | goto err_free; | 706 | goto err_free; |
705 | 707 | ||
706 | if (wm8350->irq_base) { | 708 | if (wm8350->irq_base) { |
707 | ret = request_threaded_irq(wm8350->irq_base + | 709 | ret = request_threaded_irq(wm8350->irq_base + |
708 | WM8350_IRQ_AUXADC_DATARDY, | 710 | WM8350_IRQ_AUXADC_DATARDY, |
709 | NULL, wm8350_auxadc_irq, 0, | 711 | NULL, wm8350_auxadc_irq, 0, |
710 | "auxadc", wm8350); | 712 | "auxadc", wm8350); |
711 | if (ret < 0) | 713 | if (ret < 0) |
712 | dev_warn(wm8350->dev, | 714 | dev_warn(wm8350->dev, |
713 | "Failed to request AUXADC IRQ: %d\n", ret); | 715 | "Failed to request AUXADC IRQ: %d\n", ret); |
714 | } | 716 | } |
715 | 717 | ||
716 | if (pdata && pdata->init) { | 718 | if (pdata && pdata->init) { |
717 | ret = pdata->init(wm8350); | 719 | ret = pdata->init(wm8350); |
718 | if (ret != 0) { | 720 | if (ret != 0) { |
719 | dev_err(wm8350->dev, "Platform init() failed: %d\n", | 721 | dev_err(wm8350->dev, "Platform init() failed: %d\n", |
720 | ret); | 722 | ret); |
721 | goto err_irq; | 723 | goto err_irq; |
722 | } | 724 | } |
723 | } | 725 | } |
724 | 726 | ||
725 | wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0); | 727 | wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0); |
726 | 728 | ||
727 | wm8350_client_dev_register(wm8350, "wm8350-codec", | 729 | wm8350_client_dev_register(wm8350, "wm8350-codec", |
728 | &(wm8350->codec.pdev)); | 730 | &(wm8350->codec.pdev)); |
729 | wm8350_client_dev_register(wm8350, "wm8350-gpio", | 731 | wm8350_client_dev_register(wm8350, "wm8350-gpio", |
730 | &(wm8350->gpio.pdev)); | 732 | &(wm8350->gpio.pdev)); |
731 | wm8350_client_dev_register(wm8350, "wm8350-hwmon", | 733 | wm8350_client_dev_register(wm8350, "wm8350-hwmon", |
732 | &(wm8350->hwmon.pdev)); | 734 | &(wm8350->hwmon.pdev)); |
733 | wm8350_client_dev_register(wm8350, "wm8350-power", | 735 | wm8350_client_dev_register(wm8350, "wm8350-power", |
734 | &(wm8350->power.pdev)); | 736 | &(wm8350->power.pdev)); |
735 | wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev)); | 737 | wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev)); |
736 | wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev)); | 738 | wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev)); |
737 | 739 | ||
738 | return 0; | 740 | return 0; |
739 | 741 | ||
740 | err_irq: | 742 | err_irq: |
741 | wm8350_irq_exit(wm8350); | 743 | wm8350_irq_exit(wm8350); |
742 | err_free: | 744 | err_free: |
743 | kfree(wm8350->reg_cache); | 745 | kfree(wm8350->reg_cache); |
744 | err: | 746 | err: |
745 | return ret; | 747 | return ret; |
746 | } | 748 | } |
747 | EXPORT_SYMBOL_GPL(wm8350_device_init); | 749 | EXPORT_SYMBOL_GPL(wm8350_device_init); |
748 | 750 | ||
749 | void wm8350_device_exit(struct wm8350 *wm8350) | 751 | void wm8350_device_exit(struct wm8350 *wm8350) |
750 | { | 752 | { |
751 | int i; | 753 | int i; |
752 | 754 | ||
753 | for (i = 0; i < ARRAY_SIZE(wm8350->pmic.led); i++) | 755 | for (i = 0; i < ARRAY_SIZE(wm8350->pmic.led); i++) |
754 | platform_device_unregister(wm8350->pmic.led[i].pdev); | 756 | platform_device_unregister(wm8350->pmic.led[i].pdev); |
755 | 757 | ||
756 | for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++) | 758 | for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++) |
757 | platform_device_unregister(wm8350->pmic.pdev[i]); | 759 | platform_device_unregister(wm8350->pmic.pdev[i]); |
758 | 760 | ||
759 | platform_device_unregister(wm8350->wdt.pdev); | 761 | platform_device_unregister(wm8350->wdt.pdev); |
760 | platform_device_unregister(wm8350->rtc.pdev); | 762 | platform_device_unregister(wm8350->rtc.pdev); |
761 | platform_device_unregister(wm8350->power.pdev); | 763 | platform_device_unregister(wm8350->power.pdev); |
762 | platform_device_unregister(wm8350->hwmon.pdev); | 764 | platform_device_unregister(wm8350->hwmon.pdev); |
763 | platform_device_unregister(wm8350->gpio.pdev); | 765 | platform_device_unregister(wm8350->gpio.pdev); |
764 | platform_device_unregister(wm8350->codec.pdev); | 766 | platform_device_unregister(wm8350->codec.pdev); |
765 | 767 | ||
766 | if (wm8350->irq_base) | 768 | if (wm8350->irq_base) |
767 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); | 769 | free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); |
768 | 770 | ||
769 | wm8350_irq_exit(wm8350); | 771 | wm8350_irq_exit(wm8350); |
770 | 772 | ||
771 | kfree(wm8350->reg_cache); | 773 | kfree(wm8350->reg_cache); |
772 | } | 774 | } |
773 | EXPORT_SYMBOL_GPL(wm8350_device_exit); | 775 | EXPORT_SYMBOL_GPL(wm8350_device_exit); |
774 | 776 | ||
775 | MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver"); | 777 | MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver"); |
776 | MODULE_LICENSE("GPL"); | 778 | MODULE_LICENSE("GPL"); |
777 | 779 |