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