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