Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / i2c / muxes / i2c-mux-uclass.c
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  */
24 struct 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  */
34 struct i2c_mux_bus {
35         uint channel;
36 };
37
38 /* Find out the mux channel number */
39 static 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 */
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                 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 */
102 static 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
129 int 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
141 int 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
153 static 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
168 static 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
188 static 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
208 static 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
214 U_BOOT_DRIVER(i2c_mux_bus) = {
215         .name           = "i2c_mux_bus_drv",
216         .id             = UCLASS_I2C,
217         .ops    = &i2c_mux_bus_ops,
218 };
219
220 UCLASS_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 };