Blame view

drivers/mfd/twl4030-power.c 14.3 KB
ebf0bd366   Amit Kucheria   mfd: Add support ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  /*
   * linux/drivers/i2c/chips/twl4030-power.c
   *
   * Handle TWL4030 Power initialization
   *
   * Copyright (C) 2008 Nokia Corporation
   * Copyright (C) 2006 Texas Instruments, Inc
   *
   * Written by 	Kalle Jokiniemi
   *		Peter De Schrijver <peter.de-schrijver@nokia.com>
   * Several fixes by Amit Kucheria <amit.kucheria@verdurent.com>
   *
   * This file is subject to the terms and conditions of the GNU General
   * Public License. See the file "COPYING" in the main directory of this
   * archive for more details.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  #include <linux/module.h>
  #include <linux/pm.h>
b07682b60   Santosh Shilimkar   mfd: Rename twl40...
29
  #include <linux/i2c/twl.h>
ebf0bd366   Amit Kucheria   mfd: Add support ...
30
31
32
33
34
35
36
  #include <linux/platform_device.h>
  
  #include <asm/mach-types.h>
  
  static u8 twl4030_start_script_address = 0x2b;
  
  #define PWR_P1_SW_EVENTS	0x10
26cc3ab98   Igor Grinberg   mfd: Add power of...
37
38
  #define PWR_DEVOFF		(1 << 0)
  #define SEQ_OFFSYNC		(1 << 0)
ebf0bd366   Amit Kucheria   mfd: Add support ...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  
  #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
  #define PHY_TO_OFF_PM_RECEIVER(p)	(p - 0x5b)
  
  /* resource - hfclk */
  #define R_HFCLKOUT_DEV_GRP 	PHY_TO_OFF_PM_RECEIVER(0xe6)
  
  /* PM events */
  #define R_P1_SW_EVENTS		PHY_TO_OFF_PM_MASTER(0x46)
  #define R_P2_SW_EVENTS		PHY_TO_OFF_PM_MASTER(0x47)
  #define R_P3_SW_EVENTS		PHY_TO_OFF_PM_MASTER(0x48)
  #define R_CFG_P1_TRANSITION	PHY_TO_OFF_PM_MASTER(0x36)
  #define R_CFG_P2_TRANSITION	PHY_TO_OFF_PM_MASTER(0x37)
  #define R_CFG_P3_TRANSITION	PHY_TO_OFF_PM_MASTER(0x38)
  
  #define LVL_WAKEUP	0x08
  
  #define ENABLE_WARMRESET (1<<4)
  
  #define END_OF_SCRIPT		0x3f
  
  #define R_SEQ_ADD_A2S		PHY_TO_OFF_PM_MASTER(0x55)
  #define R_SEQ_ADD_S2A12		PHY_TO_OFF_PM_MASTER(0x56)
  #define	R_SEQ_ADD_S2A3		PHY_TO_OFF_PM_MASTER(0x57)
  #define	R_SEQ_ADD_WARM		PHY_TO_OFF_PM_MASTER(0x58)
  #define R_MEMORY_ADDRESS	PHY_TO_OFF_PM_MASTER(0x59)
  #define R_MEMORY_DATA		PHY_TO_OFF_PM_MASTER(0x5a)
890463f0f   Amit Kucheria   mfd: Add comments...
66
67
68
69
70
71
  /* resource configuration registers
     <RESOURCE>_DEV_GRP   at address 'n+0'
     <RESOURCE>_TYPE      at address 'n+1'
     <RESOURCE>_REMAP     at address 'n+2'
     <RESOURCE>_DEDICATED at address 'n+3'
  */
e97d15469   Amit Kucheria   mfd: twl4030-powe...
72
  #define DEV_GRP_OFFSET		0
ebf0bd366   Amit Kucheria   mfd: Add support ...
73
  #define TYPE_OFFSET		1
b4ead61e5   Amit Kucheria   mfd: Add support ...
74
75
  #define REMAP_OFFSET		2
  #define DEDICATED_OFFSET	3
ebf0bd366   Amit Kucheria   mfd: Add support ...
76

e97d15469   Amit Kucheria   mfd: twl4030-powe...
77
  /* Bit positions in the registers */
890463f0f   Amit Kucheria   mfd: Add comments...
78
79
  
  /* <RESOURCE>_DEV_GRP */
e97d15469   Amit Kucheria   mfd: twl4030-powe...
80
81
  #define DEV_GRP_SHIFT		5
  #define DEV_GRP_MASK		(7 << DEV_GRP_SHIFT)
