xref: /openbmc/u-boot/drivers/power/pmic/as3722.c (revision 0dfe3ffe)
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 #include <dm/lists.h>
15 #include <power/as3722.h>
16 #include <power/pmic.h>
17 
18 #define AS3722_NUM_OF_REGS	0x92
19 
20 static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
21 {
22 	int ret;
23 
24 	ret = dm_i2c_read(dev, reg, buff, len);
25 	if (ret < 0)
26 		return ret;
27 
28 	return 0;
29 }
30 
31 static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
32 			int len)
33 {
34 	int ret;
35 
36 	ret = dm_i2c_write(dev, reg, buff, len);
37 	if (ret < 0)
38 		return ret;
39 
40 	return 0;
41 }
42 
43 static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp)
44 {
45 	int ret;
46 
47 	ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
48 	if (ret < 0) {
49 		error("failed to read ID1 register: %d", ret);
50 		return ret;
51 	}
52 	*idp = ret;
53 
54 	ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
55 	if (ret < 0) {
56 		error("failed to read ID2 register: %d", ret);
57 		return ret;
58 	}
59 	*revisionp = ret;
60 
61 	return 0;
62 }
63 
64 /* TODO(treding@nvidia.com): Add proper regulator support to avoid this */
65 int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value)
66 {
67 	int ret;
68 
69 	if (sd > 6)
70 		return -EINVAL;
71 
72 	ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
73 	if (ret < 0) {
74 		error("failed to write SD%u voltage register: %d", sd, ret);
75 		return ret;
76 	}
77 
78 	return 0;
79 }
80 
81 int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value)
82 {
83 	int ret;
84 
85 	if (ldo > 11)
86 		return -EINVAL;
87 
88 	ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
89 	if (ret < 0) {
90 		error("failed to write LDO%u voltage register: %d", ldo,
91 		      ret);
92 		return ret;
93 	}
94 
95 	return 0;
96 }
97 
98 static int as3722_probe(struct udevice *dev)
99 {
100 	uint id, revision;
101 	int ret;
102 
103 	ret = as3722_read_id(dev, &id, &revision);
104 	if (ret < 0) {
105 		error("failed to read ID: %d", ret);
106 		return ret;
107 	}
108 
109 	if (id != AS3722_DEVICE_ID) {
110 		error("unknown device");
111 		return -ENOENT;
112 	}
113 
114 	debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
115 
116 	return 0;
117 }
118 
119 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
120 static const struct pmic_child_info pmic_children_info[] = {
121 	{ .prefix = "sd", .driver = "as3722_stepdown"},
122 	{ .prefix = "ldo", .driver = "as3722_ldo"},
123 	{ },
124 };
125 
126 static int as3722_bind(struct udevice *dev)
127 {
128 	struct udevice *gpio_dev;
129 	ofnode regulators_node;
130 	int children;
131 	int ret;
132 
133 	regulators_node = dev_read_subnode(dev, "regulators");
134 	if (!ofnode_valid(regulators_node)) {
135 		debug("%s: %s regulators subnode not found\n", __func__,
136 		      dev->name);
137 		return -ENXIO;
138 	}
139 
140 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
141 	if (!children)
142 		debug("%s: %s - no child found\n", __func__, dev->name);
143 	ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev);
144 	if (ret) {
145 		debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret);
146 		return ret;
147 	}
148 
149 	return 0;
150 }
151 #endif
152 
153 static int as3722_reg_count(struct udevice *dev)
154 {
155 	return AS3722_NUM_OF_REGS;
156 }
157 
158 static struct dm_pmic_ops as3722_ops = {
159 	.reg_count = as3722_reg_count,
160 	.read = as3722_read,
161 	.write = as3722_write,
162 };
163 
164 static const struct udevice_id as3722_ids[] = {
165 	{ .compatible = "ams,as3722" },
166 	{ }
167 };
168 
169 U_BOOT_DRIVER(pmic_as3722) = {
170 	.name = "as3722_pmic",
171 	.id = UCLASS_PMIC,
172 	.of_match = as3722_ids,
173 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
174 	.bind = as3722_bind,
175 #endif
176 	.probe = as3722_probe,
177 	.ops = &as3722_ops,
178 };
179