blob: c22ca03f46948c9dba4e233ada1199d3860e9d8c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Oliver Schinagld3a558d2013-07-26 12:56:58 +02002/*
Hans de Goede1dd334b2014-11-29 23:54:25 +01003 * AXP221 and AXP223 driver
4 *
5 * IMPORTANT when making changes to this file check that the registers
6 * used are the same for the axp221 and axp223.
7 *
8 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
Oliver Schinagld3a558d2013-07-26 12:56:58 +02009 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
Oliver Schinagld3a558d2013-07-26 12:56:58 +020010 */
11
Hans de Goede6391f0e2015-12-20 16:14:31 +010012#include <command.h>
Oliver Schinagld3a558d2013-07-26 12:56:58 +020013#include <errno.h>
Hans de Goedebb930c32015-04-25 14:07:37 +020014#include <asm/arch/pmic_bus.h>
Hans de Goeded9ee84b2015-10-03 15:18:33 +020015#include <axp_pmic.h>
Oliver Schinagld3a558d2013-07-26 12:56:58 +020016
17static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
18{
19 if (mvolt < min)
20 mvolt = min;
21 else if (mvolt > max)
22 mvolt = max;
23
24 return (mvolt - min) / div;
25}
26
Hans de Goeded9ee84b2015-10-03 15:18:33 +020027int axp_set_dcdc1(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +020028{
29 int ret;
30 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
31
Hans de Goedebe4929c2014-12-13 14:02:38 +010032 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +020033 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
34 AXP221_OUTPUT_CTRL1_DCDC1_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +010035
Hans de Goede1dd334b2014-11-29 23:54:25 +010036 ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020037 if (ret)
38 return ret;
39
Hans de Goedebb930c32015-04-25 14:07:37 +020040 ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
41 AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +010042 if (ret)
43 return ret;
44
Hans de Goedebb930c32015-04-25 14:07:37 +020045 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
46 AXP221_OUTPUT_CTRL1_DCDC1_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020047}
48
Hans de Goeded9ee84b2015-10-03 15:18:33 +020049int axp_set_dcdc2(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +020050{
Hans de Goedebe4929c2014-12-13 14:02:38 +010051 int ret;
Oliver Schinagld3a558d2013-07-26 12:56:58 +020052 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
53
Hans de Goedebe4929c2014-12-13 14:02:38 +010054 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +020055 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
56 AXP221_OUTPUT_CTRL1_DCDC2_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +010057
58 ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
59 if (ret)
60 return ret;
61
Hans de Goedebb930c32015-04-25 14:07:37 +020062 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
63 AXP221_OUTPUT_CTRL1_DCDC2_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020064}
65
Hans de Goeded9ee84b2015-10-03 15:18:33 +020066int axp_set_dcdc3(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +020067{
Hans de Goedebe4929c2014-12-13 14:02:38 +010068 int ret;
Oliver Schinagld3a558d2013-07-26 12:56:58 +020069 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
70
Hans de Goedebe4929c2014-12-13 14:02:38 +010071 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +020072 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
73 AXP221_OUTPUT_CTRL1_DCDC3_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +010074
75 ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
76 if (ret)
77 return ret;
78
Hans de Goedebb930c32015-04-25 14:07:37 +020079 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
80 AXP221_OUTPUT_CTRL1_DCDC3_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020081}
82
Hans de Goeded9ee84b2015-10-03 15:18:33 +020083int axp_set_dcdc4(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +020084{
Hans de Goedebe4929c2014-12-13 14:02:38 +010085 int ret;
Oliver Schinagld3a558d2013-07-26 12:56:58 +020086 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
87
Hans de Goedebe4929c2014-12-13 14:02:38 +010088 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +020089 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
90 AXP221_OUTPUT_CTRL1_DCDC4_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +010091
92 ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
93 if (ret)
94 return ret;
95
Hans de Goedebb930c32015-04-25 14:07:37 +020096 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
97 AXP221_OUTPUT_CTRL1_DCDC4_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020098}
99
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200100int axp_set_dcdc5(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200101{
Hans de Goedebe4929c2014-12-13 14:02:38 +0100102 int ret;
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200103 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
104
Hans de Goedebe4929c2014-12-13 14:02:38 +0100105 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +0200106 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
107 AXP221_OUTPUT_CTRL1_DCDC5_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +0100108
109 ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
110 if (ret)
111 return ret;
112
Hans de Goedebb930c32015-04-25 14:07:37 +0200113 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
114 AXP221_OUTPUT_CTRL1_DCDC5_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200115}
116
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200117int axp_set_aldo1(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200118{
119 int ret;
120 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
121
Hans de Goedebe4929c2014-12-13 14:02:38 +0100122 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +0200123 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
124 AXP221_OUTPUT_CTRL1_ALDO1_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +0100125
Hans de Goede1dd334b2014-11-29 23:54:25 +0100126 ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200127 if (ret)
128 return ret;
129
Hans de Goedebb930c32015-04-25 14:07:37 +0200130 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
131 AXP221_OUTPUT_CTRL1_ALDO1_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200132}
133
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200134int axp_set_aldo2(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200135{
136 int ret;
137 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
138
Hans de Goedebe4929c2014-12-13 14:02:38 +0100139 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +0200140 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
141 AXP221_OUTPUT_CTRL1_ALDO2_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +0100142
Hans de Goede1dd334b2014-11-29 23:54:25 +0100143 ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200144 if (ret)
145 return ret;
146
Hans de Goedebb930c32015-04-25 14:07:37 +0200147 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
148 AXP221_OUTPUT_CTRL1_ALDO2_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200149}
150
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200151int axp_set_aldo3(unsigned int mvolt)
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200152{
153 int ret;
154 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
155
Hans de Goedebe4929c2014-12-13 14:02:38 +0100156 if (mvolt == 0)
Hans de Goedebb930c32015-04-25 14:07:37 +0200157 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3,
158 AXP221_OUTPUT_CTRL3_ALDO3_EN);
Hans de Goedebe4929c2014-12-13 14:02:38 +0100159
Hans de Goede1dd334b2014-11-29 23:54:25 +0100160 ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200161 if (ret)
162 return ret;
163
Hans de Goedebb930c32015-04-25 14:07:37 +0200164 return pmic_bus_setbits(AXP221_OUTPUT_CTRL3,
165 AXP221_OUTPUT_CTRL3_ALDO3_EN);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200166}
167
Chen-Yu Tsai2e6911f2016-01-12 14:42:37 +0800168int axp_set_dldo(int dldo_num, unsigned int mvolt)
169{
170 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
171 int ret;
172
173 if (dldo_num < 1 || dldo_num > 4)
174 return -EINVAL;
175
176 if (mvolt == 0)
177 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
178 AXP221_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
179
180 ret = pmic_bus_write(AXP221_DLDO1_CTRL + (dldo_num - 1), cfg);
181 if (ret)
182 return ret;
183
184 return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
185 AXP221_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
186}
187
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200188int axp_set_eldo(int eldo_num, unsigned int mvolt)
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200189{
190 int ret;
191 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200192
Chen-Yu Tsaic80376c2016-05-02 10:28:10 +0800193 if (eldo_num < 1 || eldo_num > 3)
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200194 return -EINVAL;
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200195
196 if (mvolt == 0)
Chen-Yu Tsaic80376c2016-05-02 10:28:10 +0800197 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
198 AXP221_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200199
Chen-Yu Tsaic80376c2016-05-02 10:28:10 +0800200 ret = pmic_bus_write(AXP221_ELDO1_CTRL + (eldo_num - 1), cfg);
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200201 if (ret)
202 return ret;
203
Chen-Yu Tsaic80376c2016-05-02 10:28:10 +0800204 return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
205 AXP221_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
Siarhei Siamashka7e4eb6c2015-01-19 05:23:30 +0200206}
207
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200208int axp_init(void)
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200209{
210 u8 axp_chip_id;
211 int ret;
212
Hans de Goede1dd334b2014-11-29 23:54:25 +0100213 ret = pmic_bus_init();
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200214 if (ret)
215 return ret;
216
Hans de Goede1dd334b2014-11-29 23:54:25 +0100217 ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200218 if (ret)
219 return ret;
220
221 if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
222 return -ENODEV;
223
Hans de Goedeaf7f67c2016-09-12 09:52:52 +0200224 /*
225 * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
226 * from android these are sometimes on.
227 */
228 ret = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
229 if (ret)
230 return ret;
231
232 ret = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
233 if (ret)
234 return ret;
235
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200236 return 0;
237}
Hans de Goede65142e92014-11-25 16:37:52 +0100238
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200239int axp_get_sid(unsigned int *sid)
Hans de Goede65142e92014-11-25 16:37:52 +0100240{
241 u8 *dest = (u8 *)sid;
242 int i, ret;
243
Hans de Goeded9ee84b2015-10-03 15:18:33 +0200244 ret = pmic_bus_init();
Hans de Goede65142e92014-11-25 16:37:52 +0100245 if (ret)
246 return ret;
247
Hans de Goede1dd334b2014-11-29 23:54:25 +0100248 ret = pmic_bus_write(AXP221_PAGE, 1);
Hans de Goede65142e92014-11-25 16:37:52 +0100249 if (ret)
250 return ret;
251
252 for (i = 0; i < 16; i++) {
Hans de Goede1dd334b2014-11-29 23:54:25 +0100253 ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
Hans de Goede65142e92014-11-25 16:37:52 +0100254 if (ret)
255 return ret;
256 }
257
Hans de Goede1dd334b2014-11-29 23:54:25 +0100258 pmic_bus_write(AXP221_PAGE, 0);
Hans de Goede65142e92014-11-25 16:37:52 +0100259
260 for (i = 0; i < 4; i++)
261 sid[i] = be32_to_cpu(sid[i]);
262
263 return 0;
264}
Hans de Goede6391f0e2015-12-20 16:14:31 +0100265
Samuel Holland41a545f2021-08-22 18:18:05 -0500266#if !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
Simon Glassed38aef2020-05-10 11:40:03 -0600267int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Hans de Goede6391f0e2015-12-20 16:14:31 +0100268{
269 pmic_bus_write(AXP221_SHUTDOWN, AXP221_SHUTDOWN_POWEROFF);
270
271 /* infinite loop during shutdown */
272 while (1) {}
273
274 /* not reached */
275 return 0;
276}
Samuel Holland41a545f2021-08-22 18:18:05 -0500277#endif