Patchwork [08/27] UBUNTU: SAUCE: powerpc/pamu: Add driver to initialize PAMU tables

login
register
mail settings
Submitter Benjamin Collins
Date June 21, 2011, 5:13 a.m.
Message ID <8083a93b52b3e64afc0132ac0261aff9afd0077e.1339455421.git.bcollins@ubuntu.com>
Download mbox | patch
Permalink /patch/164267/
State New
Headers show

Comments

Benjamin Collins - June 21, 2011, 5:13 a.m.
This patch is being maintained, and eventually merged upstream, by
Freescale directly. The powerpc-e500mc flavour uses this.

Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
Signed-off-by: Vakul Garg <Vakul@freescale.com>
Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Ben Collins <bcollins@ubuntu.com>
---
 arch/powerpc/Kconfig                |   10 +
 arch/powerpc/platforms/85xx/Kconfig |    5 +
 arch/powerpc/sysdev/Makefile        |    1 +
 arch/powerpc/sysdev/fsl_pamu.c      |  426 +++++++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/fsl_pamu.h      |  382 +++++++++++++++++++++++++++++++
 5 files changed, 824 insertions(+)
 create mode 100644 arch/powerpc/sysdev/fsl_pamu.c
 create mode 100644 arch/powerpc/sysdev/fsl_pamu.h

Patch

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a9363d2..ac7cd68 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -698,6 +698,16 @@  config FSL_GTM
 	help
 	  Freescale General-purpose Timers support
 
+config HAS_FSL_PAMU
+	bool
+	default n
+
+config FSL_PAMU
+	bool "PAMU/IOMMU support"
+	depends on HAS_FSL_PAMU
+	help
+	  Freescale PAMU/IOMMU support
+
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
 	bool
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index f000d81..87306fa 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -206,6 +206,7 @@  config P2041_RDB
 	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
+	select HAS_FSL_PAMU
 	help
 	  This option enables support for the P2041 RDB board
 
@@ -219,6 +220,7 @@  config P3041_DS
 	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
+	select HAS_FSL_PAMU
 	help
 	  This option enables support for the P3041 DS board
 
@@ -231,6 +233,7 @@  config P3060_QDS
 	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
+	select HAS_FSL_PAMU
 	help
 	  This option enables support for the P3060 QDS board
 
@@ -244,6 +247,7 @@  config P4080_DS
 	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
+	select HAS_FSL_PAMU
 	help
 	  This option enables support for the P4080 DS board
 
@@ -260,6 +264,7 @@  config P5020_DS
 	select GPIO_MPC8XXX
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
+	select HAS_FSL_PAMU
 	help
 	  This option enables support for the P5020 DS board
 
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 1bd7ecb..ef36198 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -21,6 +21,7 @@  obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_IFC)		+= fsl_ifc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
+obj-$(CONFIG_FSL_PAMU)		+= fsl_pamu.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
 obj-$(CONFIG_FSL_RIO)		+= fsl_rio.o fsl_rmu.o
