0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/gpio/consumer.h>
0010 #include <linux/kernel.h>
0011 #include <linux/i2c.h>
0012 #include <linux/i2c-mux.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 struct i2c_arbitrator_data {
0029 struct gpio_desc *our_gpio;
0030 struct gpio_desc *their_gpio;
0031 unsigned int slew_delay_us;
0032 unsigned int wait_retry_us;
0033 unsigned int wait_free_us;
0034 };
0035
0036
0037
0038
0039
0040
0041
0042 static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
0043 {
0044 const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
0045 unsigned long stop_retry, stop_time;
0046
0047
0048 stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1;
0049 do {
0050
0051 gpiod_set_value(arb->our_gpio, 1);
0052 udelay(arb->slew_delay_us);
0053
0054
0055 stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1;
0056 while (time_before(jiffies, stop_retry)) {
0057 int gpio_val = gpiod_get_value(arb->their_gpio);
0058
0059 if (!gpio_val) {
0060
0061 return 0;
0062 }
0063
0064 usleep_range(50, 200);
0065 }
0066
0067
0068 gpiod_set_value(arb->our_gpio, 0);
0069
0070 usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2);
0071 } while (time_before(jiffies, stop_time));
0072
0073
0074 gpiod_set_value(arb->our_gpio, 0);
0075 udelay(arb->slew_delay_us);
0076 dev_err(muxc->dev, "Could not claim bus, timeout\n");
0077 return -EBUSY;
0078 }
0079
0080
0081
0082
0083
0084
0085 static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
0086 {
0087 const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
0088
0089
0090 gpiod_set_value(arb->our_gpio, 0);
0091 udelay(arb->slew_delay_us);
0092
0093 return 0;
0094 }
0095
0096 static int i2c_arbitrator_probe(struct platform_device *pdev)
0097 {
0098 struct device *dev = &pdev->dev;
0099 struct device_node *np = dev->of_node;
0100 struct device_node *parent_np;
0101 struct i2c_mux_core *muxc;
0102 struct i2c_arbitrator_data *arb;
0103 struct gpio_desc *dummy;
0104 int ret;
0105
0106
0107 if (!np) {
0108 dev_err(dev, "Cannot find device tree node\n");
0109 return -ENODEV;
0110 }
0111 if (dev_get_platdata(dev)) {
0112 dev_err(dev, "Platform data is not supported\n");
0113 return -EINVAL;
0114 }
0115
0116 muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), I2C_MUX_ARBITRATOR,
0117 i2c_arbitrator_select, i2c_arbitrator_deselect);
0118 if (!muxc)
0119 return -ENOMEM;
0120 arb = i2c_mux_priv(muxc);
0121
0122 platform_set_drvdata(pdev, muxc);
0123
0124
0125 arb->our_gpio = devm_gpiod_get(dev, "our-claim", GPIOD_OUT_LOW);
0126 if (IS_ERR(arb->our_gpio)) {
0127 dev_err(dev, "could not get \"our-claim\" GPIO (%ld)\n",
0128 PTR_ERR(arb->our_gpio));
0129 return PTR_ERR(arb->our_gpio);
0130 }
0131
0132 arb->their_gpio = devm_gpiod_get(dev, "their-claim", GPIOD_IN);
0133 if (IS_ERR(arb->their_gpio)) {
0134 dev_err(dev, "could not get \"their-claim\" GPIO (%ld)\n",
0135 PTR_ERR(arb->their_gpio));
0136 return PTR_ERR(arb->their_gpio);
0137 }
0138
0139
0140 dummy = devm_gpiod_get_index(dev, "their-claim", 1, GPIOD_IN);
0141 if (!IS_ERR(dummy)) {
0142 dev_err(dev, "Only one other master is supported\n");
0143 return -EINVAL;
0144 } else if (PTR_ERR(dummy) == -EPROBE_DEFER) {
0145 return -EPROBE_DEFER;
0146 }
0147
0148
0149 if (of_property_read_u32(np, "slew-delay-us", &arb->slew_delay_us))
0150 arb->slew_delay_us = 10;
0151 if (of_property_read_u32(np, "wait-retry-us", &arb->wait_retry_us))
0152 arb->wait_retry_us = 3000;
0153 if (of_property_read_u32(np, "wait-free-us", &arb->wait_free_us))
0154 arb->wait_free_us = 50000;
0155
0156
0157 parent_np = of_parse_phandle(np, "i2c-parent", 0);
0158 if (!parent_np) {
0159 dev_err(dev, "Cannot parse i2c-parent\n");
0160 return -EINVAL;
0161 }
0162 muxc->parent = of_get_i2c_adapter_by_node(parent_np);
0163 of_node_put(parent_np);
0164 if (!muxc->parent) {
0165 dev_err(dev, "Cannot find parent bus\n");
0166 return -EPROBE_DEFER;
0167 }
0168
0169
0170 ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
0171 if (ret)
0172 i2c_put_adapter(muxc->parent);
0173
0174 return ret;
0175 }
0176
0177 static int i2c_arbitrator_remove(struct platform_device *pdev)
0178 {
0179 struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
0180
0181 i2c_mux_del_adapters(muxc);
0182 i2c_put_adapter(muxc->parent);
0183 return 0;
0184 }
0185
0186 static const struct of_device_id i2c_arbitrator_of_match[] = {
0187 { .compatible = "i2c-arb-gpio-challenge", },
0188 {},
0189 };
0190 MODULE_DEVICE_TABLE(of, i2c_arbitrator_of_match);
0191
0192 static struct platform_driver i2c_arbitrator_driver = {
0193 .probe = i2c_arbitrator_probe,
0194 .remove = i2c_arbitrator_remove,
0195 .driver = {
0196 .name = "i2c-arb-gpio-challenge",
0197 .of_match_table = i2c_arbitrator_of_match,
0198 },
0199 };
0200
0201 module_platform_driver(i2c_arbitrator_driver);
0202
0203 MODULE_DESCRIPTION("GPIO-based I2C Arbitration");
0204 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
0205 MODULE_LICENSE("GPL v2");
0206 MODULE_ALIAS("platform:i2c-arb-gpio-challenge");