linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/7] mfd: add pruss mfd driver.
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-09 11:56   ` Marc Kleine-Budde
                     ` (2 more replies)
  2011-03-08 13:57 ` [PATCH v3 2/7] da850: pruss platform specific additions Subhasish Ghosh
                   ` (5 subsequent siblings)
  6 siblings, 3 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Samuel Ortiz, open list

This patch adds the pruss MFD driver and associated include files.
For details regarding the PRUSS please refer the folowing link:
http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem

The rational behind the MFD driver being the fact that multiple devices can
be implemented on the cores independently. This is determined by the nature
of the program which is loaded into the PRU's instruction memory.
A device may be de-initialized and another loaded or two different devices
can be run simultaneously on the two cores.
It's also possible, as in our case, to implement a single device on both
the PRU's resulting in improved load sharing.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 drivers/mfd/Kconfig                     |   10 +
 drivers/mfd/Makefile                    |    1 +
 drivers/mfd/da8xx_pru.c                 |  560 +++++++++++++++++++++++++++++++
 include/linux/mfd/da8xx/da8xx_pru.h     |  135 ++++++++
 include/linux/mfd/da8xx/da8xx_prucore.h |  129 +++++++
 5 files changed, 835 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/da8xx_pru.c
 create mode 100644 include/linux/mfd/da8xx/da8xx_pru.h
 create mode 100644 include/linux/mfd/da8xx/da8xx_prucore.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fd01836..6c437df 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -81,6 +81,16 @@ config MFD_DM355EVM_MSP
 	  boards.  MSP430 firmware manages resets and power sequencing,
 	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
 
+config MFD_DA8XX_PRUSS
+	tristate "Texas Instruments DA8XX PRUSS support"
+	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
+	select MFD_CORE
+	help
+	  This driver provides support api's for the programmable
+	  realtime unit (PRU) present on TI's da8xx processors. It
+	  provides basic read, write, config, enable, disable
+	  routines to facilitate devices emulated on it.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a54e2c7..670d6b0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
 obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
 
 obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
+obj-$(CONFIG_MFD_DA8XX_PRUSS)	+= da8xx_pru.o
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
 
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
diff --git a/drivers/mfd/da8xx_pru.c b/drivers/mfd/da8xx_pru.c
new file mode 100644
index 0000000..0fd9bb2
--- /dev/null
+++ b/drivers/mfd/da8xx_pru.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mfd/da8xx/da8xx_prucore.h>
+#include <linux/mfd/da8xx/da8xx_pru.h>
+#include <linux/mfd/core.h>
+#include <linux/io.h>
+#include <mach/da8xx.h>
+
+struct da8xx_pruss {
+	struct device *dev;
+	spinlock_t lock;
+	struct resource *res;
+	struct clk *clk;
+	u32 clk_freq;
+	void __iomem *ioaddr;
+};
+
+u32 pruss_get_clk_freq(struct device *dev)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+
+	return pruss->clk_freq;
+}
+EXPORT_SYMBOL(pruss_get_clk_freq);
+
+s32 pruss_disable(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	struct da8xx_prusscore_regs *h_pruss;
+	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
+	u32 temp_reg;
+	u32 delay_cnt;
+
+	if ((pruss_num != DA8XX_PRUCORE_0) && (pruss_num != DA8XX_PRUCORE_1))
+		return -EINVAL;
+
+	spin_lock(&pruss->lock);
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* pruss deinit */
+		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT0 & 0xFFFF));
+		/* Disable PRU0  */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_0];
+
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
+		__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
+
+			temp_reg = __raw_readl(&h_pruss->CONTROL);
+			temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
+			__raw_writel(temp_reg, &h_pruss->CONTROL);
+		}
+
+		/* Reset PRU0 */
+		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
+			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+					&h_pruss->CONTROL);
+
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* pruss deinit */
+		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT1 & 0xFFFF));
+		/* Disable PRU1 */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_1];
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
+		__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
+
+			temp_reg = __raw_readl(&h_pruss->CONTROL);
+			temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
+			__raw_writel(temp_reg, &h_pruss->CONTROL);
+		}
+
+		/* Reset PRU1 */
+		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
+			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+							&h_pruss->CONTROL);
+	}
+	spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_disable);
+
+s32 pruss_enable(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	struct da8xx_prusscore_regs *h_pruss;
+	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
+
+	if ((pruss_num != DA8XX_PRUCORE_0) && (pruss_num != DA8XX_PRUCORE_1))
+		return -EINVAL;
+
+	spin_lock(&pruss->lock);
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* Reset PRU0 */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_0];
+		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+			&h_pruss->CONTROL);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* Reset PRU1  */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_1];
+		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+			&h_pruss->CONTROL);
+	}
+	spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_enable);
+
+/* Load the specified PRU with code */
+s32 pruss_load(struct device *dev, u8 pruss_num,
+			u32 *pruss_code, u32 code_size_in_words)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
+	u32 *pruss_iram;
+	u32 i;
+
+	if (pruss_num == DA8XX_PRUCORE_0)
+		pruss_iram = (u32 *)&pruss_mmap->iram0;
+	else if (pruss_num == DA8XX_PRUCORE_1)
+		pruss_iram = (u32 *)&pruss_mmap->iram1;
+	else
+		return -EINVAL;
+
+	pruss_enable(dev, pruss_num);
+
+	spin_lock(&pruss->lock);
+	/* Copy dMAX code to its instruction RAM  */
+	for (i = 0; i < code_size_in_words; i++)
+		__raw_writel(pruss_code[i], (pruss_iram + i));
+
+	spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_load);
+
+s32 pruss_run(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	struct da8xx_prusscore_regs *h_pruss;
+	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
+	u32 temp_reg;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* DA8XX_PRUCORE_0_REGS; */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_0];
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* DA8XX_PRUCORE_1_REGS; */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_1];
+	} else
+		return -EINVAL;
+
+	/* Enable dMAX, let it execute the code we just copied */
+	spin_lock(&pruss->lock);
+	temp_reg = __raw_readl(&h_pruss->CONTROL);
+	temp_reg = (temp_reg &
+			~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
+			((DA8XX_PRUCORE_CONTROL_COUNTENABLE_ENABLE <<
+			DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
+			DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
+	__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+	temp_reg = __raw_readl(&h_pruss->CONTROL);
+	temp_reg = (temp_reg &
+			~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
+			((DA8XX_PRUCORE_CONTROL_ENABLE_ENABLE <<
+			DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
+			DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
+	__raw_writel(temp_reg, &h_pruss->CONTROL);
+	 spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_run);
+
+s32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	struct da8xx_prusscore_regs *h_pruss;
+	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
+	u32 temp_reg;
+	u32 cnt = timeout;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* DA8XX_PRUCORE_0_REGS; */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_0];
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* DA8XX_PRUCORE_1_REGS; */
+		h_pruss = (struct da8xx_prusscore_regs *)
+			&pruss_mmap->core[DA8XX_PRUCORE_1];
+	} else
+		return -EINVAL;
+
+	while (cnt--) {
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		if (((temp_reg & DA8XX_PRUCORE_CONTROL_RUNSTATE_MASK) >>
+				DA8XX_PRUCORE_CONTROL_RUNSTATE_SHIFT) ==
+					DA8XX_PRUCORE_CONTROL_RUNSTATE_HALT)
+			break;
+	}
+	if (cnt == 0)
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_wait_for_halt);
+
+s32 pruss_writeb(struct device *dev, u32 offset,
+		u8 *pdatatowrite, u16 bytestowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u8 *paddresstowrite;
+	u16 loop;
+	offset = (u32)pruss->ioaddr + offset;
+	paddresstowrite = (u8 *) (offset);
+
+	for (loop = 0; loop < bytestowrite; loop++)
+		__raw_writeb(*pdatatowrite++, paddresstowrite++);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writeb);
+
+s32 pruss_rmwb(struct device *dev, u32 offset, u8 mask, u8 val)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddress;
+	u32 preg_data;
+
+	paddress = (u32 *)((u32)pruss->ioaddr + offset);
+
+	spin_lock(&pruss->lock);
+	preg_data = __raw_readb(paddress);
+	preg_data &= ~mask;
+	preg_data |= val;
+	__raw_writeb(preg_data, paddress);
+	spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_rmwb);
+
+s32 pruss_readb(struct device *dev, u32 offset,
+		u8 *pdatatoread, u16 bytestoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u8 *paddresstoread;
+	u16 loop;
+	offset = (u32)pruss->ioaddr + offset;
+	paddresstoread = (u8 *) (offset);
+
+	for (loop = 0; loop < bytestoread; loop++)
+		*pdatatoread++ = __raw_readb(paddresstoread++);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readb);
+
+s32 pruss_writel(struct device *dev, u32 offset,
+		u32 *pdatatowrite, s16 wordstowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddresstowrite;
+	s16 loop;
+
+	offset = (u32)pruss->ioaddr + offset;
+	paddresstowrite = (u32 *)(offset);
+
+	for (loop = 0; loop < wordstowrite; loop++)
+		__raw_writel(*pdatatowrite++, paddresstowrite++);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writel);
+
+s32 pruss_rmwl(struct device *dev, u32 offset, u32 mask, u32 val)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddress;
+	u32 preg_data;
+
+	paddress = (u32 *)((u32)pruss->ioaddr + offset);
+
+	spin_lock(&pruss->lock);
+	preg_data = __raw_readl(paddress);
+	preg_data &= ~mask;
+	preg_data |= val;
+	__raw_writel(preg_data, paddress);
+	spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_rmwl);
+
+s32 pruss_readl(struct device *dev, u32 offset,
+		u32 *pdatatoread, s16 wordstoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddresstoread;
+	s16 loop;
+
+	offset = (u32)pruss->ioaddr + offset;
+	paddresstoread = (u32 *)(offset);
+
+	for (loop = 0; loop < wordstoread; loop++)
+		*pdatatoread++ = __raw_readl(paddresstoread++);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readl);
+
+s32 pruss_writew(struct device *dev, u32 offset,
+		u16 *pdatatowrite, s16 wordstowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddresstowrite;
+	s16 loop;
+
+	offset = (u32)pruss->ioaddr + offset;
+	paddresstowrite = (u32 *)(offset);
+
+	for (loop = 0; loop < wordstowrite; loop++)
+		__raw_writew(*(pdatatowrite++), (paddresstowrite++));
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writew);
+
+s32 pruss_rmww(struct device *dev, u32 offset, u16 mask, u16 val)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddress;
+	u32 preg_data;
+
+	paddress = (u32 *)((u32)pruss->ioaddr + offset);
+
+	spin_lock(&pruss->lock);
+	preg_data = __raw_readw(paddress);
+	preg_data &= ~mask;
+	preg_data |= val;
+	__raw_writew(preg_data, paddress);
+	spin_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_rmww);
+
+s32 pruss_readw(struct device *dev, u32 offset,
+			u16 *pdatatoread, s16 wordstoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddresstoread;
+	s16 loop;
+
+	offset = (u32)pruss->ioaddr + offset;
+	paddresstoread = (u32 *)(offset);
+
+	for (loop = 0; loop < wordstoread; loop++)
+		*pdatatoread++ = __raw_readw(paddresstoread++);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readw);
+
+s32 pruss_idx_writel(struct device *dev, u32 offset, u32 value)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *paddresstowrite;
+
+	paddresstowrite = (u32 *)(pruss->ioaddr + offset);
+	__raw_writel(value, paddresstowrite);
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_idx_writel);
+
+static int pruss_mfd_add_devices(struct platform_device *pdev)
+{
+	struct da8xx_pruss_devices *dev_data = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct mfd_cell cell;
+	u32 err, count;
+
+	for (count = 0; dev_data[count].dev_name != NULL; count++) {
+		memset(&cell, 0, sizeof(struct mfd_cell));
+		cell.id			= count;
+		cell.name		= dev_data[count].dev_name;
+		cell.platform_data	= dev_data[count].pdata;
+		cell.data_size		= dev_data[count].pdata_size;
+		cell.resources		= dev_data[count].resources;
+		cell.num_resources	= dev_data[count].num_resources;
+
+		err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
+		if (err) {
+			dev_err(dev, "cannot add mfd cells\n");
+			return err;
+		}
+		dev_info(dev, "mfd: added %s device\n",
+				dev_data[count].dev_name);
+	}
+
+	return err;
+}
+
+static int __devinit da8xx_pruss_probe(struct platform_device *pdev)
+{
+	struct da8xx_pruss *pruss_dev = NULL;
+	u32 err;
+
+	pruss_dev = kzalloc(sizeof(struct da8xx_pruss), GFP_KERNEL);
+	if (!pruss_dev)
+		return -ENOMEM;
+
+	pruss_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pruss_dev->res) {
+		dev_err(&pdev->dev,
+		"unable to get pruss memory resources!\n");
+		err = -ENODEV;
+		goto probe_exit_kfree;
+	}
+
+	if (!request_mem_region(pruss_dev->res->start,
+		resource_size(pruss_dev->res), dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "pruss memory region already claimed!\n");
+		err = -EBUSY;
+		goto probe_exit_kfree;
+	}
+
+	pruss_dev->ioaddr = ioremap(pruss_dev->res->start,
+	resource_size(pruss_dev->res));
+	if (!pruss_dev->ioaddr) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		err = -ENOMEM;
+		goto probe_exit_free_region;
+	}
+
+	pruss_dev->clk = clk_get(NULL, "pruss");
+	if (IS_ERR(pruss_dev->clk)) {
+		dev_err(&pdev->dev, "no clock available: pruss\n");
+		err = -ENODEV;
+		pruss_dev->clk = NULL;
+		goto probe_exit_iounmap;
+	}
+	spin_lock_init(&pruss_dev->lock);
+
+	clk_enable(pruss_dev->clk);
+	pruss_dev->clk_freq = clk_get_rate(pruss_dev->clk);
+
+	err = pruss_mfd_add_devices(pdev);
+	if (err)
+		goto probe_exit_clock;
+
+	platform_set_drvdata(pdev, pruss_dev);
+	pruss_dev->dev = &pdev->dev;
+	return 0;
+
+probe_exit_clock:
+	clk_put(pruss_dev->clk);
+	clk_disable(pruss_dev->clk);
+probe_exit_iounmap:
+	iounmap(pruss_dev->ioaddr);
+probe_exit_free_region:
+	release_mem_region(pruss_dev->res->start,
+			resource_size(pruss_dev->res));
+probe_exit_kfree:
+	kfree(pruss_dev);
+	return err;
+}
+
+static int __devexit da8xx_pruss_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev);
+
+	mfd_remove_devices(dev);
+	pruss_disable(dev, DA8XX_PRUCORE_0);
+	pruss_disable(dev, DA8XX_PRUCORE_1);
+	clk_disable(pruss->clk);
+	clk_put(pruss->clk);
+	iounmap(pruss->ioaddr);
+	release_mem_region(pruss->res->start, resource_size(pruss->res));
+	kfree(pruss);
+	dev_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver da8xx_pruss_driver = {
+	.probe	= da8xx_pruss_probe,
+	.remove	= __devexit_p(da8xx_pruss_remove),
+	.driver	= {
+		.name	= "pruss_mfd",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init da8xx_pruss_init(void)
+{
+	return platform_driver_register(&da8xx_pruss_driver);
+}
+module_init(da8xx_pruss_init);
+
+static void __exit da8xx_pruss_exit(void)
+{
+	platform_driver_unregister(&da8xx_pruss_driver);
+}
+module_exit(da8xx_pruss_exit);
+
+MODULE_DESCRIPTION("Programmable Realtime Unit (PRU) Driver");
+MODULE_AUTHOR("Subhasish Ghosh");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/da8xx/da8xx_pru.h b/include/linux/mfd/da8xx/da8xx_pru.h
new file mode 100644
index 0000000..ba65ec0
--- /dev/null
+++ b/include/linux/mfd/da8xx/da8xx_pru.h
@@ -0,0 +1,135 @@
+/*
+ * 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 _PRUSS_H_
+#define _PRUSS_H_
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include "da8xx_prucore.h"
+
+#define PRUSS_NUM0			DA8XX_PRUCORE_0
+#define PRUSS_NUM1			DA8XX_PRUCORE_1
+
+#define PRUSS_PRU0_BASE_ADDRESS		0
+#define PRUSS_INTC_BASE_ADDRESS		(PRUSS_PRU0_BASE_ADDRESS + 0x4000)
+#define PRUSS_INTC_GLBLEN		(PRUSS_INTC_BASE_ADDRESS + 0x10)
+#define PRUSS_INTC_GLBLNSTLVL		(PRUSS_INTC_BASE_ADDRESS + 0x1C)
+#define PRUSS_INTC_STATIDXSET		(PRUSS_INTC_BASE_ADDRESS + 0x20)
+#define PRUSS_INTC_STATIDXCLR		(PRUSS_INTC_BASE_ADDRESS + 0x24)
+#define PRUSS_INTC_ENIDXSET		(PRUSS_INTC_BASE_ADDRESS + 0x28)
+#define PRUSS_INTC_ENIDXCLR		(PRUSS_INTC_BASE_ADDRESS + 0x2C)
+#define PRUSS_INTC_HSTINTENIDXSET	(PRUSS_INTC_BASE_ADDRESS + 0x34)
+#define PRUSS_INTC_HSTINTENIDXCLR	(PRUSS_INTC_BASE_ADDRESS + 0x38)
+#define PRUSS_INTC_GLBLPRIIDX		(PRUSS_INTC_BASE_ADDRESS + 0x80)
+#define PRUSS_INTC_STATSETINT0		(PRUSS_INTC_BASE_ADDRESS + 0x200)
+#define PRUSS_INTC_STATSETINT1		(PRUSS_INTC_BASE_ADDRESS + 0x204)
+#define PRUSS_INTC_STATCLRINT0		(PRUSS_INTC_BASE_ADDRESS + 0x280)
+#define PRUSS_INTC_STATCLRINT1		(PRUSS_INTC_BASE_ADDRESS + 0x284)
+#define PRUSS_INTC_ENABLESET0		(PRUSS_INTC_BASE_ADDRESS + 0x300)
+#define PRUSS_INTC_ENABLESET1		(PRUSS_INTC_BASE_ADDRESS + 0x304)
+#define PRUSS_INTC_ENABLECLR0		(PRUSS_INTC_BASE_ADDRESS + 0x380)
+#define PRUSS_INTC_ENABLECLR1		(PRUSS_INTC_BASE_ADDRESS + 0x384)
+#define PRUSS_INTC_CHANMAP0		(PRUSS_INTC_BASE_ADDRESS + 0x400)
+#define PRUSS_INTC_CHANMAP1		(PRUSS_INTC_BASE_ADDRESS + 0x404)
+#define PRUSS_INTC_CHANMAP2		(PRUSS_INTC_BASE_ADDRESS + 0x408)
+#define PRUSS_INTC_CHANMAP3		(PRUSS_INTC_BASE_ADDRESS + 0x40C)
+#define PRUSS_INTC_CHANMAP4		(PRUSS_INTC_BASE_ADDRESS + 0x410)
+#define PRUSS_INTC_CHANMAP5		(PRUSS_INTC_BASE_ADDRESS + 0x414)
+#define PRUSS_INTC_CHANMAP6		(PRUSS_INTC_BASE_ADDRESS + 0x418)
+#define PRUSS_INTC_CHANMAP7		(PRUSS_INTC_BASE_ADDRESS + 0x41C)
+#define PRUSS_INTC_CHANMAP8		(PRUSS_INTC_BASE_ADDRESS + 0x420)
+#define PRUSS_INTC_CHANMAP9		(PRUSS_INTC_BASE_ADDRESS + 0x424)
+#define PRUSS_INTC_CHANMAP10		(PRUSS_INTC_BASE_ADDRESS + 0x428)
+#define PRUSS_INTC_CHANMAP11		(PRUSS_INTC_BASE_ADDRESS + 0x42C)
+#define PRUSS_INTC_CHANMAP12		(PRUSS_INTC_BASE_ADDRESS + 0x430)
+#define PRUSS_INTC_CHANMAP13		(PRUSS_INTC_BASE_ADDRESS + 0x434)
+#define PRUSS_INTC_CHANMAP14		(PRUSS_INTC_BASE_ADDRESS + 0x438)
+#define PRUSS_INTC_CHANMAP15		(PRUSS_INTC_BASE_ADDRESS + 0x43C)
+#define PRUSS_INTC_HOSTMAP0		(PRUSS_INTC_BASE_ADDRESS + 0x800)
+#define PRUSS_INTC_HOSTMAP1		(PRUSS_INTC_BASE_ADDRESS + 0x804)
+#define PRUSS_INTC_HOSTMAP2		(PRUSS_INTC_BASE_ADDRESS + 0x808)
+#define PRUSS_INTC_POLARITY0		(PRUSS_INTC_BASE_ADDRESS + 0xD00)
+#define PRUSS_INTC_POLARITY1		(PRUSS_INTC_BASE_ADDRESS + 0xD04)
+#define PRUSS_INTC_TYPE0		(PRUSS_INTC_BASE_ADDRESS + 0xD80)
+#define PRUSS_INTC_TYPE1		(PRUSS_INTC_BASE_ADDRESS + 0xD84)
+#define PRUSS_INTC_HOSTINTEN		(PRUSS_INTC_BASE_ADDRESS + 0x1500)
+#define PRUSS_INTC_HOSTINTLVL_MAX	9
+
+#define PRU_INTC_HOSTMAP0_CHAN			(0x03020100)
+#define PRU_INTC_HOSTMAP1_CHAN			(0x07060504)
+#define PRU_INTC_HOSTMAP2_CHAN			(0x00000908)
+
+#define PRU_INTC_CHANMAP7_SYS_EVT31		(0x00000000)
+#define PRU_INTC_CHANMAP8_FULL			(0x02020100)
+#define PRU_INTC_CHANMAP9_FULL			(0x04040303)
+#define PRU_INTC_CHANMAP10_FULL			(0x06060505)
+#define PRU_INTC_CHANMAP11_FULL			(0x08080707)
+#define PRU_INTC_CHANMAP12_FULL			(0x00010909)
+#define PRU_INTC_CHANMAP8_HALF			(0x03020100)
+#define PRU_INTC_CHANMAP9_HALF			(0x07060504)
+#define PRU_INTC_CHANMAP10_HALF			(0x03020908)
+#define PRU_INTC_CHANMAP11_HALF			(0x07060504)
+#define PRU_INTC_CHANMAP12_HALF			(0x00010908)
+
+#define PRU_INTC_REGMAP_MASK			(0xFFFFFFFF)
+
+struct da8xx_pruss_devices {
+	const char *dev_name;
+	void *pdata;
+	size_t pdata_size;
+	int (*setup)(void);
+	u32 num_resources;
+	struct resource *resources;
+};
+
+u32 pruss_get_clk_freq(struct device *dev);
+
+s32 pruss_enable(struct device *dev, u8 pruss_num);
+
+s32 pruss_load(struct device *dev, u8 pruss_num,
+	u32 *pruss_code, u32 code_size_in_words);
+
+s32 pruss_run(struct device *dev, u8 pruss_num);
+
+s32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout);
+
+s32 pruss_disable(struct device *dev, u8 pruss_num);
+
+s32 pruss_writeb(struct device *dev, u32 offset,
+		u8 *pdatatowrite, u16 wordstowrite);
+
+s32 pruss_rmwb(struct device *dev, u32 offset, u8 mask, u8 val);
+
+s32 pruss_readb(struct device *dev, u32 offset,
+		u8 *pdatatoread, u16 wordstoread);
+
+s32 pruss_readl(struct device *dev, u32 offset,
+		u32 *pdatatoread, s16 wordstoread);
+
+s32 pruss_writel(struct device *dev, u32 offset,
+		u32 *pdatatoread, s16 wordstoread);
+
+s32 pruss_rmwl(struct device *dev, u32 offset, u32 mask, u32 val);
+
+s32 pruss_idx_writel(struct device *dev, u32 offset, u32 value);
+
+s32 pruss_writew(struct device *dev, u32 offset,
+		u16 *datatowrite, s16 wordstowrite);
+
+s32 pruss_rmww(struct device *dev, u32 offset, u16 mask, u16 val);
+
+s32 pruss_readw(struct device *dev, u32 offset,
+		u16 *pdatatoread, s16 wordstoread);
+#endif	/* End _PRUSS_H_ */
diff --git a/include/linux/mfd/da8xx/da8xx_prucore.h b/include/linux/mfd/da8xx/da8xx_prucore.h
new file mode 100644
index 0000000..913d56f
--- /dev/null
+++ b/include/linux/mfd/da8xx/da8xx_prucore.h
@@ -0,0 +1,129 @@
+/*
+ * 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 _DA8XX_PRUCORE_H_
+#define _DA8XX_PRUCORE_H_
+
+#include <linux/types.h>
+
+#define DA8XX_PRUCORE_0		(0)
+#define DA8XX_PRUCORE_1		(1)
+
+#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_MASK			(0xFFFF0000u)
+#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_SHIFT			(0x00000010u)
+#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_MASK			(0x00008000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_SHIFT			(0x0000000Fu)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_RESETVAL			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_HALT			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_RUN			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_MASK			(0x00000100u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_SHIFT			(0x00000008u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_FREERUN		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_SINGLE			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK			(0x00000008u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT			(0x00000003u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_ENABLE		(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_MASK			(0x00000004u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_SHIFT			(0x00000002u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_RESETVAL			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_NOTASLEEP		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_ASLEEP			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_MASK			(0x00000002u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_RESETVAL			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_ENABLE			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_MASK			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_SHIFT			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_RESET			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_OUT_OF_RESET		(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_RESETVAL				(0x00000000u)
+
+struct da8xx_prusscore_regs {
+	u32 CONTROL;
+	u32 STATUS;
+	u32 WAKEUP;
+	u32 CYCLECNT;
+	u32 STALLCNT;
+	u8  RSVD0[12];
+	u32 CONTABBLKIDX0;
+	u32 CONTABBLKIDX1;
+	u32 CONTABPROPTR0;
+	u32 CONTABPROPTR1;
+	u8  RSVD1[976];
+	u32 INTGPR[32];
+	u32 INTCTER[32];
+	u8  RSVD2[768];
+};
+
+struct pruss_intc_regs {
+	u32 REVID;
+	u32 CONTROL;
+	u8 RES1[8];
+	u32 GLBLEN;
+	u8 RES2[8];
+	u32 GLBLNSTLVL;
+	u32 STATIDXSET;
+	u32 STATIDXCLR;
+	u32 ENIDXSET;
+	u32 ENIDXCLR;
+	u8 RES3[4];
+	u32 HOSTINTENIDXSET;
+	u32 HOSTINTENIDXCLR;
+	u8 RES4[68];
+	u32 GLBLPRIIDX;
+	u8 RES5[380];
+	u32 STATSETINT[2];
+	u8 RES6[120];
+	u32 STATCLRINT[2];
+	u8 RES7[120];
+	u32 ENABLESET[2];
+	u8 RES8[120];
+	u32 ENABLECLR[2];
+	u8 RES9[120];
+	u32 CHANMAP[16];
+	u8 RES10[960];
+	u32 HOSTMAP[2];
+	u8 RES11[248];
+	u32 HOSTINTPRIIDX[10];
+	u8 RES12[984];
+	u32 POLARITY[2];
+	u8 RES13[120];
+	u32 TYPE[2];
+	u8 RES14[888];
+	u32 HOSTINTNSTLVL[10];
+	u8 RES15[984];
+	u32 HOSTINTEN;
+	u8 RES16[6907];
+};
+
+struct pruss_map {
+	u8 dram0[512];
+	u8 res1[7680];
+	u8 dram1[512];
+	u8 res2[7680];
+	struct pruss_intc_regs intc;
+	struct da8xx_prusscore_regs core[2];
+	u8 iram0[4096];
+	u8 res3[12288];
+	u8 iram1[4096];
+	u8 res4[12288];
+};
+
+#endif
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 2/7] da850: pruss platform specific additions.
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
  2011-03-08 13:57 ` [PATCH v3 1/7] mfd: add pruss mfd driver Subhasish Ghosh
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-08 15:17   ` Sergei Shtylyov
  2011-03-08 13:57 ` [PATCH v3 3/7] da850: pruss board " Subhasish Ghosh
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Kevin Hilman, Russell King, Michael Williamson, Sergei Shtylyov,
	Cyril Chemparathy, open list

This patch adds the platform device and assignes the platform resources
for the PRUSS mfd driver.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/da850.c              |    7 +++
 arch/arm/mach-davinci/devices-da8xx.c      |   65 ++++++++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/da8xx.h |    2 +
 3 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 8a4de97..a098263 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -238,6 +238,12 @@ static struct clk tptc2_clk = {
 	.flags		= ALWAYS_ENABLED,
 };
 
+static struct clk pruss_clk = {
+	.name		= "pruss",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC0_PRUSS,
+};
+
 static struct clk uart0_clk = {
 	.name		= "uart0",
 	.parent		= &pll0_sysclk2,
@@ -387,6 +393,7 @@ static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"tpcc1",	&tpcc1_clk),
 	CLK(NULL,		"tptc2",	&tptc2_clk),
 	CLK(NULL,		"uart0",	&uart0_clk),
+	CLK(NULL,		"pruss",	&pruss_clk),
 	CLK(NULL,		"uart1",	&uart1_clk),
 	CLK(NULL,		"uart2",	&uart2_clk),
 	CLK(NULL,		"aintc",	&aintc_clk),
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index beda8a4..a182a3b 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -20,6 +20,7 @@
 #include <mach/time.h>
 #include <mach/da8xx.h>
 #include <mach/cpuidle.h>
+#include <linux/mfd/da8xx/da8xx_pru.h>
 
 #include "clock.h"
 
@@ -499,6 +500,70 @@ void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
 	}
 }
 
+#define DA8XX_PRUSS_MEM_BASE		0x01C30000
+
+static struct resource da8xx_pruss_resources[] = {
+	{
+		.name	= "da8xx_pruss",
+		.start	= DA8XX_PRUSS_MEM_BASE,
+		.end	= DA8XX_PRUSS_MEM_BASE + 0xFFFF,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT0,
+		.end	= IRQ_DA8XX_EVTOUT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT1,
+		.end	= IRQ_DA8XX_EVTOUT1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT2,
+		.end	= IRQ_DA8XX_EVTOUT2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT3,
+		.end	= IRQ_DA8XX_EVTOUT3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT4,
+		.end	= IRQ_DA8XX_EVTOUT4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT5,
+		.end	= IRQ_DA8XX_EVTOUT5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT6,
+		.end	= IRQ_DA8XX_EVTOUT6,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT7,
+		.end	= IRQ_DA8XX_EVTOUT7,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device da8xx_pruss_mfddev = {
+	.name		= "pruss_mfd",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(da8xx_pruss_resources),
+	.resource	= da8xx_pruss_resources,
+};
+
+int __init da8xx_register_pruss_mfd(struct da8xx_pruss_devices *pruss_device)
+{
+	da8xx_pruss_mfddev.dev.platform_data = pruss_device;
+	return platform_device_register(&da8xx_pruss_mfddev);
+}
+
 static const struct display_panel disp_panel = {
 	QVGA,
 	16,
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index c3c3339..afb123d 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -15,6 +15,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/davinci_emac.h>
+#include <linux/mfd/da8xx/da8xx_pru.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -82,6 +83,7 @@ int da8xx_register_watchdog(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
 int da8xx_register_emac(void);
+int da8xx_register_pruss_mfd(struct da8xx_pruss_devices *);
 int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
 int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
 int da850_register_mmcsd1(struct davinci_mmc_config *config);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 3/7] da850: pruss board specific additions.
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
  2011-03-08 13:57 ` [PATCH v3 1/7] mfd: add pruss mfd driver Subhasish Ghosh
  2011-03-08 13:57 ` [PATCH v3 2/7] da850: pruss platform specific additions Subhasish Ghosh
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-08 15:19   ` Sergei Shtylyov
  2011-03-09 11:59   ` Marc Kleine-Budde
  2011-03-08 13:57 ` [PATCH v3 4/7] mfd: pruss SUART private data Subhasish Ghosh
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Kevin Hilman, Russell King, open list

This patch adds board specific initializations and setup routines.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/board-da850-evm.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 11f986b..c614c82 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1053,6 +1053,26 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+static struct da8xx_pruss_devices pruss_devices[] = {
+	{.dev_name = NULL,},
+};
+
+static int __init da8xx_evm_setup_pruss(void)
+{
+	u32 ret = 0;
+	u32 count;
+
+	for (count = 0; count < ARRAY_SIZE(pruss_devices); count++) {
+		if (pruss_devices[count].setup != NULL) {
+			ret = pruss_devices[count].setup();
+			if (ret)
+				return ret;
+		}
+	}
+
+	return da8xx_register_pruss_mfd(pruss_devices);
+}
+
 static __init void da850_evm_init(void)
 {
 	int ret;
@@ -1127,6 +1147,11 @@ static __init void da850_evm_init(void)
 
 	da8xx_register_mcasp(0, &da850_evm_snd_data);
 
+	ret = da8xx_evm_setup_pruss();
+	if (ret)
+		pr_warning("%s: pruss initialization failed: %d\n",
+				__func__, ret);
+
 	ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
 	if (ret)
 		pr_warning("da850_evm_init: lcdcntl mux setup failed: %d\n",
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 4/7] mfd: pruss SUART private data.
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
                   ` (2 preceding siblings ...)
  2011-03-08 13:57 ` [PATCH v3 3/7] da850: pruss board " Subhasish Ghosh
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-08 13:57 ` [PATCH v3 5/7] da850: pruss SUART board specific additions Subhasish Ghosh
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh, open list

This patch adds the PRUSS SUART data.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 include/linux/mfd/da8xx/da8xx_pru.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/include/linux/mfd/da8xx/da8xx_pru.h b/include/linux/mfd/da8xx/da8xx_pru.h
index ba65ec0..2b9d426 100644
--- a/include/linux/mfd/da8xx/da8xx_pru.h
+++ b/include/linux/mfd/da8xx/da8xx_pru.h
@@ -94,6 +94,10 @@ struct da8xx_pruss_devices {
 	struct resource *resources;
 };
 
+struct da850_evm_pruss_suart_data {
+	u32 version;
+};
+
 u32 pruss_get_clk_freq(struct device *dev);
 
 s32 pruss_enable(struct device *dev, u8 pruss_num);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 5/7] da850: pruss SUART board specific additions.
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
                   ` (3 preceding siblings ...)
  2011-03-08 13:57 ` [PATCH v3 4/7] mfd: pruss SUART private data Subhasish Ghosh
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-08 13:57 ` [PATCH v3 6/7] da850: pruss SUART platform " Subhasish Ghosh
  2011-03-08 13:57 ` [PATCH v3 7/7] tty: add pruss SUART driver Subhasish Ghosh
  6 siblings, 0 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Kevin Hilman, Russell King, open list

This patch adds the pruss SUART pin mux and registers the device
with the pruss mfd driver.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/board-da850-evm.c |   45 ++++++++++++++++++++++++++++++-
 1 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index c614c82..0cf40b2 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1053,8 +1053,51 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+const short da850_evm_pruss_suart_pins[] = {
+	DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
+	DA850_AHCLKR, DA850_ACLKR, DA850_AFSR,
+	DA850_AXR_13, DA850_AXR_9, DA850_AXR_7,
+	DA850_AXR_14, DA850_AXR_10, DA850_AXR_8,
+	-1
+};
+
+static int __init da850_evm_pruss_suart_setup(void)
+{
+	int ret;
+
+	ret = davinci_cfg_reg_list(da850_evm_pruss_suart_pins);
+	if (ret)
+		pr_warning("%s: da850_evm_pruss_suart_pins "
+			"mux setup failed: %d\n", __func__, ret);
+	return ret;
+}
+
+static struct da850_evm_pruss_suart_data suart_data = {
+	.version	= 1,
+};
+
+static struct resource da850_evm_pruss_suart_resource[] = {
+	{
+		.name	= "da8xx_mcasp0_iomem",
+		.start	= DAVINCI_DA8XX_MCASP0_REG_BASE,
+		.end	= DAVINCI_DA8XX_MCASP0_REG_BASE +
+				(SZ_1K * 12) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static struct da8xx_pruss_devices pruss_devices[] = {
-	{.dev_name = NULL,},
+	{
+		.dev_name	= "da8xx_pruss_uart",
+		.pdata		= &suart_data,
+		.pdata_size	= sizeof(suart_data),
+		.setup		= da850_evm_pruss_suart_setup,
+		.num_resources  = ARRAY_SIZE(da850_evm_pruss_suart_resource),
+		.resources	= da850_evm_pruss_suart_resource,
+	},
+	{
+		.dev_name	= NULL,
+	},
 };
 
 static int __init da8xx_evm_setup_pruss(void)
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 6/7] da850: pruss SUART platform specific additions.
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
                   ` (4 preceding siblings ...)
  2011-03-08 13:57 ` [PATCH v3 5/7] da850: pruss SUART board specific additions Subhasish Ghosh
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-08 13:57 ` [PATCH v3 7/7] tty: add pruss SUART driver Subhasish Ghosh
  6 siblings, 0 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Kevin Hilman, Russell King, open list

This patch adds the McASP clock alias.
The alias is used by the pruss suart driver
for enabling the McASP PSC.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/devices-da8xx.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index a182a3b..b7a855a 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -558,9 +558,27 @@ struct platform_device da8xx_pruss_mfddev = {
 	.resource	= da8xx_pruss_resources,
 };
 
+#ifdef CONFIG_SERIAL_PRUSS_SUART_MODULE
+int da8xx_mcasp_clk_add_alias(void)
+{
+	return clk_add_alias(NULL, "da8xx_pruss_uart.0",
+			NULL, &da850_mcasp_device.dev);
+}
+#else
+int da8xx_mcasp_clk_add_alias(void)
+{
+	return 0;
+}
+#endif
 int __init da8xx_register_pruss_mfd(struct da8xx_pruss_devices *pruss_device)
 {
+	int ret;
+
 	da8xx_pruss_mfddev.dev.platform_data = pruss_device;
+
+	ret = da8xx_mcasp_clk_add_alias();
+	if (ret < 0)
+		return ret;
 	return platform_device_register(&da8xx_pruss_mfddev);
 }
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 7/7] tty: add pruss SUART driver
       [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
                   ` (5 preceding siblings ...)
  2011-03-08 13:57 ` [PATCH v3 6/7] da850: pruss SUART platform " Subhasish Ghosh
@ 2011-03-08 13:57 ` Subhasish Ghosh
  2011-03-08 18:47   ` Randy Dunlap
  2011-03-18  5:43   ` Subhasish Ghosh
  6 siblings, 2 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-08 13:57 UTC (permalink / raw)
  To: davinci-linux-open-source
  Cc: linux-arm-kernel, m-watkins, nsekhar, sachi, Subhasish Ghosh,
	Greg Kroah-Hartman, Andrew Morton, Randy Dunlap, open list

This patch adds support for the TTY compliant
Soft-UART device emulated on PRUSS.

This patch depends on:
davinci: macro rename DA8XX_LPSC0_DMAX to DA8XX_LPSC0_PRUSS.
		https://patchwork.kernel.org/patch/615681/
davinci: changed SRAM allocator to shared ram.
		https://patchwork.kernel.org/patch/549351/

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 drivers/tty/serial/Kconfig             |   22 +
 drivers/tty/serial/Makefile            |   10 +
 drivers/tty/serial/pruss_suart.c       | 1058 +++++++++++++++++++
 drivers/tty/serial/pruss_suart.h       | 1081 ++++++++++++++++++++
 drivers/tty/serial/pruss_suart_api.c   | 1757 ++++++++++++++++++++++++++++++++
 drivers/tty/serial/pruss_suart_utils.c |  391 +++++++
 include/linux/serial_core.h            |    2 +
 7 files changed, 4321 insertions(+), 0 deletions(-)
 create mode 100644 drivers/tty/serial/pruss_suart.c
 create mode 100644 drivers/tty/serial/pruss_suart.h
 create mode 100644 drivers/tty/serial/pruss_suart_api.c
 create mode 100644 drivers/tty/serial/pruss_suart_utils.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2b83346..14ea0a3 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1596,4 +1596,26 @@ config SERIAL_PCH_UART
 	  This driver is for PCH(Platform controller Hub) UART of Intel EG20T
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
 	  Enabling PCH_DMA, this PCH UART works as DMA mode.
+
+#
+# SUART Kernel Configuration
+#
+
+config SERIAL_PRUSS_SUART
+	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
+	select SERIAL_CORE
+	tristate "PRUSS based SoftUART emulation on DA8XX"
+	---help---
+	This driver emulates upto eight different UARTs on the PRUSS.
+	You may modify the NR_SUARTS macro in the driver to emulate
+	less number of UARTS as per your requirement.
+	If not sure, mark N
+
+config PRUSS_SUART_MCASP
+    int "McASP number"
+    depends on ARCH_DAVINCI && ARCH_DAVINCI_DA830 && SERIAL_PRUSS_SUART
+    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.
 endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 8ea92e9..f52a4eb 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -92,3 +92,13 @@ obj-$(CONFIG_SERIAL_MRST_MAX3110)	+= mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
 obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
+
+#
+# Makefile for SoftUART emulation
+#
+
+suart_emu-objs :=       pruss_suart.o \
+                        pruss_suart_api.o \
+                        pruss_suart_utils.o
+
+obj-$(CONFIG_SERIAL_PRUSS_SUART)        += suart_emu.o
diff --git a/drivers/tty/serial/pruss_suart.c b/drivers/tty/serial/pruss_suart.c
new file mode 100644
index 0000000..c411ff8
--- /dev/null
+++ b/drivers/tty/serial/pruss_suart.c
@@ -0,0 +1,1058 @@
+/*
+ * PRUSS 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 <linux/bitops.h>
+#include <mach/sram.h>
+#include "pruss_suart.h"
+
+#define NR_SUART			8
+#define DRV_NAME			"da8xx_pruss_uart"
+#define DRV_DESC			"PRUSS SUART Driver v1.0"
+#define MAX_SUART_RETRIES		100
+#define SUART_CNTX_SZ			512
+#define SUART_FIFO_TIMEOUT_DFLT		5
+#define SUART_FIFO_TIMEOUT_MIN		4
+#define SUART_FIFO_TIMEOUT_MAX		500
+
+/* Default timeout set to 5ms */
+static s16 suart_timeout = SUART_FIFO_TIMEOUT_DFLT;
+module_param(suart_timeout, short, S_IRUGO);
+MODULE_PARM_DESC(suart_timeout,
+		 "fifo timeout in milli seconds (min: 4; max: 500)");
+
+struct suart_fifo {
+	void *fifo_vaddr_buff_tx;
+	void *fifo_vaddr_buff_rx;
+	void *fifo_phys_addr_tx;
+	void *fifo_phys_addr_rx;
+};
+
+struct omapl_pru_suart {
+	struct uart_port port[NR_SUART];
+	struct device *dev;
+	unsigned long tx_empty[NR_SUART];
+	struct clk *clk_mcasp;
+	struct suart_fifo suart_fifo_addr[NR_SUART];
+	const struct firmware *fw;
+	struct suart_handle suart_hdl[NR_SUART];
+	struct pruss_suart_iomap suart_iomap;
+	struct tasklet_struct tx_task[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].uart_type;
+}
+
+static inline void __stop_tx(struct omapl_pru_suart *soft_uart, u32 uart_no)
+{
+	struct device *dev = soft_uart->dev;
+	unsigned long flags = 0;
+	struct uart_port *port = &soft_uart->port[uart_no];
+	u16 txready;
+	u32 i;
+
+	/* Check if any TX in progress */
+	for (i = 0, txready = 1; (i < 10000) && txready; i++) {
+		txready = (pru_softuart_get_tx_status
+			(dev, &soft_uart->suart_hdl[uart_no]) &
+				CHN_TXRX_STATUS_RDY);
+	}
+	/* To stop tx, disable the TX interrupt */
+	spin_lock_irqsave(&port->lock, flags);
+	suart_intr_clrmask(dev, soft_uart->suart_hdl[uart_no].uart_num,
+				PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	pru_softuart_clr_tx_status(dev, &soft_uart->suart_hdl[uart_no]);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void pruss_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;
+	struct device *dev = soft_uart->dev;
+	s32 count = 0;
+
+	if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_TX))
+		return;
+
+	if (uart_circ_empty(xmit) ||
+			uart_tx_stopped(&soft_uart->port[uart_no])) {
+		pruss_suart_stop_tx(&soft_uart->port[uart_no]);
+		set_bit(0, &soft_uart->tx_empty[uart_no]);
+		return;
+	}
+
+	for (count = 0; count <= soft_uart->tx_loadsz; count++) {
+		*((s8 *)soft_uart->suart_fifo_addr[uart_no].fifo_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 (pru_softuart_write(dev,
+		&soft_uart->suart_hdl[uart_no],
+			(u32 *)&soft_uart->suart_fifo_addr
+				[uart_no].fifo_phys_addr_tx, count) != 0) {
+		dev_err(dev, "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 suart_tx_task(unsigned long data)
+{
+	struct uart_port *port = (struct uart_port *)data;
+	struct omapl_pru_suart *soft_uart =
+		container_of(port, struct omapl_pru_suart, port[port->line]);
+
+	omapl_pru_tx_chars(soft_uart, port->line);
+}
+
+static void omapl_pru_rx_chars(struct omapl_pru_suart *soft_uart, u32 uart_no)
+{
+	struct tty_struct *tty = NULL;
+	struct device *dev = soft_uart->dev;
+	s8 flags = TTY_NORMAL;
+	u16 rx_status, data_len = SUART_FIFO_LEN;
+	u32 data_len_read;
+	u8 suart_data[SUART_FIFO_LEN + 1];
+	s32 i = 0;
+
+	if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_RX))
+		return;
+
+	/* read the status */
+	rx_status = pru_softuart_get_rx_status(dev,
+			&soft_uart->suart_hdl[uart_no]);
+
+	pru_softuart_read_data(dev, &soft_uart->suart_hdl[uart_no],
+			suart_data, data_len + 1, &data_len_read);
+
+	tty = tty_port_tty_get(&soft_uart->port[uart_no].state->port);
+
+	if (!tty)
+		return;
+
+	/* 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 {
+		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;
+		}
+		tty_insert_flip_string(tty, suart_data, data_len_read);
+	}
+
+	/* push data into tty */
+	pru_softuart_clr_rx_status(dev, &soft_uart->suart_hdl[uart_no]);
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+static irqreturn_t pruss_suart_interrupt(s32 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]);
+	struct device *dev = soft_uart->dev;
+	u16 txrx_flag;
+	u32 ret;
+	unsigned long flags = 0;
+	u16 uart_num = port->line + 1;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	do {
+		ret = pru_softuart_get_isrstatus(dev, uart_num, &txrx_flag);
+		if (ret != 0) {
+			dev_err(dev, "suart%d: failed to get interrupt, ret:"
+				" 0x%X txrx_flag 0x%X\n",
+				port->line, ret, txrx_flag);
+				spin_unlock_irqrestore(&port->lock, flags);
+			return IRQ_NONE;
+		}
+		if ((PRU_RX_INTR & txrx_flag) == PRU_RX_INTR) {
+			pru_intr_clr_isrstatus(dev, uart_num, PRU_RX_INTR);
+			if ((soft_uart->port[port->line].ignore_status_mask &
+				CHN_TXRX_STATUS_RDY) == CHN_TXRX_STATUS_RDY) {
+				pru_softuart_clr_rx_status(dev,
+					&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(dev, uart_num, PRU_TX_INTR);
+			pru_softuart_clr_tx_status(dev, &soft_uart->suart_hdl
+						 [port->line]);
+			tasklet_schedule(&soft_uart->tx_task[port->line]);
+		}
+	} while (txrx_flag & (PRU_RX_INTR | PRU_TX_INTR));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static void pruss_suart_stop_rx(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+	/* disable rx interrupt */
+	suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void pruss_suart_enable_ms(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	dev_err(dev, "modem control timer not supported\n");
+}
+
+static void pruss_suart_start_tx(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	unsigned long flags = 0;
+
+	/* unmask the tx interrupts */
+	spin_lock_irqsave(&port->lock, flags);
+	suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (test_and_clear_bit(0, &soft_uart->tx_empty[port->line]))
+		omapl_pru_tx_chars(soft_uart, port->line);
+}
+
+static u32 pruss_suart_tx_empty(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+
+	return (pru_softuart_get_tx_status(dev,
+		&soft_uart->suart_hdl[port->line])
+		& CHN_TXRX_STATUS_RDY) ? 0 : TIOCSER_TEMT;
+}
+
+static u32 pruss_suart_get_mctrl(struct uart_port *port)
+{
+	return -ENOTSUPP;
+}
+
+static void pruss_suart_set_mctrl(struct uart_port *port, u32 mctrl)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	dev_dbg(dev, "modem control not supported\n");
+}
+
+static void pruss_suart_break_ctl(struct uart_port *port, s32 break_state)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (break_state == -1)
+		suart_intr_clrmask(dev,
+			soft_uart->suart_hdl[port->line].uart_num,
+			PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+	else
+		suart_intr_setmask(dev,
+			soft_uart->suart_hdl[port->line].uart_num,
+			PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void pruss_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]);
+	struct device *dev = soft_uart->dev;
+	u8 cval = 0;
+	unsigned long flags = 0;
+	u32 baud = 0;
+	u32 old_csize = old ? old->c_cflag & CSIZE : CS8;
+
+/*
+ * Do not allow unsupported configurations to be set
+ */
+	if (1) {
+		termios->c_cflag &= ~(CRTSCTS | CMSPAR | CSTOPB
+				      | PARENB | PARODD | CMSPAR);
+	}
+
+	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 (pru_softuart_setdatabits
+		(dev, &soft_uart->suart_hdl[port->line], cval, cval) != 0)
+		dev_err(dev, "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 (pru_softuart_setbaud(dev, &soft_uart->suart_hdl[port->line],
+				 SUART_DEFAULT_BAUD / baud,
+				 SUART_DEFAULT_BAUD / baud) != 0)
+		dev_err(dev, "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(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   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(dev,
+			soft_uart->suart_hdl[port->line].uart_num,
+			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(dev,
+			soft_uart->suart_hdl[port->line].uart_num,
+			PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
+	}
+/*
+ * Characters 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(dev, soft_uart->
+					   suart_hdl[port->line].uart_num,
+					   PRU_RX_INTR, CHN_TXRX_IE_MASK_FE);
+		}
+		suart_intr_clrmask(dev,
+			soft_uart->suart_hdl[port->line].uart_num,
+			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;
+		pruss_suart_stop_rx(port);
+	}
+	/*
+	* update the per port timeout
+	*/
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	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 s32 pruss_suart_startup(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	unsigned long flags = 0;
+	s32 retval;
+
+	/*
+	 * Disable interrupts from this port
+	 */
+	spin_lock_irqsave(&port->lock, flags);
+	suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	retval = request_irq(port->irq, pruss_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
+	 */
+	spin_lock_irqsave(&port->lock, flags);
+	suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_RX_INTR, SUART_GBL_INTR_ERR_MASK);
+
+	suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   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(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if ((suart_get_duplex(soft_uart, port->line) & ePRU_SUART_HALF_TX)
+	    == ePRU_SUART_HALF_TX) {
+		suart_pru_to_host_intr_enable(dev, soft_uart->
+			suart_hdl[port->line].uart_num, 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(dev, soft_uart->
+			suart_hdl[port->line].uart_num, PRU_RX_INTR, true);
+		pru_softuart_read(dev, &soft_uart->suart_hdl[port->line],
+			(u32 *)&soft_uart->suart_fifo_addr[port->line].
+			fifo_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 pruss_suart_shutdown(struct uart_port *port)
+{
+	struct omapl_pru_suart *soft_uart =
+	    container_of(port, struct omapl_pru_suart, port[port->line]);
+	struct device *dev = soft_uart->dev;
+	unsigned long flags = 0;
+
+	/*
+	 * Disable interrupts from this port
+	 */
+	/* Disable BI and FE intr */
+	spin_lock_irqsave(&port->lock, flags);
+	suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
+	suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
+			   PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
+			   | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
+			   | CHN_TXRX_IE_MASK_TIMEOUT);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	/* 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 *pruss_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 pruss_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.
+ */
+static s32 pruss_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);
+	struct device *dev = soft_uart->dev;
+	struct suart_config pru_suart_config;
+	s16 timeout = 0;
+	u32 err = 0;
+
+	if (soft_uart == NULL) {
+		dev_err(&pdev->dev, "soft_uart ptr failed\n");
+		return -ENODEV;
+	}
+	err = pru_softuart_open(&soft_uart->suart_hdl[port->line]);
+	if (err != 0) {
+		dev_err(&pdev->dev, "failed to open suart: %d\n", err);
+		err = -ENODEV;
+		goto exit;
+	}
+	set_bit(0, &soft_uart->tx_empty[port->line]);
+
+	/* set fifo /timeout */
+	if (SUART_FIFO_TIMEOUT_MIN > suart_timeout) {
+		dev_err(&pdev->dev, "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) {
+		dev_err(&pdev->dev, "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(dev, timeout);
+
+	if (soft_uart->suart_hdl[port->line].uart_num == PRU_SUART_UART1) {
+		pru_suart_config.tx_serializer = PRU_SUART0_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART0_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART2) {
+		pru_suart_config.tx_serializer = PRU_SUART1_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART1_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART3) {
+		pru_suart_config.tx_serializer = PRU_SUART2_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART2_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART4) {
+		pru_suart_config.tx_serializer = PRU_SUART3_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART3_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART5) {
+		pru_suart_config.tx_serializer = PRU_SUART4_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART4_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART6) {
+		pru_suart_config.tx_serializer = PRU_SUART5_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART5_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART7) {
+		pru_suart_config.tx_serializer = PRU_SUART6_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART6_CONFIG_RX_SER;
+	} else if (soft_uart->suart_hdl[port->line].uart_num ==
+							PRU_SUART_UART8) {
+		pru_suart_config.tx_serializer = PRU_SUART7_CONFIG_TX_SER;
+		pru_suart_config.rx_serializer = PRU_SUART7_CONFIG_RX_SER;
+	} else {
+		return -ENOTSUPP;
+	}
+
+	/* Some defaults to startup. reconfigured by terimos later */
+	pru_suart_config.tx_clk_divisor = 1;
+	pru_suart_config.rx_clk_divisor = 1;
+	pru_suart_config.tx_bits_per_char = ePRU_SUART_DATA_BITS8;
+	pru_suart_config.rx_bits_per_char = ePRU_SUART_DATA_BITS8;
+	pru_suart_config.oversampling = SUART_DEFAULT_OVRSMPL;
+
+	if (pru_softuart_setconfig(dev, &soft_uart->suart_hdl[port->line],
+			&pru_suart_config) != 0) {
+		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 pruss_suart_config_port(struct uart_port *port, s32 flags)
+{
+	if (flags & UART_CONFIG_TYPE && pruss_suart_request_port(port) == 0)
+		port->type = PORT_DA8XX_PRU_SUART;
+}
+
+/*
+ * Verify the new serial port information contained within serinfo is
+ * suitable for this port type.
+ *
+ * Locking: none.
+ * Interrupts: caller dependent.
+ */
+static s32 pruss_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]);
+	s32 ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_DA8XX_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 pruss_suart_ops = {
+	.tx_empty	= pruss_suart_tx_empty,
+	.set_mctrl	= pruss_suart_set_mctrl,
+	.get_mctrl	= pruss_suart_get_mctrl,
+	.stop_tx	= pruss_suart_stop_tx,
+	.start_tx	= pruss_suart_start_tx,
+	.stop_rx	= pruss_suart_stop_rx,
+	.enable_ms	= pruss_suart_enable_ms,
+	.break_ctl	= pruss_suart_break_ctl,
+	.startup	= pruss_suart_startup,
+	.shutdown	= pruss_suart_shutdown,
+	.set_termios	= pruss_suart_set_termios,
+	.type		= pruss_suart_type,
+	.release_port	= pruss_suart_release_port,
+	.request_port	= pruss_suart_request_port,
+	.config_port	= pruss_suart_config_port,
+	.verify_port	= pruss_suart_verify_port,
+};
+
+static struct uart_driver pruss_suart_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= DRV_NAME,
+	.dev_name	= "ttySU",
+	.major		= 0,
+	.minor		= 16,
+	.nr		= NR_SUART,
+};
+
+static s32 __devinit pruss_suart_probe(struct platform_device *pdev)
+{
+	struct omapl_pru_suart *soft_uart;
+	const struct da850_evm_pruss_suart_data *pdata;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	s32 err, i;
+	u8 *fw_data = NULL;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data not found\n");
+		return -EINVAL;
+	}
+
+	soft_uart = kzalloc(sizeof(struct omapl_pru_suart), GFP_KERNEL);
+	if (!soft_uart)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get resource");
+		return -ENOMEM;
+	}
+
+	if (!request_mem_region(res->start,
+			resource_size(res),
+			dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "mcasp memory region already claimed!\n");
+		err = -EBUSY;
+		goto probe_exit;
+	}
+
+	soft_uart->suart_iomap.mcasp_io_addr = ioremap(res->start,
+					resource_size(res));
+	if (!soft_uart->suart_iomap.mcasp_io_addr) {
+		dev_err(&pdev->dev, "mcasp ioremap failed\n");
+		err = -EFAULT;
+		goto probe_exit_1;
+	}
+
+	soft_uart->suart_iomap.p_fifo_buff_virt_base =
+	sram_alloc(SUART_CNTX_SZ * NR_SUART * 2,
+	(dma_addr_t *) &soft_uart->suart_iomap.p_fifo_buff_phys_base);
+	if (!soft_uart->suart_iomap.p_fifo_buff_virt_base)
+		goto probe_exit_iounmap;
+
+	soft_uart->clk_freq_pru = pruss_get_clk_freq(dev);
+
+	soft_uart->clk_mcasp = clk_get(&pdev->dev, NULL);
+	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_sram_free;
+	}
+
+	soft_uart->clk_freq_mcasp = clk_get_rate(soft_uart->clk_mcasp);
+	clk_enable(soft_uart->clk_mcasp);
+
+	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->suart_iomap.pru_clk_freq =
+		(soft_uart->clk_freq_pru / 1000000);
+
+	err = pru_softuart_init(dev, SUART_DEFAULT_BAUD, SUART_DEFAULT_BAUD,
+			SUART_DEFAULT_OVRSMPL, fw_data,
+			soft_uart->fw->size, &soft_uart->suart_iomap);
+	if (err) {
+		dev_err(&pdev->dev, "pruss init error\n");
+		err = -ENODEV;
+		kfree((const void *)fw_data);
+		goto probe_release_fw;
+	}
+	kfree((const void *)fw_data);
+
+	platform_set_drvdata(pdev, &soft_uart->port[0]);
+	soft_uart->dev = dev;
+
+	for (i = 0; i < NR_SUART; i++) {
+		soft_uart->port[i].ops = &pruss_suart_ops;
+		soft_uart->port[i].iotype = UPIO_MEM;
+		soft_uart->port[i].flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+		soft_uart->port[i].mapbase =
+			(u32)soft_uart->suart_iomap.p_fifo_buff_virt_base;
+		soft_uart->port[i].membase =
+			(u8 *)&soft_uart->suart_iomap;
+		soft_uart->port[i].type = PORT_DA8XX_PRU_SUART;
+		soft_uart->port[i].irq =
+			platform_get_irq(to_platform_device(dev->parent), 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;
+		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;
+		soft_uart->suart_hdl[i].uart_num = i + 1;
+		soft_uart->port[i].serial_in = NULL;
+
+		soft_uart->suart_fifo_addr[i].fifo_vaddr_buff_tx =
+		soft_uart->suart_iomap.p_fifo_buff_virt_base +
+		(2 * SUART_CNTX_SZ * i);
+
+		soft_uart->suart_fifo_addr[i].fifo_vaddr_buff_rx =
+		soft_uart->suart_iomap.p_fifo_buff_virt_base +
+		((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
+
+		soft_uart->suart_fifo_addr[i].fifo_phys_addr_tx =
+		soft_uart->suart_iomap.p_fifo_buff_phys_base +
+		(2 * SUART_CNTX_SZ * i);
+
+		soft_uart->suart_fifo_addr[i].fifo_phys_addr_rx =
+		soft_uart->suart_iomap.p_fifo_buff_phys_base +
+		((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
+
+		soft_uart->port[i].serial_out = NULL;
+		tasklet_init(&soft_uart->tx_task[i], suart_tx_task,
+				(unsigned long)&soft_uart->port[i]);
+		uart_add_one_port(&pruss_suart_reg, &soft_uart->port[i]);
+	}
+
+	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_release_fw:
+	release_firmware(soft_uart->fw);
+probe_exit_clk:
+	clk_put(soft_uart->clk_mcasp);
+	clk_disable(soft_uart->clk_mcasp);
+probe_exit_sram_free:
+	sram_free(soft_uart->suart_iomap.p_fifo_buff_virt_base,
+	SUART_CNTX_SZ * NR_SUART * 2);
+probe_exit_iounmap:
+	iounmap(soft_uart->suart_iomap.mcasp_io_addr);
+probe_exit_1:
+	release_mem_region(res->start,
+		resource_size(res));
+probe_exit:
+	kfree(soft_uart);
+	return err;
+}
+
+static s32 __devexit pruss_suart_remove(struct platform_device *pdev)
+{
+	struct omapl_pru_suart *soft_uart = platform_get_drvdata(pdev);
+	const struct da850_evm_pruss_suart_data *pdata;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int i;
+
+	pdata = dev->platform_data;
+	if (!pdata)
+		dev_err(&pdev->dev, "platform data not found\n");
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get resource");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (soft_uart) {
+		for (i = 0; i < NR_SUART; i++) {
+			uart_remove_one_port(&pruss_suart_reg,
+			&soft_uart->port[i]);
+		}
+	}
+
+	sram_free(soft_uart->suart_iomap.p_fifo_buff_virt_base,
+		SUART_CNTX_SZ * NR_SUART * 2);
+	release_firmware(soft_uart->fw);
+	clk_put(soft_uart->clk_mcasp);
+	pru_mcasp_deinit();
+	clk_disable(soft_uart->clk_mcasp);
+	iounmap(soft_uart->suart_iomap.mcasp_io_addr);
+	if (pdata) {
+		release_mem_region(res->start,
+			resource_size(res));
+	}
+	kfree(soft_uart);
+	return 0;
+}
+
+#define pruss_suart_suspend NULL
+#define pruss_suart_resume NULL
+
+static struct platform_driver serial_pruss_driver = {
+	.probe		= pruss_suart_probe,
+	.remove		= __devexit_p(pruss_suart_remove),
+	.suspend	= pruss_suart_suspend,
+	.resume		= pruss_suart_resume,
+	.driver		= {
+			.name	= DRV_NAME,
+			.owner	= THIS_MODULE,
+	},
+};
+
+static s32 __init pruss_suart_init(void)
+{
+	s32 ret;
+
+	pruss_suart_reg.nr = NR_SUART;
+	ret = uart_register_driver(&pruss_suart_reg);
+	if (ret)
+		return ret;
+	ret = platform_driver_register(&serial_pruss_driver);
+	if (ret)
+		goto out;
+
+	pr_debug("SUART serial driver loaded\n");
+	return ret;
+out:
+	uart_unregister_driver(&pruss_suart_reg);
+	return ret;
+}
+
+module_init(pruss_suart_init);
+
+static void __exit pruss_suart_exit(void)
+{
+	platform_driver_unregister(&serial_pruss_driver);
+	uart_unregister_driver(&pruss_suart_reg);
+	pr_debug("SUART serial driver unloaded\n");
+}
+
+module_exit(pruss_suart_exit);
+
+/* Module information */
+MODULE_AUTHOR("Subhasish Ghosh <subhasish@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRV_DESC);
diff --git a/drivers/tty/serial/pruss_suart.h b/drivers/tty/serial/pruss_suart.h
new file mode 100644
index 0000000..8e0b40d
--- /dev/null
+++ b/drivers/tty/serial/pruss_suart.h
@@ -0,0 +1,1081 @@
+/*
+ * 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 <linux/io.h>
+#include <linux/mfd/da8xx/da8xx_pru.h>
+
+#define SINGLE_PRU			0
+#define BOTH_PRU			1
+#define PRU_ACTIVE			BOTH_PRU
+#define PRU_CLK_228			228
+#define PRU_CLK_186			186
+
+#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)
+
+#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)
+
+#define PRU_SUART_HALF_TX		(1u)
+#define PRU_SUART_HALF_RX		(2u)
+#define PRU_SUART_HALF_TX_DISABLED	(4u)
+#define PRU_SUART_HALF_RX_DISABLED	(8u)
+
+#define PRU_SUART0_CONFIG_DUPLEX	(PRU_SUART_HALF_TX_DISABLED | \
+					PRU_SUART_HALF_RX_DISABLED)
+#define PRU_SUART0_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART0_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define PRU_SUART1_CONFIG_DUPLEX	(PRU_SUART_HALF_TX | \
+					PRU_SUART_HALF_RX)
+#define PRU_SUART1_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_7)
+#define PRU_SUART1_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_8)
+
+#define PRU_SUART2_CONFIG_DUPLEX	(PRU_SUART_HALF_TX | \
+					PRU_SUART_HALF_RX)
+#define PRU_SUART2_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_9)
+#define PRU_SUART2_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_10)
+
+#define PRU_SUART3_CONFIG_DUPLEX	(PRU_SUART_HALF_TX | \
+					PRU_SUART_HALF_RX)
+#define PRU_SUART3_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_13)
+#define PRU_SUART3_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_14)
+
+#define PRU_SUART4_CONFIG_DUPLEX	(PRU_SUART_HALF_TX_DISABLED | \
+					PRU_SUART_HALF_RX_DISABLED)
+#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	(PRU_SUART_HALF_TX_DISABLED | \
+					PRU_SUART_HALF_RX_DISABLED)
+#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	(PRU_SUART_HALF_TX_DISABLED | \
+					PRU_SUART_HALF_RX_DISABLED)
+#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	(PRU_SUART_HALF_TX_DISABLED | \
+					PRU_SUART_HALF_RX_DISABLED)
+#define PRU_SUART7_CONFIG_RX_SER	(PRU_SUART_SERIALIZER_NONE)
+#define PRU_SUART7_CONFIG_TX_SER	(PRU_SUART_SERIALIZER_NONE)
+
+#define SUART_NUM_OF_CHANNELS_PER_SUART		2
+#define SUART_NUM_OF_BYTES_PER_CHANNEL		16
+
+#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)
+#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
+
+#define SUART_DEFAULT_OVRSMPL_OFFSET		26
+#define SUART_CHN_OFFSET			31
+#define SERIALIZER_OFFSET			8
+
+#if (SUART_DEFAULT_OVRSMPL == SUART_16X_OVRSMPL)
+#define SUART_DEFAULT_BAUD			57600
+#else
+#define SUART_DEFAULT_BAUD			115200
+#endif
+
+#define PRU_MODE_INVALID			0x0
+#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)
+
+/* MCASP */
+
+#define OMAPL_MCASP_PFUNC_AFSR_MASK			(0x80000000u)
+#define OMAPL_MCASP_PFUNC_AFSR_SHIFT			(0x0000001Fu)
+#define OMAPL_MCASP_PFUNC_AFSR_RESETVAL			(0x00000000u)
+/* AFSR Tokens */
+#define OMAPL_MCASP_PFUNC_AFSR_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AFSR_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AHCLKR_MASK			(0x40000000u)
+#define OMAPL_MCASP_PFUNC_AHCLKR_SHIFT			(0x0000001Eu)
+#define OMAPL_MCASP_PFUNC_AHCLKR_RESETVAL		(0x00000000u)
+/* AHCLKR Tokens */
+#define OMAPL_MCASP_PFUNC_AHCLKR_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AHCLKR_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_ACLKR_MASK			(0x20000000u)
+#define OMAPL_MCASP_PFUNC_ACLKR_SHIFT			(0x0000001Du)
+#define OMAPL_MCASP_PFUNC_ACLKR_RESETVAL		(0x00000000u)
+/* ACLKR Tokens */
+#define OMAPL_MCASP_PFUNC_ACLKR_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_ACLKR_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AFSX_MASK			(0x10000000u)
+#define OMAPL_MCASP_PFUNC_AFSX_SHIFT			(0x0000001Cu)
+#define OMAPL_MCASP_PFUNC_AFSX_RESETVAL			(0x00000000u)
+/* AFSX Tokens */
+#define OMAPL_MCASP_PFUNC_AFSX_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AFSX_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AHCLKX_MASK			(0x08000000u)
+#define OMAPL_MCASP_PFUNC_AHCLKX_SHIFT			(0x0000001Bu)
+#define OMAPL_MCASP_PFUNC_AHCLKX_RESETVAL		(0x00000000u)
+/* AHCLKX Tokens */
+#define OMAPL_MCASP_PFUNC_AHCLKX_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AHCLKX_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_ACLKX_MASK			(0x04000000u)
+#define OMAPL_MCASP_PFUNC_ACLKX_SHIFT			(0x0000001Au)
+#define OMAPL_MCASP_PFUNC_ACLKX_RESETVAL		(0x00000000u)
+/* ACLKX Tokens */
+#define OMAPL_MCASP_PFUNC_ACLKX_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_ACLKX_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AMUTE_MASK			(0x02000000u)
+#define OMAPL_MCASP_PFUNC_AMUTE_SHIFT			(0x00000019u)
+#define OMAPL_MCASP_PFUNC_AMUTE_RESETVAL		(0x00000000u)
+/* AMUTE Tokens */
+#define OMAPL_MCASP_PFUNC_AMUTE_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AMUTE_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR15_MASK			(0x00008000u)
+#define OMAPL_MCASP_PFUNC_AXR15_SHIFT			(0x0000000Fu)
+#define OMAPL_MCASP_PFUNC_AXR15_RESETVAL		(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR15_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR15_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR14_MASK			(0x00004000u)
+#define OMAPL_MCASP_PFUNC_AXR14_SHIFT			(0x0000000Eu)
+#define OMAPL_MCASP_PFUNC_AXR14_RESETVAL		(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR14_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR14_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR13_MASK			(0x00002000u)
+#define OMAPL_MCASP_PFUNC_AXR13_SHIFT			(0x0000000Du)
+#define OMAPL_MCASP_PFUNC_AXR13_RESETVAL		(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR13_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR13_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR12_MASK			(0x00001000u)
+#define OMAPL_MCASP_PFUNC_AXR12_SHIFT			(0x0000000Cu)
+#define OMAPL_MCASP_PFUNC_AXR12_RESETVAL		(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR12_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR12_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR11_MASK			(0x00000800u)
+#define OMAPL_MCASP_PFUNC_AXR11_SHIFT			(0x0000000Bu)
+#define OMAPL_MCASP_PFUNC_AXR11_RESETVAL		(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR11_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR11_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR10_MASK			(0x00000400u)
+#define OMAPL_MCASP_PFUNC_AXR10_SHIFT			(0x0000000Au)
+#define OMAPL_MCASP_PFUNC_AXR10_RESETVAL		(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR10_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR10_GPIO			(0x00000001u)
+#define OMAPL_MCASP_PFUNC_AXR9_MASK			(0x00000200u)
+#define OMAPL_MCASP_PFUNC_AXR9_SHIFT			(0x00000009u)
+#define OMAPL_MCASP_PFUNC_AXR9_RESETVAL			(0x00000000u)
+/* AXR9 Token */
+#define OMAPL_MCASP_PFUNC_AXR9_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR9_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR8_MASK			(0x00000100u)
+#define OMAPL_MCASP_PFUNC_AXR8_SHIFT			(0x00000008u)
+#define OMAPL_MCASP_PFUNC_AXR8_RESETVAL			(0x00000000u)
+/* AXR8 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR8_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR8_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR7_MASK			(0x00000080u)
+#define OMAPL_MCASP_PFUNC_AXR7_SHIFT			(0x00000007u)
+#define OMAPL_MCASP_PFUNC_AXR7_RESETVAL			(0x00000000u)
+/* AXR7 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR7_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR7_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR6_MASK			(0x00000040u)
+#define OMAPL_MCASP_PFUNC_AXR6_SHIFT			(0x00000006u)
+#define OMAPL_MCASP_PFUNC_AXR6_RESETVAL			(0x00000000u)
+/* AXR6 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR6_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR6_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR5_MASK			(0x00000020u)
+#define OMAPL_MCASP_PFUNC_AXR5_SHIFT			(0x00000005u)
+#define OMAPL_MCASP_PFUNC_AXR5_RESETVAL			(0x00000000u)
+/* AXR5 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR5_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR5_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR4_MASK			(0x00000010u)
+#define OMAPL_MCASP_PFUNC_AXR4_SHIFT			(0x00000004u)
+#define OMAPL_MCASP_PFUNC_AXR4_RESETVAL			(0x00000000u)
+/* AXR4 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR4_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR4_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR3_MASK			(0x00000008u)
+#define OMAPL_MCASP_PFUNC_AXR3_SHIFT			(0x00000003u)
+#define OMAPL_MCASP_PFUNC_AXR3_RESETVAL			(0x00000000u)
+/* AXR3 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR3_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR3_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR2_MASK			(0x00000004u)
+#define OMAPL_MCASP_PFUNC_AXR2_SHIFT			(0x00000002u)
+#define OMAPL_MCASP_PFUNC_AXR2_RESETVAL			(0x00000000u)
+/* AXR2 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR2_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR2_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR1_MASK			(0x00000002u)
+#define OMAPL_MCASP_PFUNC_AXR1_SHIFT			(0x00000001u)
+#define OMAPL_MCASP_PFUNC_AXR1_RESETVAL			(0x00000000u)
+/* AXR1 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR1_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR1_GPIO			(0x00000001u)
+
+#define OMAPL_MCASP_PFUNC_AXR0_MASK			(0x00000001u)
+#define OMAPL_MCASP_PFUNC_AXR0_SHIFT			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR0_RESETVAL			(0x00000000u)
+/* AXR0 Tokens */
+#define OMAPL_MCASP_PFUNC_AXR0_MCASP			(0x00000000u)
+#define OMAPL_MCASP_PFUNC_AXR0_GPIO			(0x00000001u)
+#define OMAPL_MCASP_PFUNC_RESETVAL			(0x00000000u)
+
+#define OMAPL_MCASP_PDIR_AFSR_MASK			(0x80000000u)
+#define OMAPL_MCASP_PDIR_AFSR_SHIFT			(0x0000001Fu)
+#define OMAPL_MCASP_PDIR_AFSR_RESETVAL			(0x00000000u)
+/* AFSR Tokens */
+#define OMAPL_MCASP_PDIR_AFSR_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AFSR_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AHCLKR_MASK			(0x40000000u)
+#define OMAPL_MCASP_PDIR_AHCLKR_SHIFT			(0x0000001Eu)
+#define OMAPL_MCASP_PDIR_AHCLKR_RESETVAL		(0x00000000u)
+/* AHCLKR Tokens */
+#define OMAPL_MCASP_PDIR_AHCLKR_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AHCLKR_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_ACLKR_MASK			(0x20000000u)
+#define OMAPL_MCASP_PDIR_ACLKR_SHIFT			(0x0000001Du)
+#define OMAPL_MCASP_PDIR_ACLKR_RESETVAL			(0x00000000u)
+/* ACLKR Tokens */
+#define OMAPL_MCASP_PDIR_ACLKR_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_ACLKR_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AFSX_MASK			(0x10000000u)
+#define OMAPL_MCASP_PDIR_AFSX_SHIFT			(0x0000001Cu)
+#define OMAPL_MCASP_PDIR_AFSX_RESETVAL			(0x00000000u)
+/* AFSX Tokens */
+#define OMAPL_MCASP_PDIR_AFSX_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AFSX_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AHCLKX_MASK			(0x08000000u)
+#define OMAPL_MCASP_PDIR_AHCLKX_SHIFT			(0x0000001Bu)
+#define OMAPL_MCASP_PDIR_AHCLKX_RESETVAL		(0x00000000u)
+/* AHCLKX Tokens */
+#define OMAPL_MCASP_PDIR_AHCLKX_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AHCLKX_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_ACLKX_MASK			(0x04000000u)
+#define OMAPL_MCASP_PDIR_ACLKX_SHIFT			(0x0000001Au)
+#define OMAPL_MCASP_PDIR_ACLKX_RESETVAL			(0x00000000u)
+/* ACLKX Tokens */
+#define OMAPL_MCASP_PDIR_ACLKX_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_ACLKX_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AMUTE_MASK			(0x02000000u)
+#define OMAPL_MCASP_PDIR_AMUTE_SHIFT			(0x00000019u)
+#define OMAPL_MCASP_PDIR_AMUTE_RESETVAL			(0x00000000u)
+/* AMUTE Tokens */
+#define OMAPL_MCASP_PDIR_AMUTE_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AMUTE_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR15_MASK			(0x00008000u)
+#define OMAPL_MCASP_PDIR_AXR15_SHIFT			(0x0000000Fu)
+#define OMAPL_MCASP_PDIR_AXR15_RESETVAL			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR15_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR15_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR14_MASK			(0x00004000u)
+#define OMAPL_MCASP_PDIR_AXR14_SHIFT			(0x0000000Eu)
+#define OMAPL_MCASP_PDIR_AXR14_RESETVAL			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR14_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR14_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR13_MASK			(0x00002000u)
+#define OMAPL_MCASP_PDIR_AXR13_SHIFT			(0x0000000Du)
+#define OMAPL_MCASP_PDIR_AXR13_RESETVAL			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR13_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR13_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR12_MASK			(0x00001000u)
+#define OMAPL_MCASP_PDIR_AXR12_SHIFT			(0x0000000Cu)
+#define OMAPL_MCASP_PDIR_AXR12_RESETVAL			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR12_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR12_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR11_MASK			(0x00000800u)
+#define OMAPL_MCASP_PDIR_AXR11_SHIFT			(0x0000000Bu)
+#define OMAPL_MCASP_PDIR_AXR11_RESETVAL			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR11_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR11_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR10_MASK			(0x00000400u)
+#define OMAPL_MCASP_PDIR_AXR10_SHIFT			(0x0000000Au)
+#define OMAPL_MCASP_PDIR_AXR10_RESETVAL			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR10_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR10_OUTPUT			(0x00000001u)
+#define OMAPL_MCASP_PDIR_AXR9_MASK			(0x00000200u)
+#define OMAPL_MCASP_PDIR_AXR9_SHIFT			(0x00000009u)
+#define OMAPL_MCASP_PDIR_AXR9_RESETVAL			(0x00000000u)
+/* AXR9 Tokens */
+#define OMAPL_MCASP_PDIR_AXR9_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR9_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR8_MASK			(0x00000100u)
+#define OMAPL_MCASP_PDIR_AXR8_SHIFT			(0x00000008u)
+#define OMAPL_MCASP_PDIR_AXR8_RESETVAL			(0x00000000u)
+/* AXR8 Tokens */
+#define OMAPL_MCASP_PDIR_AXR8_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR8_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR7_MASK			(0x00000080u)
+#define OMAPL_MCASP_PDIR_AXR7_SHIFT			(0x00000007u)
+#define OMAPL_MCASP_PDIR_AXR7_RESETVAL			(0x00000000u)
+/*----AXR7 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR7_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR7_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR6_MASK			(0x00000040u)
+#define OMAPL_MCASP_PDIR_AXR6_SHIFT			(0x00000006u)
+#define OMAPL_MCASP_PDIR_AXR6_RESETVAL			(0x00000000u)
+/*----AXR6 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR6_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR6_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR5_MASK			(0x00000020u)
+#define OMAPL_MCASP_PDIR_AXR5_SHIFT			(0x00000005u)
+#define OMAPL_MCASP_PDIR_AXR5_RESETVAL			(0x00000000u)
+/*----AXR5 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR5_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR5_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR4_MASK			(0x00000010u)
+#define OMAPL_MCASP_PDIR_AXR4_SHIFT			(0x00000004u)
+#define OMAPL_MCASP_PDIR_AXR4_RESETVAL			(0x00000000u)
+/*----AXR4 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR4_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR4_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR3_MASK			(0x00000008u)
+#define OMAPL_MCASP_PDIR_AXR3_SHIFT			(0x00000003u)
+#define OMAPL_MCASP_PDIR_AXR3_RESETVAL			(0x00000000u)
+/*----AXR3 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR3_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR3_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR2_MASK			(0x00000004u)
+#define OMAPL_MCASP_PDIR_AXR2_SHIFT			(0x00000002u)
+#define OMAPL_MCASP_PDIR_AXR2_RESETVAL			(0x00000000u)
+/*----AXR2 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR2_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR2_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR1_MASK			(0x00000002u)
+#define OMAPL_MCASP_PDIR_AXR1_SHIFT			(0x00000001u)
+#define OMAPL_MCASP_PDIR_AXR1_RESETVAL			(0x00000000u)
+/*----AXR1 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR1_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR1_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_AXR0_MASK			(0x00000001u)
+#define OMAPL_MCASP_PDIR_AXR0_SHIFT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR0_RESETVAL			(0x00000000u)
+/*----AXR0 Tokens----*/
+#define OMAPL_MCASP_PDIR_AXR0_INPUT			(0x00000000u)
+#define OMAPL_MCASP_PDIR_AXR0_OUTPUT			(0x00000001u)
+
+#define OMAPL_MCASP_PDIR_RESETVAL			(0x00000000u)
+
+#define OMAPL_MCASP_ACLKXCTL_CLKXP_MASK			(0x00000080u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXP_SHIFT		(0x00000007u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXP_RESETVAL		(0x00000000u)
+/*----CLKXP Tokens----*/
+#define OMAPL_MCASP_ACLKXCTL_CLKXP_RISINGEDGE		(0x00000000u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXP_FALLINGEDGE		(0x00000001u)
+
+#define OMAPL_MCASP_ACLKXCTL_ASYNC_MASK			(0x00000040u)
+#define OMAPL_MCASP_ACLKXCTL_ASYNC_SHIFT		(0x00000006u)
+#define OMAPL_MCASP_ACLKXCTL_ASYNC_RESETVAL		(0x00000001u)
+/*----ASYNC Tokens----*/
+#define OMAPL_MCASP_ACLKXCTL_ASYNC_SYNC			(0x00000000u)
+#define OMAPL_MCASP_ACLKXCTL_ASYNC_ASYNC		(0x00000001u)
+
+#define OMAPL_MCASP_ACLKXCTL_CLKXM_MASK			(0x00000020u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXM_SHIFT		(0x00000005u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXM_RESETVAL		(0x00000001u)
+/*----CLKXM Tokens----*/
+#define OMAPL_MCASP_ACLKXCTL_CLKXM_EXTERNAL		(0x00000000u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXM_INTERNAL		(0x00000001u)
+
+#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_MASK		(0x0000001Fu)
+#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT		(0x00000000u)
+#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_RESETVAL		(0x00000000u)
+
+#define OMAPL_MCASP_ACLKXCTL_RESETVAL			(0x00000060u)
+
+/* AHCLKXCTL */
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_MASK		(0x00008000u)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_SHIFT		(0x0000000Fu)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_RESETVAL		(0x00000001u)
+/*----HCLKXM Tokens----*/
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_EXTERNAL		(0x00000000u)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_INTERNAL		(0x00000001u)
+
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_MASK		(0x00004000u)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_SHIFT		(0x0000000Eu)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_RESETVAL		(0x00000000u)
+/*----HCLKXP Tokens----*/
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_NOTINVERTED	(0x00000000u)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_INVERTED		(0x00000001u)
+
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_MASK		(0x00000FFFu)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT		(0x00000000u)
+#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_RESETVAL		(0x00000000u)
+
+#define OMAPL_MCASP_AHCLKXCTL_RESETVAL			(0x00008000u)
+
+#define MCASP_SUART_GBLCTL				(0X00000000)
+#define MCASP_SUART_RGBLCTL				(0X00000000)
+#define MCASP_SUART_XGBLCTL				(0X00000000)
+#define MCASP_SUART_RMASK_8				(0x000000FF)
+#define MCASP_SUART_RMASK_16				(0x0000FFFF)
+#define MCASP_SUART_RFMT_8				(0x0000A038)
+#define MCASP_SUART_RFMT_16				(0x0000A078)
+#define MCASP_SUART_FSRM				(0X00000002)
+#define MCASP_SUART_CLKRM_CLKRP				(0X000000A0)
+#define MCASP_SUART_HCLKRP				(0X00008000)
+#define MCASP_SUART_RTDMS0				(0X00000001)
+#define MCASP_SUART_RSYNCERR				(0X00000002)
+#define MCASP_SUART_RMAX_RPS_256			(0x00FF0008)
+#define MCASP_SUART_XMASK_0_31				(0X0000FFFF)
+#define MCASP_SUART_XBUSEL_XSSZ_16_XPAD_0		(0x00002078)
+#define MCASP_SUART_FSXM				(0x00000002)
+#define MCASP_SUART_CLKXM_ASYNC_CLKXP			(0x000000E0)
+#define MCASP_SUART_HCLKXM				(0x00008000)
+#define MCASP_SUART_XTDMS0				(0X00000001)
+#define MCASP_SUART_XSYNCERR				(0x00000002)
+#define MCASP_SUART_XMAX_XPS_256			(0x00FF0008)
+#define MCASP_SUART_SRCTL_DISMOD			(0x0000000c)
+#define MCASP_SUART_DIT_DISABLE				(0X00000000)
+#define MCASP_SUART_LOOPBACK_DISABLE			(0x00000000)
+#define MCASP_SUART_AMUTE_DISABLE			(0X00000000)
+#define MCASP_SUART_XSTAT				(0x0000FFFF)
+#define MCASP_SUART_RSTAT				(0x0000FFFF)
+
+/* SUART REGS */
+
+/* PRU0 DATA RAM base address */
+#define PRU0_DATARAM_OFFSET		(0x0000u)
+/* PRU1 DATA RAM base address */
+#define PRU1_DATARAM_OFFSET		(0x2000u)
+
+/* PRU0 DATA RAM size */
+#define PRU0_DATARAM_SIZE		(0x200u)
+/* PRU1 DATA RAM size */
+#define PRU1_DATARAM_SIZE		(0x200u)
+
+#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 STATUS Register*/
+#define PRU_SUART_CH_STATUS_EN_BIT_MASK		0x8000
+
+/* 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)
+
+/* 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)
+
+/*
+ *  This enum is used to specify the direction of the channel in UART
+ */
+enum SUART_CHN_DIR {
+	SUART_CHN_TX = 1,
+	SUART_CHN_RX = 2
+};
+
+/*
+ *  This enum is used to specify the state of the channel in UART. It
+ *  is either enabled or disabled.
+ */
+enum SUART_CHN_STATE {
+	SUART_CHN_DISABLED = 0,
+	SUART_CHN_ENABLED = 1
+};
+
+enum SUART_EN_BITSPERCHAR {
+	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
+};
+
+enum SUART_EN_UARTNUM {
+	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
+};
+
+enum SUART_EN_UARTTYPE {
+	ePRU_SUART_HALF_TX = 1,
+	ePRU_SUART_HALF_RX,
+	ePRU_SUART_FULL_TX_RX,
+	ePRU_SUART_HALF_TX_DISABLED = 4,
+	ePRU_SUART_HALF_RX_DISABLED = 8
+};
+
+enum SUART_EN_TXCHANNEL {
+	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
+};
+
+enum SUART_EN_RXCHANNEL {
+	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
+};
+
+enum SUART_EN_UART_STATUS {
+	ePRU_SUART_UART_FREE = 0,
+	ePRU_SUART_UART_IN_USE
+};
+
+struct pru_suart_cnh_cntrl_config1 {
+	u32 mode:2;
+	u32 service_req:1;
+	u32 asp_id:2;
+	u32 reserved1:3;
+	u32 serializer_num:4;
+	u32 reserved2:4;
+	u32 presacler:10;
+	u32 over_sampling:2;
+	u32 framing_mask:1;
+	u32 break_mask:1;
+	u32 timeout_mask:1;
+	u32 reserved3:1;
+};
+
+struct pru_suart_chn_config2_status {
+	u32 bits_per_char:4;
+	u32 reserved1:4;
+	u32 data_len:4;
+	u32 reserved2:4;
+	u32 txrx_ready:1;
+	u32 txrx_complete:1;
+	u32 txrx_error:1;
+	u32 txrx_underrun:1;
+	u32 framing_error:1;
+	u32 break_error:1;
+	u32 timeout_error:1;
+	u32 reserved3:8;
+	u32 chn_state:1;
+};
+
+struct pru_suart_regs_ovly {
+	struct pru_suart_cnh_cntrl_config1 ch_ctrl_config1;
+	struct pru_suart_chn_config2_status ch_config2_txrx_status;
+	u32 ch_txrx_data;
+	u32 reserved1;
+};
+
+struct pru_suart_tx_cntx_priv {
+	u32 asp_xsrctl_base;
+	u32 asp_xbuf_base;
+	u16 buff_addr;
+	u8 buff_size;
+	u8 bits_loaded;
+};
+
+struct pru_suart_rx_cntx_priv {
+	u32 asp_rbuf_base;
+	u32 asp_rsrctl_base;
+	u32 reserved1;
+	u32 reserved2;
+	u32 reserved3;
+	u32 reserved4;
+};
+
+struct suart_config {
+	u8  tx_serializer;
+	u8  rx_serializer;
+	u16 tx_clk_divisor;
+	u16 rx_clk_divisor;
+	u8  tx_bits_per_char;
+	u8  rx_bits_per_char;
+	u8  oversampling;
+	u8  bi_inter_mask;
+	u8  fe_intr_mask;
+};
+
+struct suart_handle {
+	u16 uart_num;
+	u16 uart_type;
+	u16 uart_tx_channel;
+	u16 uart_rx_channel;
+	u16 uart_status;
+};
+
+struct pruss_suart_iomap {
+	void *mcasp_io_addr;
+	void *p_fifo_buff_phys_base;
+	void *p_fifo_buff_virt_base;
+	u32  pru_clk_freq;
+};
+
+/* MCASP */
+struct omapl_mcasp_regs_ovly {
+	u32 REVID;
+	u32 RSVD0[3];
+	u32 PFUNC;
+	u32 PDIR;
+	u32 PDOUT;
+	u32 PDIN;
+	u32 PDCLR;
+	u32 RSVD1[8];
+	u32 GBLCTL;
+	u32 AMUTE;
+	u32 DLBCTL;
+	u32 DITCTL;
+	u32 RSVD2[3];
+	u32 RGBLCTL;
+	u32 RMASK;
+	u32 RFMT;
+	u32 AFSRCTL;
+	u32 ACLKRCTL;
+	u32 AHCLKRCTL;
+	u32 RTDM;
+	u32 RINTCTL;
+	u32 RSTAT;
+	u32 RSLOT;
+	u32 RCLKCHK;
+	u32 REVTCTL;
+	u32 RSVD3[4];
+	u32 XGBLCTL;
+	u32 XMASK;
+	u32 XFMT;
+	u32 AFSXCTL;
+	u32 ACLKXCTL;
+	u32 AHCLKXCTL;
+	u32 XTDM;
+	u32 XINTCTL;
+	u32 XSTAT;
+	u32 XSLOT;
+	u32 XCLKCHK;
+	u32 XEVTCTL;
+	u32 RSVD4[12];
+	u32 DITCSRA0;
+	u32 DITCSRA1;
+	u32 DITCSRA2;
+	u32 DITCSRA3;
+	u32 DITCSRA4;
+	u32 DITCSRA5;
+	u32 DITCSRB0;
+	u32 DITCSRB1;
+	u32 DITCSRB2;
+	u32 DITCSRB3;
+	u32 DITCSRB4;
+	u32 DITCSRB5;
+	u32 DITUDRA0;
+	u32 DITUDRA1;
+	u32 DITUDRA2;
+	u32 DITUDRA3;
+	u32 DITUDRA4;
+	u32 DITUDRA5;
+	u32 DITUDRB0;
+	u32 DITUDRB1;
+	u32 DITUDRB2;
+	u32 DITUDRB3;
+	u32 DITUDRB4;
+	u32 DITUDRB5;
+	u32 RSVD5[8];
+	u32 SRCTL0;
+	u32 SRCTL1;
+	u32 SRCTL2;
+	u32 SRCTL3;
+	u32 SRCTL4;
+	u32 SRCTL5;
+	u32 SRCTL6;
+	u32 SRCTL7;
+	u32 SRCTL8;
+	u32 SRCTL9;
+	u32 SRCTL10;
+	u32 SRCTL11;
+	u32 SRCTL12;
+	u32 SRCTL13;
+	u32 SRCTL14;
+	u32 SRCTL15;
+	u32 RSVD6[16];
+	u32 XBUF0;
+	u32 XBUF1;
+	u32 XBUF2;
+	u32 XBUF3;
+	u32 XBUF4;
+	u32 XBUF5;
+	u32 XBUF6;
+	u32 XBUF7;
+	u32 XBUF8;
+	u32 XBUF9;
+	u32 XBUF10;
+	u32 XBUF11;
+	u32 XBUF12;
+	u32 XBUF13;
+	u32 XBUF14;
+	u32 XBUF15;
+	u32 RSVD7[16];
+	u32 RBUF0;
+	u32 RBUF1;
+	u32 RBUF2;
+	u32 RBUF3;
+	u32 RBUF4;
+	u32 RBUF5;
+	u32 RBUF6;
+	u32 RBUF7;
+	u32 RBUF8;
+	u32 RBUF9;
+	u32 RBUF10;
+	u32 RBUF11;
+	u32 RBUF12;
+	u32 RBUF13;
+	u32 RBUF14;
+	u32 RBUF15;
+};
+
+/*
+ *  SUART Config regs
+ */
+struct suart_struct_pru_regs {
+	u16 chn_ctrl;
+	u16 chn_config1;
+	u16 chn_config2;
+	u16 chn_txrx_status;
+	u32 chn_txrx_data;
+};
+
+extern s16 pru_softuart_init(struct device *dev, u32 tx_baud_value,
+			u32 rx_baud_value, u32 oversampling,
+			u8 *pru_suart_emu_code, u32 fw_size,
+			struct pruss_suart_iomap *pruss_ioaddr);
+
+extern s16 pru_softuart_open(struct suart_handle *h_suart);
+
+extern s16 pru_softuart_close(struct suart_handle *h_uart);
+
+extern s16 pru_softuart_setbaud(struct device *dev,
+			struct suart_handle *h_uart,
+			u16 tx_clk_divisor, u16 rx_clk_divisor);
+
+extern s16 pru_softuart_setdatabits(struct device *dev,
+			struct suart_handle *h_uart,
+			u16 tx_data_bits, u16 rx_data_bits);
+
+extern s16 pru_softuart_setconfig(struct device *dev,
+			struct suart_handle *h_uart,
+			struct suart_config *config_uart);
+
+extern s16 pru_softuart_getconfig(struct device *dev,
+			struct suart_handle *h_uart,
+			struct suart_config *config_uart);
+
+extern s32 pru_softuart_pending_tx_request(struct device *dev);
+
+extern s16 pru_softuart_write(struct device *dev,
+			struct suart_handle *h_uart,
+			u32 *pt_tx_data_buf, u16 data_len);
+
+extern s16 pru_softuart_read(struct device *dev,
+			struct suart_handle *h_uart,
+			u32 *pt_data_buf, u16 data_len);
+
+extern s32 suart_intr_clrmask(struct device *dev, u16 uart_num,
+						u32 txrxmode,
+						u32 intrmask);
+
+extern s16 pru_softuart_clr_tx_status(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s16 pru_softuart_get_tx_status(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s16 pru_softuart_clr_rx_status(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s16 pru_softuart_get_rx_status(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s16 pru_softuart_get_isrstatus(struct device *dev, u16 uart_num,
+			u16 *txrx_flag);
+
+extern s32 pru_intr_clr_isrstatus(struct device *dev, u16 uart_num,
+							u32 txrxmode);
+
+extern s32 suart_intr_getmask(struct device *dev, u16 uart_num,
+						u32 txrxmode,
+						u32 intrmask);
+
+extern s32 suart_intr_setmask(struct device *dev, u16 uart_num,
+			u32 txrxmode, u32 intrmask);
+
+extern s16 pru_softuart_get_tx_data_len(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s16 pru_softuart_get_rx_data_len(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s16 suart_arm_to_pru_intr(struct device *dev, u16 uart_num);
+
+extern void pru_mcasp_deinit(void);
+
+extern s16 pru_softuart_read_data(struct device *dev,
+			struct suart_handle *h_uart,
+			u8 *p_data_buffer, s32 max_len,
+			u32 *pdata_read);
+
+extern s16 pru_softuart_stop_receive(struct device *dev,
+				struct suart_handle *h_uart);
+
+extern s32 suart_pru_to_host_intr_enable(struct device *dev,
+					u16 uart_num,
+					u32 txrxmode, s32 flag);
+
+extern void pru_set_fifo_timeout(struct device *dev, s16 timeout);
+
+extern void suart_mcasp_config(u32 tx_baud_value,
+			u32 rx_baud_value, u32 oversampling,
+			struct pruss_suart_iomap *pruss_ioaddr);
+
+extern void suart_mcasp_reset(struct pruss_suart_iomap *pruss_ioaddr);
+
+extern short suart_asp_baud_set(u32 tx_baud_value,
+			u32 rx_baud_value, u32 oversampling,
+			struct pruss_suart_iomap *pruss_ioaddr);
+
+extern short suart_asp_serializer_deactivate(u16 sr_num,
+			struct pruss_suart_iomap *pruss_ioaddr);
+
+extern void suart_mcasp_tx_serialzier_set(u32 serializer_num,
+			struct pruss_suart_iomap *pruss_ioaddr);
+#endif
diff --git a/drivers/tty/serial/pruss_suart_api.c b/drivers/tty/serial/pruss_suart_api.c
new file mode 100644
index 0000000..b483b90
--- /dev/null
+++ b/drivers/tty/serial/pruss_suart_api.c
@@ -0,0 +1,1757 @@
+/*
+ * 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 <linux/mfd/da8xx/da8xx_pru.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include "pruss_suart.h"
+
+static u8 uart_statu_table[8];
+static struct pruss_suart_iomap suart_iomap;
+
+static u32 uart_rx[8] = {PRU_SUART0_CONFIG_RX_SER, PRU_SUART1_CONFIG_RX_SER,
+			PRU_SUART2_CONFIG_RX_SER, PRU_SUART3_CONFIG_RX_SER,
+			PRU_SUART4_CONFIG_RX_SER, PRU_SUART5_CONFIG_RX_SER,
+			PRU_SUART6_CONFIG_RX_SER, PRU_SUART7_CONFIG_RX_SER};
+
+static u32 uart_tx[8] = {PRU_SUART0_CONFIG_TX_SER, PRU_SUART1_CONFIG_TX_SER,
+			PRU_SUART2_CONFIG_TX_SER, PRU_SUART3_CONFIG_TX_SER,
+			PRU_SUART4_CONFIG_TX_SER, PRU_SUART5_CONFIG_TX_SER,
+			PRU_SUART6_CONFIG_TX_SER, PRU_SUART7_CONFIG_TX_SER};
+
+static u32 uart_config[8] = {PRU_SUART0_CONFIG_DUPLEX, PRU_SUART1_CONFIG_DUPLEX,
+			PRU_SUART2_CONFIG_DUPLEX, PRU_SUART3_CONFIG_DUPLEX,
+			PRU_SUART4_CONFIG_DUPLEX, PRU_SUART5_CONFIG_DUPLEX,
+			PRU_SUART6_CONFIG_DUPLEX, PRU_SUART7_CONFIG_DUPLEX};
+
+static  s16 pru_softuart_clr_rx_fifo(struct device *dev,
+				struct suart_handle *h_uart);
+static s16 arm_to_pru_intr_init(struct device *dev);
+
+#if (PRU_ACTIVE == BOTH_PRU)
+static void pru_set_ram_data(struct device *dev,
+			struct pruss_suart_iomap *pruss_ioaddr)
+{
+	u32 datatowrite;
+	u32 i;
+	struct pru_suart_regs_ovly *pru_suart_regs = PRU0_DATARAM_OFFSET;
+	u32 *p_sr_ctl_addr = (u32 *)(pruss_ioaddr->mcasp_io_addr + 0x180);
+	struct pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
+	struct pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
+
+	/* RX PRU - 0 Chanel 0-7 context information */
+	for (i = 0; i < 8; i++, pru_suart_regs++) {
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+						0x3, SUART_CHN_RX);
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+				(0xF << SERIALIZER_OFFSET),
+				((0xF & uart_rx[i]) << SERIALIZER_OFFSET));
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+				(0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
+				(SUART_DEFAULT_OVRSMPL <<
+				SUART_DEFAULT_OVRSMPL_OFFSET));
+		pruss_rmwl(dev,
+			(u32) &pru_suart_regs->ch_config2_txrx_status,
+							0xF, 8);
+		if ((uart_config[i] & PRU_SUART_HALF_RX_DISABLED) ==
+					PRU_SUART_HALF_RX_DISABLED) {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_DISABLED << SUART_CHN_OFFSET));
+		} else {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_ENABLED << SUART_CHN_OFFSET));
+			__raw_writel(MCASP_SRCTL_RX_MODE, p_sr_ctl_addr +
+								uart_rx[i]);
+		}
+		/*
+		* RX is active by default, write the dummy received data at
+		* PRU RAM addr 0x1FC to avoid memory corruption.
+		*/
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_txrx_data,
+				0xFFFF, RX_DEFAULT_DATA_DUMP_ADDR);
+		pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
+							0xFFFF, 0);
+		/* SUART1 RX context base addr */
+		pru_suart_rx_priv = (struct pru_suart_rx_cntx_priv *)
+				(PRU0_DATARAM_OFFSET + (0x090 + (i * 0x020)));
+		datatowrite = (MCASP_RBUF_BASE_ADDR + (uart_rx[i] << 2));
+		pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rbuf_base,
+							&datatowrite, 1);
+		datatowrite = (MCASP_SRCTL_BASE_ADDR + (uart_rx[i] << 2));
+		pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rsrctl_base,
+							&datatowrite, 1);
+	}
+
+	/* ****************** PRU1 RAM BASE ADDR ************************ */
+	pru_suart_regs = (struct pru_suart_regs_ovly *) PRU1_DATARAM_OFFSET;
+
+	/* ******************* TX PRU - 1  *********************** */
+	/* Channel 0-7 context information */
+	for (i = 0; i < 8; i++, pru_suart_regs++) {
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+						0x3, SUART_CHN_TX);
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+				(0xF << SERIALIZER_OFFSET),
+				((0xF & uart_tx[i]) << SERIALIZER_OFFSET));
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+				(0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
+				(SUART_DEFAULT_OVRSMPL <<
+				SUART_DEFAULT_OVRSMPL_OFFSET));
+		pruss_rmwl(dev,
+			(u32) &pru_suart_regs->ch_config2_txrx_status,
+								0xF, 8);
+		if ((uart_config[i] & PRU_SUART_HALF_TX_DISABLED) ==
+						PRU_SUART_HALF_TX_DISABLED) {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_DISABLED << SUART_CHN_OFFSET));
+		} else {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_ENABLED << SUART_CHN_OFFSET));
+			__raw_writel(MCASP_SRCTL_TX_MODE,
+				p_sr_ctl_addr + uart_tx[i]);
+		}
+		pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
+							0xFFFF, 1);
+	/* SUART1 TX context base addr */
+		 pru_suart_tx_priv = (struct pru_suart_tx_cntx_priv *)
+			(PRU1_DATARAM_OFFSET + (0x0B0 + (i * 0x02C)));
+		datatowrite = (MCASP_SRCTL_BASE_ADDR + (uart_tx[i] << 2));
+		pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xsrctl_base,
+							&datatowrite, 1);
+		datatowrite = (MCASP_XBUF_BASE_ADDR + (uart_tx[i] << 2));
+		pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xbuf_base,
+							&datatowrite, 1);
+	/* SUART1 TX formatted data base addr */
+		datatowrite = (0x0090 + (i * 0x002C));
+		pruss_writel(dev, (u32) &pru_suart_tx_priv->buff_addr,
+							&datatowrite, 1);
+	}
+}
+#else
+static void pru_set_ram_data(struct device *dev,
+			struct pruss_suart_iomap *pruss_ioaddr)
+{
+
+	struct pru_suart_regs_ovly *pru_suart_regs =
+		(struct pru_suart_regs_ovly *)pruss_ioaddr->pru_io_addr;
+	u32 i;
+	u32 *p_sr_ctl_addr = (u32 *)(pruss_ioaddr->mcasp_io_addr + 0x180);
+	struct pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
+	struct pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
+
+	/* ***************** UART 0  ************************ */
+	/* Channel 0 context information is Tx */
+	for (i = 0; i < 4; i++, pru_suart_regs++) {
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+						0x3, SUART_CHN_TX);
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+						(0xF << SERIALIZER_OFFSET),
+				((0xF & uart_tx[i]) << SERIALIZER_OFFSET));
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+				(0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
+				(SUART_DEFAULT_OVRSMPL <<
+				SUART_DEFAULT_OVRSMPL_OFFSET));
+		pruss_rmwl(dev,
+			(u32) &pru_suart_regs->ch_config2_txrx_status,
+								0xF, 8);
+		if ((uart_config[i] & PRU_SUART_HALF_TX_DISABLED) ==
+						PRU_SUART_HALF_TX_DISABLED){
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_DISABLED << SUART_CHN_OFFSET));
+		} else {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_ENABLED << SUART_CHN_OFFSET));
+			__raw_writel(MCASP_SRCTL_TX_MODE,
+						p_sr_ctl_addr + uart_tx[i]);
+		}
+		pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
+					0xFFFF, 1);
+	/* SUART1 TX context base addr */
+		 pru_suart_tx_priv = (struct pru_suart_tx_cntx_priv *)
+				(PRU0_DATARAM_OFFSET + (0x0B0 + (i * 0x50)));
+		pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xsrctl_base,
+				(MCASP_SRCTL_BASE_ADDR + (uart_tx[i] << 2)), 1);
+		pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xbuf_base,
+				(MCASP_XBUF_BASE_ADDR + (uart_tx[i] << 2)), 1);
+	/* SUART1 TX formatted data base addr */
+		pruss_writel(dev, (u32) &pru_suart_tx_priv->buff_addr,
+					(0x0090 + (i * 0x050)), 1);
+
+	/* Channel 1 is Rx context information */
+		pru_suart_regs++;
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+							0x3, SUART_CHN_RX);
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+						(0xF << SERIALIZER_OFFSET),
+				((0xF & uart_rx[i]) << SERIALIZER_OFFSET));
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
+				(0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
+				(SUART_DEFAULT_OVRSMPL <<
+				SUART_DEFAULT_OVRSMPL_OFFSET));
+		pruss_rmwl(dev,
+				(u32) &pru_suart_regs->ch_config2_txrx_status,
+									0xF, 8);
+
+		if ((uart_config[i] & PRU_SUART_HALF_RX_DISABLED) ==
+						PRU_SUART_HALF_RX_DISABLED) {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_DISABLED << SUART_CHN_OFFSET));
+		} else {
+			pruss_rmwl(dev, (u32)
+				&pru_suart_regs->ch_config2_txrx_status,
+				(0x1 << SUART_CHN_OFFSET),
+				(SUART_CHN_ENABLED << SUART_CHN_OFFSET));
+			__raw_writel(MCASP_SRCTL_RX_MODE,
+					p_sr_ctl_addr + uart_rx[i]);
+		}
+	/* RX is active by default, write the dummy received data
+	 * at PRU RAM addr 0x1FC to avoid memory corruption
+	 */
+		pruss_rmwl(dev, (u32) &pru_suart_regs->ch_txrx_data,
+				0xFFFF, RX_DEFAULT_DATA_DUMP_ADDR);
+		pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
+							0xFFFF, 0);
+	/* SUART1 RX context base addr */
+		pru_suart_rx_priv = (struct pru_suart_rx_cntx_priv *)
+			(PRU0_DATARAM_OFFSET + (0x0C0 + (i * 0x50)));
+		pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rbuf_base,
+				(MCASP_RBUF_BASE_ADDR + (uart_rx[i] << 2)), 1);
+		pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rsrctl_base,
+				(MCASP_SRCTL_BASE_ADDR + (uart_rx[i] << 2)), 1);
+	}
+}
+#endif
+
+static void pru_set_rx_tx_mode(struct device *dev, u32 pru_mode, u32 pru_num)
+{
+
+	u32 pru_offset;
+
+	if (pru_num == PRUSS_NUM0)
+		pru_offset = PRU_SUART_PRU0_RX_TX_MODE;
+	else if (pru_num == PRUSS_NUM1)
+		pru_offset = PRU_SUART_PRU1_RX_TX_MODE;
+	else
+		return;
+	pruss_writeb(dev, pru_offset, (u8 *) &pru_mode, 1);
+}
+
+static void pru_set_delay_count(struct device *dev, u32 pru_freq)
+{
+	u32 delay_cnt;
+
+	if (pru_freq == PRU_CLK_228)
+		delay_cnt = 5;
+	else if (pru_freq == PRU_CLK_186)
+		delay_cnt = 5;
+	else
+		delay_cnt = 3;
+
+	/* PRU 0 */
+	pruss_writeb(dev, PRU_SUART_PRU0_DELAY_OFFSET,
+		(u8 *) &delay_cnt, 1);
+
+	/* PRU 1 */
+	pruss_writeb(dev, PRU_SUART_PRU1_DELAY_OFFSET,
+		(u8 *) &delay_cnt, 1);
+}
+
+static s32 suart_set_pru_id(struct device *dev, u32 pru_no)
+{
+	u32 offset;
+	u8 reg_val = 0;
+
+	if (PRUSS_NUM0 == pru_no)
+		offset = PRU_SUART_PRU0_ID_ADDR;
+	else if (PRUSS_NUM1 == pru_no)
+		offset = PRU_SUART_PRU1_ID_ADDR;
+	else
+		return -EINVAL;
+
+	reg_val = pru_no;
+	pruss_writeb(dev, offset, (u8 *) &reg_val, 1);
+
+	return 0;
+}
+
+/*
+ * suart Initialization routine
+ */
+s16 pru_softuart_init(struct device *dev, u32 tx_baud_value,
+			u32 rx_baud_value, u32 oversampling,
+			u8 *pru_suart_emu_code, u32 fw_size,
+			struct pruss_suart_iomap *pruss_ioaddr)
+{
+	u32 datatowrite[128] = {0};
+	s16 status = 0;
+	s16 idx;
+	s16 retval;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) &&
+				(PRU1_MODE == PRU_MODE_RX_TX_BOTH))
+		return -EINVAL;
+
+	suart_iomap.mcasp_io_addr = pruss_ioaddr->mcasp_io_addr;
+	suart_iomap.p_fifo_buff_phys_base =
+			pruss_ioaddr->p_fifo_buff_phys_base;
+	suart_iomap.p_fifo_buff_virt_base =
+			pruss_ioaddr->p_fifo_buff_virt_base;
+	suart_iomap.pru_clk_freq = pruss_ioaddr->pru_clk_freq;
+	/* Configure McASP0  */
+	suart_mcasp_config(tx_baud_value,
+			rx_baud_value, oversampling, pruss_ioaddr);
+	pruss_enable(dev, PRUSS_NUM0);
+
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		pruss_enable(dev, PRUSS_NUM1);
+
+	/* Reset PRU RAM */
+	pruss_writel(dev, PRU0_DATARAM_OFFSET, datatowrite,
+				 (PRU0_DATARAM_SIZE / sizeof(int)));
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		pruss_writel(dev, PRU1_DATARAM_OFFSET, datatowrite,
+				 (PRU1_DATARAM_SIZE / sizeof(int)));
+
+	pruss_load(dev, PRUSS_NUM0, (u32 *)pru_suart_emu_code,
+					(fw_size / sizeof(u32)));
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		pruss_load(dev, PRUSS_NUM1, (u32 *)pru_suart_emu_code,
+					(fw_size / sizeof(u32)));
+
+	retval = arm_to_pru_intr_init(dev);
+	if (-1 == retval)
+		return status;
+	pru_set_delay_count(dev, pruss_ioaddr->pru_clk_freq);
+	suart_set_pru_id(dev, PRUSS_NUM0);
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		suart_set_pru_id(dev, PRUSS_NUM1);
+
+	pru_set_rx_tx_mode(dev, PRU0_MODE, PRUSS_NUM0);
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		pru_set_rx_tx_mode(dev, PRU1_MODE, PRUSS_NUM1);
+
+	pru_set_ram_data(dev, pruss_ioaddr);
+	pruss_run(dev, PRUSS_NUM0);
+
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		pruss_run(dev, PRUSS_NUM1);
+
+	/* Initialize uart_statu_table */
+	for (idx = 0; idx < 8; idx++)
+		uart_statu_table[idx] = ePRU_SUART_UART_FREE;
+
+	return status;
+}
+
+void pru_set_fifo_timeout(struct device *dev, s16 timeout)
+{
+	pruss_writew(dev, PRU_SUART_PRU0_IDLE_TIMEOUT_OFFSET,
+						&timeout, 1);
+	if (PRU1_MODE != PRU_MODE_INVALID)
+		pruss_writew(dev, PRU_SUART_PRU1_IDLE_TIMEOUT_OFFSET,
+							&timeout, 1);
+}
+
+void pru_mcasp_deinit(void)
+{
+	suart_mcasp_reset(&suart_iomap);
+}
+
+/* suart Instance open routine  */
+s16 pru_softuart_open(struct suart_handle *h_suart)
+{
+	s16 status = 0;
+	u16 uart_num = h_suart->uart_num - 1;
+
+	if (uart_statu_table[h_suart->uart_num - 1] ==
+			ePRU_SUART_UART_IN_USE) {
+		status = EUSERS;
+		return status;
+	} else {
+		h_suart->uart_type = uart_config[uart_num];
+		h_suart->uart_tx_channel = uart_tx[uart_num];
+		h_suart->uart_rx_channel = uart_rx[uart_num];
+		h_suart->uart_status = ePRU_SUART_UART_IN_USE;
+		uart_statu_table[h_suart->uart_num - 1] =
+						ePRU_SUART_UART_IN_USE;
+	}
+	return status;
+}
+
+/* suart instance close routine */
+s16 pru_softuart_close(struct suart_handle *h_uart)
+{
+	s16 status = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	} else {
+		uart_statu_table[h_uart->uart_num - 1] =
+			ePRU_SUART_UART_FREE;
+		/* Reset the Instance to Invalid */
+		h_uart->uart_num = PRU_SUART_UARTx_INVALID;
+		h_uart->uart_status = ePRU_SUART_UART_FREE;
+	}
+	return status;
+}
+
+static s16 search_chnum(u16 uart_num, u16 *ch_num, u32 *pru_offset, u16 mode)
+{
+	*ch_num = uart_num - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+		|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		*ch_num = (uart_num *
+			SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (uart_num <= 4) {
+			*pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+		} else {
+			*pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+			*ch_num -= 8;
+		}
+		if (mode == 2)
+			*ch_num = *ch_num + 1;
+
+	} else if ((mode == 1) || (mode == 2)) {
+		if (mode == 1) {
+			if (PRU0_MODE == PRU_MODE_TX_ONLY)
+				*pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+			else if (PRU1_MODE == PRU_MODE_TX_ONLY)
+				*pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+		} else if (mode == 2)  {
+			if (PRU0_MODE == PRU_MODE_RX_ONLY)
+				*pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+			else if (PRU1_MODE == PRU_MODE_RX_ONLY)
+				*pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+		}
+	 } else {
+		return 0;
+	}
+
+		return 0;
+}
+
+/*
+ * suart routine for setting relative baud rate
+ */
+s16 pru_softuart_setbaud(struct device *dev, struct suart_handle *h_uart,
+		u16 tx_clk_divisor, u16 rx_clk_divisor)
+{
+	u32 offset;
+	u32 pru_offset;
+	s16 status = 0;
+	u16 ch_num;
+	u16 regval = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/* Set the clock divisor value s32o the McASP */
+	if ((tx_clk_divisor > 385) || (tx_clk_divisor == 0))
+		return -EINVAL;
+	if ((rx_clk_divisor > 385) || (rx_clk_divisor == 0))
+		return -EINVAL;
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	if (tx_clk_divisor != 0) {
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG1_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= (~0x3FF);
+		regval |= tx_clk_divisor;
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+			(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		ch_num++;
+	} else {
+		return 0;
+	}
+	regval = 0;
+	if (rx_clk_divisor != 0) {
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG1_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= (~0x3FF);
+		regval |= tx_clk_divisor;
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+	return status;
+}
+
+/*
+ * suart routine for setting number of bits per character for a specific uart
+ */
+s16 pru_softuart_setdatabits(struct device *dev, struct suart_handle *h_uart,
+		u16 tx_data_bits, u16 rx_data_bits)
+{
+	u32 offset;
+	u32 pru_offset;
+	s16 status = 0;
+	u16 ch_num;
+	u32 reg_val;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/*
+	 * NOTE:
+	 * The supported data bits are 6,7,8,9,10,11,12 bits per character
+	 */
+
+	if ((tx_data_bits < ePRU_SUART_DATA_BITS6)
+			|| (tx_data_bits > ePRU_SUART_DATA_BITS12))
+		return -EINVAL;
+
+	if ((rx_data_bits < ePRU_SUART_DATA_BITS6)
+			|| (rx_data_bits > ePRU_SUART_DATA_BITS12))
+		return -EINVAL;
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	if (tx_data_bits != 0) {
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG2_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 1);
+		reg_val &= ~(0xF);
+		reg_val |= tx_data_bits;
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 1);
+	}
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+			|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		ch_num++;
+	} else {
+		return 0;
+	}
+	if (rx_data_bits != 0) {
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG2_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 1);
+		reg_val &= ~(0xF);
+		reg_val |= rx_data_bits;
+		pruss_writeb(dev, offset, (u8 *) &rx_data_bits, 1);
+	}
+
+	return status;
+}
+
+/*
+ * suart routine to configure specific uart
+ */
+s16 pru_softuart_setconfig(struct device *dev, struct suart_handle *h_uart,
+				struct suart_config *config_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	s16 status = 0;
+	u16 ch_num;
+	u16 reg_val = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/*
+	 * NOTE:
+	 * Dependent baud rate for the given UART,the value MUST BE LESS THAN OR
+	 * EQUAL TO 64, preScalarValue <= 64
+	 */
+	if ((config_uart->tx_clk_divisor > 384)
+			|| (config_uart->rx_clk_divisor > 384)) {
+		return -EINVAL;
+	}
+	if ((config_uart->tx_bits_per_char < 8)
+			|| (config_uart->tx_bits_per_char > 14)) {
+		return -EINVAL;
+	}
+	if ((config_uart->rx_bits_per_char < 8)
+			|| (config_uart->rx_bits_per_char > 14)) {
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	/* 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
+	 * (config_uart->tx_serializer, &suart_iomap);
+	 */
+	/* Configuring TX serializer  */
+	if (config_uart->tx_serializer != PRU_SUART_SERIALIZER_NONE) {
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CTRL_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+		reg_val = reg_val | (config_uart->tx_serializer <<
+			PRU_SUART_CH_CTRL_SR_SHIFT);
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG1_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+		reg_val = reg_val | (config_uart->tx_clk_divisor <<
+			PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG2_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+		reg_val = reg_val | (config_uart->tx_bits_per_char <<
+			PRU_SUART_CH_CONFIG2_BITPERCHAR_SHIFT);
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+	}
+
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+			(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		ch_num++;
+	} else {
+		return 0;
+	}
+
+	/* Configuring the Transmit part of the given UART */
+	if (config_uart->rx_serializer != PRU_SUART_SERIALIZER_NONE) {
+		/* Configuring RX serializer  */
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CTRL_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+		reg_val = reg_val | (config_uart->rx_serializer <<
+			PRU_SUART_CH_CTRL_SR_SHIFT);
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+
+		/* Configuring RX prescalar value and Oversampling */
+		offset = pru_offset +
+			(ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_CONFIG1_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+		reg_val = reg_val | (config_uart->rx_clk_divisor <<
+			PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT) |
+			(config_uart->oversampling <<
+			PRU_SUART_CH_CONFIG1_OVS_SHIFT);
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+
+		/* Configuring RX bits per character value */
+		offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
+						+ PRU_SUART_CH_CONFIG2_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+		reg_val = reg_val | (config_uart->rx_bits_per_char <<
+			PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+		pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+	}
+	return status;
+}
+
+/*
+ * suart routine for getting the number of bytes transfered
+ */
+s16 pru_softuart_get_tx_data_len(struct device *dev,
+					struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 ch_num;
+	u16 read_value = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &read_value, 2);
+	read_value = ((read_value & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+	return read_value;
+}
+
+/*
+ * suart routine for getting the number of bytes received
+ */
+s16 pru_softuart_get_rx_data_len(struct device *dev,
+					struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 ch_num;
+	u16 read_value = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &read_value, 2);
+	read_value = ((read_value & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+
+	return read_value;
+}
+
+/*
+ * suart routine to get the configuration information from a specific uart
+ */
+s16 pru_softuart_getconfig(struct device *dev,
+			 struct suart_handle *h_uart,
+			struct suart_config *config_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 ch_num;
+	u16 reg_val = 0;
+	s16 status = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/*
+	 * NOTE:
+	 * Dependent baud rate for the given UART,the value MUST BE LESS THAN OR
+	 * EQUAL TO 64, preScalarValue <= 64
+	 */
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	/* Configuring the Transmit part of the given UART */
+	/* Configuring TX serializer  */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CTRL_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	config_uart->tx_serializer = ((reg_val & PRU_SUART_CH_CTRL_SR_MASK) >>
+						PRU_SUART_CH_CTRL_SR_SHIFT);
+	/* Configuring TX prescalar value */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG1_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	config_uart->tx_clk_divisor = ((reg_val &
+				 PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
+					 PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+
+	/* Configuring TX bits per character value */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+					PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	config_uart->tx_bits_per_char = ((reg_val &
+				 PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
+					PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+
+	if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+				(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		ch_num++;
+	} else {
+		return 0;
+	}
+	/* Configuring the Transmit part of the given UART */
+	/* Configuring RX serializer  */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CTRL_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	config_uart->rx_serializer = ((reg_val & PRU_SUART_CH_CTRL_SR_MASK) >>
+						PRU_SUART_CH_CTRL_SR_SHIFT);
+
+	/* Configuring RX prescalar value and oversampling */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG1_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	config_uart->rx_clk_divisor = ((reg_val &
+					 PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+	config_uart->oversampling = ((reg_val &
+					 PRU_SUART_CH_CONFIG1_OVS_MASK) >>
+						PRU_SUART_CH_CONFIG1_OVS_SHIFT);
+
+	/* Configuring RX bits per character value */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	config_uart->rx_bits_per_char = ((reg_val &
+					 PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
+					>> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
+
+	return status;
+}
+
+s32 pru_softuart_pending_tx_request(struct device *dev)
+{
+	u32 offset = 0;
+	u32 ISR_value = 0;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		return 0;
+	} else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
+		/* Read PRU Interrupt Status Register from PRU */
+		offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
+		pruss_readl(dev, offset, (u32 *)&ISR_value, 1);
+		if ((ISR_value & 0x1) == 0x1)
+			return -EINVAL;
+	} else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
+		/* Read PRU Interrupt Status Register from PRU */
+		offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
+		pruss_readl(dev, offset, (u32 *)&ISR_value, 1);
+		if ((ISR_value & 0x2) == 0x2)
+			return -EINVAL;
+	} else {
+		return 0;
+	}
+
+	return 0;
+}
+
+/*
+ * suart data transmit routine
+ */
+s16 pru_softuart_write(struct device *dev, struct suart_handle *h_uart,
+		u32 *pt_tx_data_buf, u16 data_len)
+{
+	u32 offset = 0;
+	u32 pru_offset;
+	s16 status = 0;
+	u16 ch_num;
+	u16 reg_val = 0;
+	u16 pru_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+				(PRU1_MODE == PRU_MODE_RX_TX_BOTH))
+		pru_num = h_uart->uart_num;
+	else if (PRU0_MODE == PRU_MODE_TX_ONLY)
+		pru_num = 0;
+	else if (PRU1_MODE == PRU_MODE_TX_ONLY)
+		pru_num = 1;
+	else
+		return 0;
+
+	/* Writing data length to SUART channel register */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+				PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	reg_val &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
+	reg_val = reg_val | (data_len << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+	pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+
+	/* Writing the data pos32er to channel TX data pointer */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+				PRU_SUART_CH_TXRXDATA_OFFSET;
+	pruss_writeb(dev, offset, (u8 *) pt_tx_data_buf, 4);
+
+	/* Service Request to PRU */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+				PRU_SUART_CH_CTRL_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK |
+			PRU_SUART_CH_CTRL_SREQ_MASK);
+	reg_val |= (PRU_SUART_CH_CTRL_TX_MODE <<
+		PRU_SUART_CH_CTRL_MODE_SHIFT) | (PRU_SUART_CH_CTRL_SREQ <<
+		PRU_SUART_CH_CTRL_SREQ_SHIFT);
+	pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+
+	/* generate ARM->PRU event */
+	suart_arm_to_pru_intr(dev, pru_num);
+
+	return status;
+}
+
+/*
+ * suart data receive routine
+ */
+s16 pru_softuart_read(struct device *dev, struct suart_handle *h_uart,
+		u32 *ptDataBuf, u16 data_len)
+{
+	u32 offset = 0;
+	u32 pru_offset;
+	s16 status = 0;
+	u16 ch_num;
+	u16 reg_val = 0;
+	u16 pru_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+	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 */
+		ch_num = (h_uart->uart_num *
+			SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		pru_num = h_uart->uart_num;
+	} else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
+		pru_num = 0;
+	} else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
+		pru_num = 1;
+	} else {
+		return 0;
+	}
+	/* Writing data length to SUART channel register */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+					PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	reg_val &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
+	reg_val = reg_val | (data_len << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
+	pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+
+	/* Writing the data pos32er to channel RX data pointer */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+		PRU_SUART_CH_TXRXDATA_OFFSET;
+	pruss_writeb(dev, offset, (u8 *) ptDataBuf, 4);
+
+	/* Service Request to PRU */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+		PRU_SUART_CH_CTRL_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK |
+		PRU_SUART_CH_CTRL_SREQ_MASK);
+	reg_val |= (PRU_SUART_CH_CTRL_RX_MODE <<
+		PRU_SUART_CH_CTRL_MODE_SHIFT) | (PRU_SUART_CH_CTRL_SREQ <<
+		PRU_SUART_CH_CTRL_SREQ_SHIFT);
+	pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+
+	/* enable the timeout s32errupt */
+	suart_intr_setmask(dev, h_uart->uart_num, PRU_RX_INTR,
+		CHN_TXRX_IE_MASK_TIMEOUT);
+
+	/* generate ARM->PRU event */
+	suart_arm_to_pru_intr(dev, pru_num);
+
+	return status;
+}
+
+/*
+ * suart routine to read the data from the RX FIFO
+ */
+s16 pru_softuart_read_data(struct device *dev, struct suart_handle *h_uart,
+				u8 *p_data_buffer, s32 max_len,
+					u32 *pdata_read)
+{
+	s16 ret_val = 0;
+	u8 *psrc_addr = NULL;
+	u32 data_read = 0;
+	u32 data_len = 0;
+	u32 char_len = 0;
+	u32 offset = 0;
+	u32 pru_offset;
+	u16 ch_num;
+	u16 status = 0;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+
+	/* Get the data pos32er from channel RX data pointer */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_TXRXDATA_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &psrc_addr, 4);
+
+	/* Reading data length from SUART channel register */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CONFIG2_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &data_len, 2);
+
+	/* read the character length */
+	char_len = data_len & PRU_SUART_CH_CONFIG2_BITPERCHAR_MASK;
+	char_len -= 2;	/* remove the START & STOP bit */
+
+	data_len &= PRU_SUART_CH_CONFIG2_DATALEN_MASK;
+	data_len = data_len >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT;
+	data_len++;
+
+	/* if the character length is greater than 8, then the size doubles */
+	if (char_len > 8)
+		data_len *= 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 = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 1);
+	if (CHN_TXRX_STATUS_TIMEOUT == (status & CHN_TXRX_STATUS_TIMEOUT)) {
+		/* determine the number of bytes read s32o the FIFO */
+		offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
+				 + PRU_SUART_CH_BYTESDONECNTR_OFFSET;
+		pruss_readb(dev, offset, (u8 *) &data_read, 1);
+
+		/* if the character length is greater than 8,
+				then the size doubles */
+		if (char_len > 8)
+			data_read *= 2;
+
+/*
+ * the data corresponding is loaded in second
+ * half during the timeout
+ */
+		if (data_read > data_len) {
+			data_read -= data_len;
+			psrc_addr += data_len;
+		}
+
+		pru_softuart_clr_rx_fifo(dev, h_uart);
+	} else {
+		data_read = data_len;
+/*
+ * 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 (status & CHN_TXRX_STATUS_CMPLT)
+			psrc_addr += data_len;
+	}
+
+	/* we should be copying only max len given by the application */
+	if (data_read > max_len)
+		data_read = max_len;
+
+/* evaluate the virtual address of the FIFO address
+ * based on the physical addr
+ */
+	psrc_addr = (u8 *)((u32) psrc_addr -
+		(u32) suart_iomap.p_fifo_buff_phys_base +
+		(u32) suart_iomap.p_fifo_buff_virt_base);
+
+	/* Now we have both the data length and the source address. copy */
+	for (offset = 0; offset < data_read; offset++)
+		*p_data_buffer++ = *psrc_addr++;
+	*pdata_read = data_read;
+	ret_val = 0;
+
+	return ret_val;
+}
+
+/*
+ * 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_stop_receive(struct device *dev, struct suart_handle *h_uart)
+{
+	u16 ret_status = 0;
+	u32 offset;
+	u32 pru_offset;
+	u16 ch_num;
+	u16 status;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+
+	/* read the existing value of status flag */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 1);
+
+	/* we need to clear the busy bit corresponding to receive channel */
+	status &= ~(CHN_TXRX_STATUS_RDY);
+	pruss_writeb(dev, offset, (u8 *) &status, 1);
+
+	/* get the serizlizer number being used for this Rx channel */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CTRL_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 2);
+	status &= PRU_SUART_CH_CTRL_SR_MASK;
+	status = status >> PRU_SUART_CH_CTRL_SR_SHIFT;
+
+	/* we need to de-activate the serializer corresponding to this rx */
+	ret_status = suart_asp_serializer_deactivate(status, &suart_iomap);
+
+	return ret_status;
+}
+
+/*
+ * suart routine to get the tx status for a specific uart
+ */
+s16 pru_softuart_get_tx_status(struct device *dev, struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 status = 0;
+	u16 ch_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+					PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 1);
+	return status;
+}
+
+s16 pru_softuart_clr_tx_status(struct device *dev, struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 status = 0;
+	u16 ch_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
+
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+					PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 1);
+	status &= ~(0x2);
+	pruss_writeb(dev, offset, (u8 *) &status, 1);
+	return status;
+}
+
+/*
+ * suart routine to get the rx status for a specific uart
+ */
+s16 pru_softuart_get_rx_status(struct device *dev, struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 status = 0;
+	u16 ch_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+				PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 1);
+	return status;
+}
+
+static s16 pru_softuart_clr_rx_fifo(struct device *dev,
+				struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 status = 0;
+	u16 ch_num;
+	u16 reg_val;
+	u16 uart_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	uart_num = h_uart->uart_num;
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+	if (PRU0_MODE == PRU_MODE_RX_ONLY)
+		uart_num = 0;
+	else if (PRU1_MODE == PRU_MODE_RX_ONLY)
+		uart_num = 1;
+
+	/* Reset the number of bytes read into the FIFO */
+		offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
+					+ PRU_SUART_CH_BYTESDONECNTR_OFFSET;
+		pruss_readw(dev, offset, (u16 *) &reg_val, 1);
+	reg_val &= 0x00;
+		pruss_writew(dev, offset, (u16 *) &reg_val, 1);
+
+
+	/* Service Request to PRU */
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+						PRU_SUART_CH_CTRL_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &reg_val, 2);
+	reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK | PRU_SUART_CH_CTRL_SREQ_MASK);
+	reg_val |= (PRU_SUART_CH_CTRL_RX_MODE << PRU_SUART_CH_CTRL_MODE_SHIFT) |
+		(PRU_SUART_CH_CTRL_SREQ << PRU_SUART_CH_CTRL_SREQ_SHIFT);
+	pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
+	suart_intr_setmask(dev, h_uart->uart_num, PRU_RX_INTR,
+						CHN_TXRX_IE_MASK_TIMEOUT);
+
+	/* generate ARM->PRU event */
+	suart_arm_to_pru_intr(dev, uart_num);
+
+	return status;
+}
+
+s16 pru_softuart_clr_rx_status(struct device *dev, struct suart_handle *h_uart)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 status = 0;
+	u16 ch_num;
+
+	if (h_uart == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
+
+	offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
+			PRU_SUART_CH_TXRXSTATUS_OFFSET;
+	pruss_readb(dev, offset, (u8 *) &status, 1);
+	status &= ~(0x3C);
+	pruss_writeb(dev, offset, (u8 *) &status, 1);
+	return status;
+}
+
+/*
+ * suart_s32r_status_read: Gets the Global Interrupt status register
+ * for the specified SUART.
+ * uart_num < 1 to 6 >
+ * txrx_flag < Indicates TX or RX s32errupt for the uart >
+ */
+s16 pru_softuart_get_isrstatus(struct device *dev, u16 uart_num, u16 *txrx_flag)
+{
+	u32 intc_offset;
+	u32 ch_num = 0xFF;
+	u32 reg_val = 0;
+	u32 reg_val2 = 0;
+	u32 ISR_value = 0;
+	u32 ack_reg_val = 0;
+	u32 stat_inx_clr_regoffset = 0;
+
+	/* initialize the status & Flag to known value */
+	*txrx_flag = 0;
+
+	stat_inx_clr_regoffset = (u32) (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+
+	/* Read PRU Interrupt Status Register from PRU */
+	intc_offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
+
+	pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+		|| (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* Check if the interrupt occured for Tx */
+		ch_num = uart_num * 2 - 2;
+		reg_val2 = PRU_SUART0_TX_EVT_BIT << ((uart_num - 1) * 2);
+		if (ISR_value & reg_val2) {
+			/* interupt occured for TX */
+			*txrx_flag |= PRU_TX_INTR;
+			/* acknowledge the RX interrupt  */
+			ack_reg_val  = ch_num + PRU_SUART0_TX_EVT;
+			pruss_writel(dev, stat_inx_clr_regoffset,
+					(u32 *)&ack_reg_val, 1);
+		}
+
+		/* Check if the interrupt occured for Rx */
+		reg_val2 = PRU_SUART0_RX_EVT_BIT << ((uart_num - 1) * 2);
+		pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
+		if (ISR_value & reg_val2) {
+			/* interupt occured for RX */
+			*txrx_flag |= PRU_RX_INTR;
+			ch_num += 1;
+
+			/* acknowledge the RX interrupt  */
+			ack_reg_val  = ch_num + PRU_SUART0_TX_EVT;
+			pruss_writel(dev, stat_inx_clr_regoffset,
+						(u32 *)&ack_reg_val, 1);
+		}
+	} else {
+		ch_num = uart_num - 1;
+		if ((ISR_value & 0x03FC) != 0) {
+			reg_val2 = 1 << (uart_num + 1);
+			if (ISR_value & reg_val2) {
+				/* acknowledge the s32errupt  */
+				ack_reg_val = ch_num + PRU_SUART0_TX_EVT;
+				pruss_writel(dev, stat_inx_clr_regoffset,
+					(u32 *)&ack_reg_val, 1);
+				*txrx_flag |= PRU_RX_INTR;
+			}
+		}
+		pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
+		if (ISR_value & 0x3FC00) {
+			reg_val2 = 1 << (uart_num + 9);
+			if (ISR_value & reg_val2) {
+				/* acknowledge the s32errupt  */
+				ack_reg_val = ch_num + PRU_SUART4_TX_EVT;
+				pruss_writel(dev, stat_inx_clr_regoffset,
+					(u32 *)&ack_reg_val, 1);
+				*txrx_flag |= PRU_TX_INTR;
+			}
+		}
+	}
+	return reg_val;
+}
+
+s32 pru_intr_clr_isrstatus(struct device *dev, u16 uart_num, u32 txrxmode)
+{
+	u32 offset;
+	u16 txrx_flag = 0;
+	u16 chn_num;
+
+	chn_num = uart_num - 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 */
+		chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if (uart_num <= 4) {
+			/* PRU0 */
+			offset = PRU_SUART_PRU0_ISR_OFFSET + 1;
+		} else {
+			/* PRU1 */
+			offset = PRU_SUART_PRU1_ISR_OFFSET + 1;
+			/* First 8 channel corresponds to PRU0 */
+			chn_num -= 8;
+		}
+		if (2 == txrxmode)
+			chn_num++;
+	} 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 0;
+	}
+
+	pruss_readb(dev, offset, (u8 *) &txrx_flag, 1);
+	txrx_flag &= ~(0x2);
+	pruss_writeb(dev, offset, (u8 *) &txrx_flag, 1);
+
+	return 0;
+}
+
+s16 suart_arm_to_pru_intr(struct device *dev, u16 uart_num)
+{
+	u32 offset;
+	u32 value;
+	s16 retval;
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		if ((uart_num > 0) && (uart_num <= 4)) {
+			/* PRU0 SYS_EVT32 */
+			value = 0x20;
+		} else if ((uart_num > 4) && (uart_num <= 8)) {
+			/* PRU1 SYS_EVT33 */
+			value = 0x21;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	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 (uart_num == PRUSS_NUM0) {
+			/* PRU0 SYS_EVT32 */
+			value = 0x20;
+		}
+
+		if (uart_num == PRUSS_NUM1) {
+			/* PRU0 SYS_EVT33 */
+			value = 0x21;
+		}
+	}
+
+	offset = (u32) (PRUSS_INTC_STATIDXSET & 0xFFFF);
+	retval = pruss_writel(dev, offset, (u32 *)&value, 1);
+	if (retval == -1)
+		return -1;
+	return 0;
+}
+
+static s16 arm_to_pru_intr_init(struct device *dev)
+{
+	u32 value;
+	u32 int_offset;
+
+	/* Clear all the host interrupts */
+	for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
+							int_offset++)
+		pruss_idx_writel(dev, PRUSS_INTC_HSTINTENIDXCLR, int_offset);
+
+	/* Enable the global s32errupt */
+	pruss_rmwl(dev, (u32) (PRUSS_INTC_GLBLEN & 0xFFFF), 0, 1);
+
+	/* Enable the Host interrupts for all host channels */
+	for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
+							 int_offset++)
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_HSTINTENIDXSET & 0xFFFF),
+								0, int_offset);
+	pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP0 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP0_CHAN);
+	pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP1 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP1_CHAN);
+	pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP2 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP2_CHAN);
+
+	 /* MAP Channel 0 to SYS_EVT31 */
+	pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP7 & 0xFFFF),
+			PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP7_SYS_EVT31);
+
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
+	    || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		/* Sets the channels for the system interrupt */
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP8 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP8_FULL);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP9 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP9_FULL);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP10 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP10_FULL);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP11 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP11_FULL);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP12 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP12_FULL);
+	}
+	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 channels for the system interrupt */
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP8 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP8_HALF);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP9 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP9_HALF);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP10 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP10_HALF);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP11 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP11_HALF);
+		pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP12 & 0xFFFF),
+				PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP12_HALF);
+	}
+
+	/* Clear required set of system events
+	* and enable them using indexed register
+	*/
+	for (int_offset = 0; int_offset < 18; int_offset++) {
+		value = 32 + int_offset;
+		pruss_idx_writel(dev, PRUSS_INTC_STATIDXCLR, value);
+	}
+
+	/* enable only the HOST to PRU interrupts and let the PRU to Host events
+	 * enabled by the separate API on demand basis.
+	 */
+	pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 31);
+	pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 32);
+	pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 33);
+	pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 50);
+	pruss_rmwl(dev, (u32) (PRUSS_INTC_GLBLEN & 0xFFFF), 0, 1);
+
+	/* Enable the Host interrupts for all host channels */
+	for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
+							int_offset++)
+		pruss_idx_writel(dev, PRUSS_INTC_HSTINTENIDXSET, int_offset);
+
+	return 0;
+}
+
+s32 suart_pru_to_host_intr_enable(struct device *dev, u16 uart_num,
+		u32 txrxmode, s32 flag)
+{
+	s32 ret_val = 0;
+	u32 offset;
+	u32 chn_num;
+	u32 value;
+	s16 retval = 0;
+
+	if (uart_num > 8)
+		return -EINVAL;
+
+	chn_num = uart_num - 1;
+	if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
+		(PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
+		chn_num = (uart_num * 2) - 2;
+		if (2 == txrxmode)	/* Rx mode */
+			chn_num++;
+		value = 34 + chn_num;
+	} else if ((PRU_MODE_RX_ONLY == txrxmode)
+		&& (PRU0_MODE == PRU_MODE_RX_ONLY))
+		value = 34 + chn_num;
+	else if ((PRU_MODE_RX_ONLY == txrxmode)
+		&& (PRU1_MODE == PRU_MODE_RX_ONLY))
+		value = 42 + chn_num;
+	else if ((PRU_MODE_TX_ONLY == txrxmode)
+		&& (PRU0_MODE == PRU_MODE_TX_ONLY))
+		value = 34 + chn_num;
+	else if ((PRU_MODE_TX_ONLY == txrxmode)
+		&& (PRU1_MODE == PRU_MODE_TX_ONLY))
+		value = 42 + chn_num;
+	else
+		return -1;
+
+	if (true == flag) {
+		offset = (u32) (PRUSS_INTC_ENIDXSET & 0xFFFF);
+		retval = pruss_writel(dev, offset, (u32 *)&value, 1);
+		if (retval == -1)
+			return -1;
+	} else {
+		offset = (u32) (PRUSS_INTC_ENIDXCLR & 0xFFFF);
+		retval = pruss_writel(dev, offset, (u32 *)&value, 1);
+		if (retval == -1)
+			return -1;
+	}
+	return ret_val;
+}
+
+s32 suart_intr_setmask(struct device *dev, u16 uart_num,
+		u32 txrxmode, u32 rmask)
+{
+	u32 offset;
+	u32 pru_offset;
+	u32 regval = 0;
+	u32 chn_num;
+
+	chn_num = uart_num - 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 */
+		chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if ((uart_num > 0) && (uart_num <= 4)) {
+			pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+			offset = PRU_SUART_PRU0_IMR_OFFSET;
+		} else if ((uart_num > 4) && (uart_num <= 8)) {
+			offset = PRU_SUART_PRU1_IMR_OFFSET;
+			pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+			chn_num -= 8;
+		} else {
+			return -EINVAL;
+		}
+		if (2 == txrxmode) {	/* rx mode */
+			chn_num++;
+		}
+	} else if (PRU0_MODE == txrxmode) {
+		pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+		offset = PRU_SUART_PRU0_IMR_OFFSET;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_IMR_OFFSET;
+		pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return 0;
+	}
+	regval = 1 << chn_num;
+	if (CHN_TXRX_IE_MASK_CMPLT == (rmask & CHN_TXRX_IE_MASK_CMPLT))
+		pruss_rmww(dev, offset, regval, regval);
+
+	if ((rmask & SUART_GBL_INTR_ERR_MASK) ==
+			SUART_GBL_INTR_ERR_MASK) {
+		regval = SUART_GBL_INTR_ERR_MASK;
+		pruss_rmww(dev, offset, regval, regval);
+	}
+
+	offset = pru_offset +
+		(chn_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
+				+ PRU_SUART_CH_CONFIG1_OFFSET;
+	/* Framing Error Interrupt Masked */
+	if ((rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
+		regval = 0;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= ~(CHN_TXRX_IE_MASK_FE);
+		regval |= CHN_TXRX_IE_MASK_FE;
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+
+	/* Break Indicator Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_BI == (rmask & CHN_TXRX_IE_MASK_BI)) {
+		regval = 0;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= ~(CHN_TXRX_IE_MASK_BI);
+		regval |= CHN_TXRX_IE_MASK_BI;
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+
+	/* Timeout error Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_TIMEOUT ==
+			(rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
+		regval = 0;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
+		regval |= CHN_TXRX_IE_MASK_TIMEOUT;
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+	return 0;
+}
+
+s32 suart_intr_clrmask(struct device *dev, u16 uart_num,
+		u32 txrxmode, u32 rmask)
+{
+	u32 offset;
+	u32 pru_offset;
+	u16 regval = 0;
+	u16 chn_num;
+
+	chn_num = uart_num - 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 */
+		chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+		if ((uart_num > 0) && (uart_num <= 4)) {
+			pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+			offset = PRU_SUART_PRU0_IMR_OFFSET;
+		} else if ((uart_num > 4) && (uart_num <= 8)) {
+			/* PRU1 */
+			offset = PRU_SUART_PRU1_IMR_OFFSET;
+			pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chn_num -= 8;
+		} else {
+			return -EINVAL;
+		}
+		if (2 == txrxmode) {	/* rx mode */
+			chn_num++;
+		}
+	} else if (PRU0_MODE == txrxmode) {
+		pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
+		offset = PRU_SUART_PRU0_IMR_OFFSET;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_IMR_OFFSET;
+		pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
+	} else {
+		return 0;
+	}
+	regval = 1 << chn_num;
+	if (CHN_TXRX_IE_MASK_CMPLT == (rmask & CHN_TXRX_IE_MASK_CMPLT))
+		pruss_rmww(dev, offset, regval, 0);
+
+	if ((rmask & SUART_GBL_INTR_ERR_MASK) == SUART_GBL_INTR_ERR_MASK)
+		pruss_rmww(dev, offset, SUART_GBL_INTR_ERR_MASK, 0);
+
+	offset = pru_offset +
+		(chn_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
+				+ PRU_SUART_CH_CONFIG1_OFFSET;
+
+	/* Framing Error Interrupt Masked */
+	if ((rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
+		regval = 0;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= ~(CHN_TXRX_IE_MASK_FE);
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+
+	/* Break Indicator Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_BI == (rmask & CHN_TXRX_IE_MASK_BI)) {
+		regval = 0;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= ~(CHN_TXRX_IE_MASK_BI);
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+
+	/* Timeout error Interrupt Masked */
+	if (CHN_TXRX_IE_MASK_TIMEOUT ==
+			(rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
+		regval = 0;
+		pruss_readb(dev, offset, (u8 *) &regval, 2);
+		regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
+		pruss_writeb(dev, offset, (u8 *) &regval, 2);
+	}
+
+	return 0;
+}
+
+s32 suart_intr_getmask(struct device *dev, u16 uart_num, u32 txrxmode,
+			u32 rmask)
+{
+	u16 chn_num;
+	u32 offset;
+	u16 txrx_flag;
+	u16 regval = 1;
+
+	chn_num = uart_num - 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 */
+		chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
+
+		if ((uart_num > 0) && (uart_num <= 4)) {
+
+			offset = PRU_SUART_PRU0_IMR_OFFSET;
+		} else if ((uart_num > 4) && (uart_num <= 8)) {
+			/* PRU1 */
+			offset = PRU_SUART_PRU1_IMR_OFFSET;
+			/* First 8 channel corresponds to PRU0 */
+			chn_num -= 8;
+		} else {
+			return -EINVAL;
+		}
+
+		if (2 == txrxmode) {	/* rx mode */
+			chn_num++;
+		}
+	} else if (PRU0_MODE == txrxmode) {
+		offset = PRU_SUART_PRU0_IMR_OFFSET;
+	} else if (PRU1_MODE == txrxmode) {
+		offset = PRU_SUART_PRU1_IMR_OFFSET;
+	} else {
+		return 0;
+	}
+	regval = regval << chn_num;
+	pruss_readb(dev, offset, (u8 *) &txrx_flag, 2);
+	txrx_flag &= regval;
+	if (0 == rmask) {
+		if (txrx_flag == 0)
+			return 1;
+	}
+	if (1 == rmask) {
+		if (txrx_flag == regval)
+			return 1;
+	}
+	return 0;
+}
diff --git a/drivers/tty/serial/pruss_suart_utils.c b/drivers/tty/serial/pruss_suart_utils.c
new file mode 100644
index 0000000..2bd6983
--- /dev/null
+++ b/drivers/tty/serial/pruss_suart_utils.c
@@ -0,0 +1,391 @@
+/*
+ * 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/mfd/da8xx/da8xx_pru.h>
+#include "pruss_suart.h"
+
+#define SUART_TRX_DIV_CONF_SZ	4
+
+static s16 suart_mcasp_tx_baud_set(u32 tx_baud_value,
+			struct pruss_suart_iomap *pruss_ioaddr);
+static s16 suart_mcasp_rx_baud_set(u32 rx_baud_value, u32 oversampling,
+			struct pruss_suart_iomap *pruss_ioaddr);
+
+/*
+ * 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_reset(struct pruss_suart_iomap *pruss_ioaddr)
+{
+	struct omapl_mcasp_regs_ovly *mcasp0_regs =
+		(struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
+	/* reset mcasp. */
+	__raw_writel(MCASP_SUART_GBLCTL, &mcasp0_regs->GBLCTL);
+	__raw_writel(MCASP_SUART_RGBLCTL, &mcasp0_regs->RGBLCTL);
+	__raw_writel(MCASP_SUART_XGBLCTL, &mcasp0_regs->XGBLCTL);
+	__raw_writel(MCASP_SUART_XSTAT, &mcasp0_regs->XSTAT);
+	__raw_writel(MCASP_SUART_RSTAT, &mcasp0_regs->RSTAT);
+}
+
+void suart_mcasp_config(u32 tx_baud_value,
+			u32 rx_baud_value,
+			u32 oversampling,
+			struct pruss_suart_iomap *pruss_ioaddr)
+{
+	struct omapl_mcasp_regs_ovly *mcasp0_regs =
+		(struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
+	u32 temp_reg;
+
+	/* reset mcasp */
+	__raw_writel(MCASP_SUART_GBLCTL, &mcasp0_regs->GBLCTL);
+	__raw_writel(MCASP_SUART_RGBLCTL, &mcasp0_regs->RGBLCTL);
+	__raw_writel(MCASP_SUART_XGBLCTL, &mcasp0_regs->XGBLCTL);
+
+	/* configure receive registers */
+	if ((SUART_8X_OVRSMPL == oversampling) || (0 == oversampling)) {
+		__raw_writel(MCASP_SUART_RMASK_8, &mcasp0_regs->RMASK);
+		__raw_writel(MCASP_SUART_RFMT_8, &mcasp0_regs->RFMT);
+	}
+	if (SUART_16X_OVRSMPL == oversampling) {
+		__raw_writel(MCASP_SUART_RMASK_16, &mcasp0_regs->RMASK);
+		__raw_writel(MCASP_SUART_RFMT_16, &mcasp0_regs->RFMT);
+
+	}
+
+	__raw_writel(MCASP_SUART_FSRM, &mcasp0_regs->AFSRCTL);
+	__raw_writel(MCASP_SUART_CLKRM_CLKRP, &mcasp0_regs->ACLKRCTL);
+	__raw_writel(MCASP_SUART_HCLKRP, &mcasp0_regs->AHCLKRCTL);
+	suart_mcasp_rx_baud_set(rx_baud_value, oversampling, pruss_ioaddr);
+	__raw_writel(MCASP_SUART_RTDMS0, &mcasp0_regs->RTDM);
+	__raw_writel(MCASP_SUART_RSYNCERR, &mcasp0_regs->RINTCTL);
+	__raw_writel(MCASP_SUART_RMAX_RPS_256, &mcasp0_regs->RCLKCHK);
+
+	/* configure transmit registers. */
+	__raw_writel(MCASP_SUART_XMASK_0_31, &mcasp0_regs->XMASK);
+	__raw_writel(MCASP_SUART_XBUSEL_XSSZ_16_XPAD_0, &mcasp0_regs->XFMT);
+	__raw_writel(MCASP_SUART_FSXM, &mcasp0_regs->AFSXCTL);
+	__raw_writel(MCASP_SUART_CLKXM_ASYNC_CLKXP, &mcasp0_regs->ACLKXCTL);
+	__raw_writel(MCASP_SUART_HCLKXM, &mcasp0_regs->AHCLKXCTL);
+
+	suart_mcasp_tx_baud_set(tx_baud_value, pruss_ioaddr);
+	__raw_writel(MCASP_SUART_XTDMS0, &mcasp0_regs->XTDM);
+	__raw_writel(MCASP_SUART_XSYNCERR, &mcasp0_regs->XINTCTL);
+	__raw_writel(MCASP_SUART_XMAX_XPS_256, &mcasp0_regs->XCLKCHK);
+
+	/* Serializer as a transmitter */
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL0);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL1);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL2);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL3);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL4);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL5);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL6);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL7);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL8);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL9);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL10);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL11);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL12);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL13);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL14);
+	__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL15);
+
+	/* 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 */
+	temp_reg = (OMAPL_MCASP_PFUNC_RESETVAL) |
+	    (1 << PRU_SUART0_CONFIG_TX_SER) | (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);
+	__raw_writel(temp_reg, &mcasp0_regs->PFUNC);
+
+	__raw_writel(0xFFF, &mcasp0_regs->PDOUT);
+
+	/* config pin function and direction */
+	__raw_writel(0x00000000, &mcasp0_regs->PDIR);
+	temp_reg =
+	    (1 << PRU_SUART0_CONFIG_TX_SER) | (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) |
+	    (MCASP_PDIR_VAL);
+	__raw_writel(temp_reg, &mcasp0_regs->PDIR);
+
+	__raw_writel(MCASP_SUART_DIT_DISABLE, &mcasp0_regs->DITCTL);
+	__raw_writel(MCASP_SUART_LOOPBACK_DISABLE, &mcasp0_regs->DLBCTL);
+	__raw_writel(MCASP_SUART_AMUTE_DISABLE, &mcasp0_regs->AMUTE);
+
+	__raw_writel(MCASP_SUART_XSTAT, &mcasp0_regs->XSTAT);
+	__raw_writel(MCASP_SUART_RSTAT, &mcasp0_regs->RSTAT);
+}
+
+void suart_mcasp_tx_serialzier_set(u32 serializer_num,
+		struct pruss_suart_iomap *pruss_ioaddr)
+{
+	struct omapl_mcasp_regs_ovly *mcasp0_regs =
+	    (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
+	u32 temp_reg;
+	temp_reg = mcasp0_regs->PFUNC | (0x1 << serializer_num);
+	__raw_writel(temp_reg, &mcasp0_regs->PFUNC);
+}
+
+/*
+ * mcasp TX buard rate setting routine
+ */
+s16 suart_mcasp_tx_baud_set(u32 tx_baud_value,
+		struct pruss_suart_iomap *pruss_ioaddr)
+{
+	u32 clk_div_val;
+	u32 loop_cnt;
+	s16 status = 0;
+	s16 found_val = false;
+
+	struct omapl_mcasp_regs_ovly *mcasp0_regs =
+	    (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
+	u32 temp_reg;
+
+	/* Search the supported baud rate in the table */
+	for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+							loop_cnt++) {
+		if (tx_baud_value == lt_tx_baud_rate[loop_cnt][0]) {
+			found_val = true;
+			break;
+		}
+	}
+	if (found_val == true) {
+		clk_div_val = lt_tx_baud_rate[loop_cnt][2];
+		temp_reg = mcasp0_regs->ACLKXCTL |
+			clk_div_val << OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
+		__raw_writel(temp_reg, &mcasp0_regs->ACLKXCTL);
+		clk_div_val = lt_tx_baud_rate[loop_cnt][3];
+		temp_reg = mcasp0_regs->AHCLKXCTL |
+			clk_div_val << OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
+		__raw_writel(temp_reg, &mcasp0_regs->AHCLKXCTL);
+	} else {
+		return -EINVAL ;
+	}
+	return status;
+}
+
+/*
+ * mcasp RX buard rate setting routine
+ */
+s16 suart_mcasp_rx_baud_set(u32 rx_baud_value,
+	u32 oversampling, struct pruss_suart_iomap *pruss_ioaddr)
+{
+	u32 clk_div_val;
+	u32 loop_cnt;
+	s16 status = 0;
+	s16 found_val = false;
+
+	struct omapl_mcasp_regs_ovly *mcasp0_regs =
+	    (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
+	u32 temp_reg;
+
+	if (oversampling == SUART_8X_OVRSMPL) {
+		for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+		     loop_cnt++) {
+			if (rx_baud_value == lt_rx_8x_baud_rate[loop_cnt][0]) {
+				clk_div_val = lt_rx_8x_baud_rate[loop_cnt][2];
+				temp_reg = mcasp0_regs->ACLKRCTL | (clk_div_val
+					<< OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
+
+				__raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
+
+				clk_div_val =
+				lt_rx_8x_baud_rate[loop_cnt][3] - 1;
+
+				temp_reg = mcasp0_regs->AHCLKRCTL | (clk_div_val
+				<< OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
+
+				__raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
+
+				found_val = true;
+				break;
+			}
+		}
+	} else if (oversampling == SUART_16X_OVRSMPL) {
+		for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+		     loop_cnt++) {
+			if (rx_baud_value == lt_rx_16x_baud_rate[loop_cnt][0]) {
+				clk_div_val = lt_rx_16x_baud_rate[loop_cnt][2];
+				temp_reg =
+					mcasp0_regs->ACLKRCTL | (clk_div_val <<
+					OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
+				__raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
+				clk_div_val = lt_rx_16x_baud_rate[loop_cnt][3];
+				temp_reg =
+				mcasp0_regs->AHCLKRCTL | (clk_div_val <<
+				OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
+				__raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
+				found_val = true;
+				break;
+			}
+		}
+	} else if (oversampling == 0) {
+		for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
+		     loop_cnt++) {
+			if (rx_baud_value == lt_tx_baud_rate[loop_cnt][0]) {
+				clk_div_val = lt_tx_baud_rate[loop_cnt][2];
+				temp_reg =
+				mcasp0_regs->ACLKRCTL | (clk_div_val <<
+				OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
+				__raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
+				clk_div_val = lt_tx_baud_rate[loop_cnt][3];
+				temp_reg =
+				mcasp0_regs->AHCLKRCTL | (clk_div_val <<
+				OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
+				__raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
+				found_val = true;
+				break;
+			}
+		}
+	} else {
+		return -EINVAL ;
+	}
+
+	if (found_val != true)
+		return -EINVAL ;
+
+	return status;
+}
+
+/*
+ * mcasp buard rate setting routine
+ */
+s16 suart_asp_baud_set(u32 tx_baud_value, u32 rx_baud_value, u32 oversampling,
+					struct pruss_suart_iomap *pruss_ioaddr)
+{
+	s16 status = 0;
+
+	status = suart_mcasp_tx_baud_set(tx_baud_value, pruss_ioaddr);
+	status = suart_mcasp_rx_baud_set(rx_baud_value, oversampling,
+					pruss_ioaddr);
+
+	return status;
+}
+
+/*
+ * mcasp deactivate the selected serializer
+ */
+s16 suart_asp_serializer_deactivate(u16 sr_num,
+		struct pruss_suart_iomap *pruss_ioaddr)
+{
+	s16 status = 0;
+	struct omapl_mcasp_regs_ovly *mcasp0_regs =
+		 (struct omapl_mcasp_regs_ovly *)pruss_ioaddr->mcasp_io_addr;
+	if (sr_num > 15)
+		status = -EINVAL;
+	else
+		__raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL0);
+
+	return status;
+}
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 758c5b0..eae37fe 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -202,6 +202,8 @@
 /* VIA VT8500 SoC */
 #define PORT_VT8500	97
 
+#define PORT_DA8XX_PRU_SUART	98
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 2/7] da850: pruss platform specific additions.
  2011-03-08 13:57 ` [PATCH v3 2/7] da850: pruss platform specific additions Subhasish Ghosh
@ 2011-03-08 15:17   ` Sergei Shtylyov
  0 siblings, 0 replies; 31+ messages in thread
From: Sergei Shtylyov @ 2011-03-08 15:17 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: davinci-linux-open-source, linux-arm-kernel, m-watkins, nsekhar,
	sachi,
	Kevin Hilman (supporter:TI DAVINCI
	MACHIN...,commit_signer:16/18=89%),
	Russell King (maintainer:ARM PORT),
	Michael Williamson (commit_signer:5/18=28%),
	Sergei Shtylyov (commit_signer:3/18=17%),
	Cyril Chemparathy (commit_signer:3/18=17%),
	open list

Hello.

On 08.03.2011 16:57, Subhasish Ghosh wrote:

> This patch adds the platform device and assignes the platform resources
> for the PRUSS mfd driver.

    It also adds the PRUSS clock (which I'd have done in a sperate patch). I 
think I've already said that though...

> Signed-off-by: Subhasish Ghosh<subhasish@mistralsolutions.com>

WBR, Sergei

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 3/7] da850: pruss board specific additions.
  2011-03-08 13:57 ` [PATCH v3 3/7] da850: pruss board " Subhasish Ghosh
@ 2011-03-08 15:19   ` Sergei Shtylyov
  2011-03-09  4:29     ` Subhasish Ghosh
  2011-03-09 11:59   ` Marc Kleine-Budde
  1 sibling, 1 reply; 31+ messages in thread
From: Sergei Shtylyov @ 2011-03-08 15:19 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: davinci-linux-open-source, sachi, Russell King, open list,
	m-watkins, linux-arm-kernel

Hello.

On 08-03-2011 16:57, Subhasish Ghosh wrote:

> This patch adds board specific initializations and setup routines.

> Signed-off-by: Subhasish Ghosh<subhasish@mistralsolutions.com>
[...]

> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index 11f986b..c614c82 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1053,6 +1053,26 @@ static __init int da850_evm_init_cpufreq(void)
>   static __init int da850_evm_init_cpufreq(void) { return 0; }
>   #endif
>
> +static struct da8xx_pruss_devices pruss_devices[] = {
> +	{.dev_name = NULL,},

    No need to explictly intialize to NULL.

WBR, Sergei

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 7/7] tty: add pruss SUART driver
  2011-03-08 13:57 ` [PATCH v3 7/7] tty: add pruss SUART driver Subhasish Ghosh
@ 2011-03-08 18:47   ` Randy Dunlap
  2011-03-15  7:23     ` Subhasish Ghosh
  2011-03-18  5:43   ` Subhasish Ghosh
  1 sibling, 1 reply; 31+ messages in thread
From: Randy Dunlap @ 2011-03-08 18:47 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: davinci-linux-open-source, linux-arm-kernel, m-watkins, nsekhar,
	sachi, maintainer:TTY LAYER <gregkh@suse.de>,
	commit_signer:2/4=50%, commit_signer:1/2=50%,
	Andrew Morton, Randy Dunlap, open list

On Tue,  8 Mar 2011 19:27:46 +0530 Subhasish Ghosh wrote:

> This patch adds support for the TTY compliant
> Soft-UART device emulated on PRUSS.
> 
> This patch depends on:
> davinci: macro rename DA8XX_LPSC0_DMAX to DA8XX_LPSC0_PRUSS.
> 		https://patchwork.kernel.org/patch/615681/
> davinci: changed SRAM allocator to shared ram.
> 		https://patchwork.kernel.org/patch/549351/
> 
> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
> ---
>  drivers/tty/serial/Kconfig             |   22 +
>  drivers/tty/serial/Makefile            |   10 +
>  drivers/tty/serial/pruss_suart.c       | 1058 +++++++++++++++++++
>  drivers/tty/serial/pruss_suart.h       | 1081 ++++++++++++++++++++
>  drivers/tty/serial/pruss_suart_api.c   | 1757 ++++++++++++++++++++++++++++++++
>  drivers/tty/serial/pruss_suart_utils.c |  391 +++++++
>  include/linux/serial_core.h            |    2 +
>  7 files changed, 4321 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/tty/serial/pruss_suart.c
>  create mode 100644 drivers/tty/serial/pruss_suart.h
>  create mode 100644 drivers/tty/serial/pruss_suart_api.c
>  create mode 100644 drivers/tty/serial/pruss_suart_utils.c
> 
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 2b83346..14ea0a3 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1596,4 +1596,26 @@ config SERIAL_PCH_UART
>  	  This driver is for PCH(Platform controller Hub) UART of Intel EG20T
>  	  which is an IOH(Input/Output Hub) for x86 embedded processor.
>  	  Enabling PCH_DMA, this PCH UART works as DMA mode.
> +
> +#
> +# SUART Kernel Configuration
> +#
> +
> +config SERIAL_PRUSS_SUART
> +	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
> +	select SERIAL_CORE
> +	tristate "PRUSS based SoftUART emulation on DA8XX"
> +	---help---
> +	This driver emulates upto eight different UARTs on the PRUSS.

	                     up to

> +	You may modify the NR_SUARTS macro in the driver to emulate
> +	less number of UARTS as per your requirement.
> +	If not sure, mark N

	             mark N.

> +
> +config PRUSS_SUART_MCASP
> +    int "McASP number"
> +    depends on ARCH_DAVINCI && ARCH_DAVINCI_DA830 && SERIAL_PRUSS_SUART
> +    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.

The 2 help text lines should be indented the same.

>  endmenu


---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 3/7] da850: pruss board specific additions.
  2011-03-08 15:19   ` Sergei Shtylyov
@ 2011-03-09  4:29     ` Subhasish Ghosh
  0 siblings, 0 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-09  4:29 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: davinci-linux-open-source, sachi, Russell King, open list,
	m-watkins, linux-arm-kernel

Hello,

If I don't initialize it to NULL, its getting initialized to some garbage 
string.

--------------------------------------------------
From: "Sergei Shtylyov" <sshtylyov@mvista.com>
Sent: Tuesday, March 08, 2011 8:49 PM
To: "Subhasish Ghosh" <subhasish@mistralsolutions.com>
Cc: <davinci-linux-open-source@linux.davincidsp.com>; 
<sachi@mistralsolutions.com>; "Russell King" <linux@arm.linux.org.uk>; "open 
list" <linux-kernel@vger.kernel.org>; <m-watkins@ti.com>; 
<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v3 3/7] da850: pruss board specific additions.

> Hello.
>
> On 08-03-2011 16:57, Subhasish Ghosh wrote:
>
>> This patch adds board specific initializations and setup routines.
>
>> Signed-off-by: Subhasish Ghosh<subhasish@mistralsolutions.com>
> [...]
>
>> diff --git a/arch/arm/mach-davinci/board-da850-evm.c 
>> b/arch/arm/mach-davinci/board-da850-evm.c
>> index 11f986b..c614c82 100644
>> --- a/arch/arm/mach-davinci/board-da850-evm.c
>> +++ b/arch/arm/mach-davinci/board-da850-evm.c
>> @@ -1053,6 +1053,26 @@ static __init int da850_evm_init_cpufreq(void)
>>   static __init int da850_evm_init_cpufreq(void) { return 0; }
>>   #endif
>>
>> +static struct da8xx_pruss_devices pruss_devices[] = {
>> + {.dev_name = NULL,},
>
>    No need to explictly intialize to NULL.
>
> WBR, Sergei 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-08 13:57 ` [PATCH v3 1/7] mfd: add pruss mfd driver Subhasish Ghosh
@ 2011-03-09 11:56   ` Marc Kleine-Budde
  2011-03-24 13:16     ` Subhasish Ghosh
  2011-03-11 15:28   ` Arnd Bergmann
  2011-03-18 11:59   ` Nori, Sekhar
  2 siblings, 1 reply; 31+ messages in thread
From: Marc Kleine-Budde @ 2011-03-09 11:56 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: davinci-linux-open-source, sachi, Samuel Ortiz, nsekhar,
	open list, m-watkins, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 32479 bytes --]

On 03/08/2011 02:57 PM, Subhasish Ghosh wrote:
> This patch adds the pruss MFD driver and associated include files.
> For details regarding the PRUSS please refer the folowing link:
> http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem
> 
> The rational behind the MFD driver being the fact that multiple devices can
> be implemented on the cores independently. This is determined by the nature
> of the program which is loaded into the PRU's instruction memory.
> A device may be de-initialized and another loaded or two different devices
> can be run simultaneously on the two cores.
> It's also possible, as in our case, to implement a single device on both
> the PRU's resulting in improved load sharing.

Make you driver compile with sparse "make C=1", you cast way too much
when accessing io mem. Use void __iomem * instead of u32 *.

See more comments inline.

> 
> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
> ---
>  drivers/mfd/Kconfig                     |   10 +
>  drivers/mfd/Makefile                    |    1 +
>  drivers/mfd/da8xx_pru.c                 |  560 +++++++++++++++++++++++++++++++
>  include/linux/mfd/da8xx/da8xx_pru.h     |  135 ++++++++
>  include/linux/mfd/da8xx/da8xx_prucore.h |  129 +++++++
>  5 files changed, 835 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mfd/da8xx_pru.c
>  create mode 100644 include/linux/mfd/da8xx/da8xx_pru.h
>  create mode 100644 include/linux/mfd/da8xx/da8xx_prucore.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index fd01836..6c437df 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -81,6 +81,16 @@ config MFD_DM355EVM_MSP
>  	  boards.  MSP430 firmware manages resets and power sequencing,
>  	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
>  
> +config MFD_DA8XX_PRUSS
> +	tristate "Texas Instruments DA8XX PRUSS support"
> +	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
> +	select MFD_CORE
> +	help
> +	  This driver provides support api's for the programmable
> +	  realtime unit (PRU) present on TI's da8xx processors. It
> +	  provides basic read, write, config, enable, disable
> +	  routines to facilitate devices emulated on it.
> +
>  config HTC_EGPIO
>  	bool "HTC EGPIO support"
>  	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index a54e2c7..670d6b0 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
>  obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
>  
>  obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
> +obj-$(CONFIG_MFD_DA8XX_PRUSS)	+= da8xx_pru.o
>  obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
>  
>  obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
> diff --git a/drivers/mfd/da8xx_pru.c b/drivers/mfd/da8xx_pru.c
> new file mode 100644
> index 0000000..0fd9bb2
> --- /dev/null
> +++ b/drivers/mfd/da8xx_pru.c
> @@ -0,0 +1,560 @@
> +/*
> + * Copyright (C) 2011 Texas Instruments Incorporated
> + *
> + * 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/init.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/bitops.h>
> +#include <linux/interrupt.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mfd/da8xx/da8xx_prucore.h>
> +#include <linux/mfd/da8xx/da8xx_pru.h>
> +#include <linux/mfd/core.h>
> +#include <linux/io.h>
> +#include <mach/da8xx.h>
> +
> +struct da8xx_pruss {
> +	struct device *dev;
> +	spinlock_t lock;
> +	struct resource *res;
> +	struct clk *clk;
> +	u32 clk_freq;
> +	void __iomem *ioaddr;
> +};
> +
> +u32 pruss_get_clk_freq(struct device *dev)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +
> +	return pruss->clk_freq;
> +}
> +EXPORT_SYMBOL(pruss_get_clk_freq);
> +
> +s32 pruss_disable(struct device *dev, u8 pruss_num)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct da8xx_prusscore_regs *h_pruss;
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +	u32 temp_reg;
> +	u32 delay_cnt;
> +
> +	if ((pruss_num != DA8XX_PRUCORE_0) && (pruss_num != DA8XX_PRUCORE_1))
> +		return -EINVAL;
> +
> +	spin_lock(&pruss->lock);
> +	if (pruss_num == DA8XX_PRUCORE_0) {
> +		/* pruss deinit */
> +		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT0 & 0xFFFF));
> +		/* Disable PRU0  */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_0];
> +
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +		__raw_writel(temp_reg, &h_pruss->CONTROL);
> +
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
> +
> +			temp_reg = __raw_readl(&h_pruss->CONTROL);
> +			temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +			__raw_writel(temp_reg, &h_pruss->CONTROL);
> +		}
> +
> +		/* Reset PRU0 */
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
> +			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +					&h_pruss->CONTROL);
> +
> +	} else if (pruss_num == DA8XX_PRUCORE_1) {
> +		/* pruss deinit */
> +		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT1 & 0xFFFF));
> +		/* Disable PRU1 */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_1];
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +		__raw_writel(temp_reg, &h_pruss->CONTROL);
> +
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
> +
> +			temp_reg = __raw_readl(&h_pruss->CONTROL);
> +			temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +			__raw_writel(temp_reg, &h_pruss->CONTROL);
> +		}
> +
> +		/* Reset PRU1 */
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
> +			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +							&h_pruss->CONTROL);
> +	}

unneeded code duplication

> +	spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_disable);
> +
> +s32 pruss_enable(struct device *dev, u8 pruss_num)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct da8xx_prusscore_regs *h_pruss;
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +
> +	if ((pruss_num != DA8XX_PRUCORE_0) && (pruss_num != DA8XX_PRUCORE_1))
> +		return -EINVAL;
> +
> +	spin_lock(&pruss->lock);

just use pruss_num in &pruss_mmap->core[DA8XX_PRUCORE_0], then remove
the "if..else if"

> +	if (pruss_num == DA8XX_PRUCORE_0) {
> +		/* Reset PRU0 */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_0];
> +		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +			&h_pruss->CONTROL);
> +	} else if (pruss_num == DA8XX_PRUCORE_1) {
> +		/* Reset PRU1  */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_1];
> +		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +			&h_pruss->CONTROL);
> +	}
> +	spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_enable);
> +
> +/* Load the specified PRU with code */
> +s32 pruss_load(struct device *dev, u8 pruss_num,
> +			u32 *pruss_code, u32 code_size_in_words)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +	u32 *pruss_iram;
> +	u32 i;
> +
> +	if (pruss_num == DA8XX_PRUCORE_0)
> +		pruss_iram = (u32 *)&pruss_mmap->iram0;
> +	else if (pruss_num == DA8XX_PRUCORE_1)
> +		pruss_iram = (u32 *)&pruss_mmap->iram1;

u32 * looks fishy, should be probavly a void __iomem
also make pruss_mmap->iram0,1 an array

> +	else
> +		return -EINVAL;
> +
> +	pruss_enable(dev, pruss_num);
> +
> +	spin_lock(&pruss->lock);
> +	/* Copy dMAX code to its instruction RAM  */
> +	for (i = 0; i < code_size_in_words; i++)
> +		__raw_writel(pruss_code[i], (pruss_iram + i));
> +
> +	spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_load);
> +
> +s32 pruss_run(struct device *dev, u8 pruss_num)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct da8xx_prusscore_regs *h_pruss;
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +	u32 temp_reg;
> +
> +	if (pruss_num == DA8XX_PRUCORE_0) {
> +		/* DA8XX_PRUCORE_0_REGS; */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_0];
> +	} else if (pruss_num == DA8XX_PRUCORE_1) {
> +		/* DA8XX_PRUCORE_1_REGS; */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_1];

if you first check if pruss_num is correct, then you can just use
pruss_num in "pruss_mmap->core[DA8XX_PRUCORE_1]"

> +	} else
> +		return -EINVAL;
> +
> +	/* Enable dMAX, let it execute the code we just copied */

is it possible to use the _rmw function you defined later?

> +	spin_lock(&pruss->lock);
> +	temp_reg = __raw_readl(&h_pruss->CONTROL);
> +	temp_reg = (temp_reg &
> +			~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +			((DA8XX_PRUCORE_CONTROL_COUNTENABLE_ENABLE <<
> +			DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +			DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +	__raw_writel(temp_reg, &h_pruss->CONTROL);
> +
> +	temp_reg = __raw_readl(&h_pruss->CONTROL);
> +	temp_reg = (temp_reg &
> +			~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +			((DA8XX_PRUCORE_CONTROL_ENABLE_ENABLE <<
> +			DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +			DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +	__raw_writel(temp_reg, &h_pruss->CONTROL);
> +	 spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_run);
> +
> +s32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct da8xx_prusscore_regs *h_pruss;
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +	u32 temp_reg;
> +	u32 cnt = timeout;
> +
> +	if (pruss_num == DA8XX_PRUCORE_0) {
> +		/* DA8XX_PRUCORE_0_REGS; */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_0];
> +	} else if (pruss_num == DA8XX_PRUCORE_1) {
> +		/* DA8XX_PRUCORE_1_REGS; */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_1];

dito

> +	} else
> +		return -EINVAL;
> +
> +	while (cnt--) {
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		if (((temp_reg & DA8XX_PRUCORE_CONTROL_RUNSTATE_MASK) >>
> +				DA8XX_PRUCORE_CONTROL_RUNSTATE_SHIFT) ==
> +					DA8XX_PRUCORE_CONTROL_RUNSTATE_HALT)
> +			break;
> +	}
> +	if (cnt == 0)
> +		return -EBUSY;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_wait_for_halt);
> +
> +s32 pruss_writeb(struct device *dev, u32 offset,
> +		u8 *pdatatowrite, u16 bytestowrite)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u8 *paddresstowrite;
> +	u16 loop;
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstowrite = (u8 *) (offset);

Why all this casing? Checck your driver with sparse, please compile your
driver with "make C=1".

> +
> +	for (loop = 0; loop < bytestowrite; loop++)
> +		__raw_writeb(*pdatatowrite++, paddresstowrite++);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_writeb);
> +
> +s32 pruss_rmwb(struct device *dev, u32 offset, u8 mask, u8 val)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddress;
> +	u32 preg_data;
> +
> +	paddress = (u32 *)((u32)pruss->ioaddr + offset);
same here
> +
> +	spin_lock(&pruss->lock);
> +	preg_data = __raw_readb(paddress);
> +	preg_data &= ~mask;
> +	preg_data |= val;
> +	__raw_writeb(preg_data, paddress);
> +	spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_rmwb);
> +
> +s32 pruss_readb(struct device *dev, u32 offset,
> +		u8 *pdatatoread, u16 bytestoread)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u8 *paddresstoread;
> +	u16 loop;
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstoread = (u8 *) (offset);
same here
> +
> +	for (loop = 0; loop < bytestoread; loop++)
> +		*pdatatoread++ = __raw_readb(paddresstoread++);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_readb);
> +
> +s32 pruss_writel(struct device *dev, u32 offset,
> +		u32 *pdatatowrite, s16 wordstowrite)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddresstowrite;
> +	s16 loop;
> +
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstowrite = (u32 *)(offset);
dito
> +
> +	for (loop = 0; loop < wordstowrite; loop++)
> +		__raw_writel(*pdatatowrite++, paddresstowrite++);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_writel);
> +
> +s32 pruss_rmwl(struct device *dev, u32 offset, u32 mask, u32 val)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddress;
> +	u32 preg_data;
> +
> +	paddress = (u32 *)((u32)pruss->ioaddr + offset);
dito
> +
> +	spin_lock(&pruss->lock);
> +	preg_data = __raw_readl(paddress);
> +	preg_data &= ~mask;
> +	preg_data |= val;
> +	__raw_writel(preg_data, paddress);
> +	spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_rmwl);
> +
> +s32 pruss_readl(struct device *dev, u32 offset,
> +		u32 *pdatatoread, s16 wordstoread)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddresstoread;
> +	s16 loop;
> +
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstoread = (u32 *)(offset);

dito

> +
> +	for (loop = 0; loop < wordstoread; loop++)
> +		*pdatatoread++ = __raw_readl(paddresstoread++);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_readl);
> +
> +s32 pruss_writew(struct device *dev, u32 offset,
> +		u16 *pdatatowrite, s16 wordstowrite)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddresstowrite;
> +	s16 loop;
> +
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstowrite = (u32 *)(offset);

dito

> +
> +	for (loop = 0; loop < wordstowrite; loop++)
> +		__raw_writew(*(pdatatowrite++), (paddresstowrite++));
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_writew);
> +
> +s32 pruss_rmww(struct device *dev, u32 offset, u16 mask, u16 val)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddress;
> +	u32 preg_data;
> +
> +	paddress = (u32 *)((u32)pruss->ioaddr + offset);

dito

> +
> +	spin_lock(&pruss->lock);
> +	preg_data = __raw_readw(paddress);
> +	preg_data &= ~mask;
> +	preg_data |= val;
> +	__raw_writew(preg_data, paddress);
> +	spin_unlock(&pruss->lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_rmww);
> +
> +s32 pruss_readw(struct device *dev, u32 offset,
> +			u16 *pdatatoread, s16 wordstoread)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddresstoread;
> +	s16 loop;
> +
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstoread = (u32 *)(offset);
> +

dito

> +	for (loop = 0; loop < wordstoread; loop++)
use "i" as loop variable
> +		*pdatatoread++ = __raw_readw(paddresstoread++);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_readw);
> +
> +s32 pruss_idx_writel(struct device *dev, u32 offset, u32 value)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u32 *paddresstowrite;
> +
> +	paddresstowrite = (u32 *)(pruss->ioaddr + offset);

dito
> +	__raw_writel(value, paddresstowrite);



> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_idx_writel);
> +
> +static int pruss_mfd_add_devices(struct platform_device *pdev)
> +{
> +	struct da8xx_pruss_devices *dev_data = pdev->dev.platform_data;
> +	struct device *dev = &pdev->dev;
> +	struct mfd_cell cell;
> +	u32 err, count;
> +
> +	for (count = 0; dev_data[count].dev_name != NULL; count++) {

nitpick:
we usually use "i" as counter variable

> +		memset(&cell, 0, sizeof(struct mfd_cell));
> +		cell.id			= count;
> +		cell.name		= dev_data[count].dev_name;
> +		cell.platform_data	= dev_data[count].pdata;
> +		cell.data_size		= dev_data[count].pdata_size;
> +		cell.resources		= dev_data[count].resources;
> +		cell.num_resources	= dev_data[count].num_resources;
> +
> +		err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
> +		if (err) {
> +			dev_err(dev, "cannot add mfd cells\n");
> +			return err;

you forget to clean up already registered mfd devices. I suggest to
rearrange your code so that you can use mfd_add_devices() to register
all of your devices at once.

> +		}
> +		dev_info(dev, "mfd: added %s device\n",
> +				dev_data[count].dev_name);
> +	}
> +
> +	return err;
> +}
> +
> +static int __devinit da8xx_pruss_probe(struct platform_device *pdev)
> +{
> +	struct da8xx_pruss *pruss_dev = NULL;
> +	u32 err;
> +
> +	pruss_dev = kzalloc(sizeof(struct da8xx_pruss), GFP_KERNEL);
> +	if (!pruss_dev)
> +		return -ENOMEM;
> +
> +	pruss_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!pruss_dev->res) {
> +		dev_err(&pdev->dev,
> +		"unable to get pruss memory resources!\n");
> +		err = -ENODEV;
> +		goto probe_exit_kfree;
> +	}
> +
> +	if (!request_mem_region(pruss_dev->res->start,
> +		resource_size(pruss_dev->res), dev_name(&pdev->dev))) {
> +		dev_err(&pdev->dev, "pruss memory region already claimed!\n");
> +		err = -EBUSY;
> +		goto probe_exit_kfree;
> +	}
> +
> +	pruss_dev->ioaddr = ioremap(pruss_dev->res->start,
> +	resource_size(pruss_dev->res));
> +	if (!pruss_dev->ioaddr) {
> +		dev_err(&pdev->dev, "ioremap failed\n");
> +		err = -ENOMEM;
> +		goto probe_exit_free_region;
> +	}
> +
> +	pruss_dev->clk = clk_get(NULL, "pruss");
> +	if (IS_ERR(pruss_dev->clk)) {
> +		dev_err(&pdev->dev, "no clock available: pruss\n");
> +		err = -ENODEV;
> +		pruss_dev->clk = NULL;
> +		goto probe_exit_iounmap;c
> +	}
> +	spin_lock_init(&pruss_dev->lock);
> +
> +	clk_enable(pruss_dev->clk);
> +	pruss_dev->clk_freq = clk_get_rate(pruss_dev->clk);

pruss_dev->clk_freq in an u32, but clk_get_rate returns an unsigned long

> +
> +	err = pruss_mfd_add_devices(pdev);
> +	if (err)
> +		goto probe_exit_clock;
> +
> +	platform_set_drvdata(pdev, pruss_dev);
> +	pruss_dev->dev = &pdev->dev;
> +	return 0;
> +
> +probe_exit_clock:
> +	clk_put(pruss_dev->clk);
> +	clk_disable(pruss_dev->clk);
> +probe_exit_iounmap:
> +	iounmap(pruss_dev->ioaddr);
> +probe_exit_free_region:
> +	release_mem_region(pruss_dev->res->start,
> +			resource_size(pruss_dev->res));
> +probe_exit_kfree:
> +	kfree(pruss_dev);
> +	return err;
> +}
> +
> +static int __devexit da8xx_pruss_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev);
> +
> +	mfd_remove_devices(dev);
> +	pruss_disable(dev, DA8XX_PRUCORE_0);
> +	pruss_disable(dev, DA8XX_PRUCORE_1);
> +	clk_disable(pruss->clk);
> +	clk_put(pruss->clk);
> +	iounmap(pruss->ioaddr);
> +	release_mem_region(pruss->res->start, resource_size(pruss->res));
> +	kfree(pruss);
> +	dev_set_drvdata(dev, NULL);
> +	return 0;
> +}
> +
> +static struct platform_driver da8xx_pruss_driver = {
> +	.probe	= da8xx_pruss_probe,
> +	.remove	= __devexit_p(da8xx_pruss_remove),
> +	.driver	= {
> +		.name	= "pruss_mfd",
> +		.owner	= THIS_MODULE,
> +	}
> +};
> +
> +static int __init da8xx_pruss_init(void)
> +{
> +	return platform_driver_register(&da8xx_pruss_driver);
> +}
> +module_init(da8xx_pruss_init);
> +
> +static void __exit da8xx_pruss_exit(void)
> +{
> +	platform_driver_unregister(&da8xx_pruss_driver);
> +}
> +module_exit(da8xx_pruss_exit);
> +
> +MODULE_DESCRIPTION("Programmable Realtime Unit (PRU) Driver");
> +MODULE_AUTHOR("Subhasish Ghosh");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/da8xx/da8xx_pru.h b/include/linux/mfd/da8xx/da8xx_pru.h
> new file mode 100644
> index 0000000..ba65ec0
> --- /dev/null
> +++ b/include/linux/mfd/da8xx/da8xx_pru.h
> @@ -0,0 +1,135 @@
> +/*
> + * 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 _PRUSS_H_
> +#define _PRUSS_H_
> +
> +#include <linux/types.h>
> +#include <linux/platform_device.h>
> +#include "da8xx_prucore.h"
> +
> +#define PRUSS_NUM0			DA8XX_PRUCORE_0
> +#define PRUSS_NUM1			DA8XX_PRUCORE_1
> +
> +#define PRUSS_PRU0_BASE_ADDRESS		0
> +#define PRUSS_INTC_BASE_ADDRESS		(PRUSS_PRU0_BASE_ADDRESS + 0x4000)
> +#define PRUSS_INTC_GLBLEN		(PRUSS_INTC_BASE_ADDRESS + 0x10)
> +#define PRUSS_INTC_GLBLNSTLVL		(PRUSS_INTC_BASE_ADDRESS + 0x1C)
> +#define PRUSS_INTC_STATIDXSET		(PRUSS_INTC_BASE_ADDRESS + 0x20)
> +#define PRUSS_INTC_STATIDXCLR		(PRUSS_INTC_BASE_ADDRESS + 0x24)
> +#define PRUSS_INTC_ENIDXSET		(PRUSS_INTC_BASE_ADDRESS + 0x28)
> +#define PRUSS_INTC_ENIDXCLR		(PRUSS_INTC_BASE_ADDRESS + 0x2C)
> +#define PRUSS_INTC_HSTINTENIDXSET	(PRUSS_INTC_BASE_ADDRESS + 0x34)
> +#define PRUSS_INTC_HSTINTENIDXCLR	(PRUSS_INTC_BASE_ADDRESS + 0x38)
> +#define PRUSS_INTC_GLBLPRIIDX		(PRUSS_INTC_BASE_ADDRESS + 0x80)
> +#define PRUSS_INTC_STATSETINT0		(PRUSS_INTC_BASE_ADDRESS + 0x200)
> +#define PRUSS_INTC_STATSETINT1		(PRUSS_INTC_BASE_ADDRESS + 0x204)
> +#define PRUSS_INTC_STATCLRINT0		(PRUSS_INTC_BASE_ADDRESS + 0x280)
> +#define PRUSS_INTC_STATCLRINT1		(PRUSS_INTC_BASE_ADDRESS + 0x284)
> +#define PRUSS_INTC_ENABLESET0		(PRUSS_INTC_BASE_ADDRESS + 0x300)
> +#define PRUSS_INTC_ENABLESET1		(PRUSS_INTC_BASE_ADDRESS + 0x304)
> +#define PRUSS_INTC_ENABLECLR0		(PRUSS_INTC_BASE_ADDRESS + 0x380)
> +#define PRUSS_INTC_ENABLECLR1		(PRUSS_INTC_BASE_ADDRESS + 0x384)
> +#define PRUSS_INTC_CHANMAP0		(PRUSS_INTC_BASE_ADDRESS + 0x400)
> +#define PRUSS_INTC_CHANMAP1		(PRUSS_INTC_BASE_ADDRESS + 0x404)
> +#define PRUSS_INTC_CHANMAP2		(PRUSS_INTC_BASE_ADDRESS + 0x408)
> +#define PRUSS_INTC_CHANMAP3		(PRUSS_INTC_BASE_ADDRESS + 0x40C)
> +#define PRUSS_INTC_CHANMAP4		(PRUSS_INTC_BASE_ADDRESS + 0x410)
> +#define PRUSS_INTC_CHANMAP5		(PRUSS_INTC_BASE_ADDRESS + 0x414)
> +#define PRUSS_INTC_CHANMAP6		(PRUSS_INTC_BASE_ADDRESS + 0x418)
> +#define PRUSS_INTC_CHANMAP7		(PRUSS_INTC_BASE_ADDRESS + 0x41C)
> +#define PRUSS_INTC_CHANMAP8		(PRUSS_INTC_BASE_ADDRESS + 0x420)
> +#define PRUSS_INTC_CHANMAP9		(PRUSS_INTC_BASE_ADDRESS + 0x424)
> +#define PRUSS_INTC_CHANMAP10		(PRUSS_INTC_BASE_ADDRESS + 0x428)
> +#define PRUSS_INTC_CHANMAP11		(PRUSS_INTC_BASE_ADDRESS + 0x42C)
> +#define PRUSS_INTC_CHANMAP12		(PRUSS_INTC_BASE_ADDRESS + 0x430)
> +#define PRUSS_INTC_CHANMAP13		(PRUSS_INTC_BASE_ADDRESS + 0x434)
> +#define PRUSS_INTC_CHANMAP14		(PRUSS_INTC_BASE_ADDRESS + 0x438)
> +#define PRUSS_INTC_CHANMAP15		(PRUSS_INTC_BASE_ADDRESS + 0x43C)
> +#define PRUSS_INTC_HOSTMAP0		(PRUSS_INTC_BASE_ADDRESS + 0x800)
> +#define PRUSS_INTC_HOSTMAP1		(PRUSS_INTC_BASE_ADDRESS + 0x804)
> +#define PRUSS_INTC_HOSTMAP2		(PRUSS_INTC_BASE_ADDRESS + 0x808)
> +#define PRUSS_INTC_POLARITY0		(PRUSS_INTC_BASE_ADDRESS + 0xD00)
> +#define PRUSS_INTC_POLARITY1		(PRUSS_INTC_BASE_ADDRESS + 0xD04)
> +#define PRUSS_INTC_TYPE0		(PRUSS_INTC_BASE_ADDRESS + 0xD80)
> +#define PRUSS_INTC_TYPE1		(PRUSS_INTC_BASE_ADDRESS + 0xD84)
> +#define PRUSS_INTC_HOSTINTEN		(PRUSS_INTC_BASE_ADDRESS + 0x1500)
> +#define PRUSS_INTC_HOSTINTLVL_MAX	9
> +
> +#define PRU_INTC_HOSTMAP0_CHAN			(0x03020100)
> +#define PRU_INTC_HOSTMAP1_CHAN			(0x07060504)
> +#define PRU_INTC_HOSTMAP2_CHAN			(0x00000908)
> +
> +#define PRU_INTC_CHANMAP7_SYS_EVT31		(0x00000000)
> +#define PRU_INTC_CHANMAP8_FULL			(0x02020100)
> +#define PRU_INTC_CHANMAP9_FULL			(0x04040303)
> +#define PRU_INTC_CHANMAP10_FULL			(0x06060505)
> +#define PRU_INTC_CHANMAP11_FULL			(0x08080707)
> +#define PRU_INTC_CHANMAP12_FULL			(0x00010909)
> +#define PRU_INTC_CHANMAP8_HALF			(0x03020100)
> +#define PRU_INTC_CHANMAP9_HALF			(0x07060504)
> +#define PRU_INTC_CHANMAP10_HALF			(0x03020908)
> +#define PRU_INTC_CHANMAP11_HALF			(0x07060504)
> +#define PRU_INTC_CHANMAP12_HALF			(0x00010908)
> +
> +#define PRU_INTC_REGMAP_MASK			(0xFFFFFFFF)
> +
> +struct da8xx_pruss_devices {
> +	const char *dev_name;
> +	void *pdata;
> +	size_t pdata_size;
> +	int (*setup)(void);
> +	u32 num_resources;
> +	struct resource *resources;
> +};
> +
> +u32 pruss_get_(struct device *dev);
> +
> +s32 pruss_enable(struct device *dev, u8 pruss_num);
> +
> +s32 pruss_load(struct device *dev, u8 pruss_num,
> +	u32 *pruss_code, u32 code_size_in_words);
> +
> +s32 pruss_run(struct device *dev, u8 pruss_num);
> +
> +s32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout);
> +
> +s32 pruss_disable(struct device *dev, u8 pruss_num);
> +
> +s32 pruss_writeb(struct device *dev, u32 offset,
> +		u8 *pdatatowrite, u16 wordstowrite);
> +
> +s32 pruss_rmwb(struct device *dev, u32 offset, u8 mask, u8 val);
> +
> +s32 pruss_readb(struct device *dev, u32 offset,
> +		u8 *pdatatoread, u16 wordstoread);
> +
> +s32 pruss_readl(struct device *dev, u32 offset,
> +		u32 *pdatatoread, s16 wordstoread);
> +
> +s32 pruss_writel(struct device *dev, u32 offset,
> +		u32 *pdatatoread, s16 wordstoread);
> +
> +s32 pruss_rmwl(struct device *dev, u32 offset, u32 mask, u32 val);
> +
> +s32 pruss_idx_writel(struct device *dev, u32 offset, u32 value);
> +
> +s32 pruss_writew(struct device *dev, u32 offset,
> +		u16 *datatowrite, s16 wordstowrite);
> +
> +s32 pruss_rmww(struct device *dev, u32 offset, u16 mask, u16 val);
> +
> +s32 pruss_readw(struct device *dev, u32 offset,
> +		u16 *pdatatoread, s16 wordstoread);
> +#endif	/* End _PRUSS_H_ */
> diff --git a/include/linux/mfd/da8xx/da8xx_prucore.h b/include/linux/mfd/da8xx/da8xx_prucore.h
> new file mode 100644
> index 0000000..913d56f
> --- /dev/null
> +++ b/include/linux/mfd/da8xx/da8xx_prucore.h
> @@ -0,0 +1,129 @@
> +/*
> + * 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 _DA8XX_PRUCORE_H_
> +#define _DA8XX_PRUCORE_H_
> +
> +#include <linux/types.h>
> +
> +#define DA8XX_PRUCORE_0		(0)
> +#define DA8XX_PRUCORE_1		(1)
> +
> +#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_MASK			(0xFFFF0000u)
> +#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_SHIFT			(0x00000010u)
> +#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_RESETVAL		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_RUNSTATE_MASK			(0x00008000u)
> +#define DA8XX_PRUCORE_CONTROL_RUNSTATE_SHIFT			(0x0000000Fu)
> +#define DA8XX_PRUCORE_CONTROL_RUNSTATE_RESETVAL			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_RUNSTATE_HALT			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_RUNSTATE_RUN			(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_MASK			(0x00000100u)
> +#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_SHIFT			(0x00000008u)
> +#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_RESETVAL		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_FREERUN		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_SINGLE			(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK			(0x00000008u)
> +#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT			(0x00000003u)
> +#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_RESETVAL		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_ENABLE		(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_SLEEPING_MASK			(0x00000004u)
> +#define DA8XX_PRUCORE_CONTROL_SLEEPING_SHIFT			(0x00000002u)
> +#define DA8XX_PRUCORE_CONTROL_SLEEPING_RESETVAL			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SLEEPING_NOTASLEEP		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SLEEPING_ASLEEP			(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_ENABLE_MASK			(0x00000002u)
> +#define DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT			(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_ENABLE_RESETVAL			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_ENABLE_ENABLE			(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_SOFTRESET_MASK			(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_SOFTRESET_SHIFT			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SOFTRESET_RESETVAL		(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SOFTRESET_RESET			(0x00000000u)
> +#define DA8XX_PRUCORE_CONTROL_SOFTRESET_OUT_OF_RESET		(0x00000001u)
> +#define DA8XX_PRUCORE_CONTROL_RESETVAL				(0x00000000u)
> +
> +struct da8xx_prusscore_regs {
> +	u32 CONTROL;
> +	u32 STATUS;
> +	u32 WAKEUP;
> +	u32 CYCLECNT;
> +	u32 STALLCNT;
> +	u8  RSVD0[12];
> +	u32 CONTABBLKIDX0;
> +	u32 CONTABBLKIDX1;
> +	u32 CONTABPROPTR0;
> +	u32 CONTABPROPTR1;
> +	u8  RSVD1[976];
> +	u32 INTGPR[32];
> +	u32 INTCTER[32];
> +	u8  RSVD2[768];
> +};

struct members are usually lowercase

> +
> +struct pruss_intc_regs {
> +	u32 REVID;
> +	u32 CONTROL;
> +	u8 RES1[8];
> +	u32 GLBLEN;
> +	u8 RES2[8];
> +	u32 GLBLNSTLVL;
> +	u32 STATIDXSET;
> +	u32 STATIDXCLR;
> +	u32 ENIDXSET;
> +	u32 ENIDXCLR;
> +	u8 RES3[4];
> +	u32 HOSTINTENIDXSET;
> +	u32 HOSTINTENIDXCLR;
> +	u8 RES4[68];
> +	u32 GLBLPRIIDX;
> +	u8 RES5[380];
> +	u32 STATSETINT[2];
> +	u8 RES6[120];
> +	u32 STATCLRINT[2];
> +	u8 RES7[120];
> +	u32 ENABLESET[2];
> +	u8 RES8[120];
> +	u32 ENABLECLR[2];
> +	u8 RES9[120];
> +	u32 CHANMAP[16];
> +	u8 RES10[960];
> +	u32 HOSTMAP[2];
> +	u8 RES11[248];
> +	u32 HOSTINTPRIIDX[10];
> +	u8 RES12[984];
> +	u32 POLARITY[2];
> +	u8 RES13[120];
> +	u32 TYPE[2];
> +	u8 RES14[888];
> +	u32 HOSTINTNSTLVL[10];
> +	u8 RES15[984];
> +	u32 HOSTINTEN;
> +	u8 RES16[6907];
> +};
> +
> +struct pruss_map {
> +	u8 dram0[512];
> +	u8 res1[7680];
> +	u8 dram1[512];
> +	u8 res2[7680];
> +	struct pruss_intc_regs intc;
> +	struct da8xx_prusscore_regs core[2];
> +	u8 iram0[4096];
> +	u8 res3[12288];
> +	u8 iram1[4096];
> +	u8 res4[12288];
> +};
> +
> +#endif


-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 3/7] da850: pruss board specific additions.
  2011-03-08 13:57 ` [PATCH v3 3/7] da850: pruss board " Subhasish Ghosh
  2011-03-08 15:19   ` Sergei Shtylyov
@ 2011-03-09 11:59   ` Marc Kleine-Budde
  1 sibling, 0 replies; 31+ messages in thread
From: Marc Kleine-Budde @ 2011-03-09 11:59 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: davinci-linux-open-source, Kevin Hilman, sachi, Russell King,
	nsekhar, open list, m-watkins, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 2086 bytes --]

On 03/08/2011 02:57 PM, Subhasish Ghosh wrote:
> This patch adds board specific initializations and setup routines.
> 
> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
> ---
>  arch/arm/mach-davinci/board-da850-evm.c |   25 +++++++++++++++++++++++++
>  1 files changed, 25 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index 11f986b..c614c82 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1053,6 +1053,26 @@ static __init int da850_evm_init_cpufreq(void)
>  static __init int da850_evm_init_cpufreq(void) { return 0; }
>  #endif
>  
> +static struct da8xx_pruss_devices pruss_devices[] = {
> +	{.dev_name = NULL,},
> +};
> +
> +static int __init da8xx_evm_setup_pruss(void)
> +{
> +	u32 ret = 0;
your functions returns an int, not an u32
> +	u32 count;

use "int i" for loop counter.

> +
> +	for (count = 0; count < ARRAY_SIZE(pruss_devices); count++) {
> +		if (pruss_devices[count].setup != NULL) {

you may omit the "!= NULL"

> +			ret = pruss_devices[count].setup();
> +			if (ret)
> +				return ret;

in case of an error you don't clean up correct

> +		}
> +	}
> +
> +	return da8xx_register_pruss_mfd(pruss_devices);
> +}
> +
>  static __init void da850_evm_init(void)
>  {
>  	int ret;
> @@ -1127,6 +1147,11 @@ static __init void da850_evm_init(void)
>  
>  	da8xx_register_mcasp(0, &da850_evm_snd_data);
>  
> +	ret = da8xx_evm_setup_pruss();
> +	if (ret)
> +		pr_warning("%s: pruss initialization failed: %d\n",
> +				__func__, ret);
> +
>  	ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
>  	if (ret)
>  		pr_warning("da850_evm_init: lcdcntl mux setup failed: %d\n",


-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-08 13:57 ` [PATCH v3 1/7] mfd: add pruss mfd driver Subhasish Ghosh
  2011-03-09 11:56   ` Marc Kleine-Budde
@ 2011-03-11 15:28   ` Arnd Bergmann
  2011-03-30  7:16     ` Subhasish Ghosh
  2011-03-30  9:15     ` Subhasish Ghosh
  2011-03-18 11:59   ` Nori, Sekhar
  2 siblings, 2 replies; 31+ messages in thread
From: Arnd Bergmann @ 2011-03-11 15:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Subhasish Ghosh, davinci-linux-open-source, sachi, Samuel Ortiz,
	nsekhar, open list, m-watkins, Marc Kleine-Budde

On Tuesday 08 March 2011, Subhasish Ghosh wrote:

> +struct da8xx_pruss {
> +	struct device *dev;
> +	spinlock_t lock;
> +	struct resource *res;
> +	struct clk *clk;
> +	u32 clk_freq;
> +	void __iomem *ioaddr;
> +};

> +s32 pruss_disable(struct device *dev, u8 pruss_num)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct da8xx_prusscore_regs *h_pruss;
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +	u32 temp_reg;
> +	u32 delay_cnt;

Can you explain the significance of pruss_num? As far as I
can tell, you always pass constants in here, so it should
be possible to determine the number from the device.

> +	if ((pruss_num != DA8XX_PRUCORE_0) && (pruss_num != DA8XX_PRUCORE_1))
> +		return -EINVAL;
> +
> +	spin_lock(&pruss->lock);
> +	if (pruss_num == DA8XX_PRUCORE_0) {
> +		/* pruss deinit */
> +		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT0 & 0xFFFF));
> +		/* Disable PRU0  */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_0];
> +
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +		__raw_writel(temp_reg, &h_pruss->CONTROL);

Better use readl/writel, the __raw_ variants are not reliable in general.

> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
> +
> +			temp_reg = __raw_readl(&h_pruss->CONTROL);
> +			temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +			__raw_writel(temp_reg, &h_pruss->CONTROL);
> +		}
> +
> +		/* Reset PRU0 */
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
> +			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +					&h_pruss->CONTROL);

Why do you need to reset it 65536 times? Is once not enough?

> +	} else if (pruss_num == DA8XX_PRUCORE_1) {
> +		/* pruss deinit */
> +		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT1 & 0xFFFF));
> +		/* Disable PRU1 */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_1];
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +		__raw_writel(temp_reg, &h_pruss->CONTROL);
> +
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
> +
> +			temp_reg = __raw_readl(&h_pruss->CONTROL);
> +			temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +			__raw_writel(temp_reg, &h_pruss->CONTROL);
> +		}
> +
> +		/* Reset PRU1 */
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
> +			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +							&h_pruss->CONTROL);
> +	}
> +	spin_unlock(&pruss->lock);

This is almost the exact same code as for the DA8XX_PRUCORE_0 case.
Please be a little more creative in order to avoid such code duplication.

> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_disable);

EXPORT_SYMBOL_GPL, please. Also for the other symbols.

> +s32 pruss_writeb(struct device *dev, u32 offset,
> +		u8 *pdatatowrite, u16 bytestowrite)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	u8 *paddresstowrite;
> +	u16 loop;
> +	offset = (u32)pruss->ioaddr + offset;
> +	paddresstowrite = (u8 *) (offset);
> +
> +	for (loop = 0; loop < bytestowrite; loop++)
> +		__raw_writeb(*pdatatowrite++, paddresstowrite++);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(pruss_writeb);

I would recommend providing a simpler variant of your all I/O accessors,
which write a single word. Most of the users of these simply
pass bytestowrite=1 anyway, so the caller can become more readable.

Also, my comments about __raw_* and Marc's comments about the
type cast apply to all of these.

> +static int pruss_mfd_add_devices(struct platform_device *pdev)
> +{
> +	struct da8xx_pruss_devices *dev_data = pdev->dev.platform_data;
> +	struct device *dev = &pdev->dev;
> +	struct mfd_cell cell;
> +	u32 err, count;
> +
> +	for (count = 0; dev_data[count].dev_name != NULL; count++) {
> +		memset(&cell, 0, sizeof(struct mfd_cell));
> +		cell.id			= count;
> +		cell.name		= dev_data[count].dev_name;
> +		cell.platform_data	= dev_data[count].pdata;
> +		cell.data_size		= dev_data[count].pdata_size;
> +		cell.resources		= dev_data[count].resources;
> +		cell.num_resources	= dev_data[count].num_resources;
> +
> +		err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
> +		if (err) {
> +			dev_err(dev, "cannot add mfd cells\n");
> +			return err;
> +		}
> +		dev_info(dev, "mfd: added %s device\n",
> +				dev_data[count].dev_name);
> +	}
> +
> +	return err;
> +}

This would get much simpler if you just replaced the da8xx_pruss_devices
array with an mfd_cell array.

	Arnd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 7/7] tty: add pruss SUART driver
  2011-03-08 18:47   ` Randy Dunlap
@ 2011-03-15  7:23     ` Subhasish Ghosh
  0 siblings, 0 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-15  7:23 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: davinci-linux-open-source, linux-arm-kernel, m-watkins, nsekhar,
	sachi, maintainer:TTY LAYER <gregkh@suse.de>,
	commit_signer:2/4=50%, commit_signer:1/2=50%,
	Andrew Morton (commit_signer:1/4=25%),
	Randy Dunlap (commit_signer:1/4=25%),
	open list

Hello,

Thank you for your comments.
Would really appreciate more comments and ways to fix this patch and bring 
it
up to Linux Standards.
If I have missed something/misunderstood then please let me know.


>> +config SERIAL_PRUSS_SUART
>> + depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
>> + select SERIAL_CORE
>> + tristate "PRUSS based SoftUART emulation on DA8XX"
>> + ---help---
>> + This driver emulates upto eight different UARTs on the PRUSS.
>
>                      up to
>
SG -- Ok Will do.


>> + You may modify the NR_SUARTS macro in the driver to emulate
>> + less number of UARTS as per your requirement.
>> + If not sure, mark N
>
>              mark N.
>
SG -- Ok Will do.


>> +    Enter the McASP number to use with SUART (0, 1 or 2).
>> + You will need to recompile the kernel if this is changed.
>
> The 2 help text lines should be indented the same.
>
SG - Ok will do.
 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 7/7] tty: add pruss SUART driver
  2011-03-08 13:57 ` [PATCH v3 7/7] tty: add pruss SUART driver Subhasish Ghosh
  2011-03-08 18:47   ` Randy Dunlap
@ 2011-03-18  5:43   ` Subhasish Ghosh
  2011-03-18 11:45     ` Alan Cox
  2011-03-18 12:07     ` Arnd Bergmann
  1 sibling, 2 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-18  5:43 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Alan Cox
  Cc: Alan Cox, Arnd Bergmann, Thomas Gleixner, linux-arm-kernel,
	m-watkins, nsekhar, sachi, Andrew Morton (commit_signer:1/4=25%),
	Randy Dunlap (commit_signer:1/4=25%),
	open list

Hi Greg/Alan,

Any comments regarding this driver.

--------------------------------------------------
From: "Subhasish Ghosh" <subhasish@mistralsolutions.com>
Sent: Tuesday, March 08, 2011 7:27 PM
To: <davinci-linux-open-source@linux.davincidsp.com>
Cc: <linux-arm-kernel@lists.infradead.org>; <m-watkins@ti.com>; 
<nsekhar@ti.com>; <sachi@mistralsolutions.com>; "Subhasish Ghosh" 
<subhasish@mistralsolutions.com>; "Greg Kroah-Hartman (maintainer:TTY 
LAYER,commit_signer:2/4=50%,commit_signer:1/2=50%)" <gregkh@suse.de>; 
"Andrew Morton (commit_signer:1/4=25%)" <akpm@linux-foundation.org>; "Randy 
Dunlap (commit_signer:1/4=25%)" <randy.dunlap@oracle.com>; "open list" 
<linux-kernel@vger.kernel.org>
Subject: [PATCH v3 7/7] tty: add pruss SUART driver

> This patch adds support for the TTY compliant
> Soft-UART device emulated on PRUSS.
>
> This patch depends on:
> davinci: macro rename DA8XX_LPSC0_DMAX to DA8XX_LPSC0_PRUSS.
> https://patchwork.kernel.org/patch/615681/
> davinci: changed SRAM allocator to shared ram.
> https://patchwork.kernel.org/patch/549351/
>
> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
> ---
> drivers/tty/serial/Kconfig             |   22 +
> drivers/tty/serial/Makefile            |   10 +
> drivers/tty/serial/pruss_suart.c       | 1058 +++++++++++++++++++
> drivers/tty/serial/pruss_suart.h       | 1081 ++++++++++++++++++++
> drivers/tty/serial/pruss_suart_api.c   | 1757 
> ++++++++++++++++++++++++++++++++
> drivers/tty/serial/pruss_suart_utils.c |  391 +++++++
> include/linux/serial_core.h            |    2 +
> 7 files changed, 4321 insertions(+), 0 deletions(-)
> create mode 100644 drivers/tty/serial/pruss_suart.c
> create mode 100644 drivers/tty/serial/pruss_suart.h
> create mode 100644 drivers/tty/serial/pruss_suart_api.c
> create mode 100644 drivers/tty/serial/pruss_suart_utils.c
>
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 2b83346..14ea0a3 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1596,4 +1596,26 @@ config SERIAL_PCH_UART
>    This driver is for PCH(Platform controller Hub) UART of Intel EG20T
>    which is an IOH(Input/Output Hub) for x86 embedded processor.
>    Enabling PCH_DMA, this PCH UART works as DMA mode.
> +
> +#
> +# SUART Kernel Configuration
> +#
> +
> +config SERIAL_PRUSS_SUART
> + depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
> + select SERIAL_CORE
> + tristate "PRUSS based SoftUART emulation on DA8XX"
> + ---help---
> + This driver emulates upto eight different UARTs on the PRUSS.
> + You may modify the NR_SUARTS macro in the driver to emulate
> + less number of UARTS as per your requirement.
> + If not sure, mark N
> +
> +config PRUSS_SUART_MCASP
> +    int "McASP number"
> +    depends on ARCH_DAVINCI && ARCH_DAVINCI_DA830 && SERIAL_PRUSS_SUART
> +    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.
> endmenu
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index 8ea92e9..f52a4eb 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -92,3 +92,13 @@ obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
> obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
> obj-$(CONFIG_SERIAL_IFX6X60)  += ifx6x60.o
> obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
> +
> +#
> +# Makefile for SoftUART emulation
> +#
> +
> +suart_emu-objs :=       pruss_suart.o \
> +                        pruss_suart_api.o \
> +                        pruss_suart_utils.o
> +
> +obj-$(CONFIG_SERIAL_PRUSS_SUART)        += suart_emu.o
> diff --git a/drivers/tty/serial/pruss_suart.c 
> b/drivers/tty/serial/pruss_suart.c
> new file mode 100644
> index 0000000..c411ff8
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart.c
> @@ -0,0 +1,1058 @@
> +/*
> + * PRUSS 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 <linux/bitops.h>
> +#include <mach/sram.h>
> +#include "pruss_suart.h"
> +
> +#define NR_SUART 8
> +#define DRV_NAME "da8xx_pruss_uart"
> +#define DRV_DESC "PRUSS SUART Driver v1.0"
> +#define MAX_SUART_RETRIES 100
> +#define SUART_CNTX_SZ 512
> +#define SUART_FIFO_TIMEOUT_DFLT 5
> +#define SUART_FIFO_TIMEOUT_MIN 4
> +#define SUART_FIFO_TIMEOUT_MAX 500
> +
> +/* Default timeout set to 5ms */
> +static s16 suart_timeout = SUART_FIFO_TIMEOUT_DFLT;
> +module_param(suart_timeout, short, S_IRUGO);
> +MODULE_PARM_DESC(suart_timeout,
> + "fifo timeout in milli seconds (min: 4; max: 500)");
> +
> +struct suart_fifo {
> + void *fifo_vaddr_buff_tx;
> + void *fifo_vaddr_buff_rx;
> + void *fifo_phys_addr_tx;
> + void *fifo_phys_addr_rx;
> +};
> +
> +struct omapl_pru_suart {
> + struct uart_port port[NR_SUART];
> + struct device *dev;
> + unsigned long tx_empty[NR_SUART];
> + struct clk *clk_mcasp;
> + struct suart_fifo suart_fifo_addr[NR_SUART];
> + const struct firmware *fw;
> + struct suart_handle suart_hdl[NR_SUART];
> + struct pruss_suart_iomap suart_iomap;
> + struct tasklet_struct tx_task[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].uart_type;
> +}
> +
> +static inline void __stop_tx(struct omapl_pru_suart *soft_uart, u32 
> uart_no)
> +{
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> + struct uart_port *port = &soft_uart->port[uart_no];
> + u16 txready;
> + u32 i;
> +
> + /* Check if any TX in progress */
> + for (i = 0, txready = 1; (i < 10000) && txready; i++) {
> + txready = (pru_softuart_get_tx_status
> + (dev, &soft_uart->suart_hdl[uart_no]) &
> + CHN_TXRX_STATUS_RDY);
> + }
> + /* To stop tx, disable the TX interrupt */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[uart_no].uart_num,
> + PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + pru_softuart_clr_tx_status(dev, &soft_uart->suart_hdl[uart_no]);
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void pruss_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;
> + struct device *dev = soft_uart->dev;
> + s32 count = 0;
> +
> + if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_TX))
> + return;
> +
> + if (uart_circ_empty(xmit) ||
> + uart_tx_stopped(&soft_uart->port[uart_no])) {
> + pruss_suart_stop_tx(&soft_uart->port[uart_no]);
> + set_bit(0, &soft_uart->tx_empty[uart_no]);
> + return;
> + }
> +
> + for (count = 0; count <= soft_uart->tx_loadsz; count++) {
> + *((s8 *)soft_uart->suart_fifo_addr[uart_no].fifo_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 (pru_softuart_write(dev,
> + &soft_uart->suart_hdl[uart_no],
> + (u32 *)&soft_uart->suart_fifo_addr
> + [uart_no].fifo_phys_addr_tx, count) != 0) {
> + dev_err(dev, "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 suart_tx_task(unsigned long data)
> +{
> + struct uart_port *port = (struct uart_port *)data;
> + struct omapl_pru_suart *soft_uart =
> + container_of(port, struct omapl_pru_suart, port[port->line]);
> +
> + omapl_pru_tx_chars(soft_uart, port->line);
> +}
> +
> +static void omapl_pru_rx_chars(struct omapl_pru_suart *soft_uart, u32 
> uart_no)
> +{
> + struct tty_struct *tty = NULL;
> + struct device *dev = soft_uart->dev;
> + s8 flags = TTY_NORMAL;
> + u16 rx_status, data_len = SUART_FIFO_LEN;
> + u32 data_len_read;
> + u8 suart_data[SUART_FIFO_LEN + 1];
> + s32 i = 0;
> +
> + if (!(suart_get_duplex(soft_uart, uart_no) & ePRU_SUART_HALF_RX))
> + return;
> +
> + /* read the status */
> + rx_status = pru_softuart_get_rx_status(dev,
> + &soft_uart->suart_hdl[uart_no]);
> +
> + pru_softuart_read_data(dev, &soft_uart->suart_hdl[uart_no],
> + suart_data, data_len + 1, &data_len_read);
> +
> + tty = tty_port_tty_get(&soft_uart->port[uart_no].state->port);
> +
> + if (!tty)
> + return;
> +
> + /* 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 {
> + 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;
> + }
> + tty_insert_flip_string(tty, suart_data, data_len_read);
> + }
> +
> + /* push data into tty */
> + pru_softuart_clr_rx_status(dev, &soft_uart->suart_hdl[uart_no]);
> + tty_flip_buffer_push(tty);
> + tty_kref_put(tty);
> +}
> +
> +static irqreturn_t pruss_suart_interrupt(s32 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]);
> + struct device *dev = soft_uart->dev;
> + u16 txrx_flag;
> + u32 ret;
> + unsigned long flags = 0;
> + u16 uart_num = port->line + 1;
> +
> + spin_lock_irqsave(&port->lock, flags);
> +
> + do {
> + ret = pru_softuart_get_isrstatus(dev, uart_num, &txrx_flag);
> + if (ret != 0) {
> + dev_err(dev, "suart%d: failed to get interrupt, ret:"
> + " 0x%X txrx_flag 0x%X\n",
> + port->line, ret, txrx_flag);
> + spin_unlock_irqrestore(&port->lock, flags);
> + return IRQ_NONE;
> + }
> + if ((PRU_RX_INTR & txrx_flag) == PRU_RX_INTR) {
> + pru_intr_clr_isrstatus(dev, uart_num, PRU_RX_INTR);
> + if ((soft_uart->port[port->line].ignore_status_mask &
> + CHN_TXRX_STATUS_RDY) == CHN_TXRX_STATUS_RDY) {
> + pru_softuart_clr_rx_status(dev,
> + &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(dev, uart_num, PRU_TX_INTR);
> + pru_softuart_clr_tx_status(dev, &soft_uart->suart_hdl
> + [port->line]);
> + tasklet_schedule(&soft_uart->tx_task[port->line]);
> + }
> + } while (txrx_flag & (PRU_RX_INTR | PRU_TX_INTR));
> +
> + spin_unlock_irqrestore(&port->lock, flags);
> + return IRQ_HANDLED;
> +}
> +
> +static void pruss_suart_stop_rx(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + spin_lock_irqsave(&port->lock, flags);
> + /* disable rx interrupt */
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> +    | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> +    | CHN_TXRX_IE_MASK_TIMEOUT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void pruss_suart_enable_ms(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + dev_err(dev, "modem control timer not supported\n");
> +}
> +
> +static void pruss_suart_start_tx(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + /* unmask the tx interrupts */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + if (test_and_clear_bit(0, &soft_uart->tx_empty[port->line]))
> + omapl_pru_tx_chars(soft_uart, port->line);
> +}
> +
> +static u32 pruss_suart_tx_empty(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> +
> + return (pru_softuart_get_tx_status(dev,
> + &soft_uart->suart_hdl[port->line])
> + & CHN_TXRX_STATUS_RDY) ? 0 : TIOCSER_TEMT;
> +}
> +
> +static u32 pruss_suart_get_mctrl(struct uart_port *port)
> +{
> + return -ENOTSUPP;
> +}
> +
> +static void pruss_suart_set_mctrl(struct uart_port *port, u32 mctrl)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + dev_dbg(dev, "modem control not supported\n");
> +}
> +
> +static void pruss_suart_break_ctl(struct uart_port *port, s32 
> break_state)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + spin_lock_irqsave(&port->lock, flags);
> +
> + if (break_state == -1)
> + suart_intr_clrmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> + else
> + suart_intr_setmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> +
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void pruss_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]);
> + struct device *dev = soft_uart->dev;
> + u8 cval = 0;
> + unsigned long flags = 0;
> + u32 baud = 0;
> + u32 old_csize = old ? old->c_cflag & CSIZE : CS8;
> +
> +/*
> + * Do not allow unsupported configurations to be set
> + */
> + if (1) {
> + termios->c_cflag &= ~(CRTSCTS | CMSPAR | CSTOPB
> +       | PARENB | PARODD | CMSPAR);
> + }
> +
> + 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 (pru_softuart_setdatabits
> + (dev, &soft_uart->suart_hdl[port->line], cval, cval) != 0)
> + dev_err(dev, "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 (pru_softuart_setbaud(dev, &soft_uart->suart_hdl[port->line],
> + SUART_DEFAULT_BAUD / baud,
> + SUART_DEFAULT_BAUD / baud) != 0)
> + dev_err(dev, "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(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    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(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + 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(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + PRU_RX_INTR, CHN_TXRX_IE_MASK_BI);
> + }
> +/*
> + * Characters 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(dev, soft_uart->
> +    suart_hdl[port->line].uart_num,
> +    PRU_RX_INTR, CHN_TXRX_IE_MASK_FE);
> + }
> + suart_intr_clrmask(dev,
> + soft_uart->suart_hdl[port->line].uart_num,
> + 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;
> + pruss_suart_stop_rx(port);
> + }
> + /*
> + * update the per port timeout
> + */
> + uart_update_timeout(port, termios->c_cflag, baud);
> +
> + 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 s32 pruss_suart_startup(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> + s32 retval;
> +
> + /*
> + * Disable interrupts from this port
> + */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> +    | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> +    | CHN_TXRX_IE_MASK_TIMEOUT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + retval = request_irq(port->irq, pruss_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
> + */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_RX_INTR, SUART_GBL_INTR_ERR_MASK);
> +
> + suart_intr_setmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    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(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + if ((suart_get_duplex(soft_uart, port->line) & ePRU_SUART_HALF_TX)
> +     == ePRU_SUART_HALF_TX) {
> + suart_pru_to_host_intr_enable(dev, soft_uart->
> + suart_hdl[port->line].uart_num, 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(dev, soft_uart->
> + suart_hdl[port->line].uart_num, PRU_RX_INTR, true);
> + pru_softuart_read(dev, &soft_uart->suart_hdl[port->line],
> + (u32 *)&soft_uart->suart_fifo_addr[port->line].
> + fifo_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 pruss_suart_shutdown(struct uart_port *port)
> +{
> + struct omapl_pru_suart *soft_uart =
> +     container_of(port, struct omapl_pru_suart, port[port->line]);
> + struct device *dev = soft_uart->dev;
> + unsigned long flags = 0;
> +
> + /*
> + * Disable interrupts from this port
> + */
> + /* Disable BI and FE intr */
> + spin_lock_irqsave(&port->lock, flags);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_TX_INTR, CHN_TXRX_IE_MASK_CMPLT);
> + suart_intr_clrmask(dev, soft_uart->suart_hdl[port->line].uart_num,
> +    PRU_RX_INTR, CHN_TXRX_IE_MASK_BI
> +    | CHN_TXRX_IE_MASK_FE | CHN_TXRX_IE_MASK_CMPLT
> +    | CHN_TXRX_IE_MASK_TIMEOUT);
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + /* 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 *pruss_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 pruss_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.
> + */
> +static s32 pruss_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);
> + struct device *dev = soft_uart->dev;
> + struct suart_config pru_suart_config;
> + s16 timeout = 0;
> + u32 err = 0;
> +
> + if (soft_uart == NULL) {
> + dev_err(&pdev->dev, "soft_uart ptr failed\n");
> + return -ENODEV;
> + }
> + err = pru_softuart_open(&soft_uart->suart_hdl[port->line]);
> + if (err != 0) {
> + dev_err(&pdev->dev, "failed to open suart: %d\n", err);
> + err = -ENODEV;
> + goto exit;
> + }
> + set_bit(0, &soft_uart->tx_empty[port->line]);
> +
> + /* set fifo /timeout */
> + if (SUART_FIFO_TIMEOUT_MIN > suart_timeout) {
> + dev_err(&pdev->dev, "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) {
> + dev_err(&pdev->dev, "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(dev, timeout);
> +
> + if (soft_uart->suart_hdl[port->line].uart_num == PRU_SUART_UART1) {
> + pru_suart_config.tx_serializer = PRU_SUART0_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART0_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART2) {
> + pru_suart_config.tx_serializer = PRU_SUART1_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART1_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART3) {
> + pru_suart_config.tx_serializer = PRU_SUART2_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART2_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART4) {
> + pru_suart_config.tx_serializer = PRU_SUART3_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART3_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART5) {
> + pru_suart_config.tx_serializer = PRU_SUART4_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART4_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART6) {
> + pru_suart_config.tx_serializer = PRU_SUART5_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART5_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART7) {
> + pru_suart_config.tx_serializer = PRU_SUART6_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART6_CONFIG_RX_SER;
> + } else if (soft_uart->suart_hdl[port->line].uart_num ==
> + PRU_SUART_UART8) {
> + pru_suart_config.tx_serializer = PRU_SUART7_CONFIG_TX_SER;
> + pru_suart_config.rx_serializer = PRU_SUART7_CONFIG_RX_SER;
> + } else {
> + return -ENOTSUPP;
> + }
> +
> + /* Some defaults to startup. reconfigured by terimos later */
> + pru_suart_config.tx_clk_divisor = 1;
> + pru_suart_config.rx_clk_divisor = 1;
> + pru_suart_config.tx_bits_per_char = ePRU_SUART_DATA_BITS8;
> + pru_suart_config.rx_bits_per_char = ePRU_SUART_DATA_BITS8;
> + pru_suart_config.oversampling = SUART_DEFAULT_OVRSMPL;
> +
> + if (pru_softuart_setconfig(dev, &soft_uart->suart_hdl[port->line],
> + &pru_suart_config) != 0) {
> + 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 pruss_suart_config_port(struct uart_port *port, s32 flags)
> +{
> + if (flags & UART_CONFIG_TYPE && pruss_suart_request_port(port) == 0)
> + port->type = PORT_DA8XX_PRU_SUART;
> +}
> +
> +/*
> + * Verify the new serial port information contained within serinfo is
> + * suitable for this port type.
> + *
> + * Locking: none.
> + * Interrupts: caller dependent.
> + */
> +static s32 pruss_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]);
> + s32 ret = 0;
> +
> + if (ser->type != PORT_UNKNOWN && ser->type != PORT_DA8XX_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 pruss_suart_ops = {
> + .tx_empty = pruss_suart_tx_empty,
> + .set_mctrl = pruss_suart_set_mctrl,
> + .get_mctrl = pruss_suart_get_mctrl,
> + .stop_tx = pruss_suart_stop_tx,
> + .start_tx = pruss_suart_start_tx,
> + .stop_rx = pruss_suart_stop_rx,
> + .enable_ms = pruss_suart_enable_ms,
> + .break_ctl = pruss_suart_break_ctl,
> + .startup = pruss_suart_startup,
> + .shutdown = pruss_suart_shutdown,
> + .set_termios = pruss_suart_set_termios,
> + .type = pruss_suart_type,
> + .release_port = pruss_suart_release_port,
> + .request_port = pruss_suart_request_port,
> + .config_port = pruss_suart_config_port,
> + .verify_port = pruss_suart_verify_port,
> +};
> +
> +static struct uart_driver pruss_suart_reg = {
> + .owner = THIS_MODULE,
> + .driver_name = DRV_NAME,
> + .dev_name = "ttySU",
> + .major = 0,
> + .minor = 16,
> + .nr = NR_SUART,
> +};
> +
> +static s32 __devinit pruss_suart_probe(struct platform_device *pdev)
> +{
> + struct omapl_pru_suart *soft_uart;
> + const struct da850_evm_pruss_suart_data *pdata;
> + struct device *dev = &pdev->dev;
> + struct resource *res;
> + s32 err, i;
> + u8 *fw_data = NULL;
> +
> + pdata = dev->platform_data;
> + if (!pdata) {
> + dev_err(&pdev->dev, "platform data not found\n");
> + return -EINVAL;
> + }
> +
> + soft_uart = kzalloc(sizeof(struct omapl_pru_suart), GFP_KERNEL);
> + if (!soft_uart)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "failed to get resource");
> + return -ENOMEM;
> + }
> +
> + if (!request_mem_region(res->start,
> + resource_size(res),
> + dev_name(&pdev->dev))) {
> + dev_err(&pdev->dev, "mcasp memory region already claimed!\n");
> + err = -EBUSY;
> + goto probe_exit;
> + }
> +
> + soft_uart->suart_iomap.mcasp_io_addr = ioremap(res->start,
> + resource_size(res));
> + if (!soft_uart->suart_iomap.mcasp_io_addr) {
> + dev_err(&pdev->dev, "mcasp ioremap failed\n");
> + err = -EFAULT;
> + goto probe_exit_1;
> + }
> +
> + soft_uart->suart_iomap.p_fifo_buff_virt_base =
> + sram_alloc(SUART_CNTX_SZ * NR_SUART * 2,
> + (dma_addr_t *) &soft_uart->suart_iomap.p_fifo_buff_phys_base);
> + if (!soft_uart->suart_iomap.p_fifo_buff_virt_base)
> + goto probe_exit_iounmap;
> +
> + soft_uart->clk_freq_pru = pruss_get_clk_freq(dev);
> +
> + soft_uart->clk_mcasp = clk_get(&pdev->dev, NULL);
> + 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_sram_free;
> + }
> +
> + soft_uart->clk_freq_mcasp = clk_get_rate(soft_uart->clk_mcasp);
> + clk_enable(soft_uart->clk_mcasp);
> +
> + 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->suart_iomap.pru_clk_freq =
> + (soft_uart->clk_freq_pru / 1000000);
> +
> + err = pru_softuart_init(dev, SUART_DEFAULT_BAUD, SUART_DEFAULT_BAUD,
> + SUART_DEFAULT_OVRSMPL, fw_data,
> + soft_uart->fw->size, &soft_uart->suart_iomap);
> + if (err) {
> + dev_err(&pdev->dev, "pruss init error\n");
> + err = -ENODEV;
> + kfree((const void *)fw_data);
> + goto probe_release_fw;
> + }
> + kfree((const void *)fw_data);
> +
> + platform_set_drvdata(pdev, &soft_uart->port[0]);
> + soft_uart->dev = dev;
> +
> + for (i = 0; i < NR_SUART; i++) {
> + soft_uart->port[i].ops = &pruss_suart_ops;
> + soft_uart->port[i].iotype = UPIO_MEM;
> + soft_uart->port[i].flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
> + soft_uart->port[i].mapbase =
> + (u32)soft_uart->suart_iomap.p_fifo_buff_virt_base;
> + soft_uart->port[i].membase =
> + (u8 *)&soft_uart->suart_iomap;
> + soft_uart->port[i].type = PORT_DA8XX_PRU_SUART;
> + soft_uart->port[i].irq =
> + platform_get_irq(to_platform_device(dev->parent), 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;
> + 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;
> + soft_uart->suart_hdl[i].uart_num = i + 1;
> + soft_uart->port[i].serial_in = NULL;
> +
> + soft_uart->suart_fifo_addr[i].fifo_vaddr_buff_tx =
> + soft_uart->suart_iomap.p_fifo_buff_virt_base +
> + (2 * SUART_CNTX_SZ * i);
> +
> + soft_uart->suart_fifo_addr[i].fifo_vaddr_buff_rx =
> + soft_uart->suart_iomap.p_fifo_buff_virt_base +
> + ((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
> +
> + soft_uart->suart_fifo_addr[i].fifo_phys_addr_tx =
> + soft_uart->suart_iomap.p_fifo_buff_phys_base +
> + (2 * SUART_CNTX_SZ * i);
> +
> + soft_uart->suart_fifo_addr[i].fifo_phys_addr_rx =
> + soft_uart->suart_iomap.p_fifo_buff_phys_base +
> + ((2 * SUART_CNTX_SZ * i) + SUART_CNTX_SZ);
> +
> + soft_uart->port[i].serial_out = NULL;
> + tasklet_init(&soft_uart->tx_task[i], suart_tx_task,
> + (unsigned long)&soft_uart->port[i]);
> + uart_add_one_port(&pruss_suart_reg, &soft_uart->port[i]);
> + }
> +
> + 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_release_fw:
> + release_firmware(soft_uart->fw);
> +probe_exit_clk:
> + clk_put(soft_uart->clk_mcasp);
> + clk_disable(soft_uart->clk_mcasp);
> +probe_exit_sram_free:
> + sram_free(soft_uart->suart_iomap.p_fifo_buff_virt_base,
> + SUART_CNTX_SZ * NR_SUART * 2);
> +probe_exit_iounmap:
> + iounmap(soft_uart->suart_iomap.mcasp_io_addr);
> +probe_exit_1:
> + release_mem_region(res->start,
> + resource_size(res));
> +probe_exit:
> + kfree(soft_uart);
> + return err;
> +}
> +
> +static s32 __devexit pruss_suart_remove(struct platform_device *pdev)
> +{
> + struct omapl_pru_suart *soft_uart = platform_get_drvdata(pdev);
> + const struct da850_evm_pruss_suart_data *pdata;
> + struct device *dev = &pdev->dev;
> + struct resource *res;
> + int i;
> +
> + pdata = dev->platform_data;
> + if (!pdata)
> + dev_err(&pdev->dev, "platform data not found\n");
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "failed to get resource");
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + if (soft_uart) {
> + for (i = 0; i < NR_SUART; i++) {
> + uart_remove_one_port(&pruss_suart_reg,
> + &soft_uart->port[i]);
> + }
> + }
> +
> + sram_free(soft_uart->suart_iomap.p_fifo_buff_virt_base,
> + SUART_CNTX_SZ * NR_SUART * 2);
> + release_firmware(soft_uart->fw);
> + clk_put(soft_uart->clk_mcasp);
> + pru_mcasp_deinit();
> + clk_disable(soft_uart->clk_mcasp);
> + iounmap(soft_uart->suart_iomap.mcasp_io_addr);
> + if (pdata) {
> + release_mem_region(res->start,
> + resource_size(res));
> + }
> + kfree(soft_uart);
> + return 0;
> +}
> +
> +#define pruss_suart_suspend NULL
> +#define pruss_suart_resume NULL
> +
> +static struct platform_driver serial_pruss_driver = {
> + .probe = pruss_suart_probe,
> + .remove = __devexit_p(pruss_suart_remove),
> + .suspend = pruss_suart_suspend,
> + .resume = pruss_suart_resume,
> + .driver = {
> + .name = DRV_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +static s32 __init pruss_suart_init(void)
> +{
> + s32 ret;
> +
> + pruss_suart_reg.nr = NR_SUART;
> + ret = uart_register_driver(&pruss_suart_reg);
> + if (ret)
> + return ret;
> + ret = platform_driver_register(&serial_pruss_driver);
> + if (ret)
> + goto out;
> +
> + pr_debug("SUART serial driver loaded\n");
> + return ret;
> +out:
> + uart_unregister_driver(&pruss_suart_reg);
> + return ret;
> +}
> +
> +module_init(pruss_suart_init);
> +
> +static void __exit pruss_suart_exit(void)
> +{
> + platform_driver_unregister(&serial_pruss_driver);
> + uart_unregister_driver(&pruss_suart_reg);
> + pr_debug("SUART serial driver unloaded\n");
> +}
> +
> +module_exit(pruss_suart_exit);
> +
> +/* Module information */
> +MODULE_AUTHOR("Subhasish Ghosh <subhasish@mistralsolutions.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION(DRV_DESC);
> diff --git a/drivers/tty/serial/pruss_suart.h 
> b/drivers/tty/serial/pruss_suart.h
> new file mode 100644
> index 0000000..8e0b40d
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart.h
> @@ -0,0 +1,1081 @@
> +/*
> + * 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 <linux/io.h>
> +#include <linux/mfd/da8xx/da8xx_pru.h>
> +
> +#define SINGLE_PRU 0
> +#define BOTH_PRU 1
> +#define PRU_ACTIVE BOTH_PRU
> +#define PRU_CLK_228 228
> +#define PRU_CLK_186 186
> +
> +#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)
> +
> +#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)
> +
> +#define PRU_SUART_HALF_TX (1u)
> +#define PRU_SUART_HALF_RX (2u)
> +#define PRU_SUART_HALF_TX_DISABLED (4u)
> +#define PRU_SUART_HALF_RX_DISABLED (8u)
> +
> +#define PRU_SUART0_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART0_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART0_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define PRU_SUART1_CONFIG_DUPLEX (PRU_SUART_HALF_TX | \
> + PRU_SUART_HALF_RX)
> +#define PRU_SUART1_CONFIG_RX_SER (PRU_SUART_SERIALIZER_7)
> +#define PRU_SUART1_CONFIG_TX_SER (PRU_SUART_SERIALIZER_8)
> +
> +#define PRU_SUART2_CONFIG_DUPLEX (PRU_SUART_HALF_TX | \
> + PRU_SUART_HALF_RX)
> +#define PRU_SUART2_CONFIG_RX_SER (PRU_SUART_SERIALIZER_9)
> +#define PRU_SUART2_CONFIG_TX_SER (PRU_SUART_SERIALIZER_10)
> +
> +#define PRU_SUART3_CONFIG_DUPLEX (PRU_SUART_HALF_TX | \
> + PRU_SUART_HALF_RX)
> +#define PRU_SUART3_CONFIG_RX_SER (PRU_SUART_SERIALIZER_13)
> +#define PRU_SUART3_CONFIG_TX_SER (PRU_SUART_SERIALIZER_14)
> +
> +#define PRU_SUART4_CONFIG_DUPLEX (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#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 (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#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 (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#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 (PRU_SUART_HALF_TX_DISABLED | \
> + PRU_SUART_HALF_RX_DISABLED)
> +#define PRU_SUART7_CONFIG_RX_SER (PRU_SUART_SERIALIZER_NONE)
> +#define PRU_SUART7_CONFIG_TX_SER (PRU_SUART_SERIALIZER_NONE)
> +
> +#define SUART_NUM_OF_CHANNELS_PER_SUART 2
> +#define SUART_NUM_OF_BYTES_PER_CHANNEL 16
> +
> +#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)
> +#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
> +
> +#define SUART_DEFAULT_OVRSMPL_OFFSET 26
> +#define SUART_CHN_OFFSET 31
> +#define SERIALIZER_OFFSET 8
> +
> +#if (SUART_DEFAULT_OVRSMPL == SUART_16X_OVRSMPL)
> +#define SUART_DEFAULT_BAUD 57600
> +#else
> +#define SUART_DEFAULT_BAUD 115200
> +#endif
> +
> +#define PRU_MODE_INVALID 0x0
> +#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)
> +
> +/* MCASP */
> +
> +#define OMAPL_MCASP_PFUNC_AFSR_MASK (0x80000000u)
> +#define OMAPL_MCASP_PFUNC_AFSR_SHIFT (0x0000001Fu)
> +#define OMAPL_MCASP_PFUNC_AFSR_RESETVAL (0x00000000u)
> +/* AFSR Tokens */
> +#define OMAPL_MCASP_PFUNC_AFSR_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AFSR_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AHCLKR_MASK (0x40000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKR_SHIFT (0x0000001Eu)
> +#define OMAPL_MCASP_PFUNC_AHCLKR_RESETVAL (0x00000000u)
> +/* AHCLKR Tokens */
> +#define OMAPL_MCASP_PFUNC_AHCLKR_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKR_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_ACLKR_MASK (0x20000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKR_SHIFT (0x0000001Du)
> +#define OMAPL_MCASP_PFUNC_ACLKR_RESETVAL (0x00000000u)
> +/* ACLKR Tokens */
> +#define OMAPL_MCASP_PFUNC_ACLKR_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKR_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AFSX_MASK (0x10000000u)
> +#define OMAPL_MCASP_PFUNC_AFSX_SHIFT (0x0000001Cu)
> +#define OMAPL_MCASP_PFUNC_AFSX_RESETVAL (0x00000000u)
> +/* AFSX Tokens */
> +#define OMAPL_MCASP_PFUNC_AFSX_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AFSX_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AHCLKX_MASK (0x08000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKX_SHIFT (0x0000001Bu)
> +#define OMAPL_MCASP_PFUNC_AHCLKX_RESETVAL (0x00000000u)
> +/* AHCLKX Tokens */
> +#define OMAPL_MCASP_PFUNC_AHCLKX_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AHCLKX_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_ACLKX_MASK (0x04000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKX_SHIFT (0x0000001Au)
> +#define OMAPL_MCASP_PFUNC_ACLKX_RESETVAL (0x00000000u)
> +/* ACLKX Tokens */
> +#define OMAPL_MCASP_PFUNC_ACLKX_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_ACLKX_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AMUTE_MASK (0x02000000u)
> +#define OMAPL_MCASP_PFUNC_AMUTE_SHIFT (0x00000019u)
> +#define OMAPL_MCASP_PFUNC_AMUTE_RESETVAL (0x00000000u)
> +/* AMUTE Tokens */
> +#define OMAPL_MCASP_PFUNC_AMUTE_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AMUTE_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR15_MASK (0x00008000u)
> +#define OMAPL_MCASP_PFUNC_AXR15_SHIFT (0x0000000Fu)
> +#define OMAPL_MCASP_PFUNC_AXR15_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR15_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR15_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR14_MASK (0x00004000u)
> +#define OMAPL_MCASP_PFUNC_AXR14_SHIFT (0x0000000Eu)
> +#define OMAPL_MCASP_PFUNC_AXR14_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR14_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR14_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR13_MASK (0x00002000u)
> +#define OMAPL_MCASP_PFUNC_AXR13_SHIFT (0x0000000Du)
> +#define OMAPL_MCASP_PFUNC_AXR13_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR13_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR13_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR12_MASK (0x00001000u)
> +#define OMAPL_MCASP_PFUNC_AXR12_SHIFT (0x0000000Cu)
> +#define OMAPL_MCASP_PFUNC_AXR12_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR12_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR12_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR11_MASK (0x00000800u)
> +#define OMAPL_MCASP_PFUNC_AXR11_SHIFT (0x0000000Bu)
> +#define OMAPL_MCASP_PFUNC_AXR11_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR11_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR11_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR10_MASK (0x00000400u)
> +#define OMAPL_MCASP_PFUNC_AXR10_SHIFT (0x0000000Au)
> +#define OMAPL_MCASP_PFUNC_AXR10_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR10_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR10_GPIO (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_AXR9_MASK (0x00000200u)
> +#define OMAPL_MCASP_PFUNC_AXR9_SHIFT (0x00000009u)
> +#define OMAPL_MCASP_PFUNC_AXR9_RESETVAL (0x00000000u)
> +/* AXR9 Token */
> +#define OMAPL_MCASP_PFUNC_AXR9_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR9_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR8_MASK (0x00000100u)
> +#define OMAPL_MCASP_PFUNC_AXR8_SHIFT (0x00000008u)
> +#define OMAPL_MCASP_PFUNC_AXR8_RESETVAL (0x00000000u)
> +/* AXR8 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR8_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR8_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR7_MASK (0x00000080u)
> +#define OMAPL_MCASP_PFUNC_AXR7_SHIFT (0x00000007u)
> +#define OMAPL_MCASP_PFUNC_AXR7_RESETVAL (0x00000000u)
> +/* AXR7 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR7_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR7_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR6_MASK (0x00000040u)
> +#define OMAPL_MCASP_PFUNC_AXR6_SHIFT (0x00000006u)
> +#define OMAPL_MCASP_PFUNC_AXR6_RESETVAL (0x00000000u)
> +/* AXR6 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR6_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR6_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR5_MASK (0x00000020u)
> +#define OMAPL_MCASP_PFUNC_AXR5_SHIFT (0x00000005u)
> +#define OMAPL_MCASP_PFUNC_AXR5_RESETVAL (0x00000000u)
> +/* AXR5 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR5_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR5_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR4_MASK (0x00000010u)
> +#define OMAPL_MCASP_PFUNC_AXR4_SHIFT (0x00000004u)
> +#define OMAPL_MCASP_PFUNC_AXR4_RESETVAL (0x00000000u)
> +/* AXR4 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR4_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR4_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR3_MASK (0x00000008u)
> +#define OMAPL_MCASP_PFUNC_AXR3_SHIFT (0x00000003u)
> +#define OMAPL_MCASP_PFUNC_AXR3_RESETVAL (0x00000000u)
> +/* AXR3 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR3_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR3_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR2_MASK (0x00000004u)
> +#define OMAPL_MCASP_PFUNC_AXR2_SHIFT (0x00000002u)
> +#define OMAPL_MCASP_PFUNC_AXR2_RESETVAL (0x00000000u)
> +/* AXR2 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR2_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR2_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR1_MASK (0x00000002u)
> +#define OMAPL_MCASP_PFUNC_AXR1_SHIFT (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_AXR1_RESETVAL (0x00000000u)
> +/* AXR1 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR1_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR1_GPIO (0x00000001u)
> +
> +#define OMAPL_MCASP_PFUNC_AXR0_MASK (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_AXR0_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR0_RESETVAL (0x00000000u)
> +/* AXR0 Tokens */
> +#define OMAPL_MCASP_PFUNC_AXR0_MCASP (0x00000000u)
> +#define OMAPL_MCASP_PFUNC_AXR0_GPIO (0x00000001u)
> +#define OMAPL_MCASP_PFUNC_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_PDIR_AFSR_MASK (0x80000000u)
> +#define OMAPL_MCASP_PDIR_AFSR_SHIFT (0x0000001Fu)
> +#define OMAPL_MCASP_PDIR_AFSR_RESETVAL (0x00000000u)
> +/* AFSR Tokens */
> +#define OMAPL_MCASP_PDIR_AFSR_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AFSR_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AHCLKR_MASK (0x40000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKR_SHIFT (0x0000001Eu)
> +#define OMAPL_MCASP_PDIR_AHCLKR_RESETVAL (0x00000000u)
> +/* AHCLKR Tokens */
> +#define OMAPL_MCASP_PDIR_AHCLKR_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKR_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_ACLKR_MASK (0x20000000u)
> +#define OMAPL_MCASP_PDIR_ACLKR_SHIFT (0x0000001Du)
> +#define OMAPL_MCASP_PDIR_ACLKR_RESETVAL (0x00000000u)
> +/* ACLKR Tokens */
> +#define OMAPL_MCASP_PDIR_ACLKR_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_ACLKR_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AFSX_MASK (0x10000000u)
> +#define OMAPL_MCASP_PDIR_AFSX_SHIFT (0x0000001Cu)
> +#define OMAPL_MCASP_PDIR_AFSX_RESETVAL (0x00000000u)
> +/* AFSX Tokens */
> +#define OMAPL_MCASP_PDIR_AFSX_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AFSX_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AHCLKX_MASK (0x08000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKX_SHIFT (0x0000001Bu)
> +#define OMAPL_MCASP_PDIR_AHCLKX_RESETVAL (0x00000000u)
> +/* AHCLKX Tokens */
> +#define OMAPL_MCASP_PDIR_AHCLKX_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AHCLKX_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_ACLKX_MASK (0x04000000u)
> +#define OMAPL_MCASP_PDIR_ACLKX_SHIFT (0x0000001Au)
> +#define OMAPL_MCASP_PDIR_ACLKX_RESETVAL (0x00000000u)
> +/* ACLKX Tokens */
> +#define OMAPL_MCASP_PDIR_ACLKX_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_ACLKX_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AMUTE_MASK (0x02000000u)
> +#define OMAPL_MCASP_PDIR_AMUTE_SHIFT (0x00000019u)
> +#define OMAPL_MCASP_PDIR_AMUTE_RESETVAL (0x00000000u)
> +/* AMUTE Tokens */
> +#define OMAPL_MCASP_PDIR_AMUTE_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AMUTE_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR15_MASK (0x00008000u)
> +#define OMAPL_MCASP_PDIR_AXR15_SHIFT (0x0000000Fu)
> +#define OMAPL_MCASP_PDIR_AXR15_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR15_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR15_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR14_MASK (0x00004000u)
> +#define OMAPL_MCASP_PDIR_AXR14_SHIFT (0x0000000Eu)
> +#define OMAPL_MCASP_PDIR_AXR14_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR14_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR14_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR13_MASK (0x00002000u)
> +#define OMAPL_MCASP_PDIR_AXR13_SHIFT (0x0000000Du)
> +#define OMAPL_MCASP_PDIR_AXR13_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR13_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR13_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR12_MASK (0x00001000u)
> +#define OMAPL_MCASP_PDIR_AXR12_SHIFT (0x0000000Cu)
> +#define OMAPL_MCASP_PDIR_AXR12_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR12_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR12_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR11_MASK (0x00000800u)
> +#define OMAPL_MCASP_PDIR_AXR11_SHIFT (0x0000000Bu)
> +#define OMAPL_MCASP_PDIR_AXR11_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR11_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR11_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR10_MASK (0x00000400u)
> +#define OMAPL_MCASP_PDIR_AXR10_SHIFT (0x0000000Au)
> +#define OMAPL_MCASP_PDIR_AXR10_RESETVAL (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR10_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR10_OUTPUT (0x00000001u)
> +#define OMAPL_MCASP_PDIR_AXR9_MASK (0x00000200u)
> +#define OMAPL_MCASP_PDIR_AXR9_SHIFT (0x00000009u)
> +#define OMAPL_MCASP_PDIR_AXR9_RESETVAL (0x00000000u)
> +/* AXR9 Tokens */
> +#define OMAPL_MCASP_PDIR_AXR9_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR9_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR8_MASK (0x00000100u)
> +#define OMAPL_MCASP_PDIR_AXR8_SHIFT (0x00000008u)
> +#define OMAPL_MCASP_PDIR_AXR8_RESETVAL (0x00000000u)
> +/* AXR8 Tokens */
> +#define OMAPL_MCASP_PDIR_AXR8_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR8_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR7_MASK (0x00000080u)
> +#define OMAPL_MCASP_PDIR_AXR7_SHIFT (0x00000007u)
> +#define OMAPL_MCASP_PDIR_AXR7_RESETVAL (0x00000000u)
> +/*----AXR7 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR7_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR7_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR6_MASK (0x00000040u)
> +#define OMAPL_MCASP_PDIR_AXR6_SHIFT (0x00000006u)
> +#define OMAPL_MCASP_PDIR_AXR6_RESETVAL (0x00000000u)
> +/*----AXR6 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR6_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR6_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR5_MASK (0x00000020u)
> +#define OMAPL_MCASP_PDIR_AXR5_SHIFT (0x00000005u)
> +#define OMAPL_MCASP_PDIR_AXR5_RESETVAL (0x00000000u)
> +/*----AXR5 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR5_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR5_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR4_MASK (0x00000010u)
> +#define OMAPL_MCASP_PDIR_AXR4_SHIFT (0x00000004u)
> +#define OMAPL_MCASP_PDIR_AXR4_RESETVAL (0x00000000u)
> +/*----AXR4 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR4_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR4_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR3_MASK (0x00000008u)
> +#define OMAPL_MCASP_PDIR_AXR3_SHIFT (0x00000003u)
> +#define OMAPL_MCASP_PDIR_AXR3_RESETVAL (0x00000000u)
> +/*----AXR3 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR3_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR3_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR2_MASK (0x00000004u)
> +#define OMAPL_MCASP_PDIR_AXR2_SHIFT (0x00000002u)
> +#define OMAPL_MCASP_PDIR_AXR2_RESETVAL (0x00000000u)
> +/*----AXR2 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR2_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR2_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR1_MASK (0x00000002u)
> +#define OMAPL_MCASP_PDIR_AXR1_SHIFT (0x00000001u)
> +#define OMAPL_MCASP_PDIR_AXR1_RESETVAL (0x00000000u)
> +/*----AXR1 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR1_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR1_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_AXR0_MASK (0x00000001u)
> +#define OMAPL_MCASP_PDIR_AXR0_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR0_RESETVAL (0x00000000u)
> +/*----AXR0 Tokens----*/
> +#define OMAPL_MCASP_PDIR_AXR0_INPUT (0x00000000u)
> +#define OMAPL_MCASP_PDIR_AXR0_OUTPUT (0x00000001u)
> +
> +#define OMAPL_MCASP_PDIR_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_MASK (0x00000080u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_SHIFT (0x00000007u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_RESETVAL (0x00000000u)
> +/*----CLKXP Tokens----*/
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_RISINGEDGE (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXP_FALLINGEDGE (0x00000001u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_MASK (0x00000040u)
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_SHIFT (0x00000006u)
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_RESETVAL (0x00000001u)
> +/*----ASYNC Tokens----*/
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_SYNC (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_ASYNC_ASYNC (0x00000001u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_MASK (0x00000020u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_SHIFT (0x00000005u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_RESETVAL (0x00000001u)
> +/*----CLKXM Tokens----*/
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_EXTERNAL (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXM_INTERNAL (0x00000001u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_MASK (0x0000001Fu)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_ACLKXCTL_CLKXDIV_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_ACLKXCTL_RESETVAL (0x00000060u)
> +
> +/* AHCLKXCTL */
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_MASK (0x00008000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_SHIFT (0x0000000Fu)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_RESETVAL (0x00000001u)
> +/*----HCLKXM Tokens----*/
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_EXTERNAL (0x00000000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXM_INTERNAL (0x00000001u)
> +
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_MASK (0x00004000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_SHIFT (0x0000000Eu)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_RESETVAL (0x00000000u)
> +/*----HCLKXP Tokens----*/
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_NOTINVERTED (0x00000000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXP_INVERTED (0x00000001u)
> +
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_MASK (0x00000FFFu)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT (0x00000000u)
> +#define OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_RESETVAL (0x00000000u)
> +
> +#define OMAPL_MCASP_AHCLKXCTL_RESETVAL (0x00008000u)
> +
> +#define MCASP_SUART_GBLCTL (0X00000000)
> +#define MCASP_SUART_RGBLCTL (0X00000000)
> +#define MCASP_SUART_XGBLCTL (0X00000000)
> +#define MCASP_SUART_RMASK_8 (0x000000FF)
> +#define MCASP_SUART_RMASK_16 (0x0000FFFF)
> +#define MCASP_SUART_RFMT_8 (0x0000A038)
> +#define MCASP_SUART_RFMT_16 (0x0000A078)
> +#define MCASP_SUART_FSRM (0X00000002)
> +#define MCASP_SUART_CLKRM_CLKRP (0X000000A0)
> +#define MCASP_SUART_HCLKRP (0X00008000)
> +#define MCASP_SUART_RTDMS0 (0X00000001)
> +#define MCASP_SUART_RSYNCERR (0X00000002)
> +#define MCASP_SUART_RMAX_RPS_256 (0x00FF0008)
> +#define MCASP_SUART_XMASK_0_31 (0X0000FFFF)
> +#define MCASP_SUART_XBUSEL_XSSZ_16_XPAD_0 (0x00002078)
> +#define MCASP_SUART_FSXM (0x00000002)
> +#define MCASP_SUART_CLKXM_ASYNC_CLKXP (0x000000E0)
> +#define MCASP_SUART_HCLKXM (0x00008000)
> +#define MCASP_SUART_XTDMS0 (0X00000001)
> +#define MCASP_SUART_XSYNCERR (0x00000002)
> +#define MCASP_SUART_XMAX_XPS_256 (0x00FF0008)
> +#define MCASP_SUART_SRCTL_DISMOD (0x0000000c)
> +#define MCASP_SUART_DIT_DISABLE (0X00000000)
> +#define MCASP_SUART_LOOPBACK_DISABLE (0x00000000)
> +#define MCASP_SUART_AMUTE_DISABLE (0X00000000)
> +#define MCASP_SUART_XSTAT (0x0000FFFF)
> +#define MCASP_SUART_RSTAT (0x0000FFFF)
> +
> +/* SUART REGS */
> +
> +/* PRU0 DATA RAM base address */
> +#define PRU0_DATARAM_OFFSET (0x0000u)
> +/* PRU1 DATA RAM base address */
> +#define PRU1_DATARAM_OFFSET (0x2000u)
> +
> +/* PRU0 DATA RAM size */
> +#define PRU0_DATARAM_SIZE (0x200u)
> +/* PRU1 DATA RAM size */
> +#define PRU1_DATARAM_SIZE (0x200u)
> +
> +#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 STATUS Register*/
> +#define PRU_SUART_CH_STATUS_EN_BIT_MASK 0x8000
> +
> +/* 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)
> +
> +/* 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)
> +
> +/*
> + *  This enum is used to specify the direction of the channel in UART
> + */
> +enum SUART_CHN_DIR {
> + SUART_CHN_TX = 1,
> + SUART_CHN_RX = 2
> +};
> +
> +/*
> + *  This enum is used to specify the state of the channel in UART. It
> + *  is either enabled or disabled.
> + */
> +enum SUART_CHN_STATE {
> + SUART_CHN_DISABLED = 0,
> + SUART_CHN_ENABLED = 1
> +};
> +
> +enum SUART_EN_BITSPERCHAR {
> + 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
> +};
> +
> +enum SUART_EN_UARTNUM {
> + 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
> +};
> +
> +enum SUART_EN_UARTTYPE {
> + ePRU_SUART_HALF_TX = 1,
> + ePRU_SUART_HALF_RX,
> + ePRU_SUART_FULL_TX_RX,
> + ePRU_SUART_HALF_TX_DISABLED = 4,
> + ePRU_SUART_HALF_RX_DISABLED = 8
> +};
> +
> +enum SUART_EN_TXCHANNEL {
> + 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
> +};
> +
> +enum SUART_EN_RXCHANNEL {
> + 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
> +};
> +
> +enum SUART_EN_UART_STATUS {
> + ePRU_SUART_UART_FREE = 0,
> + ePRU_SUART_UART_IN_USE
> +};
> +
> +struct pru_suart_cnh_cntrl_config1 {
> + u32 mode:2;
> + u32 service_req:1;
> + u32 asp_id:2;
> + u32 reserved1:3;
> + u32 serializer_num:4;
> + u32 reserved2:4;
> + u32 presacler:10;
> + u32 over_sampling:2;
> + u32 framing_mask:1;
> + u32 break_mask:1;
> + u32 timeout_mask:1;
> + u32 reserved3:1;
> +};
> +
> +struct pru_suart_chn_config2_status {
> + u32 bits_per_char:4;
> + u32 reserved1:4;
> + u32 data_len:4;
> + u32 reserved2:4;
> + u32 txrx_ready:1;
> + u32 txrx_complete:1;
> + u32 txrx_error:1;
> + u32 txrx_underrun:1;
> + u32 framing_error:1;
> + u32 break_error:1;
> + u32 timeout_error:1;
> + u32 reserved3:8;
> + u32 chn_state:1;
> +};
> +
> +struct pru_suart_regs_ovly {
> + struct pru_suart_cnh_cntrl_config1 ch_ctrl_config1;
> + struct pru_suart_chn_config2_status ch_config2_txrx_status;
> + u32 ch_txrx_data;
> + u32 reserved1;
> +};
> +
> +struct pru_suart_tx_cntx_priv {
> + u32 asp_xsrctl_base;
> + u32 asp_xbuf_base;
> + u16 buff_addr;
> + u8 buff_size;
> + u8 bits_loaded;
> +};
> +
> +struct pru_suart_rx_cntx_priv {
> + u32 asp_rbuf_base;
> + u32 asp_rsrctl_base;
> + u32 reserved1;
> + u32 reserved2;
> + u32 reserved3;
> + u32 reserved4;
> +};
> +
> +struct suart_config {
> + u8  tx_serializer;
> + u8  rx_serializer;
> + u16 tx_clk_divisor;
> + u16 rx_clk_divisor;
> + u8  tx_bits_per_char;
> + u8  rx_bits_per_char;
> + u8  oversampling;
> + u8  bi_inter_mask;
> + u8  fe_intr_mask;
> +};
> +
> +struct suart_handle {
> + u16 uart_num;
> + u16 uart_type;
> + u16 uart_tx_channel;
> + u16 uart_rx_channel;
> + u16 uart_status;
> +};
> +
> +struct pruss_suart_iomap {
> + void *mcasp_io_addr;
> + void *p_fifo_buff_phys_base;
> + void *p_fifo_buff_virt_base;
> + u32  pru_clk_freq;
> +};
> +
> +/* MCASP */
> +struct omapl_mcasp_regs_ovly {
> + u32 REVID;
> + u32 RSVD0[3];
> + u32 PFUNC;
> + u32 PDIR;
> + u32 PDOUT;
> + u32 PDIN;
> + u32 PDCLR;
> + u32 RSVD1[8];
> + u32 GBLCTL;
> + u32 AMUTE;
> + u32 DLBCTL;
> + u32 DITCTL;
> + u32 RSVD2[3];
> + u32 RGBLCTL;
> + u32 RMASK;
> + u32 RFMT;
> + u32 AFSRCTL;
> + u32 ACLKRCTL;
> + u32 AHCLKRCTL;
> + u32 RTDM;
> + u32 RINTCTL;
> + u32 RSTAT;
> + u32 RSLOT;
> + u32 RCLKCHK;
> + u32 REVTCTL;
> + u32 RSVD3[4];
> + u32 XGBLCTL;
> + u32 XMASK;
> + u32 XFMT;
> + u32 AFSXCTL;
> + u32 ACLKXCTL;
> + u32 AHCLKXCTL;
> + u32 XTDM;
> + u32 XINTCTL;
> + u32 XSTAT;
> + u32 XSLOT;
> + u32 XCLKCHK;
> + u32 XEVTCTL;
> + u32 RSVD4[12];
> + u32 DITCSRA0;
> + u32 DITCSRA1;
> + u32 DITCSRA2;
> + u32 DITCSRA3;
> + u32 DITCSRA4;
> + u32 DITCSRA5;
> + u32 DITCSRB0;
> + u32 DITCSRB1;
> + u32 DITCSRB2;
> + u32 DITCSRB3;
> + u32 DITCSRB4;
> + u32 DITCSRB5;
> + u32 DITUDRA0;
> + u32 DITUDRA1;
> + u32 DITUDRA2;
> + u32 DITUDRA3;
> + u32 DITUDRA4;
> + u32 DITUDRA5;
> + u32 DITUDRB0;
> + u32 DITUDRB1;
> + u32 DITUDRB2;
> + u32 DITUDRB3;
> + u32 DITUDRB4;
> + u32 DITUDRB5;
> + u32 RSVD5[8];
> + u32 SRCTL0;
> + u32 SRCTL1;
> + u32 SRCTL2;
> + u32 SRCTL3;
> + u32 SRCTL4;
> + u32 SRCTL5;
> + u32 SRCTL6;
> + u32 SRCTL7;
> + u32 SRCTL8;
> + u32 SRCTL9;
> + u32 SRCTL10;
> + u32 SRCTL11;
> + u32 SRCTL12;
> + u32 SRCTL13;
> + u32 SRCTL14;
> + u32 SRCTL15;
> + u32 RSVD6[16];
> + u32 XBUF0;
> + u32 XBUF1;
> + u32 XBUF2;
> + u32 XBUF3;
> + u32 XBUF4;
> + u32 XBUF5;
> + u32 XBUF6;
> + u32 XBUF7;
> + u32 XBUF8;
> + u32 XBUF9;
> + u32 XBUF10;
> + u32 XBUF11;
> + u32 XBUF12;
> + u32 XBUF13;
> + u32 XBUF14;
> + u32 XBUF15;
> + u32 RSVD7[16];
> + u32 RBUF0;
> + u32 RBUF1;
> + u32 RBUF2;
> + u32 RBUF3;
> + u32 RBUF4;
> + u32 RBUF5;
> + u32 RBUF6;
> + u32 RBUF7;
> + u32 RBUF8;
> + u32 RBUF9;
> + u32 RBUF10;
> + u32 RBUF11;
> + u32 RBUF12;
> + u32 RBUF13;
> + u32 RBUF14;
> + u32 RBUF15;
> +};
> +
> +/*
> + *  SUART Config regs
> + */
> +struct suart_struct_pru_regs {
> + u16 chn_ctrl;
> + u16 chn_config1;
> + u16 chn_config2;
> + u16 chn_txrx_status;
> + u32 chn_txrx_data;
> +};
> +
> +extern s16 pru_softuart_init(struct device *dev, u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + u8 *pru_suart_emu_code, u32 fw_size,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern s16 pru_softuart_open(struct suart_handle *h_suart);
> +
> +extern s16 pru_softuart_close(struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_setbaud(struct device *dev,
> + struct suart_handle *h_uart,
> + u16 tx_clk_divisor, u16 rx_clk_divisor);
> +
> +extern s16 pru_softuart_setdatabits(struct device *dev,
> + struct suart_handle *h_uart,
> + u16 tx_data_bits, u16 rx_data_bits);
> +
> +extern s16 pru_softuart_setconfig(struct device *dev,
> + struct suart_handle *h_uart,
> + struct suart_config *config_uart);
> +
> +extern s16 pru_softuart_getconfig(struct device *dev,
> + struct suart_handle *h_uart,
> + struct suart_config *config_uart);
> +
> +extern s32 pru_softuart_pending_tx_request(struct device *dev);
> +
> +extern s16 pru_softuart_write(struct device *dev,
> + struct suart_handle *h_uart,
> + u32 *pt_tx_data_buf, u16 data_len);
> +
> +extern s16 pru_softuart_read(struct device *dev,
> + struct suart_handle *h_uart,
> + u32 *pt_data_buf, u16 data_len);
> +
> +extern s32 suart_intr_clrmask(struct device *dev, u16 uart_num,
> + u32 txrxmode,
> + u32 intrmask);
> +
> +extern s16 pru_softuart_clr_tx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_tx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_clr_rx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_rx_status(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_isrstatus(struct device *dev, u16 uart_num,
> + u16 *txrx_flag);
> +
> +extern s32 pru_intr_clr_isrstatus(struct device *dev, u16 uart_num,
> + u32 txrxmode);
> +
> +extern s32 suart_intr_getmask(struct device *dev, u16 uart_num,
> + u32 txrxmode,
> + u32 intrmask);
> +
> +extern s32 suart_intr_setmask(struct device *dev, u16 uart_num,
> + u32 txrxmode, u32 intrmask);
> +
> +extern s16 pru_softuart_get_tx_data_len(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 pru_softuart_get_rx_data_len(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s16 suart_arm_to_pru_intr(struct device *dev, u16 uart_num);
> +
> +extern void pru_mcasp_deinit(void);
> +
> +extern s16 pru_softuart_read_data(struct device *dev,
> + struct suart_handle *h_uart,
> + u8 *p_data_buffer, s32 max_len,
> + u32 *pdata_read);
> +
> +extern s16 pru_softuart_stop_receive(struct device *dev,
> + struct suart_handle *h_uart);
> +
> +extern s32 suart_pru_to_host_intr_enable(struct device *dev,
> + u16 uart_num,
> + u32 txrxmode, s32 flag);
> +
> +extern void pru_set_fifo_timeout(struct device *dev, s16 timeout);
> +
> +extern void suart_mcasp_config(u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern void suart_mcasp_reset(struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern short suart_asp_baud_set(u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern short suart_asp_serializer_deactivate(u16 sr_num,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +extern void suart_mcasp_tx_serialzier_set(u32 serializer_num,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +#endif
> diff --git a/drivers/tty/serial/pruss_suart_api.c 
> b/drivers/tty/serial/pruss_suart_api.c
> new file mode 100644
> index 0000000..b483b90
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart_api.c
> @@ -0,0 +1,1757 @@
> +/*
> + * 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 <linux/mfd/da8xx/da8xx_pru.h>
> +#include <linux/io.h>
> +#include <mach/hardware.h>
> +#include "pruss_suart.h"
> +
> +static u8 uart_statu_table[8];
> +static struct pruss_suart_iomap suart_iomap;
> +
> +static u32 uart_rx[8] = {PRU_SUART0_CONFIG_RX_SER, 
> PRU_SUART1_CONFIG_RX_SER,
> + PRU_SUART2_CONFIG_RX_SER, PRU_SUART3_CONFIG_RX_SER,
> + PRU_SUART4_CONFIG_RX_SER, PRU_SUART5_CONFIG_RX_SER,
> + PRU_SUART6_CONFIG_RX_SER, PRU_SUART7_CONFIG_RX_SER};
> +
> +static u32 uart_tx[8] = {PRU_SUART0_CONFIG_TX_SER, 
> PRU_SUART1_CONFIG_TX_SER,
> + PRU_SUART2_CONFIG_TX_SER, PRU_SUART3_CONFIG_TX_SER,
> + PRU_SUART4_CONFIG_TX_SER, PRU_SUART5_CONFIG_TX_SER,
> + PRU_SUART6_CONFIG_TX_SER, PRU_SUART7_CONFIG_TX_SER};
> +
> +static u32 uart_config[8] = {PRU_SUART0_CONFIG_DUPLEX, 
> PRU_SUART1_CONFIG_DUPLEX,
> + PRU_SUART2_CONFIG_DUPLEX, PRU_SUART3_CONFIG_DUPLEX,
> + PRU_SUART4_CONFIG_DUPLEX, PRU_SUART5_CONFIG_DUPLEX,
> + PRU_SUART6_CONFIG_DUPLEX, PRU_SUART7_CONFIG_DUPLEX};
> +
> +static  s16 pru_softuart_clr_rx_fifo(struct device *dev,
> + struct suart_handle *h_uart);
> +static s16 arm_to_pru_intr_init(struct device *dev);
> +
> +#if (PRU_ACTIVE == BOTH_PRU)
> +static void pru_set_ram_data(struct device *dev,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 datatowrite;
> + u32 i;
> + struct pru_suart_regs_ovly *pru_suart_regs = PRU0_DATARAM_OFFSET;
> + u32 *p_sr_ctl_addr = (u32 *)(pruss_ioaddr->mcasp_io_addr + 0x180);
> + struct pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
> + struct pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
> +
> + /* RX PRU - 0 Chanel 0-7 context information */
> + for (i = 0; i < 8; i++, pru_suart_regs++) {
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_RX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_rx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> + if ((uart_config[i] & PRU_SUART_HALF_RX_DISABLED) ==
> + PRU_SUART_HALF_RX_DISABLED) {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_RX_MODE, p_sr_ctl_addr +
> + uart_rx[i]);
> + }
> + /*
> + * RX is active by default, write the dummy received data at
> + * PRU RAM addr 0x1FC to avoid memory corruption.
> + */
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_txrx_data,
> + 0xFFFF, RX_DEFAULT_DATA_DUMP_ADDR);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 0);
> + /* SUART1 RX context base addr */
> + pru_suart_rx_priv = (struct pru_suart_rx_cntx_priv *)
> + (PRU0_DATARAM_OFFSET + (0x090 + (i * 0x020)));
> + datatowrite = (MCASP_RBUF_BASE_ADDR + (uart_rx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rbuf_base,
> + &datatowrite, 1);
> + datatowrite = (MCASP_SRCTL_BASE_ADDR + (uart_rx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rsrctl_base,
> + &datatowrite, 1);
> + }
> +
> + /* ****************** PRU1 RAM BASE ADDR ************************ */
> + pru_suart_regs = (struct pru_suart_regs_ovly *) PRU1_DATARAM_OFFSET;
> +
> + /* ******************* TX PRU - 1  *********************** */
> + /* Channel 0-7 context information */
> + for (i = 0; i < 8; i++, pru_suart_regs++) {
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_TX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_tx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> + if ((uart_config[i] & PRU_SUART_HALF_TX_DISABLED) ==
> + PRU_SUART_HALF_TX_DISABLED) {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_TX_MODE,
> + p_sr_ctl_addr + uart_tx[i]);
> + }
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 1);
> + /* SUART1 TX context base addr */
> + pru_suart_tx_priv = (struct pru_suart_tx_cntx_priv *)
> + (PRU1_DATARAM_OFFSET + (0x0B0 + (i * 0x02C)));
> + datatowrite = (MCASP_SRCTL_BASE_ADDR + (uart_tx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xsrctl_base,
> + &datatowrite, 1);
> + datatowrite = (MCASP_XBUF_BASE_ADDR + (uart_tx[i] << 2));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xbuf_base,
> + &datatowrite, 1);
> + /* SUART1 TX formatted data base addr */
> + datatowrite = (0x0090 + (i * 0x002C));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->buff_addr,
> + &datatowrite, 1);
> + }
> +}
> +#else
> +static void pru_set_ram_data(struct device *dev,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> +
> + struct pru_suart_regs_ovly *pru_suart_regs =
> + (struct pru_suart_regs_ovly *)pruss_ioaddr->pru_io_addr;
> + u32 i;
> + u32 *p_sr_ctl_addr = (u32 *)(pruss_ioaddr->mcasp_io_addr + 0x180);
> + struct pru_suart_tx_cntx_priv *pru_suart_tx_priv = NULL;
> + struct pru_suart_rx_cntx_priv *pru_suart_rx_priv = NULL;
> +
> + /* ***************** UART 0  ************************ */
> + /* Channel 0 context information is Tx */
> + for (i = 0; i < 4; i++, pru_suart_regs++) {
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_TX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_tx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> + if ((uart_config[i] & PRU_SUART_HALF_TX_DISABLED) ==
> + PRU_SUART_HALF_TX_DISABLED){
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_TX_MODE,
> + p_sr_ctl_addr + uart_tx[i]);
> + }
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 1);
> + /* SUART1 TX context base addr */
> + pru_suart_tx_priv = (struct pru_suart_tx_cntx_priv *)
> + (PRU0_DATARAM_OFFSET + (0x0B0 + (i * 0x50)));
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xsrctl_base,
> + (MCASP_SRCTL_BASE_ADDR + (uart_tx[i] << 2)), 1);
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->asp_xbuf_base,
> + (MCASP_XBUF_BASE_ADDR + (uart_tx[i] << 2)), 1);
> + /* SUART1 TX formatted data base addr */
> + pruss_writel(dev, (u32) &pru_suart_tx_priv->buff_addr,
> + (0x0090 + (i * 0x050)), 1);
> +
> + /* Channel 1 is Rx context information */
> + pru_suart_regs++;
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + 0x3, SUART_CHN_RX);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0xF << SERIALIZER_OFFSET),
> + ((0xF & uart_rx[i]) << SERIALIZER_OFFSET));
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_ctrl_config1,
> + (0x3 << SUART_DEFAULT_OVRSMPL_OFFSET),
> + (SUART_DEFAULT_OVRSMPL <<
> + SUART_DEFAULT_OVRSMPL_OFFSET));
> + pruss_rmwl(dev,
> + (u32) &pru_suart_regs->ch_config2_txrx_status,
> + 0xF, 8);
> +
> + if ((uart_config[i] & PRU_SUART_HALF_RX_DISABLED) ==
> + PRU_SUART_HALF_RX_DISABLED) {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_DISABLED << SUART_CHN_OFFSET));
> + } else {
> + pruss_rmwl(dev, (u32)
> + &pru_suart_regs->ch_config2_txrx_status,
> + (0x1 << SUART_CHN_OFFSET),
> + (SUART_CHN_ENABLED << SUART_CHN_OFFSET));
> + __raw_writel(MCASP_SRCTL_RX_MODE,
> + p_sr_ctl_addr + uart_rx[i]);
> + }
> + /* RX is active by default, write the dummy received data
> + * at PRU RAM addr 0x1FC to avoid memory corruption
> + */
> + pruss_rmwl(dev, (u32) &pru_suart_regs->ch_txrx_data,
> + 0xFFFF, RX_DEFAULT_DATA_DUMP_ADDR);
> + pruss_rmwl(dev, (u32) &pru_suart_regs->reserved1,
> + 0xFFFF, 0);
> + /* SUART1 RX context base addr */
> + pru_suart_rx_priv = (struct pru_suart_rx_cntx_priv *)
> + (PRU0_DATARAM_OFFSET + (0x0C0 + (i * 0x50)));
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rbuf_base,
> + (MCASP_RBUF_BASE_ADDR + (uart_rx[i] << 2)), 1);
> + pruss_writel(dev, (u32) &pru_suart_rx_priv->asp_rsrctl_base,
> + (MCASP_SRCTL_BASE_ADDR + (uart_rx[i] << 2)), 1);
> + }
> +}
> +#endif
> +
> +static void pru_set_rx_tx_mode(struct device *dev, u32 pru_mode, u32 
> pru_num)
> +{
> +
> + u32 pru_offset;
> +
> + if (pru_num == PRUSS_NUM0)
> + pru_offset = PRU_SUART_PRU0_RX_TX_MODE;
> + else if (pru_num == PRUSS_NUM1)
> + pru_offset = PRU_SUART_PRU1_RX_TX_MODE;
> + else
> + return;
> + pruss_writeb(dev, pru_offset, (u8 *) &pru_mode, 1);
> +}
> +
> +static void pru_set_delay_count(struct device *dev, u32 pru_freq)
> +{
> + u32 delay_cnt;
> +
> + if (pru_freq == PRU_CLK_228)
> + delay_cnt = 5;
> + else if (pru_freq == PRU_CLK_186)
> + delay_cnt = 5;
> + else
> + delay_cnt = 3;
> +
> + /* PRU 0 */
> + pruss_writeb(dev, PRU_SUART_PRU0_DELAY_OFFSET,
> + (u8 *) &delay_cnt, 1);
> +
> + /* PRU 1 */
> + pruss_writeb(dev, PRU_SUART_PRU1_DELAY_OFFSET,
> + (u8 *) &delay_cnt, 1);
> +}
> +
> +static s32 suart_set_pru_id(struct device *dev, u32 pru_no)
> +{
> + u32 offset;
> + u8 reg_val = 0;
> +
> + if (PRUSS_NUM0 == pru_no)
> + offset = PRU_SUART_PRU0_ID_ADDR;
> + else if (PRUSS_NUM1 == pru_no)
> + offset = PRU_SUART_PRU1_ID_ADDR;
> + else
> + return -EINVAL;
> +
> + reg_val = pru_no;
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 1);
> +
> + return 0;
> +}
> +
> +/*
> + * suart Initialization routine
> + */
> +s16 pru_softuart_init(struct device *dev, u32 tx_baud_value,
> + u32 rx_baud_value, u32 oversampling,
> + u8 *pru_suart_emu_code, u32 fw_size,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 datatowrite[128] = {0};
> + s16 status = 0;
> + s16 idx;
> + s16 retval;
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) &&
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH))
> + return -EINVAL;
> +
> + suart_iomap.mcasp_io_addr = pruss_ioaddr->mcasp_io_addr;
> + suart_iomap.p_fifo_buff_phys_base =
> + pruss_ioaddr->p_fifo_buff_phys_base;
> + suart_iomap.p_fifo_buff_virt_base =
> + pruss_ioaddr->p_fifo_buff_virt_base;
> + suart_iomap.pru_clk_freq = pruss_ioaddr->pru_clk_freq;
> + /* Configure McASP0  */
> + suart_mcasp_config(tx_baud_value,
> + rx_baud_value, oversampling, pruss_ioaddr);
> + pruss_enable(dev, PRUSS_NUM0);
> +
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_enable(dev, PRUSS_NUM1);
> +
> + /* Reset PRU RAM */
> + pruss_writel(dev, PRU0_DATARAM_OFFSET, datatowrite,
> + (PRU0_DATARAM_SIZE / sizeof(int)));
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_writel(dev, PRU1_DATARAM_OFFSET, datatowrite,
> + (PRU1_DATARAM_SIZE / sizeof(int)));
> +
> + pruss_load(dev, PRUSS_NUM0, (u32 *)pru_suart_emu_code,
> + (fw_size / sizeof(u32)));
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_load(dev, PRUSS_NUM1, (u32 *)pru_suart_emu_code,
> + (fw_size / sizeof(u32)));
> +
> + retval = arm_to_pru_intr_init(dev);
> + if (-1 == retval)
> + return status;
> + pru_set_delay_count(dev, pruss_ioaddr->pru_clk_freq);
> + suart_set_pru_id(dev, PRUSS_NUM0);
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + suart_set_pru_id(dev, PRUSS_NUM1);
> +
> + pru_set_rx_tx_mode(dev, PRU0_MODE, PRUSS_NUM0);
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pru_set_rx_tx_mode(dev, PRU1_MODE, PRUSS_NUM1);
> +
> + pru_set_ram_data(dev, pruss_ioaddr);
> + pruss_run(dev, PRUSS_NUM0);
> +
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_run(dev, PRUSS_NUM1);
> +
> + /* Initialize uart_statu_table */
> + for (idx = 0; idx < 8; idx++)
> + uart_statu_table[idx] = ePRU_SUART_UART_FREE;
> +
> + return status;
> +}
> +
> +void pru_set_fifo_timeout(struct device *dev, s16 timeout)
> +{
> + pruss_writew(dev, PRU_SUART_PRU0_IDLE_TIMEOUT_OFFSET,
> + &timeout, 1);
> + if (PRU1_MODE != PRU_MODE_INVALID)
> + pruss_writew(dev, PRU_SUART_PRU1_IDLE_TIMEOUT_OFFSET,
> + &timeout, 1);
> +}
> +
> +void pru_mcasp_deinit(void)
> +{
> + suart_mcasp_reset(&suart_iomap);
> +}
> +
> +/* suart Instance open routine  */
> +s16 pru_softuart_open(struct suart_handle *h_suart)
> +{
> + s16 status = 0;
> + u16 uart_num = h_suart->uart_num - 1;
> +
> + if (uart_statu_table[h_suart->uart_num - 1] ==
> + ePRU_SUART_UART_IN_USE) {
> + status = EUSERS;
> + return status;
> + } else {
> + h_suart->uart_type = uart_config[uart_num];
> + h_suart->uart_tx_channel = uart_tx[uart_num];
> + h_suart->uart_rx_channel = uart_rx[uart_num];
> + h_suart->uart_status = ePRU_SUART_UART_IN_USE;
> + uart_statu_table[h_suart->uart_num - 1] =
> + ePRU_SUART_UART_IN_USE;
> + }
> + return status;
> +}
> +
> +/* suart instance close routine */
> +s16 pru_softuart_close(struct suart_handle *h_uart)
> +{
> + s16 status = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + } else {
> + uart_statu_table[h_uart->uart_num - 1] =
> + ePRU_SUART_UART_FREE;
> + /* Reset the Instance to Invalid */
> + h_uart->uart_num = PRU_SUART_UARTx_INVALID;
> + h_uart->uart_status = ePRU_SUART_UART_FREE;
> + }
> + return status;
> +}
> +
> +static s16 search_chnum(u16 uart_num, u16 *ch_num, u32 *pru_offset, u16 
> mode)
> +{
> + *ch_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + *ch_num = (uart_num *
> + SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + if (uart_num <= 4) {
> + *pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else {
> + *pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + *ch_num -= 8;
> + }
> + if (mode == 2)
> + *ch_num = *ch_num + 1;
> +
> + } else if ((mode == 1) || (mode == 2)) {
> + if (mode == 1) {
> + if (PRU0_MODE == PRU_MODE_TX_ONLY)
> + *pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + else if (PRU1_MODE == PRU_MODE_TX_ONLY)
> + *pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if (mode == 2)  {
> + if (PRU0_MODE == PRU_MODE_RX_ONLY)
> + *pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + else if (PRU1_MODE == PRU_MODE_RX_ONLY)
> + *pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + }
> + } else {
> + return 0;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * suart routine for setting relative baud rate
> + */
> +s16 pru_softuart_setbaud(struct device *dev, struct suart_handle *h_uart,
> + u16 tx_clk_divisor, u16 rx_clk_divisor)
> +{
> + u32 offset;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 regval = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /* Set the clock divisor value s32o the McASP */
> + if ((tx_clk_divisor > 385) || (tx_clk_divisor == 0))
> + return -EINVAL;
> + if ((rx_clk_divisor > 385) || (rx_clk_divisor == 0))
> + return -EINVAL;
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + if (tx_clk_divisor != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= (~0x3FF);
> + regval |= tx_clk_divisor;
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> + regval = 0;
> + if (rx_clk_divisor != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= (~0x3FF);
> + regval |= tx_clk_divisor;
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> + return status;
> +}
> +
> +/*
> + * suart routine for setting number of bits per character for a specific 
> uart
> + */
> +s16 pru_softuart_setdatabits(struct device *dev, struct suart_handle 
> *h_uart,
> + u16 tx_data_bits, u16 rx_data_bits)
> +{
> + u32 offset;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u32 reg_val;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /*
> + * NOTE:
> + * The supported data bits are 6,7,8,9,10,11,12 bits per character
> + */
> +
> + if ((tx_data_bits < ePRU_SUART_DATA_BITS6)
> + || (tx_data_bits > ePRU_SUART_DATA_BITS12))
> + return -EINVAL;
> +
> + if ((rx_data_bits < ePRU_SUART_DATA_BITS6)
> + || (rx_data_bits > ePRU_SUART_DATA_BITS12))
> + return -EINVAL;
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + if (tx_data_bits != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 1);
> + reg_val &= ~(0xF);
> + reg_val |= tx_data_bits;
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 1);
> + }
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> + if (rx_data_bits != 0) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 1);
> + reg_val &= ~(0xF);
> + reg_val |= rx_data_bits;
> + pruss_writeb(dev, offset, (u8 *) &rx_data_bits, 1);
> + }
> +
> + return status;
> +}
> +
> +/*
> + * suart routine to configure specific uart
> + */
> +s16 pru_softuart_setconfig(struct device *dev, struct suart_handle 
> *h_uart,
> + struct suart_config *config_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 reg_val = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /*
> + * NOTE:
> + * Dependent baud rate for the given UART,the value MUST BE LESS THAN OR
> + * EQUAL TO 64, preScalarValue <= 64
> + */
> + if ((config_uart->tx_clk_divisor > 384)
> + || (config_uart->rx_clk_divisor > 384)) {
> + return -EINVAL;
> + }
> + if ((config_uart->tx_bits_per_char < 8)
> + || (config_uart->tx_bits_per_char > 14)) {
> + return -EINVAL;
> + }
> + if ((config_uart->rx_bits_per_char < 8)
> + || (config_uart->rx_bits_per_char > 14)) {
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + /* 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
> + * (config_uart->tx_serializer, &suart_iomap);
> + */
> + /* Configuring TX serializer  */
> + if (config_uart->tx_serializer != PRU_SUART_SERIALIZER_NONE) {
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val = reg_val | (config_uart->tx_serializer <<
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val = reg_val | (config_uart->tx_clk_divisor <<
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val = reg_val | (config_uart->tx_bits_per_char <<
> + PRU_SUART_CH_CONFIG2_BITPERCHAR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> + }
> +
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> +
> + /* Configuring the Transmit part of the given UART */
> + if (config_uart->rx_serializer != PRU_SUART_SERIALIZER_NONE) {
> + /* Configuring RX serializer  */
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val = reg_val | (config_uart->rx_serializer <<
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> +
> + /* Configuring RX prescalar value and Oversampling */
> + offset = pru_offset +
> + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val = reg_val | (config_uart->rx_clk_divisor <<
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT) |
> + (config_uart->oversampling <<
> + PRU_SUART_CH_CONFIG1_OVS_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> +
> + /* Configuring RX bits per character value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val = reg_val | (config_uart->rx_bits_per_char <<
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> + }
> + return status;
> +}
> +
> +/*
> + * suart routine for getting the number of bytes transfered
> + */
> +s16 pru_softuart_get_tx_data_len(struct device *dev,
> + struct suart_handle *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 read_value = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &read_value, 2);
> + read_value = ((read_value & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> + return read_value;
> +}
> +
> +/*
> + * suart routine for getting the number of bytes received
> + */
> +s16 pru_softuart_get_rx_data_len(struct device *dev,
> + struct suart_handle *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 read_value = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &read_value, 2);
> + read_value = ((read_value & PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> +
> + return read_value;
> +}
> +
> +/*
> + * suart routine to get the configuration information from a specific 
> uart
> + */
> +s16 pru_softuart_getconfig(struct device *dev,
> + struct suart_handle *h_uart,
> + struct suart_config *config_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 reg_val = 0;
> + s16 status = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> +
> + /*
> + * NOTE:
> + * Dependent baud rate for the given UART,the value MUST BE LESS THAN OR
> + * EQUAL TO 64, preScalarValue <= 64
> + */
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + /* Configuring the Transmit part of the given UART */
> + /* Configuring TX serializer  */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + config_uart->tx_serializer = ((reg_val & PRU_SUART_CH_CTRL_SR_MASK) >>
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> + /* Configuring TX prescalar value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + config_uart->tx_clk_divisor = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> +
> + /* Configuring TX bits per character value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + config_uart->tx_bits_per_char = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK) >>
> + PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> +
> + if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + ch_num++;
> + } else {
> + return 0;
> + }
> + /* Configuring the Transmit part of the given UART */
> + /* Configuring RX serializer  */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + config_uart->rx_serializer = ((reg_val & PRU_SUART_CH_CTRL_SR_MASK) >>
> + PRU_SUART_CH_CTRL_SR_SHIFT);
> +
> + /* Configuring RX prescalar value and oversampling */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG1_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + config_uart->rx_clk_divisor = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> + config_uart->oversampling = ((reg_val &
> + PRU_SUART_CH_CONFIG1_OVS_MASK) >>
> + PRU_SUART_CH_CONFIG1_OVS_SHIFT);
> +
> + /* Configuring RX bits per character value */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + config_uart->rx_bits_per_char = ((reg_val &
> + PRU_SUART_CH_CONFIG1_DIVISOR_MASK)
> + >> PRU_SUART_CH_CONFIG1_DIVISOR_SHIFT);
> +
> + return status;
> +}
> +
> +s32 pru_softuart_pending_tx_request(struct device *dev)
> +{
> + u32 offset = 0;
> + u32 ISR_value = 0;
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> +     || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + return 0;
> + } else if (PRU0_MODE == PRU_MODE_TX_ONLY) {
> + /* Read PRU Interrupt Status Register from PRU */
> + offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
> + pruss_readl(dev, offset, (u32 *)&ISR_value, 1);
> + if ((ISR_value & 0x1) == 0x1)
> + return -EINVAL;
> + } else if (PRU1_MODE == PRU_MODE_TX_ONLY) {
> + /* Read PRU Interrupt Status Register from PRU */
> + offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
> + pruss_readl(dev, offset, (u32 *)&ISR_value, 1);
> + if ((ISR_value & 0x2) == 0x2)
> + return -EINVAL;
> + } else {
> + return 0;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * suart data transmit routine
> + */
> +s16 pru_softuart_write(struct device *dev, struct suart_handle *h_uart,
> + u32 *pt_tx_data_buf, u16 data_len)
> +{
> + u32 offset = 0;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 reg_val = 0;
> + u16 pru_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH))
> + pru_num = h_uart->uart_num;
> + else if (PRU0_MODE == PRU_MODE_TX_ONLY)
> + pru_num = 0;
> + else if (PRU1_MODE == PRU_MODE_TX_ONLY)
> + pru_num = 1;
> + else
> + return 0;
> +
> + /* Writing data length to SUART channel register */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
> + reg_val = reg_val | (data_len << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> +
> + /* Writing the data pos32er to channel TX data pointer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXDATA_OFFSET;
> + pruss_writeb(dev, offset, (u8 *) pt_tx_data_buf, 4);
> +
> + /* Service Request to PRU */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK |
> + PRU_SUART_CH_CTRL_SREQ_MASK);
> + reg_val |= (PRU_SUART_CH_CTRL_TX_MODE <<
> + PRU_SUART_CH_CTRL_MODE_SHIFT) | (PRU_SUART_CH_CTRL_SREQ <<
> + PRU_SUART_CH_CTRL_SREQ_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> +
> + /* generate ARM->PRU event */
> + suart_arm_to_pru_intr(dev, pru_num);
> +
> + return status;
> +}
> +
> +/*
> + * suart data receive routine
> + */
> +s16 pru_softuart_read(struct device *dev, struct suart_handle *h_uart,
> + u32 *ptDataBuf, u16 data_len)
> +{
> + u32 offset = 0;
> + u32 pru_offset;
> + s16 status = 0;
> + u16 ch_num;
> + u16 reg_val = 0;
> + u16 pru_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> + 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 */
> + ch_num = (h_uart->uart_num *
> + SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + pru_num = h_uart->uart_num;
> + } else if (PRU0_MODE == PRU_MODE_RX_ONLY) {
> + pru_num = 0;
> + } else if (PRU1_MODE == PRU_MODE_RX_ONLY) {
> + pru_num = 1;
> + } else {
> + return 0;
> + }
> + /* Writing data length to SUART channel register */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val &= ~PRU_SUART_CH_CONFIG2_DATALEN_MASK;
> + reg_val = reg_val | (data_len << PRU_SUART_CH_CONFIG2_DATALEN_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> +
> + /* Writing the data pos32er to channel RX data pointer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXDATA_OFFSET;
> + pruss_writeb(dev, offset, (u8 *) ptDataBuf, 4);
> +
> + /* Service Request to PRU */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK |
> + PRU_SUART_CH_CTRL_SREQ_MASK);
> + reg_val |= (PRU_SUART_CH_CTRL_RX_MODE <<
> + PRU_SUART_CH_CTRL_MODE_SHIFT) | (PRU_SUART_CH_CTRL_SREQ <<
> + PRU_SUART_CH_CTRL_SREQ_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> +
> + /* enable the timeout s32errupt */
> + suart_intr_setmask(dev, h_uart->uart_num, PRU_RX_INTR,
> + CHN_TXRX_IE_MASK_TIMEOUT);
> +
> + /* generate ARM->PRU event */
> + suart_arm_to_pru_intr(dev, pru_num);
> +
> + return status;
> +}
> +
> +/*
> + * suart routine to read the data from the RX FIFO
> + */
> +s16 pru_softuart_read_data(struct device *dev, struct suart_handle 
> *h_uart,
> + u8 *p_data_buffer, s32 max_len,
> + u32 *pdata_read)
> +{
> + s16 ret_val = 0;
> + u8 *psrc_addr = NULL;
> + u32 data_read = 0;
> + u32 data_len = 0;
> + u32 char_len = 0;
> + u32 offset = 0;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 status = 0;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + /* Get the data pos32er from channel RX data pointer */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXDATA_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &psrc_addr, 4);
> +
>+ /* Reading data length from SUART channel register */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CONFIG2_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &data_len, 2);
> +
> + /* read the character length */
> + char_len = data_len & PRU_SUART_CH_CONFIG2_BITPERCHAR_MASK;
> + char_len -= 2; /* remove the START & STOP bit */
> +
> + data_len &= PRU_SUART_CH_CONFIG2_DATALEN_MASK;
> + data_len = data_len >> PRU_SUART_CH_CONFIG2_DATALEN_SHIFT;
> + data_len++;
> +
> + /* if the character length is greater than 8, then the size doubles */
> + if (char_len > 8)
> + data_len *= 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 = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + if (CHN_TXRX_STATUS_TIMEOUT == (status & CHN_TXRX_STATUS_TIMEOUT)) {
> + /* determine the number of bytes read s32o the FIFO */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_BYTESDONECNTR_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &data_read, 1);
> +
> + /* if the character length is greater than 8,
> + then the size doubles */
> + if (char_len > 8)
> + data_read *= 2;
> +
> +/*
> + * the data corresponding is loaded in second
> + * half during the timeout
> + */
> + if (data_read > data_len) {
> + data_read -= data_len;
> + psrc_addr += data_len;
> + }
> +
> + pru_softuart_clr_rx_fifo(dev, h_uart);
> + } else {
> + data_read = data_len;
> +/*
> + * 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 (status & CHN_TXRX_STATUS_CMPLT)
> + psrc_addr += data_len;
> + }
> +
> + /* we should be copying only max len given by the application */
> + if (data_read > max_len)
> + data_read = max_len;
> +
> +/* evaluate the virtual address of the FIFO address
> + * based on the physical addr
> + */
> + psrc_addr = (u8 *)((u32) psrc_addr -
> + (u32) suart_iomap.p_fifo_buff_phys_base +
> + (u32) suart_iomap.p_fifo_buff_virt_base);
> +
> + /* Now we have both the data length and the source address. copy */
> + for (offset = 0; offset < data_read; offset++)
> + *p_data_buffer++ = *psrc_addr++;
> + *pdata_read = data_read;
> + ret_val = 0;
> +
> + return ret_val;
> +}
> +
> +/*
> + * 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_stop_receive(struct device *dev, struct suart_handle 
> *h_uart)
> +{
> + u16 ret_status = 0;
> + u32 offset;
> + u32 pru_offset;
> + u16 ch_num;
> + u16 status;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + /* read the existing value of status flag */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> +
> + /* we need to clear the busy bit corresponding to receive channel */
> + status &= ~(CHN_TXRX_STATUS_RDY);
> + pruss_writeb(dev, offset, (u8 *) &status, 1);
> +
> + /* get the serizlizer number being used for this Rx channel */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 2);
> + status &= PRU_SUART_CH_CTRL_SR_MASK;
> + status = status >> PRU_SUART_CH_CTRL_SR_SHIFT;
> +
> + /* we need to de-activate the serializer corresponding to this rx */
> + ret_status = suart_asp_serializer_deactivate(status, &suart_iomap);
> +
> + return ret_status;
> +}
> +
> +/*
> + * suart routine to get the tx status for a specific uart
> + */
> +s16 pru_softuart_get_tx_status(struct device *dev, struct suart_handle 
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +s16 pru_softuart_clr_tx_status(struct device *dev, struct suart_handle 
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 1);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + status &= ~(0x2);
> + pruss_writeb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +/*
> + * suart routine to get the rx status for a specific uart
> + */
> +s16 pru_softuart_get_rx_status(struct device *dev, struct suart_handle 
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +static s16 pru_softuart_clr_rx_fifo(struct device *dev,
> + struct suart_handle *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> + u16 reg_val;
> + u16 uart_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + uart_num = h_uart->uart_num;
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> + if (PRU0_MODE == PRU_MODE_RX_ONLY)
> + uart_num = 0;
> + else if (PRU1_MODE == PRU_MODE_RX_ONLY)
> + uart_num = 1;
> +
> + /* Reset the number of bytes read into the FIFO */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_BYTESDONECNTR_OFFSET;
> + pruss_readw(dev, offset, (u16 *) &reg_val, 1);
> + reg_val &= 0x00;
> + pruss_writew(dev, offset, (u16 *) &reg_val, 1);
> +
> +
> + /* Service Request to PRU */
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_CTRL_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &reg_val, 2);
> + reg_val &= ~(PRU_SUART_CH_CTRL_MODE_MASK | PRU_SUART_CH_CTRL_SREQ_MASK);
> + reg_val |= (PRU_SUART_CH_CTRL_RX_MODE << PRU_SUART_CH_CTRL_MODE_SHIFT) |
> + (PRU_SUART_CH_CTRL_SREQ << PRU_SUART_CH_CTRL_SREQ_SHIFT);
> + pruss_writeb(dev, offset, (u8 *) &reg_val, 2);
> + suart_intr_setmask(dev, h_uart->uart_num, PRU_RX_INTR,
> + CHN_TXRX_IE_MASK_TIMEOUT);
> +
> + /* generate ARM->PRU event */
> + suart_arm_to_pru_intr(dev, uart_num);
> +
> + return status;
> +}
> +
> +s16 pru_softuart_clr_rx_status(struct device *dev, struct suart_handle 
> *h_uart)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 status = 0;
> + u16 ch_num;
> +
> + if (h_uart == NULL) {
> + WARN_ON(1);
> + return -EINVAL;
> + }
> + search_chnum(h_uart->uart_num, &ch_num, &pru_offset, 2);
> +
> + offset = pru_offset + (ch_num * SUART_NUM_OF_BYTES_PER_CHANNEL) +
> + PRU_SUART_CH_TXRXSTATUS_OFFSET;
> + pruss_readb(dev, offset, (u8 *) &status, 1);
> + status &= ~(0x3C);
> + pruss_writeb(dev, offset, (u8 *) &status, 1);
> + return status;
> +}
> +
> +/*
> + * suart_s32r_status_read: Gets the Global Interrupt status register
> + * for the specified SUART.
> + * uart_num < 1 to 6 >
> + * txrx_flag < Indicates TX or RX s32errupt for the uart >
> + */
> +s16 pru_softuart_get_isrstatus(struct device *dev, u16 uart_num, u16 
> *txrx_flag)
> +{
> + u32 intc_offset;
> + u32 ch_num = 0xFF;
> + u32 reg_val = 0;
> + u32 reg_val2 = 0;
> + u32 ISR_value = 0;
> + u32 ack_reg_val = 0;
> + u32 stat_inx_clr_regoffset = 0;
> +
> + /* initialize the status & Flag to known value */
> + *txrx_flag = 0;
> +
> + stat_inx_clr_regoffset = (u32) (PRUSS_INTC_STATIDXCLR & 0xFFFF);
> +
> + /* Read PRU Interrupt Status Register from PRU */
> + intc_offset = (u32) (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
> +
> + pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> + || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* Check if the interrupt occured for Tx */
> + ch_num = uart_num * 2 - 2;
> + reg_val2 = PRU_SUART0_TX_EVT_BIT << ((uart_num - 1) * 2);
> + if (ISR_value & reg_val2) {
> + /* interupt occured for TX */
> + *txrx_flag |= PRU_TX_INTR;
> + /* acknowledge the RX interrupt  */
> + ack_reg_val  = ch_num + PRU_SUART0_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + }
> +
> + /* Check if the interrupt occured for Rx */
> + reg_val2 = PRU_SUART0_RX_EVT_BIT << ((uart_num - 1) * 2);
> + pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
> + if (ISR_value & reg_val2) {
> + /* interupt occured for RX */
> + *txrx_flag |= PRU_RX_INTR;
> + ch_num += 1;
> +
> + /* acknowledge the RX interrupt  */
> + ack_reg_val  = ch_num + PRU_SUART0_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + }
> + } else {
> + ch_num = uart_num - 1;
> + if ((ISR_value & 0x03FC) != 0) {
> + reg_val2 = 1 << (uart_num + 1);
> + if (ISR_value & reg_val2) {
> + /* acknowledge the s32errupt  */
> + ack_reg_val = ch_num + PRU_SUART0_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + *txrx_flag |= PRU_RX_INTR;
> + }
> + }
> + pruss_readl(dev, intc_offset, (u32 *)&ISR_value, 1);
> + if (ISR_value & 0x3FC00) {
> + reg_val2 = 1 << (uart_num + 9);
> + if (ISR_value & reg_val2) {
> + /* acknowledge the s32errupt  */
> + ack_reg_val = ch_num + PRU_SUART4_TX_EVT;
> + pruss_writel(dev, stat_inx_clr_regoffset,
> + (u32 *)&ack_reg_val, 1);
> + *txrx_flag |= PRU_TX_INTR;
> + }
> + }
> + }
> + return reg_val;
> +}
> +
> +s32 pru_intr_clr_isrstatus(struct device *dev, u16 uart_num, u32 
> txrxmode)
> +{
> + u32 offset;
> + u16 txrx_flag = 0;
> + u16 chn_num;
> +
> + chn_num = uart_num - 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 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + if (uart_num <= 4) {
> + /* PRU0 */
> + offset = PRU_SUART_PRU0_ISR_OFFSET + 1;
> + } else {
> + /* PRU1 */
> + offset = PRU_SUART_PRU1_ISR_OFFSET + 1;
> + /* First 8 channel corresponds to PRU0 */
> + chn_num -= 8;
> + }
> + if (2 == txrxmode)
> + chn_num++;
> + } 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 0;
> + }
> +
> + pruss_readb(dev, offset, (u8 *) &txrx_flag, 1);
> + txrx_flag &= ~(0x2);
> + pruss_writeb(dev, offset, (u8 *) &txrx_flag, 1);
> +
> + return 0;
> +}
> +
> +s16 suart_arm_to_pru_intr(struct device *dev, u16 uart_num)
> +{
> + u32 offset;
> + u32 value;
> + s16 retval;
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> +     || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + if ((uart_num > 0) && (uart_num <= 4)) {
> + /* PRU0 SYS_EVT32 */
> + value = 0x20;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + /* PRU1 SYS_EVT33 */
> + value = 0x21;
> + } else {
> + return -EINVAL;
> + }
> + }
> +
> + 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 (uart_num == PRUSS_NUM0) {
> + /* PRU0 SYS_EVT32 */
> + value = 0x20;
> + }
> +
> + if (uart_num == PRUSS_NUM1) {
> + /* PRU0 SYS_EVT33 */
> + value = 0x21;
> + }
> + }
> +
> + offset = (u32) (PRUSS_INTC_STATIDXSET & 0xFFFF);
> + retval = pruss_writel(dev, offset, (u32 *)&value, 1);
> + if (retval == -1)
> + return -1;
> + return 0;
> +}
> +
> +static s16 arm_to_pru_intr_init(struct device *dev)
> +{
> + u32 value;
> + u32 int_offset;
> +
> + /* Clear all the host interrupts */
> + for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
> + int_offset++)
> + pruss_idx_writel(dev, PRUSS_INTC_HSTINTENIDXCLR, int_offset);
> +
> + /* Enable the global s32errupt */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_GLBLEN & 0xFFFF), 0, 1);
> +
> + /* Enable the Host interrupts for all host channels */
> + for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
> + int_offset++)
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HSTINTENIDXSET & 0xFFFF),
> + 0, int_offset);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP0 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP0_CHAN);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP1 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP1_CHAN);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_HOSTMAP2 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_HOSTMAP2_CHAN);
> +
> + /* MAP Channel 0 to SYS_EVT31 */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP7 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP7_SYS_EVT31);
> +
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH)
> +     || (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + /* Sets the channels for the system interrupt */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP8 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP8_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP9 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP9_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP10 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP10_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP11 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP11_FULL);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP12 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP12_FULL);
> + }
> + 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 channels for the system interrupt */
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP8 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP8_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP9 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP9_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP10 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP10_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP11 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP11_HALF);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_CHANMAP12 & 0xFFFF),
> + PRU_INTC_REGMAP_MASK, PRU_INTC_CHANMAP12_HALF);
> + }
> +
> + /* Clear required set of system events
> + * and enable them using indexed register
> + */
> + for (int_offset = 0; int_offset < 18; int_offset++) {
> + value = 32 + int_offset;
> + pruss_idx_writel(dev, PRUSS_INTC_STATIDXCLR, value);
> + }
> +
> + /* enable only the HOST to PRU interrupts and let the PRU to Host events
> + * enabled by the separate API on demand basis.
> + */
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 31);
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 32);
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 33);
> + pruss_idx_writel(dev, PRUSS_INTC_ENIDXSET, 50);
> + pruss_rmwl(dev, (u32) (PRUSS_INTC_GLBLEN & 0xFFFF), 0, 1);
> +
> + /* Enable the Host interrupts for all host channels */
> + for (int_offset = 0; int_offset <= PRUSS_INTC_HOSTINTLVL_MAX;
> + int_offset++)
> + pruss_idx_writel(dev, PRUSS_INTC_HSTINTENIDXSET, int_offset);
> +
> + return 0;
> +}
> +
> +s32 suart_pru_to_host_intr_enable(struct device *dev, u16 uart_num,
> + u32 txrxmode, s32 flag)
> +{
> + s32 ret_val = 0;
> + u32 offset;
> + u32 chn_num;
> + u32 value;
> + s16 retval = 0;
> +
> + if (uart_num > 8)
> + return -EINVAL;
> +
> + chn_num = uart_num - 1;
> + if ((PRU0_MODE == PRU_MODE_RX_TX_BOTH) ||
> + (PRU1_MODE == PRU_MODE_RX_TX_BOTH)) {
> + chn_num = (uart_num * 2) - 2;
> + if (2 == txrxmode) /* Rx mode */
> + chn_num++;
> + value = 34 + chn_num;
> + } else if ((PRU_MODE_RX_ONLY == txrxmode)
> + && (PRU0_MODE == PRU_MODE_RX_ONLY))
> + value = 34 + chn_num;
> + else if ((PRU_MODE_RX_ONLY == txrxmode)
> + && (PRU1_MODE == PRU_MODE_RX_ONLY))
> + value = 42 + chn_num;
> + else if ((PRU_MODE_TX_ONLY == txrxmode)
> + && (PRU0_MODE == PRU_MODE_TX_ONLY))
> + value = 34 + chn_num;
> + else if ((PRU_MODE_TX_ONLY == txrxmode)
> + && (PRU1_MODE == PRU_MODE_TX_ONLY))
> + value = 42 + chn_num;
> + else
> + return -1;
> +
> + if (true == flag) {
> + offset = (u32) (PRUSS_INTC_ENIDXSET & 0xFFFF);
> + retval = pruss_writel(dev, offset, (u32 *)&value, 1);
> + if (retval == -1)
> + return -1;
> + } else {
> + offset = (u32) (PRUSS_INTC_ENIDXCLR & 0xFFFF);
> + retval = pruss_writel(dev, offset, (u32 *)&value, 1);
> + if (retval == -1)
> + return -1;
> + }
> + return ret_val;
> +}
> +
> +s32 suart_intr_setmask(struct device *dev, u16 uart_num,
> + u32 txrxmode, u32 rmask)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u32 regval = 0;
> + u32 chn_num;
> +
> + chn_num = uart_num - 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 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> +
> + if ((uart_num > 0) && (uart_num <= 4)) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + chn_num -= 8;
> + } else {
> + return -EINVAL;
> + }
> + if (2 == txrxmode) { /* rx mode */
> + chn_num++;
> + }
> + } else if (PRU0_MODE == txrxmode) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else {
> + return 0;
> + }
> + regval = 1 << chn_num;
> + if (CHN_TXRX_IE_MASK_CMPLT == (rmask & CHN_TXRX_IE_MASK_CMPLT))
> + pruss_rmww(dev, offset, regval, regval);
> +
> + if ((rmask & SUART_GBL_INTR_ERR_MASK) ==
> + SUART_GBL_INTR_ERR_MASK) {
> + regval = SUART_GBL_INTR_ERR_MASK;
> + pruss_rmww(dev, offset, regval, regval);
> + }
> +
> + offset = pru_offset +
> + (chn_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_CONFIG1_OFFSET;
> + /* Framing Error Interrupt Masked */
> + if ((rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_FE);
> + regval |= CHN_TXRX_IE_MASK_FE;
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> +
> + /* Break Indicator Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_BI == (rmask & CHN_TXRX_IE_MASK_BI)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_BI);
> + regval |= CHN_TXRX_IE_MASK_BI;
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> +
> + /* Timeout error Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_TIMEOUT ==
> + (rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
> + regval |= CHN_TXRX_IE_MASK_TIMEOUT;
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> + return 0;
> +}
> +
> +s32 suart_intr_clrmask(struct device *dev, u16 uart_num,
> + u32 txrxmode, u32 rmask)
> +{
> + u32 offset;
> + u32 pru_offset;
> + u16 regval = 0;
> + u16 chn_num;
> +
> + chn_num = uart_num - 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 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> + if ((uart_num > 0) && (uart_num <= 4)) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + /* PRU1 */
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + /* First 8 channel corresponds to PRU0 */
> + chn_num -= 8;
> + } else {
> + return -EINVAL;
> + }
> + if (2 == txrxmode) { /* rx mode */
> + chn_num++;
> + }
> + } else if (PRU0_MODE == txrxmode) {
> + pru_offset = PRU_SUART_PRU0_CH0_OFFSET;
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + pru_offset = PRU_SUART_PRU1_CH0_OFFSET;
> + } else {
> + return 0;
> + }
> + regval = 1 << chn_num;
> + if (CHN_TXRX_IE_MASK_CMPLT == (rmask & CHN_TXRX_IE_MASK_CMPLT))
> + pruss_rmww(dev, offset, regval, 0);
> +
> + if ((rmask & SUART_GBL_INTR_ERR_MASK) == SUART_GBL_INTR_ERR_MASK)
> + pruss_rmww(dev, offset, SUART_GBL_INTR_ERR_MASK, 0);
> +
> + offset = pru_offset +
> + (chn_num * SUART_NUM_OF_BYTES_PER_CHANNEL)
> + + PRU_SUART_CH_CONFIG1_OFFSET;
> +
> + /* Framing Error Interrupt Masked */
> + if ((rmask & CHN_TXRX_IE_MASK_FE) == CHN_TXRX_IE_MASK_FE) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_FE);
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> +
> + /* Break Indicator Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_BI == (rmask & CHN_TXRX_IE_MASK_BI)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_BI);
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> +
> + /* Timeout error Interrupt Masked */
> + if (CHN_TXRX_IE_MASK_TIMEOUT ==
> + (rmask & CHN_TXRX_IE_MASK_TIMEOUT)) {
> + regval = 0;
> + pruss_readb(dev, offset, (u8 *) &regval, 2);
> + regval &= ~(CHN_TXRX_IE_MASK_TIMEOUT);
> + pruss_writeb(dev, offset, (u8 *) &regval, 2);
> + }
> +
> + return 0;
> +}
> +
> +s32 suart_intr_getmask(struct device *dev, u16 uart_num, u32 txrxmode,
> + u32 rmask)
> +{
> + u16 chn_num;
> + u32 offset;
> + u16 txrx_flag;
> + u16 regval = 1;
> +
> + chn_num = uart_num - 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 */
> + chn_num = (uart_num * SUART_NUM_OF_CHANNELS_PER_SUART) - 2;
> +
> + if ((uart_num > 0) && (uart_num <= 4)) {
> +
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if ((uart_num > 4) && (uart_num <= 8)) {
> + /* PRU1 */
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + /* First 8 channel corresponds to PRU0 */
> + chn_num -= 8;
> + } else {
> + return -EINVAL;
> + }
> +
> + if (2 == txrxmode) { /* rx mode */
> + chn_num++;
> + }
> + } else if (PRU0_MODE == txrxmode) {
> + offset = PRU_SUART_PRU0_IMR_OFFSET;
> + } else if (PRU1_MODE == txrxmode) {
> + offset = PRU_SUART_PRU1_IMR_OFFSET;
> + } else {
> + return 0;
> + }
> + regval = regval << chn_num;
> + pruss_readb(dev, offset, (u8 *) &txrx_flag, 2);
> + txrx_flag &= regval;
> + if (0 == rmask) {
> + if (txrx_flag == 0)
> + return 1;
> + }
> + if (1 == rmask) {
> + if (txrx_flag == regval)
> + return 1;
> + }
> + return 0;
> +}
> diff --git a/drivers/tty/serial/pruss_suart_utils.c 
> b/drivers/tty/serial/pruss_suart_utils.c
> new file mode 100644
> index 0000000..2bd6983
> --- /dev/null
> +++ b/drivers/tty/serial/pruss_suart_utils.c
> @@ -0,0 +1,391 @@
> +/*
> + * 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/mfd/da8xx/da8xx_pru.h>
> +#include "pruss_suart.h"
> +
> +#define SUART_TRX_DIV_CONF_SZ 4
> +
> +static s16 suart_mcasp_tx_baud_set(u32 tx_baud_value,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +static s16 suart_mcasp_rx_baud_set(u32 rx_baud_value, u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr);
> +
> +/*
> + * 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_reset(struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + /* reset mcasp. */
> + __raw_writel(MCASP_SUART_GBLCTL, &mcasp0_regs->GBLCTL);
> + __raw_writel(MCASP_SUART_RGBLCTL, &mcasp0_regs->RGBLCTL);
> + __raw_writel(MCASP_SUART_XGBLCTL, &mcasp0_regs->XGBLCTL);
> + __raw_writel(MCASP_SUART_XSTAT, &mcasp0_regs->XSTAT);
> + __raw_writel(MCASP_SUART_RSTAT, &mcasp0_regs->RSTAT);
> +}
> +
> +void suart_mcasp_config(u32 tx_baud_value,
> + u32 rx_baud_value,
> + u32 oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> +
> + /* reset mcasp */
> + __raw_writel(MCASP_SUART_GBLCTL, &mcasp0_regs->GBLCTL);
> + __raw_writel(MCASP_SUART_RGBLCTL, &mcasp0_regs->RGBLCTL);
> + __raw_writel(MCASP_SUART_XGBLCTL, &mcasp0_regs->XGBLCTL);
> +
> + /* configure receive registers */
> + if ((SUART_8X_OVRSMPL == oversampling) || (0 == oversampling)) {
> + __raw_writel(MCASP_SUART_RMASK_8, &mcasp0_regs->RMASK);
> + __raw_writel(MCASP_SUART_RFMT_8, &mcasp0_regs->RFMT);
> + }
> + if (SUART_16X_OVRSMPL == oversampling) {
> + __raw_writel(MCASP_SUART_RMASK_16, &mcasp0_regs->RMASK);
> + __raw_writel(MCASP_SUART_RFMT_16, &mcasp0_regs->RFMT);
> +
> + }
> +
> + __raw_writel(MCASP_SUART_FSRM, &mcasp0_regs->AFSRCTL);
> + __raw_writel(MCASP_SUART_CLKRM_CLKRP, &mcasp0_regs->ACLKRCTL);
> + __raw_writel(MCASP_SUART_HCLKRP, &mcasp0_regs->AHCLKRCTL);
> + suart_mcasp_rx_baud_set(rx_baud_value, oversampling, pruss_ioaddr);
> + __raw_writel(MCASP_SUART_RTDMS0, &mcasp0_regs->RTDM);
> + __raw_writel(MCASP_SUART_RSYNCERR, &mcasp0_regs->RINTCTL);
> + __raw_writel(MCASP_SUART_RMAX_RPS_256, &mcasp0_regs->RCLKCHK);
> +
> + /* configure transmit registers. */
> + __raw_writel(MCASP_SUART_XMASK_0_31, &mcasp0_regs->XMASK);
> + __raw_writel(MCASP_SUART_XBUSEL_XSSZ_16_XPAD_0, &mcasp0_regs->XFMT);
> + __raw_writel(MCASP_SUART_FSXM, &mcasp0_regs->AFSXCTL);
> + __raw_writel(MCASP_SUART_CLKXM_ASYNC_CLKXP, &mcasp0_regs->ACLKXCTL);
> + __raw_writel(MCASP_SUART_HCLKXM, &mcasp0_regs->AHCLKXCTL);
> +
> + suart_mcasp_tx_baud_set(tx_baud_value, pruss_ioaddr);
> + __raw_writel(MCASP_SUART_XTDMS0, &mcasp0_regs->XTDM);
> + __raw_writel(MCASP_SUART_XSYNCERR, &mcasp0_regs->XINTCTL);
> + __raw_writel(MCASP_SUART_XMAX_XPS_256, &mcasp0_regs->XCLKCHK);
> +
> + /* Serializer as a transmitter */
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL0);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL1);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL2);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL3);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL4);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL5);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL6);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL7);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL8);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL9);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL10);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL11);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL12);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL13);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL14);
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL15);
> +
> + /* 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 */
> + temp_reg = (OMAPL_MCASP_PFUNC_RESETVAL) |
> +     (1 << PRU_SUART0_CONFIG_TX_SER) | (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);
> + __raw_writel(temp_reg, &mcasp0_regs->PFUNC);
> +
> + __raw_writel(0xFFF, &mcasp0_regs->PDOUT);
> +
> + /* config pin function and direction */
> + __raw_writel(0x00000000, &mcasp0_regs->PDIR);
> + temp_reg =
> +     (1 << PRU_SUART0_CONFIG_TX_SER) | (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) |
> +     (MCASP_PDIR_VAL);
> + __raw_writel(temp_reg, &mcasp0_regs->PDIR);
> +
> + __raw_writel(MCASP_SUART_DIT_DISABLE, &mcasp0_regs->DITCTL);
> + __raw_writel(MCASP_SUART_LOOPBACK_DISABLE, &mcasp0_regs->DLBCTL);
> + __raw_writel(MCASP_SUART_AMUTE_DISABLE, &mcasp0_regs->AMUTE);
> +
> + __raw_writel(MCASP_SUART_XSTAT, &mcasp0_regs->XSTAT);
> + __raw_writel(MCASP_SUART_RSTAT, &mcasp0_regs->RSTAT);
> +}
> +
> +void suart_mcasp_tx_serialzier_set(u32 serializer_num,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> +     (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> + temp_reg = mcasp0_regs->PFUNC | (0x1 << serializer_num);
> + __raw_writel(temp_reg, &mcasp0_regs->PFUNC);
> +}
> +
> +/*
> + * mcasp TX buard rate setting routine
> + */
> +s16 suart_mcasp_tx_baud_set(u32 tx_baud_value,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 clk_div_val;
> + u32 loop_cnt;
> + s16 status = 0;
> + s16 found_val = false;
> +
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> +     (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> +
> + /* Search the supported baud rate in the table */
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> + loop_cnt++) {
> + if (tx_baud_value == lt_tx_baud_rate[loop_cnt][0]) {
> + found_val = true;
> + break;
> + }
> + }
> + if (found_val == true) {
> + clk_div_val = lt_tx_baud_rate[loop_cnt][2];
> + temp_reg = mcasp0_regs->ACLKXCTL |
> + clk_div_val << OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT;
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKXCTL);
> + clk_div_val = lt_tx_baud_rate[loop_cnt][3];
> + temp_reg = mcasp0_regs->AHCLKXCTL |
> + clk_div_val << OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT;
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKXCTL);
> + } else {
> + return -EINVAL ;
> + }
> + return status;
> +}
> +
> +/*
> + * mcasp RX buard rate setting routine
> + */
> +s16 suart_mcasp_rx_baud_set(u32 rx_baud_value,
> + u32 oversampling, struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + u32 clk_div_val;
> + u32 loop_cnt;
> + s16 status = 0;
> + s16 found_val = false;
> +
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> +     (struct omapl_mcasp_regs_ovly *) pruss_ioaddr->mcasp_io_addr;
> + u32 temp_reg;
> +
> + if (oversampling == SUART_8X_OVRSMPL) {
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> +      loop_cnt++) {
> + if (rx_baud_value == lt_rx_8x_baud_rate[loop_cnt][0]) {
> + clk_div_val = lt_rx_8x_baud_rate[loop_cnt][2];
> + temp_reg = mcasp0_regs->ACLKRCTL | (clk_div_val
> + << OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
> +
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
> +
> + clk_div_val =
> + lt_rx_8x_baud_rate[loop_cnt][3] - 1;
> +
> + temp_reg = mcasp0_regs->AHCLKRCTL | (clk_div_val
> + << OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
> +
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
> +
> + found_val = true;
> + break;
> + }
> + }
> + } else if (oversampling == SUART_16X_OVRSMPL) {
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> +      loop_cnt++) {
> + if (rx_baud_value == lt_rx_16x_baud_rate[loop_cnt][0]) {
> + clk_div_val = lt_rx_16x_baud_rate[loop_cnt][2];
> + temp_reg =
> + mcasp0_regs->ACLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
> + clk_div_val = lt_rx_16x_baud_rate[loop_cnt][3];
> + temp_reg =
> + mcasp0_regs->AHCLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
> + found_val = true;
> + break;
> + }
> + }
> + } else if (oversampling == 0) {
> + for (loop_cnt = 0; loop_cnt < SUART_NUM_OF_BAUDS_SUPPORTED;
> +      loop_cnt++) {
> + if (rx_baud_value == lt_tx_baud_rate[loop_cnt][0]) {
> + clk_div_val = lt_tx_baud_rate[loop_cnt][2];
> + temp_reg =
> + mcasp0_regs->ACLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_ACLKXCTL_CLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->ACLKRCTL);
> + clk_div_val = lt_tx_baud_rate[loop_cnt][3];
> + temp_reg =
> + mcasp0_regs->AHCLKRCTL | (clk_div_val <<
> + OMAPL_MCASP_AHCLKXCTL_HCLKXDIV_SHIFT);
> + __raw_writel(temp_reg, &mcasp0_regs->AHCLKRCTL);
> + found_val = true;
> + break;
> + }
> + }
> + } else {
> + return -EINVAL ;
> + }
> +
> + if (found_val != true)
> + return -EINVAL ;
> +
> + return status;
> +}
> +
> +/*
> + * mcasp buard rate setting routine
> + */
> +s16 suart_asp_baud_set(u32 tx_baud_value, u32 rx_baud_value, u32 
> oversampling,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + s16 status = 0;
> +
> + status = suart_mcasp_tx_baud_set(tx_baud_value, pruss_ioaddr);
> + status = suart_mcasp_rx_baud_set(rx_baud_value, oversampling,
> + pruss_ioaddr);
> +
> + return status;
> +}
> +
> +/*
> + * mcasp deactivate the selected serializer
> + */
> +s16 suart_asp_serializer_deactivate(u16 sr_num,
> + struct pruss_suart_iomap *pruss_ioaddr)
> +{
> + s16 status = 0;
> + struct omapl_mcasp_regs_ovly *mcasp0_regs =
> + (struct omapl_mcasp_regs_ovly *)pruss_ioaddr->mcasp_io_addr;
> + if (sr_num > 15)
> + status = -EINVAL;
> + else
> + __raw_writel(MCASP_SUART_SRCTL_DISMOD, &mcasp0_regs->SRCTL0);
> +
> + return status;
> +}
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 758c5b0..eae37fe 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -202,6 +202,8 @@
> /* VIA VT8500 SoC */
> #define PORT_VT8500 97
>
> +#define PORT_DA8XX_PRU_SUART 98
> +
> #ifdef __KERNEL__
>
> #include <linux/compiler.h>
> -- 
> 1.7.2.3
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 7/7] tty: add pruss SUART driver
  2011-03-18  5:43   ` Subhasish Ghosh
@ 2011-03-18 11:45     ` Alan Cox
  2011-03-18 12:07     ` Arnd Bergmann
  1 sibling, 0 replies; 31+ messages in thread
From: Alan Cox @ 2011-03-18 11:45 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: Greg Kroah-Hartman, Arnd Bergmann, Thomas Gleixner,
	linux-arm-kernel, m-watkins, nsekhar, sachi,
	Andrew Morton (commit_signer:1/4=25%),
	Randy Dunlap (commit_signer:1/4=25%),
	open list

On Fri, 18 Mar 2011 11:13:34 +0530
"Subhasish Ghosh" <subhasish@mistralsolutions.com> wrote:

> Hi Greg/Alan,
> 
> Any comments regarding this driver.


I'm fine with the tty/serial side. Can't really evaluate the rest of the
hardware side of things.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-08 13:57 ` [PATCH v3 1/7] mfd: add pruss mfd driver Subhasish Ghosh
  2011-03-09 11:56   ` Marc Kleine-Budde
  2011-03-11 15:28   ` Arnd Bergmann
@ 2011-03-18 11:59   ` Nori, Sekhar
  2011-03-18 12:39     ` Mark Brown
  2 siblings, 1 reply; 31+ messages in thread
From: Nori, Sekhar @ 2011-03-18 11:59 UTC (permalink / raw)
  To: Subhasish Ghosh, davinci-linux-open-source
  Cc: linux-arm-kernel, Watkins, Melissa, sachi, Samuel Ortiz, open list

Hi Subhasish,

On Tue, Mar 08, 2011 at 19:27:40, Subhasish Ghosh wrote:
> This patch adds the pruss MFD driver and associated include files.
> For details regarding the PRUSS please refer the folowing link:
> http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem
> 
> The rational behind the MFD driver being the fact that multiple devices can
> be implemented on the cores independently. This is determined by the nature
> of the program which is loaded into the PRU's instruction memory.
> A device may be de-initialized and another loaded or two different devices
> can be run simultaneously on the two cores.
> It's also possible, as in our case, to implement a single device on both
> the PRU's resulting in improved load sharing.
> 
> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
> ---
>  drivers/mfd/Kconfig                     |   10 +
>  drivers/mfd/Makefile                    |    1 +
>  drivers/mfd/da8xx_pru.c                 |  560 +++++++++++++++++++++++++++++++
>  include/linux/mfd/da8xx/da8xx_pru.h     |  135 ++++++++
>  include/linux/mfd/da8xx/da8xx_prucore.h |  129 +++++++
>  5 files changed, 835 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mfd/da8xx_pru.c
>  create mode 100644 include/linux/mfd/da8xx/da8xx_pru.h
>  create mode 100644 include/linux/mfd/da8xx/da8xx_prucore.h

PRUSS as an IP is not really tied to the DA8xx SoC architecture.
So, can you please name the files ti-pruss* or even just pruss if
MFD folks are okay with it?

> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index fd01836..6c437df 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -81,6 +81,16 @@ config MFD_DM355EVM_MSP
>  	  boards.  MSP430 firmware manages resets and power sequencing,
>  	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
>  
> +config MFD_DA8XX_PRUSS
> +	tristate "Texas Instruments DA8XX PRUSS support"
> +	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850

Just ARCH_DAVINCI_DA850 should be okay since ARCH_DAVINCI_DA850
Already depends on ARCH_DAVINCI

> +	select MFD_CORE
> +	help
> +	  This driver provides support api's for the programmable

"API" would be preferred. Also please remove the apostrophe.

> +	  realtime unit (PRU) present on TI's da8xx processors. It
> +	  provides basic read, write, config, enable, disable
> +	  routines to facilitate devices emulated on it.
> +
>  config HTC_EGPIO
>  	bool "HTC EGPIO support"
>  	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index a54e2c7..670d6b0 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
>  obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
>  
>  obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
> +obj-$(CONFIG_MFD_DA8XX_PRUSS)	+= da8xx_pru.o
>  obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
>  
>  obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
> diff --git a/drivers/mfd/da8xx_pru.c b/drivers/mfd/da8xx_pru.c
> new file mode 100644
> index 0000000..0fd9bb2
> --- /dev/null
> +++ b/drivers/mfd/da8xx_pru.c
> @@ -0,0 +1,560 @@
> +/*
> + * Copyright (C) 2011 Texas Instruments Incorporated
> + *
> + * 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/init.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/bitops.h>
> +#include <linux/interrupt.h>
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mfd/da8xx/da8xx_prucore.h>
> +#include <linux/mfd/da8xx/da8xx_pru.h>
> +#include <linux/mfd/core.h>
> +#include <linux/io.h>
> +#include <mach/da8xx.h>

Hmm, this means the driver is tied to the platform.
This should not be the case. 

I was able to get this patch compiled even
after removing this include. Please remove it
in the next version.

> +
> +struct da8xx_pruss {

I would prefer if the variables and data structures
and includes are not pre-fixed with da8xx as well.

> +	struct device *dev;
> +	spinlock_t lock;
> +	struct resource *res;
> +	struct clk *clk;
> +	u32 clk_freq;
> +	void __iomem *ioaddr;
> +};
> +
> +u32 pruss_get_clk_freq(struct device *dev)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +
> +	return pruss->clk_freq;
> +}
> +EXPORT_SYMBOL(pruss_get_clk_freq);

This looks strange. Why do we need this? There
is clk_get_rate() API in the kernel would would
seem more suitable.

> +
> +s32 pruss_disable(struct device *dev, u8 pruss_num)
> +{
> +	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> +	struct da8xx_prusscore_regs *h_pruss;
> +	struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> +	u32 temp_reg;
> +	u32 delay_cnt;
> +
> +	if ((pruss_num != DA8XX_PRUCORE_0) && (pruss_num != DA8XX_PRUCORE_1))
> +		return -EINVAL;
> +
> +	spin_lock(&pruss->lock);
> +	if (pruss_num == DA8XX_PRUCORE_0) {
> +		/* pruss deinit */
> +		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT0 & 0xFFFF));

Why not use writel instead? Per my understanding
The __raw_ variants are unsafe to use on ARMv6
and above.

> +		/* Disable PRU0  */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_0];
> +
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +		__raw_writel(temp_reg, &h_pruss->CONTROL);
> +
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
> +
> +			temp_reg = __raw_readl(&h_pruss->CONTROL);
> +			temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +			__raw_writel(temp_reg, &h_pruss->CONTROL);
> +		}
> +
> +		/* Reset PRU0 */
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
> +			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +					&h_pruss->CONTROL);
> +
> +	} else if (pruss_num == DA8XX_PRUCORE_1) {
> +		/* pruss deinit */
> +		__raw_writel(0xFFFFFFFF, (PRUSS_INTC_STATCLRINT1 & 0xFFFF));
> +		/* Disable PRU1 */
> +		h_pruss = (struct da8xx_prusscore_regs *)
> +			&pruss_mmap->core[DA8XX_PRUCORE_1];
> +		temp_reg = __raw_readl(&h_pruss->CONTROL);
> +		temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
> +		__raw_writel(temp_reg, &h_pruss->CONTROL);
> +
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--) {
> +
> +			temp_reg = __raw_readl(&h_pruss->CONTROL);
> +			temp_reg = (temp_reg &
> +				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
> +				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
> +				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
> +				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
> +			__raw_writel(temp_reg, &h_pruss->CONTROL);
> +		}
> +
> +		/* Reset PRU1 */
> +		for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
> +			__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
> +							&h_pruss->CONTROL);
> +	}

There is a lot of code repeated between the if and else and
I am sure it will be possible to remove the if-else block
altogether and use the pruss_num as an index know which
core to operate on. Doing this will also help add more cores
later.

I really couldn't complete this review (got to rush now),
but I thought I will send you what I have. You can wait
for review to complete before posting another version.

Thanks,
Sekhar

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 7/7] tty: add pruss SUART driver
  2011-03-18  5:43   ` Subhasish Ghosh
  2011-03-18 11:45     ` Alan Cox
@ 2011-03-18 12:07     ` Arnd Bergmann
  1 sibling, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2011-03-18 12:07 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: Greg Kroah-Hartman, Alan Cox, Thomas Gleixner, linux-arm-kernel,
	m-watkins, nsekhar, sachi, Andrew Morton (commit_signer:1/4=25%),
	Randy Dunlap (commit_signer:1/4=25%),
	open list

On Friday 18 March 2011, Subhasish Ghosh wrote:
> Hi Greg/Alan,
> 
> Any comments regarding this driver.
> 

I already did a review of the base MFD driver that you have not replied
to yet. A number of the points I brought up in that review and in my
review of the pruss CAN driver also apply to this one. Please post
cleaned-up versions of all those drivers, and I'll have another look.

	Arnd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-18 11:59   ` Nori, Sekhar
@ 2011-03-18 12:39     ` Mark Brown
  2011-03-22  9:35       ` Nori, Sekhar
  0 siblings, 1 reply; 31+ messages in thread
From: Mark Brown @ 2011-03-18 12:39 UTC (permalink / raw)
  To: Nori, Sekhar
  Cc: Subhasish Ghosh, davinci-linux-open-source, Watkins, Melissa,
	open list, Samuel Ortiz, linux-arm-kernel, sachi

On Fri, Mar 18, 2011 at 05:29:39PM +0530, Nori, Sekhar wrote:

> PRUSS as an IP is not really tied to the DA8xx SoC architecture.
> So, can you please name the files ti-pruss* or even just pruss if
> MFD folks are okay with it?

This...

> > +EXPORT_SYMBOL(pruss_get_clk_freq);

> This looks strange. Why do we need this? There
> is clk_get_rate() API in the kernel would would
> seem more suitable.

...unfortunately conflicts with this - currently all clock API
implementations are unique to the platform and there's no way of adding
clocks that works over multiple platforms.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-18 12:39     ` Mark Brown
@ 2011-03-22  9:35       ` Nori, Sekhar
  2011-03-22  9:43         ` Nori, Sekhar
  2011-03-22 16:52         ` Mark Brown
  0 siblings, 2 replies; 31+ messages in thread
From: Nori, Sekhar @ 2011-03-22  9:35 UTC (permalink / raw)
  To: Mark Brown
  Cc: Subhasish Ghosh, davinci-linux-open-source, Watkins, Melissa,
	open list, Samuel Ortiz, linux-arm-kernel, sachi

Hi Mark,

On Fri, Mar 18, 2011 at 18:09:17, Mark Brown wrote:
> On Fri, Mar 18, 2011 at 05:29:39PM +0530, Nori, Sekhar wrote:
> 
> > PRUSS as an IP is not really tied to the DA8xx SoC architecture.
> > So, can you please name the files ti-pruss* or even just pruss if
> > MFD folks are okay with it?
> 
> This...
> 
> > > +EXPORT_SYMBOL(pruss_get_clk_freq);
> 
> > This looks strange. Why do we need this? There
> > is clk_get_rate() API in the kernel would would
> > seem more suitable.
> 
> ...unfortunately conflicts with this - currently all clock API
> implementations are unique to the platform and there's no way of adding
> clocks that works over multiple platforms.

Hmm, I guess I have a limited view of this. We do have drivers which
use clock API and work across OMAP and DaVinci series of ARM SoCs.
The clock implementation in this case is under mach-omap and mach-davinci
respectively.

Thanks,
Sekhar


^ permalink raw reply	[flat|nested] 31+ messages in thread

* RE: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-22  9:35       ` Nori, Sekhar
@ 2011-03-22  9:43         ` Nori, Sekhar
  2011-03-22 16:52         ` Mark Brown
  1 sibling, 0 replies; 31+ messages in thread
From: Nori, Sekhar @ 2011-03-22  9:43 UTC (permalink / raw)
  To: Nori, Sekhar, Mark Brown
  Cc: sachi, davinci-linux-open-source, Samuel Ortiz, Subhasish Ghosh,
	open list, Watkins, Melissa, linux-arm-kernel

On Tue, Mar 22, 2011 at 15:05:07, Nori, Sekhar wrote:
> Hi Mark,
> 
> On Fri, Mar 18, 2011 at 18:09:17, Mark Brown wrote:
> > On Fri, Mar 18, 2011 at 05:29:39PM +0530, Nori, Sekhar wrote:
> > 
> > > PRUSS as an IP is not really tied to the DA8xx SoC architecture.
> > > So, can you please name the files ti-pruss* or even just pruss if
> > > MFD folks are okay with it?
> > 
> > This...
> > 
> > > > +EXPORT_SYMBOL(pruss_get_clk_freq);
> > 
> > > This looks strange. Why do we need this? There
> > > is clk_get_rate() API in the kernel would would
> > > seem more suitable.
> > 
> > ...unfortunately conflicts with this - currently all clock API
> > implementations are unique to the platform and there's no way of adding
> > clocks that works over multiple platforms.
> 
> Hmm, I guess I have a limited view of this. We do have drivers which
> use clock API and work across OMAP and DaVinci series of ARM SoCs.
> The clock implementation in this case is under mach-omap and mach-davinci

This should have read "under plat-omap/mach-omap2 and mach-davinci"

Thanks,
Sekhar


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-22  9:35       ` Nori, Sekhar
  2011-03-22  9:43         ` Nori, Sekhar
@ 2011-03-22 16:52         ` Mark Brown
  1 sibling, 0 replies; 31+ messages in thread
From: Mark Brown @ 2011-03-22 16:52 UTC (permalink / raw)
  To: Nori, Sekhar
  Cc: Subhasish Ghosh, davinci-linux-open-source, Watkins, Melissa,
	open list, Samuel Ortiz, linux-arm-kernel, sachi

On Tue, Mar 22, 2011 at 03:05:07PM +0530, Nori, Sekhar wrote:
> On Fri, Mar 18, 2011 at 18:09:17, Mark Brown wrote:

> > ...unfortunately conflicts with this - currently all clock API
> > implementations are unique to the platform and there's no way of adding
> > clocks that works over multiple platforms.

> Hmm, I guess I have a limited view of this. We do have drivers which
> use clock API and work across OMAP and DaVinci series of ARM SoCs.
> The clock implementation in this case is under mach-omap and mach-davinci
> respectively.

It's mostly fine from the point of view of using clocks, it's if you're
trying to provide a clock that there's no API you can rely on - the
clock API itself only includes the user side and every platform gets to
provide its own implementation.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-09 11:56   ` Marc Kleine-Budde
@ 2011-03-24 13:16     ` Subhasish Ghosh
  2011-03-24 13:24       ` Marc Kleine-Budde
  0 siblings, 1 reply; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-24 13:16 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: davinci-linux-open-source, sachi, Samuel Ortiz, nsekhar,
	open list, m-watkins, linux-arm-kernel, Stalin Srinivasan

Hello,

> A device may be de-initialized and another loaded or two different devices
> can be run simultaneously on the two cores.
> It's also possible, as in our case, to implement a single device on both
> the PRU's resulting in improved load sharing.

>Make you driver compile with sparse "make C=1", you cast way too much
>when accessing io mem. Use void __iomem * instead of u32 *.


With make C=1 I am receiving some warnings such as:

warning: cast removes address space of expression
drivers/mfd/da8xx_pru.c:61:17: warning: incorrect type in argument 1 
(different base types)
drivers/mfd/da8xx_pru.c:61:17:    expected void const volatile [noderef] 
<asn:2>*<noident>
drivers/mfd/da8xx_pru.c:61:17:    got int
drivers/mfd/da8xx_pru.c:66:28: warning: incorrect type in argument 1 
(different address spaces)

I can remove all of these by casting to (__force void  __iomem *) but is 
this correct.

-SG 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-24 13:16     ` Subhasish Ghosh
@ 2011-03-24 13:24       ` Marc Kleine-Budde
  2011-03-24 13:41         ` Kurt Van Dijck
  0 siblings, 1 reply; 31+ messages in thread
From: Marc Kleine-Budde @ 2011-03-24 13:24 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: davinci-linux-open-source, sachi, Samuel Ortiz, nsekhar,
	open list, m-watkins, linux-arm-kernel, Stalin Srinivasan

[-- Attachment #1: Type: text/plain, Size: 1645 bytes --]

On 03/24/2011 02:16 PM, Subhasish Ghosh wrote:
> Hello,
> 
>> A device may be de-initialized and another loaded or two different
>> devices
>> can be run simultaneously on the two cores.
>> It's also possible, as in our case, to implement a single device on both
>> the PRU's resulting in improved load sharing.
> 
>> Make you driver compile with sparse "make C=1", you cast way too much
>> when accessing io mem. Use void __iomem * instead of u32 *.
> 
> 
> With make C=1 I am receiving some warnings such as:
> 
> warning: cast removes address space of expression
> drivers/mfd/da8xx_pru.c:61:17: warning: incorrect type in argument 1
> (different base types)
> drivers/mfd/da8xx_pru.c:61:17:    expected void const volatile [noderef]
> <asn:2>*<noident>
> drivers/mfd/da8xx_pru.c:61:17:    got int
> drivers/mfd/da8xx_pru.c:66:28: warning: incorrect type in argument 1
> (different address spaces)

(Re)read the warning carefully:

You have to fix drivers/mfd/da8xx_pru.c, the first argument should be
__void iomem *, not an int. Fix the type of the first argument. Don't
use any casts at all, follow all warnings, eventually you will have void
__iomem * (or struct * instead of void *) and no warnings.

> I can remove all of these by casting to (__force void  __iomem *) but is
> this correct.

No evil casts, please :)

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-24 13:24       ` Marc Kleine-Budde
@ 2011-03-24 13:41         ` Kurt Van Dijck
  0 siblings, 0 replies; 31+ messages in thread
From: Kurt Van Dijck @ 2011-03-24 13:41 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Subhasish Ghosh, sachi, davinci-linux-open-source, Samuel Ortiz,
	Stalin Srinivasan, nsekhar, open list, m-watkins,
	linux-arm-kernel

On Thu, Mar 24, 2011 at 02:24:51PM +0100, Marc Kleine-Budde wrote:
> On 03/24/2011 02:16 PM, Subhasish Ghosh wrote:
> > Hello,
> > 
> > With make C=1 I am receiving some warnings such as:
> > 
> > warning: cast removes address space of expression
> > drivers/mfd/da8xx_pru.c:61:17: warning: incorrect type in argument 1
> > (different base types)
> > drivers/mfd/da8xx_pru.c:61:17:    expected void const volatile [noderef]
> > <asn:2>*<noident>
> > drivers/mfd/da8xx_pru.c:61:17:    got int
> > drivers/mfd/da8xx_pru.c:66:28: warning: incorrect type in argument 1
> > (different address spaces)
> 
> (Re)read the warning carefully:
> 
> You have to fix drivers/mfd/da8xx_pru.c, the first argument should be
> __void iomem *, not an int. Fix the type of the first argument. Don't
> use any casts at all, follow all warnings, eventually you will have void
> __iomem * (or struct * instead of void *) and no warnings.
> 
> > I can remove all of these by casting to (__force void  __iomem *) but is
> > this correct.
> 
> No evil casts, please :)
In addition, I learned that if a driver is not bound to a specific architecture,
you better use ioread/iowrite & friends, rather that accessing the iomemory
directly.
> 
Kurt


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-11 15:28   ` Arnd Bergmann
@ 2011-03-30  7:16     ` Subhasish Ghosh
  2011-03-30 10:59       ` Arnd Bergmann
  2011-03-30  9:15     ` Subhasish Ghosh
  1 sibling, 1 reply; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-30  7:16 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: davinci-linux-open-source, sachi, Samuel Ortiz, nsekhar,
	open list, m-watkins, Marc Kleine-Budde, Stalin Srinivasan


>> +s32 pruss_disable(struct device *dev, u8 pruss_num)
>> +{
>> + struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
>> + struct da8xx_prusscore_regs *h_pruss;
>> + struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
>> + u32 temp_reg;
>> + u32 delay_cnt;
>
> Can you explain the significance of pruss_num? As far as I
> can tell, you always pass constants in here, so it should
> be possible to determine the number from the device.

SG - The number is not programmed in the device, I need something to decide 
which PRU to disable
or enable.

>> + ~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
>> + ((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
>> + DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
>> + DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
>> + __raw_writel(temp_reg, &h_pruss->CONTROL);
>
> Better use readl/writel, the __raw_ variants are not reliable in general.

SG - Have changed this to iowrite32 and variants.


>> +
>> + /* Reset PRU0 */
>> + for (delay_cnt = 0x10000; delay_cnt > 0; delay_cnt--)
>> + __raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
>> + &h_pruss->CONTROL);
>
> Why do you need to reset it 65536 times? Is once not enough?

SG - I am not sure why this was done, but I have removed it now.

>> + }
>> + spin_unlock(&pruss->lock);
>
> This is almost the exact same code as for the DA8XX_PRUCORE_0 case.
> Please be a little more creative in order to avoid such code duplication.

SG - Ok, cleanup done.


>> +
>> + for (loop = 0; loop < bytestowrite; loop++)
>> + __raw_writeb(*pdatatowrite++, paddresstowrite++);
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(pruss_writeb);
>
> I would recommend providing a simpler variant of your all I/O accessors,
> which write a single word. Most of the users of these simply
> pass bytestowrite=1 anyway, so the caller can become more readable.

SG - At some sections in the code I am using upto 8 bytescount.
            If its ok, I would want to keep it as is.

>
> Also, my comments about __raw_* and Marc's comments about the
> type cast apply to all of these.

SG - Changed to iowrite32 variants and also used make C=1


>> + err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
>> + if (err) {
>> + dev_err(dev, "cannot add mfd cells\n");
>> + return err;
>> + }
>> + dev_info(dev, "mfd: added %s device\n",
>> + dev_data[count].dev_name);
>> + }
>> +
>> + return err;
>> +}
>
> This would get much simpler if you just replaced the da8xx_pruss_devices
> array with an mfd_cell array.

SG - Will do. 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-11 15:28   ` Arnd Bergmann
  2011-03-30  7:16     ` Subhasish Ghosh
@ 2011-03-30  9:15     ` Subhasish Ghosh
  2011-03-30 11:38       ` Arnd Bergmann
  1 sibling, 1 reply; 31+ messages in thread
From: Subhasish Ghosh @ 2011-03-30  9:15 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: davinci-linux-open-source, sachi, Samuel Ortiz, nsekhar,
	open list, m-watkins, Marc Kleine-Budde

Hi Arnd,

I am using a .setup to initialize pin mux etc. To use the mfd_cells directly 
should I
use .enable and .disable of the mfd_cells instead of the .setup.

>> +static int pruss_mfd_add_devices(struct platform_device *pdev)
>> +{
>> + struct da8xx_pruss_devices *dev_data = pdev->dev.platform_data;
>> + struct device *dev = &pdev->dev;
>> + struct mfd_cell cell;
>> + u32 err, count;
>> +
>> + for (count = 0; dev_data[count].dev_name != NULL; count++) {
>> + memset(&cell, 0, sizeof(struct mfd_cell));
>> + cell.id = count;
>> + cell.name = dev_data[count].dev_name;
>> + cell.platform_data = dev_data[count].pdata;
>> + cell.data_size = dev_data[count].pdata_size;
>> + cell.resources = dev_data[count].resources;
>> + cell.num_resources = dev_data[count].num_resources;
>> +
>> + err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
>> + if (err) {
>> + dev_err(dev, "cannot add mfd cells\n");
>> + return err;
>> + }
>> + dev_info(dev, "mfd: added %s device\n",
>> + dev_data[count].dev_name);
>> + }
>> +
>> + return err;
>> +}
>
> This would get much simpler if you just replaced the da8xx_pruss_devices
> array with an mfd_cell array. 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-30  7:16     ` Subhasish Ghosh
@ 2011-03-30 10:59       ` Arnd Bergmann
  2011-04-05  6:40         ` Subhasish Ghosh
  0 siblings, 1 reply; 31+ messages in thread
From: Arnd Bergmann @ 2011-03-30 10:59 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: linux-arm-kernel, davinci-linux-open-source, sachi, Samuel Ortiz,
	nsekhar, open list, m-watkins, Marc Kleine-Budde,
	Stalin Srinivasan

On Wednesday 30 March 2011, Subhasish Ghosh wrote:
> 
> >> +s32 pruss_disable(struct device *dev, u8 pruss_num)
> >> +{
> >> + struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
> >> + struct da8xx_prusscore_regs *h_pruss;
> >> + struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
> >> + u32 temp_reg;
> >> + u32 delay_cnt;
> >
> > Can you explain the significance of pruss_num? As far as I
> > can tell, you always pass constants in here, so it should
> > be possible to determine the number from the device.
> 
> SG - The number is not programmed in the device, I need something to decide 
> which PRU to disable or enable.

I still don't understand. Please explain how the devices
relate to the multiple PRUs in hardware. 

> >> + for (loop = 0; loop < bytestowrite; loop++)
> >> + __raw_writeb(*pdatatowrite++, paddresstowrite++);
> >> +
> >> + return 0;
> >> +}
> >> +EXPORT_SYMBOL(pruss_writeb);
> >
> > I would recommend providing a simpler variant of your all I/O accessors,
> > which write a single word. Most of the users of these simply
> > pass bytestowrite=1 anyway, so the caller can become more readable.
> 
> SG - At some sections in the code I am using upto 8 bytescount.
>             If its ok, I would want to keep it as is.

You can of course have both, but I would recommend making the common
case simpler by providing a version that writes just one word.

	Arnd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-30  9:15     ` Subhasish Ghosh
@ 2011-03-30 11:38       ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2011-03-30 11:38 UTC (permalink / raw)
  To: Subhasish Ghosh
  Cc: linux-arm-kernel, davinci-linux-open-source, sachi, Samuel Ortiz,
	nsekhar, open list, m-watkins, Marc Kleine-Budde

On Wednesday 30 March 2011, Subhasish Ghosh wrote:
> I am using a .setup to initialize pin mux etc. To use the mfd_cells directly 
> should I
> use .enable and .disable of the mfd_cells instead of the .setup.

I think it would be best not to define any per-board functions that
are needed to set up the cell, but rather to initialize it from
the ->probe function of the cell specific driver.

If you need board specific data such as GPIO lists, you can pass
them in the mfd_cell platform_data.
	
	Arnd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 1/7] mfd: add pruss mfd driver.
  2011-03-30 10:59       ` Arnd Bergmann
@ 2011-04-05  6:40         ` Subhasish Ghosh
  0 siblings, 0 replies; 31+ messages in thread
From: Subhasish Ghosh @ 2011-04-05  6:40 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, davinci-linux-open-source, sachi, Samuel Ortiz,
	nsekhar, open list, m-watkins, Marc Kleine-Budde,
	Stalin Srinivasan


> On Wednesday 30 March 2011, Subhasish Ghosh wrote:
>>
>> >> +s32 pruss_disable(struct device *dev, u8 pruss_num)
>> >> +{
>> >> + struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
>> >> + struct da8xx_prusscore_regs *h_pruss;
>> >> + struct pruss_map *pruss_mmap = (struct pruss_map *)pruss->ioaddr;
>> >> + u32 temp_reg;
>> >> + u32 delay_cnt;
>> >
>> > Can you explain the significance of pruss_num? As far as I
>> > can tell, you always pass constants in here, so it should
>> > be possible to determine the number from the device.
>>
>> SG - The number is not programmed in the device, I need something to 
>> decide
>> which PRU to disable or enable.
>
> I still don't understand. Please explain how the devices
> relate to the multiple PRUs in hardware.

There are two devices, CAN and UART, in our case we use the PRU as follows:
1. CAN-TX on PRU0, CAN-RX on PRU1
2. SUART-TX on PRU0, SUART-RX on PRU1
3. SUART-TXRX on PRU0, SUART-TXRX on PRU1


 


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2011-04-05  6:37 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1299592667-21367-1-git-send-email-subhasish@mistralsolutions.com>
2011-03-08 13:57 ` [PATCH v3 1/7] mfd: add pruss mfd driver Subhasish Ghosh
2011-03-09 11:56   ` Marc Kleine-Budde
2011-03-24 13:16     ` Subhasish Ghosh
2011-03-24 13:24       ` Marc Kleine-Budde
2011-03-24 13:41         ` Kurt Van Dijck
2011-03-11 15:28   ` Arnd Bergmann
2011-03-30  7:16     ` Subhasish Ghosh
2011-03-30 10:59       ` Arnd Bergmann
2011-04-05  6:40         ` Subhasish Ghosh
2011-03-30  9:15     ` Subhasish Ghosh
2011-03-30 11:38       ` Arnd Bergmann
2011-03-18 11:59   ` Nori, Sekhar
2011-03-18 12:39     ` Mark Brown
2011-03-22  9:35       ` Nori, Sekhar
2011-03-22  9:43         ` Nori, Sekhar
2011-03-22 16:52         ` Mark Brown
2011-03-08 13:57 ` [PATCH v3 2/7] da850: pruss platform specific additions Subhasish Ghosh
2011-03-08 15:17   ` Sergei Shtylyov
2011-03-08 13:57 ` [PATCH v3 3/7] da850: pruss board " Subhasish Ghosh
2011-03-08 15:19   ` Sergei Shtylyov
2011-03-09  4:29     ` Subhasish Ghosh
2011-03-09 11:59   ` Marc Kleine-Budde
2011-03-08 13:57 ` [PATCH v3 4/7] mfd: pruss SUART private data Subhasish Ghosh
2011-03-08 13:57 ` [PATCH v3 5/7] da850: pruss SUART board specific additions Subhasish Ghosh
2011-03-08 13:57 ` [PATCH v3 6/7] da850: pruss SUART platform " Subhasish Ghosh
2011-03-08 13:57 ` [PATCH v3 7/7] tty: add pruss SUART driver Subhasish Ghosh
2011-03-08 18:47   ` Randy Dunlap
2011-03-15  7:23     ` Subhasish Ghosh
2011-03-18  5:43   ` Subhasish Ghosh
2011-03-18 11:45     ` Alan Cox
2011-03-18 12:07     ` Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).