All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/9] pruss mfd drivers
@ 2011-02-01 14:47 Subhasish Ghosh
  2011-02-01 14:47 ` [PATCH v1 1/9] mfd: pruss mfd driver Subhasish Ghosh
                   ` (9 more replies)
  0 siblings, 10 replies; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Programmable Realtime Unit (PRU) is basically a 32-bit RISC
processor available within TI's DA8XX SOCs. It consists of local
instruction and data RAM and also has access to SOC resources
via a Switched Central Resource (SCR).

There are two PRU's available within DA8XX SOC's PRUSS, hence providing
two execution cores. Devices/Protocols can be emulated on these utilizing
either both or only one of the PRUs independently.

The rational behind the MFD driver being the fact that multiple devices can
be implemented on the cores independently.
It's also possible, as in our case, to implement a single device on both
the PRU's resulting in improved load sharing.

A detailed description is also available here:
http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem

version 1:
==========
* added pruss mfd driver.
* added pruss mfd board and platform changes.
* added pruss SocketCAN driver.
* added pruss SocketCAN board and platform changes.
* added pruss SocketCAN GPIOs.
* added previous review comments.

Subhasish Ghosh (9):
  mfd: pruss mfd driver.
  da850: pruss board specific additions.
  da850: pruss platform specific additions.
  can: pruss CAN driver.
  da850: pruss CAN board specific additions.
  da850: pruss CAN platform specific additions.
  mfd: pruss CAN private data.
  da850: pruss CAN board specific changes for gpios.
  da850: pruss CAN platform specific changes for gpios.

 arch/arm/mach-davinci/board-da850-evm.c     |   75 ++
 arch/arm/mach-davinci/da850.c               |   12 +
 arch/arm/mach-davinci/devices-da8xx.c       |   65 ++
 arch/arm/mach-davinci/include/mach/da8xx.h  |    2 +
 arch/arm/mach-davinci/include/mach/mux.h    |    5 +
 drivers/mfd/Kconfig                         |   10 +
 drivers/mfd/Makefile                        |    1 +
 drivers/mfd/da8xx_pru.c                     |  403 +++++++++
 drivers/net/can/Kconfig                     |    1 +
 drivers/net/can/Makefile                    |    1 +
 drivers/net/can/da8xx_pruss/Kconfig         |   73 ++
 drivers/net/can/da8xx_pruss/Makefile        |    7 +
 drivers/net/can/da8xx_pruss/pruss_can.c     |  759 +++++++++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.c | 1224 +++++++++++++++++++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.h |  290 +++++++
 include/linux/mfd/pruss/da8xx_pru.h         |  106 +++
 include/linux/mfd/pruss/da8xx_prucore.h     |   74 ++
 17 files changed, 3108 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/da8xx_pru.c
 create mode 100644 drivers/net/can/da8xx_pruss/Kconfig
 create mode 100644 drivers/net/can/da8xx_pruss/Makefile
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.h
 create mode 100644 include/linux/mfd/pruss/da8xx_pru.h
 create mode 100644 include/linux/mfd/pruss/da8xx_prucore.h

-- 
1.7.2.3

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

* [PATCH v1 1/9] mfd: pruss mfd driver.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-01 14:47 ` [PATCH v1 2/9] da850: pruss board specific additions Subhasish Ghosh
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the pruss MFD driver and associated include files.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 drivers/mfd/Kconfig                     |   10 +
 drivers/mfd/Makefile                    |    1 +
 drivers/mfd/da8xx_pru.c                 |  403 +++++++++++++++++++++++++++++++
 include/linux/mfd/pruss/da8xx_pru.h     |  102 ++++++++
 include/linux/mfd/pruss/da8xx_prucore.h |   74 ++++++
 5 files changed, 590 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/da8xx_pru.c
 create mode 100644 include/linux/mfd/pruss/da8xx_pru.h
 create mode 100644 include/linux/mfd/pruss/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..4657054
--- /dev/null
+++ b/drivers/mfd/da8xx_pru.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2010 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/errno.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mfd/pruss/da8xx_prucore.h>
+#include <linux/mfd/pruss/da8xx_pru.h>
+#include <linux/mfd/core.h>
+#include <linux/io.h>
+#include <mach/da8xx.h>
+
+struct da8xx_pruss {
+	struct device *dev;
+	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);
+
+u32 pruss_disable(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+	u32 temp_reg;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* Disable PRU0  */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+
+		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);
+
+		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 */
+		h_pruss->CONTROL = DA8XX_PRUCORE_CONTROL_RESETVAL;
+
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* Disable PRU1 */
+		h_pruss = (da8xx_prusscore_regs)
+		((u32) pruss->ioaddr + 0x7800);
+		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);
+
+		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 */
+		h_pruss->CONTROL = DA8XX_PRUCORE_CONTROL_RESETVAL;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_disable);
+
+u32 pruss_enable(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* Reset PRU0 */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+		h_pruss->CONTROL = DA8XX_PRUCORE_CONTROL_RESETVAL;
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* Reset PRU1  */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7800);
+		h_pruss->CONTROL = DA8XX_PRUCORE_CONTROL_RESETVAL;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_enable);
+
+/* Load the specified PRU with code */
+u32 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);
+	u32 *pruss_iram;
+	u32 i;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		pruss_iram = (u32 *) ((u32) pruss->ioaddr + 0x8000);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		pruss_iram = (u32 *) ((u32) pruss->ioaddr + 0xc000);
+	} else
+		return -EINVAL;
+
+	pruss_enable(dev, pruss_num);
+
+	/* Copy dMAX code to its instruction RAM  */
+	for (i = 0; i < code_size_in_words; i++) {
+		pruss_iram[i] = pruss_code[i];
+	}
+	return 0;
+}
+EXPORT_SYMBOL(pruss_load);
+
+u32 pruss_run(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+
+	u32 temp_reg;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* DA8XX_PRUCORE_0_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* DA8XX_PRUCORE_1_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7800);
+	} else
+		return -EINVAL;
+
+	/* Enable dMAX, let it execute the code we just copied */
+	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);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_run);
+
+u32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+	u32 temp_reg;
+	u32 cnt = timeout;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* DA8XX_PRUCORE_0_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* DA8XX_PRUCORE_1_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7800);
+	} 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);
+
+s16 pruss_writeb(struct device *dev, u32 u32offset,
+					u8 *pu8datatowrite, u16 u16bytestowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u8 *pu8addresstowrite;
+	u16 u16loop;
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu8addresstowrite = (u8 *) (u32offset);
+
+	for (u16loop = 0; u16loop < u16bytestowrite; u16loop++)
+		__raw_writeb(*pu8datatowrite++, pu8addresstowrite++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writeb);
+
+s16 pruss_readb(struct device *dev, u32 u32offset,
+					u8 *pu8datatoread, u16 u16bytestoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u8 *pu8addresstoread;
+	u16 u16loop;
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu8addresstoread = (u8 *) (u32offset);
+
+	for (u16loop = 0; u16loop < u16bytestoread; u16loop++)
+		*pu8datatoread++ = __raw_readb(pu8addresstoread++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readb);
+
+s16 pruss_writel(struct device *dev, u32 u32offset,
+						u32 *pu32datatowrite, s16 u16wordstowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pu32addresstowrite;
+	s16 u16loop;
+
+	/* TODO: Get all the driver API's fixed */
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu32addresstowrite = (u32 *)(u32offset);
+
+	for (u16loop = 0; u16loop < u16wordstowrite; u16loop++)
+		__raw_writel(*pu32datatowrite++, pu32addresstowrite++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writel);
+
+s16 pruss_readl(struct device *dev, u32 u32offset,
+						u32 *pu32datatoread, s16 u16wordstoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pu32addresstoread;
+	s16 u16loop;
+
+	/* TODO: Get all the driver API's fixed */
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu32addresstoread = (u32 *)(u32offset);
+
+	for (u16loop = 0; u16loop < u16wordstoread; u16loop++)
+		*pu32datatoread++ = __raw_readl(pu32addresstoread++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readl);
+
+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;
+
+		err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
+		if (err) {
+			dev_err(dev, "cannot add mfd cells\n");
+			return err;
+		}
+	}
+	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;
+	}
+
+	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);
+	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	= "da8xx_pruss",
+		.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/pruss/da8xx_pru.h b/include/linux/mfd/pruss/da8xx_pru.h
new file mode 100644
index 0000000..318dad8
--- /dev/null
+++ b/include/linux/mfd/pruss/da8xx_pru.h
@@ -0,0 +1,102 @@
+/*
+ * 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
+
+struct da8xx_pruss_devices {
+	const char *dev_name;
+	void *pdata;
+	size_t pdata_size;
+	int (*setup)(void);
+};
+
+u32 pruss_get_clk_freq(struct device *dev);
+
+u32 pruss_enable(struct device *dev, u8 pruss_num);
+
+u32 pruss_load(struct device *dev, u8 pruss_num, u32 *pruss_code,
+			u32 code_size_in_words);
+
+u32 pruss_run(struct device *dev, u8 pruss_num);
+
+u32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout);
+
+u32 pruss_disable(struct device *dev, u8 pruss_num);
+
+s16 pruss_writeb(struct device *dev, u32 u32offset,
+			u8 *pu8datatowrite, u16 u16wordstowrite);
+
+s16 pruss_readb(struct device *dev, u32 u32offset,
+			u8 *pu8datatoread, u16 u16wordstoread);
+
+s16 pruss_readl(struct device *dev, u32 u32offset,
+			u32 *pu32datatoread, s16 s16wordstoread);
+
+s16 pruss_writel(struct device *dev, u32 u32offset,
+			u32 *pu32datatoread, s16 s16wordstoread);
+
+#endif	/* End _PRUSS_H_ */
diff --git a/include/linux/mfd/pruss/da8xx_prucore.h b/include/linux/mfd/pruss/da8xx_prucore.h
new file mode 100644
index 0000000..56b0eac
--- /dev/null
+++ b/include/linux/mfd/pruss/da8xx_prucore.h
@@ -0,0 +1,74 @@
+/*
+ * 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)
+
+typedef struct {
+	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];
+} *da8xx_prusscore_regs;
+
+#endif
-- 
1.7.2.3

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

* [PATCH v1 2/9] da850: pruss board specific additions.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
  2011-02-01 14:47 ` [PATCH v1 1/9] mfd: pruss mfd driver Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 11:49   ` Sergei Shtylyov
  2011-02-01 14:47 ` [PATCH v1 3/9] da850: pruss platform " Subhasish Ghosh
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

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 |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 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..7938c6d 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1053,6 +1053,29 @@ 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) {
+				pr_warning("%s: %s init failed: %d\n", __func__,
+					pruss_devices[count].dev_name, ret);
+				return ret;
+			}
+		}
+	}
+
+	return da8xx_register_pruss(pruss_devices);
+}
+
 static __init void da850_evm_init(void)
 {
 	int ret;
@@ -1127,6 +1150,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] 21+ messages in thread

* [PATCH v1 3/9] da850: pruss platform specific additions.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
  2011-02-01 14:47 ` [PATCH v1 1/9] mfd: pruss mfd driver Subhasish Ghosh
  2011-02-01 14:47 ` [PATCH v1 2/9] da850: pruss board specific additions Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 11:55   ` Sergei Shtylyov
  2011-02-01 14:47 ` [PATCH v1 4/9] can: pruss CAN driver Subhasish Ghosh
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

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 3443d97..341d836 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_DMAX,
+};
+
 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..562882c 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/pruss/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_dev = {
+	.name			=	"da8xx_pruss",
+	.id				=	-1,
+	.num_resources	=	ARRAY_SIZE(da8xx_pruss_resources),
+	.resource		=	da8xx_pruss_resources,
+};
+
+int __init da8xx_register_pruss(struct da8xx_pruss_devices *pruss_device)
+{
+	da8xx_pruss_dev.dev.platform_data = pruss_device;
+	return platform_device_register(&da8xx_pruss_dev);
+}
+
 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 cfcb223..e5c178a 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/pruss/da8xx_pru.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -81,6 +82,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(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] 21+ messages in thread

