xref: /openbmc/u-boot/drivers/power/pmic/as3722.c (revision 00fc38ae)
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 int as3722_read(struct udevice *pmic, u8 reg, u8 *value)
31 {
32 	int err;
33 
34 	err = dm_i2c_read(pmic, reg, value, 1);
35 	if (err < 0)
36 		return err;
37 
38 	return 0;
39 }
40 
41 int as3722_write(struct udevice *pmic, u8 reg, u8 value)
42 {
43 	int err;
44 
45 	err = dm_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 /* Temporary function until we get the pmic framework */
238 int as3722_get(struct udevice **devp)
239 {
240 	int bus = 0;
241 	int address = 0x40;
242 
243 	return i2c_get_chip_for_busnum(bus, address, 1, devp);
244 }
245 
246 int as3722_init(struct udevice **devp)
247 {
248 	struct udevice *pmic;
249 	u8 id, revision;
250 	const unsigned int bus = 0;
251 	const unsigned int address = 0x40;
252 	int err;
253 
254 	err = i2c_get_chip_for_busnum(bus, address, 1, &pmic);
255 	if (err)
256 		return err;
257 	err = as3722_read_id(pmic, &id, &revision);
258 	if (err < 0) {
259 		error("failed to read ID: %d", err);
260 		return err;
261 	}
262 
263 	if (id != AS3722_DEVICE_ID) {
264 		error("unknown device");
265 		return -ENOENT;
266 	}
267 
268 	debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
269 	      revision, bus, address);
270 	if (devp)
271 		*devp = pmic;
272 
273 	return 0;
274 }
275