[PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

Subsystems: linux for powerpc (32-bit and 64-bit), linux for powerpc embedded ppc4xx, the rest

STALE5195d

6 messages, 3 authors, 2012-06-15 · open the first message on its own page

[PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

From: Vinh Nguyen Huu Tuong <hidden>
Date: 2012-05-07 03:58:40

This patch consists of:
- Add driver for OCM component
- Export OCM Information at /sys/class/ocm/ocminfo

Signed-off-by: Vinh Nguyen Huu Tuong <redacted>
---
 arch/powerpc/boot/dts/bluestone.dts   |    8 +
 arch/powerpc/include/asm/ppc4xx_ocm.h |   47 ++++
 arch/powerpc/platforms/44x/Kconfig    |    8 +
 arch/powerpc/sysdev/Makefile          |    1 +
 arch/powerpc/sysdev/ppc4xx_ocm.c      |  420 +++++++++++++++++++++++++++++++++
 5 files changed, 484 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/include/asm/ppc4xx_ocm.h
 create mode 100644 arch/powerpc/sysdev/ppc4xx_ocm.c
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
index 7bda373..2687c11 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -107,6 +107,14 @@
 		interrupt-parent = <&UIC0>;
 	};
 
+	OCM1: ocm@400040000 {
+		compatible = "ibm,ocm";
+		status = "ok";
+		cell-index = <1>;
+		/* configured in U-Boot */
+		reg = <4 0x00040000 0x8000>; /* 32K */
+	};
+
 	SDR0: sdr {
 		compatible = "ibm,sdr-apm821xx";
 		dcr-reg = <0x00e 0x002>;
diff --git a/arch/powerpc/include/asm/ppc4xx_ocm.h b/arch/powerpc/include/asm/ppc4xx_ocm.h
new file mode 100644
index 0000000..ff7f386
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx_ocm.h
@@ -0,0 +1,47 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_POWERPC_PPC4xx_OCM_H__
+#define __ASM_POWERPC_PPC4xx_OCM_H__
+
+#include <linux/types.h>
+
+#define OCM_NON_CACHED 0
+#define OCM_CACHED     1
+
+#if defined(CONFIG_PPC4xx_OCM)
+
+void *ocm_alloc(phys_addr_t *phys, int size, int align,
+		  int flags, const char *owner);
+void ocm_free(const void *virt);
+
+#else
+
+#define ocm_alloc(phys, size, align, flags, owner)	NULL
+#define ocm_free(addr)	((void)0)
+
+#endif /* CONFIG_PPC4xx_OCM */
+
+#endif  /* __ASM_POWERPC_PPC4xx_OCM_H__ */
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 2e4e64a..6b1a64e 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -250,6 +250,14 @@ config PPC4xx_GPIO
 	help
 	  Enable gpiolib support for ppc440 based boards
 
+config PPC4xx_OCM
+	bool "PPC4xx On Chip Memory (OCM) support"
+	depends on 4xx
+	select PPC_LIB_RHEAP
+	help
+	  Enable OCM support for PowerPC 4xx platforms with on chip memory,
+	  OCM provides the fast place for memory access to improve performance.
+
 # 44x specific CPU modules, selected based on the board above.
 config 440EP
 	bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 1bd7ecb..6f768e2 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
 obj-$(CONFIG_IPIC)		+= ipic.o
 obj-$(CONFIG_4xx)		+= uic.o
+obj-$(CONFIG_PPC4xx_OCM)	+= ppc4xx_ocm.o
 obj-$(CONFIG_4xx_SOC)		+= ppc4xx_soc.o
 obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
 obj-$(CONFIG_XILINX_PCI)	+= xilinx_pci.o
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c
new file mode 100644
index 0000000..ba3e450
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -0,0 +1,420 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <asm/prom.h>
+#include <asm/dcr.h>
+#include <asm/rheap.h>
+#include <asm/mmu.h>
+#include <asm/ppc4xx_ocm.h>
+#include <linux/export.h>
+
+#define OCM_DISABLED	0
+#define OCM_ENABLED		1
+
+struct ocm_block {
+	struct list_head	list;
+	void __iomem		*addr;
+	int					size;
+	const char			*owner;
+};
+
+/* non-cached or cached region */
+struct ocm_region {
+	phys_addr_t			phys;
+	void __iomem		*virt;
+
+	int					memtotal;
+	int					memfree;
+
+	rh_info_t			*rh;
+	struct list_head	list;
+};
+
+struct ocm_info {
+	int			index;
+	int			status;
+	int			ready;
+
+	phys_addr_t		phys;
+
+	int			alignment;
+	int			memtotal;
+	int			cache_size;
+
+	struct ocm_region	nc;	/* non-cached region */
+	struct ocm_region	c;	/* cached region */
+};
+
+static struct ocm_info *ocm_nodes;
+static int ocm_count;
+
+static struct ocm_info *ocm_get_node(unsigned int index)
+{
+	if (index >= ocm_count) {
+		printk(KERN_ERR "OCM: invalid index");
+		return NULL;
+	}
+
+	return &ocm_nodes[index];
+}
+
+void *ocm_alloc(phys_addr_t *phys, int size, int align,
+		  int flags, const char *owner)
+{
+	void __iomem *addr = NULL;
+	unsigned long offset;
+	struct ocm_info *ocm;
+	struct ocm_region *ocm_reg;
+	struct ocm_block *ocm_blk;
+	int i;
+
+	for (i = 0; i < ocm_count; i++) {
+		ocm = ocm_get_node(i);
+
+		if (!ocm || !ocm->ready)
+			continue;
+
+		if (flags == OCM_NON_CACHED)
+			ocm_reg = &ocm->nc;
+		else
+			ocm_reg = &ocm->c;
+
+		if (!ocm_reg->virt)
+			continue;
+
+		if (align < ocm->alignment)
+			align = ocm->alignment;
+
+		offset = rh_alloc_align(ocm_reg->rh, size, align, NULL);
+
+		if (IS_ERR_VALUE(offset))
+			continue;
+
+		ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
+		if (!ocm_blk) {
+			printk(KERN_ERR "OCM: could not allocate ocm block");
+			rh_free(ocm_reg->rh, offset);
+			break;
+		}
+
+		*phys = ocm_reg->phys + offset;
+		addr = ocm_reg->virt + offset;
+		size = ALIGN(size, align);
+
+		ocm_blk->addr = addr;
+		ocm_blk->size = size;
+		ocm_blk->owner = owner;
+		list_add_tail(&ocm_blk->list, &ocm_reg->list);
+
+		ocm_reg->memfree -= size;
+
+		break;
+	}
+
+	return addr;
+}
+
+static int ocm_free_region(struct ocm_region *ocm_reg, const void *addr)
+{
+	struct ocm_block *blk, *tmp;
+	unsigned long offset;
+
+	if (!ocm_reg->virt)
+		return 0;
+
+	list_for_each_entry_safe(blk, tmp, &ocm_reg->list, list) {
+		if (blk->addr == addr) {
+			offset = addr - ocm_reg->virt;
+			ocm_reg->memfree += blk->size;
+			rh_free(ocm_reg->rh, offset);
+			list_del(&blk->list);
+			kfree(blk);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void ocm_free(const void *addr)
+{
+	int i;
+
+	if (!addr)
+		return;
+
+	for (i = 0; i < ocm_count; i++) {
+		struct ocm_info *ocm = ocm_get_node(i);
+
+		if (!ocm || !ocm->ready)
+			continue;
+
+		if (ocm_free_region(&ocm->nc, addr) ||
+		    ocm_free_region(&ocm->c, addr))
+			return;
+	}
+}
+
+static void __init ocm_init_node(int count, struct device_node *node)
+{
+	struct ocm_info *ocm;
+
+	const unsigned int *cell_index;
+	const unsigned int *cache_size;
+	int len;
+
+	struct resource rsrc;
+	int ioflags;
+
+	ocm = ocm_get_node(count);
+
+	cell_index = of_get_property(node, "cell-index", &len);
+	if (!cell_index) {
+		printk(KERN_ERR "OCM: missing cell-index property");
+		return;
+	}
+	ocm->index = *cell_index;
+
+	if (of_device_is_available(node))
+		ocm->status = OCM_ENABLED;
+
+	cache_size = of_get_property(node, "cached-region-size", &len);
+	if (cache_size)
+		ocm->cache_size = *cache_size;
+
+	if (of_address_to_resource(node, 0, &rsrc)) {
+		printk(KERN_ERR "OCM%d: could not get resource address\n",
+			ocm->index);
+		return;
+	}
+
+	ocm->phys = rsrc.start;
+	ocm->memtotal = (rsrc.end - rsrc.start + 1);
+
+	printk(KERN_INFO "OCM%d: %d Bytes (%s)\n",
+		ocm->index, ocm->memtotal,
+		(ocm->status == OCM_DISABLED) ? "disabled" : "enabled");
+
+	if (ocm->status == OCM_DISABLED)
+		return;
+
+	/* request region */
+
+	if (!request_mem_region(ocm->phys, ocm->memtotal, "ppc4xx_ocm")) {
+		printk(KERN_ERR "OCM%d: could not request region\n",
+			ocm->index);
+		return;
+	}
+
+	/* Configure non-cached and cached regions */
+
+	ocm->nc.phys = ocm->phys;
+	ocm->nc.memtotal = ocm->memtotal - ocm->cache_size;
+	ocm->nc.memfree = ocm->nc.memtotal;
+
+	ocm->c.phys = ocm->phys + ocm->nc.memtotal;
+	ocm->c.memtotal = ocm->cache_size;
+	ocm->c.memfree = ocm->c.memtotal;
+
+	if (ocm->nc.memtotal == 0)
+		ocm->nc.phys = 0;
+
+	if (ocm->c.memtotal == 0)
+		ocm->c.phys = 0;
+
+	printk(KERN_INFO "OCM%d: %d Bytes (non-cached)\n",
+		ocm->index, ocm->nc.memtotal);
+
+	printk(KERN_INFO "OCM%d: %d Bytes (cached)\n",
+		ocm->index, ocm->c.memtotal);
+
+	/* ioremap the non-cached region */
+	if (ocm->nc.memtotal) {
+		ioflags = _PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_EXEC;
+		ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal,
+					  ioflags);
+
+		if (!ocm->nc.virt) {
+			printk(KERN_ERR
+			       "OCM%d: failed to ioremap non-cached memory\n",
+			       ocm->index);
+			ocm->nc.memfree = 0;
+			return;
+		}
+	}
+
+	/* ioremap the cached region */
+
+	if (ocm->c.memtotal) {
+		ioflags = _PAGE_EXEC;
+		ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal,
+					 ioflags);
+
+		if (!ocm->c.virt) {
+			printk(KERN_ERR
+			       "OCM%d: failed to ioremap cached memory\n",
+			       ocm->index);
+			ocm->c.memfree = 0;
+			return;
+		}
+	}
+
+	/* Create Remote Heaps */
+
+	ocm->alignment = 4; /* default 4 byte alignment */
+
+	if (ocm->nc.virt) {
+		ocm->nc.rh = rh_create(ocm->alignment);
+		rh_attach_region(ocm->nc.rh, 0, ocm->nc.memtotal);
+	}
+
+	if (ocm->c.virt) {
+		ocm->c.rh = rh_create(ocm->alignment);
+		rh_attach_region(ocm->c.rh, 0, ocm->c.memtotal);
+	}
+
+	INIT_LIST_HEAD(&ocm->nc.list);
+	INIT_LIST_HEAD(&ocm->c.list);
+
+	ocm->ready = 1;
+
+	return;
+}
+
+static ssize_t ocm_sysfs_show(struct class *class,
+			struct class_attribute *attr, char *buf)
+{
+	struct ocm_block *blk, *tmp;
+	unsigned int count, i;
+
+	count = 0;
+	for (i = 0; i < ocm_count; i++) {
+		struct ocm_info *ocm = ocm_get_node(i);
+
+		if (!ocm || !ocm->ready)
+			continue;
+
+		count += sprintf(buf + count, "OCM          : %d\n",
+							ocm->index);
+		count += sprintf(buf + count, "PhysAddr     : 0x%llx\n",
+							ocm->phys);
+		count += sprintf(buf + count, "MemTotal     : %d Bytes\n",
+							ocm->memtotal);
+		count += sprintf(buf + count, "MemTotal(NC) : %d Bytes\n",
+							ocm->nc.memtotal);
+		count += sprintf(buf + count, "MemTotal(C)  : %d Bytes\n",
+							ocm->c.memtotal);
+
+		count += sprintf(buf + count, "\n");
+
+		count += sprintf(buf + count, "NC.PhysAddr  : 0x%llx\n",
+							ocm->nc.phys);
+		count += sprintf(buf + count, "NC.VirtAddr  : 0x%p\n",
+							ocm->nc.virt);
+		count += sprintf(buf + count, "NC.MemTotal  : %d Bytes\n",
+							ocm->nc.memtotal);
+		count += sprintf(buf + count, "NC.MemFree   : %d Bytes\n",
+							ocm->nc.memfree);
+
+		list_for_each_entry_safe(blk, tmp, &ocm->nc.list, list) {
+			count += sprintf(buf + count, "NC.MemUsed   : %d Bytes (%s)\n",
+							blk->size, blk->owner);
+		}
+
+		count += sprintf(buf + count, "\n");
+
+		count += sprintf(buf + count, "C.PhysAddr   : 0x%llx\n",
+							ocm->c.phys);
+		count += sprintf(buf + count, "C.VirtAddr   : 0x%p\n",
+							ocm->c.virt);
+		count += sprintf(buf + count, "C.MemTotal   : %d Bytes\n",
+							ocm->c.memtotal);
+		count += sprintf(buf + count, "C.MemFree    : %d Bytes\n",
+							ocm->c.memfree);
+
+		list_for_each_entry_safe(blk, tmp, &ocm->c.list, list) {
+			count += sprintf(buf + count, "C.MemUsed    : %d Bytes (%s)\n",
+					blk->size, blk->owner);
+		}
+
+		count += sprintf(buf + count, "\n");
+	}
+
+	return count;
+}
+
+static struct class *mem_class;
+
+static CLASS_ATTR(ocminfo, S_IRUGO, ocm_sysfs_show, NULL);
+
+static int ocm_sysfs_init(void)
+{
+	mem_class = class_create(THIS_MODULE, "ocm");
+	if (IS_ERR(mem_class))
+		return PTR_ERR(mem_class);
+
+	return class_create_file(mem_class, &class_attr_ocminfo);
+}
+
+static int __init ocm_init(void)
+{
+	struct device_node *np;
+	int count;
+
+	count = 0;
+	for_each_compatible_node(np, NULL, "ibm,ocm")
+		count++;
+
+	if (!count)
+		return 0;
+
+	ocm_nodes = kzalloc((count * sizeof(struct ocm_info)), GFP_KERNEL);
+	if (!ocm_nodes) {
+		printk(KERN_ERR "OCM: failed to allocate OCM nodes!\n");
+		return -ENOMEM;
+	}
+
+	ocm_count = count;
+	count = 0;
+
+	for_each_compatible_node(np, NULL, "ibm,ocm") {
+		ocm_init_node(count, np);
+		count++;
+	}
+
+	ocm_sysfs_init();
+
+	return 0;
+}
+
+arch_initcall(ocm_init);
-- 
1.7.2.5

RE: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

From: Vinh Huu Tuong Nguyen <hidden>
Date: 2012-06-12 10:31:59

quoted hunk
-----Original Message-----
From: Vinh Nguyen Huu Tuong [mailto:vhtnguyen@apm.com]
Sent: Monday, May 07, 2012 10:53 AM
To: Benjamin Herrenschmidt; Paul Mackerras; Josh Boyer; Matt Porter;
Grant Likely; Rob Herring; Duc Dang; David S. Miller; Kumar Gala; Li
Yang; Ashish Kalra; Anatolij Gustschin; Liu Gang; linuxppc-
dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; devicetree-
discuss@lists.ozlabs.org
Cc: Vinh Nguyen Huu Tuong
Subject: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx
SoC and Bluestone board

This patch consists of:
- Add driver for OCM component
- Export OCM Information at /sys/class/ocm/ocminfo

Signed-off-by: Vinh Nguyen Huu Tuong <redacted>
---
 arch/powerpc/boot/dts/bluestone.dts   |    8 +
 arch/powerpc/include/asm/ppc4xx_ocm.h |   47 ++++
 arch/powerpc/platforms/44x/Kconfig    |    8 +
 arch/powerpc/sysdev/Makefile          |    1 +
 arch/powerpc/sysdev/ppc4xx_ocm.c      |  420
+++++++++++++++++++++++++++++++++
 5 files changed, 484 insertions(+), 0 deletions(-)  create mode 100644
arch/powerpc/include/asm/ppc4xx_ocm.h
 create mode 100644 arch/powerpc/sysdev/ppc4xx_ocm.c
diff --git a/arch/powerpc/boot/dts/bluestone.dts
b/arch/powerpc/boot/dts/bluestone.dts
index 7bda373..2687c11 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -107,6 +107,14 @@
 		interrupt-parent = <&UIC0>;
 	};

+	OCM1: ocm@400040000 {
+		compatible = "ibm,ocm";
+		status = "ok";
+		cell-index = <1>;
+		/* configured in U-Boot */
+		reg = <4 0x00040000 0x8000>; /* 32K */
+	};
+
 	SDR0: sdr {
 		compatible = "ibm,sdr-apm821xx";
 		dcr-reg = <0x00e 0x002>;
diff --git a/arch/powerpc/include/asm/ppc4xx_ocm.h
b/arch/powerpc/include/asm/ppc4xx_ocm.h
new file mode 100644
index 0000000..ff7f386
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx_ocm.h
@@ -0,0 +1,47 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_POWERPC_PPC4xx_OCM_H__
+#define __ASM_POWERPC_PPC4xx_OCM_H__
+
+#include <linux/types.h>
+
+#define OCM_NON_CACHED 0
+#define OCM_CACHED     1
+
+#if defined(CONFIG_PPC4xx_OCM)
+
+void *ocm_alloc(phys_addr_t *phys, int size, int align,
+		  int flags, const char *owner);
+void ocm_free(const void *virt);
+
+#else
+
+#define ocm_alloc(phys, size, align, flags, owner)	NULL
+#define ocm_free(addr)	((void)0)
+
+#endif /* CONFIG_PPC4xx_OCM */
+
+#endif  /* __ASM_POWERPC_PPC4xx_OCM_H__ */
diff --git a/arch/powerpc/platforms/44x/Kconfig
b/arch/powerpc/platforms/44x/Kconfig
index 2e4e64a..6b1a64e 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -250,6 +250,14 @@ config PPC4xx_GPIO
 	help
 	  Enable gpiolib support for ppc440 based boards

+config PPC4xx_OCM
+	bool "PPC4xx On Chip Memory (OCM) support"
+	depends on 4xx
+	select PPC_LIB_RHEAP
+	help
+	  Enable OCM support for PowerPC 4xx platforms with on chip
memory,
+	  OCM provides the fast place for memory access to improve
performance.
+
 # 44x specific CPU modules, selected based on the board above.
 config 440EP
 	bool
diff --git a/arch/powerpc/sysdev/Makefile
b/arch/powerpc/sysdev/Makefile index 1bd7ecb..6f768e2 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
 obj-$(CONFIG_IPIC)		+= ipic.o
 obj-$(CONFIG_4xx)		+= uic.o
+obj-$(CONFIG_PPC4xx_OCM)	+= ppc4xx_ocm.o
 obj-$(CONFIG_4xx_SOC)		+= ppc4xx_soc.o
 obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
 obj-$(CONFIG_XILINX_PCI)	+= xilinx_pci.o
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c
b/arch/powerpc/sysdev/ppc4xx_ocm.c
new file mode 100644
index 0000000..ba3e450
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -0,0 +1,420 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <asm/prom.h>
+#include <asm/dcr.h>
+#include <asm/rheap.h>
+#include <asm/mmu.h>
+#include <asm/ppc4xx_ocm.h>
+#include <linux/export.h>
+
+#define OCM_DISABLED	0
+#define OCM_ENABLED		1
+
+struct ocm_block {
+	struct list_head	list;
+	void __iomem		*addr;
+	int					size;
+	const char			*owner;
+};
+
+/* non-cached or cached region */
+struct ocm_region {
+	phys_addr_t			phys;
+	void __iomem		*virt;
+
+	int					memtotal;
+	int					memfree;
+
+	rh_info_t			*rh;
+	struct list_head	list;
+};
+
+struct ocm_info {
+	int			index;
+	int			status;
+	int			ready;
+
+	phys_addr_t		phys;
+
+	int			alignment;
+	int			memtotal;
+	int			cache_size;
+
+	struct ocm_region	nc;	/* non-cached region */
+	struct ocm_region	c;	/* cached region */
+};
+
+static struct ocm_info *ocm_nodes;
+static int ocm_count;
+
+static struct ocm_info *ocm_get_node(unsigned int index) {
+	if (index >= ocm_count) {
+		printk(KERN_ERR "OCM: invalid index");
+		return NULL;
+	}
+
+	return &ocm_nodes[index];
+}
+
+void *ocm_alloc(phys_addr_t *phys, int size, int align,
+		  int flags, const char *owner)
+{
+	void __iomem *addr = NULL;
+	unsigned long offset;
+	struct ocm_info *ocm;
+	struct ocm_region *ocm_reg;
+	struct ocm_block *ocm_blk;
+	int i;
+
+	for (i = 0; i < ocm_count; i++) {
+		ocm = ocm_get_node(i);
+
+		if (!ocm || !ocm->ready)
+			continue;
+
+		if (flags == OCM_NON_CACHED)
+			ocm_reg = &ocm->nc;
+		else
+			ocm_reg = &ocm->c;
+
+		if (!ocm_reg->virt)
+			continue;
+
+		if (align < ocm->alignment)
+			align = ocm->alignment;
+
+		offset = rh_alloc_align(ocm_reg->rh, size, align, NULL);
+
+		if (IS_ERR_VALUE(offset))
+			continue;
+
+		ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
+		if (!ocm_blk) {
+			printk(KERN_ERR "OCM: could not allocate ocm
block");
+			rh_free(ocm_reg->rh, offset);
+			break;
+		}
+
+		*phys = ocm_reg->phys + offset;
+		addr = ocm_reg->virt + offset;
+		size = ALIGN(size, align);
+
+		ocm_blk->addr = addr;
+		ocm_blk->size = size;
+		ocm_blk->owner = owner;
+		list_add_tail(&ocm_blk->list, &ocm_reg->list);
+
+		ocm_reg->memfree -= size;
+
+		break;
+	}
+
+	return addr;
+}
+
+static int ocm_free_region(struct ocm_region *ocm_reg, const void
+*addr) {
+	struct ocm_block *blk, *tmp;
+	unsigned long offset;
+
+	if (!ocm_reg->virt)
+		return 0;
+
+	list_for_each_entry_safe(blk, tmp, &ocm_reg->list, list) {
+		if (blk->addr == addr) {
+			offset = addr - ocm_reg->virt;
+			ocm_reg->memfree += blk->size;
+			rh_free(ocm_reg->rh, offset);
+			list_del(&blk->list);
+			kfree(blk);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void ocm_free(const void *addr)
+{
+	int i;
+
+	if (!addr)
+		return;
+
+	for (i = 0; i < ocm_count; i++) {
+		struct ocm_info *ocm = ocm_get_node(i);
+
+		if (!ocm || !ocm->ready)
+			continue;
+
+		if (ocm_free_region(&ocm->nc, addr) ||
+		    ocm_free_region(&ocm->c, addr))
+			return;
+	}
+}
+
+static void __init ocm_init_node(int count, struct device_node *node)
{
+	struct ocm_info *ocm;
+
+	const unsigned int *cell_index;
+	const unsigned int *cache_size;
+	int len;
+
+	struct resource rsrc;
+	int ioflags;
+
+	ocm = ocm_get_node(count);
+
+	cell_index = of_get_property(node, "cell-index", &len);
+	if (!cell_index) {
+		printk(KERN_ERR "OCM: missing cell-index property");
+		return;
+	}
+	ocm->index = *cell_index;
+
+	if (of_device_is_available(node))
+		ocm->status = OCM_ENABLED;
+
+	cache_size = of_get_property(node, "cached-region-size", &len);
+	if (cache_size)
+		ocm->cache_size = *cache_size;
+
+	if (of_address_to_resource(node, 0, &rsrc)) {
+		printk(KERN_ERR "OCM%d: could not get resource address\n",
+			ocm->index);
+		return;
+	}
+
+	ocm->phys = rsrc.start;
+	ocm->memtotal = (rsrc.end - rsrc.start + 1);
+
+	printk(KERN_INFO "OCM%d: %d Bytes (%s)\n",
+		ocm->index, ocm->memtotal,
+		(ocm->status == OCM_DISABLED) ? "disabled" : "enabled");
+
+	if (ocm->status == OCM_DISABLED)
+		return;
+
+	/* request region */
+
+	if (!request_mem_region(ocm->phys, ocm->memtotal, "ppc4xx_ocm"))
{
+		printk(KERN_ERR "OCM%d: could not request region\n",
+			ocm->index);
+		return;
+	}
+
+	/* Configure non-cached and cached regions */
+
+	ocm->nc.phys = ocm->phys;
+	ocm->nc.memtotal = ocm->memtotal - ocm->cache_size;
+	ocm->nc.memfree = ocm->nc.memtotal;
+
+	ocm->c.phys = ocm->phys + ocm->nc.memtotal;
+	ocm->c.memtotal = ocm->cache_size;
+	ocm->c.memfree = ocm->c.memtotal;
+
+	if (ocm->nc.memtotal == 0)
+		ocm->nc.phys = 0;
+
+	if (ocm->c.memtotal == 0)
+		ocm->c.phys = 0;
+
+	printk(KERN_INFO "OCM%d: %d Bytes (non-cached)\n",
+		ocm->index, ocm->nc.memtotal);
+
+	printk(KERN_INFO "OCM%d: %d Bytes (cached)\n",
+		ocm->index, ocm->c.memtotal);
+
+	/* ioremap the non-cached region */
+	if (ocm->nc.memtotal) {
+		ioflags = _PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_EXEC;
+		ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal,
+					  ioflags);
+
+		if (!ocm->nc.virt) {
+			printk(KERN_ERR
+			       "OCM%d: failed to ioremap non-cached
memory\n",
+			       ocm->index);
+			ocm->nc.memfree = 0;
+			return;
+		}
+	}
+
+	/* ioremap the cached region */
+
+	if (ocm->c.memtotal) {
+		ioflags = _PAGE_EXEC;
+		ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal,
+					 ioflags);
+
+		if (!ocm->c.virt) {
+			printk(KERN_ERR
+			       "OCM%d: failed to ioremap cached memory\n",
+			       ocm->index);
+			ocm->c.memfree = 0;
+			return;
+		}
+	}
+
+	/* Create Remote Heaps */
+
+	ocm->alignment = 4; /* default 4 byte alignment */
+
+	if (ocm->nc.virt) {
+		ocm->nc.rh = rh_create(ocm->alignment);
+		rh_attach_region(ocm->nc.rh, 0, ocm->nc.memtotal);
+	}
+
+	if (ocm->c.virt) {
+		ocm->c.rh = rh_create(ocm->alignment);
+		rh_attach_region(ocm->c.rh, 0, ocm->c.memtotal);
+	}
+
+	INIT_LIST_HEAD(&ocm->nc.list);
+	INIT_LIST_HEAD(&ocm->c.list);
+
+	ocm->ready = 1;
+
+	return;
+}
+
+static ssize_t ocm_sysfs_show(struct class *class,
+			struct class_attribute *attr, char *buf) {
+	struct ocm_block *blk, *tmp;
+	unsigned int count, i;
+
+	count = 0;
+	for (i = 0; i < ocm_count; i++) {
+		struct ocm_info *ocm = ocm_get_node(i);
+
+		if (!ocm || !ocm->ready)
+			continue;
+
+		count += sprintf(buf + count, "OCM          : %d\n",
+							ocm->index);
+		count += sprintf(buf + count, "PhysAddr     : 0x%llx\n",
+							ocm->phys);
+		count += sprintf(buf + count, "MemTotal     : %d Bytes\n",
+							ocm->memtotal);
+		count += sprintf(buf + count, "MemTotal(NC) : %d Bytes\n",
+							ocm->nc.memtotal);
+		count += sprintf(buf + count, "MemTotal(C)  : %d Bytes\n",
+							ocm->c.memtotal);
+
+		count += sprintf(buf + count, "\n");
+
+		count += sprintf(buf + count, "NC.PhysAddr  : 0x%llx\n",
+							ocm->nc.phys);
+		count += sprintf(buf + count, "NC.VirtAddr  : 0x%p\n",
+							ocm->nc.virt);
+		count += sprintf(buf + count, "NC.MemTotal  : %d Bytes\n",
+							ocm->nc.memtotal);
+		count += sprintf(buf + count, "NC.MemFree   : %d Bytes\n",
+							ocm->nc.memfree);
+
+		list_for_each_entry_safe(blk, tmp, &ocm->nc.list, list) {
+			count += sprintf(buf + count, "NC.MemUsed   : %d
Bytes (%s)\n",
+							blk->size,
blk->owner);
+		}
+
+		count += sprintf(buf + count, "\n");
+
+		count += sprintf(buf + count, "C.PhysAddr   : 0x%llx\n",
+							ocm->c.phys);
+		count += sprintf(buf + count, "C.VirtAddr   : 0x%p\n",
+							ocm->c.virt);
+		count += sprintf(buf + count, "C.MemTotal   : %d Bytes\n",
+							ocm->c.memtotal);
+		count += sprintf(buf + count, "C.MemFree    : %d Bytes\n",
+							ocm->c.memfree);
+
+		list_for_each_entry_safe(blk, tmp, &ocm->c.list, list) {
+			count += sprintf(buf + count, "C.MemUsed    : %d
Bytes (%s)\n",
+					blk->size, blk->owner);
+		}
+
+		count += sprintf(buf + count, "\n");
+	}
+
+	return count;
+}
+
+static struct class *mem_class;
+
+static CLASS_ATTR(ocminfo, S_IRUGO, ocm_sysfs_show, NULL);
+
+static int ocm_sysfs_init(void)
+{
+	mem_class = class_create(THIS_MODULE, "ocm");
+	if (IS_ERR(mem_class))
+		return PTR_ERR(mem_class);
+
+	return class_create_file(mem_class, &class_attr_ocminfo); }
+
+static int __init ocm_init(void)
+{
+	struct device_node *np;
+	int count;
+
+	count = 0;
+	for_each_compatible_node(np, NULL, "ibm,ocm")
+		count++;
+
+	if (!count)
+		return 0;
+
+	ocm_nodes = kzalloc((count * sizeof(struct ocm_info)),
GFP_KERNEL);
+	if (!ocm_nodes) {
+		printk(KERN_ERR "OCM: failed to allocate OCM nodes!\n");
+		return -ENOMEM;
+	}
+
+	ocm_count = count;
+	count = 0;
+
+	for_each_compatible_node(np, NULL, "ibm,ocm") {
+		ocm_init_node(count, np);
+		count++;
+	}
+
+	ocm_sysfs_init();
+
+	return 0;
+}
+
+arch_initcall(ocm_init);
--
1.7.2.5
Hi all reviewers,
One month pass from the day I sent out this patch, but I didn't receive
any comments from you. Could you please do me a favor to take a look on it
and give me your advices?

Best regards,
Vinh Nguyen.

RE: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: 2012-06-13 00:40:47

On Tue, 2012-06-12 at 17:26 +0700, Vinh Huu Tuong Nguyen wrote:
quoted
-----Original Message-----
From: Vinh Nguyen Huu Tuong [mailto:vhtnguyen@apm.com]
Sent: Monday, May 07, 2012 10:53 AM
To: Benjamin Herrenschmidt; Paul Mackerras; Josh Boyer; Matt Porter;
Grant Likely; Rob Herring; Duc Dang; David S. Miller; Kumar Gala; Li
Yang; Ashish Kalra; Anatolij Gustschin; Liu Gang; linuxppc-
dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; devicetree-
discuss@lists.ozlabs.org
Cc: Vinh Nguyen Huu Tuong
Subject: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx
SoC and Bluestone board
Such a CC list won't get you any good will. Send it only to the relevant
mailing lists with possibly the -one- concerned maintainer on CC. I
doubt Dave Miller or Matt Porter give any damn about those patches.

As for why it wasn't reviewed yet, well, reviewers are a finite resource
with limited time dedicated to it. If the patch is properly formed and
was posted to the linuxppc-dev@ozlabs.org, it should be tracked on
patchwork.ozlabs.org and won't be lost. Double check it's there (if it's
not, then the patch was probably corrupt).

Cheers,
Ben.

Re: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

From: Josh Boyer <hidden>
Date: 2012-06-13 01:22:16

On Tue, Jun 12, 2012 at 8:40 PM, Benjamin Herrenschmidt
[off-list ref] wrote:
On Tue, 2012-06-12 at 17:26 +0700, Vinh Huu Tuong Nguyen wrote:
quoted
quoted
-----Original Message-----
From: Vinh Nguyen Huu Tuong [mailto:vhtnguyen@apm.com]
Sent: Monday, May 07, 2012 10:53 AM
To: Benjamin Herrenschmidt; Paul Mackerras; Josh Boyer; Matt Porter;
Grant Likely; Rob Herring; Duc Dang; David S. Miller; Kumar Gala; Li
Yang; Ashish Kalra; Anatolij Gustschin; Liu Gang; linuxppc-
dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; devicetree-
discuss@lists.ozlabs.org
Cc: Vinh Nguyen Huu Tuong
Subject: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx
SoC and Bluestone board
Such a CC list won't get you any good will. Send it only to the relevant
mailing lists with possibly the -one- concerned maintainer on CC. I
doubt Dave Miller or Matt Porter give any damn about those patches.

As for why it wasn't reviewed yet, well, reviewers are a finite resource
with limited time dedicated to it. If the patch is properly formed and
was posted to the linuxppc-dev@ozlabs.org, it should be tracked on
patchwork.ozlabs.org and won't be lost. Double check it's there (if it's
not, then the patch was probably corrupt).
It's there.  I just missed it until today.  My apologies Vinh.  I'll
do a more formal review tomorrow, but at first glance I'm concerned
with the sysfs usage.  The files in sysfs are supposed to be one file
per value, and you see to have something akin to /proc/meminfo in the
sysfs file being created.  Perhaps that would be better either split
into unique file names per field in sysfs, or in a debugfs file
instead?

Again, I'll review more closely tomrorow.

josh

Re: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

From: Josh Boyer <hidden>
Date: 2012-06-14 17:47:29

On Sun, May 6, 2012 at 11:52 PM, Vinh Nguyen Huu Tuong
[off-list ref] wrote:
This patch consists of:
- Add driver for OCM component
- Export OCM Information at /sys/class/ocm/ocminfo
Again, apologies for the delay.  Aside from the incorrect sysfs usage
I pointed out in my other reply, I have just a few comments/questions
below.
quoted hunk
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/=
bluestone.dts
quoted hunk
index 7bda373..2687c11 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -107,6 +107,14 @@
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0interrupt-parent =3D <&UIC0>;
=A0 =A0 =A0 =A0};

+ =A0 =A0 =A0 OCM1: ocm@400040000 {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "ibm,ocm";
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 status =3D "ok";
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 cell-index =3D <1>;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* configured in U-Boot */
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <4 0x00040000 0x8000>; /* 32K */
+ =A0 =A0 =A0 };
+
=A0 =A0 =A0 =A0SDR0: sdr {
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "ibm,sdr-apm821xx";
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dcr-reg =3D <0x00e 0x002>;
diff --git a/arch/powerpc/include/asm/ppc4xx_ocm.h b/arch/powerpc/include=
/asm/ppc4xx_ocm.h
quoted hunk
new file mode 100644
index 0000000..ff7f386
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx_ocm.h
@@ -0,0 +1,47 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_POWERPC_PPC4xx_OCM_H__
+#define __ASM_POWERPC_PPC4xx_OCM_H__
+
+#include <linux/types.h>
+
+#define OCM_NON_CACHED 0
+#define OCM_CACHED =A0 =A0 1
+
+#if defined(CONFIG_PPC4xx_OCM)
+
+void *ocm_alloc(phys_addr_t *phys, int size, int align,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int flags, const char *owner);
+void ocm_free(const void *virt);
+
+#else
+
+#define ocm_alloc(phys, size, align, flags, owner) =A0 =A0 NULL
+#define ocm_free(addr) ((void)0)
+
+#endif /* CONFIG_PPC4xx_OCM */
+
+#endif =A0/* __ASM_POWERPC_PPC4xx_OCM_H__ */
I don't see any users of this header included in the patch.  I'm going
to guess that follow-on drivers/users are queued once this is in the
tree?  Also, you might want to name these 'ppc4xx_ocm_alloc' or
similar.  The concept of OCM isn't limited to ppc4xx or even SoCs, so
just using 'ocm' in the global kernel namespace might not be great.
quoted hunk
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4x=
x_ocm.c
quoted hunk
new file mode 100644
index 0000000..ba3e450
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -0,0 +1,420 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
Why do you need proc_fs.h?
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <asm/prom.h>
+#include <asm/dcr.h>
+#include <asm/rheap.h>
+#include <asm/mmu.h>
+#include <asm/ppc4xx_ocm.h>
+#include <linux/export.h>
+
+#define OCM_DISABLED =A0 0
+#define OCM_ENABLED =A0 =A0 =A0 =A0 =A0 =A01
+
+struct ocm_block {
+ =A0 =A0 =A0 struct list_head =A0 =A0 =A0 =A0list;
+ =A0 =A0 =A0 void __iomem =A0 =A0 =A0 =A0 =A0 =A0*addr;
+ =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 size;
+ =A0 =A0 =A0 const char =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*owne=
r;
+};
+
+/* non-cached or cached region */
+struct ocm_region {
+ =A0 =A0 =A0 phys_addr_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 phys;
+ =A0 =A0 =A0 void __iomem =A0 =A0 =A0 =A0 =A0 =A0*virt;
+
+ =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 memtotal;
+ =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 memfree;
+
+ =A0 =A0 =A0 rh_info_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *rh;
+ =A0 =A0 =A0 struct list_head =A0 =A0 =A0 =A0list;
+};
There's some interesting whitespace usage in these struct definitions.

josh

RE: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for APM821xx SoC and Bluestone board

From: Vinh Huu Tuong Nguyen <hidden>
Date: 2012-06-15 03:19:34

-----Original Message-----
From: Josh Boyer [mailto:jwboyer@gmail.com]
Sent: Friday, June 15, 2012 12:47 AM
To: Vinh Nguyen Huu Tuong
Cc: Benjamin Herrenschmidt; Paul Mackerras; Matt Porter; Grant Likely;
Rob Herring; Duc Dang; David S. Miller; Kumar Gala; Li Yang; Ashish
Kalra; Anatolij Gustschin; Liu Gang; linuxppc-dev@lists.ozlabs.org;
linux-kernel@vger.kernel.org; devicetree-discuss@lists.ozlabs.org
Subject: Re: [PATCH] powerpc/44x: Support OCM(On Chip Memory) for
APM821xx SoC and Bluestone board

On Sun, May 6, 2012 at 11:52 PM, Vinh Nguyen Huu Tuong
[off-list ref] wrote:
quoted
This patch consists of:
- Add driver for OCM component
- Export OCM Information at /sys/class/ocm/ocminfo
Again, apologies for the delay.  Aside from the incorrect sysfs usage I
pointed out in my other reply, I have just a few comments/questions
below.
[Vinh Nguyen] You're welcome. About the files on sysfs, the first place of
ocm is in procfs, but procfs is deprecated and replaced by sysfs, then I
decided to move it to sysfs. With your comments, I think I can move it to
debugfs.
quoted
diff --git a/arch/powerpc/boot/dts/bluestone.dts
b/arch/powerpc/boot/dts/bluestone.dts
index 7bda373..2687c11 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -107,6 +107,14 @@
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0interrupt-parent =3D <&UIC0>;
=A0 =A0 =A0 =A0};

+ =A0 =A0 =A0 OCM1: ocm@400040000 {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "ibm,ocm";
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 status =3D "ok";
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 cell-index =3D <1>;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* configured in U-Boot */
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <4 0x00040000 0x8000>; /* 32K */
+ =A0 =A0 =A0 };
+
=A0 =A0 =A0 =A0SDR0: sdr {
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "ibm,sdr-apm821xx";
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dcr-reg =3D <0x00e 0x002>; diff --git
a/arch/powerpc/include/asm/ppc4xx_ocm.h
b/arch/powerpc/include/asm/ppc4xx_ocm.h
new file mode 100644
index 0000000..ff7f386
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx_ocm.h
@@ -0,0 +1,47 @@
+/*
+ * PowerPC 4xx OCM memory allocation support
+ *
+ * (C) Copyright 2009, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@amcc.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_POWERPC_PPC4xx_OCM_H__
+#define __ASM_POWERPC_PPC4xx_OCM_H__
+
+#include <linux/types.h>
+
+#define OCM_NON_CACHED 0
+#define OCM_CACHED =A0 =A0 1
+
+#if defined(CONFIG_PPC4xx_OCM)
+
+void *ocm_alloc(phys_addr_t *phys, int size, int align,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int flags, const char *owner); void o=
cm_free(const
quoted
+void *virt);
+
+#else
+
+#define ocm_alloc(phys, size, align, flags, owner) =A0 =A0 NULL #defin=
e
quoted
+ocm_free(addr) ((void)0)
+
+#endif /* CONFIG_PPC4xx_OCM */
+
+#endif =A0/* __ASM_POWERPC_PPC4xx_OCM_H__ */
I don't see any users of this header included in the patch.  I'm going
to guess that follow-on drivers/users are queued once this is in the
tree?  Also, you might want to name these 'ppc4xx_ocm_alloc' or
similar.  The concept of OCM isn't limited to ppc4xx or even SoCs, so
just using 'ocm' in the global kernel namespace might not be great.
[Vinh Nguyen] With our plan, the next submit of IBM NEW EMAC will use it
for speedup. About the naming convention, I will change as your comments.
quoted
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c
b/arch/powerpc/sysdev/ppc4xx_ocm.c
new file mode 100644
index 0000000..ba3e450
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -0,0 +1,420 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
Why do you need proc_fs.h?
[Vinh Nguyen] I will remove it.
quoted
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <asm/prom.h>
+#include <asm/dcr.h>
+#include <asm/rheap.h>
+#include <asm/mmu.h>
+#include <asm/ppc4xx_ocm.h>
+#include <linux/export.h>
+
+#define OCM_DISABLED =A0 0
+#define OCM_ENABLED =A0 =A0 =A0 =A0 =A0 =A01
+
+struct ocm_block {
+ =A0 =A0 =A0 struct list_head =A0 =A0 =A0 =A0list;
+ =A0 =A0 =A0 void __iomem =A0 =A0 =A0 =A0 =A0 =A0*addr;
+ =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 size;
quoted
+ =A0 =A0 =A0 const char =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ow=
ner; };
quoted
+
+/* non-cached or cached region */
+struct ocm_region {
+ =A0 =A0 =A0 phys_addr_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 phys;
+ =A0 =A0 =A0 void __iomem =A0 =A0 =A0 =A0 =A0 =A0*virt;
+
+ =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 memtotal;
quoted
+ =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 memfree;
quoted
+
+ =A0 =A0 =A0 rh_info_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *rh=
;
quoted
+ =A0 =A0 =A0 struct list_head =A0 =A0 =A0 =A0list;
+};
There's some interesting whitespace usage in these struct definitions.
[Vinh Nguyen] I'll check again and remove them. I used the scripts check
in kernel but it can't remove them all.
josh
I'll update the patch soon but I need send out to internal review first
before sending out to community. It takes one or two week, please be
patient for the next review.

Best regards,
Vinh Nguyen
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help