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 #define SEQ_OFFSYNC (1 << 0) 39 40 #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) 41 #define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b) 42 43 /* resource - hfclk */ 44 #define R_HFCLKOUT_DEV_GRP PHY_TO_OFF_PM_RECEIVER(0xe6) 45 46 /* PM events */ 47 #define R_P1_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x46) 48 #define R_P2_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x47) 49 #define R_P3_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x48) 50 #define R_CFG_P1_TRANSITION PHY_TO_OFF_PM_MASTER(0x36) 51 #define R_CFG_P2_TRANSITION PHY_TO_OFF_PM_MASTER(0x37) 52 #define R_CFG_P3_TRANSITION PHY_TO_OFF_PM_MASTER(0x38) 53 54 #define LVL_WAKEUP 0x08 55 56 #define ENABLE_WARMRESET (1<<4) 57 58 #define END_OF_SCRIPT 0x3f 59 60 #define R_SEQ_ADD_A2S PHY_TO_OFF_PM_MASTER(0x55) 61 #define R_SEQ_ADD_S2A12 PHY_TO_OFF_PM_MASTER(0x56) 62 #define R_SEQ_ADD_S2A3 PHY_TO_OFF_PM_MASTER(0x57) 63 #define R_SEQ_ADD_WARM PHY_TO_OFF_PM_MASTER(0x58) 64 #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) 65 #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) 66 67 /* resource configuration registers 68 <RESOURCE>_DEV_GRP at address 'n+0' 69 <RESOURCE>_TYPE at address 'n+1' 70 <RESOURCE>_REMAP at address 'n+2' 71 <RESOURCE>_DEDICATED at address 'n+3' 72 */ 73 #define DEV_GRP_OFFSET 0 74 #define TYPE_OFFSET 1 75 #define REMAP_OFFSET 2 76 #define DEDICATED_OFFSET 3 77 78 /* Bit positions in the registers */ 79 80 /* <RESOURCE>_DEV_GRP */ 81 #define DEV_GRP_SHIFT 5 82 #define DEV_GRP_MASK (7 << DEV_GRP_SHIFT) 83 84 /* <RESOURCE>_TYPE */ 85 #define TYPE_SHIFT 0 86 #define TYPE_MASK (7 << TYPE_SHIFT) 87 #define TYPE2_SHIFT 3 88 #define TYPE2_MASK (3 << TYPE2_SHIFT) 89 90 /* <RESOURCE>_REMAP */ 91 #define SLEEP_STATE_SHIFT 0 92 #define SLEEP_STATE_MASK (0xf << SLEEP_STATE_SHIFT) 93 #define OFF_STATE_SHIFT 4 94 #define OFF_STATE_MASK (0xf << OFF_STATE_SHIFT) 95 96 static u8 res_config_addrs[] = { 97 [RES_VAUX1] = 0x17, 98 [RES_VAUX2] = 0x1b, 99 [RES_VAUX3] = 0x1f, 100 [RES_VAUX4] = 0x23, 101 [RES_VMMC1] = 0x27, 102 [RES_VMMC2] = 0x2b, 103 [RES_VPLL1] = 0x2f, 104 [RES_VPLL2] = 0x33, 105 [RES_VSIM] = 0x37, 106 [RES_VDAC] = 0x3b, 107 [RES_VINTANA1] = 0x3f, 108 [RES_VINTANA2] = 0x43, 109 [RES_VINTDIG] = 0x47, 110 [RES_VIO] = 0x4b, 111 [RES_VDD1] = 0x55, 112 [RES_VDD2] = 0x63, 113 [RES_VUSB_1V5] = 0x71, 114 [RES_VUSB_1V8] = 0x74, 115 [RES_VUSB_3V1] = 0x77, 116 [RES_VUSBCP] = 0x7a, 117 [RES_REGEN] = 0x7f, 118 [RES_NRES_PWRON] = 0x82, 119 [RES_CLKEN] = 0x85, 120 [RES_SYSEN] = 0x88, 121 [RES_HFCLKOUT] = 0x8b, 122 [RES_32KCLKOUT] = 0x8e, 123 [RES_RESET] = 0x91, 124 [RES_MAIN_REF] = 0x94, 125 }; 126 127 static int __devinit twl4030_write_script_byte(u8 address, u8 byte) 128 { 129 int err; 130 131 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 132 R_MEMORY_ADDRESS); 133 if (err) 134 goto out; 135 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte, 136 R_MEMORY_DATA); 137 out: 138 return err; 139 } 140 141 static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message, 142 u8 delay, u8 next) 143 { 144 int err; 145 146 address *= 4; 147 err = twl4030_write_script_byte(address++, pmb_message >> 8); 148 if (err) 149 goto out; 150 err = twl4030_write_script_byte(address++, pmb_message & 0xff); 151 if (err) 152 goto out; 153 err = twl4030_write_script_byte(address++, delay); 154 if (err) 155 goto out; 156 err = twl4030_write_script_byte(address++, next); 157 out: 158 return err; 159 } 160 161 static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script, 162 int len) 163 { 164 int err; 165 166 for (; len; len--, address++, script++) { 167 if (len == 1) { 168 err = twl4030_write_script_ins(address, 169 script->pmb_message, 170 script->delay, 171 END_OF_SCRIPT); 172 if (err) 173 break; 174 } else { 175 err = twl4030_write_script_ins(address, 176 script->pmb_message, 177 script->delay, 178 address + 1); 179 if (err) 180 break; 181 } 182 } 183 return err; 184 } 185 186 static int __devinit twl4030_config_wakeup3_sequence(u8 address) 187 { 188 int err; 189 u8 data; 190 191 /* Set SLEEP to ACTIVE SEQ address for P3 */ 192 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 193 R_SEQ_ADD_S2A3); 194 if (err) 195 goto out; 196 197 /* P3 LVL_WAKEUP should be on LEVEL */ 198 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 199 R_P3_SW_EVENTS); 200 if (err) 201 goto out; 202 data |= LVL_WAKEUP; 203 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, 204 R_P3_SW_EVENTS); 205 out: 206 if (err) 207 pr_err("TWL4030 wakeup sequence for P3 config error\n"); 208 return err; 209 } 210 211 static int __devinit twl4030_config_wakeup12_sequence(u8 address) 212 { 213 int err = 0; 214 u8 data; 215 216 /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ 217 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 218 R_SEQ_ADD_S2A12); 219 if (err) 220 goto out; 221 222 /* P1/P2 LVL_WAKEUP should be on LEVEL */ 223 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 224 R_P1_SW_EVENTS); 225 if (err) 226 goto out; 227 228 data |= LVL_WAKEUP; 229 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, 230 R_P1_SW_EVENTS); 231 if (err) 232 goto out; 233 234 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 235 R_P2_SW_EVENTS); 236 if (err) 237 goto out; 238 239 data |= LVL_WAKEUP; 240 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data, 241 R_P2_SW_EVENTS); 242 if (err) 243 goto out; 244 245 if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) { 246 /* Disabling AC charger effect on sleep-active transitions */ 247 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data, 248 R_CFG_P1_TRANSITION); 249 if (err) 250 goto out; 251 data &= ~(1<<1); 252 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data , 253 R_CFG_P1_TRANSITION); 254 if (err) 255 goto out; 256 } 257 258 out: 259 if (err) 260 pr_err("TWL4030 wakeup sequence for P1 and P2" \ 261 "config error\n"); 262 return err; 263 } 264 265 static int __devinit twl4030_config_sleep_sequence(u8 address) 266 { 267 int err; 268 269 /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ 270 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 271 R_SEQ_ADD_A2S); 272 273 if (err) 274 pr_err("TWL4030 sleep sequence config error\n"); 275 276 return err; 277 } 278 279 static int __devinit twl4030_config_warmreset_sequence(u8 address) 280 { 281 int err; 282 u8 rd_data; 283 284 /* Set WARM RESET SEQ address for P1 */ 285 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address, 286 R_SEQ_ADD_WARM); 287 if (err) 288 goto out; 289 290 /* P1/P2/P3 enable WARMRESET */ 291 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, 292 R_P1_SW_EVENTS); 293 if (err) 294 goto out; 295 296 rd_data |= ENABLE_WARMRESET; 297 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, 298 R_P1_SW_EVENTS); 299 if (err) 300 goto out; 301 302 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, 303 R_P2_SW_EVENTS); 304 if (err) 305 goto out; 306 307 rd_data |= ENABLE_WARMRESET; 308 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, 309 R_P2_SW_EVENTS); 310 if (err) 311 goto out; 312 313 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data, 314 R_P3_SW_EVENTS); 315 if (err) 316 goto out; 317 318 rd_data |= ENABLE_WARMRESET; 319 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data, 320 R_P3_SW_EVENTS); 321 out: 322 if (err) 323 pr_err("TWL4030 warmreset seq config error\n"); 324 return err; 325 } 326 327 static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig) 328 { 329 int rconfig_addr; 330 int err; 331 u8 type; 332 u8 grp; 333 u8 remap; 334 335 if (rconfig->resource > TOTAL_RESOURCES) { 336 pr_err("TWL4030 Resource %d does not exist\n", 337 rconfig->resource); 338 return -EINVAL; 339 } 340 341 rconfig_addr = res_config_addrs[rconfig->resource]; 342 343 /* Set resource group */ 344 err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, 345 rconfig_addr + DEV_GRP_OFFSET); 346 if (err) { 347 pr_err("TWL4030 Resource %d group could not be read\n", 348 rconfig->resource); 349 return err; 350 } 351 352 if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { 353 grp &= ~DEV_GRP_MASK; 354 grp |= rconfig->devgroup << DEV_GRP_SHIFT; 355 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 356 grp, rconfig_addr + DEV_GRP_OFFSET); 357 if (err < 0) { 358 pr_err("TWL4030 failed to program devgroup\n"); 359 return err; 360 } 361 } 362 363 /* Set resource types */ 364 err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, 365 rconfig_addr + TYPE_OFFSET); 366 if (err < 0) { 367 pr_err("TWL4030 Resource %d type could not be read\n", 368 rconfig->resource); 369 return err; 370 } 371 372 if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { 373 type &= ~TYPE_MASK; 374 type |= rconfig->type << TYPE_SHIFT; 375 } 376 377 if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { 378 type &= ~TYPE2_MASK; 379 type |= rconfig->type2 << TYPE2_SHIFT; 380 } 381 382 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 383 type, rconfig_addr + TYPE_OFFSET); 384 if (err < 0) { 385 pr_err("TWL4030 failed to program resource type\n"); 386 return err; 387 } 388 389 /* Set remap states */ 390 err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, 391 rconfig_addr + REMAP_OFFSET); 392 if (err < 0) { 393 pr_err("TWL4030 Resource %d remap could not be read\n", 394 rconfig->resource); 395 return err; 396 } 397 398 if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { 399 remap &= ~OFF_STATE_MASK; 400 remap |= rconfig->remap_off << OFF_STATE_SHIFT; 401 } 402 403 if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { 404 remap &= ~SLEEP_STATE_MASK; 405 remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; 406 } 407 408 err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 409 remap, 410 rconfig_addr + REMAP_OFFSET); 411 if (err < 0) { 412 pr_err("TWL4030 failed to program remap\n"); 413 return err; 414 } 415 416 return 0; 417 } 418 419 static int __devinit load_twl4030_script(struct twl4030_script *tscript, 420 u8 address) 421 { 422 int err; 423 static int order; 424 425 /* Make sure the script isn't going beyond last valid address (0x3f) */ 426 if ((address + tscript->size) > END_OF_SCRIPT) { 427 pr_err("TWL4030 scripts too big error\n"); 428 return -EINVAL; 429 } 430 431 err = twl4030_write_script(address, tscript->script, tscript->size); 432 if (err) 433 goto out; 434 435 if (tscript->flags & TWL4030_WRST_SCRIPT) { 436 err = twl4030_config_warmreset_sequence(address); 437 if (err) 438 goto out; 439 } 440 if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) { 441 err = twl4030_config_wakeup12_sequence(address); 442 if (err) 443 goto out; 444 order = 1; 445 } 446 if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) { 447 err = twl4030_config_wakeup3_sequence(address); 448 if (err) 449 goto out; 450 } 451 if (tscript->flags & TWL4030_SLEEP_SCRIPT) { 452 if (!order) 453 pr_warning("TWL4030: Bad order of scripts (sleep "\ 454 "script before wakeup) Leads to boot"\ 455 "failure on some boards\n"); 456 err = twl4030_config_sleep_sequence(address); 457 } 458 out: 459 return err; 460 } 461 462 int twl4030_remove_script(u8 flags) 463 { 464 int err = 0; 465 466 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 467 TWL4030_PM_MASTER_KEY_CFG1, 468 TWL4030_PM_MASTER_PROTECT_KEY); 469 if (err) { 470 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 471 return err; 472 } 473 474 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 475 TWL4030_PM_MASTER_KEY_CFG2, 476 TWL4030_PM_MASTER_PROTECT_KEY); 477 if (err) { 478 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 479 return err; 480 } 481 482 if (flags & TWL4030_WRST_SCRIPT) { 483 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 484 R_SEQ_ADD_WARM); 485 if (err) 486 return err; 487 } 488 if (flags & TWL4030_WAKEUP12_SCRIPT) { 489 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 490 R_SEQ_ADD_S2A12); 491 if (err) 492 return err; 493 } 494 if (flags & TWL4030_WAKEUP3_SCRIPT) { 495 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 496 R_SEQ_ADD_S2A3); 497 if (err) 498 return err; 499 } 500 if (flags & TWL4030_SLEEP_SCRIPT) { 501 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT, 502 R_SEQ_ADD_A2S); 503 if (err) 504 return err; 505 } 506 507 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, 508 TWL4030_PM_MASTER_PROTECT_KEY); 509 if (err) 510 pr_err("TWL4030 Unable to relock registers\n"); 511 512 return err; 513 } 514 515 /* 516 * In master mode, start the power off sequence. 517 * After a successful execution, TWL shuts down the power to the SoC 518 * and all peripherals connected to it. 519 */ 520 void twl4030_power_off(void) 521 { 522 int err; 523 524 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF, 525 TWL4030_PM_MASTER_P1_SW_EVENTS); 526 if (err) 527 pr_err("TWL4030 Unable to power off\n"); 528 } 529 530 void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts) 531 { 532 int err = 0; 533 int i; 534 struct twl4030_resconfig *resconfig; 535 u8 val, address = twl4030_start_script_address; 536 537 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 538 TWL4030_PM_MASTER_KEY_CFG1, 539 TWL4030_PM_MASTER_PROTECT_KEY); 540 if (err) 541 goto unlock; 542 543 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 544 TWL4030_PM_MASTER_KEY_CFG2, 545 TWL4030_PM_MASTER_PROTECT_KEY); 546 if (err) 547 goto unlock; 548 549 for (i = 0; i < twl4030_scripts->num; i++) { 550 err = load_twl4030_script(twl4030_scripts->scripts[i], address); 551 if (err) 552 goto load; 553 address += twl4030_scripts->scripts[i]->size; 554 } 555 556 resconfig = twl4030_scripts->resource_config; 557 if (resconfig) { 558 while (resconfig->resource) { 559 err = twl4030_configure_resource(resconfig); 560 if (err) 561 goto resource; 562 resconfig++; 563 564 } 565 } 566 567 /* Board has to be wired properly to use this feature */ 568 if (twl4030_scripts->use_poweroff && !pm_power_off) { 569 /* Default for SEQ_OFFSYNC is set, lets ensure this */ 570 err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val, 571 TWL4030_PM_MASTER_CFG_P123_TRANSITION); 572 if (err) { 573 pr_warning("TWL4030 Unable to read registers\n"); 574 575 } else if (!(val & SEQ_OFFSYNC)) { 576 val |= SEQ_OFFSYNC; 577 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val, 578 TWL4030_PM_MASTER_CFG_P123_TRANSITION); 579 if (err) { 580 pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n"); 581 goto relock; 582 } 583 } 584 585 pm_power_off = twl4030_power_off; 586 } 587 588 relock: 589 err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, 590 TWL4030_PM_MASTER_PROTECT_KEY); 591 if (err) 592 pr_err("TWL4030 Unable to relock registers\n"); 593 return; 594 595 unlock: 596 if (err) 597 pr_err("TWL4030 Unable to unlock registers\n"); 598 return; 599 load: 600 if (err) 601 pr_err("TWL4030 failed to load scripts\n"); 602 return; 603 resource: 604 if (err) 605 pr_err("TWL4030 failed to configure resource\n"); 606 return; 607 } 608