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