diff mbox

[RFC:,5/5] da850: tty compliant driver for TI's PRU SoftUART Emulation.

Message ID 1293797894-15964-5-git-send-email-subhasish@mistralsolutions.com (mailing list archive)
State Superseded
Headers show

Commit Message

Subhasish Ghosh Dec. 31, 2010, 12:18 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/serial/omapl_pru/Kconfig b/drivers/serial/omapl_pru/Kconfig
new file mode 100644
index 0000000..f984bc5
--- /dev/null
+++ b/drivers/serial/omapl_pru/Kconfig
@@ -0,0 +1,20 @@ 
+#
+# SUART Kernel Configuration
+#
+
+config SERIAL_SUART_OMAPL_PRU
+	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
+	select SERIAL_CORE
+	tristate "PRU based SoftUART emulation for OMAPL"
+	---help---
+	Enable this to emulate a UART controller on the PRU of OMAPL.
+	Enable this to emulate a UART controller on the PRU of OMAPL.
+	If not sure, mark N
+
+config OMAPL_SUART_MCASP
+    int "McASP number"
+    depends on ARCH_DAVINCI && ARCH_DAVINCI_DA830 && SERIAL_SUART_OMAPL_PRU
+    default "0"
+    ---help---
+    Enter the McASP number to use with SUART (0, 1 or 2).
+	You will need to recompile the kernel if this is changed.
diff --git a/drivers/serial/omapl_pru/Makefile b/drivers/serial/omapl_pru/Makefile
new file mode 100644
index 0000000..3378e0f
--- /dev/null
+++ b/drivers/serial/omapl_pru/Makefile
@@ -0,0 +1,9 @@ 
+#
+# Makefile for SoftUART emulation
+#
+
+suart_emu-objs := 	ti_omapl_pru_suart.o \
+					suart_api.o \
+					suart_utils.o
+
+obj-$(CONFIG_SERIAL_SUART_OMAPL_PRU)	+= suart_emu.o
diff --git a/drivers/serial/omapl_pru/omapl_suart_board.h b/drivers/serial/omapl_pru/omapl_suart_board.h
new file mode 100644
index 0000000..0d29623
--- /dev/null
+++ b/drivers/serial/omapl_pru/omapl_suart_board.h
@@ -0,0 +1,50 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: subhasish@mistralsolutions.com
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _OMAPL_SUART_BOARD_H_
+#define _OMAPL_SUART_BOARD_H_
+
+#define PRU_SUART1_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART1_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART1_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define PRU_SUART2_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART2_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_7)
+#define PRU_SUART2_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_8)
+
+#define PRU_SUART3_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART3_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_9)
+#define PRU_SUART3_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_10)
+
+#define PRU_SUART4_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART4_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART4_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define PRU_SUART5_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART5_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART5_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define PRU_SUART6_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART6_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART6_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define PRU_SUART7_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART7_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART7_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define PRU_SUART8_CONFIG_DUPLEX	(ePRU_SUART_HALF_TX | ePRU_SUART_HALF_RX)
+#define PRU_SUART8_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART8_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#endif				/* End of _OMAPL_SUART_BOARD_H_ */
diff --git a/drivers/serial/omapl_pru/suart_api.c b/drivers/serial/omapl_pru/suart_api.c
new file mode 100644
index 0000000..c46d6b4
--- /dev/null
+++ b/drivers/serial/omapl_pru/suart_api.c
@@ -0,0 +1,2758 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Jitendra Kumar <jitendra@mistralsolutions.com>
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include <mach/pru/pru.h>
+#include "suart_api.h"
+#include "suart_pru_regs.h"
+#include "omapl_suart_board.h"
+#include "suart_utils.h"
+#include "suart_err.h"
+
+static u8 gUartStatuTable[8];
+static arm_pru_iomap pru_arm_iomap;
+
+#if (PRU_ACTIVE == BOTH_PRU)
+void pru_set_ram_data(arm_pru_iomap *arm_iomap_pru)
+{
+	PRU_SUART_RegsOvly pru_suart_regs =
+		(PRU_SUART_RegsOvly) arm_iomap_pru->pru_io_addr;
+	u32 *pu32SrCtlAddr = (u32 *)(arm_iomap_pru->mcasp_io_addr + 0x180);
+	pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
+	pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
+	u8 *pu32_pru_ram_base = (u8 *)arm_iomap_pru->pru_io_addr;
+	/* RX PRU - 0 Chanel 0 context information */
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART1_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART1_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART1_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/*
+	 * RX is active by default, write the dummy received data at
+	 * PRU RAM addr 0x1FC to avoid memory corruption.
+	 */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART1 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x090);
+	pru_suart_rx_priv->asp_rbuf_base =
+			(u32)(MCASP_RBUF_BASE_ADDR + (PRU_SUART1_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+				(PRU_SUART1_CONFIG_RX_SER << 2));
+
+	/* Chanel 1 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+				(0xF & PRU_SUART2_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART2_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART2_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	 * at PRU RAM addr 0x1FC to avoid memory corruption        */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART2 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x0B0);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+							(PRU_SUART2_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART2_CONFIG_RX_SER << 2));
+
+	/* Chanel 2 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+	    (0xF & PRU_SUART3_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART3_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART3_CONFIG_RX_SER)) =
+					MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy
+	 * received data at PRU RAM addr 0x1FC to avoid memory corruption  */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+						(pu32_pru_ram_base + 0x0D0);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+					(PRU_SUART3_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+			(PRU_SUART3_CONFIG_RX_SER << 2));
+
+	/* Chanel 3 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART4_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART4_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART4_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	 * at PRU RAM addr 0x1FC to avoid memory corruption       */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART4 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+	    (pu32_pru_ram_base + 0x0F0);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+		(PRU_SUART4_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART4_CONFIG_RX_SER << 2));
+
+	/* Chanel 4 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+	    (0xF & PRU_SUART5_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART5_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART5_CONFIG_RX_SER)) =
+			MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	 * at PRU RAM addr 0x1FC to avoid memory corruption */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART5 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+				(pu32_pru_ram_base + 0x110);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+					(PRU_SUART5_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART5_CONFIG_RX_SER << 2));
+
+	/* Chanel 5 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+			(0xF & PRU_SUART6_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART6_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART6_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	 * at PRU RAM addr 0x1FC to avoid memory corruption */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x130);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+			   (PRU_SUART6_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base =
+	    (u32)(MCASP_SRCTL_BASE_ADDR +
+			   (PRU_SUART6_CONFIG_RX_SER << 2));
+
+	/* Chanel 6 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+			(0xF & PRU_SUART7_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART7_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART7_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	 * at PRU RAM addr 0x1FC to avoid memory corruption */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART7 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x150);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+					(PRU_SUART7_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART7_CONFIG_RX_SER << 2));
+
+	/* Chanel 7 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+			(0xF & PRU_SUART8_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling =
+			SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART8_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART8_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data at
+	 * PRU RAM addr 0x1FC to avoid memory corruption */
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART8 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x170);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+					(PRU_SUART8_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART8_CONFIG_RX_SER << 2));
+
+	/* ****************** PRU1 RAM BASE ADDR ************************ */
+	pru_suart_regs = (PRU_SUART_RegsOvly)
+				(arm_iomap_pru->pru_io_addr + 0x2000);
+	pu32_pru_ram_base = (u8 *)(arm_iomap_pru->pru_io_addr + 0x2000);
+
+	/* ******************* TX PRU - 1  *********************** */
+	/* Channel 0 context information */
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+	    (0xF & PRU_SUART1_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART1_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART1_CONFIG_TX_SER)) =
+		MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART1 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x0B0);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART1_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART1_CONFIG_TX_SER << 2));
+	/* SUART1 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x0090;
+
+	/* Channel 1 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART2_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART2_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART2_CONFIG_TX_SER)) =
+	    MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART2 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+					(pu32_pru_ram_base + 0x0DC);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+			   (PRU_SUART2_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+			   (PRU_SUART2_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->buff_addr = 0x00BC;
+
+	/* Channel 2 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+				(0xF & PRU_SUART3_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART3_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART3_CONFIG_TX_SER)) =
+	    MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART3 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x108);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART3_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART3_CONFIG_TX_SER << 2));
+	/* SUART3 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x00E8;
+
+	/* Channel 3 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+	    (0xF & PRU_SUART4_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART4_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART4_CONFIG_TX_SER)) =
+	    MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART4 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x134);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART4_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART4_CONFIG_TX_SER << 2));
+	/* SUART4 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x0114;
+
+	/* Channel 4 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART5_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART5_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART5_CONFIG_TX_SER)) =
+	    MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART5 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+					(pu32_pru_ram_base + 0x160);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART5_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART5_CONFIG_TX_SER << 2));
+	/* SUART5 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x0140;
+
+	/* Channel 5 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART6_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART6_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART6_CONFIG_TX_SER)) =
+					MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART6 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x18C);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART6_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART6_CONFIG_TX_SER << 2));
+	/* SUART6 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x016C;
+
+	/* Channel 6 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART7_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART7_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART7_CONFIG_TX_SER)) =
+					MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART7 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x1B8);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART7_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART7_CONFIG_TX_SER << 2));
+	/* SUART7 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x0198;
+
+	/* Channel 7 context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART8_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART8_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART8_CONFIG_TX_SER)) =
+					MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART8 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x1E4);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART8_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART8_CONFIG_TX_SER << 2));
+	/* SUART8  TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x01C4;
+}
+#else
+void pru_set_ram_data(arm_pru_iomap *arm_iomap_pru)
+{
+
+	PRU_SUART_RegsOvly pru_suart_regs = (PRU_SUART_RegsOvly)
+						arm_iomap_pru->pru_io_addr;
+	u32 *pu32SrCtlAddr = (u32 *)(arm_iomap_pru->mcasp_io_addr + 0x180);
+	pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
+	pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
+	u8 *pu32_pru_ram_base = (u8 *)arm_iomap_pru->pru_io_addr;
+
+	/* ***************** UART 0  ************************ */
+	/* Channel 0 context information is Tx */
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART1_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART1_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART1_CONFIG_TX_SER)) =
+					MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART1 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x0B0);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART1_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART1_CONFIG_TX_SER << 2));
+	/* SUART1 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x0090;
+
+	/* Channel 1 is Rx context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART1_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART1_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART1_CONFIG_RX_SER)) =
+	    MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	 *at PRU RAM addr 0x1FC to avoid memory corruption
+	*/
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART1 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+				(pu32_pru_ram_base + 0x0C0);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+					(PRU_SUART1_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART1_CONFIG_RX_SER << 2));
+
+	/* ************** UART 1  ************************ */
+	/* Channel 2 context information is Tx */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+					(0xF & PRU_SUART2_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART2_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART2_CONFIG_TX_SER)) =
+					MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART2 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+				(pu32_pru_ram_base + 0x100);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART2_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+					(PRU_SUART2_CONFIG_TX_SER << 2));
+	/* SUART2 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x00E0;
+
+	/* Channel 3 is Rx context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+			(0xF & PRU_SUART2_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling =
+			SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART2_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART2_CONFIG_RX_SER)) =
+								MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	* at PRU RAM addr 0x1FC to avoid memory corruption
+	*/
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART2 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x110);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+						(PRU_SUART2_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+						(PRU_SUART2_CONFIG_RX_SER << 2));
+
+	/* **************** UART 2  ********************* */
+	/* Channel 4 context information is Tx */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+						(0xF & PRU_SUART3_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART3_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART3_CONFIG_TX_SER)) =
+						MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	 /* SUART3 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+					(pu32_pru_ram_base + 0x150);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+						(PRU_SUART3_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+						(PRU_SUART3_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->buff_addr = 0x0130;
+
+	/* Channel 5 is Rx context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+						(0xF & PRU_SUART3_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART3_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART3_CONFIG_RX_SER)) =
+						MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	* at PRU RAM addr 0x1FC to avoid memory corruption
+	*/
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART3 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+					(pu32_pru_ram_base + 0x160);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+						(PRU_SUART3_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+						(PRU_SUART3_CONFIG_RX_SER << 2));
+
+	/* *********** UART 3  *********************** */
+	/* Channel 6 context information is Tx */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_TX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+						(0xF & PRU_SUART4_CONFIG_TX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART4_CONFIG_TX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART4_CONFIG_TX_SER)) =
+						MCASP_SRCTL_TX_MODE;
+#endif
+	pru_suart_regs->Reserved1 = 1;
+	/* SUART4 TX context base addr */
+	pru_suart_tx_priv = (pru_suart_tx_cntx_priv *)
+					(pu32_pru_ram_base + 0x1A0);
+	pru_suart_tx_priv->asp_xsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+						(PRU_SUART4_CONFIG_TX_SER << 2));
+	pru_suart_tx_priv->asp_xbuf_base = (u32)(MCASP_XBUF_BASE_ADDR +
+						(PRU_SUART4_CONFIG_TX_SER << 2));
+	/* SUART4 TX formatted data base addr */
+	pru_suart_tx_priv->buff_addr = 0x0180;
+
+	/* Channel 7 is Rx context information */
+	pru_suart_regs++;
+	pru_suart_regs->CH_Ctrl.mode = SUART_CHN_RX;
+	pru_suart_regs->CH_Ctrl.serializer_num =
+						(0xF & PRU_SUART4_CONFIG_RX_SER);
+	pru_suart_regs->CH_Config1.over_sampling = SUART_DEFAULT_OVRSMPL;
+	pru_suart_regs->CH_Config2.bits_per_char = 8;
+#if (PRU_SUART4_CONFIG_RX_SER == PRU_SUART_SERIALIZER_NONE)
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_DISABLED;
+#else
+	pru_suart_regs->CH_TXRXStatus.chn_state = SUART_CHN_ENABLED;
+	*((u32 *)(pu32SrCtlAddr + PRU_SUART4_CONFIG_RX_SER)) =
+					MCASP_SRCTL_RX_MODE;
+#endif
+	/* RX is active by default, write the dummy received data
+	*  at PRU RAM addr 0x1FC to avoid memory corruption
+	*/
+	pru_suart_regs->CH_TXRXData = RX_DEFAULT_DATA_DUMP_ADDR;
+	pru_suart_regs->Reserved1 = 0;
+	/* SUART4 RX context base addr */
+	pru_suart_rx_priv = (pru_suart_rx_cntx_priv *)
+				(pu32_pru_ram_base + 0x1B0);
+	pru_suart_rx_priv->asp_rbuf_base = (u32)(MCASP_RBUF_BASE_ADDR +
+					(PRU_SUART4_CONFIG_RX_SER << 2));
+	pru_suart_rx_priv->asp_rsrctl_base = (u32)(MCASP_SRCTL_BASE_ADDR +
+					(PRU_SUART4_CONFIG_RX_SER << 2));
+}
+
+#endif
+
+static void pru_set_rx_tx_mode(u32 pru_mode, u32 pruNum)
+{
+
+	u32 pruOffset;
+
+	if (pruNum == PRU_NUM0) {
+		pruOffset = PRU_SUART_PRU0_RX_TX_MODE;
+	} else if (pruNum == PRU_NUM1) {
+		pruOffset = PRU_SUART_PRU1_RX_TX_MODE;
+	} else {
+		return;
+	}
+	pru_ram_write_data(pruOffset, (u8 *) &pru_mode, 1, &pru_arm_iomap);
+}
+
+static void pru_set_delay_count(u32 pru_freq)
+{
+	u32 u32delay_cnt;
+
+	if (pru_freq == 228)
+		u32delay_cnt = 5;
+	else if (pru_freq == 186)
+		u32delay_cnt = 5;
+	else
+		u32delay_cnt = 3;
+
+	/* PRU 0 */
+	pru_ram_write_data(PRU_SUART_PRU0_DELAY_OFFSET,
+		(u8 *) &u32delay_cnt, 1, &pru_arm_iomap);
+
+	/* PRU 1 */
+	pru_ram_write_data(PRU_SUART_PRU1_DELAY_OFFSET,
+		(u8 *) &u32delay_cnt, 1, &pru_arm_iomap);
+}
+
+static s32 suart_set_pru_id(u32 pru_no)
+{
+	u32 offset;
+	u16 reg_val = 0;
+
+	if (0 == pru_no)
+		offset = PRU_SUART_PRU0_ID_ADDR;
+	else if (1 == pru_no)
+		offset = PRU_SUART_PRU1_ID_ADDR;
+	else
+		return PRU_SUART_FAILURE;
+
+	pru_ram_read_data(offset, (u8 *) &reg_val, 1, &pru_arm_iomap);
+	reg_val &= ~SUART_PRU_ID_MASK;
+	reg_val = pru_no;
+	pru_ram_write_data(offset, (u8 *) &reg_val, 1, &pru_arm_iomap);
+
+	return PRU_SUART_SUCCESS;
+}
+
+/*
+ * suart Initialization routine
+ */
+s16 pru_softuart_init(u32 txBaudValue,
+			u32 rxBaudValue,
+			u32 oversampling,
+			u8 *pru_suart_emu_code,
+			u32 fw_size, arm_pru_iomap *arm_iomap_pru)
+{
+	u32 omapl_addr;
+	u32 u32loop;
+	s16 status = PRU_SUART_SUCCESS;
+	s16 idx;
+	s16 retval;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) &&
+					(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		return PRU_SUART_FAILURE;
+	}
+
+	pru_arm_iomap.pru_io_addr = arm_iomap_pru->pru_io_addr;
+	pru_arm_iomap.mcasp_io_addr = arm_iomap_pru->mcasp_io_addr;
+	pru_arm_iomap.pFifoBufferPhysBase = arm_iomap_pru->pFifoBufferPhysBase;
+	pru_arm_iomap.pFifoBufferVirtBase = arm_iomap_pru->pFifoBufferVirtBase;
+	pru_arm_iomap.pru_clk_freq = arm_iomap_pru->pru_clk_freq;
+	omapl_addr = (u32)arm_iomap_pru->mcasp_io_addr;
+	/* Configure McASP0  */
+	suart_mcasp_config(omapl_addr, txBaudValue, rxBaudValue, oversampling,
+								arm_iomap_pru);
+	pru_enable(0, arm_iomap_pru);
+	pru_enable(1, arm_iomap_pru);
+	omapl_addr = (u32)arm_iomap_pru->pru_io_addr;
+	for (u32loop = 0; u32loop < 512; u32loop++) {
+		*(u32 *)(omapl_addr | u32loop) = 0x0;
+		*(u32 *)(omapl_addr | u32loop | 0x2000) = 0x0;
+	}
+	pru_load(PRU_NUM0, (u32 *)pru_suart_emu_code, (fw_size / sizeof(u32)),
+								 arm_iomap_pru);
+	pru_load(PRU_NUM1, (u32 *)pru_suart_emu_code, (fw_size / sizeof(u32)),
+								 arm_iomap_pru);
+	retval = arm_to_pru_intr_init();
+	if (-1 == retval)
+		return status;
+	pru_set_delay_count(pru_arm_iomap.pru_clk_freq);
+	suart_set_pru_id(PRU_NUM0);
+	suart_set_pru_id(PRU_NUM1);
+	pru_set_rx_tx_mode(PRU0_MODE, PRU_NUM0);
+	pru_set_rx_tx_mode(PRU1_MODE, PRU_NUM1);
+	pru_set_ram_data(arm_iomap_pru);
+	pru_run(PRU_NUM0, arm_iomap_pru);
+	pru_run(PRU_NUM1, arm_iomap_pru);
+
+	/* Initialize gUartStatuTable */
+	for (idx = 0; idx < 8; idx++) {
+		gUartStatuTable[idx] = ePRU_SUART_UART_FREE;
+	}
+
+	return status;
+}
+
+void pru_set_fifo_timeout(u32 timeout)
+{
+	pru_ram_write_data(PRU_SUART_PRU0_IDLE_TIMEOUT_OFFSET, (u8 *) &timeout,
+								 2, &pru_arm_iomap);
+	pru_ram_write_data(PRU_SUART_PRU1_IDLE_TIMEOUT_OFFSET, (u8 *) &timeout,
+								 2, &pru_arm_iomap);
+}
+
+s16 pru_softuart_deinit(void)
+{
+	u32 offset;
+	s16 s16retval = 0;
+	u32 u32value = 0;
+
+	offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_STATCLRINT1 & 0xFFFF);
+	u32value = 0xFFFFFFFF;
+	s16retval = pru_ram_write_data_4byte(offset, (u32 *)&u32value, 1);
+	if (-1 == s16retval)
+		return -1;
+	offset =
+	    (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_STATCLRINT0 &
+						       0xFFFF);
+	u32value = 0xFFFFFFFF;
+	s16retval = pru_ram_write_data_4byte(offset, (u32 *)&u32value, 1);
+	if (-1 == s16retval)
+		return -1;
+	pru_disable(&pru_arm_iomap);
+
+	return PRU_SUART_SUCCESS;
+}
+
+/* suart Instance open routine  */
+s16 pru_softuart_open(suart_handle hSuart)
+{
+	s16 status = PRU_SUART_SUCCESS;
+
+	switch (hSuart->uartNum) {
+	case PRU_SUART_UART1:
+		if (gUartStatuTable[PRU_SUART_UART1 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART1_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART1_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART1_CONFIG_RX_SER;
+			gUartStatuTable[PRU_SUART_UART1 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART2:
+		if (gUartStatuTable[PRU_SUART_UART2 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART2_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART2_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART2_CONFIG_RX_SER;
+			gUartStatuTable[PRU_SUART_UART2 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART3:
+		if (gUartStatuTable[PRU_SUART_UART3 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART3_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART3_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART3_CONFIG_RX_SER;
+			gUartStatuTable[PRU_SUART_UART3 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART4:
+		if (gUartStatuTable[PRU_SUART_UART4 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART4_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART4_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART4_CONFIG_RX_SER;
+
+			gUartStatuTable[PRU_SUART_UART4 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART5:
+		if (gUartStatuTable[PRU_SUART_UART5 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART5_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART5_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART5_CONFIG_RX_SER;
+
+			gUartStatuTable[PRU_SUART_UART5 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART6:
+		if (gUartStatuTable[PRU_SUART_UART6 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART6_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART6_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART6_CONFIG_RX_SER;
+			gUartStatuTable[PRU_SUART_UART6 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART7:
+		if (gUartStatuTable[PRU_SUART_UART7 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART7_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART7_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART7_CONFIG_RX_SER;
+			gUartStatuTable[PRU_SUART_UART7 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	case PRU_SUART_UART8:
+		if (gUartStatuTable[PRU_SUART_UART8 - 1] ==
+							ePRU_SUART_UART_IN_USE) {
+			status = SUART_UART_IN_USE;
+			return status;
+		} else {
+			hSuart->uartStatus = ePRU_SUART_UART_IN_USE;
+			hSuart->uartType = PRU_SUART8_CONFIG_DUPLEX;
+			hSuart->uartTxChannel = PRU_SUART8_CONFIG_TX_SER;
+			hSuart->uartRxChannel = PRU_SUART8_CONFIG_RX_SER;
+			gUartStatuTable[PRU_SUART_UART8 - 1] =
+			    ePRU_SUART_UART_IN_USE;
+		}
+		break;
+
+	default:
+		status = SUART_INVALID_UART_NUM;
+		break;
+	}
+	return status;
+}
+
+/* suart instance close routine */
+s16 pru_softuart_close(suart_handle hUart)
+{
+	s16 status = SUART_SUCCESS;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	} else {
+		gUartStatuTable[hUart->uartNum - 1] = ePRU_SUART_UART_FREE;
+		/* Reset the Instance to Invalid */
+		hUart->uartNum = PRU_SUART_UARTx_INVALID;
+		hUart->uartStatus = ePRU_SUART_UART_FREE;
+	}
+	return status;
+}
+
+/*
+ * suart routine for setting relative baud rate
+ */
+s16 pru_softuart_setbaud(suart_handle hUart, u16 txClkDivisor, u16 rxClkDivisor)
+{
+	u32 offset;
+	u32 pruOffset;
+	s16 status = SUART_SUCCESS;
+	u16 chNum;
+	u16 regval = 0;
+
+	if (hUart == NULL)
+		return PRU_SUART_ERR_HANDLE_INVALID;
+
+	/* Set the clock divisor value s32o the McASP */
+	if ((txClkDivisor > 385) || (txClkDivisor == 0))
+		return SUART_INVALID_CLKDIVISOR;
+	if ((rxClkDivisor > 385) || (rxClkDivisor == 0))
+		return SUART_INVALID_CLKDIVISOR;
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+						|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	if (txClkDivisor != 0) {
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= (~0x3FF);
+		regval |= txClkDivisor;
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+					(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum++;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	regval = 0;
+	if (rxClkDivisor != 0) {
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= (~0x3FF);
+		regval |= txClkDivisor;
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	return status;
+}
+
+/*
+ * suart routine for setting number of bits per character for a specific uart
+ */
+s16 pru_softuart_setdatabits(suart_handle hUart, u16 txDataBits, u16 rxDataBits)
+{
+	u32 offset;
+	u32 pruOffset;
+	s16 status = SUART_SUCCESS;
+	u16 chNum;
+	u32 reg_val;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	/*
+	 * NOTE:
+	 * The supported data bits are 6, 7, 8, 9, 10, 11, 12 bits per character
+	 */
+
+	if ((txDataBits < ePRU_SUART_DATA_BITS6)
+					|| (txDataBits > ePRU_SUART_DATA_BITS12)) {
+		return PRU_SUART_ERR_PARAMETER_INVALID;
+	}
+
+	if ((rxDataBits < ePRU_SUART_DATA_BITS6)
+					|| (rxDataBits > ePRU_SUART_DATA_BITS12)) {
+		return PRU_SUART_ERR_PARAMETER_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+					|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	if (txDataBits != 0) {
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &reg_val, 1, &pru_arm_iomap);
+		reg_val &= ~(0xF);
+		reg_val |= txDataBits;
+		pru_ram_write_data(offset, (u8 *) &reg_val, 1, &pru_arm_iomap);
+	}
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+						|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum++;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	if (rxDataBits != 0) {
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &reg_val, 1, &pru_arm_iomap);
+		reg_val &= ~(0xF);
+		reg_val |= rxDataBits;
+		pru_ram_write_data(offset, (u8 *) &rxDataBits, 1, &pru_arm_iomap);
+	}
+
+	return status;
+}
+
+/*
+ * suart routine to configure specific uart
+ */
+s16 pru_softuart_setconfig(suart_handle hUart, suart_config *configUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	s16 status = SUART_SUCCESS;
+	u16 chNum;
+	u16 regVal = 0;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	/*
+	 * NOTE:
+	 * Dependent baud rate for the given UART, the value MUST BE LESS THAN OR
+	 * EQUAL TO 64, preScalarValue <= 64
+	 */
+	if ((configUart->txClkDivisor > 384)
+					|| (configUart->rxClkDivisor > 384)) {
+		return SUART_INVALID_CLKDIVISOR;
+	}
+	if ((configUart->txBitsPerChar < 8) || (configUart->txBitsPerChar > 14)) {
+		return PRU_SUART_ERR_PARAMETER_INVALID;
+	}
+	if ((configUart->rxBitsPerChar < 8) || (configUart->rxBitsPerChar > 14)) {
+		return PRU_SUART_ERR_PARAMETER_INVALID;
+	}
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+					|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* Configuring the Transmit part of the given UART */
+	/* Serializer has been as TX in mcasp config, by writing 1 in bits
+	*  corresponding to tx serializer in PFUNC regsiter ie already set
+	*  to GPIO mode PRU code will set then back to MCASP mode once TX
+	*  request for that serializer is posted.It is required because at this
+	*  pos32 Mcasp is accessed by both PRU and DSP have lower priority for
+	*  Mcasp in comparison to PRU and DPS keeps on looping there only
+	*/
+	/*
+	 * suart_mcasp_tx_serialzier_set
+	*                   (configUart->TXSerializer, &pru_arm_iomap);
+	 */
+	/* Configuring TX serializer  */
+	if (configUart->TXSerializer != PRU_SUART_SERIALIZER_NONE) {
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		regVal = regVal | (configUart->TXSerializer <<
+							PRU_SUART_CH_CTRL_SR_SHIFT);
+		pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		regVal = regVal | (configUart->txClkDivisor <<
+						PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+		pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG2_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		regVal = regVal | (configUart->txBitsPerChar <<
+						PRU_SUART_CH_CONFIG2_BITPERCHAR_SHIFT);
+		pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		offset = 8;
+		pru_softuart_write(hUart, &offset, 0);
+	}
+
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+					(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum++;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* Configuring the Transmit part of the given UART */
+	if (configUart->RXSerializer != PRU_SUART_SERIALIZER_NONE) {
+		/* Configuring RX serializer  */
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		regVal = regVal | (configUart->RXSerializer <<
+							PRU_SUART_CH_CTRL_SR_SHIFT);
+		pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+
+		/* Configuring RX prescalar value and Oversampling */
+		offset =
+		    pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+		    PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		regVal = regVal | (configUart->rxClkDivisor <<
+						PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT) |
+						(configUart->Oversampling <<
+						PRU_SUART_CH_CONFIG1_OVS_SHIFT);
+		pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+
+		/* Configuring RX bits per character value */
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG2_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+		regVal = regVal | (configUart->rxBitsPerChar <<
+						PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+		pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	}
+	return status;
+}
+
+/*
+ * suart routine for getting the number of bytes transfered
+ */
+s16 pru_softuart_getTxDataLen(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 chNum;
+	u16 u16ReadValue = 0;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+				(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &u16ReadValue, 2, &pru_arm_iomap);
+	u16ReadValue = ((u16ReadValue & PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
+					PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+	return u16ReadValue;
+}
+
+/*
+ * suart routine for getting the number of bytes received
+ */
+s16 pru_softuart_getRxDataLen(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 chNum;
+	u16 u16ReadValue = 0;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+				(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &u16ReadValue, 2, &pru_arm_iomap);
+	u16ReadValue = ((u16ReadValue & PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
+						PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+
+	return u16ReadValue;
+}
+
+/*
+ * suart routine to get the configuration information from a specific uart
+ */
+s16 pru_softuart_getconfig(suart_handle hUart, suart_config *configUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 chNum;
+	u16 regVal = 0;
+	s16 status = SUART_SUCCESS;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	/*
+	 * NOTE:
+	 * Dependent baud rate for the given UART, the value MUST BE LESS THAN OR
+	 * EQUAL TO 64, preScalarValue <= 64
+	 */
+
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+					 (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* Configuring the Transmit part of the given UART */
+	/* Configuring TX serializer  */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	configUart->TXSerializer = ((regVal & PRU_SUART_CH_CTRL_SR_MASK) >>
+							PRU_SUART_CH_CTRL_SR_SHIFT);
+	/* Configuring TX prescalar value */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	configUart->txClkDivisor = ((regVal & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+
+	/* Configuring TX bits per character value */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+					PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	configUart->txBitsPerChar = ((regVal & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+						>> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+				(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum++;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	/* Configuring the Transmit part of the given UART */
+	/* Configuring RX serializer  */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+								PRU_SUART_CH_CTRL_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	configUart->RXSerializer = ((regVal & PRU_SUART_CH_CTRL_SR_MASK) >>
+							PRU_SUART_CH_CTRL_SR_SHIFT);
+
+	/* Configuring RX prescalar value and Oversampling */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	configUart->rxClkDivisor = ((regVal & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+	configUart->Oversampling = ((regVal & PRU_SUART_CH_CONFIG1_OVS_MASK) >>
+							PRU_SUART_CH_CONFIG1_OVS_SHIFT);
+
+	/* Configuring RX bits per character value */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	configUart->rxBitsPerChar = ((regVal & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+
+	return status;
+}
+
+s32 pru_softuart_pending_tx_request(void)
+{
+	u32 offset = 0;
+	u32 u32ISRValue = 0;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		return SUART_SUCCESS;
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		/* Read PRU Interrupt Status Register from PRU */
+		offset = (u32)pru_arm_iomap.pru_io_addr |
+							(PRU_INTC_STATCLRINT1 & 0xFFFF);
+		pru_ram_read_data_4byte(offset, (u32 *)&u32ISRValue, 1);
+		if ((u32ISRValue & 0x1) == 0x1)
+			return PRU_SUART_FAILURE;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		/* Read PRU Interrupt Status Register from PRU */
+		offset = (u32)pru_arm_iomap.pru_io_addr |
+					 (PRU_INTC_STATCLRINT1 & 0xFFFF);
+		pru_ram_read_data_4byte(offset, (u32 *)&u32ISRValue, 1);
+		if ((u32ISRValue & 0x2) == 0x2)
+			return PRU_SUART_FAILURE;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	return SUART_SUCCESS;
+}
+
+/*
+ * suart data transmit routine
+ */
+s16 pru_softuart_write(suart_handle hUart, u32 *ptTxDataBuf, u16 dataLen)
+{
+	u32 offset = 0;
+	u32 pruOffset;
+	s16 status = SUART_SUCCESS;
+	u16 chNum;
+	u16 regVal = 0;
+	u16 pru_num;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+			pru_num = hUart->uartNum;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+			pru_num = hUart->uartNum;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		pru_num = 0;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+		pru_num = 1;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* Writing data length to SUART channel register */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	regVal &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
+	regVal = regVal | (dataLen << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+	pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+
+	/* Writing the data pos32er to channel TX data pointer */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXDATA_OFFSET;
+	pru_ram_write_data(offset, (u8 *) ptTxDataBuf, 4, &pru_arm_iomap);
+
+	/* Service Request to PRU */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	regVal &= ~(PRU_SUART_CH_CTRL_MODE_MASK | PRU_SUART_CH_CTRL_SREQ_MASK);
+	regVal |= (PRU_SUART_CH_CTRL_TX_MODE << PRU_SUART_CH_CTRL_MODE_SHIFT) |
+				(PRU_SUART_CH_CTRL_SREQ << PRU_SUART_CH_CTRL_SREQ_SHIFT);
+	pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+
+	/* generate ARM->PRU event */
+	suart_arm_to_pru_intr(pru_num);
+
+	return status;
+}
+
+/*
+ * suart data receive routine
+ */
+s16 pru_softuart_read(suart_handle hUart, u32 *ptDataBuf, u16 dataLen)
+{
+	u32 offset = 0;
+	u32 pruOffset;
+	s16 status = SUART_SUCCESS;
+	u16 chNum;
+	u16 regVal = 0;
+	u16 pru_num;
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+			 (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+			pru_num = hUart->uartNum;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+			pru_num = hUart->uartNum;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		pru_num = 0;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+		pru_num = 1;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	/* Writing data length to SUART channel register */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+								PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	regVal &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
+	regVal = regVal | (dataLen << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+	pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+
+	/* Writing the data pos32er to channel RX data pointer */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXDATA_OFFSET;
+	pru_ram_write_data(offset, (u8 *) ptDataBuf, 4, &pru_arm_iomap);
+
+	/* Service Request to PRU */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	regVal &= ~(PRU_SUART_CH_CTRL_MODE_MASK | PRU_SUART_CH_CTRL_SREQ_MASK);
+	regVal |= (PRU_SUART_CH_CTRL_RX_MODE << PRU_SUART_CH_CTRL_MODE_SHIFT) |
+			(PRU_SUART_CH_CTRL_SREQ << PRU_SUART_CH_CTRL_SREQ_SHIFT);
+	pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+
+	/* enable the timeout s32errupt */
+	suart_intr_setmask(hUart->uartNum, PRU_RX_INTR, CHN_TXRX_IE_MASK_TIMEOUT);
+
+	/* generate ARM->PRU event */
+	suart_arm_to_pru_intr(pru_num);
+
+	return status;
+}
+
+/*
+ * suart routine to read the data from the RX FIFO
+ */
+s16 pru_softuart_read_data(suart_handle hUart, u8 *pDataBuffer,
+			     s32 s32MaxLen, u32 *pu32DataRead)
+{
+	s16 retVal = PRU_SUART_SUCCESS;
+	u8 *pu8SrcAddr = NULL;
+	u32 u32DataRead = 0;
+	u32 u32DataLen = 0;
+	u32 u32CharLen = 0;
+	u32 offset = 0;
+	u32 pruOffset;
+	u16 chNum;
+	u16 u16Status = 0;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (hUart->uartNum <= 4) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chNum -= 8;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* Get the data pos32er from channel RX data pointer */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXDATA_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &pu8SrcAddr, 4, &pru_arm_iomap);
+
+	/* Reading data length from SUART channel register */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG2_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &u32DataLen, 2, &pru_arm_iomap);
+
+	/* read the character length */
+	u32CharLen = u32DataLen & PRU_SUART_CH_CONFIG2_BITPERCHAR_MASK;
+	u32CharLen -= 2;	/* remove the START & STOP bit */
+
+	u32DataLen &= PRU_SUART_CH_CONFIG2_DATALEN_MASK;
+	u32DataLen = u32DataLen >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT;
+	u32DataLen++;
+
+	/* if the character length is greater than 8, then the size doubles */
+	if (u32CharLen > 8)
+		u32DataLen *= 2;
+
+	/* Check if the time-out had occured. If, yes, then we need to find the
+	 * number of bytes read from PRU. Else, we need to
+	 * read the requested bytes
+	 */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &u16Status, 1, &pru_arm_iomap);
+	if (CHN_TXRX_STATUS_TIMEOUT == (u16Status & CHN_TXRX_STATUS_TIMEOUT)) {
+		/* determine the number of bytes read s32o the FIFO */
+		offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_BYTESDONECNTR_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &u32DataRead, 1, &pru_arm_iomap);
+
+		/* if the character length is greater than 8, then the size doubles */
+		if (u32CharLen > 8)
+			u32DataRead *= 2;
+
+/*
+ * the data corresponding is loaded in second
+ * half during the timeout
+ */
+		if (u32DataRead > u32DataLen) {
+			u32DataRead -= u32DataLen;
+			pu8SrcAddr += (u32DataLen + 1);
+		}
+
+		pru_softuart_clrRxFifo(hUart);
+	} else {
+		u32DataRead = u32DataLen;
+/*
+ * if the bit is set, the data is in the first
+ * half of the FIFO else the data is in the second half
+ */
+		/* Determine the buffer index by reading FIFO_OddEven flag*/
+		if (u16Status & CHN_TXRX_STATUS_CMPLT) {
+			pu8SrcAddr += u32DataLen;
+		}
+	}
+
+	/* we should be copying only max len given by the application */
+	if (u32DataRead > s32MaxLen)
+		u32DataRead = s32MaxLen;
+
+/* evaluate the virtual address of the FIFO address
+ * based on the physical addr
+ */
+	pu8SrcAddr = (u8 *)((u32) pu8SrcAddr -
+				(u32) pru_arm_iomap.pFifoBufferPhysBase +
+					(u32) pru_arm_iomap.pFifoBufferVirtBase);
+
+	/* Now we have both the data length and the source address. copy */
+	for (offset = 0; offset < u32DataRead; offset++)
+		*pDataBuffer++ = *pu8SrcAddr++;
+	*pu32DataRead = u32DataRead;
+	retVal = PRU_SUART_SUCCESS;
+
+	return retVal;
+}
+
+/*
+ * suart routine to disable the receive functionality.
+ * This routine stops the PRU from receiving on selected
+ * UART and also disables the McASP serializer corresponding
+ * to this UART Rx line.
+ */
+s16 pru_softuart_stopReceive(suart_handle hUart)
+{
+	u16 status = SUART_SUCCESS;
+	u32 offset;
+	u32 pruOffset;
+	u16 chNum;
+	u16 u16Status;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if (hUart->uartNum <= 4) {
+			/* PRU0 */
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			/* PRU1 */
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chNum -= 8;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* read the existing value of status flag */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &u16Status, 1, &pru_arm_iomap);
+
+	/* we need to clear the busy bit corresponding to this receive channel */
+	u16Status &= ~(CHN_TXRX_STATUS_RDY);
+	pru_ram_write_data(offset, (u8 *) &u16Status, 1, &pru_arm_iomap);
+
+	/* get the serizlizer number being used for this Rx channel */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &u16Status, 2, &pru_arm_iomap);
+	u16Status &= PRU_SUART_CH_CTRL_SR_MASK;
+	u16Status = u16Status >> PRU_SUART_CH_CTRL_SR_SHIFT;
+
+	/* we need to de-activate the serializer corresponding to this receive */
+	status = suart_asp_serializer_deactivate(u16Status, &pru_arm_iomap);
+
+	return status;
+
+}
+
+/*
+ * suart routine to get the tx status for a specific uart
+ */
+s16 pru_softuart_getTxStatus(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 status = SUART_SUCCESS;
+	u16 chNum;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if (hUart->uartNum <= 4) {
+			/* PRU0 */
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			/* PRU1 */
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &status, 1, &pru_arm_iomap);
+	return status;
+}
+
+s16 pru_softuart_clrTxStatus(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 status = SUART_SUCCESS;
+	u16 chNum;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if (hUart->uartNum <= 4) {
+			/* PRU0 */
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			/* PRU1 */
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chNum -= 8;
+		}
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &status, 1, &pru_arm_iomap);
+	status &= ~(0x2);
+	pru_ram_write_data(offset, (u8 *) &status, 1, &pru_arm_iomap);
+	return status;
+}
+
+/*
+ * suart routine to get the rx status for a specific uart
+ */
+s16 pru_softuart_getRxStatus(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 status = SUART_SUCCESS;
+	u16 chNum;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if (hUart->uartNum <= 4) {
+			/* PRU0 */
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			/* PRU1 */
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chNum -= 8;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &status, 1, &pru_arm_iomap);
+	return status;
+}
+
+s16 pru_softuart_clrRxFifo(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 status = SUART_SUCCESS;
+	u16 chNum;
+	u16 regVal;
+	u16 uartNum;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+	uartNum = hUart->uartNum;
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if (hUart->uartNum <= 4) {
+			/* PRU0 */
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			/* PRU1 */
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chNum -= 8;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		uartNum = 0;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+		uartNum = 1;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	/* Service Request to PRU */
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CTRL_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	regVal &= ~(PRU_SUART_CH_CTRL_MODE_MASK | PRU_SUART_CH_CTRL_SREQ_MASK);
+	regVal |= (PRU_SUART_CH_CTRL_RX_MODE << PRU_SUART_CH_CTRL_MODE_SHIFT) |
+			(PRU_SUART_CH_CTRL_SREQ << PRU_SUART_CH_CTRL_SREQ_SHIFT);
+	pru_ram_write_data(offset, (u8 *) &regVal, 2, &pru_arm_iomap);
+	suart_intr_setmask(hUart->uartNum, PRU_RX_INTR, CHN_TXRX_IE_MASK_TIMEOUT);
+
+	/* generate ARM->PRU event */
+	suart_arm_to_pru_intr(uartNum);
+
+	return status;
+}
+
+s16 pru_softuart_clrRxStatus(suart_handle hUart)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 status = SUART_SUCCESS;
+	u16 chNum;
+
+	if (hUart == NULL) {
+		return PRU_SUART_ERR_HANDLE_INVALID;
+	}
+
+	chNum = hUart->uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = (hUart->uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if (hUart->uartNum <= 4) {
+			/* PRU0 */
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			/* PRU1 */
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chNum -= 8;
+		}
+		chNum++;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	offset = pruOffset + (chNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pru_ram_read_data(offset, (u8 *) &status, 1, &pru_arm_iomap);
+	status &= ~(0x3C);
+	pru_ram_write_data(offset, (u8 *) &status, 1, &pru_arm_iomap);
+	return status;
+}
+
+/*
+ * suart_s32r_status_read: Gets the Global Interrupt status register
+ * for the specified SUART.
+ * uartNum < 1 to 6 >
+ * txrxFlag < Indicates TX or RX s32errupt for the uart >
+ */
+s16 pru_softuart_get_isrstatus(u16 uartNum, u16 *txrxFlag)
+{
+	u32 offset;
+	u32 u32IntcOffset;
+	u32 chNum = 0xFF;
+	u32 regVal = 0;
+	u32 u32RegVal = 0;
+	u32 u32ISRValue = 0;
+	u32 u32AckRegVal = 0;
+	u8 pru0_mode = PRU_MODE_INVALID;
+	u8 pru1_mode = PRU_MODE_INVALID;
+	u32 u32StatInxClrRegoffset = 0;
+
+	/* initialize the status & Flag to known value */
+	*txrxFlag = 0;
+
+	u32StatInxClrRegoffset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_STATIDXCLR & 0xFFFF);
+
+	/* Read PRU Interrupt Status Register from PRU */
+	u32IntcOffset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_STATCLRINT1 & 0xFFFF);
+
+	pru_ram_read_data_4byte(u32IntcOffset, (u32 *)&u32ISRValue, 1);
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* determine if the s32errupt occured in the current UART context */
+		u32RegVal = (PRU_SUART0_TX_EVT_BIT | PRU_SUART0_RX_EVT_BIT) <<
+									((uartNum - 1) * 2);
+
+		/* channel starts from 0 and uart instance starts from 1 */
+		chNum = uartNum * 2 - 2;
+		if (uartNum <= 4) {
+			pru0_mode = PRU_MODE_RX_TX_BOTH;
+		} else {
+			pru1_mode = PRU_MODE_RX_TX_BOTH;
+		}
+	} else {
+		chNum = uartNum - 1;
+		if ((u32ISRValue & 0x03FC) != 0) {
+			u32RegVal = 0;
+
+			offset = PRU_SUART_PRU0_RX_TX_MODE;
+			pru_ram_read_data(offset, (u8 *) &pru0_mode, 1,
+								&pru_arm_iomap);
+			u32RegVal |= 1 << (uartNum + 1);
+			if (u32ISRValue & u32RegVal) {
+				/* acknowledge the s32errupt  */
+				u32AckRegVal = chNum + PRU_SUART0_TX_EVT;
+				pru_ram_write_data_4byte(u32StatInxClrRegoffset,
+							 (u32 *)
+							 &u32AckRegVal, 1);
+				*txrxFlag |= PRU_RX_INTR;
+			}
+		}
+		pru_ram_read_data_4byte(u32IntcOffset, (u32 *)&u32ISRValue, 1);
+		if (u32ISRValue & 0x3FC00) {
+			u32RegVal = 0;
+			offset = PRU_SUART_PRU1_RX_TX_MODE;
+			pru_ram_read_data(offset, (u8 *) &pru1_mode, 1,
+								&pru_arm_iomap);
+			u32RegVal |= 1 << (uartNum + 9);
+			if (u32ISRValue & u32RegVal) {
+				/* acknowledge the s32errupt  */
+				u32AckRegVal = chNum + PRU_SUART4_TX_EVT;
+				pru_ram_write_data_4byte(u32StatInxClrRegoffset,
+							(u32 *)&u32AckRegVal, 1);
+				*txrxFlag |= PRU_TX_INTR;
+			}
+		}
+	}
+	if (u32ISRValue & u32RegVal) {
+		if ((pru0_mode == PRU_MODE_RX_TX_BOTH)
+		    || (pru1_mode == PRU_MODE_RX_TX_BOTH)) {
+			/* Check if the s32errupt occured for Tx */
+			u32RegVal = PRU_SUART0_TX_EVT_BIT << ((uartNum - 1) * 2);
+			if (u32ISRValue & u32RegVal) {
+				/* s32erupt occured for TX */
+				*txrxFlag |= PRU_TX_INTR;
+				/* acknowledge the RX s32errupt  */
+				u32AckRegVal = chNum + PRU_SUART0_TX_EVT;
+				pru_ram_write_data_4byte(u32StatInxClrRegoffset,
+						(u32 *)&u32AckRegVal, 1);
+			}
+
+			/* Check if the s32errupt occured for Rx */
+			u32RegVal = PRU_SUART0_RX_EVT_BIT<<((uartNum - 1) * 2);
+			if (u32ISRValue & u32RegVal) {
+				/* s32erupt occured for RX */
+				*txrxFlag |= PRU_RX_INTR;
+				chNum += 1;
+
+				/* acknowledge the RX s32errupt  */
+				u32AckRegVal = chNum + PRU_SUART0_TX_EVT;
+				pru_ram_write_data_4byte(u32StatInxClrRegoffset,
+						(u32 *)&u32AckRegVal, 1);
+			}
+		}
+		regVal = SUART_SUCCESS;
+	}
+	return regVal;
+}
+
+s32 pru_intr_clr_isrstatus(u16 uartNum, u32 txrxmode)
+{
+	u32 offset;
+	u16 txrxFlag = 0;
+	u16 chnNum;
+
+	chnNum = uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chnNum = (uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (uartNum <= 4) {
+			/* PRU0 */
+			offset = PRU_SUART_PRU0_ISR_OFFSET + 1;
+		} else {
+			/* PRU1 */
+			offset = PRU_SUART_PRU1_ISR_OFFSET + 1;
+			/* First 8 channel corresponds to PRU0 */
+			chnNum -= 8;
+		}
+		if (2 == txrxmode)
+			chnNum++;
+	} else if (PRU0_MODE == txrxmode) {
+		offset = PRU_SUART_PRU0_ISR_OFFSET + 1;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_ISR_OFFSET + 1;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+
+	pru_ram_read_data(offset, (u8 *) &txrxFlag, 1, &pru_arm_iomap);
+	txrxFlag &= ~(0x2);
+	pru_ram_write_data(offset, (u8 *) &txrxFlag, 1, &pru_arm_iomap);
+
+	return 0;
+}
+
+s16 suart_arm_to_pru_intr(u16 uartNum)
+{
+	u32 u32offset;
+	u32 u32value;
+	s16 s16retval;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		if ((uartNum > 0) && (uartNum <= 4)) {
+			/* PRU0 SYS_EVT32 */
+			u32value = 0x20;
+		} else if ((uartNum > 4) && (uartNum <= 8)) {
+			/* PRU1 SYS_EVT33 */
+			u32value = 0x21;
+		} else {
+			return SUART_INVALID_UART_NUM;
+		}
+	}
+
+	if ((PRU0_MODE == PRU_MODE_RX_ONLY) || (PRU1_MODE == PRU_MODE_RX_ONLY)
+	    || (PRU0_MODE == PRU_MODE_TX_ONLY)
+	    || (PRU1_MODE == PRU_MODE_TX_ONLY)) {
+		if (uartNum == PRU_NUM0) {
+			/* PRU0 SYS_EVT32 */
+			u32value = 0x20;
+		}
+
+		if (uartNum == PRU_NUM1) {
+			/* PRU0 SYS_EVT33 */
+			u32value = 0x21;
+		}
+	}
+
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_STATIDXSET &
+										0xFFFF);
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+s16 arm_to_pru_intr_init(void)
+{
+	u32 u32offset;
+	u32 u32value;
+	u32 intOffset;
+	s16 s16retval = -1;
+#if 0
+	/* Set the MCASP Event to PRU0 as Edge Triggered */
+	u32offset =
+	    (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_TYPE0 & 0xFFFF);
+	u32value = 0x80000000;
+	s16retval =
+	    pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1)
+		return -1;
+
+#endif
+	/* Clear all the host s32errupts */
+	for (intOffset = 0; intOffset <= PRU_INTC_HOSTINTLVL_MAX; intOffset++) {
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_HSTINTENIDXCLR & 0xFFFF);
+		u32value = intOffset;
+		s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+		if (s16retval == -1)
+			return -1;
+	}
+
+	/* Enable the global s32errupt */
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_GLBLEN & 0xFFFF);
+	u32value = 0x1;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1) {
+		return -1;
+	}
+
+	/* Enable the Host s32errupts for all host channels */
+	for (intOffset = 0; intOffset <= PRU_INTC_HOSTINTLVL_MAX; intOffset++) {
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_HSTINTENIDXSET & 0xFFFF);
+		u32value = intOffset;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (s16retval == -1) {
+			return -1;
+		}
+	}
+
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_HOSTMAP0 &
+										0xFFFF);
+	u32value = 0x03020100;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (-1 == s16retval) {
+		return -1;
+	}
+
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_HOSTMAP1 &
+										0xFFFF);
+	u32value = 0x07060504;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (-1 == s16retval) {
+		return -1;
+	}
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_HOSTMAP2 &
+										0xFFFF);
+	u32value = 0x00000908;
+	s16retval =
+	    pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (-1 == s16retval)
+		return -1;
+
+	/* Set the channel for System s32rrupts
+	 * MAP Channel 0 to SYS_EVT31
+	 */
+	u32offset =
+	    (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_CHANMAP7 &
+						       0xFFFF);
+	u32value = 0x0000000000;
+	s16retval =
+	    pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (-1 == s16retval)
+		return -1;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		u32offset =
+		    (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_CHANMAP8
+							       & 0xFFFF);
+		u32value = 0x02020100;
+		s16retval =
+		    pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 3 to SYS_EVT36   SUART1-Tx
+		 * MAP channel 3 to SYS_EVT37   SUART1-Rx
+		 * MAP channel 4 to SYS_EVT38   SUART2-Tx
+		 * MAP channel 4 to SYS_EVT39   SUART2-Rx
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_CHANMAP9
+									& 0xFFFF);
+		u32value = 0x04040303;
+		s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value,
+									 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 5 to SYS_EVT40   SUART3-Tx
+		 * MAP channel 5 to SYS_EVT41   SUART3-Rx
+		 * MAP channel 6 to SYS_EVT42   SUART4-Tx
+		 * MAP channel 6 to SYS_EVT43   SUART4-Rx
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+							(PRU_INTC_CHANMAP10 & 0xFFFF);
+		u32value = 0x06060505;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+							(u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 7 to SYS_EVT44   SUART5-Tx
+		 * MAP channel 7 to SYS_EVT45   SUART5-Rx
+		 * MAP channel 8 to SYS_EVT46   SUART6-Tx
+		 * MAP channel 8 to SYS_EVT47   SUART6-Rx
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_CHANMAP11 & 0xFFFF);
+		u32value = 0x08080707;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					   (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 9 to SYS_EVT48   SUART7-Tx
+		 * MAP channel 9 to SYS_EVT49   SUART7-Rx
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+							(PRU_INTC_CHANMAP12 & 0xFFFF);
+		u32value = 0x00010909;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+							(u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+	}
+	if ((PRU0_MODE == PRU_MODE_RX_ONLY) || (PRU1_MODE == PRU_MODE_RX_ONLY)
+	    || (PRU0_MODE == PRU_MODE_TX_ONLY)
+	    || (PRU1_MODE == PRU_MODE_TX_ONLY)) {
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 0 to SYS_EVT32
+		 * MAP channel 1 to SYS_EVT33
+		 * MAP channel 2 to SYS_EVT34  SUART0
+		 * MAP channel 3 to SYS_EVT35  SUART1
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_CHANMAP8
+							       & 0xFFFF);
+		u32value = 0x03020100;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 4 to SYS_EVT36   SUART2
+		 * MAP channel 5 to SYS_EVT37   SUART3
+		 * MAP channel 6 to SYS_EVT38   SUART4
+		 * MAP channel 7 to SYS_EVT39   SUART5
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_CHANMAP9
+							       & 0xFFFF);
+		u32value = 0x07060504;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 8 to SYS_EVT40   SUART6
+		 * MAP channel 9 to SYS_EVT41   SUART7
+		 * MAP channel 2 to SYS_EVT42   SUART0
+		 * MAP channel 3 to SYS_EVT43   SUART1
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+							(PRU_INTC_CHANMAP10 & 0xFFFF);
+		u32value = 0x03020908;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 4 to SYS_EVT44   SUART2
+		 * MAP channel 5 to SYS_EVT45   SUART3
+		 * MAP channel 6 to SYS_EVT46   SUART4
+		 * MAP channel 7 to SYS_EVT47   SUART5
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_CHANMAP11 & 0xFFFF);
+		u32value = 0x07060504;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+
+		/* Sets the channel for the system s32errupt
+		 * MAP channel 8 to SYS_EVT48   SUART6
+		 * MAP channel 9 to SYS_EVT49   SUART7
+		 */
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+							(PRU_INTC_CHANMAP12 & 0xFFFF);
+		u32value = 0x00010908;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (-1 == s16retval) {
+			return -1;
+		}
+	}
+
+	/* Clear required set of system events
+	* and enable them using indexed register
+	*/
+	for (intOffset = 0; intOffset < 18; intOffset++) {
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_STATIDXCLR & 0xFFFF);
+		u32value = 32 + intOffset;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (s16retval == -1)
+			return -1;
+
+	}
+	/* enable only the HOST to PRU s32errupts and let the PRU to Host events be
+	 * enabled by the separate API on demand basis.
+	 */
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_ENIDXSET &
+						       0xFFFF);
+	u32value = 31;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1)
+		return -1;
+
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_ENIDXSET &
+						       0xFFFF);
+	u32value = 32;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1)
+		return -1;
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_ENIDXSET &
+						       0xFFFF);
+	u32value = 33;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1)
+		return -1;
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_ENIDXSET &
+						       0xFFFF);
+	u32value = 50;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1) {
+		return -1;
+	}
+
+	/* Enable the global s32errupt */
+	u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_GLBLEN &
+							       0xFFFF);
+	u32value = 0x1;
+	s16retval = pru_ram_write_data_4byte(u32offset, (u32 *)&u32value, 1);
+	if (s16retval == -1) {
+		return -1;
+	}
+
+	/* Enable the Host s32errupts for all host channels */
+	for (intOffset = 0; intOffset <= PRU_INTC_HOSTINTLVL_MAX; intOffset++) {
+		u32offset = (u32)pru_arm_iomap.pru_io_addr |
+						(PRU_INTC_HSTINTENIDXSET & 0xFFFF);
+		u32value = intOffset;
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (s16retval == -1) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+s32 suart_pru_to_host_intr_enable(u16 uartNum, u32 txrxmode, s32 s32Flag)
+{
+	s32 retVal = 0;
+	u32 u32offset;
+	u32 chnNum;
+	u32 u32value;
+	s16 s16retval = 0;
+
+	if (uartNum > 8) {
+		return SUART_INVALID_UART_NUM;
+	}
+
+	chnNum = uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chnNum = (uartNum * 2) - 2;
+		if (2 == txrxmode) {	/* Rx mode */
+			chnNum++;
+		}
+		u32value = 34 + chnNum;
+	} else if ((PRU_MODE_RX_ONLY == txrxmode)
+		   && (PRU0_MODE == PRU_MODE_RX_ONLY))
+		u32value = 34 + chnNum;
+	else if ((PRU_MODE_RX_ONLY == txrxmode)
+		 && (PRU1_MODE == PRU_MODE_RX_ONLY))
+		u32value = 42 + chnNum;
+	else if ((PRU_MODE_TX_ONLY == txrxmode)
+		 && (PRU0_MODE == PRU_MODE_TX_ONLY))
+		u32value = 34 + chnNum;
+	else if ((PRU_MODE_TX_ONLY == txrxmode)
+		 && (PRU1_MODE == PRU_MODE_TX_ONLY))
+		u32value = 42 + chnNum;
+	else
+		return -1;
+
+	if (SUART_TRUE == s32Flag) {
+		u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_ENIDXSET
+							       & 0xFFFF);
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (s16retval == -1) {
+			return -1;
+		}
+	} else {
+		u32offset = (u32)pru_arm_iomap.pru_io_addr | (PRU_INTC_ENIDXCLR
+							       & 0xFFFF);
+		s16retval = pru_ram_write_data_4byte(u32offset,
+					     (u32 *)&u32value, 1);
+		if (s16retval == -1) {
+			return -1;
+		}
+	}
+	return retVal;
+}
+
+s32 suart_intr_setmask(u16 uartNum, u32 txrxmode, u32 s32rmask)
+{
+	u32 offset;
+	u32 pruOffset;
+	u32 txrxFlag;
+	u32 regval = 0;
+	u32 chnNum;
+
+	chnNum = uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chnNum = (uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if ((uartNum > 0) && (uartNum <= 4)) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+			offset = PRU_SUART_PRU0_IMR_OFFSET;
+		} else if ((uartNum > 4) && (uartNum <= 8)) {
+			offset = PRU_SUART_PRU1_IMR_OFFSET;
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			chnNum -= 8;
+		} else {
+			return SUART_INVALID_UART_NUM;
+		}
+		if (2 == txrxmode) {	/* rx mode */
+			chnNum++;
+		}
+	} else if (PRU0_MODE == txrxmode) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		offset = PRU_SUART_PRU0_IMR_OFFSET;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_IMR_OFFSET;
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	regval = 1 << chnNum;
+	if (CHN_TXRX_IE_MASK_CMPLT == (s32rmask & CHN_TXRX_IE_MASK_CMPLT)) {
+		pru_ram_read_data(offset, (u8 *) &txrxFlag, 2, &pru_arm_iomap);
+		txrxFlag &= ~(regval);
+		txrxFlag |= regval;
+		pru_ram_write_data(offset, (u8 *) &txrxFlag, 2, &pru_arm_iomap);
+	}
+	if ((s32rmask & SUART_GBL_INTR_ERR_MASK) == SUART_GBL_INTR_ERR_MASK) {
+		regval = 0;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(SUART_GBL_INTR_ERR_MASK);
+		regval |= (SUART_GBL_INTR_ERR_MASK);
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+
+	}
+	/* Break Indicator Interrupt Masked */
+	if ((s32rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
+		regval = 0;
+		offset = pruOffset + (chnNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(CHN_TXRX_IE_MASK_FE);
+		regval |= CHN_TXRX_IE_MASK_FE;
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	/* Framing Error Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_BI == (s32rmask & CHN_TXRX_IE_MASK_BI)) {
+		regval = 0;
+		offset = pruOffset + (chnNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(CHN_TXRX_IE_MASK_BI);
+		regval |= CHN_TXRX_IE_MASK_BI;
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	/* Timeout error Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_TIMEOUT == (s32rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
+		regval = 0;
+		offset = pruOffset + (chnNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
+		regval |= CHN_TXRX_IE_MASK_TIMEOUT;
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	return 0;
+}
+
+s32 suart_intr_clrmask(u16 uartNum, u32 txrxmode, u32 s32rmask)
+{
+	u32 offset;
+	u32 pruOffset;
+	u16 txrxFlag;
+	u16 regval = 0;
+	u16 chnNum;
+
+	chnNum = uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chnNum = (uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if ((uartNum > 0) && (uartNum <= 4)) {
+			pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+			offset = PRU_SUART_PRU0_IMR_OFFSET;
+		} else if ((uartNum > 4) && (uartNum <= 8)) {
+			/* PRU1 */
+			offset = PRU_SUART_PRU1_IMR_OFFSET;
+			pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chnNum -= 8;
+		} else {
+			return SUART_INVALID_UART_NUM;
+		}
+		if (2 == txrxmode) {	/* rx mode */
+			chnNum++;
+		}
+	} else if (PRU0_MODE == txrxmode) {
+		pruOffset = PRU_SUART_PRU0_CH0_OFFSET;
+		offset = PRU_SUART_PRU0_IMR_OFFSET;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_IMR_OFFSET;
+		pruOffset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	regval = 1 << chnNum;
+	if (CHN_TXRX_IE_MASK_CMPLT == (s32rmask & CHN_TXRX_IE_MASK_CMPLT)) {
+		pru_ram_read_data(offset, (u8 *) &txrxFlag, 2, &pru_arm_iomap);
+		txrxFlag &= ~(regval);
+		pru_ram_write_data(offset, (u8 *) &txrxFlag, 2, &pru_arm_iomap);
+	}
+
+	if ((s32rmask & SUART_GBL_INTR_ERR_MASK) == SUART_GBL_INTR_ERR_MASK) {
+		regval = 0;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(SUART_GBL_INTR_ERR_MASK);
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+
+	}
+	/* Break Indicator Interrupt Masked */
+	if ((s32rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
+		regval = 0;
+		offset =
+		    pruOffset + (chnNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+		    PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(CHN_TXRX_IE_MASK_FE);
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	/* Framing Error Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_BI == (s32rmask & CHN_TXRX_IE_MASK_BI)) {
+		regval = 0;
+		offset = pruOffset + (chnNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(CHN_TXRX_IE_MASK_BI);
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+
+	/* Timeout error Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_TIMEOUT == (s32rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
+		regval = 0;
+		offset = pruOffset + (chnNum * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+							PRU_SUART_CH_CONFIG1_OFFSET;
+		pru_ram_read_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+		regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
+		pru_ram_write_data(offset, (u8 *) &regval, 2, &pru_arm_iomap);
+	}
+	return 0;
+}
+
+s32 suart_intr_getmask(u16 uartNum, u32 txrxmode, u32 s32rmask)
+{
+	u16 chnNum;
+	u32 offset;
+	u16 txrxFlag;
+	u16 regval = 1;
+
+	chnNum = uartNum - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* channel starts from 0 and uart instance starts from 1 */
+		chnNum = (uartNum * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if ((uartNum > 0) && (uartNum <= 4)) {
+
+			offset = PRU_SUART_PRU0_IMR_OFFSET;
+		} else if ((uartNum > 4) && (uartNum <= 8)) {
+			/* PRU1 */
+			offset = PRU_SUART_PRU1_IMR_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chnNum -= 8;
+		} else {
+			return SUART_INVALID_UART_NUM;
+		}
+
+		if (2 == txrxmode) {	/* rx mode */
+			chnNum++;
+		}
+	} else if (PRU0_MODE == txrxmode) {
+		offset = PRU_SUART_PRU0_IMR_OFFSET;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_IMR_OFFSET;
+	} else {
+		return PRU_MODE_INVALID;
+	}
+	regval = regval << chnNum;
+	pru_ram_read_data(offset, (u8 *) &txrxFlag, 2, &pru_arm_iomap);
+	txrxFlag &= regval;
+	if (0 == s32rmask) {
+		if (txrxFlag == 0)
+			return 1;
+	}
+	if (1 == s32rmask) {
+		if (txrxFlag == regval)
+			return 1;
+	}
+	return 0;
+}
diff --git a/drivers/serial/omapl_pru/suart_api.h b/drivers/serial/omapl_pru/suart_api.h
new file mode 100644
index 0000000..3fb979e
--- /dev/null
+++ b/drivers/serial/omapl_pru/suart_api.h
@@ -0,0 +1,325 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Jitendra Kumar <jitendra@mistralsolutions.com>
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _SUART_API_H_
+#define _SUART_API_H_
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <mach/pru/pru.h>
+
+#define	SINGLE_PRU	0
+#define BOTH_PRU	1
+#define PRU_ACTIVE	BOTH_PRU
+
+#define SUART_NUM_OF_CHANNELS_PER_SUART		2
+#define SUART_NUM_OF_BYTES_PER_CHANNEL		16
+
+#define SUART_PASS		0
+#define SUART_SUCCESS	0
+#define SUART_FAIL		1
+#define SUART_FALSE		0
+#define SUART_TRUE		1
+
+#define PRU_TX_INTR		1
+#define PRU_RX_INTR		2
+
+#define CHN_TXRX_STATUS_TIMEOUT	BIT(6)
+#define CHN_TXRX_STATUS_BI		BIT(5)
+#define CHN_TXRX_STATUS_FE		BIT(4)
+#define CHN_TXRX_STATUS_UNERR	BIT(3)
+#define CHN_TXRX_STATUS_OVRNERR	BIT(3)	/* UNERR->TX & OVRNERR->RX */
+#define CHN_TXRX_STATUS_ERR		BIT(2)
+#define CHN_TXRX_STATUS_CMPLT	BIT(1)
+#define CHN_TXRX_STATUS_RDY		BIT(0)
+
+#define CHN_TXRX_IE_MASK_TIMEOUT	BIT(14)
+#define CHN_TXRX_IE_MASK_BI			BIT(13)
+#define CHN_TXRX_IE_MASK_FE			BIT(12)
+#define CHN_TXRX_IE_MASK_CMPLT		BIT(1)
+
+#define SUART_GBL_INTR_ERR_MASK		BIT(9)
+#define SUART_PRU_ID_MASK			0xFF
+
+#define SUART_FIFO_LEN			15
+#define SUART_8X_OVRSMPL		1
+#define SUART_16X_OVRSMPL		2
+#define SUART_DEFAULT_OVRSMPL	SUART_8X_OVRSMPL
+
+#if (SUART_DEFAULT_OVRSMPL == SUART_16X_OVRSMPL)
+#define SUART_DEFAULT_BAUD		57600
+#else
+#define SUART_DEFAULT_BAUD		115200
+#endif
+
+#define PRU_MODE_INVALID		0x00
+#define PRU_MODE_TX_ONLY		0x1
+#define PRU_MODE_RX_ONLY		0x2
+#define PRU_MODE_RX_TX_BOTH		0x3
+
+#if (PRU_ACTIVE == BOTH_PRU)
+#define PRU0_MODE	PRU_MODE_RX_ONLY
+#define PRU1_MODE	PRU_MODE_TX_ONLY
+#elif (PRU_ACTIVE ==  SINGLE_PRU)
+#define PRU0_MODE	PRU_MODE_RX_TX_BOTH
+#define PRU1_MODE	PRU_MODE_INVALID
+#else
+#define PRU0_MODE	PRU_MODE_INVALID
+#define PRU1_MODE	PRU_MODE_INVALID
+#endif
+
+#define MCASP_XBUF_BASE_ADDR	(0x01d00200)
+#define MCASP_RBUF_BASE_ADDR	(0x01d00280)
+#define MCASP_SRCTL_BASE_ADDR	(0x01d00180)
+
+#define MCASP_SRCTL_TX_MODE		(0x000D)
+#define MCASP_SRCTL_RX_MODE		(0x000E)
+
+/* Since only PRU0 can work as RX */
+#define RX_DEFAULT_DATA_DUMP_ADDR	(0x00001FC)
+#define PRU_NUM_OF_CHANNELS			(16)
+
+#define PRU_SUART_UART1		(1u)
+#define PRU_SUART_UART2		(2u)
+#define PRU_SUART_UART3		(3u)
+#define PRU_SUART_UART4		(4u)
+#define PRU_SUART_UART5		(5u)
+#define PRU_SUART_UART6		(6u)
+#define PRU_SUART_UART7		(7u)
+#define PRU_SUART_UART8		(8u)
+
+#define PRU_SUART_UARTx_INVALID	(9u)
+
+/*
+ *  This enum is used to specify the direction of the channel in UART
+ */
+typedef enum {
+	SUART_CHN_TX = 1,
+	SUART_CHN_RX = 2
+} SUART_CHN_DIR;
+
+/*
+ *  This enum is used to specify the state of the channel in UART. It
+ *  is either enabled or disabled.
+ */
+typedef enum {
+	SUART_CHN_DISABLED = 0,
+	SUART_CHN_ENABLED = 1
+} SUART_CHN_STATE;
+
+typedef enum {
+	ePRU_SUART_DATA_BITS6 = 8,
+	ePRU_SUART_DATA_BITS7,
+	ePRU_SUART_DATA_BITS8,
+	ePRU_SUART_DATA_BITS9,
+	ePRU_SUART_DATA_BITS10,
+	ePRU_SUART_DATA_BITS11,
+	ePRU_SUART_DATA_BITS12
+	} SUART_EN_BITSPERCHAR;
+
+typedef enum {
+	ePRU_SUART_NUM_1 = 1,
+	ePRU_SUART_NUM_2,
+	ePRU_SUART_NUM_3,
+	ePRU_SUART_NUM_4,
+	ePRU_SUART_NUM_5,
+	ePRU_SUART_NUM_6,
+	ePRU_SUART_NUM_7,
+	ePRU_SUART_NUM_8
+} SUART_EN_UARTNUM;
+
+typedef enum {
+	ePRU_SUART_HALF_TX = 1,
+	ePRU_SUART_HALF_RX,
+	ePRU_SUART_FULL_TX_RX
+} SUART_EN_UARTTYPE;
+
+typedef enum {
+	ePRU_SUART_TX_CH0 = 0,
+	ePRU_SUART_TX_CH1,
+	ePRU_SUART_TX_CH2,
+	ePRU_SUART_TX_CH3,
+	ePRU_SUART_TX_CH4,
+	ePRU_SUART_TX_CH5,
+	ePRU_SUART_TX_CH6,
+	ePRU_SUART_TX_CH7
+} SUART_EN_TXCHANNEL;
+
+typedef enum {
+	ePRU_SUART_RX_CH0 = 0,
+	ePRU_SUART_RX_CH1,
+	ePRU_SUART_RX_CH2,
+	ePRU_SUART_RX_CH3,
+	ePRU_SUART_RX_CH4,
+	ePRU_SUART_RX_CH5,
+	ePRU_SUART_RX_CH6,
+	ePRU_SUART_RX_CH7
+} SUART_EN_RXCHANNEL;
+
+typedef enum {
+	ePRU_SUART_UART_FREE = 0,
+	ePRU_SUART_UART_IN_USE
+} SUART_EN_UART_STATUS;
+
+typedef struct {
+	u16 mode:2;
+	u16 service_req:1;
+	u16 asp_id:2;
+	u16 reserved1:3;
+	u16 serializer_num:4;
+	u16 reserved2:4;
+
+} pru_suart_chn_cntrl;
+
+typedef struct {
+	u16 presacler:10;
+	u16 over_sampling:2;
+	u16 framing_mask:1;
+	u16 break_mask:1;
+	u16 timeout_mask:1;
+	u16 reserved:1;
+} pru_suart_cnh_config1;
+
+typedef struct {
+	u16 bits_per_char:4;
+	u16 reserved1:4;
+	u16 data_len:4;
+	u16 reserved:4;
+} pru_suart_chn_config2;
+
+typedef struct {
+	u16 txrx_ready:1;
+	u16 txrx_complete:1;
+	u16 txrx_error:1;
+	u16 txrx_underrun:1;
+	u16 framing_error:1;
+	u16 break_error:1;
+	u16 timeout_error:1;
+	u16 reserved:8;
+	u16 chn_state:1;
+} pru_suart_chn_status;
+
+typedef struct {
+	pru_suart_chn_cntrl CH_Ctrl;
+	pru_suart_cnh_config1 CH_Config1;
+	pru_suart_chn_config2 CH_Config2;
+	pru_suart_chn_status CH_TXRXStatus;
+	u32 CH_TXRXData;
+	u32 Reserved1;
+} pru_suart_regs, *PRU_SUART_RegsOvly;
+
+typedef struct {
+	u32 asp_xsrctl_base;
+	u32 asp_xbuf_base;
+	u16 buff_addr;
+	u8 buff_size;
+	u8 bits_loaded;
+} pru_suart_tx_cntx_priv, *ppru_suart_tx_cntx_priv;
+
+typedef struct {
+	u32 asp_rbuf_base;
+	u32 asp_rsrctl_base;
+	u32 reserved1;
+	u32 reserved2;
+	u32 reserved3;
+	u32 reserved4;
+} pru_suart_rx_cntx_priv, *ppru_suart_rx_cntx_priv;
+
+typedef struct {
+	u8 TXSerializer;
+	u8 RXSerializer;
+	u16 txClkDivisor;
+	u16 rxClkDivisor;
+	u8 txBitsPerChar;
+	u8 rxBitsPerChar;
+	u8 Oversampling;
+	u8 BIIntrMask;
+	u8 FEIntrMask;
+} suart_config;
+
+typedef struct {
+	u16 uartNum;
+	u16 uartType;
+	u16 uartTxChannel;
+	u16 uartRxChannel;
+	u16 uartStatus;
+} suart_struct_handle, *suart_handle;
+
+s16 pru_softuart_init(u32 txBaudValue, u32 rxBaudValue, u32 oversampling,
+					u8 *pru_suart_emu_code, u32 fw_size,
+					arm_pru_iomap *pru_arm_iomap1);
+
+s32 pru_intr_set_mask(u16 uartNum, u32 txrxmode, u32 intrmask);
+
+s16 pru_softuart_reset(u32 txBaudValue, u32 rxBaudValue, u32 oversampling);
+
+s16 pru_softuart_open(suart_handle hSuart);
+
+s16 pru_softuart_close(suart_handle hUart);
+
+s16 pru_softuart_setbaud(suart_handle hUart, u16 txClkDivisor,
+						u16 rxClkDivisor);
+
+s16 pru_softuart_setdatabits(suart_handle hUart, u16 txDataBits,
+							u16 rxDataBits);
+
+s16 pru_softuart_setconfig(suart_handle hUart, suart_config *configUart);
+
+s16 pru_softuart_getconfig(suart_handle hUart, suart_config *configUart);
+
+s32 pru_softuart_pending_tx_request(void);
+
+s16 pru_softuart_write(suart_handle hUart, u32 *ptTxDataBuf, u16 dataLen);
+
+s16 pru_softuart_read(suart_handle hUart, u32 *ptDataBuf, u16 dataLen);
+
+s32 suart_intr_clrmask(u16 uartNum, u32 txrxmode, u32 intrmask);
+
+s16 pru_softuart_clrTxStatus(suart_handle hUart);
+
+s16 pru_softuart_getTxStatus(suart_handle hUart);
+
+s16 pru_softuart_clrRxStatus(suart_handle hUart);
+
+s16 pru_softuart_getRxStatus(suart_handle hUart);
+
+s16 pru_softuart_get_isrstatus(u16 uartNum, u16 *txrxFlag);
+
+s32 pru_intr_clr_isrstatus(u16 uartNum, u32 txrxmode);
+
+s32 suart_intr_getmask(u16 uartNum, u32 txrxmode, u32 intrmask);
+
+s32 suart_intr_setmask(u16 uartNum, u32 txrxmode, u32 intrmask);
+
+s16 pru_softuart_getTxDataLen(suart_handle hUart);
+
+s16 pru_softuart_getRxDataLen(suart_handle hUart);
+
+s16 suart_arm_to_pru_intr(u16 uartNum);
+
+s16 arm_to_pru_intr_init(void);
+
+s16 pru_softuart_deinit(void);
+
+s16 pru_softuart_clrRxFifo(suart_handle hUart);
+
+s16 pru_softuart_read_data(suart_handle hUart, u8 *pDataBuffer,
+					     s32 s32MaxLen, u32 *pu32DataRead);
+
+s16 pru_softuart_stopReceive(suart_handle hUart);
+
+s32 suart_pru_to_host_intr_enable(u16 uartNum, u32 txrxmode, s32 s32Flag);
+
+void pru_set_fifo_timeout(u32 timeout);
+#endif
diff --git a/drivers/serial/omapl_pru/suart_err.h b/drivers/serial/omapl_pru/suart_err.h
new file mode 100644
index 0000000..ef114e3
--- /dev/null
+++ b/drivers/serial/omapl_pru/suart_err.h
@@ -0,0 +1,48 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: jitendra@mistralsolutions.com
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _SUART_ERR_H_
+#define _SUART_ERR_H_
+
+#define PRU_SUART_SUCCESS	(0u)
+#define PRU_SUART_FAILURE	(-1)
+
+#define PRU_SUART_ERR_DEVICE_NOT_OPEN	(1u)
+#define PRU_SUART_ERR_UARTS_INIT_FAIL	(2u)
+#define PRU_SUART_ERR_UARTS_RESET_FAIL	(3u)
+#define PRU_SUART_ERR_HANDLE_INVALID	(4u)
+#define PRU_SUART_ERR_PARAMETER_INVALID	(5u)
+
+#define PRU_SUART_ERR_TX		(6u)
+#define PRU_SUART_TX_COMPLETE	(7u)
+#define PRU_SUART_TX_BUSY		(8u)
+#define PRU_SUART_TX_UNDERRUN	(9u)
+
+#define PRU_SUART_ERR_RX		(10u)
+#define PRU_SUART_RX_COMPLETE	(11u)
+#define PRU_SUART_RX_BUSY		(12u)
+#define PRU_SUART_RX_OVERRUN	(13u)
+
+/* API Specific Errors */
+#define SUART_INVALID_TX_BAUD		(14u)
+#define SUART_INVALID_OVERSAMPLING	(15u)
+#define SUART_INVALID_RX_BAUD		(16u)
+
+#define SUART_UART_IN_USE	(17u)
+
+#define SUART_INVALID_CLKDIVISOR	(18u)
+#define SUART_INVALID_UART_NUM		(19u)
+#define SUART_INVALID_SR_NUM		(20u)
+
+#endif
diff --git a/drivers/serial/omapl_pru/suart_pru_regs.h b/drivers/serial/omapl_pru/suart_pru_regs.h
new file mode 100644
index 0000000..393cf27
--- /dev/null
+++ b/drivers/serial/omapl_pru/suart_pru_regs.h
@@ -0,0 +1,152 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: jitendra@mistralsolutions.com
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _SUART_PRU_REGS_H_
+#define _SUART_PRU_REGS_H_
+
+#include <linux/types.h>
+
+#define PRU_DATARAM_BASE_ADDR		(0x01C30000u)
+#define PRU0_DATARAM0_OFFSET		(0x0000u)
+/** PRU0 DATA RAM base address */
+#define PRU0_DATARAM1_OFFSET		(0x2000u)
+/** PRU0 DATA RAM base address */
+#define PRU_SUART_DATARAM0_BASE		(PRU_DATARAM_BASE_ADDR + PRU0_DATARAM0_OFFSET)
+/** PRU1 DATA RAM base address */
+#define PRU_SUART_DATARAM1_BASE		(PRU_DATARAM_BASE_ADDR + PRU0_DATARAM0_OFFSET)
+/** PRU1 DATA RAM base address */
+#define PRU_SUART_PRU0_CH0_OFFSET	(0x0000)
+#define PRU_SUART_PRU0_CH1_OFFSET	(0x0010)
+#define PRU_SUART_PRU0_CH2_OFFSET	(0x0020)
+#define PRU_SUART_PRU0_CH3_OFFSET	(0x0030)
+#define PRU_SUART_PRU0_CH4_OFFSET	(0x0040)
+#define PRU_SUART_PRU0_CH5_OFFSET	(0x0050)
+#define PRU_SUART_PRU0_CH6_OFFSET	(0x0060)
+#define PRU_SUART_PRU0_CH7_OFFSET	(0x0070)
+#define PRU_SUART_PRU0_IMR_OFFSET	(0x0080)
+/** Interrupt Mask Register */
+#define PRU_SUART_PRU0_ISR_OFFSET	(0x0082)
+/** Interrupt Status Register */
+#define PRU_SUART_PRU0_ID_ADDR		(0x0084)
+/** PRU ID Register */
+#define PRU_SUART_PRU0_RX_TX_MODE	(0x0085)
+#define PRU_SUART_PRU0_DELAY_OFFSET	(0x0086)
+#define PRU_SUART_PRU0_IDLE_TIMEOUT_OFFSET	(0x0088)
+
+/* ********* PRU 1 Macros ************* */
+#define PRU_SUART_PRU1_CH0_OFFSET	(0x2000)
+#define PRU_SUART_PRU1_CH1_OFFSET	(0x2010)
+#define PRU_SUART_PRU1_CH2_OFFSET	(0x2020)
+#define PRU_SUART_PRU1_CH3_OFFSET	(0x2030)
+#define PRU_SUART_PRU1_CH4_OFFSET	(0x2040)
+#define PRU_SUART_PRU1_CH5_OFFSET	(0x2050)
+#define PRU_SUART_PRU1_CH6_OFFSET	(0x2060)
+#define PRU_SUART_PRU1_CH7_OFFSET	(0x2070)
+#define PRU_SUART_PRU1_IMR_OFFSET	(0x2080)
+#define PRU_SUART_PRU1_ISR_OFFSET	(0x2082)
+#define PRU_SUART_PRU1_ID_ADDR      (0x2084)
+#define PRU_SUART_PRU1_RX_TX_MODE   (0x2085)
+#define PRU_SUART_PRU1_DELAY_OFFSET	(0x2086)
+#define PRU_SUART_PRU1_IDLE_TIMEOUT_OFFSET		(0x2088)
+
+/* SUART Channel Control Register bit descriptions */
+#define PRU_SUART_CH_CTRL_MODE_SHIFT			0x0000
+#define PRU_SUART_CH_CTRL_MODE_MASK				0x0003
+#define PRU_SUART_CH_CTRL_TX_MODE				0x0001
+#define PRU_SUART_CH_CTRL_RX_MODE				0x0002
+
+/* Service Request */
+#define PRU_SUART_CH_CTRL_SREQ_SHIFT			0x0002
+#define PRU_SUART_CH_CTRL_SREQ_MASK				0x0004
+#define PRU_SUART_CH_CTRL_SREQ					0x0001
+
+/* McASP Instance */
+#define PRU_SUART_CH_CTRL_MCASP_SHIFT			0x0003
+#define PRU_SUART_CH_CTRL_MCASP_MASK			0x0018
+#define PRU_SUART_CH_CTRL_SR_SHIFT				0x0008
+#define PRU_SUART_CH_CTRL_SR_MASK				0x0F00
+
+/* SUART channel configuration1 register descriptions */
+
+/* clock divisor -  relative baud value */
+#define PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT		0x0000
+#define PRU_SUART_CH_CONFIG1_DIVISOR_MASK		0x03FF
+/* oversampling */
+#define PRU_SUART_CH_CONFIG1_OVS_SHIFT			0x000A
+#define PRU_SUART_CH_CONFIG1_OVS_MASK			0x0C00
+
+/* SUART channel configuration2 register descriptions */
+/* Bits per character */
+#define PRU_SUART_CH_CONFIG2_BITPERCHAR_SHIFT	0x0000
+#define PRU_SUART_CH_CONFIG2_BITPERCHAR_MASK	0x000F
+
+/* Bits per character */
+#define PRU_SUART_CH_CONFIG2_DATALEN_SHIFT		0x0008
+#define PRU_SUART_CH_CONFIG2_DATALEN_MASK		0x0F00
+
+/* SUART Channel register offsets */
+#define PRU_SUART_CH_CTRL_OFFSET				0x00
+#define PRU_SUART_CH_CONFIG1_OFFSET				0x02
+#define PRU_SUART_CH_CONFIG2_OFFSET				0x04
+#define PRU_SUART_CH_TXRXSTATUS_OFFSET			0x06
+#define PRU_SUART_CH_TXRXDATA_OFFSET			0x08
+#define PRU_SUART_CH_BYTESDONECNTR_OFFSET		0x0C
+
+/* SUART Event Numbers macros */
+#define PRU_SUART0_TX_EVT	34
+#define PRU_SUART0_RX_EVT	35
+#define PRU_SUART1_TX_EVT	36
+#define PRU_SUART1_RX_EVT	37
+#define PRU_SUART2_TX_EVT	38
+#define PRU_SUART2_RX_EVT	39
+#define PRU_SUART3_TX_EVT	40
+#define PRU_SUART3_RX_EVT	41
+#define PRU_SUART4_TX_EVT	42
+#define PRU_SUART4_RX_EVT	43
+#define PRU_SUART5_TX_EVT	44
+#define PRU_SUART5_RX_EVT	45
+#define PRU_SUART6_TX_EVT	46
+#define PRU_SUART6_RX_EVT	47
+#define PRU_SUART7_TX_EVT	48
+#define PRU_SUART7_RX_EVT	49
+
+#define PRU_SUART0_TX_EVT_BIT	BIT(2)
+#define PRU_SUART0_RX_EVT_BIT	BIT(3)
+#define PRU_SUART1_TX_EVT_BIT	BIT(4)
+#define PRU_SUART1_RX_EVT_BIT	BIT(5)
+#define PRU_SUART2_TX_EVT_BIT	BIT(6)
+#define PRU_SUART2_RX_EVT_BIT	BIT(7)
+#define PRU_SUART3_TX_EVT_BIT	BIT(8)
+#define PRU_SUART3_RX_EVT_BIT	BIT(9)
+#define PRU_SUART4_TX_EVT_BIT	BIT(10)
+#define PRU_SUART4_RX_EVT_BIT	BIT(11)
+#define PRU_SUART5_TX_EVT_BIT	BIT(12)
+#define PRU_SUART5_RX_EVT_BIT	BIT(13)
+#define PRU_SUART6_TX_EVT_BIT	BIT(14)
+#define PRU_SUART6_RX_EVT_BIT	BIT(15)
+#define PRU_SUART7_TX_EVT_BIT	BIT(16)
+#define PRU_SUART7_RX_EVT_BIT	BIT(17)
+
+/*
+ *  SUART Config regs
+ */
+typedef struct {
+	unsigned short CHn_Ctrl;
+	unsigned short CHn_Config1;
+	unsigned short CHn_Config2;
+	unsigned short CHn_TXRXStatus;
+	unsigned int CHn_TXRXData;
+} suart_struct_pru_regs;
+
+#endif
diff --git a/drivers/serial/omapl_pru/suart_utils.c b/drivers/serial/omapl_pru/suart_utils.c
new file mode 100644
index 0000000..5ea93f2
--- /dev/null
+++ b/drivers/serial/omapl_pru/suart_utils.c
@@ -0,0 +1,363 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Jitendra Kumar <jitendra@mistralsolutions.com>
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <mach/pru/pru.h>
+#include <mach/pru/omapl_mcasp.h>
+#include "suart_pru_regs.h"
+#include "omapl_suart_board.h"
+#include "suart_api.h"
+#include "suart_utils.h"
+#include "suart_err.h"
+
+#define SUART_TRX_DIV_CONF_SZ	4
+
+static s16 suart_mcasp_tx_baud_set(u32 txBaudValue,
+							arm_pru_iomap *pru_arm_iomap);
+static s16 suart_mcasp_rx_baud_set(u32 rxBaudValue, u32 oversampling,
+							arm_pru_iomap *pru_arm_iomap);
+
+/*
+ * Lookup table for TX baud rate
+ * The divisor value is calculated using the formula
+ *
+ * ACLKX = (AUXCLK)/(CLKXDIV * HCLKXDIV)
+ *
+ * Where
+ *		CLKXDIV takes values from 1-32
+ *		HCLKXDIV takes values from 1-4096
+ * Here
+ *		AUXCLK = 24MHz
+ */
+u32 lt_tx_baud_rate[][SUART_TRX_DIV_CONF_SZ] = {
+	/*BaudRate,	Divisor,	CLKXDIV,HCLKXDIV */
+	{300,		80000,		24,		3200},
+	{600,		40000,		15,		2500},
+	{1800,		13333,		10,		1212},
+	{2400,		10000,		4,		2000},
+	{4800,		5000,		1,		2500},
+	{7200,		3333,		0,		3333},
+	{9600,		2500,		0,		2500},
+	{14400,		1666,		0,		1666},
+	{19200,		1250,		0,		1250},
+	{38400,		625,		0,		625},
+	{57600,		416,		0,		416},
+	{115200,	208,		0,		208},
+	{230400,	104,		0,		104}
+};
+
+/*
+ * Lookup table for RX baud rate for 8 bit oversampling
+ * The divisor value is calculated using the formula
+ *
+ *	ACLKR = (AUXCLK)/(CLKRDIV * HCLKRDIV) * Oversampling
+ *
+ * Where
+ *		CLKRDIV takes values from 1-32
+ *		HCLKRDIV takes values from 1-4096
+ * Here
+ *		AUXCLK = 24MHz
+ */
+u32 lt_rx_8x_baud_rate[][SUART_TRX_DIV_CONF_SZ] = {
+/* BaudRate,	Divisor,	CLKXDIV,	HCLKXDIV */
+	{300,		10000,		4,		2000},
+	{600,		5000,		1,		2500},
+	{1800,		1667,		0,		1667},
+	{2400,		1250,		0,		1250},
+	{7200,		417,		0,		417},
+	{4800,		625,		0,		625},
+	{9600,		312,		0,		312},
+	{14400,		208,		0,		208},
+	{19200,		156,		0,		156},
+	{38400,		78,			0,		78},
+	{57600,		52,			0,		52},
+	{115200,	26,			0,		26},
+	{230400,	13,			0,		13}
+};
+
+/*
+ * Lookup table for RX baud rate for 16 bit oversampling
+ * The divisor value is calculated using the formula
+ *
+ *	ACLKR = (AUXCLK)/(CLKRDIV * HCLKRDIV) * Oversampling
+ *
+ * Where
+ *		CLKRDIV takes values from 1-32
+ *		HCLKRDIV takes values from 1-4096
+ * Here
+ *		AUXCLK = 24MHz
+ */
+u32 lt_rx_16x_baud_rate[][SUART_TRX_DIV_CONF_SZ] = {
+/*BaudRate,	Divisor,	CLKXDIV,	HCLKXDIV */
+	{300,		5000,		1,		2500},
+	{600,		2500,		0,		2500},
+	{1800,		833,		0,		833},
+	{2400,		625,		0,		625},
+	{4800,		312,		0,		312},
+	{7200,		208,		0,		208},
+	{9600,		156,		0,		156},
+	{14400,		104,		0,		104},
+	{19200,		78,			0,		78},
+	{38400,		39,			0,		39},
+	{57600,		26,			0,		26},
+	{115200,	13,			0,		13},
+	{230400,	6,			0,		6}
+};
+
+/*
+ * McASP configuration routine
+ */
+void suart_mcasp_config(u32 mcasp_addr,
+			u32 txBaudValue,
+			u32 rxBaudValue,
+			u32 oversampling,
+			arm_pru_iomap *pru_arm_iomap)
+{
+	OMAPL_McaspRegsOvly mcasp0Regs = (OMAPL_McaspRegsOvly) mcasp_addr;
+
+	/* reset mcasp */
+	mcasp0Regs->GBLCTL = 0;
+	mcasp0Regs->RGBLCTL = 0;
+	mcasp0Regs->XGBLCTL = 0;
+
+	/* configure receive registers */
+	if ((SUART_8X_OVRSMPL == oversampling) || (0 == oversampling)) {
+		mcasp0Regs->RMASK = 0x000000FF;
+		mcasp0Regs->RFMT = 0x0000A038;	/* slot size 8 bits,RPAD=1 */
+	}
+	if (SUART_16X_OVRSMPL == oversampling) {
+		mcasp0Regs->RMASK = 0x0000FFFF;
+		mcasp0Regs->RFMT = 0x0000A078;
+	}
+
+	mcasp0Regs->AFSRCTL = 0x00000002;	/* burst mode */
+	mcasp0Regs->ACLKRCTL = 0x000000A0;
+	mcasp0Regs->AHCLKRCTL = 0x00008000;
+	suart_mcasp_rx_baud_set(rxBaudValue, oversampling, pru_arm_iomap);
+
+	mcasp0Regs->RTDM = 0x00000001;
+	mcasp0Regs->RINTCTL = 0x00000002;
+	mcasp0Regs->RCLKCHK = 0x00FF0008;
+
+	/* configure transmit registers. */
+	mcasp0Regs->XMASK = 0x0000FFFF;
+	mcasp0Regs->XFMT = 0x00002078;
+	mcasp0Regs->AFSXCTL = 0x0000002;	/* Burst mode */
+	mcasp0Regs->ACLKXCTL = 0x000000E0;
+	mcasp0Regs->AHCLKXCTL = 0x00008000;
+
+	suart_mcasp_tx_baud_set(txBaudValue, pru_arm_iomap);
+
+	mcasp0Regs->XTDM = 0x00000001;
+	mcasp0Regs->XINTCTL = 0x00000002;
+	mcasp0Regs->XCLKCHK = 0x00FF0008;
+
+	/* Serializer as a transmitter */
+	mcasp0Regs->SRCTL0 = 0x000c;
+	mcasp0Regs->SRCTL1 = 0x000c;
+	mcasp0Regs->SRCTL2 = 0x000c;
+	mcasp0Regs->SRCTL3 = 0x000c;
+	mcasp0Regs->SRCTL4 = 0x000c;
+	mcasp0Regs->SRCTL5 = 0x000c;
+	mcasp0Regs->SRCTL6 = 0x000c;
+	mcasp0Regs->SRCTL7 = 0x000c;
+	mcasp0Regs->SRCTL8 = 0x000c;
+	mcasp0Regs->SRCTL9 = 0x000c;
+	mcasp0Regs->SRCTL10 = 0x000c;
+	mcasp0Regs->SRCTL11 = 0x000c;
+	mcasp0Regs->SRCTL12 = 0x000c;
+	mcasp0Regs->SRCTL13 = 0x000c;
+	mcasp0Regs->SRCTL14 = 0x000c;
+	mcasp0Regs->SRCTL15 = 0x000c;
+
+	/* Configure all AXR[n] as McASP pins  */
+
+	/*
+	 *  Setting  all TX MCASP AXR[n] Pin mapped to Even Serializer number
+	 *  (0,2,4,6,8,10,12,14) to GPIO Mode by default. During setting the
+	 *  serializer to TX mode in PRU assembly code, the MCASP AXR[n] Pin
+	 *  would get configured to MCASP mode of operation,
+	 *  before Actual Data Transfer
+	 */
+
+	/* Setting  all TX Pin to GPIO Mode by default */
+	mcasp0Regs->PFUNC = (OMAPL_MCASP_PFUNC_RESETVAL) |
+	    (1 << PRU_SUART1_CONFIG_TX_SER) | (1 << PRU_SUART2_CONFIG_TX_SER) |
+	    (1 << PRU_SUART3_CONFIG_TX_SER) | (1 << PRU_SUART4_CONFIG_TX_SER) |
+	    (1 << PRU_SUART5_CONFIG_TX_SER) | (1 << PRU_SUART6_CONFIG_TX_SER) |
+	    (1 << PRU_SUART7_CONFIG_TX_SER) | (1 << PRU_SUART8_CONFIG_TX_SER);
+
+	mcasp0Regs->PDOUT = 0xFFFF;
+
+	/* config pin function and direction */
+	mcasp0Regs->PDIR = 0x00000000;
+	mcasp0Regs->PDIR =
+	    (1 << PRU_SUART1_CONFIG_TX_SER) | (1 << PRU_SUART2_CONFIG_TX_SER) |
+	    (1 << PRU_SUART3_CONFIG_TX_SER) | (1 << PRU_SUART4_CONFIG_TX_SER) |
+	    (1 << PRU_SUART5_CONFIG_TX_SER) | (1 << PRU_SUART6_CONFIG_TX_SER) |
+	    (1 << PRU_SUART7_CONFIG_TX_SER) | (1 << PRU_SUART8_CONFIG_TX_SER) |
+	    (MCASP_PDIR_VAL);
+
+	mcasp0Regs->PDOUT = 0xFFFF;
+
+	mcasp0Regs->DITCTL = 0x00000000;
+	mcasp0Regs->DLBCTL = 0x00000000;
+	mcasp0Regs->AMUTE = 0x00000000;
+
+	mcasp0Regs->XSTAT = 0x0000FFFF;	/* Clear all */
+	mcasp0Regs->RSTAT = 0x0000FFFF;	/* Clear all */
+}
+
+void suart_mcasp_tx_serialzier_set(u32 serializerNum,
+				arm_pru_iomap *pru_arm_iomap)
+{
+	OMAPL_McaspRegsOvly mcasp0Regs =
+	    (OMAPL_McaspRegsOvly) pru_arm_iomap->mcasp_io_addr;
+
+	mcasp0Regs->PFUNC |= (0x1 << serializerNum);
+}
+
+/*
+ * mcasp TX buard rate setting routine
+ */
+s16 suart_mcasp_tx_baud_set(u32 txBaudValue,
+				arm_pru_iomap *pru_arm_iomap)
+{
+	u32 clkDivVal;
+	u32 loopCnt;
+	s16 status = SUART_SUCCESS;
+	s16 foundVal = SUART_FALSE;
+
+	OMAPL_McaspRegsOvly mcasp0Regs =
+	    (OMAPL_McaspRegsOvly) pru_arm_iomap->mcasp_io_addr;
+
+	/* Search the supported baud rate in the table */
+	for (loopCnt = 0; loopCnt < SUART_NUM_OF_BAUDS_SUPPORTED; loopCnt++) {
+		if (txBaudValue == lt_tx_baud_rate[loopCnt][0]) {
+			foundVal = SUART_TRUE;
+			break;
+		}
+	}
+	if (foundVal == SUART_TRUE) {
+		clkDivVal = lt_tx_baud_rate[loopCnt][2];
+
+		mcasp0Regs->ACLKXCTL |=
+		    clkDivVal << OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
+		clkDivVal = lt_tx_baud_rate[loopCnt][3];	/* starts from 0 */
+		mcasp0Regs->AHCLKXCTL |=
+		    clkDivVal << OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
+	} else {
+		return SUART_INVALID_TX_BAUD;
+	}
+	return status;
+}
+
+/*
+ * mcasp RX buard rate setting routine
+ */
+s16 suart_mcasp_rx_baud_set(u32 rxBaudValue,
+			u32 oversampling, arm_pru_iomap *pru_arm_iomap)
+{
+	u32 clkDivVal;
+	u32 loopCnt;
+	s16 status = SUART_SUCCESS;
+	s16 foundVal = SUART_FALSE;
+
+	OMAPL_McaspRegsOvly mcasp0Regs =
+	    (OMAPL_McaspRegsOvly) pru_arm_iomap->mcasp_io_addr;
+
+	if (oversampling == SUART_8X_OVRSMPL) {
+		for (loopCnt = 0; loopCnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+		     loopCnt++) {
+			if (rxBaudValue == lt_rx_8x_baud_rate[loopCnt][0]) {
+				clkDivVal = lt_rx_8x_baud_rate[loopCnt][2];
+				mcasp0Regs->ACLKRCTL |= clkDivVal <<
+						OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
+				clkDivVal = lt_rx_8x_baud_rate[loopCnt][3] - 1;
+				mcasp0Regs->AHCLKRCTL |= clkDivVal <<
+					 OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
+				foundVal = SUART_TRUE;
+				break;
+			}
+		}
+	} else if (oversampling == SUART_16X_OVRSMPL) {
+		for (loopCnt = 0; loopCnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+		     loopCnt++) {
+			if (rxBaudValue == lt_rx_16x_baud_rate[loopCnt][0]) {
+				clkDivVal = lt_rx_16x_baud_rate[loopCnt][2];
+				mcasp0Regs->ACLKRCTL |= clkDivVal <<
+				    OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
+				clkDivVal = lt_rx_16x_baud_rate[loopCnt][3];
+				mcasp0Regs->AHCLKRCTL |= clkDivVal <<
+				    OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
+				foundVal = SUART_TRUE;
+				break;
+			}
+		}
+	} else if (oversampling == 0) {
+		for (loopCnt = 0; loopCnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+		     loopCnt++) {
+			if (rxBaudValue == lt_tx_baud_rate[loopCnt][0]) {
+				clkDivVal = lt_tx_baud_rate[loopCnt][2];
+				mcasp0Regs->ACLKRCTL |= clkDivVal <<
+				    OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
+				clkDivVal = lt_tx_baud_rate[loopCnt][3];
+				mcasp0Regs->AHCLKRCTL |= clkDivVal <<
+				    OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
+				foundVal = SUART_TRUE;
+				break;
+			}
+		}
+	} else {
+		return SUART_INVALID_OVERSAMPLING;
+	}
+
+	if (foundVal != SUART_TRUE) {
+		return SUART_INVALID_RX_BAUD;
+	}
+	return status;
+}
+
+/*
+ * mcasp buard rate setting routine
+ */
+s16 suart_asp_baud_set(u32 txBaudValue, u32 rxBaudValue, u32 oversampling,
+					arm_pru_iomap *pru_arm_iomap)
+{
+	s16 status = SUART_SUCCESS;
+
+	status = suart_mcasp_tx_baud_set(txBaudValue, pru_arm_iomap);
+	status = suart_mcasp_rx_baud_set(rxBaudValue, oversampling,
+							pru_arm_iomap);
+
+	return status;
+}
+
+/*
+ * mcasp deactivate the selected serializer
+ */
+s16 suart_asp_serializer_deactivate(u16 u16srNum, arm_pru_iomap *pru_arm_iomap)
+{
+	s16 status = SUART_SUCCESS;
+	OMAPL_McaspRegsOvly mcasp0Regs = (OMAPL_McaspRegsOvly)
+						pru_arm_iomap->mcasp_io_addr;
+	u32 *pu32SrCtlAddr = NULL;
+	if (u16srNum > 15) {
+		status = SUART_INVALID_SR_NUM;
+	} else {
+		pu32SrCtlAddr = (u32 *)&(mcasp0Regs->SRCTL0);
+		pu32SrCtlAddr += u16srNum;
+		*(pu32SrCtlAddr) = 0x000C;
+	}
+	return status;
+}
diff --git a/drivers/serial/omapl_pru/suart_utils.h b/drivers/serial/omapl_pru/suart_utils.h
new file mode 100644
index 0000000..64ec6c0
--- /dev/null
+++ b/drivers/serial/omapl_pru/suart_utils.h
@@ -0,0 +1,62 @@ 
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: jitendra@mistralsolutions.com
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _SUART_UTILS_H_
+#define _SUART_UTILS_H_
+
+#include<linux/types.h>
+
+/* ************ Serializers ***************** */
+#define PRU_SUART_SERIALIZER_0		(0u)
+#define PRU_SUART_SERIALIZER_1		(1u)
+#define PRU_SUART_SERIALIZER_2		(2u)
+#define PRU_SUART_SERIALIZER_3		(3u)
+#define PRU_SUART_SERIALIZER_4		(4u)
+#define PRU_SUART_SERIALIZER_5		(5u)
+#define PRU_SUART_SERIALIZER_6		(6u)
+#define PRU_SUART_SERIALIZER_7		(7u)
+#define PRU_SUART_SERIALIZER_8		(8u)
+#define PRU_SUART_SERIALIZER_9		(9u)
+#define PRU_SUART_SERIALIZER_10		(10u)
+#define PRU_SUART_SERIALIZER_11		(11u)
+#define PRU_SUART_SERIALIZER_12		(12u)
+#define PRU_SUART_SERIALIZER_13		(13u)
+#define PRU_SUART_SERIALIZER_14		(14u)
+#define PRU_SUART_SERIALIZER_15		(15u)
+#define PRU_SUART_SERIALIZER_NONE	(16u)
+
+/* Total number of baud rates supported */
+#define SUART_NUM_OF_BAUDS_SUPPORTED	13
+
+#define MCASP_PDIR_VAL ( \
+			OMAPL_MCASP_PDIR_AFSR_OUTPUT<<OMAPL_MCASP_PDIR_AFSR_SHIFT | \
+			OMAPL_MCASP_PDIR_AHCLKR_OUTPUT<<OMAPL_MCASP_PDIR_AHCLKR_SHIFT | \
+			OMAPL_MCASP_PDIR_ACLKR_OUTPUT<<OMAPL_MCASP_PDIR_ACLKR_SHIFT | \
+			OMAPL_MCASP_PDIR_AFSX_OUTPUT<<OMAPL_MCASP_PDIR_AFSX_SHIFT | \
+			OMAPL_MCASP_PDIR_AHCLKX_OUTPUT<<OMAPL_MCASP_PDIR_AHCLKX_SHIFT | \
+			OMAPL_MCASP_PDIR_ACLKX_OUTPUT<<OMAPL_MCASP_PDIR_ACLKX_SHIFT)
+
+extern void suart_mcasp_config(u32 mcasp_addr, u32 txBaudValue,
+							u32 rxBaudValue, u32 oversampling,
+							arm_pru_iomap *pru_arm_iomap);
+
+extern short suart_asp_baud_set(u32 txBaudValue, u32 rxBaudValue,
+							u32 oversampling, arm_pru_iomap *pru_arm_iomap);
+
+extern short suart_asp_serializer_deactivate(u16 u16srNum,
+						     arm_pru_iomap *pru_arm_iomap);
+
+extern void suart_mcasp_tx_serialzier_set(u32 serializerNum,
+								arm_pru_iomap *pru_arm_iomap);
+#endif
diff --git a/drivers/serial/omapl_pru/ti_omapl_pru_suart.c b/drivers/serial/omapl_pru/ti_omapl_pru_suart.c
new file mode 100644
index 0000000..515fac5
--- /dev/null
+++ b/drivers/serial/omapl_pru/ti_omapl_pru_suart.c
@@ -0,0 +1,1026 @@ 
+/*
+ * TI OMAPL PRU SUART Emulation device driver
+ * Author: subhasish@mistralsolutions.com
+ *
+ * This driver supports TI's PRU SUART Emulation and the
+ * specs for the same is available at <http://www.ti.com>
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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 version 2.
+ *
+ * This program is distributed as is WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/module.h>
+#include <mach/da8xx.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/clk.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+#include "omapl_suart_board.h"
+#include "suart_api.h"
+#include "suart_utils.h"
+#include "suart_err.h"
+
+#define  NR_SUART	         	8
+#define  DRV_NAME               "davinci_pru_suart"
+#define  DRV_DESC               "TI PRU SUART Controller Driver v0.1"
+#define  MAX_SUART_RETRIES       100
+#define  SUART_CNTX_SZ           512
+#define  PLATFORM_SUART_RES_SZ   3
+#define  SUART_FIFO_TIMEOUT_DFLT 5
+#define  SUART_FIFO_TIMEOUT_MIN  4
+#define  SUART_FIFO_TIMEOUT_MAX  500
+
+#ifdef __SUART_DEBUG
+	#define __suart_debug(fmt, args...) \
+				printk(KERN_DEBUG "suart_debug: " fmt, ## args)
+#else
+	#define __suart_debug(fmt, args...)
+#endif
+
+#define  __suart_err(fmt, args...) printk(KERN_ERR "suart_err: " fmt, ## args)
+
+/* Default timeout set to 5ms */
+static int suart_timeout = SUART_FIFO_TIMEOUT_DFLT;
+module_param(suart_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(suart_timeout,
+		 "fifo timeout in milli seconds (min: 4; max: 500)");
+
+struct suart_dma {
+	void *dma_vaddr_buff_tx;
+	void *dma_vaddr_buff_rx;
+	dma_addr_t dma_phys_addr_tx;
+	dma_addr_t dma_phys_addr_rx;
+};
+
+struct omapl_pru_suart {
+	struct uart_port port[NR_SUART];
+	arm_pru_iomap pru_arm_iomap;
+	struct semaphore port_sem[NR_SUART];
+	struct clk *clk_pru;
+	struct clk *clk_mcasp;
+	const struct firmware *fw;
+	suart_struct_handle suart_hdl[NR_SUART];
+	struct suart_dma suart_dma_addr[NR_SUART];
+	u32 clk_freq_pru;
+	u32 clk_freq_mcasp;
+	u32 tx_loadsz;
+};
+
+static u32 suart_get_duplex(struct omapl_pru_suart *soft_uart, u32 uart_no)
+{
+	return soft_uart->suart_hdl[uart_no].uartType;
+}
+
+static inline void __stop_tx(struct omapl_pru_suart *soft_uart, u32 uart_no)
+{
+	u16 txready;
+	u32 i;
+
+	/* Check if any TX in progress */
+	for (i = 0, txready = 1; (i < 10000) && txready; i++) {
+		txready = (pru_softuart_getTxStatus
+			(&soft_uart->suart_hdl[uart_no]) & CHN_TXRX_STATUS_RDY);
+	}
+	/* To stop tx, disable the TX interrupt */
+	suart_intr_clrmask(soft_uart->suart_hdl[uart_no].uartNum, PRU_TX_INTR,
+			   CHN_TXRX_IE_MASK_CMPLT);
+	pru_softuart_clrTxStatus(&soft_uart->suart_hdl[uart_no]);
+}
+
+static void pru_suart_stop_tx(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	__stop_tx(soft_uart, port->line);
+}
+
+static void omapl_pru_tx_chars(struct omapl_pru_suart *soft_uart, u32 uart_no)
+{
+	struct circ_buf *xmit = &soft_uart->port[uart_no].state->xmit;
+	int count = 0;
+
+	if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_TX)) {
+		return;
+	}
+
+	if (down_trylock(&soft_uart->port_sem[uart_no]))
+		return;
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&soft_uart->port[uart_no])) {
+		pru_suart_stop_tx(&soft_uart->port[uart_no]);
+		up(&soft_uart->port_sem[uart_no]);
+		return;
+	}
+
+	for (count = 0; count <= soft_uart->tx_loadsz; count++) {
+		*((char *)soft_uart->suart_dma_addr[uart_no].dma_vaddr_buff_tx +
+		  count) = xmit->buf[xmit->tail];
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		soft_uart->port[uart_no].icount.tx++;
+		if (uart_circ_empty(xmit)) {
+			uart_circ_clear(xmit);
+			break;
+		}
+	}
+
+	if (count == (SUART_FIFO_LEN + 1))
+		count = SUART_FIFO_LEN;
+
+	/* Write the character to the data port */
+	if (SUART_SUCCESS != pru_softuart_write(&soft_uart->suart_hdl[uart_no],
+						(unsigned int *)
+						&soft_uart->suart_dma_addr
+						[uart_no].dma_phys_addr_tx,
+						count)) {
+		__suart_err("failed to tx data\n");
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&soft_uart->port[uart_no]);
+
+#if 0
+	if (uart_circ_empty(xmit))
+		__stop_tx(soft_uart, uart_no);
+#endif
+}
+
+static void omapl_pru_rx_chars(struct omapl_pru_suart *soft_uart, u32 uart_no)
+{
+	struct tty_struct *tty = soft_uart->port[uart_no].state->port.tty;
+	char flags = TTY_NORMAL;
+	u16 rx_status, data_len = SUART_FIFO_LEN;
+	unsigned int data_len_read;
+	unsigned char suart_data[SUART_FIFO_LEN + 1];
+	int i = 0;
+
+	if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_RX))
+		return;
+	/* read the status */
+	rx_status = pru_softuart_getRxStatus(&soft_uart->suart_hdl[uart_no]);
+
+	/* check for errors */
+	if (rx_status & CHN_TXRX_STATUS_ERR) {
+		if (rx_status & CHN_TXRX_STATUS_FE)
+			soft_uart->port[uart_no].icount.frame++;
+		if (rx_status & CHN_TXRX_STATUS_OVRNERR)
+			soft_uart->port[uart_no].icount.overrun++;
+		if (rx_status & CHN_TXRX_STATUS_BI)
+			soft_uart->port[uart_no].icount.brk++;
+		rx_status &= soft_uart->port[uart_no].read_status_mask;
+		if (rx_status & CHN_TXRX_STATUS_FE)
+			flags = TTY_FRAME;
+		if (rx_status & CHN_TXRX_STATUS_OVRNERR)
+			flags = TTY_OVERRUN;
+		if (rx_status & CHN_TXRX_STATUS_BI)
+			flags = TTY_BREAK;
+
+#ifdef SUPPORT_SYSRQ
+		soft_uart->port[uart_no].sysrq = 0;
+#endif
+	} else {
+		pru_softuart_read_data(&soft_uart->suart_hdl[uart_no],
+				       suart_data, data_len + 1,
+				       &data_len_read);
+
+		for (i = 0; i <= data_len_read; i++) {
+			soft_uart->port[uart_no].icount.rx++;
+			/* check for sys rq */
+			if (uart_handle_sysrq_char
+			    (&soft_uart->port[uart_no], suart_data))
+				continue;
+		}
+		/* update the tty data structure */
+		tty_insert_flip_string(tty, suart_data, data_len_read);
+	}
+
+	/* push data into tty */
+	pru_softuart_clrRxStatus(&soft_uart->suart_hdl[uart_no]);
+	spin_unlock(&soft_uart->port[uart_no].lock);
+	tty_flip_buffer_push(tty);
+	spin_lock(&soft_uart->port[uart_no].lock);
+}
+
+static irqreturn_t omapl_pru_suart_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	u16 txrx_flag;
+	u32 ret;
+	unsigned long flags = 0;
+	u16 uartNum = port->line + 1;
+
+	spin_lock_irqsave(&soft_uart->port[port->line].lock, flags);
+	do {
+		ret = pru_softuart_get_isrstatus(uartNum, &txrx_flag);
+		if (PRU_SUART_SUCCESS != ret) {
+			__suart_err("suart%d: failed to get interrupt, ret:"
+				" 0x%X txrx_flag 0x%X\n",
+				port->line, ret, txrx_flag);
+			spin_unlock_irqrestore(&soft_uart->
+					       port[port->line].lock, flags);
+			return IRQ_NONE;
+		}
+		if ((PRU_RX_INTR & txrx_flag) == PRU_RX_INTR) {
+			pru_intr_clr_isrstatus(uartNum, PRU_RX_INTR);
+			if ((soft_uart->port[port->line].ignore_status_mask &
+			     CHN_TXRX_STATUS_RDY) == CHN_TXRX_STATUS_RDY) {
+				pru_softuart_clrRxStatus(&soft_uart->suart_hdl
+							 [port->line]);
+			} else {
+				omapl_pru_rx_chars(soft_uart, port->line);
+			}
+		}
+
+		if ((PRU_TX_INTR & txrx_flag) == PRU_TX_INTR) {
+			pru_intr_clr_isrstatus(uartNum, PRU_TX_INTR);
+			pru_softuart_clrTxStatus(&soft_uart->suart_hdl
+						 [port->line]);
+			up(&soft_uart->port_sem[port->line]);
+			omapl_pru_tx_chars(soft_uart, port->line);
+		}
+	} while (txrx_flag & (PRU_RX_INTR | PRU_TX_INTR));
+
+	spin_unlock_irqrestore(&soft_uart->port[port->line].lock, flags);
+	return IRQ_HANDLED;
+}
+
+static void pru_suart_stop_rx(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	/* disable rx interrupt */
+	suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+}
+
+static void pru_suart_enable_ms(struct uart_port *port)
+{
+	__suart_err("modem control timer not supported\n");
+}
+
+static void pru_suart_start_tx(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	/* unmask the tx interrupts */
+
+	suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	omapl_pru_tx_chars(soft_uart, port->line);
+}
+
+static unsigned int pru_suart_tx_empty(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+
+	return (pru_softuart_getTxStatus(&soft_uart->suart_hdl[port->line])
+		& CHN_TXRX_STATUS_RDY) ? 0 : TIOCSER_TEMT;
+}
+
+static unsigned int pru_suart_get_mctrl(struct uart_port *port)
+{
+	return -ENOTSUPP;
+}
+
+static void pru_suart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	__suart_debug("modem control not supported\n");
+}
+
+static void pru_suart_break_ctl(struct uart_port *port, int break_state)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (break_state == -1)
+		suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+				   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+	else
+		suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+				   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void pru_suart_set_termios(struct uart_port *port,
+				  struct ktermios *termios,
+				  struct ktermios *old)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	unsigned char cval = 0;
+	unsigned long flags = 0;
+	unsigned int baud = 0;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+
+/*
+ * Do not allow unsupported configurations to be set
+ */
+	if (1) {
+		termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR | CSTOPB
+				      | PARENB | PARODD | CMSPAR);
+		termios->c_cflag |= CLOCAL;
+	}
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS6:
+		cval = ePRU_SUART_DATA_BITS6;
+		break;
+	case CS7:
+		cval = ePRU_SUART_DATA_BITS7;
+		break;
+	default:
+	case CS8:
+		cval = ePRU_SUART_DATA_BITS8;
+		break;
+	}
+	/*
+	 * We do not support CS5.
+	 */
+	if ((termios->c_cflag & CSIZE) == CS5) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+	}
+	if (SUART_SUCCESS != pru_softuart_setdatabits
+			(&soft_uart->suart_hdl[port->line], cval, cval))
+		__suart_err("failed to set data bits to: %d\n", cval);
+
+/*
+ * Ask the core to calculate the divisor for us.
+ */
+	baud = uart_get_baud_rate(port, termios, old,
+				  port->uartclk / 16 / 0xffff,
+				  port->uartclk / 16);
+
+/*
+ * Ok, we're now changing the port state.  Do it with
+ * interrupts disabled.
+ */
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Set the baud */
+	if (SUART_SUCCESS !=
+	    pru_softuart_setbaud(&soft_uart->suart_hdl[port->line],
+				 SUART_DEFAULT_BAUD / baud,
+				 SUART_DEFAULT_BAUD / baud))
+		__suart_err("failed to set baud to: %d\n", baud);
+
+/*
+ * update port->read_config_mask and port->ignore_config_mask
+ * to indicate the events we are interested in receiving
+ */
+	suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_RX_INTR, SUART_GBL_INTR_ERR_MASK);
+	port->read_status_mask = 0;
+	if (termios->c_iflag & INPCK) {	/* Input parity check not supported,
+									just enabled FE */
+		port->read_status_mask |= CHN_TXRX_STATUS_FE;
+		suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+				   PRU_RX_INTR, CHN_TXRX_IE_MASK_FE);
+	}
+	if (termios->c_iflag & (BRKINT | PARMRK)) {
+		port->read_status_mask |= CHN_TXRX_STATUS_BI;
+		suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+				   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+	}
+/*
+ * Characteres to ignore
+ */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= CHN_TXRX_STATUS_BI;
+		/*
+		 * If we're ignoring break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR) {
+			port->ignore_status_mask |=
+			    (CHN_TXRX_STATUS_OVRNERR | CHN_TXRX_STATUS_FE);
+			/*
+			 * Overrun in case of RX
+			 * Underrun in case of TX
+			 */
+			suart_intr_clrmask(soft_uart->
+					   suart_hdl[port->line].uartNum,
+					   PRU_RX_INTR, CHN_TXRX_IE_MASK_FE);
+		}
+		suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+				   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+	}
+/*
+ * ignore all characters if CREAD is not set
+ */
+	if ((termios->c_cflag & CREAD) == 0) {
+		port->ignore_status_mask |= CHN_TXRX_STATUS_RDY;
+		pru_suart_stop_rx(port);
+	}
+
+	spin_unlock_irqrestore(&port->lock, flags);
+	/* Don't rewrite B0 */
+	if (tty_termios_baud_rate(termios))
+		tty_termios_encode_baud_rate(termios, baud, baud);
+}
+
+/*
+ *	Grab any interrupt resources and initialise any low level driver
+ *	state.  Enable the port for reception.  It should not activate
+ *	RTS nor DTR; this will be done via a separate call to set_mctrl.
+ *
+ *	This method will only be called when the port is initially opened.
+ *
+ *	Locking: port_sem taken.
+ *	Interrupts: globally disabled.
+ */
+static int pru_suart_startup(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	int retval;
+
+	/*
+	 * Disable interrupts from this port
+	 */
+	suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+
+	retval = request_irq(port->irq, omapl_pru_suart_interrupt,
+			     port->irqflags, "suart_irq", port);
+	if (retval) {
+		free_irq(port->irq, port);	/* should we free this if err */
+		goto out;
+	}
+	/*
+	 * enable interrupts from this port
+	 */
+	suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_RX_INTR, SUART_GBL_INTR_ERR_MASK);
+
+	suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+
+	suart_intr_setmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+
+	if ((suart_get_duplex(soft_uart, port->line) & ePRU_SUART_HALF_TX)
+	    == ePRU_SUART_HALF_TX) {
+		suart_pru_to_host_intr_enable(soft_uart->
+					      suart_hdl[port->line].uartNum,
+					      PRU_TX_INTR, true);
+	}
+	/* Seed RX if port is half-rx or full-duplex */
+	if ((suart_get_duplex(soft_uart, port->line) & ePRU_SUART_HALF_RX)
+	    == ePRU_SUART_HALF_RX) {
+		suart_pru_to_host_intr_enable(soft_uart->
+					      suart_hdl[port->line].uartNum,
+					      PRU_RX_INTR, true);
+		pru_softuart_read(&soft_uart->suart_hdl[port->line],
+				  (unsigned int *)
+				  &soft_uart->suart_dma_addr[port->line].
+				  dma_phys_addr_rx, SUART_FIFO_LEN);
+	}
+
+out:
+	return retval;
+}
+
+/*
+ *	Disable the port, disable any break condition that may be in
+ *	effect, and free any interrupt resources.  It should not disable
+ *	RTS nor DTR; this will have already been done via a separate
+ *	call to set_mctrl.
+ *
+ *	Drivers must not access port->info once this call has completed.
+ *
+ *	This method will only be called when there are no more users of
+ *	this port.
+ *
+ *	Locking: port_sem taken.
+ *	Interrupts: caller dependent.
+ */
+
+static void pru_suart_shutdown(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+
+	/*
+	 * Disable interrupts from this port
+	 */
+	/* Disable BI and FE intr */
+	suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	suart_intr_clrmask(soft_uart->suart_hdl[port->line].uartNum,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+
+	/* free interrupts */
+	free_irq(port->irq, port);
+}
+
+/*
+ *	Return a pointer to a string constant describing the specified
+ *  port, or return NULL, in which case the string 'unknown' is
+ *  substituted.
+ *
+ *  Locking: none.
+ *	Interrupts: caller dependent.
+ */
+
+static const char *pru_suart_type(struct uart_port *port)
+{
+	return "suart_tty";
+}
+
+/*
+ *	Release any memory and IO region resources currently in use by
+ *	the port.
+ *
+ *	Locking: none.
+ *	Interrupts: caller dependent.
+ */
+
+static void pru_suart_release_port(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct platform_device *pdev = to_platform_device(port->dev);
+
+	if (0 != pru_softuart_close(&soft_uart->suart_hdl[port->line])) {
+		dev_err(&pdev->dev, "failed to close suart\n");
+	}
+	return;
+}
+
+/*
+ *	Request any memory and IO region resources required by the port.
+ *	If any fail, no resources should be registered when this function
+ *	returns, and it should return -EBUSY on failure.
+ *
+ *	Locking: none.
+ *	Interrupts: caller dependent.
+ *
+ *	We need to d/l the f/w in probe and since this api
+ *	is called per uart, the request_mem_region should
+ *	be called in probe itself.
+ *	We call the pru_open routein only here. not sure if aesthetically correct.
+ */
+static int pru_suart_request_port(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct platform_device *pdev = to_platform_device(port->dev);
+	suart_config pru_suart_config;
+	u32 timeout = 0;
+	u32 err = 0;
+	if (soft_uart == NULL) {
+		__suart_err("soft_uart ptr failed\n");
+		return -ENODEV;
+	}
+	err = pru_softuart_open(&soft_uart->suart_hdl[port->line]);
+	if (PRU_SUART_SUCCESS != err) {
+		dev_err(&pdev->dev, "failed to open suart: %d\n", err);
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/* set fifo timeout */
+	if (SUART_FIFO_TIMEOUT_MIN > suart_timeout) {
+		__suart_err("fifo timeout less than %d ms not supported\n",
+			    SUART_FIFO_TIMEOUT_MIN);
+		suart_timeout = SUART_FIFO_TIMEOUT_MIN;
+	} else if (SUART_FIFO_TIMEOUT_MAX < suart_timeout) {
+		__suart_err("fifo timeout more than %d ms not supported\n",
+			    SUART_FIFO_TIMEOUT_MAX);
+		suart_timeout = SUART_FIFO_TIMEOUT_MAX;
+	}
+
+	/* This is only for x8 */
+	timeout = (SUART_DEFAULT_BAUD * suart_timeout) / 1000;
+	pru_set_fifo_timeout(timeout);
+
+	if (soft_uart->suart_hdl[port->line].uartNum == PRU_SUART_UART1) {
+		pru_suart_config.TXSerializer = PRU_SUART1_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART1_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART2) {
+		pru_suart_config.TXSerializer = PRU_SUART2_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART2_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART3) {
+		pru_suart_config.TXSerializer = PRU_SUART3_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART3_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART4) {
+		pru_suart_config.TXSerializer = PRU_SUART4_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART4_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART5) {
+		pru_suart_config.TXSerializer = PRU_SUART5_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART5_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART6) {
+		pru_suart_config.TXSerializer = PRU_SUART6_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART6_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART7) {
+		pru_suart_config.TXSerializer = PRU_SUART7_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART7_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uartNum ==
+							PRU_SUART_UART8) {
+		pru_suart_config.TXSerializer = PRU_SUART8_CONFIG_TX_SER;
+		pru_suart_config.RXSerializer = PRU_SUART8_CONFIG_RX_SER;
+	} else {
+		return -ENOTSUPP;
+	}
+
+	/* Some defaults to startup. reconfigured by terimos later */
+	pru_suart_config.txClkDivisor = 1;
+	pru_suart_config.rxClkDivisor = 1;
+	pru_suart_config.txBitsPerChar = ePRU_SUART_DATA_BITS8;
+	pru_suart_config.rxBitsPerChar = ePRU_SUART_DATA_BITS8;
+	pru_suart_config.Oversampling = SUART_DEFAULT_OVRSMPL;
+
+	if (PRU_SUART_SUCCESS !=
+	    pru_softuart_setconfig(&soft_uart->suart_hdl[port->line],
+				   &pru_suart_config)) {
+		dev_err(&pdev->dev,
+			"pru_softuart_setconfig: failed to set config: %X\n",
+			err);
+	}
+exit:
+	return err;
+}
+
+/*
+ * Perform any autoconfiguration steps required for the port.  `flag`
+ * contains a bit mask of the required configuration.  UART_CONFIG_TYPE
+ * indicates that the port requires detection and identification.
+ * port->type should be set to the type found, or PORT_UNKNOWN if
+ * no port was detected.
+ *
+ * UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal,
+ * which should be probed using standard kernel autoprobing techniques.
+ * This is not necessary on platforms where ports have interrupts
+ * internally hard wired (eg, system on a chip implementations).
+ *
+ * Locking: none.
+ * Interrupts: caller dependent.
+ */
+
+static void pru_suart_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE && pru_suart_request_port(port) == 0)
+		port->type = PORT_OMAPL_PRU_SUART;
+}
+
+/*
+ * Verify the new serial port information contained within serinfo is
+ * suitable for this port type.
+ *
+ * Locking: none.
+ * Interrupts: caller dependent.
+ */
+static int pru_suart_verify_port(struct uart_port *port,
+				 struct serial_struct *ser)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_OMAPL_PRU_SUART)
+		ret = -EINVAL;
+	if (soft_uart->port[port->line].irq != ser->irq)
+		ret = -EINVAL;
+	if (ser->io_type != UPIO_MEM)
+		ret = -EINVAL;
+	if (soft_uart->port[port->line].uartclk / 16 != ser->baud_base)
+		ret = -EINVAL;
+	if ((void *)soft_uart->port[port->line].mapbase != ser->iomem_base)
+		ret = -EINVAL;
+	if (soft_uart->port[port->line].iobase != ser->port)
+		ret = -EINVAL;
+	return ret;
+}
+
+static struct uart_ops pru_suart_ops = {
+	.tx_empty = pru_suart_tx_empty,
+	.set_mctrl = pru_suart_set_mctrl,
+	.get_mctrl = pru_suart_get_mctrl,
+	.stop_tx = pru_suart_stop_tx,
+	.start_tx = pru_suart_start_tx,
+	.stop_rx = pru_suart_stop_rx,
+	.enable_ms = pru_suart_enable_ms,
+	.break_ctl = pru_suart_break_ctl,
+	.startup = pru_suart_startup,
+	.shutdown = pru_suart_shutdown,
+	.set_termios = pru_suart_set_termios,
+	.type = pru_suart_type,
+	.release_port = pru_suart_release_port,
+	.request_port = pru_suart_request_port,
+	.config_port = pru_suart_config_port,
+	.verify_port = pru_suart_verify_port,
+};
+
+static struct uart_driver pru_suart_reg = {
+	.owner = THIS_MODULE,
+	.driver_name = DRV_NAME,
+	.dev_name = "ttySU",
+	.major = 0,
+	.minor = 16,
+	.nr = NR_SUART,
+};
+
+static int __devinit omapl_pru_suart_probe(struct platform_device *pdev)
+{
+	struct omapl_pru_suart *soft_uart;
+	struct resource *res_mem[PLATFORM_SUART_RES_SZ];
+	int err, i;
+	unsigned char *fw_data = NULL;
+
+	soft_uart = kzalloc(sizeof(struct omapl_pru_suart), GFP_KERNEL);
+	if (!soft_uart)
+		return -ENOMEM;
+
+	for (i = 0; i < PLATFORM_SUART_RES_SZ; i++) {
+		res_mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res_mem[i]) {
+			dev_err(&pdev->dev,
+				"unable to get pru memory resources!\n");
+			err = -ENODEV;
+			goto probe_exit;
+		}
+	}
+
+	if (!request_mem_region(res_mem[0]->start, resource_size(res_mem[0]),
+				dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "pru memory region already claimed!\n");
+		err = -EBUSY;
+		goto probe_exit;
+	}
+	if (!request_mem_region(res_mem[1]->start, resource_size(res_mem[1]),
+				dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "mcasp memory region already claimed!\n");
+		err = -EBUSY;
+		goto probe_exit_1;
+	}
+
+	soft_uart->pru_arm_iomap.pru_io_addr = ioremap(res_mem[0]->start,
+						       resource_size(res_mem[0]));
+	if (!soft_uart->pru_arm_iomap.pru_io_addr) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		err = -ENOMEM;
+		goto probe_exit_free_region;
+	}
+	soft_uart->pru_arm_iomap.mcasp_io_addr = ioremap(res_mem[1]->start,
+							 resource_size(res_mem[1]));
+	if (!soft_uart->pru_arm_iomap.mcasp_io_addr) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		err = -ENOMEM;
+		goto probe_exit_iounmap_1;
+	}
+
+	soft_uart->clk_pru = clk_get(&pdev->dev, "pruss");
+	if (IS_ERR(soft_uart->clk_pru)) {
+		dev_err(&pdev->dev, "no clock available: pruss\n");
+		err = -ENODEV;
+		soft_uart->clk_pru = NULL;
+		goto probe_exit_iounmap_2;
+	}
+	soft_uart->clk_freq_pru = clk_get_rate(soft_uart->clk_pru);
+
+	/* mcasp_clk is tied with mcasp driver, hence using mcasp_pru */
+	soft_uart->clk_mcasp = clk_get(NULL, "mcasp_pru");
+	if (IS_ERR(soft_uart->clk_mcasp)) {
+		dev_err(&pdev->dev, "no clock available: mcasp\n");
+		err = -ENODEV;
+		soft_uart->clk_mcasp = NULL;
+		goto probe_exit_clk_pru;
+	}
+	soft_uart->clk_freq_mcasp = clk_get_rate(soft_uart->clk_mcasp);
+	clk_enable(soft_uart->clk_mcasp);
+	clk_enable(soft_uart->clk_pru);
+	err = request_firmware(&soft_uart->fw, "PRU_SUART_Emulation.bin",
+			       &pdev->dev);
+	if (err) {
+		dev_err(&pdev->dev, "can't load firmware\n");
+		err = -ENODEV;
+		goto probe_exit_clk;
+	}
+	dev_info(&pdev->dev, "fw size %td. downloading...\n",
+		 soft_uart->fw->size);
+
+	/* download firmware into pru  & init */
+	fw_data = kmalloc(soft_uart->fw->size, GFP_KERNEL);
+	memcpy((void *)fw_data, (const void *)soft_uart->fw->data,
+	       soft_uart->fw->size);
+
+	soft_uart->pru_arm_iomap.pFifoBufferPhysBase = (void *)res_mem[2]->start;
+	soft_uart->pru_arm_iomap.pFifoBufferVirtBase =
+		(void *)ioremap(res_mem[2]->start, resource_size(res_mem[2]));
+	if (!soft_uart->pru_arm_iomap.pFifoBufferVirtBase) {
+		__suart_err("Failed to allocate shared ram.\n");
+		err = -EFAULT;
+		goto probe_release_fw;
+	}
+
+	soft_uart->pru_arm_iomap.pru_clk_freq =
+	    (soft_uart->clk_freq_pru / 1000000);
+
+	err = pru_softuart_init(SUART_DEFAULT_BAUD, SUART_DEFAULT_BAUD,
+				SUART_DEFAULT_OVRSMPL, fw_data,
+				soft_uart->fw->size, &soft_uart->pru_arm_iomap);
+	if (err) {
+		dev_err(&pdev->dev, "pru init error\n");
+		err = -ENODEV;
+		kfree((const void *)fw_data);
+		goto probe_exit_iounmap_3;
+	}
+	kfree((const void *)fw_data);
+
+	for (i = 0; i < NR_SUART; i++) {
+		soft_uart->port[i].ops = &pru_suart_ops;
+		soft_uart->port[i].iotype = UPIO_MEM;	/* user conf parallel io */
+		soft_uart->port[i].flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+		soft_uart->port[i].mapbase = res_mem[1]->start;
+		soft_uart->port[i].membase =
+					(unsigned char *)&soft_uart->pru_arm_iomap;
+		soft_uart->port[i].type = PORT_OMAPL_PRU_SUART;
+		soft_uart->port[i].irq = platform_get_irq(pdev, i);
+		soft_uart->port[i].dev = &pdev->dev;
+		soft_uart->port[i].irqflags = IRQF_SHARED;
+		soft_uart->port[i].uartclk = soft_uart->clk_freq_mcasp;	/* 24MHz */
+		soft_uart->port[i].fifosize = SUART_FIFO_LEN;
+		soft_uart->tx_loadsz = SUART_FIFO_LEN;
+		soft_uart->port[i].custom_divisor = 1;
+		soft_uart->port[i].line = i;	/* need the id/line from pdev */
+		soft_uart->suart_hdl[i].uartNum = i + 1;
+		spin_lock_init(&soft_uart->port[i].lock);
+		soft_uart->port[i].serial_in = NULL;
+
+		soft_uart->suart_dma_addr[i].dma_vaddr_buff_tx =
+			soft_uart->pru_arm_iomap.pFifoBufferVirtBase +
+			(2 * SUART_CNTX_SZ * i);
+
+		soft_uart->suart_dma_addr[i].dma_vaddr_buff_rx =
+			soft_uart->pru_arm_iomap.pFifoBufferVirtBase +
+			((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
+
+		soft_uart->suart_dma_addr[i].dma_phys_addr_tx =
+			(dma_addr_t)soft_uart->pru_arm_iomap.pFifoBufferPhysBase +
+			(2 * SUART_CNTX_SZ * i);
+
+		soft_uart->suart_dma_addr[i].dma_phys_addr_rx =
+			(dma_addr_t)soft_uart->pru_arm_iomap.pFifoBufferPhysBase +
+			((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
+
+		soft_uart->port[i].serial_out = NULL;
+		uart_add_one_port(&pru_suart_reg, &soft_uart->port[i]);
+		sema_init(&soft_uart->port_sem[i], 1);
+	}
+	platform_set_drvdata(pdev, &soft_uart->port[0]);
+
+	dev_info(&pdev->dev,
+		 "%s device registered"
+		 "(pru_clk=%d, asp_clk=%d)\n",
+		 DRV_NAME, soft_uart->clk_freq_pru, soft_uart->clk_freq_mcasp);
+
+	return 0;
+
+probe_exit_iounmap_3:
+	iounmap(soft_uart->pru_arm_iomap.pFifoBufferVirtBase);
+probe_release_fw:
+	release_firmware(soft_uart->fw);
+probe_exit_clk:
+	clk_put(soft_uart->clk_mcasp);
+probe_exit_clk_pru:
+	clk_put(soft_uart->clk_pru);
+probe_exit_iounmap_2:
+	iounmap(soft_uart->pru_arm_iomap.mcasp_io_addr);
+probe_exit_iounmap_1:
+	iounmap(soft_uart->pru_arm_iomap.pru_io_addr);
+probe_exit_free_region:
+	release_mem_region(res_mem[1]->start, resource_size(res_mem[1]));
+probe_exit_1:
+	release_mem_region(res_mem[0]->start, resource_size(res_mem[0]));
+probe_exit:
+	kfree(soft_uart);
+	return err;
+}
+
+static int __devexit omapl_pru_suart_remove(struct platform_device *pdev)
+{
+	struct omapl_pru_suart *soft_uart = platform_get_drvdata(pdev);
+	struct resource *res_mem[PLATFORM_SUART_RES_SZ];
+	int i;
+	u32 err = 0;
+
+	platform_set_drvdata(pdev, NULL);
+
+	for (i = 0; i < PLATFORM_SUART_RES_SZ; i++) {
+		res_mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res_mem[i]) {
+			dev_err(&pdev->dev,
+				"unable to get pru memory resources!\n");
+			err = -ENODEV;
+		}
+	}
+
+	if (soft_uart) {
+		for (i = 0; i < NR_SUART; i++) {
+			uart_remove_one_port(&pru_suart_reg,
+					     &soft_uart->port[i]);
+		}
+	}
+	release_firmware(soft_uart->fw);
+	clk_put(soft_uart->clk_mcasp);
+	clk_put(soft_uart->clk_pru);
+	clk_disable(soft_uart->clk_mcasp);
+	clk_disable(soft_uart->clk_pru);
+	iounmap(soft_uart->pru_arm_iomap.mcasp_io_addr);
+	iounmap(soft_uart->pru_arm_iomap.pru_io_addr);
+	iounmap(soft_uart->pru_arm_iomap.pFifoBufferVirtBase);
+	release_mem_region(res_mem[0]->start, resource_size(res_mem[0]));
+	release_mem_region(res_mem[1]->start, resource_size(res_mem[1]));
+	kfree(soft_uart);
+	return err;
+}
+
+#define omapl_pru_suart_suspend NULL
+#define omapl_pru__suart_resume NULL
+
+static struct platform_driver serial_omapl_pru_driver = {
+	.probe = omapl_pru_suart_probe,
+	.remove = __devexit_p(omapl_pru_suart_remove),
+	.suspend = omapl_pru_suart_suspend,
+	.resume = omapl_pru__suart_resume,
+	.driver = {
+		   .name = DRV_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static int __init pru_suart_init(void)
+{
+	int ret;
+
+	pru_suart_reg.nr = NR_SUART;
+	ret = uart_register_driver(&pru_suart_reg);
+	if (ret)
+		return ret;
+	ret = platform_driver_register(&serial_omapl_pru_driver);
+	if (ret)
+		goto out;
+
+	__suart_debug("SUART serial driver loaded\n");
+	return ret;
+out:
+	uart_unregister_driver(&pru_suart_reg);
+	return ret;
+}
+
+module_init(pru_suart_init);
+
+static void __exit omapl_pru_suart_exit(void)
+{
+	platform_driver_unregister(&serial_omapl_pru_driver);
+	uart_unregister_driver(&pru_suart_reg);
+	__suart_debug("SUART serial driver unloaded\n");
+}
+
+module_exit(omapl_pru_suart_exit);
+
+/* Module information */
+MODULE_AUTHOR("Subhasish Ghosh <subhasish@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRV_DESC);