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