2 * linux/drivers/i2c/chips/twl4030-power.c
4 * Handle TWL4030 Power initialization
6 * Copyright (C) 2008 Nokia Corporation
7 * Copyright (C) 2006 Texas Instruments, Inc
9 * Written by Kalle Jokiniemi
10 * Peter De Schrijver <peter.de-schrijver@nokia.com>
11 * Several fixes by Amit Kucheria <amit.kucheria@verdurent.com>
13 * This file is subject to the terms and conditions of the GNU General
14 * Public License. See the file "COPYING" in the main directory of this
15 * archive for more details.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/module.h>
29 #include <linux/i2c/twl.h>
30 #include <linux/platform_device.h>
32 #include <asm/mach-types.h>
34 static u8 twl4030_start_script_address
= 0x2b;
36 #define PWR_P1_SW_EVENTS 0x10
37 #define PWR_DEVOFF (1<<0)
39 #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36)
40 #define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b)
42 /* resource - hfclk */
43 #define R_HFCLKOUT_DEV_GRP PHY_TO_OFF_PM_RECEIVER(0xe6)
46 #define R_P1_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x46)
47 #define R_P2_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x47)
48 #define R_P3_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x48)
49 #define R_CFG_P1_TRANSITION PHY_TO_OFF_PM_MASTER(0x36)
50 #define R_CFG_P2_TRANSITION PHY_TO_OFF_PM_MASTER(0x37)
51 #define R_CFG_P3_TRANSITION PHY_TO_OFF_PM_MASTER(0x38)
53 #define LVL_WAKEUP 0x08
55 #define ENABLE_WARMRESET (1<<4)
57 #define END_OF_SCRIPT 0x3f
59 #define R_SEQ_ADD_A2S PHY_TO_OFF_PM_MASTER(0x55)
60 #define R_SEQ_ADD_S2A12 PHY_TO_OFF_PM_MASTER(0x56)
61 #define R_SEQ_ADD_S2A3 PHY_TO_OFF_PM_MASTER(0x57)
62 #define R_SEQ_ADD_WARM PHY_TO_OFF_PM_MASTER(0x58)
63 #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59)
64 #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a)
66 /* resource configuration registers
67 <RESOURCE>_DEV_GRP at address 'n+0'
68 <RESOURCE>_TYPE at address 'n+1'
69 <RESOURCE>_REMAP at address 'n+2'
70 <RESOURCE>_DEDICATED at address 'n+3'
72 #define DEV_GRP_OFFSET 0
74 #define REMAP_OFFSET 2
75 #define DEDICATED_OFFSET 3
77 /* Bit positions in the registers */
79 /* <RESOURCE>_DEV_GRP */
80 #define DEV_GRP_SHIFT 5
81 #define DEV_GRP_MASK (7 << DEV_GRP_SHIFT)
85 #define TYPE_MASK (7 << TYPE_SHIFT)
87 #define TYPE2_MASK (3 << TYPE2_SHIFT)
89 /* <RESOURCE>_REMAP */
90 #define SLEEP_STATE_SHIFT 0
91 #define SLEEP_STATE_MASK (0xf << SLEEP_STATE_SHIFT)
92 #define OFF_STATE_SHIFT 4
93 #define OFF_STATE_MASK (0xf << OFF_STATE_SHIFT)
95 static u8 res_config_addrs
[] = {
106 [RES_VINTANA1
] = 0x3f,
107 [RES_VINTANA2
] = 0x43,
108 [RES_VINTDIG
] = 0x47,
112 [RES_VUSB_1V5
] = 0x71,
113 [RES_VUSB_1V8
] = 0x74,
114 [RES_VUSB_3V1
] = 0x77,
117 [RES_NRES_PWRON
] = 0x82,
120 [RES_HFCLKOUT
] = 0x8b,
121 [RES_32KCLKOUT
] = 0x8e,
123 [RES_MAIN_REF
] = 0x94,
126 static int __init
twl4030_write_script_byte(u8 address
, u8 byte
)
130 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, address
,
134 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, byte
,
140 static int __init
twl4030_write_script_ins(u8 address
, u16 pmb_message
,
146 err
= twl4030_write_script_byte(address
++, pmb_message
>> 8);
149 err
= twl4030_write_script_byte(address
++, pmb_message
& 0xff);
152 err
= twl4030_write_script_byte(address
++, delay
);
155 err
= twl4030_write_script_byte(address
++, next
);
160 static int __init
twl4030_write_script(u8 address
, struct twl4030_ins
*script
,
165 for (; len
; len
--, address
++, script
++) {
167 err
= twl4030_write_script_ins(address
,
174 err
= twl4030_write_script_ins(address
,
185 static int __init
twl4030_config_wakeup3_sequence(u8 address
)
190 /* Set SLEEP to ACTIVE SEQ address for P3 */
191 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, address
,
196 /* P3 LVL_WAKEUP should be on LEVEL */
197 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &data
,
202 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, data
,
206 pr_err("TWL4030 wakeup sequence for P3 config error\n");
210 static int __init
twl4030_config_wakeup12_sequence(u8 address
)
215 /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
216 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, address
,
221 /* P1/P2 LVL_WAKEUP should be on LEVEL */
222 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &data
,
228 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, data
,
233 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &data
,
239 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, data
,
244 if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
245 /* Disabling AC charger effect on sleep-active transitions */
246 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &data
,
247 R_CFG_P1_TRANSITION
);
251 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, data
,
252 R_CFG_P1_TRANSITION
);
259 pr_err("TWL4030 wakeup sequence for P1 and P2" \
264 static int __init
twl4030_config_sleep_sequence(u8 address
)
268 /* Set ACTIVE to SLEEP SEQ address in T2 memory*/
269 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, address
,
273 pr_err("TWL4030 sleep sequence config error\n");
278 static int __init
twl4030_config_warmreset_sequence(u8 address
)
283 /* Set WARM RESET SEQ address for P1 */
284 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, address
,
289 /* P1/P2/P3 enable WARMRESET */
290 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &rd_data
,
295 rd_data
|= ENABLE_WARMRESET
;
296 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, rd_data
,
301 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &rd_data
,
306 rd_data
|= ENABLE_WARMRESET
;
307 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, rd_data
,
312 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER
, &rd_data
,
317 rd_data
|= ENABLE_WARMRESET
;
318 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, rd_data
,
322 pr_err("TWL4030 warmreset seq config error\n");
326 static int __init
twl4030_configure_resource(struct twl4030_resconfig
*rconfig
)
334 if (rconfig
->resource
> TOTAL_RESOURCES
) {
335 pr_err("TWL4030 Resource %d does not exist\n",
340 rconfig_addr
= res_config_addrs
[rconfig
->resource
];
342 /* Set resource group */
343 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER
, &grp
,
344 rconfig_addr
+ DEV_GRP_OFFSET
);
346 pr_err("TWL4030 Resource %d group could not be read\n",
351 if (rconfig
->devgroup
!= TWL4030_RESCONFIG_UNDEF
) {
352 grp
&= ~DEV_GRP_MASK
;
353 grp
|= rconfig
->devgroup
<< DEV_GRP_SHIFT
;
354 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER
,
355 grp
, rconfig_addr
+ DEV_GRP_OFFSET
);
357 pr_err("TWL4030 failed to program devgroup\n");
362 /* Set resource types */
363 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER
, &type
,
364 rconfig_addr
+ TYPE_OFFSET
);
366 pr_err("TWL4030 Resource %d type could not be read\n",
371 if (rconfig
->type
!= TWL4030_RESCONFIG_UNDEF
) {
373 type
|= rconfig
->type
<< TYPE_SHIFT
;
376 if (rconfig
->type2
!= TWL4030_RESCONFIG_UNDEF
) {
378 type
|= rconfig
->type2
<< TYPE2_SHIFT
;
381 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER
,
382 type
, rconfig_addr
+ TYPE_OFFSET
);
384 pr_err("TWL4030 failed to program resource type\n");
388 /* Set remap states */
389 err
= twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER
, &remap
,
390 rconfig_addr
+ REMAP_OFFSET
);
392 pr_err("TWL4030 Resource %d remap could not be read\n",
397 if (rconfig
->remap_off
!= TWL4030_RESCONFIG_UNDEF
) {
398 remap
&= ~OFF_STATE_MASK
;
399 remap
|= rconfig
->remap_off
<< OFF_STATE_SHIFT
;
402 if (rconfig
->remap_sleep
!= TWL4030_RESCONFIG_UNDEF
) {
403 remap
&= ~SLEEP_STATE_MASK
;
404 remap
|= rconfig
->remap_sleep
<< SLEEP_STATE_SHIFT
;
407 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER
,
409 rconfig_addr
+ REMAP_OFFSET
);
411 pr_err("TWL4030 failed to program remap\n");
418 static int __init
load_twl4030_script(struct twl4030_script
*tscript
,
424 /* Make sure the script isn't going beyond last valid address (0x3f) */
425 if ((address
+ tscript
->size
) > END_OF_SCRIPT
) {
426 pr_err("TWL4030 scripts too big error\n");
430 err
= twl4030_write_script(address
, tscript
->script
, tscript
->size
);
434 if (tscript
->flags
& TWL4030_WRST_SCRIPT
) {
435 err
= twl4030_config_warmreset_sequence(address
);
439 if (tscript
->flags
& TWL4030_WAKEUP12_SCRIPT
) {
440 err
= twl4030_config_wakeup12_sequence(address
);
445 if (tscript
->flags
& TWL4030_WAKEUP3_SCRIPT
) {
446 err
= twl4030_config_wakeup3_sequence(address
);
450 if (tscript
->flags
& TWL4030_SLEEP_SCRIPT
) {
452 pr_warning("TWL4030: Bad order of scripts (sleep "\
453 "script before wakeup) Leads to boot"\
454 "failure on some boards\n");
455 err
= twl4030_config_sleep_sequence(address
);
461 int twl4030_remove_script(u8 flags
)
465 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
,
466 TWL4030_PM_MASTER_KEY_CFG1
,
467 TWL4030_PM_MASTER_PROTECT_KEY
);
469 pr_err("twl4030: unable to unlock PROTECT_KEY\n");
473 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
,
474 TWL4030_PM_MASTER_KEY_CFG2
,
475 TWL4030_PM_MASTER_PROTECT_KEY
);
477 pr_err("twl4030: unable to unlock PROTECT_KEY\n");
481 if (flags
& TWL4030_WRST_SCRIPT
) {
482 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, END_OF_SCRIPT
,
487 if (flags
& TWL4030_WAKEUP12_SCRIPT
) {
488 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, END_OF_SCRIPT
,
493 if (flags
& TWL4030_WAKEUP3_SCRIPT
) {
494 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, END_OF_SCRIPT
,
499 if (flags
& TWL4030_SLEEP_SCRIPT
) {
500 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, END_OF_SCRIPT
,
506 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, 0,
507 TWL4030_PM_MASTER_PROTECT_KEY
);
509 pr_err("TWL4030 Unable to relock registers\n");
514 void __init
twl4030_power_init(struct twl4030_power_data
*twl4030_scripts
)
518 struct twl4030_resconfig
*resconfig
;
519 u8 address
= twl4030_start_script_address
;
521 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
,
522 TWL4030_PM_MASTER_KEY_CFG1
,
523 TWL4030_PM_MASTER_PROTECT_KEY
);
527 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
,
528 TWL4030_PM_MASTER_KEY_CFG2
,
529 TWL4030_PM_MASTER_PROTECT_KEY
);
533 for (i
= 0; i
< twl4030_scripts
->num
; i
++) {
534 err
= load_twl4030_script(twl4030_scripts
->scripts
[i
], address
);
537 address
+= twl4030_scripts
->scripts
[i
]->size
;
540 resconfig
= twl4030_scripts
->resource_config
;
542 while (resconfig
->resource
) {
543 err
= twl4030_configure_resource(resconfig
);
551 err
= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER
, 0,
552 TWL4030_PM_MASTER_PROTECT_KEY
);
554 pr_err("TWL4030 Unable to relock registers\n");
559 pr_err("TWL4030 Unable to unlock registers\n");
563 pr_err("TWL4030 failed to load scripts\n");
567 pr_err("TWL4030 failed to configure resource\n");