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 */ 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 channel = dev_read_u32_default(dev, "reg", -1); 42 if (channel < 0) 43 return -EINVAL; 44 plat->channel = channel; 45 46 return 0; 47 } 48 49 /* Find the I2C buses selected by this mux */ 50 static int i2c_mux_post_bind(struct udevice *mux) 51 { 52 ofnode node; 53 int ret; 54 55 debug("%s: %s\n", __func__, mux->name); 56 /* 57 * There is no compatible string in the sub-nodes, so we must manually 58 * bind these 59 */ 60 dev_for_each_subnode(node, mux) { 61 struct udevice *dev; 62 const char *name; 63 64 name = ofnode_get_name(node); 65 ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv", name, 66 node, &dev); 67 debug(" - bind ret=%d, %s\n", ret, dev ? dev->name : NULL); 68 if (ret) 69 return ret; 70 } 71 72 return 0; 73 } 74 75 /* Set up the mux ready for use */ 76 static int i2c_mux_post_probe(struct udevice *mux) 77 { 78 struct i2c_mux *priv = dev_get_uclass_priv(mux); 79 int ret; 80 81 debug("%s: %s\n", __func__, mux->name); 82 priv->selected = -1; 83 84 /* if parent is of i2c uclass already, we'll take that, otherwise 85 * look if we find an i2c-parent phandle 86 */ 87 if (UCLASS_I2C == device_get_uclass_id(mux->parent)) { 88 priv->i2c_bus = dev_get_parent(mux); 89 debug("%s: bus=%p/%s\n", __func__, priv->i2c_bus, 90 priv->i2c_bus->name); 91 return 0; 92 } 93 94 ret = uclass_get_device_by_phandle(UCLASS_I2C, mux, "i2c-parent", 95 &priv->i2c_bus); 96 if (ret) 97 return ret; 98 debug("%s: bus=%p/%s\n", __func__, priv->i2c_bus, priv->i2c_bus->name); 99 100 return 0; 101 } 102 103 int i2c_mux_select(struct udevice *dev) 104 { 105 struct i2c_mux_bus *plat = dev_get_parent_platdata(dev); 106 struct udevice *mux = dev->parent; 107 struct i2c_mux_ops *ops = i2c_mux_get_ops(mux); 108 109 if (!ops->select) 110 return -ENOSYS; 111 112 return ops->select(mux, dev, plat->channel); 113 } 114 115 int i2c_mux_deselect(struct udevice *dev) 116 { 117 struct i2c_mux_bus *plat = dev_get_parent_platdata(dev); 118 struct udevice *mux = dev->parent; 119 struct i2c_mux_ops *ops = i2c_mux_get_ops(mux); 120 121 if (!ops->deselect) 122 return -ENOSYS; 123 124 return ops->deselect(mux, dev, plat->channel); 125 } 126 127 static int i2c_mux_bus_set_bus_speed(struct udevice *dev, unsigned int speed) 128 { 129 struct udevice *mux = dev->parent; 130 struct i2c_mux *priv = dev_get_uclass_priv(mux); 131 int ret, ret2; 132 133 ret = i2c_mux_select(dev); 134 if (ret) 135 return ret; 136 ret = dm_i2c_set_bus_speed(priv->i2c_bus, speed); 137 ret2 = i2c_mux_deselect(dev); 138 139 return ret ? ret : ret2; 140 } 141 142 static int i2c_mux_bus_probe(struct udevice *dev, uint chip_addr, 143 uint chip_flags) 144 { 145 struct udevice *mux = dev->parent; 146 struct i2c_mux *priv = dev_get_uclass_priv(mux); 147 struct dm_i2c_ops *ops = i2c_get_ops(priv->i2c_bus); 148 int ret, ret2; 149 150 debug("%s: %s, bus %s\n", __func__, dev->name, priv->i2c_bus->name); 151 if (!ops->probe_chip) 152 return -ENOSYS; 153 ret = i2c_mux_select(dev); 154 if (ret) 155 return ret; 156 ret = ops->probe_chip(priv->i2c_bus, chip_addr, chip_flags); 157 ret2 = i2c_mux_deselect(dev); 158 159 return ret ? ret : ret2; 160 } 161 162 static int i2c_mux_bus_xfer(struct udevice *dev, struct i2c_msg *msg, 163 int nmsgs) 164 { 165 struct udevice *mux = dev->parent; 166 struct i2c_mux *priv = dev_get_uclass_priv(mux); 167 struct dm_i2c_ops *ops = i2c_get_ops(priv->i2c_bus); 168 int ret, ret2; 169 170 debug("%s: %s, bus %s\n", __func__, dev->name, priv->i2c_bus->name); 171 if (!ops->xfer) 172 return -ENOSYS; 173 ret = i2c_mux_select(dev); 174 if (ret) 175 return ret; 176 ret = ops->xfer(priv->i2c_bus, msg, nmsgs); 177 ret2 = i2c_mux_deselect(dev); 178 179 return ret ? ret : ret2; 180 } 181 182 static const struct dm_i2c_ops i2c_mux_bus_ops = { 183 .xfer = i2c_mux_bus_xfer, 184 .probe_chip = i2c_mux_bus_probe, 185 .set_bus_speed = i2c_mux_bus_set_bus_speed, 186 }; 187 188 U_BOOT_DRIVER(i2c_mux_bus) = { 189 .name = "i2c_mux_bus_drv", 190 .id = UCLASS_I2C, 191 .ops = &i2c_mux_bus_ops, 192 }; 193 194 UCLASS_DRIVER(i2c_mux) = { 195 .id = UCLASS_I2C_MUX, 196 .name = "i2c_mux", 197 .post_bind = i2c_mux_post_bind, 198 .post_probe = i2c_mux_post_probe, 199 .per_device_auto_alloc_size = sizeof(struct i2c_mux), 200 .per_child_platdata_auto_alloc_size = sizeof(struct i2c_mux_bus), 201 .child_post_bind = i2c_mux_child_post_bind, 202 }; 203