xref: /openbmc/linux/drivers/mfd/twl4030-power.c (revision 63dc02bd)
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