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