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 * @parent: Parent adapter 32 * @child: Child bus 33 * @our_gpio: GPIO we'll use to claim. 34 * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == 35 * this then consider it released. 36 * @their_gpio: GPIO that the other side will use to claim. 37 * @their_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == 38 * this then consider it released. 39 * @slew_delay_us: microseconds to wait for a GPIO to go high. 40 * @wait_retry_us: we'll attempt another claim after this many microseconds. 41 * @wait_free_us: we'll give up after this many microseconds. 42 */ 43 44struct i2c_arbitrator_data { 45 struct i2c_adapter *parent; 46 struct i2c_adapter *child; 47 int our_gpio; 48 int our_gpio_release; 49 int their_gpio; 50 int their_gpio_release; 51 unsigned int slew_delay_us; 52 unsigned int wait_retry_us; 53 unsigned int wait_free_us; 54}; 55 56 57/** 58 * i2c_arbitrator_select - claim the I2C bus 59 * 60 * Use the GPIO-based signalling protocol; return -EBUSY if we fail. 61 */ 62static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan) 63{ 64 const struct i2c_arbitrator_data *arb = data; 65 unsigned long stop_retry, stop_time; 66 67 /* Start a round of trying to claim the bus */ 68 stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; 69 do { 70 /* Indicate that we want to claim the bus */ 71 gpio_set_value(arb->our_gpio, !arb->our_gpio_release); 72 udelay(arb->slew_delay_us); 73 74 /* Wait for the other master to release it */ 75 stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; 76 while (time_before(jiffies, stop_retry)) { 77 int gpio_val = !!gpio_get_value(arb->their_gpio); 78 79 if (gpio_val == arb->their_gpio_release) { 80 /* We got it, so return */ 81 return 0; 82 } 83 84 usleep_range(50, 200); 85 } 86 87 /* It didn't release, so give up, wait, and try again */ 88 gpio_set_value(arb->our_gpio, arb->our_gpio_release); 89 90 usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2); 91 } while (time_before(jiffies, stop_time)); 92 93 /* Give up, release our claim */ 94 gpio_set_value(arb->our_gpio, arb->our_gpio_release); 95 udelay(arb->slew_delay_us); 96 dev_err(&adap->dev, "Could not claim bus, timeout\n"); 97 return -EBUSY; 98} 99 100/** 101 * i2c_arbitrator_deselect - release the I2C bus 102 * 103 * Release the I2C bus using the GPIO-based signalling protocol. 104 */ 105static int i2c_arbitrator_deselect(struct i2c_adapter *adap, void *data, 106 u32 chan) 107{ 108 const struct i2c_arbitrator_data *arb = data; 109 110 /* Release the bus and wait for the other master to notice */ 111 gpio_set_value(arb->our_gpio, arb->our_gpio_release); 112 udelay(arb->slew_delay_us); 113 114 return 0; 115} 116 117static int i2c_arbitrator_probe(struct platform_device *pdev) 118{ 119 struct device *dev = &pdev->dev; 120 struct device_node *np = dev->of_node; 121 struct device_node *parent_np; 122 struct i2c_arbitrator_data *arb; 123 enum of_gpio_flags gpio_flags; 124 unsigned long out_init; 125 int ret; 126 127 /* We only support probing from device tree; no platform_data */ 128 if (!np) { 129 dev_err(dev, "Cannot find device tree node\n"); 130 return -ENODEV; 131 } 132 if (dev_get_platdata(dev)) { 133 dev_err(dev, "Platform data is not supported\n"); 134 return -EINVAL; 135 } 136 137 arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL); 138 if (!arb) { 139 dev_err(dev, "Cannot allocate i2c_arbitrator_data\n"); 140 return -ENOMEM; 141 } 142 platform_set_drvdata(pdev, arb); 143 144 /* Request GPIOs */ 145 ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags); 146 if (!gpio_is_valid(ret)) { 147 if (ret != -EPROBE_DEFER) 148 dev_err(dev, "Error getting our-claim-gpio\n"); 149 return ret; 150 } 151 arb->our_gpio = ret; 152 arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); 153 out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? 154 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 155 ret = devm_gpio_request_one(dev, arb->our_gpio, out_init, 156 "our-claim-gpio"); 157 if (ret) { 158 if (ret != -EPROBE_DEFER) 159 dev_err(dev, "Error requesting our-claim-gpio\n"); 160 return ret; 161 } 162 163 ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags); 164 if (!gpio_is_valid(ret)) { 165 if (ret != -EPROBE_DEFER) 166 dev_err(dev, "Error getting their-claim-gpio\n"); 167 return ret; 168 } 169 arb->their_gpio = ret; 170 arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); 171 ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN, 172 "their-claim-gpio"); 173 if (ret) { 174 if (ret != -EPROBE_DEFER) 175 dev_err(dev, "Error requesting their-claim-gpio\n"); 176 return ret; 177 } 178 179 /* At the moment we only support a single two master (us + 1 other) */ 180 if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) { 181 dev_err(dev, "Only one other master is supported\n"); 182 return -EINVAL; 183 } 184 185 /* Arbitration parameters */ 186 if (of_property_read_u32(np, "slew-delay-us", &arb->slew_delay_us)) 187 arb->slew_delay_us = 10; 188 if (of_property_read_u32(np, "wait-retry-us", &arb->wait_retry_us)) 189 arb->wait_retry_us = 3000; 190 if (of_property_read_u32(np, "wait-free-us", &arb->wait_free_us)) 191 arb->wait_free_us = 50000; 192 193 /* Find our parent */ 194 parent_np = of_parse_phandle(np, "i2c-parent", 0); 195 if (!parent_np) { 196 dev_err(dev, "Cannot parse i2c-parent\n"); 197 return -EINVAL; 198 } 199 arb->parent = of_find_i2c_adapter_by_node(parent_np); 200 if (!arb->parent) { 201 dev_err(dev, "Cannot find parent bus\n"); 202 return -EPROBE_DEFER; 203 } 204 205 /* Actually add the mux adapter */ 206 arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0, 207 i2c_arbitrator_select, 208 i2c_arbitrator_deselect); 209 if (!arb->child) { 210 dev_err(dev, "Failed to add adapter\n"); 211 ret = -ENODEV; 212 i2c_put_adapter(arb->parent); 213 } 214 215 return ret; 216} 217 218static int i2c_arbitrator_remove(struct platform_device *pdev) 219{ 220 struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev); 221 222 i2c_del_mux_adapter(arb->child); 223 i2c_put_adapter(arb->parent); 224 225 return 0; 226} 227 228static const struct of_device_id i2c_arbitrator_of_match[] = { 229 { .compatible = "i2c-arb-gpio-challenge", }, 230 {}, 231}; 232MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match); 233 234static struct platform_driver i2c_arbitrator_driver = { 235 .probe = i2c_arbitrator_probe, 236 .remove = i2c_arbitrator_remove, 237 .driver = { 238 .name = "i2c-arb-gpio-challenge", 239 .of_match_table = i2c_arbitrator_of_match, 240 }, 241}; 242 243module_platform_driver(i2c_arbitrator_driver); 244 245MODULE_DESCRIPTION("GPIO-based I2C Arbitration"); 246MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>"); 247MODULE_LICENSE("GPL v2"); 248MODULE_ALIAS("platform:i2c-arb-gpio-challenge"); 249