colibri_imx6: fix video stdout in default environment
[oweals/u-boot.git] / drivers / power / twl4030.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2009 Wind River Systems, Inc.
4  * Tom Rix <Tom.Rix at windriver.com>
5  *
6  * twl4030_power_reset_init is derived from code on omapzoom,
7  * git://git.omapzoom.com/repo/u-boot.git
8  *
9  * Copyright (C) 2007-2009 Texas Instruments, Inc.
10  *
11  * twl4030_power_init is from cpu/omap3/common.c, power_init_r
12  *
13  * (C) Copyright 2004-2008
14  * Texas Instruments, <www.ti.com>
15  *
16  * Author :
17  *      Sunil Kumar <sunilsaini05 at gmail.com>
18  *      Shashi Ranjan <shashiranjanmca05 at gmail.com>
19  *
20  * Derived from Beagle Board and 3430 SDP code by
21  *      Richard Woodruff <r-woodruff2 at ti.com>
22  *      Syed Mohammed Khasim <khasim at ti.com>
23  */
24
25 #include <command.h>
26 #include <twl4030.h>
27 #include <linux/delay.h>
28
29 /*
30  * Power Reset
31  */
32 void twl4030_power_reset_init(void)
33 {
34         u8 val = 0;
35         if (twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
36                                 TWL4030_PM_MASTER_P1_SW_EVENTS, &val)) {
37                 printf("Error:TWL4030: failed to read the power register\n");
38                 printf("Could not initialize hardware reset\n");
39         } else {
40                 val |= TWL4030_PM_MASTER_SW_EVENTS_STOPON_PWRON;
41                 if (twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
42                                          TWL4030_PM_MASTER_P1_SW_EVENTS, val)) {
43                         printf("Error:TWL4030: failed to write the power register\n");
44                         printf("Could not initialize hardware reset\n");
45                 }
46         }
47 }
48
49 /*
50  * Power off
51  */
52 void twl4030_power_off(void)
53 {
54         u8 data;
55
56         /* PM master unlock (CFG and TST keys) */
57
58         data = 0xCE;
59         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
60                              TWL4030_PM_MASTER_PROTECT_KEY, data);
61         data = 0xEC;
62         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
63                              TWL4030_PM_MASTER_PROTECT_KEY, data);
64
65         /* VBAT start disable */
66
67         twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
68                             TWL4030_PM_MASTER_CFG_P1_TRANSITION, &data);
69         data &= ~TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT;
70         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
71                              TWL4030_PM_MASTER_CFG_P1_TRANSITION, data);
72
73         twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
74                             TWL4030_PM_MASTER_CFG_P2_TRANSITION, &data);
75         data &= ~TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT;
76         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
77                              TWL4030_PM_MASTER_CFG_P2_TRANSITION, data);
78
79         twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
80                             TWL4030_PM_MASTER_CFG_P3_TRANSITION, &data);
81         data &= ~TWL4030_PM_MASTER_CFG_TRANSITION_STARTON_VBAT;
82         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
83                              TWL4030_PM_MASTER_CFG_P3_TRANSITION, data);
84
85         /* High jitter for PWRANA2 */
86
87         twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
88                             TWL4030_PM_MASTER_CFG_PWRANA2, &data);
89         data &= ~(TWL4030_PM_MASTER_CFG_PWRANA2_LOJIT0_LOWV |
90                   TWL4030_PM_MASTER_CFG_PWRANA2_LOJIT1_LOWV);
91         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
92                              TWL4030_PM_MASTER_CFG_PWRANA2, data);
93
94         /* PM master lock */
95
96         data = 0xFF;
97         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
98                              TWL4030_PM_MASTER_PROTECT_KEY, data);
99
100         /* Power off */
101
102         twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER,
103                             TWL4030_PM_MASTER_P1_SW_EVENTS, &data);
104         data |= TWL4030_PM_MASTER_SW_EVENTS_DEVOFF;
105         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
106                              TWL4030_PM_MASTER_P1_SW_EVENTS, data);
107 }
108
109 /*
110  * Set Device Group and Voltage
111  */
112 void twl4030_pmrecv_vsel_cfg(u8 vsel_reg, u8 vsel_val,
113                                 u8 dev_grp, u8 dev_grp_sel)
114 {
115         int ret;
116
117         /* Select the Voltage */
118         ret = twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, vsel_reg,
119                                    vsel_val);
120         if (ret != 0) {
121                 printf("Could not write vsel to reg %02x (%d)\n",
122                         vsel_reg, ret);
123                 return;
124         }
125
126         /* Select the Device Group (enable the supply if dev_grp_sel != 0) */
127         ret = twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, dev_grp,
128                                    dev_grp_sel);
129         if (ret != 0)
130                 printf("Could not write grp_sel to reg %02x (%d)\n",
131                         dev_grp, ret);
132 }
133
134 void twl4030_power_init(void)
135 {
136         /* set VAUX3 to 2.8V */
137         twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VAUX3_DEDICATED,
138                                 TWL4030_PM_RECEIVER_VAUX3_VSEL_28,
139                                 TWL4030_PM_RECEIVER_VAUX3_DEV_GRP,
140                                 TWL4030_PM_RECEIVER_DEV_GRP_P1);
141
142         /* set VPLL2 to 1.8V */
143         twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VPLL2_DEDICATED,
144                                 TWL4030_PM_RECEIVER_VPLL2_VSEL_18,
145                                 TWL4030_PM_RECEIVER_VPLL2_DEV_GRP,
146                                 TWL4030_PM_RECEIVER_DEV_GRP_ALL);
147
148         /* set VDAC to 1.8V */
149         twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VDAC_DEDICATED,
150                                 TWL4030_PM_RECEIVER_VDAC_VSEL_18,
151                                 TWL4030_PM_RECEIVER_VDAC_DEV_GRP,
152                                 TWL4030_PM_RECEIVER_DEV_GRP_P1);
153 }
154
155 void twl4030_power_mmc_init(int dev_index)
156 {
157         if (dev_index == 0) {
158                 /* Set VMMC1 to 3.15 Volts */
159                 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC1_DEDICATED,
160                                         TWL4030_PM_RECEIVER_VMMC1_VSEL_32,
161                                         TWL4030_PM_RECEIVER_VMMC1_DEV_GRP,
162                                         TWL4030_PM_RECEIVER_DEV_GRP_P1);
163
164                 mdelay(100);    /* ramp-up delay from Linux code */
165         } else if (dev_index == 1) {
166                 /* Set VMMC2 to 3.15 Volts */
167                 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC2_DEDICATED,
168                                         TWL4030_PM_RECEIVER_VMMC2_VSEL_32,
169                                         TWL4030_PM_RECEIVER_VMMC2_DEV_GRP,
170                                         TWL4030_PM_RECEIVER_DEV_GRP_P1);
171
172                 mdelay(100);    /* ramp-up delay from Linux code */
173         }
174 }
175
176 #ifdef CONFIG_CMD_POWEROFF
177 int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
178 {
179         twl4030_power_off();
180
181         return 0;
182 }
183 #endif
184
185 #ifdef CONFIG_DM_I2C
186 int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
187 {
188         struct udevice *dev;
189         int ret;
190
191         ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
192         if (ret) {
193                 pr_err("unable to get I2C bus. ret %d\n", ret);
194                 return ret;
195         }
196         ret = dm_i2c_reg_write(dev, reg, val);
197         if (ret) {
198                 pr_err("writing to twl4030 failed. ret %d\n", ret);
199                 return ret;
200         }
201         return 0;
202 }
203
204 int twl4030_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp)
205 {
206         struct udevice *dev;
207         int ret;
208
209         ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
210         if (ret) {
211                 pr_err("unable to get I2C bus. ret %d\n", ret);
212                 return ret;
213         }
214         ret = dm_i2c_reg_read(dev, reg);
215         if (ret < 0) {
216                 pr_err("reading from twl4030 failed. ret %d\n", ret);
217                 return ret;
218         }
219         *valp = (u8)ret;
220         return 0;
221 }
222 #endif