aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2012-02-28 07:56:31 -0500
committerWolfram Sang <wsa@the-dreams.de>2013-03-24 05:30:54 -0400
commit5f9296ba21b3c395e53dd84e7ff9578f97f24295 (patch)
treeddc02adbdaa1b703b04aeee9b8d8f1ca13fa2443
parentee5c27440cc24d62ec463cce4c000bb32c5692c7 (diff)
i2c: Add bus recovery infrastructure
Add i2c bus recovery infrastructure to i2c adapters as specified in the i2c protocol Rev. 03 section 3.1.16 titled "Bus clear". http://www.nxp.com/documents/user_manual/UM10204.pdf Sometimes during operation i2c bus hangs and we need to give dummy clocks to slave device to start the transfer again. Now we may have capability in the bus controller to generate these clocks or platform may have gpio pins which can be toggled to generate dummy clocks. This patch supports both. This patch also adds in generic bus recovery routines gpio or scl line based which can be used by bus controller. In addition controller driver may provide its own version of the bus recovery routine. This doesn't support multi-master recovery for now. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> [wsa: changed gpio type to int and minor reformatting] Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/i2c-core.c159
-rw-r--r--include/linux/i2c.h41
2 files changed, 200 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index f7dfe878a51b..0d873ba2e82e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -27,7 +27,9 @@
27 27
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/delay.h>
30#include <linux/errno.h> 31#include <linux/errno.h>
32#include <linux/gpio.h>
31#include <linux/slab.h> 33#include <linux/slab.h>
32#include <linux/i2c.h> 34#include <linux/i2c.h>
33#include <linux/init.h> 35#include <linux/init.h>
@@ -109,6 +111,130 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
109#define i2c_device_uevent NULL 111#define i2c_device_uevent NULL
110#endif /* CONFIG_HOTPLUG */ 112#endif /* CONFIG_HOTPLUG */
111 113
114/* i2c bus recovery routines */
115static int get_scl_gpio_value(struct i2c_adapter *adap)
116{
117 return gpio_get_value(adap->bus_recovery_info->scl_gpio);
118}
119
120static void set_scl_gpio_value(struct i2c_adapter *adap, int val)
121{
122 gpio_set_value(adap->bus_recovery_info->scl_gpio, val);
123}
124
125static int get_sda_gpio_value(struct i2c_adapter *adap)
126{
127 return gpio_get_value(adap->bus_recovery_info->sda_gpio);
128}
129
130static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap)
131{
132 struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
133 struct device *dev = &adap->dev;
134 int ret = 0;
135
136 ret = gpio_request_one(bri->scl_gpio, GPIOF_OPEN_DRAIN |
137 GPIOF_OUT_INIT_HIGH, "i2c-scl");
138 if (ret) {
139 dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio);
140 return ret;
141 }
142
143 if (bri->get_sda) {
144 if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) {
145 /* work without SDA polling */
146 dev_warn(dev, "Can't get SDA gpio: %d. Not using SDA polling\n",
147 bri->sda_gpio);
148 bri->get_sda = NULL;
149 }
150 }
151
152 return ret;
153}
154
155static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap)
156{
157 struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
158
159 if (bri->get_sda)
160 gpio_free(bri->sda_gpio);
161
162 gpio_free(bri->scl_gpio);
163}
164
165/*
166 * We are generating clock pulses. ndelay() determines durating of clk pulses.
167 * We will generate clock with rate 100 KHz and so duration of both clock levels
168 * is: delay in ns = (10^6 / 100) / 2
169 */
170#define RECOVERY_NDELAY 5000
171#define RECOVERY_CLK_CNT 9
172
173static int i2c_generic_recovery(struct i2c_adapter *adap)
174{
175 struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
176 int i = 0, val = 1, ret = 0;
177
178 if (bri->prepare_recovery)
179 bri->prepare_recovery(bri);
180
181 /*
182 * By this time SCL is high, as we need to give 9 falling-rising edges
183 */
184 while (i++ < RECOVERY_CLK_CNT * 2) {
185 if (val) {
186 /* Break if SDA is high */
187 if (bri->get_sda && bri->get_sda(adap))
188 break;
189 /* SCL shouldn't be low here */
190 if (!bri->get_scl(adap)) {
191 dev_err(&adap->dev,
192 "SCL is stuck low, exit recovery\n");
193 ret = -EBUSY;
194 break;
195 }
196 }
197
198 val = !val;
199 bri->set_scl(adap, val);
200 ndelay(RECOVERY_NDELAY);
201 }
202
203 if (bri->unprepare_recovery)
204 bri->unprepare_recovery(bri);
205
206 return ret;
207}
208
209int i2c_generic_scl_recovery(struct i2c_adapter *adap)
210{
211 adap->bus_recovery_info->set_scl(adap, 1);
212 return i2c_generic_recovery(adap);
213}
214
215int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
216{
217 int ret;
218
219 ret = i2c_get_gpios_for_recovery(adap);
220 if (ret)
221 return ret;
222
223 ret = i2c_generic_recovery(adap);
224 i2c_put_gpios_for_recovery(adap);
225
226 return ret;
227}
228
229int i2c_recover_bus(struct i2c_adapter *adap)
230{
231 if (!adap->bus_recovery_info)
232 return -EOPNOTSUPP;
233
234 dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
235 return adap->bus_recovery_info->recover_bus(adap);
236}
237
112static int i2c_device_probe(struct device *dev) 238static int i2c_device_probe(struct device *dev)
113{ 239{
114 struct i2c_client *client = i2c_verify_client(dev); 240 struct i2c_client *client = i2c_verify_client(dev);
@@ -902,6 +1028,39 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
902 "Failed to create compatibility class link\n"); 1028 "Failed to create compatibility class link\n");
903#endif 1029#endif
904 1030
1031 /* bus recovery specific initialization */
1032 if (adap->bus_recovery_info) {
1033 struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
1034
1035 if (!bri->recover_bus) {
1036 dev_err(&adap->dev, "No recover_bus() found, not using recovery\n");
1037 adap->bus_recovery_info = NULL;
1038 goto exit_recovery;
1039 }
1040
1041 /* Generic GPIO recovery */
1042 if (bri->recover_bus == i2c_generic_gpio_recovery) {
1043 if (!gpio_is_valid(bri->scl_gpio)) {
1044 dev_err(&adap->dev, "Invalid SCL gpio, not using recovery\n");
1045 adap->bus_recovery_info = NULL;
1046 goto exit_recovery;
1047 }
1048
1049 if (gpio_is_valid(bri->sda_gpio))
1050 bri->get_sda = get_sda_gpio_value;
1051 else
1052 bri->get_sda = NULL;
1053
1054 bri->get_scl = get_scl_gpio_value;
1055 bri->set_scl = set_scl_gpio_value;
1056 } else if (!bri->set_scl || !bri->get_scl) {
1057 /* Generic SCL recovery */
1058 dev_err(&adap->dev, "No {get|set}_gpio() found, not using recovery\n");
1059 adap->bus_recovery_info = NULL;
1060 }
1061 }
1062
1063exit_recovery:
905 /* create pre-declared device nodes */ 1064 /* create pre-declared device nodes */
906 if (adap->nr < __i2c_first_dynamic_bus_num) 1065 if (adap->nr < __i2c_first_dynamic_bus_num)
907 i2c_scan_static_board_info(adap); 1066 i2c_scan_static_board_info(adap);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index d0c4db7b4872..2eca3860b77f 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -370,6 +370,45 @@ struct i2c_algorithm {
370 u32 (*functionality) (struct i2c_adapter *); 370 u32 (*functionality) (struct i2c_adapter *);
371}; 371};
372 372
373/**
374 * struct i2c_bus_recovery_info - I2C bus recovery information
375 * @recover_bus: Recover routine. Either pass driver's recover_bus() routine, or
376 * i2c_generic_scl_recovery() or i2c_generic_gpio_recovery().
377 * @get_scl: This gets current value of SCL line. Mandatory for generic SCL
378 * recovery. Used internally for generic GPIO recovery.
379 * @set_scl: This sets/clears SCL line. Mandatory for generic SCL recovery. Used
380 * internally for generic GPIO recovery.
381 * @get_sda: This gets current value of SDA line. Optional for generic SCL
382 * recovery. Used internally, if sda_gpio is a valid GPIO, for generic GPIO
383 * recovery.
384 * @prepare_recovery: This will be called before starting recovery. Platform may
385 * configure padmux here for SDA/SCL line or something else they want.
386 * @unprepare_recovery: This will be called after completing recovery. Platform
387 * may configure padmux here for SDA/SCL line or something else they want.
388 * @scl_gpio: gpio number of the SCL line. Only required for GPIO recovery.
389 * @sda_gpio: gpio number of the SDA line. Only required for GPIO recovery.
390 */
391struct i2c_bus_recovery_info {
392 int (*recover_bus)(struct i2c_adapter *);
393
394 int (*get_scl)(struct i2c_adapter *);
395 void (*set_scl)(struct i2c_adapter *, int val);
396 int (*get_sda)(struct i2c_adapter *);
397
398 void (*prepare_recovery)(struct i2c_bus_recovery_info *bri);
399 void (*unprepare_recovery)(struct i2c_bus_recovery_info *bri);
400
401 /* gpio recovery */
402 int scl_gpio;
403 int sda_gpio;
404};
405
406int i2c_recover_bus(struct i2c_adapter *adap);
407
408/* Generic recovery routines */
409int i2c_generic_gpio_recovery(struct i2c_adapter *adap);
410int i2c_generic_scl_recovery(struct i2c_adapter *adap);
411
373/* 412/*
374 * i2c_adapter is the structure used to identify a physical i2c bus along 413 * i2c_adapter is the structure used to identify a physical i2c bus along
375 * with the access algorithms necessary to access it. 414 * with the access algorithms necessary to access it.
@@ -393,6 +432,8 @@ struct i2c_adapter {
393 432
394 struct mutex userspace_clients_lock; 433 struct mutex userspace_clients_lock;
395 struct list_head userspace_clients; 434 struct list_head userspace_clients;
435
436 struct i2c_bus_recovery_info *bus_recovery_info;
396}; 437};
397#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) 438#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
398 439