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/init.h> 16 #include <linux/module.h> 17 #include <linux/slab.h> 18 #include <linux/gpio.h> 19 20 struct gpiomux { 21 struct i2c_adapter *parent; 22 struct i2c_adapter **adap; /* child busses */ 23 struct i2c_mux_gpio_platform_data data; 24 unsigned gpio_base; 25 }; 26 27 static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val) 28 { 29 int i; 30 31 for (i = 0; i < mux->data.n_gpios; i++) 32 gpio_set_value(mux->gpio_base + mux->data.gpios[i], 33 val & (1 << i)); 34 } 35 36 static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan) 37 { 38 struct gpiomux *mux = data; 39 40 i2c_mux_gpio_set(mux, mux->data.values[chan]); 41 42 return 0; 43 } 44 45 static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan) 46 { 47 struct gpiomux *mux = data; 48 49 i2c_mux_gpio_set(mux, mux->data.idle); 50 51 return 0; 52 } 53 54 static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip, 55 void *data) 56 { 57 return !strcmp(chip->label, data); 58 } 59 60 static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev) 61 { 62 struct gpiomux *mux; 63 struct i2c_mux_gpio_platform_data *pdata; 64 struct i2c_adapter *parent; 65 int (*deselect) (struct i2c_adapter *, void *, u32); 66 unsigned initial_state, gpio_base; 67 int i, ret; 68 69 pdata = pdev->dev.platform_data; 70 if (!pdata) { 71 dev_err(&pdev->dev, "Missing platform data\n"); 72 return -ENODEV; 73 } 74 75 /* 76 * If a GPIO chip name is provided, the GPIO pin numbers provided are 77 * relative to its base GPIO number. Otherwise they are absolute. 78 */ 79 if (pdata->gpio_chip) { 80 struct gpio_chip *gpio; 81 82 gpio = gpiochip_find(pdata->gpio_chip, 83 match_gpio_chip_by_label); 84 if (!gpio) 85 return -EPROBE_DEFER; 86 87 gpio_base = gpio->base; 88 } else { 89 gpio_base = 0; 90 } 91 92 parent = i2c_get_adapter(pdata->parent); 93 if (!parent) { 94 dev_err(&pdev->dev, "Parent adapter (%d) not found\n", 95 pdata->parent); 96 return -ENODEV; 97 } 98 99 mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); 100 if (!mux) { 101 ret = -ENOMEM; 102 goto alloc_failed; 103 } 104 105 mux->parent = parent; 106 mux->data = *pdata; 107 mux->gpio_base = gpio_base; 108 mux->adap = devm_kzalloc(&pdev->dev, 109 sizeof(*mux->adap) * pdata->n_values, 110 GFP_KERNEL); 111 if (!mux->adap) { 112 ret = -ENOMEM; 113 goto alloc_failed; 114 } 115 116 if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) { 117 initial_state = pdata->idle; 118 deselect = i2c_mux_gpio_deselect; 119 } else { 120 initial_state = pdata->values[0]; 121 deselect = NULL; 122 } 123 124 for (i = 0; i < pdata->n_gpios; i++) { 125 ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio"); 126 if (ret) 127 goto err_request_gpio; 128 gpio_direction_output(gpio_base + pdata->gpios[i], 129 initial_state & (1 << i)); 130 } 131 132 for (i = 0; i < pdata->n_values; i++) { 133 u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; 134 unsigned int class = pdata->classes ? pdata->classes[i] : 0; 135 136 mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, 137 i, class, 138 i2c_mux_gpio_select, deselect); 139 if (!mux->adap[i]) { 140 ret = -ENODEV; 141 dev_err(&pdev->dev, "Failed to add adapter %d\n", i); 142 goto add_adapter_failed; 143 } 144 } 145 146 dev_info(&pdev->dev, "%d port mux on %s adapter\n", 147 pdata->n_values, parent->name); 148 149 platform_set_drvdata(pdev, mux); 150 151 return 0; 152 153 add_adapter_failed: 154 for (; i > 0; i--) 155 i2c_del_mux_adapter(mux->adap[i - 1]); 156 i = pdata->n_gpios; 157 err_request_gpio: 158 for (; i > 0; i--) 159 gpio_free(gpio_base + pdata->gpios[i - 1]); 160 alloc_failed: 161 i2c_put_adapter(parent); 162 163 return ret; 164 } 165 166 static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev) 167 { 168 struct gpiomux *mux = platform_get_drvdata(pdev); 169 int i; 170 171 for (i = 0; i < mux->data.n_values; i++) 172 i2c_del_mux_adapter(mux->adap[i]); 173 174 for (i = 0; i < mux->data.n_gpios; i++) 175 gpio_free(mux->gpio_base + mux->data.gpios[i]); 176 177 platform_set_drvdata(pdev, NULL); 178 i2c_put_adapter(mux->parent); 179 180 return 0; 181 } 182 183 static struct platform_driver i2c_mux_gpio_driver = { 184 .probe = i2c_mux_gpio_probe, 185 .remove = __devexit_p(i2c_mux_gpio_remove), 186 .driver = { 187 .owner = THIS_MODULE, 188 .name = "i2c-mux-gpio", 189 }, 190 }; 191 192 module_platform_driver(i2c_mux_gpio_driver); 193 194 MODULE_DESCRIPTION("GPIO-based I2C multiplexer driver"); 195 MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>"); 196 MODULE_LICENSE("GPL"); 197 MODULE_ALIAS("platform:i2c-mux-gpio"); 198