Commit 3b8ce3aed986090d9249629f97c53b4dfb8c9783
1 parent
8f7346bdea
Exists in
master
and in
6 other branches
mfd: fix build failures in recently added ab5500 code
These files had implicit dependencies on modular support which now show up as build failures with the module cleanup work merged to mainline. Reported-by: Axel Lin <axel.lin@gmail.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Showing 2 changed files with 2 additions and 0 deletions Inline Diff
drivers/mfd/ab5500-core.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2007-2011 ST-Ericsson | 2 | * Copyright (C) 2007-2011 ST-Ericsson |
3 | * License terms: GNU General Public License (GPL) version 2 | 3 | * License terms: GNU General Public License (GPL) version 2 |
4 | * Low-level core for exclusive access to the AB5500 IC on the I2C bus | 4 | * Low-level core for exclusive access to the AB5500 IC on the I2C bus |
5 | * and some basic chip-configuration. | 5 | * and some basic chip-configuration. |
6 | * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> | 6 | * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> |
7 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> | 7 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> |
8 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> | 8 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> |
9 | * Author: Rickard Andersson <rickard.andersson@stericsson.com> | 9 | * Author: Rickard Andersson <rickard.andersson@stericsson.com> |
10 | * Author: Karl Komierowski <karl.komierowski@stericsson.com> | 10 | * Author: Karl Komierowski <karl.komierowski@stericsson.com> |
11 | * Author: Bibek Basu <bibek.basu@stericsson.com> | 11 | * Author: Bibek Basu <bibek.basu@stericsson.com> |
12 | * | 12 | * |
13 | * TODO: Event handling with irq_chip. Waiting for PRCMU fw support. | 13 | * TODO: Event handling with irq_chip. Waiting for PRCMU fw support. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | ||
16 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
21 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/random.h> | 24 | #include <linux/random.h> |
24 | #include <linux/mfd/ab5500/ab5500.h> | 25 | #include <linux/mfd/ab5500/ab5500.h> |
25 | #include <linux/mfd/abx500.h> | 26 | #include <linux/mfd/abx500.h> |
26 | #include <linux/list.h> | 27 | #include <linux/list.h> |
27 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
28 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
29 | #include <linux/mfd/core.h> | 30 | #include <linux/mfd/core.h> |
30 | #include <linux/version.h> | 31 | #include <linux/version.h> |
31 | #include <linux/mfd/db5500-prcmu.h> | 32 | #include <linux/mfd/db5500-prcmu.h> |
32 | 33 | ||
33 | #include "ab5500-core.h" | 34 | #include "ab5500-core.h" |
34 | #include "ab5500-debugfs.h" | 35 | #include "ab5500-debugfs.h" |
35 | 36 | ||
36 | #define AB5500_NUM_EVENT_REG 23 | 37 | #define AB5500_NUM_EVENT_REG 23 |
37 | #define AB5500_IT_LATCH0_REG 0x40 | 38 | #define AB5500_IT_LATCH0_REG 0x40 |
38 | #define AB5500_IT_MASK0_REG 0x60 | 39 | #define AB5500_IT_MASK0_REG 0x60 |
39 | 40 | ||
40 | /* | 41 | /* |
41 | * Permissible register ranges for reading and writing per device and bank. | 42 | * Permissible register ranges for reading and writing per device and bank. |
42 | * | 43 | * |
43 | * The ranges must be listed in increasing address order, and no overlaps are | 44 | * The ranges must be listed in increasing address order, and no overlaps are |
44 | * allowed. It is assumed that write permission implies read permission | 45 | * allowed. It is assumed that write permission implies read permission |
45 | * (i.e. only RO and RW permissions should be used). Ranges with write | 46 | * (i.e. only RO and RW permissions should be used). Ranges with write |
46 | * permission must not be split up. | 47 | * permission must not be split up. |
47 | */ | 48 | */ |
48 | 49 | ||
49 | #define NO_RANGE {.count = 0, .range = NULL,} | 50 | #define NO_RANGE {.count = 0, .range = NULL,} |
50 | static struct ab5500_i2c_banks ab5500_bank_ranges[AB5500_NUM_DEVICES] = { | 51 | static struct ab5500_i2c_banks ab5500_bank_ranges[AB5500_NUM_DEVICES] = { |
51 | [AB5500_DEVID_USB] = { | 52 | [AB5500_DEVID_USB] = { |
52 | .nbanks = 1, | 53 | .nbanks = 1, |
53 | .bank = (struct ab5500_i2c_ranges []) { | 54 | .bank = (struct ab5500_i2c_ranges []) { |
54 | { | 55 | { |
55 | .bankid = AB5500_BANK_USB, | 56 | .bankid = AB5500_BANK_USB, |
56 | .nranges = 12, | 57 | .nranges = 12, |
57 | .range = (struct ab5500_reg_range[]) { | 58 | .range = (struct ab5500_reg_range[]) { |
58 | { | 59 | { |
59 | .first = 0x01, | 60 | .first = 0x01, |
60 | .last = 0x01, | 61 | .last = 0x01, |
61 | .perm = AB5500_PERM_RW, | 62 | .perm = AB5500_PERM_RW, |
62 | }, | 63 | }, |
63 | { | 64 | { |
64 | .first = 0x80, | 65 | .first = 0x80, |
65 | .last = 0x83, | 66 | .last = 0x83, |
66 | .perm = AB5500_PERM_RW, | 67 | .perm = AB5500_PERM_RW, |
67 | }, | 68 | }, |
68 | { | 69 | { |
69 | .first = 0x87, | 70 | .first = 0x87, |
70 | .last = 0x8A, | 71 | .last = 0x8A, |
71 | .perm = AB5500_PERM_RW, | 72 | .perm = AB5500_PERM_RW, |
72 | }, | 73 | }, |
73 | { | 74 | { |
74 | .first = 0x8B, | 75 | .first = 0x8B, |
75 | .last = 0x8B, | 76 | .last = 0x8B, |
76 | .perm = AB5500_PERM_RO, | 77 | .perm = AB5500_PERM_RO, |
77 | }, | 78 | }, |
78 | { | 79 | { |
79 | .first = 0x91, | 80 | .first = 0x91, |
80 | .last = 0x92, | 81 | .last = 0x92, |
81 | .perm = AB5500_PERM_RO, | 82 | .perm = AB5500_PERM_RO, |
82 | }, | 83 | }, |
83 | { | 84 | { |
84 | .first = 0x93, | 85 | .first = 0x93, |
85 | .last = 0x93, | 86 | .last = 0x93, |
86 | .perm = AB5500_PERM_RW, | 87 | .perm = AB5500_PERM_RW, |
87 | }, | 88 | }, |
88 | { | 89 | { |
89 | .first = 0x94, | 90 | .first = 0x94, |
90 | .last = 0x94, | 91 | .last = 0x94, |
91 | .perm = AB5500_PERM_RO, | 92 | .perm = AB5500_PERM_RO, |
92 | }, | 93 | }, |
93 | { | 94 | { |
94 | .first = 0xA8, | 95 | .first = 0xA8, |
95 | .last = 0xB0, | 96 | .last = 0xB0, |
96 | .perm = AB5500_PERM_RO, | 97 | .perm = AB5500_PERM_RO, |
97 | }, | 98 | }, |
98 | { | 99 | { |
99 | .first = 0xB2, | 100 | .first = 0xB2, |
100 | .last = 0xB2, | 101 | .last = 0xB2, |
101 | .perm = AB5500_PERM_RO, | 102 | .perm = AB5500_PERM_RO, |
102 | }, | 103 | }, |
103 | { | 104 | { |
104 | .first = 0xB4, | 105 | .first = 0xB4, |
105 | .last = 0xBC, | 106 | .last = 0xBC, |
106 | .perm = AB5500_PERM_RO, | 107 | .perm = AB5500_PERM_RO, |
107 | }, | 108 | }, |
108 | { | 109 | { |
109 | .first = 0xBF, | 110 | .first = 0xBF, |
110 | .last = 0xBF, | 111 | .last = 0xBF, |
111 | .perm = AB5500_PERM_RO, | 112 | .perm = AB5500_PERM_RO, |
112 | }, | 113 | }, |
113 | { | 114 | { |
114 | .first = 0xC1, | 115 | .first = 0xC1, |
115 | .last = 0xC5, | 116 | .last = 0xC5, |
116 | .perm = AB5500_PERM_RO, | 117 | .perm = AB5500_PERM_RO, |
117 | }, | 118 | }, |
118 | }, | 119 | }, |
119 | }, | 120 | }, |
120 | }, | 121 | }, |
121 | }, | 122 | }, |
122 | [AB5500_DEVID_ADC] = { | 123 | [AB5500_DEVID_ADC] = { |
123 | .nbanks = 1, | 124 | .nbanks = 1, |
124 | .bank = (struct ab5500_i2c_ranges []) { | 125 | .bank = (struct ab5500_i2c_ranges []) { |
125 | { | 126 | { |
126 | .bankid = AB5500_BANK_ADC, | 127 | .bankid = AB5500_BANK_ADC, |
127 | .nranges = 6, | 128 | .nranges = 6, |
128 | .range = (struct ab5500_reg_range[]) { | 129 | .range = (struct ab5500_reg_range[]) { |
129 | { | 130 | { |
130 | .first = 0x1F, | 131 | .first = 0x1F, |
131 | .last = 0x22, | 132 | .last = 0x22, |
132 | .perm = AB5500_PERM_RO, | 133 | .perm = AB5500_PERM_RO, |
133 | }, | 134 | }, |
134 | { | 135 | { |
135 | .first = 0x23, | 136 | .first = 0x23, |
136 | .last = 0x24, | 137 | .last = 0x24, |
137 | .perm = AB5500_PERM_RW, | 138 | .perm = AB5500_PERM_RW, |
138 | }, | 139 | }, |
139 | { | 140 | { |
140 | .first = 0x26, | 141 | .first = 0x26, |
141 | .last = 0x2D, | 142 | .last = 0x2D, |
142 | .perm = AB5500_PERM_RO, | 143 | .perm = AB5500_PERM_RO, |
143 | }, | 144 | }, |
144 | { | 145 | { |
145 | .first = 0x2F, | 146 | .first = 0x2F, |
146 | .last = 0x34, | 147 | .last = 0x34, |
147 | .perm = AB5500_PERM_RW, | 148 | .perm = AB5500_PERM_RW, |
148 | }, | 149 | }, |
149 | { | 150 | { |
150 | .first = 0x37, | 151 | .first = 0x37, |
151 | .last = 0x57, | 152 | .last = 0x57, |
152 | .perm = AB5500_PERM_RW, | 153 | .perm = AB5500_PERM_RW, |
153 | }, | 154 | }, |
154 | { | 155 | { |
155 | .first = 0x58, | 156 | .first = 0x58, |
156 | .last = 0x58, | 157 | .last = 0x58, |
157 | .perm = AB5500_PERM_RO, | 158 | .perm = AB5500_PERM_RO, |
158 | }, | 159 | }, |
159 | }, | 160 | }, |
160 | }, | 161 | }, |
161 | }, | 162 | }, |
162 | }, | 163 | }, |
163 | [AB5500_DEVID_LEDS] = { | 164 | [AB5500_DEVID_LEDS] = { |
164 | .nbanks = 1, | 165 | .nbanks = 1, |
165 | .bank = (struct ab5500_i2c_ranges []) { | 166 | .bank = (struct ab5500_i2c_ranges []) { |
166 | { | 167 | { |
167 | .bankid = AB5500_BANK_LED, | 168 | .bankid = AB5500_BANK_LED, |
168 | .nranges = 1, | 169 | .nranges = 1, |
169 | .range = (struct ab5500_reg_range[]) { | 170 | .range = (struct ab5500_reg_range[]) { |
170 | { | 171 | { |
171 | .first = 0x00, | 172 | .first = 0x00, |
172 | .last = 0x0C, | 173 | .last = 0x0C, |
173 | .perm = AB5500_PERM_RW, | 174 | .perm = AB5500_PERM_RW, |
174 | }, | 175 | }, |
175 | }, | 176 | }, |
176 | }, | 177 | }, |
177 | }, | 178 | }, |
178 | }, | 179 | }, |
179 | [AB5500_DEVID_VIDEO] = { | 180 | [AB5500_DEVID_VIDEO] = { |
180 | .nbanks = 1, | 181 | .nbanks = 1, |
181 | .bank = (struct ab5500_i2c_ranges []) { | 182 | .bank = (struct ab5500_i2c_ranges []) { |
182 | { | 183 | { |
183 | .bankid = AB5500_BANK_VDENC, | 184 | .bankid = AB5500_BANK_VDENC, |
184 | .nranges = 12, | 185 | .nranges = 12, |
185 | .range = (struct ab5500_reg_range[]) { | 186 | .range = (struct ab5500_reg_range[]) { |
186 | { | 187 | { |
187 | .first = 0x00, | 188 | .first = 0x00, |
188 | .last = 0x08, | 189 | .last = 0x08, |
189 | .perm = AB5500_PERM_RW, | 190 | .perm = AB5500_PERM_RW, |
190 | }, | 191 | }, |
191 | { | 192 | { |
192 | .first = 0x09, | 193 | .first = 0x09, |
193 | .last = 0x09, | 194 | .last = 0x09, |
194 | .perm = AB5500_PERM_RO, | 195 | .perm = AB5500_PERM_RO, |
195 | }, | 196 | }, |
196 | { | 197 | { |
197 | .first = 0x0A, | 198 | .first = 0x0A, |
198 | .last = 0x12, | 199 | .last = 0x12, |
199 | .perm = AB5500_PERM_RW, | 200 | .perm = AB5500_PERM_RW, |
200 | }, | 201 | }, |
201 | { | 202 | { |
202 | .first = 0x15, | 203 | .first = 0x15, |
203 | .last = 0x19, | 204 | .last = 0x19, |
204 | .perm = AB5500_PERM_RW, | 205 | .perm = AB5500_PERM_RW, |
205 | }, | 206 | }, |
206 | { | 207 | { |
207 | .first = 0x1B, | 208 | .first = 0x1B, |
208 | .last = 0x21, | 209 | .last = 0x21, |
209 | .perm = AB5500_PERM_RW, | 210 | .perm = AB5500_PERM_RW, |
210 | }, | 211 | }, |
211 | { | 212 | { |
212 | .first = 0x27, | 213 | .first = 0x27, |
213 | .last = 0x2C, | 214 | .last = 0x2C, |
214 | .perm = AB5500_PERM_RW, | 215 | .perm = AB5500_PERM_RW, |
215 | }, | 216 | }, |
216 | { | 217 | { |
217 | .first = 0x41, | 218 | .first = 0x41, |
218 | .last = 0x41, | 219 | .last = 0x41, |
219 | .perm = AB5500_PERM_RW, | 220 | .perm = AB5500_PERM_RW, |
220 | }, | 221 | }, |
221 | { | 222 | { |
222 | .first = 0x45, | 223 | .first = 0x45, |
223 | .last = 0x5B, | 224 | .last = 0x5B, |
224 | .perm = AB5500_PERM_RW, | 225 | .perm = AB5500_PERM_RW, |
225 | }, | 226 | }, |
226 | { | 227 | { |
227 | .first = 0x5D, | 228 | .first = 0x5D, |
228 | .last = 0x5D, | 229 | .last = 0x5D, |
229 | .perm = AB5500_PERM_RW, | 230 | .perm = AB5500_PERM_RW, |
230 | }, | 231 | }, |
231 | { | 232 | { |
232 | .first = 0x69, | 233 | .first = 0x69, |
233 | .last = 0x69, | 234 | .last = 0x69, |
234 | .perm = AB5500_PERM_RW, | 235 | .perm = AB5500_PERM_RW, |
235 | }, | 236 | }, |
236 | { | 237 | { |
237 | .first = 0x6C, | 238 | .first = 0x6C, |
238 | .last = 0x6D, | 239 | .last = 0x6D, |
239 | .perm = AB5500_PERM_RW, | 240 | .perm = AB5500_PERM_RW, |
240 | }, | 241 | }, |
241 | { | 242 | { |
242 | .first = 0x80, | 243 | .first = 0x80, |
243 | .last = 0x81, | 244 | .last = 0x81, |
244 | .perm = AB5500_PERM_RW, | 245 | .perm = AB5500_PERM_RW, |
245 | }, | 246 | }, |
246 | }, | 247 | }, |
247 | }, | 248 | }, |
248 | }, | 249 | }, |
249 | }, | 250 | }, |
250 | [AB5500_DEVID_REGULATORS] = { | 251 | [AB5500_DEVID_REGULATORS] = { |
251 | .nbanks = 2, | 252 | .nbanks = 2, |
252 | .bank = (struct ab5500_i2c_ranges []) { | 253 | .bank = (struct ab5500_i2c_ranges []) { |
253 | { | 254 | { |
254 | .bankid = AB5500_BANK_STARTUP, | 255 | .bankid = AB5500_BANK_STARTUP, |
255 | .nranges = 12, | 256 | .nranges = 12, |
256 | .range = (struct ab5500_reg_range[]) { | 257 | .range = (struct ab5500_reg_range[]) { |
257 | { | 258 | { |
258 | .first = 0x00, | 259 | .first = 0x00, |
259 | .last = 0x01, | 260 | .last = 0x01, |
260 | .perm = AB5500_PERM_RW, | 261 | .perm = AB5500_PERM_RW, |
261 | }, | 262 | }, |
262 | { | 263 | { |
263 | .first = 0x1F, | 264 | .first = 0x1F, |
264 | .last = 0x1F, | 265 | .last = 0x1F, |
265 | .perm = AB5500_PERM_RW, | 266 | .perm = AB5500_PERM_RW, |
266 | }, | 267 | }, |
267 | { | 268 | { |
268 | .first = 0x2E, | 269 | .first = 0x2E, |
269 | .last = 0x2E, | 270 | .last = 0x2E, |
270 | .perm = AB5500_PERM_RO, | 271 | .perm = AB5500_PERM_RO, |
271 | }, | 272 | }, |
272 | { | 273 | { |
273 | .first = 0x2F, | 274 | .first = 0x2F, |
274 | .last = 0x30, | 275 | .last = 0x30, |
275 | .perm = AB5500_PERM_RW, | 276 | .perm = AB5500_PERM_RW, |
276 | }, | 277 | }, |
277 | { | 278 | { |
278 | .first = 0x50, | 279 | .first = 0x50, |
279 | .last = 0x51, | 280 | .last = 0x51, |
280 | .perm = AB5500_PERM_RW, | 281 | .perm = AB5500_PERM_RW, |
281 | }, | 282 | }, |
282 | { | 283 | { |
283 | .first = 0x60, | 284 | .first = 0x60, |
284 | .last = 0x61, | 285 | .last = 0x61, |
285 | .perm = AB5500_PERM_RW, | 286 | .perm = AB5500_PERM_RW, |
286 | }, | 287 | }, |
287 | { | 288 | { |
288 | .first = 0x66, | 289 | .first = 0x66, |
289 | .last = 0x8A, | 290 | .last = 0x8A, |
290 | .perm = AB5500_PERM_RW, | 291 | .perm = AB5500_PERM_RW, |
291 | }, | 292 | }, |
292 | { | 293 | { |
293 | .first = 0x8C, | 294 | .first = 0x8C, |
294 | .last = 0x96, | 295 | .last = 0x96, |
295 | .perm = AB5500_PERM_RW, | 296 | .perm = AB5500_PERM_RW, |
296 | }, | 297 | }, |
297 | { | 298 | { |
298 | .first = 0xAA, | 299 | .first = 0xAA, |
299 | .last = 0xB4, | 300 | .last = 0xB4, |
300 | .perm = AB5500_PERM_RW, | 301 | .perm = AB5500_PERM_RW, |
301 | }, | 302 | }, |
302 | { | 303 | { |
303 | .first = 0xB7, | 304 | .first = 0xB7, |
304 | .last = 0xBF, | 305 | .last = 0xBF, |
305 | .perm = AB5500_PERM_RW, | 306 | .perm = AB5500_PERM_RW, |
306 | }, | 307 | }, |
307 | { | 308 | { |
308 | .first = 0xC1, | 309 | .first = 0xC1, |
309 | .last = 0xCA, | 310 | .last = 0xCA, |
310 | .perm = AB5500_PERM_RW, | 311 | .perm = AB5500_PERM_RW, |
311 | }, | 312 | }, |
312 | { | 313 | { |
313 | .first = 0xD3, | 314 | .first = 0xD3, |
314 | .last = 0xE0, | 315 | .last = 0xE0, |
315 | .perm = AB5500_PERM_RW, | 316 | .perm = AB5500_PERM_RW, |
316 | }, | 317 | }, |
317 | }, | 318 | }, |
318 | }, | 319 | }, |
319 | { | 320 | { |
320 | .bankid = AB5500_BANK_SIM_USBSIM, | 321 | .bankid = AB5500_BANK_SIM_USBSIM, |
321 | .nranges = 1, | 322 | .nranges = 1, |
322 | .range = (struct ab5500_reg_range[]) { | 323 | .range = (struct ab5500_reg_range[]) { |
323 | { | 324 | { |
324 | .first = 0x13, | 325 | .first = 0x13, |
325 | .last = 0x19, | 326 | .last = 0x19, |
326 | .perm = AB5500_PERM_RW, | 327 | .perm = AB5500_PERM_RW, |
327 | }, | 328 | }, |
328 | }, | 329 | }, |
329 | }, | 330 | }, |
330 | }, | 331 | }, |
331 | }, | 332 | }, |
332 | [AB5500_DEVID_SIM] = { | 333 | [AB5500_DEVID_SIM] = { |
333 | .nbanks = 1, | 334 | .nbanks = 1, |
334 | .bank = (struct ab5500_i2c_ranges []) { | 335 | .bank = (struct ab5500_i2c_ranges []) { |
335 | { | 336 | { |
336 | .bankid = AB5500_BANK_SIM_USBSIM, | 337 | .bankid = AB5500_BANK_SIM_USBSIM, |
337 | .nranges = 1, | 338 | .nranges = 1, |
338 | .range = (struct ab5500_reg_range[]) { | 339 | .range = (struct ab5500_reg_range[]) { |
339 | { | 340 | { |
340 | .first = 0x13, | 341 | .first = 0x13, |
341 | .last = 0x19, | 342 | .last = 0x19, |
342 | .perm = AB5500_PERM_RW, | 343 | .perm = AB5500_PERM_RW, |
343 | }, | 344 | }, |
344 | }, | 345 | }, |
345 | }, | 346 | }, |
346 | }, | 347 | }, |
347 | }, | 348 | }, |
348 | [AB5500_DEVID_RTC] = { | 349 | [AB5500_DEVID_RTC] = { |
349 | .nbanks = 1, | 350 | .nbanks = 1, |
350 | .bank = (struct ab5500_i2c_ranges []) { | 351 | .bank = (struct ab5500_i2c_ranges []) { |
351 | { | 352 | { |
352 | .bankid = AB5500_BANK_RTC, | 353 | .bankid = AB5500_BANK_RTC, |
353 | .nranges = 2, | 354 | .nranges = 2, |
354 | .range = (struct ab5500_reg_range[]) { | 355 | .range = (struct ab5500_reg_range[]) { |
355 | { | 356 | { |
356 | .first = 0x00, | 357 | .first = 0x00, |
357 | .last = 0x04, | 358 | .last = 0x04, |
358 | .perm = AB5500_PERM_RW, | 359 | .perm = AB5500_PERM_RW, |
359 | }, | 360 | }, |
360 | { | 361 | { |
361 | .first = 0x06, | 362 | .first = 0x06, |
362 | .last = 0x0C, | 363 | .last = 0x0C, |
363 | .perm = AB5500_PERM_RW, | 364 | .perm = AB5500_PERM_RW, |
364 | }, | 365 | }, |
365 | }, | 366 | }, |
366 | }, | 367 | }, |
367 | }, | 368 | }, |
368 | }, | 369 | }, |
369 | [AB5500_DEVID_CHARGER] = { | 370 | [AB5500_DEVID_CHARGER] = { |
370 | .nbanks = 1, | 371 | .nbanks = 1, |
371 | .bank = (struct ab5500_i2c_ranges []) { | 372 | .bank = (struct ab5500_i2c_ranges []) { |
372 | { | 373 | { |
373 | .bankid = AB5500_BANK_CHG, | 374 | .bankid = AB5500_BANK_CHG, |
374 | .nranges = 2, | 375 | .nranges = 2, |
375 | .range = (struct ab5500_reg_range[]) { | 376 | .range = (struct ab5500_reg_range[]) { |
376 | { | 377 | { |
377 | .first = 0x11, | 378 | .first = 0x11, |
378 | .last = 0x11, | 379 | .last = 0x11, |
379 | .perm = AB5500_PERM_RO, | 380 | .perm = AB5500_PERM_RO, |
380 | }, | 381 | }, |
381 | { | 382 | { |
382 | .first = 0x12, | 383 | .first = 0x12, |
383 | .last = 0x1B, | 384 | .last = 0x1B, |
384 | .perm = AB5500_PERM_RW, | 385 | .perm = AB5500_PERM_RW, |
385 | }, | 386 | }, |
386 | }, | 387 | }, |
387 | }, | 388 | }, |
388 | }, | 389 | }, |
389 | }, | 390 | }, |
390 | [AB5500_DEVID_FUELGAUGE] = { | 391 | [AB5500_DEVID_FUELGAUGE] = { |
391 | .nbanks = 1, | 392 | .nbanks = 1, |
392 | .bank = (struct ab5500_i2c_ranges []) { | 393 | .bank = (struct ab5500_i2c_ranges []) { |
393 | { | 394 | { |
394 | .bankid = AB5500_BANK_FG_BATTCOM_ACC, | 395 | .bankid = AB5500_BANK_FG_BATTCOM_ACC, |
395 | .nranges = 2, | 396 | .nranges = 2, |
396 | .range = (struct ab5500_reg_range[]) { | 397 | .range = (struct ab5500_reg_range[]) { |
397 | { | 398 | { |
398 | .first = 0x00, | 399 | .first = 0x00, |
399 | .last = 0x0B, | 400 | .last = 0x0B, |
400 | .perm = AB5500_PERM_RO, | 401 | .perm = AB5500_PERM_RO, |
401 | }, | 402 | }, |
402 | { | 403 | { |
403 | .first = 0x0C, | 404 | .first = 0x0C, |
404 | .last = 0x10, | 405 | .last = 0x10, |
405 | .perm = AB5500_PERM_RW, | 406 | .perm = AB5500_PERM_RW, |
406 | }, | 407 | }, |
407 | }, | 408 | }, |
408 | }, | 409 | }, |
409 | }, | 410 | }, |
410 | }, | 411 | }, |
411 | [AB5500_DEVID_VIBRATOR] = { | 412 | [AB5500_DEVID_VIBRATOR] = { |
412 | .nbanks = 1, | 413 | .nbanks = 1, |
413 | .bank = (struct ab5500_i2c_ranges []) { | 414 | .bank = (struct ab5500_i2c_ranges []) { |
414 | { | 415 | { |
415 | .bankid = AB5500_BANK_VIBRA, | 416 | .bankid = AB5500_BANK_VIBRA, |
416 | .nranges = 2, | 417 | .nranges = 2, |
417 | .range = (struct ab5500_reg_range[]) { | 418 | .range = (struct ab5500_reg_range[]) { |
418 | { | 419 | { |
419 | .first = 0x10, | 420 | .first = 0x10, |
420 | .last = 0x13, | 421 | .last = 0x13, |
421 | .perm = AB5500_PERM_RW, | 422 | .perm = AB5500_PERM_RW, |
422 | }, | 423 | }, |
423 | { | 424 | { |
424 | .first = 0xFE, | 425 | .first = 0xFE, |
425 | .last = 0xFE, | 426 | .last = 0xFE, |
426 | .perm = AB5500_PERM_RW, | 427 | .perm = AB5500_PERM_RW, |
427 | }, | 428 | }, |
428 | }, | 429 | }, |
429 | }, | 430 | }, |
430 | }, | 431 | }, |
431 | }, | 432 | }, |
432 | [AB5500_DEVID_CODEC] = { | 433 | [AB5500_DEVID_CODEC] = { |
433 | .nbanks = 1, | 434 | .nbanks = 1, |
434 | .bank = (struct ab5500_i2c_ranges []) { | 435 | .bank = (struct ab5500_i2c_ranges []) { |
435 | { | 436 | { |
436 | .bankid = AB5500_BANK_AUDIO_HEADSETUSB, | 437 | .bankid = AB5500_BANK_AUDIO_HEADSETUSB, |
437 | .nranges = 2, | 438 | .nranges = 2, |
438 | .range = (struct ab5500_reg_range[]) { | 439 | .range = (struct ab5500_reg_range[]) { |
439 | { | 440 | { |
440 | .first = 0x00, | 441 | .first = 0x00, |
441 | .last = 0x48, | 442 | .last = 0x48, |
442 | .perm = AB5500_PERM_RW, | 443 | .perm = AB5500_PERM_RW, |
443 | }, | 444 | }, |
444 | { | 445 | { |
445 | .first = 0xEB, | 446 | .first = 0xEB, |
446 | .last = 0xFB, | 447 | .last = 0xFB, |
447 | .perm = AB5500_PERM_RW, | 448 | .perm = AB5500_PERM_RW, |
448 | }, | 449 | }, |
449 | }, | 450 | }, |
450 | }, | 451 | }, |
451 | }, | 452 | }, |
452 | }, | 453 | }, |
453 | [AB5500_DEVID_POWER] = { | 454 | [AB5500_DEVID_POWER] = { |
454 | .nbanks = 2, | 455 | .nbanks = 2, |
455 | .bank = (struct ab5500_i2c_ranges []) { | 456 | .bank = (struct ab5500_i2c_ranges []) { |
456 | { | 457 | { |
457 | .bankid = AB5500_BANK_STARTUP, | 458 | .bankid = AB5500_BANK_STARTUP, |
458 | .nranges = 1, | 459 | .nranges = 1, |
459 | .range = (struct ab5500_reg_range[]) { | 460 | .range = (struct ab5500_reg_range[]) { |
460 | { | 461 | { |
461 | .first = 0x30, | 462 | .first = 0x30, |
462 | .last = 0x30, | 463 | .last = 0x30, |
463 | .perm = AB5500_PERM_RW, | 464 | .perm = AB5500_PERM_RW, |
464 | }, | 465 | }, |
465 | }, | 466 | }, |
466 | }, | 467 | }, |
467 | { | 468 | { |
468 | .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, | 469 | .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, |
469 | .nranges = 1, | 470 | .nranges = 1, |
470 | .range = (struct ab5500_reg_range[]) { | 471 | .range = (struct ab5500_reg_range[]) { |
471 | { | 472 | { |
472 | .first = 0x01, | 473 | .first = 0x01, |
473 | .last = 0x01, | 474 | .last = 0x01, |
474 | .perm = AB5500_PERM_RW, | 475 | .perm = AB5500_PERM_RW, |
475 | }, | 476 | }, |
476 | }, | 477 | }, |
477 | }, | 478 | }, |
478 | }, | 479 | }, |
479 | }, | 480 | }, |
480 | }; | 481 | }; |
481 | 482 | ||
482 | #define AB5500_IRQ(bank, bit) ((bank) * 8 + (bit)) | 483 | #define AB5500_IRQ(bank, bit) ((bank) * 8 + (bit)) |
483 | 484 | ||
484 | /* I appologize for the resource names beeing a mix of upper case | 485 | /* I appologize for the resource names beeing a mix of upper case |
485 | * and lower case but I want them to be exact as the documentation */ | 486 | * and lower case but I want them to be exact as the documentation */ |
486 | static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { | 487 | static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { |
487 | [AB5500_DEVID_LEDS] = { | 488 | [AB5500_DEVID_LEDS] = { |
488 | .name = "ab5500-leds", | 489 | .name = "ab5500-leds", |
489 | .id = AB5500_DEVID_LEDS, | 490 | .id = AB5500_DEVID_LEDS, |
490 | }, | 491 | }, |
491 | [AB5500_DEVID_POWER] = { | 492 | [AB5500_DEVID_POWER] = { |
492 | .name = "ab5500-power", | 493 | .name = "ab5500-power", |
493 | .id = AB5500_DEVID_POWER, | 494 | .id = AB5500_DEVID_POWER, |
494 | }, | 495 | }, |
495 | [AB5500_DEVID_REGULATORS] = { | 496 | [AB5500_DEVID_REGULATORS] = { |
496 | .name = "ab5500-regulator", | 497 | .name = "ab5500-regulator", |
497 | .id = AB5500_DEVID_REGULATORS, | 498 | .id = AB5500_DEVID_REGULATORS, |
498 | }, | 499 | }, |
499 | [AB5500_DEVID_SIM] = { | 500 | [AB5500_DEVID_SIM] = { |
500 | .name = "ab5500-sim", | 501 | .name = "ab5500-sim", |
501 | .id = AB5500_DEVID_SIM, | 502 | .id = AB5500_DEVID_SIM, |
502 | .num_resources = 1, | 503 | .num_resources = 1, |
503 | .resources = (struct resource[]) { | 504 | .resources = (struct resource[]) { |
504 | { | 505 | { |
505 | .name = "SIMOFF", | 506 | .name = "SIMOFF", |
506 | .flags = IORESOURCE_IRQ, | 507 | .flags = IORESOURCE_IRQ, |
507 | .start = AB5500_IRQ(2, 0), /*rising*/ | 508 | .start = AB5500_IRQ(2, 0), /*rising*/ |
508 | .end = AB5500_IRQ(2, 1), /*falling*/ | 509 | .end = AB5500_IRQ(2, 1), /*falling*/ |
509 | }, | 510 | }, |
510 | }, | 511 | }, |
511 | }, | 512 | }, |
512 | [AB5500_DEVID_RTC] = { | 513 | [AB5500_DEVID_RTC] = { |
513 | .name = "ab5500-rtc", | 514 | .name = "ab5500-rtc", |
514 | .id = AB5500_DEVID_RTC, | 515 | .id = AB5500_DEVID_RTC, |
515 | .num_resources = 1, | 516 | .num_resources = 1, |
516 | .resources = (struct resource[]) { | 517 | .resources = (struct resource[]) { |
517 | { | 518 | { |
518 | .name = "RTC_Alarm", | 519 | .name = "RTC_Alarm", |
519 | .flags = IORESOURCE_IRQ, | 520 | .flags = IORESOURCE_IRQ, |
520 | .start = AB5500_IRQ(1, 7), | 521 | .start = AB5500_IRQ(1, 7), |
521 | .end = AB5500_IRQ(1, 7), | 522 | .end = AB5500_IRQ(1, 7), |
522 | } | 523 | } |
523 | }, | 524 | }, |
524 | }, | 525 | }, |
525 | [AB5500_DEVID_CHARGER] = { | 526 | [AB5500_DEVID_CHARGER] = { |
526 | .name = "ab5500-charger", | 527 | .name = "ab5500-charger", |
527 | .id = AB5500_DEVID_CHARGER, | 528 | .id = AB5500_DEVID_CHARGER, |
528 | }, | 529 | }, |
529 | [AB5500_DEVID_ADC] = { | 530 | [AB5500_DEVID_ADC] = { |
530 | .name = "ab5500-adc", | 531 | .name = "ab5500-adc", |
531 | .id = AB5500_DEVID_ADC, | 532 | .id = AB5500_DEVID_ADC, |
532 | .num_resources = 10, | 533 | .num_resources = 10, |
533 | .resources = (struct resource[]) { | 534 | .resources = (struct resource[]) { |
534 | { | 535 | { |
535 | .name = "TRIGGER-0", | 536 | .name = "TRIGGER-0", |
536 | .flags = IORESOURCE_IRQ, | 537 | .flags = IORESOURCE_IRQ, |
537 | .start = AB5500_IRQ(0, 0), | 538 | .start = AB5500_IRQ(0, 0), |
538 | .end = AB5500_IRQ(0, 0), | 539 | .end = AB5500_IRQ(0, 0), |
539 | }, | 540 | }, |
540 | { | 541 | { |
541 | .name = "TRIGGER-1", | 542 | .name = "TRIGGER-1", |
542 | .flags = IORESOURCE_IRQ, | 543 | .flags = IORESOURCE_IRQ, |
543 | .start = AB5500_IRQ(0, 1), | 544 | .start = AB5500_IRQ(0, 1), |
544 | .end = AB5500_IRQ(0, 1), | 545 | .end = AB5500_IRQ(0, 1), |
545 | }, | 546 | }, |
546 | { | 547 | { |
547 | .name = "TRIGGER-2", | 548 | .name = "TRIGGER-2", |
548 | .flags = IORESOURCE_IRQ, | 549 | .flags = IORESOURCE_IRQ, |
549 | .start = AB5500_IRQ(0, 2), | 550 | .start = AB5500_IRQ(0, 2), |
550 | .end = AB5500_IRQ(0, 2), | 551 | .end = AB5500_IRQ(0, 2), |
551 | }, | 552 | }, |
552 | { | 553 | { |
553 | .name = "TRIGGER-3", | 554 | .name = "TRIGGER-3", |
554 | .flags = IORESOURCE_IRQ, | 555 | .flags = IORESOURCE_IRQ, |
555 | .start = AB5500_IRQ(0, 3), | 556 | .start = AB5500_IRQ(0, 3), |
556 | .end = AB5500_IRQ(0, 3), | 557 | .end = AB5500_IRQ(0, 3), |
557 | }, | 558 | }, |
558 | { | 559 | { |
559 | .name = "TRIGGER-4", | 560 | .name = "TRIGGER-4", |
560 | .flags = IORESOURCE_IRQ, | 561 | .flags = IORESOURCE_IRQ, |
561 | .start = AB5500_IRQ(0, 4), | 562 | .start = AB5500_IRQ(0, 4), |
562 | .end = AB5500_IRQ(0, 4), | 563 | .end = AB5500_IRQ(0, 4), |
563 | }, | 564 | }, |
564 | { | 565 | { |
565 | .name = "TRIGGER-5", | 566 | .name = "TRIGGER-5", |
566 | .flags = IORESOURCE_IRQ, | 567 | .flags = IORESOURCE_IRQ, |
567 | .start = AB5500_IRQ(0, 5), | 568 | .start = AB5500_IRQ(0, 5), |
568 | .end = AB5500_IRQ(0, 5), | 569 | .end = AB5500_IRQ(0, 5), |
569 | }, | 570 | }, |
570 | { | 571 | { |
571 | .name = "TRIGGER-6", | 572 | .name = "TRIGGER-6", |
572 | .flags = IORESOURCE_IRQ, | 573 | .flags = IORESOURCE_IRQ, |
573 | .start = AB5500_IRQ(0, 6), | 574 | .start = AB5500_IRQ(0, 6), |
574 | .end = AB5500_IRQ(0, 6), | 575 | .end = AB5500_IRQ(0, 6), |
575 | }, | 576 | }, |
576 | { | 577 | { |
577 | .name = "TRIGGER-7", | 578 | .name = "TRIGGER-7", |
578 | .flags = IORESOURCE_IRQ, | 579 | .flags = IORESOURCE_IRQ, |
579 | .start = AB5500_IRQ(0, 7), | 580 | .start = AB5500_IRQ(0, 7), |
580 | .end = AB5500_IRQ(0, 7), | 581 | .end = AB5500_IRQ(0, 7), |
581 | }, | 582 | }, |
582 | { | 583 | { |
583 | .name = "TRIGGER-VBAT", | 584 | .name = "TRIGGER-VBAT", |
584 | .flags = IORESOURCE_IRQ, | 585 | .flags = IORESOURCE_IRQ, |
585 | .start = AB5500_IRQ(0, 8), | 586 | .start = AB5500_IRQ(0, 8), |
586 | .end = AB5500_IRQ(0, 8), | 587 | .end = AB5500_IRQ(0, 8), |
587 | }, | 588 | }, |
588 | { | 589 | { |
589 | .name = "TRIGGER-VBAT-TXON", | 590 | .name = "TRIGGER-VBAT-TXON", |
590 | .flags = IORESOURCE_IRQ, | 591 | .flags = IORESOURCE_IRQ, |
591 | .start = AB5500_IRQ(0, 9), | 592 | .start = AB5500_IRQ(0, 9), |
592 | .end = AB5500_IRQ(0, 9), | 593 | .end = AB5500_IRQ(0, 9), |
593 | }, | 594 | }, |
594 | }, | 595 | }, |
595 | }, | 596 | }, |
596 | [AB5500_DEVID_FUELGAUGE] = { | 597 | [AB5500_DEVID_FUELGAUGE] = { |
597 | .name = "ab5500-fuelgauge", | 598 | .name = "ab5500-fuelgauge", |
598 | .id = AB5500_DEVID_FUELGAUGE, | 599 | .id = AB5500_DEVID_FUELGAUGE, |
599 | .num_resources = 6, | 600 | .num_resources = 6, |
600 | .resources = (struct resource[]) { | 601 | .resources = (struct resource[]) { |
601 | { | 602 | { |
602 | .name = "Batt_attach", | 603 | .name = "Batt_attach", |
603 | .flags = IORESOURCE_IRQ, | 604 | .flags = IORESOURCE_IRQ, |
604 | .start = AB5500_IRQ(7, 5), | 605 | .start = AB5500_IRQ(7, 5), |
605 | .end = AB5500_IRQ(7, 5), | 606 | .end = AB5500_IRQ(7, 5), |
606 | }, | 607 | }, |
607 | { | 608 | { |
608 | .name = "Batt_removal", | 609 | .name = "Batt_removal", |
609 | .flags = IORESOURCE_IRQ, | 610 | .flags = IORESOURCE_IRQ, |
610 | .start = AB5500_IRQ(7, 6), | 611 | .start = AB5500_IRQ(7, 6), |
611 | .end = AB5500_IRQ(7, 6), | 612 | .end = AB5500_IRQ(7, 6), |
612 | }, | 613 | }, |
613 | { | 614 | { |
614 | .name = "UART_framing", | 615 | .name = "UART_framing", |
615 | .flags = IORESOURCE_IRQ, | 616 | .flags = IORESOURCE_IRQ, |
616 | .start = AB5500_IRQ(7, 7), | 617 | .start = AB5500_IRQ(7, 7), |
617 | .end = AB5500_IRQ(7, 7), | 618 | .end = AB5500_IRQ(7, 7), |
618 | }, | 619 | }, |
619 | { | 620 | { |
620 | .name = "UART_overrun", | 621 | .name = "UART_overrun", |
621 | .flags = IORESOURCE_IRQ, | 622 | .flags = IORESOURCE_IRQ, |
622 | .start = AB5500_IRQ(8, 0), | 623 | .start = AB5500_IRQ(8, 0), |
623 | .end = AB5500_IRQ(8, 0), | 624 | .end = AB5500_IRQ(8, 0), |
624 | }, | 625 | }, |
625 | { | 626 | { |
626 | .name = "UART_Rdy_RX", | 627 | .name = "UART_Rdy_RX", |
627 | .flags = IORESOURCE_IRQ, | 628 | .flags = IORESOURCE_IRQ, |
628 | .start = AB5500_IRQ(8, 1), | 629 | .start = AB5500_IRQ(8, 1), |
629 | .end = AB5500_IRQ(8, 1), | 630 | .end = AB5500_IRQ(8, 1), |
630 | }, | 631 | }, |
631 | { | 632 | { |
632 | .name = "UART_Rdy_TX", | 633 | .name = "UART_Rdy_TX", |
633 | .flags = IORESOURCE_IRQ, | 634 | .flags = IORESOURCE_IRQ, |
634 | .start = AB5500_IRQ(8, 2), | 635 | .start = AB5500_IRQ(8, 2), |
635 | .end = AB5500_IRQ(8, 2), | 636 | .end = AB5500_IRQ(8, 2), |
636 | }, | 637 | }, |
637 | }, | 638 | }, |
638 | }, | 639 | }, |
639 | [AB5500_DEVID_VIBRATOR] = { | 640 | [AB5500_DEVID_VIBRATOR] = { |
640 | .name = "ab5500-vibrator", | 641 | .name = "ab5500-vibrator", |
641 | .id = AB5500_DEVID_VIBRATOR, | 642 | .id = AB5500_DEVID_VIBRATOR, |
642 | }, | 643 | }, |
643 | [AB5500_DEVID_CODEC] = { | 644 | [AB5500_DEVID_CODEC] = { |
644 | .name = "ab5500-codec", | 645 | .name = "ab5500-codec", |
645 | .id = AB5500_DEVID_CODEC, | 646 | .id = AB5500_DEVID_CODEC, |
646 | .num_resources = 3, | 647 | .num_resources = 3, |
647 | .resources = (struct resource[]) { | 648 | .resources = (struct resource[]) { |
648 | { | 649 | { |
649 | .name = "audio_spkr1_ovc", | 650 | .name = "audio_spkr1_ovc", |
650 | .flags = IORESOURCE_IRQ, | 651 | .flags = IORESOURCE_IRQ, |
651 | .start = AB5500_IRQ(9, 5), | 652 | .start = AB5500_IRQ(9, 5), |
652 | .end = AB5500_IRQ(9, 5), | 653 | .end = AB5500_IRQ(9, 5), |
653 | }, | 654 | }, |
654 | { | 655 | { |
655 | .name = "audio_plllocked", | 656 | .name = "audio_plllocked", |
656 | .flags = IORESOURCE_IRQ, | 657 | .flags = IORESOURCE_IRQ, |
657 | .start = AB5500_IRQ(9, 6), | 658 | .start = AB5500_IRQ(9, 6), |
658 | .end = AB5500_IRQ(9, 6), | 659 | .end = AB5500_IRQ(9, 6), |
659 | }, | 660 | }, |
660 | { | 661 | { |
661 | .name = "audio_spkr2_ovc", | 662 | .name = "audio_spkr2_ovc", |
662 | .flags = IORESOURCE_IRQ, | 663 | .flags = IORESOURCE_IRQ, |
663 | .start = AB5500_IRQ(17, 4), | 664 | .start = AB5500_IRQ(17, 4), |
664 | .end = AB5500_IRQ(17, 4), | 665 | .end = AB5500_IRQ(17, 4), |
665 | }, | 666 | }, |
666 | }, | 667 | }, |
667 | }, | 668 | }, |
668 | [AB5500_DEVID_USB] = { | 669 | [AB5500_DEVID_USB] = { |
669 | .name = "ab5500-usb", | 670 | .name = "ab5500-usb", |
670 | .id = AB5500_DEVID_USB, | 671 | .id = AB5500_DEVID_USB, |
671 | .num_resources = 36, | 672 | .num_resources = 36, |
672 | .resources = (struct resource[]) { | 673 | .resources = (struct resource[]) { |
673 | { | 674 | { |
674 | .name = "Link_Update", | 675 | .name = "Link_Update", |
675 | .flags = IORESOURCE_IRQ, | 676 | .flags = IORESOURCE_IRQ, |
676 | .start = AB5500_IRQ(22, 1), | 677 | .start = AB5500_IRQ(22, 1), |
677 | .end = AB5500_IRQ(22, 1), | 678 | .end = AB5500_IRQ(22, 1), |
678 | }, | 679 | }, |
679 | { | 680 | { |
680 | .name = "DCIO", | 681 | .name = "DCIO", |
681 | .flags = IORESOURCE_IRQ, | 682 | .flags = IORESOURCE_IRQ, |
682 | .start = AB5500_IRQ(8, 3), | 683 | .start = AB5500_IRQ(8, 3), |
683 | .end = AB5500_IRQ(8, 4), | 684 | .end = AB5500_IRQ(8, 4), |
684 | }, | 685 | }, |
685 | { | 686 | { |
686 | .name = "VBUS_R", | 687 | .name = "VBUS_R", |
687 | .flags = IORESOURCE_IRQ, | 688 | .flags = IORESOURCE_IRQ, |
688 | .start = AB5500_IRQ(8, 5), | 689 | .start = AB5500_IRQ(8, 5), |
689 | .end = AB5500_IRQ(8, 5), | 690 | .end = AB5500_IRQ(8, 5), |
690 | }, | 691 | }, |
691 | { | 692 | { |
692 | .name = "VBUS_F", | 693 | .name = "VBUS_F", |
693 | .flags = IORESOURCE_IRQ, | 694 | .flags = IORESOURCE_IRQ, |
694 | .start = AB5500_IRQ(8, 6), | 695 | .start = AB5500_IRQ(8, 6), |
695 | .end = AB5500_IRQ(8, 6), | 696 | .end = AB5500_IRQ(8, 6), |
696 | }, | 697 | }, |
697 | { | 698 | { |
698 | .name = "CHGstate_10_PCVBUSchg", | 699 | .name = "CHGstate_10_PCVBUSchg", |
699 | .flags = IORESOURCE_IRQ, | 700 | .flags = IORESOURCE_IRQ, |
700 | .start = AB5500_IRQ(8, 7), | 701 | .start = AB5500_IRQ(8, 7), |
701 | .end = AB5500_IRQ(8, 7), | 702 | .end = AB5500_IRQ(8, 7), |
702 | }, | 703 | }, |
703 | { | 704 | { |
704 | .name = "DCIOreverse_ovc", | 705 | .name = "DCIOreverse_ovc", |
705 | .flags = IORESOURCE_IRQ, | 706 | .flags = IORESOURCE_IRQ, |
706 | .start = AB5500_IRQ(9, 0), | 707 | .start = AB5500_IRQ(9, 0), |
707 | .end = AB5500_IRQ(9, 0), | 708 | .end = AB5500_IRQ(9, 0), |
708 | }, | 709 | }, |
709 | { | 710 | { |
710 | .name = "USBCharDetDone", | 711 | .name = "USBCharDetDone", |
711 | .flags = IORESOURCE_IRQ, | 712 | .flags = IORESOURCE_IRQ, |
712 | .start = AB5500_IRQ(9, 1), | 713 | .start = AB5500_IRQ(9, 1), |
713 | .end = AB5500_IRQ(9, 1), | 714 | .end = AB5500_IRQ(9, 1), |
714 | }, | 715 | }, |
715 | { | 716 | { |
716 | .name = "DCIO_no_limit", | 717 | .name = "DCIO_no_limit", |
717 | .flags = IORESOURCE_IRQ, | 718 | .flags = IORESOURCE_IRQ, |
718 | .start = AB5500_IRQ(9, 2), | 719 | .start = AB5500_IRQ(9, 2), |
719 | .end = AB5500_IRQ(9, 2), | 720 | .end = AB5500_IRQ(9, 2), |
720 | }, | 721 | }, |
721 | { | 722 | { |
722 | .name = "USB_suspend", | 723 | .name = "USB_suspend", |
723 | .flags = IORESOURCE_IRQ, | 724 | .flags = IORESOURCE_IRQ, |
724 | .start = AB5500_IRQ(9, 3), | 725 | .start = AB5500_IRQ(9, 3), |
725 | .end = AB5500_IRQ(9, 3), | 726 | .end = AB5500_IRQ(9, 3), |
726 | }, | 727 | }, |
727 | { | 728 | { |
728 | .name = "DCIOreverse_fwdcurrent", | 729 | .name = "DCIOreverse_fwdcurrent", |
729 | .flags = IORESOURCE_IRQ, | 730 | .flags = IORESOURCE_IRQ, |
730 | .start = AB5500_IRQ(9, 4), | 731 | .start = AB5500_IRQ(9, 4), |
731 | .end = AB5500_IRQ(9, 4), | 732 | .end = AB5500_IRQ(9, 4), |
732 | }, | 733 | }, |
733 | { | 734 | { |
734 | .name = "Vbus_Imeasmax_change", | 735 | .name = "Vbus_Imeasmax_change", |
735 | .flags = IORESOURCE_IRQ, | 736 | .flags = IORESOURCE_IRQ, |
736 | .start = AB5500_IRQ(9, 5), | 737 | .start = AB5500_IRQ(9, 5), |
737 | .end = AB5500_IRQ(9, 6), | 738 | .end = AB5500_IRQ(9, 6), |
738 | }, | 739 | }, |
739 | { | 740 | { |
740 | .name = "OVV", | 741 | .name = "OVV", |
741 | .flags = IORESOURCE_IRQ, | 742 | .flags = IORESOURCE_IRQ, |
742 | .start = AB5500_IRQ(14, 5), | 743 | .start = AB5500_IRQ(14, 5), |
743 | .end = AB5500_IRQ(14, 5), | 744 | .end = AB5500_IRQ(14, 5), |
744 | }, | 745 | }, |
745 | { | 746 | { |
746 | .name = "USBcharging_NOTok", | 747 | .name = "USBcharging_NOTok", |
747 | .flags = IORESOURCE_IRQ, | 748 | .flags = IORESOURCE_IRQ, |
748 | .start = AB5500_IRQ(15, 3), | 749 | .start = AB5500_IRQ(15, 3), |
749 | .end = AB5500_IRQ(15, 3), | 750 | .end = AB5500_IRQ(15, 3), |
750 | }, | 751 | }, |
751 | { | 752 | { |
752 | .name = "usb_adp_sensoroff", | 753 | .name = "usb_adp_sensoroff", |
753 | .flags = IORESOURCE_IRQ, | 754 | .flags = IORESOURCE_IRQ, |
754 | .start = AB5500_IRQ(15, 6), | 755 | .start = AB5500_IRQ(15, 6), |
755 | .end = AB5500_IRQ(15, 6), | 756 | .end = AB5500_IRQ(15, 6), |
756 | }, | 757 | }, |
757 | { | 758 | { |
758 | .name = "usb_adp_probeplug", | 759 | .name = "usb_adp_probeplug", |
759 | .flags = IORESOURCE_IRQ, | 760 | .flags = IORESOURCE_IRQ, |
760 | .start = AB5500_IRQ(15, 7), | 761 | .start = AB5500_IRQ(15, 7), |
761 | .end = AB5500_IRQ(15, 7), | 762 | .end = AB5500_IRQ(15, 7), |
762 | }, | 763 | }, |
763 | { | 764 | { |
764 | .name = "usb_adp_sinkerror", | 765 | .name = "usb_adp_sinkerror", |
765 | .flags = IORESOURCE_IRQ, | 766 | .flags = IORESOURCE_IRQ, |
766 | .start = AB5500_IRQ(16, 0), | 767 | .start = AB5500_IRQ(16, 0), |
767 | .end = AB5500_IRQ(16, 6), | 768 | .end = AB5500_IRQ(16, 6), |
768 | }, | 769 | }, |
769 | { | 770 | { |
770 | .name = "usb_adp_sourceerror", | 771 | .name = "usb_adp_sourceerror", |
771 | .flags = IORESOURCE_IRQ, | 772 | .flags = IORESOURCE_IRQ, |
772 | .start = AB5500_IRQ(16, 1), | 773 | .start = AB5500_IRQ(16, 1), |
773 | .end = AB5500_IRQ(16, 1), | 774 | .end = AB5500_IRQ(16, 1), |
774 | }, | 775 | }, |
775 | { | 776 | { |
776 | .name = "usb_idgnd_r", | 777 | .name = "usb_idgnd_r", |
777 | .flags = IORESOURCE_IRQ, | 778 | .flags = IORESOURCE_IRQ, |
778 | .start = AB5500_IRQ(16, 2), | 779 | .start = AB5500_IRQ(16, 2), |
779 | .end = AB5500_IRQ(16, 2), | 780 | .end = AB5500_IRQ(16, 2), |
780 | }, | 781 | }, |
781 | { | 782 | { |
782 | .name = "usb_idgnd_f", | 783 | .name = "usb_idgnd_f", |
783 | .flags = IORESOURCE_IRQ, | 784 | .flags = IORESOURCE_IRQ, |
784 | .start = AB5500_IRQ(16, 3), | 785 | .start = AB5500_IRQ(16, 3), |
785 | .end = AB5500_IRQ(16, 3), | 786 | .end = AB5500_IRQ(16, 3), |
786 | }, | 787 | }, |
787 | { | 788 | { |
788 | .name = "usb_iddetR1", | 789 | .name = "usb_iddetR1", |
789 | .flags = IORESOURCE_IRQ, | 790 | .flags = IORESOURCE_IRQ, |
790 | .start = AB5500_IRQ(16, 4), | 791 | .start = AB5500_IRQ(16, 4), |
791 | .end = AB5500_IRQ(16, 5), | 792 | .end = AB5500_IRQ(16, 5), |
792 | }, | 793 | }, |
793 | { | 794 | { |
794 | .name = "usb_iddetR2", | 795 | .name = "usb_iddetR2", |
795 | .flags = IORESOURCE_IRQ, | 796 | .flags = IORESOURCE_IRQ, |
796 | .start = AB5500_IRQ(16, 6), | 797 | .start = AB5500_IRQ(16, 6), |
797 | .end = AB5500_IRQ(16, 7), | 798 | .end = AB5500_IRQ(16, 7), |
798 | }, | 799 | }, |
799 | { | 800 | { |
800 | .name = "usb_iddetR3", | 801 | .name = "usb_iddetR3", |
801 | .flags = IORESOURCE_IRQ, | 802 | .flags = IORESOURCE_IRQ, |
802 | .start = AB5500_IRQ(17, 0), | 803 | .start = AB5500_IRQ(17, 0), |
803 | .end = AB5500_IRQ(17, 1), | 804 | .end = AB5500_IRQ(17, 1), |
804 | }, | 805 | }, |
805 | { | 806 | { |
806 | .name = "usb_iddetR4", | 807 | .name = "usb_iddetR4", |
807 | .flags = IORESOURCE_IRQ, | 808 | .flags = IORESOURCE_IRQ, |
808 | .start = AB5500_IRQ(17, 2), | 809 | .start = AB5500_IRQ(17, 2), |
809 | .end = AB5500_IRQ(17, 3), | 810 | .end = AB5500_IRQ(17, 3), |
810 | }, | 811 | }, |
811 | { | 812 | { |
812 | .name = "CharTempWindowOk", | 813 | .name = "CharTempWindowOk", |
813 | .flags = IORESOURCE_IRQ, | 814 | .flags = IORESOURCE_IRQ, |
814 | .start = AB5500_IRQ(17, 7), | 815 | .start = AB5500_IRQ(17, 7), |
815 | .end = AB5500_IRQ(18, 0), | 816 | .end = AB5500_IRQ(18, 0), |
816 | }, | 817 | }, |
817 | { | 818 | { |
818 | .name = "USB_SprDetect", | 819 | .name = "USB_SprDetect", |
819 | .flags = IORESOURCE_IRQ, | 820 | .flags = IORESOURCE_IRQ, |
820 | .start = AB5500_IRQ(18, 1), | 821 | .start = AB5500_IRQ(18, 1), |
821 | .end = AB5500_IRQ(18, 1), | 822 | .end = AB5500_IRQ(18, 1), |
822 | }, | 823 | }, |
823 | { | 824 | { |
824 | .name = "usb_adp_probe_unplug", | 825 | .name = "usb_adp_probe_unplug", |
825 | .flags = IORESOURCE_IRQ, | 826 | .flags = IORESOURCE_IRQ, |
826 | .start = AB5500_IRQ(18, 2), | 827 | .start = AB5500_IRQ(18, 2), |
827 | .end = AB5500_IRQ(18, 2), | 828 | .end = AB5500_IRQ(18, 2), |
828 | }, | 829 | }, |
829 | { | 830 | { |
830 | .name = "VBUSChDrop", | 831 | .name = "VBUSChDrop", |
831 | .flags = IORESOURCE_IRQ, | 832 | .flags = IORESOURCE_IRQ, |
832 | .start = AB5500_IRQ(18, 3), | 833 | .start = AB5500_IRQ(18, 3), |
833 | .end = AB5500_IRQ(18, 4), | 834 | .end = AB5500_IRQ(18, 4), |
834 | }, | 835 | }, |
835 | { | 836 | { |
836 | .name = "dcio_char_rec_done", | 837 | .name = "dcio_char_rec_done", |
837 | .flags = IORESOURCE_IRQ, | 838 | .flags = IORESOURCE_IRQ, |
838 | .start = AB5500_IRQ(18, 5), | 839 | .start = AB5500_IRQ(18, 5), |
839 | .end = AB5500_IRQ(18, 5), | 840 | .end = AB5500_IRQ(18, 5), |
840 | }, | 841 | }, |
841 | { | 842 | { |
842 | .name = "Charging_stopped_by_temp", | 843 | .name = "Charging_stopped_by_temp", |
843 | .flags = IORESOURCE_IRQ, | 844 | .flags = IORESOURCE_IRQ, |
844 | .start = AB5500_IRQ(18, 6), | 845 | .start = AB5500_IRQ(18, 6), |
845 | .end = AB5500_IRQ(18, 6), | 846 | .end = AB5500_IRQ(18, 6), |
846 | }, | 847 | }, |
847 | { | 848 | { |
848 | .name = "CHGstate_11_SafeModeVBUS", | 849 | .name = "CHGstate_11_SafeModeVBUS", |
849 | .flags = IORESOURCE_IRQ, | 850 | .flags = IORESOURCE_IRQ, |
850 | .start = AB5500_IRQ(21, 1), | 851 | .start = AB5500_IRQ(21, 1), |
851 | .end = AB5500_IRQ(21, 2), | 852 | .end = AB5500_IRQ(21, 2), |
852 | }, | 853 | }, |
853 | { | 854 | { |
854 | .name = "CHGstate_12_comletedVBUS", | 855 | .name = "CHGstate_12_comletedVBUS", |
855 | .flags = IORESOURCE_IRQ, | 856 | .flags = IORESOURCE_IRQ, |
856 | .start = AB5500_IRQ(21, 2), | 857 | .start = AB5500_IRQ(21, 2), |
857 | .end = AB5500_IRQ(21, 2), | 858 | .end = AB5500_IRQ(21, 2), |
858 | }, | 859 | }, |
859 | { | 860 | { |
860 | .name = "CHGstate_13_completedVBUS", | 861 | .name = "CHGstate_13_completedVBUS", |
861 | .flags = IORESOURCE_IRQ, | 862 | .flags = IORESOURCE_IRQ, |
862 | .start = AB5500_IRQ(21, 3), | 863 | .start = AB5500_IRQ(21, 3), |
863 | .end = AB5500_IRQ(21, 3), | 864 | .end = AB5500_IRQ(21, 3), |
864 | }, | 865 | }, |
865 | { | 866 | { |
866 | .name = "CHGstate_14_FullChgDCIO", | 867 | .name = "CHGstate_14_FullChgDCIO", |
867 | .flags = IORESOURCE_IRQ, | 868 | .flags = IORESOURCE_IRQ, |
868 | .start = AB5500_IRQ(21, 4), | 869 | .start = AB5500_IRQ(21, 4), |
869 | .end = AB5500_IRQ(21, 4), | 870 | .end = AB5500_IRQ(21, 4), |
870 | }, | 871 | }, |
871 | { | 872 | { |
872 | .name = "CHGstate_15_SafeModeDCIO", | 873 | .name = "CHGstate_15_SafeModeDCIO", |
873 | .flags = IORESOURCE_IRQ, | 874 | .flags = IORESOURCE_IRQ, |
874 | .start = AB5500_IRQ(21, 5), | 875 | .start = AB5500_IRQ(21, 5), |
875 | .end = AB5500_IRQ(21, 5), | 876 | .end = AB5500_IRQ(21, 5), |
876 | }, | 877 | }, |
877 | { | 878 | { |
878 | .name = "CHGstate_16_OFFsuspendDCIO", | 879 | .name = "CHGstate_16_OFFsuspendDCIO", |
879 | .flags = IORESOURCE_IRQ, | 880 | .flags = IORESOURCE_IRQ, |
880 | .start = AB5500_IRQ(21, 6), | 881 | .start = AB5500_IRQ(21, 6), |
881 | .end = AB5500_IRQ(21, 6), | 882 | .end = AB5500_IRQ(21, 6), |
882 | }, | 883 | }, |
883 | { | 884 | { |
884 | .name = "CHGstate_17_completedDCIO", | 885 | .name = "CHGstate_17_completedDCIO", |
885 | .flags = IORESOURCE_IRQ, | 886 | .flags = IORESOURCE_IRQ, |
886 | .start = AB5500_IRQ(21, 7), | 887 | .start = AB5500_IRQ(21, 7), |
887 | .end = AB5500_IRQ(21, 7), | 888 | .end = AB5500_IRQ(21, 7), |
888 | }, | 889 | }, |
889 | }, | 890 | }, |
890 | }, | 891 | }, |
891 | [AB5500_DEVID_OTP] = { | 892 | [AB5500_DEVID_OTP] = { |
892 | .name = "ab5500-otp", | 893 | .name = "ab5500-otp", |
893 | .id = AB5500_DEVID_OTP, | 894 | .id = AB5500_DEVID_OTP, |
894 | }, | 895 | }, |
895 | [AB5500_DEVID_VIDEO] = { | 896 | [AB5500_DEVID_VIDEO] = { |
896 | .name = "ab5500-video", | 897 | .name = "ab5500-video", |
897 | .id = AB5500_DEVID_VIDEO, | 898 | .id = AB5500_DEVID_VIDEO, |
898 | .num_resources = 1, | 899 | .num_resources = 1, |
899 | .resources = (struct resource[]) { | 900 | .resources = (struct resource[]) { |
900 | { | 901 | { |
901 | .name = "plugTVdet", | 902 | .name = "plugTVdet", |
902 | .flags = IORESOURCE_IRQ, | 903 | .flags = IORESOURCE_IRQ, |
903 | .start = AB5500_IRQ(22, 2), | 904 | .start = AB5500_IRQ(22, 2), |
904 | .end = AB5500_IRQ(22, 2), | 905 | .end = AB5500_IRQ(22, 2), |
905 | }, | 906 | }, |
906 | }, | 907 | }, |
907 | }, | 908 | }, |
908 | [AB5500_DEVID_DBIECI] = { | 909 | [AB5500_DEVID_DBIECI] = { |
909 | .name = "ab5500-dbieci", | 910 | .name = "ab5500-dbieci", |
910 | .id = AB5500_DEVID_DBIECI, | 911 | .id = AB5500_DEVID_DBIECI, |
911 | .num_resources = 10, | 912 | .num_resources = 10, |
912 | .resources = (struct resource[]) { | 913 | .resources = (struct resource[]) { |
913 | { | 914 | { |
914 | .name = "COLL", | 915 | .name = "COLL", |
915 | .flags = IORESOURCE_IRQ, | 916 | .flags = IORESOURCE_IRQ, |
916 | .start = AB5500_IRQ(14, 0), | 917 | .start = AB5500_IRQ(14, 0), |
917 | .end = AB5500_IRQ(14, 0), | 918 | .end = AB5500_IRQ(14, 0), |
918 | }, | 919 | }, |
919 | { | 920 | { |
920 | .name = "RESERR", | 921 | .name = "RESERR", |
921 | .flags = IORESOURCE_IRQ, | 922 | .flags = IORESOURCE_IRQ, |
922 | .start = AB5500_IRQ(14, 1), | 923 | .start = AB5500_IRQ(14, 1), |
923 | .end = AB5500_IRQ(14, 1), | 924 | .end = AB5500_IRQ(14, 1), |
924 | }, | 925 | }, |
925 | { | 926 | { |
926 | .name = "FRAERR", | 927 | .name = "FRAERR", |
927 | .flags = IORESOURCE_IRQ, | 928 | .flags = IORESOURCE_IRQ, |
928 | .start = AB5500_IRQ(14, 2), | 929 | .start = AB5500_IRQ(14, 2), |
929 | .end = AB5500_IRQ(14, 2), | 930 | .end = AB5500_IRQ(14, 2), |
930 | }, | 931 | }, |
931 | { | 932 | { |
932 | .name = "COMERR", | 933 | .name = "COMERR", |
933 | .flags = IORESOURCE_IRQ, | 934 | .flags = IORESOURCE_IRQ, |
934 | .start = AB5500_IRQ(14, 3), | 935 | .start = AB5500_IRQ(14, 3), |
935 | .end = AB5500_IRQ(14, 3), | 936 | .end = AB5500_IRQ(14, 3), |
936 | }, | 937 | }, |
937 | { | 938 | { |
938 | .name = "BSI_indicator", | 939 | .name = "BSI_indicator", |
939 | .flags = IORESOURCE_IRQ, | 940 | .flags = IORESOURCE_IRQ, |
940 | .start = AB5500_IRQ(14, 4), | 941 | .start = AB5500_IRQ(14, 4), |
941 | .end = AB5500_IRQ(14, 4), | 942 | .end = AB5500_IRQ(14, 4), |
942 | }, | 943 | }, |
943 | { | 944 | { |
944 | .name = "SPDSET", | 945 | .name = "SPDSET", |
945 | .flags = IORESOURCE_IRQ, | 946 | .flags = IORESOURCE_IRQ, |
946 | .start = AB5500_IRQ(14, 6), | 947 | .start = AB5500_IRQ(14, 6), |
947 | .end = AB5500_IRQ(14, 6), | 948 | .end = AB5500_IRQ(14, 6), |
948 | }, | 949 | }, |
949 | { | 950 | { |
950 | .name = "DSENT", | 951 | .name = "DSENT", |
951 | .flags = IORESOURCE_IRQ, | 952 | .flags = IORESOURCE_IRQ, |
952 | .start = AB5500_IRQ(14, 7), | 953 | .start = AB5500_IRQ(14, 7), |
953 | .end = AB5500_IRQ(14, 7), | 954 | .end = AB5500_IRQ(14, 7), |
954 | }, | 955 | }, |
955 | { | 956 | { |
956 | .name = "DREC", | 957 | .name = "DREC", |
957 | .flags = IORESOURCE_IRQ, | 958 | .flags = IORESOURCE_IRQ, |
958 | .start = AB5500_IRQ(15, 0), | 959 | .start = AB5500_IRQ(15, 0), |
959 | .end = AB5500_IRQ(15, 0), | 960 | .end = AB5500_IRQ(15, 0), |
960 | }, | 961 | }, |
961 | { | 962 | { |
962 | .name = "ACCINT", | 963 | .name = "ACCINT", |
963 | .flags = IORESOURCE_IRQ, | 964 | .flags = IORESOURCE_IRQ, |
964 | .start = AB5500_IRQ(15, 1), | 965 | .start = AB5500_IRQ(15, 1), |
965 | .end = AB5500_IRQ(15, 1), | 966 | .end = AB5500_IRQ(15, 1), |
966 | }, | 967 | }, |
967 | { | 968 | { |
968 | .name = "NOPINT", | 969 | .name = "NOPINT", |
969 | .flags = IORESOURCE_IRQ, | 970 | .flags = IORESOURCE_IRQ, |
970 | .start = AB5500_IRQ(15, 2), | 971 | .start = AB5500_IRQ(15, 2), |
971 | .end = AB5500_IRQ(15, 2), | 972 | .end = AB5500_IRQ(15, 2), |
972 | }, | 973 | }, |
973 | }, | 974 | }, |
974 | }, | 975 | }, |
975 | [AB5500_DEVID_ONSWA] = { | 976 | [AB5500_DEVID_ONSWA] = { |
976 | .name = "ab5500-onswa", | 977 | .name = "ab5500-onswa", |
977 | .id = AB5500_DEVID_ONSWA, | 978 | .id = AB5500_DEVID_ONSWA, |
978 | .num_resources = 2, | 979 | .num_resources = 2, |
979 | .resources = (struct resource[]) { | 980 | .resources = (struct resource[]) { |
980 | { | 981 | { |
981 | .name = "ONSWAn_rising", | 982 | .name = "ONSWAn_rising", |
982 | .flags = IORESOURCE_IRQ, | 983 | .flags = IORESOURCE_IRQ, |
983 | .start = AB5500_IRQ(1, 3), | 984 | .start = AB5500_IRQ(1, 3), |
984 | .end = AB5500_IRQ(1, 3), | 985 | .end = AB5500_IRQ(1, 3), |
985 | }, | 986 | }, |
986 | { | 987 | { |
987 | .name = "ONSWAn_falling", | 988 | .name = "ONSWAn_falling", |
988 | .flags = IORESOURCE_IRQ, | 989 | .flags = IORESOURCE_IRQ, |
989 | .start = AB5500_IRQ(1, 4), | 990 | .start = AB5500_IRQ(1, 4), |
990 | .end = AB5500_IRQ(1, 4), | 991 | .end = AB5500_IRQ(1, 4), |
991 | }, | 992 | }, |
992 | }, | 993 | }, |
993 | }, | 994 | }, |
994 | }; | 995 | }; |
995 | 996 | ||
996 | /* | 997 | /* |
997 | * Functionality for getting/setting register values. | 998 | * Functionality for getting/setting register values. |
998 | */ | 999 | */ |
999 | int ab5500_get_register_interruptible_raw(struct ab5500 *ab, | 1000 | int ab5500_get_register_interruptible_raw(struct ab5500 *ab, |
1000 | u8 bank, u8 reg, | 1001 | u8 bank, u8 reg, |
1001 | u8 *value) | 1002 | u8 *value) |
1002 | { | 1003 | { |
1003 | int err; | 1004 | int err; |
1004 | 1005 | ||
1005 | if (bank >= AB5500_NUM_BANKS) | 1006 | if (bank >= AB5500_NUM_BANKS) |
1006 | return -EINVAL; | 1007 | return -EINVAL; |
1007 | 1008 | ||
1008 | err = mutex_lock_interruptible(&ab->access_mutex); | 1009 | err = mutex_lock_interruptible(&ab->access_mutex); |
1009 | if (err) | 1010 | if (err) |
1010 | return err; | 1011 | return err; |
1011 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, reg, value, 1); | 1012 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, reg, value, 1); |
1012 | 1013 | ||
1013 | mutex_unlock(&ab->access_mutex); | 1014 | mutex_unlock(&ab->access_mutex); |
1014 | return err; | 1015 | return err; |
1015 | } | 1016 | } |
1016 | 1017 | ||
1017 | static int get_register_page_interruptible(struct ab5500 *ab, u8 bank, | 1018 | static int get_register_page_interruptible(struct ab5500 *ab, u8 bank, |
1018 | u8 first_reg, u8 *regvals, u8 numregs) | 1019 | u8 first_reg, u8 *regvals, u8 numregs) |
1019 | { | 1020 | { |
1020 | int err; | 1021 | int err; |
1021 | 1022 | ||
1022 | if (bank >= AB5500_NUM_BANKS) | 1023 | if (bank >= AB5500_NUM_BANKS) |
1023 | return -EINVAL; | 1024 | return -EINVAL; |
1024 | 1025 | ||
1025 | err = mutex_lock_interruptible(&ab->access_mutex); | 1026 | err = mutex_lock_interruptible(&ab->access_mutex); |
1026 | if (err) | 1027 | if (err) |
1027 | return err; | 1028 | return err; |
1028 | 1029 | ||
1029 | while (numregs) { | 1030 | while (numregs) { |
1030 | /* The hardware limit for get page is 4 */ | 1031 | /* The hardware limit for get page is 4 */ |
1031 | u8 curnum = min_t(u8, numregs, 4u); | 1032 | u8 curnum = min_t(u8, numregs, 4u); |
1032 | 1033 | ||
1033 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, | 1034 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, |
1034 | first_reg, regvals, curnum); | 1035 | first_reg, regvals, curnum); |
1035 | if (err) | 1036 | if (err) |
1036 | goto out; | 1037 | goto out; |
1037 | 1038 | ||
1038 | numregs -= curnum; | 1039 | numregs -= curnum; |
1039 | first_reg += curnum; | 1040 | first_reg += curnum; |
1040 | regvals += curnum; | 1041 | regvals += curnum; |
1041 | } | 1042 | } |
1042 | 1043 | ||
1043 | out: | 1044 | out: |
1044 | mutex_unlock(&ab->access_mutex); | 1045 | mutex_unlock(&ab->access_mutex); |
1045 | return err; | 1046 | return err; |
1046 | } | 1047 | } |
1047 | 1048 | ||
1048 | int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank, | 1049 | int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank, |
1049 | u8 reg, u8 bitmask, u8 bitvalues) | 1050 | u8 reg, u8 bitmask, u8 bitvalues) |
1050 | { | 1051 | { |
1051 | int err = 0; | 1052 | int err = 0; |
1052 | 1053 | ||
1053 | if (bank >= AB5500_NUM_BANKS) | 1054 | if (bank >= AB5500_NUM_BANKS) |
1054 | return -EINVAL; | 1055 | return -EINVAL; |
1055 | 1056 | ||
1056 | if (bitmask) { | 1057 | if (bitmask) { |
1057 | u8 buf; | 1058 | u8 buf; |
1058 | 1059 | ||
1059 | err = mutex_lock_interruptible(&ab->access_mutex); | 1060 | err = mutex_lock_interruptible(&ab->access_mutex); |
1060 | if (err) | 1061 | if (err) |
1061 | return err; | 1062 | return err; |
1062 | 1063 | ||
1063 | if (bitmask == 0xFF) /* No need to read in this case. */ | 1064 | if (bitmask == 0xFF) /* No need to read in this case. */ |
1064 | buf = bitvalues; | 1065 | buf = bitvalues; |
1065 | else { /* Read and modify the register value. */ | 1066 | else { /* Read and modify the register value. */ |
1066 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, | 1067 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, |
1067 | reg, &buf, 1); | 1068 | reg, &buf, 1); |
1068 | if (err) | 1069 | if (err) |
1069 | return err; | 1070 | return err; |
1070 | 1071 | ||
1071 | buf = ((~bitmask & buf) | (bitmask & bitvalues)); | 1072 | buf = ((~bitmask & buf) | (bitmask & bitvalues)); |
1072 | } | 1073 | } |
1073 | /* Write the new value. */ | 1074 | /* Write the new value. */ |
1074 | err = db5500_prcmu_abb_write(bankinfo[bank].slave_addr, reg, | 1075 | err = db5500_prcmu_abb_write(bankinfo[bank].slave_addr, reg, |
1075 | &buf, 1); | 1076 | &buf, 1); |
1076 | 1077 | ||
1077 | mutex_unlock(&ab->access_mutex); | 1078 | mutex_unlock(&ab->access_mutex); |
1078 | } | 1079 | } |
1079 | return err; | 1080 | return err; |
1080 | } | 1081 | } |
1081 | 1082 | ||
1082 | static int | 1083 | static int |
1083 | set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value) | 1084 | set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value) |
1084 | { | 1085 | { |
1085 | return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg, | 1086 | return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg, |
1086 | 0xff, value); | 1087 | 0xff, value); |
1087 | } | 1088 | } |
1088 | 1089 | ||
1089 | /* | 1090 | /* |
1090 | * Read/write permission checking functions. | 1091 | * Read/write permission checking functions. |
1091 | */ | 1092 | */ |
1092 | static const struct ab5500_i2c_ranges *get_bankref(u8 devid, u8 bank) | 1093 | static const struct ab5500_i2c_ranges *get_bankref(u8 devid, u8 bank) |
1093 | { | 1094 | { |
1094 | u8 i; | 1095 | u8 i; |
1095 | 1096 | ||
1096 | if (devid < AB5500_NUM_DEVICES) { | 1097 | if (devid < AB5500_NUM_DEVICES) { |
1097 | for (i = 0; i < ab5500_bank_ranges[devid].nbanks; i++) { | 1098 | for (i = 0; i < ab5500_bank_ranges[devid].nbanks; i++) { |
1098 | if (ab5500_bank_ranges[devid].bank[i].bankid == bank) | 1099 | if (ab5500_bank_ranges[devid].bank[i].bankid == bank) |
1099 | return &ab5500_bank_ranges[devid].bank[i]; | 1100 | return &ab5500_bank_ranges[devid].bank[i]; |
1100 | } | 1101 | } |
1101 | } | 1102 | } |
1102 | return NULL; | 1103 | return NULL; |
1103 | } | 1104 | } |
1104 | 1105 | ||
1105 | static bool page_write_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg) | 1106 | static bool page_write_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg) |
1106 | { | 1107 | { |
1107 | u8 i; /* range loop index */ | 1108 | u8 i; /* range loop index */ |
1108 | const struct ab5500_i2c_ranges *bankref; | 1109 | const struct ab5500_i2c_ranges *bankref; |
1109 | 1110 | ||
1110 | bankref = get_bankref(devid, bank); | 1111 | bankref = get_bankref(devid, bank); |
1111 | if (bankref == NULL || last_reg < first_reg) | 1112 | if (bankref == NULL || last_reg < first_reg) |
1112 | return false; | 1113 | return false; |
1113 | 1114 | ||
1114 | for (i = 0; i < bankref->nranges; i++) { | 1115 | for (i = 0; i < bankref->nranges; i++) { |
1115 | if (first_reg < bankref->range[i].first) | 1116 | if (first_reg < bankref->range[i].first) |
1116 | break; | 1117 | break; |
1117 | if ((last_reg <= bankref->range[i].last) && | 1118 | if ((last_reg <= bankref->range[i].last) && |
1118 | (bankref->range[i].perm & AB5500_PERM_WR)) | 1119 | (bankref->range[i].perm & AB5500_PERM_WR)) |
1119 | return true; | 1120 | return true; |
1120 | } | 1121 | } |
1121 | return false; | 1122 | return false; |
1122 | } | 1123 | } |
1123 | 1124 | ||
1124 | static bool reg_write_allowed(u8 devid, u8 bank, u8 reg) | 1125 | static bool reg_write_allowed(u8 devid, u8 bank, u8 reg) |
1125 | { | 1126 | { |
1126 | return page_write_allowed(devid, bank, reg, reg); | 1127 | return page_write_allowed(devid, bank, reg, reg); |
1127 | } | 1128 | } |
1128 | 1129 | ||
1129 | static bool page_read_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg) | 1130 | static bool page_read_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg) |
1130 | { | 1131 | { |
1131 | u8 i; | 1132 | u8 i; |
1132 | const struct ab5500_i2c_ranges *bankref; | 1133 | const struct ab5500_i2c_ranges *bankref; |
1133 | 1134 | ||
1134 | bankref = get_bankref(devid, bank); | 1135 | bankref = get_bankref(devid, bank); |
1135 | if (bankref == NULL || last_reg < first_reg) | 1136 | if (bankref == NULL || last_reg < first_reg) |
1136 | return false; | 1137 | return false; |
1137 | 1138 | ||
1138 | 1139 | ||
1139 | /* Find the range (if it exists in the list) that includes first_reg. */ | 1140 | /* Find the range (if it exists in the list) that includes first_reg. */ |
1140 | for (i = 0; i < bankref->nranges; i++) { | 1141 | for (i = 0; i < bankref->nranges; i++) { |
1141 | if (first_reg < bankref->range[i].first) | 1142 | if (first_reg < bankref->range[i].first) |
1142 | return false; | 1143 | return false; |
1143 | if (first_reg <= bankref->range[i].last) | 1144 | if (first_reg <= bankref->range[i].last) |
1144 | break; | 1145 | break; |
1145 | } | 1146 | } |
1146 | /* Make sure that the entire range up to and including last_reg is | 1147 | /* Make sure that the entire range up to and including last_reg is |
1147 | * readable. This may span several of the ranges in the list. | 1148 | * readable. This may span several of the ranges in the list. |
1148 | */ | 1149 | */ |
1149 | while ((i < bankref->nranges) && | 1150 | while ((i < bankref->nranges) && |
1150 | (bankref->range[i].perm & AB5500_PERM_RD)) { | 1151 | (bankref->range[i].perm & AB5500_PERM_RD)) { |
1151 | if (last_reg <= bankref->range[i].last) | 1152 | if (last_reg <= bankref->range[i].last) |
1152 | return true; | 1153 | return true; |
1153 | if ((++i >= bankref->nranges) || | 1154 | if ((++i >= bankref->nranges) || |
1154 | (bankref->range[i].first != | 1155 | (bankref->range[i].first != |
1155 | (bankref->range[i - 1].last + 1))) { | 1156 | (bankref->range[i - 1].last + 1))) { |
1156 | break; | 1157 | break; |
1157 | } | 1158 | } |
1158 | } | 1159 | } |
1159 | return false; | 1160 | return false; |
1160 | } | 1161 | } |
1161 | 1162 | ||
1162 | static bool reg_read_allowed(u8 devid, u8 bank, u8 reg) | 1163 | static bool reg_read_allowed(u8 devid, u8 bank, u8 reg) |
1163 | { | 1164 | { |
1164 | return page_read_allowed(devid, bank, reg, reg); | 1165 | return page_read_allowed(devid, bank, reg, reg); |
1165 | } | 1166 | } |
1166 | 1167 | ||
1167 | 1168 | ||
1168 | /* | 1169 | /* |
1169 | * The exported register access functionality. | 1170 | * The exported register access functionality. |
1170 | */ | 1171 | */ |
1171 | static int ab5500_get_chip_id(struct device *dev) | 1172 | static int ab5500_get_chip_id(struct device *dev) |
1172 | { | 1173 | { |
1173 | struct ab5500 *ab = dev_get_drvdata(dev->parent); | 1174 | struct ab5500 *ab = dev_get_drvdata(dev->parent); |
1174 | 1175 | ||
1175 | return (int)ab->chip_id; | 1176 | return (int)ab->chip_id; |
1176 | } | 1177 | } |
1177 | 1178 | ||
1178 | static int ab5500_mask_and_set_register_interruptible(struct device *dev, | 1179 | static int ab5500_mask_and_set_register_interruptible(struct device *dev, |
1179 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) | 1180 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) |
1180 | { | 1181 | { |
1181 | struct ab5500 *ab; | 1182 | struct ab5500 *ab; |
1182 | struct platform_device *pdev = to_platform_device(dev); | 1183 | struct platform_device *pdev = to_platform_device(dev); |
1183 | 1184 | ||
1184 | if ((AB5500_NUM_BANKS <= bank) || | 1185 | if ((AB5500_NUM_BANKS <= bank) || |
1185 | !reg_write_allowed(pdev->id, bank, reg)) | 1186 | !reg_write_allowed(pdev->id, bank, reg)) |
1186 | return -EINVAL; | 1187 | return -EINVAL; |
1187 | 1188 | ||
1188 | ab = dev_get_drvdata(dev->parent); | 1189 | ab = dev_get_drvdata(dev->parent); |
1189 | return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg, | 1190 | return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg, |
1190 | bitmask, bitvalues); | 1191 | bitmask, bitvalues); |
1191 | } | 1192 | } |
1192 | 1193 | ||
1193 | static int ab5500_set_register_interruptible(struct device *dev, u8 bank, | 1194 | static int ab5500_set_register_interruptible(struct device *dev, u8 bank, |
1194 | u8 reg, u8 value) | 1195 | u8 reg, u8 value) |
1195 | { | 1196 | { |
1196 | return ab5500_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | 1197 | return ab5500_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, |
1197 | value); | 1198 | value); |
1198 | } | 1199 | } |
1199 | 1200 | ||
1200 | static int ab5500_get_register_interruptible(struct device *dev, u8 bank, | 1201 | static int ab5500_get_register_interruptible(struct device *dev, u8 bank, |
1201 | u8 reg, u8 *value) | 1202 | u8 reg, u8 *value) |
1202 | { | 1203 | { |
1203 | struct ab5500 *ab; | 1204 | struct ab5500 *ab; |
1204 | struct platform_device *pdev = to_platform_device(dev); | 1205 | struct platform_device *pdev = to_platform_device(dev); |
1205 | 1206 | ||
1206 | if ((AB5500_NUM_BANKS <= bank) || | 1207 | if ((AB5500_NUM_BANKS <= bank) || |
1207 | !reg_read_allowed(pdev->id, bank, reg)) | 1208 | !reg_read_allowed(pdev->id, bank, reg)) |
1208 | return -EINVAL; | 1209 | return -EINVAL; |
1209 | 1210 | ||
1210 | ab = dev_get_drvdata(dev->parent); | 1211 | ab = dev_get_drvdata(dev->parent); |
1211 | return ab5500_get_register_interruptible_raw(ab, bank, reg, value); | 1212 | return ab5500_get_register_interruptible_raw(ab, bank, reg, value); |
1212 | } | 1213 | } |
1213 | 1214 | ||
1214 | static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank, | 1215 | static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank, |
1215 | u8 first_reg, u8 *regvals, u8 numregs) | 1216 | u8 first_reg, u8 *regvals, u8 numregs) |
1216 | { | 1217 | { |
1217 | struct ab5500 *ab; | 1218 | struct ab5500 *ab; |
1218 | struct platform_device *pdev = to_platform_device(dev); | 1219 | struct platform_device *pdev = to_platform_device(dev); |
1219 | 1220 | ||
1220 | if ((AB5500_NUM_BANKS <= bank) || | 1221 | if ((AB5500_NUM_BANKS <= bank) || |
1221 | !page_read_allowed(pdev->id, bank, | 1222 | !page_read_allowed(pdev->id, bank, |
1222 | first_reg, (first_reg + numregs - 1))) | 1223 | first_reg, (first_reg + numregs - 1))) |
1223 | return -EINVAL; | 1224 | return -EINVAL; |
1224 | 1225 | ||
1225 | ab = dev_get_drvdata(dev->parent); | 1226 | ab = dev_get_drvdata(dev->parent); |
1226 | return get_register_page_interruptible(ab, bank, first_reg, regvals, | 1227 | return get_register_page_interruptible(ab, bank, first_reg, regvals, |
1227 | numregs); | 1228 | numregs); |
1228 | } | 1229 | } |
1229 | 1230 | ||
1230 | static int | 1231 | static int |
1231 | ab5500_event_registers_startup_state_get(struct device *dev, u8 *event) | 1232 | ab5500_event_registers_startup_state_get(struct device *dev, u8 *event) |
1232 | { | 1233 | { |
1233 | struct ab5500 *ab; | 1234 | struct ab5500 *ab; |
1234 | 1235 | ||
1235 | ab = dev_get_drvdata(dev->parent); | 1236 | ab = dev_get_drvdata(dev->parent); |
1236 | if (!ab->startup_events_read) | 1237 | if (!ab->startup_events_read) |
1237 | return -EAGAIN; /* Try again later */ | 1238 | return -EAGAIN; /* Try again later */ |
1238 | 1239 | ||
1239 | memcpy(event, ab->startup_events, AB5500_NUM_EVENT_REG); | 1240 | memcpy(event, ab->startup_events, AB5500_NUM_EVENT_REG); |
1240 | return 0; | 1241 | return 0; |
1241 | } | 1242 | } |
1242 | 1243 | ||
1243 | static struct abx500_ops ab5500_ops = { | 1244 | static struct abx500_ops ab5500_ops = { |
1244 | .get_chip_id = ab5500_get_chip_id, | 1245 | .get_chip_id = ab5500_get_chip_id, |
1245 | .get_register = ab5500_get_register_interruptible, | 1246 | .get_register = ab5500_get_register_interruptible, |
1246 | .set_register = ab5500_set_register_interruptible, | 1247 | .set_register = ab5500_set_register_interruptible, |
1247 | .get_register_page = ab5500_get_register_page_interruptible, | 1248 | .get_register_page = ab5500_get_register_page_interruptible, |
1248 | .set_register_page = NULL, | 1249 | .set_register_page = NULL, |
1249 | .mask_and_set_register = ab5500_mask_and_set_register_interruptible, | 1250 | .mask_and_set_register = ab5500_mask_and_set_register_interruptible, |
1250 | .event_registers_startup_state_get = | 1251 | .event_registers_startup_state_get = |
1251 | ab5500_event_registers_startup_state_get, | 1252 | ab5500_event_registers_startup_state_get, |
1252 | .startup_irq_enabled = NULL, | 1253 | .startup_irq_enabled = NULL, |
1253 | }; | 1254 | }; |
1254 | 1255 | ||
1255 | /* | 1256 | /* |
1256 | * ab5500_setup : Basic set-up, datastructure creation/destruction | 1257 | * ab5500_setup : Basic set-up, datastructure creation/destruction |
1257 | * and I2C interface.This sets up a default config | 1258 | * and I2C interface.This sets up a default config |
1258 | * in the AB5500 chip so that it will work as expected. | 1259 | * in the AB5500 chip so that it will work as expected. |
1259 | * @ab : Pointer to ab5500 structure | 1260 | * @ab : Pointer to ab5500 structure |
1260 | * @settings : Pointer to struct abx500_init_settings | 1261 | * @settings : Pointer to struct abx500_init_settings |
1261 | * @size : Size of init data | 1262 | * @size : Size of init data |
1262 | */ | 1263 | */ |
1263 | static int __init ab5500_setup(struct ab5500 *ab, | 1264 | static int __init ab5500_setup(struct ab5500 *ab, |
1264 | struct abx500_init_settings *settings, unsigned int size) | 1265 | struct abx500_init_settings *settings, unsigned int size) |
1265 | { | 1266 | { |
1266 | int err = 0; | 1267 | int err = 0; |
1267 | int i; | 1268 | int i; |
1268 | 1269 | ||
1269 | for (i = 0; i < size; i++) { | 1270 | for (i = 0; i < size; i++) { |
1270 | err = ab5500_mask_and_set_register_interruptible_raw(ab, | 1271 | err = ab5500_mask_and_set_register_interruptible_raw(ab, |
1271 | settings[i].bank, | 1272 | settings[i].bank, |
1272 | settings[i].reg, | 1273 | settings[i].reg, |
1273 | 0xFF, settings[i].setting); | 1274 | 0xFF, settings[i].setting); |
1274 | if (err) | 1275 | if (err) |
1275 | goto exit_no_setup; | 1276 | goto exit_no_setup; |
1276 | 1277 | ||
1277 | /* If event mask register update the event mask in ab5500 */ | 1278 | /* If event mask register update the event mask in ab5500 */ |
1278 | if ((settings[i].bank == AB5500_BANK_IT) && | 1279 | if ((settings[i].bank == AB5500_BANK_IT) && |
1279 | (AB5500_MASK_BASE <= settings[i].reg) && | 1280 | (AB5500_MASK_BASE <= settings[i].reg) && |
1280 | (settings[i].reg <= AB5500_MASK_END)) { | 1281 | (settings[i].reg <= AB5500_MASK_END)) { |
1281 | ab->mask[settings[i].reg - AB5500_MASK_BASE] = | 1282 | ab->mask[settings[i].reg - AB5500_MASK_BASE] = |
1282 | settings[i].setting; | 1283 | settings[i].setting; |
1283 | } | 1284 | } |
1284 | } | 1285 | } |
1285 | exit_no_setup: | 1286 | exit_no_setup: |
1286 | return err; | 1287 | return err; |
1287 | } | 1288 | } |
1288 | 1289 | ||
1289 | struct ab_family_id { | 1290 | struct ab_family_id { |
1290 | u8 id; | 1291 | u8 id; |
1291 | char *name; | 1292 | char *name; |
1292 | }; | 1293 | }; |
1293 | 1294 | ||
1294 | static const struct ab_family_id ids[] __initdata = { | 1295 | static const struct ab_family_id ids[] __initdata = { |
1295 | /* AB5500 */ | 1296 | /* AB5500 */ |
1296 | { | 1297 | { |
1297 | .id = AB5500_1_0, | 1298 | .id = AB5500_1_0, |
1298 | .name = "1.0" | 1299 | .name = "1.0" |
1299 | }, | 1300 | }, |
1300 | { | 1301 | { |
1301 | .id = AB5500_1_1, | 1302 | .id = AB5500_1_1, |
1302 | .name = "1.1" | 1303 | .name = "1.1" |
1303 | }, | 1304 | }, |
1304 | /* Terminator */ | 1305 | /* Terminator */ |
1305 | { | 1306 | { |
1306 | .id = 0x00, | 1307 | .id = 0x00, |
1307 | } | 1308 | } |
1308 | }; | 1309 | }; |
1309 | 1310 | ||
1310 | static int __init ab5500_probe(struct platform_device *pdev) | 1311 | static int __init ab5500_probe(struct platform_device *pdev) |
1311 | { | 1312 | { |
1312 | struct ab5500 *ab; | 1313 | struct ab5500 *ab; |
1313 | struct ab5500_platform_data *ab5500_plf_data = | 1314 | struct ab5500_platform_data *ab5500_plf_data = |
1314 | pdev->dev.platform_data; | 1315 | pdev->dev.platform_data; |
1315 | int err; | 1316 | int err; |
1316 | int i; | 1317 | int i; |
1317 | 1318 | ||
1318 | ab = kzalloc(sizeof(struct ab5500), GFP_KERNEL); | 1319 | ab = kzalloc(sizeof(struct ab5500), GFP_KERNEL); |
1319 | if (!ab) { | 1320 | if (!ab) { |
1320 | dev_err(&pdev->dev, | 1321 | dev_err(&pdev->dev, |
1321 | "could not allocate ab5500 device\n"); | 1322 | "could not allocate ab5500 device\n"); |
1322 | return -ENOMEM; | 1323 | return -ENOMEM; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | /* Initialize data structure */ | 1326 | /* Initialize data structure */ |
1326 | mutex_init(&ab->access_mutex); | 1327 | mutex_init(&ab->access_mutex); |
1327 | mutex_init(&ab->irq_lock); | 1328 | mutex_init(&ab->irq_lock); |
1328 | ab->dev = &pdev->dev; | 1329 | ab->dev = &pdev->dev; |
1329 | 1330 | ||
1330 | platform_set_drvdata(pdev, ab); | 1331 | platform_set_drvdata(pdev, ab); |
1331 | 1332 | ||
1332 | /* Read chip ID register */ | 1333 | /* Read chip ID register */ |
1333 | err = ab5500_get_register_interruptible_raw(ab, | 1334 | err = ab5500_get_register_interruptible_raw(ab, |
1334 | AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, | 1335 | AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, |
1335 | AB5500_CHIP_ID, &ab->chip_id); | 1336 | AB5500_CHIP_ID, &ab->chip_id); |
1336 | if (err) { | 1337 | if (err) { |
1337 | dev_err(&pdev->dev, "could not communicate with the analog " | 1338 | dev_err(&pdev->dev, "could not communicate with the analog " |
1338 | "baseband chip\n"); | 1339 | "baseband chip\n"); |
1339 | goto exit_no_detect; | 1340 | goto exit_no_detect; |
1340 | } | 1341 | } |
1341 | 1342 | ||
1342 | for (i = 0; ids[i].id != 0x0; i++) { | 1343 | for (i = 0; ids[i].id != 0x0; i++) { |
1343 | if (ids[i].id == ab->chip_id) { | 1344 | if (ids[i].id == ab->chip_id) { |
1344 | snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1, | 1345 | snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1, |
1345 | "AB5500 %s", ids[i].name); | 1346 | "AB5500 %s", ids[i].name); |
1346 | break; | 1347 | break; |
1347 | } | 1348 | } |
1348 | } | 1349 | } |
1349 | if (ids[i].id == 0x0) { | 1350 | if (ids[i].id == 0x0) { |
1350 | dev_err(&pdev->dev, "unknown analog baseband chip id: 0x%x\n", | 1351 | dev_err(&pdev->dev, "unknown analog baseband chip id: 0x%x\n", |
1351 | ab->chip_id); | 1352 | ab->chip_id); |
1352 | dev_err(&pdev->dev, "driver not started!\n"); | 1353 | dev_err(&pdev->dev, "driver not started!\n"); |
1353 | goto exit_no_detect; | 1354 | goto exit_no_detect; |
1354 | } | 1355 | } |
1355 | 1356 | ||
1356 | /* Clear and mask all interrupts */ | 1357 | /* Clear and mask all interrupts */ |
1357 | for (i = 0; i < AB5500_NUM_IRQ_REGS; i++) { | 1358 | for (i = 0; i < AB5500_NUM_IRQ_REGS; i++) { |
1358 | u8 latchreg = AB5500_IT_LATCH0_REG + i; | 1359 | u8 latchreg = AB5500_IT_LATCH0_REG + i; |
1359 | u8 maskreg = AB5500_IT_MASK0_REG + i; | 1360 | u8 maskreg = AB5500_IT_MASK0_REG + i; |
1360 | u8 val; | 1361 | u8 val; |
1361 | 1362 | ||
1362 | ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT, | 1363 | ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT, |
1363 | latchreg, &val); | 1364 | latchreg, &val); |
1364 | set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff); | 1365 | set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff); |
1365 | ab->mask[i] = ab->oldmask[i] = 0xff; | 1366 | ab->mask[i] = ab->oldmask[i] = 0xff; |
1366 | } | 1367 | } |
1367 | 1368 | ||
1368 | err = abx500_register_ops(&pdev->dev, &ab5500_ops); | 1369 | err = abx500_register_ops(&pdev->dev, &ab5500_ops); |
1369 | if (err) { | 1370 | if (err) { |
1370 | dev_err(&pdev->dev, "ab5500_register ops error\n"); | 1371 | dev_err(&pdev->dev, "ab5500_register ops error\n"); |
1371 | goto exit_no_detect; | 1372 | goto exit_no_detect; |
1372 | } | 1373 | } |
1373 | 1374 | ||
1374 | /* Set up and register the platform devices. */ | 1375 | /* Set up and register the platform devices. */ |
1375 | for (i = 0; i < AB5500_NUM_DEVICES; i++) { | 1376 | for (i = 0; i < AB5500_NUM_DEVICES; i++) { |
1376 | ab5500_devs[i].platform_data = ab5500_plf_data->dev_data[i]; | 1377 | ab5500_devs[i].platform_data = ab5500_plf_data->dev_data[i]; |
1377 | ab5500_devs[i].pdata_size = | 1378 | ab5500_devs[i].pdata_size = |
1378 | sizeof(ab5500_plf_data->dev_data[i]); | 1379 | sizeof(ab5500_plf_data->dev_data[i]); |
1379 | } | 1380 | } |
1380 | 1381 | ||
1381 | err = mfd_add_devices(&pdev->dev, 0, ab5500_devs, | 1382 | err = mfd_add_devices(&pdev->dev, 0, ab5500_devs, |
1382 | ARRAY_SIZE(ab5500_devs), NULL, | 1383 | ARRAY_SIZE(ab5500_devs), NULL, |
1383 | ab5500_plf_data->irq.base); | 1384 | ab5500_plf_data->irq.base); |
1384 | if (err) { | 1385 | if (err) { |
1385 | dev_err(&pdev->dev, "ab5500_mfd_add_device error\n"); | 1386 | dev_err(&pdev->dev, "ab5500_mfd_add_device error\n"); |
1386 | goto exit_no_detect; | 1387 | goto exit_no_detect; |
1387 | } | 1388 | } |
1388 | 1389 | ||
1389 | err = ab5500_setup(ab, ab5500_plf_data->init_settings, | 1390 | err = ab5500_setup(ab, ab5500_plf_data->init_settings, |
1390 | ab5500_plf_data->init_settings_sz); | 1391 | ab5500_plf_data->init_settings_sz); |
1391 | if (err) { | 1392 | if (err) { |
1392 | dev_err(&pdev->dev, "ab5500_setup error\n"); | 1393 | dev_err(&pdev->dev, "ab5500_setup error\n"); |
1393 | goto exit_no_detect; | 1394 | goto exit_no_detect; |
1394 | } | 1395 | } |
1395 | 1396 | ||
1396 | ab5500_setup_debugfs(ab); | 1397 | ab5500_setup_debugfs(ab); |
1397 | 1398 | ||
1398 | dev_info(&pdev->dev, "detected AB chip: %s\n", &ab->chip_name[0]); | 1399 | dev_info(&pdev->dev, "detected AB chip: %s\n", &ab->chip_name[0]); |
1399 | return 0; | 1400 | return 0; |
1400 | 1401 | ||
1401 | exit_no_detect: | 1402 | exit_no_detect: |
1402 | kfree(ab); | 1403 | kfree(ab); |
1403 | return err; | 1404 | return err; |
1404 | } | 1405 | } |
1405 | 1406 | ||
1406 | static int __exit ab5500_remove(struct platform_device *pdev) | 1407 | static int __exit ab5500_remove(struct platform_device *pdev) |
1407 | { | 1408 | { |
1408 | struct ab5500 *ab = platform_get_drvdata(pdev); | 1409 | struct ab5500 *ab = platform_get_drvdata(pdev); |
1409 | 1410 | ||
1410 | ab5500_remove_debugfs(); | 1411 | ab5500_remove_debugfs(); |
1411 | mfd_remove_devices(&pdev->dev); | 1412 | mfd_remove_devices(&pdev->dev); |
1412 | kfree(ab); | 1413 | kfree(ab); |
1413 | return 0; | 1414 | return 0; |
1414 | } | 1415 | } |
1415 | 1416 | ||
1416 | static struct platform_driver ab5500_driver = { | 1417 | static struct platform_driver ab5500_driver = { |
1417 | .driver = { | 1418 | .driver = { |
1418 | .name = "ab5500-core", | 1419 | .name = "ab5500-core", |
1419 | .owner = THIS_MODULE, | 1420 | .owner = THIS_MODULE, |
1420 | }, | 1421 | }, |
1421 | .remove = __exit_p(ab5500_remove), | 1422 | .remove = __exit_p(ab5500_remove), |
1422 | }; | 1423 | }; |
1423 | 1424 | ||
1424 | static int __init ab5500_core_init(void) | 1425 | static int __init ab5500_core_init(void) |
1425 | { | 1426 | { |
1426 | return platform_driver_probe(&ab5500_driver, ab5500_probe); | 1427 | return platform_driver_probe(&ab5500_driver, ab5500_probe); |
1427 | } | 1428 | } |
1428 | 1429 | ||
1429 | static void __exit ab5500_core_exit(void) | 1430 | static void __exit ab5500_core_exit(void) |
1430 | { | 1431 | { |
1431 | platform_driver_unregister(&ab5500_driver); | 1432 | platform_driver_unregister(&ab5500_driver); |
1432 | } | 1433 | } |
1433 | 1434 | ||
1434 | subsys_initcall(ab5500_core_init); | 1435 | subsys_initcall(ab5500_core_init); |
1435 | module_exit(ab5500_core_exit); | 1436 | module_exit(ab5500_core_exit); |
1436 | 1437 | ||
1437 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); | 1438 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); |
1438 | MODULE_DESCRIPTION("AB5500 core driver"); | 1439 | MODULE_DESCRIPTION("AB5500 core driver"); |
1439 | MODULE_LICENSE("GPL"); | 1440 | MODULE_LICENSE("GPL"); |
1440 | 1441 |
drivers/mfd/ab5500-debugfs.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2011 ST-Ericsson | 2 | * Copyright (C) 2011 ST-Ericsson |
3 | * License terms: GNU General Public License (GPL) version 2 | 3 | * License terms: GNU General Public License (GPL) version 2 |
4 | * Debugfs support for the AB5500 MFD driver | 4 | * Debugfs support for the AB5500 MFD driver |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/export.h> | ||
7 | #include <linux/debugfs.h> | 8 | #include <linux/debugfs.h> |
8 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
9 | #include <linux/mfd/ab5500/ab5500.h> | 10 | #include <linux/mfd/ab5500/ab5500.h> |
10 | #include <linux/mfd/abx500.h> | 11 | #include <linux/mfd/abx500.h> |
11 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
12 | 13 | ||
13 | #include "ab5500-core.h" | 14 | #include "ab5500-core.h" |
14 | #include "ab5500-debugfs.h" | 15 | #include "ab5500-debugfs.h" |
15 | 16 | ||
16 | static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = { | 17 | static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = { |
17 | [AB5500_BANK_LED] = { | 18 | [AB5500_BANK_LED] = { |
18 | .bankid = AB5500_BANK_LED, | 19 | .bankid = AB5500_BANK_LED, |
19 | .nranges = 1, | 20 | .nranges = 1, |
20 | .range = (struct ab5500_reg_range[]) { | 21 | .range = (struct ab5500_reg_range[]) { |
21 | { | 22 | { |
22 | .first = 0x00, | 23 | .first = 0x00, |
23 | .last = 0x0C, | 24 | .last = 0x0C, |
24 | .perm = AB5500_PERM_RW, | 25 | .perm = AB5500_PERM_RW, |
25 | }, | 26 | }, |
26 | }, | 27 | }, |
27 | }, | 28 | }, |
28 | [AB5500_BANK_ADC] = { | 29 | [AB5500_BANK_ADC] = { |
29 | .bankid = AB5500_BANK_ADC, | 30 | .bankid = AB5500_BANK_ADC, |
30 | .nranges = 6, | 31 | .nranges = 6, |
31 | .range = (struct ab5500_reg_range[]) { | 32 | .range = (struct ab5500_reg_range[]) { |
32 | { | 33 | { |
33 | .first = 0x1F, | 34 | .first = 0x1F, |
34 | .last = 0x22, | 35 | .last = 0x22, |
35 | .perm = AB5500_PERM_RO, | 36 | .perm = AB5500_PERM_RO, |
36 | }, | 37 | }, |
37 | { | 38 | { |
38 | .first = 0x23, | 39 | .first = 0x23, |
39 | .last = 0x24, | 40 | .last = 0x24, |
40 | .perm = AB5500_PERM_RW, | 41 | .perm = AB5500_PERM_RW, |
41 | }, | 42 | }, |
42 | { | 43 | { |
43 | .first = 0x26, | 44 | .first = 0x26, |
44 | .last = 0x2D, | 45 | .last = 0x2D, |
45 | .perm = AB5500_PERM_RO, | 46 | .perm = AB5500_PERM_RO, |
46 | }, | 47 | }, |
47 | { | 48 | { |
48 | .first = 0x2F, | 49 | .first = 0x2F, |
49 | .last = 0x34, | 50 | .last = 0x34, |
50 | .perm = AB5500_PERM_RW, | 51 | .perm = AB5500_PERM_RW, |
51 | }, | 52 | }, |
52 | { | 53 | { |
53 | .first = 0x37, | 54 | .first = 0x37, |
54 | .last = 0x57, | 55 | .last = 0x57, |
55 | .perm = AB5500_PERM_RW, | 56 | .perm = AB5500_PERM_RW, |
56 | }, | 57 | }, |
57 | { | 58 | { |
58 | .first = 0x58, | 59 | .first = 0x58, |
59 | .last = 0x58, | 60 | .last = 0x58, |
60 | .perm = AB5500_PERM_RO, | 61 | .perm = AB5500_PERM_RO, |
61 | }, | 62 | }, |
62 | }, | 63 | }, |
63 | }, | 64 | }, |
64 | [AB5500_BANK_RTC] = { | 65 | [AB5500_BANK_RTC] = { |
65 | .bankid = AB5500_BANK_RTC, | 66 | .bankid = AB5500_BANK_RTC, |
66 | .nranges = 2, | 67 | .nranges = 2, |
67 | .range = (struct ab5500_reg_range[]) { | 68 | .range = (struct ab5500_reg_range[]) { |
68 | { | 69 | { |
69 | .first = 0x00, | 70 | .first = 0x00, |
70 | .last = 0x04, | 71 | .last = 0x04, |
71 | .perm = AB5500_PERM_RW, | 72 | .perm = AB5500_PERM_RW, |
72 | }, | 73 | }, |
73 | { | 74 | { |
74 | .first = 0x06, | 75 | .first = 0x06, |
75 | .last = 0x0C, | 76 | .last = 0x0C, |
76 | .perm = AB5500_PERM_RW, | 77 | .perm = AB5500_PERM_RW, |
77 | }, | 78 | }, |
78 | }, | 79 | }, |
79 | }, | 80 | }, |
80 | [AB5500_BANK_STARTUP] = { | 81 | [AB5500_BANK_STARTUP] = { |
81 | .bankid = AB5500_BANK_STARTUP, | 82 | .bankid = AB5500_BANK_STARTUP, |
82 | .nranges = 12, | 83 | .nranges = 12, |
83 | .range = (struct ab5500_reg_range[]) { | 84 | .range = (struct ab5500_reg_range[]) { |
84 | { | 85 | { |
85 | .first = 0x00, | 86 | .first = 0x00, |
86 | .last = 0x01, | 87 | .last = 0x01, |
87 | .perm = AB5500_PERM_RW, | 88 | .perm = AB5500_PERM_RW, |
88 | }, | 89 | }, |
89 | { | 90 | { |
90 | .first = 0x1F, | 91 | .first = 0x1F, |
91 | .last = 0x1F, | 92 | .last = 0x1F, |
92 | .perm = AB5500_PERM_RW, | 93 | .perm = AB5500_PERM_RW, |
93 | }, | 94 | }, |
94 | { | 95 | { |
95 | .first = 0x2E, | 96 | .first = 0x2E, |
96 | .last = 0x2E, | 97 | .last = 0x2E, |
97 | .perm = AB5500_PERM_RO, | 98 | .perm = AB5500_PERM_RO, |
98 | }, | 99 | }, |
99 | { | 100 | { |
100 | .first = 0x2F, | 101 | .first = 0x2F, |
101 | .last = 0x30, | 102 | .last = 0x30, |
102 | .perm = AB5500_PERM_RW, | 103 | .perm = AB5500_PERM_RW, |
103 | }, | 104 | }, |
104 | { | 105 | { |
105 | .first = 0x50, | 106 | .first = 0x50, |
106 | .last = 0x51, | 107 | .last = 0x51, |
107 | .perm = AB5500_PERM_RW, | 108 | .perm = AB5500_PERM_RW, |
108 | }, | 109 | }, |
109 | { | 110 | { |
110 | .first = 0x60, | 111 | .first = 0x60, |
111 | .last = 0x61, | 112 | .last = 0x61, |
112 | .perm = AB5500_PERM_RW, | 113 | .perm = AB5500_PERM_RW, |
113 | }, | 114 | }, |
114 | { | 115 | { |
115 | .first = 0x66, | 116 | .first = 0x66, |
116 | .last = 0x8A, | 117 | .last = 0x8A, |
117 | .perm = AB5500_PERM_RW, | 118 | .perm = AB5500_PERM_RW, |
118 | }, | 119 | }, |
119 | { | 120 | { |
120 | .first = 0x8C, | 121 | .first = 0x8C, |
121 | .last = 0x96, | 122 | .last = 0x96, |
122 | .perm = AB5500_PERM_RW, | 123 | .perm = AB5500_PERM_RW, |
123 | }, | 124 | }, |
124 | { | 125 | { |
125 | .first = 0xAA, | 126 | .first = 0xAA, |
126 | .last = 0xB4, | 127 | .last = 0xB4, |
127 | .perm = AB5500_PERM_RW, | 128 | .perm = AB5500_PERM_RW, |
128 | }, | 129 | }, |
129 | { | 130 | { |
130 | .first = 0xB7, | 131 | .first = 0xB7, |
131 | .last = 0xBF, | 132 | .last = 0xBF, |
132 | .perm = AB5500_PERM_RW, | 133 | .perm = AB5500_PERM_RW, |
133 | }, | 134 | }, |
134 | { | 135 | { |
135 | .first = 0xC1, | 136 | .first = 0xC1, |
136 | .last = 0xCA, | 137 | .last = 0xCA, |
137 | .perm = AB5500_PERM_RW, | 138 | .perm = AB5500_PERM_RW, |
138 | }, | 139 | }, |
139 | { | 140 | { |
140 | .first = 0xD3, | 141 | .first = 0xD3, |
141 | .last = 0xE0, | 142 | .last = 0xE0, |
142 | .perm = AB5500_PERM_RW, | 143 | .perm = AB5500_PERM_RW, |
143 | }, | 144 | }, |
144 | }, | 145 | }, |
145 | }, | 146 | }, |
146 | [AB5500_BANK_DBI_ECI] = { | 147 | [AB5500_BANK_DBI_ECI] = { |
147 | .bankid = AB5500_BANK_DBI_ECI, | 148 | .bankid = AB5500_BANK_DBI_ECI, |
148 | .nranges = 3, | 149 | .nranges = 3, |
149 | .range = (struct ab5500_reg_range[]) { | 150 | .range = (struct ab5500_reg_range[]) { |
150 | { | 151 | { |
151 | .first = 0x00, | 152 | .first = 0x00, |
152 | .last = 0x07, | 153 | .last = 0x07, |
153 | .perm = AB5500_PERM_RW, | 154 | .perm = AB5500_PERM_RW, |
154 | }, | 155 | }, |
155 | { | 156 | { |
156 | .first = 0x10, | 157 | .first = 0x10, |
157 | .last = 0x10, | 158 | .last = 0x10, |
158 | .perm = AB5500_PERM_RW, | 159 | .perm = AB5500_PERM_RW, |
159 | }, | 160 | }, |
160 | { | 161 | { |
161 | .first = 0x13, | 162 | .first = 0x13, |
162 | .last = 0x13, | 163 | .last = 0x13, |
163 | .perm = AB5500_PERM_RW, | 164 | .perm = AB5500_PERM_RW, |
164 | }, | 165 | }, |
165 | }, | 166 | }, |
166 | }, | 167 | }, |
167 | [AB5500_BANK_CHG] = { | 168 | [AB5500_BANK_CHG] = { |
168 | .bankid = AB5500_BANK_CHG, | 169 | .bankid = AB5500_BANK_CHG, |
169 | .nranges = 2, | 170 | .nranges = 2, |
170 | .range = (struct ab5500_reg_range[]) { | 171 | .range = (struct ab5500_reg_range[]) { |
171 | { | 172 | { |
172 | .first = 0x11, | 173 | .first = 0x11, |
173 | .last = 0x11, | 174 | .last = 0x11, |
174 | .perm = AB5500_PERM_RO, | 175 | .perm = AB5500_PERM_RO, |
175 | }, | 176 | }, |
176 | { | 177 | { |
177 | .first = 0x12, | 178 | .first = 0x12, |
178 | .last = 0x1B, | 179 | .last = 0x1B, |
179 | .perm = AB5500_PERM_RW, | 180 | .perm = AB5500_PERM_RW, |
180 | }, | 181 | }, |
181 | }, | 182 | }, |
182 | }, | 183 | }, |
183 | [AB5500_BANK_FG_BATTCOM_ACC] = { | 184 | [AB5500_BANK_FG_BATTCOM_ACC] = { |
184 | .bankid = AB5500_BANK_FG_BATTCOM_ACC, | 185 | .bankid = AB5500_BANK_FG_BATTCOM_ACC, |
185 | .nranges = 2, | 186 | .nranges = 2, |
186 | .range = (struct ab5500_reg_range[]) { | 187 | .range = (struct ab5500_reg_range[]) { |
187 | { | 188 | { |
188 | .first = 0x00, | 189 | .first = 0x00, |
189 | .last = 0x0B, | 190 | .last = 0x0B, |
190 | .perm = AB5500_PERM_RO, | 191 | .perm = AB5500_PERM_RO, |
191 | }, | 192 | }, |
192 | { | 193 | { |
193 | .first = 0x0C, | 194 | .first = 0x0C, |
194 | .last = 0x10, | 195 | .last = 0x10, |
195 | .perm = AB5500_PERM_RW, | 196 | .perm = AB5500_PERM_RW, |
196 | }, | 197 | }, |
197 | }, | 198 | }, |
198 | }, | 199 | }, |
199 | [AB5500_BANK_USB] = { | 200 | [AB5500_BANK_USB] = { |
200 | .bankid = AB5500_BANK_USB, | 201 | .bankid = AB5500_BANK_USB, |
201 | .nranges = 12, | 202 | .nranges = 12, |
202 | .range = (struct ab5500_reg_range[]) { | 203 | .range = (struct ab5500_reg_range[]) { |
203 | { | 204 | { |
204 | .first = 0x01, | 205 | .first = 0x01, |
205 | .last = 0x01, | 206 | .last = 0x01, |
206 | .perm = AB5500_PERM_RW, | 207 | .perm = AB5500_PERM_RW, |
207 | }, | 208 | }, |
208 | { | 209 | { |
209 | .first = 0x80, | 210 | .first = 0x80, |
210 | .last = 0x83, | 211 | .last = 0x83, |
211 | .perm = AB5500_PERM_RW, | 212 | .perm = AB5500_PERM_RW, |
212 | }, | 213 | }, |
213 | { | 214 | { |
214 | .first = 0x87, | 215 | .first = 0x87, |
215 | .last = 0x8A, | 216 | .last = 0x8A, |
216 | .perm = AB5500_PERM_RW, | 217 | .perm = AB5500_PERM_RW, |
217 | }, | 218 | }, |
218 | { | 219 | { |
219 | .first = 0x8B, | 220 | .first = 0x8B, |
220 | .last = 0x8B, | 221 | .last = 0x8B, |
221 | .perm = AB5500_PERM_RO, | 222 | .perm = AB5500_PERM_RO, |
222 | }, | 223 | }, |
223 | { | 224 | { |
224 | .first = 0x91, | 225 | .first = 0x91, |
225 | .last = 0x92, | 226 | .last = 0x92, |
226 | .perm = AB5500_PERM_RO, | 227 | .perm = AB5500_PERM_RO, |
227 | }, | 228 | }, |
228 | { | 229 | { |
229 | .first = 0x93, | 230 | .first = 0x93, |
230 | .last = 0x93, | 231 | .last = 0x93, |
231 | .perm = AB5500_PERM_RW, | 232 | .perm = AB5500_PERM_RW, |
232 | }, | 233 | }, |
233 | { | 234 | { |
234 | .first = 0x94, | 235 | .first = 0x94, |
235 | .last = 0x94, | 236 | .last = 0x94, |
236 | .perm = AB5500_PERM_RO, | 237 | .perm = AB5500_PERM_RO, |
237 | }, | 238 | }, |
238 | { | 239 | { |
239 | .first = 0xA8, | 240 | .first = 0xA8, |
240 | .last = 0xB0, | 241 | .last = 0xB0, |
241 | .perm = AB5500_PERM_RO, | 242 | .perm = AB5500_PERM_RO, |
242 | }, | 243 | }, |
243 | { | 244 | { |
244 | .first = 0xB2, | 245 | .first = 0xB2, |
245 | .last = 0xB2, | 246 | .last = 0xB2, |
246 | .perm = AB5500_PERM_RO, | 247 | .perm = AB5500_PERM_RO, |
247 | }, | 248 | }, |
248 | { | 249 | { |
249 | .first = 0xB4, | 250 | .first = 0xB4, |
250 | .last = 0xBC, | 251 | .last = 0xBC, |
251 | .perm = AB5500_PERM_RO, | 252 | .perm = AB5500_PERM_RO, |
252 | }, | 253 | }, |
253 | { | 254 | { |
254 | .first = 0xBF, | 255 | .first = 0xBF, |
255 | .last = 0xBF, | 256 | .last = 0xBF, |
256 | .perm = AB5500_PERM_RO, | 257 | .perm = AB5500_PERM_RO, |
257 | }, | 258 | }, |
258 | { | 259 | { |
259 | .first = 0xC1, | 260 | .first = 0xC1, |
260 | .last = 0xC5, | 261 | .last = 0xC5, |
261 | .perm = AB5500_PERM_RO, | 262 | .perm = AB5500_PERM_RO, |
262 | }, | 263 | }, |
263 | }, | 264 | }, |
264 | }, | 265 | }, |
265 | [AB5500_BANK_IT] = { | 266 | [AB5500_BANK_IT] = { |
266 | .bankid = AB5500_BANK_IT, | 267 | .bankid = AB5500_BANK_IT, |
267 | .nranges = 4, | 268 | .nranges = 4, |
268 | .range = (struct ab5500_reg_range[]) { | 269 | .range = (struct ab5500_reg_range[]) { |
269 | { | 270 | { |
270 | .first = 0x00, | 271 | .first = 0x00, |
271 | .last = 0x02, | 272 | .last = 0x02, |
272 | .perm = AB5500_PERM_RO, | 273 | .perm = AB5500_PERM_RO, |
273 | }, | 274 | }, |
274 | { | 275 | { |
275 | .first = 0x20, | 276 | .first = 0x20, |
276 | .last = 0x36, | 277 | .last = 0x36, |
277 | .perm = AB5500_PERM_RO, | 278 | .perm = AB5500_PERM_RO, |
278 | }, | 279 | }, |
279 | { | 280 | { |
280 | .first = 0x40, | 281 | .first = 0x40, |
281 | .last = 0x56, | 282 | .last = 0x56, |
282 | .perm = AB5500_PERM_RO, | 283 | .perm = AB5500_PERM_RO, |
283 | }, | 284 | }, |
284 | { | 285 | { |
285 | .first = 0x60, | 286 | .first = 0x60, |
286 | .last = 0x76, | 287 | .last = 0x76, |
287 | .perm = AB5500_PERM_RO, | 288 | .perm = AB5500_PERM_RO, |
288 | }, | 289 | }, |
289 | }, | 290 | }, |
290 | }, | 291 | }, |
291 | [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = { | 292 | [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = { |
292 | .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST, | 293 | .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST, |
293 | .nranges = 7, | 294 | .nranges = 7, |
294 | .range = (struct ab5500_reg_range[]) { | 295 | .range = (struct ab5500_reg_range[]) { |
295 | { | 296 | { |
296 | .first = 0x02, | 297 | .first = 0x02, |
297 | .last = 0x02, | 298 | .last = 0x02, |
298 | .perm = AB5500_PERM_RW, | 299 | .perm = AB5500_PERM_RW, |
299 | }, | 300 | }, |
300 | { | 301 | { |
301 | .first = 0x12, | 302 | .first = 0x12, |
302 | .last = 0x12, | 303 | .last = 0x12, |
303 | .perm = AB5500_PERM_RW, | 304 | .perm = AB5500_PERM_RW, |
304 | }, | 305 | }, |
305 | { | 306 | { |
306 | .first = 0x30, | 307 | .first = 0x30, |
307 | .last = 0x34, | 308 | .last = 0x34, |
308 | .perm = AB5500_PERM_RW, | 309 | .perm = AB5500_PERM_RW, |
309 | }, | 310 | }, |
310 | { | 311 | { |
311 | .first = 0x40, | 312 | .first = 0x40, |
312 | .last = 0x44, | 313 | .last = 0x44, |
313 | .perm = AB5500_PERM_RW, | 314 | .perm = AB5500_PERM_RW, |
314 | }, | 315 | }, |
315 | { | 316 | { |
316 | .first = 0x50, | 317 | .first = 0x50, |
317 | .last = 0x54, | 318 | .last = 0x54, |
318 | .perm = AB5500_PERM_RW, | 319 | .perm = AB5500_PERM_RW, |
319 | }, | 320 | }, |
320 | { | 321 | { |
321 | .first = 0x60, | 322 | .first = 0x60, |
322 | .last = 0x64, | 323 | .last = 0x64, |
323 | .perm = AB5500_PERM_RW, | 324 | .perm = AB5500_PERM_RW, |
324 | }, | 325 | }, |
325 | { | 326 | { |
326 | .first = 0x70, | 327 | .first = 0x70, |
327 | .last = 0x74, | 328 | .last = 0x74, |
328 | .perm = AB5500_PERM_RW, | 329 | .perm = AB5500_PERM_RW, |
329 | }, | 330 | }, |
330 | }, | 331 | }, |
331 | }, | 332 | }, |
332 | [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = { | 333 | [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = { |
333 | .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, | 334 | .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, |
334 | .nranges = 13, | 335 | .nranges = 13, |
335 | .range = (struct ab5500_reg_range[]) { | 336 | .range = (struct ab5500_reg_range[]) { |
336 | { | 337 | { |
337 | .first = 0x01, | 338 | .first = 0x01, |
338 | .last = 0x01, | 339 | .last = 0x01, |
339 | .perm = AB5500_PERM_RW, | 340 | .perm = AB5500_PERM_RW, |
340 | }, | 341 | }, |
341 | { | 342 | { |
342 | .first = 0x02, | 343 | .first = 0x02, |
343 | .last = 0x02, | 344 | .last = 0x02, |
344 | .perm = AB5500_PERM_RO, | 345 | .perm = AB5500_PERM_RO, |
345 | }, | 346 | }, |
346 | { | 347 | { |
347 | .first = 0x0D, | 348 | .first = 0x0D, |
348 | .last = 0x0F, | 349 | .last = 0x0F, |
349 | .perm = AB5500_PERM_RW, | 350 | .perm = AB5500_PERM_RW, |
350 | }, | 351 | }, |
351 | { | 352 | { |
352 | .first = 0x1C, | 353 | .first = 0x1C, |
353 | .last = 0x1C, | 354 | .last = 0x1C, |
354 | .perm = AB5500_PERM_RW, | 355 | .perm = AB5500_PERM_RW, |
355 | }, | 356 | }, |
356 | { | 357 | { |
357 | .first = 0x1E, | 358 | .first = 0x1E, |
358 | .last = 0x1E, | 359 | .last = 0x1E, |
359 | .perm = AB5500_PERM_RW, | 360 | .perm = AB5500_PERM_RW, |
360 | }, | 361 | }, |
361 | { | 362 | { |
362 | .first = 0x20, | 363 | .first = 0x20, |
363 | .last = 0x21, | 364 | .last = 0x21, |
364 | .perm = AB5500_PERM_RW, | 365 | .perm = AB5500_PERM_RW, |
365 | }, | 366 | }, |
366 | { | 367 | { |
367 | .first = 0x25, | 368 | .first = 0x25, |
368 | .last = 0x25, | 369 | .last = 0x25, |
369 | .perm = AB5500_PERM_RW, | 370 | .perm = AB5500_PERM_RW, |
370 | }, | 371 | }, |
371 | { | 372 | { |
372 | .first = 0x28, | 373 | .first = 0x28, |
373 | .last = 0x2A, | 374 | .last = 0x2A, |
374 | .perm = AB5500_PERM_RW, | 375 | .perm = AB5500_PERM_RW, |
375 | }, | 376 | }, |
376 | { | 377 | { |
377 | .first = 0x30, | 378 | .first = 0x30, |
378 | .last = 0x33, | 379 | .last = 0x33, |
379 | .perm = AB5500_PERM_RW, | 380 | .perm = AB5500_PERM_RW, |
380 | }, | 381 | }, |
381 | { | 382 | { |
382 | .first = 0x40, | 383 | .first = 0x40, |
383 | .last = 0x43, | 384 | .last = 0x43, |
384 | .perm = AB5500_PERM_RW, | 385 | .perm = AB5500_PERM_RW, |
385 | }, | 386 | }, |
386 | { | 387 | { |
387 | .first = 0x50, | 388 | .first = 0x50, |
388 | .last = 0x53, | 389 | .last = 0x53, |
389 | .perm = AB5500_PERM_RW, | 390 | .perm = AB5500_PERM_RW, |
390 | }, | 391 | }, |
391 | { | 392 | { |
392 | .first = 0x60, | 393 | .first = 0x60, |
393 | .last = 0x63, | 394 | .last = 0x63, |
394 | .perm = AB5500_PERM_RW, | 395 | .perm = AB5500_PERM_RW, |
395 | }, | 396 | }, |
396 | { | 397 | { |
397 | .first = 0x70, | 398 | .first = 0x70, |
398 | .last = 0x73, | 399 | .last = 0x73, |
399 | .perm = AB5500_PERM_RW, | 400 | .perm = AB5500_PERM_RW, |
400 | }, | 401 | }, |
401 | }, | 402 | }, |
402 | }, | 403 | }, |
403 | [AB5500_BANK_VIBRA] = { | 404 | [AB5500_BANK_VIBRA] = { |
404 | .bankid = AB5500_BANK_VIBRA, | 405 | .bankid = AB5500_BANK_VIBRA, |
405 | .nranges = 2, | 406 | .nranges = 2, |
406 | .range = (struct ab5500_reg_range[]) { | 407 | .range = (struct ab5500_reg_range[]) { |
407 | { | 408 | { |
408 | .first = 0x10, | 409 | .first = 0x10, |
409 | .last = 0x13, | 410 | .last = 0x13, |
410 | .perm = AB5500_PERM_RW, | 411 | .perm = AB5500_PERM_RW, |
411 | }, | 412 | }, |
412 | { | 413 | { |
413 | .first = 0xFE, | 414 | .first = 0xFE, |
414 | .last = 0xFE, | 415 | .last = 0xFE, |
415 | .perm = AB5500_PERM_RW, | 416 | .perm = AB5500_PERM_RW, |
416 | }, | 417 | }, |
417 | }, | 418 | }, |
418 | }, | 419 | }, |
419 | [AB5500_BANK_AUDIO_HEADSETUSB] = { | 420 | [AB5500_BANK_AUDIO_HEADSETUSB] = { |
420 | .bankid = AB5500_BANK_AUDIO_HEADSETUSB, | 421 | .bankid = AB5500_BANK_AUDIO_HEADSETUSB, |
421 | .nranges = 2, | 422 | .nranges = 2, |
422 | .range = (struct ab5500_reg_range[]) { | 423 | .range = (struct ab5500_reg_range[]) { |
423 | { | 424 | { |
424 | .first = 0x00, | 425 | .first = 0x00, |
425 | .last = 0x48, | 426 | .last = 0x48, |
426 | .perm = AB5500_PERM_RW, | 427 | .perm = AB5500_PERM_RW, |
427 | }, | 428 | }, |
428 | { | 429 | { |
429 | .first = 0xEB, | 430 | .first = 0xEB, |
430 | .last = 0xFB, | 431 | .last = 0xFB, |
431 | .perm = AB5500_PERM_RW, | 432 | .perm = AB5500_PERM_RW, |
432 | }, | 433 | }, |
433 | }, | 434 | }, |
434 | }, | 435 | }, |
435 | [AB5500_BANK_SIM_USBSIM] = { | 436 | [AB5500_BANK_SIM_USBSIM] = { |
436 | .bankid = AB5500_BANK_SIM_USBSIM, | 437 | .bankid = AB5500_BANK_SIM_USBSIM, |
437 | .nranges = 1, | 438 | .nranges = 1, |
438 | .range = (struct ab5500_reg_range[]) { | 439 | .range = (struct ab5500_reg_range[]) { |
439 | { | 440 | { |
440 | .first = 0x13, | 441 | .first = 0x13, |
441 | .last = 0x19, | 442 | .last = 0x19, |
442 | .perm = AB5500_PERM_RW, | 443 | .perm = AB5500_PERM_RW, |
443 | }, | 444 | }, |
444 | }, | 445 | }, |
445 | }, | 446 | }, |
446 | [AB5500_BANK_VDENC] = { | 447 | [AB5500_BANK_VDENC] = { |
447 | .bankid = AB5500_BANK_VDENC, | 448 | .bankid = AB5500_BANK_VDENC, |
448 | .nranges = 12, | 449 | .nranges = 12, |
449 | .range = (struct ab5500_reg_range[]) { | 450 | .range = (struct ab5500_reg_range[]) { |
450 | { | 451 | { |
451 | .first = 0x00, | 452 | .first = 0x00, |
452 | .last = 0x08, | 453 | .last = 0x08, |
453 | .perm = AB5500_PERM_RW, | 454 | .perm = AB5500_PERM_RW, |
454 | }, | 455 | }, |
455 | { | 456 | { |
456 | .first = 0x09, | 457 | .first = 0x09, |
457 | .last = 0x09, | 458 | .last = 0x09, |
458 | .perm = AB5500_PERM_RO, | 459 | .perm = AB5500_PERM_RO, |
459 | }, | 460 | }, |
460 | { | 461 | { |
461 | .first = 0x0A, | 462 | .first = 0x0A, |
462 | .last = 0x12, | 463 | .last = 0x12, |
463 | .perm = AB5500_PERM_RW, | 464 | .perm = AB5500_PERM_RW, |
464 | }, | 465 | }, |
465 | { | 466 | { |
466 | .first = 0x15, | 467 | .first = 0x15, |
467 | .last = 0x19, | 468 | .last = 0x19, |
468 | .perm = AB5500_PERM_RW, | 469 | .perm = AB5500_PERM_RW, |
469 | }, | 470 | }, |
470 | { | 471 | { |
471 | .first = 0x1B, | 472 | .first = 0x1B, |
472 | .last = 0x21, | 473 | .last = 0x21, |
473 | .perm = AB5500_PERM_RW, | 474 | .perm = AB5500_PERM_RW, |
474 | }, | 475 | }, |
475 | { | 476 | { |
476 | .first = 0x27, | 477 | .first = 0x27, |
477 | .last = 0x2C, | 478 | .last = 0x2C, |
478 | .perm = AB5500_PERM_RW, | 479 | .perm = AB5500_PERM_RW, |
479 | }, | 480 | }, |
480 | { | 481 | { |
481 | .first = 0x41, | 482 | .first = 0x41, |
482 | .last = 0x41, | 483 | .last = 0x41, |
483 | .perm = AB5500_PERM_RW, | 484 | .perm = AB5500_PERM_RW, |
484 | }, | 485 | }, |
485 | { | 486 | { |
486 | .first = 0x45, | 487 | .first = 0x45, |
487 | .last = 0x5B, | 488 | .last = 0x5B, |
488 | .perm = AB5500_PERM_RW, | 489 | .perm = AB5500_PERM_RW, |
489 | }, | 490 | }, |
490 | { | 491 | { |
491 | .first = 0x5D, | 492 | .first = 0x5D, |
492 | .last = 0x5D, | 493 | .last = 0x5D, |
493 | .perm = AB5500_PERM_RW, | 494 | .perm = AB5500_PERM_RW, |
494 | }, | 495 | }, |
495 | { | 496 | { |
496 | .first = 0x69, | 497 | .first = 0x69, |
497 | .last = 0x69, | 498 | .last = 0x69, |
498 | .perm = AB5500_PERM_RW, | 499 | .perm = AB5500_PERM_RW, |
499 | }, | 500 | }, |
500 | { | 501 | { |
501 | .first = 0x6C, | 502 | .first = 0x6C, |
502 | .last = 0x6D, | 503 | .last = 0x6D, |
503 | .perm = AB5500_PERM_RW, | 504 | .perm = AB5500_PERM_RW, |
504 | }, | 505 | }, |
505 | { | 506 | { |
506 | .first = 0x80, | 507 | .first = 0x80, |
507 | .last = 0x81, | 508 | .last = 0x81, |
508 | .perm = AB5500_PERM_RW, | 509 | .perm = AB5500_PERM_RW, |
509 | }, | 510 | }, |
510 | }, | 511 | }, |
511 | }, | 512 | }, |
512 | }; | 513 | }; |
513 | 514 | ||
514 | static int ab5500_registers_print(struct seq_file *s, void *p) | 515 | static int ab5500_registers_print(struct seq_file *s, void *p) |
515 | { | 516 | { |
516 | struct ab5500 *ab = s->private; | 517 | struct ab5500 *ab = s->private; |
517 | unsigned int i; | 518 | unsigned int i; |
518 | u8 bank = (u8)ab->debug_bank; | 519 | u8 bank = (u8)ab->debug_bank; |
519 | 520 | ||
520 | seq_printf(s, "ab5500 register values:\n"); | 521 | seq_printf(s, "ab5500 register values:\n"); |
521 | for (bank = 0; bank < AB5500_NUM_BANKS; bank++) { | 522 | for (bank = 0; bank < AB5500_NUM_BANKS; bank++) { |
522 | seq_printf(s, " bank %u, %s (0x%x):\n", bank, | 523 | seq_printf(s, " bank %u, %s (0x%x):\n", bank, |
523 | bankinfo[bank].name, | 524 | bankinfo[bank].name, |
524 | bankinfo[bank].slave_addr); | 525 | bankinfo[bank].slave_addr); |
525 | for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) { | 526 | for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) { |
526 | u8 reg; | 527 | u8 reg; |
527 | int err; | 528 | int err; |
528 | 529 | ||
529 | for (reg = ab5500_reg_ranges[bank].range[i].first; | 530 | for (reg = ab5500_reg_ranges[bank].range[i].first; |
530 | reg <= ab5500_reg_ranges[bank].range[i].last; | 531 | reg <= ab5500_reg_ranges[bank].range[i].last; |
531 | reg++) { | 532 | reg++) { |
532 | u8 value; | 533 | u8 value; |
533 | 534 | ||
534 | err = ab5500_get_register_interruptible_raw(ab, | 535 | err = ab5500_get_register_interruptible_raw(ab, |
535 | bank, reg, | 536 | bank, reg, |
536 | &value); | 537 | &value); |
537 | if (err < 0) { | 538 | if (err < 0) { |
538 | dev_err(ab->dev, "get_reg failed %d" | 539 | dev_err(ab->dev, "get_reg failed %d" |
539 | "bank 0x%x reg 0x%x\n", | 540 | "bank 0x%x reg 0x%x\n", |
540 | err, bank, reg); | 541 | err, bank, reg); |
541 | return err; | 542 | return err; |
542 | } | 543 | } |
543 | 544 | ||
544 | err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n", | 545 | err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n", |
545 | bank, reg, value); | 546 | bank, reg, value); |
546 | if (err < 0) { | 547 | if (err < 0) { |
547 | dev_err(ab->dev, | 548 | dev_err(ab->dev, |
548 | "seq_printf overflow\n"); | 549 | "seq_printf overflow\n"); |
549 | /* | 550 | /* |
550 | * Error is not returned here since | 551 | * Error is not returned here since |
551 | * the output is wanted in any case | 552 | * the output is wanted in any case |
552 | */ | 553 | */ |
553 | return 0; | 554 | return 0; |
554 | } | 555 | } |
555 | } | 556 | } |
556 | } | 557 | } |
557 | } | 558 | } |
558 | return 0; | 559 | return 0; |
559 | } | 560 | } |
560 | 561 | ||
561 | static int ab5500_registers_open(struct inode *inode, struct file *file) | 562 | static int ab5500_registers_open(struct inode *inode, struct file *file) |
562 | { | 563 | { |
563 | return single_open(file, ab5500_registers_print, inode->i_private); | 564 | return single_open(file, ab5500_registers_print, inode->i_private); |
564 | } | 565 | } |
565 | 566 | ||
566 | static const struct file_operations ab5500_registers_fops = { | 567 | static const struct file_operations ab5500_registers_fops = { |
567 | .open = ab5500_registers_open, | 568 | .open = ab5500_registers_open, |
568 | .read = seq_read, | 569 | .read = seq_read, |
569 | .llseek = seq_lseek, | 570 | .llseek = seq_lseek, |
570 | .release = single_release, | 571 | .release = single_release, |
571 | .owner = THIS_MODULE, | 572 | .owner = THIS_MODULE, |
572 | }; | 573 | }; |
573 | 574 | ||
574 | static int ab5500_bank_print(struct seq_file *s, void *p) | 575 | static int ab5500_bank_print(struct seq_file *s, void *p) |
575 | { | 576 | { |
576 | struct ab5500 *ab = s->private; | 577 | struct ab5500 *ab = s->private; |
577 | 578 | ||
578 | seq_printf(s, "%d\n", ab->debug_bank); | 579 | seq_printf(s, "%d\n", ab->debug_bank); |
579 | return 0; | 580 | return 0; |
580 | } | 581 | } |
581 | 582 | ||
582 | static int ab5500_bank_open(struct inode *inode, struct file *file) | 583 | static int ab5500_bank_open(struct inode *inode, struct file *file) |
583 | { | 584 | { |
584 | return single_open(file, ab5500_bank_print, inode->i_private); | 585 | return single_open(file, ab5500_bank_print, inode->i_private); |
585 | } | 586 | } |
586 | 587 | ||
587 | static ssize_t ab5500_bank_write(struct file *file, | 588 | static ssize_t ab5500_bank_write(struct file *file, |
588 | const char __user *user_buf, | 589 | const char __user *user_buf, |
589 | size_t count, loff_t *ppos) | 590 | size_t count, loff_t *ppos) |
590 | { | 591 | { |
591 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; | 592 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; |
592 | char buf[32]; | 593 | char buf[32]; |
593 | int buf_size; | 594 | int buf_size; |
594 | unsigned long user_bank; | 595 | unsigned long user_bank; |
595 | int err; | 596 | int err; |
596 | 597 | ||
597 | /* Get userspace string and assure termination */ | 598 | /* Get userspace string and assure termination */ |
598 | buf_size = min(count, (sizeof(buf) - 1)); | 599 | buf_size = min(count, (sizeof(buf) - 1)); |
599 | if (copy_from_user(buf, user_buf, buf_size)) | 600 | if (copy_from_user(buf, user_buf, buf_size)) |
600 | return -EFAULT; | 601 | return -EFAULT; |
601 | buf[buf_size] = 0; | 602 | buf[buf_size] = 0; |
602 | 603 | ||
603 | err = strict_strtoul(buf, 0, &user_bank); | 604 | err = strict_strtoul(buf, 0, &user_bank); |
604 | if (err) | 605 | if (err) |
605 | return -EINVAL; | 606 | return -EINVAL; |
606 | 607 | ||
607 | if (user_bank >= AB5500_NUM_BANKS) { | 608 | if (user_bank >= AB5500_NUM_BANKS) { |
608 | dev_err(ab->dev, | 609 | dev_err(ab->dev, |
609 | "debugfs error input > number of banks\n"); | 610 | "debugfs error input > number of banks\n"); |
610 | return -EINVAL; | 611 | return -EINVAL; |
611 | } | 612 | } |
612 | 613 | ||
613 | ab->debug_bank = user_bank; | 614 | ab->debug_bank = user_bank; |
614 | 615 | ||
615 | return buf_size; | 616 | return buf_size; |
616 | } | 617 | } |
617 | 618 | ||
618 | static int ab5500_address_print(struct seq_file *s, void *p) | 619 | static int ab5500_address_print(struct seq_file *s, void *p) |
619 | { | 620 | { |
620 | struct ab5500 *ab = s->private; | 621 | struct ab5500 *ab = s->private; |
621 | 622 | ||
622 | seq_printf(s, "0x%02X\n", ab->debug_address); | 623 | seq_printf(s, "0x%02X\n", ab->debug_address); |
623 | return 0; | 624 | return 0; |
624 | } | 625 | } |
625 | 626 | ||
626 | static int ab5500_address_open(struct inode *inode, struct file *file) | 627 | static int ab5500_address_open(struct inode *inode, struct file *file) |
627 | { | 628 | { |
628 | return single_open(file, ab5500_address_print, inode->i_private); | 629 | return single_open(file, ab5500_address_print, inode->i_private); |
629 | } | 630 | } |
630 | 631 | ||
631 | static ssize_t ab5500_address_write(struct file *file, | 632 | static ssize_t ab5500_address_write(struct file *file, |
632 | const char __user *user_buf, | 633 | const char __user *user_buf, |
633 | size_t count, loff_t *ppos) | 634 | size_t count, loff_t *ppos) |
634 | { | 635 | { |
635 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; | 636 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; |
636 | char buf[32]; | 637 | char buf[32]; |
637 | int buf_size; | 638 | int buf_size; |
638 | unsigned long user_address; | 639 | unsigned long user_address; |
639 | int err; | 640 | int err; |
640 | 641 | ||
641 | /* Get userspace string and assure termination */ | 642 | /* Get userspace string and assure termination */ |
642 | buf_size = min(count, (sizeof(buf) - 1)); | 643 | buf_size = min(count, (sizeof(buf) - 1)); |
643 | if (copy_from_user(buf, user_buf, buf_size)) | 644 | if (copy_from_user(buf, user_buf, buf_size)) |
644 | return -EFAULT; | 645 | return -EFAULT; |
645 | buf[buf_size] = 0; | 646 | buf[buf_size] = 0; |
646 | 647 | ||
647 | err = strict_strtoul(buf, 0, &user_address); | 648 | err = strict_strtoul(buf, 0, &user_address); |
648 | if (err) | 649 | if (err) |
649 | return -EINVAL; | 650 | return -EINVAL; |
650 | if (user_address > 0xff) { | 651 | if (user_address > 0xff) { |
651 | dev_err(ab->dev, | 652 | dev_err(ab->dev, |
652 | "debugfs error input > 0xff\n"); | 653 | "debugfs error input > 0xff\n"); |
653 | return -EINVAL; | 654 | return -EINVAL; |
654 | } | 655 | } |
655 | ab->debug_address = user_address; | 656 | ab->debug_address = user_address; |
656 | return buf_size; | 657 | return buf_size; |
657 | } | 658 | } |
658 | 659 | ||
659 | static int ab5500_val_print(struct seq_file *s, void *p) | 660 | static int ab5500_val_print(struct seq_file *s, void *p) |
660 | { | 661 | { |
661 | struct ab5500 *ab = s->private; | 662 | struct ab5500 *ab = s->private; |
662 | int err; | 663 | int err; |
663 | u8 regvalue; | 664 | u8 regvalue; |
664 | 665 | ||
665 | err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank, | 666 | err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank, |
666 | (u8)ab->debug_address, ®value); | 667 | (u8)ab->debug_address, ®value); |
667 | if (err) { | 668 | if (err) { |
668 | dev_err(ab->dev, "get_reg failed %d, bank 0x%x" | 669 | dev_err(ab->dev, "get_reg failed %d, bank 0x%x" |
669 | ", reg 0x%x\n", err, ab->debug_bank, | 670 | ", reg 0x%x\n", err, ab->debug_bank, |
670 | ab->debug_address); | 671 | ab->debug_address); |
671 | return -EINVAL; | 672 | return -EINVAL; |
672 | } | 673 | } |
673 | seq_printf(s, "0x%02X\n", regvalue); | 674 | seq_printf(s, "0x%02X\n", regvalue); |
674 | 675 | ||
675 | return 0; | 676 | return 0; |
676 | } | 677 | } |
677 | 678 | ||
678 | static int ab5500_val_open(struct inode *inode, struct file *file) | 679 | static int ab5500_val_open(struct inode *inode, struct file *file) |
679 | { | 680 | { |
680 | return single_open(file, ab5500_val_print, inode->i_private); | 681 | return single_open(file, ab5500_val_print, inode->i_private); |
681 | } | 682 | } |
682 | 683 | ||
683 | static ssize_t ab5500_val_write(struct file *file, | 684 | static ssize_t ab5500_val_write(struct file *file, |
684 | const char __user *user_buf, | 685 | const char __user *user_buf, |
685 | size_t count, loff_t *ppos) | 686 | size_t count, loff_t *ppos) |
686 | { | 687 | { |
687 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; | 688 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; |
688 | char buf[32]; | 689 | char buf[32]; |
689 | int buf_size; | 690 | int buf_size; |
690 | unsigned long user_val; | 691 | unsigned long user_val; |
691 | int err; | 692 | int err; |
692 | u8 regvalue; | 693 | u8 regvalue; |
693 | 694 | ||
694 | /* Get userspace string and assure termination */ | 695 | /* Get userspace string and assure termination */ |
695 | buf_size = min(count, (sizeof(buf)-1)); | 696 | buf_size = min(count, (sizeof(buf)-1)); |
696 | if (copy_from_user(buf, user_buf, buf_size)) | 697 | if (copy_from_user(buf, user_buf, buf_size)) |
697 | return -EFAULT; | 698 | return -EFAULT; |
698 | buf[buf_size] = 0; | 699 | buf[buf_size] = 0; |
699 | 700 | ||
700 | err = strict_strtoul(buf, 0, &user_val); | 701 | err = strict_strtoul(buf, 0, &user_val); |
701 | if (err) | 702 | if (err) |
702 | return -EINVAL; | 703 | return -EINVAL; |
703 | if (user_val > 0xff) { | 704 | if (user_val > 0xff) { |
704 | dev_err(ab->dev, | 705 | dev_err(ab->dev, |
705 | "debugfs error input > 0xff\n"); | 706 | "debugfs error input > 0xff\n"); |
706 | return -EINVAL; | 707 | return -EINVAL; |
707 | } | 708 | } |
708 | err = ab5500_mask_and_set_register_interruptible_raw( | 709 | err = ab5500_mask_and_set_register_interruptible_raw( |
709 | ab, (u8)ab->debug_bank, | 710 | ab, (u8)ab->debug_bank, |
710 | (u8)ab->debug_address, 0xFF, (u8)user_val); | 711 | (u8)ab->debug_address, 0xFF, (u8)user_val); |
711 | if (err) | 712 | if (err) |
712 | return -EINVAL; | 713 | return -EINVAL; |
713 | 714 | ||
714 | ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank, | 715 | ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank, |
715 | (u8)ab->debug_address, ®value); | 716 | (u8)ab->debug_address, ®value); |
716 | if (err) | 717 | if (err) |
717 | return -EINVAL; | 718 | return -EINVAL; |
718 | 719 | ||
719 | return buf_size; | 720 | return buf_size; |
720 | } | 721 | } |
721 | 722 | ||
722 | static const struct file_operations ab5500_bank_fops = { | 723 | static const struct file_operations ab5500_bank_fops = { |
723 | .open = ab5500_bank_open, | 724 | .open = ab5500_bank_open, |
724 | .write = ab5500_bank_write, | 725 | .write = ab5500_bank_write, |
725 | .read = seq_read, | 726 | .read = seq_read, |
726 | .llseek = seq_lseek, | 727 | .llseek = seq_lseek, |
727 | .release = single_release, | 728 | .release = single_release, |
728 | .owner = THIS_MODULE, | 729 | .owner = THIS_MODULE, |
729 | }; | 730 | }; |
730 | 731 | ||
731 | static const struct file_operations ab5500_address_fops = { | 732 | static const struct file_operations ab5500_address_fops = { |
732 | .open = ab5500_address_open, | 733 | .open = ab5500_address_open, |
733 | .write = ab5500_address_write, | 734 | .write = ab5500_address_write, |
734 | .read = seq_read, | 735 | .read = seq_read, |
735 | .llseek = seq_lseek, | 736 | .llseek = seq_lseek, |
736 | .release = single_release, | 737 | .release = single_release, |
737 | .owner = THIS_MODULE, | 738 | .owner = THIS_MODULE, |
738 | }; | 739 | }; |
739 | 740 | ||
740 | static const struct file_operations ab5500_val_fops = { | 741 | static const struct file_operations ab5500_val_fops = { |
741 | .open = ab5500_val_open, | 742 | .open = ab5500_val_open, |
742 | .write = ab5500_val_write, | 743 | .write = ab5500_val_write, |
743 | .read = seq_read, | 744 | .read = seq_read, |
744 | .llseek = seq_lseek, | 745 | .llseek = seq_lseek, |
745 | .release = single_release, | 746 | .release = single_release, |
746 | .owner = THIS_MODULE, | 747 | .owner = THIS_MODULE, |
747 | }; | 748 | }; |
748 | 749 | ||
749 | static struct dentry *ab5500_dir; | 750 | static struct dentry *ab5500_dir; |
750 | static struct dentry *ab5500_reg_file; | 751 | static struct dentry *ab5500_reg_file; |
751 | static struct dentry *ab5500_bank_file; | 752 | static struct dentry *ab5500_bank_file; |
752 | static struct dentry *ab5500_address_file; | 753 | static struct dentry *ab5500_address_file; |
753 | static struct dentry *ab5500_val_file; | 754 | static struct dentry *ab5500_val_file; |
754 | 755 | ||
755 | void __init ab5500_setup_debugfs(struct ab5500 *ab) | 756 | void __init ab5500_setup_debugfs(struct ab5500 *ab) |
756 | { | 757 | { |
757 | ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP; | 758 | ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP; |
758 | ab->debug_address = AB5500_CHIP_ID; | 759 | ab->debug_address = AB5500_CHIP_ID; |
759 | 760 | ||
760 | ab5500_dir = debugfs_create_dir("ab5500", NULL); | 761 | ab5500_dir = debugfs_create_dir("ab5500", NULL); |
761 | if (!ab5500_dir) | 762 | if (!ab5500_dir) |
762 | goto exit_no_debugfs; | 763 | goto exit_no_debugfs; |
763 | 764 | ||
764 | ab5500_reg_file = debugfs_create_file("all-bank-registers", | 765 | ab5500_reg_file = debugfs_create_file("all-bank-registers", |
765 | S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops); | 766 | S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops); |
766 | if (!ab5500_reg_file) | 767 | if (!ab5500_reg_file) |
767 | goto exit_destroy_dir; | 768 | goto exit_destroy_dir; |
768 | 769 | ||
769 | ab5500_bank_file = debugfs_create_file("register-bank", | 770 | ab5500_bank_file = debugfs_create_file("register-bank", |
770 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops); | 771 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops); |
771 | if (!ab5500_bank_file) | 772 | if (!ab5500_bank_file) |
772 | goto exit_destroy_reg; | 773 | goto exit_destroy_reg; |
773 | 774 | ||
774 | ab5500_address_file = debugfs_create_file("register-address", | 775 | ab5500_address_file = debugfs_create_file("register-address", |
775 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops); | 776 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops); |
776 | if (!ab5500_address_file) | 777 | if (!ab5500_address_file) |
777 | goto exit_destroy_bank; | 778 | goto exit_destroy_bank; |
778 | 779 | ||
779 | ab5500_val_file = debugfs_create_file("register-value", | 780 | ab5500_val_file = debugfs_create_file("register-value", |
780 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops); | 781 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops); |
781 | if (!ab5500_val_file) | 782 | if (!ab5500_val_file) |
782 | goto exit_destroy_address; | 783 | goto exit_destroy_address; |
783 | 784 | ||
784 | return; | 785 | return; |
785 | 786 | ||
786 | exit_destroy_address: | 787 | exit_destroy_address: |
787 | debugfs_remove(ab5500_address_file); | 788 | debugfs_remove(ab5500_address_file); |
788 | exit_destroy_bank: | 789 | exit_destroy_bank: |
789 | debugfs_remove(ab5500_bank_file); | 790 | debugfs_remove(ab5500_bank_file); |
790 | exit_destroy_reg: | 791 | exit_destroy_reg: |
791 | debugfs_remove(ab5500_reg_file); | 792 | debugfs_remove(ab5500_reg_file); |
792 | exit_destroy_dir: | 793 | exit_destroy_dir: |
793 | debugfs_remove(ab5500_dir); | 794 | debugfs_remove(ab5500_dir); |
794 | exit_no_debugfs: | 795 | exit_no_debugfs: |
795 | dev_err(ab->dev, "failed to create debugfs entries.\n"); | 796 | dev_err(ab->dev, "failed to create debugfs entries.\n"); |
796 | return; | 797 | return; |
797 | } | 798 | } |
798 | 799 | ||
799 | void __exit ab5500_remove_debugfs(void) | 800 | void __exit ab5500_remove_debugfs(void) |
800 | { | 801 | { |
801 | debugfs_remove(ab5500_val_file); | 802 | debugfs_remove(ab5500_val_file); |
802 | debugfs_remove(ab5500_address_file); | 803 | debugfs_remove(ab5500_address_file); |
803 | debugfs_remove(ab5500_bank_file); | 804 | debugfs_remove(ab5500_bank_file); |
804 | debugfs_remove(ab5500_reg_file); | 805 | debugfs_remove(ab5500_reg_file); |
805 | debugfs_remove(ab5500_dir); | 806 | debugfs_remove(ab5500_dir); |
806 | } | 807 | } |
807 | 808 |