* [PATCH v1 4/9] can: pruss CAN driver.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (2 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 3/9] da850: pruss platform " Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-03 16:14   ` Detlev Zundel
  2011-02-01 14:47 ` [PATCH v1 5/9] da850: pruss CAN board specific additions Subhasish Ghosh
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for the CAN device emulated on PRUSS.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 drivers/net/can/Kconfig                     |    1 +
 drivers/net/can/Makefile                    |    1 +
 drivers/net/can/da8xx_pruss/Kconfig         |   73 ++
 drivers/net/can/da8xx_pruss/Makefile        |    7 +
 drivers/net/can/da8xx_pruss/pruss_can.c     |  759 +++++++++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.c | 1224 +++++++++++++++++++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.h |  290 +++++++
 7 files changed, 2355 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/da8xx_pruss/Kconfig
 create mode 100644 drivers/net/can/da8xx_pruss/Makefile
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.h

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index d5a9db6..ae8f0f9 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -112,6 +112,7 @@ config PCH_CAN
 	  This driver can access CAN bus.
 
 source "drivers/net/can/mscan/Kconfig"
+source "drivers/net/can/da8xx_pruss/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
 
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 07ca159..849cdbf 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_MSCAN)		+= mscan/
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
+obj-$(CONFIG_CAN_TI_DA8XX_PRU)	+= da8xx_pruss/
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
 obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o
 obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
diff --git a/drivers/net/can/da8xx_pruss/Kconfig b/drivers/net/can/da8xx_pruss/Kconfig
new file mode 100644
index 0000000..8b68f68
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/Kconfig
@@ -0,0 +1,73 @@
+#
+# CAN Lite Kernel Configuration
+#
+config CAN_TI_DA8XX_PRU
+	depends on CAN_DEV && ARCH_DAVINCI && ARCH_DAVINCI_DA850
+	tristate "PRU based CAN emulation for DA8XX"
+	---help---
+	Enable this to emulate a CAN controller on the PRU of DA8XX.
+	If not sure, mark N
+
+config DA8XX_PRU_CANID_MBX0
+	hex "CANID for mailbox 0"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 0
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX1
+	hex "CANID for mailbox 1"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	 ---help---
+	Enter the CANID for mailbox 1
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX2
+	hex "CANID for mailbox 2"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 2
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX3
+	hex "CANID for mailbox 3"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 3
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX4
+	hex "CANID for mailbox 4"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 4
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX5
+	hex "CANID for mailbox 5"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 5
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX6
+	hex "CANID for mailbox 6"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 6
+	Default value is set to 0x123, change this as required.
+
+config DA8XX_PRU_CANID_MBX7
+	hex "CANID for mailbox 7"
+	depends on CAN_TI_DA8XX_PRU
+	default "0x123"
+	---help---
+	Enter the CANID for mailbox 7
+	Default value is set to 0x123, change this as required.
diff --git a/drivers/net/can/da8xx_pruss/Makefile b/drivers/net/can/da8xx_pruss/Makefile
new file mode 100644
index 0000000..48f3055
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for CAN Lite emulation
+#
+can_emu-objs :=   pruss_can.o \
+                  pruss_can_api.o
+
+obj-$(CONFIG_CAN_TI_DA8XX_PRU)    += can_emu.o
diff --git a/drivers/net/can/da8xx_pruss/pruss_can.c b/drivers/net/can/da8xx_pruss/pruss_can.c
new file mode 100644
index 0000000..44f60fa
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/pruss_can.c
@@ -0,0 +1,759 @@
+/*
+ *  TI DA8XX PRU CAN Emulation device driver
+ *  Author: subhasish at mistralsolutions.com
+ *
+ *  This driver supports TI's PRU CAN 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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <mach/da8xx.h>
+#include "pruss_can_api.h"
+
+#define DRV_NAME "da8xx_pruss_can"
+#define DRV_DESC "TI PRU CAN Controller Driver v0.1"
+#define PRU_CAN_START	1
+#define PRU_CAN_STOP	0
+#define MB_MIN			0
+#define MB_MAX			7
+
+#define PRU_CANMID_IDE			BIT(29)	/* Extended frame format */
+
+#define PRU_CAN_ISR_BIT_CCI		BIT(15)
+#define PRU_CAN_ISR_BIT_ESI		BIT(14)
+#define PRU_CAN_ISR_BIT_SRDI	BIT(13)
+#define PRU_CAN_ISR_BIT_RRI		BIT(8)
+
+#define PRU_CAN_MBXSR_BIT_STATE		BIT(7)
+#define PRU_CAN_MBXSR_BIT_TC		BIT(6)
+#define PRU_CAN_MBXSR_BIT_ERR		BIT(5)
+#define PRU_CAN_MBXSR_BIT_OF		BIT(0)
+
+#define PRU_CAN_GSR_BIT_TXM		BIT(7)
+#define PRU_CAN_GSR_BIT_RXM		BIT(6)
+#define PRU_CAN_GSR_BIT_CM		BIT(5)
+#define PRU_CAN_GSR_BIT_EPM		BIT(4)
+#define PRU_CAN_GSR_BIT_BFM		BIT(3)
+#define RTR_MBX_NO	8
+#define MAX_INIT_RETRIES	20
+#define L138_PRU_ARM_FREQ		312000
+#define DFLT_PRU_FREQ			156000000
+#define DFLT_PRU_BITRATE		125000
+
+#define CONFIG_DA8XX_PRU_CANID_MBX0 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX1 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX2 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX3 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX4 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX5 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX6 0x123
+#define CONFIG_DA8XX_PRU_CANID_MBX7 0x123
+
+#ifdef __CAN_DEBUG
+#define __can_debug(fmt, args...) printk(KERN_DEBUG "can_debug: " fmt, ## args)
+#else
+#define __can_debug(fmt, args...)
+#endif
+#define __can_err(fmt, args...) printk(KERN_ERR "can_err: " fmt, ## args)
+
+/*
+ * omapl_pru can private data
+ */
+struct omapl_pru_can_priv {
+	struct can_priv can;
+	struct workqueue_struct *pru_can_wQ;
+	struct work_struct rx_work;
+	struct net_device *ndev;
+	struct device *dev; /* pdev->dev */
+	struct clk *clk_timer;
+	u32 timer_freq;
+	can_emu_app_hndl can_tx_hndl;
+	can_emu_app_hndl can_rx_hndl;
+	const struct firmware *fw_rx;
+	const struct firmware *fw_tx;
+	spinlock_t mbox_lock;
+	u32 trx_irq;
+	u32 tx_head;
+	u32 tx_tail;
+	u32 tx_next;
+	u32 rx_next;
+};
+
+static int omapl_pru_can_get_state(const struct net_device *ndev,
+				   enum can_state *state)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	*state = priv->can.state;
+	return 0;
+}
+
+static int omapl_pru_can_set_bittiming(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	long bit_error = 0;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) {
+		dev_warn(priv->dev, "WARN: Triple"
+			 "sampling not set due to h/w limitations");
+	}
+	if (pru_can_calc_timing(priv->dev, priv->can.clock.freq, bt->bitrate) != 0)
+		return -EINVAL;
+	bit_error =
+	    (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
+	      bt->bitrate) * 1000) / bt->bitrate;
+	if (bit_error) {
+		bit_error =
+		    (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
+		      bt->bitrate) * 1000000) / bt->bitrate;
+		printk(KERN_INFO "\nBitrate error %ld.%ld%%\n",
+			bit_error / 10000, bit_error % 1000);
+	} else
+		printk(KERN_INFO "\nBitrate error 0.0%%\n");
+
+	return 0;
+}
+
+static void omapl_pru_can_stop(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	u16 int_mask = 0;
+
+	pru_can_mask_ints(priv->dev, int_mask);	/* mask all ints */
+	pru_can_start_abort_tx(priv->dev, PRU_CAN_STOP);
+	priv->can.state = CAN_STATE_STOPPED;
+}
+
+/*
+ * This is to just set the can state to ERROR_ACTIVE
+ *	ip link set canX up type can bitrate 125000
+ */
+static void omapl_pru_can_start(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	u16 int_mask = 0xFFFF;
+
+	if (priv->can.state != CAN_STATE_STOPPED)
+		omapl_pru_can_stop(ndev);
+
+	pru_can_mask_ints(priv->dev, int_mask);	/* unmask all ints */
+
+	pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
+	pru_can_get_global_status(priv->dev, &priv->can_rx_hndl);
+
+	if (PRU_CAN_GSR_BIT_EPM & priv->can_tx_hndl.u32globalstatus)
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+	else if (PRU_CAN_GSR_BIT_BFM & priv->can_tx_hndl.u32globalstatus)
+		priv->can.state = CAN_STATE_BUS_OFF;
+	else
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+}
+
+static int omapl_pru_can_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+	int ret = 0;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		omapl_pru_can_start(ndev);
+		if (netif_queue_stopped(ndev))
+			netif_wake_queue(ndev);
+		break;
+	case CAN_MODE_STOP:
+		omapl_pru_can_stop(ndev);
+		if (!netif_queue_stopped(ndev))
+			netif_stop_queue(ndev);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	return ret;
+}
+
+static netdev_tx_t omapl_pru_can_start_xmit(struct sk_buff *skb,
+					    struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	int count;
+	u8 *data = cf->data;
+	u8 dlc = cf->can_dlc;
+	u8 *ptr8data = NULL;
+
+	netif_stop_queue(ndev);
+	if (cf->can_id & CAN_EFF_FLAG)	/* Extended frame format */
+		*((u32 *) &priv->can_tx_hndl.strcanmailbox) =
+		    (cf->can_id & CAN_EFF_MASK) | PRU_CANMID_IDE;
+	else			/* Standard frame format */
+		*((u32 *) &priv->can_tx_hndl.strcanmailbox) =
+		    (cf->can_id & CAN_SFF_MASK) << 18;
+
+	if (cf->can_id & CAN_RTR_FLAG)	/* Remote transmission request */
+		*((u32 *) &priv->can_tx_hndl.strcanmailbox) |= CAN_RTR_FLAG;
+
+	ptr8data = &priv->can_tx_hndl.strcanmailbox.u8data7 + (dlc - 1);
+	for (count = 0; count < (u8) dlc; count++) {
+		*ptr8data-- = *data++;
+	}
+	*((u32 *) &priv->can_tx_hndl.strcanmailbox.u16datalength) = (u32) dlc;
+/*
+ * search for the next available mbx
+ * if the next mbx is busy, then try the next + 1
+ * do this until the head is reached.
+ * if still unable to tx, stop accepting any packets
+ * if able to tx and the head is reached, then reset next to tail, i.e mbx0
+ * if head is not reached, then just point to the next mbx
+ */
+	for (; priv->tx_next <= priv->tx_head; priv->tx_next++) {
+		priv->can_tx_hndl.ecanmailboxnumber =
+		    (can_mailbox_number) priv->tx_next;
+		if (-1 == pru_can_write_data_to_mailbox(priv->dev,
+					&priv->can_tx_hndl)) {
+			if (priv->tx_next == priv->tx_head) {
+				priv->tx_next = priv->tx_tail;
+				if (!netif_queue_stopped(ndev))
+					netif_stop_queue(ndev);	/* IF stalled */
+				dev_err(priv->dev,
+					"%s: no tx mbx available", __func__);
+				return NETDEV_TX_BUSY;
+			} else
+				continue;
+		} else {
+			/* set transmit request */
+			pru_can_tx(priv->dev, priv->tx_next, CAN_TX_PRU_1);
+			pru_can_tx_mode_set(priv->dev, false, ecanreceive);
+			pru_can_tx_mode_set(priv->dev, true, ecantransmit);
+			pru_can_start_abort_tx(priv->dev, PRU_CAN_START);
+			priv->tx_next++;
+			can_put_echo_skb(skb, ndev, 0);
+			break;
+		}
+	}
+	if (priv->tx_next > priv->tx_head) {
+		priv->tx_next = priv->tx_tail;
+	}
+	return NETDEV_TX_OK;
+}
+
+static int omapl_pru_can_rx(struct net_device *ndev, u32 mbxno)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u32 pru_can_mbx_data;
+	u8 *data = NULL;
+	u8 *ptr8data = NULL;
+	int count = 0;
+
+	skb = alloc_can_skb(ndev, &cf);
+	if (!skb) {
+		if (printk_ratelimit())
+			dev_err(priv->dev,
+				"alloc_can_skb() failed\n");
+		return -ENOMEM;
+	}
+	data = cf->data;
+	/*      get payload */
+	priv->can_rx_hndl.ecanmailboxnumber = (can_mailbox_number) mbxno;
+	if (pru_can_get_data_from_mailbox(priv->dev, &priv->can_rx_hndl)) {
+		__can_err("failed to get data from mailbox\n");
+		return -EAGAIN;
+	}
+	/* give ownweship to pru */
+	pru_can_tx(priv->dev, mbxno, CAN_RX_PRU_0);
+
+	/* get data length code */
+	cf->can_dlc =
+	    get_can_dlc(*
+			((u32 *) &priv->can_rx_hndl.strcanmailbox.
+			 u16datalength) & 0xF);
+	if (cf->can_dlc <= 4) {
+		ptr8data =
+		    &priv->can_rx_hndl.strcanmailbox.u8data3 + (4 -
+								cf->can_dlc);
+		for (count = 0; count < cf->can_dlc; count++) {
+			*data++ = *ptr8data++;
+		}
+	} else {
+		ptr8data = &priv->can_rx_hndl.strcanmailbox.u8data3;
+		for (count = 0; count < 4; count++) {
+			*data++ = *ptr8data++;
+		}
+		ptr8data =
+		    &priv->can_rx_hndl.strcanmailbox.u8data4 - (cf->can_dlc -
+								5);
+		for (count = 0; count < cf->can_dlc - 4; count++) {
+			*data++ = *ptr8data++;
+		}
+	}
+
+	pru_can_mbx_data = *((u32 *) &priv->can_rx_hndl.strcanmailbox);
+	/* get id extended or std */
+	if (pru_can_mbx_data & PRU_CANMID_IDE)
+		cf->can_id = (pru_can_mbx_data & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		cf->can_id = (pru_can_mbx_data >> 18) & CAN_SFF_MASK;
+
+	if (pru_can_mbx_data & CAN_RTR_FLAG)
+		cf->can_id |= CAN_RTR_FLAG;
+
+	netif_rx_ni(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+	return 0;
+}
+
+static int omapl_pru_can_err(struct net_device *ndev, int int_status,
+			     int err_status)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	int tx_err_cnt, rx_err_cnt;
+
+	/* propogate the error condition to the can stack */
+	skb = alloc_can_err_skb(ndev, &cf);
+	if (!skb) {
+		if (printk_ratelimit())
+			dev_err(priv->dev,
+				"alloc_can_err_skb() failed\n");
+		return -ENOMEM;
+	}
+
+	if (err_status & PRU_CAN_GSR_BIT_EPM) {	/* error passive int */
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+		++priv->can.can_stats.error_passive;
+		cf->can_id |= CAN_ERR_CRTL;
+		tx_err_cnt = pru_can_get_error_cnt(priv->dev, CAN_TX_PRU_1);
+		rx_err_cnt = pru_can_get_error_cnt(priv->dev, CAN_RX_PRU_0);
+		if (tx_err_cnt > 127)
+			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+		if (rx_err_cnt > 127)
+			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+
+		dev_dbg(priv->ndev->dev.parent, "Error passive interrupt\n");
+	}
+
+	if (err_status & PRU_CAN_GSR_BIT_BFM) {
+		priv->can.state = CAN_STATE_BUS_OFF;
+		cf->can_id |= CAN_ERR_BUSOFF;
+		/*
+		 *      Disable all interrupts in bus-off to avoid int hog
+		 *      this should be handled by the pru
+		 */
+		pru_can_mask_ints(priv->dev, 0xFFFF);
+		can_bus_off(ndev);
+		dev_dbg(priv->ndev->dev.parent, "Bus off mode\n");
+	}
+
+	netif_rx(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+	return 0;
+}
+
+void omapl_pru_can_rx_wQ(struct work_struct *work)
+{
+	struct omapl_pru_can_priv *priv = container_of(work,
+						       struct
+						       omapl_pru_can_priv,
+						       rx_work);
+	struct net_device *ndev = priv->ndev;
+	u32 bit_set, mbxno = 0;
+
+	if (-1 == pru_can_get_intr_status(priv->dev, &priv->can_rx_hndl))
+		return;
+
+	if (PRU_CAN_ISR_BIT_RRI & priv->can_rx_hndl.u32interruptstatus) {
+		mbxno = RTR_MBX_NO;
+		omapl_pru_can_rx(ndev, mbxno);
+	} else {
+		/* Extract the mboxno from the status */
+		for (bit_set = 0; ((priv->can_rx_hndl.u32interruptstatus & 0xFF)
+											>> bit_set != 0); bit_set++)
+		;
+		if (0 == bit_set) {
+			dev_err(priv->dev,
+				"%s: invalid mailbox number: %X\n", __func__,
+				priv->can_rx_hndl.u32interruptstatus);
+		} else {
+			mbxno = bit_set - 1;	/* mail box numbering starts from 0 */
+			if (PRU_CAN_ISR_BIT_ESI & priv->can_rx_hndl.
+			    u32interruptstatus) {
+				pru_can_get_global_status(priv->dev, &priv->can_rx_hndl);
+				omapl_pru_can_err(ndev,
+						  priv->can_rx_hndl.
+						  u32interruptstatus,
+						  priv->can_rx_hndl.
+						  u32globalstatus);
+			} else {
+				omapl_pru_can_rx(ndev, mbxno);
+			}
+		}
+	}
+}
+
+irqreturn_t omapl_tx_can_intr(int irq, void *dev_id)
+{
+	struct net_device *ndev = dev_id;
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	struct net_device_stats *stats = &ndev->stats;
+	u32 bit_set, mbxno;
+
+	pru_can_get_intr_status(priv->dev, &priv->can_tx_hndl);
+	if ((PRU_CAN_ISR_BIT_CCI & priv->can_tx_hndl.u32interruptstatus)
+	    || (PRU_CAN_ISR_BIT_SRDI & priv->can_tx_hndl.u32interruptstatus)) {
+		__can_debug("tx_int_status = 0x%X\n",
+			    priv->can_tx_hndl.u32interruptstatus);
+		can_free_echo_skb(ndev, 0);
+	} else {
+		for (bit_set = 0; ((priv->can_tx_hndl.u32interruptstatus & 0xFF)
+											>> bit_set != 0); bit_set++)
+		;
+		if (0 == bit_set) {
+			__can_err("%s: invalid mailbox number\n", __func__);
+			can_free_echo_skb(ndev, 0);
+		} else {
+			mbxno = bit_set - 1;	/* mail box numbering starts from 0 */
+			if (PRU_CAN_ISR_BIT_ESI & priv->can_tx_hndl.
+			    u32interruptstatus) {
+				/* read gsr and ack pru */
+				pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
+				omapl_pru_can_err(ndev,
+						  priv->can_tx_hndl.
+						  u32interruptstatus,
+						  priv->can_tx_hndl.
+						  u32globalstatus);
+			} else {
+				stats->tx_packets++;
+				/* stats->tx_bytes += dlc; */
+				/*can_get_echo_skb(ndev, 0);*/
+			}
+		}
+	}
+	if (netif_queue_stopped(ndev))
+		netif_wake_queue(ndev);
+
+	can_get_echo_skb(ndev, 0);
+	pru_can_tx_mode_set(priv->dev, true, ecanreceive);
+	return IRQ_HANDLED;
+}
+
+irqreturn_t omapl_rx_can_intr(int irq, void *dev_id)
+{
+
+	struct net_device *ndev = dev_id;
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	u32 intc_status = 0;
+
+	intc_status = pru_can_get_intc_status(priv->dev);
+	if (intc_status & 4)
+		return omapl_tx_can_intr(irq, dev_id);
+	if (intc_status & 2) {
+		if (!work_pending(&priv->rx_work))
+			queue_work(priv->pru_can_wQ, &priv->rx_work);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int omapl_pru_can_open(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+	int err;
+
+	/* register interrupt handler */
+	err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
+			  "pru_can_irq", ndev);
+	if (err) {
+		dev_err(priv->dev, "error requesting rx interrupt\n");
+		goto exit_trx_irq;
+	}
+	/* common open */
+	err = open_candev(ndev);
+	if (err) {
+		dev_err(priv->dev, "open_candev() failed %d\n", err);
+		goto exit_open;
+	}
+
+	pru_can_emu_init(priv->dev, priv->can.clock.freq);
+	priv->tx_tail = MB_MIN;
+	priv->tx_head = MB_MAX;
+
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX0, 0);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX1, 1);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX2, 2);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX3, 3);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX4, 4);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX5, 5);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX6, 6);
+	pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX7, 7);
+
+	omapl_pru_can_start(ndev);
+	netif_start_queue(ndev);
+	return 0;
+
+exit_open:
+	free_irq(priv->trx_irq, ndev);
+exit_trx_irq:
+	return err;
+}
+
+static int omapl_pru_can_close(struct net_device *ndev)
+{
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+
+	if (!netif_queue_stopped(ndev))
+		netif_stop_queue(ndev);
+
+	close_candev(ndev);
+
+	free_irq(priv->trx_irq, ndev);
+	return 0;
+}
+
+static const struct net_device_ops omapl_pru_can_netdev_ops = {
+	.ndo_open		= omapl_pru_can_open,
+	.ndo_stop		= omapl_pru_can_close,
+	.ndo_start_xmit	= omapl_pru_can_start_xmit,
+};
+
+static int __devinit omapl_pru_can_probe(struct platform_device *pdev)
+{
+	struct net_device *ndev = NULL;
+	const struct da8xx_pru_can_data *pdata;
+	struct omapl_pru_can_priv *priv = NULL;
+	struct device *dev = &pdev->dev;
+	u32 err;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data not found\n");
+		return -EINVAL;
+	}
+
+	ndev = alloc_candev(sizeof(struct omapl_pru_can_priv), MB_MAX + 1);
+	if (!ndev) {
+		dev_err(&pdev->dev, "alloc_candev failed\n");
+		err = -ENOMEM;
+		goto probe_exit;
+	}
+	priv = netdev_priv(ndev);
+
+	priv->trx_irq = platform_get_irq(to_platform_device(dev->parent), 0);
+	if (!priv->trx_irq) {
+		dev_err(&pdev->dev, "unable to get pru interrupt resources!\n");
+		err = -ENODEV;
+		goto probe_exit;
+	}
+
+	priv->ndev = ndev;
+	priv->dev = dev; /* priv->dev = pdev->dev */
+
+	priv->can.bittiming_const = NULL;
+	priv->can.do_set_bittiming = omapl_pru_can_set_bittiming;
+	priv->can.do_set_mode = omapl_pru_can_set_mode;
+	priv->can.do_get_state = omapl_pru_can_get_state;
+	priv->can_tx_hndl.u8prunumber = CAN_TX_PRU_1;
+	priv->can_rx_hndl.u8prunumber = CAN_RX_PRU_0;
+
+	/* we support local echo, no arp */
+	ndev->flags |= (IFF_ECHO | IFF_NOARP);
+
+	/* pdev->dev->device_private->driver_data = ndev */
+	platform_set_drvdata(pdev, ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ndev->netdev_ops = &omapl_pru_can_netdev_ops;
+
+	priv->can.clock.freq = pruss_get_clk_freq(priv->dev);
+
+	priv->clk_timer = clk_get(&pdev->dev, "pll1_sysclk2");
+	if (IS_ERR(priv->clk_timer)) {
+		dev_err(&pdev->dev, "no timer clock available\n");
+		err = PTR_ERR(priv->clk_timer);
+		priv->clk_timer = NULL;
+		goto probe_exit_candev;
+	}
+	priv->timer_freq = clk_get_rate(priv->clk_timer);
+
+	err = register_candev(ndev);
+	if (err) {
+		dev_err(&pdev->dev, "register_candev() failed\n");
+		err = -ENODEV;
+		goto probe_exit_clk;
+	}
+
+	err = request_firmware(&priv->fw_tx, "PRU_CAN_Emulation_Tx.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_tx size %d. downloading...\n",
+		 priv->fw_tx->size);
+
+	err = request_firmware(&priv->fw_rx, "PRU_CAN_Emulation_Rx.bin",
+			&pdev->dev);
+	if (err) {
+		dev_err(&pdev->dev, "can't load firmware\n");
+		err = -ENODEV;
+		goto probe_release_fw;
+	}
+	dev_info(&pdev->dev, "fw_rx size %d. downloading...\n",
+		 priv->fw_rx->size);
+
+	/* init the pru */
+	pru_can_emu_init(priv->dev, priv->can.clock.freq);
+	udelay(200);
+
+	pruss_enable(priv->dev, CAN_RX_PRU_0);
+	pruss_enable(priv->dev, CAN_TX_PRU_1);
+
+	/* download firmware into pru */
+	err = pruss_load(priv->dev, CAN_RX_PRU_0,
+				(u32 *)priv->fw_rx->data, (priv->fw_rx->size / 4));
+	if (err) {
+		dev_err(&pdev->dev, "firmware download error\n");
+		err = -ENODEV;
+		goto probe_release_fw_1;
+	}
+	err = pruss_load(priv->dev, CAN_TX_PRU_1,
+				(u32 *)priv->fw_tx->data, (priv->fw_tx->size / 4));
+	if (err) {
+		dev_err(&pdev->dev, "firmware download error\n");
+		err = -ENODEV;
+		goto probe_release_fw_1;
+	}
+
+	if (pru_can_calc_timing(priv->dev, DFLT_PRU_FREQ, DFLT_PRU_BITRATE) != 0)
+		return -EINVAL;
+
+	pruss_run(priv->dev, CAN_RX_PRU_0);
+	pruss_run(priv->dev, CAN_TX_PRU_1);
+
+	/*Create The Work Queue */
+	priv->pru_can_wQ = create_freezeable_workqueue("omapl_pru_wQ");
+	if (priv->pru_can_wQ == NULL) {
+		dev_err(&pdev->dev, "failed to create work queue\n");
+		err = -ENODEV;
+		goto probe_release_fw_1;
+	}
+
+	INIT_WORK(&priv->rx_work, omapl_pru_can_rx_wQ);
+	dev_info(&pdev->dev,
+		 "%s device registered (trx_irq = %d,  clk = %d)\n",
+		 DRV_NAME, priv->trx_irq, priv->can.clock.freq);
+
+	return 0;
+
+probe_release_fw_1:
+	release_firmware(priv->fw_rx);
+probe_release_fw:
+	release_firmware(priv->fw_tx);
+probe_exit_clk:
+	clk_put(priv->clk_timer);
+probe_exit_candev:
+	if (NULL != ndev)
+		free_candev(ndev);
+probe_exit:
+	return err;
+}
+
+static int __devexit omapl_pru_can_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct omapl_pru_can_priv *priv = netdev_priv(ndev);
+
+	omapl_pru_can_stop(ndev);
+
+	pru_can_emu_exit(priv->dev);
+	release_firmware(priv->fw_tx);
+	release_firmware(priv->fw_rx);
+	clk_put(priv->clk_timer);
+	flush_workqueue(priv->pru_can_wQ);
+	destroy_workqueue(priv->pru_can_wQ);
+	unregister_candev(ndev);
+	free_candev(ndev);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omapl_pru_can_suspend(struct platform_device *pdev,
+				 pm_message_t mesg)
+{
+	dev_info(&pdev->dev, "%s not yet implemented\n", __func__);
+	return 0;
+}
+
+static int omapl_pru_can_resume(struct platform_device *pdev)
+{
+	dev_info(&pdev->dev, "%s not yet implemented\n", __func__);
+	return 0;
+}
+#else
+#define omapl_pru_can_suspend NULL
+#define omapl_pru_can_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver omapl_pru_can_driver = {
+	.probe		= omapl_pru_can_probe,
+	.remove		= __devexit_p(omapl_pru_can_remove),
+	.suspend	= omapl_pru_can_suspend,
+	.resume		= omapl_pru_can_resume,
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init omapl_pru_can_init(void)
+{
+	__can_debug(KERN_INFO DRV_DESC "\n");
+	return platform_driver_register(&omapl_pru_can_driver);
+}
+
+module_init(omapl_pru_can_init);
+
+static void __exit omapl_pru_can_exit(void)
+{
+	__can_debug(KERN_INFO DRV_DESC " unloaded\n");
+	platform_driver_unregister(&omapl_pru_can_driver);
+}
+
+module_exit(omapl_pru_can_exit);
+
+MODULE_AUTHOR("Subhasish Ghosh <subhasish@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("omapl pru CAN netdevice driver");
diff --git a/drivers/net/can/da8xx_pruss/pruss_can_api.c b/drivers/net/can/da8xx_pruss/pruss_can_api.c
new file mode 100644
index 0000000..e48c877
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/pruss_can_api.c
@@ -0,0 +1,1224 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Wilfred Felix
+ *
+ * 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 "pruss_can_api.h"
+
+static can_emu_drv_inst gstr_can_inst[ecanmaxinst];
+
+/*
+ * pru_can_set_brp()	Updates the  BRP register of PRU0
+ * and PRU1 of OMAP L138. This API will be called by the
+ * Application to updtae the BRP register of PRU0 and PRU1
+ *
+ * param	u16bitrateprescaler		The can bus bitrate
+ * prescaler value be set
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_set_brp(struct device *dev, u16 u16bitrateprescaler)
+{
+
+	u32 u32offset;
+
+	if (u16bitrateprescaler > 255) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_CLOCK_BRP_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u16bitrateprescaler, 1);
+
+	u32offset = (PRU_CAN_TX_CLOCK_BRP_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u16bitrateprescaler, 1);
+
+	return 0;
+
+}
+
+/*
+ * pru_can_set_bit_timing()		Updates the timing register
+ * of PRU0 and PRU1 of OMAP L138. This API will be called by
+ * the Application to updtae the timing register of PRU0 and PRU1
+ *
+ * param	pstrbittiming		Pointer to structure holding
+ * the bit timing values for can bus.
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_set_bit_timing(struct device *dev,
+					can_bit_timing_consts *pstrbittiming)
+{
+
+	u32 u32offset;
+	u32 u32serregister;
+
+	u32serregister = 0;
+
+	if (pstrbittiming == NULL) {
+		return -1;
+	}
+
+	if ((pstrbittiming->u8syncjumpwidth > PRU_CAN_MAX_SJW) ||
+	    (pstrbittiming->u8phseg1 > PRU_CAN_MAX_PHSEG1) ||
+	    (pstrbittiming->u8phseg2 > PRU_CAN_MAX_PHSEG2)) {
+		return -1;
+	}
+
+	u32serregister = u32serregister |
+			((pstrbittiming->u8syncjumpwidth << 7) |
+			(pstrbittiming->u8phseg1 << 3) |
+			(pstrbittiming->u8phseg2));
+
+	u32offset = (PRU_CAN_TX_TIMING_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u32serregister, 1);
+
+	u32offset = (PRU_CAN_RX_TIMING_REGISTER);
+	pruss_writel(dev, u32offset, (u32 *) &u32serregister, 1);
+
+	return 0;
+}
+
+
+/*
+ * pru_can_calc_timing()	Updates the  timing values of
+ * PRU0 and PRU1 of OMAP L138. This API will be called by the
+ * Application to updtae the timing values of PRU0 and PRU1
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_calc_timing(struct device *dev, u32 pru_freq, u32 bit_rate)
+{
+	u16 u16phaseseg1;
+	u16 u16phaseseg2;
+	u32 u32offset;
+	u32 u32timing_value;
+	u32 u32setup_value;
+	u32timing_value = TIMER_CLK_FREQ / bit_rate;
+	u32offset = (PRU_CAN_TIMING_VAL_TX);
+	pruss_writel(dev, u32offset, (u32 *) &u32timing_value, 4);
+	pruss_readl(dev, u32offset, (u32 *) &u32timing_value, 4);
+	u32setup_value =
+	    (GPIO_SETUP_DELAY * (pru_freq / 1000000) / 1000) /
+	    DELAY_LOOP_LENGTH;
+	u32offset = (PRU_CAN_TIMING_VAL_TX_SJW);
+	pruss_writel(dev, u32offset, (u32 *) &u32setup_value, 4);
+	u16phaseseg1 = (u16) (u32timing_value / 2);
+	u16phaseseg2 = u32timing_value - u16phaseseg1;
+	u16phaseseg1 -= TIMER_SETUP_DELAY;
+	u16phaseseg2 -= TIMER_SETUP_DELAY;
+	u32setup_value = (u16phaseseg1 << 16) | u16phaseseg2;
+	u32offset = (PRU_CAN_TIMING_VAL_RX);
+	pruss_writel(dev, u32offset, (u32 *) &u32setup_value, 4);
+	u32offset = (PRU_CAN_TIMING_VAL_RX + 4);
+	pruss_writel(dev, u32offset, (u32 *) &u32timing_value, 4);
+
+	return 0;
+}
+
+/*
+ * pru_can_write_data_to_mailbox()		Updates the transmit
+ * mailboxes of PRU1 of OMAP L138. This API will be called by
+ * the Application to updtae the transmit mailboxes of PRU1
+ *
+ * param	pu16canframedata	Can mailbox data buffer
+ *
+ * param	u8mailboxnum		Mailbox to be updated
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_write_data_to_mailbox(struct device *dev,
+					can_emu_app_hndl *pstremuapphndl)
+{
+	s16 s16subrtnretval;
+	u32 u32offset;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	switch ((u8) pstremuapphndl->ecanmailboxnumber) {
+	case 0:
+		u32offset = (PRU_CAN_TX_MAILBOX0);
+		break;
+	case 1:
+		u32offset = (PRU_CAN_TX_MAILBOX1);
+		break;
+	case 2:
+		u32offset = (PRU_CAN_TX_MAILBOX2);
+		break;
+	case 3:
+		u32offset = (PRU_CAN_TX_MAILBOX3);
+		break;
+	case 4:
+		u32offset = (PRU_CAN_TX_MAILBOX4);
+		break;
+	case 5:
+		u32offset = (PRU_CAN_TX_MAILBOX5);
+		break;
+	case 6:
+		u32offset = (PRU_CAN_TX_MAILBOX6);
+		break;
+	case 7:
+		u32offset = (PRU_CAN_TX_MAILBOX7);
+		break;
+	default:
+		return -1;
+	}
+
+	s16subrtnretval = pruss_writel(dev, u32offset,
+				(u32 *) &(pstremuapphndl->strcanmailbox), 4);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * pru_can_get_data_from_mailbox()		Receive data from the
+ * receive mailboxes of PRU0  of OMAP L138. This API will be called by
+ * the Application to get data from the receive mailboxes of PRU0
+ *
+ * param	pu16canframedata	Can mailbox data buffer
+ *
+ * param	u8mailboxnum		Mailbox to be updated
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_data_from_mailbox(struct device *dev,
+				can_emu_app_hndl *pstremuapphndl)
+{
+	s16 s16subrtnretval;
+	u32 u32offset;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	switch ((u8) pstremuapphndl->ecanmailboxnumber) {
+	case 0:
+		u32offset = (PRU_CAN_RX_MAILBOX0);
+		break;
+	case 1:
+		u32offset = (PRU_CAN_RX_MAILBOX1);
+		break;
+	case 2:
+		u32offset = (PRU_CAN_RX_MAILBOX2);
+		break;
+	case 3:
+		u32offset = (PRU_CAN_RX_MAILBOX3);
+		break;
+	case 4:
+		u32offset = (PRU_CAN_RX_MAILBOX4);
+		break;
+	case 5:
+		u32offset = (PRU_CAN_RX_MAILBOX5);
+		break;
+	case 6:
+		u32offset = (PRU_CAN_RX_MAILBOX6);
+		break;
+	case 7:
+		u32offset = (PRU_CAN_RX_MAILBOX7);
+		break;
+	case 8:
+		u32offset = (PRU_CAN_RX_MAILBOX8);
+		break;
+	default:
+		return -1;
+	}
+
+	s16subrtnretval =
+	    pruss_readl(dev, u32offset,
+				  (u32 *) &(pstremuapphndl->strcanmailbox),
+				  4);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * pru_can_receive_id_map()		Receive mailboxes ID Mapping of
+ * PRU0  of OMAP L138. This API will be called by the Application
+ * to map the IDs  to receive mailboxes of PRU0
+ *
+ * param	u32nodeid			Can node ID
+ *
+ * param	ecanmailboxno		Mailbox to be mapped
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_rx_id_map(struct device *dev, u32 u32nodeid,
+					can_mailbox_number ecanmailboxno)
+{
+
+	pruss_writel(dev, (PRU_CAN_ID_MAP +
+				(((u8) ecanmailboxno) * 4)), (u32 *) &u32nodeid, 1);
+
+	return 0;
+}
+
+/*
+ * pru_can_get_intr_status()	Gets the interrupts
+ * status register value. This API will be called by the Application
+ * to get the interrupts status register value
+ *
+ * param	u8prunumber		PRU number for which IntStatusReg
+ * has to be read
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_intr_status(struct device *dev,
+					can_emu_app_hndl *pstremuapphndl)
+{
+	u32 u32offset;
+	s16 s16subrtnretval = -1;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
+		u32offset = (PRU_CAN_TX_INTERRUPT_STATUS_REGISTER);
+	} else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
+		u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER);
+	} else {
+		return -1;
+	}
+
+	s16subrtnretval = pruss_readl(dev, u32offset,
+					(u32 *) &pstremuapphndl->u32interruptstatus, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * pru_can_get_global_status()	Gets the globalstatus
+ * register value. This API will be called by the Application
+ * to  get the global status register value
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_global_status(struct device *dev,
+					can_emu_app_hndl *pstremuapphndl)
+{
+	u32 u32offset;
+	int s16subrtnretval = -1;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
+		u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
+	} else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
+		u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
+	} else {
+		return -1;
+	}
+
+	s16subrtnretval = pruss_readl(dev, u32offset,
+					(u32 *) &pstremuapphndl->u32globalstatus, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * pru_can_get_mailbox_status()		Gets the mailbox status
+ * register value. This API will be called by the Application
+ * to get the mailbox status register value
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_get_mailbox_status(struct device *dev,
+						can_emu_app_hndl *pstremuapphndl)
+{
+	u32 u32offset;
+	s16 s16subrtnretval = -1;
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
+		switch (pstremuapphndl->ecanmailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER);
+			break;
+		case 1:
+			u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER);
+			break;
+		case 2:
+			u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER);
+			break;
+		case 3:
+			u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER);
+			break;
+		case 4:
+			u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER);
+			break;
+		case 5:
+			u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER);
+			break;
+		case 6:
+			u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER);
+			break;
+		case 7:
+			u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER);
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
+		switch (pstremuapphndl->ecanmailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER);
+			break;
+		case 1:
+			u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER);
+			break;
+		case 2:
+			u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER);
+			break;
+		case 3:
+			u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER);
+			break;
+		case 4:
+			u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER);
+			break;
+		case 5:
+			u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER);
+			break;
+		case 6:
+			u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER);
+			break;
+		case 7:
+			u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER);
+			break;
+		case 8:
+			u32offset = (PRU_CAN_RX_MAILBOX8_STATUS_REGISTER);
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	else {
+		return -1;
+	}
+
+	s16subrtnretval = pruss_readl(dev, u32offset,
+				(u32 *) &pstremuapphndl->u32mailboxstatus, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+s16 pru_can_tx_mode_set(struct device *dev, bool btransfer_flag,
+								can_transfer_direction ecan_trx)
+{
+	u32 u32offset;
+	u32 u32value;
+
+	if (ecan_trx == ecantransmit) {
+		u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
+		pruss_readl(dev, u32offset, &u32value, 1);
+		if (btransfer_flag == true) {
+			u32value &= 0x1F;
+			u32value |= 0x80;
+		} else {
+			u32value &= 0x7F;
+		}
+		pruss_writel(dev, u32offset, &u32value, 1);
+		u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
+		pruss_writel(dev, u32offset, &u32value, 1);
+	} else if (ecan_trx == ecanreceive) {
+		u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
+		pruss_readl(dev, u32offset, &u32value, 1);
+		if (btransfer_flag == true) {
+			u32value &= 0x1F;
+			u32value |= 0x40;
+		} else {
+			u32value &= 0xBF;
+		}
+		pruss_writel(dev, u32offset, &u32value, 1);
+		u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
+		pruss_writel(dev, u32offset, &u32value, 1);
+	} else
+		return -1;
+
+	return 0;
+}
+
+/*
+ * pru_can_config_mode_set()		Sets the timing value
+ * for data transfer. This API will be called by the Application
+ * to set timing valus for data transfer
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_config_mode_set(struct device *dev, bool bconfigmodeflag)
+{
+
+	u32 u32bitrateprescaler;
+	u32 u32canbittiming;
+
+	pruss_readl(dev, (PRU_CAN_TX_CLOCK_BRP_REGISTER),
+							(u32 *) &u32bitrateprescaler, 1);
+	pruss_readl(dev, (PRU_CAN_TX_TIMING_REGISTER),
+							(u32 *) &u32canbittiming, 1);
+
+	if (bconfigmodeflag == 1) {
+		pru_can_calc_timing(dev, u32canbittiming, u32bitrateprescaler);
+	}
+
+	else {
+		pru_can_calc_timing(dev, 0, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * pru_can_emu_init()		Initializes the Can
+ * Emulation Parameters. This API will be called by the Application
+ * to Initialize the Can Emulation Parameters
+ *
+ * param    u32pruclock         PRU Clock value
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_init(struct device *dev, u32 u32pruclock)
+{
+	u32 u32offset;
+	u32 u32value;
+	s16 s16subrtnretval = -1;
+	u8 u8loop;
+
+	for (u8loop = 0; u8loop < (u8) ecanmaxinst; u8loop++) {
+		gstr_can_inst[u8loop].bcaninststate = (bool) 0;
+		gstr_can_inst[u8loop].ecantransferdirection =
+		    (can_transfer_direction) 0;
+		gstr_can_inst[u8loop].u32apphandlerptr = 0;
+	}
+
+	u32offset = (PRU_CAN_TX_GLOBAL_CONTROL_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000040;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000040;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_INTERRUPT_MASK_REGISTER & 0xFFFF);
+	u32value = 0x00004000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval =
+	    pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000001;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_ERROR_COUNTER_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_TIMING_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_CLOCK_BRP_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_TX_ERROR_COUNTER_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_POLARITY0 & 0xFFFF);
+	u32value = 0xFFFFFFFF;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_POLARITY1 & 0xFFFF);
+	u32value = 0xFFFFFFFF;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_TYPE0 & 0xFFFF);
+	u32value = 0x1C000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_TYPE1 & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HSTINTENIDXCLR & 0xFFFF);
+	u32value = 0x0;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_GLBLEN & 0xFFFF);
+	u32value = 0x1;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	/* tx intr map arm->pru */
+	u32offset = (PRUSS_INTC_HSTINTENIDXSET & 0xFFFF);
+	u32value = 0x0;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTMAP0 & 0xFFFF);
+	u32value = 0x03020100;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTMAP1 & 0xFFFF);
+	u32value = 0x07060504;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTMAP2 & 0xFFFF);
+	u32value = 0x0000908;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_CHANMAP0 & 0xFFFF);
+	u32value = 0;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_CHANMAP8 & 0xFFFF);
+	u32value = 0x00020200;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 19;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 19;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 18;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 18;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 34;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 34;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRUSS_INTC_HOSTINTEN & 0xFFFF);
+	u32value = 0x5;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+/* PRU0 - Rx Internal Registers Initializations */
+
+	u32offset = (PRU_CAN_RX_GLOBAL_CONTROL_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000040;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_INTERRUPT_MASK_REGISTER & 0xFFFF);
+	u32value = 0x00004000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x0000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_ERROR_COUNTER_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_TIMING_REGISTER & 0xFFFF);
+	u32value = 0x0000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+
+	u32offset = (PRU_CAN_RX_CLOCK_BRP_REGISTER & 0xFFFF);
+	u32value = 0x00000000;
+	s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+
+/*
+ * pru_can_emu_open()		Opens the can emu for
+ * application to use. This API will be called by the Application
+ * to Open the can emu for application to use.
+ *
+ * param	pstremuapphndl	Pointer to application handler
+ * structure
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_open(struct device *dev, can_emu_app_hndl *pstremuapphndl)
+{
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+
+	if (gstr_can_inst[pstremuapphndl->ecaninstance].bcaninststate
+																	== 1) {
+		return -1;
+	}
+
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].
+					bcaninststate = (bool)1;
+	gstr_can_inst[(u8) pstremuapphndl->
+		ecaninstance].ecantransferdirection =
+		(can_transfer_direction)(u8)pstremuapphndl->ecantransferdirection;
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].
+					u32apphandlerptr = (u32) pstremuapphndl;
+
+	return 0;
+}
+
+
+/*
+ * brief    pru_can_emu_close()	Closes the can emu for other
+ * applications to use. This API will be called by the Application to Close
+ * the can emu for other applications to use
+ *
+ * param	pstremuapphndl		Pointer to application handler structure
+ *
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_close(struct device *dev, can_emu_app_hndl *pstremuapphndl)
+{
+
+	if (pstremuapphndl == NULL) {
+		return -1;
+	}
+	if (gstr_can_inst[pstremuapphndl->ecaninstance].bcaninststate
+																	== 0) {
+		return -1;
+	}
+	if ((u32) pstremuapphndl != gstr_can_inst[(u8) pstremuapphndl->
+										ecaninstance].u32apphandlerptr){
+		return -1;
+	}
+	gstr_can_inst[(u8) pstremuapphndl->ecaninstance].bcaninststate
+																= (bool) 0;
+	gstr_can_inst[(u8) pstremuapphndl->
+	ecaninstance].ecantransferdirection = (can_transfer_direction) 0;
+	gstr_can_inst[(u8) pstremuapphndl->
+									ecaninstance].u32apphandlerptr = 0;
+
+	return 0;
+}
+
+/*
+ * brief    pru_can_emu_exit()	Diables all the PRUs
+ * This API will be called by the Application to disable all PRUs
+ * param	None
+ * return   SUCCESS or FAILURE
+ */
+s16 pru_can_emu_exit(struct device *dev)
+{
+	s16 s16subrtnretval;
+
+	s16subrtnretval = pruss_disable(dev, CAN_RX_PRU_0);
+	if (s16subrtnretval == -1)
+		return -1;
+	s16subrtnretval = pruss_disable(dev, CAN_TX_PRU_1);
+	if (s16subrtnretval == -1)
+		return -1;
+
+	return 0;
+}
+
+s16 pru_can_emu_sreset(struct device *dev)
+{
+	return 0;
+}
+
+s16 pru_can_tx(struct device *dev, u8 u8mailboxnumber, u8 u8prunumber)
+{
+	u32 u32offset = 0;
+	u32 u32value = 0;
+	s16 s16subrtnretval = -1;
+
+	if (DA8XX_PRUCORE_1 == u8prunumber) {
+		switch (u8mailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 1:
+			u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+										(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 2:
+			u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+										(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 3:
+			u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+										(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 4:
+			u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 5:
+			u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 6:
+			u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 7:
+			u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000080;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		default:
+			return -1;
+		}
+	} else {
+
+		u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
+		u32value = 0x00000000;
+		s16subrtnretval = pruss_readl(dev, u32offset,
+											(u32 *) &u32value, 1);
+		if (s16subrtnretval == -1) {
+			return -1;
+		}
+		u32value = u32value & ~(1 << u8mailboxnumber);
+		s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+		if (s16subrtnretval == -1) {
+			return -1;
+		}
+
+		switch (u8mailboxnumber) {
+		case 0:
+			u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 1:
+			u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 2:
+			u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 3:
+			u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 4:
+			u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 5:
+			u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 6:
+			u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		case 7:
+			u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
+			u32value = 0x00000000;
+			s16subrtnretval = pruss_writel(dev, u32offset,
+											(u32 *) &u32value, 1);
+			if (s16subrtnretval == -1) {
+				return -1;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+	return 0;
+}
+
+s16 pru_can_start_abort_tx(struct device *dev, bool bcantransmitabortflag)
+{
+	u32 u32offset;
+	u32 u32value;
+	s16 s16subrtnretval;
+	u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset,
+								(u32 *) &u32value, 1);
+
+	u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset,
+								(u32 *) &u32value, 1);
+
+	u32offset = (PRUSS_INTC_STATIDXSET & 0xFFFF);
+	u32value = 32;
+	s16subrtnretval = pruss_writel(dev, u32offset,
+								(u32 *) &u32value, 1);
+	if (s16subrtnretval == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+s16 pru_can_mask_ints(struct device *dev, u32 int_mask)
+{
+	return 0;
+}
+
+int pru_can_get_error_cnt(struct device *dev, u8 u8prunumber)
+{
+	return 0;
+}
+
+int pru_can_get_intc_status(struct device *dev)
+{
+	u32 u32offset = 0;
+	u32 u32getvalue = 0;
+	u32 u32clrvalue = 0;
+
+	u32offset = (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
+	pruss_readl(dev, u32offset, (u32 *) &u32getvalue, 1);
+
+	if (u32getvalue & 4)
+		u32clrvalue = 34;	/* CLR Event 34 */
+
+	if (u32getvalue & 2)
+		u32clrvalue = 33;	/* CLR Event 33  */
+
+	if (u32clrvalue) {
+		u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
+		pruss_writel(dev, u32offset, &u32clrvalue, 1);
+	} else
+		return -1;
+
+	return u32getvalue;
+}
diff --git a/drivers/net/can/da8xx_pruss/pruss_can_api.h b/drivers/net/can/da8xx_pruss/pruss_can_api.h
new file mode 100644
index 0000000..f5f704b
--- /dev/null
+++ b/drivers/net/can/da8xx_pruss/pruss_can_api.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Ganeshan N
+ *
+ * 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 _PRU_CAN_API_H_
+#define _PRU_CAN_API_H_
+
+#include <linux/types.h>
+#include <linux/mfd/pruss/da8xx_pru.h>
+
+
+#define CAN_BIT_TIMINGS			(0x273)
+
+/* Timer Clock is sourced from DDR freq (PLL1 SYS CLK 2) */
+#define	TIMER_CLK_FREQ			132000000
+
+#define TIMER_SETUP_DELAY		14
+#define GPIO_SETUP_DELAY		150
+
+#define CAN_RX_PRU_0			PRUSS_NUM0
+#define CAN_TX_PRU_1			PRUSS_NUM1
+
+/* Number of Instruction in the Delay loop */
+#define DELAY_LOOP_LENGTH		2
+
+#define PRU1_BASE_ADDR			0x2000
+
+#define PRU_CAN_TX_GLOBAL_CONTROL_REGISTER		(PRU1_BASE_ADDR)
+#define PRU_CAN_TX_GLOBAL_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x04)
+#define PRU_CAN_TX_INTERRUPT_MASK_REGISTER		(PRU1_BASE_ADDR	+	0x08)
+#define PRU_CAN_TX_INTERRUPT_STATUS_REGISTER	(PRU1_BASE_ADDR	+	0x0C)
+#define PRU_CAN_TX_MAILBOX0_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x10)
+#define PRU_CAN_TX_MAILBOX1_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x14)
+#define PRU_CAN_TX_MAILBOX2_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x18)
+#define PRU_CAN_TX_MAILBOX3_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x1C)
+#define PRU_CAN_TX_MAILBOX4_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x20)
+#define PRU_CAN_TX_MAILBOX5_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x24)
+#define PRU_CAN_TX_MAILBOX6_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x28)
+#define PRU_CAN_TX_MAILBOX7_STATUS_REGISTER		(PRU1_BASE_ADDR	+	0x2C)
+#define PRU_CAN_TX_ERROR_COUNTER_REGISTER		(PRU1_BASE_ADDR	+	0x30)
+#define PRU_CAN_TX_TIMING_REGISTER				(PRU1_BASE_ADDR	+	0x34)
+#define PRU_CAN_TX_CLOCK_BRP_REGISTER			(PRU1_BASE_ADDR	+	0x38)
+
+#define PRU_CAN_TX_MAILBOX0						(PRU1_BASE_ADDR	+	0x40)
+#define PRU_CAN_TX_MAILBOX1						(PRU1_BASE_ADDR	+	0x50)
+#define PRU_CAN_TX_MAILBOX2						(PRU1_BASE_ADDR	+	0x60)
+#define PRU_CAN_TX_MAILBOX3						(PRU1_BASE_ADDR	+	0x70)
+#define PRU_CAN_TX_MAILBOX4						(PRU1_BASE_ADDR	+	0x80)
+#define PRU_CAN_TX_MAILBOX5						(PRU1_BASE_ADDR	+	0x90)
+#define PRU_CAN_TX_MAILBOX6						(PRU1_BASE_ADDR	+	0xA0)
+#define PRU_CAN_TX_MAILBOX7						(PRU1_BASE_ADDR	+	0xB0)
+
+#define PRU_CAN_TIMING_VAL_TX					(PRU1_BASE_ADDR	+	0xC0)
+#define PRU_CAN_TIMING_VAL_TX_SJW				(PRU1_BASE_ADDR	+	0xC4)
+#define PRU_CAN_TRANSMIT_FRAME					(PRU1_BASE_ADDR	+	0xE0)
+
+#define PRU0_BASE_ADDR					0
+
+#define PRU_CAN_RX_GLOBAL_CONTROL_REGISTER		(PRU0_BASE_ADDR)
+#define PRU_CAN_RX_GLOBAL_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x04)
+#define PRU_CAN_RX_INTERRUPT_MASK_REGISTER		(PRU0_BASE_ADDR	+	0x08)
+#define PRU_CAN_RX_INTERRUPT_STATUS_REGISTER	(PRU0_BASE_ADDR	+	0x0C)
+#define PRU_CAN_RX_MAILBOX0_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x10)
+#define PRU_CAN_RX_MAILBOX1_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x14)
+#define PRU_CAN_RX_MAILBOX2_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x18)
+#define PRU_CAN_RX_MAILBOX3_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x1C)
+#define PRU_CAN_RX_MAILBOX4_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x20)
+#define PRU_CAN_RX_MAILBOX5_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x24)
+#define PRU_CAN_RX_MAILBOX6_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x28)
+#define PRU_CAN_RX_MAILBOX7_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x2C)
+#define PRU_CAN_RX_MAILBOX8_STATUS_REGISTER		(PRU0_BASE_ADDR	+	0x30)
+#define PRU_CAN_RX_ERROR_COUNTER_REGISTER		(PRU0_BASE_ADDR	+	0x34)
+#define PRU_CAN_RX_TIMING_REGISTER				(PRU0_BASE_ADDR	+	0x38)
+#define PRU_CAN_RX_CLOCK_BRP_REGISTER			(PRU0_BASE_ADDR	+	0x3C)
+
+#define PRU_CAN_RX_MAILBOX0						(PRU0_BASE_ADDR	+	0x40)
+#define PRU_CAN_RX_MAILBOX1						(PRU0_BASE_ADDR	+	0x50)
+#define PRU_CAN_RX_MAILBOX2						(PRU0_BASE_ADDR	+	0x60)
+#define PRU_CAN_RX_MAILBOX3						(PRU0_BASE_ADDR	+	0x70)
+#define PRU_CAN_RX_MAILBOX4						(PRU0_BASE_ADDR	+	0x80)
+#define PRU_CAN_RX_MAILBOX5						(PRU0_BASE_ADDR	+	0x90)
+#define PRU_CAN_RX_MAILBOX6						(PRU0_BASE_ADDR	+	0xA0)
+#define PRU_CAN_RX_MAILBOX7						(PRU0_BASE_ADDR	+	0xB0)
+#define PRU_CAN_RX_MAILBOX8						(PRU0_BASE_ADDR	+	0xC0)
+
+#define PRU_CAN_TIMING_VAL_RX					(PRU0_BASE_ADDR	+	0xD0)
+#define PRU_CAN_RECEIVE_FRAME					(PRU0_BASE_ADDR	+	0xD4)
+#define PRU_CAN_ID_MAP							(PRU0_BASE_ADDR	+	0xF0)
+
+#define PRU_CAN_ERROR_ACTIVE					128
+
+#define CAN_ACK_FAILED							0xE
+#define CAN_ARBTR_FAIL							0xD
+#define CAN_BIT_ERROR							0xC
+#define CAN_TRANSMISSION_SUCCESS				0xA
+
+#define STD_DATA_FRAME							0x1
+#define EXTD_DATA_FRAME							0x2
+#define STD_REMOTE_FRAME						0x3
+#define EXTD_REMOTE_FRAME						0x4
+
+#define PRU_CAN_MAX_SJW							8
+#define PRU_CAN_MAX_PHSEG1						25
+#define PRU_CAN_MAX_PHSEG2						25
+
+#define DA8XX_PRUCANCORE_0_REGS					0x7000
+#define DA8XX_PRUCANCORE_1_REGS					0x7800
+#define PRU0_PROG_RAM_START_OFFSET				0x8000
+#define PRU1_PROG_RAM_START_OFFSET				0xC000
+#define PRU_CAN_INIT_MAX_TIMEOUT				0xFF
+
+typedef enum {
+	ecaninst0 = 0,
+	ecaninst1,
+	ecanmaxinst
+} can_instance_enum;
+
+typedef enum {
+	ecanmailbox0 = 0,
+	ecanmailbox1,
+	ecanmailbox2,
+	ecanmailbox3,
+	ecanmailbox4,
+	ecanmailbox5,
+	ecanmailbox6,
+	ecanmailbox7
+} can_mailbox_number;
+
+typedef enum {
+	ecandirectioninit = 0,
+	ecantransmit,
+	ecanreceive
+} can_transfer_direction;
+
+typedef struct {
+	u16 u16extendedidentifier;
+	u16 u16baseidentifier;
+	u8 u8data7;
+	u8 u8data6;
+	u8 u8data5;
+	u8 u8data4;
+	u8 u8data3;
+	u8 u8data2;
+	u8 u8data1;
+	u8 u8data0;
+	u16 u16datalength;
+	u16 u16crc;
+} can_mail_box_structure;
+
+typedef struct {
+	can_transfer_direction ecantransferdirection;
+} can_mailbox_config;
+
+typedef struct {
+	can_instance_enum ecaninstance;
+	can_transfer_direction ecantransferdirection;
+	can_mail_box_structure strcanmailbox;
+	can_mailbox_number ecanmailboxnumber;
+	u8 u8prunumber;
+	u32 u32globalstatus;
+	u32 u32interruptstatus;
+	u32 u32mailboxstatus;
+} can_emu_app_hndl;
+
+typedef struct {
+	bool bcaninststate;
+	can_transfer_direction ecantransferdirection;
+	u32 u32apphandlerptr;
+} can_emu_drv_inst;
+
+typedef struct {
+	u8 u8syncjumpwidth;
+	u8 u8phseg1;
+	u8 u8phseg2;
+} can_bit_timing_consts;
+
+/* Field Definition Macros  */
+
+/* CONTROL */
+
+/*
+ * pru_can_set_brp()	Updates the  BRP register of PRU.
+ */
+s16 pru_can_set_brp(struct device *dev, u16 u16prescaler);
+
+/*
+ * pru_can_set_bit_timing()	Updates the  timing register of PRU
+ */
+s16 pru_can_set_bit_timing(struct device *dev,
+			can_bit_timing_consts *pstrbittiming);
+
+/*
+ * pru_can_calc_timing()	Updates the timing values of PRU
+ */
+s16 pru_can_calc_timing(struct device *dev,
+			u32 u32bittiming, u32 u32bitrateprescaler);
+
+/*
+ * pru_can_write_data_to_mailbox()	Updates the transmit mailboxes of PRU1
+ */
+s16 pru_can_write_data_to_mailbox(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_get_data_from_mailbox()	Receive data from receive mailboxes
+ */
+s16 pru_can_get_data_from_mailbox(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_rx_id_map()Receive mailboxes ID Mapping of PRU0
+ */
+s16 pru_can_rx_id_map(struct device *dev,
+			u32 u32nodeid, can_mailbox_number ecanmailboxno);
+
+/*
+ *pru_can_get_intr_status()	Get interrupts status register value
+ */
+s16 pru_can_get_intr_status(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+
+/*
+ * pru_can_get_global_status()	Get the globalstatus register value
+ */
+s16 pru_can_get_global_status(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_get_mailbox_status()	Get mailbox status reg value
+ */
+s16 pru_can_get_mailbox_status(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_configuration_mode_set() Sets timing val for data transfer
+ */
+s16 pru_can_config_mode_set(struct device *dev,
+			bool bconfig_modeflag);
+
+/*
+ * pru_can_emu_init()	Initializes Can Emulation Parameters
+ */
+s16 pru_can_emu_init(struct device *dev,
+			u32 u32pruclock);
+
+/*
+ * pru_can_emu_open() Opens can emu for application to use
+ */
+s16 pru_can_emu_open(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_emu_close() Closes can emu for applications to use
+ */
+s16 pru_can_emu_close(struct device *dev,
+			can_emu_app_hndl *pstremuapphndl);
+
+/*
+ * pru_can_emu_exit()		Diables all the PRUs
+ */
+s16 pru_can_emu_exit(struct device *dev);
+
+s16 pru_can_tx_mode_set(struct device *dev, bool btransfer_flag,
+								 can_transfer_direction ecan_trx);
+
+s16 pru_can_emu_sreset(struct device *dev);
+
+s16 pru_can_tx(struct device *dev,
+			u8 u8mailboxnumber, u8 u8prunumber);
+
+s16 pru_can_start_abort_tx(struct device *dev,
+			bool btxabort_flag);
+
+s16 pru_can_mask_ints(struct device *dev, u32 int_mask);
+
+s32 pru_can_get_error_cnt(struct device *dev, u8 u8prunumber);
+
+s32 pru_can_get_intc_status(struct device *dev);
+#endif
-- 
1.7.2.3

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

* [PATCH v1 5/9] da850: pruss CAN board specific additions.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (3 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 4/9] can: pruss CAN driver Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 12:01   ` Sergei Shtylyov
  2011-02-01 14:47 ` [PATCH v1 6/9] da850: pruss CAN platform " Subhasish Ghosh
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the pruss CAN 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 |   40 ++++++++++++++++++++++++++++++-
 1 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 7938c6d..285545f 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1053,8 +1053,46 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+const short da850_pruss_can_pins[] = {
+	DA850_PRUSS_PRU0_R31_0, DA850_PRUSS_PRU1_R30_15,
+	DA850_PRUSS_PRU1_R31_18,
+	-1
+};
+
+static int __init da850_evm_setup_pruss_can(void)
+{
+	int ret, val = 0;
+	void __iomem *cfg_chip3_base;
+
+	if (!machine_is_davinci_da850_evm())
+		return 0;
+
+	ret = davinci_cfg_reg_list(da850_pruss_can_pins);
+	if (ret)
+		pr_warning("%s: da850_pruss_can_pins mux setup "
+					"failed:%d\n", __func__, ret);
+	cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
+	val = __raw_readl(cfg_chip3_base);
+	val |= BIT(3);
+	__raw_writel(val, cfg_chip3_base);
+
+	return ret;
+}
+
+static struct da8xx_pruss_can_data can_data = {
+	.version	= 1,
+};
+
 static struct da8xx_pruss_devices pruss_devices[] = {
-	{.dev_name = NULL,},
+	{
+		.dev_name	= "da8xx_pruss_can",
+		.pdata		= &can_data,
+		.pdata_size	= sizeof(can_data),
+		.setup		= da850_evm_setup_pruss_can,
+	},
+	{
+		.dev_name	= NULL,
+	},
 };
 
 static int __init da8xx_evm_setup_pruss(void)
-- 
1.7.2.3

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

* [PATCH v1 6/9] da850: pruss CAN platform specific additions.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (4 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 5/9] da850: pruss CAN board specific additions Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 12:03   ` Sergei Shtylyov
  2011-02-01 14:47 ` [PATCH v1 7/9] mfd: pruss CAN private data Subhasish Ghosh
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the necessary pins for the pruss CAN.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/da850.c            |    4 ++++
 arch/arm/mach-davinci/include/mach/mux.h |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 341d836..11ce7ba 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -565,6 +565,10 @@ static const struct mux_config da850_pins[] = {
 	MUX_CFG(DA850, EMA_CLK,		6,	0,	15,	1,	false)
 	MUX_CFG(DA850, EMA_WAIT_1,	6,	24,	15,	1,	false)
 	MUX_CFG(DA850, NEMA_CS_2,	7,	0,	15,	1,	false)
+	/* PRU functions for soft CAN */
+	MUX_CFG(DA850, PRUSS_PRU0_R31_0,	7,	28,	15,	0,	false)
+	MUX_CFG(DA850, PRUSS_PRU1_R30_15,	12,	0,	15,	4,	false)
+	MUX_CFG(DA850, PRUSS_PRU1_R31_18,	11,	20,	15,	0,	false)
 	/* GPIO function */
 	MUX_CFG(DA850, GPIO2_4,		6,	12,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_6,		6,	4,	15,	8,	false)
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index 5d4e0fe..10f49f2 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -906,6 +906,10 @@ enum davinci_da850_index {
 	DA850_EMA_CLK,
 	DA850_EMA_WAIT_1,
 	DA850_NEMA_CS_2,
+	/* PRU I/O */
+	DA850_PRUSS_PRU0_R31_0,
+	DA850_PRUSS_PRU1_R30_15,
+	DA850_PRUSS_PRU1_R31_18,
 
 	/* GPIO function */
 	DA850_GPIO2_4,
-- 
1.7.2.3

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

* [PATCH v1 7/9] mfd: pruss CAN private data.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (5 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 6/9] da850: pruss CAN platform " Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 12:05   ` Sergei Shtylyov
  2011-02-01 14:47 ` [PATCH v1 8/9] da850: pruss CAN board specific changes for gpios Subhasish Ghosh
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the PRUSS CAN data.

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

diff --git a/include/linux/mfd/pruss/da8xx_pru.h b/include/linux/mfd/pruss/da8xx_pru.h
index 318dad8..2fa7ff5 100644
--- a/include/linux/mfd/pruss/da8xx_pru.h
+++ b/include/linux/mfd/pruss/da8xx_pru.h
@@ -74,6 +74,10 @@ struct da8xx_pruss_devices {
 	int (*setup)(void);
 };
 
+struct da8xx_pruss_can_data {
+	u32 version;
+};
+
 u32 pruss_get_clk_freq(struct device *dev);
 
 u32 pruss_enable(struct device *dev, u8 pruss_num);
-- 
1.7.2.3

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

* [PATCH v1 8/9] da850: pruss CAN board specific changes for gpios.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (6 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 7/9] mfd: pruss CAN private data Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 12:07   ` Sergei Shtylyov
  2011-02-01 14:47 ` [PATCH v1 9/9] da850: pruss CAN platform " Subhasish Ghosh
  2011-02-02 16:13 ` [PATCH v1 0/9] pruss mfd drivers Nori, Sekhar
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the GPIO modifications required for the pruss CAN.

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

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 285545f..737df73 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -45,6 +45,7 @@
 
 #define DA850_MMCSD_CD_PIN		GPIO_TO_PIN(4, 0)
 #define DA850_MMCSD_WP_PIN		GPIO_TO_PIN(4, 1)
