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 #include <linux/of.h> 32 #include <linux/of_device.h> 33 34 #include <asm/mach-types.h> 35 36 static u8 twl4030_start_script_address = 0x2b; 37 38 /* Register bits for P1, P2 and P3_SW_EVENTS */ 39 #define PWR_STOPON_PRWON BIT(6) 40 #define PWR_STOPON_SYSEN BIT(5) 41 #define PWR_ENABLE_WARMRESET BIT(4) 42 #define PWR_LVL_WAKEUP BIT(3) 43 #define PWR_DEVACT BIT(2) 44 #define PWR_DEVSLP BIT(1) 45 #define PWR_DEVOFF BIT(0) 46 47 #define SEQ_OFFSYNC (1 << 0) 48 49 #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) 50 #define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b) 51 52 /* resource - hfclk */ 53 #define R_HFCLKOUT_DEV_GRP PHY_TO_OFF_PM_RECEIVER(0xe6) 54 55 /* PM events */ 56 #define R_P1_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x46) 57 #define R_P2_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x47) 58 #define R_P3_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x48) 59 #define R_CFG_P1_TRANSITION PHY_TO_OFF_PM_MASTER(0x36) 60 #define R_CFG_P2_TRANSITION PHY_TO_OFF_PM_MASTER(0x37) 61 #define R_CFG_P3_TRANSITION PHY_TO_OFF_PM_MASTER(0x38) 62 63 #define END_OF_SCRIPT 0x3f 64 65 #define R_SEQ_ADD_A2S PHY_TO_OFF_PM_MASTER(0x55) 66 #define R_SEQ_ADD_S2A12 PHY_TO_OFF_PM_MASTER(0x56) 67 #define R_SEQ_ADD_S2A3 PHY_TO_OFF_PM_MASTER(0x57) 68 #define R_SEQ_ADD_WARM PHY_TO_OFF_PM_MASTER(0x58) 69 #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) 70 #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) 71 72 /* resource configuration registers 73 <RESOURCE>_DEV_GRP at address 'n+0' 74 <RESOURCE>_TYPE at address 'n+1' 75 <RESOURCE>_REMAP at address 'n+2' 76 <RESOURCE>_DEDICATED at address 'n+3' 77 */ 78 #define DEV_GRP_OFFSET 0 79 #define TYPE_OFFSET 1 80 #define REMAP_OFFSET 2 81 #define DEDICATED_OFFSET 3 82 83 /* Bit positions in the registers */ 84 85 /* <RESOURCE>_DEV_GRP */ 86 #define DEV_GRP_SHIFT 5 87 #define DEV_GRP_MASK (7 << DEV_GRP_SHIFT) 88 89 /* <RESOURCE>_TYPE */ 90 #define TYPE_SHIFT 0 91 #define TYPE_MASK (7 << TYPE_SHIFT) 92 #define TYPE2_SHIFT 3 93 #define TYPE2_MASK (3 << TYPE2_SHIFT) 94 95 /* <RESOURCE>_REMAP */ 96 #define SLEEP_STATE_SHIFT 0 97 #define SLEEP_STATE_MASK (0xf << SLEEP_STATE_SHIFT) 98 #define OFF_STATE_SHIFT 4 99 #define OFF_STATE_MASK (0xf << OFF_STATE_SHIFT) 100 101 static u8 res_config_addrs[] = { 102 [RES_VAUX1] = 0x17, 103 [RES_VAUX2] = 0x1b, 104 [RES_VAUX3] = 0x1f, 105 [RES_VAUX4] = 0x23, 106 [RES_VMMC1] = 0x27, 107 [RES_VMMC2] = 0x2b, 108 [RES_VPLL1] = 0x2f, 109 [RES_VPLL2] = 0x33, 110 [RES_VSIM] = 0x37, 111 [RES_VDAC] = 0x3b, 112 [RES_VINTANA1] = 0x3f, 113 [RES_VINTANA2] = 0x43, 114 [RES_VINTDIG] = 0x47, 115 [RES_VIO] = 0x4b, 116 [RES_VDD1] = 0x55, 117 [RES_VDD2] = 0x63, 118 [RES_VUSB_1V5] = 0x71, 119 [RES_VUSB_1V8] = 0x74, 120 [RES_VUSB_3V1] = 0x77, 121 [RES_VUSBCP] = 0x7a, 122 [RES_REGEN] = 0x7f, 123 [RES_NRES_PWRON] = 0x82, 124 [RES_CLKEN] = 0x85, 125 [RES_SYSEN] = 0x88, 126 [RES_HFCLKOUT] = 0x8b, 127 [RES_32KCLKOUT] = 0x8e, 128 [RES_RESET] = 0x91, 129 [RES_MAIN_REF] = 0x94, 130 }; 131 132 /* 133 * Usable values for .remap_sleep and .remap_off 134 * Based on table "5.3.3 Resource Operating modes" 135 */ 136 enum { 137 TWL_REMAP_OFF = 0, 138 TWL_REMAP_SLEEP = 8, 139 TWL_REMAP_ACTIVE = 9, 140 }; 141 142 /* 143 * Macros to configure the PM register states for various resources. 144 * Note that we can make MSG_SINGULAR etc private to this driver once 145 * omap3 has been made DT only. 146 */ 147 #define TWL_DFLT_DELAY 2 /* typically 2 32 KiHz cycles */ 148 #define TWL_RESOURCE_SET(res, state) \ 149 { MSG_SINGULAR(DEV_GRP_NULL, (res), (state)), TWL_DFLT_DELAY } 150 #define TWL_RESOURCE_ON(res) TWL_RESOURCE_SET(res, RES_STATE_ACTIVE) 151 #define TWL_RESOURCE_OFF(res) TWL_RESOURCE_SET(res, RES_STATE_OFF) 152 #define TWL_RESOURCE_RESET(res) TWL_RESOURCE_SET(res, RES_STATE_WRST) 153 /* 154 * It seems that type1 and type2 is just the resource init order 155 * number for the type1 and type2 group. 156 */ 157 #define TWL_RESOURCE_GROUP_RESET(group, type1, type2) \ 158 { MSG_BROADCAST(DEV_GRP_NULL, (group), (type1), (type2), \ 159 RES_STATE_WRST), TWL_DFLT_DELAY } 160 #define TWL_REMAP_SLEEP(res, devgrp, typ, typ2) \ 161 { .resource = (res), .devgroup = (devgrp), \ 162 .type = (typ), .type2 = (typ2), \ 163 .remap_off = TWL_REMAP_OFF, \ 164 .remap_sleep = TWL_REMAP_SLEEP, } 165 166 static int twl4030_write_script_byte(u8 address, u8 byte) 167 { 168 int err; 169 170 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS); 171 if (err) 172 goto out; 173 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA); 174 out: 175 return err; 176 } 177 178 static int twl4030_write_script_ins(u8 address, u16 pmb_message, 179 u8 delay, u8 next) 180 { 181 int err; 182 183 address *= 4; 184 err = twl4030_write_script_byte(address++, pmb_message >> 8); 185 if (err) 186 goto out; 187 err = twl4030_write_script_byte(address++, pmb_message & 0xff); 188 if (err) 189 goto out; 190 err = twl4030_write_script_byte(address++, delay); 191 if (err) 192 goto out; 193 err = twl4030_write_script_byte(address++, next); 194 out: 195 return err; 196 } 197 198 static int twl4030_write_script(u8 address, struct twl4030_ins *script, 199 int len) 200 { 201 int err = -EINVAL; 202 203 for (; len; len--, address++, script++) { 204 if (len == 1) { 205 err = twl4030_write_script_ins(address, 206 script->pmb_message, 207 script->delay, 208 END_OF_SCRIPT); 209 if (err) 210 break; 211 } else { 212 err = twl4030_write_script_ins(address, 213 script->pmb_message, 214 script->delay, 215 address + 1); 216 if (err) 217 break; 218 } 219 } 220 return err; 221 } 222 223 static int twl4030_config_wakeup3_sequence(u8 address) 224 { 225 int err; 226 u8 data; 227 228 /* Set SLEEP to ACTIVE SEQ address for P3 */ 229 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3); 230 if (err) 231 goto out; 232 233 /* P3 LVL_WAKEUP should be on LEVEL */ 234 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS); 235 if (err) 236 goto out; 237 data |= PWR_LVL_WAKEUP; 238 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS); 239 out: 240 if (err) 241 pr_err("TWL4030 wakeup sequence for P3 config error\n"); 242 return err; 243 } 244 245 static int twl4030_config_wakeup12_sequence(u8 address) 246 { 247 int err = 0; 248 u8 data; 249 250 /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ 251 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12); 252 if (err) 253 goto out; 254 255 /* P1/P2 LVL_WAKEUP should be on LEVEL */ 256 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS); 257 if (err) 258 goto out; 259 260 data |= PWR_LVL_WAKEUP; 261 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS); 262 if (err) 263 goto out; 264 265 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS); 266 if (err) 267 goto out; 268 269 data |= PWR_LVL_WAKEUP; 270 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS); 271 if (err) 272 goto out; 273 274 if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) { 275 /* Disabling AC charger effect on sleep-active transitions */ 276 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, 277 R_CFG_P1_TRANSITION); 278 if (err) 279 goto out; 280 data &= ~(1<<1); 281 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, 282 R_CFG_P1_TRANSITION); 283 if (err) 284 goto out; 285 } 286 287 out: 288 if (err) 289 pr_err("TWL4030 wakeup sequence for P1 and P2" \ 290 "config error\n"); 291 return err; 292 } 293 294 static int twl4030_config_sleep_sequence(u8 address) 295 { 296 int err; 297 298 /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ 299 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S); 300 301 if (err) 302 pr_err("TWL4030 sleep sequence config error\n"); 303 304 return err; 305 } 306 307 static int twl4030_config_warmreset_sequence(u8 address) 308 { 309 int err; 310 u8 rd_data; 311 312 /* Set WARM RESET SEQ address for P1 */ 313 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM); 314 if (err) 315 goto out; 316 317 /* P1/P2/P3 enable WARMRESET */ 318 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS); 319 if (err) 320 goto out; 321 322 rd_data |= PWR_ENABLE_WARMRESET; 323 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS); 324 if (err) 325 goto out; 326 327 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS); 328 if (err) 329 goto out; 330 331 rd_data |= PWR_ENABLE_WARMRESET; 332 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS); 333 if (err) 334 goto out; 335 336 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS); 337 if (err) 338 goto out; 339 340 rd_data |= PWR_ENABLE_WARMRESET; 341 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS); 342 out: 343 if (err) 344 pr_err("TWL4030 warmreset seq config error\n"); 345 return err; 346 } 347 348 static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) 349 { 350 int rconfig_addr; 351 int err; 352 u8 type; 353 u8 grp; 354 u8 remap; 355 356 if (rconfig->resource > TOTAL_RESOURCES) { 357 pr_err("TWL4030 Resource %d does not exist\n", 358 rconfig->resource); 359 return -EINVAL; 360 } 361 362 rconfig_addr = res_config_addrs[rconfig->resource]; 363 364 /* Set resource group */ 365 err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp, 366 rconfig_addr + DEV_GRP_OFFSET); 367 if (err) { 368 pr_err("TWL4030 Resource %d group could not be read\n", 369 rconfig->resource); 370 return err; 371 } 372 373 if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { 374 grp &= ~DEV_GRP_MASK; 375 grp |= rconfig->devgroup << DEV_GRP_SHIFT; 376 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 377 grp, rconfig_addr + DEV_GRP_OFFSET); 378 if (err < 0) { 379 pr_err("TWL4030 failed to program devgroup\n"); 380 return err; 381 } 382 } 383 384 /* Set resource types */ 385 err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type, 386 rconfig_addr + TYPE_OFFSET); 387 if (err < 0) { 388 pr_err("TWL4030 Resource %d type could not be read\n", 389 rconfig->resource); 390 return err; 391 } 392 393 if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { 394 type &= ~TYPE_MASK; 395 type |= rconfig->type << TYPE_SHIFT; 396 } 397 398 if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { 399 type &= ~TYPE2_MASK; 400 type |= rconfig->type2 << TYPE2_SHIFT; 401 } 402 403 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 404 type, rconfig_addr + TYPE_OFFSET); 405 if (err < 0) { 406 pr_err("TWL4030 failed to program resource type\n"); 407 return err; 408 } 409 410 /* Set remap states */ 411 err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap, 412 rconfig_addr + REMAP_OFFSET); 413 if (err < 0) { 414 pr_err("TWL4030 Resource %d remap could not be read\n", 415 rconfig->resource); 416 return err; 417 } 418 419 if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { 420 remap &= ~OFF_STATE_MASK; 421 remap |= rconfig->remap_off << OFF_STATE_SHIFT; 422 } 423 424 if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { 425 remap &= ~SLEEP_STATE_MASK; 426 remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; 427 } 428 429 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 430 remap, 431 rconfig_addr + REMAP_OFFSET); 432 if (err < 0) { 433 pr_err("TWL4030 failed to program remap\n"); 434 return err; 435 } 436 437 return 0; 438 } 439 440 static int load_twl4030_script(struct twl4030_script *tscript, 441 u8 address) 442 { 443 int err; 444 static int order; 445 446 /* Make sure the script isn't going beyond last valid address (0x3f) */ 447 if ((address + tscript->size) > END_OF_SCRIPT) { 448 pr_err("TWL4030 scripts too big error\n"); 449 return -EINVAL; 450 } 451 452 err = twl4030_write_script(address, tscript->script, tscript->size); 453 if (err) 454 goto out; 455 456 if (tscript->flags & TWL4030_WRST_SCRIPT) { 457 err = twl4030_config_warmreset_sequence(address); 458 if (err) 459 goto out; 460 } 461 if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) { 462 /* Reset any existing sleep script to avoid hangs on reboot */ 463 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 464 R_SEQ_ADD_A2S); 465 if (err) 466 goto out; 467 468 err = twl4030_config_wakeup12_sequence(address); 469 if (err) 470 goto out; 471 order = 1; 472 } 473 if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) { 474 err = twl4030_config_wakeup3_sequence(address); 475 if (err) 476 goto out; 477 } 478 if (tscript->flags & TWL4030_SLEEP_SCRIPT) { 479 if (!order) 480 pr_warning("TWL4030: Bad order of scripts (sleep "\ 481 "script before wakeup) Leads to boot"\ 482 "failure on some boards\n"); 483 err = twl4030_config_sleep_sequence(address); 484 } 485 out: 486 return err; 487 } 488 489 int twl4030_remove_script(u8 flags) 490 { 491 int err = 0; 492 493 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, 494 TWL4030_PM_MASTER_PROTECT_KEY); 495 if (err) { 496 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 497 return err; 498 } 499 500 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, 501 TWL4030_PM_MASTER_PROTECT_KEY); 502 if (err) { 503 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 504 return err; 505 } 506 507 if (flags & TWL4030_WRST_SCRIPT) { 508 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 509 R_SEQ_ADD_WARM); 510 if (err) 511 return err; 512 } 513 if (flags & TWL4030_WAKEUP12_SCRIPT) { 514 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 515 R_SEQ_ADD_S2A12); 516 if (err) 517 return err; 518 } 519 if (flags & TWL4030_WAKEUP3_SCRIPT) { 520 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 521 R_SEQ_ADD_S2A3); 522 if (err) 523 return err; 524 } 525 if (flags & TWL4030_SLEEP_SCRIPT) { 526 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 527 R_SEQ_ADD_A2S); 528 if (err) 529 return err; 530 } 531 532 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, 533 TWL4030_PM_MASTER_PROTECT_KEY); 534 if (err) 535 pr_err("TWL4030 Unable to relock registers\n"); 536 537 return err; 538 } 539 540 static int 541 twl4030_power_configure_scripts(const struct twl4030_power_data *pdata) 542 { 543 int err; 544 int i; 545 u8 address = twl4030_start_script_address; 546 547 for (i = 0; i < pdata->num; i++) { 548 err = load_twl4030_script(pdata->scripts[i], address); 549 if (err) 550 return err; 551 address += pdata->scripts[i]->size; 552 } 553 554 return 0; 555 } 556 557 static int 558 twl4030_power_configure_resources(const struct twl4030_power_data *pdata) 559 { 560 struct twl4030_resconfig *resconfig = pdata->resource_config; 561 int err; 562 563 if (resconfig) { 564 while (resconfig->resource) { 565 err = twl4030_configure_resource(resconfig); 566 if (err) 567 return err; 568 resconfig++; 569 } 570 } 571 572 return 0; 573 } 574 575 /* 576 * In master mode, start the power off sequence. 577 * After a successful execution, TWL shuts down the power to the SoC 578 * and all peripherals connected to it. 579 */ 580 void twl4030_power_off(void) 581 { 582 int err; 583 584 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF, 585 TWL4030_PM_MASTER_P1_SW_EVENTS); 586 if (err) 587 pr_err("TWL4030 Unable to power off\n"); 588 } 589 590 static bool twl4030_power_use_poweroff(const struct twl4030_power_data *pdata, 591 struct device_node *node) 592 { 593 if (pdata && pdata->use_poweroff) 594 return true; 595 596 if (of_property_read_bool(node, "ti,use_poweroff")) 597 return true; 598 599 return false; 600 } 601 602 #ifdef CONFIG_OF 603 604 /* Generic warm reset configuration for omap3 */ 605 606 static struct twl4030_ins omap3_wrst_seq[] = { 607 TWL_RESOURCE_OFF(RES_NRES_PWRON), 608 TWL_RESOURCE_OFF(RES_RESET), 609 TWL_RESOURCE_RESET(RES_MAIN_REF), 610 TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2), 611 TWL_RESOURCE_RESET(RES_VUSB_3V1), 612 TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1), 613 TWL_RESOURCE_GROUP_RESET(RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0), 614 TWL_RESOURCE_ON(RES_RESET), 615 TWL_RESOURCE_ON(RES_NRES_PWRON), 616 }; 617 618 static struct twl4030_script omap3_wrst_script = { 619 .script = omap3_wrst_seq, 620 .size = ARRAY_SIZE(omap3_wrst_seq), 621 .flags = TWL4030_WRST_SCRIPT, 622 }; 623 624 static struct twl4030_script *omap3_reset_scripts[] = { 625 &omap3_wrst_script, 626 }; 627 628 static struct twl4030_resconfig omap3_rconfig[] = { 629 TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, -1, -1), 630 TWL_REMAP_SLEEP(RES_VDD1, DEV_GRP_P1, -1, -1), 631 TWL_REMAP_SLEEP(RES_VDD2, DEV_GRP_P1, -1, -1), 632 { 0, 0 }, 633 }; 634 635 static struct twl4030_power_data omap3_reset = { 636 .scripts = omap3_reset_scripts, 637 .num = ARRAY_SIZE(omap3_reset_scripts), 638 .resource_config = omap3_rconfig, 639 }; 640 641 static struct of_device_id twl4030_power_of_match[] = { 642 { 643 .compatible = "ti,twl4030-power-reset", 644 .data = &omap3_reset, 645 }, 646 { }, 647 }; 648 MODULE_DEVICE_TABLE(of, twl4030_power_of_match); 649 #endif /* CONFIG_OF */ 650 651 static int twl4030_power_probe(struct platform_device *pdev) 652 { 653 const struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev); 654 struct device_node *node = pdev->dev.of_node; 655 const struct of_device_id *match; 656 int err = 0; 657 int err2 = 0; 658 u8 val; 659 660 if (!pdata && !node) { 661 dev_err(&pdev->dev, "Platform data is missing\n"); 662 return -EINVAL; 663 } 664 665 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, 666 TWL4030_PM_MASTER_PROTECT_KEY); 667 err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 668 TWL4030_PM_MASTER_KEY_CFG2, 669 TWL4030_PM_MASTER_PROTECT_KEY); 670 671 if (err) { 672 pr_err("TWL4030 Unable to unlock registers\n"); 673 return err; 674 } 675 676 match = of_match_device(of_match_ptr(twl4030_power_of_match), 677 &pdev->dev); 678 if (match && match->data) 679 pdata = match->data; 680 681 if (pdata) { 682 err = twl4030_power_configure_scripts(pdata); 683 if (err) { 684 pr_err("TWL4030 failed to load scripts\n"); 685 goto relock; 686 } 687 err = twl4030_power_configure_resources(pdata); 688 if (err) { 689 pr_err("TWL4030 failed to configure resource\n"); 690 goto relock; 691 } 692 } 693 694 /* Board has to be wired properly to use this feature */ 695 if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) { 696 /* Default for SEQ_OFFSYNC is set, lets ensure this */ 697 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, 698 TWL4030_PM_MASTER_CFG_P123_TRANSITION); 699 if (err) { 700 pr_warning("TWL4030 Unable to read registers\n"); 701 702 } else if (!(val & SEQ_OFFSYNC)) { 703 val |= SEQ_OFFSYNC; 704 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val, 705 TWL4030_PM_MASTER_CFG_P123_TRANSITION); 706 if (err) { 707 pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n"); 708 goto relock; 709 } 710 } 711 712 pm_power_off = twl4030_power_off; 713 } 714 715 relock: 716 err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, 717 TWL4030_PM_MASTER_PROTECT_KEY); 718 if (err2) { 719 pr_err("TWL4030 Unable to relock registers\n"); 720 return err2; 721 } 722 723 return err; 724 } 725 726 static int twl4030_power_remove(struct platform_device *pdev) 727 { 728 return 0; 729 } 730 731 static struct platform_driver twl4030_power_driver = { 732 .driver = { 733 .name = "twl4030_power", 734 .owner = THIS_MODULE, 735 .of_match_table = of_match_ptr(twl4030_power_of_match), 736 }, 737 .probe = twl4030_power_probe, 738 .remove = twl4030_power_remove, 739 }; 740 741 module_platform_driver(twl4030_power_driver); 742 743 MODULE_AUTHOR("Nokia Corporation"); 744 MODULE_AUTHOR("Texas Instruments, Inc."); 745 MODULE_DESCRIPTION("Power management for TWL4030"); 746 MODULE_LICENSE("GPL"); 747 MODULE_ALIAS("platform:twl4030_power"); 748