blob: de11fbe1bdba18231781fd68ddb354a96a3dc67b [file] [log] [blame]
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -05001/*
2 * Driver for X-Powers AXP 209 Power Management Unit
3 *
4 * Despite axp209_read/write only working on a byte at a time, there is no such
5 * limitation in the AXP209.
6 *
7 * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
8 * Subject to the GNU GPL v2, or (at your option) any later version.
9 */
10
11#include "axp209.h"
Alexandru Gagniuc4d3a89d2014-01-09 20:07:10 -060012#include "chip.h"
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050013
Alexandru Gagniucabe9b812014-01-09 20:17:18 -060014#include <console/console.h>
Alexandru Gagniuc4d3a89d2014-01-09 20:07:10 -060015#include <device/device.h>
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050016#include <device/i2c.h>
17
18/* Hide these definitions from the rest of the source, so keep them here */
19enum registers {
20 REG_POWER_STATUS = 0x00,
21 REG_POWER_MODE = 0x01,
22 REG_OTG_VBUS = 0x02,
23 REG_CHIP_ID = 0x03,
24 REG_CHIP_PWROUT_CTL = 0x12,
25 REG_DCDC2_VOLTAGE = 0x23,
26 REG_DCDC2_LDO3_CTL = 0x25,
27 REG_DCDC3_VOLTAGE = 0x27,
28 REG_LDO24_VOLTAGE = 0x28,
29 REG_LDO3_VOLTAGE = 0x29,
30 REG_VBUS_IPSOUT = 0x30,
31 REG_PWROFF_VOLTAGE = 0x31,
32 REG_SHTDWN_SETTING = 0x32,
33};
34
35/* REG_LDO24_VOLTAGE definitions */
36#define REG_LDO24_VOLTAGE_LDO2_MASK (0xf << 4)
37#define REG_LDO24_VOLTAGE_LDO2_VAL(x) ((x << 4) & REG_LDO24_VOLTAGE_LDO2_MASK)
38#define REG_LDO24_VOLTAGE_LDO4_MASK (0xf << 0)
39#define REG_LDO24_VOLTAGE_LDO4_VAL(x) ((x << 0) & REG_LDO24_VOLTAGE_LDO4_MASK)
40
41/*
42 * Read and write accessors. We only work on one register at a time, but there
43 * is no limitation on the AXP209 as to how many registers we may read or write
44 * in one transaction.
45 * These return the number of bytes read/written, or an error code. In this
Alexandru Gagniuc1959abd2015-02-13 16:39:42 -060046 * case, they return 1 on success, or an error code otherwise. This is done to
Martin Roth0cd338e2016-07-29 14:07:30 -060047 * work with I2C drivers that return either 0 on success or the number of bytes
Alexandru Gagniuc1959abd2015-02-13 16:39:42 -060048 * actually transferred.
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050049 */
50static int axp209_read(u8 bus, u8 reg, u8 *val)
51{
Alexandru Gagniuc1959abd2015-02-13 16:39:42 -060052 if (i2c_readb(bus, AXP209_I2C_ADDR, reg, val) < 0)
53 return CB_ERR;
54 return 1;
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050055}
56
57static int axp209_write(u8 bus, u8 reg, u8 val)
58{
Alexandru Gagniuc1959abd2015-02-13 16:39:42 -060059 if (i2c_writeb(bus, AXP209_I2C_ADDR, reg, val) < 0)
60 return CB_ERR;
61 return 1;
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050062}
63
64/**
Martin Roth0cd338e2016-07-29 14:07:30 -060065 * \brief Identify and initialize an AXP209 on the I2C bus
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050066 *
Martin Roth0cd338e2016-07-29 14:07:30 -060067 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050068 * @return CB_SUCCES on if an AXP209 is found, or an error code otherwise.
69 */
70enum cb_err axp209_init(u8 bus)
71{
72 u8 id;
73
74 if (axp209_read(bus, REG_CHIP_ID, &id) != 1)
75 return CB_ERR;
76
77 /* From U-Boot code : Low 4 bits is chip version */
Alexandru Gagniuc23804fc2015-02-13 17:10:04 -060078 if ((id & 0x0f) != 0x1) {
79 printk(BIOS_ERR, "[axp209] ID 0x%x does not match\n", id);
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050080 return CB_ERR;
Alexandru Gagniuc23804fc2015-02-13 17:10:04 -060081 }
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050082
83 return CB_SUCCESS;
84}
85
86/**
87 * \brief Configure the output voltage of DC-DC2 converter
88 *
89 * If the requested voltage is not available, the next lowest voltage will
90 * be applied.
91 * Valid values are between 700mV and 2275mV
92 *
93 * @param[in] millivolts voltage in mV units.
Martin Roth0cd338e2016-07-29 14:07:30 -060094 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -050095 * @return CB_SUCCES on success,
96 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
97 */
98enum cb_err axp209_set_dcdc2_voltage(u8 bus, u16 millivolts)
99{
100 u8 val;
101
102 if (millivolts < 700 || millivolts > 2275)
103 return CB_ERR_ARG;
104
105 val = (millivolts - 700) / 25;
106
107 if (axp209_write(bus, REG_DCDC2_VOLTAGE, val) != 1)
108 return CB_ERR;
109
110 return CB_SUCCESS;
111}
112
113/**
114 * \brief Configure the output voltage of DC-DC3 converter
115 *
116 * If the requested voltage is not available, the next lowest voltage will
117 * be applied.
118 * Valid values are between 700mV and 3500mV
119 *
120 * @param[in] millivolts voltage in mV units.
Martin Roth0cd338e2016-07-29 14:07:30 -0600121 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -0500122 * @return CB_SUCCES on success,
123 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
124 */
125enum cb_err axp209_set_dcdc3_voltage(u8 bus, u16 millivolts)
126{
127 u8 val;
128
129 if (millivolts < 700 || millivolts > 3500)
130 return CB_ERR_ARG;
131
132 val = (millivolts - 700) / 25;
133
134 if (axp209_write(bus, REG_DCDC3_VOLTAGE, val) != 1)
135 return CB_ERR;
136
137 return CB_SUCCESS;
138}
139
140/**
141 * \brief Configure the output voltage of LDO2 regulator
142 *
143 * If the requested voltage is not available, the next lowest voltage will
144 * be applied.
145 * Valid values are between 700mV and 3300mV
146 *
147 * @param[in] millivolts voltage in mV units.
Martin Roth0cd338e2016-07-29 14:07:30 -0600148 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -0500149 * @return CB_SUCCES on success,
150 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
151 */
152enum cb_err axp209_set_ldo2_voltage(u8 bus, u16 millivolts)
153{
154 u8 reg8, val;
155
156 if (millivolts < 1800 || millivolts > 3300)
157 return CB_ERR_ARG;
158
159 /* Try to read the register first, and stop here on error */
160 if (axp209_read(bus, REG_LDO24_VOLTAGE, &reg8) != 1)
161 return CB_ERR;
162
163 val = (millivolts - 1800) / 100;
164 reg8 &= ~REG_LDO24_VOLTAGE_LDO2_MASK;
165 reg8 |= REG_LDO24_VOLTAGE_LDO2_VAL(val);
166
167 if (axp209_write(bus, REG_LDO24_VOLTAGE, reg8) != 1)
168 return CB_ERR;
169
170 return CB_SUCCESS;
171}
172
173/**
174 * \brief Configure the output voltage of LDO4 regulator
175 *
176 * If the requested voltage is not available, the next lowest voltage will
177 * be applied.
178 * Valid values are between 700mV and 3500mV. Datasheet lists maximum voltage at
179 * 2250mV, but hardware samples go as high as 3500mV.
180 *
181 * @param[in] millivolts voltage in mV units.
Martin Roth0cd338e2016-07-29 14:07:30 -0600182 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -0500183 * @return CB_SUCCES on success,
184 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
185 */
186enum cb_err axp209_set_ldo3_voltage(u8 bus, u16 millivolts)
187{
188 u8 val;
189
190 /* Datasheet lists 2250 max, but PMU will output up to 3500mV */
191 if (millivolts < 700 || millivolts > 3500)
192 return CB_ERR_ARG;
193
194 val = (millivolts - 700) / 25;
195
196 if (axp209_write(bus, REG_LDO3_VOLTAGE, val) != 1)
197 return CB_ERR;
198
199 return CB_SUCCESS;
200}
201
202/**
203 * \brief Configure the output voltage of DC-DC2 converter
204 *
205 * If the requested voltage is not available, the next lowest voltage will
206 * be applied.
207 * Valid values are between 1250V and 3300mV
208 *
209 * @param[in] millivolts voltage in mV units.
Martin Roth0cd338e2016-07-29 14:07:30 -0600210 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -0500211 * @return CB_SUCCES on success,
212 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
213 */
214enum cb_err axp209_set_ldo4_voltage(u8 bus, u16 millivolts)
215{
216 u8 reg8, val;
217
218 if (millivolts < 1250 || millivolts > 3300)
219 return CB_ERR_ARG;
220
221 /* Try to read the register first, and stop here on error */
222 if (axp209_read(bus, REG_LDO24_VOLTAGE, &reg8) != 1)
223 return CB_ERR;
224
225 if (millivolts <= 2000)
226 val = (millivolts - 1200) / 100;
227 else if (millivolts <= 2700)
228 val = 9 + (millivolts - 2500) / 100;
229 else if (millivolts <= 2800)
230 val = 11;
231 else
232 val = 12 + (millivolts - 3000) / 100;
233
234 reg8 &= ~REG_LDO24_VOLTAGE_LDO4_MASK;
235 reg8 |= REG_LDO24_VOLTAGE_LDO4_VAL(val);
236
237 if (axp209_write(bus, REG_LDO24_VOLTAGE, reg8) != 1)
Alexandru Gagniucabe9b812014-01-09 20:17:18 -0600238 return CB_ERR;
239
240 return CB_SUCCESS;
241}
242
243static const struct {
244 enum cb_err (*set_voltage) (u8 bus, u16 mv);
245 const char *name;
246} vtable[] = { {
247 .set_voltage = axp209_set_dcdc2_voltage,
248 .name = "DCDC2",
249 }, {
250 .set_voltage = axp209_set_dcdc3_voltage,
251 .name = "DCDC3",
252 }, {
253 .set_voltage = axp209_set_ldo2_voltage,
254 .name = "LDO2",
255 }, {
256 .set_voltage = axp209_set_ldo3_voltage,
257 .name = "LDO3",
258 }, {
259 .set_voltage = axp209_set_ldo4_voltage,
260 .name = "LDO4",
261 }
262};
263
264static enum cb_err set_rail(u8 bus, int idx, u16 mv)
265{
266 enum cb_err err;
267 const char *name = vtable[idx].name;
268
269 /* If voltage isn't specified, don't touch the rail */
270 if (mv == 0) {
271 printk(BIOS_DEBUG, "[axp209] Skipping %s configuration\n",
272 name);
273 return CB_SUCCESS;
274 }
275
276 if ((err = vtable[idx].set_voltage(bus, mv) != CB_SUCCESS)) {
277 printk(BIOS_ERR, "[axp209] Failed to set %s to %u mv\n",
278 name, mv);
279 return err;
280 }
281
282 return CB_SUCCESS;
283}
284
285/**
286 * \brief Configure all voltage rails
287 *
288 * Configure all converters and regulators from devicetree config. If any of the
289 * voltages are not declared (i.e. are zero), the respective rail will not be
290 * reconfigured, and retain its powerup voltage.
291 *
292 * @param[in] cfg pointer to @ref drivers_xpowers_axp209_config structure
Martin Roth0cd338e2016-07-29 14:07:30 -0600293 * @param[in] bus I2C bus to which the AXP209 is connected
Alexandru Gagniucabe9b812014-01-09 20:17:18 -0600294 * @return CB_SUCCES on success, or an error code otherwise.
295 */
296enum cb_err axp209_set_voltages(u8 bus, const struct
297 drivers_xpowers_axp209_config *cfg)
298{
299 enum cb_err err;
300
301 /* Don't worry about what the error is. Console prints that */
302 err = set_rail(bus, 0, cfg->dcdc2_voltage_mv);
303 err |= set_rail(bus, 1, cfg->dcdc3_voltage_mv);
304 err |= set_rail(bus, 2, cfg->ldo2_voltage_mv);
305 err |= set_rail(bus, 3, cfg->ldo3_voltage_mv);
306 err |= set_rail(bus, 4, cfg->ldo4_voltage_mv);
307
308 if (err != CB_SUCCESS)
309 return CB_ERR;
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -0500310
311 return CB_SUCCESS;
312}
Alexandru Gagniuc4d3a89d2014-01-09 20:07:10 -0600313
314/*
315 * Usually, the AXP209 is enabled and configured in romstage, so there is no
316 * need for a full ramstage driver. Hence .enable_dev is NULL.
317 */
318#ifndef __PRE_RAM__
319struct chip_operations drivers_xpowers_axp209_config = {
320 CHIP_NAME("X-Powers AXP 209 Power Management Unit")
321 .enable_dev = NULL,
322};
323#endif /* __PRE_RAM__ */