arm: tegra: cardhu: IrDA support on UARTB
Ramalingam C [Wed, 11 Jul 2012 09:17:48 +0000 (14:17 +0530)]
Adds the IrDA support functions to the platform_data of UARTB on Verbier
boards(E1198 and E1186). And also adds a config variable CONFIG_TEGRA_IRDA
to control the IrDA support on Tegra.

Bug 999895

Change-Id: Iab77c419004292190421d55fd02e249ff98c728e
Signed-off-by: Ramalingam C <ramalingamc@nvidia.com>
Reviewed-on: http://git-master/r/114930
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

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

index b84d32a..b69f0dc 100644 (file)
@@ -90,6 +90,14 @@ config TEGRA_PCI
        help
          Adds PCIe Host controller driver for tegra based systems
 
+config TEGRA_IRDA
+       bool "IRDA on UARTB Port of Verbier"
+       select IRDA_CPLD
+       depends on ARCH_TEGRA_3x_SOC && MACH_CARDHU
+       help
+         Adds support for Vishay IrDA transceiver at UARTB port
+         of Verbier Boards(E1186 and E1198) with no ULPI rework done.
+
 comment "Tegra board type"
 
 config MACH_HARMONY
index 6a563be..cf51359 100644 (file)
@@ -163,6 +163,7 @@ obj-${CONFIG_MACH_WHISTLER}             += board-whistler-memory.o
 
 obj-${CONFIG_MACH_CARDHU}               += board-cardhu.o
 obj-${CONFIG_MACH_CARDHU}               += board-cardhu-kbc.o
+obj-${CONFIG_MACH_CARDHU}               += board-cardhu-irda.o
 obj-${CONFIG_MACH_CARDHU}               += board-cardhu-panel.o
 obj-${CONFIG_MACH_CARDHU}               += board-cardhu-pinmux.o
 obj-${CONFIG_MACH_CARDHU}               += board-cardhu-power.o
diff --git a/arch/arm/mach-tegra/board-cardhu-irda.c b/arch/arm/mach-tegra/board-cardhu-irda.c
new file mode 100644 (file)
index 0000000..489d473
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * arch/arm/mach-tegra/board-cardhu-irda.c
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* This driver tested with tfdu6103 irda transceiver */
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/serial_8250.h>
+#include <linux/tegra_uart.h>
+
+#include "gpio-names.h"
+#include "board-cardhu.h"
+#include "board.h"
+#include "devices.h"
+
+/* Uncomment the next line to get the function entry logs */
+/*#define DRV_FUNC     1*/
+
+#undef FPRINT
+#ifdef DRV_FUNC
+#define FPRINT(fmt, args...) printk(KERN_INFO "IRDA: " fmt, ## args)
+#else
+#define FPRINT(fmt, args...)
+#endif
+
+#define CARDHU_IRDA_SD TEGRA_GPIO_PJ6
+#define CARDHU_IRDA_TX TEGRA_GPIO_PC2
+#define CARDHU_IRDA_RX TEGRA_GPIO_PC3
+
+#define IRDA_DELAY     1
+
+#define SIR            1
+#define FIR            2
+#define VFIR           3       /* tfdu6108 doesn't support */
+
+
+static int irda_mode;
+
+/* If mode = SIR       mode switch will be FIR -> SIR
+   If mode = FIR       mode switch will be SIR ->FIR   */
+
+static int cardhu_irda_mode_switch(int mode)
+{
+       int ret = -1;
+
+       FPRINT("Start of Func %s\n", __func__);
+
+       if ((mode != SIR) && (mode != FIR)) {
+               pr_err("Unsupported irda mode\n");
+               return ret;
+       }
+
+       gpio_set_value(CARDHU_IRDA_SD, 1);
+
+       udelay(IRDA_DELAY);
+
+       ret = gpio_request(CARDHU_IRDA_TX, "irda_tx");
+       if (ret < 0) {
+               pr_err("%s: cardhu_irda_tx gpio request failed %d\n",
+                                                        __func__, ret);
+               gpio_set_value(CARDHU_IRDA_SD, 0);
+               return ret;
+       }
+
+       if (mode == SIR)
+               ret = gpio_direction_output(CARDHU_IRDA_TX, 0);
+       else if (mode == FIR)
+               ret = gpio_direction_output(CARDHU_IRDA_TX, 1);
+
+       if (ret) {
+               pr_err("%s: cardhu_irda_tx Direction configuration failed %d\n",
+                                                       __func__, ret);
+               gpio_set_value(CARDHU_IRDA_SD, 0);
+               goto closure;
+       }
+
+       udelay(IRDA_DELAY);
+
+       gpio_set_value(CARDHU_IRDA_SD, 0);
+
+       udelay(IRDA_DELAY);
+
+       if (mode == FIR) {
+               gpio_set_value(CARDHU_IRDA_TX, 0);
+               irda_mode = FIR;
+               pr_info("IrDA Transceiver is switched to FIR mode\n");
+       } else {
+               pr_info("IrDA Transceiver is switched to SIR mode\n");
+               irda_mode = SIR;
+       }
+
+       udelay(IRDA_DELAY);
+
+closure:
+       gpio_free(CARDHU_IRDA_TX);
+       return ret;
+}
+
+static int SD_config(void)
+{
+       int ret = -1;
+
+       FPRINT("Start of the Func %s\n", __func__);
+       /* Gpio enable for SD */
+       ret = gpio_request(CARDHU_IRDA_SD, "irda_sd");
+       if (ret < 0) {
+               pr_err("%s: cardhu_irda_sd gpio request failed %d\n",
+                                                       __func__, ret);
+               return ret;
+       }
+
+       ret = gpio_direction_output(CARDHU_IRDA_SD, 1);
+       if (ret)
+               pr_err("%s: cardhu_irda_sd Direction configuration failed %d\n",
+                                               __func__, ret);
+       return ret;
+}
+
+static void cardhu_irda_start(void)
+{
+       FPRINT("Start of the Func %s\n", __func__);
+       pr_info("IrDA transceiver is enabled\n");
+       gpio_set_value(CARDHU_IRDA_SD, 0);
+       irda_mode = SIR;
+}
+
+static void cardhu_irda_shutdown(void)
+{
+       FPRINT("Start of the Func %s\n", __func__);
+       pr_info("IrDA transceiver is disabled\n");
+       /* Setting the IrDA transceiver into shutdown mode*/
+       gpio_set_value(CARDHU_IRDA_SD, 1);
+}
+
+static int cardhu_irda_init(void)
+{
+       int ret = 0;
+
+       FPRINT("Start of the Func %s\n", __func__);
+       if (SD_config() < 0) {
+               pr_err("%s: Error in IRDA_SD signal configuration\n", __func__);
+               ret = -1;
+       }
+       return ret;
+}
+
+static void cardhu_irda_remove(void)
+{
+       FPRINT("Start of the Func %s\n", __func__);
+       gpio_free(CARDHU_IRDA_SD);
+}
+
+
+struct tegra_uart_platform_data cardhu_irda_pdata = {
+       .is_irda                = true,
+       .irda_init              = cardhu_irda_init,
+       .irda_start             = cardhu_irda_start,
+       .irda_mode_switch       = cardhu_irda_mode_switch,
+       .irda_shutdown          = cardhu_irda_shutdown,
+       .irda_remove            = cardhu_irda_remove,
+};
index f8fb5c5..80cab77 100644 (file)
@@ -492,6 +492,16 @@ static void __init uart_debug_init(void)
                                debug_port_id = 1;
        }
 
