1 /* 2 * linux/drivers/i2c/chips/twl4030-power.c 3 * 4 * Handle TWL4030 Power initialization 5 * 6 * Copyright (C) 2008 Nokia Corporation 7 * Copyright (C) 2006 Texas Instruments, Inc 8 * 9 * Written by Kalle Jokiniemi 10 * Peter De Schrijver <peter.de-schrijver@nokia.com> 11 * Several fixes by Amit Kucheria <amit.kucheria@verdurent.com> 12 * 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. 16 * 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. 21 * 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 25 */ 26 27 #include <linux/module.h> 28 #include <linux/pm.h> 29 #include <linux/i2c/twl.h> 30 #include <linux/platform_device.h> 31 32 #include <asm/mach-types.h> 33 34 static u8 twl4030_start_script_address = 0x2b; 35 36 #define PWR_P1_SW_EVENTS 0x10 37 #define PWR_DEVOFF (1<<0) 38 39 #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) 40 #define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b) 41 42 /* resource - hfclk */ 43 #define R_HFCLKOUT_DEV_GRP PHY_TO_OFF_PM_RECEIVER(0xe6) 44 45 /* PM events */ 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) 52 53 #define LVL_WAKEUP 0x08 54 55 #define ENABLE_WARMRESET (1<<4) 56 57 #define END_OF_SCRIPT 0x3f 58 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) 65 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' 71 */ 72 #define DEV_GRP_OFFSET 0 73 #define TYPE_OFFSET 1 74 #define REMAP_OFFSET 2 75 #define DEDICATED_OFFSET 3 76 77 /* Bit positions in the registers */ 78 79 /* <RESOURCE>_DEV_GRP */ 80 #define DEV_GRP_SHIFT 5 81 #define DEV_GRP_MASK (7 << DEV_GRP_SHIFT) 82 83 /* <RESOURCE>_TYPE */ 84 #define TYPE_SHIFT 0 85 #define TYPE_MASK (7 << TYPE_SHIFT) 86 #define TYPE2_SHIFT 3 87 #define TYPE2_MASK (3 << TYPE2_SHIFT) 88 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) 94 95 static u8 res_config_addrs[] = { 96 [RES_VAUX1] = 0x17, 97 [RES_VAUX2] = 0x1b, 98 [RES_VAUX3] = 0x1f, 99 [RES_VAUX4] = 0x23, 100 [RES_VMMC1] = 0x27, 101 [RES_VMMC2] = 0x2b, 102 [RES_VPLL1] = 0x2f, 103 [RES_VPLL2] = 0x33, 104 [RES_VSIM] = 0x37, 105 [RES_VDAC] = 0x3b, 106 [RES_VINTANA1] = 0x3f, 107 [RES_VINTANA2] = 0x43, 108 [RES_VINTDIG] = 0x47, 109 [RES_VIO] = 0x4b, 110 [RES_VDD1] = 0x55, 111 [RES_VDD2] = 0x63, 112 [RES_VUSB_1V5] = 0x71, 113 [RES_VUSB_1V8] = 0x74, 114 [RES_VUSB_3V1] = 0x77, 115 [RES_VUSBCP] = 0x7a, 116 [RES_REGEN] = 0x7f, 117 [RES_NRES_PWRON] = 0x82, 118 [RES_CLKEN] = 0x85, 119 [RES_SYSEN] = 0x88, 120 [RES_HFCLKOUT] = 0x8b, 121 [RES_32KCLKOUT] = 0x8e, 122 [RES_RESET] = 0x91, 123 [RES_Main_Ref] = 0x94, 124 }; 125 126 static int __init twl4030_write_script_byte(u8 address, u8 byte) 127 { 128 int err; 129 130 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 131 R_MEMORY_ADDRESS); 132 if (err) 133 goto out; 134 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte, 135 R_MEMORY_DATA); 136 out: 137 return err; 138 } 139 140 static int __init twl4030_write_script_ins(u8 address, u16 pmb_message, 141 u8 delay, u8 next) 142 { 143 int err; 144 145 address *= 4; 146 err = twl4030_write_script_byte(address++, pmb_message >> 8); 147 if (err) 148 goto out; 149 err = twl4030_write_script_byte(address++, pmb_message & 0xff); 150 if (err) 151 goto out; 152 err = twl4030_write_script_byte(address++, delay); 153 if (err) 154 goto out; 155 err = twl4030_write_script_byte(address++, next); 156 out: 157 return err; 158 } 159 160 static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, 161 int len) 162 { 163 int err; 164 165 for (; len; len--, address++, script++) { 166 if (len == 1) { 167 err = twl4030_write_script_ins(address, 168 script->pmb_message, 169 script->delay, 170 END_OF_SCRIPT); 171 if (err) 172 break; 173 } else { 174 err = twl4030_write_script_ins(address, 175 script->pmb_message, 176 script->delay, 177 address + 1); 178 if (err) 179 break; 180 } 181 } 182 return err; 183 } 184 185 static int __init twl4030_config_wakeup3_sequence(u8 address) 186 { 187 int err; 188 u8 data; 189 190 /* Set SLEEP to ACTIVE SEQ address for P3 */ 191 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 192 R_SEQ_ADD_S2A3); 193 if (err) 194 goto out; 195 196 /* P3 LVL_WAKEUP should be on LEVEL */ 197 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 198 R_P3_SW_EVENTS); 199 if (err) 200 goto out; 201 data |= LVL_WAKEUP; 202 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, 203 R_P3_SW_EVENTS); 204 out: 205 if (err) 206 pr_err("TWL4030 wakeup sequence for P3 config error\n"); 207 return err; 208 } 209 210 static int __init twl4030_config_wakeup12_sequence(u8 address) 211 { 212 int err = 0; 213 u8 data; 214 215 /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ 216 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 217 R_SEQ_ADD_S2A12); 218 if (err) 219 goto out; 220 221 /* P1/P2 LVL_WAKEUP should be on LEVEL */ 222 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 223 R_P1_SW_EVENTS); 224 if (err) 225 goto out; 226 227 data |= LVL_WAKEUP; 228 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, 229 R_P1_SW_EVENTS); 230 if (err) 231 goto out; 232 233 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 234 R_P2_SW_EVENTS); 235 if (err) 236 goto out; 237 238 data |= LVL_WAKEUP; 239 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, 240 R_P2_SW_EVENTS); 241 if (err) 242 goto out; 243 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); 248 if (err) 249 goto out; 250 data &= ~(1<<1); 251 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data , 252 R_CFG_P1_TRANSITION); 253 if (err) 254 goto out; 255 } 256 257 out: 258 if (err) 259 pr_err("TWL4030 wakeup sequence for P1 and P2" \ 260 "config error\n"); 261 return err; 262 } 263 264 static int __init twl4030_config_sleep_sequence(u8 address) 265 { 266 int err; 267 268 /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ 269 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 270 R_SEQ_ADD_A2S); 271 272 if (err) 273 pr_err("TWL4030 sleep sequence config error\n"); 274 275 return err; 276 } 277 278 static int __init twl4030_config_warmreset_sequence(u8 address) 279 { 280 int err; 281 u8 rd_data; 282 283 /* Set WARM RESET SEQ address for P1 */ 284 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 285 R_SEQ_ADD_WARM); 286 if (err) 287 goto out; 288 289 /* P1/P2/P3 enable WARMRESET */ 290 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, 291 R_P1_SW_EVENTS); 292 if (err) 293 goto out; 294 295 rd_data |= ENABLE_WARMRESET; 296 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, 297 R_P1_SW_EVENTS); 298 if (err) 299 goto out; 300 301 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, 302 R_P2_SW_EVENTS); 303 if (err) 304 goto out; 305 306 rd_data |= ENABLE_WARMRESET; 307 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, 308 R_P2_SW_EVENTS); 309 if (err) 310 goto out; 311 312 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, 313 R_P3_SW_EVENTS); 314 if (err) 315 goto out; 316 317 rd_data |= ENABLE_WARMRESET; 318 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, 319 R_P3_SW_EVENTS); 320 out: 321 if (err) 322 pr_err("TWL4030 warmreset seq config error\n"); 323 return err; 324 } 325 326 static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) 327 { 328 int rconfig_addr; 329 int err; 330 u8 type; 331 u8 grp; 332 u8 remap; 333 334 if (rconfig->resource > TOTAL_RESOURCES) { 335 pr_err("TWL4030 Resource %d does not exist\n", 336 rconfig->resource); 337 return -EINVAL; 338 } 339 340 rconfig_addr = res_config_addrs[rconfig->resource]; 341 342 /* Set resource group */ 343 err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, 344 rconfig_addr + DEV_GRP_OFFSET); 345 if (err) { 346 pr_err("TWL4030 Resource %d group could not be read\n", 347 rconfig->resource); 348 return err; 349 } 350 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); 356 if (err < 0) { 357 pr_err("TWL4030 failed to program devgroup\n"); 358 return err; 359 } 360 } 361 362 /* Set resource types */ 363 err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, 364 rconfig_addr + TYPE_OFFSET); 365 if (err < 0) { 366 pr_err("TWL4030 Resource %d type could not be read\n", 367 rconfig->resource); 368 return err; 369 } 370 371 if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { 372 type &= ~TYPE_MASK; 373 type |= rconfig->type << TYPE_SHIFT; 374 } 375 376 if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { 377 type &= ~TYPE2_MASK; 378 type |= rconfig->type2 << TYPE2_SHIFT; 379 } 380 381 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 382 type, rconfig_addr + TYPE_OFFSET); 383 if (err < 0) { 384 pr_err("TWL4030 failed to program resource type\n"); 385 return err; 386 } 387 388 /* Set remap states */ 389 err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, 390 rconfig_addr + REMAP_OFFSET); 391 if (err < 0) { 392 pr_err("TWL4030 Resource %d remap could not be read\n", 393 rconfig->resource); 394 return err; 395 } 396 397 if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { 398 remap &= ~OFF_STATE_MASK; 399 remap |= rconfig->remap_off << OFF_STATE_SHIFT; 400 } 401 402 if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { 403 remap &= ~SLEEP_STATE_MASK; 404 remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; 405 } 406 407 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 408 remap, 409 rconfig_addr + REMAP_OFFSET); 410 if (err < 0) { 411 pr_err("TWL4030 failed to program remap\n"); 412 return err; 413 } 414 415 return 0; 416 } 417 418 static int __init load_twl4030_script(struct twl4030_script *tscript, 419 u8 address) 420 { 421 int err; 422 static int order; 423 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"); 427 return -EINVAL; 428 } 429 430 err = twl4030_write_script(address, tscript->script, tscript->size); 431 if (err) 432 goto out; 433 434 if (tscript->flags & TWL4030_WRST_SCRIPT) { 435 err = twl4030_config_warmreset_sequence(address); 436 if (err) 437 goto out; 438 } 439 if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) { 440 err = twl4030_config_wakeup12_sequence(address); 441 if (err) 442 goto out; 443 order = 1; 444 } 445 if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) { 446 err = twl4030_config_wakeup3_sequence(address); 447 if (err) 448 goto out; 449 } 450 if (tscript->flags & TWL4030_SLEEP_SCRIPT) 451 if (order) 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); 456 out: 457 return err; 458 } 459 460 int twl4030_remove_script(u8 flags) 461 { 462 int err = 0; 463 464 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 465 TWL4030_PM_MASTER_KEY_CFG1, 466 TWL4030_PM_MASTER_PROTECT_KEY); 467 if (err) { 468 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 469 return err; 470 } 471 472 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 473 TWL4030_PM_MASTER_KEY_CFG2, 474 TWL4030_PM_MASTER_PROTECT_KEY); 475 if (err) { 476 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 477 return err; 478 } 479 480 if (flags & TWL4030_WRST_SCRIPT) { 481 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 482 R_SEQ_ADD_WARM); 483 if (err) 484 return err; 485 } 486 if (flags & TWL4030_WAKEUP12_SCRIPT) { 487 if (err) 488 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 489 R_SEQ_ADD_S2A12); 490 return err; 491 } 492 if (flags & TWL4030_WAKEUP3_SCRIPT) { 493 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 494 R_SEQ_ADD_S2A3); 495 if (err) 496 return err; 497 } 498 if (flags & TWL4030_SLEEP_SCRIPT) { 499 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 500 R_SEQ_ADD_A2S); 501 if (err) 502 return err; 503 } 504 505 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, 506 TWL4030_PM_MASTER_PROTECT_KEY); 507 if (err) 508 pr_err("TWL4030 Unable to relock registers\n"); 509 510 return err; 511 } 512 513 void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) 514 { 515 int err = 0; 516 int i; 517 struct twl4030_resconfig *resconfig; 518 u8 address = twl4030_start_script_address; 519 520 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 521 TWL4030_PM_MASTER_KEY_CFG1, 522 TWL4030_PM_MASTER_PROTECT_KEY); 523 if (err) 524 goto unlock; 525 526 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 527 TWL4030_PM_MASTER_KEY_CFG2, 528 TWL4030_PM_MASTER_PROTECT_KEY); 529 if (err) 530 goto unlock; 531 532 for (i = 0; i < twl4030_scripts->num; i++) { 533 err = load_twl4030_script(twl4030_scripts->scripts[i], address); 534 if (err) 535 goto load; 536 address += twl4030_scripts->scripts[i]->size; 537 } 538 539 resconfig = twl4030_scripts->resource_config; 540 if (resconfig) { 541 while (resconfig->resource) { 542 err = twl4030_configure_resource(resconfig); 543 if (err) 544 goto resource; 545 resconfig++; 546 547 } 548 } 549 550 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, 551 TWL4030_PM_MASTER_PROTECT_KEY); 552 if (err) 553 pr_err("TWL4030 Unable to relock registers\n"); 554 return; 555 556 unlock: 557 if (err) 558 pr_err("TWL4030 Unable to unlock registers\n"); 559 return; 560 load: 561 if (err) 562 pr_err("TWL4030 failed to load scripts\n"); 563 return; 564 resource: 565 if (err) 566 pr_err("TWL4030 failed to configure resource\n"); 567 return; 568 } 569