890463f0f   Amit Kucheria   mfd: Add comments...
82
83
  
  /* <RESOURCE>_TYPE */
ebf0bd366   Amit Kucheria   mfd: Add support ...
84
85
86
87
  #define TYPE_SHIFT		0
  #define TYPE_MASK		(7 << TYPE_SHIFT)
  #define TYPE2_SHIFT		3
  #define TYPE2_MASK		(3 << TYPE2_SHIFT)
b4ead61e5   Amit Kucheria   mfd: Add support ...
88
89
90
91
92
  /* <RESOURCE>_REMAP */
  #define SLEEP_STATE_SHIFT	0
  #define SLEEP_STATE_MASK	(0xf << SLEEP_STATE_SHIFT)
  #define OFF_STATE_SHIFT		4
  #define OFF_STATE_MASK		(0xf << OFF_STATE_SHIFT)
ebf0bd366   Amit Kucheria   mfd: Add support ...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  static u8 res_config_addrs[] = {
  	[RES_VAUX1]	= 0x17,
  	[RES_VAUX2]	= 0x1b,
  	[RES_VAUX3]	= 0x1f,
  	[RES_VAUX4]	= 0x23,
  	[RES_VMMC1]	= 0x27,
  	[RES_VMMC2]	= 0x2b,
  	[RES_VPLL1]	= 0x2f,
  	[RES_VPLL2]	= 0x33,
  	[RES_VSIM]	= 0x37,
  	[RES_VDAC]	= 0x3b,
  	[RES_VINTANA1]	= 0x3f,
  	[RES_VINTANA2]	= 0x43,
  	[RES_VINTDIG]	= 0x47,
  	[RES_VIO]	= 0x4b,
  	[RES_VDD1]	= 0x55,
  	[RES_VDD2]	= 0x63,
  	[RES_VUSB_1V5]	= 0x71,
  	[RES_VUSB_1V8]	= 0x74,
  	[RES_VUSB_3V1]	= 0x77,
  	[RES_VUSBCP]	= 0x7a,
  	[RES_REGEN]	= 0x7f,
  	[RES_NRES_PWRON] = 0x82,
  	[RES_CLKEN]	= 0x85,
  	[RES_SYSEN]	= 0x88,
  	[RES_HFCLKOUT]	= 0x8b,
  	[RES_32KCLKOUT]	= 0x8e,
  	[RES_RESET]	= 0x91,
d7ac829fa   Lesly A M   mfd: Modifying th...
121
  	[RES_MAIN_REF]	= 0x94,
ebf0bd366   Amit Kucheria   mfd: Add support ...
122
123
124
125
126
  };
  
  static int __init twl4030_write_script_byte(u8 address, u8 byte)
  {
  	int err;
fc7b92fca   Balaji T K   mfd: Rename all t...
127
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
ebf0bd366   Amit Kucheria   mfd: Add support ...
128
129
130
  				R_MEMORY_ADDRESS);
  	if (err)
  		goto out;
fc7b92fca   Balaji T K   mfd: Rename all t...
131
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte,
ebf0bd366   Amit Kucheria   mfd: Add support ...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  				R_MEMORY_DATA);
  out:
  	return err;
  }
  
  static int __init twl4030_write_script_ins(u8 address, u16 pmb_message,
  					   u8 delay, u8 next)
  {
  	int err;
  
  	address *= 4;
  	err = twl4030_write_script_byte(address++, pmb_message >> 8);
  	if (err)
  		goto out;
  	err = twl4030_write_script_byte(address++, pmb_message & 0xff);
  	if (err)
  		goto out;
  	err = twl4030_write_script_byte(address++, delay);
  	if (err)
  		goto out;
  	err = twl4030_write_script_byte(address++, next);
  out:
  	return err;
  }
  
  static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
  				       int len)
  {
  	int err;
  
  	for (; len; len--, address++, script++) {
  		if (len == 1) {
  			err = twl4030_write_script_ins(address,
  						script->pmb_message,
  						script->delay,
  						END_OF_SCRIPT);
  			if (err)
  				break;
  		} else {
  			err = twl4030_write_script_ins(address,
  						script->pmb_message,
  						script->delay,
  						address + 1);
  			if (err)
  				break;
  		}
  	}
  	return err;
  }
  
  static int __init twl4030_config_wakeup3_sequence(u8 address)
  {
  	int err;
  	u8 data;
  
  	/* Set SLEEP to ACTIVE SEQ address for P3 */
fc7b92fca   Balaji T K   mfd: Rename all t...
188
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
ebf0bd366   Amit Kucheria   mfd: Add support ...
189
190
191
192
193
  				R_SEQ_ADD_S2A3);
  	if (err)
  		goto out;
  
  	/* P3 LVL_WAKEUP should be on LEVEL */
