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