diff options
Diffstat (limited to 'drivers/mfd/twl4030-core.c')
-rw-r--r-- | drivers/mfd/twl4030-core.c | 806 |
1 files changed, 806 insertions, 0 deletions
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c new file mode 100644 index 000000000000..dd843c4fbcc7 --- /dev/null +++ b/drivers/mfd/twl4030-core.c | |||
@@ -0,0 +1,806 @@ | |||
1 | /* | ||
2 | * twl4030_core.c - driver for TWL4030/TPS659x0 PM and audio CODEC devices | ||
3 | * | ||
4 | * Copyright (C) 2005-2006 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Modifications to defer interrupt handling to a kernel thread: | ||
7 | * Copyright (C) 2006 MontaVista Software, Inc. | ||
8 | * | ||
9 | * Based on tlv320aic23.c: | ||
10 | * Copyright (c) by Kai Svahn <kai.svahn@nokia.com> | ||
11 | * | ||
12 | * Code cleanup and modifications to IRQ handler. | ||
13 | * by syed khasim <x0khasim@ti.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/init.h> | ||
31 | #include <linux/mutex.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/err.h> | ||
35 | |||
36 | #include <linux/i2c.h> | ||
37 | #include <linux/i2c/twl4030.h> | ||
38 | |||
39 | |||
40 | /* | ||
41 | * The TWL4030 "Triton 2" is one of a family of a multi-function "Power | ||
42 | * Management and System Companion Device" chips originally designed for | ||
43 | * use in OMAP2 and OMAP 3 based systems. Its control interfaces use I2C, | ||
44 | * often at around 3 Mbit/sec, including for interrupt handling. | ||
45 | * | ||
46 | * This driver core provides genirq support for the interrupts emitted, | ||
47 | * by the various modules, and exports register access primitives. | ||
48 | * | ||
49 | * FIXME this driver currently requires use of the first interrupt line | ||
50 | * (and associated registers). | ||
51 | */ | ||
52 | |||
53 | #define DRIVER_NAME "twl4030" | ||
54 | |||
55 | #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ | ||
56 | defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) | ||
57 | #define twl_has_bci() true | ||
58 | #else | ||
59 | #define twl_has_bci() false | ||
60 | #endif | ||
61 | |||
62 | #if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE) | ||
63 | #define twl_has_keypad() true | ||
64 | #else | ||
65 | #define twl_has_keypad() false | ||
66 | #endif | ||
67 | |||
68 | #if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE) | ||
69 | #define twl_has_gpio() true | ||
70 | #else | ||
71 | #define twl_has_gpio() false | ||
72 | #endif | ||
73 | |||
74 | #if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) | ||
75 | #define twl_has_madc() true | ||
76 | #else | ||
77 | #define twl_has_madc() false | ||
78 | #endif | ||
79 | |||
80 | #if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE) | ||
81 | #define twl_has_rtc() true | ||
82 | #else | ||
83 | #define twl_has_rtc() false | ||
84 | #endif | ||
85 | |||
86 | #if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) | ||
87 | #define twl_has_usb() true | ||
88 | #else | ||
89 | #define twl_has_usb() false | ||
90 | #endif | ||
91 | |||
92 | |||
93 | /* Triton Core internal information (BEGIN) */ | ||
94 | |||
95 | /* Last - for index max*/ | ||
96 | #define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG | ||
97 | |||
98 | #define TWL4030_NUM_SLAVES 4 | ||
99 | |||
100 | |||
101 | /* Base Address defns for twl4030_map[] */ | ||
102 | |||
103 | /* subchip/slave 0 - USB ID */ | ||
104 | #define TWL4030_BASEADD_USB 0x0000 | ||
105 | |||
106 | /* subchip/slave 1 - AUD ID */ | ||
107 | #define TWL4030_BASEADD_AUDIO_VOICE 0x0000 | ||
108 | #define TWL4030_BASEADD_GPIO 0x0098 | ||
109 | #define TWL4030_BASEADD_INTBR 0x0085 | ||
110 | #define TWL4030_BASEADD_PIH 0x0080 | ||
111 | #define TWL4030_BASEADD_TEST 0x004C | ||
112 | |||
113 | /* subchip/slave 2 - AUX ID */ | ||
114 | #define TWL4030_BASEADD_INTERRUPTS 0x00B9 | ||
115 | #define TWL4030_BASEADD_LED 0x00EE | ||
116 | #define TWL4030_BASEADD_MADC 0x0000 | ||
117 | #define TWL4030_BASEADD_MAIN_CHARGE 0x0074 | ||
118 | #define TWL4030_BASEADD_PRECHARGE 0x00AA | ||
119 | #define TWL4030_BASEADD_PWM0 0x00F8 | ||
120 | #define TWL4030_BASEADD_PWM1 0x00FB | ||
121 | #define TWL4030_BASEADD_PWMA 0x00EF | ||
122 | #define TWL4030_BASEADD_PWMB 0x00F1 | ||
123 | #define TWL4030_BASEADD_KEYPAD 0x00D2 | ||
124 | |||
125 | /* subchip/slave 3 - POWER ID */ | ||
126 | #define TWL4030_BASEADD_BACKUP 0x0014 | ||
127 | #define TWL4030_BASEADD_INT 0x002E | ||
128 | #define TWL4030_BASEADD_PM_MASTER 0x0036 | ||
129 | #define TWL4030_BASEADD_PM_RECEIVER 0x005B | ||
130 | #define TWL4030_BASEADD_RTC 0x001C | ||
131 | #define TWL4030_BASEADD_SECURED_REG 0x0000 | ||
132 | |||
133 | /* Triton Core internal information (END) */ | ||
134 | |||
135 | |||
136 | /* Few power values */ | ||
137 | #define R_CFG_BOOT 0x05 | ||
138 | #define R_PROTECT_KEY 0x0E | ||
139 | |||
140 | /* access control values for R_PROTECT_KEY */ | ||
141 | #define KEY_UNLOCK1 0xce | ||
142 | #define KEY_UNLOCK2 0xec | ||
143 | #define KEY_LOCK 0x00 | ||
144 | |||
145 | /* some fields in R_CFG_BOOT */ | ||
146 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) | ||
147 | #define HFCLK_FREQ_26_MHZ (2 << 0) | ||
148 | #define HFCLK_FREQ_38p4_MHZ (3 << 0) | ||
149 | #define HIGH_PERF_SQ (1 << 3) | ||
150 | |||
151 | |||
152 | /*----------------------------------------------------------------------*/ | ||
153 | |||
154 | /* is driver active, bound to a chip? */ | ||
155 | static bool inuse; | ||
156 | |||
157 | /* Structure for each TWL4030 Slave */ | ||
158 | struct twl4030_client { | ||
159 | struct i2c_client *client; | ||
160 | u8 address; | ||
161 | |||
162 | /* max numb of i2c_msg required is for read =2 */ | ||
163 | struct i2c_msg xfer_msg[2]; | ||
164 | |||
165 | /* To lock access to xfer_msg */ | ||
166 | struct mutex xfer_lock; | ||
167 | }; | ||
168 | |||
169 | static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES]; | ||
170 | |||
171 | |||
172 | /* mapping the module id to slave id and base address */ | ||
173 | struct twl4030mapping { | ||
174 | unsigned char sid; /* Slave ID */ | ||
175 | unsigned char base; /* base address */ | ||
176 | }; | ||
177 | |||
178 | static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | ||
179 | /* | ||
180 | * NOTE: don't change this table without updating the | ||
181 | * <linux/i2c/twl4030.h> defines for TWL4030_MODULE_* | ||
182 | * so they continue to match the order in this table. | ||
183 | */ | ||
184 | |||
185 | { 0, TWL4030_BASEADD_USB }, | ||
186 | |||
187 | { 1, TWL4030_BASEADD_AUDIO_VOICE }, | ||
188 | { 1, TWL4030_BASEADD_GPIO }, | ||
189 | { 1, TWL4030_BASEADD_INTBR }, | ||
190 | { 1, TWL4030_BASEADD_PIH }, | ||
191 | { 1, TWL4030_BASEADD_TEST }, | ||
192 | |||
193 | { 2, TWL4030_BASEADD_KEYPAD }, | ||
194 | { 2, TWL4030_BASEADD_MADC }, | ||
195 | { 2, TWL4030_BASEADD_INTERRUPTS }, | ||
196 | { 2, TWL4030_BASEADD_LED }, | ||
197 | { 2, TWL4030_BASEADD_MAIN_CHARGE }, | ||
198 | { 2, TWL4030_BASEADD_PRECHARGE }, | ||
199 | { 2, TWL4030_BASEADD_PWM0 }, | ||
200 | { 2, TWL4030_BASEADD_PWM1 }, | ||
201 | { 2, TWL4030_BASEADD_PWMA }, | ||
202 | { 2, TWL4030_BASEADD_PWMB }, | ||
203 | |||
204 | { 3, TWL4030_BASEADD_BACKUP }, | ||
205 | { 3, TWL4030_BASEADD_INT }, | ||
206 | { 3, TWL4030_BASEADD_PM_MASTER }, | ||
207 | { 3, TWL4030_BASEADD_PM_RECEIVER }, | ||
208 | { 3, TWL4030_BASEADD_RTC }, | ||
209 | { 3, TWL4030_BASEADD_SECURED_REG }, | ||
210 | }; | ||
211 | |||
212 | /*----------------------------------------------------------------------*/ | ||
213 | |||
214 | /* Exported Functions */ | ||
215 | |||
216 | /** | ||
217 | * twl4030_i2c_write - Writes a n bit register in TWL4030 | ||
218 | * @mod_no: module number | ||
219 | * @value: an array of num_bytes+1 containing data to write | ||
220 | * @reg: register address (just offset will do) | ||
221 | * @num_bytes: number of bytes to transfer | ||
222 | * | ||
223 | * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and | ||
224 | * valid data starts at Offset 1. | ||
225 | * | ||
226 | * Returns the result of operation - 0 is success | ||
227 | */ | ||
228 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes) | ||
229 | { | ||
230 | int ret; | ||
231 | int sid; | ||
232 | struct twl4030_client *twl; | ||
233 | struct i2c_msg *msg; | ||
234 | |||
235 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { | ||
236 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | ||
237 | return -EPERM; | ||
238 | } | ||
239 | sid = twl4030_map[mod_no].sid; | ||
240 | twl = &twl4030_modules[sid]; | ||
241 | |||
242 | if (unlikely(!inuse)) { | ||
243 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); | ||
244 | return -EPERM; | ||
245 | } | ||
246 | mutex_lock(&twl->xfer_lock); | ||
247 | /* | ||
248 | * [MSG1]: fill the register address data | ||
249 | * fill the data Tx buffer | ||
250 | */ | ||
251 | msg = &twl->xfer_msg[0]; | ||
252 | msg->addr = twl->address; | ||
253 | msg->len = num_bytes + 1; | ||
254 | msg->flags = 0; | ||
255 | msg->buf = value; | ||
256 | /* over write the first byte of buffer with the register address */ | ||
257 | *value = twl4030_map[mod_no].base + reg; | ||
258 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); | ||
259 | mutex_unlock(&twl->xfer_lock); | ||
260 | |||
261 | /* i2cTransfer returns num messages.translate it pls.. */ | ||
262 | if (ret >= 0) | ||
263 | ret = 0; | ||
264 | return ret; | ||
265 | } | ||
266 | EXPORT_SYMBOL(twl4030_i2c_write); | ||
267 | |||
268 | /** | ||
269 | * twl4030_i2c_read - Reads a n bit register in TWL4030 | ||
270 | * @mod_no: module number | ||
271 | * @value: an array of num_bytes containing data to be read | ||
272 | * @reg: register address (just offset will do) | ||
273 | * @num_bytes: number of bytes to transfer | ||
274 | * | ||
275 | * Returns result of operation - num_bytes is success else failure. | ||
276 | */ | ||
277 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes) | ||
278 | { | ||
279 | int ret; | ||
280 | u8 val; | ||
281 | int sid; | ||
282 | struct twl4030_client *twl; | ||
283 | struct i2c_msg *msg; | ||
284 | |||
285 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { | ||
286 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | ||
287 | return -EPERM; | ||
288 | } | ||
289 | sid = twl4030_map[mod_no].sid; | ||
290 | twl = &twl4030_modules[sid]; | ||
291 | |||
292 | if (unlikely(!inuse)) { | ||
293 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); | ||
294 | return -EPERM; | ||
295 | } | ||
296 | mutex_lock(&twl->xfer_lock); | ||
297 | /* [MSG1] fill the register address data */ | ||
298 | msg = &twl->xfer_msg[0]; | ||
299 | msg->addr = twl->address; | ||
300 | msg->len = 1; | ||
301 | msg->flags = 0; /* Read the register value */ | ||
302 | val = twl4030_map[mod_no].base + reg; | ||
303 | msg->buf = &val; | ||
304 | /* [MSG2] fill the data rx buffer */ | ||
305 | msg = &twl->xfer_msg[1]; | ||
306 | msg->addr = twl->address; | ||
307 | msg->flags = I2C_M_RD; /* Read the register value */ | ||
308 | msg->len = num_bytes; /* only n bytes */ | ||
309 | msg->buf = value; | ||
310 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); | ||
311 | mutex_unlock(&twl->xfer_lock); | ||
312 | |||
313 | /* i2cTransfer returns num messages.translate it pls.. */ | ||
314 | if (ret >= 0) | ||
315 | ret = 0; | ||
316 | return ret; | ||
317 | } | ||
318 | EXPORT_SYMBOL(twl4030_i2c_read); | ||
319 | |||
320 | /** | ||
321 | * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030 | ||
322 | * @mod_no: module number | ||
323 | * @value: the value to be written 8 bit | ||
324 | * @reg: register address (just offset will do) | ||
325 | * | ||
326 | * Returns result of operation - 0 is success | ||
327 | */ | ||
328 | int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg) | ||
329 | { | ||
330 | |||
331 | /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ | ||
332 | u8 temp_buffer[2] = { 0 }; | ||
333 | /* offset 1 contains the data */ | ||
334 | temp_buffer[1] = value; | ||
335 | return twl4030_i2c_write(mod_no, temp_buffer, reg, 1); | ||
336 | } | ||
337 | EXPORT_SYMBOL(twl4030_i2c_write_u8); | ||
338 | |||
339 | /** | ||
340 | * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030 | ||
341 | * @mod_no: module number | ||
342 | * @value: the value read 8 bit | ||
343 | * @reg: register address (just offset will do) | ||
344 | * | ||
345 | * Returns result of operation - 0 is success | ||
346 | */ | ||
347 | int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) | ||
348 | { | ||
349 | return twl4030_i2c_read(mod_no, value, reg, 1); | ||
350 | } | ||
351 | EXPORT_SYMBOL(twl4030_i2c_read_u8); | ||
352 | |||
353 | /*----------------------------------------------------------------------*/ | ||
354 | |||
355 | /* | ||
356 | * NOTE: We know the first 8 IRQs after pdata->base_irq are | ||
357 | * for the PIH, and the next are for the PWR_INT SIH, since | ||
358 | * that's how twl_init_irq() sets things up. | ||
359 | */ | ||
360 | |||
361 | static int add_children(struct twl4030_platform_data *pdata) | ||
362 | { | ||
363 | struct platform_device *pdev = NULL; | ||
364 | struct twl4030_client *twl = NULL; | ||
365 | int status = 0; | ||
366 | |||
367 | if (twl_has_bci() && pdata->bci) { | ||
368 | twl = &twl4030_modules[3]; | ||
369 | |||
370 | pdev = platform_device_alloc("twl4030_bci", -1); | ||
371 | if (!pdev) { | ||
372 | pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME); | ||
373 | status = -ENOMEM; | ||
374 | goto err; | ||
375 | } | ||
376 | |||
377 | if (status == 0) { | ||
378 | pdev->dev.parent = &twl->client->dev; | ||
379 | status = platform_device_add_data(pdev, pdata->bci, | ||
380 | sizeof(*pdata->bci)); | ||
381 | if (status < 0) { | ||
382 | dev_dbg(&twl->client->dev, | ||
383 | "can't add bci data, %d\n", | ||
384 | status); | ||
385 | goto err; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | if (status == 0) { | ||
390 | struct resource r = { | ||
391 | .start = pdata->irq_base + 8 + 1, | ||
392 | .flags = IORESOURCE_IRQ, | ||
393 | }; | ||
394 | |||
395 | status = platform_device_add_resources(pdev, &r, 1); | ||
396 | } | ||
397 | |||
398 | if (status == 0) | ||
399 | status = platform_device_add(pdev); | ||
400 | |||
401 | if (status < 0) { | ||
402 | platform_device_put(pdev); | ||
403 | dev_dbg(&twl->client->dev, | ||
404 | "can't create bci dev, %d\n", | ||
405 | status); | ||
406 | goto err; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | if (twl_has_gpio() && pdata->gpio) { | ||
411 | twl = &twl4030_modules[1]; | ||
412 | |||
413 | pdev = platform_device_alloc("twl4030_gpio", -1); | ||
414 | if (!pdev) { | ||
415 | pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME); | ||
416 | status = -ENOMEM; | ||
417 | goto err; | ||
418 | } | ||
419 | |||
420 | /* more driver model init */ | ||
421 | if (status == 0) { | ||
422 | pdev->dev.parent = &twl->client->dev; | ||
423 | /* device_init_wakeup(&pdev->dev, 1); */ | ||
424 | |||
425 | status = platform_device_add_data(pdev, pdata->gpio, | ||
426 | sizeof(*pdata->gpio)); | ||
427 | if (status < 0) { | ||
428 | dev_dbg(&twl->client->dev, | ||
429 | "can't add gpio data, %d\n", | ||
430 | status); | ||
431 | goto err; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /* GPIO module IRQ */ | ||
436 | if (status == 0) { | ||
437 | struct resource r = { | ||
438 | .start = pdata->irq_base + 0, | ||
439 | .flags = IORESOURCE_IRQ, | ||
440 | }; | ||
441 | |||
442 | status = platform_device_add_resources(pdev, &r, 1); | ||
443 | } | ||
444 | |||
445 | if (status == 0) | ||
446 | status = platform_device_add(pdev); | ||
447 | |||
448 | if (status < 0) { | ||
449 | platform_device_put(pdev); | ||
450 | dev_dbg(&twl->client->dev, | ||
451 | "can't create gpio dev, %d\n", | ||
452 | status); | ||
453 | goto err; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | if (twl_has_keypad() && pdata->keypad) { | ||
458 | pdev = platform_device_alloc("twl4030_keypad", -1); | ||
459 | if (pdev) { | ||
460 | twl = &twl4030_modules[2]; | ||
461 | pdev->dev.parent = &twl->client->dev; | ||
462 | device_init_wakeup(&pdev->dev, 1); | ||
463 | status = platform_device_add_data(pdev, pdata->keypad, | ||
464 | sizeof(*pdata->keypad)); | ||
465 | if (status < 0) { | ||
466 | dev_dbg(&twl->client->dev, | ||
467 | "can't add keypad data, %d\n", | ||
468 | status); | ||
469 | platform_device_put(pdev); | ||
470 | goto err; | ||
471 | } | ||
472 | status = platform_device_add(pdev); | ||
473 | if (status < 0) { | ||
474 | platform_device_put(pdev); | ||
475 | dev_dbg(&twl->client->dev, | ||
476 | "can't create keypad dev, %d\n", | ||
477 | status); | ||
478 | goto err; | ||
479 | } | ||
480 | } else { | ||
481 | pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME); | ||
482 | status = -ENOMEM; | ||
483 | goto err; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | if (twl_has_madc() && pdata->madc) { | ||
488 | pdev = platform_device_alloc("twl4030_madc", -1); | ||
489 | if (pdev) { | ||
490 | twl = &twl4030_modules[2]; | ||
491 | pdev->dev.parent = &twl->client->dev; | ||
492 | device_init_wakeup(&pdev->dev, 1); | ||
493 | status = platform_device_add_data(pdev, pdata->madc, | ||
494 | sizeof(*pdata->madc)); | ||
495 | if (status < 0) { | ||
496 | platform_device_put(pdev); | ||
497 | dev_dbg(&twl->client->dev, | ||
498 | "can't add madc data, %d\n", | ||
499 | status); | ||
500 | goto err; | ||
501 | } | ||
502 | status = platform_device_add(pdev); | ||
503 | if (status < 0) { | ||
504 | platform_device_put(pdev); | ||
505 | dev_dbg(&twl->client->dev, | ||
506 | "can't create madc dev, %d\n", | ||
507 | status); | ||
508 | goto err; | ||
509 | } | ||
510 | } else { | ||
511 | pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME); | ||
512 | status = -ENOMEM; | ||
513 | goto err; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | if (twl_has_rtc()) { | ||
518 | twl = &twl4030_modules[3]; | ||
519 | |||
520 | pdev = platform_device_alloc("twl4030_rtc", -1); | ||
521 | if (!pdev) { | ||
522 | pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME); | ||
523 | status = -ENOMEM; | ||
524 | } else { | ||
525 | pdev->dev.parent = &twl->client->dev; | ||
526 | device_init_wakeup(&pdev->dev, 1); | ||
527 | } | ||
528 | |||
529 | /* | ||
530 | * REVISIT platform_data here currently might use of | ||
531 | * "msecure" line ... but for now we just expect board | ||
532 | * setup to tell the chip "we are secure" at all times. | ||
533 | * Eventually, Linux might become more aware of such | ||
534 | * HW security concerns, and "least privilege". | ||
535 | */ | ||
536 | |||
537 | /* RTC module IRQ */ | ||
538 | if (status == 0) { | ||
539 | struct resource r = { | ||
540 | .start = pdata->irq_base + 8 + 3, | ||
541 | .flags = IORESOURCE_IRQ, | ||
542 | }; | ||
543 | |||
544 | status = platform_device_add_resources(pdev, &r, 1); | ||
545 | } | ||
546 | |||
547 | if (status == 0) | ||
548 | status = platform_device_add(pdev); | ||
549 | |||
550 | if (status < 0) { | ||
551 | platform_device_put(pdev); | ||
552 | dev_dbg(&twl->client->dev, | ||
553 | "can't create rtc dev, %d\n", | ||
554 | status); | ||
555 | goto err; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (twl_has_usb() && pdata->usb) { | ||
560 | twl = &twl4030_modules[0]; | ||
561 | |||
562 | pdev = platform_device_alloc("twl4030_usb", -1); | ||
563 | if (!pdev) { | ||
564 | pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME); | ||
565 | status = -ENOMEM; | ||
566 | goto err; | ||
567 | } | ||
568 | |||
569 | if (status == 0) { | ||
570 | pdev->dev.parent = &twl->client->dev; | ||
571 | device_init_wakeup(&pdev->dev, 1); | ||
572 | status = platform_device_add_data(pdev, pdata->usb, | ||
573 | sizeof(*pdata->usb)); | ||
574 | if (status < 0) { | ||
575 | platform_device_put(pdev); | ||
576 | dev_dbg(&twl->client->dev, | ||
577 | "can't add usb data, %d\n", | ||
578 | status); | ||
579 | goto err; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (status == 0) { | ||
584 | struct resource r = { | ||
585 | .start = pdata->irq_base + 8 + 2, | ||
586 | .flags = IORESOURCE_IRQ, | ||
587 | }; | ||
588 | |||
589 | status = platform_device_add_resources(pdev, &r, 1); | ||
590 | } | ||
591 | |||
592 | if (status == 0) | ||
593 | status = platform_device_add(pdev); | ||
594 | |||
595 | if (status < 0) { | ||
596 | platform_device_put(pdev); | ||
597 | dev_dbg(&twl->client->dev, | ||
598 | "can't create usb dev, %d\n", | ||
599 | status); | ||
600 | } | ||
601 | } | ||
602 | |||
603 | err: | ||
604 | if (status) | ||
605 | pr_err("failed to add twl4030's children (status %d)\n", status); | ||
606 | return status; | ||
607 | } | ||
608 | |||
609 | /*----------------------------------------------------------------------*/ | ||
610 | |||
611 | /* | ||
612 | * These three functions initialize the on-chip clock framework, | ||
613 | * letting it generate the right frequencies for USB, MADC, and | ||
614 | * other purposes. | ||
615 | */ | ||
616 | static inline int __init protect_pm_master(void) | ||
617 | { | ||
618 | int e = 0; | ||
619 | |||
620 | e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK, | ||
621 | R_PROTECT_KEY); | ||
622 | return e; | ||
623 | } | ||
624 | |||
625 | static inline int __init unprotect_pm_master(void) | ||
626 | { | ||
627 | int e = 0; | ||
628 | |||
629 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1, | ||
630 | R_PROTECT_KEY); | ||
631 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2, | ||
632 | R_PROTECT_KEY); | ||
633 | return e; | ||
634 | } | ||
635 | |||
636 | static void __init clocks_init(void) | ||
637 | { | ||
638 | int e = 0; | ||
639 | struct clk *osc; | ||
640 | u32 rate; | ||
641 | u8 ctrl = HFCLK_FREQ_26_MHZ; | ||
642 | |||
643 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | ||
644 | if (cpu_is_omap2430()) | ||
645 | osc = clk_get(NULL, "osc_ck"); | ||
646 | else | ||
647 | osc = clk_get(NULL, "osc_sys_ck"); | ||
648 | #else | ||
649 | /* REVISIT for non-OMAP systems, pass the clock rate from | ||
650 | * board init code, using platform_data. | ||
651 | */ | ||
652 | osc = ERR_PTR(-EIO); | ||
653 | #endif | ||
654 | if (IS_ERR(osc)) { | ||
655 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | ||
656 | "using bootloader value (unknown osc rate)\n"); | ||
657 | return; | ||
658 | } | ||
659 | |||
660 | rate = clk_get_rate(osc); | ||
661 | clk_put(osc); | ||
662 | |||
663 | switch (rate) { | ||
664 | case 19200000: | ||
665 | ctrl = HFCLK_FREQ_19p2_MHZ; | ||
666 | break; | ||
667 | case 26000000: | ||
668 | ctrl = HFCLK_FREQ_26_MHZ; | ||
669 | break; | ||
670 | case 38400000: | ||
671 | ctrl = HFCLK_FREQ_38p4_MHZ; | ||
672 | break; | ||
673 | } | ||
674 | |||
675 | ctrl |= HIGH_PERF_SQ; | ||
676 | e |= unprotect_pm_master(); | ||
677 | /* effect->MADC+USB ck en */ | ||
678 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); | ||
679 | e |= protect_pm_master(); | ||
680 | |||
681 | if (e < 0) | ||
682 | pr_err("%s: clock init err [%d]\n", DRIVER_NAME, e); | ||
683 | } | ||
684 | |||
685 | /*----------------------------------------------------------------------*/ | ||
686 | |||
687 | int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | ||
688 | int twl_exit_irq(void); | ||
689 | |||
690 | static int twl4030_remove(struct i2c_client *client) | ||
691 | { | ||
692 | unsigned i; | ||
693 | int status; | ||
694 | |||
695 | status = twl_exit_irq(); | ||
696 | if (status < 0) | ||
697 | return status; | ||
698 | |||
699 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { | ||
700 | struct twl4030_client *twl = &twl4030_modules[i]; | ||
701 | |||
702 | if (twl->client && twl->client != client) | ||
703 | i2c_unregister_device(twl->client); | ||
704 | twl4030_modules[i].client = NULL; | ||
705 | } | ||
706 | inuse = false; | ||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ | ||
711 | static int | ||
712 | twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
713 | { | ||
714 | int status; | ||
715 | unsigned i; | ||
716 | struct twl4030_platform_data *pdata = client->dev.platform_data; | ||
717 | |||
718 | if (!pdata) { | ||
719 | dev_dbg(&client->dev, "no platform data?\n"); | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | |||
723 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { | ||
724 | dev_dbg(&client->dev, "can't talk I2C?\n"); | ||
725 | return -EIO; | ||
726 | } | ||
727 | |||
728 | if (inuse) { | ||
729 | dev_dbg(&client->dev, "driver is already in use\n"); | ||
730 | return -EBUSY; | ||
731 | } | ||
732 | |||
733 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { | ||
734 | struct twl4030_client *twl = &twl4030_modules[i]; | ||
735 | |||
736 | twl->address = client->addr + i; | ||
737 | if (i == 0) | ||
738 | twl->client = client; | ||
739 | else { | ||
740 | twl->client = i2c_new_dummy(client->adapter, | ||
741 | twl->address); | ||
742 | if (!twl->client) { | ||
743 | dev_err(&twl->client->dev, | ||
744 | "can't attach client %d\n", i); | ||
745 | status = -ENOMEM; | ||
746 | goto fail; | ||
747 | } | ||
748 | strlcpy(twl->client->name, id->name, | ||
749 | sizeof(twl->client->name)); | ||
750 | } | ||
751 | mutex_init(&twl->xfer_lock); | ||
752 | } | ||
753 | inuse = true; | ||
754 | |||
755 | /* setup clock framework */ | ||
756 | clocks_init(); | ||
757 | |||
758 | /* Maybe init the T2 Interrupt subsystem */ | ||
759 | if (client->irq | ||
760 | && pdata->irq_base | ||
761 | && pdata->irq_end > pdata->irq_base) { | ||
762 | status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); | ||
763 | if (status < 0) | ||
764 | goto fail; | ||
765 | } | ||
766 | |||
767 | status = add_children(pdata); | ||
768 | fail: | ||
769 | if (status < 0) | ||
770 | twl4030_remove(client); | ||
771 | return status; | ||
772 | } | ||
773 | |||
774 | static const struct i2c_device_id twl4030_ids[] = { | ||
775 | { "twl4030", 0 }, /* "Triton 2" */ | ||
776 | { "tps65950", 0 }, /* catalog version of twl4030 */ | ||
777 | { "tps65930", 0 }, /* fewer LDOs and DACs; no charger */ | ||
778 | { "tps65920", 0 }, /* fewer LDOs; no codec or charger */ | ||
779 | { "twl5030", 0 }, /* T2 updated */ | ||
780 | { /* end of list */ }, | ||
781 | }; | ||
782 | MODULE_DEVICE_TABLE(i2c, twl4030_ids); | ||
783 | |||
784 | /* One Client Driver , 4 Clients */ | ||
785 | static struct i2c_driver twl4030_driver = { | ||
786 | .driver.name = DRIVER_NAME, | ||
787 | .id_table = twl4030_ids, | ||
788 | .probe = twl4030_probe, | ||
789 | .remove = twl4030_remove, | ||
790 | }; | ||
791 | |||
792 | static int __init twl4030_init(void) | ||
793 | { | ||
794 | return i2c_add_driver(&twl4030_driver); | ||
795 | } | ||
796 | subsys_initcall(twl4030_init); | ||
797 | |||
798 | static void __exit twl4030_exit(void) | ||
799 | { | ||
800 | i2c_del_driver(&twl4030_driver); | ||
801 | } | ||
802 | module_exit(twl4030_exit); | ||
803 | |||
804 | MODULE_AUTHOR("Texas Instruments, Inc."); | ||
805 | MODULE_DESCRIPTION("I2C Core interface for TWL4030"); | ||
806 | MODULE_LICENSE("GPL"); | ||