blob: 4f984e6b51d5fe0f8f20ad1dfa683c693738efc9 [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
46 * case, they return 1 on success, or an error code otherwise.
47 */
48static int axp209_read(u8 bus, u8 reg, u8 *val)
49{
50 return i2c_read(bus, AXP209_I2C_ADDR, reg, 1, val, 1);
51}
52
53static int axp209_write(u8 bus, u8 reg, u8 val)
54{
55 return i2c_write(bus, AXP209_I2C_ADDR, reg, 1, &val, 1);
56}
57
58/**
59 * \brief Identify and initialize an AXP209 on the I²C bus
60 *
61 * @param[in] bus I²C bus to which the AXP209 is connected
62 * @return CB_SUCCES on if an AXP209 is found, or an error code otherwise.
63 */
64enum cb_err axp209_init(u8 bus)
65{
66 u8 id;
67
68 if (axp209_read(bus, REG_CHIP_ID, &id) != 1)
69 return CB_ERR;
70
71 /* From U-Boot code : Low 4 bits is chip version */
72 if ((id & 0x0f) != 0x1)
73 return CB_ERR;
74
75 return CB_SUCCESS;
76}
77
78/**
79 * \brief Configure the output voltage of DC-DC2 converter
80 *
81 * If the requested voltage is not available, the next lowest voltage will
82 * be applied.
83 * Valid values are between 700mV and 2275mV
84 *
85 * @param[in] millivolts voltage in mV units.
86 * @param[in] bus I²C bus to which the AXP209 is connected
87 * @return CB_SUCCES on success,
88 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
89 */
90enum cb_err axp209_set_dcdc2_voltage(u8 bus, u16 millivolts)
91{
92 u8 val;
93
94 if (millivolts < 700 || millivolts > 2275)
95 return CB_ERR_ARG;
96
97 val = (millivolts - 700) / 25;
98
99 if (axp209_write(bus, REG_DCDC2_VOLTAGE, val) != 1)
100 return CB_ERR;
101
102 return CB_SUCCESS;
103}
104
105/**
106 * \brief Configure the output voltage of DC-DC3 converter
107 *
108 * If the requested voltage is not available, the next lowest voltage will
109 * be applied.
110 * Valid values are between 700mV and 3500mV
111 *
112 * @param[in] millivolts voltage in mV units.
113 * @param[in] bus I²C bus to which the AXP209 is connected
114 * @return CB_SUCCES on success,
115 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
116 */
117enum cb_err axp209_set_dcdc3_voltage(u8 bus, u16 millivolts)
118{
119 u8 val;
120
121 if (millivolts < 700 || millivolts > 3500)
122 return CB_ERR_ARG;
123
124 val = (millivolts - 700) / 25;
125
126 if (axp209_write(bus, REG_DCDC3_VOLTAGE, val) != 1)
127 return CB_ERR;
128
129 return CB_SUCCESS;
130}
131
132/**
133 * \brief Configure the output voltage of LDO2 regulator
134 *
135 * If the requested voltage is not available, the next lowest voltage will
136 * be applied.
137 * Valid values are between 700mV and 3300mV
138 *
139 * @param[in] millivolts voltage in mV units.
140 * @param[in] bus I²C bus to which the AXP209 is connected
141 * @return CB_SUCCES on success,
142 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
143 */
144enum cb_err axp209_set_ldo2_voltage(u8 bus, u16 millivolts)
145{
146 u8 reg8, val;
147
148 if (millivolts < 1800 || millivolts > 3300)
149 return CB_ERR_ARG;
150
151 /* Try to read the register first, and stop here on error */
152 if (axp209_read(bus, REG_LDO24_VOLTAGE, &reg8) != 1)
153 return CB_ERR;
154
155 val = (millivolts - 1800) / 100;
156 reg8 &= ~REG_LDO24_VOLTAGE_LDO2_MASK;
157 reg8 |= REG_LDO24_VOLTAGE_LDO2_VAL(val);
158
159 if (axp209_write(bus, REG_LDO24_VOLTAGE, reg8) != 1)
160 return CB_ERR;
161
162 return CB_SUCCESS;
163}
164
165/**
166 * \brief Configure the output voltage of LDO4 regulator
167 *
168 * If the requested voltage is not available, the next lowest voltage will
169 * be applied.
170 * Valid values are between 700mV and 3500mV. Datasheet lists maximum voltage at
171 * 2250mV, but hardware samples go as high as 3500mV.
172 *
173 * @param[in] millivolts voltage in mV units.
174 * @param[in] bus I²C bus to which the AXP209 is connected
175 * @return CB_SUCCES on success,
176 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
177 */
178enum cb_err axp209_set_ldo3_voltage(u8 bus, u16 millivolts)
179{
180 u8 val;
181
182 /* Datasheet lists 2250 max, but PMU will output up to 3500mV */
183 if (millivolts < 700 || millivolts > 3500)
184 return CB_ERR_ARG;
185
186 val = (millivolts - 700) / 25;
187
188 if (axp209_write(bus, REG_LDO3_VOLTAGE, val) != 1)
189 return CB_ERR;
190
191 return CB_SUCCESS;
192}
193
194/**
195 * \brief Configure the output voltage of DC-DC2 converter
196 *
197 * If the requested voltage is not available, the next lowest voltage will
198 * be applied.
199 * Valid values are between 1250V and 3300mV
200 *
201 * @param[in] millivolts voltage in mV units.
202 * @param[in] bus I²C bus to which the AXP209 is connected
203 * @return CB_SUCCES on success,
204 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
205 */
206enum cb_err axp209_set_ldo4_voltage(u8 bus, u16 millivolts)
207{
208 u8 reg8, val;
209
210 if (millivolts < 1250 || millivolts > 3300)
211 return CB_ERR_ARG;
212
213 /* Try to read the register first, and stop here on error */
214 if (axp209_read(bus, REG_LDO24_VOLTAGE, &reg8) != 1)
215 return CB_ERR;
216
217 if (millivolts <= 2000)
218 val = (millivolts - 1200) / 100;
219 else if (millivolts <= 2700)
220 val = 9 + (millivolts - 2500) / 100;
221 else if (millivolts <= 2800)
222 val = 11;
223 else
224 val = 12 + (millivolts - 3000) / 100;
225
226 reg8 &= ~REG_LDO24_VOLTAGE_LDO4_MASK;
227 reg8 |= REG_LDO24_VOLTAGE_LDO4_VAL(val);
228
229 if (axp209_write(bus, REG_LDO24_VOLTAGE, reg8) != 1)
Alexandru Gagniucabe9b812014-01-09 20:17:18 -0600230 return CB_ERR;
231
232 return CB_SUCCESS;
233}
234
235static const struct {
236 enum cb_err (*set_voltage) (u8 bus, u16 mv);
237 const char *name;
238} vtable[] = { {
239 .set_voltage = axp209_set_dcdc2_voltage,
240 .name = "DCDC2",
241 }, {
242 .set_voltage = axp209_set_dcdc3_voltage,
243 .name = "DCDC3",
244 }, {
245 .set_voltage = axp209_set_ldo2_voltage,
246 .name = "LDO2",
247 }, {
248 .set_voltage = axp209_set_ldo3_voltage,
249 .name = "LDO3",
250 }, {
251 .set_voltage = axp209_set_ldo4_voltage,
252 .name = "LDO4",
253 }
254};
255
256static enum cb_err set_rail(u8 bus, int idx, u16 mv)
257{
258 enum cb_err err;
259 const char *name = vtable[idx].name;
260
261 /* If voltage isn't specified, don't touch the rail */
262 if (mv == 0) {
263 printk(BIOS_DEBUG, "[axp209] Skipping %s configuration\n",
264 name);
265 return CB_SUCCESS;
266 }
267
268 if ((err = vtable[idx].set_voltage(bus, mv) != CB_SUCCESS)) {
269 printk(BIOS_ERR, "[axp209] Failed to set %s to %u mv\n",
270 name, mv);
271 return err;
272 }
273
274 return CB_SUCCESS;
275}
276
277/**
278 * \brief Configure all voltage rails
279 *
280 * Configure all converters and regulators from devicetree config. If any of the
281 * voltages are not declared (i.e. are zero), the respective rail will not be
282 * reconfigured, and retain its powerup voltage.
283 *
284 * @param[in] cfg pointer to @ref drivers_xpowers_axp209_config structure
285 * @param[in] bus I²C bus to which the AXP209 is connected
286 * @return CB_SUCCES on success, or an error code otherwise.
287 */
288enum cb_err axp209_set_voltages(u8 bus, const struct
289 drivers_xpowers_axp209_config *cfg)
290{
291 enum cb_err err;
292
293 /* Don't worry about what the error is. Console prints that */
294 err = set_rail(bus, 0, cfg->dcdc2_voltage_mv);
295 err |= set_rail(bus, 1, cfg->dcdc3_voltage_mv);
296 err |= set_rail(bus, 2, cfg->ldo2_voltage_mv);
297 err |= set_rail(bus, 3, cfg->ldo3_voltage_mv);
298 err |= set_rail(bus, 4, cfg->ldo4_voltage_mv);
299
300 if (err != CB_SUCCESS)
301 return CB_ERR;
Alexandru Gagniuc428eeff2013-12-30 01:21:55 -0500302
303 return CB_SUCCESS;
304}
Alexandru Gagniuc4d3a89d2014-01-09 20:07:10 -0600305
306/*
307 * Usually, the AXP209 is enabled and configured in romstage, so there is no
308 * need for a full ramstage driver. Hence .enable_dev is NULL.
309 */
310#ifndef __PRE_RAM__
311struct chip_operations drivers_xpowers_axp209_config = {
312 CHIP_NAME("X-Powers AXP 209 Power Management Unit")
313 .enable_dev = NULL,
314};
315#endif /* __PRE_RAM__ */