Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / mfd / twl4030-power.c
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 twl4030_write_script_byte(u8 address, u8 byte)
128 {
129         int err;
130
131         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS);
132         if (err)
133                 goto out;
134         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA);
135 out:
136         return err;
137 }
138
139 static int twl4030_write_script_ins(u8 address, u16 pmb_message,
140                                            u8 delay, u8 next)
141 {
142         int err;
143
144         address *= 4;
145         err = twl4030_write_script_byte(address++, pmb_message >> 8);
146         if (err)
147                 goto out;
148         err = twl4030_write_script_byte(address++, pmb_message & 0xff);
149         if (err)
150                 goto out;
151         err = twl4030_write_script_byte(address++, delay);
152         if (err)
153                 goto out;
154         err = twl4030_write_script_byte(address++, next);
155 out:
156         return err;
157 }
158
159 static int twl4030_write_script(u8 address, struct twl4030_ins *script,
160                                        int len)
161 {
162         int err = -EINVAL;
163
164         for (; len; len--, address++, script++) {
165                 if (len == 1) {
166                         err = twl4030_write_script_ins(address,
167                                                 script->pmb_message,
168                                                 script->delay,
169                                                 END_OF_SCRIPT);
170                         if (err)
171                                 break;
172                 } else {
173                         err = twl4030_write_script_ins(address,
174                                                 script->pmb_message,
175                                                 script->delay,
176                                                 address + 1);
177                         if (err)
178                                 break;
179                 }
180         }
181         return err;
182 }
183
184 static int twl4030_config_wakeup3_sequence(u8 address)
185 {
186         int err;
187         u8 data;
188
189         /* Set SLEEP to ACTIVE SEQ address for P3 */
190         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3);
191         if (err)
192                 goto out;
193
194         /* P3 LVL_WAKEUP should be on LEVEL */
195         err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS);
196         if (err)
197                 goto out;
198         data |= LVL_WAKEUP;
199         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS);
200 out:
201         if (err)
202                 pr_err("TWL4030 wakeup sequence for P3 config error\n");
203         return err;
204 }
205
206 static int twl4030_config_wakeup12_sequence(u8 address)
207 {
208         int err = 0;
209         u8 data;
210
211         /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
212         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12);
213         if (err)
214                 goto out;
215
216         /* P1/P2 LVL_WAKEUP should be on LEVEL */
217         err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS);
218         if (err)
219                 goto out;
220
221         data |= LVL_WAKEUP;
222         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS);
223         if (err)
224                 goto out;
225
226         err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS);
227         if (err)
228                 goto out;
229
230         data |= LVL_WAKEUP;
231         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS);
232         if (err)
233                 goto out;
234
235         if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
236                 /* Disabling AC charger effect on sleep-active transitions */
237                 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data,
238                                       R_CFG_P1_TRANSITION);
239                 if (err)
240                         goto out;
241                 data &= ~(1<<1);
242                 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data,
243                                        R_CFG_P1_TRANSITION);
244                 if (err)
245                         goto out;
246         }
247
248 out:
249         if (err)
250                 pr_err("TWL4030 wakeup sequence for P1 and P2" \
251                         "config error\n");
252         return err;
253 }
254
255 static int twl4030_config_sleep_sequence(u8 address)
256 {
257         int err;
258
259         /* Set ACTIVE to SLEEP SEQ address in T2 memory*/
260         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S);
261
262         if (err)
263                 pr_err("TWL4030 sleep sequence config error\n");
264
265         return err;
266 }
267
268 static int twl4030_config_warmreset_sequence(u8 address)
269 {
270         int err;
271         u8 rd_data;
272
273         /* Set WARM RESET SEQ address for P1 */
274         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM);
275         if (err)
276                 goto out;
277
278         /* P1/P2/P3 enable WARMRESET */
279         err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS);
280         if (err)
281                 goto out;
282
283         rd_data |= ENABLE_WARMRESET;
284         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS);
285         if (err)
286                 goto out;
287
288         err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS);
289         if (err)
290                 goto out;
291
292         rd_data |= ENABLE_WARMRESET;
293         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS);
294         if (err)
295                 goto out;
296
297         err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS);
298         if (err)
299                 goto out;
300
301         rd_data |= ENABLE_WARMRESET;
302         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS);
303 out:
304         if (err)
305                 pr_err("TWL4030 warmreset seq config error\n");
306         return err;
307 }
308
309 static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
310 {
311         int rconfig_addr;
312         int err;
313         u8 type;
314         u8 grp;
315         u8 remap;
316
317         if (rconfig->resource > TOTAL_RESOURCES) {
318                 pr_err("TWL4030 Resource %d does not exist\n",
319                         rconfig->resource);
320                 return -EINVAL;
321         }
322
323         rconfig_addr = res_config_addrs[rconfig->resource];
324
325         /* Set resource group */
326         err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp,
327                               rconfig_addr + DEV_GRP_OFFSET);
328         if (err) {
329                 pr_err("TWL4030 Resource %d group could not be read\n",
330                         rconfig->resource);
331                 return err;
332         }
333
334         if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
335                 grp &= ~DEV_GRP_MASK;
336                 grp |= rconfig->devgroup << DEV_GRP_SHIFT;
337                 err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
338                                        grp, rconfig_addr + DEV_GRP_OFFSET);
339                 if (err < 0) {
340                         pr_err("TWL4030 failed to program devgroup\n");
341                         return err;
342                 }
343         }
344
345         /* Set resource types */
346         err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type,
347                                 rconfig_addr + TYPE_OFFSET);
348         if (err < 0) {
349                 pr_err("TWL4030 Resource %d type could not be read\n",
350                         rconfig->resource);
351                 return err;
352         }
353
354         if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
355                 type &= ~TYPE_MASK;
356                 type |= rconfig->type << TYPE_SHIFT;
357         }
358
359         if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
360                 type &= ~TYPE2_MASK;
361                 type |= rconfig->type2 << TYPE2_SHIFT;
362         }
363
364         err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
365                                 type, rconfig_addr + TYPE_OFFSET);
366         if (err < 0) {
367                 pr_err("TWL4030 failed to program resource type\n");
368                 return err;
369         }
370
371         /* Set remap states */
372         err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap,
373                               rconfig_addr + REMAP_OFFSET);
374         if (err < 0) {
375                 pr_err("TWL4030 Resource %d remap could not be read\n",
376                         rconfig->resource);
377                 return err;
378         }
379
380         if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
381                 remap &= ~OFF_STATE_MASK;
382                 remap |= rconfig->remap_off << OFF_STATE_SHIFT;
383         }
384
385         if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
386                 remap &= ~SLEEP_STATE_MASK;
387                 remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
388         }
389
390         err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
391                                remap,
392                                rconfig_addr + REMAP_OFFSET);
393         if (err < 0) {
394                 pr_err("TWL4030 failed to program remap\n");
395                 return err;
396         }
397
398         return 0;
399 }
400
401 static int load_twl4030_script(struct twl4030_script *tscript,
402                u8 address)
403 {
404         int err;
405         static int order;
406
407         /* Make sure the script isn't going beyond last valid address (0x3f) */
408         if ((address + tscript->size) > END_OF_SCRIPT) {
409                 pr_err("TWL4030 scripts too big error\n");
410                 return -EINVAL;
411         }
412
413         err = twl4030_write_script(address, tscript->script, tscript->size);
414         if (err)
415                 goto out;
416
417         if (tscript->flags & TWL4030_WRST_SCRIPT) {
418                 err = twl4030_config_warmreset_sequence(address);
419                 if (err)
420                         goto out;
421         }
422         if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) {
423                 err = twl4030_config_wakeup12_sequence(address);
424                 if (err)
425                         goto out;
426                 order = 1;
427         }
428         if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) {
429                 err = twl4030_config_wakeup3_sequence(address);
430                 if (err)
431                         goto out;
432         }
433         if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
434                 if (!order)
435                         pr_warning("TWL4030: Bad order of scripts (sleep "\
436                                         "script before wakeup) Leads to boot"\
437                                         "failure on some boards\n");
438                 err = twl4030_config_sleep_sequence(address);
439         }
440 out:
441         return err;
442 }
443
444 int twl4030_remove_script(u8 flags)
445 {
446         int err = 0;
447
448         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
449                                TWL4030_PM_MASTER_PROTECT_KEY);
450         if (err) {
451                 pr_err("twl4030: unable to unlock PROTECT_KEY\n");
452                 return err;
453         }
454
455         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
456                                TWL4030_PM_MASTER_PROTECT_KEY);
457         if (err) {
458                 pr_err("twl4030: unable to unlock PROTECT_KEY\n");
459                 return err;
460         }
461
462         if (flags & TWL4030_WRST_SCRIPT) {
463                 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
464                                        R_SEQ_ADD_WARM);
465                 if (err)
466                         return err;
467         }
468         if (flags & TWL4030_WAKEUP12_SCRIPT) {
469                 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
470                                        R_SEQ_ADD_S2A12);
471                 if (err)
472                         return err;
473         }
474         if (flags & TWL4030_WAKEUP3_SCRIPT) {
475                 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
476                                        R_SEQ_ADD_S2A3);
477                 if (err)
478                         return err;
479         }
480         if (flags & TWL4030_SLEEP_SCRIPT) {
481                 err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
482                                        R_SEQ_ADD_A2S);
483                 if (err)
484                         return err;
485         }
486
487         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
488                                TWL4030_PM_MASTER_PROTECT_KEY);
489         if (err)
490                 pr_err("TWL4030 Unable to relock registers\n");
491
492         return err;
493 }
494
495 /*
496  * In master mode, start the power off sequence.
497  * After a successful execution, TWL shuts down the power to the SoC
498  * and all peripherals connected to it.
499  */
500 void twl4030_power_off(void)
501 {
502         int err;
503
504         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
505                                TWL4030_PM_MASTER_P1_SW_EVENTS);
506         if (err)
507                 pr_err("TWL4030 Unable to power off\n");
508 }
509
510 void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
511 {
512         int err = 0;
513         int i;
514         struct twl4030_resconfig *resconfig;
515         u8 val, address = twl4030_start_script_address;
516
517         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
518                                TWL4030_PM_MASTER_PROTECT_KEY);
519         if (err)
520                 goto unlock;
521
522         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
523                                TWL4030_PM_MASTER_PROTECT_KEY);
524         if (err)
525                 goto unlock;
526
527         for (i = 0; i < twl4030_scripts->num; i++) {
528                 err = load_twl4030_script(twl4030_scripts->scripts[i], address);
529                 if (err)
530                         goto load;
531                 address += twl4030_scripts->scripts[i]->size;
532         }
533
534         resconfig = twl4030_scripts->resource_config;
535         if (resconfig) {
536                 while (resconfig->resource) {
537                         err = twl4030_configure_resource(resconfig);
538                         if (err)
539                                 goto resource;
540                         resconfig++;
541
542                 }
543         }
544
545         /* Board has to be wired properly to use this feature */
546         if (twl4030_scripts->use_poweroff && !pm_power_off) {
547                 /* Default for SEQ_OFFSYNC is set, lets ensure this */
548                 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
549                                       TWL4030_PM_MASTER_CFG_P123_TRANSITION);
550                 if (err) {
551                         pr_warning("TWL4030 Unable to read registers\n");
552
553                 } else if (!(val & SEQ_OFFSYNC)) {
554                         val |= SEQ_OFFSYNC;
555                         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
556                                         TWL4030_PM_MASTER_CFG_P123_TRANSITION);
557                         if (err) {
558                                 pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
559                                 goto relock;
560                         }
561                 }
562
563                 pm_power_off = twl4030_power_off;
564         }
565
566 relock:
567         err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
568                                TWL4030_PM_MASTER_PROTECT_KEY);
569         if (err)
570                 pr_err("TWL4030 Unable to relock registers\n");
571         return;
572
573 unlock:
574         if (err)
575                 pr_err("TWL4030 Unable to unlock registers\n");
576         return;
577 load:
578         if (err)
579                 pr_err("TWL4030 failed to load scripts\n");
580         return;
581 resource:
582         if (err)
583                 pr_err("TWL4030 failed to configure resource\n");
584         return;
585 }