This patch series add support for PRUSS (Programmable Real-time Unit Sub
System) UIO driver in Texas Instruments DA850, AM18xx and OMAPL1-38 processors.
PRUSS is programmable RISC core which can be used to implement Soft IPs
(eg:- DMA, CAN, UART,SmartCard) and Industrial communications data link layers
(eg:- PROFIBUS). UIO driver exposes PRUSS resources like memory and interrupts
to user space application.PRUSS UIO application API can be used to control PRUs
in PRUSS, setup PRU INTC, load firmware to PRUs and implement IPC between Host
processor and PRUs. More information on PRUSS and UIO linux user space API
available in the links below
http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem
http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader_API_Guide
Pratheesh Gangadhar (2):
PRUSS UIO driver support
Defines DA850/AM18xx/OMAPL1-38 SOC resources used by PRUSS UIO driver
arch/arm/mach-davinci/board-da850-evm.c | 4 +
arch/arm/mach-davinci/da850.c | 35 +++++
arch/arm/mach-davinci/devices-da8xx.c | 73 ++++++++++
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +
drivers/uio/Kconfig | 17 +++
drivers/uio/Makefile | 1 +
drivers/uio/uio_pruss.c | 216 ++++++++++++++++++++++++++++
7 files changed, 349 insertions(+), 0 deletions(-)
create mode 100644 drivers/uio/uio_pruss.c
This patch defines PRUSS, ECAP clocks, memory and IRQ resources
used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
DDR buffer to user space. PRUSS has 8 host event interrupt lines
mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
with shared memory can be used to implement IPC between ARM9 and
PRUSS.
Signed-off-by: Pratheesh Gangadhar <[email protected]>
---
arch/arm/mach-davinci/board-da850-evm.c | 4 ++
arch/arm/mach-davinci/da850.c | 35 +++++++++++++
arch/arm/mach-davinci/devices-da8xx.c | 73 ++++++++++++++++++++++++++++
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +
4 files changed, 115 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..bd85aa3 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
ret);
+ ret = da8xx_register_pruss();
+ if (ret)
+ pr_warning("da850_evm_init: pruss registration failed: %d\n",
+ ret);
ret = da8xx_register_watchdog();
if (ret)
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 3443d97..0096d4f 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
.flags = ALWAYS_ENABLED,
};
+static struct clk pruss_clk = {
+ .name = "pruss",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC0_DMAX,
+ .flags = ALWAYS_ENABLED,
+};
+
static struct clk uart0_clk = {
.name = "uart0",
.parent = &pll0_sysclk2,
@@ -359,6 +366,30 @@ static struct clk usb20_clk = {
.gpsc = 1,
};
+static struct clk ecap0_clk = {
+ .name = "ecap0",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
+static struct clk ecap1_clk = {
+ .name = "ecap1",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
+static struct clk ecap2_clk = {
+ .name = "ecap2",
+ .parent = &pll0_sysclk2,
+ .lpsc = DA8XX_LPSC1_ECAP,
+ .flags = DA850_CLK_ASYNC3,
+ .gpsc = 1,
+};
+
static struct clk_lookup da850_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll0", &pll0_clk),
@@ -386,6 +417,7 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "tptc1", &tptc1_clk),
CLK(NULL, "tpcc1", &tpcc1_clk),
CLK(NULL, "tptc2", &tptc2_clk),
+ CLK(NULL, "pruss", &pruss_clk),
CLK(NULL, "uart0", &uart0_clk),
CLK(NULL, "uart1", &uart1_clk),
CLK(NULL, "uart2", &uart2_clk),
@@ -403,6 +435,9 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "usb11", &usb11_clk),
CLK(NULL, "usb20", &usb20_clk),
+ CLK(NULL, "ecap0", &ecap0_clk),
+ CLK(NULL, "ecap1", &ecap1_clk),
+ CLK(NULL, "ecap2", &ecap2_clk),
CLK(NULL, NULL, NULL),
};
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index beda8a4..4ea3d1f 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
return platform_device_register(&da8xx_cpuidle_device);
}
+static struct resource pruss_resources[] = {
+ [0] = {
+ .start = DA8XX_PRUSS_BASE,
+ .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DA8XX_L3RAM_BASE,
+ .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 0,
+ .end = SZ_256K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ [3] = {
+ .start = IRQ_DA8XX_EVTOUT0,
+ .end = IRQ_DA8XX_EVTOUT0,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = IRQ_DA8XX_EVTOUT1,
+ .end = IRQ_DA8XX_EVTOUT1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = IRQ_DA8XX_EVTOUT2,
+ .end = IRQ_DA8XX_EVTOUT2,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = IRQ_DA8XX_EVTOUT3,
+ .end = IRQ_DA8XX_EVTOUT3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = IRQ_DA8XX_EVTOUT4,
+ .end = IRQ_DA8XX_EVTOUT4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [8] = {
+ .start = IRQ_DA8XX_EVTOUT5,
+ .end = IRQ_DA8XX_EVTOUT5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [9] = {
+ .start = IRQ_DA8XX_EVTOUT6,
+ .end = IRQ_DA8XX_EVTOUT6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [10] = {
+ .start = IRQ_DA8XX_EVTOUT7,
+ .end = IRQ_DA8XX_EVTOUT7,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pruss_device = {
+ .name = "pruss",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(pruss_resources),
+ .resource = pruss_resources,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ }
+};
+
+int __init da8xx_register_pruss()
+{
+ return platform_device_register(&pruss_device);
+}
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index cfcb223..3ed6ee0 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -60,6 +60,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_PLL0_BASE 0x01c11000
#define DA8XX_TIMER64P0_BASE 0x01c20000
#define DA8XX_TIMER64P1_BASE 0x01c21000
+#define DA8XX_PRUSS_BASE 0x01c30000
#define DA8XX_GPIO_BASE 0x01e26000
#define DA8XX_PSC1_BASE 0x01e27000
#define DA8XX_LCD_CNTRL_BASE 0x01e13000
@@ -68,6 +69,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_AEMIF_CS2_BASE 0x60000000
#define DA8XX_AEMIF_CS3_BASE 0x62000000
#define DA8XX_AEMIF_CTL_BASE 0x68000000
+#define DA8XX_L3RAM_BASE 0x80000000
#define DA8XX_DDR2_CTL_BASE 0xb0000000
#define DA8XX_ARM_RAM_BASE 0xffff0000
@@ -90,6 +92,7 @@ int da850_register_cpufreq(char *async_clk);
int da8xx_register_cpuidle(void);
void __iomem * __init da8xx_get_mem_ctlr(void);
int da850_register_pm(struct platform_device *pdev);
+int da8xx_register_pruss(void);
extern struct platform_device da8xx_serial_device;
extern struct emac_platform_data da8xx_emac_pdata;
--
1.6.0.6
This patch implements PRUSS (Programmable Real-time Unit Sub System)
UIO driver which exports SOC resources associated with PRUSS like
I/O, memories and IRQs to user space. PRUSS is dual 32-bit RISC
processors which is efficient in performing embedded tasks that
require manipulation of packed memory mapped data structures and
efficient in handling system events that have tight real time
constraints. This driver is currently supported on Texas Instruments
DA850, AM18xx and OMAPL1-38 devices.
For example, PRUSS runs firmware for real-time critical industrial
communication data link layer and communicates with application stack
running in user space via shared memory and IRQs.
Signed-off-by: Pratheesh Gangadhar <[email protected]>
---
drivers/uio/Kconfig | 17 ++++
drivers/uio/Makefile | 1 +
drivers/uio/uio_pruss.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 234 insertions(+), 0 deletions(-)
create mode 100644 drivers/uio/uio_pruss.c
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index bb44079..6f3ea9b 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -94,4 +94,21 @@ config UIO_NETX
To compile this driver as a module, choose M here; the module
will be called uio_netx.
+config UIO_PRUSS
+ tristate "Texas Instruments PRUSS driver"
+ depends on ARCH_DAVINCI_DA850
+ help
+ PRUSS driver for OMAPL138/DA850/AM18XX devices
+ PRUSS driver requires user space components, examples and user space
+ driver is available from below SVN repo - you may use anonymous login
+
+ https://gforge.ti.com/gf/project/pru_sw/
+
+ More info on API is available at below wiki
+
+ http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
+
+ To compile this driver as a module, choose M here: the module
+ will be called uio_pruss.
+
endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18fd818..d4dd9a5 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o
obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
obj-$(CONFIG_UIO_NETX) += uio_netx.o
+obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
new file mode 100644
index 0000000..bb92941
--- /dev/null
+++ b/drivers/uio/uio_pruss.c
@@ -0,0 +1,216 @@
+/*
+ * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
+ *
+ * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
+ * and DDR RAM to user space for applications interacting with PRUSS firmware
+ *
+ * Copyright (C) 2010-11 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/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#define DRV_NAME "pruss"
+#define DRV_VERSION "0.50"
+
+/*
+ * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt
+ * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
+ * firmware and user space application, async notification from PRU firmware
+ * to user space application
+ * 3 PRU_EVTOUT0
+ * 4 PRU_EVTOUT1
+ * 5 PRU_EVTOUT2
+ * 6 PRU_EVTOUT3
+ * 7 PRU_EVTOUT4
+ * 8 PRU_EVTOUT5
+ * 9 PRU_EVTOUT6
+ * 10 PRU_EVTOUT7
+*/
+
+#define MAX_PRUSS_EVT 8
+
+#define PINTC_HIPIR 0x4900
+#define HIPIR_NOPEND 0x80000000
+#define PINTC_HIER 0x5500
+
+static struct clk *pruss_clk;
+static struct uio_info *info;
+static dma_addr_t ddr_paddr;
+static void *ddr_vaddr, *prussio_vaddr;
+
+static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
+{
+ void __iomem *base = dev_info->mem[0].internal_addr;
+ void __iomem *intren_reg = base + PINTC_HIER;
+ void __iomem *intrstat_reg = base + PINTC_HIPIR + ((irq - 1) << 2);
+ int val = ioread32(intren_reg), intr_mask = (1 << (irq - 1));
+
+ /* Is interrupt enabled and active ? */
+ if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND))
+ return IRQ_NONE;
+
+ /* Disable interrupt */
+ iowrite32((val & ~intr_mask), intren_reg);
+ return IRQ_HANDLED;
+}
+
+static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
+{
+ struct uio_info *p = info;
+ int cnt;
+
+ for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+ uio_unregister_device(p);
+ kfree(p->name);
+ }
+ iounmap(prussio_vaddr);
+ if (ddr_vaddr)
+ dma_free_coherent(&dev->dev, info->mem[2].size,
+ info->mem[2].internal_addr, info->mem[2].addr);
+ kfree(info);
+ clk_put(pruss_clk);
+}
+
+static int __devinit pruss_probe(struct platform_device *dev)
+{
+ struct uio_info *p;
+ int ret = -ENODEV, cnt = 0, len;
+ struct resource *regs_prussio, *regs_l3ram, *regs_ddr;
+
+ info = kzalloc(sizeof(struct uio_info) * MAX_PRUSS_EVT, GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ /* Power on PRU in case its not done as part of boot-loader */
+ pruss_clk = clk_get(&dev->dev, "pruss");
+ if (IS_ERR(pruss_clk)) {
+ dev_err(&dev->dev, "Failed to get clock\n");
+ kfree(info);
+ ret = PTR_ERR(pruss_clk);
+ return ret;
+ } else {
+ clk_enable(pruss_clk);
+ }
+
+ regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!regs_prussio) {
+ dev_err(&dev->dev, "No PRUSS I/O resource specified\n");
+ goto out_free;
+ }
+
+ regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ if (!regs_l3ram) {
+ dev_err(&dev->dev, "No L3 RAM resource specified\n");
+ goto out_free;
+ }
+
+ regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ if (!regs_ddr) {
+ dev_err(&dev->dev, "No External RAM resource specified\n");
+ goto out_free;
+ }
+
+ if (!regs_prussio->start || !regs_l3ram->start) {
+ dev_err(&dev->dev, "Invalid memory resource\n");
+ goto out_free;
+ }
+ len = resource_size(regs_ddr);
+ ddr_vaddr =
+ dma_alloc_coherent(&dev->dev, len, &ddr_paddr, GFP_KERNEL | GFP_DMA);
+ if (!ddr_vaddr) {
+ dev_err(&dev->dev, "Could not allocate external memory\n");
+ goto out_free;
+ }
+ len = resource_size(regs_prussio);
+ prussio_vaddr = ioremap(regs_prussio->start, len);
+ if (!prussio_vaddr) {
+ dev_err(&dev->dev, "Can't remap PRUSS I/O address range\n");
+ goto out_free;
+ }
+
+ for (cnt = 0, p = info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+ p->mem[0].internal_addr = prussio_vaddr;
+ p->mem[0].addr = regs_prussio->start;
+ p->mem[0].size = resource_size(regs_prussio);
+ p->mem[0].memtype = UIO_MEM_PHYS;
+
+ p->mem[1].addr = regs_l3ram->start;
+ p->mem[1].size = resource_size(regs_l3ram);
+ p->mem[1].memtype = UIO_MEM_PHYS;
+
+ p->mem[2].internal_addr = ddr_vaddr;
+ p->mem[2].addr = ddr_paddr;
+ p->mem[2].size = resource_size(regs_ddr);
+ p->mem[2].memtype = UIO_MEM_PHYS;
+
+ p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+ p->version = "0.50";
+
+ /* Register PRUSS IRQ lines */
+ p->irq = IRQ_DA8XX_EVTOUT0 + cnt;
+ p->handler = pruss_handler;
+
+ ret = uio_register_device(&dev->dev, p);
+
+ if (ret < 0)
+ goto out_free;
+ }
+
+ platform_set_drvdata(dev, info);
+ return 0;
+
+out_free:
+ pruss_cleanup(dev, info);
+ return ret;
+}
+
+static int __devexit pruss_remove(struct platform_device *dev)
+{
+ struct uio_info *info = platform_get_drvdata(dev);
+
+ pruss_cleanup(dev, info);
+ platform_set_drvdata(dev, NULL);
+ return 0;
+}
+
+static struct platform_driver pruss_driver = {
+ .probe = pruss_probe,
+ .remove = __devexit_p(pruss_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pruss_init_module(void)
+{
+ return platform_driver_register(&pruss_driver);
+}
+
+module_init(pruss_init_module);
+
+static void __exit pruss_exit_module(void)
+{
+ platform_driver_unregister(&pruss_driver);
+}
+
+module_exit(pruss_exit_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Amit Chatterjee <[email protected]>");
+MODULE_AUTHOR("Pratheesh Gangadhar <[email protected]>");
--
1.6.0.6
On Thu, 24 Feb 2011, Pratheesh Gangadhar wrote:
A few nits.
> +static void pruss_cleanup(struct platform_device *dev, struct uio_info *info)
> +{
> + struct uio_info *p = info;
> + int cnt;
> +
> + for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
> + uio_unregister_device(p);
> + kfree(p->name);
> + }
> + iounmap(prussio_vaddr);
> + if (ddr_vaddr)
> + dma_free_coherent(&dev->dev, info->mem[2].size,
> + info->mem[2].internal_addr, info->mem[2].addr);
That is easier to read with curly braces even if they are strictly not
necessary
if (ddr_vaddr) {
dma_free_coherent(&dev->dev, info->mem[2].size,
info->mem[2].internal_addr, info->mem[2].addr);
}
> + kfree(info);
> + clk_put(pruss_clk);
> +}
> + len = resource_size(regs_ddr);
> + ddr_vaddr =
> + dma_alloc_coherent(&dev->dev, len, &ddr_paddr, GFP_KERNEL | GFP_DMA);
That wants to be:
ddr_vaddr = dma_alloc_coherent(&dev->dev, len, &ddr_paddr,
GFP_KERNEL | GFP_DMA);
Otherwise this looks very clean and readable now and I can't spot any
technical problems with it anymore.
Please fixup the nits and feel free to add
Reviewed-by: Thomas Gleixner <[email protected]>
Thanks for following up on all this!
tglx
On 24-02-2011 17:06, Pratheesh Gangadhar wrote:
> This patch defines PRUSS, ECAP clocks, memory and IRQ resources
> used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
It's OMAP-L138.
> driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
> DDR buffer to user space. PRUSS has 8 host event interrupt lines
> mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
> with shared memory can be used to implement IPC between ARM9 and
> PRUSS.
> Signed-off-by: Pratheesh Gangadhar<[email protected]>
[...]
> diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
> index 11f986b..bd85aa3 100644
> --- a/arch/arm/mach-davinci/board-da850-evm.c
> +++ b/arch/arm/mach-davinci/board-da850-evm.c
> @@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
> pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
> ret);
>
> + ret = da8xx_register_pruss();
> + if (ret)
> + pr_warning("da850_evm_init: pruss registration failed: %d\n",
> + ret);
Use __func__ to print the function name.
>
> ret = da8xx_register_watchdog();
> if (ret)
As I said, please put this into serpate patch.
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index 3443d97..0096d4f 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
> .flags = ALWAYS_ENABLED,
> };
>
> +static struct clk pruss_clk = {
> + .name = "pruss",
> + .parent = &pll0_sysclk2,
> + .lpsc = DA8XX_LPSC0_DMAX,
> + .flags = ALWAYS_ENABLED,
> +};
> +
This conflicts with previously posted patch.
> static struct clk uart0_clk = {
> .name = "uart0",
> .parent =&pll0_sysclk2,
> @@ -359,6 +366,30 @@ static struct clk usb20_clk = {
> .gpsc = 1,
> };
>
> +static struct clk ecap0_clk = {
> + .name = "ecap0",
> + .parent = &pll0_sysclk2,
> + .lpsc = DA8XX_LPSC1_ECAP,
> + .flags = DA850_CLK_ASYNC3,
> + .gpsc = 1,
> +};
> +
> +static struct clk ecap1_clk = {
> + .name = "ecap1",
> + .parent = &pll0_sysclk2,
> + .lpsc = DA8XX_LPSC1_ECAP,
> + .flags = DA850_CLK_ASYNC3,
> + .gpsc = 1,
> +};
> +
> +static struct clk ecap2_clk = {
> + .name = "ecap2",
> + .parent = &pll0_sysclk2,
> + .lpsc = DA8XX_LPSC1_ECAP,
> + .flags = DA850_CLK_ASYNC3,
> + .gpsc = 1,
> +};
> +
This is worth separate patch too...
> diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
> index beda8a4..4ea3d1f 100644
> --- a/arch/arm/mach-davinci/devices-da8xx.c
> +++ b/arch/arm/mach-davinci/devices-da8xx.c
> @@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
>
> return platform_device_register(&da8xx_cpuidle_device);
> }
> +static struct resource pruss_resources[] = {
> + [0] = {
> + .start = DA8XX_PRUSS_BASE,
> + .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = DA8XX_L3RAM_BASE,
> + .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [2] = {
> + .start = 0,
> + .end = SZ_256K - 1,
Huh? I don't see where it's filled...
> + .flags = IORESOURCE_MEM,
> + },
> +
[...]
> +int __init da8xx_register_pruss()
> +{
> + return platform_device_register(&pruss_device);
> +}
> diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
> index cfcb223..3ed6ee0 100644
> --- a/arch/arm/mach-davinci/include/mach/da8xx.h
> +++ b/arch/arm/mach-davinci/include/mach/da8xx.h
> @@ -60,6 +60,7 @@ extern unsigned int da850_max_speed;
> #define DA8XX_PLL0_BASE 0x01c11000
> #define DA8XX_TIMER64P0_BASE 0x01c20000
> #define DA8XX_TIMER64P1_BASE 0x01c21000
> +#define DA8XX_PRUSS_BASE 0x01c30000
> #define DA8XX_GPIO_BASE 0x01e26000
> #define DA8XX_PSC1_BASE 0x01e27000
> #define DA8XX_LCD_CNTRL_BASE 0x01e13000
> @@ -68,6 +69,7 @@ extern unsigned int da850_max_speed;
> #define DA8XX_AEMIF_CS2_BASE 0x60000000
> #define DA8XX_AEMIF_CS3_BASE 0x62000000
> #define DA8XX_AEMIF_CTL_BASE 0x68000000
> +#define DA8XX_L3RAM_BASE 0x80000000
There were already patches defining macros for these base addresses...
WBR, Sergei
On Fri, Feb 25, 2011 at 02:47:34PM +0300, Sergei Shtylyov wrote:
> On 24-02-2011 17:06, Pratheesh Gangadhar wrote:
>
> >This patch defines PRUSS, ECAP clocks, memory and IRQ resources
> >used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
>
> It's OMAP-L138.
>From the TI wiki: "The PRU subsystem is supported on
OMAP-L1x8/C674m/AM18xx devices (where m is an even number)."
http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem
Thanks,
Hans
Hello.
On 25-02-2011 16:02, Hans J. Koch wrote:
>>> This patch defines PRUSS, ECAP clocks, memory and IRQ resources
>>> used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
>> It's OMAP-L138.
> From the TI wiki: "The PRU subsystem is supported on
> OMAP-L1x8/C674m/AM18xx devices (where m is an even number)."
> http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem
I meant there's a typo in "OMAPL1-38".
> Thanks,
> Hans
WBR, Sergei
Hi,
> -----Original Message-----
> From: Sergei Shtylyov [mailto:[email protected]]
> Sent: Friday, February 25, 2011 5:18 PM
> To: TK, Pratheesh Gangadhar
> Cc: [email protected]; [email protected];
> [email protected]; [email protected]; [email protected]; Chatterjee, Amit;
> [email protected]; [email protected]
> Subject: Re: [PATCH v4 2/2] Defines DA850/AM18xx/OMAPL1-38 SOC resources
> used by PRUSS UIO driver
>
> On 24-02-2011 17:06, Pratheesh Gangadhar wrote:
>
> > This patch defines PRUSS, ECAP clocks, memory and IRQ resources
> > used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
>
> It's OMAP-L138.
Ok.
>
> > driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
> > DDR buffer to user space. PRUSS has 8 host event interrupt lines
> > mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
> > with shared memory can be used to implement IPC between ARM9 and
> > PRUSS.
>
> > Signed-off-by: Pratheesh Gangadhar<[email protected]>
> [...]
>
> > diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-
> davinci/board-da850-evm.c
> > index 11f986b..bd85aa3 100644
> > --- a/arch/arm/mach-davinci/board-da850-evm.c
> > +++ b/arch/arm/mach-davinci/board-da850-evm.c
> > @@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
> > pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
> > ret);
> >
> > + ret = da8xx_register_pruss();
> > + if (ret)
> > + pr_warning("da850_evm_init: pruss registration failed: %d\n",
> > + ret);
>
> Use __func__ to print the function name.
>
> >
> > ret = da8xx_register_watchdog();
> > if (ret)
>
> As I said, please put this into serpate patch.
>
Ok, will do.
> > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-
> davinci/da850.c
> > index 3443d97..0096d4f 100644
> > --- a/arch/arm/mach-davinci/da850.c
> > +++ b/arch/arm/mach-davinci/da850.c
> > @@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
> > .flags = ALWAYS_ENABLED,
> > };
> >
> > +static struct clk pruss_clk = {
> > + .name = "pruss",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC0_DMAX,
> > + .flags = ALWAYS_ENABLED,
> > +};
> > +
>
> This conflicts with previously posted patch.
>
Ok, shall I rename to align with previous patch from Mistral or drop this from my patchset ?
> > static struct clk uart0_clk = {
> > .name = "uart0",
> > .parent =&pll0_sysclk2,
> > @@ -359,6 +366,30 @@ static struct clk usb20_clk = {
> > .gpsc = 1,
> > };
> >
> > +static struct clk ecap0_clk = {
> > + .name = "ecap0",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC1_ECAP,
> > + .flags = DA850_CLK_ASYNC3,
> > + .gpsc = 1,
> > +};
> > +
> > +static struct clk ecap1_clk = {
> > + .name = "ecap1",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC1_ECAP,
> > + .flags = DA850_CLK_ASYNC3,
> > + .gpsc = 1,
> > +};
> > +
> > +static struct clk ecap2_clk = {
> > + .name = "ecap2",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC1_ECAP,
> > + .flags = DA850_CLK_ASYNC3,
> > + .gpsc = 1,
> > +};
> > +
>
> This is worth separate patch too...
>
Ok.
> > diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-
> davinci/devices-da8xx.c
> > index beda8a4..4ea3d1f 100644
> > --- a/arch/arm/mach-davinci/devices-da8xx.c
> > +++ b/arch/arm/mach-davinci/devices-da8xx.c
> > @@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
> >
> > return platform_device_register(&da8xx_cpuidle_device);
> > }
> > +static struct resource pruss_resources[] = {
> > + [0] = {
> > + .start = DA8XX_PRUSS_BASE,
> > + .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [1] = {
> > + .start = DA8XX_L3RAM_BASE,
> > + .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [2] = {
> > + .start = 0,
> > + .end = SZ_256K - 1,
>
> Huh? I don't see where it's filled...
>
The current use is only to indicate memory block size to the PRUSS UIO driver when we allocate DDR memory using dma_alloc_coherent. sram_alloc is changed to use L3_RAM (128KB) instead of ARM RAM (8KB) in Mistral patch set - I need to follow the same convention for L3 RAM as well if I need to align with that patch. Is there a better way to do this?
> > + .flags = IORESOURCE_MEM,
> > + },
> > +
> [...]
> > +int __init da8xx_register_pruss()
> > +{
> > + return platform_device_register(&pruss_device);
> > +}
> > diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-
> davinci/include/mach/da8xx.h
> > index cfcb223..3ed6ee0 100644
> > --- a/arch/arm/mach-davinci/include/mach/da8xx.h
> > +++ b/arch/arm/mach-davinci/include/mach/da8xx.h
> > @@ -60,6 +60,7 @@ extern unsigned int da850_max_speed;
> > #define DA8XX_PLL0_BASE 0x01c11000
> > #define DA8XX_TIMER64P0_BASE 0x01c20000
> > #define DA8XX_TIMER64P1_BASE 0x01c21000
> > +#define DA8XX_PRUSS_BASE 0x01c30000
> > #define DA8XX_GPIO_BASE 0x01e26000
> > #define DA8XX_PSC1_BASE 0x01e27000
> > #define DA8XX_LCD_CNTRL_BASE 0x01e13000
> > @@ -68,6 +69,7 @@ extern unsigned int da850_max_speed;
> > #define DA8XX_AEMIF_CS2_BASE 0x60000000
> > #define DA8XX_AEMIF_CS3_BASE 0x62000000
> > #define DA8XX_AEMIF_CTL_BASE 0x68000000
> > +#define DA8XX_L3RAM_BASE 0x80000000
>
> There were already patches defining macros for these base addresses...
>
Ok - will align with this.
Thanks,
Pratheesh
Hi Pratheesh,
On Mon, Feb 28, 2011 at 10:16:18, TK, Pratheesh Gangadhar wrote:
> > > diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-
> > davinci/devices-da8xx.c
> > > index beda8a4..4ea3d1f 100644
> > > --- a/arch/arm/mach-davinci/devices-da8xx.c
> > > +++ b/arch/arm/mach-davinci/devices-da8xx.c
> > > @@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
> > >
> > > return platform_device_register(&da8xx_cpuidle_device);
> > > }
> > > +static struct resource pruss_resources[] = {
> > > + [0] = {
> > > + .start = DA8XX_PRUSS_BASE,
> > > + .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
> > > + .flags = IORESOURCE_MEM,
> > > + },
> > > + [1] = {
> > > + .start = DA8XX_L3RAM_BASE,
> > > + .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
> > > + .flags = IORESOURCE_MEM,
> > > + },
> > > + [2] = {
> > > + .start = 0,
> > > + .end = SZ_256K - 1,
> >
> > Huh? I don't see where it's filled...
> >
> The current use is only to indicate memory block size to the PRUSS UIO
> driver when we allocate DDR memory using dma_alloc_coherent.
If the user/platform needs to specify the amount of memory that
will be allocated by the driver, it can be done though platform
data or (better) using module params.
> sram_alloc is changed to use L3_RAM (128KB) instead of ARM RAM (8KB) in
> Mistral patch set - I need to follow the same convention for L3 RAM as well
> if I need to align with that patch. Is there a better way to do this?
Yes, with that patch sram_alloc() will allocate from L3 RAM. You can make
calls to sram_alloc() in your driver. Again the size to be allocated can
be platform data or module params.
Thanks,
Sekhar
Hello.
On 28-02-2011 7:46, TK, Pratheesh Gangadhar wrote:
>>> This patch defines PRUSS, ECAP clocks, memory and IRQ resources
>>> used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
>> It's OMAP-L138.
> Ok.
>>> driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
>>> DDR buffer to user space. PRUSS has 8 host event interrupt lines
>>> mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
>>> with shared memory can be used to implement IPC between ARM9 and
>>> PRUSS.
>>> Signed-off-by: Pratheesh Gangadhar<[email protected]>
[...]
>>> diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-
>> davinci/devices-da8xx.c
>>> index beda8a4..4ea3d1f 100644
>>> --- a/arch/arm/mach-davinci/devices-da8xx.c
>>> +++ b/arch/arm/mach-davinci/devices-da8xx.c
>>> @@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
>>>
>>> return platform_device_register(&da8xx_cpuidle_device);
>>> }
>>> +static struct resource pruss_resources[] = {
>>> + [0] = {
>>> + .start = DA8XX_PRUSS_BASE,
>>> + .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
>>> + .flags = IORESOURCE_MEM,
>>> + },
>>> + [1] = {
>>> + .start = DA8XX_L3RAM_BASE,
>>> + .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
>>> + .flags = IORESOURCE_MEM,
>>> + },
>>> + [2] = {
>>> + .start = 0,
>>> + .end = SZ_256K - 1,
>> Huh? I don't see where it's filled...
> The current use is only to indicate memory block size to the PRUSS UIO driver when we allocate DDR memory using dma_alloc_coherent.
Why not pass this size via the platform data? There shouldn't be "dummy"
resources.
> sram_alloc is changed to use L3_RAM (128KB) instead of ARM RAM (8KB) in Mistral patch set - I need to follow the same convention
> for L3 RAM as well if I need to align with that patch. Is there a better
way to do this?
Didn't understand about L3 RAM.
Also, please wrap your text at 80 columns.
WBR, Sergei