diff --git a/arch/powerpc/sysdev/fsl_pamu.c b/arch/powerpc/sysdev/fsl_pamu.c
new file mode 100644
index 0000000..eab0cb1
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_pamu.c
@@ -0,0 +1,426 @@ 
+/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/of_platform.h>
+#include <linux/bootmem.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+
+#include "fsl_pamu.h"
+
+#define PAMUBYPENR 0x604
+
+/* define indexes for each operation mapping scenario */
+#define OMI_QMAN        0x00
+#define OMI_FMAN        0x01
+#define OMI_QMAN_PRIV   0x02
+#define OMI_CAAM        0x03
+
+void setup_omt(struct ome *omt)
+{
+	struct ome *ome;
+
+	/* Configure OMI_QMAN */
+	ome = &omt[OMI_QMAN];
+
+	ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READ;
+	ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA;
+	ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE;
+	ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSAO;
+
+	/*
+	 * When it comes to stashing DIRECTIVEs, the QMan BG says
+	 * (1.5.6.7.1:  FQD Context_A field used for dequeued etc.
+	 * etc. stashing control):
+	 * - AE/DE/CE == 0:  don't stash exclusive.  Use DIRECT0,
+	 *                   which should be a non-PE LOADEC.
+	 * - AE/DE/CE == 1:  stash exclusive via DIRECT1, i.e.
+	 *                   LOADEC-PE
+	 * If one desires to alter how the three different types of
+	 * stashing are done, please alter rx_conf.exclusive in
+	 * ipfwd_a.c (that specifies the 3-bit AE/DE/CE field), and
+	 * do not alter the settings here.  - bgrayson
+	 */
+	ome->moe[IOE_DIRECT0_IDX] = EOE_VALID | EOE_LDEC;
+	ome->moe[IOE_DIRECT1_IDX] = EOE_VALID | EOE_LDECPE;
+
+	/* Configure OMI_FMAN */
+	ome = &omt[OMI_FMAN];
+	ome->moe[IOE_READ_IDX]  = EOE_VALID | EOE_READI;
+	ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE;
+
+	/* Configure OMI_QMAN private */
+	ome = &omt[OMI_QMAN_PRIV];
+	ome->moe[IOE_READ_IDX]  = EOE_VALID | EOE_READ;
+	ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE;
+	ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RSA;
+	ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSA;
+
+	/* Configure OMI_CAAM */
+	ome = &omt[OMI_CAAM];
+	ome->moe[IOE_READ_IDX]  = EOE_VALID | EOE_READI;
+	ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE;
+}
+
+#define L1 1
+#define L2 2
+#define L3 3
+
+u32 get_stash_id(u32 stash_dest_hint, struct device_node *portal_dn)
+{
+	const u32 *prop;
+	struct device_node *node;
+	u32 cache_level;
+
+	/* Fastpath, exit early if L3/CPC cache is target for stashing */
+	if (stash_dest_hint == L3) {
+		node = of_find_compatible_node(NULL, NULL,
+				"fsl,p4080-l3-cache-controller");
+		if (node) {
+			prop = of_get_property(node, "cache-stash-id", 0);
+			if (!prop) {
+				printk(KERN_ERR "missing cache-stash-id at %s\n", node->full_name);
+				of_node_put(node);
+				return ~(u32)0;
+			}
+			of_node_put(node);
+			return *prop;
+		}
+		return ~(u32)0;
+	}
+
+	prop = of_get_property(portal_dn, "cpu-handle", 0);
+	/* if no cpu-phandle assume that this is not a per-cpu portal */
+	if (!prop)
+		return ~(u32)0;
+
+	node = of_find_node_by_phandle(*prop);
+	if (!node) {
+		printk(KERN_ERR "bad cpu phandle reference in %s\n",
+				 portal_dn->full_name);
+		return ~(u32)0;
+	}
+
+	/* find the hwnode that represents the cache */
+	for (cache_level = L1; cache_level <= L3; cache_level++) {
+		if (stash_dest_hint == cache_level) {
+			prop = of_get_property(node, "cache-stash-id", 0);
+			if (!prop) {
+				printk(KERN_ERR "missing cache-stash-id at %s\n", node->full_name);
+				of_node_put(node);
+				return ~(u32)0;
+			}
+			of_node_put(node);
+			return *prop;
+		}
+
+		prop = of_get_property(node, "next-level-cache", 0);
+		if (!prop) {
+			printk(KERN_ERR "can't find next-level-cache at %s\n",
+			          node->full_name);
+			of_node_put(node);
+			return ~(u32)0;  /* can't traverse any further */
+		}
+		of_node_put(node);
+
+		/* advance to next node in cache hierarchy */
+		node = of_find_node_by_phandle(*prop);
+		if (!node) {
+			printk(KERN_ERR "bad cpu phandle reference in %s\n",
+			          portal_dn->full_name);
+			return ~(u32)0;
+		}
+	}
+
+	printk(KERN_ERR "stash dest not found for %d on %s\n",
+	          stash_dest_hint, portal_dn->full_name);
+	return ~(u32)0;
+}
+
+void setup_liodns(struct ppaace *ppaact)
+{
+	int i, len;
+	struct ppaace *ppaace;
+	struct device_node *qman_portal_dn = NULL;
+	struct device_node *qman_dn = NULL;
+	const u32 *prop;
+	u32 cache_id, prop_cnt;
+
+	for (i = 0; i < PAACE_NUMBER_ENTRIES; i++) {
+		ppaace = &ppaact[i];
+		ppaace->pt = PAACE_PT_PRIMARY;
+		ppaace->domain_attr.to_host.coherency_required =
+				PAACE_M_COHERENCE_REQ;
+		/* window size is 2^(WSE+1) bytes */
+		ppaace->wse = 35; /* 36-bit phys. addr space */
+		ppaace->wbah = ppaace->wbal = 0;
+		ppaace->atm = PAACE_ATM_NO_XLATE;
+		ppaace->ap = PAACE_AP_PERMS_ALL;
+		mb();
+		ppaace->v = 1;
+	}
+
+	/*
+	 * Now, do specific stashing setup for qman portals.
+	 * We need stashing setup for LIODNs for  qman portal(s) dqrr stashing
+	 * (DLIODNs), qman portal(s) data stashing (FLIODNs)
+	 */
+
+	for_each_compatible_node(qman_portal_dn, NULL, "fsl,qman-portal") {
+
+		pr_debug("qman portal found, name = %s\n",
+					qman_portal_dn->full_name);
+		prop = of_get_property(qman_portal_dn, "fsl,liodn", &len);
+		if (prop) {
+			prop_cnt = len / sizeof(u32);
+			do {
+				pr_debug("liodn = %d\n", *prop);
+				ppaace = &ppaact[*prop++];
+				ppaace->otm = PAACE_OTM_INDEXED;
+				ppaace->op_encode.index_ot.omi = OMI_QMAN;
+				cache_id = get_stash_id(L1, qman_portal_dn);
+				pr_debug("cache_stash_id = %d\n", cache_id);
+				if (~cache_id != 0)
+					ppaace->impl_attr.cid = cache_id;
+			} while(--prop_cnt);
+		} else {
+			printk (KERN_ERR "missing fsl,liodn property at %s\n",
+			          qman_portal_dn->full_name);
+		}
+	}
+
+	/*
+	 * Next, do stashing setups for qman private memory access
+	 */
+
+	qman_dn = of_find_compatible_node(NULL, NULL, "fsl,qman");
+	if (qman_dn) {
+		prop = of_get_property(qman_dn, "fsl,liodn", NULL);
+		if (prop) {
+			ppaace = &ppaact[*prop];
+			ppaace->otm = PAACE_OTM_INDEXED;
+			ppaace->op_encode.index_ot.omi = OMI_QMAN_PRIV;
+			cache_id = get_stash_id(L3, qman_dn);
+			pr_debug("cache_stash_id = %d\n", cache_id);
+			if (~cache_id != 0)
+				ppaace->impl_attr.cid = cache_id;
+		} else {
+			printk (KERN_ERR "missing fsl,liodn property at %s\n",
+			          qman_dn->full_name);
+		}
+		of_node_put(qman_dn);
+	}
+}
+
+int setup_one_pamu(unsigned long pamu_reg_base, unsigned long pamu_reg_size,
+			struct ppaace *ppaact, struct ome *omt)
+{
+	u32 *pc;
+	phys_addr_t phys;
+	struct pamu_mmap_regs *pamu_regs;
+
+	pc = (u32 *) (pamu_reg_base + PAMU_PC);
+	pamu_regs = (struct pamu_mmap_regs *) 
+		(pamu_reg_base + PAMU_MMAP_REGS_BASE);
+
+	/* set up pointers to corenet control blocks */
+
+	phys = virt_to_phys(ppaact);
+	out_be32(&pamu_regs->ppbah, ((u64)phys) >> 32);
+	out_be32(&pamu_regs->ppbal, phys);
+	phys = virt_to_phys(ppaact + PAACE_NUMBER_ENTRIES);
+	out_be32(&pamu_regs->pplah, ((u64)phys) >> 32);
+	out_be32(&pamu_regs->pplal, phys);
+
+	phys = virt_to_phys(omt);
+	out_be32(&pamu_regs->obah, ((u64)phys) >> 32);
+	out_be32(&pamu_regs->obal, phys);
+	phys = virt_to_phys(omt + OME_NUMBER_ENTRIES);
+	out_be32(&pamu_regs->olah, ((u64)phys) >> 32);
+	out_be32(&pamu_regs->olal, phys);
+
+	/*
+	 * set PAMU enable bit,
+	 * allow ppaact & omt to be cached
+	 * & enable PAMU access violation interrupts.
+	 */
+
+	out_be32((u32 *)(pamu_reg_base + PAMU_PICS),
+			PAMU_ACCESS_VIOLATION_ENABLE);
+	out_be32(pc, PAMU_PC_PE | PAMU_PC_OCE | PAMU_PC_SPCC | PAMU_PC_PPCC);
+	return 0;
+}
+
+irqreturn_t pamu_av_isr(int irq, void *arg)
+{
+	panic("FSL_PAMU: access violation interrupt\n");
+	/* NOTREACHED */
+}
+
+static int __devinit fsl_of_pamu_probe(struct platform_device *dev)
+{
+	void __iomem *pamu_regs, *guts_regs;
+	u32 pamubypenr, pamu_counter;
+	unsigned long pamu_reg_base, pamu_reg_off;
+	struct device_node *guts_node;
+	u64 size;
+	struct ppaace *ppaact = NULL;
+	struct ome *omt = NULL;
+	int irq;
+	struct page *p;
+
+	printk(KERN_INFO "Setting Freescale static PAMU/IOMMU configuration\n");
+
+	/*
+	 * enumerate all PAMUs and allocate and setup PAMU tables
+	 * for each of them,
+	 * NOTE : All PAMUs share the same LIODN tables.
+	 */
+
+	pamu_regs = of_iomap(dev->dev.of_node, 0);
+	if (!pamu_regs) {
+		dev_err(&dev->dev, "ioremap failed\n");
+		return -ENOMEM;
+	}
+	of_get_address(dev->dev.of_node, 0, &size, NULL);
+
+	guts_node = of_find_compatible_node(NULL, NULL,
+			"fsl,qoriq-device-config-1.0");
+	if (!guts_node) {
+		dev_err(&dev->dev, "%s guts devnode not found!\n",
+				dev->dev.of_node->full_name);
+		iounmap(pamu_regs);
+		return -ENODEV;
+	}
+
+	guts_regs = of_iomap(guts_node, 0);
+	if (!guts_regs) {
+		dev_err(&dev->dev, "guts ioremap failed\n");
+		iounmap(pamu_regs);
+		return -ENOMEM;
+	}
+	of_node_put(guts_node);
+
+	p = alloc_pages(GFP_KERNEL, get_order(PAACT_SIZE));
+	if (!p) {
+		printk(KERN_ERR "Unable to allocate space for PAACT table\n");
+		iounmap(pamu_regs);
+		iounmap(guts_regs);
+		return -ENOMEM;
+	}
+	ppaact = page_address(p);
+	memset(ppaact, 0, PAACT_SIZE);
+
+	pr_debug("fsl_pamu, paact_mem, v : %p, p : 0x%lx\n",
+			ppaact, virt_to_phys(ppaact));
+
+	p = alloc_pages(GFP_KERNEL, get_order(OMT_SIZE));
+	if (!p) {
+		printk(KERN_ERR "Unable to allocate space for OMT table\n");
+		iounmap(pamu_regs);
+		iounmap(guts_regs);
+		free_pages((unsigned long)ppaact, get_order(PAACT_SIZE));
+		return -ENOMEM;
+	}
+	omt = page_address(p);
+	memset(omt, 0, OMT_SIZE);
+
+	pr_debug("fsl_pamu, omt_mem, v : %p, p : 0x%lx\n", 
+			omt, virt_to_phys(omt));
+
+	pamubypenr = in_be32(guts_regs + PAMUBYPENR);
+
+	for (pamu_reg_off = 0, pamu_counter = 0x80000000; pamu_reg_off < size;
+	     pamu_reg_off += PAMU_OFFSET, pamu_counter >>= 1) {
+
+		pamu_reg_base = (unsigned long) pamu_regs + pamu_reg_off;
+		setup_one_pamu(pamu_reg_base, pamu_reg_off, ppaact, omt);
+
+		/* Disable PAMU bypass for this PAMU */
+		pamubypenr &= ~pamu_counter;
+	}
+
+	setup_omt(omt);
+
+	irq = irq_of_parse_and_map(dev->dev.of_node, 0);
+	if (request_irq(irq, pamu_av_isr, IRQF_DISABLED, "pamu", 0) < 0) {
+		printk(KERN_ERR "Cannot request PAMU AV interrupt\n");
+		iounmap(pamu_regs);
+		iounmap(guts_regs);
+		free_pages((unsigned long)ppaact, get_order(PAACT_SIZE));
+		free_pages((unsigned long)omt, get_order(OMT_SIZE));
+		return -ENODEV;
+	}
+
+	/* 
+	 * setup all LIODNS(s) to define a 1:1 mapping for the entire
+	 * 36-bit physical address space
+	 */
+	setup_liodns(ppaact);
+	mb();
+
+	/* Enable all relevant PAMU(s) */
+	out_be32(guts_regs + PAMUBYPENR, pamubypenr);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_of_pamu_ids[] = {
+	{
+		.compatible = "fsl,p4080-pamu",
+	},
+	{
+		.compatible = "fsl,pamu",
+	},
+	{},
+};
+
+static struct platform_driver fsl_of_pamu_driver = {
+	.driver = {
+		.name = "fsl-of-pamu",
+		.of_match_table = fsl_of_pamu_ids,
+	},
+	.probe = fsl_of_pamu_probe,
+};
+
+static __init int fsl_of_pamu_init(void)
+{
+	return platform_driver_register(&fsl_of_pamu_driver);
+}
+
+arch_initcall(fsl_of_pamu_init);
diff --git a/arch/powerpc/sysdev/fsl_pamu.h b/arch/powerpc/sysdev/fsl_pamu.h
new file mode 100644
index 0000000..9e5f2a3
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_pamu.h
@@ -0,0 +1,382 @@ 
+/* Copyright (c) 2008-2010 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PAMU_H
+#define __PAMU_H
+
+/* PAMU CCSR space */
+#define PAMU_PGC 0x00000000     /* Allows all peripheral accesses */
+#define PAMU_PE 0x40000000      /* enable PAMU                    */
+
+/* PAMU_OFFSET to the next pamu space in ccsr */
+#define PAMU_OFFSET 0x1000	
+
+#define PAMU_MMAP_REGS_BASE 0
+
+struct pamu_mmap_regs {
+	u32 ppbah;
+	u32 ppbal;
+	u32 pplah;
+	u32 pplal;
+	u32 spbah;
+	u32 spbal;
+	u32 splah;
+	u32 splal;
+	u32 obah;
+	u32 obal;
+	u32 olah;
+	u32 olal;
+};
+
+/* PAMU Error Registers */
+#define PAMU_POES1 0x0040
+#define PAMU_POES2 0x0044
+#define PAMU_POEAH 0x0048
+#define PAMU_POEAL 0x004C
+#define PAMU_AVS1  0x0050
+#define PAMU_AVS1_AV    0x1
+#define PAMU_AVS1_OTV   0x6
+#define PAMU_AVS1_APV   0x78
+#define PAMU_AVS1_WAV   0x380
+#define PAMU_AVS1_LAV   0x1c00
+#define PAMU_AVS1_GCV   0x2000
+#define PAMU_AVS1_PDV   0x4000
+#define PAMU_AV_MASK    (PAMU_AVS1_AV | PAMU_AVS1_OTV | PAMU_AVS1_APV | PAMU_AVS1_WAV \
+			| PAMU_AVS1_LAV | PAMU_AVS1_GCV | PAMU_AVS1_PDV)
+#define PAMU_AVS1_LIODN_SHIFT 16
+#define PAMU_LAV_LIODN_NOT_IN_PPAACT 0x400
+
+#define PAMU_AVS2  0x0054
+#define PAMU_AVAH  0x0058
+#define PAMU_AVAL  0x005C
+#define PAMU_EECTL 0x0060
+#define PAMU_EEDIS 0x0064
+#define PAMU_EEINTEN 0x0068
+#define PAMU_EEDET 0x006C
+#define PAMU_EEATTR 0x0070
+#define PAMU_EEAHI 0x0074
+#define PAMU_EEALO 0x0078
+#define PAMU_EEDHI 0X007C
+#define PAMU_EEDLO 0x0080
+#define PAMU_EECC  0x0084
+
+/* PAMU Revision Registers */
+#define PAMU_PR1 0x0BF8
+#define PAMU_PR2 0x0BFC
+
+/* PAMU Capabilities Registers */
+#define PAMU_PC1 0x0C00
+#define PAMU_PC2 0x0C04
+#define PAMU_PC3 0x0C08
+#define PAMU_PC4 0x0C0C
+
+/* PAMU Control Register */
+#define PAMU_PC 0x0C10
+
+/* PAMU control defs */
+#define PAMU_CONTROL 0x0C10
+#define PAMU_PC_PGC 0x80000000 /* 1 = PAMU Gate Closed : block all 
+peripheral access, 0 : may allow peripheral access */
+
+#define PAMU_PC_PE   0x40000000 /* 0 = PAMU disabled, 1 = PAMU enabled */   
+#define PAMU_PC_SPCC 0x00000010 /* sPAACE cache enable */
+#define PAMU_PC_PPCC 0x00000001 /* pPAACE cache enable */
+#define PAMU_PC_OCE  0x00001000 /* OMT cache enable */
+
+#define PAMU_PFA1 0x0C14
+#define PAMU_PFA2 0x0C18
+
+/* PAMU Interrupt control and Status Register */
+#define PAMU_PICS 0x0C1C
+#define PAMU_ACCESS_VIOLATION_STAT   0x8
+#define PAMU_ACCESS_VIOLATION_ENABLE 0x4
+
+/* PAMU Debug Registers */
+#define PAMU_PD1 0x0F00
+#define PAMU_PD2 0x0F04
+#define PAMU_PD3 0x0F08
+#define PAMU_PD4 0x0F0C
+
+#define PAACE_AP_PERMS_DENIED  0x0
+#define PAACE_AP_PERMS_QUERY   0x1
+#define PAACE_AP_PERMS_UPDATE  0x2
+#define PAACE_AP_PERMS_ALL     0x3
+#define PAACE_DD_TO_HOST       0x0
+#define PAACE_DD_TO_IO         0x1
+#define PAACE_PT_PRIMARY       0x0
+#define PAACE_PT_SECONDARY     0x1
+#define PAACE_V_INVALID        0x0
+#define PAACE_V_VALID          0x1
+#define PAACE_MW_SUBWINDOWS    0x1
+
+#define PAACE_WSE_4K           0xB
+#define PAACE_WSE_8K           0xC
+#define PAACE_WSE_16K          0xD
+#define PAACE_WSE_32K          0xE
+#define PAACE_WSE_64K          0xF
+#define PAACE_WSE_128K         0x10
+#define PAACE_WSE_256K         0x11
+#define PAACE_WSE_512K         0x12
+#define PAACE_WSE_1M           0x13
+#define PAACE_WSE_2M           0x14
+#define PAACE_WSE_4M           0x15
+#define PAACE_WSE_8M           0x16
+#define PAACE_WSE_16M          0x17
+#define PAACE_WSE_32M          0x18
+#define PAACE_WSE_64M          0x19
+#define PAACE_WSE_128M         0x1A
+#define PAACE_WSE_256M         0x1B
+#define PAACE_WSE_512M         0x1C
+#define PAACE_WSE_1G           0x1D
+#define PAACE_WSE_2G           0x1E
+#define PAACE_WSE_4G           0x1F
+
+#define PAACE_DID_PCI_EXPRESS_1 0x00
+#define PAACE_DID_PCI_EXPRESS_2 0x01
+#define PAACE_DID_PCI_EXPRESS_3 0x02
+#define PAACE_DID_PCI_EXPRESS_4 0x03
+#define PAACE_DID_LOCAL_BUS     0x04
+#define PAACE_DID_SRIO          0x0C
+#define PAACE_DID_MEM_1         0x10
+#define PAACE_DID_MEM_2         0x11
+#define PAACE_DID_MEM_3         0x12
+#define PAACE_DID_MEM_4         0x13
+#define PAACE_DID_MEM_1_2       0x14
+#define PAACE_DID_MEM_3_4       0x15
+#define PAACE_DID_MEM_1_4       0x16
+#define PAACE_DID_BM_SW_PORTAL  0x18
+#define PAACE_DID_PAMU          0x1C
+#define PAACE_DID_CAAM          0x21
+#define PAACE_DID_QM_SW_PORTAL  0x3C
+#define PAACE_DID_CORE0_INST    0x80
+#define PAACE_DID_CORE0_DATA    0x81
+#define PAACE_DID_CORE1_INST    0x82
+#define PAACE_DID_CORE1_DATA    0x83
+#define PAACE_DID_CORE2_INST    0x84
+#define PAACE_DID_CORE2_DATA    0x85
+#define PAACE_DID_CORE3_INST    0x86
+#define PAACE_DID_CORE3_DATA    0x87
+#define PAACE_DID_CORE4_INST    0x88
+#define PAACE_DID_CORE4_DATA    0x89
+#define PAACE_DID_CORE5_INST    0x8A
+#define PAACE_DID_CORE5_DATA    0x8B
+#define PAACE_DID_CORE6_INST    0x8C
+#define PAACE_DID_CORE6_DATA    0x8D
+#define PAACE_DID_CORE7_INST    0x8E
+#define PAACE_DID_CORE7_DATA    0x8F
+#define PAACE_DID_BROADCAST     0xFF
+
+#define PAACE_ATM_NO_XLATE      0x00
+#define PAACE_ATM_WINDOW_XLATE  0x01
+#define PAACE_ATM_PAGE_XLATE    0x02
+#define PAACE_ATM_WIN_PG_XLATE  \
+                ( PAACE_ATM_WINDOW_XLATE | PAACE_ATM_PAGE_XLATE )
+#define PAACE_OTM_NO_XLATE      0x00
+#define PAACE_OTM_IMMEDIATE     0x01
+#define PAACE_OTM_INDEXED       0x02
+#define PAACE_OTM_RESERVED      0x03
+
+#define PAACE_M_COHERENCE_REQ   0x01
+
+#define PAACE_PID_0             0x0
+#define PAACE_PID_1             0x1
+#define PAACE_PID_2             0x2
+#define PAACE_PID_3             0x3
+#define PAACE_PID_4             0x4
+#define PAACE_PID_5             0x5
+#define PAACE_PID_6             0x6
+#define PAACE_PID_7             0x7
+
+#define PAACE_TCEF_FORMAT0_8B   0x00
+#define PAACE_TCEF_FORMAT1_RSVD 0x01
+
+#define PAACE_NUMBER_ENTRIES    0xFF
+
+#define	OME_NUMBER_ENTRIES      16   /* based on P4080 2.0 silicon plan */
+
+/* PAMU Data Structures */
+
+struct ppaace {
+	/* PAACE Offset 0x00 */
+	/* Window Base Address */
+	u32        wbah;
+	unsigned int    wbal : 20;
+	/* Window Size, 2^(N+1), N must be > 10 */
+	unsigned int    wse : 6;
+	/* 1 Means there are secondary windows, wce is count */
+	unsigned int    mw : 1;
+	/* Permissions, see PAACE_AP_PERMS_* defines */
+	unsigned int    ap : 2;
+	/* 
+	 * Destination Domain, see PAACE_DD_* defines,
+	 * defines data structure reference for ingress ops into 
+	 * host/coherency domain or ingress ops into I/O domain
+	 */
+	unsigned int    dd : 1;
+	/* PAACE Type, see PAACE_PT_* defines */
+	unsigned int    pt : 1;
+	/* PAACE Valid, 0 is invalid */
+	unsigned int    v : 1;
+
+	/* PAACE Offset 0x08 */
+	/* Interpretation of first 32 bits dependent on DD above */
+	union {
+		struct {
+			/* Destination ID, see PAACE_DID_* defines */
+			u8 did;  
+			/* Partition ID */
+			u8 pid;
+			/* Snoop ID */
+			u8 snpid;
+			unsigned int coherency_required : 1;
+			unsigned int reserved : 7;
+		} to_host;
+		struct {
+			/* Destination ID, see PAACE_DID_* defines */
+			u8 did;
+			unsigned int __reserved : 24;
+		} to_io;
+	} __attribute__ ((packed)) domain_attr;
+	/* Implementation attributes */
+	struct {
+		unsigned int reserved1 : 8;
+		unsigned int cid : 8;
+		unsigned int reserved2 : 8;
+	} __attribute__ ((packed)) impl_attr;
+	/* Window Count; 2^(N+1) sub-windows; only valid for primary PAACE */
+	unsigned int wce : 4;
+	/* Address translation mode, see PAACE_ATM_* defines */
+	unsigned int atm : 2;
+	/* Operation translation mode, see PAACE_OTM_* defines */
+	unsigned int otm : 2;
+
+	/* PAACE Offset 0x10 */
+	/* Translated window base address */
+	u32 twbah;
+	unsigned int twbal : 20;
+	/* Subwindow size encoding; 2^(N+1), N > 10 */
+	unsigned int swse : 6;
+	unsigned int reserved4 : 6;
+
+	/* PAACE Offset 0x18 */
+	u32 fspi;
+	union {
+		struct {
+			u8 ioea;
+			u8 moea;
+			u8 ioeb;
+			u8 moeb;
+		} immed_ot;
+		struct {
+			u16 reserved;
+			u16 omi;
+		} index_ot;
+	} __attribute__ ((packed)) op_encode;
+
+	/* PAACE Offset 0x20 */
+	u32 sbah;
+	unsigned int sbal : 20;
+	unsigned int sse : 6;
+	unsigned int reserved5 : 6;
+
+	/* PAACE Offset 0x28 */
+	u32 tctbah;
+	unsigned int tctbal : 20;
+	unsigned int pse : 6;
+	unsigned int tcef :1;
+	unsigned int reserved6 : 5;
+
+	/* PAACE Offset 0x30 */
+	u32 reserved7[2];
+
+	/* PAACE Offset 0x38 */
+	u32 reserved8[2];
+} __attribute__ ((packed)) ppaace;
+
+/* MOE : Mapped Operation Encodings */
+#define NUM_MOE 128
+struct ome {
+	u8 moe[NUM_MOE];
+} __attribute__((packed)) ome;
+
+#define PAACT_SIZE              (sizeof(struct ppaace) * PAACE_NUMBER_ENTRIES)
+#define OMT_SIZE                (sizeof(struct ome) * OME_NUMBER_ENTRIES)
+
+#define IOE_READ        0x00
+#define IOE_READ_IDX    0x00
+#define IOE_WRITE       0x81
+#define IOE_WRITE_IDX   0x01
+#define IOE_EREAD0      0x82    /* Enhanced read type 0 */
+#define IOE_EREAD0_IDX  0x02    /* Enhanced read type 0 */
+#define IOE_EWRITE0     0x83    /* Enhanced write type 0 */
+#define IOE_EWRITE0_IDX 0x03    /* Enhanced write type 0 */
+#define IOE_DIRECT0     0x84    /* Directive type 0 */
+#define IOE_DIRECT0_IDX 0x04    /* Directive type 0 */
+#define IOE_EREAD1      0x85    /* Enhanced read type 1 */
+#define IOE_EREAD1_IDX  0x05    /* Enhanced read type 1 */
+#define IOE_EWRITE1     0x86    /* Enhanced write type 1 */
+#define IOE_EWRITE1_IDX 0x06    /* Enhanced write type 1 */
+#define IOE_DIRECT1     0x87    /* Directive type 1 */
+#define IOE_DIRECT1_IDX 0x07    /* Directive type 1 */
+#define IOE_RAC         0x8c    /* Read with Atomic clear */
+#define IOE_RAC_IDX     0x0c    /* Read with Atomic clear */
+#define IOE_RAS         0x8d    /* Read with Atomic set */
+#define IOE_RAS_IDX     0x0d    /* Read with Atomic set */
+#define IOE_RAD         0x8e    /* Read with Atomic decrement */
+#define IOE_RAD_IDX     0x0e    /* Read with Atomic decrement */
+#define IOE_RAI         0x8f    /* Read with Atomic increment */
+#define IOE_RAI_IDX     0x0f    /* Read with Atomic increment */
+
+#define EOE_READ        0x00
+#define EOE_WRITE       0x01
+#define EOE_RAC         0x0c    /* Read with Atomic clear */
+#define EOE_RAS         0x0d    /* Read with Atomic set */
+#define EOE_RAD         0x0e    /* Read with Atomic decrement */
+#define EOE_RAI         0x0f    /* Read with Atomic increment */
+#define EOE_LDEC        0x10    /* Load external cache */
+#define EOE_LDECL       0x11    /* Load external cache with stash lock */
+#define EOE_LDECPE      0x12    /* Load external cache with preferred exclusive */
+#define EOE_LDECPEL     0x13    /* Load external cache with preferred exclusive and lock */
+#define EOE_LDECFE      0x14    /* Load external cache with forced exclusive */
+#define EOE_LDECFEL     0x15    /* Load external cache with forced exclusive and lock */
+#define EOE_RSA         0x16    /* Read with stash allocate */
+#define EOE_RSAU        0x17    /* Read with stash allocate and unlock */
+#define EOE_READI       0x18    /* Read with invalidate */
+#define EOE_RWNITC      0x19    /* Read with no intention to cache */
+#define EOE_WCI         0x1a    /* Write cache inhibited */
+#define EOE_WWSA        0x1b    /* Write with stash allocate */
+#define EOE_WWSAL       0x1c    /* Write with stash allocate and lock */
+#define EOE_WWSAO       0x1d    /* Write with stash allocate only */
+#define EOE_WWSAOL      0x1e    /* Write with stash allocate only and lock */
+#define EOE_VALID       0x80
+
+#endif  /* __PAMU_H */