Ventana: KBC: Removing the KBC usage on ventana
[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 "gpio-names.h"\r
25 #include "board.h"\r
26 \r
27 #define RETRY_MAX_COUNT (9*8+1) /*I2C controller supports eight-byte burst transfer*/\r
28 \r
29 int arb_lost_recovery(int scl_gpio, int sda_gpio)\r
30 {\r
31         int ret;\r
32         int retry = RETRY_MAX_COUNT;\r
33         int recovered_successfully = 0;\r
34         int val;\r
35 \r
36         if ((!scl_gpio) || (!sda_gpio)) {\r
37                 pr_err("not proper input:scl_gpio 0x%08x,"\r
38                         "sda_gpio 0x%08x\n", scl_gpio, sda_gpio);\r
39                 return -EINVAL;;\r
40         }\r
41 \r
42         ret = gpio_request(scl_gpio, "scl_gpio");\r
43         if (ret < 0) {\r
44                 pr_err("error in gpio 0x%08x request 0x%08x\n",\r
45                         scl_gpio, ret);\r
46                 return -EINVAL;;\r
47         }\r
48         tegra_gpio_enable(scl_gpio);\r
49 \r
50         ret = gpio_request(sda_gpio, "sda_gpio");\r
51         if (ret < 0) {\r
52                 pr_err("error in gpio 0x%08x request 0x%08x\n",\r
53                         sda_gpio, ret);\r
54                 goto err;\r
55         }\r
56         tegra_gpio_enable(sda_gpio);\r
57         gpio_direction_input(sda_gpio);\r
58 \r
59         while (retry--) {\r
60                 gpio_direction_output(scl_gpio,0);\r
61                 udelay(5);\r
62                 gpio_direction_output(scl_gpio,1);\r
63                 udelay(5);\r
64 \r
65                 /* check whether sda struct low release */\r
66                 val = gpio_get_value(sda_gpio);\r
67                 if (val) {\r
68                         /* send START */\r
69                         gpio_direction_output(sda_gpio,0);\r
70                         udelay(5);\r
71 \r
72                         /* send STOP in next clock cycle */\r
73                         gpio_direction_output(scl_gpio,0);\r
74                         udelay(5);\r
75                         gpio_direction_output(scl_gpio,1);\r
76                         udelay(5);\r
77                         gpio_direction_output(sda_gpio,1);\r
78                         udelay(5);\r
79 \r
80                         recovered_successfully = 1;\r
81                         break;\r
82                 }\r
83         }\r
84 \r
85         gpio_free(scl_gpio);\r
86         tegra_gpio_disable(scl_gpio);\r
87         gpio_free(sda_gpio);\r
88         tegra_gpio_disable(sda_gpio);\r
89 \r
90         if (likely(recovered_successfully)) {\r
91                 pr_err("arbitration lost recovered by re-try-count 0x%08x\n",\r
92                         RETRY_MAX_COUNT - retry);\r
93                 return 0;\r
94         } else {\r
95                 pr_err("Un-recovered arbitration lost.\n");\r
96                 return -EINVAL;\r
97         }\r
98 \r
99 err:\r
100         gpio_free(scl_gpio);\r
101         tegra_gpio_disable(scl_gpio);\r
102         return ret;\r
103 }\r
104 \r