1 /* 2 * GPIO-based I2C Arbitration Using a Challenge & Response Mechanism 3 * 4 * Copyright (C) 2012 Google, Inc 5 * 6 * This software is licensed under the terms of the GNU General Public 7 * License version 2, as published by the Free Software Foundation, and 8 * may be copied, distributed, and modified under those terms. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 */ 16 17 #include <linux/delay.h> 18 #include <linux/gpio.h> 19 #include <linux/kernel.h> 20 #include <linux/i2c.h> 21 #include <linux/i2c-mux.h> 22 #include <linux/module.h> 23 #include <linux/of_gpio.h> 24 #include <linux/platform_device.h> 25 #include <linux/slab.h> 26 27 28 /** 29 * struct i2c_arbitrator_data - Driver data for I2C arbitrator 30 * 31 * @our_gpio: GPIO we'll use to claim. 32 * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == 33 * this then consider it released. 34 * @their_gpio: GPIO that the other side will use to claim. 35 * @their_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == 36 * this then consider it released. 37 * @slew_delay_us: microseconds to wait for a GPIO to go high. 38 * @wait_retry_us: we'll attempt another claim after this many microseconds. 39 * @wait_free_us: we'll give up after this many microseconds. 40 */ 41 42 struct i2c_arbitrator_data { 43 int our_gpio; 44 int our_gpio_release; 45 int their_gpio; 46 int their_gpio_release; 47 unsigned int slew_delay_us; 48 unsigned int wait_retry_us; 49 unsigned int wait_free_us; 50 }; 51 52 53 /** 54 * i2c_arbitrator_select - claim the I2C bus 55 * 56 * Use the GPIO-based signalling protocol; return -EBUSY if we fail. 57 */ 58 static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) 59 { 60 const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); 61 unsigned long stop_retry, stop_time; 62 63 /* Start a round of trying to claim the bus */ 64 stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; 65 do { 66 /* Indicate that we want to claim the bus */ 67 gpio_set_value(arb->our_gpio, !arb->our_gpio_release); 68 udelay(arb->slew_delay_us); 69 70 /* Wait for the other master to release it */ 71 stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; 72 while (time_before(jiffies, stop_retry)) { 73 int gpio_val = !!gpio_get_value(arb->their_gpio); 74 75 if (gpio_val == arb->their_gpio_release) { 76 /* We got it, so return */ 77 return 0; 78 } 79 80 usleep_range(50, 200); 81 } 82 83 /* It didn't release, so give up, wait, and try again */ 84 gpio_set_value(arb->our_gpio, arb->our_gpio_release); 85 86 usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2); 87 } while (time_before(jiffies, stop_time)); 88 89 /* Give up, release our claim */ 90 gpio_set_value(arb->our_gpio, arb->our_gpio_release); 91 udelay(arb->slew_delay_us); 92 dev_err(muxc->dev, "Could not claim bus, timeout\n"); 93 return -EBUSY; 94 } 95 96 /** 97 * i2c_arbitrator_deselect - release the I2C bus 98 * 99 * Release the I2C bus using the GPIO-based signalling protocol. 100 */ 101 static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan) 102 { 103 const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); 104 105 /* Release the bus and wait for the other master to notice */ 106 gpio_set_value(arb->our_gpio, arb->our_gpio_release); 107 udelay(arb->slew_delay_us); 108 109 return 0; 110 } 111 112 static int i2c_arbitrator_probe(struct platform_device *pdev) 113 { 114 struct device *dev = &pdev->dev; 115 struct device_node *np = dev->of_node; 116 struct device_node *parent_np; 117 struct i2c_mux_core *muxc; 118 struct i2c_arbitrator_data *arb; 119 enum of_gpio_flags gpio_flags; 120 unsigned long out_init; 121 int ret; 122 123 /* We only support probing from device tree; no platform_data */ 124 if (!np) { 125 dev_err(dev, "Cannot find device tree node\n"); 126 return -ENODEV; 127 } 128 if (dev_get_platdata(dev)) { 129 dev_err(dev, "Platform data is not supported\n"); 130 return -EINVAL; 131 } 132 133 muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), I2C_MUX_ARBITRATOR, 134 i2c_arbitrator_select, i2c_arbitrator_deselect); 135 if (!muxc) 136 return -ENOMEM; 137 arb = i2c_mux_priv(muxc); 138 139 platform_set_drvdata(pdev, muxc); 140 141 /* Request GPIOs */ 142 ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags); 143 if (!gpio_is_valid(ret)) { 144 if (ret != -EPROBE_DEFER) 145 dev_err(dev, "Error getting our-claim-gpio\n"); 146 return ret; 147 } 148 arb->our_gpio = ret; 149 arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); 150 out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? 151 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 152 ret = devm_gpio_request_one(dev, arb->our_gpio, out_init, 153 "our-claim-gpio"); 154 if (ret) { 155 if (ret != -EPROBE_DEFER) 156 dev_err(dev, "Error requesting our-claim-gpio\n"); 157 return ret; 158 } 159 160 ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags); 161 if (!gpio_is_valid(ret)) { 162 if (ret != -EPROBE_DEFER) 163 dev_err(dev, "Error getting their-claim-gpio\n"); 164 return ret; 165 } 166 arb->their_gpio = ret; 167 arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); 168 ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN, 169 "their-claim-gpio"); 170 if (ret) { 171 if (ret != -EPROBE_DEFER) 172 dev_err(dev, "Error requesting their-claim-gpio\n"); 173 return ret; 174 } 175 176 /* At the moment we only support a single two master (us + 1 other) */ 177 if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) { 178 dev_err(dev, "Only one other master is supported\n"); 179 return -EINVAL; 180 } 181 182 /* Arbitration parameters */ 183 if (of_property_read_u32(np, "slew-delay-us", &arb->slew_delay_us)) 184 arb->slew_delay_us = 10; 185 if (of_property_read_u32(np, "wait-retry-us", &arb->wait_retry_us)) 186 arb->wait_retry_us = 3000; 187 if (of_property_read_u32(np, "wait-free-us", &arb->wait_free_us)) 188 arb->wait_free_us = 50000; 189 190 /* Find our parent */ 191 parent_np = of_parse_phandle(np, "i2c-parent", 0); 192 if (!parent_np) { 193 dev_err(dev, "Cannot parse i2c-parent\n"); 194 return -EINVAL; 195 } 196 muxc->parent = of_get_i2c_adapter_by_node(parent_np); 197 of_node_put(parent_np); 198 if (!muxc->parent) { 199 dev_err(dev, "Cannot find parent bus\n"); 200 return -EPROBE_DEFER; 201 } 202 203 /* Actually add the mux adapter */ 204 ret = i2c_mux_add_adapter(muxc, 0, 0, 0); 205 if (ret) 206 i2c_put_adapter(muxc->parent); 207 208 return ret; 209 } 210 211 static int i2c_arbitrator_remove(struct platform_device *pdev) 212 { 213 struct i2c_mux_core *muxc = platform_get_drvdata(pdev); 214 215 i2c_mux_del_adapters(muxc); 216 i2c_put_adapter(muxc->parent); 217 return 0; 218 } 219 220 static const struct of_device_id i2c_arbitrator_of_match[] = { 221 { .compatible = "i2c-arb-gpio-challenge", }, 222 {}, 223 }; 224 MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match); 225 226 static struct platform_driver i2c_arbitrator_driver = { 227 .probe = i2c_arbitrator_probe, 228 .remove = i2c_arbitrator_remove, 229 .driver = { 230 .name = "i2c-arb-gpio-challenge", 231 .of_match_table = i2c_arbitrator_of_match, 232 }, 233 }; 234 235 module_platform_driver(i2c_arbitrator_driver); 236 237 MODULE_DESCRIPTION("GPIO-based I2C Arbitration"); 238 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>"); 239 MODULE_LICENSE("GPL v2"); 240 MODULE_ALIAS("platform:i2c-arb-gpio-challenge"); 241