1 /* 2 * I2C multiplexer using GPIO API 3 * 4 * Peter Korsgaard <peter.korsgaard@barco.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/i2c.h> 12 #include <linux/i2c-mux.h> 13 #include <linux/i2c-mux-gpio.h> 14 #include <linux/platform_device.h> 15 #include <linux/module.h> 16 #include <linux/slab.h> 17 #include <linux/gpio.h> 18 #include "../../gpio/gpiolib.h" 19 #include <linux/of_gpio.h> 20 21 struct gpiomux { 22 struct i2c_mux_gpio_platform_data data; 23 unsigned gpio_base; 24 }; 25 26 static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val) 27 { 28 int i; 29 30 for (i = 0; i < mux->data.n_gpios; i++) 31 gpio_set_value_cansleep(mux->gpio_base + mux->data.gpios[i], 32 val & (1 << i)); 33 } 34 35 static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan) 36 { 37 struct gpiomux *mux = i2c_mux_priv(muxc); 38 39 i2c_mux_gpio_set(mux, chan); 40 41 return 0; 42 } 43 44 static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan) 45 { 46 struct gpiomux *mux = i2c_mux_priv(muxc); 47 48 i2c_mux_gpio_set(mux, mux->data.idle); 49 50 return 0; 51 } 52 53 static int match_gpio_chip_by_label(struct gpio_chip *chip, 54 void *data) 55 { 56 return !strcmp(chip->label, data); 57 } 58 59 #ifdef CONFIG_OF 60 static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, 61 struct platform_device *pdev) 62 { 63 struct device_node *np = pdev->dev.of_node; 64 struct device_node *adapter_np, *child; 65 struct i2c_adapter *adapter; 66 unsigned *values, *gpios; 67 int i = 0, ret; 68 69 if (!np) 70 return -ENODEV; 71 72 adapter_np = of_parse_phandle(np, "i2c-parent", 0); 73 if (!adapter_np) { 74 dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); 75 return -ENODEV; 76 } 77 adapter = of_find_i2c_adapter_by_node(adapter_np); 78 of_node_put(adapter_np); 79 if (!adapter) 80 return -EPROBE_DEFER; 81 82 mux->data.parent = i2c_adapter_id(adapter); 83 put_device(&adapter->dev); 84 85 mux->data.n_values = of_get_child_count(np); 86 87 values = devm_kzalloc(&pdev->dev, 88 sizeof(*mux->data.values) * mux->data.n_values, 89 GFP_KERNEL); 90 if (!values) { 91 dev_err(&pdev->dev, "Cannot allocate values array"); 92 return -ENOMEM; 93 } 94 95 for_each_child_of_node(np, child) { 96 of_property_read_u32(child, "reg", values + i); 97 i++; 98 } 99 mux->data.values = values; 100 101 if (of_property_read_u32(np, "idle-state", &mux->data.idle)) 102 mux->data.idle = I2C_MUX_GPIO_NO_IDLE; 103 104 mux->data.n_gpios = of_gpio_named_count(np, "mux-gpios"); 105 if (mux->data.n_gpios < 0) { 106 dev_err(&pdev->dev, "Missing mux-gpios property in the DT.\n"); 107 return -EINVAL; 108 } 109 110 gpios = devm_kzalloc(&pdev->dev, 111 sizeof(*mux->data.gpios) * mux->data.n_gpios, GFP_KERNEL); 112 if (!gpios) { 113 dev_err(&pdev->dev, "Cannot allocate gpios array"); 114 return -ENOMEM; 115 } 116 117 for (i = 0; i < mux->data.n_gpios; i++) { 118 ret = of_get_named_gpio(np, "mux-gpios", i); 119 if (ret < 0) 120 return ret; 121 gpios[i] = ret; 122 } 123 124 mux->data.gpios = gpios; 125 126 return 0; 127 } 128 #else 129 static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, 130 struct platform_device *pdev) 131 { 132 return 0; 133 } 134 #endif 135 136 static int i2c_mux_gpio_probe(struct platform_device *pdev) 137 { 138 struct i2c_mux_core *muxc; 139 struct gpiomux *mux; 140 struct i2c_adapter *parent; 141 struct i2c_adapter *root; 142 unsigned initial_state, gpio_base; 143 int i, ret; 144 145 mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); 146 if (!mux) 147 return -ENOMEM; 148 149 if (!dev_get_platdata(&pdev->dev)) { 150 ret = i2c_mux_gpio_probe_dt(mux, pdev); 151 if (ret < 0) 152 return ret; 153 } else { 154 memcpy(&mux->data, dev_get_platdata(&pdev->dev), 155 sizeof(mux->data)); 156 } 157 158 /* 159 * If a GPIO chip name is provided, the GPIO pin numbers provided are 160 * relative to its base GPIO number. Otherwise they are absolute. 161 */ 162 if (mux->data.gpio_chip) { 163 struct gpio_chip *gpio; 164 165 gpio = gpiochip_find(mux->data.gpio_chip, 166 match_gpio_chip_by_label); 167 if (!gpio) 168 return -EPROBE_DEFER; 169 170 gpio_base = gpio->base; 171 } else { 172 gpio_base = 0; 173 } 174 175 parent = i2c_get_adapter(mux->data.parent); 176 if (!parent) 177 return -EPROBE_DEFER; 178 179 muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0, 180 i2c_mux_gpio_select, NULL); 181 if (!muxc) { 182 ret = -ENOMEM; 183 goto alloc_failed; 184 } 185 muxc->priv = mux; 186 187 platform_set_drvdata(pdev, muxc); 188 189 root = i2c_root_adapter(&parent->dev); 190 191 muxc->mux_locked = true; 192 mux->gpio_base = gpio_base; 193 194 if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) { 195 initial_state = mux->data.idle; 196 muxc->deselect = i2c_mux_gpio_deselect; 197 } else { 198 initial_state = mux->data.values[0]; 199 } 200 201 for (i = 0; i < mux->data.n_gpios; i++) { 202 struct device *gpio_dev; 203 struct gpio_desc *gpio_desc; 204 205 ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio"); 206 if (ret) { 207 dev_err(&pdev->dev, "Failed to request GPIO %d\n", 208 mux->data.gpios[i]); 209 goto err_request_gpio; 210 } 211 212 ret = gpio_direction_output(gpio_base + mux->data.gpios[i], 213 initial_state & (1 << i)); 214 if (ret) { 215 dev_err(&pdev->dev, 216 "Failed to set direction of GPIO %d to output\n", 217 mux->data.gpios[i]); 218 i++; /* gpio_request above succeeded, so must free */ 219 goto err_request_gpio; 220 } 221 222 if (!muxc->mux_locked) 223 continue; 224 225 gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]); 226 gpio_dev = &gpio_desc->gdev->dev; 227 muxc->mux_locked = i2c_root_adapter(gpio_dev) == root; 228 } 229 230 if (muxc->mux_locked) 231 dev_info(&pdev->dev, "mux-locked i2c mux\n"); 232 233 for (i = 0; i < mux->data.n_values; i++) { 234 u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; 235 unsigned int class = mux->data.classes ? mux->data.classes[i] : 0; 236 237 ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); 238 if (ret) { 239 dev_err(&pdev->dev, "Failed to add adapter %d\n", i); 240 goto add_adapter_failed; 241 } 242 } 243 244 dev_info(&pdev->dev, "%d port mux on %s adapter\n", 245 mux->data.n_values, parent->name); 246 247 return 0; 248 249 add_adapter_failed: 250 i2c_mux_del_adapters(muxc); 251 i = mux->data.n_gpios; 252 err_request_gpio: 253 for (; i > 0; i--) 254 gpio_free(gpio_base + mux->data.gpios[i - 1]); 255 alloc_failed: 256 i2c_put_adapter(parent); 257 258 return ret; 259 } 260 261 static int i2c_mux_gpio_remove(struct platform_device *pdev) 262 { 263 struct i2c_mux_core *muxc = platform_get_drvdata(pdev); 264 struct gpiomux *mux = i2c_mux_priv(muxc); 265 int i; 266 267 i2c_mux_del_adapters(muxc); 268 269 for (i = 0; i < mux->data.n_gpios; i++) 270 gpio_free(mux->gpio_base + mux->data.gpios[i]); 271 272 i2c_put_adapter(muxc->parent); 273 274 return 0; 275 } 276 277 static const struct of_device_id i2c_mux_gpio_of_match[] = { 278 { .compatible = "i2c-mux-gpio", }, 279 {}, 280 }; 281 MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match); 282 283 static struct platform_driver i2c_mux_gpio_driver = { 284 .probe = i2c_mux_gpio_probe, 285 .remove = i2c_mux_gpio_remove, 286 .driver = { 287 .name = "i2c-mux-gpio", 288 .of_match_table = i2c_mux_gpio_of_match, 289 }, 290 }; 291 292 module_platform_driver(i2c_mux_gpio_driver); 293 294 MODULE_DESCRIPTION("GPIO-based I2C multiplexer driver"); 295 MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>"); 296 MODULE_LICENSE("GPL"); 297 MODULE_ALIAS("platform:i2c-mux-gpio"); 298