xref: /openbmc/u-boot/drivers/power/axp209.c (revision f77d4410)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2012
4  * Henrik Nordstrom <henrik@henriknordstrom.net>
5  */
6 
7 #include <common.h>
8 #include <command.h>
9 #include <asm/arch/pmic_bus.h>
10 #include <axp_pmic.h>
11 
12 static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
13 {
14 	if (mvolt < min)
15 		mvolt = min;
16 	else if (mvolt > max)
17 		mvolt = max;
18 
19 	return (mvolt - min) / div;
20 }
21 
22 int axp_set_dcdc2(unsigned int mvolt)
23 {
24 	int rc;
25 	u8 cfg, current;
26 
27 	if (mvolt == 0)
28 		return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
29 					AXP209_OUTPUT_CTRL_DCDC2);
30 
31 	rc = pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC2);
32 	if (rc)
33 		return rc;
34 
35 	cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
36 
37 	/* Do we really need to be this gentle? It has built-in voltage slope */
38 	while ((rc = pmic_bus_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
39 	       current != cfg) {
40 		if (current < cfg)
41 			current++;
42 		else
43 			current--;
44 
45 		rc = pmic_bus_write(AXP209_DCDC2_VOLTAGE, current);
46 		if (rc)
47 			break;
48 	}
49 
50 	return rc;
51 }
52 
53 int axp_set_dcdc3(unsigned int mvolt)
54 {
55 	u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
56 	int rc;
57 
58 	if (mvolt == 0)
59 		return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
60 					AXP209_OUTPUT_CTRL_DCDC3);
61 
62 	rc = pmic_bus_write(AXP209_DCDC3_VOLTAGE, cfg);
63 	if (rc)
64 		return rc;
65 
66 	return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC3);
67 }
68 
69 int axp_set_aldo2(unsigned int mvolt)
70 {
71 	int rc;
72 	u8 cfg, reg;
73 
74 	if (mvolt == 0)
75 		return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
76 					AXP209_OUTPUT_CTRL_LDO2);
77 
78 	cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
79 
80 	rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
81 	if (rc)
82 		return rc;
83 
84 	/* LDO2 configuration is in upper 4 bits */
85 	reg = (reg & 0x0f) | (cfg << 4);
86 	rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
87 	if (rc)
88 		return rc;
89 
90 	return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO2);
91 }
92 
93 int axp_set_aldo3(unsigned int mvolt)
94 {
95 	u8 cfg;
96 	int rc;
97 
98 	if (mvolt == 0)
99 		return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
100 					AXP209_OUTPUT_CTRL_LDO3);
101 
102 	if (mvolt == -1)
103 		cfg = 0x80;	/* determined by LDO3IN pin */
104 	else
105 		cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
106 
107 	rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, cfg);
108 	if (rc)
109 		return rc;
110 
111 	return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3);
112 }
113 
114 int axp_set_aldo4(unsigned int mvolt)
115 {
116 	int rc;
117 	static const unsigned int vindex[] = {
118 		1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
119 		2700, 2800, 3000, 3100, 3200, 3300
120 	};
121 	u8 cfg, reg;
122 
123 	if (mvolt == 0)
124 		return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
125 					AXP209_OUTPUT_CTRL_LDO4);
126 
127 	/* Translate mvolt to register cfg value, requested <= selected */
128 	for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
129 
130 	rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
131 	if (rc)
132 		return rc;
133 
134 	/* LDO4 configuration is in lower 4 bits */
135 	reg = (reg & 0xf0) | (cfg << 0);
136 	rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
137 	if (rc)
138 		return rc;
139 
140 	return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO4);
141 }
142 
143 int axp_init(void)
144 {
145 	u8 ver;
146 	int i, rc;
147 
148 	rc = pmic_bus_init();
149 	if (rc)
150 		return rc;
151 
152 	rc = pmic_bus_read(AXP209_CHIP_VERSION, &ver);
153 	if (rc)
154 		return rc;
155 
156 	/* Low 4 bits is chip version */
157 	ver &= 0x0f;
158 
159 	if (ver != 0x1)
160 		return -EINVAL;
161 
162 	/* Mask all interrupts */
163 	for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) {
164 		rc = pmic_bus_write(i, 0);
165 		if (rc)
166 			return rc;
167 	}
168 
169 	/*
170 	 * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
171 	 * from android these are sometimes on.
172 	 */
173 	rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
174 	if (rc)
175 		return rc;
176 
177 	rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
178 	if (rc)
179 		return rc;
180 
181 	rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT);
182 	if (rc)
183 		return rc;
184 
185 	return 0;
186 }
187 
188 int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
189 {
190 	pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF);
191 
192 	/* infinite loop during shutdown */
193 	while (1) {}
194 
195 	/* not reached */
196 	return 0;
197 }
198