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