1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * I2C multiplexer using GPIO API 4 * 5 * Copyright 2017 NXP 6 * 7 * Peng Fan <peng.fan@nxp.com> 8 */ 9 10 #include <asm/io.h> 11 #include <asm-generic/gpio.h> 12 #include <common.h> 13 #include <dm.h> 14 #include <dm/pinctrl.h> 15 #include <fdtdec.h> 16 #include <i2c.h> 17 #include <linux/errno.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 /** 22 * struct i2c_mux_gpio_priv - private data for i2c mux gpio 23 * 24 * @values: the reg value of each child node 25 * @n_values: num of regs 26 * @gpios: the mux-gpios array 27 * @n_gpios: num of gpios in mux-gpios 28 * @idle: the value of idle-state 29 */ 30 struct i2c_mux_gpio_priv { 31 u32 *values; 32 int n_values; 33 struct gpio_desc *gpios; 34 int n_gpios; 35 u32 idle; 36 }; 37 38 39 static int i2c_mux_gpio_select(struct udevice *dev, struct udevice *bus, 40 uint channel) 41 { 42 struct i2c_mux_gpio_priv *priv = dev_get_priv(dev); 43 int i, ret; 44 45 for (i = 0; i < priv->n_gpios; i++) { 46 ret = dm_gpio_set_value(&priv->gpios[i], (channel >> i) & 1); 47 if (ret) 48 return ret; 49 } 50 51 return 0; 52 } 53 54 static int i2c_mux_gpio_deselect(struct udevice *dev, struct udevice *bus, 55 uint channel) 56 { 57 struct i2c_mux_gpio_priv *priv = dev_get_priv(dev); 58 int i, ret; 59 60 for (i = 0; i < priv->n_gpios; i++) { 61 ret = dm_gpio_set_value(&priv->gpios[i], (priv->idle >> i) & 1); 62 if (ret) 63 return ret; 64 } 65 66 return 0; 67 } 68 69 static int i2c_mux_gpio_probe(struct udevice *dev) 70 { 71 const void *fdt = gd->fdt_blob; 72 int node = dev_of_offset(dev); 73 struct i2c_mux_gpio_priv *mux = dev_get_priv(dev); 74 struct gpio_desc *gpios; 75 u32 *values; 76 int i = 0, subnode, ret; 77 78 mux->n_values = fdtdec_get_child_count(fdt, node); 79 values = devm_kzalloc(dev, sizeof(*mux->values) * mux->n_values, 80 GFP_KERNEL); 81 if (!values) { 82 dev_err(dev, "Cannot alloc values array"); 83 return -ENOMEM; 84 } 85 86 fdt_for_each_subnode(subnode, fdt, node) { 87 *(values + i) = fdtdec_get_uint(fdt, subnode, "reg", -1); 88 i++; 89 } 90 91 mux->values = values; 92 93 mux->idle = fdtdec_get_uint(fdt, node, "idle-state", -1); 94 95 mux->n_gpios = gpio_get_list_count(dev, "mux-gpios"); 96 if (mux->n_gpios < 0) { 97 dev_err(dev, "Missing mux-gpios property\n"); 98 return -EINVAL; 99 } 100 101 gpios = devm_kzalloc(dev, sizeof(struct gpio_desc) * mux->n_gpios, 102 GFP_KERNEL); 103 if (!gpios) { 104 dev_err(dev, "Cannot allocate gpios array\n"); 105 return -ENOMEM; 106 } 107 108 ret = gpio_request_list_by_name(dev, "mux-gpios", gpios, mux->n_gpios, 109 GPIOD_IS_OUT_ACTIVE); 110 if (ret <= 0) { 111 dev_err(dev, "Failed to request mux-gpios\n"); 112 return ret; 113 } 114 115 mux->gpios = gpios; 116 117 return 0; 118 } 119 120 static const struct i2c_mux_ops i2c_mux_gpio_ops = { 121 .select = i2c_mux_gpio_select, 122 .deselect = i2c_mux_gpio_deselect, 123 }; 124 125 static const struct udevice_id i2c_mux_gpio_ids[] = { 126 { .compatible = "i2c-mux-gpio", }, 127 {} 128 }; 129 130 U_BOOT_DRIVER(i2c_mux_gpio) = { 131 .name = "i2c_mux_gpio", 132 .id = UCLASS_I2C_MUX, 133 .of_match = i2c_mux_gpio_ids, 134 .ops = &i2c_mux_gpio_ops, 135 .probe = i2c_mux_gpio_probe, 136 .priv_auto_alloc_size = sizeof(struct i2c_mux_gpio_priv), 137 }; 138