arm: tegra: cardhu: Added I2C arbitration lost recovery mechanism
Alok Chauhan [Tue, 26 Jul 2011 10:30:32 +0000 (15:30 +0530)]
Added the code for arbitration lost recovery mechanism for i2c
driver and Initialize gpio number for i2c clock and data as
part of platform data.

bug 854305

Original-Change-Id: Icdc243a5025c766d65816542a6d5aabd61e6eee1
Reviewed-on: http://git-master/r/43200
Reviewed-by: Bandi Krishna Chaitanya <bandik@nvidia.com>
Tested-by: Bandi Krishna Chaitanya <bandik@nvidia.com>
Reviewed-by: Alok Chauhan <alokc@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>

Rebase-Id: R11e00587725418e6e6ef5d0fa2f718424cc0635e

arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-cardhu.c
arch/arm/mach-tegra/board-enterprise.c
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/i2c_error_recovery.c [new file with mode: 0644]

index 6132ab0..ed30b20 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += sleep-t3.o
 obj-y                                   += fuse.o
 obj-y                                   += kfuse.o
 obj-y                                   += tegra_odm_fuses.o
+obj-y                                   += i2c_error_recovery.o
 obj-$(CONFIG_TEGRA_LEGACY_AUDIO)        += tegra_i2s_audio.o
 obj-$(CONFIG_TEGRA_LEGACY_AUDIO)        += tegra_spdif_audio.o
 obj-y                                   += mc.o
