blob: c09e1de06f4c51147968978da7234a3aab7db617 [file] [log] [blame]
Thierry Reding6173c452014-12-09 22:25:05 -07001/*
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
Simon Glassd55b7d42015-04-14 21:03:26 -060030int as3722_read(struct udevice *pmic, u8 reg, u8 *value)
Thierry Reding6173c452014-12-09 22:25:05 -070031{
32 int err;
33
Simon Glassf9a4c2d2015-01-12 18:02:07 -070034 err = dm_i2c_read(pmic, reg, value, 1);
Thierry Reding6173c452014-12-09 22:25:05 -070035 if (err < 0)
36 return err;
37
38 return 0;
39}
40
Simon Glassd55b7d42015-04-14 21:03:26 -060041int as3722_write(struct udevice *pmic, u8 reg, u8 value)
Thierry Reding6173c452014-12-09 22:25:05 -070042{
43 int err;
44
Simon Glassf9a4c2d2015-01-12 18:02:07 -070045 err = dm_i2c_write(pmic, reg, &value, 1);
Thierry Reding6173c452014-12-09 22:25:05 -070046 if (err < 0)
47 return err;
48
49 return 0;
50}
51
52static 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
71int 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
96int 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
112int 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
137int 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
154int 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
175static 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
208int 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
Simon Glassd55b7d42015-04-14 21:03:26 -0600237/* Temporary function until we get the pmic framework */
238int 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
Thierry Reding6173c452014-12-09 22:25:05 -0700246int 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
Simon Glass25ab4b02015-01-25 08:26:55 -0700254 err = i2c_get_chip_for_busnum(bus, address, 1, &pmic);
Thierry Reding6173c452014-12-09 22:25:05 -0700255 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);
Simon Glassd55b7d42015-04-14 21:03:26 -0600270 if (devp)
271 *devp = pmic;
Thierry Reding6173c452014-12-09 22:25:05 -0700272
273 return 0;
274}