blob: 68ab8a5d423854742db647f38378a72762465695 [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"
12
13#include <device/i2c.h>
14
15/* Hide these definitions from the rest of the source, so keep them here */
16enum registers {
17 REG_POWER_STATUS = 0x00,
18 REG_POWER_MODE = 0x01,
19 REG_OTG_VBUS = 0x02,
20 REG_CHIP_ID = 0x03,
21 REG_CHIP_PWROUT_CTL = 0x12,
22 REG_DCDC2_VOLTAGE = 0x23,
23 REG_DCDC2_LDO3_CTL = 0x25,
24 REG_DCDC3_VOLTAGE = 0x27,
25 REG_LDO24_VOLTAGE = 0x28,
26 REG_LDO3_VOLTAGE = 0x29,
27 REG_VBUS_IPSOUT = 0x30,
28 REG_PWROFF_VOLTAGE = 0x31,
29 REG_SHTDWN_SETTING = 0x32,
30};
31
32/* REG_LDO24_VOLTAGE definitions */
33#define REG_LDO24_VOLTAGE_LDO2_MASK (0xf << 4)
34#define REG_LDO24_VOLTAGE_LDO2_VAL(x) ((x << 4) & REG_LDO24_VOLTAGE_LDO2_MASK)
35#define REG_LDO24_VOLTAGE_LDO4_MASK (0xf << 0)
36#define REG_LDO24_VOLTAGE_LDO4_VAL(x) ((x << 0) & REG_LDO24_VOLTAGE_LDO4_MASK)
37
38/*
39 * Read and write accessors. We only work on one register at a time, but there
40 * is no limitation on the AXP209 as to how many registers we may read or write
41 * in one transaction.
42 * These return the number of bytes read/written, or an error code. In this
43 * case, they return 1 on success, or an error code otherwise.
44 */
45static int axp209_read(u8 bus, u8 reg, u8 *val)
46{
47 return i2c_read(bus, AXP209_I2C_ADDR, reg, 1, val, 1);
48}
49
50static int axp209_write(u8 bus, u8 reg, u8 val)
51{
52 return i2c_write(bus, AXP209_I2C_ADDR, reg, 1, &val, 1);
53}
54
55/**
56 * \brief Identify and initialize an AXP209 on the I²C bus
57 *
58 * @param[in] bus I²C bus to which the AXP209 is connected
59 * @return CB_SUCCES on if an AXP209 is found, or an error code otherwise.
60 */
61enum cb_err axp209_init(u8 bus)
62{
63 u8 id;
64
65 if (axp209_read(bus, REG_CHIP_ID, &id) != 1)
66 return CB_ERR;
67
68 /* From U-Boot code : Low 4 bits is chip version */
69 if ((id & 0x0f) != 0x1)
70 return CB_ERR;
71
72 return CB_SUCCESS;
73}
74
75/**
76 * \brief Configure the output voltage of DC-DC2 converter
77 *
78 * If the requested voltage is not available, the next lowest voltage will
79 * be applied.
80 * Valid values are between 700mV and 2275mV
81 *
82 * @param[in] millivolts voltage in mV units.
83 * @param[in] bus I²C bus to which the AXP209 is connected
84 * @return CB_SUCCES on success,
85 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
86 */
87enum cb_err axp209_set_dcdc2_voltage(u8 bus, u16 millivolts)
88{
89 u8 val;
90
91 if (millivolts < 700 || millivolts > 2275)
92 return CB_ERR_ARG;
93
94 val = (millivolts - 700) / 25;
95
96 if (axp209_write(bus, REG_DCDC2_VOLTAGE, val) != 1)
97 return CB_ERR;
98
99 return CB_SUCCESS;
100}
101
102/**
103 * \brief Configure the output voltage of DC-DC3 converter
104 *
105 * If the requested voltage is not available, the next lowest voltage will
106 * be applied.
107 * Valid values are between 700mV and 3500mV
108 *
109 * @param[in] millivolts voltage in mV units.
110 * @param[in] bus I²C bus to which the AXP209 is connected
111 * @return CB_SUCCES on success,
112 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
113 */
114enum cb_err axp209_set_dcdc3_voltage(u8 bus, u16 millivolts)
115{
116 u8 val;
117
118 if (millivolts < 700 || millivolts > 3500)
119 return CB_ERR_ARG;
120
121 val = (millivolts - 700) / 25;
122
123 if (axp209_write(bus, REG_DCDC3_VOLTAGE, val) != 1)
124 return CB_ERR;
125
126 return CB_SUCCESS;
127}
128
129/**
130 * \brief Configure the output voltage of LDO2 regulator
131 *
132 * If the requested voltage is not available, the next lowest voltage will
133 * be applied.
134 * Valid values are between 700mV and 3300mV
135 *
136 * @param[in] millivolts voltage in mV units.
137 * @param[in] bus I²C bus to which the AXP209 is connected
138 * @return CB_SUCCES on success,
139 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
140 */
141enum cb_err axp209_set_ldo2_voltage(u8 bus, u16 millivolts)
142{
143 u8 reg8, val;
144
145 if (millivolts < 1800 || millivolts > 3300)
146 return CB_ERR_ARG;
147
148 /* Try to read the register first, and stop here on error */
149 if (axp209_read(bus, REG_LDO24_VOLTAGE, &reg8) != 1)
150 return CB_ERR;
151
152 val = (millivolts - 1800) / 100;
153 reg8 &= ~REG_LDO24_VOLTAGE_LDO2_MASK;
154 reg8 |= REG_LDO24_VOLTAGE_LDO2_VAL(val);
155
156 if (axp209_write(bus, REG_LDO24_VOLTAGE, reg8) != 1)
157 return CB_ERR;
158
159 return CB_SUCCESS;
160}
161
162/**
163 * \brief Configure the output voltage of LDO4 regulator
164 *
165 * If the requested voltage is not available, the next lowest voltage will
166 * be applied.
167 * Valid values are between 700mV and 3500mV. Datasheet lists maximum voltage at
168 * 2250mV, but hardware samples go as high as 3500mV.
169 *
170 * @param[in] millivolts voltage in mV units.
171 * @param[in] bus I²C bus to which the AXP209 is connected
172 * @return CB_SUCCES on success,
173 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
174 */
175enum cb_err axp209_set_ldo3_voltage(u8 bus, u16 millivolts)
176{
177 u8 val;
178
179 /* Datasheet lists 2250 max, but PMU will output up to 3500mV */
180 if (millivolts < 700 || millivolts > 3500)
181 return CB_ERR_ARG;
182
183 val = (millivolts - 700) / 25;
184
185 if (axp209_write(bus, REG_LDO3_VOLTAGE, val) != 1)
186 return CB_ERR;
187
188 return CB_SUCCESS;
189}
190
191/**
192 * \brief Configure the output voltage of DC-DC2 converter
193 *
194 * If the requested voltage is not available, the next lowest voltage will
195 * be applied.
196 * Valid values are between 1250V and 3300mV
197 *
198 * @param[in] millivolts voltage in mV units.
199 * @param[in] bus I²C bus to which the AXP209 is connected
200 * @return CB_SUCCES on success,
201 * CB_ERR_ARG if voltage is out of range, or an error code otherwise.
202 */
203enum cb_err axp209_set_ldo4_voltage(u8 bus, u16 millivolts)
204{
205 u8 reg8, val;
206
207 if (millivolts < 1250 || millivolts > 3300)
208 return CB_ERR_ARG;
209
210 /* Try to read the register first, and stop here on error */
211 if (axp209_read(bus, REG_LDO24_VOLTAGE, &reg8) != 1)
212 return CB_ERR;
213
214 if (millivolts <= 2000)
215 val = (millivolts - 1200) / 100;
216 else if (millivolts <= 2700)
217 val = 9 + (millivolts - 2500) / 100;
218 else if (millivolts <= 2800)
219 val = 11;
220 else
221 val = 12 + (millivolts - 3000) / 100;
222
223 reg8 &= ~REG_LDO24_VOLTAGE_LDO4_MASK;
224 reg8 |= REG_LDO24_VOLTAGE_LDO4_VAL(val);
225
226 if (axp209_write(bus, REG_LDO24_VOLTAGE, reg8) != 1)
227 return CB_ERR;
228
229 return CB_SUCCESS;
230}