colibri_imx6: fix video stdout in default environment
[oweals/u-boot.git] / drivers / power / axp809.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * AXP809 driver based on AXP221 driver
4  *
5  *
6  * (C) Copyright 2016 Chen-Yu Tsai <wens@csie.org>
7  *
8  * Based on axp221.c
9  * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
10  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
11  */
12
13 #include <common.h>
14 #include <command.h>
15 #include <errno.h>
16 #include <asm/arch/gpio.h>
17 #include <asm/arch/pmic_bus.h>
18 #include <axp_pmic.h>
19
20 static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div)
21 {
22         if (mvolt < min)
23                 mvolt = min;
24         else if (mvolt > max)
25                 mvolt = max;
26
27         return (mvolt - min) / div;
28 }
29
30 int axp_set_dcdc1(unsigned int mvolt)
31 {
32         int ret;
33         u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100);
34
35         if (mvolt == 0)
36                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
37                                         AXP809_OUTPUT_CTRL1_DCDC1_EN);
38
39         ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg);
40         if (ret)
41                 return ret;
42
43         ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
44                                AXP809_OUTPUT_CTRL2_DC1SW_EN);
45         if (ret)
46                 return ret;
47
48         return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
49                                 AXP809_OUTPUT_CTRL1_DCDC1_EN);
50 }
51
52 int axp_set_dcdc2(unsigned int mvolt)
53 {
54         int ret;
55         u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
56
57         if (mvolt == 0)
58                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
59                                         AXP809_OUTPUT_CTRL1_DCDC2_EN);
60
61         ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg);
62         if (ret)
63                 return ret;
64
65         return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
66                                 AXP809_OUTPUT_CTRL1_DCDC2_EN);
67 }
68
69 int axp_set_dcdc3(unsigned int mvolt)
70 {
71         int ret;
72         u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20);
73
74         if (mvolt == 0)
75                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
76                                         AXP809_OUTPUT_CTRL1_DCDC3_EN);
77
78         ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg);
79         if (ret)
80                 return ret;
81
82         return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
83                                 AXP809_OUTPUT_CTRL1_DCDC3_EN);
84 }
85
86 int axp_set_dcdc4(unsigned int mvolt)
87 {
88         int ret;
89         u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
90
91         if (mvolt >= 1540)
92                 cfg = 0x30 + axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100);
93
94         if (mvolt == 0)
95                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
96                                         AXP809_OUTPUT_CTRL1_DCDC4_EN);
97
98         ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
99         if (ret)
100                 return ret;
101
102         return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
103                                 AXP809_OUTPUT_CTRL1_DCDC4_EN);
104 }
105
106 int axp_set_dcdc5(unsigned int mvolt)
107 {
108         int ret;
109         u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50);
110
111         if (mvolt == 0)
112                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
113                                         AXP809_OUTPUT_CTRL1_DCDC5_EN);
114
115         ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
116         if (ret)
117                 return ret;
118
119         return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
120                                 AXP809_OUTPUT_CTRL1_DCDC5_EN);
121 }
122
123 int axp_set_aldo(int aldo_num, unsigned int mvolt)
124 {
125         int ret;
126         u8 cfg;
127
128         if (aldo_num < 1 || aldo_num > 3)
129                 return -EINVAL;
130
131         if (mvolt == 0 && aldo_num == 3)
132                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
133                                         AXP809_OUTPUT_CTRL2_ALDO3_EN);
134         if (mvolt == 0)
135                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
136                                 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
137
138         cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
139         ret = pmic_bus_write(AXP809_ALDO1_CTRL + (aldo_num - 1), cfg);
140         if (ret)
141                 return ret;
142
143         if (aldo_num == 3)
144                 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
145                                         AXP809_OUTPUT_CTRL2_ALDO3_EN);
146         return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
147                                 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
148 }
149
150 /* TODO: re-work other AXP drivers to consolidate ALDO functions. */
151 int axp_set_aldo1(unsigned int mvolt)
152 {
153         return axp_set_aldo(1, mvolt);
154 }
155
156 int axp_set_aldo2(unsigned int mvolt)
157 {
158         return axp_set_aldo(2, mvolt);
159 }
160
161 int axp_set_aldo3(unsigned int mvolt)
162 {
163         return axp_set_aldo(3, mvolt);
164 }
165
166 int axp_set_dldo(int dldo_num, unsigned int mvolt)
167 {
168         u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
169         int ret;
170
171         if (dldo_num < 1 || dldo_num > 2)
172                 return -EINVAL;
173
174         if (mvolt == 0)
175                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
176                                 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
177
178         if (dldo_num == 1 && mvolt > 3300)
179                 cfg += 1 + axp809_mvolt_to_cfg(mvolt, 3400, 4200, 200);
180         ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg);
181         if (ret)
182                 return ret;
183
184         return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
185                                 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
186 }
187
188 int axp_set_eldo(int eldo_num, unsigned int mvolt)
189 {
190         int ret;
191         u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
192
193         if (eldo_num < 1 || eldo_num > 3)
194                 return -EINVAL;
195
196         if (mvolt == 0)
197                 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
198                                 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
199
200         ret = pmic_bus_write(AXP809_ELDO1_CTRL + (eldo_num - 1), cfg);
201         if (ret)
202                 return ret;
203
204         return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
205                                 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
206 }
207
208 int axp_set_sw(bool on)
209 {
210         if (on)
211                 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
212                                         AXP809_OUTPUT_CTRL2_SWOUT_EN);
213
214         return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
215                                 AXP809_OUTPUT_CTRL2_SWOUT_EN);
216 }
217
218 int axp_init(void)
219 {
220         return pmic_bus_init();
221 }
222
223 int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
224 {
225         pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF);
226
227         /* infinite loop during shutdown */
228         while (1) {}
229
230         /* not reached */
231         return 0;
232 }