]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/power/axp209.c
ARM: atmel: sama5d4_xplained: enable usb ethernet gadget
[karo-tx-uboot.git] / drivers / power / axp209.c
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 <i2c.h>
10 #include <axp209.h>
11
12 enum axp209_reg {
13         AXP209_POWER_STATUS = 0x00,
14         AXP209_CHIP_VERSION = 0x03,
15         AXP209_DCDC2_VOLTAGE = 0x23,
16         AXP209_DCDC3_VOLTAGE = 0x27,
17         AXP209_LDO24_VOLTAGE = 0x28,
18         AXP209_LDO3_VOLTAGE = 0x29,
19         AXP209_IRQ_STATUS5 = 0x4c,
20         AXP209_SHUTDOWN = 0x32,
21         AXP209_GPIO0_CTRL = 0x90,
22         AXP209_GPIO1_CTRL = 0x92,
23         AXP209_GPIO2_CTRL = 0x93,
24         AXP209_GPIO_STATE = 0x94,
25         AXP209_GPIO3_CTRL = 0x95,
26 };
27
28 #define AXP209_POWER_STATUS_ON_BY_DC    (1 << 0)
29
30 #define AXP209_IRQ5_PEK_UP              (1 << 6)
31 #define AXP209_IRQ5_PEK_DOWN            (1 << 5)
32
33 #define AXP209_POWEROFF                 (1 << 7)
34
35 #define AXP209_GPIO_OUTPUT_LOW          0x00 /* Drive pin low */
36 #define AXP209_GPIO_OUTPUT_HIGH         0x01 /* Drive pin high */
37 #define AXP209_GPIO_INPUT               0x02 /* Float pin */
38
39 /* GPIO3 is different from the others */
40 #define AXP209_GPIO3_OUTPUT_LOW         0x00 /* Drive pin low, Output mode */
41 #define AXP209_GPIO3_OUTPUT_HIGH        0x02 /* Float pin, Output mode */
42 #define AXP209_GPIO3_INPUT              0x06 /* Float pin, Input mode */
43
44 static int axp209_write(enum axp209_reg reg, u8 val)
45 {
46         return i2c_write(0x34, reg, 1, &val, 1);
47 }
48
49 static int axp209_read(enum axp209_reg reg, u8 *val)
50 {
51         return i2c_read(0x34, reg, 1, val, 1);
52 }
53
54 static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
55 {
56         if (mvolt < min)
57                 mvolt = min;
58         else if (mvolt > max)
59                 mvolt = max;
60
61         return (mvolt - min) / div;
62 }
63
64 int axp209_set_dcdc2(int mvolt)
65 {
66         int rc;
67         u8 cfg, current;
68
69         cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
70
71         /* Do we really need to be this gentle? It has built-in voltage slope */
72         while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
73                current != cfg) {
74                 if (current < cfg)
75                         current++;
76                 else
77                         current--;
78
79                 rc = axp209_write(AXP209_DCDC2_VOLTAGE, current);
80                 if (rc)
81                         break;
82         }
83
84         return rc;
85 }
86
87 int axp209_set_dcdc3(int mvolt)
88 {
89         u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
90
91         return axp209_write(AXP209_DCDC3_VOLTAGE, cfg);
92 }
93
94 int axp209_set_ldo2(int mvolt)
95 {
96         int rc;
97         u8 cfg, reg;
98
99         cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
100
101         rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
102         if (rc)
103                 return rc;
104
105         /* LDO2 configuration is in upper 4 bits */
106         reg = (reg & 0x0f) | (cfg << 4);
107         return axp209_write(AXP209_LDO24_VOLTAGE, reg);
108 }
109
110 int axp209_set_ldo3(int mvolt)
111 {
112         u8 cfg;
113
114         if (mvolt == -1)
115                 cfg = 0x80;     /* determined by LDO3IN pin */
116         else
117                 cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
118
119         return axp209_write(AXP209_LDO3_VOLTAGE, cfg);
120 }
121
122 int axp209_set_ldo4(int mvolt)
123 {
124         int rc;
125         static const int vindex[] = {
126                 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
127                 2700, 2800, 3000, 3100, 3200, 3300
128         };
129         u8 cfg, reg;
130
131         /* Translate mvolt to register cfg value, requested <= selected */
132         for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
133
134         rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
135         if (rc)
136                 return rc;
137
138         /* LDO4 configuration is in lower 4 bits */
139         reg = (reg & 0xf0) | (cfg << 0);
140         return axp209_write(AXP209_LDO24_VOLTAGE, reg);
141 }
142
143 int axp209_init(void)
144 {
145         u8 ver;
146         int rc;
147
148         rc = axp209_read(AXP209_CHIP_VERSION, &ver);
149         if (rc)
150                 return rc;
151
152         /* Low 4 bits is chip version */
153         ver &= 0x0f;
154
155         if (ver != 0x1)
156                 return -1;
157
158         return 0;
159 }
160
161 int axp209_poweron_by_dc(void)
162 {
163         u8 v;
164
165         if (axp209_read(AXP209_POWER_STATUS, &v))
166                 return 0;
167
168         return (v & AXP209_POWER_STATUS_ON_BY_DC);
169 }
170
171 int axp209_power_button(void)
172 {
173         u8 v;
174
175         if (axp209_read(AXP209_IRQ_STATUS5, &v))
176                 return 0;
177
178         axp209_write(AXP209_IRQ_STATUS5, AXP209_IRQ5_PEK_DOWN);
179
180         return v & AXP209_IRQ5_PEK_DOWN;
181 }
182
183 static u8 axp209_get_gpio_ctrl_reg(unsigned int pin)
184 {
185         switch (pin) {
186         case 0: return AXP209_GPIO0_CTRL;
187         case 1: return AXP209_GPIO1_CTRL;
188         case 2: return AXP209_GPIO2_CTRL;
189         case 3: return AXP209_GPIO3_CTRL;
190         }
191         return 0;
192 }
193
194 int axp_gpio_direction_input(unsigned int pin)
195 {
196         u8 reg = axp209_get_gpio_ctrl_reg(pin);
197         /* GPIO3 is "special" */
198         u8 val = (pin == 3) ? AXP209_GPIO3_INPUT : AXP209_GPIO_INPUT;
199
200         return axp209_write(reg, val);
201 }
202
203 int axp_gpio_direction_output(unsigned int pin, unsigned int val)
204 {
205         u8 reg = axp209_get_gpio_ctrl_reg(pin);
206
207         if (val) {
208                 val = (pin == 3) ? AXP209_GPIO3_OUTPUT_HIGH :
209                                    AXP209_GPIO_OUTPUT_HIGH;
210         } else {
211                 val = (pin == 3) ? AXP209_GPIO3_OUTPUT_LOW :
212                                    AXP209_GPIO_OUTPUT_LOW;
213         }
214
215         return axp209_write(reg, val);
216 }
217
218 int axp_gpio_get_value(unsigned int pin)
219 {
220         u8 val, mask;
221         int rc;
222
223         if (pin == 3) {
224                 rc = axp209_read(AXP209_GPIO3_CTRL, &val);
225                 mask = 1;
226         } else {
227                 rc = axp209_read(AXP209_GPIO_STATE, &val);
228                 mask = 1 << (pin + 4);
229         }
230         if (rc)
231                 return rc;
232
233         return (val & mask) ? 1 : 0;
234 }
235
236 int axp_gpio_set_value(unsigned int pin, unsigned int val)
237 {
238         return axp_gpio_direction_output(pin, val);
239 }