blob: 60f69ec27ac965912bae1adff6ab4a90f0b661b1 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +02002/*
3 * (C) Copyright 2012
4 * Henrik Nordstrom <henrik@henriknordstrom.net>
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +02005 */
6
7#include <common.h>
Michael van Slingerland467e92b2015-12-13 13:17:31 +01008#include <command.h>
Hans de Goede30490b52015-10-03 16:12:27 +02009#include <asm/arch/pmic_bus.h>
Hans de Goede6944aff2015-10-03 15:18:33 +020010#include <axp_pmic.h>
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020011
Olliver Schinagl61436d52018-11-21 20:05:30 +020012#ifdef CONFIG_AXP_ALDO3_VOLT_SLOPE_08
13# define AXP209_VRC_SLOPE AXP209_VRC_LDO3_800uV_uS
14#endif
15#ifdef CONFIG_AXP_ALDO3_VOLT_SLOPE_16
16# define AXP209_VRC_SLOPE AXP209_VRC_LDO3_1600uV_uS
17#endif
18#if defined CONFIG_AXP_ALDO3_VOLT_SLOPE_NONE || !defined AXP209_VRC_SLOPE
19# define AXP209_VRC_SLOPE 0x00
20#endif
21
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020022static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
23{
24 if (mvolt < min)
25 mvolt = min;
26 else if (mvolt > max)
27 mvolt = max;
28
29 return (mvolt - min) / div;
30}
31
Hans de Goede6944aff2015-10-03 15:18:33 +020032int axp_set_dcdc2(unsigned int mvolt)
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020033{
34 int rc;
35 u8 cfg, current;
36
Hans de Goedebeba4012015-10-04 12:01:17 +020037 if (mvolt == 0)
38 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
39 AXP209_OUTPUT_CTRL_DCDC2);
40
41 rc = pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC2);
42 if (rc)
43 return rc;
44
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020045 cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
46
47 /* Do we really need to be this gentle? It has built-in voltage slope */
Hans de Goede30490b52015-10-03 16:12:27 +020048 while ((rc = pmic_bus_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020049 current != cfg) {
50 if (current < cfg)
51 current++;
52 else
53 current--;
54
Hans de Goede30490b52015-10-03 16:12:27 +020055 rc = pmic_bus_write(AXP209_DCDC2_VOLTAGE, current);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020056 if (rc)
57 break;
58 }
59
60 return rc;
61}
62
Hans de Goede6944aff2015-10-03 15:18:33 +020063int axp_set_dcdc3(unsigned int mvolt)
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020064{
65 u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
Hans de Goedebeba4012015-10-04 12:01:17 +020066 int rc;
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020067
Hans de Goedebeba4012015-10-04 12:01:17 +020068 if (mvolt == 0)
69 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
70 AXP209_OUTPUT_CTRL_DCDC3);
71
72 rc = pmic_bus_write(AXP209_DCDC3_VOLTAGE, cfg);
73 if (rc)
74 return rc;
75
76 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC3);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020077}
78
Hans de Goede6944aff2015-10-03 15:18:33 +020079int axp_set_aldo2(unsigned int mvolt)
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020080{
81 int rc;
82 u8 cfg, reg;
83
Hans de Goedebeba4012015-10-04 12:01:17 +020084 if (mvolt == 0)
85 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
86 AXP209_OUTPUT_CTRL_LDO2);
87
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020088 cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
89
Hans de Goede30490b52015-10-03 16:12:27 +020090 rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +020091 if (rc)
92 return rc;
93
Olliver Schinagl3f7d76a2018-11-21 20:05:29 +020094 reg |= AXP209_LDO24_LDO2_SET(reg, cfg);
Hans de Goedebeba4012015-10-04 12:01:17 +020095 rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
96 if (rc)
97 return rc;
98
99 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO2);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200100}
101
Hans de Goede6944aff2015-10-03 15:18:33 +0200102int axp_set_aldo3(unsigned int mvolt)
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200103{
104 u8 cfg;
Hans de Goedebeba4012015-10-04 12:01:17 +0200105 int rc;
106
107 if (mvolt == 0)
108 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
109 AXP209_OUTPUT_CTRL_LDO3);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200110
Olliver Schinagl61436d52018-11-21 20:05:30 +0200111 /*
112 * Some boards have trouble reaching the target voltage without causing
113 * great inrush currents. To prevent this, boards can enable a certain
114 * slope to ramp up voltage. Note, this only works when changing an
115 * already active power rail. When toggling power on, the AXP ramps up
116 * steeply at 0.0167 V/uS.
117 */
118 rc = pmic_bus_read(AXP209_VRC_DCDC2_LDO3, &cfg);
119 cfg = AXP209_VRC_LDO3_SLOPE_SET(cfg, AXP209_VRC_SLOPE);
120 rc |= pmic_bus_write(AXP209_VRC_DCDC2_LDO3, cfg);
121
122 if (rc)
123 return rc;
124
Olliver Schinaglef526052018-11-21 20:05:31 +0200125#ifdef CONFIG_AXP_ALDO3_INRUSH_QUIRK
126 /*
127 * On some boards, LDO3 has a too big capacitor installed. When
128 * turning on LDO3, this causes the AXP209 to shutdown on
129 * voltages over 1.9 volt. As a workaround, we enable LDO3
130 * first with the lowest possible voltage. If this still causes
131 * high inrush currents, the voltage slope should be increased.
132 */
133 rc = pmic_bus_read(AXP209_OUTPUT_CTRL, &cfg);
134 if (rc)
135 return rc;
136
137 if (!(cfg & AXP209_OUTPUT_CTRL_LDO3)) {
138 rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, 0x0); /* 0.7 Volt */
139 mdelay(1);
140 rc |= pmic_bus_setbits(AXP209_OUTPUT_CTRL,
141 AXP209_OUTPUT_CTRL_LDO3);
142
143 if (rc)
144 return rc;
145 }
146#endif
147
Olliver Schinagl3f7d76a2018-11-21 20:05:29 +0200148 if (mvolt == -1) {
149 cfg = AXP209_LDO3_VOLTAGE_FROM_LDO3IN;
150 } else {
Iain Paton99deda12015-03-25 16:03:26 +0000151 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
Olliver Schinagl3f7d76a2018-11-21 20:05:29 +0200152 cfg = AXP209_LDO3_VOLTAGE_SET(cfg);
153 }
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200154
Hans de Goedebeba4012015-10-04 12:01:17 +0200155 rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, cfg);
156 if (rc)
157 return rc;
158
159 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200160}
161
Hans de Goede6944aff2015-10-03 15:18:33 +0200162int axp_set_aldo4(unsigned int mvolt)
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200163{
164 int rc;
Hans de Goede6944aff2015-10-03 15:18:33 +0200165 static const unsigned int vindex[] = {
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200166 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
167 2700, 2800, 3000, 3100, 3200, 3300
168 };
169 u8 cfg, reg;
170
Hans de Goedebeba4012015-10-04 12:01:17 +0200171 if (mvolt == 0)
172 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
173 AXP209_OUTPUT_CTRL_LDO4);
174
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200175 /* Translate mvolt to register cfg value, requested <= selected */
176 for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
177
Hans de Goede30490b52015-10-03 16:12:27 +0200178 rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200179 if (rc)
180 return rc;
181
Olliver Schinagl3f7d76a2018-11-21 20:05:29 +0200182 reg |= AXP209_LDO24_LDO4_SET(reg, cfg);
Hans de Goedebeba4012015-10-04 12:01:17 +0200183 rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
184 if (rc)
185 return rc;
186
187 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO4);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200188}
189
Hans de Goede6944aff2015-10-03 15:18:33 +0200190int axp_init(void)
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200191{
192 u8 ver;
Hans de Goede9dcf68f2015-01-17 16:39:20 +0100193 int i, rc;
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200194
Hans de Goede30490b52015-10-03 16:12:27 +0200195 rc = pmic_bus_init();
196 if (rc)
197 return rc;
198
199 rc = pmic_bus_read(AXP209_CHIP_VERSION, &ver);
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200200 if (rc)
201 return rc;
202
Olliver Schinaglf5eebc72018-11-21 20:05:28 +0200203 if ((ver & AXP209_CHIP_VERSION_MASK) != 0x1)
Jaehoon Chung505cf472016-12-15 20:49:50 +0900204 return -EINVAL;
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200205
Hans de Goede9dcf68f2015-01-17 16:39:20 +0100206 /* Mask all interrupts */
207 for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) {
Hans de Goede30490b52015-10-03 16:12:27 +0200208 rc = pmic_bus_write(i, 0);
Hans de Goede9dcf68f2015-01-17 16:39:20 +0100209 if (rc)
210 return rc;
211 }
212
Hans de Goede253e62b2016-09-12 09:52:52 +0200213 /*
214 * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
215 * from android these are sometimes on.
216 */
217 rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
218 if (rc)
219 return rc;
220
221 rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
222 if (rc)
223 return rc;
224
225 rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT);
226 if (rc)
227 return rc;
228
Henrik Nordstrom14bc66b2014-06-13 22:55:50 +0200229 return 0;
230}
Michael van Slingerland467e92b2015-12-13 13:17:31 +0100231
Simon Glass09140112020-05-10 11:40:03 -0600232int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Michael van Slingerland467e92b2015-12-13 13:17:31 +0100233{
234 pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF);
235
236 /* infinite loop during shutdown */
237 while (1) {}
238
239 /* not reached */
240 return 0;
241}