+#define DA850_PRUSS_CAN_TRX_PIN	GPIO_TO_PIN(2, 0)
 
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
@@ -1055,7 +1056,7 @@ static __init int da850_evm_init_cpufreq(void) { return 0; }
 
 const short da850_pruss_can_pins[] = {
 	DA850_PRUSS_PRU0_R31_0, DA850_PRUSS_PRU1_R30_15,
-	DA850_PRUSS_PRU1_R31_18,
+	DA850_PRUSS_PRU1_R31_18, DA850_GPIO2_0,
 	-1
 };
 
@@ -1076,6 +1077,14 @@ static int __init da850_evm_setup_pruss_can(void)
 	val |= BIT(3);
 	__raw_writel(val, cfg_chip3_base);
 
+	/* value = 0 to enable the CAN transceiver */
+	ret = gpio_request_one(DA850_PRUSS_CAN_TRX_PIN,
+					GPIOF_OUT_INIT_LOW, "pruss_can_en");
+	if (ret) {
+		pr_warning("Cannot setup GPIO %d\n", DA850_PRUSS_CAN_TRX_PIN);
+		gpio_free(DA850_PRUSS_CAN_TRX_PIN);
+	}
+
 	return ret;
 }
 
-- 
1.7.2.3

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

* [PATCH v1 9/9] da850: pruss CAN platform specific changes for gpios.
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (7 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 8/9] da850: pruss CAN board specific changes for gpios Subhasish Ghosh
@ 2011-02-01 14:47 ` Subhasish Ghosh
  2011-02-02 12:08   ` Sergei Shtylyov
  2011-02-02 16:13 ` [PATCH v1 0/9] pruss mfd drivers Nori, Sekhar
  9 siblings, 1 reply; 21+ messages in thread
From: Subhasish Ghosh @ 2011-02-01 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the GPIOs for the pruss CAN device.

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

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 11ce7ba..9382b4f 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -570,6 +570,7 @@ static const struct mux_config da850_pins[] = {
 	MUX_CFG(DA850, PRUSS_PRU1_R30_15,	12,	0,	15,	4,	false)
 	MUX_CFG(DA850, PRUSS_PRU1_R31_18,	11,	20,	15,	0,	false)
 	/* GPIO function */
+	MUX_CFG(DA850, GPIO2_0,		6,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_4,		6,	12,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_6,		6,	4,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_8,		5,	28,	15,	8,	false)
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index 10f49f2..85b3a0d 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -912,6 +912,7 @@ enum davinci_da850_index {
 	DA850_PRUSS_PRU1_R31_18,
 
 	/* GPIO function */
+	DA850_GPIO2_0,
 	DA850_GPIO2_4,
 	DA850_GPIO2_6,
 	DA850_GPIO2_8,
-- 
1.7.2.3

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

* [PATCH v1 2/9] da850: pruss board specific additions.
  2011-02-01 14:47 ` [PATCH v1 2/9] da850: pruss board specific additions Subhasish Ghosh
