Revert "Merge commit 'main-jb-2012.08.03-B4' into t114-0806"
[linux-2.6.git] / arch / arm / mach-tegra / i2c_error_recovery.c
1 /*\r
2  * arch/arm/mach-tegra/i2c_error_recovery.c\r
3  *\r
4  * Copyright (c) 2011, NVIDIA Corporation.\r
5  *\r
6  * This program is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * This program is distributed in the hope that it will be useful, but WITHOUT\r
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
14  * more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License along\r
17  * with this program; if not, write to the Free Software Foundation, Inc.,\r
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19  */\r
20 #include <linux/gpio.h>\r
21 #include <linux/delay.h>\r
22 #include <linux/init.h>\r
23 \r
24 #include <mach/gpio-tegra.h>\r
25 \r
26 #include "board.h"\r
27 \r
28 #define RETRY_MAX_COUNT (9*8+1) /*I2C controller supports eight-byte burst transfer*/\r
29 \r
30 int arb_lost_recovery(int scl_gpio, int sda_gpio)\r
31 {\r
32         int ret;\r
33         int retry = RETRY_MAX_COUNT;\r
34         int recovered_successfully = 0;\r
35         int val;\r
36 \r
37         if ((!scl_gpio) || (!sda_gpio)) {\r
38                 pr_err("not proper input:scl_gpio 0x%08x,"\r
39                         "sda_gpio 0x%08x\n", scl_gpio, sda_gpio);\r
40                 return -EINVAL;;\r
41         }\r
42 \r
43         ret = gpio_request(scl_gpio, "scl_gpio");\r
44         if (ret < 0) {\r
45                 pr_err("error in gpio 0x%08x request 0x%08x\n",\r
46                         scl_gpio, ret);\r
47                 return -EINVAL;;\r
48         }\r
49         tegra_gpio_enable(scl_gpio);\r
50 \r
51         ret = gpio_request(sda_gpio, "sda_gpio");\r
52         if (ret < 0) {\r
53                 pr_err("error in gpio 0x%08x request 0x%08x\n",\r
54                         sda_gpio, ret);\r
55                 goto err;\r
56         }\r
57         tegra_gpio_enable(sda_gpio);\r
58         gpio_direction_input(sda_gpio);\r
59 \r
60         while (retry--) {\r
61                 gpio_direction_output(scl_gpio,0);\r
62                 udelay(5);\r
63                 gpio_direction_output(scl_gpio,1);\r
64                 udelay(5);\r
65 \r
66                 /* check whether sda struct low release */\r
67                 val = gpio_get_value(sda_gpio);\r
68                 if (val) {\r
69                         /* send START */\r
70                         gpio_direction_output(sda_gpio,0);\r
71                         udelay(5);\r
72 \r
73                         /* send STOP in next clock cycle */\r
74                         gpio_direction_output(scl_gpio,0);\r
75                         udelay(5);\r
76                         gpio_direction_output(scl_gpio,1);\r
77                         udelay(5);\r
78                         gpio_direction_output(sda_gpio,1);\r
79                         udelay(5);\r
80 \r
81                         recovered_successfully = 1;\r
82                         break;\r
83                 }\r
84         }\r
85 \r
86         gpio_free(scl_gpio);\r
87         tegra_gpio_disable(scl_gpio);\r
88         gpio_free(sda_gpio);\r
89         tegra_gpio_disable(sda_gpio);\r
90 \r
91         if (likely(recovered_successfully)) {\r
92                 pr_err("arbitration lost recovered by re-try-count 0x%08x\n",\r
93                         RETRY_MAX_COUNT - retry);\r
94                 return 0;\r
95         } else {\r
96                 pr_err("Un-recovered arbitration lost.\n");\r
97                 return -EINVAL;\r
98         }\r
99 \r
100 err:\r
101         gpio_free(scl_gpio);\r
102         tegra_gpio_disable(scl_gpio);\r
103         return ret;\r
104 }\r
105 \r