fc7b92fca   Balaji T K   mfd: Rename all t...
194
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
195
196
197
198
  				R_P3_SW_EVENTS);
  	if (err)
  		goto out;
  	data |= LVL_WAKEUP;
fc7b92fca   Balaji T K   mfd: Rename all t...
199
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  				R_P3_SW_EVENTS);
  out:
  	if (err)
  		pr_err("TWL4030 wakeup sequence for P3 config error
  ");
  	return err;
  }
  
  static int __init twl4030_config_wakeup12_sequence(u8 address)
  {
  	int err = 0;
  	u8 data;
  
  	/* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
fc7b92fca   Balaji T K   mfd: Rename all t...
214
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
ebf0bd366   Amit Kucheria   mfd: Add support ...
215
216
217
218
219
  				R_SEQ_ADD_S2A12);
  	if (err)
  		goto out;
  
  	/* P1/P2 LVL_WAKEUP should be on LEVEL */
fc7b92fca   Balaji T K   mfd: Rename all t...
220
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
221
222
223
224
225
  				R_P1_SW_EVENTS);
  	if (err)
  		goto out;
  
  	data |= LVL_WAKEUP;
fc7b92fca   Balaji T K   mfd: Rename all t...
226
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
227
228
229
  				R_P1_SW_EVENTS);
  	if (err)
  		goto out;
fc7b92fca   Balaji T K   mfd: Rename all t...
230
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
231
232
233
234
235
  				R_P2_SW_EVENTS);
  	if (err)
  		goto out;
  
  	data |= LVL_WAKEUP;
fc7b92fca   Balaji T K   mfd: Rename all t...
236
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
237
238
239
240
241
242
  				R_P2_SW_EVENTS);
  	if (err)
  		goto out;
  
  	if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
  		/* Disabling AC charger effect on sleep-active transitions */
fc7b92fca   Balaji T K   mfd: Rename all t...
243
  		err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
244
245
246
247
  					R_CFG_P1_TRANSITION);
  		if (err)
  			goto out;
  		data &= ~(1<<1);
fc7b92fca   Balaji T K   mfd: Rename all t...
248
  		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data ,
ebf0bd366   Amit Kucheria   mfd: Add support ...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  					R_CFG_P1_TRANSITION);
  		if (err)
  			goto out;
  	}
  
  out:
  	if (err)
  		pr_err("TWL4030 wakeup sequence for P1 and P2" \
  			"config error
  ");
  	return err;
  }
  
  static int __init twl4030_config_sleep_sequence(u8 address)
  {
  	int err;
  
  	/* Set ACTIVE to SLEEP SEQ address in T2 memory*/
fc7b92fca   Balaji T K   mfd: Rename all t...
267
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
ebf0bd366   Amit Kucheria   mfd: Add support ...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  				R_SEQ_ADD_A2S);
  
  	if (err)
  		pr_err("TWL4030 sleep sequence config error
  ");
  
  	return err;
  }
  
  static int __init twl4030_config_warmreset_sequence(u8 address)
  {
  	int err;
  	u8 rd_data;
  
  	/* Set WARM RESET SEQ address for P1 */
fc7b92fca   Balaji T K   mfd: Rename all t...
283
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
ebf0bd366   Amit Kucheria   mfd: Add support ...
284
285
286
287
288
  				R_SEQ_ADD_WARM);
  	if (err)
  		goto out;
  
  	/* P1/P2/P3 enable WARMRESET */
fc7b92fca   Balaji T K   mfd: Rename all t...
289
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
290
291
292
293
294
  				R_P1_SW_EVENTS);
  	if (err)
  		goto out;
  
  	rd_data |= ENABLE_WARMRESET;
fc7b92fca   Balaji T K   mfd: Rename all t...
295
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
296
297
298
  				R_P1_SW_EVENTS);
  	if (err)
  		goto out;
fc7b92fca   Balaji T K   mfd: Rename all t...
299
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
300
301
302
303
304
  				R_P2_SW_EVENTS);
  	if (err)
  		goto out;
  
  	rd_data |= ENABLE_WARMRESET;