@ 2011-02-02 11:49   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 01-02-2011 17:47, 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..7938c6d 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1053,6 +1053,29 @@ 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)

    Only da850_evm_setup_pruss() -- we're in the DA850 EVM support file.

> +{
> +	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) {
> +				pr_warning("%s: %s init failed: %d\n", __func__,
> +					pruss_devices[count].dev_name, ret);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	return da8xx_register_pruss(pruss_devices);
> +}
> +
>   static __init void da850_evm_init(void)
>   {
>   	int ret;
> @@ -1127,6 +1150,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);

    Does it really make sense to print 2 messages for one error?

WBR, Sergei

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

* [PATCH v1 3/9] da850: pruss platform specific additions.
  2011-02-01 14:47 ` [PATCH v1 3/9] da850: pruss platform " Subhasish Ghosh
@ 2011-02-02 11:55   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 01-02-2011 17:47, Subhasish Ghosh wrote:

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

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

> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 3443d97..341d836 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_DMAX,

    IIRC, you were asked to change/add a new name for what is known as 
DA8XX_LPSC0_DMAX...

> diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
> index beda8a4..562882c 100644
> --- a/arch/arm/mach-davinci/devices-da8xx.c
> +++ b/arch/arm/mach-davinci/devices-da8xx.c

> +struct platform_device da8xx_pruss_dev = {
> +	.name			=	"da8xx_pruss",
> +	.id				=	-1,
> +	.num_resources	=	ARRAY_SIZE(da8xx_pruss_resources),
> +	.resource		=	da8xx_pruss_resources,

    Please align = uniformly.

> diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
> index cfcb223..e5c178a 100644
> --- a/arch/arm/mach-davinci/include/mach/da8xx.h
> +++ b/arch/arm/mach-davinci/include/mach/da8xx.h
[...]
> @@ -81,6 +82,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(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);

    This patch should clearly precede the patch 2/9 as it defines 
da8xx_register_pruss() which 2/9 uses.

WBR, Sergei

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

* [PATCH v1 5/9] da850: pruss CAN board specific additions.
  2011-02-01 14:47 ` [PATCH v1 5/9] da850: pruss CAN board specific additions Subhasish Ghosh
