xref: /openbmc/u-boot/drivers/power/axp209.c (revision c5f18a0b)
1 /*
2  * (C) Copyright 2012
3  * Henrik Nordstrom <henrik@henriknordstrom.net>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.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 -1;
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 	return 0;
170 }
171