index c468415..b63f958 100644 (file)
@@ -192,6 +192,9 @@ static struct tegra_i2c_platform_data cardhu_i2c1_platform_data = {
        .adapter_nr     = 0,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PC4,
+       .sda_gpio               = TEGRA_GPIO_PC5,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data cardhu_i2c2_platform_data = {
@@ -199,24 +202,36 @@ static struct tegra_i2c_platform_data cardhu_i2c2_platform_data = {
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
        .is_clkon_always = true,
+       .scl_gpio               = TEGRA_GPIO_PT5,
+       .sda_gpio               = TEGRA_GPIO_PT6,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data cardhu_i2c3_platform_data = {
        .adapter_nr     = 2,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PBB1,
+       .sda_gpio               = TEGRA_GPIO_PBB2,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data cardhu_i2c4_platform_data = {
        .adapter_nr     = 3,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PV4,
+       .sda_gpio               = TEGRA_GPIO_PV5,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data cardhu_i2c5_platform_data = {
        .adapter_nr     = 4,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PZ6,
+       .sda_gpio               = TEGRA_GPIO_PZ7,
+       .arb_recovery = arb_lost_recovery,
 };
 
 
index 430e685..526dca2 100644 (file)
@@ -186,6 +186,9 @@ static struct tegra_i2c_platform_data enterprise_i2c1_platform_data = {
        .adapter_nr     = 0,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PC4,
+       .sda_gpio               = TEGRA_GPIO_PC5,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data enterprise_i2c2_platform_data = {
@@ -193,24 +196,36 @@ static struct tegra_i2c_platform_data enterprise_i2c2_platform_data = {
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
        .is_clkon_always = true,
+       .scl_gpio               = TEGRA_GPIO_PT5,
+       .sda_gpio               = TEGRA_GPIO_PT6,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data enterprise_i2c3_platform_data = {
        .adapter_nr     = 2,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PBB1,
+       .sda_gpio               = TEGRA_GPIO_PBB2,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data enterprise_i2c4_platform_data = {
        .adapter_nr     = 3,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PV4,
+       .sda_gpio               = TEGRA_GPIO_PV5,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static struct tegra_i2c_platform_data enterprise_i2c5_platform_data = {
        .adapter_nr     = 4,
        .bus_count      = 1,
        .bus_clk_rate   = { 100000, 0 },
+       .scl_gpio               = TEGRA_GPIO_PZ6,
+       .sda_gpio               = TEGRA_GPIO_PZ7,
+       .arb_recovery = arb_lost_recovery,
 };
 
 static void enterprise_i2c_init(void)
index 942a186..66800ce 100644 (file)
@@ -47,6 +47,7 @@ void __init tegra_protected_aperture_init(unsigned long aperture);
 void tegra_move_framebuffer(unsigned long to, unsigned long from,
        unsigned long size);
 bool is_tegra_debug_uartport_hs(void);
+int arb_lost_recovery(int scl_gpio, int sda_gpio);
 
 extern unsigned long tegra_bootloader_fb_start;
 extern unsigned long tegra_bootloader_fb_size;
diff --git a/arch/arm/mach-tegra/i2c_error_recovery.c b/arch/arm/mach-tegra/i2c_error_recovery.c
new file mode 100644 (file)
index 0000000..bea3133
--- /dev/null
@@ -0,0 +1,104 @@
+/*\r
+ * arch/arm/mach-tegra/i2c_error_recovery.c\r
+ *\r
+ * Copyright (c) 2011, NVIDIA Corporation.\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+ * more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
+ */\r
+#include <linux/gpio.h>\r
+#include <linux/delay.h>\r
+#include <linux/init.h>\r
+\r
+#include "gpio-names.h"\r
+#include "board.h"\r
+\r
+#define RETRY_MAX_COUNT (9*8+1) /*I2C controller supports eight-byte burst transfer*/\r
+\r
+int arb_lost_recovery(int scl_gpio, int sda_gpio)\r
+{\r
+       int ret;\r
+       int retry = RETRY_MAX_COUNT;\r
+       int recovered_successfully = 0;\r
+       int val;\r
+\r
+       if ((!scl_gpio) || (!sda_gpio)) {\r
+               pr_err("not proper input:scl_gpio 0x%08x,"\r
+                       "sda_gpio 0x%08x\n", scl_gpio, sda_gpio);\r
+               return -EINVAL;;\r
+       }\r
+\r
+       ret = gpio_request(scl_gpio, "scl_gpio");\r
+       if (ret < 0) {\r
+               pr_err("error in gpio 0x%08x request 0x%08x\n",\r
+                       scl_gpio, ret);\r
+               return -EINVAL;;\r
+       }\r
+       tegra_gpio_enable(scl_gpio);\r
+\r
+       ret = gpio_request(sda_gpio, "sda_gpio");\r
+       if (ret < 0) {\r
+               pr_err("error in gpio 0x%08x request 0x%08x\n",\r
+                       sda_gpio, ret);\r
+               goto err;\r
+       }\r
+       tegra_gpio_enable(sda_gpio);\r
+       gpio_direction_input(sda_gpio);\r
+\r
+       while (retry--) {\r
+               gpio_direction_output(scl_gpio,0);\r
+               udelay(5);\r
+               gpio_direction_output(scl_gpio,1);\r
+               udelay(5);\r
+\r
+               /* check whether sda struct low release */\r
+               val = gpio_get_value(sda_gpio);\r
+               if (val) {\r
+                       /* send START */\r
+                       gpio_direction_output(sda_gpio,0);\r
+                       udelay(5);\r
+\r
+                       /* send STOP in next clock cycle */\r
+                       gpio_direction_output(scl_gpio,0);\r
+                       udelay(5);\r
+                       gpio_direction_output(scl_gpio,1);\r
+                       udelay(5);\r
+                       gpio_direction_output(sda_gpio,1);\r
+                       udelay(5);\r
+\r
+                       recovered_successfully = 1;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       gpio_free(scl_gpio);\r
+       tegra_gpio_disable(scl_gpio);\r
+       gpio_free(sda_gpio);\r
+       tegra_gpio_disable(sda_gpio);\r
+\r
+       if (likely(recovered_successfully)) {\r
+               pr_err("arbitration lost recovered by re-try-count 0x%08x\n",\r
+                       RETRY_MAX_COUNT - retry);\r
+               return 0;\r
+       } else {\r
+               pr_err("Un-recovered arbitration lost.\n");\r
+               return -EINVAL;\r
+       }\r
+\r
+err:\r
+       gpio_free(scl_gpio);\r
+       tegra_gpio_disable(scl_gpio);\r
+       return ret;\r
+}\r
+\r