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