@ 2011-02-02 12:01   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 12:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 01-02-2011 17:47, Subhasish Ghosh wrote:

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

> 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 7938c6d..285545f 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1053,8 +1053,46 @@ static __init int da850_evm_init_cpufreq(void)
>   static __init int da850_evm_init_cpufreq(void) { return 0; }
>   #endif
>
> +const short da850_pruss_can_pins[] = {

    Only da850_evm_pruss_can_pins[].

> +	DA850_PRUSS_PRU0_R31_0, DA850_PRUSS_PRU1_R30_15,
> +	DA850_PRUSS_PRU1_R31_18,
> +	-1
> +};
> +
> +static int __init da850_evm_setup_pruss_can(void)
> +{
> +	int ret, val = 0;
> +	void __iomem *cfg_chip3_base;

    CFGCHIP3 is a signle register, so it doesn't make sense to talk about its 
base...

> +	if (!machine_is_davinci_da850_evm())
> +		return 0;

    This check doesn't make sense as this function is not declared as 
*_initcall(). It will only be called on this machine anyway.

> +	ret = davinci_cfg_reg_list(da850_pruss_can_pins);
> +	if (ret)
> +		pr_warning("%s: da850_pruss_can_pins mux setup "
> +					"failed:%d\n", __func__, ret);
> +	cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
> +	val = __raw_readl(cfg_chip3_base);
> +	val |= BIT(3);
> +	__raw_writel(val, cfg_chip3_base);
> +
> +	return ret;
> +}
> +
> +static struct da8xx_pruss_can_data can_data = {
> +	.version	= 1,
> +};
> +
>   static struct da8xx_pruss_devices pruss_devices[] = {
> -	{.dev_name = NULL,},
> +	{
> +		.dev_name	= "da8xx_pruss_can",
> +		.pdata		= &can_data,
> +		.pdata_size	= sizeof(can_data),
> +		.setup		= da850_evm_setup_pruss_can,
> +	},
> +	{
> +		.dev_name	= NULL,
> +	},

    Why you need a dummy lst element in this array?

WBR, Sergei

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

* [PATCH v1 6/9] da850: pruss CAN platform specific additions.
  2011-02-01 14:47 ` [PATCH v1 6/9] da850: pruss CAN platform " Subhasish Ghosh
@ 2011-02-02 12:03   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 01-02-2011 17:47, Subhasish Ghosh wrote:

> This patch adds the necessary pins for the pruss CAN.

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

> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 341d836..11ce7ba 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -565,6 +565,10 @@ static const struct mux_config da850_pins[] = {
>   	MUX_CFG(DA850, EMA_CLK,		6,	0,	15,	1,	false)
>   	MUX_CFG(DA850, EMA_WAIT_1,	6,	24,	15,	1,	false)
>   	MUX_CFG(DA850, NEMA_CS_2,	7,	0,	15,	1,	false)
> +	/* PRU functions for soft CAN */
> +	MUX_CFG(DA850, PRUSS_PRU0_R31_0,	7,	28,	15,	0,	false)
> +	MUX_CFG(DA850, PRUSS_PRU1_R30_15,	12,	0,	15,	4,	false)
> +	MUX_CFG(DA850, PRUSS_PRU1_R31_18,	11,	20,	15,	0,	false)
>   	/* GPIO function */
>   	MUX_CFG(DA850, GPIO2_4,		6,	12,	15,	8,	false)
>   	MUX_CFG(DA850, GPIO2_6,		6,	4,	15,	8,	false)
> diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
> index 5d4e0fe..10f49f2 100644
> --- a/arch/arm/mach-davinci/include/mach/mux.h
> +++ b/arch/arm/mach-davinci/include/mach/mux.h
> @@ -906,6 +906,10 @@ enum davinci_da850_index {
>   	DA850_EMA_CLK,
>   	DA850_EMA_WAIT_1,
>   	DA850_NEMA_CS_2,
> +	/* PRU I/O */
> +	DA850_PRUSS_PRU0_R31_0,
> +	DA850_PRUSS_PRU1_R30_15,
> +	DA850_PRUSS_PRU1_R31_18,

    Again, this patch should precede the patch 5/9 due to PinMux dependencies. 
I thought it must be pretty clear...

WBR, Sergei

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

* [PATCH v1 7/9] mfd: pruss CAN private data.
  2011-02-01 14:47 ` [PATCH v1 7/9] mfd: pruss CAN private data Subhasish Ghosh
@ 2011-02-02 12:05   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 12:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 01-02-2011 17:47, Subhasish Ghosh wrote:

> This patch adds the PRUSS CAN data.

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

> diff --git a/include/linux/mfd/pruss/da8xx_pru.h b/include/linux/mfd/pruss/da8xx_pru.h
> index 318dad8..2fa7ff5 100644
> --- a/include/linux/mfd/pruss/da8xx_pru.h
> +++ b/include/linux/mfd/pruss/da8xx_pru.h
> @@ -74,6 +74,10 @@ struct da8xx_pruss_devices {
>   	int (*setup)(void);
>   };
>
> +struct da8xx_pruss_can_data {
> +	u32 version;
> +};
> +

    This patch too should precede the patch 5/9 as it defines the stucture 
used there...

WBR, Sergei

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

* [PATCH v1 8/9] da850: pruss CAN board specific changes for gpios.
  2011-02-01 14:47 ` [PATCH v1 8/9] da850: pruss CAN board specific changes for gpios Subhasish Ghosh
@ 2011-02-02 12:07   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 01-02-2011 17:47, Subhasish Ghosh wrote:

> This patch adds the GPIO modifications required for the pruss CAN.

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

> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index 285545f..737df73 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -45,6 +45,7 @@
>
>   #define DA850_MMCSD_CD_PIN		GPIO_TO_PIN(4, 0)
>   #define DA850_MMCSD_WP_PIN		GPIO_TO_PIN(4, 1)
> +#define DA850_PRUSS_CAN_TRX_PIN	GPIO_TO_PIN(2, 0)
>
>   #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
>
> @@ -1055,7 +1056,7 @@ static __init int da850_evm_init_cpufreq(void) { return 0; }
>
>   const short da850_pruss_can_pins[] = {
>   	DA850_PRUSS_PRU0_R31_0, DA850_PRUSS_PRU1_R30_15,
> -	DA850_PRUSS_PRU1_R31_18,
> +	DA850_PRUSS_PRU1_R31_18, DA850_GPIO2_0,
>   	-1
>   };
>
> @@ -1076,6 +1077,14 @@ static int __init da850_evm_setup_pruss_can(void)
>   	val |= BIT(3);
>   	__raw_writel(val, cfg_chip3_base);
>
> +	/* value = 0 to enable the CAN transceiver */
> +	ret = gpio_request_one(DA850_PRUSS_CAN_TRX_PIN,
> +					GPIOF_OUT_INIT_LOW, "pruss_can_en");
> +	if (ret) {
> +		pr_warning("Cannot setup GPIO %d\n", DA850_PRUSS_CAN_TRX_PIN);
> +		gpio_free(DA850_PRUSS_CAN_TRX_PIN);
> +	}
> +
>   	return ret;
>   }

    Should be mereged with patch 5/9, I think...

WBR, Sergei

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

* [PATCH v1 9/9] da850: pruss CAN platform specific changes for gpios.
  2011-02-01 14:47 ` [PATCH v1 9/9] da850: pruss CAN platform " Subhasish Ghosh
@ 2011-02-02 12:08   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2011-02-02 12:08 UTC (permalink / raw)
  To: linux-arm-kernel

On 01-02-2011 17:47, Subhasish Ghosh wrote:

> This patch adds the GPIOs for the pruss CAN device.

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

> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 11ce7ba..9382b4f 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -570,6 +570,7 @@ static const struct mux_config da850_pins[] = {
>   	MUX_CFG(DA850, PRUSS_PRU1_R30_15,	12,	0,	15,	4,	false)
>   	MUX_CFG(DA850, PRUSS_PRU1_R31_18,	11,	20,	15,	0,	false)
>   	/* GPIO function */
> +	MUX_CFG(DA850, GPIO2_0,		6,	28,	15,	8,	false)
>   	MUX_CFG(DA850, GPIO2_4,		6,	12,	15,	8,	false)
>   	MUX_CFG(DA850, GPIO2_6,		6,	4,	15,	8,	false)
>   	MUX_CFG(DA850, GPIO2_8,		5,	28,	15,	8,	false)
> diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
> index 10f49f2..85b3a0d 100644
> --- a/arch/arm/mach-davinci/include/mach/mux.h
> +++ b/arch/arm/mach-davinci/include/mach/mux.h
> @@ -912,6 +912,7 @@ enum davinci_da850_index {
>   	DA850_PRUSS_PRU1_R31_18,
>
>   	/* GPIO function */
> +	DA850_GPIO2_0,
>   	DA850_GPIO2_4,
>   	DA850_GPIO2_6,
>   	DA850_GPIO2_8,

    Should again precede the previous patch. I thought that must be obvious...

WBR, Sergei

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

* [PATCH v1 0/9] pruss mfd drivers
  2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
                   ` (8 preceding siblings ...)
  2011-02-01 14:47 ` [PATCH v1 9/9] da850: pruss CAN platform " Subhasish Ghosh
@ 2011-02-02 16:13 ` Nori, Sekhar
  2011-02-02 16:20   ` Mark Brown
  9 siblings, 1 reply; 21+ messages in thread
From: Nori, Sekhar @ 2011-02-02 16:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 20:17:38, Subhasish Ghosh wrote:

>  arch/arm/mach-davinci/board-da850-evm.c     |   75 ++
>  arch/arm/mach-davinci/da850.c               |   12 +
>  arch/arm/mach-davinci/devices-da8xx.c       |   65 ++
>  arch/arm/mach-davinci/include/mach/da8xx.h  |    2 +
>  arch/arm/mach-davinci/include/mach/mux.h    |    5 +
>  drivers/mfd/Kconfig                         |   10 +
>  drivers/mfd/Makefile                        |    1 +
>  drivers/mfd/da8xx_pru.c                     |  403 +++++++++
>  drivers/net/can/Kconfig                     |    1 +
>  drivers/net/can/Makefile                    |    1 +
>  drivers/net/can/da8xx_pruss/Kconfig         |   73 ++
>  drivers/net/can/da8xx_pruss/Makefile        |    7 +
>  drivers/net/can/da8xx_pruss/pruss_can.c     |  759 +++++++++++++++++
>  drivers/net/can/da8xx_pruss/pruss_can_api.c | 1224 

The MFD and netdev lists need to be copied on this submission
as this cannot be merged without an ack from the maintainers
of those subsystems.

To automate copying the right folks on each patch, please use:

git-send-email --to <davinci list> --cc-cmd=scripts/get_maintainer.pl  [...]

Thanks,
Sekhar

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

* [PATCH v1 0/9] pruss mfd drivers
  2011-02-02 16:13 ` [PATCH v1 0/9] pruss mfd drivers Nori, Sekhar
@ 2011-02-02 16:20   ` Mark Brown
  2011-02-02 16:36     ` Nori, Sekhar
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Brown @ 2011-02-02 16:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 02, 2011 at 09:43:51PM +0530, Nori, Sekhar wrote:

> To automate copying the right folks on each patch, please use:

> git-send-email --to <davinci list> --cc-cmd=scripts/get_maintainer.pl  [...]

Please don't use get_maintainer.pl directly like this - you need to
apply some thought and consideration to the results as it generates both
false positives and false negatives.

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

* [PATCH v1 0/9] pruss mfd drivers
  2011-02-02 16:20   ` Mark Brown
@ 2011-02-02 16:36     ` Nori, Sekhar
  0 siblings, 0 replies; 21+ messages in thread
From: Nori, Sekhar @ 2011-02-02 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 02, 2011 at 21:50:48, Mark Brown wrote:
> On Wed, Feb 02, 2011 at 09:43:51PM +0530, Nori, Sekhar wrote:
> 
> > To automate copying the right folks on each patch, please use:
> 
> > git-send-email --to <davinci list> --cc-cmd=scripts/get_maintainer.pl  [...]
> 
> Please don't use get_maintainer.pl directly like this - you need to
> apply some thought and consideration to the results as it generates both
> false positives and false negatives.

Point taken. I usually do a --dry-run before actually sending
just to verify the results.

Thanks,
Sekhar

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

* [PATCH v1 4/9] can: pruss CAN driver.
  2011-02-01 14:47 ` [PATCH v1 4/9] can: pruss CAN driver Subhasish Ghosh
@ 2011-02-03 16:14   ` Detlev Zundel
  0 siblings, 0 replies; 21+ messages in thread
From: Detlev Zundel @ 2011-02-03 16:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

> This patch adds support for the CAN device emulated on PRUSS.

You should CC the netdev[1] and the socketcan mailing lists[2] on these
patches.

Cheers
  Detlev

[1] netdev at vger.kernel.org
[2] socketcan-core at lists.berlios.de

--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

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

end of thread, other threads:[~2011-02-03 16:14 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-01 14:47 [PATCH v1 0/9] pruss mfd drivers Subhasish Ghosh
2011-02-01 14:47 ` [PATCH v1 1/9] mfd: pruss mfd driver Subhasish Ghosh
2011-02-01 14:47 ` [PATCH v1 2/9] da850: pruss board specific additions Subhasish Ghosh
2011-02-02 11:49   ` Sergei Shtylyov
2011-02-01 14:47 ` [PATCH v1 3/9] da850: pruss platform " Subhasish Ghosh
2011-02-02 11:55   ` Sergei Shtylyov
2011-02-01 14:47 ` [PATCH v1 4/9] can: pruss CAN driver Subhasish Ghosh
2011-02-03 16:14   ` Detlev Zundel
2011-02-01 14:47 ` [PATCH v1 5/9] da850: pruss CAN board specific additions Subhasish Ghosh
2011-02-02 12:01   ` Sergei Shtylyov
2011-02-01 14:47 ` [PATCH v1 6/9] da850: pruss CAN platform " Subhasish Ghosh
2011-02-02 12:03   ` Sergei Shtylyov
2011-02-01 14:47 ` [PATCH v1 7/9] mfd: pruss CAN private data Subhasish Ghosh
2011-02-02 12:05   ` Sergei Shtylyov
2011-02-01 14:47 ` [PATCH v1 8/9] da850: pruss CAN board specific changes for gpios Subhasish Ghosh
2011-02-02 12:07   ` Sergei Shtylyov
2011-02-01 14:47 ` [PATCH v1 9/9] da850: pruss CAN platform " Subhasish Ghosh
2011-02-02 12:08   ` Sergei Shtylyov
2011-02-02 16:13 ` [PATCH v1 0/9] pruss mfd drivers Nori, Sekhar
2011-02-02 16:20   ` Mark Brown
2011-02-02 16:36     ` Nori, Sekhar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.