1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <i2c.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <dm/lists.h>
14 #include <dm/root.h>
15 
16 /**
17  * struct i2c_mux: Information the uclass stores about an I2C mux
18  *
19  * @selected:	Currently selected mux, or -1 for none
20  * @i2c_bus: I2C bus to use for communcation
21  */
22 struct i2c_mux {
23 	int selected;
24 	struct udevice *i2c_bus;
25 };
26 
27 /**
28  * struct i2c_mux_bus: Information about each bus the mux controls
29  *
30  * @channel: Channel number used to select this bus
31  */
32 struct i2c_mux_bus {
33 	uint channel;
34 };
35 
36 /* Find out the mux channel number */
i2c_mux_child_post_bind(struct udevice * dev)37 static int i2c_mux_child_post_bind(struct udevice *dev)
38 {
39 	struct i2c_mux_bus *plat = dev_get_parent_plat(dev);
40 	int channel;
41 
42 	channel = dev_read_u32_default(dev, "reg", -1);
43 	if (channel < 0)
44 		return -EINVAL;
45 	plat->channel = channel;
46 
47 	return 0;
48 }
49 
50 /* Find the I2C buses selected by this mux */
i2c_mux_post_bind(struct udevice * mux)51 static int i2c_mux_post_bind(struct udevice *mux)
52 {
53 	ofnode node;
54 	int ret;
55 
56 	debug("%s: %s\n", __func__, mux->name);
57 	/*
58 	 * There is no compatible string in the sub-nodes, so we must manually
59 	 * bind these
60 	 */
61 	dev_for_each_subnode(node, mux) {
62 		struct udevice *dev;
63 		const char *name;
64 		const char *arrow = "->";
65 		char *full_name;
66 		int parent_name_len, arrow_len, mux_name_len, name_len;
67 
68 		name = ofnode_get_name(node);
69 
70 		/* Calculate lenghts of strings */
71 		parent_name_len = strlen(mux->parent->name);
72 		arrow_len = strlen(arrow);
73 		mux_name_len = strlen(mux->name);
74 		name_len = strlen(name);
75 
76 		full_name = calloc(1, parent_name_len + arrow_len +
77 				   mux_name_len + arrow_len + name_len + 1);
78 		if (!full_name)
79 			return -ENOMEM;
80 
81 		/* Compose bus name */
82 		strcat(full_name, mux->parent->name);
83 		strcat(full_name, arrow);
84 		strcat(full_name, mux->name);
85 		strcat(full_name, arrow);
86 		strcat(full_name, name);
87 
88 		ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv",
89 						 full_name, node, &dev);
90 		debug("   - bind ret=%d, %s, seq %d\n", ret,
91 		      dev ? dev->name : NULL, dev_seq(dev));
92 		if (ret)
93 			return ret;
94 	}
95 
96 	return 0;
97 }
98 
99 /* Set up the mux ready for use */
i2c_mux_post_probe(struct udevice * mux)100 static int i2c_mux_post_probe(struct udevice *mux)
101 {
102 	struct i2c_mux *priv = dev_get_uclass_priv(mux);
103 	int ret;
104 
105 	debug("%s: %s\n", __func__, mux->name);
106 	priv->selected = -1;
107 
108 	/* if parent is of i2c uclass already, we'll take that, otherwise
109 	 * look if we find an i2c-parent phandle
110 	 */
111 	if (UCLASS_I2C == device_get_uclass_id(mux->parent)) {
112 		priv->i2c_bus = dev_get_parent(mux);
113 		debug("%s: bus=%p/%s\n", __func__, priv->i2c_bus,
114 		      priv->i2c_bus->name);
115 		return 0;
116 	}
117 
118 	ret = uclass_get_device_by_phandle(UCLASS_I2C, mux, "i2c-parent",
119 					   &priv->i2c_bus);
120 	if (ret)
121 		return ret;
122 	debug("%s: bus=%p/%s\n", __func__, priv->i2c_bus, priv->i2c_bus->name);
123 
124 	return 0;
125 }
126 
i2c_mux_select(struct udevice * dev)127 int i2c_mux_select(struct udevice *dev)
128 {
129 	struct i2c_mux_bus *plat = dev_get_parent_plat(dev);
130 	struct udevice *mux = dev->parent;
131 	struct i2c_mux_ops *ops = i2c_mux_get_ops(mux);
132 
133 	if (!ops->select)
134 		return -ENOSYS;
135 
136 	return ops->select(mux, dev, plat->channel);
137 }
138 
i2c_mux_deselect(struct udevice * dev)139 int i2c_mux_deselect(struct udevice *dev)
140 {
141 	struct i2c_mux_bus *plat = dev_get_parent_plat(dev);
142 	struct udevice *mux = dev->parent;
143 	struct i2c_mux_ops *ops = i2c_mux_get_ops(mux);
144 
145 	if (!ops->deselect)
146 		return -ENOSYS;
147 
148 	return ops->deselect(mux, dev, plat->channel);
149 }
150 
i2c_mux_bus_set_bus_speed(struct udevice * dev,unsigned int speed)151 static int i2c_mux_bus_set_bus_speed(struct udevice *dev, unsigned int speed)
152 {
153 	struct udevice *mux = dev->parent;
154 	struct i2c_mux *priv = dev_get_uclass_priv(mux);
155 	int ret, ret2;
156 
157 	ret = i2c_mux_select(dev);
158 	if (ret)
159 		return ret;
160 	ret = dm_i2c_set_bus_speed(priv->i2c_bus, speed);
161 	ret2 = i2c_mux_deselect(dev);
162 
163 	return ret ? ret : ret2;
164 }
165 
i2c_mux_bus_probe(struct udevice * dev,uint chip_addr,uint chip_flags)166 static int i2c_mux_bus_probe(struct udevice *dev, uint chip_addr,
167 			     uint chip_flags)
168 {
169 	struct udevice *mux = dev->parent;
170 	struct i2c_mux *priv = dev_get_uclass_priv(mux);
171 	struct dm_i2c_ops *ops = i2c_get_ops(priv->i2c_bus);
172 	int ret, ret2;
173 
174 	debug("%s: %s, bus %s\n", __func__, dev->name, priv->i2c_bus->name);
175 	if (!ops->probe_chip)
176 		return -ENOSYS;
177 	ret = i2c_mux_select(dev);
178 	if (ret)
179 		return ret;
180 	ret = ops->probe_chip(priv->i2c_bus, chip_addr, chip_flags);
181 	ret2 = i2c_mux_deselect(dev);
182 
183 	return ret ? ret : ret2;
184 }
185 
i2c_mux_bus_xfer(struct udevice * dev,struct i2c_msg * msg,int nmsgs)186 static int i2c_mux_bus_xfer(struct udevice *dev, struct i2c_msg *msg,
187 			    int nmsgs)
188 {
189 	struct udevice *mux = dev->parent;
190 	struct i2c_mux *priv = dev_get_uclass_priv(mux);
191 	struct dm_i2c_ops *ops = i2c_get_ops(priv->i2c_bus);
192 	int ret, ret2;
193 
194 	debug("%s: %s, bus %s\n", __func__, dev->name, priv->i2c_bus->name);
195 	if (!ops->xfer)
196 		return -ENOSYS;
197 	ret = i2c_mux_select(dev);
198 	if (ret)
199 		return ret;
200 	ret = ops->xfer(priv->i2c_bus, msg, nmsgs);
201 	ret2 = i2c_mux_deselect(dev);
202 
203 	return ret ? ret : ret2;
204 }
205 
206 static const struct dm_i2c_ops i2c_mux_bus_ops = {
207 	.xfer		= i2c_mux_bus_xfer,
208 	.probe_chip	= i2c_mux_bus_probe,
209 	.set_bus_speed	= i2c_mux_bus_set_bus_speed,
210 };
211 
212 U_BOOT_DRIVER(i2c_mux_bus) = {
213 	.name		= "i2c_mux_bus_drv",
214 	.id		= UCLASS_I2C,
215 	.ops	= &i2c_mux_bus_ops,
216 };
217 
218 UCLASS_DRIVER(i2c_mux) = {
219 	.id		= UCLASS_I2C_MUX,
220 	.name		= "i2c_mux",
221 	.post_bind	= i2c_mux_post_bind,
222 	.post_probe	= i2c_mux_post_probe,
223 	.per_device_auto	= sizeof(struct i2c_mux),
224 	.per_child_plat_auto	= sizeof(struct i2c_mux_bus),
225 	.child_post_bind = i2c_mux_child_post_bind,
226 };
227