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