+#ifdef CONFIG_TEGRA_IRDA
+       if ((board_info.board_id == BOARD_E1186) ||
+               (board_info.board_id == BOARD_E1198)) {
+               if (debug_port_id == 1) {
+                       cardhu_irda_pdata.is_irda = false;
+                       pr_err("UARTB is not available for IrDA\n");
+               }
+       }
+#endif
+
        switch (debug_port_id) {
        case 0:
                /* UARTA is the debug port. */
@@ -553,6 +563,9 @@ static void __init cardhu_uart_init(void)
 {
        struct clk *c;
        int i;
+       struct board_info board_info;
+
+       tegra_get_board_info(&board_info);
 
        for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) {
                c = tegra_get_clock_by_name(uart_parent_clk[i].name);
@@ -598,6 +611,18 @@ static void __init cardhu_uart_init(void)
                }
        }
 
+#ifdef CONFIG_TEGRA_IRDA
+       if (((board_info.board_id == BOARD_E1186) ||
+               (board_info.board_id == BOARD_E1198)) &&
+                       cardhu_irda_pdata.is_irda) {
+               cardhu_irda_pdata.parent_clk_list = uart_parent_clk;
+               cardhu_irda_pdata.parent_clk_count =
+                                       ARRAY_SIZE(uart_parent_clk);
+
+               tegra_uartb_device.dev.platform_data = &cardhu_irda_pdata;
+       }
+#endif
+
        platform_add_devices(cardhu_uart_devices,
                                ARRAY_SIZE(cardhu_uart_devices));
 }
index a8be32e..7c6a132 100644 (file)
@@ -221,6 +221,8 @@ int cardhu_pm298_regulator_init(void);
 int cardhu_pm299_gpio_switch_regulator_init(void);
 int cardhu_pm299_regulator_init(void);
 
+extern struct tegra_uart_platform_data cardhu_irda_pdata;
+
 #define MPU_TYPE_MPU3050       1
 #define MPU_TYPE_MPU6050       2
 #define MPU_GYRO_TYPE          MPU_TYPE_MPU3050