From patchwork Tue Jun 21 05:13:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [08/27] UBUNTU: SAUCE: powerpc/pamu: Add driver to initialize PAMU tables From: Benjamin Collins X-Patchwork-Id: 164267 Message-Id: <8083a93b52b3e64afc0132ac0261aff9afd0077e.1339455421.git.bcollins@ubuntu.com> To: kernel-team@lists.ubuntu.com Date: Tue, 21 Jun 2011 00:13:39 -0500 This patch is being maintained, and eventually merged upstream, by Freescale directly. The powerpc-e500mc flavour uses this. Signed-off-by: Stuart Yoder Signed-off-by: Vakul Garg Signed-off-by: Varun Sethi Signed-off-by: Ben Collins --- 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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 */