Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.10 978 lines 26 kB view raw
1/* 2 * 3 * Handle TWL4030 Power initialization 4 * 5 * Copyright (C) 2008 Nokia Corporation 6 * Copyright (C) 2006 Texas Instruments, Inc 7 * 8 * Written by Kalle Jokiniemi 9 * Peter De Schrijver <peter.de-schrijver@nokia.com> 10 * Several fixes by Amit Kucheria <amit.kucheria@verdurent.com> 11 * 12 * This file is subject to the terms and conditions of the GNU General 13 * Public License. See the file "COPYING" in the main directory of this 14 * archive for more details. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26#include <linux/module.h> 27#include <linux/pm.h> 28#include <linux/i2c/twl.h> 29#include <linux/platform_device.h> 30#include <linux/of.h> 31#include <linux/of_device.h> 32 33#include <asm/mach-types.h> 34 35static u8 twl4030_start_script_address = 0x2b; 36 37/* Register bits for P1, P2 and P3_SW_EVENTS */ 38#define PWR_STOPON_PRWON BIT(6) 39#define PWR_STOPON_SYSEN BIT(5) 40#define PWR_ENABLE_WARMRESET BIT(4) 41#define PWR_LVL_WAKEUP BIT(3) 42#define PWR_DEVACT BIT(2) 43#define PWR_DEVSLP BIT(1) 44#define PWR_DEVOFF BIT(0) 45 46/* Register bits for CFG_P1_TRANSITION (also for P2 and P3) */ 47#define STARTON_SWBUG BIT(7) /* Start on watchdog */ 48#define STARTON_VBUS BIT(5) /* Start on VBUS */ 49#define STARTON_VBAT BIT(4) /* Start on battery insert */ 50#define STARTON_RTC BIT(3) /* Start on RTC */ 51#define STARTON_USB BIT(2) /* Start on USB host */ 52#define STARTON_CHG BIT(1) /* Start on charger */ 53#define STARTON_PWON BIT(0) /* Start on PWRON button */ 54 55#define SEQ_OFFSYNC (1 << 0) 56 57#define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) 58#define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b) 59 60/* resource - hfclk */ 61#define R_HFCLKOUT_DEV_GRP PHY_TO_OFF_PM_RECEIVER(0xe6) 62 63/* PM events */ 64#define R_P1_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x46) 65#define R_P2_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x47) 66#define R_P3_SW_EVENTS PHY_TO_OFF_PM_MASTER(0x48) 67#define R_CFG_P1_TRANSITION PHY_TO_OFF_PM_MASTER(0x36) 68#define R_CFG_P2_TRANSITION PHY_TO_OFF_PM_MASTER(0x37) 69#define R_CFG_P3_TRANSITION PHY_TO_OFF_PM_MASTER(0x38) 70 71#define END_OF_SCRIPT 0x3f 72 73#define R_SEQ_ADD_A2S PHY_TO_OFF_PM_MASTER(0x55) 74#define R_SEQ_ADD_S2A12 PHY_TO_OFF_PM_MASTER(0x56) 75#define R_SEQ_ADD_S2A3 PHY_TO_OFF_PM_MASTER(0x57) 76#define R_SEQ_ADD_WARM PHY_TO_OFF_PM_MASTER(0x58) 77#define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) 78#define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) 79 80/* resource configuration registers 81 <RESOURCE>_DEV_GRP at address 'n+0' 82 <RESOURCE>_TYPE at address 'n+1' 83 <RESOURCE>_REMAP at address 'n+2' 84 <RESOURCE>_DEDICATED at address 'n+3' 85*/ 86#define DEV_GRP_OFFSET 0 87#define TYPE_OFFSET 1 88#define REMAP_OFFSET 2 89#define DEDICATED_OFFSET 3 90 91/* Bit positions in the registers */ 92 93/* <RESOURCE>_DEV_GRP */ 94#define DEV_GRP_SHIFT 5 95#define DEV_GRP_MASK (7 << DEV_GRP_SHIFT) 96 97/* <RESOURCE>_TYPE */ 98#define TYPE_SHIFT 0 99#define TYPE_MASK (7 << TYPE_SHIFT) 100#define TYPE2_SHIFT 3 101#define TYPE2_MASK (3 << TYPE2_SHIFT) 102 103/* <RESOURCE>_REMAP */ 104#define SLEEP_STATE_SHIFT 0 105#define SLEEP_STATE_MASK (0xf << SLEEP_STATE_SHIFT) 106#define OFF_STATE_SHIFT 4 107#define OFF_STATE_MASK (0xf << OFF_STATE_SHIFT) 108 109static u8 res_config_addrs[] = { 110 [RES_VAUX1] = 0x17, 111 [RES_VAUX2] = 0x1b, 112 [RES_VAUX3] = 0x1f, 113 [RES_VAUX4] = 0x23, 114 [RES_VMMC1] = 0x27, 115 [RES_VMMC2] = 0x2b, 116 [RES_VPLL1] = 0x2f, 117 [RES_VPLL2] = 0x33, 118 [RES_VSIM] = 0x37, 119 [RES_VDAC] = 0x3b, 120 [RES_VINTANA1] = 0x3f, 121 [RES_VINTANA2] = 0x43, 122 [RES_VINTDIG] = 0x47, 123 [RES_VIO] = 0x4b, 124 [RES_VDD1] = 0x55, 125 [RES_VDD2] = 0x63, 126 [RES_VUSB_1V5] = 0x71, 127 [RES_VUSB_1V8] = 0x74, 128 [RES_VUSB_3V1] = 0x77, 129 [RES_VUSBCP] = 0x7a, 130 [RES_REGEN] = 0x7f, 131 [RES_NRES_PWRON] = 0x82, 132 [RES_CLKEN] = 0x85, 133 [RES_SYSEN] = 0x88, 134 [RES_HFCLKOUT] = 0x8b, 135 [RES_32KCLKOUT] = 0x8e, 136 [RES_RESET] = 0x91, 137 [RES_MAIN_REF] = 0x94, 138}; 139 140/* 141 * Usable values for .remap_sleep and .remap_off 142 * Based on table "5.3.3 Resource Operating modes" 143 */ 144enum { 145 TWL_REMAP_OFF = 0, 146 TWL_REMAP_SLEEP = 8, 147 TWL_REMAP_ACTIVE = 9, 148}; 149 150/* 151 * Macros to configure the PM register states for various resources. 152 * Note that we can make MSG_SINGULAR etc private to this driver once 153 * omap3 has been made DT only. 154 */ 155#define TWL_DFLT_DELAY 2 /* typically 2 32 KiHz cycles */ 156#define TWL_DEV_GRP_P123 (DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3) 157#define TWL_RESOURCE_SET(res, state) \ 158 { MSG_SINGULAR(DEV_GRP_NULL, (res), (state)), TWL_DFLT_DELAY } 159#define TWL_RESOURCE_ON(res) TWL_RESOURCE_SET(res, RES_STATE_ACTIVE) 160#define TWL_RESOURCE_OFF(res) TWL_RESOURCE_SET(res, RES_STATE_OFF) 161#define TWL_RESOURCE_RESET(res) TWL_RESOURCE_SET(res, RES_STATE_WRST) 162/* 163 * It seems that type1 and type2 is just the resource init order 164 * number for the type1 and type2 group. 165 */ 166#define TWL_RESOURCE_SET_ACTIVE(res, state) \ 167 { MSG_SINGULAR(DEV_GRP_NULL, (res), RES_STATE_ACTIVE), (state) } 168#define TWL_RESOURCE_GROUP_RESET(group, type1, type2) \ 169 { MSG_BROADCAST(DEV_GRP_NULL, (group), (type1), (type2), \ 170 RES_STATE_WRST), TWL_DFLT_DELAY } 171#define TWL_RESOURCE_GROUP_SLEEP(group, type, type2) \ 172 { MSG_BROADCAST(DEV_GRP_NULL, (group), (type), (type2), \ 173 RES_STATE_SLEEP), TWL_DFLT_DELAY } 174#define TWL_RESOURCE_GROUP_ACTIVE(group, type, type2) \ 175 { MSG_BROADCAST(DEV_GRP_NULL, (group), (type), (type2), \ 176 RES_STATE_ACTIVE), TWL_DFLT_DELAY } 177#define TWL_REMAP_SLEEP(res, devgrp, typ, typ2) \ 178 { .resource = (res), .devgroup = (devgrp), \ 179 .type = (typ), .type2 = (typ2), \ 180 .remap_off = TWL_REMAP_OFF, \ 181 .remap_sleep = TWL_REMAP_SLEEP, } 182#define TWL_REMAP_OFF(res, devgrp, typ, typ2) \ 183 { .resource = (res), .devgroup = (devgrp), \ 184 .type = (typ), .type2 = (typ2), \ 185 .remap_off = TWL_REMAP_OFF, .remap_sleep = TWL_REMAP_OFF, } 186 187static int twl4030_write_script_byte(u8 address, u8 byte) 188{ 189 int err; 190 191 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS); 192 if (err) 193 goto out; 194 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA); 195out: 196 return err; 197} 198 199static int twl4030_write_script_ins(u8 address, u16 pmb_message, 200 u8 delay, u8 next) 201{ 202 int err; 203 204 address *= 4; 205 err = twl4030_write_script_byte(address++, pmb_message >> 8); 206 if (err) 207 goto out; 208 err = twl4030_write_script_byte(address++, pmb_message & 0xff); 209 if (err) 210 goto out; 211 err = twl4030_write_script_byte(address++, delay); 212 if (err) 213 goto out; 214 err = twl4030_write_script_byte(address++, next); 215out: 216 return err; 217} 218 219static int twl4030_write_script(u8 address, struct twl4030_ins *script, 220 int len) 221{ 222 int err = -EINVAL; 223 224 for (; len; len--, address++, script++) { 225 if (len == 1) { 226 err = twl4030_write_script_ins(address, 227 script->pmb_message, 228 script->delay, 229 END_OF_SCRIPT); 230 if (err) 231 break; 232 } else { 233 err = twl4030_write_script_ins(address, 234 script->pmb_message, 235 script->delay, 236 address + 1); 237 if (err) 238 break; 239 } 240 } 241 return err; 242} 243 244static int twl4030_config_wakeup3_sequence(u8 address) 245{ 246 int err; 247 u8 data; 248 249 /* Set SLEEP to ACTIVE SEQ address for P3 */ 250 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3); 251 if (err) 252 goto out; 253 254 /* P3 LVL_WAKEUP should be on LEVEL */ 255 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS); 256 if (err) 257 goto out; 258 data |= PWR_LVL_WAKEUP; 259 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS); 260out: 261 if (err) 262 pr_err("TWL4030 wakeup sequence for P3 config error\n"); 263 return err; 264} 265 266static int 267twl4030_config_wakeup12_sequence(const struct twl4030_power_data *pdata, 268 u8 address) 269{ 270 int err = 0; 271 u8 data; 272 273 /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */ 274 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12); 275 if (err) 276 goto out; 277 278 /* P1/P2 LVL_WAKEUP should be on LEVEL */ 279 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS); 280 if (err) 281 goto out; 282 283 data |= PWR_LVL_WAKEUP; 284 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS); 285 if (err) 286 goto out; 287 288 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS); 289 if (err) 290 goto out; 291 292 data |= PWR_LVL_WAKEUP; 293 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS); 294 if (err) 295 goto out; 296 297 if (pdata->ac_charger_quirk || machine_is_omap_3430sdp() || 298 machine_is_omap_ldp()) { 299 /* Disabling AC charger effect on sleep-active transitions */ 300 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, 301 R_CFG_P1_TRANSITION); 302 if (err) 303 goto out; 304 data &= ~STARTON_CHG; 305 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, 306 R_CFG_P1_TRANSITION); 307 if (err) 308 goto out; 309 } 310 311out: 312 if (err) 313 pr_err("TWL4030 wakeup sequence for P1 and P2" \ 314 "config error\n"); 315 return err; 316} 317 318static int twl4030_config_sleep_sequence(u8 address) 319{ 320 int err; 321 322 /* Set ACTIVE to SLEEP SEQ address in T2 memory*/ 323 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S); 324 325 if (err) 326 pr_err("TWL4030 sleep sequence config error\n"); 327 328 return err; 329} 330 331static int twl4030_config_warmreset_sequence(u8 address) 332{ 333 int err; 334 u8 rd_data; 335 336 /* Set WARM RESET SEQ address for P1 */ 337 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM); 338 if (err) 339 goto out; 340 341 /* P1/P2/P3 enable WARMRESET */ 342 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS); 343 if (err) 344 goto out; 345 346 rd_data |= PWR_ENABLE_WARMRESET; 347 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS); 348 if (err) 349 goto out; 350 351 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS); 352 if (err) 353 goto out; 354 355 rd_data |= PWR_ENABLE_WARMRESET; 356 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS); 357 if (err) 358 goto out; 359 360 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS); 361 if (err) 362 goto out; 363 364 rd_data |= PWR_ENABLE_WARMRESET; 365 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS); 366out: 367 if (err) 368 pr_err("TWL4030 warmreset seq config error\n"); 369 return err; 370} 371 372static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) 373{ 374 int rconfig_addr; 375 int err; 376 u8 type; 377 u8 grp; 378 u8 remap; 379 380 if (rconfig->resource > TOTAL_RESOURCES) { 381 pr_err("TWL4030 Resource %d does not exist\n", 382 rconfig->resource); 383 return -EINVAL; 384 } 385 386 rconfig_addr = res_config_addrs[rconfig->resource]; 387 388 /* Set resource group */ 389 err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp, 390 rconfig_addr + DEV_GRP_OFFSET); 391 if (err) { 392 pr_err("TWL4030 Resource %d group could not be read\n", 393 rconfig->resource); 394 return err; 395 } 396 397 if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { 398 grp &= ~DEV_GRP_MASK; 399 grp |= rconfig->devgroup << DEV_GRP_SHIFT; 400 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 401 grp, rconfig_addr + DEV_GRP_OFFSET); 402 if (err < 0) { 403 pr_err("TWL4030 failed to program devgroup\n"); 404 return err; 405 } 406 } 407 408 /* Set resource types */ 409 err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type, 410 rconfig_addr + TYPE_OFFSET); 411 if (err < 0) { 412 pr_err("TWL4030 Resource %d type could not be read\n", 413 rconfig->resource); 414 return err; 415 } 416 417 if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { 418 type &= ~TYPE_MASK; 419 type |= rconfig->type << TYPE_SHIFT; 420 } 421 422 if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { 423 type &= ~TYPE2_MASK; 424 type |= rconfig->type2 << TYPE2_SHIFT; 425 } 426 427 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 428 type, rconfig_addr + TYPE_OFFSET); 429 if (err < 0) { 430 pr_err("TWL4030 failed to program resource type\n"); 431 return err; 432 } 433 434 /* Set remap states */ 435 err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap, 436 rconfig_addr + REMAP_OFFSET); 437 if (err < 0) { 438 pr_err("TWL4030 Resource %d remap could not be read\n", 439 rconfig->resource); 440 return err; 441 } 442 443 if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { 444 remap &= ~OFF_STATE_MASK; 445 remap |= rconfig->remap_off << OFF_STATE_SHIFT; 446 } 447 448 if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { 449 remap &= ~SLEEP_STATE_MASK; 450 remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; 451 } 452 453 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 454 remap, 455 rconfig_addr + REMAP_OFFSET); 456 if (err < 0) { 457 pr_err("TWL4030 failed to program remap\n"); 458 return err; 459 } 460 461 return 0; 462} 463 464static int load_twl4030_script(const struct twl4030_power_data *pdata, 465 struct twl4030_script *tscript, 466 u8 address) 467{ 468 int err; 469 static int order; 470 471 /* Make sure the script isn't going beyond last valid address (0x3f) */ 472 if ((address + tscript->size) > END_OF_SCRIPT) { 473 pr_err("TWL4030 scripts too big error\n"); 474 return -EINVAL; 475 } 476 477 err = twl4030_write_script(address, tscript->script, tscript->size); 478 if (err) 479 goto out; 480 481 if (tscript->flags & TWL4030_WRST_SCRIPT) { 482 err = twl4030_config_warmreset_sequence(address); 483 if (err) 484 goto out; 485 } 486 if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) { 487 /* Reset any existing sleep script to avoid hangs on reboot */ 488 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 489 R_SEQ_ADD_A2S); 490 if (err) 491 goto out; 492 493 err = twl4030_config_wakeup12_sequence(pdata, address); 494 if (err) 495 goto out; 496 order = 1; 497 } 498 if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) { 499 err = twl4030_config_wakeup3_sequence(address); 500 if (err) 501 goto out; 502 } 503 if (tscript->flags & TWL4030_SLEEP_SCRIPT) { 504 if (!order) 505 pr_warning("TWL4030: Bad order of scripts (sleep "\ 506 "script before wakeup) Leads to boot"\ 507 "failure on some boards\n"); 508 err = twl4030_config_sleep_sequence(address); 509 } 510out: 511 return err; 512} 513 514int twl4030_remove_script(u8 flags) 515{ 516 int err = 0; 517 518 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, 519 TWL4030_PM_MASTER_PROTECT_KEY); 520 if (err) { 521 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 522 return err; 523 } 524 525 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, 526 TWL4030_PM_MASTER_PROTECT_KEY); 527 if (err) { 528 pr_err("twl4030: unable to unlock PROTECT_KEY\n"); 529 return err; 530 } 531 532 if (flags & TWL4030_WRST_SCRIPT) { 533 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 534 R_SEQ_ADD_WARM); 535 if (err) 536 return err; 537 } 538 if (flags & TWL4030_WAKEUP12_SCRIPT) { 539 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 540 R_SEQ_ADD_S2A12); 541 if (err) 542 return err; 543 } 544 if (flags & TWL4030_WAKEUP3_SCRIPT) { 545 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 546 R_SEQ_ADD_S2A3); 547 if (err) 548 return err; 549 } 550 if (flags & TWL4030_SLEEP_SCRIPT) { 551 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, 552 R_SEQ_ADD_A2S); 553 if (err) 554 return err; 555 } 556 557 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, 558 TWL4030_PM_MASTER_PROTECT_KEY); 559 if (err) 560 pr_err("TWL4030 Unable to relock registers\n"); 561 562 return err; 563} 564 565static int 566twl4030_power_configure_scripts(const struct twl4030_power_data *pdata) 567{ 568 int err; 569 int i; 570 u8 address = twl4030_start_script_address; 571 572 for (i = 0; i < pdata->num; i++) { 573 err = load_twl4030_script(pdata, pdata->scripts[i], address); 574 if (err) 575 return err; 576 address += pdata->scripts[i]->size; 577 } 578 579 return 0; 580} 581 582static void twl4030_patch_rconfig(struct twl4030_resconfig *common, 583 struct twl4030_resconfig *board) 584{ 585 while (common->resource) { 586 struct twl4030_resconfig *b = board; 587 588 while (b->resource) { 589 if (b->resource == common->resource) { 590 *common = *b; 591 break; 592 } 593 b++; 594 } 595 common++; 596 } 597} 598 599static int 600twl4030_power_configure_resources(const struct twl4030_power_data *pdata) 601{ 602 struct twl4030_resconfig *resconfig = pdata->resource_config; 603 struct twl4030_resconfig *boardconf = pdata->board_config; 604 int err; 605 606 if (resconfig) { 607 if (boardconf) 608 twl4030_patch_rconfig(resconfig, boardconf); 609 610 while (resconfig->resource) { 611 err = twl4030_configure_resource(resconfig); 612 if (err) 613 return err; 614 resconfig++; 615 } 616 } 617 618 return 0; 619} 620 621static int twl4030_starton_mask_and_set(u8 bitmask, u8 bitvalues) 622{ 623 u8 regs[3] = { TWL4030_PM_MASTER_CFG_P1_TRANSITION, 624 TWL4030_PM_MASTER_CFG_P2_TRANSITION, 625 TWL4030_PM_MASTER_CFG_P3_TRANSITION, }; 626 u8 val; 627 int i, err; 628 629 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, 630 TWL4030_PM_MASTER_PROTECT_KEY); 631 if (err) 632 goto relock; 633 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 634 TWL4030_PM_MASTER_KEY_CFG2, 635 TWL4030_PM_MASTER_PROTECT_KEY); 636 if (err) 637 goto relock; 638 639 for (i = 0; i < sizeof(regs); i++) { 640 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, 641 &val, regs[i]); 642 if (err) 643 break; 644 val = (~bitmask & val) | (bitmask & bitvalues); 645 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 646 val, regs[i]); 647 if (err) 648 break; 649 } 650 651 if (err) 652 pr_err("TWL4030 Register access failed: %i\n", err); 653 654relock: 655 return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, 656 TWL4030_PM_MASTER_PROTECT_KEY); 657} 658 659/* 660 * In master mode, start the power off sequence. 661 * After a successful execution, TWL shuts down the power to the SoC 662 * and all peripherals connected to it. 663 */ 664void twl4030_power_off(void) 665{ 666 int err; 667 668 /* Disable start on charger or VBUS as it can break poweroff */ 669 err = twl4030_starton_mask_and_set(STARTON_VBUS | STARTON_CHG, 0); 670 if (err) 671 pr_err("TWL4030 Unable to configure start-up\n"); 672 673 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF, 674 TWL4030_PM_MASTER_P1_SW_EVENTS); 675 if (err) 676 pr_err("TWL4030 Unable to power off\n"); 677} 678 679static bool twl4030_power_use_poweroff(const struct twl4030_power_data *pdata, 680 struct device_node *node) 681{ 682 if (pdata && pdata->use_poweroff) 683 return true; 684 685 if (of_property_read_bool(node, "ti,system-power-controller")) 686 return true; 687 688 if (of_property_read_bool(node, "ti,use_poweroff")) 689 return true; 690 691 return false; 692} 693 694#ifdef CONFIG_OF 695 696/* Generic warm reset configuration for omap3 */ 697 698static struct twl4030_ins omap3_wrst_seq[] = { 699 TWL_RESOURCE_OFF(RES_NRES_PWRON), 700 TWL_RESOURCE_OFF(RES_RESET), 701 TWL_RESOURCE_RESET(RES_MAIN_REF), 702 TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2), 703 TWL_RESOURCE_RESET(RES_VUSB_3V1), 704 TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1), 705 TWL_RESOURCE_GROUP_RESET(RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0), 706 TWL_RESOURCE_ON(RES_RESET), 707 TWL_RESOURCE_ON(RES_NRES_PWRON), 708}; 709 710static struct twl4030_script omap3_wrst_script = { 711 .script = omap3_wrst_seq, 712 .size = ARRAY_SIZE(omap3_wrst_seq), 713 .flags = TWL4030_WRST_SCRIPT, 714}; 715 716static struct twl4030_script *omap3_reset_scripts[] = { 717 &omap3_wrst_script, 718}; 719 720static struct twl4030_resconfig omap3_rconfig[] = { 721 TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, -1, -1), 722 TWL_REMAP_SLEEP(RES_VDD1, DEV_GRP_P1, -1, -1), 723 TWL_REMAP_SLEEP(RES_VDD2, DEV_GRP_P1, -1, -1), 724 { 0, 0 }, 725}; 726 727static struct twl4030_power_data omap3_reset = { 728 .scripts = omap3_reset_scripts, 729 .num = ARRAY_SIZE(omap3_reset_scripts), 730 .resource_config = omap3_rconfig, 731}; 732 733/* Recommended generic default idle configuration for off-idle */ 734 735/* Broadcast message to put res to sleep */ 736static struct twl4030_ins omap3_idle_sleep_on_seq[] = { 737 TWL_RESOURCE_GROUP_SLEEP(RES_GRP_ALL, RES_TYPE_ALL, 0), 738}; 739 740static struct twl4030_script omap3_idle_sleep_on_script = { 741 .script = omap3_idle_sleep_on_seq, 742 .size = ARRAY_SIZE(omap3_idle_sleep_on_seq), 743 .flags = TWL4030_SLEEP_SCRIPT, 744}; 745 746/* Broadcast message to put res to active */ 747static struct twl4030_ins omap3_idle_wakeup_p12_seq[] = { 748 TWL_RESOURCE_GROUP_ACTIVE(RES_GRP_ALL, RES_TYPE_ALL, 0), 749}; 750 751static struct twl4030_script omap3_idle_wakeup_p12_script = { 752 .script = omap3_idle_wakeup_p12_seq, 753 .size = ARRAY_SIZE(omap3_idle_wakeup_p12_seq), 754 .flags = TWL4030_WAKEUP12_SCRIPT, 755}; 756 757/* Broadcast message to put res to active */ 758static struct twl4030_ins omap3_idle_wakeup_p3_seq[] = { 759 TWL_RESOURCE_SET_ACTIVE(RES_CLKEN, 0x37), 760 TWL_RESOURCE_GROUP_ACTIVE(RES_GRP_ALL, RES_TYPE_ALL, 0), 761}; 762 763static struct twl4030_script omap3_idle_wakeup_p3_script = { 764 .script = omap3_idle_wakeup_p3_seq, 765 .size = ARRAY_SIZE(omap3_idle_wakeup_p3_seq), 766 .flags = TWL4030_WAKEUP3_SCRIPT, 767}; 768 769static struct twl4030_script *omap3_idle_scripts[] = { 770 &omap3_idle_wakeup_p12_script, 771 &omap3_idle_wakeup_p3_script, 772 &omap3_wrst_script, 773 &omap3_idle_sleep_on_script, 774}; 775 776/* 777 * Recommended configuration based on "Recommended Sleep 778 * Sequences for the Zoom Platform": 779 * http://omappedia.com/wiki/File:Recommended_Sleep_Sequences_Zoom.pdf 780 * Note that the type1 and type2 seem to be just the init order number 781 * for type1 and type2 groups as specified in the document mentioned 782 * above. 783 */ 784static struct twl4030_resconfig omap3_idle_rconfig[] = { 785 TWL_REMAP_SLEEP(RES_VAUX1, TWL4030_RESCONFIG_UNDEF, 0, 0), 786 TWL_REMAP_SLEEP(RES_VAUX2, TWL4030_RESCONFIG_UNDEF, 0, 0), 787 TWL_REMAP_SLEEP(RES_VAUX3, TWL4030_RESCONFIG_UNDEF, 0, 0), 788 TWL_REMAP_SLEEP(RES_VAUX4, TWL4030_RESCONFIG_UNDEF, 0, 0), 789 TWL_REMAP_SLEEP(RES_VMMC1, TWL4030_RESCONFIG_UNDEF, 0, 0), 790 TWL_REMAP_SLEEP(RES_VMMC2, TWL4030_RESCONFIG_UNDEF, 0, 0), 791 TWL_REMAP_OFF(RES_VPLL1, DEV_GRP_P1, 3, 1), 792 TWL_REMAP_SLEEP(RES_VPLL2, DEV_GRP_P1, 0, 0), 793 TWL_REMAP_SLEEP(RES_VSIM, TWL4030_RESCONFIG_UNDEF, 0, 0), 794 TWL_REMAP_SLEEP(RES_VDAC, TWL4030_RESCONFIG_UNDEF, 0, 0), 795 TWL_REMAP_SLEEP(RES_VINTANA1, TWL_DEV_GRP_P123, 1, 2), 796 TWL_REMAP_SLEEP(RES_VINTANA2, TWL_DEV_GRP_P123, 0, 2), 797 TWL_REMAP_SLEEP(RES_VINTDIG, TWL_DEV_GRP_P123, 1, 2), 798 TWL_REMAP_SLEEP(RES_VIO, TWL_DEV_GRP_P123, 2, 2), 799 TWL_REMAP_OFF(RES_VDD1, DEV_GRP_P1, 4, 1), 800 TWL_REMAP_OFF(RES_VDD2, DEV_GRP_P1, 3, 1), 801 TWL_REMAP_SLEEP(RES_VUSB_1V5, TWL4030_RESCONFIG_UNDEF, 0, 0), 802 TWL_REMAP_SLEEP(RES_VUSB_1V8, TWL4030_RESCONFIG_UNDEF, 0, 0), 803 TWL_REMAP_SLEEP(RES_VUSB_3V1, TWL_DEV_GRP_P123, 0, 0), 804 /* Resource #20 USB charge pump skipped */ 805 TWL_REMAP_SLEEP(RES_REGEN, TWL_DEV_GRP_P123, 2, 1), 806 TWL_REMAP_SLEEP(RES_NRES_PWRON, TWL_DEV_GRP_P123, 0, 1), 807 TWL_REMAP_SLEEP(RES_CLKEN, TWL_DEV_GRP_P123, 3, 2), 808 TWL_REMAP_SLEEP(RES_SYSEN, TWL_DEV_GRP_P123, 6, 1), 809 TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, 0, 2), 810 TWL_REMAP_SLEEP(RES_32KCLKOUT, TWL_DEV_GRP_P123, 0, 0), 811 TWL_REMAP_SLEEP(RES_RESET, TWL_DEV_GRP_P123, 6, 0), 812 TWL_REMAP_SLEEP(RES_MAIN_REF, TWL_DEV_GRP_P123, 0, 0), 813 { /* Terminator */ }, 814}; 815 816static struct twl4030_power_data omap3_idle = { 817 .scripts = omap3_idle_scripts, 818 .num = ARRAY_SIZE(omap3_idle_scripts), 819 .resource_config = omap3_idle_rconfig, 820}; 821 822/* Disable 32 KiHz oscillator during idle */ 823static struct twl4030_resconfig osc_off_rconfig[] = { 824 TWL_REMAP_OFF(RES_CLKEN, DEV_GRP_P1 | DEV_GRP_P3, 3, 2), 825 { /* Terminator */ }, 826}; 827 828static struct twl4030_power_data osc_off_idle = { 829 .scripts = omap3_idle_scripts, 830 .num = ARRAY_SIZE(omap3_idle_scripts), 831 .resource_config = omap3_idle_rconfig, 832 .board_config = osc_off_rconfig, 833}; 834 835static struct twl4030_power_data omap3_idle_ac_quirk = { 836 .scripts = omap3_idle_scripts, 837 .num = ARRAY_SIZE(omap3_idle_scripts), 838 .resource_config = omap3_idle_rconfig, 839 .ac_charger_quirk = true, 840}; 841 842static struct twl4030_power_data omap3_idle_ac_quirk_osc_off = { 843 .scripts = omap3_idle_scripts, 844 .num = ARRAY_SIZE(omap3_idle_scripts), 845 .resource_config = omap3_idle_rconfig, 846 .board_config = osc_off_rconfig, 847 .ac_charger_quirk = true, 848}; 849 850static const struct of_device_id twl4030_power_of_match[] = { 851 { 852 .compatible = "ti,twl4030-power", 853 }, 854 { 855 .compatible = "ti,twl4030-power-reset", 856 .data = &omap3_reset, 857 }, 858 { 859 .compatible = "ti,twl4030-power-idle", 860 .data = &omap3_idle, 861 }, 862 { 863 .compatible = "ti,twl4030-power-idle-osc-off", 864 .data = &osc_off_idle, 865 }, 866 { 867 .compatible = "ti,twl4030-power-omap3-sdp", 868 .data = &omap3_idle_ac_quirk, 869 }, 870 { 871 .compatible = "ti,twl4030-power-omap3-ldp", 872 .data = &omap3_idle_ac_quirk_osc_off, 873 }, 874 { 875 .compatible = "ti,twl4030-power-omap3-evm", 876 .data = &omap3_idle_ac_quirk, 877 }, 878 { }, 879}; 880MODULE_DEVICE_TABLE(of, twl4030_power_of_match); 881#endif /* CONFIG_OF */ 882 883static int twl4030_power_probe(struct platform_device *pdev) 884{ 885 const struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev); 886 struct device_node *node = pdev->dev.of_node; 887 const struct of_device_id *match; 888 int err = 0; 889 int err2 = 0; 890 u8 val; 891 892 if (!pdata && !node) { 893 dev_err(&pdev->dev, "Platform data is missing\n"); 894 return -EINVAL; 895 } 896 897 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, 898 TWL4030_PM_MASTER_PROTECT_KEY); 899 err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 900 TWL4030_PM_MASTER_KEY_CFG2, 901 TWL4030_PM_MASTER_PROTECT_KEY); 902 903 if (err) { 904 pr_err("TWL4030 Unable to unlock registers\n"); 905 return err; 906 } 907 908 match = of_match_device(of_match_ptr(twl4030_power_of_match), 909 &pdev->dev); 910 if (match && match->data) 911 pdata = match->data; 912 913 if (pdata) { 914 err = twl4030_power_configure_scripts(pdata); 915 if (err) { 916 pr_err("TWL4030 failed to load scripts\n"); 917 goto relock; 918 } 919 err = twl4030_power_configure_resources(pdata); 920 if (err) { 921 pr_err("TWL4030 failed to configure resource\n"); 922 goto relock; 923 } 924 } 925 926 /* Board has to be wired properly to use this feature */ 927 if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) { 928 /* Default for SEQ_OFFSYNC is set, lets ensure this */ 929 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, 930 TWL4030_PM_MASTER_CFG_P123_TRANSITION); 931 if (err) { 932 pr_warning("TWL4030 Unable to read registers\n"); 933 934 } else if (!(val & SEQ_OFFSYNC)) { 935 val |= SEQ_OFFSYNC; 936 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val, 937 TWL4030_PM_MASTER_CFG_P123_TRANSITION); 938 if (err) { 939 pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n"); 940 goto relock; 941 } 942 } 943 944 pm_power_off = twl4030_power_off; 945 } 946 947relock: 948 err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, 949 TWL4030_PM_MASTER_PROTECT_KEY); 950 if (err2) { 951 pr_err("TWL4030 Unable to relock registers\n"); 952 return err2; 953 } 954 955 return err; 956} 957 958static int twl4030_power_remove(struct platform_device *pdev) 959{ 960 return 0; 961} 962 963static struct platform_driver twl4030_power_driver = { 964 .driver = { 965 .name = "twl4030_power", 966 .of_match_table = of_match_ptr(twl4030_power_of_match), 967 }, 968 .probe = twl4030_power_probe, 969 .remove = twl4030_power_remove, 970}; 971 972module_platform_driver(twl4030_power_driver); 973 974MODULE_AUTHOR("Nokia Corporation"); 975MODULE_AUTHOR("Texas Instruments, Inc."); 976MODULE_DESCRIPTION("Power management for TWL4030"); 977MODULE_LICENSE("GPL"); 978MODULE_ALIAS("platform:twl4030_power");