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