blob: 9e38e1a74508469a30eddf1191d90528981a5d0d [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +08002/*
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>
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +080011 */
12
Simon Glassed38aef2020-05-10 11:40:03 -060013#include <command.h>
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +080014#include <errno.h>
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +080015#include <asm/arch/pmic_bus.h>
16#include <axp_pmic.h>
17
18static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div)
19{
20 if (mvolt < min)
21 mvolt = min;
22 else if (mvolt > max)
23 mvolt = max;
24
25 return (mvolt - min) / div;
26}
27
28int axp_set_dcdc1(unsigned int mvolt)
29{
30 int ret;
31 u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100);
32
33 if (mvolt == 0)
34 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
35 AXP809_OUTPUT_CTRL1_DCDC1_EN);
36
37 ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg);
38 if (ret)
39 return ret;
40
41 ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
42 AXP809_OUTPUT_CTRL2_DC1SW_EN);
43 if (ret)
44 return ret;
45
46 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
47 AXP809_OUTPUT_CTRL1_DCDC1_EN);
48}
49
50int axp_set_dcdc2(unsigned int mvolt)
51{
52 int ret;
53 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
54
55 if (mvolt == 0)
56 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
57 AXP809_OUTPUT_CTRL1_DCDC2_EN);
58
59 ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg);
60 if (ret)
61 return ret;
62
63 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
64 AXP809_OUTPUT_CTRL1_DCDC2_EN);
65}
66
67int axp_set_dcdc3(unsigned int mvolt)
68{
69 int ret;
70 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20);
71
72 if (mvolt == 0)
73 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
74 AXP809_OUTPUT_CTRL1_DCDC3_EN);
75
76 ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg);
77 if (ret)
78 return ret;
79
80 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
81 AXP809_OUTPUT_CTRL1_DCDC3_EN);
82}
83
84int axp_set_dcdc4(unsigned int mvolt)
85{
86 int ret;
87 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
88
89 if (mvolt >= 1540)
90 cfg = 0x30 + axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100);
91
92 if (mvolt == 0)
93 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
94 AXP809_OUTPUT_CTRL1_DCDC4_EN);
95
96 ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
97 if (ret)
98 return ret;
99
100 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
101 AXP809_OUTPUT_CTRL1_DCDC4_EN);
102}
103
104int axp_set_dcdc5(unsigned int mvolt)
105{
106 int ret;
107 u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50);
108
109 if (mvolt == 0)
110 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
111 AXP809_OUTPUT_CTRL1_DCDC5_EN);
112
113 ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
114 if (ret)
115 return ret;
116
117 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
118 AXP809_OUTPUT_CTRL1_DCDC5_EN);
119}
120
121int axp_set_aldo(int aldo_num, unsigned int mvolt)
122{
123 int ret;
124 u8 cfg;
125
126 if (aldo_num < 1 || aldo_num > 3)
127 return -EINVAL;
128
129 if (mvolt == 0 && aldo_num == 3)
130 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
131 AXP809_OUTPUT_CTRL2_ALDO3_EN);
132 if (mvolt == 0)
133 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
134 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
135
136 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
137 ret = pmic_bus_write(AXP809_ALDO1_CTRL + (aldo_num - 1), cfg);
138 if (ret)
139 return ret;
140
141 if (aldo_num == 3)
142 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
143 AXP809_OUTPUT_CTRL2_ALDO3_EN);
Rask Ingemann Lambertsen51ad3732017-01-18 21:53:40 +0100144 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +0800145 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
146}
147
148/* TODO: re-work other AXP drivers to consolidate ALDO functions. */
149int axp_set_aldo1(unsigned int mvolt)
150{
151 return axp_set_aldo(1, mvolt);
152}
153
154int axp_set_aldo2(unsigned int mvolt)
155{
156 return axp_set_aldo(2, mvolt);
157}
158
159int axp_set_aldo3(unsigned int mvolt)
160{
161 return axp_set_aldo(3, mvolt);
162}
163
164int axp_set_dldo(int dldo_num, unsigned int mvolt)
165{
166 u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
167 int ret;
168
169 if (dldo_num < 1 || dldo_num > 2)
170 return -EINVAL;
171
172 if (mvolt == 0)
173 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
174 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
175
176 if (dldo_num == 1 && mvolt > 3300)
177 cfg += 1 + axp809_mvolt_to_cfg(mvolt, 3400, 4200, 200);
178 ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg);
179 if (ret)
180 return ret;
181
182 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
183 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
184}
185
186int axp_set_eldo(int eldo_num, unsigned int mvolt)
187{
188 int ret;
189 u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
190
191 if (eldo_num < 1 || eldo_num > 3)
192 return -EINVAL;
193
194 if (mvolt == 0)
195 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
196 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
197
198 ret = pmic_bus_write(AXP809_ELDO1_CTRL + (eldo_num - 1), cfg);
199 if (ret)
200 return ret;
201
202 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
203 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
204}
205
206int axp_set_sw(bool on)
207{
208 if (on)
209 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
210 AXP809_OUTPUT_CTRL2_SWOUT_EN);
211
212 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
213 AXP809_OUTPUT_CTRL2_SWOUT_EN);
214}
215
216int axp_init(void)
217{
Masahiro Yamada30fe3572016-09-06 22:17:39 +0900218 return pmic_bus_init();
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +0800219}
220
Samuel Holland41a545f2021-08-22 18:18:05 -0500221#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
Simon Glassed38aef2020-05-10 11:40:03 -0600222int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Chen-Yu Tsaif1e66e72016-05-02 10:28:15 +0800223{
224 pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF);
225
226 /* infinite loop during shutdown */
227 while (1) {}
228
229 /* not reached */
230 return 0;
231}
Samuel Holland41a545f2021-08-22 18:18:05 -0500232#endif