fc7b92fca   Balaji T K   mfd: Rename all t...
305
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
306
307
308
  				R_P2_SW_EVENTS);
  	if (err)
  		goto out;
fc7b92fca   Balaji T K   mfd: Rename all t...
309
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
310
311
312
313
314
  				R_P3_SW_EVENTS);
  	if (err)
  		goto out;
  
  	rd_data |= ENABLE_WARMRESET;
fc7b92fca   Balaji T K   mfd: Rename all t...
315
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
ebf0bd366   Amit Kucheria   mfd: Add support ...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  				R_P3_SW_EVENTS);
  out:
  	if (err)
  		pr_err("TWL4030 warmreset seq config error
  ");
  	return err;
  }
  
  static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
  {
  	int rconfig_addr;
  	int err;
  	u8 type;
  	u8 grp;
b4ead61e5   Amit Kucheria   mfd: Add support ...
330
  	u8 remap;
ebf0bd366   Amit Kucheria   mfd: Add support ...
331
332
333
334
335
336
337
338
339
340
341
  
  	if (rconfig->resource > TOTAL_RESOURCES) {
  		pr_err("TWL4030 Resource %d does not exist
  ",
  			rconfig->resource);
  		return -EINVAL;
  	}
  
  	rconfig_addr = res_config_addrs[rconfig->resource];
  
  	/* Set resource group */
fc7b92fca   Balaji T K   mfd: Rename all t...
342
343
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
  			      rconfig_addr + DEV_GRP_OFFSET);
ebf0bd366   Amit Kucheria   mfd: Add support ...
344
345
346
347
348
349
  	if (err) {
  		pr_err("TWL4030 Resource %d group could not be read
  ",
  			rconfig->resource);
  		return err;
  	}
56baa6679   Aaro Koskinen   mfd: fix undefine...
350
  	if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
e97d15469   Amit Kucheria   mfd: twl4030-powe...
351
352
  		grp &= ~DEV_GRP_MASK;
  		grp |= rconfig->devgroup << DEV_GRP_SHIFT;
fc7b92fca   Balaji T K   mfd: Rename all t...
353
354
  		err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
  				       grp, rconfig_addr + DEV_GRP_OFFSET);
ebf0bd366   Amit Kucheria   mfd: Add support ...
355
356
357
358
359
360
361
362
  		if (err < 0) {
  			pr_err("TWL4030 failed to program devgroup
  ");
  			return err;
  		}
  	}
  
  	/* Set resource types */
fc7b92fca   Balaji T K   mfd: Rename all t...
363
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
ebf0bd366   Amit Kucheria   mfd: Add support ...
364
365
366
367
368
369
370
  				rconfig_addr + TYPE_OFFSET);
  	if (err < 0) {
  		pr_err("TWL4030 Resource %d type could not be read
  ",
  			rconfig->resource);
  		return err;
  	}
56baa6679   Aaro Koskinen   mfd: fix undefine...
371
  	if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
ebf0bd366   Amit Kucheria   mfd: Add support ...
372
373
374
  		type &= ~TYPE_MASK;
  		type |= rconfig->type << TYPE_SHIFT;
  	}
56baa6679   Aaro Koskinen   mfd: fix undefine...
375
  	if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
ebf0bd366   Amit Kucheria   mfd: Add support ...
376
377
378
  		type &= ~TYPE2_MASK;
  		type |= rconfig->type2 << TYPE2_SHIFT;
  	}
fc7b92fca   Balaji T K   mfd: Rename all t...
379
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
ebf0bd366   Amit Kucheria   mfd: Add support ...
380
381
382
383
384
385
  				type, rconfig_addr + TYPE_OFFSET);
  	if (err < 0) {
  		pr_err("TWL4030 failed to program resource type
  ");
  		return err;
  	}
b4ead61e5   Amit Kucheria   mfd: Add support ...
386
  	/* Set remap states */
fc7b92fca   Balaji T K   mfd: Rename all t...
387
388
  	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
  			      rconfig_addr + REMAP_OFFSET);
b4ead61e5   Amit Kucheria   mfd: Add support ...
389
390
391
392
393
394
  	if (err < 0) {
  		pr_err("TWL4030 Resource %d remap could not be read
  ",
  			rconfig->resource);
  		return err;
  	}
53cf9a605   Amit Kucheria   mfd: Fix more und...
395
  	if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
