]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/power/as3722.c
power: Add AMS AS3722 PMIC support
[karo-tx-uboot.git] / drivers / power / as3722.c
1 /*
2  * Copyright (C) 2014 NVIDIA Corporation
3  *
4  * SPDX-License-Identifier: GPL-2.0+
5  */
6
7 #define pr_fmt(fmt) "as3722: " fmt
8
9 #include <common.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <fdtdec.h>
13 #include <i2c.h>
14
15 #include <power/as3722.h>
16
17 #define AS3722_SD_VOLTAGE(n) (0x00 + (n))
18 #define AS3722_GPIO_CONTROL(n) (0x08 + (n))
19 #define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0)
20 #define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0)
21 #define  AS3722_GPIO_CONTROL_INVERT (1 << 7)
22 #define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
23 #define AS3722_GPIO_SIGNAL_OUT 0x20
24 #define AS3722_SD_CONTROL 0x4d
25 #define AS3722_LDO_CONTROL 0x4e
26 #define AS3722_ASIC_ID1 0x90
27 #define  AS3722_DEVICE_ID 0x0c
28 #define AS3722_ASIC_ID2 0x91
29
30 static int as3722_read(struct udevice *pmic, u8 reg, u8 *value)
31 {
32         int err;
33
34         err = i2c_read(pmic, reg, value, 1);
35         if (err < 0)
36                 return err;
37
38         return 0;
39 }
40
41 static int as3722_write(struct udevice *pmic, u8 reg, u8 value)
42 {
43         int err;
44
45         err = i2c_write(pmic, reg, &value, 1);
46         if (err < 0)
47                 return err;
48
49         return 0;
50 }
51
52 static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision)
53 {
54         int err;
55
56         err = as3722_read(pmic, AS3722_ASIC_ID1, id);
57         if (err) {
58                 error("failed to read ID1 register: %d", err);
59                 return err;
60         }
61
62         err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
63         if (err) {
64                 error("failed to read ID2 register: %d", err);
65                 return err;
66         }
67
68         return 0;
69 }
70
71 int as3722_sd_enable(struct udevice *pmic, unsigned int sd)
72 {
73         u8 value;
74         int err;
75
76         if (sd > 6)
77                 return -EINVAL;
78
79         err = as3722_read(pmic, AS3722_SD_CONTROL, &value);
80         if (err) {
81                 error("failed to read SD control register: %d", err);
82                 return err;
83         }
84
85         value |= 1 << sd;
86
87         err = as3722_write(pmic, AS3722_SD_CONTROL, value);
88         if (err < 0) {
89                 error("failed to write SD control register: %d", err);
90                 return err;
91         }
92
93         return 0;
94 }
95
96 int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value)
97 {
98         int err;
99
100         if (sd > 6)
101                 return -EINVAL;
102
103         err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
104         if (err < 0) {
105                 error("failed to write SD%u voltage register: %d", sd, err);
106                 return err;
107         }
108
109         return 0;
110 }
111
112 int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo)
113 {
114         u8 value;
115         int err;
116
117         if (ldo > 11)
118                 return -EINVAL;
119
120         err = as3722_read(pmic, AS3722_LDO_CONTROL, &value);
121         if (err) {
122                 error("failed to read LDO control register: %d", err);
123                 return err;
124         }
125
126         value |= 1 << ldo;
127
128         err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
129         if (err < 0) {
130                 error("failed to write LDO control register: %d", err);
131                 return err;
132         }
133
134         return 0;
135 }
136
137 int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value)
138 {
139         int err;
140
141         if (ldo > 11)
142                 return -EINVAL;
143
144         err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
145         if (err < 0) {
146                 error("failed to write LDO%u voltage register: %d", ldo,
147                       err);
148                 return err;
149         }
150
151         return 0;
152 }
153
154 int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
155                           unsigned long flags)
156 {
157         u8 value = 0;
158         int err;
159
160         if (flags & AS3722_GPIO_OUTPUT_VDDH)
161                 value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
162
163         if (flags & AS3722_GPIO_INVERT)
164                 value |= AS3722_GPIO_CONTROL_INVERT;
165
166         err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
167         if (err) {
168                 error("failed to configure GPIO#%u: %d", gpio, err);
169                 return err;
170         }
171
172         return 0;
173 }
174
175 static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio,
176                            unsigned int level)
177 {
178         const char *l;
179         u8 value;
180         int err;
181
182         if (gpio > 7)
183                 return -EINVAL;
184
185         err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value);
186         if (err < 0) {
187                 error("failed to read GPIO signal out register: %d", err);
188                 return err;
189         }
190
191         if (level == 0) {
192                 value &= ~(1 << gpio);
193                 l = "low";
194         } else {
195                 value |= 1 << gpio;
196                 l = "high";
197         }
198
199         err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
200         if (err) {
201                 error("failed to set GPIO#%u %s: %d", gpio, l, err);
202                 return err;
203         }
204
205         return 0;
206 }
207
208 int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
209                                  unsigned int level)
210 {
211         u8 value;
212         int err;
213
214         if (gpio > 7)
215                 return -EINVAL;
216
217         if (level == 0)
218                 value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
219         else
220                 value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
221
222         err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
223         if (err) {
224                 error("failed to configure GPIO#%u as output: %d", gpio, err);
225                 return err;
226         }
227
228         err = as3722_gpio_set(pmic, gpio, level);
229         if (err < 0) {
230                 error("failed to set GPIO#%u high: %d", gpio, err);
231                 return err;
232         }
233
234         return 0;
235 }
236
237 int as3722_init(struct udevice **devp)
238 {
239         struct udevice *pmic;
240         u8 id, revision;
241         const unsigned int bus = 0;
242         const unsigned int address = 0x40;
243         int err;
244
245         err = i2c_get_chip_for_busnum(bus, address, &pmic);
246         if (err)
247                 return err;
248         err = as3722_read_id(pmic, &id, &revision);
249         if (err < 0) {
250                 error("failed to read ID: %d", err);
251                 return err;
252         }
253
254         if (id != AS3722_DEVICE_ID) {
255                 error("unknown device");
256                 return -ENOENT;
257         }
258
259         debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
260               revision, bus, address);
261         *devp = pmic;
262
263         return 0;
264 }