b4ead61e5   Amit Kucheria   mfd: Add support ...
396
397
398
  		remap &= ~OFF_STATE_MASK;
  		remap |= rconfig->remap_off << OFF_STATE_SHIFT;
  	}
53cf9a605   Amit Kucheria   mfd: Fix more und...
399
  	if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
b4ead61e5   Amit Kucheria   mfd: Add support ...
400
  		remap &= ~SLEEP_STATE_MASK;
1ea933f4c   Mike Turquette   mfd: Program twl4...
401
  		remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
b4ead61e5   Amit Kucheria   mfd: Add support ...
402
  	}
fc7b92fca   Balaji T K   mfd: Rename all t...
403
404
405
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
  			       remap,
  			       rconfig_addr + REMAP_OFFSET);
b4ead61e5   Amit Kucheria   mfd: Add support ...
406
407
408
409
410
  	if (err < 0) {
  		pr_err("TWL4030 failed to program remap
  ");
  		return err;
  	}
ebf0bd366   Amit Kucheria   mfd: Add support ...
411
412
413
414
415
416
417
  	return 0;
  }
  
  static int __init load_twl4030_script(struct twl4030_script *tscript,
  	       u8 address)
  {
  	int err;
75a745653   Amit Kucheria   mfd: Print warnin...
418
  	static int order;
ebf0bd366   Amit Kucheria   mfd: Add support ...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  
  	/* Make sure the script isn't going beyond last valid address (0x3f) */
  	if ((address + tscript->size) > END_OF_SCRIPT) {
  		pr_err("TWL4030 scripts too big error
  ");
  		return -EINVAL;
  	}
  
  	err = twl4030_write_script(address, tscript->script, tscript->size);
  	if (err)
  		goto out;
  
  	if (tscript->flags & TWL4030_WRST_SCRIPT) {
  		err = twl4030_config_warmreset_sequence(address);
  		if (err)
  			goto out;
  	}
  	if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) {
  		err = twl4030_config_wakeup12_sequence(address);
  		if (err)
  			goto out;
75a745653   Amit Kucheria   mfd: Print warnin...
440
  		order = 1;
ebf0bd366   Amit Kucheria   mfd: Add support ...
441
442
443
444
445
446
  	}
  	if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) {
  		err = twl4030_config_wakeup3_sequence(address);
  		if (err)
  			goto out;
  	}
c62dd365e   Lesly A M   mfd: Fix for the ...
447
  	if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
1f968ff61   Lesly A M   mfd: Correct the ...
448
  		if (!order)
75a745653   Amit Kucheria   mfd: Print warnin...
449
450
451
452
  			pr_warning("TWL4030: Bad order of scripts (sleep "\
  					"script before wakeup) Leads to boot"\
  					"failure on some boards
  ");
ebf0bd366   Amit Kucheria   mfd: Add support ...
453
  		err = twl4030_config_sleep_sequence(address);
c62dd365e   Lesly A M   mfd: Fix for the ...
454
  	}
ebf0bd366   Amit Kucheria   mfd: Add support ...
455
456
457
  out:
  	return err;
  }
11a441ce8   Mike Turquette   mfd: Introduce re...
458
459
460
  int twl4030_remove_script(u8 flags)
  {
  	int err = 0;
71084406b   Felipe Balbi   mfd: Switch twl40...
461
462
463
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
  			TWL4030_PM_MASTER_KEY_CFG1,
  			TWL4030_PM_MASTER_PROTECT_KEY);
11a441ce8   Mike Turquette   mfd: Introduce re...
464
465
466
467
468
  	if (err) {
  		pr_err("twl4030: unable to unlock PROTECT_KEY
  ");
  		return err;
  	}
71084406b   Felipe Balbi   mfd: Switch twl40...
469
470
471
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
  			TWL4030_PM_MASTER_KEY_CFG2,
  			TWL4030_PM_MASTER_PROTECT_KEY);
11a441ce8   Mike Turquette   mfd: Introduce re...
472
473
474
475
476
477
478
479
480
481
482
483
484
  	if (err) {
  		pr_err("twl4030: unable to unlock PROTECT_KEY
  ");
  		return err;
  	}
  
  	if (flags & TWL4030_WRST_SCRIPT) {
  		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
  				R_SEQ_ADD_WARM);
  		if (err)
  			return err;
  	}
  	if (flags & TWL4030_WAKEUP12_SCRIPT) {
11a441ce8   Mike Turquette   mfd: Introduce re...
485
486
  		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
  				R_SEQ_ADD_S2A12);
eac78a210   Lesly A M   mfd: Check twl403...
487
  		if (err)
11a441ce8   Mike Turquette   mfd: Introduce re...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
  			return err;
  	}
  	if (flags & TWL4030_WAKEUP3_SCRIPT) {
  		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
  				R_SEQ_ADD_S2A3);
  		if (err)
  			return err;
  	}
  	if (flags & TWL4030_SLEEP_SCRIPT) {
  		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
  				R_SEQ_ADD_A2S);
  		if (err)
  			return err;
  	}
71084406b   Felipe Balbi   mfd: Switch twl40...
502
503
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
  			TWL4030_PM_MASTER_PROTECT_KEY);
11a441ce8   Mike Turquette   mfd: Introduce re...
504
505
506
507
508
509
  	if (err)
  		pr_err("TWL4030 Unable to relock registers
  ");
  
  	return err;
  }
26cc3ab98   Igor Grinberg   mfd: Add power of...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  /*
   * In master mode, start the power off sequence.
   * After a successful execution, TWL shuts down the power to the SoC
   * and all peripherals connected to it.
   */
  void twl4030_power_off(void)
  {
  	int err;
  
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF,
  			       TWL4030_PM_MASTER_P1_SW_EVENTS);
  	if (err)
  		pr_err("TWL4030 Unable to power off
  ");
  }
ebf0bd366   Amit Kucheria   mfd: Add support ...
525
526
527
528
529
  void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
  {
  	int err = 0;
  	int i;
  	struct twl4030_resconfig *resconfig;
26cc3ab98   Igor Grinberg   mfd: Add power of...
530
  	u8 val, address = twl4030_start_script_address;
ebf0bd366   Amit Kucheria   mfd: Add support ...
531

71084406b   Felipe Balbi   mfd: Switch twl40...
532
533
534
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
  			TWL4030_PM_MASTER_KEY_CFG1,
  			TWL4030_PM_MASTER_PROTECT_KEY);
ebf0bd366   Amit Kucheria   mfd: Add support ...
535
536
  	if (err)
  		goto unlock;
71084406b   Felipe Balbi   mfd: Switch twl40...
537
538
539
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
  			TWL4030_PM_MASTER_KEY_CFG2,
  			TWL4030_PM_MASTER_PROTECT_KEY);
ebf0bd366   Amit Kucheria   mfd: Add support ...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  	if (err)
  		goto unlock;
  
  	for (i = 0; i < twl4030_scripts->num; i++) {
  		err = load_twl4030_script(twl4030_scripts->scripts[i], address);
  		if (err)
  			goto load;
  		address += twl4030_scripts->scripts[i]->size;
  	}
  
  	resconfig = twl4030_scripts->resource_config;
  	if (resconfig) {
  		while (resconfig->resource) {
  			err = twl4030_configure_resource(resconfig);
  			if (err)
  				goto resource;
  			resconfig++;
  
  		}
  	}
26cc3ab98   Igor Grinberg   mfd: Add power of...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  	/* Board has to be wired properly to use this feature */
  	if (twl4030_scripts->use_poweroff && !pm_power_off) {
  		/* Default for SEQ_OFFSYNC is set, lets ensure this */
  		err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
  				      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
  		if (err) {
  			pr_warning("TWL4030 Unable to read registers
  ");
  
  		} else if (!(val & SEQ_OFFSYNC)) {
  			val |= SEQ_OFFSYNC;
  			err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
  					TWL4030_PM_MASTER_CFG_P123_TRANSITION);
  			if (err) {
  				pr_err("TWL4030 Unable to setup SEQ_OFFSYNC
  ");
  				goto relock;
  			}
  		}
  
  		pm_power_off = twl4030_power_off;
  	}
  
  relock:
71084406b   Felipe Balbi   mfd: Switch twl40...
584
585
  	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
  			TWL4030_PM_MASTER_PROTECT_KEY);
ebf0bd366   Amit Kucheria   mfd: Add support ...
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
  	if (err)
  		pr_err("TWL4030 Unable to relock registers
  ");
  	return;
  
  unlock:
  	if (err)
  		pr_err("TWL4030 Unable to unlock registers
  ");
  	return;
  load:
  	if (err)
  		pr_err("TWL4030 failed to load scripts
  ");
  	return;
  resource:
  	if (err)
  		pr_err("TWL4030 failed to configure resource
  ");
  	return;
  }