diff options
44 files changed, 42 insertions, 6986 deletions
@@ -44,12 +44,6 @@ . = 0 .global __head __head: - /* - * When booting a P7 machine in OPAL mode this pointer is used to - * find the opal variant of the NACA. Unused on other machines. - */ - .llong opal_naca - /* This entry point is used when booting with a flat device-tree * pointer in r3 */ @@ -343,10 +337,6 @@ boot_entry: mfspr %r28,SPR_PVR li %r26,3 /* Default to SMT4 */ srdi %r3,%r28,16 - cmpwi cr0,%r3,PVR_TYPE_P7 - beq 1f - cmpwi cr0,%r3,PVR_TYPE_P7P - beq 1f cmpwi cr0,%r3,PVR_TYPE_P8 beq 2f cmpwi cr0,%r3,PVR_TYPE_P8E @@ -693,10 +683,6 @@ init_shared_sprs: mfspr %r3,SPR_PVR srdi %r3,%r3,16 - cmpwi cr0,%r3,PVR_TYPE_P7 - beq 1f - cmpwi cr0,%r3,PVR_TYPE_P7P - beq 2f cmpwi cr0,%r3,PVR_TYPE_P8E beq 3f cmpwi cr0,%r3,PVR_TYPE_P8 @@ -710,20 +696,6 @@ init_shared_sprs: /* Unsupported CPU type... what do we do ? */ b 9f -1: /* P7 */ - mtspr SPR_SDR1, %r0 - /* TSCR: Value from pHyp */ - LOAD_IMM32(%r3,0x880DE880) - mtspr SPR_TSCR, %r3 - b 9f - -2: /* P7+ */ - mtspr SPR_SDR1, %r0 - /* TSCR: Recommended value by HW folks */ - LOAD_IMM32(%r3,0x88CDE880) - mtspr SPR_TSCR, %r3 - b 9f - 3: /* P8E/P8 */ mtspr SPR_SDR1, %r0 /* TSCR: Recommended value by HW folks */ @@ -795,10 +767,6 @@ init_shared_sprs: init_replicated_sprs: mfspr %r3,SPR_PVR srdi %r3,%r3,16 - cmpwi cr0,%r3,PVR_TYPE_P7 - beq 1f - cmpwi cr0,%r3,PVR_TYPE_P7P - beq 1f cmpwi cr0,%r3,PVR_TYPE_P8E beq 3f cmpwi cr0,%r3,PVR_TYPE_P8 @@ -812,16 +780,6 @@ init_replicated_sprs: /* Unsupported CPU type... what do we do ? */ b 9f -1: /* P7, P7+ */ - /* LPCR: sane value */ - LOAD_IMM64(%r3,0x0040000000000004) - mtspr SPR_LPCR, %r3 - sync - isync - LOAD_IMM64(%r3,0x0) - mtspr SPR_DSCR,%r3 - b 9f - 3: /* P8, P8E */ /* LPCR: sane value */ LOAD_IMM64(%r3,0x0040000000000000) @@ -903,22 +861,6 @@ hv_lid_load_table: .long 0 .long 0 -/* - * - * OPAL variant of NACA. This is only used when booting a P7 in OPAL mode. - * - */ -.global opal_naca -opal_naca: - .llong opal_boot_trampoline /* Primary entry (used ?) */ - .llong opal_boot_trampoline /* Secondary entry (used ?) */ - .llong spira /* Spira pointer */ - .llong 0 /* Load address */ - .llong opal_boot_trampoline /* 0x180 trampoline */ - .llong 0 /* More stuff as seen in objdump ...*/ - .llong 0 - .llong 0 - .llong 0 /* The FSP seems to ignore our primary/secondary entry * points and instead copy that bit down to 0x180 and diff --git a/core/affinity.c b/core/affinity.c index 10d483d..070a1cd 100644 --- a/core/affinity.c +++ b/core/affinity.c @@ -120,9 +120,7 @@ void add_core_associativity(struct cpu_thread *cpu) if (!chip) return; - if (proc_gen == proc_gen_p7) - core_id = (cpu->pir >> 2) & 0x7; - else if (proc_gen == proc_gen_p8) + if (proc_gen == proc_gen_p8) core_id = (cpu->pir >> 3) & 0xf; else if (proc_gen == proc_gen_p9) core_id = (cpu->pir >> 2) & 0x1f; diff --git a/core/chip.c b/core/chip.c index b01ec5b..221cf2d 100644 --- a/core/chip.c +++ b/core/chip.c @@ -31,7 +31,7 @@ uint32_t pir_to_chip_id(uint32_t pir) else if (proc_gen == proc_gen_p8) return P8_PIR2GCID(pir); else - return P7_PIR2GCID(pir); + assert(false); } uint32_t pir_to_core_id(uint32_t pir) @@ -41,7 +41,7 @@ uint32_t pir_to_core_id(uint32_t pir) else if (proc_gen == proc_gen_p8) return P8_PIR2COREID(pir); else - return P7_PIR2COREID(pir); + assert(false); } uint32_t pir_to_thread_id(uint32_t pir) @@ -51,7 +51,7 @@ uint32_t pir_to_thread_id(uint32_t pir) else if (proc_gen == proc_gen_p8) return P8_PIR2THREADID(pir); else - return P7_PIR2THREADID(pir); + assert(false); } struct proc_chip *next_chip(struct proc_chip *chip) @@ -110,7 +110,7 @@ static void cpu_wake(struct cpu_thread *cpu) if (!cpu->in_idle) return; - if (proc_gen == proc_gen_p8 || proc_gen == proc_gen_p7) { + if (proc_gen == proc_gen_p8) { /* Poke IPI */ icp_kick_cpu(cpu); } else if (proc_gen == proc_gen_p9) { @@ -992,10 +992,6 @@ void init_boot_cpu(void) /* Get CPU family and other flags based on PVR */ switch(PVR_TYPE(pvr)) { - case PVR_TYPE_P7: - case PVR_TYPE_P7P: - proc_gen = proc_gen_p7; - break; case PVR_TYPE_P8E: case PVR_TYPE_P8: proc_gen = proc_gen_p8; @@ -1023,11 +1019,6 @@ void init_boot_cpu(void) /* Get a CPU thread count based on family */ switch(proc_gen) { - case proc_gen_p7: - cpu_thread_count = 4; - prlog(PR_INFO, "CPU: P7 generation processor" - " (max %d threads/core)\n", cpu_thread_count); - break; case proc_gen_p8: cpu_thread_count = 8; prlog(PR_INFO, "CPU: P8 generation processor" @@ -1580,13 +1571,6 @@ static int64_t opal_reinit_cpus(uint64_t flags) if (req.set_bits || req.clr_bits) cpu_change_all_hid0(&req); - /* If we have a P7, error out for LE switch, do nothing for BE */ - if (proc_gen < proc_gen_p8) { - if (flags & OPAL_REINIT_CPUS_HILE_LE) - rc = OPAL_UNSUPPORTED; - flags &= ~(OPAL_REINIT_CPUS_HILE_BE | OPAL_REINIT_CPUS_HILE_LE); - } - if (flags & OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED) { flags &= ~OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED; diff --git a/core/init.c b/core/init.c index 2c39688..3db9df3 100644 --- a/core/init.c +++ b/core/init.c @@ -1103,9 +1103,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) /* Allocate our split trace buffers now. Depends add_opal_node() */ init_trace_buffers(); - /* On P7/P8, get the ICPs and make sure they are in a sane state */ + /* On P8, get the ICPs and make sure they are in a sane state */ init_interrupts(); - if (proc_gen == proc_gen_p7 || proc_gen == proc_gen_p8) + if (proc_gen == proc_gen_p8) cpu_set_ipi_enable(true); /* On P9, initialize XIVE */ @@ -1238,9 +1238,6 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) /* Init In-Memory Collection related stuff (load the IMC dtb into memory) */ imc_init(); - /* Probe IO hubs */ - probe_p7ioc(); - /* Probe PHB3 on P8 */ probe_phb3(); diff --git a/core/interrupts.c b/core/interrupts.c index 5d7a68c..b053401 100644 --- a/core/interrupts.c +++ b/core/interrupts.c @@ -152,16 +152,6 @@ uint32_t get_psi_interrupt(uint32_t chip_id) uint32_t irq; switch(proc_gen) { - case proc_gen_p7: - /* Get the chip ID into position, it already has - * the T bit so all we need is room for the GX - * bit, 9 bit BUID and 4 bit level - */ - irq = chip_id << (1 + 9 + 4); - - /* Add in the BUID */ - irq |= P7_PSI_IRQ_BUID << 4; - break; case proc_gen_p8: irq = p8_chip_irq_block_base(chip_id, P8_IRQ_BLOCK_MISC); irq += P8_IRQ_MISC_PSI_BASE; diff --git a/core/test/run-cpufeatures.c b/core/test/run-cpufeatures.c index 9db2144..c072e5f 100644 --- a/core/test/run-cpufeatures.c +++ b/core/test/run-cpufeatures.c @@ -44,7 +44,7 @@ static inline unsigned long mfspr(unsigned int spr); #include "../cpufeatures.c" -static unsigned long fake_pvr = PVR_TYPE_P7; +static unsigned long fake_pvr = PVR_TYPE_P8; static inline unsigned long mfspr(unsigned int spr) { diff --git a/core/test/run-flash-firmware-versions.c b/core/test/run-flash-firmware-versions.c index 924f3e9..8fff714 100644 --- a/core/test/run-flash-firmware-versions.c +++ b/core/test/run-flash-firmware-versions.c @@ -103,7 +103,7 @@ char __rodata_start[1], __rodata_end[1]; const char version[]="Hello world!"; -enum proc_gen proc_gen = proc_gen_p7; +enum proc_gen proc_gen = proc_gen_p8; static char *loaded_version_buf; static size_t loaded_version_buf_size; diff --git a/doc/opal-api/opal-pci-get-hub-diag-data-50.rst b/doc/opal-api/opal-pci-get-hub-diag-data-50.rst index e7b2584..7ee9806 100644 --- a/doc/opal-api/opal-pci-get-hub-diag-data-50.rst +++ b/doc/opal-api/opal-pci-get-hub-diag-data-50.rst @@ -7,61 +7,14 @@ OPAL_PCI_GET_HUB_DIAG_DATA #define OPAL_PCI_GET_HUB_DIAG_DATA 50 - enum { - OPAL_P7IOC_DIAG_TYPE_NONE = 0, - OPAL_P7IOC_DIAG_TYPE_RGC = 1, - OPAL_P7IOC_DIAG_TYPE_BI = 2, - OPAL_P7IOC_DIAG_TYPE_CI = 3, - OPAL_P7IOC_DIAG_TYPE_MISC = 4, - OPAL_P7IOC_DIAG_TYPE_I2C = 5, - OPAL_P7IOC_DIAG_TYPE_LAST = 6 - }; - - struct OpalIoP7IOCErrorData { - __be16 type; - - /* GEM */ - __be64 gemXfir; - __be64 gemRfir; - __be64 gemRirqfir; - __be64 gemMask; - __be64 gemRwof; - - /* LEM */ - __be64 lemFir; - __be64 lemErrMask; - __be64 lemAction0; - __be64 lemAction1; - __be64 lemWof; - - union { - struct OpalIoP7IOCRgcErrorData { - __be64 rgcStatus; /* 3E1C10 */ - __be64 rgcLdcp; /* 3E1C18 */ - }rgc; - struct OpalIoP7IOCBiErrorData { - __be64 biLdcp0; /* 3C0100, 3C0118 */ - __be64 biLdcp1; /* 3C0108, 3C0120 */ - __be64 biLdcp2; /* 3C0110, 3C0128 */ - __be64 biFenceStatus; /* 3C0130, 3C0130 */ - - uint8_t biDownbound; /* BI Downbound or Upbound */ - }bi; - struct OpalIoP7IOCCiErrorData { - __be64 ciPortStatus; /* 3Dn008 */ - __be64 ciPortLdcp; /* 3Dn010 */ - - uint8_t ciPort; /* Index of CI port: 0/1 */ - }ci; - }; - }; - int64_t opal_pci_get_hub_diag_data(uint64_t hub_id, void *diag_buffer, uint64_t diag_buffer_len); -Fetch diagnostic data for an IO hub. Currently, this is only implemented for -p7ioc, which is specific to POWER7, something that was only ever available +Fetch diagnostic data for an IO hub. This was only implemented for hardware +specific to POWER7 systems, something that was only ever available internally to IBM for development purposes. +It is currently not used. + If :ref:`OPAL_PCI_NEXT_ERROR` error type is `OPAL_EEH_IOC_ERROR` and severity is `OPAL_EEH_SEV_INF`, then the OS should call :ref:`OPAL_PCI_GET_HUB_DIAG_DATA` to retreive diagnostic data to log appropriately. diff --git a/external/xscom-utils/adu_scoms.py b/external/xscom-utils/adu_scoms.py index bb077db..a1b7d89 100755 --- a/external/xscom-utils/adu_scoms.py +++ b/external/xscom-utils/adu_scoms.py @@ -176,11 +176,7 @@ class GetSCom(object): c_id = val >> 44 id = c_id & 0xff - if id == 0xf9: - name = "P7 processor" - elif id == 0xe8: - name = "P7+ processor" - elif id == 0xef: + if id == 0xef: name = "P8E (Murano) processor" elif id == 0xea: name = "P8 (Venice) processor" diff --git a/external/xscom-utils/getscom.c b/external/xscom-utils/getscom.c index 8c96634..dab4994 100644 --- a/external/xscom-utils/getscom.c +++ b/external/xscom-utils/getscom.c @@ -47,12 +47,6 @@ static void print_chip_info(uint32_t chip_id) cfam_id = f000f >> 44; switch(cfam_id & 0xff) { - case 0xf9: - name = "P7 processor"; - break; - case 0xe8: - name = "P7+ processor"; - break; case 0xef: name = "P8E (Murano) processor"; break; @@ -79,7 +73,6 @@ static void print_chip_info(uint32_t chip_id) printf("%08x | DD%lx.%lx | %s\n", chip_id, (cfam_id >> 16) & 0xf, (cfam_id >> 8) & 0xf, name); - } extern const char version[]; diff --git a/hdata/cpu-common.c b/hdata/cpu-common.c index f6dda4e..0924dd5 100644 --- a/hdata/cpu-common.c +++ b/hdata/cpu-common.c @@ -30,12 +30,6 @@ struct dt_node * add_core_common(struct dt_node *cpus, struct dt_node *cpu; uint32_t version; uint64_t freq; - const uint8_t pa_features_p7[] = { - 6, 0, - 0xf6, 0x3f, 0xc7, 0x00, 0x80, 0xc0 }; - const uint8_t pa_features_p7p[] = { - 6, 0, - 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xc0 }; const uint8_t pa_features_p8[] = { 24, 0, 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xd0, 0x80, 0x00, @@ -80,16 +74,6 @@ struct dt_node * add_core_common(struct dt_node *cpus, */ version = mfspr(SPR_PVR); switch(PVR_TYPE(version)) { - case PVR_TYPE_P7: - name = "PowerPC,POWER7"; - pa_features = pa_features_p7; - pa_features_size = sizeof(pa_features_p7); - break; - case PVR_TYPE_P7P: - name = "PowerPC,POWER7+"; - pa_features = pa_features_p7p; - pa_features_size = sizeof(pa_features_p7p); - break; case PVR_TYPE_P8E: case PVR_TYPE_P8: case PVR_TYPE_P8NVL: diff --git a/hdata/iohub.c b/hdata/iohub.c index feb8d6a..c81dc5e 100644 --- a/hdata/iohub.c +++ b/hdata/iohub.c @@ -22,43 +22,12 @@ #include <ccan/str/str.h> #include <ccan/array_size/array_size.h> #include <device.h> -#include <p7ioc.h> #include <vpd.h> #include <inttypes.h> #include <string.h> #include "hdata.h" -static void io_add_common(struct dt_node *hn, const struct cechub_io_hub *hub) -{ - dt_add_property_cells(hn, "#address-cells", 2); - dt_add_property_cells(hn, "#size-cells", 2); - dt_add_property_cells(hn, "ibm,buid-ext", be32_to_cpu(hub->buid_ext)); - dt_add_property_cells(hn, "ibm,chip-id", - pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id))); - dt_add_property_cells(hn, "ibm,gx-index", be32_to_cpu(hub->gx_index)); - dt_add_property_cells(hn, "revision", be32_to_cpu(hub->ec_level)); - - /* Instead of exposing the GX BARs as separate ranges as we *should* - * do in an ideal world, we just create a pass-through ranges and - * we use separate properties for the BARs. - * - * This is hackish but will do for now and avoids us having to - * do too complex ranges property parsing - */ - dt_add_property(hn, "ranges", NULL, 0); - dt_add_property_u64(hn, "ibm,gx-bar-1", be64_to_cpu(hub->gx_ctrl_bar1)); - dt_add_property_u64(hn, "ibm,gx-bar-2", be64_to_cpu(hub->gx_ctrl_bar2)); - - /* Add presence detect if valid */ - if (hub->flags & CECHUB_HUB_FLAG_FAB_BR0_PDT) - dt_add_property_cells(hn, "ibm,br0-presence-detect", - hub->fab_br0_pdt); - if (hub->flags & CECHUB_HUB_FLAG_FAB_BR1_PDT) - dt_add_property_cells(hn, "ibm,br1-presence-detect", - hub->fab_br1_pdt); -} - static bool io_get_lx_info(const void *kwvpd, unsigned int kwvpd_sz, int lx_idx, struct dt_node *hn) { @@ -131,63 +100,6 @@ static void io_get_loc_code(const void *sp_iohubs, struct dt_node *hn, const cha } } -static struct dt_node *io_add_p7ioc(const struct cechub_io_hub *hub, - const void *sp_iohubs) -{ - struct dt_node *hn; - uint64_t reg[2]; - - const void *kwvpd; - unsigned int kwvpd_sz; - - prlog(PR_DEBUG, " GX#%d BUID_Ext = 0x%x\n", - be32_to_cpu(hub->gx_index), - be32_to_cpu(hub->buid_ext)); - prlog(PR_DEBUG, " GX BAR 0 = 0x%016"PRIx64"\n", - be64_to_cpu(hub->gx_ctrl_bar0)); - prlog(PR_DEBUG, " GX BAR 1 = 0x%016"PRIx64"\n", - be64_to_cpu(hub->gx_ctrl_bar1)); - prlog(PR_DEBUG, " GX BAR 2 = 0x%016"PRIx64"\n", - be64_to_cpu(hub->gx_ctrl_bar2)); - prlog(PR_DEBUG, " GX BAR 3 = 0x%016"PRIx64"\n", - be64_to_cpu(hub->gx_ctrl_bar3)); - prlog(PR_DEBUG, " GX BAR 4 = 0x%016"PRIx64"\n", - be64_to_cpu(hub->gx_ctrl_bar4)); - - /* We only know about memory map 1 */ - if (be32_to_cpu(hub->mem_map_vers) != 1) { - prerror("P7IOC: Unknown memory map %d\n", be32_to_cpu(hub->mem_map_vers)); - /* We try to continue anyway ... */ - } - - reg[0] = cleanup_addr(be64_to_cpu(hub->gx_ctrl_bar1)); - reg[1] = 0x2000000; - - hn = dt_new_addr(dt_root, "io-hub", reg[0]); - if (!hn) - return NULL; - - dt_add_property(hn, "reg", reg, sizeof(reg)); - dt_add_property_strings(hn, "compatible", "ibm,p7ioc", "ibm,ioda-hub"); - - kwvpd = HDIF_get_idata(sp_iohubs, CECHUB_ASCII_KEYWORD_VPD, &kwvpd_sz); - if (kwvpd && kwvpd != sp_iohubs) { - /* - * XX We don't know how to properly find the LXRn - * record so for now we'll just try LXR0 and if not - * found, we try LXR1 - */ - if (!io_get_lx_info(kwvpd, kwvpd_sz, 0, hn)) - io_get_lx_info(kwvpd, kwvpd_sz, 1, hn); - } else { - prlog(PR_DEBUG, "CEC: P7IOC Keywords not found.\n"); - } - - io_get_loc_code(sp_iohubs, hn, "ibm,io-base-loc-code"); - - return hn; -} - static struct dt_node *io_add_phb3(const struct cechub_io_hub *hub, const struct HDIF_common_hdr *sp_iohubs, unsigned int index, struct dt_node *xcom, @@ -856,7 +768,6 @@ static void io_parse_fru(const void *sp_iohubs) for (i = 0; i < count; i++) { const struct cechub_io_hub *hub; unsigned int size, hub_id; - struct dt_node *hn; uint32_t chip_id; hub = HDIF_get_iarray_item(sp_iohubs, CECHUB_FRU_IO_HUBS, @@ -892,11 +803,6 @@ static void io_parse_fru(const void *sp_iohubs) be32_to_cpu(hub->ec_level), be16_to_cpu(hub->hub_num)); switch(hub_id) { - case CECHUB_HUB_P7IOC: - prlog(PR_INFO, "CEC: P7IOC !\n"); - hn = io_add_p7ioc(hub, sp_iohubs); - io_add_common(hn, hub); - break; case CECHUB_HUB_MURANO: case CECHUB_HUB_MURANO_SEGU: prlog(PR_INFO, "CEC: Murano !\n"); diff --git a/hdata/pcia.c b/hdata/pcia.c index 9b210e4..0638327 100644 --- a/hdata/pcia.c +++ b/hdata/pcia.c @@ -158,9 +158,7 @@ static struct dt_node *add_core_node(struct dt_node *cpus, be32_to_cpu(t->pir), okay); dt_add_property_cells(cpu, "l2-cache", l2_phandle); - if (proc_gen == proc_gen_p7) - icp_compat = "IBM,power7-icp"; - else + if (proc_gen == proc_gen_p8) icp_compat = "IBM,power8-icp"; /* Get HW Chip ID */ @@ -182,7 +180,7 @@ static struct dt_node *add_core_node(struct dt_node *cpus, dt_add_property(cpu, "ibm,ppc-interrupt-server#s", iserv, 4 * threads); - /* Add the ICP node for this CPU for P7 / P8 */ + /* Add the ICP node for this CPU for P8 */ if (proc_gen <= proc_gen_p8) add_xics_icp(pcia, threads, icp_compat); diff --git a/hdata/spira.c b/hdata/spira.c index 43c76f9..6891a9c 100644 --- a/hdata/spira.c +++ b/hdata/spira.c @@ -255,9 +255,8 @@ static struct dt_node *add_xscom_node(uint64_t base, uint32_t hw_id, uint64_t freq; switch (proc_gen) { - case proc_gen_p7: case proc_gen_p8: - /* On P7 and P8 all the chip SCOMs share single region */ + /* On P8 all the chip SCOMs share single region */ addr = base | ((uint64_t)hw_id << PPC_BITLSHIFT(28)); break; case proc_gen_p9: @@ -285,10 +284,6 @@ static struct dt_node *add_xscom_node(uint64_t base, uint32_t hw_id, dt_add_property(node, "scom-controller", NULL, 0); switch(proc_gen) { - case proc_gen_p7: - dt_add_property_strings(node, "compatible", - "ibm,xscom", "ibm,power7-xscom"); - break; case proc_gen_p8: dt_add_property_strings(node, "compatible", "ibm,xscom", "ibm,power8-xscom"); @@ -375,11 +370,6 @@ static void add_psihb_node(struct dt_node *np) /* PSI host bridge */ switch(proc_gen) { - case proc_gen_p7: - psi_scom = 0x2010c00; - psi_slen = 0x10; - psi_comp = "ibm,power7-psihb-x"; - break; case proc_gen_p8: psi_scom = 0x2010900; psi_slen = 0x20; @@ -635,72 +625,6 @@ static bool add_xscom_sppcrd(uint64_t xscom_base) return i > 0; } -static void add_xscom_sppaca(uint64_t xscom_base) -{ - const struct HDIF_common_hdr *hdif; - unsigned int i; - struct dt_node *np, *vpd_node; - - for_each_ntuple_idx(&spira.ntuples.paca, hdif, i, PACA_HDIF_SIG) { - const struct sppaca_cpu_id *id; - unsigned int chip_id, size; - int ve; - - /* We only suport old style PACA on P7 ! */ - assert(proc_gen == proc_gen_p7); - - id = HDIF_get_idata(hdif, SPPACA_IDATA_CPU_ID, &size); - - if (!CHECK_SPPTR(id)) { - prerror("XSCOM: Bad processor data %d\n", i); - continue; - } - - ve = be32_to_cpu(id->verify_exists_flags) & CPU_ID_VERIFY_MASK; - ve >>= CPU_ID_VERIFY_SHIFT; - if (ve == CPU_ID_VERIFY_NOT_INSTALLED || - ve == CPU_ID_VERIFY_UNUSABLE) - continue; - - /* Convert to HW chip ID */ - chip_id = P7_PIR2GCID(be32_to_cpu(id->pir)); - - /* do we already have an XSCOM for this chip? */ - if (find_xscom_for_chip(chip_id)) - continue; - - /* Create the XSCOM node */ - np = add_xscom_node(xscom_base, chip_id, - be32_to_cpu(id->processor_chip_id)); - if (!np) - continue; - - /* Add chip VPD */ - vpd_node = dt_add_vpd_node(hdif, SPPACA_IDATA_FRU_ID, - SPPACA_IDATA_KW_VPD); - if (vpd_node) - dt_add_property_cells(vpd_node, "ibm,chip-id", chip_id); - - /* Add chip associativity data */ - dt_add_property_cells(np, "ibm,ccm-node-id", - be32_to_cpu(id->ccm_node_id)); - if (size > SPIRA_CPU_ID_MIN_SIZE) { - dt_add_property_cells(np, "ibm,hw-card-id", - be32_to_cpu(id->hw_card_id)); - dt_add_property_cells(np, "ibm,hw-module-id", - be32_to_cpu(id->hardware_module_id)); - if (!dt_find_property(np, "ibm,dbob-id")) - dt_add_property_cells(np, "ibm,dbob-id", - be32_to_cpu(id->drawer_book_octant_blade_id)); - dt_add_property_cells(np, "ibm,mem-interleave-scope", - be32_to_cpu(id->memory_interleaving_scope)); - } - - /* Add PSI Host bridge */ - add_psihb_node(np); - } -} - static void add_xscom(void) { const void *ms_vpd; @@ -727,23 +651,12 @@ static void add_xscom(void) xscom_base = be64_to_cpu(pmbs->xscom_addr); - /* Some FSP (on P7) give me a crap base address for XSCOM (it has - * spurious bits set as far as I can tell). Since only 5 bits 18:22 can - * be programmed in hardware, let's isolate these. This seems to give - * me the right value on VPL1 - */ - if (cpu_type == PVR_TYPE_P7) - xscom_base &= 0x80003e0000000000ul; - /* Get rid of the top bits */ xscom_base = cleanup_addr(xscom_base); /* First, try the new proc_chip ntuples for chip data */ if (add_xscom_sppcrd(xscom_base)) return; - - /* Otherwise, check the old-style PACA, looking for unique chips */ - add_xscom_sppaca(xscom_base); } static void add_chiptod_node(unsigned int chip_id, int flags) @@ -766,9 +679,6 @@ static void add_chiptod_node(unsigned int chip_id, int flags) len = 0x34; switch(proc_gen) { - case proc_gen_p7: - compat_str = "ibm,power7-chiptod"; - break; case proc_gen_p8: compat_str = "ibm,power8-chiptod"; break; @@ -908,10 +818,6 @@ static void add_nx_node(u32 gcid) return; switch (proc_gen) { - case proc_gen_p7: - dt_add_property_strings(nx, "compatible", "ibm,power-nx", - "ibm,power7-nx"); - break; case proc_gen_p8: dt_add_property_strings(nx, "compatible", "ibm,power-nx", "ibm,power8-nx"); @@ -1314,24 +1220,6 @@ uint32_t pcid_to_chip_id(uint32_t proc_chip_id) return be32_to_cpu(cinfo->xscom_id); } - /* Otherwise, check the old-style PACA, looking for unique chips */ - for_each_ntuple_idx(&spira.ntuples.paca, hdif, i, PACA_HDIF_SIG) { - const struct sppaca_cpu_id *id; - - /* We only suport old style PACA on P7 ! */ - assert(proc_gen == proc_gen_p7); - - id = HDIF_get_idata(hdif, SPPACA_IDATA_CPU_ID, NULL); - - if (!CHECK_SPPTR(id)) { - prerror("XSCOM: Bad processor data %d\n", i); - continue; - } - - if (proc_chip_id == be32_to_cpu(id->processor_chip_id)) - return P7_PIR2GCID(be32_to_cpu(id->pir)); - } - /* Not found, what to do ? Assert ? For now return a number * guaranteed to not exist */ diff --git a/hdata/spira.h b/hdata/spira.h index 41159d2..09de4da 100644 --- a/hdata/spira.h +++ b/hdata/spira.h @@ -518,11 +518,6 @@ struct msvpd_pmover_bsr_synchro { #define MSVPD_PMS_FLAG_PMOVER_EN 0x40000000 #define MSVPD_PMS_FLAG_BSR_EN 0x20000000 #define MSVPD_PMS_FLAG_XSCOMBASE_VALID 0x10000000 - /* P7 values for BSR mode */ -#define MSVPD_PMS_FLAG_P7BSR_1M_MODE 0x00000000 -#define MSVPD_PMS_FLAG_P7BSR_2M_MODE 0x02000000 -#define MSVPD_PMS_FLAG_P7BSR_4M_MODE 0x04000000 -#define MSVPD_PMS_FLAG_P7BSR_8M_MODE 0x06000000 __be32 hwlocks_per_page; __be64 hwlock_addr; __be64 pmover_addr; @@ -655,7 +650,6 @@ struct cechub_io_hub { #define CECHUB_HUB_FAB_BR1_PDT_PHB4 0x08 /* p7ioc only */ #define CECHUB_HUB_FAB_BR1_PDT_PHB5 0x04 /* p7ioc only */ __be16 iohub_id; /* the type of hub */ -#define CECHUB_HUB_P7IOC 0x60e7 /* from VPL3 */ #define CECHUB_HUB_MURANO 0x20ef /* Murano from spec */ #define CECHUB_HUB_MURANO_SEGU 0x0001 /* Murano+Seguso from spec */ #define CECHUB_HUB_VENICE_WYATT 0x0010 /* Venice+Wyatt from spec */ diff --git a/hdata/test/hdata_to_dt.c b/hdata/test/hdata_to_dt.c index 5d30600..8692177 100644 --- a/hdata/test/hdata_to_dt.c +++ b/hdata/test/hdata_to_dt.c @@ -63,15 +63,11 @@ unsigned long tb_hz = 512000000; #define PVR_VERS_MIN(_pvr) GETFIELD(SPR_PVR_VERS_MIN, _pvr) /* PVR definitions - copied from skiboot include/processor.h */ -#define PVR_TYPE_P7 0x003f -#define PVR_TYPE_P7P 0x004a #define PVR_TYPE_P8E 0x004b #define PVR_TYPE_P8 0x004d #define PVR_TYPE_P8NVL 0x004c #define PVR_TYPE_P9 0x004e #define PVR_TYPE_P9P 0x004f -#define PVR_P7 0x003f0201 -#define PVR_P7P 0x004a0201 #define PVR_P8E 0x004b0201 #define PVR_P8 0x004d0200 #define PVR_P8NVL 0x004c0100 @@ -103,7 +99,7 @@ static inline struct cpu_job *cpu_queue_job(struct cpu_thread *cpu, } struct cpu_thread __boot_cpu, *boot_cpu = &__boot_cpu; -static unsigned long fake_pvr = PVR_P7; +static unsigned long fake_pvr = PVR_P8; static inline unsigned long mfspr(unsigned int spr) { @@ -186,7 +182,7 @@ void op_display(enum op_severity s, enum op_module m, uint16_t code) char __rodata_start[1], __rodata_end[1]; -enum proc_gen proc_gen = proc_gen_p7; +enum proc_gen proc_gen = proc_gen_p8; static bool spira_check_ptr(const void *ptr, const char *file, unsigned int line) { @@ -316,10 +312,6 @@ int main(int argc, char *argv[]) } else if (strcmp(argv[i], "-b") == 0) { blobs = true; opt_count++; - } else if (strcmp(argv[i], "-7") == 0) { - fake_pvr = PVR_P7; - proc_gen = proc_gen_p7; - opt_count++; } else if (strcmp(argv[i], "-8E") == 0) { fake_pvr = PVR_P8; proc_gen = proc_gen_p8; @@ -352,7 +344,6 @@ int main(int argc, char *argv[]) " -q Quiet mode\n" " -b Keep blobs in the output\n" "\n" - " -7 Force PVR to POWER7\n" " -8 Force PVR to POWER8\n" " -8E Force PVR to POWER8E\n" " -9 Force PVR to POWER9 (nimbus)\n" diff --git a/hw/Makefile.inc b/hw/Makefile.inc index 2885b50..e90f5cd 100644 --- a/hw/Makefile.inc +++ b/hw/Makefile.inc @@ -1,9 +1,8 @@ # -*-Makefile-*- SUBDIRS += hw -HW_OBJS = xscom.o chiptod.o gx.o cec.o lpc.o lpc-uart.o psi.o +HW_OBJS = xscom.o chiptod.o cec.o lpc.o lpc-uart.o psi.o HW_OBJS += homer.o slw.o occ.o fsi-master.o centaur.o imc.o HW_OBJS += nx.o nx-rng.o nx-crypto.o nx-compress.o nx-842.o nx-gzip.o -HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o prd.o HW_OBJS += dts.o lpc-rtc.o npu.o npu-hw-procedures.o xive.o phb4.o HW_OBJS += fake-nvram.o lpc-mbox.o npu2.o npu2-hw-procedures.o @@ -16,9 +16,9 @@ #include <skiboot.h> #include <cec.h> -#include <p7ioc.h> #include <interrupts.h> #include <opal-api.h> +#include <opal-internal.h> /* * Note: This file os only used on P7/P7+ diff --git a/hw/chiptod.c b/hw/chiptod.c index 668789e..a2eaf02 100644 --- a/hw/chiptod.c +++ b/hw/chiptod.c @@ -132,7 +132,6 @@ static enum chiptod_type { chiptod_unknown, - chiptod_p7, chiptod_p8, chiptod_p9 } chiptod_type; @@ -1647,8 +1646,6 @@ static bool chiptod_probe(void) if (dt_has_node_property(np, "primary", NULL)) { chiptod_primary = chip; - if (dt_node_is_compatible(np, "ibm,power7-chiptod")) - chiptod_type = chiptod_p7; if (dt_node_is_compatible(np, "ibm,power8-chiptod")) chiptod_type = chiptod_p8; if (dt_node_is_compatible(np, "ibm,power9-chiptod")) @@ -38,67 +38,6 @@ enum { SENSOR_DTS_ATTR_TEMP_TRIP }; -/* Different sensor locations */ -#define P7_CT_ZONE_LSU 0 -#define P7_CT_ZONE_ISU 1 -#define P7_CT_ZONE_IFU 2 -#define P7_CT_ZONE_VFU 3 -#define P7_CT_ZONE_L3C 4 -#define P7_CT_ZONES 5 - -/* Per core Digital Thermal Sensors */ -#define EX_THERM_P7_DTS_RESULT0 0x8050000 -#define EX_THERM_P7_DTS_RESULT1 0x8050001 - -/* - * DTS2 Thermal Sensor Results - * - * 0..7 sensor with id 0. - * 8..15 sensor with id 1. (Only chiplets) - * 16..23 sensor with id 2. (Only chiplets) - * 24..31 sensor with id 3. (Only chiplets) - * 32..39 sensor with id 4. (Only chiplets) - * 40..56 reserved0 - * 57 Trip warning history - * 58 Trip critical history - * 59 Trip fatal history - * 60 reserved1 - * 61..63 ID of worst case DTS2 (Only valid in EX core chiplets) - */ -static int dts_read_core_temp_p7(uint32_t pir, struct dts *dts) -{ - int32_t chip_id = pir_to_chip_id(pir); - int32_t core = pir_to_core_id(pir); - uint64_t dts0; - struct dts temps[P7_CT_ZONES]; - int i; - int rc; - - rc = xscom_read(chip_id, - XSCOM_ADDR_P8_EX(core, EX_THERM_P7_DTS_RESULT0), - &dts0); - if (rc) - return rc; - - temps[P7_CT_ZONE_LSU].temp = (dts0 >> 56) & 0xff; - temps[P7_CT_ZONE_ISU].temp = (dts0 >> 48) & 0xff; - temps[P7_CT_ZONE_IFU].temp = (dts0 >> 40) & 0xff; - temps[P7_CT_ZONE_VFU].temp = (dts0 >> 32) & 0xff; - temps[P7_CT_ZONE_L3C].temp = (dts0 >> 24) & 0xff; - - /* keep the max DTS */ - for (i = 0; i < P7_CT_ZONES; i++) { - int16_t t = temps[i].temp; - if (t > dts->temp) - dts->temp = t; - } - dts->trip = (dts0 >> 3) & 0xf; - - prlog(PR_TRACE, "DTS: Chip %x Core %x temp:%dC trip:%x\n", - chip_id, core, dts->temp, dts->trip); - - return 0; -} /* Therm mac result masking for DTS (result(0:15) * 0:3 - 0x0 @@ -271,9 +210,6 @@ static int dts_read_core_temp(u32 pir, struct dts *dts, u8 attr, int rc; switch (proc_gen) { - case proc_gen_p7: - rc = dts_read_core_temp_p7(pir, dts); - break; case proc_gen_p8: rc = dts_read_core_temp_p8(pir, dts); break; diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c index 8fe2aed..aa393c7 100644 --- a/hw/fsp/fsp.c +++ b/hw/fsp/fsp.c @@ -29,7 +29,6 @@ #include <fsp.h> #include <lock.h> #include <interrupts.h> -#include <gx.h> #include <device.h> #include <trace.h> #include <timebase.h> diff --git a/hw/gx.c b/hw/gx.c deleted file mode 100644 index 12cea5b..0000000 --- a/hw/gx.c +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <skiboot.h> -#include <gx.h> -#include <xscom.h> - -/* - * Note: This file os only used on P7/P7+ - */ - -/* Configuration of the PSI BUID, see the explanation in - * interrupts.h - */ -static int gx_p7_configure_psi_buid(uint32_t chip, uint32_t buid) -{ - uint64_t mode1; - int rc; - - rc = xscom_read(chip, GX_P7_MODE1_REG, &mode1); - if (rc) { - prerror("GX: XSCOM error %d reading GX MODE1 REG\n", rc); - return rc; - } - - mode1 = SETFIELD(GX_P7_MODE1_PSI_BUID, mode1, buid); - mode1 &= ~GX_P7_MODE1_PSI_BUID_DISABLE; - - printf("GX: MODE1_REG set to 0x%llx\n", mode1); - rc = xscom_write(chip, GX_P7_MODE1_REG, mode1); - if (rc) { - prerror("GX: XSCOM error %d writing GX MODE1 REG\n", rc); - return rc; - } - - return 0; -} - -static int gx_p7p_configure_psi_buid(uint32_t chip, uint32_t buid) -{ - uint64_t mode4; - int rc; - - rc = xscom_read(chip, GX_P7P_MODE4_REG, &mode4); - if (rc) { - prerror("GX: XSCOM error %d reading GX MODE1 REG\n", rc); - return rc; - } - - mode4 = SETFIELD(GX_P7P_MODE4_PSI_BUID, mode4, buid); - mode4 &= ~GX_P7P_MODE4_PSI_BUID_DISABLE; - - rc = xscom_write(chip, GX_P7P_MODE4_REG, mode4); - if (rc) { - prerror("GX: XSCOM error %d writing GX MODE1 REG\n", rc); - return rc; - } - - return 0; -} - -/* Configure the BUID of the PSI interrupt in the GX - * controller. - * - * @chip: Chip number (0..31) - * @buid: 9-bit BUID value - */ -int gx_configure_psi_buid(uint32_t chip, uint32_t buid) -{ - uint32_t pvr = mfspr(SPR_PVR); - - printf("GX: PSI BUID for PVR %x (type %x) chip %d BUID 0x%x\n", - pvr, PVR_TYPE(pvr), chip, buid); - - switch (PVR_TYPE(pvr)) { - case PVR_TYPE_P7: - return gx_p7_configure_psi_buid(chip, buid); - case PVR_TYPE_P7P: - return gx_p7p_configure_psi_buid(chip, buid); - } - return -1; -} - - -static int gx_p7_configure_tce_bar(uint32_t chip, uint32_t gx, uint64_t addr, - uint64_t size) -{ - uint32_t areg, mreg; - int rc; - - switch (gx) { - case 0: - areg = GX_P7_GX0_TCE_BAR; - mreg = GX_P7_GX0_TCE_MASK; - break; - case 1: - areg = GX_P7_GX1_TCE_BAR; - mreg = GX_P7_GX1_TCE_MASK; - break; - default: - return -EINVAL; - } - - if (addr) { - uint64_t taddr, tmask; - - /* The address field contains bits 18 to 43 of the address */ - taddr = SETFIELD(GX_P7_TCE_BAR_ADDR, 0ul, - (addr >> GX_P7_TCE_BAR_ADDR_SHIFT)); - taddr |= GX_P7_TCE_BAR_ENABLE; - tmask = SETFIELD(GX_P7_TCE_MASK, 0ul, - ~((size - 1) >> GX_P7_TCE_BAR_ADDR_SHIFT)); - rc = xscom_write(chip, areg, 0); - rc |= xscom_write(chip, mreg, tmask); - rc |= xscom_write(chip, areg, taddr); - } else { - rc = xscom_write(chip, areg, 0); - } - return rc ? -EIO : 0; -} - -/* Configure the TCE BAR of a given GX bus - * - * @chip: Chip number (0..31) - * @gx : GX bus index - * @addr: base address of TCE table - * @size: size of TCE table - */ -int gx_configure_tce_bar(uint32_t chip, uint32_t gx, uint64_t addr, - uint64_t size) -{ - uint32_t pvr = mfspr(SPR_PVR); - - printf("GX: TCE BAR for PVR %x (type %x) chip %d gx %d\n", - pvr, PVR_TYPE(pvr), chip, gx); - - /* We only support P7... is there a P7+ with P5IOC2 ? */ - switch (PVR_TYPE(pvr)) { - case PVR_TYPE_P7: - return gx_p7_configure_tce_bar(chip, gx, addr, size); - } - return -EINVAL; -} - - diff --git a/hw/nx-842.c b/hw/nx-842.c index 8009f03..d4abe08 100644 --- a/hw/nx-842.c +++ b/hw/nx-842.c @@ -191,11 +191,7 @@ void nx_enable_842(struct dt_node *node, u32 gcid, u32 pb_base) u64 cfg_dma, cfg_842, cfg_ee; int rc; - if (dt_node_is_compatible(node, "ibm,power7-nx")) { - cfg_dma = pb_base + NX_P7_DMA_CFG; - cfg_842 = pb_base + NX_P7_842_CFG; - cfg_ee = pb_base + NX_P7_EE_CFG; - } else if (dt_node_is_compatible(node, "ibm,power8-nx")) { + if (dt_node_is_compatible(node, "ibm,power8-nx")) { cfg_dma = pb_base + NX_P8_DMA_CFG; cfg_842 = pb_base + NX_P8_842_CFG; cfg_ee = pb_base + NX_P8_EE_CFG; diff --git a/hw/nx-crypto.c b/hw/nx-crypto.c index 769112f..04cc789 100644 --- a/hw/nx-crypto.c +++ b/hw/nx-crypto.c @@ -38,10 +38,10 @@ #define AMF_COMPLETION_MODE NX_DMA_COMPLETION_MODE_PDMA #define AMF_CPB_WR (0) /* CPB WR not done with AMF */ #define AMF_OUTPUT_DATA_WR NX_DMA_OUTPUT_DATA_WR_DMA -#define EE_CH7 (0) /* disable engine AMF 2(P7) / 3(P8) */ -#define EE_CH6 (0) /* disable engine AMF 1(P7) / 2(P8) */ -#define EE_CH5 (0) /* disable engine AMF 0(P7) / 1(P8) */ -#define EE_CH4 (0) /* disable engine SYM 2(P7) / AMF 0(P8) */ +#define EE_CH7 (0) /* disable engine AMF 3(P8) */ +#define EE_CH6 (0) /* disable engine AMF 2(P8) */ +#define EE_CH5 (0) /* disable engine AMF 1(P8) */ +#define EE_CH4 (0) /* disable engine SYM AMF 0(P8) */ #define EE_CH3 (0) /* disable engine SYM 1 */ #define EE_CH2 (0) /* disable engine SYM 0 */ @@ -268,13 +268,7 @@ void nx_create_crypto_node(struct dt_node *node) prlog(PR_INFO, "NX%d: Crypto at 0x%x\n", gcid, pb_base); - if (dt_node_is_compatible(node, "ibm,power7-nx")) { - cfg_dma = pb_base + NX_P7_DMA_CFG; - cfg_sym = pb_base + NX_P7_SYM_CFG; - cfg_asym = pb_base + NX_P7_ASYM_CFG; - cfg_iq = pb_base + NX_P7_CRB_IQ; - cfg_ee = pb_base + NX_P7_EE_CFG; - } else if (dt_node_is_compatible(node, "ibm,power8-nx")) { + if (dt_node_is_compatible(node, "ibm,power8-nx")) { cfg_dma = pb_base + NX_P8_DMA_CFG; cfg_sym = pb_base + NX_P8_SYM_CFG; cfg_asym = pb_base + NX_P8_ASYM_CFG; diff --git a/hw/nx-rng.c b/hw/nx-rng.c index c0c90f5..d2fc7a3 100644 --- a/hw/nx-rng.c +++ b/hw/nx-rng.c @@ -58,11 +58,7 @@ void nx_create_rng_node(struct dt_node *node) gcid = dt_get_chip_id(node); pb_base = dt_get_address(node, 0, NULL); - if (dt_node_is_compatible(node, "ibm,power7-nx")) { - xbar = pb_base + NX_P7_RNG_BAR; - xcfg = pb_base + NX_P7_RNG_CFG; - addr_mask = NX_P7_RNG_BAR_ADDR; - } else if (dt_node_is_compatible(node, "ibm,power8-nx")) { + if (dt_node_is_compatible(node, "ibm,power8-nx")) { xbar = pb_base + NX_P8_RNG_BAR; xcfg = pb_base + NX_P8_RNG_CFG; addr_mask = NX_P8_RNG_BAR_ADDR; diff --git a/hw/p7ioc-inits.c b/hw/p7ioc-inits.c deleted file mode 100644 index 0d50694..0000000 --- a/hw/p7ioc-inits.c +++ /dev/null @@ -1,1096 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This inits are in part auto-generated from tables coming - * from the HW guys, then hand updated - */ -#include <skiboot.h> -#include <p7ioc.h> -#include <p7ioc-regs.h> -#include <io.h> -#include <processor.h> -#include <timebase.h> - -#undef DUMP_CI_ROUTING -#undef DUMP_REG_WRITES - -#ifdef DUMP_REG_WRITES -#define REGW(offset, value) do { \ - out_be64(ioc->regs + (offset), (value)); \ - printf(" REGW: %06lx=%016lx RB: %016llx\n", \ - (unsigned long)(offset), \ - (unsigned long)(value), \ - in_be64(ioc->regs + (offset))); \ - in_be64(ioc->regs + (offset)); \ - } while(0) -#else -#define REGW(offset, value) do { \ - out_be64(ioc->regs + (offset), (value)); \ - in_be64(ioc->regs + (offset)); \ - } while(0) -#endif -#define REGR(offset) in_be64(ioc->regs + (offset)) - -static void p7ioc_init_BI(struct p7ioc *ioc) -{ - printf("P7IOC: Init BI...\n"); - - /*** General settings ***/ - - /* Init_1 and Init_2: Different between P7 and P7+ */ - if (PVR_TYPE(mfspr(SPR_PVR)) == PVR_TYPE_P7P) { - printf("P7IOC: -> Configured for P7+\n"); - - /* Chicken switches */ - REGW(0x3c00d8, 0x0004000000000600UL); - /* GX config */ - REGW(0x3c00a0, 0x9F8929BE00880085UL); - } else { - printf("P7IOC: -> Configured for P7\n"); - - /* P7 setting assumes "early write done" mode is - * enabled in the GX controller. It seems to be - * the case but maybe we want to check/set it via - * xscom ? - */ - /* Chicken switches */ - REGW(0x3c00d8, 0x00040000000004C0UL); - /* GX config */ - REGW(0x3c00a0, 0x9C8929BE00880085UL); - } - - /* - * Note: While running skiboot on Firebird-L, I have - * to print something or wait for a while. The root - * cause wasn't identified yet. - */ - time_wait_ms(100); - - /* Init_3: Upbound Credit Config */ - REGW(0x3c00c8, 0x0303060403030000UL); - /* Init_4: Credit Init Timer */ - REGW(0x3c00e8, 0x00000000000000FFUL); - - /* Init_4.1: BI Ack Timing */ - REGW(0x3c00e8, 0x0000FC0000000000UL); - /* Init_5: Ordering Override 0*/ - REGW(0x3c0200, 0x0000000000000000UL); - /* Init_6: Ordering Override 1*/ - REGW(0x3c0208, 0x0000000000000000UL); - - /*** Downbound TTYPE table ***/ - - /* Init_7: Enable sequence / speculation for CI Loads */ - REGW(0x3c00a8, 0x0000000000000004UL); - /* Init_8: */ - REGW(0x3c00b0, 0x700800C000000000UL); - /* Init_9: Enable sequence / speculation for CI Stores */ - REGW(0x3c00a8, 0x0000000000000005UL); - /* Init_10: */ - REGW(0x3c00b0, 0x704820C000000000UL); - /* Init_11: Enable speculation for EOI */ - REGW(0x3c00a8, 0x000000000000001BUL); - /* Init_12: */ - REGW(0x3c00b0, 0x3590204000000000UL); - /* Init_13: ENable speculation for DMA Rd Responses */ - REGW(0x3c00a8, 0x0000000000000020UL); - /* Init_14: */ - REGW(0x3c00b0, 0x1103C4C000000000UL); - /* Init_15: Enable sequence for DMA RWNITC */ - REGW(0x3c00a8, 0x0000000000000001UL); - /* Init_16: */ - REGW(0x3c00b0, 0xC000000000000000UL); - /* Init_17: Enable sequence for IOKill */ - REGW(0x3c00a8, 0x0000000000000009UL); - /* Init_18: */ - REGW(0x3c00b0, 0x4208210000000000UL); - /* Init_19: Enable sequence for IOKill */ - REGW(0x3c00a8, 0x000000000000000AUL); - /* Init_20: */ - REGW(0x3c00b0, 0x4200210000000000UL); - /* Init_21: Enable sequence for FMTC CI Store w/Kill */ - REGW(0x3c00a8, 0x0000000000000021UL); - - /*** Timer controls ***/ - - /* Init_22: */ - REGW(0x3c00b0, 0x4200300000000000UL); - /* Init_23: Dnbound timer mask */ - REGW(0x3c0190, 0x0040000000000000UL); - /* Init_24: Upbound timer mask 0 */ - REGW(0x3c0180, 0x0010001000100010UL); - /* Init_25: Upbound timer mask 1 */ - REGW(0x3c0188, 0x0010000000000000UL); - /* Init_26: Credit sync check config */ - REGW(0x3c00f0, 0xC102000000000000UL); - - /*** Setup trace ***/ - - /* Init_27: DBG stop trace */ - REGW(0x3c0410, 0x4000000000000000UL); - /* Init_28: DBG control */ - REGW(0x3c0400, 0x0000000000000000UL); - /* Init_29: DBG Mode */ - REGW(0x3c0408, 0xA0000000F0CC3300UL); - /* Init_29a: DBG C0 (Stop on Error) */ - REGW(0x3c0418, 0xF4F00FFF00000000UL); - /* Init_30: DBG pre-mux select */ - REGW(0x3c0478, 0x0023000000000000UL); - /* Init_31: CA0 mode */ - REGW(0x3c04b0, 0x8000000000000000UL); - /* Init_32: CA0 Compression 0 */ - REGW(0x3c04b8, 0x0000000000000000UL); - /* Init_33: CA0 Compression 1 */ - REGW(0x3c04c0, 0x0000000000000000UL); - /* Init_34: CA0 Pattern A march (cmd1 selected val) */ - REGW(0x3c0480, 0x008000007FFFFF00UL); - /* Init_35: CA0 Trigger 0 definition (pattern A) */ - REGW(0x3c04a0, 0x8000000000000000UL); - /* Init_36: CA1 mode */ - REGW(0x3c0530, 0x8000000000000000UL); - /* Init_37: CA1 Compression 0 */ - REGW(0x3c0538, 0x0000000000000000UL); - /* Init_38: CA1 Compression 1 */ - REGW(0x3c0540, 0x0000000000000000UL); - /* Init_39: CA2 mode */ - REGW(0x3c05b0, 0x8000000000000000UL); - /* Init_40: CA2 Compression 0 */ - REGW(0x3c05b8, 0x0000000000000000UL); - /* Init_41: CA2 Compression 1 */ - REGW(0x3c05c0, 0x0000000000000000UL); - /* Init_42: CA3 Mode */ - REGW(0x3c0630, 0x8000000000000000UL); - /* Init_43: CA3 Compression 0 */ - REGW(0x3c0638, 0x0000000000000000UL); - /* Init_44: CA3 Compression 1 */ - REGW(0x3c0640, 0x0000000000000000UL); - /* Init_45: CA3 Pattern A match (AIB val) */ - REGW(0x3c0600, 0x80000100FFFEFF00UL); - /* Init_46: CA3 Trigger 0 definition (pattern A) */ - REGW(0x3c0620, 0x8000000000000000UL); - /* Init_47: DBG unfreeze trace */ - REGW(0x3c0410, 0x1000000000000000UL); - /* Init_48: DBG start trace */ - REGW(0x3c0410, 0x8000000000000000UL); - - /*** AIB Port Config ***/ - - /* Init_49: AIB Port Information */ - REGW(0x3c00d0, 0x0888888800000000UL); - /* Init_50: Port Ordering controls */ - REGW(0x3c0200, 0x0000000000000000UL); - - /*** LEMs (need to match recov. tables) ***/ - - /* Init_51: Clear upbound LEM */ - REGW(0x3c0000, 0x0000000000000000UL); - /* Init_52: Clear upbound WOF */ - REGW(0x3c0040, 0x0000000000000000UL); - /* Init_53: Clear Dnbound LEM */ - REGW(0x3c0050, 0x0000000000000000UL); - /* Init_54: Clear Dnbound WOF */ - REGW(0x3c0090, 0x0000000000000000UL); - /* Init_55: Clear Fences */ - REGW(0x3c0130, 0x0000000000000000UL); - /* Init_56: Clear Erpt latches */ - REGW(0x3c0148, 0x0080000000000000UL); - /* Init_57: Set Upbound LEM Action0 */ - REGW(0x3c0030, 0x0800000000800000UL); - /* Init_58: Set Upbound LEN Action1 */ - REGW(0x3c0038, 0x0000000000000000UL); - /* Init_59: Set Upbound LEM Mask (AND write) */ - REGW(0x3c0020, 0x0800000000000000UL); - /* Init_60: Set Dnbound LEM Action0 */ - REGW(0x3c0080, 0x2000080CA07FFF40UL); - /* Init_61: Set Dnbound LEM Action1 */ - REGW(0x3c0088, 0x0000000000000000UL); - /* Init_62: Set Dnbound LEM Mask (AND write) */ - REGW(0x3c0070, 0x00000800200FFE00UL); - - /*** Setup Fences (need to match recov. tables) ***/ - - /* Init_63: Set Upbound Damage Control 0 (GX Err) */ - REGW(0x3c0100, 0xF7FFFFFFFF7FFFFFUL); - /* Init_64: Set Upbound Damage Control 1 (AIB Fence) */ - REGW(0x3c0108, 0xF7FFFFFFFF7FFFFFUL); - /* Init_65: Set Upbound Damage Control 2 (Drop Pkt) */ - REGW(0x3c0110, 0x0010054000000000UL); - /* Init_66: Set Dnbound Damage Control 0 (GX Err) */ - REGW(0x3c0118, 0xDFFFF7F35F8000BFUL); - /* Init_67: Set Dnbound Damage Control 1 (AIB Fence) */ - REGW(0x3c0120, 0xDFFFF7F35F8000BFUL); - /* Init_68: Set Dnbound Damage Control 2 (Drop Pkt) */ - REGW(0x3c0128, 0x0000000C00000000UL); -} - -static void p7ioc_init_MISC_HSS(struct p7ioc *ioc) -{ - unsigned int i, regbase; - - printf("P7IOC: Init HSS...\n"); - - /* Note: These values might need to be tweaked per system and - * per physical port depending on electrical characteristics. - * - * For now we stick to the defaults provided by the spec. - */ - for (i = 0; i < P7IOC_NUM_PHBS; i++) { - regbase = P7IOC_HSS_BASE + i * P7IOC_HSS_STRIDE; - - if (!p7ioc_phb_enabled(ioc, i)) - continue; - - /* Init_1: HSSn CTL2 */ - REGW(regbase + P7IOC_HSSn_CTL2_OFFSET, 0xFFFF6DB6DB000000UL); - /* Init_2: HSSn CTL3 */ - REGW(regbase + P7IOC_HSSn_CTL3_OFFSET, 0x1130000320000000UL); - /* Init_3: HSSn CTL8 */ - REGW(regbase + P7IOC_HSSn_CTL8_OFFSET, 0xDDDDDDDD00000000UL); - -#if 0 /* All these remain set to the values configured by the FSP */ - /* Init_4: HSSn CTL9 */ - REGW(regbase + P7IOC_HSSn_CTL9_OFFSET, 0x9999999900000000); - /* Init_5: HSSn CTL10 */ - REGW(regbase + P7IOC_HSSn_CTL10_OFFSET, 0x8888888800000000); - /* Init_6: HSSn CTL11 */ - REGW(regbase + P7IOC_HSSn_CTL11_OFFSET, 0x4444444400000000); - /* Init_7: HSSn CTL12 */ - REGW(regbase + P7IOC_HSSn_CTL12_OFFSET, 0x3333333300000000); - /* Init_8: HSSn CTL13 */ - REGW(regbase + P7IOC_HSSn_CTL13_OFFSET, 0x2222222200000000); - /* Init_9: HSSn CTL14 */ - REGW(regbase + P7IOC_HSSn_CTL14_OFFSET, 0x1111111100000000); - /* Init_10: HSSn CTL15 */ - REGW(regbase + P7IOC_HSSn_CTL15_OFFSET, 0x1111111100000000); - /* Init_11: HSSn CTL16 */ - REGW(regbase + P7IOC_HSSn_CTL16_OFFSET, 0x9999999900000000); - /* Init_12: HSSn CTL17 */ - REGW(regbase + P7IOC_HSSn_CTL17_OFFSET, 0x8888888800000000); - /* Init_13: HSSn CTL18 */ - REGW(regbase + P7IOC_HSSn_CTL18_OFFSET, 0xDDDDDDDD00000000); - /* Init_14: HSSn CTL19 */ - REGW(regbase + P7IOC_HSSn_CTL19_OFFSET, 0xCCCCCCCC00000000); - /* Init_15: HSSn CTL20 */ - REGW(regbase + P7IOC_HSSn_CTL20_OFFSET, 0xBBBBBBBB00000000); - /* Init_16: HSSn CTL21 */ - REGW(regbase + P7IOC_HSSn_CTL21_OFFSET, 0x9999999900000000); - /* Init_17: HSSn CTL22 */ - REGW(regbase + P7IOC_HSSn_CTL22_OFFSET, 0x8888888800000000); - /* Init_18: HSSn CTL23 */ - REGW(regbase + P7IOC_HSSn_CTL23_OFFSET, 0x7777777700000000); -#endif - } -} - -static void p7ioc_init_RGC(struct p7ioc *ioc) -{ - unsigned int i; - uint64_t val, cfg; - - printf("P7IOC: Init RGC...\n"); - - /*** Clear ERPT Macros ***/ - - /* Init_1: RGC Configuration reg */ - cfg = REGR(0x3e1c08); - REGW(0x3e1c08, cfg | PPC_BIT(1)); - time_wait_ms(1); - - /* Init_2: RGC Configuration reg */ - REGW(0x3e1c08, cfg); - - /*** Set LEM regs (needs to match recov. code) */ - - /* Init_3: LEM FIR Accumulator */ - REGW(0x3e1e00, 0x0000000000000000UL); - /* Init_4: LEM Action 0 */ - REGW(0x3e1e30, 0x0FFF791F0B030000UL); - /* Init_5: LEN Action 1 */ - REGW(0x3e1e38, 0x0000000000000000UL); - /* Init_6: LEM WOF */ - REGW(0x3e1e40, 0x0000000000000000UL); - /* Init_7: LEM Mask Reg (AND write) */ - REGW(0x3e1e20, 0x0FFF001F03030000UL); - - /*** Set GEM regs (masks still on, no irpts can occur yet) ***/ - - /* Init_8: GEM XFIR */ - REGW(0x3e0008, 0x0000000000000000UL); - /* Init_9: GEM WOF */ - REGW(0x3e0028, 0x0000000000000000UL); - - /*** Set Damage Controls (needs to match recov.) ***/ - - /* Init_10: LDCP */ - REGW(0x3e1c18, 0xF00086C0B4FCFFFFUL); - - /*** Read status (optional) ***/ - - /* Init_11: Read status */ - val = REGR(0x3e1c10); - printf("P7IOC: Init_11 Status: %016llx\n", val); - - /*** Set running configuration **/ - - /* Init_12: Configuration reg (modes, values, timers) */ - REGW(0x3e1c08, 0x10000077CE100000UL); - - /* Init_13: Cmd/Dat Crd Allocation */ - REGW(0x3e1c20, 0x00000103000700FFUL); - /* Init_14: GP reg - disable errs, wrap, stop_trc */ - REGW(0x3e1018, 0x0000000000000000UL); - /* Init_15: Configuration reg (start init timers) */ - cfg = REGR(0x3e1c08); - REGW(0x3e1c08, cfg | 0x00003f0000000000UL); - - /*** Setup interrupts ***/ - - /* Init_16: BUID Register - * - * XXX NOTE: This needs to be clarified. According to the doc - * the register contains a 9-bit BUID, which makes sense so far. - * - * However, the initialization sequence says "depends on which - * GX bus) which doesn't since afaik the GX bus number is encoded - * in the BUID Extension bit which is right *above* the 9-bit - * BUID in the interrupt message. - * - * So I must be missing something here... For now I'll just - * write my 9-bit BUID and we'll see what happens. - * - */ - REGW(0x3e1800, (uint64_t)ioc->rgc_buid << PPC_BITLSHIFT(31)); - - /* Init_17: Supposed to lock the IODA table but we aren't racing - * with anybody so there is little point. - * - * Note: If/when we support some kind of error recovery that - * involves re-initializing the IOC, then we might have - * to take some locks but it's assumed that the necessary - * lock(s) will be obtained by the caller. - */ - //REGR(0x3e1840, 0x0000000000000000); - - /* Init_18: IODA Table Addr: Select IST*/ - REGW(0x3e1820, 0x8001000000000000UL); - /* Init_19: IODA Table Data: IRPT 0 */ - REGW(0x3e1830, 0x0000000000000000UL); - /* Init_20: IODA Table Data: IRPT 1 */ - REGW(0x3e1830, 0x0000000000000000UL); - /* Init_21: IODA Table Addr: Select HRT */ - REGW(0x3e1820, 0x8000000000000000UL); - /* Init_22: IODA Table Data: HRT - * - * XXX Figure out what this actually is and what value should - * we use. For now, do like BML and use 0 - */ - for (i = 0; i < 4; i++) - REGW(0x3e1830, 0x0000000000000000UL); - - /* Init_23: IODA Table Addr: select XIVT */ - REGW(0x3e1820, 0x8002000000000000UL); - /* Init_24: IODA Table Data: Mask all interrupts */ - for (i = 0; i < 16; i++) - REGW(0x3e1830, 0x000000ff00000000UL); - - /* Init_25: Clear table lock if any was stale */ - REGW(0x3e1840, 0x0000000000000000UL); - - /* Init_32..37: Set the PHB AIB addresses. We configure those - * to the values recommended in the p7IOC doc. - * - * XXX NOTE: I cannot find a documentation for these, I assume - * they just take the full 64-bit address, but we may want to - * dbl check just in case (it seems to be what BML does but - * I'm good at mis-reading Milton's Perl). - */ - for (i = 0; i < P7IOC_NUM_PHBS; i++) { - if (!p7ioc_phb_enabled(ioc, i)) - continue; - REGW(0x3e1080 + (i << 3), - ioc->mmio1_win_start + PHBn_AIB_BASE(i)); - } -} - -static void p7ioc_init_ci_routing(struct p7ioc *ioc) -{ - unsigned int i, j = 0; - uint64_t rmatch[47]; - uint64_t rmask[47]; - uint64_t pmask; - - /* Init_130: clear all matches (except 47 which routes to the RGC) */ - for (i = 0; i < 47; i++) { - rmatch[i] = REGR(P7IOC_CI_RMATC_REG(i)) & - ~(P7IOC_CI_RMATC_ADDR_VALID | - P7IOC_CI_RMATC_BUID_VALID | - P7IOC_CI_RMATC_TYPE_VALID); - rmask[i] = 0; - REGW(P7IOC_CI_RMATC_REG(i), rmatch[i]); - } - - /* Init_131...224: configure routing for everything except RGC - * - * We are using a slightly different routing setup than the - * example to make the code easier. We configure all PHB - * routing entries by doing all of PHB0 first, then all of PHB1 - * etc... - * - * Then we append everything else except the RGC itself which - * remains hard wired at entry 47. So the unused entries live - * at 39..46. - * - * - 0 : PHB0 LSI BUID - * - 1 : PHB0 MSI BUID - * - 2 : PHB0 AIB Registers - * - 3 : PHB0 IO Space - * - 4 : PHB0 M32 Space - * - 5 : PHB0 M64 Space - * - 6..11 : PHB1 - * - 12..17 : PHB2 - * - 18..23 : PHB3 - * - 24..29 : PHB4 - * - 30..35 : PHB5 - * - 36 : Invalidates broadcast (FMTC) - * - 37 : Interrupt response for RGC - * - 38 : RGC GEM BUID - * - 39..46 : Unused (alternate M64 ?) - * - 47 : RGC ASB Registers (catch all) - */ - - /* Helper macro to set a rule */ -#define CI_ADD_RULE(p, k, d, m) do { \ - rmask[j] = P7IOC_CI_RMATC_ENCODE_##k(m); \ - rmatch[j]= P7IOC_CI_RMATC_PORT(p) | \ - P7IOC_CI_RMATC_##k##_VALID | \ - P7IOC_CI_RMATC_ENCODE_##k(d); \ - j++; \ - } while (0) - - pmask = 0; - for (i = 0; i < P7IOC_NUM_PHBS; i++) { - unsigned int buid_base = ioc->buid_base + PHBn_BUID_BASE(i); - - if (!p7ioc_phb_enabled(ioc, i)) - continue; - - /* LSI BUIDs, match all 9 bits (1 BUID per PHB) */ - CI_ADD_RULE(P7IOC_CI_PHB_PORT(i), BUID, - buid_base + PHB_BUID_LSI_OFFSET, 0x1ff); - - /* MSI BUIDs, match 4 bits (16 BUIDs per PHB) */ - CI_ADD_RULE(P7IOC_CI_PHB_PORT(i), BUID, - buid_base + PHB_BUID_MSI_OFFSET, 0x1f0); - - /* AIB reg space */ - CI_ADD_RULE(P7IOC_CI_PHB_PORT(i), ADDR, - ioc->mmio1_win_start + PHBn_AIB_BASE(i), - ~(PHBn_AIB_SIZE - 1)); - - /* IO space */ - CI_ADD_RULE(P7IOC_CI_PHB_PORT(i), ADDR, - ioc->mmio1_win_start + PHBn_IO_BASE(i), - ~(PHB_IO_SIZE - 1)); - - /* M32 space */ - CI_ADD_RULE(P7IOC_CI_PHB_PORT(i), ADDR, - ioc->mmio2_win_start + PHBn_M32_BASE(i), - ~(PHB_M32_SIZE - 1)); - - /* M64 space */ - CI_ADD_RULE(P7IOC_CI_PHB_PORT(i), ADDR, - ioc->mmio2_win_start + PHBn_M64_BASE(i), - ~(PHB_M64_SIZE - 1)); - - /* For use with invalidate bcasts */ - pmask |= P7IOC_CI_PHB_PORT(i); - } - - /* Invalidates broadcast to all PHBs */ - CI_ADD_RULE(pmask, TYPE, 0x80, 0xf0); - - /* Interrupt responses go to RGC */ - CI_ADD_RULE(P7IOC_CI_RGC_PORT, TYPE, 0x60, 0xf0); - - /* RGC GEM BUID (1 BUID) */ - CI_ADD_RULE(P7IOC_CI_RGC_PORT, BUID, ioc->rgc_buid, 0x1ff); - - /* Program the values masks first */ - for (i = 0; i < 47; i++) - REGW(P7IOC_CI_RMASK_REG(i), rmask[i]); - for (i = 0; i < 47; i++) - REGW(P7IOC_CI_RMATC_REG(i), rmatch[i]); - - /* Init_225: CI Match 47 (Configure RGC catch all) */ - REGW(P7IOC_CI_RMASK_REG(47), 0x0000000000000000UL); - REGW(P7IOC_CI_RMATC_REG(47), 0x4000800000000000UL); - -#ifdef DUMP_CI_ROUTING - printf("P7IOC: CI Routing table:\n"); - for (i = 0; i < 48; i++) - printf(" [%.2d] MTCH: %016llx MSK: %016llx\n", i, - REGR(P7IOC_CI_RMATC_REG(i)), - REGR(P7IOC_CI_RMASK_REG(i))); -#endif /* DUMP_CI_ROUTING */ -} - -static void p7ioc_init_CI(struct p7ioc *ioc) -{ - printf("P7IOC: Init CI...\n"); - - /*** Clear ERPT macros ***/ - - /* XXX NOTE: The doc seems to also provide "alternate freq ratio" - * settings. Not sure what they are about, let's stick to the - * original values for now. - */ - - /* Init_1: CI Port 0 Configuration */ - REGW(0x3d0000, 0x420000C0073F0002UL); - /* Init_2: CI Port 0 Configuration */ - REGW(0x3d0000, 0x020000C0073F0002UL); - /* Init_3: CI Port 1 Configuration */ - REGW(0x3d1000, 0x42000FCF07200002UL); - /* Init_4: CI Port 1 Configuration */ - REGW(0x3d1000, 0x02000FCF07200002UL); - /* Init_5: CI Port 2 Configuration */ - REGW(0x3d2000, 0x420000C307200002UL); - /* Init_6: CI Port 2 Configuration */ - REGW(0x3d2000, 0x020000C307200002UL); - /* Init_7: CI Port 3 Configuration */ - REGW(0x3d3000, 0x420000C307200002UL); - /* Init_8: CI Port 3 Configuration */ - REGW(0x3d3000, 0x020000C307200002UL); - /* Init_9: CI Port 4 Configuration */ - REGW(0x3d4000, 0x420000C307200002UL); - /* Init_10: CI Port 4 Configuration */ - REGW(0x3d4000, 0x020000C307200002UL); - /* Init_11: CI Port 5 Configuration */ - REGW(0x3d5000, 0x420000C307200002UL); - /* Init_12: CI Port 5 Configuration */ - REGW(0x3d5000, 0x020000C307200002UL); - /* Init_13: CI Port 6 Configuration */ - REGW(0x3d6000, 0x420000C307200002UL); - /* Init_14: CI Port 6 Configuration */ - REGW(0x3d6000, 0x020000C307200002UL); - /* Init_15: CI Port 7 Configuration */ - REGW(0x3d7000, 0x420000C307200002UL); - /* Init_16: CI Port 7 Configuration */ - REGW(0x3d7000, 0x020000C307200002UL); - - /*** Set LEM regs (need to match recov.) ***/ - - /* Init_17: CI Port 0 LEM FIR Accumulator */ - REGW(0x3d0200, 0x0000000000000000UL); - /* Init_18: CI Port 0 LEM Action 0 */ - REGW(0x3d0230, 0x0A00000000000000UL); - /* Init_19: CI Port 0 LEM Action 1 */ - REGW(0x3d0238, 0x0000000000000000UL); - /* Init_20: CI Port 0 LEM WOF */ - REGW(0x3d0240, 0x0000000000000000UL); - /* Init_21: CI Port 0 LEM Mask (AND write) */ - REGW(0x3d0220, 0x0200000000000000UL); - /* Init_22: CI Port 1 LEM FIR Accumularor */ - REGW(0x3d1200, 0x0000000000000000UL); - /* Init_23: CI Port 1 LEM Action 0 */ - REGW(0x3d1230, 0x0000000000000000UL); - /* Init_24: CI Port 1 LEM Action 1 */ - REGW(0x3d1238, 0x0000000000000000UL); - /* Init_25: CI Port 1 LEM WOF */ - REGW(0x3d1240, 0x0000000000000000UL); - /* Init_26: CI Port 1 LEM Mask (AND write) */ - REGW(0x3d1220, 0x0000000000000000UL); - /* Init_27: CI Port 2 LEM FIR Accumulator */ - REGW(0x3d2200, 0x0000000000000000UL); - /* Init_28: CI Port 2 LEM Action 0 */ - REGW(0x3d2230, 0xA4F4000000000000UL); - /* Init_29: CI Port 2 LEM Action 1 */ - REGW(0x3d2238, 0x0000000000000000UL); - /* Init_30: CI Port 2 LEM WOF */ - REGW(0x3d2240, 0x0000000000000000UL); - /* Init_31: CI Port 2 LEM Mask (AND write) */ - REGW(0x3d2220, 0x0000000000000000UL); - /* Init_32: CI Port 3 LEM FIR Accumulator */ - REGW(0x3d3200, 0x0000000000000000UL); - /* Init_33: CI Port 3 LEM Action 0 */ - REGW(0x3d3230, 0xA4F4000000000000UL); - /* Init_34: CI Port 3 LEM Action 1 */ - REGW(0x3d3238, 0x0000000000000000UL); - /* Init_35: CI Port 3 LEM WOF */ - REGW(0x3d3240, 0x0000000000000000UL); - /* Init_36: CI Port 3 LEM Mask (AND write) */ - REGW(0x3d3220, 0x0000000000000000UL); - /* Init_37: CI Port 4 LEM FIR Accumulator */ - REGW(0x3d4200, 0x0000000000000000UL); - /* Init_38: CI Port 4 Action 0 */ - REGW(0x3d4230, 0xA4F4000000000000UL); - /* Init_39: CI Port 4 Action 1 */ - REGW(0x3d4238, 0x0000000000000000UL); - /* Init_40: CI Port 4 WOF */ - REGW(0x3d4240, 0x0000000000000000UL); - /* Init_41: CI Port 4 Mask (AND write) */ - REGW(0x3d4220, 0x0000000000000000UL); - /* Init_42: CI Port 5 LEM FIR Accumulator */ - REGW(0x3d5200, 0x0000000000000000UL); - /* Init_43: CI Port 5 Action 0 */ - REGW(0x3d5230, 0xA4F4000000000000UL); - /* Init_44: CI Port 5 Action 1 */ - REGW(0x3d5238, 0x0000000000000000UL); - /* Init_45: CI Port 4 WOF */ - REGW(0x3d5240, 0x0000000000000000UL); - /* Init_46: CI Port 5 Mask (AND write) */ - REGW(0x3d5220, 0x0000000000000000UL); - /* Init_47: CI Port 6 LEM FIR Accumulator */ - REGW(0x3d6200, 0x0000000000000000UL); - /* Init_48: CI Port 6 Action 0 */ - REGW(0x3d6230, 0xA4F4000000000000UL); - /* Init_49: CI Port 6 Action 1 */ - REGW(0x3d6238, 0x0000000000000000UL); - /* Init_50: CI Port 6 WOF */ - REGW(0x3d6240, 0x0000000000000000UL); - /* Init_51: CI Port 6 Mask (AND write) */ - REGW(0x3d6220, 0x0000000000000000UL); - /* Init_52: CI Port 7 LEM FIR Accumulator */ - REGW(0x3d7200, 0x0000000000000000UL); - /* Init_53: CI Port 7 Action 0 */ - REGW(0x3d7230, 0xA4F4000000000000UL); - /* Init_54: CI Port 7 Action 1 */ - REGW(0x3d7238, 0x0000000000000000UL); - /* Init_55: CI Port 7 WOF */ - REGW(0x3d7240, 0x0000000000000000UL); - /* Init_56: CI Port 7 Mask (AND write) */ - REGW(0x3d7220, 0x0000000000000000UL); - - /*** Set Damage Controls (need match recov.) ***/ - - /* Init_57: CI Port 0 LDCP*/ - REGW(0x3d0010, 0x421A0000000075FFUL); - /* Init_58: CI Port 1 LDCP */ - REGW(0x3d1010, 0x421A000000007FFFUL); - /* Init_59: CI Port 2 LDCP */ - REGW(0x3d2010, 0x421A24F400005B0BUL); - /* Init_60: CI Port 3 LDCP */ - REGW(0x3d3010, 0x421A24F400005B0BUL); - /* Init_61: CI Port 4 LDCP */ - REGW(0x3d4010, 0x421A24F400005B0BUL); - /* Init_62: CI Port 5 LDCP */ - REGW(0x3d5010, 0x421A24F400005B0BUL); - /* Init_63: CI Port 6 LDCP */ - REGW(0x3d6010, 0x421A24F400005B0BUL); - /* Init_64: CI Port 7 LDCP */ - REGW(0x3d7010, 0x421A24F400005B0BUL); - - /*** Setup Trace 0 ***/ - - /* Init_65: CI Trc 0 DBG - Run/Status (stop trace) */ - REGW(0x3d0810, 0x5000000000000000UL); - /* Init_66: CI Trc 0 DBG - Mode (not cross trig CA's) */ - REGW(0x3d0808, 0xB0000000F0000000UL); - /* Init_66a: CI Trc 0 DBG - C0 (stop on error) */ - REGW(0x3d0818, 0xF4F00FFF00000000UL); - /* Init_67: CI Trc 0 DBG - Select (port 0 mode 2) */ - REGW(0x3d0878, 0x0002000000000000UL); - /* Init_68: CI Trc 0 CA0 - Pattern A (RX cmd val) */ - REGW(0x3d0880, 0xC0200000DFFFFF00UL); - /* Init_69: CI Trc 0 CA0 - Trigger 0 (Pattern A) */ - REGW(0x3d08a0, 0x8000000000000000UL); - /* Init_70: CI Trc 0 - Mode */ - REGW(0x3d08b0, 0x8000000000000000UL); - /* Init_71: CI Trc 0 CA1 - Pattern A (TX cmd val) */ - REGW(0x3d0900, 0xC0200000DFFFFF00UL); - /* Init_72: CI Trc 0 CA1 - Trigger 0 (Pattern A) */ - REGW(0x3d0920, 0x8000000000000000UL); - /* Init_73: CI Trc 0 CA1 - Mode */ - REGW(0x3d0930, 0x8000000000000000UL); - /* Init_74: CI Trc 0 DBG - Run/Status (start trace) */ - REGW(0x3d0810, 0x8000000000000000UL); - - /*** Setup Trace 1 ***/ - - /* Init_75: CI Trc 1 DBG - Run/Status (stop trace) */ - REGW(0x3d0c10, 0x5000000000000000UL); - /* Init_76: CI Trc 1 DBG - Mode (not cross trig CA's) */ - REGW(0x3d0c08, 0xB0000000F0000000UL); - /* Init_76a: CI Trc 1 DBG - C0 (stop on error) */ - REGW(0x3d0c18, 0xF4F00FFF00000000UL); - /* Init_77: CI Trc 1 DBG - Select (port 1 mode 2) */ - REGW(0x3d0c78, 0x0102000000000000UL); - /* Init_78: CI Trc 1 CA0 - Pattern A (RX cmd val) */ - REGW(0x3d0c80, 0xC0200000DFFFFF00UL); - /* Init_79: CI Trc 1 CA0 - Trigger 0 (Pattern A) */ - REGW(0x3d0ca0, 0x8000000000000000UL); - /* Init_80: CI Trc 1 CA0 - Mode */ - REGW(0x3d0cb0, 0x8000000000000000UL); - /* Init_81: CI Trc 1 CA1 - Pattern A (TX cmd val) */ - REGW(0x3d0d00, 0xC0200000DFFFFF00UL); - /* Init_82: CI Trc 1 CA1 - Trigger 0 (Pattern A) */ - REGW(0x3d0d20, 0x8000000000000000UL); - /* Init_83: CI Trc 1 CA1 - Mode */ - REGW(0x3d0d30, 0x8000000000000000UL); - /* Init_84: CI Trc 1 DBG - Run/Status (start trace) */ - REGW(0x3d0c10, 0x8000000000000000UL); - - /* Init_85...92: - * - * XXX NOTE: Here we normally read the Port 0 to 7 status regs - * which is optional. Eventually we might want to do it to check - * if the status matches expectations - * - * (regs 0x3d0008 to 0x3d7008) - */ - - /*** Set buffer allocations (credits) ***/ - - /* Init_93: CI Port 0 Rx Cmd Buffer Allocation */ - REGW(0x3d0050, 0x0808040400000000UL); - /* Init_94: CI Port 0 Rx Dat Buffer Allocation */ - REGW(0x3d0060, 0x0006000200000000UL); - /* Init_95: CI Port 1 Tx Cmd Buffer Allocation */ - REGW(0x3d1030, 0x0000040400000000UL); - /* Init_96: CI Port 1 Tx Dat Buffer Allocation */ - REGW(0x3d1040, 0x0000004800000000UL); - /* Init_97: CI Port 1 Rx Cmd Buffer Allocation */ - REGW(0x3d1050, 0x0008000000000000UL); - /* Init_98: CI Port 1 Rx Dat Buffer Allocation */ - REGW(0x3d1060, 0x0048000000000000UL); - /* Init_99: CI Port 2 Tx Cmd Buffer Allocation */ - REGW(0x3d2030, 0x0808080800000000UL); - /* Init_100: CI Port 2 Tx Dat Buffer Allocation */ - REGW(0x3d2040, 0x0086008200000000UL); - /* Init_101: CI Port 2 Rx Cmd Buffer Allocation */ - REGW(0x3d2050, 0x0808080800000000UL); - /* Init_102: CI Port 2 Rx Dat Buffer Allocation */ - REGW(0x3d2060, 0x8648000000000000UL); - /* Init_103: CI Port 3 Tx Cmd Buffer Allocation */ - REGW(0x3d3030, 0x0808080800000000UL); - /* Init_104: CI Port 3 Tx Dat Buffer Allocation */ - REGW(0x3d3040, 0x0086008200000000UL); - /* Init_105: CI Port 3 Rx Cmd Buffer Allocation */ - REGW(0x3d3050, 0x0808080800000000UL); - /* Init_106: CI Port 3 Rx Dat Buffer Allocation */ - REGW(0x3d3060, 0x8648000000000000UL); - /* Init_107: CI Port 4 Tx Cmd Buffer Allocation */ - REGW(0x3d4030, 0x0808080800000000UL); - /* Init_108: CI Port 4 Tx Dat Buffer Allocation */ - REGW(0x3d4040, 0x0086008200000000UL); - /* Init_109: CI Port 4 Rx Cmd Buffer Allocation */ - REGW(0x3d4050, 0x0808080800000000UL); - /* Init_110: CI Port 4 Rx Dat Buffer Allocation */ - REGW(0x3d4060, 0x8648000000000000UL); - /* Init_111: CI Port 5 Tx Cmd Buffer Allocation */ - REGW(0x3d5030, 0x0808080800000000UL); - /* Init_112: CI Port 5 Tx Dat Buffer Allocation */ - REGW(0x3d5040, 0x0086008200000000UL); - /* Init_113: CI Port 5 Rx Cmd Buffer Allocation */ - REGW(0x3d5050, 0x0808080800000000UL); - /* Init_114: CI Port 5 Rx Dat Buffer Allocation */ - REGW(0x3d5060, 0x8648000000000000UL); - /* Init_115: CI Port 6 Tx Cmd Buffer Allocation */ - REGW(0x3d6030, 0x0808080800000000UL); - /* Init_116: CI Port 6 Tx Dat Buffer Allocation */ - REGW(0x3d6040, 0x0086008200000000UL); - /* Init_117: CI Port 6 Rx Cmd Buffer Allocation */ - REGW(0x3d6050, 0x0808080800000000UL); - /* Init_118: CI Port 6 Rx Dat Buffer Allocation */ - REGW(0x3d6060, 0x8648000000000000UL); - /* Init_119: CI Port 7 Tx Cmd Buffer Allocation */ - REGW(0x3d7030, 0x0808080800000000UL); - /* Init_120: CI Port 7 Tx Dat Buffer Allocation */ - REGW(0x3d7040, 0x0086008200000000UL); - /* Init_121: CI Port 7 Rx Cmd Buffer Allocation */ - REGW(0x3d7050, 0x0808080800000000UL); - /* Init_122: CI Port 6 Rx Dat Buffer Allocation */ - REGW(0x3d7060, 0x8648000000000000UL); - - /*** Channel ordering ***/ - - /* Init_123: CI Port 1 Ordering */ - REGW(0x3d1070, 0x73D0735E00000000UL); - /* Init_124: CI Port 2 Ordering */ - REGW(0x3d2070, 0x73D0735E00000000UL); - /* Init_125: CI Port 3 Ordering */ - REGW(0x3d3070, 0x73D0735E00000000UL); - /* Init_126: CI Port 4 Ordering */ - REGW(0x3d4070, 0x73D0735E00000000UL); - /* Init_127: CI Port 5 Ordering */ - REGW(0x3d5070, 0x73D0735E00000000UL); - /* Init_128: CI Port 6 Ordering */ - REGW(0x3d6070, 0x73D0735E00000000UL); - /* Init_129: CI POrt 7 Ordering */ - REGW(0x3d7070, 0x73D0735E00000000UL); - - /*** Setup routing (port 0 only) */ - - p7ioc_init_ci_routing(ioc); - - /*** Set Running Configuration/Crd Init Timers *** - * - * XXX NOTE: Supposed to only modify bits 8:15 - */ - - /* Init_226: CI Port 1 Configuration */ - REGW(0x3d1000, 0x023F0FCF07200002UL); - /* Init_227: CI Port 2 Configuration */ - REGW(0x3d2000, 0x023F00C307200002UL); - /* Init_228: CI Port 3 Configuration */ - REGW(0x3d3000, 0x023F00C307200002UL); - /* Init_229: CI Port 4 Configuration */ - REGW(0x3d4000, 0x023F00C307200002UL); - /* Init_230: CI Port 5 Configuration */ - REGW(0x3d5000, 0x023F00C307200002UL); - /* Init_231: CI Port 6 Configuration */ - REGW(0x3d6000, 0x023F00C307200002UL); - /* Init_232: CI Port 7 Configuration */ - REGW(0x3d7000, 0x023F00C307200002UL); - /* Init_233: CI Port 0 Configuration */ - REGW(0x3d0000, 0x023F00C0073F0002UL); -} - -static void p7ioc_init_PHBs(struct p7ioc *ioc) -{ - unsigned int i; - - printf("P7IOC: Init PHBs...\n"); - - /* We use the same reset sequence that we use for - * fast reboot for consistency - */ - for (i = 0; i < P7IOC_NUM_PHBS; i++) { - if (p7ioc_phb_enabled(ioc, i)) - p7ioc_phb_reset(&ioc->phbs[i].phb); - } -} - -static void p7ioc_init_MISC(struct p7ioc *ioc) -{ - printf("P7IOC: Init MISC...\n"); - - /*** Set LEM regs ***/ - - /* Init_1: LEM FIR Accumulator */ - REGW(0x3ea000, 0x0000000000000000UL); - /* Init_2: LEM Action 0 */ - REGW(0x3ea030, 0xFFFFFFFCEE3FFFFFUL); - /* Init_3: LEM Action 1 */ - REGW(0x3ea038, 0x0000000001C00000UL); - /* Init_4: LEM WOF */ - REGW(0x3ea040, 0x0000000000000000UL); - /* Init_5: LEM Mask (AND write) */ - REGW(0x3ea020, 0x000F03F0CD3FFFFFUL); - /* Init_5.1: I2C LEM FIR Accumulator */ - REGW(0x3eb000, 0x0000000000000000UL); - /* Init_5.2: I2C LEM Action 0 */ - REGW(0x3eb030, 0xEE00000000000000UL); - /* Init_5.3: I2C LEM Action 1 */ - REGW(0x3eb038, 0x0000000000000000UL); - /* Init_5.4: I2C LEM WOF */ - REGW(0x3eb040, 0x0000000000000000UL); - /* Init_5.5: I2C LEM Mask (AND write) */ - REGW(0x3eb020, 0x4600000000000000UL); - - /*** Set RGC GP bits (error enables) ***/ - - /* Init_7: RGC GP0 control (enable umux errors) */ - REGW(0x3e1018, 0x8888880000000000ULL); - - /*** Central Trace Setup *** - * - * By default trace 4 PHBs Rx/Tx, but this can be changed - * for debugging purposes - */ - - /* Init_8: */ - REGW(0x3ea810, 0x5000000000000000UL); - /* Init_9: */ - REGW(0x3ea800, 0x0000000000000000UL); - /* Init_10: */ - REGW(0x3ea808, 0xB0000000F0000000UL); - /* Init_11: */ - REGW(0x3ea818, 0xF4F00FFF00000000UL); - /* Init_12: */ - REGW(0x3ea820, 0x0000000000000000UL); - /* Init_13: */ - REGW(0x3ea828, 0x0000000000000000UL); - /* Init_14: */ - REGW(0x3ea830, 0x0000000000000000UL); - /* Init_15: */ - REGW(0x3ea838, 0x0000000000000000UL); - /* Init_16: */ - REGW(0x3ea840, 0x0000000000000000UL); - /* Init_17: */ - REGW(0x3ea878, 0x0300000000000000UL); - - /* Init_18: PHB0 mux select (Rx/Tx) */ - REGW(0x000F80, 0x0000000000000000UL); - /* Init_19: PHB1 mux select (Rx/Tx) */ - REGW(0x010F80, 0x0000000000000000UL); - /* Init_19.0: PHB2 mux select (Rx/Tx) */ - REGW(0x020F80, 0x0000000000000000UL); - /* Init_19.1: PHB3 mux select (Rx/Tx) */ - REGW(0x030F80, 0x0000000000000000UL); - /* Init_19.2: PHB4 mux select (Rx/Tx) */ - REGW(0x040F80, 0x0000000000000000UL); - /* Init_19.3: PHB5 mux select (Rx/Tx) */ - REGW(0x050F80, 0x0000000000000000UL); - - /* Init_20: */ - REGW(0x3ea880, 0x40008000FF7F0000UL); - /* Init_21: */ - REGW(0x3ea888, 0x0000000000000000UL); - /* Init_22: */ - REGW(0x3ea890, 0x0000000000000000UL); - /* Init_23: */ - REGW(0x3ea898, 0x0000000000000000UL); - /* Init_24: */ - REGW(0x3ea8a0, 0x8000000000000000UL); - /* Init_25: */ - REGW(0x3ea8a8, 0x0000000000000000UL); - /* Init_26: */ - REGW(0x3ea8b0, 0x8000000000000000UL); - /* Init_27: */ - REGW(0x3ea8b8, 0x0000000000000000UL); - /* Init_28: */ - REGW(0x3ea8c0, 0x0000000000000000UL); - /* Init_29: */ - REGW(0x3ea900, 0x40008000FF7F0000UL); - /* Init_30: */ - REGW(0x3ea908, 0x0000000000000000UL); - /* Init_31: */ - REGW(0x3ea910, 0x0000000000000000UL); - /* Init_32: */ - REGW(0x3ea918, 0x0000000000000000UL); - /* Init_33: */ - REGW(0x3ea920, 0x8000000000000000UL); - /* Init_34: */ - REGW(0x3ea928, 0x0000000000000000UL); - /* Init_35: */ - REGW(0x3ea930, 0x8000000000000000UL); - /* Init_36: */ - REGW(0x3ea938, 0x0000000000000000UL); - /* Init_37: */ - REGW(0x3ea940, 0x0000000000000000UL); - /* Init_38: */ - REGW(0x3ea980, 0x40008000FF7F0000UL); - /* Init_39: */ - REGW(0x3ea988, 0x0000000000000000UL); - /* Init_40: */ - REGW(0x3ea990, 0x0000000000000000UL); - /* Init_41: */ - REGW(0x3ea998, 0x0000000000000000UL); - /* Init_42: */ - REGW(0x3ea9a0, 0x8000000000000000UL); - /* Init_43: */ - REGW(0x3ea9a8, 0x0000000000000000UL); - /* Init_44: */ - REGW(0x3ea9b0, 0x8000000000000000UL); - /* Init_45: */ - REGW(0x3ea9b8, 0x0000000000000000UL); - /* Init_46: */ - REGW(0x3ea9c0, 0x0000000000000000UL); - /* Init_47: */ - REGW(0x3eaa00, 0x40008000FF7F0000UL); - /* Init_48: */ - REGW(0x3eaa08, 0x0000000000000000UL); - /* Init_49: */ - REGW(0x3eaa10, 0x0000000000000000UL); - /* Init_50: */ - REGW(0x3eaa18, 0x0000000000000000UL); - /* Init_51: */ - REGW(0x3eaa20, 0x8000000000000000UL); - /* Init_52: */ - REGW(0x3eaa28, 0x0000000000000000UL); - /* Init_53: */ - REGW(0x3eaa30, 0x8000000000000000UL); - /* Init_54: */ - REGW(0x3eaa38, 0x0000000000000000UL); - /* Init_55: */ - REGW(0x3eaa40, 0x0000000000000000UL); - /* Init_56: */ - REGW(0x3ea810, 0x1000000000000000UL); - /* Init_57: */ - REGW(0x3ea810, 0x8000000000000000UL); - - /*** I2C Master init fixup */ - - /* Init_58: I2C Master Operation Control */ - REGW(0x3eb0a8, 0x8100000000000000UL); -} - -static void p7ioc_init_GEM(struct p7ioc *ioc) -{ - printf("P7IOC: Init GEM...\n"); - - /*** Check for errors */ - - /* XXX TODO */ -#if 0 - /* Init_1: */ - REGR(0x3e0008, 0); - /* Init_2: */ - REGR(0x3e0010, 0); - /* Init_3: */ - REGR(0x3e0018, 0); -#endif - - /*** Get ready for new errors, allow interrupts *** - * - * XXX: Need to leave all unused port masked to prevent - * invalid errors - */ - - /* Init_4: GEM XFIR */ - REGW(0x3e0008, 0x0000000000000000); - /* Init_5: GEM Mask (See FIXME) */ - REGW(0x3e0020, 0x000F033FFFFFFFFFUL); - /* Init_6: GEM WOF */ - REGW(0x3e0028, 0x0000000000000000); -} - -int64_t p7ioc_inits(struct p7ioc *ioc) -{ - p7ioc_init_BI(ioc); - p7ioc_init_MISC_HSS(ioc); - p7ioc_init_RGC(ioc); - p7ioc_init_CI(ioc); - p7ioc_init_PHBs(ioc); - p7ioc_init_MISC(ioc); - p7ioc_init_GEM(ioc); - - return OPAL_SUCCESS; - -} - -void p7ioc_reset(struct io_hub *hub) -{ - struct p7ioc *ioc = iohub_to_p7ioc(hub); - unsigned int i; - - /* We could do a full cold reset of P7IOC but for now, let's - * not bother and just try to clean up the interrupts as best - * as possible - */ - - /* XXX TODO: RGC interrupts */ - - printf("P7IOC: Clearing IODA...\n"); - - /* First clear all IODA tables and wait a bit */ - for (i = 0; i < 6; i++) { - if (p7ioc_phb_enabled(ioc, i)) - p7ioc_phb_reset(&ioc->phbs[i].phb); - } -} diff --git a/hw/p7ioc-phb.c b/hw/p7ioc-phb.c deleted file mode 100644 index ac01103..0000000 --- a/hw/p7ioc-phb.c +++ /dev/null @@ -1,3242 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <skiboot.h> -#include <p7ioc.h> -#include <p7ioc-regs.h> -#include <io.h> -#include <timebase.h> -#include <affinity.h> -#include <pci-cfg.h> -#include <pci.h> -#include <pci-slot.h> -#include <interrupts.h> -#include <opal.h> -#include <ccan/str/str.h> - -#define PHBDBG(p, fmt, a...) prlog(PR_DEBUG, "PHB#%04x: " fmt, \ - (p)->phb.opal_id, ## a) -#define PHBERR(p, fmt, a...) prlog(PR_ERR, "PHB#%04x: " fmt, \ - (p)->phb.opal_id, ## a) - -/* Helper to select an IODA table entry */ -static inline void p7ioc_phb_ioda_sel(struct p7ioc_phb *p, uint32_t table, - uint32_t addr, bool autoinc) -{ - out_be64(p->regs + PHB_IODA_ADDR, - (autoinc ? PHB_IODA_AD_AUTOINC : 0) | - SETFIELD(PHB_IODA_AD_TSEL, 0ul, table) | - SETFIELD(PHB_IODA_AD_TADR, 0ul, addr)); -} - -static bool p7ioc_phb_fenced(struct p7ioc_phb *p) -{ - struct p7ioc *ioc = p->ioc; - uint64_t fence, fbits; - - fbits = 0x0003000000000000UL >> (p->index * 4); - fence = in_be64(ioc->regs + P7IOC_CHIP_FENCE_SHADOW); - - return (fence & fbits) != 0; -} - -/* - * Configuration space access - * - * The PHB lock is assumed to be already held - */ -static int64_t p7ioc_pcicfg_check(struct p7ioc_phb *p, uint32_t bdfn, - uint32_t offset, uint32_t size) -{ - uint32_t sm = size - 1; - - if (offset > 0xfff || bdfn > 0xffff) - return OPAL_PARAMETER; - if (offset & sm) - return OPAL_PARAMETER; - - /* The root bus only has a device at 0 and we get into an - * error state if we try to probe beyond that, so let's - * avoid that and just return an error to Linux - */ - if ((bdfn >> 8) == 0 && (bdfn & 0xff)) - return OPAL_HARDWARE; - - /* Check PHB state */ - if (p->broken) - return OPAL_HARDWARE; - - return OPAL_SUCCESS; -} - -#define P7IOC_PCI_CFG_READ(size, type) \ -static int64_t p7ioc_pcicfg_read##size(struct phb *phb, uint32_t bdfn, \ - uint32_t offset, type *data) \ -{ \ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); \ - uint64_t addr; \ - void *base = p->regs; \ - int64_t rc; \ - \ - /* Initialize data in case of error */ \ - *data = (type)0xffffffff; \ - \ - rc = p7ioc_pcicfg_check(p, bdfn, offset, sizeof(type)); \ - if (rc) \ - return rc; \ - \ - if (p7ioc_phb_fenced(p)) { \ - if (!(p->flags & P7IOC_PHB_CFG_USE_ASB)) \ - return OPAL_HARDWARE; \ - \ - base = p->regs_asb; \ - } else if ((p->flags & P7IOC_PHB_CFG_BLOCKED) && bdfn != 0) { \ - return OPAL_HARDWARE; \ - } \ - \ - addr = PHB_CA_ENABLE; \ - addr = SETFIELD(PHB_CA_BDFN, addr, bdfn); \ - addr = SETFIELD(PHB_CA_REG, addr, offset); \ - out_be64(base + PHB_CONFIG_ADDRESS, addr); \ - *data = in_le##size(base + PHB_CONFIG_DATA + \ - (offset & (4 - sizeof(type)))); \ - \ - return OPAL_SUCCESS; \ -} - -#define P7IOC_PCI_CFG_WRITE(size, type) \ -static int64_t p7ioc_pcicfg_write##size(struct phb *phb, uint32_t bdfn, \ - uint32_t offset, type data) \ -{ \ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); \ - void *base = p->regs; \ - uint64_t addr; \ - int64_t rc; \ - \ - rc = p7ioc_pcicfg_check(p, bdfn, offset, sizeof(type)); \ - if (rc) \ - return rc; \ - \ - if (p7ioc_phb_fenced(p)) { \ - if (!(p->flags & P7IOC_PHB_CFG_USE_ASB)) \ - return OPAL_HARDWARE; \ - \ - base = p->regs_asb; \ - } else if ((p->flags & P7IOC_PHB_CFG_BLOCKED) && bdfn != 0) { \ - return OPAL_HARDWARE; \ - } \ - \ - addr = PHB_CA_ENABLE; \ - addr = SETFIELD(PHB_CA_BDFN, addr, bdfn); \ - addr = SETFIELD(PHB_CA_REG, addr, offset); \ - out_be64(base + PHB_CONFIG_ADDRESS, addr); \ - out_le##size(base + PHB_CONFIG_DATA + \ - (offset & (4 - sizeof(type))), data); \ - \ - return OPAL_SUCCESS; \ -} - -P7IOC_PCI_CFG_READ(8, uint8_t) -P7IOC_PCI_CFG_READ(16, uint16_t) -P7IOC_PCI_CFG_READ(32, uint32_t) -P7IOC_PCI_CFG_WRITE(8, uint8_t) -P7IOC_PCI_CFG_WRITE(16, uint16_t) -P7IOC_PCI_CFG_WRITE(32, uint32_t) - -static void p7ioc_eeh_read_phb_status(struct p7ioc_phb *p, - struct OpalIoP7IOCPhbErrorData *stat) -{ - uint16_t tmp16; - unsigned int i; - - memset(stat, 0, sizeof(struct OpalIoP7IOCPhbErrorData)); - - - /* Error data common part */ - stat->common.version = OPAL_PHB_ERROR_DATA_VERSION_1; - stat->common.ioType = OPAL_PHB_ERROR_DATA_TYPE_P7IOC; - stat->common.len = sizeof(struct OpalIoP7IOCPhbErrorData); - - /* - * We read some registers using config space through AIB. - * - * Get to other registers using ASB when possible to get to them - * through a fence if one is present. - * - * Note that the OpalIoP7IOCPhbErrorData has oddities, such as the - * bridge control being 32-bit and the UTL registers being 32-bit - * (which they really are, but they use the top 32-bit of a 64-bit - * register so we need to be a bit careful). - */ - - /* Use ASB to access PCICFG if the PHB has been fenced */ - p->flags |= P7IOC_PHB_CFG_USE_ASB; - - /* Grab RC bridge control, make it 32-bit */ - p7ioc_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &tmp16); - stat->brdgCtl = tmp16; - - /* Grab UTL status registers */ - stat->portStatusReg = hi32(in_be64(p->regs_asb - + UTL_PCIE_PORT_STATUS)); - stat->rootCmplxStatus = hi32(in_be64(p->regs_asb - + UTL_RC_STATUS)); - stat->busAgentStatus = hi32(in_be64(p->regs_asb - + UTL_SYS_BUS_AGENT_STATUS)); - - /* - * Grab various RC PCIe capability registers. All device, slot - * and link status are 16-bit, so we grab the pair control+status - * for each of them - */ - p7ioc_pcicfg_read32(&p->phb, 0, p->ecap + PCICAP_EXP_DEVCTL, - &stat->deviceStatus); - p7ioc_pcicfg_read32(&p->phb, 0, p->ecap + PCICAP_EXP_SLOTCTL, - &stat->slotStatus); - p7ioc_pcicfg_read32(&p->phb, 0, p->ecap + PCICAP_EXP_LCTL, - &stat->linkStatus); - - /* - * I assume those are the standard config space header, cmd & status - * together makes 32-bit. Secondary status is 16-bit so I'll clear - * the top on that one - */ - p7ioc_pcicfg_read32(&p->phb, 0, PCI_CFG_CMD, &stat->devCmdStatus); - p7ioc_pcicfg_read16(&p->phb, 0, PCI_CFG_SECONDARY_STATUS, &tmp16); - stat->devSecStatus = tmp16; - - /* Grab a bunch of AER regs */ - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_RERR_STA, - &stat->rootErrorStatus); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_UE_STATUS, - &stat->uncorrErrorStatus); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_CE_STATUS, - &stat->corrErrorStatus); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG0, - &stat->tlpHdr1); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG1, - &stat->tlpHdr2); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG2, - &stat->tlpHdr3); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_HDR_LOG3, - &stat->tlpHdr4); - p7ioc_pcicfg_read32(&p->phb, 0, p->aercap + PCIECAP_AER_SRCID, - &stat->sourceId); - - /* Restore to AIB */ - p->flags &= ~P7IOC_PHB_CFG_USE_ASB; - - /* - * No idea what that that is supposed to be, opal.h says - * "Record data about the call to allocate a buffer." - * - * Let's leave them alone for now... - * - * uint64_t errorClass; - * uint64_t correlator; - */ - - /* P7IOC MMIO Error Regs */ - stat->p7iocPlssr = in_be64(p->regs_asb + PHB_CPU_LOADSTORE_STATUS); - stat->p7iocCsr = in_be64(p->regs_asb + PHB_DMA_CHAN_STATUS); - stat->lemFir = in_be64(p->regs_asb + PHB_LEM_FIR_ACCUM); - stat->lemErrorMask = in_be64(p->regs_asb + PHB_LEM_ERROR_MASK); - stat->lemWOF = in_be64(p->regs_asb + PHB_LEM_WOF); - stat->phbErrorStatus = in_be64(p->regs_asb + PHB_ERR_STATUS); - stat->phbFirstErrorStatus = in_be64(p->regs_asb + PHB_ERR1_STATUS); - stat->phbErrorLog0 = in_be64(p->regs_asb + PHB_ERR_LOG_0); - stat->phbErrorLog1 = in_be64(p->regs_asb + PHB_ERR_LOG_1); - stat->mmioErrorStatus = in_be64(p->regs_asb + PHB_OUT_ERR_STATUS); - stat->mmioFirstErrorStatus = in_be64(p->regs_asb + PHB_OUT_ERR1_STATUS); - stat->mmioErrorLog0 = in_be64(p->regs_asb + PHB_OUT_ERR_LOG_0); - stat->mmioErrorLog1 = in_be64(p->regs_asb + PHB_OUT_ERR_LOG_1); - stat->dma0ErrorStatus = in_be64(p->regs_asb + PHB_INA_ERR_STATUS); - stat->dma0FirstErrorStatus = in_be64(p->regs_asb + PHB_INA_ERR1_STATUS); - stat->dma0ErrorLog0 = in_be64(p->regs_asb + PHB_INA_ERR_LOG_0); - stat->dma0ErrorLog1 = in_be64(p->regs_asb + PHB_INA_ERR_LOG_1); - stat->dma1ErrorStatus = in_be64(p->regs_asb + PHB_INB_ERR_STATUS); - stat->dma1FirstErrorStatus = in_be64(p->regs_asb + PHB_INB_ERR1_STATUS); - stat->dma1ErrorLog0 = in_be64(p->regs_asb + PHB_INB_ERR_LOG_0); - stat->dma1ErrorLog1 = in_be64(p->regs_asb + PHB_INB_ERR_LOG_1); - - /* Grab PESTA & B content */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTA, 0, true); - for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) - stat->pestA[i] = in_be64(p->regs_asb + PHB_IODA_DATA0); - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTB, 0, true); - for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) - stat->pestB[i] = in_be64(p->regs_asb + PHB_IODA_DATA0); -} - -static int64_t p7ioc_eeh_freeze_status(struct phb *phb, uint64_t pe_number, - uint8_t *freeze_state, - uint16_t *pci_error_type, - uint16_t *severity) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t peev_bit = PPC_BIT(pe_number & 0x3f); - uint64_t peev, pesta, pestb; - - /* Defaults: not frozen */ - *freeze_state = OPAL_EEH_STOPPED_NOT_FROZEN; - *pci_error_type = OPAL_EEH_NO_ERROR; - - /* Check dead */ - if (p->broken) { - *freeze_state = OPAL_EEH_STOPPED_MMIO_DMA_FREEZE; - *pci_error_type = OPAL_EEH_PHB_ERROR; - if (severity) - *severity = OPAL_EEH_SEV_PHB_DEAD; - return OPAL_SUCCESS; - } - - /* Check fence */ - if (p7ioc_phb_fenced(p)) { - /* Should be OPAL_EEH_STOPPED_TEMP_UNAVAIL ? */ - *freeze_state = OPAL_EEH_STOPPED_MMIO_DMA_FREEZE; - *pci_error_type = OPAL_EEH_PHB_ERROR; - if (severity) - *severity = OPAL_EEH_SEV_PHB_FENCED; - return OPAL_SUCCESS; - } - - /* Check the PEEV */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PEEV, 0, true); - peev = in_be64(p->regs + PHB_IODA_DATA0); - if (pe_number > 63) - peev = in_be64(p->regs + PHB_IODA_DATA0); - if (!(peev & peev_bit)) - return OPAL_SUCCESS; - - /* Indicate that we have an ER pending */ - p7ioc_phb_set_err_pending(p, true); - if (severity) - *severity = OPAL_EEH_SEV_PE_ER; - - /* Read the PESTA & PESTB */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTA, pe_number, false); - pesta = in_be64(p->regs + PHB_IODA_DATA0); - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTB, pe_number, false); - pestb = in_be64(p->regs + PHB_IODA_DATA0); - - /* Convert them */ - if (pesta & IODA_PESTA_MMIO_FROZEN) - *freeze_state |= OPAL_EEH_STOPPED_MMIO_FREEZE; - if (pestb & IODA_PESTB_DMA_STOPPED) - *freeze_state |= OPAL_EEH_STOPPED_DMA_FREEZE; - - /* XXX Handle more causes */ - if (pesta & IODA_PESTA_MMIO_CAUSE) - *pci_error_type = OPAL_EEH_PE_MMIO_ERROR; - else - *pci_error_type = OPAL_EEH_PE_DMA_ERROR; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_eeh_next_error(struct phb *phb, uint64_t *first_frozen_pe, - uint16_t *pci_error_type, uint16_t *severity) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - struct p7ioc *ioc = p->ioc; - uint64_t fir, peev0, peev1; - uint32_t cfg32, i; - - /* Check if there're pending errors on the IOC. */ - if (p7ioc_err_pending(ioc) && - p7ioc_check_LEM(ioc, pci_error_type, severity)) - return OPAL_SUCCESS; - - /* Clear result */ - *pci_error_type = OPAL_EEH_NO_ERROR; - *severity = OPAL_EEH_SEV_NO_ERROR; - *first_frozen_pe = (uint64_t)-1; - - /* Check dead */ - if (p->broken) { - *pci_error_type = OPAL_EEH_PHB_ERROR; - *severity = OPAL_EEH_SEV_PHB_DEAD; - return OPAL_SUCCESS; - } - - /* Check fence */ - if (p7ioc_phb_fenced(p)) { - /* Should be OPAL_EEH_STOPPED_TEMP_UNAVAIL ? */ - *pci_error_type = OPAL_EEH_PHB_ERROR; - *severity = OPAL_EEH_SEV_PHB_FENCED; - p7ioc_phb_set_err_pending(p, false); - return OPAL_SUCCESS; - } - - /* - * If we don't have pending errors, which might be moved - * from IOC to the PHB, then check if there has any frozen PEs. - */ - if (!p7ioc_phb_err_pending(p)) { - p7ioc_phb_ioda_sel(p, IODA_TBL_PEEV, 0, true); - peev0 = in_be64(p->regs + PHB_IODA_DATA0); - peev1 = in_be64(p->regs + PHB_IODA_DATA0); - if (peev0 || peev1) { - p->err.err_src = P7IOC_ERR_SRC_PHB0 + p->index; - p->err.err_class = P7IOC_ERR_CLASS_ER; - p->err.err_bit = 0; - p7ioc_phb_set_err_pending(p, true); - } - } - - /* Check the pending errors, which might come from IOC */ - if (p7ioc_phb_err_pending(p)) { - /* - * If the frozen PE is caused by a malfunctioning TLP, we - * need reset the PHB. So convert ER to PHB-fatal error - * for the case. - */ - if (p->err.err_class == P7IOC_ERR_CLASS_ER) { - fir = in_be64(p->regs_asb + PHB_LEM_FIR_ACCUM); - if (fir & PPC_BIT(60)) { - p7ioc_pcicfg_read32(&p->phb, 0, - p->aercap + PCIECAP_AER_UE_STATUS, &cfg32); - if (cfg32 & PCIECAP_AER_UE_MALFORMED_TLP) - p->err.err_class = P7IOC_ERR_CLASS_PHB; - } - } - - /* - * Map P7IOC internal error class to that one OS can handle. - * For P7IOC_ERR_CLASS_ER, we also need figure out the frozen - * PE. - */ - switch (p->err.err_class) { - case P7IOC_ERR_CLASS_PHB: - *pci_error_type = OPAL_EEH_PHB_ERROR; - *severity = OPAL_EEH_SEV_PHB_FENCED; - p7ioc_phb_set_err_pending(p, false); - break; - case P7IOC_ERR_CLASS_MAL: - case P7IOC_ERR_CLASS_INF: - *pci_error_type = OPAL_EEH_PHB_ERROR; - *severity = OPAL_EEH_SEV_INF; - p7ioc_phb_set_err_pending(p, false); - break; - case P7IOC_ERR_CLASS_ER: - *pci_error_type = OPAL_EEH_PE_ERROR; - *severity = OPAL_EEH_SEV_PE_ER; - p7ioc_phb_ioda_sel(p, IODA_TBL_PEEV, 0, true); - peev0 = in_be64(p->regs + PHB_IODA_DATA0); - peev1 = in_be64(p->regs + PHB_IODA_DATA0); - - for (i = 0 ; i < 64; i++) { - if (PPC_BIT(i) & peev1) { - *first_frozen_pe = i + 64; - break; - } - } - for (i = 0 ; - *first_frozen_pe == (uint64_t)-1 && i < 64; - i++) { - if (PPC_BIT(i) & peev0) { - *first_frozen_pe = i; - break; - } - } - - /* No frozen PE? */ - if (*first_frozen_pe == (uint64_t)-1) { - *pci_error_type = OPAL_EEH_NO_ERROR; - *severity = OPAL_EEH_SEV_NO_ERROR; - p7ioc_phb_set_err_pending(p, false); - } - - break; - default: - *pci_error_type = OPAL_EEH_NO_ERROR; - *severity = OPAL_EEH_SEV_NO_ERROR; - p7ioc_phb_set_err_pending(p, false); - } - } - - return OPAL_SUCCESS; -} - -static void p7ioc_ER_err_clear(struct p7ioc_phb *p) -{ - u64 err, lem; - u32 val; - - /* Rec 1,2 */ - lem = in_be64(p->regs + PHB_LEM_FIR_ACCUM); - - /* Rec 3,4,5 AER registers (could use cfg space accessors) */ - out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000001c00000000ull); - out_be32(p->regs + PHB_CONFIG_DATA, 0x10000000); - - /* Rec 6,7,8 XXX DOC whacks payload & req size ... we don't */ - out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000005000000000ull); - val = in_be32(p->regs + PHB_CONFIG_DATA); - out_be32(p->regs + PHB_CONFIG_DATA, (val & 0xe0700000) | 0x0f000f00); - - /* Rec 9,10,11 */ - out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000010400000000ull); - out_be32(p->regs + PHB_CONFIG_DATA, 0xffffffff); - - /* Rec 12,13,14 */ - out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000011000000000ull); - out_be32(p->regs + PHB_CONFIG_DATA, 0xffffffff); - - /* Rec 23,24,25 */ - out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000013000000000ull); - out_be32(p->regs + PHB_CONFIG_DATA, 0xffffffff); - - /* Rec 26,27,28 */ - out_be64(p->regs + PHB_CONFIG_ADDRESS, 0x8000004000000000ull); - out_be32(p->regs + PHB_CONFIG_DATA, 0x470100f8); - - /* Rec 29..34 UTL registers */ - err = in_be64(p->regs + UTL_SYS_BUS_AGENT_STATUS); - out_be64(p->regs + UTL_SYS_BUS_AGENT_STATUS, err); - err = in_be64(p->regs + UTL_PCIE_PORT_STATUS); - out_be64(p->regs + UTL_PCIE_PORT_STATUS, err); - err = in_be64(p->regs + UTL_RC_STATUS); - out_be64(p->regs + UTL_RC_STATUS, err); - - /* PHB error traps registers */ - err = in_be64(p->regs + PHB_ERR_STATUS); - out_be64(p->regs + PHB_ERR_STATUS, err); - out_be64(p->regs + PHB_ERR1_STATUS, 0); - out_be64(p->regs + PHB_ERR_LOG_0, 0); - out_be64(p->regs + PHB_ERR_LOG_1, 0); - - err = in_be64(p->regs + PHB_OUT_ERR_STATUS); - out_be64(p->regs + PHB_OUT_ERR_STATUS, err); - out_be64(p->regs + PHB_OUT_ERR1_STATUS, 0); - out_be64(p->regs + PHB_OUT_ERR_LOG_0, 0); - out_be64(p->regs + PHB_OUT_ERR_LOG_1, 0); - - err = in_be64(p->regs + PHB_INA_ERR_STATUS); - out_be64(p->regs + PHB_INA_ERR_STATUS, err); - out_be64(p->regs + PHB_INA_ERR1_STATUS, 0); - out_be64(p->regs + PHB_INA_ERR_LOG_0, 0); - out_be64(p->regs + PHB_INA_ERR_LOG_1, 0); - - err = in_be64(p->regs + PHB_INB_ERR_STATUS); - out_be64(p->regs + PHB_INB_ERR_STATUS, err); - out_be64(p->regs + PHB_INB_ERR1_STATUS, 0); - out_be64(p->regs + PHB_INB_ERR_LOG_0, 0); - out_be64(p->regs + PHB_INB_ERR_LOG_1, 0); - - /* Rec 67, 68 LEM */ - out_be64(p->regs + PHB_LEM_FIR_AND_MASK, ~lem); - out_be64(p->regs + PHB_LEM_WOF, 0); -} - -static int64_t p7ioc_eeh_freeze_clear(struct phb *phb, uint64_t pe_number, - uint64_t eeh_action_token) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t peev0, peev1; - - /* XXX Now this is a heavy hammer, coming roughly from the P7IOC doc - * and my old "pseudopal" code. It will need to be refined. In general - * error handling will have to be reviewed and probably done properly - * "from scratch" based on the description in the p7IOC spec. - * - * XXX Additionally, when handling interrupts, we might want to consider - * masking while processing and/or ack'ing interrupt bits etc... - */ - u64 err; - - /* Summary. If nothing, move to clearing the PESTs which can - * contain a freeze state from a previous error or simply set - * explicitly by the user - */ - err = in_be64(p->regs + PHB_ETU_ERR_SUMMARY); - if (err == 0) - goto clear_pest; - - p7ioc_ER_err_clear(p); - - clear_pest: - /* XXX We just clear the whole PESTA for MMIO clear and PESTB - * for DMA clear. We might want to only clear the frozen bit - * as to not clobber the rest of the state. However, we expect - * the state to have been harvested before the clear operations - * so this might not be an issue - */ - if (eeh_action_token & OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO) { - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTA, pe_number, false); - out_be64(p->regs + PHB_IODA_DATA0, 0); - } - if (eeh_action_token & OPAL_EEH_ACTION_CLEAR_FREEZE_DMA) { - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTB, pe_number, false); - out_be64(p->regs + PHB_IODA_DATA0, 0); - } - - /* Update ER pending indication */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PEEV, 0, true); - peev0 = in_be64(p->regs + PHB_IODA_DATA0); - peev1 = in_be64(p->regs + PHB_IODA_DATA0); - if (peev0 || peev1) { - p->err.err_src = P7IOC_ERR_SRC_PHB0 + p->index; - p->err.err_class = P7IOC_ERR_CLASS_ER; - p->err.err_bit = 0; - p7ioc_phb_set_err_pending(p, true); - } else - p7ioc_phb_set_err_pending(p, false); - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_eeh_freeze_set(struct phb *phb, uint64_t pe_number, - uint64_t eeh_action_token) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t data; - - if (pe_number > 127) - return OPAL_PARAMETER; - - if (eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_MMIO && - eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_DMA && - eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_ALL) - return OPAL_PARAMETER; - - if (eeh_action_token & OPAL_EEH_ACTION_SET_FREEZE_MMIO) { - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTA, pe_number, false); - data = in_be64(p->regs + PHB_IODA_DATA0); - data |= IODA_PESTA_MMIO_FROZEN; - out_be64(p->regs + PHB_IODA_DATA0, data); - } - - if (eeh_action_token & OPAL_EEH_ACTION_SET_FREEZE_DMA) { - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTB, pe_number, false); - data = in_be64(p->regs + PHB_IODA_DATA0); - data |= IODA_PESTB_DMA_STOPPED; - out_be64(p->regs + PHB_IODA_DATA0, data); - } - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_err_inject_finalize(struct p7ioc_phb *p, uint64_t addr, - uint64_t mask, uint64_t ctrl, - bool is_write) -{ - if (is_write) - ctrl |= PHB_PAPR_ERR_INJ_CTL_WR; - else - ctrl |= PHB_PAPR_ERR_INJ_CTL_RD; - - /* HW100549: Take read and write for outbound errors - * on DD10 chip - */ - if (p->rev == P7IOC_REV_DD10) - ctrl |= (PHB_PAPR_ERR_INJ_CTL_RD | PHB_PAPR_ERR_INJ_CTL_WR); - - out_be64(p->regs + PHB_PAPR_ERR_INJ_ADDR, addr); - out_be64(p->regs + PHB_PAPR_ERR_INJ_MASK, mask); - out_be64(p->regs + PHB_PAPR_ERR_INJ_CTL, ctrl); - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_err_inject_mem32(struct p7ioc_phb *p, uint64_t pe_number, - uint64_t addr, uint64_t mask, - bool is_write) -{ - uint64_t a, m, prefer, base; - uint64_t ctrl = PHB_PAPR_ERR_INJ_CTL_OUTB; - int32_t index; - - a = 0x0ull; - prefer = 0x0ull; - for (index = 0; index < 128; index++) { - if (GETFIELD(IODA_XXDT_PE, p->m32d_cache[index]) != pe_number) - continue; - - base = p->m32_base + M32_PCI_START + - (M32_PCI_SIZE / 128) * index; - - /* Update preferred address */ - if (!prefer) { - prefer = GETFIELD(PHB_PAPR_ERR_INJ_MASK_MMIO, base); - prefer = SETFIELD(PHB_PAPR_ERR_INJ_MASK_MMIO, - 0x0ull, prefer); - } - - /* The input address matches ? */ - if (addr >= base && - addr < base + (M32_PCI_SIZE / 128)) { - a = addr; - break; - } - } - - /* Invalid PE number */ - if (!prefer) - return OPAL_PARAMETER; - - /* Specified address is out of range */ - if (!a) { - a = prefer; - m = PHB_PAPR_ERR_INJ_MASK_MMIO; - } else { - m = mask; - } - - return p7ioc_err_inject_finalize(p, a, m, ctrl, is_write); -} - -static int64_t p7ioc_err_inject_io32(struct p7ioc_phb *p, uint64_t pe_number, - uint64_t addr, uint64_t mask, - bool is_write) -{ - uint64_t a, m, prefer, base; - uint64_t ctrl = PHB_PAPR_ERR_INJ_CTL_OUTB; - int32_t index; - - a = 0x0ull; - prefer = 0x0ull; - for (index = 0; index < 128; index++) { - if (GETFIELD(IODA_XXDT_PE, p->iod_cache[index]) != pe_number) - continue; - - base = p->io_base + (PHB_IO_SIZE / 128) * index; - - /* Update preferred address */ - if (!prefer) { - prefer = GETFIELD(PHB_PAPR_ERR_INJ_MASK_IO, base); - prefer = SETFIELD(PHB_PAPR_ERR_INJ_MASK_IO, 0x0ull, prefer); - } - - /* The input address matches ? */ - if (addr >= base && - addr < base + (PHB_IO_SIZE / 128)) { - a = addr; - break; - } - } - - /* Invalid PE number */ - if (!prefer) - return OPAL_PARAMETER; - - /* Specified address is out of range */ - if (!a) { - a = prefer; - m = PHB_PAPR_ERR_INJ_MASK_IO; - } else { - m = mask; - } - - return p7ioc_err_inject_finalize(p, a, m, ctrl, is_write); -} - -static int64_t p7ioc_err_inject_cfg(struct p7ioc_phb *p, uint64_t pe_number, - uint64_t addr, uint64_t mask, - bool is_write) -{ - uint64_t a, m; - uint64_t ctrl = PHB_PAPR_ERR_INJ_CTL_CFG; - uint8_t v_bits, base, bus_no; - - /* Looking into PELTM to see if the PCI bus# is owned - * by the PE#. Otherwise, we have to figure one out. - */ - base = GETFIELD(IODA_PELTM_BUS, p->peltm_cache[pe_number]); - v_bits = GETFIELD(IODA_PELTM_BUS_VALID, p->peltm_cache[pe_number]); - switch (v_bits) { - case IODA_BUS_VALID_3_BITS: - case IODA_BUS_VALID_4_BITS: - case IODA_BUS_VALID_5_BITS: - case IODA_BUS_VALID_6_BITS: - case IODA_BUS_VALID_7_BITS: - case IODA_BUS_VALID_ALL: - base = GETFIELD(IODA_PELTM_BUS, p->peltm_cache[pe_number]); - base &= (0xff - (((1 << (7 - v_bits)) - 1))); - a = SETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG, 0x0ul, base); - m = PHB_PAPR_ERR_INJ_MASK_CFG; - - bus_no = GETFIELD(PHB_PAPR_ERR_INJ_MASK_CFG, addr); - bus_no &= (0xff - (((1 << (7 - v_bits)) - 1))); - if (base == bus_no) { - a = addr; - m = mask; - } - - break; - case IODA_BUS_VALID_ANY: - default: - return OPAL_PARAMETER; - } - - return p7ioc_err_inject_finalize(p, a, m, ctrl, is_write); -} - -static int64_t p7ioc_err_inject_dma(struct p7ioc_phb *p, uint64_t pe_number, - uint64_t addr, uint64_t mask, - bool is_write) -{ - uint64_t ctrl = PHB_PAPR_ERR_INJ_CTL_INB; - int32_t index; - - /* For DMA, we just pick address from TVT */ - for (index = 0; index < 128; index++) { - if (GETFIELD(IODA_TVT1_PE_NUM, p->tve_hi_cache[index]) != - pe_number) - continue; - - addr = SETFIELD(PHB_PAPR_ERR_INJ_MASK_DMA, 0ul, index); - mask = PHB_PAPR_ERR_INJ_MASK_DMA; - break; - } - - /* Some PE might not have DMA capability */ - if (index >= 128) - return OPAL_PARAMETER; - - return p7ioc_err_inject_finalize(p, addr, mask, ctrl, is_write); -} - -static int64_t p7ioc_err_inject(struct phb *phb, uint64_t pe_number, - uint32_t type, uint32_t func, - uint64_t addr, uint64_t mask) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - int64_t (*handler)(struct p7ioc_phb *p, uint64_t pe_number, - uint64_t addr, uint64_t mask, bool is_write); - bool is_write; - - /* To support 64-bits error later */ - if (type == OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64) - return OPAL_UNSUPPORTED; - - /* We can't inject error to the reserved PE#127 */ - if (pe_number > 126) - return OPAL_PARAMETER; - - /* Clear the leftover from last time */ - out_be64(p->regs + PHB_PAPR_ERR_INJ_CTL, 0x0ul); - - /* Check if PE number is valid one in PELTM cache */ - if (p->peltm_cache[pe_number] == 0x0001f80000000000ull) - return OPAL_PARAMETER; - - /* Clear the leftover from last time */ - out_be64(p->regs + PHB_PAPR_ERR_INJ_CTL, 0x0ul); - - switch (func) { - case OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_DATA: - is_write = false; - handler = p7ioc_err_inject_mem32; - break; - case OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_DATA: - is_write = true; - handler = p7ioc_err_inject_mem32; - break; - case OPAL_ERR_INJECT_FUNC_IOA_LD_IO_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_LD_IO_DATA: - is_write = false; - handler = p7ioc_err_inject_io32; - break; - case OPAL_ERR_INJECT_FUNC_IOA_ST_IO_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_ST_IO_DATA: - is_write = true; - handler = p7ioc_err_inject_io32; - break; - case OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_DATA: - is_write = false; - handler = p7ioc_err_inject_cfg; - break; - case OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_DATA: - is_write = true; - handler = p7ioc_err_inject_cfg; - break; - case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_DATA: - case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_MASTER: - case OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_TARGET: - is_write = false; - handler = p7ioc_err_inject_dma; - break; - case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_ADDR: - case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_DATA: - case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_MASTER: - case OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET: - is_write = true; - handler = p7ioc_err_inject_dma; - break; - default: - return OPAL_PARAMETER; - } - - return handler(p, pe_number, addr, mask, is_write); -} - -static int64_t p7ioc_get_diag_data(struct phb *phb, void *diag_buffer, - uint64_t diag_buffer_len) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - struct OpalIoP7IOCPhbErrorData *diag = diag_buffer; - - if (diag_buffer_len < sizeof(struct OpalIoP7IOCPhbErrorData)) - return OPAL_PARAMETER; - - /* Specific error data */ - p7ioc_eeh_read_phb_status(p, diag); - - /* - * We're running to here probably because of errors (MAL - * or INF class) from IOC. For the case, we need clear - * the pending errors and mask the error bit for MAL class - * error. Fortunately, we shouldn't get MAL class error from - * IOC on P7IOC. - */ - if (p7ioc_phb_err_pending(p) && - p->err.err_class == P7IOC_ERR_CLASS_INF && - p->err.err_src >= P7IOC_ERR_SRC_PHB0 && - p->err.err_src <= P7IOC_ERR_SRC_PHB5) { - p7ioc_ER_err_clear(p); - p7ioc_phb_set_err_pending(p, false); - } - - return OPAL_SUCCESS; -} - -/* - * We don't support address remapping now since all M64 - * BARs are sharing on remapping base address. We might - * introduce flag to the PHB in order to trace that. The - * flag allows to be changed for once. It's something to - * do in future. - */ -static int64_t p7ioc_set_phb_mem_window(struct phb *phb, - uint16_t window_type, - uint16_t window_num, - uint64_t base, - uint64_t __unused pci_base, - uint64_t size) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t data64; - - switch (window_type) { - case OPAL_IO_WINDOW_TYPE: - case OPAL_M32_WINDOW_TYPE: - return OPAL_UNSUPPORTED; - case OPAL_M64_WINDOW_TYPE: - if (window_num >= 16) - return OPAL_PARAMETER; - /* The base and size should be 16MB aligned */ - if (base & 0xFFFFFF || size & 0xFFFFFF) - return OPAL_PARAMETER; - data64 = p->m64b_cache[window_num]; - data64 = SETFIELD(IODA_M64BT_BASE, data64, base >> 24); - size = (size >> 24); - data64 = SETFIELD(IODA_M64BT_MASK, data64, 0x1000000 - size); - break; - default: - return OPAL_PARAMETER; - } - - /* - * If the M64 BAR hasn't enabled yet, we needn't flush - * the setting to hardware and just keep it to the cache - */ - p->m64b_cache[window_num] = data64; - if (!(data64 & IODA_M64BT_ENABLE)) - return OPAL_SUCCESS; - p7ioc_phb_ioda_sel(p, IODA_TBL_M64BT, window_num, false); - out_be64(p->regs + PHB_IODA_DATA0, data64); - - return OPAL_SUCCESS; -} - -/* - * We can't enable or disable I/O and M32 dynamically, even - * unnecessary. So the function only support M64 BARs. - */ -static int64_t p7ioc_phb_mmio_enable(struct phb *phb, - uint16_t window_type, - uint16_t window_num, - uint16_t enable) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t data64, base, mask; - - switch (window_type) { - case OPAL_IO_WINDOW_TYPE: - case OPAL_M32_WINDOW_TYPE: - return OPAL_UNSUPPORTED; - case OPAL_M64_WINDOW_TYPE: - if (window_num >= 16 || - enable >= OPAL_ENABLE_M64_NON_SPLIT) - return OPAL_PARAMETER; - - break; - default: - return OPAL_PARAMETER; - } - - /* - * While enabling one specific M64 BAR, we should have - * the base/size configured correctly. Otherwise, it - * probably incurs fenced AIB. - */ - data64 = p->m64b_cache[window_num]; - if (enable == OPAL_ENABLE_M64_SPLIT) { - base = GETFIELD(IODA_M64BT_BASE, data64); - base = (base << 24); - mask = GETFIELD(IODA_M64BT_MASK, data64); - if (base < p->m64_base || mask == 0x0ul) - return OPAL_PARTIAL; - - data64 |= IODA_M64BT_ENABLE; - } else if (enable == OPAL_DISABLE_M64) { - data64 &= ~IODA_M64BT_ENABLE; - } - - p7ioc_phb_ioda_sel(p, IODA_TBL_M64BT, window_num, false); - out_be64(p->regs + PHB_IODA_DATA0, data64); - p->m64b_cache[window_num] = data64; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_map_pe_mmio_window(struct phb *phb, uint64_t pe_number, - uint16_t window_type, - uint16_t window_num, - uint16_t segment_num) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t tbl, index; - uint64_t *cache; - - if (pe_number > 127) - return OPAL_PARAMETER; - - switch(window_type) { - case OPAL_IO_WINDOW_TYPE: - if (window_num != 0 || segment_num > 127) - return OPAL_PARAMETER; - tbl = IODA_TBL_IODT; - index = segment_num; - cache = &p->iod_cache[index]; - break; - case OPAL_M32_WINDOW_TYPE: - if (window_num != 0 || segment_num > 127) - return OPAL_PARAMETER; - tbl = IODA_TBL_M32DT; - index = segment_num; - cache = &p->m32d_cache[index]; - break; - case OPAL_M64_WINDOW_TYPE: - if (window_num > 15 || segment_num > 7) - return OPAL_PARAMETER; - - tbl = IODA_TBL_M64DT; - index = window_num << 3 | segment_num; - cache = &p->m64d_cache[index]; - break; - default: - return OPAL_PARAMETER; - } - - p7ioc_phb_ioda_sel(p, tbl, index, false); - out_be64(p->regs + PHB_IODA_DATA0, - SETFIELD(IODA_XXDT_PE, 0ull, pe_number)); - - /* Update cache */ - *cache = SETFIELD(IODA_XXDT_PE, 0ull, pe_number); - - return OPAL_SUCCESS; -} - - -static int64_t p7ioc_set_pe(struct phb *phb, uint64_t pe_number, - uint64_t bdfn, uint8_t bus_compare, - uint8_t dev_compare, uint8_t func_compare, - uint8_t pe_action) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t pelt; - uint64_t *cache = &p->peltm_cache[pe_number]; - - if (pe_number > 127 || bdfn > 0xffff) - return OPAL_PARAMETER; - if (pe_action != OPAL_MAP_PE && pe_action != OPAL_UNMAP_PE) - return OPAL_PARAMETER; - if (bus_compare > 7) - return OPAL_PARAMETER; - - if (pe_action == OPAL_MAP_PE) { - pelt = SETFIELD(IODA_PELTM_BUS, 0ul, bdfn >> 8); - pelt |= SETFIELD(IODA_PELTM_DEV, 0ul, (bdfn >> 3) & 0x1f); - pelt |= SETFIELD(IODA_PELTM_FUNC, 0ul, bdfn & 0x7); - pelt |= SETFIELD(IODA_PELTM_BUS_VALID, 0ul, bus_compare); - if (dev_compare) - pelt |= IODA_PELTM_DEV_VALID; - if (func_compare) - pelt |= IODA_PELTM_FUNC_VALID; - } else - pelt = 0; - - p7ioc_phb_ioda_sel(p, IODA_TBL_PELTM, pe_number, false); - out_be64(p->regs + PHB_IODA_DATA0, pelt); - - /* Update cache */ - *cache = pelt; - - return OPAL_SUCCESS; -} - - -static int64_t p7ioc_set_peltv(struct phb *phb, uint32_t parent_pe, - uint32_t child_pe, uint8_t state) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint32_t reg; - uint64_t mask, peltv; - uint64_t *cache; - if (parent_pe > 127 || child_pe > 127) - return OPAL_PARAMETER; - - cache = (child_pe >> 6) ? &p->peltv_hi_cache[parent_pe] : - &p->peltv_lo_cache[parent_pe]; - reg = (child_pe >> 6) ? PHB_IODA_DATA1 : PHB_IODA_DATA0; - child_pe &= 0x2f; - mask = 1ull << (63 - child_pe); - - p7ioc_phb_ioda_sel(p, IODA_TBL_PELTV, parent_pe, false); - peltv = in_be64(p->regs + reg); - if (state) - peltv |= mask; - else - peltv &= ~mask; - out_be64(p->regs + reg, peltv); - - /* Update cache */ - *cache = peltv; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_map_pe_dma_window(struct phb *phb, uint64_t pe_number, - uint16_t window_id, uint16_t tce_levels, - uint64_t tce_table_addr, - uint64_t tce_table_size, - uint64_t tce_page_size) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t tvt0, tvt1, t, pelt; - uint64_t dma_window_size; - uint64_t *cache_lo, *cache_hi; - - if (pe_number > 127 || window_id > 127 || tce_levels != 1) - return OPAL_PARAMETER; - cache_lo = &p->tve_lo_cache[window_id]; - cache_hi = &p->tve_hi_cache[window_id]; - - /* Encode table size */ - dma_window_size = tce_page_size * (tce_table_size >> 3); - t = ilog2(dma_window_size); - if (t < 27) - return OPAL_PARAMETER; - tvt0 = SETFIELD(IODA_TVT0_TCE_TABLE_SIZE, 0ul, (t - 26)); - - /* Encode TCE page size */ - switch(tce_page_size) { - case 0x1000: /* 4K */ - tvt1 = SETFIELD(IODA_TVT1_IO_PSIZE, 0ul, 1ul); - break; - case 0x10000: /* 64K */ - tvt1 = SETFIELD(IODA_TVT1_IO_PSIZE, 0ul, 5ul); - break; - case 0x1000000: /* 16M */ - tvt1 = SETFIELD(IODA_TVT1_IO_PSIZE, 0ul, 13ul); - break; - case 0x400000000UL: /* 16G */ - tvt1 = SETFIELD(IODA_TVT1_IO_PSIZE, 0ul, 23ul); - break; - default: - return OPAL_PARAMETER; - } - - /* XXX Hub number ... leave 0 for now */ - - /* Shift in the address. The table address is "off by 4 bits" - * but since the field is itself shifted by 16, we basically - * need to write the address >> 12, which basically boils down - * to writing a 4k page address - */ - tvt0 = SETFIELD(IODA_TVT0_TABLE_ADDR, tvt0, tce_table_addr >> 12); - - /* Read the PE filter info from the PELT-M */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PELTM, pe_number, false); - pelt = in_be64(p->regs + PHB_IODA_DATA0); - - /* Copy in filter bits from PELT */ - tvt0 = SETFIELD(IODA_TVT0_BUS_VALID, tvt0, - GETFIELD(IODA_PELTM_BUS_VALID, pelt)); - tvt0 = SETFIELD(IODA_TVT0_BUS_NUM, tvt0, - GETFIELD(IODA_PELTM_BUS, pelt)); - tvt1 = SETFIELD(IODA_TVT1_DEV_NUM, tvt1, - GETFIELD(IODA_PELTM_DEV, pelt)); - tvt1 = SETFIELD(IODA_TVT1_FUNC_NUM, tvt1, - GETFIELD(IODA_PELTM_FUNC, pelt)); - if (pelt & IODA_PELTM_DEV_VALID) - tvt1 |= IODA_TVT1_DEV_VALID; - if (pelt & IODA_PELTM_FUNC_VALID) - tvt1 |= IODA_TVT1_FUNC_VALID; - tvt1 = SETFIELD(IODA_TVT1_PE_NUM, tvt1, pe_number); - - /* Write the TVE */ - p7ioc_phb_ioda_sel(p, IODA_TBL_TVT, window_id, false); - out_be64(p->regs + PHB_IODA_DATA1, tvt1); - out_be64(p->regs + PHB_IODA_DATA0, tvt0); - - /* Update cache */ - *cache_lo = tvt0; - *cache_hi = tvt1; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_map_pe_dma_window_real(struct phb *phb __unused, - uint64_t pe_number __unused, - uint16_t dma_window_num __unused, - uint64_t pci_start_addr __unused, - uint64_t pci_mem_size __unused) -{ - /* XXX Not yet implemented (not yet used by Linux) */ - return OPAL_UNSUPPORTED; -} - -static int64_t p7ioc_set_mve(struct phb *phb, uint32_t mve_number, - uint64_t pe_number) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t pelt, mve = 0; - uint64_t *cache = &p->mve_cache[mve_number]; - - if (pe_number > 127 || mve_number > 255) - return OPAL_PARAMETER; - - /* Read the PE filter info from the PELT-M */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PELTM, pe_number, false); - pelt = in_be64(p->regs + PHB_IODA_DATA0); - - mve = SETFIELD(IODA_MVT_BUS_VALID, mve, - GETFIELD(IODA_PELTM_BUS_VALID, pelt)); - mve = SETFIELD(IODA_MVT_BUS_NUM, mve, - GETFIELD(IODA_PELTM_BUS, pelt)); - mve = SETFIELD(IODA_MVT_DEV_NUM, mve, - GETFIELD(IODA_PELTM_DEV, pelt)); - mve = SETFIELD(IODA_MVT_FUNC_NUM, mve, - GETFIELD(IODA_PELTM_FUNC, pelt)); - if (pelt & IODA_PELTM_DEV_VALID) - mve |= IODA_MVT_DEV_VALID; - if (pelt & IODA_PELTM_FUNC_VALID) - mve |= IODA_MVT_FUNC_VALID; - mve = SETFIELD(IODA_MVT_PE_NUM, mve, pe_number); - - p7ioc_phb_ioda_sel(p, IODA_TBL_MVT, mve_number, false); - out_be64(p->regs + PHB_IODA_DATA0, mve); - - /* Update cache */ - *cache = mve; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_set_mve_enable(struct phb *phb, uint32_t mve_number, - uint32_t state) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t mve; - uint64_t *cache = &p->mve_cache[mve_number]; - - if (mve_number > 255) - return OPAL_PARAMETER; - - p7ioc_phb_ioda_sel(p, IODA_TBL_MVT, mve_number, false); - mve = in_be64(p->regs + PHB_IODA_DATA0); - if (state) - mve |= IODA_MVT_VALID; - else - mve &= ~IODA_MVT_VALID; - out_be64(p->regs + PHB_IODA_DATA0, mve); - - /* Update cache */ - *cache = mve; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_set_xive_pe(struct phb *phb, uint64_t pe_number, - uint32_t xive_num) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - uint64_t xive; - - if (pe_number > 127 || xive_num > 255) - return OPAL_PARAMETER; - - /* Update MXIVE cache */ - xive = p->mxive_cache[xive_num]; - xive = SETFIELD(IODA_XIVT_PENUM, xive, pe_number); - p->mxive_cache[xive_num] = xive; - - /* Update HW */ - p7ioc_phb_ioda_sel(p, IODA_TBL_MXIVT, xive_num, false); - xive = in_be64(p->regs + PHB_IODA_DATA0); - xive = SETFIELD(IODA_XIVT_PENUM, xive, pe_number); - out_be64(p->regs + PHB_IODA_DATA0, xive); - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_get_msi_32(struct phb *phb __unused, uint64_t mve_number, - uint32_t xive_num, uint8_t msi_range, - uint32_t *msi_address, uint32_t *message_data) -{ - if (mve_number > 255 || xive_num > 255 || msi_range != 1) - return OPAL_PARAMETER; - - *msi_address = 0xffff0000 | (mve_number << 4); - *message_data = xive_num; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_get_msi_64(struct phb *phb __unused, uint64_t mve_number, - uint32_t xive_num, uint8_t msi_range, - uint64_t *msi_address, uint32_t *message_data) -{ - if (mve_number > 255 || xive_num > 255 || msi_range != 1) - return OPAL_PARAMETER; - - *msi_address = (9ul << 60) | (((u64)mve_number) << 48); - *message_data = xive_num; - - return OPAL_SUCCESS; -} - -static void p7ioc_root_port_init(struct phb *phb, struct pci_device *dev, - int ecap, int aercap) -{ - uint16_t bdfn = dev->bdfn; - uint16_t val16; - uint32_t val32; - - /* Enable SERR and parity checking */ - pci_cfg_read16(phb, bdfn, PCI_CFG_CMD, &val16); - val16 |= (PCI_CFG_CMD_SERR_EN | PCI_CFG_CMD_PERR_RESP); - pci_cfg_write16(phb, bdfn, PCI_CFG_CMD, val16); - - /* Enable reporting various errors */ - if (!ecap) return; - pci_cfg_read16(phb, bdfn, ecap + PCICAP_EXP_DEVCTL, &val16); - val16 |= (PCICAP_EXP_DEVCTL_CE_REPORT | - PCICAP_EXP_DEVCTL_NFE_REPORT | - PCICAP_EXP_DEVCTL_FE_REPORT | - PCICAP_EXP_DEVCTL_UR_REPORT); - pci_cfg_write16(phb, bdfn, ecap + PCICAP_EXP_DEVCTL, val16); - - /* Mask various unrecoverable errors */ - if (!aercap) return; - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_UE_MASK, &val32); - val32 |= (PCIECAP_AER_UE_MASK_POISON_TLP | - PCIECAP_AER_UE_MASK_COMPL_TIMEOUT | - PCIECAP_AER_UE_MASK_COMPL_ABORT | - PCIECAP_AER_UE_MASK_ECRC); - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_UE_MASK, val32); - - /* Report various unrecoverable errors as fatal errors */ - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_UE_SEVERITY, &val32); - val32 |= (PCIECAP_AER_UE_SEVERITY_DLLP | - PCIECAP_AER_UE_SEVERITY_SURPRISE_DOWN | - PCIECAP_AER_UE_SEVERITY_FLOW_CTL_PROT | - PCIECAP_AER_UE_SEVERITY_UNEXP_COMPL | - PCIECAP_AER_UE_SEVERITY_RECV_OVFLOW | - PCIECAP_AER_UE_SEVERITY_MALFORMED_TLP); - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_UE_SEVERITY, val32); - - /* Mask various recoverable errors */ - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_CE_MASK, &val32); - val32 |= PCIECAP_AER_CE_MASK_ADV_NONFATAL; - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_CE_MASK, val32); - - /* Enable ECRC check */ - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_CAPCTL, &val32); - val32 |= (PCIECAP_AER_CAPCTL_ECRCG_EN | - PCIECAP_AER_CAPCTL_ECRCC_EN); - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_CAPCTL, val32); - - /* Enable all error reporting */ - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_RERR_CMD, &val32); - val32 |= (PCIECAP_AER_RERR_CMD_FE | - PCIECAP_AER_RERR_CMD_NFE | - PCIECAP_AER_RERR_CMD_CE); - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_RERR_CMD, val32); -} - -static void p7ioc_switch_port_init(struct phb *phb, - struct pci_device *dev, - int ecap, int aercap) -{ - uint16_t bdfn = dev->bdfn; - uint16_t val16; - uint32_t val32; - - /* Enable SERR and parity checking and disable INTx */ - pci_cfg_read16(phb, bdfn, PCI_CFG_CMD, &val16); - val16 |= (PCI_CFG_CMD_PERR_RESP | - PCI_CFG_CMD_SERR_EN | - PCI_CFG_CMD_INTx_DIS); - pci_cfg_write16(phb, bdfn, PCI_CFG_CMD, val16); - - /* Disable partity error and enable system error */ - pci_cfg_read16(phb, bdfn, PCI_CFG_BRCTL, &val16); - val16 &= ~PCI_CFG_BRCTL_PERR_RESP_EN; - val16 |= PCI_CFG_BRCTL_SERR_EN; - pci_cfg_write16(phb, bdfn, PCI_CFG_BRCTL, val16); - - /* Enable reporting various errors */ - if (!ecap) return; - pci_cfg_read16(phb, bdfn, ecap + PCICAP_EXP_DEVCTL, &val16); - val16 |= (PCICAP_EXP_DEVCTL_CE_REPORT | - PCICAP_EXP_DEVCTL_NFE_REPORT | - PCICAP_EXP_DEVCTL_FE_REPORT); - pci_cfg_write16(phb, bdfn, ecap + PCICAP_EXP_DEVCTL, val16); - - /* Unmask all unrecoverable errors */ - if (!aercap) return; - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_UE_MASK, 0x0); - - /* Severity of unrecoverable errors */ - if (dev->dev_type == PCIE_TYPE_SWITCH_UPPORT) - val32 = (PCIECAP_AER_UE_SEVERITY_DLLP | - PCIECAP_AER_UE_SEVERITY_SURPRISE_DOWN | - PCIECAP_AER_UE_SEVERITY_FLOW_CTL_PROT | - PCIECAP_AER_UE_SEVERITY_RECV_OVFLOW | - PCIECAP_AER_UE_SEVERITY_MALFORMED_TLP | - PCIECAP_AER_UE_SEVERITY_INTERNAL); - else - val32 = (PCIECAP_AER_UE_SEVERITY_FLOW_CTL_PROT | - PCIECAP_AER_UE_SEVERITY_INTERNAL); - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_UE_SEVERITY, val32); - - /* Mask various correctable errors */ - val32 = PCIECAP_AER_CE_MASK_ADV_NONFATAL; - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_CE_MASK, val32); - - /* Enable ECRC generation and disable ECRC check */ - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_CAPCTL, &val32); - val32 |= PCIECAP_AER_CAPCTL_ECRCG_EN; - val32 &= ~PCIECAP_AER_CAPCTL_ECRCC_EN; - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_CAPCTL, val32); -} - -static void p7ioc_endpoint_init(struct phb *phb, - struct pci_device *dev, - int ecap, int aercap) -{ - uint16_t bdfn = dev->bdfn; - uint16_t val16; - uint32_t val32; - - /* Enable SERR and parity checking */ - pci_cfg_read16(phb, bdfn, PCI_CFG_CMD, &val16); - val16 |= (PCI_CFG_CMD_PERR_RESP | - PCI_CFG_CMD_SERR_EN); - pci_cfg_write16(phb, bdfn, PCI_CFG_CMD, val16); - - /* Enable reporting various errors */ - if (!ecap) return; - pci_cfg_read16(phb, bdfn, ecap + PCICAP_EXP_DEVCTL, &val16); - val16 &= ~PCICAP_EXP_DEVCTL_CE_REPORT; - val16 |= (PCICAP_EXP_DEVCTL_NFE_REPORT | - PCICAP_EXP_DEVCTL_FE_REPORT | - PCICAP_EXP_DEVCTL_UR_REPORT); - pci_cfg_write16(phb, bdfn, ecap + PCICAP_EXP_DEVCTL, val16); - - /* Enable ECRC generation and check */ - pci_cfg_read32(phb, bdfn, aercap + PCIECAP_AER_CAPCTL, &val32); - val32 |= (PCIECAP_AER_CAPCTL_ECRCG_EN | - PCIECAP_AER_CAPCTL_ECRCC_EN); - pci_cfg_write32(phb, bdfn, aercap + PCIECAP_AER_CAPCTL, val32); -} - -static int p7ioc_device_init(struct phb *phb, - struct pci_device *dev, - void *data __unused) -{ - int ecap, aercap; - - /* Common initialization for the device */ - pci_device_init(phb, dev); - - ecap = pci_cap(dev, PCI_CFG_CAP_ID_EXP, false); - aercap = pci_cap(dev, PCIECAP_ID_AER, true); - if (dev->dev_type == PCIE_TYPE_ROOT_PORT) - p7ioc_root_port_init(phb, dev, ecap, aercap); - else if (dev->dev_type == PCIE_TYPE_SWITCH_UPPORT || - dev->dev_type == PCIE_TYPE_SWITCH_DNPORT) - p7ioc_switch_port_init(phb, dev, ecap, aercap); - else - p7ioc_endpoint_init(phb, dev, ecap, aercap); - - return 0; -} - -static int64_t p7ioc_pci_reinit(struct phb *phb, - uint64_t scope, uint64_t data) -{ - struct pci_device *pd; - uint16_t bdfn = data; - int ret; - - if (scope != OPAL_REINIT_PCI_DEV) - return OPAL_PARAMETER; - - pd = pci_find_dev(phb, bdfn); - if (!pd) - return OPAL_PARAMETER; - - ret = p7ioc_device_init(phb, pd, NULL); - if (ret) - return OPAL_HARDWARE; - - return OPAL_SUCCESS; -} - -static uint8_t p7ioc_choose_bus(struct phb *phb __unused, - struct pci_device *bridge, - uint8_t candidate, uint8_t *max_bus, - bool *use_max) -{ - uint8_t m, al; - int i; - - /* Bus number selection is nasty on P7IOC. Our EEH HW can only cope - * with bus ranges that are naturally aligned powers of two. It also - * has "issues" with dealing with more than 32 bus numbers. - * - * On the other hand we can deal with overlaps to some extent as - * the PELT-M entries are ordered. - * - * We also don't need to bother with the busses between the upstream - * and downstream ports of switches. - * - * For now we apply this simple mechanism which matche what OFW does - * under OPAL: - * - * - Top level bus (PHB to RC) is 0 - * - RC to first device is 1..ff - * - Then going down, a switch gets (N = parent bus, M = parent max) - * * Upstream bridge is N+1, M, use_max = false - * * Downstream bridge is closest power of two from 32 down and - * * use max - * - * XXX NOTE: If we have access to HW VPDs, we could know whether - * this is a bridge with a single device on it such as IPR and - * limit ourselves to a single bus number. - */ - - /* Default use_max is false (legacy) */ - *use_max = false; - - /* If we are the root complex or we are not in PCIe land anymore, just - * use legacy algorithm - */ - if (!bridge || !pci_has_cap(bridge, PCI_CFG_CAP_ID_EXP, false)) - return candidate; - - /* Figure out the bridge type */ - switch(bridge->dev_type) { - case PCIE_TYPE_PCIX_TO_PCIE: - /* PCI-X to PCIE ... hrm, let's not bother too much with that */ - return candidate; - case PCIE_TYPE_SWITCH_UPPORT: - case PCIE_TYPE_ROOT_PORT: - /* Upstream port, we use legacy handling as well */ - return candidate; - case PCIE_TYPE_SWITCH_DNPORT: - case PCIE_TYPE_PCIE_TO_PCIX: - /* That leaves us with the interesting cases that we handle */ - break; - default: - /* Should not happen, treat as legacy */ - prerror("PCI: Device %04x has unsupported type %d in choose_bus\n", - bridge->bdfn, bridge->dev_type); - return candidate; - } - - /* Ok, let's find a power of two that fits, fallback to 1 */ - for (i = 5; i >= 0; i--) { - m = (1 << i) - 1; - al = (candidate + m) & ~m; - if (al <= *max_bus && (al + m) <= *max_bus) - break; - } - if (i < 0) - return 0; - *use_max = true; - *max_bus = al + m; - return al; -} - -static int64_t p7ioc_get_reserved_pe_number(struct phb *phb __unused) -{ - return 127; -} - -/* p7ioc_phb_init_ioda_cache - Reset the IODA cache values - */ -static void p7ioc_phb_init_ioda_cache(struct p7ioc_phb *p) -{ - unsigned int i; - - for (i = 0; i < 8; i++) - p->lxive_cache[i] = SETFIELD(IODA_XIVT_PRIORITY, 0ull, 0xff); - for (i = 0; i < 256; i++) { - p->mxive_cache[i] = SETFIELD(IODA_XIVT_PRIORITY, 0ull, 0xff); - p->mve_cache[i] = 0; - } - for (i = 0; i < 16; i++) - p->m64b_cache[i] = 0; - - /* - * Since there is only one root port under the PHB, - * We make all PELTM entries except last one to be - * invalid by configuring their RID to 00:00.1. The - * last entry is to encompass all RIDs. - */ - for (i = 0; i < 127; i++) - p->peltm_cache[i] = 0x0001f80000000000UL; - p->peltm_cache[127] = 0x0ul; - - for (i = 0; i < 128; i++) { - p->peltv_lo_cache[i] = 0; - p->peltv_hi_cache[i] = 0; - p->tve_lo_cache[i] = 0; - p->tve_hi_cache[i] = 0; - p->iod_cache[i] = 0; - p->m32d_cache[i] = 0; - p->m64d_cache[i] = 0; - } -} - -/* p7ioc_phb_ioda_reset - Reset the IODA tables - * - * @purge: If true, the cache is cleared and the cleared values - * are applied to HW. If false, the cached values are - * applied to HW - * - * This reset the IODA tables in the PHB. It is called at - * initialization time, on PHB reset, and can be called - * explicitly from OPAL - */ -static int64_t p7ioc_ioda_reset(struct phb *phb, bool purge) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - unsigned int i; - uint64_t reg64; - uint64_t data64, data64_hi; - uint8_t prio; - uint16_t server; - uint64_t m_server, m_prio; - - /* If the "purge" argument is set, we clear the table cache */ - if (purge) - p7ioc_phb_init_ioda_cache(p); - - /* Init_18..19: Setup the HRT - * - * XXX NOTE: I still don't completely get that HRT business so - * I'll just mimmic BML and put the PHB number + 1 in there - */ - p7ioc_phb_ioda_sel(p, IODA_TBL_HRT, 0, true); - out_be64(p->regs + PHB_IODA_DATA0, p->index + 1); - out_be64(p->regs + PHB_IODA_DATA0, p->index + 1); - out_be64(p->regs + PHB_IODA_DATA0, p->index + 1); - out_be64(p->regs + PHB_IODA_DATA0, p->index + 1); - - /* Init_20..21: Cleanup the LXIVT - * - * We set the priority to FF (masked) and clear everything - * else. That means we leave the HRT index to 0 which is - * going to remain unmodified... for now. - */ - p7ioc_phb_ioda_sel(p, IODA_TBL_LXIVT, 0, true); - for (i = 0; i < 8; i++) { - data64 = p->lxive_cache[i]; - server = GETFIELD(IODA_XIVT_SERVER, data64); - prio = GETFIELD(IODA_XIVT_PRIORITY, data64); - - /* Now we mangle the server and priority */ - if (prio == 0xff) { - m_server = 0; - m_prio = 0xff; - } else { - m_server = server >> 3; - m_prio = (prio >> 3) | ((server & 7) << 5); - } - - data64 = SETFIELD(IODA_XIVT_SERVER, data64, m_server); - data64 = SETFIELD(IODA_XIVT_PRIORITY, data64, m_prio); - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_22..23: Cleanup the MXIVT - * - * We set the priority to FF (masked) and clear everything - * else. That means we leave the HRT index to 0 which is - * going to remain unmodified... for now. - */ - p7ioc_phb_ioda_sel(p, IODA_TBL_MXIVT, 0, true); - for (i = 0; i < 256; i++) { - data64 = p->mxive_cache[i]; - server = GETFIELD(IODA_XIVT_SERVER, data64); - prio = GETFIELD(IODA_XIVT_PRIORITY, data64); - - /* Now we mangle the server and priority */ - if (prio == 0xff) { - m_server = 0; - m_prio = 0xff; - } else { - m_server = server >> 3; - m_prio = (prio >> 3) | ((server & 7) << 5); - } - - data64 = SETFIELD(IODA_XIVT_SERVER, data64, m_server); - data64 = SETFIELD(IODA_XIVT_PRIORITY, data64, m_prio); - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_24..25: Cleanup the MVT */ - p7ioc_phb_ioda_sel(p, IODA_TBL_MVT, 0, true); - for (i = 0; i < 256; i++) { - data64 = p->mve_cache[i]; - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_26..27: Cleanup the PELTM - * - * A completely clear PELTM should make everything match PE 0 - */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PELTM, 0, true); - for (i = 0; i < 127; i++) { - data64 = p->peltm_cache[i]; - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_28..30: Cleanup the PELTV */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PELTV, 0, true); - for (i = 0; i < 127; i++) { - data64 = p->peltv_lo_cache[i]; - data64_hi = p->peltv_hi_cache[i]; - out_be64(p->regs + PHB_IODA_DATA1, data64_hi); - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_31..33: Cleanup the TVT */ - p7ioc_phb_ioda_sel(p, IODA_TBL_TVT, 0, true); - for (i = 0; i < 127; i++) { - data64 = p->tve_lo_cache[i]; - data64_hi = p->tve_hi_cache[i]; - out_be64(p->regs + PHB_IODA_DATA1, data64_hi); - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_34..35: Cleanup the M64BT - * - * We don't enable M64 BARs by default. However, - * we shouldn't purge the hw and cache for it in - * future. - */ - p7ioc_phb_ioda_sel(p, IODA_TBL_M64BT, 0, true); - for (i = 0; i < 16; i++) - out_be64(p->regs + PHB_IODA_DATA0, 0); - - /* Init_36..37: Cleanup the IODT */ - p7ioc_phb_ioda_sel(p, IODA_TBL_IODT, 0, true); - for (i = 0; i < 127; i++) { - data64 = p->iod_cache[i]; - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_38..39: Cleanup the M32DT */ - p7ioc_phb_ioda_sel(p, IODA_TBL_M32DT, 0, true); - for (i = 0; i < 127; i++) { - data64 = p->m32d_cache[i]; - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Init_40..41: Cleanup the M64DT */ - p7ioc_phb_ioda_sel(p, IODA_TBL_M64BT, 0, true); - for (i = 0; i < 16; i++) { - data64 = p->m64b_cache[i]; - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - p7ioc_phb_ioda_sel(p, IODA_TBL_M64DT, 0, true); - for (i = 0; i < 127; i++) { - data64 = p->m64d_cache[i]; - out_be64(p->regs + PHB_IODA_DATA0, data64); - } - - /* Clear up the TCE cache */ - reg64 = in_be64(p->regs + PHB_PHB2_CONFIG); - reg64 &= ~PHB_PHB2C_64B_TCE_EN; - out_be64(p->regs + PHB_PHB2_CONFIG, reg64); - reg64 |= PHB_PHB2C_64B_TCE_EN; - out_be64(p->regs + PHB_PHB2_CONFIG, reg64); - in_be64(p->regs + PHB_PHB2_CONFIG); - - /* Clear PEST & PEEV */ - for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { - uint64_t pesta, pestb; - - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTA, i, false); - pesta = in_be64(p->regs + PHB_IODA_DATA0); - out_be64(p->regs + PHB_IODA_DATA0, 0); - p7ioc_phb_ioda_sel(p, IODA_TBL_PESTB, i, false); - pestb = in_be64(p->regs + PHB_IODA_DATA0); - out_be64(p->regs + PHB_IODA_DATA0, 0); - - if ((pesta & IODA_PESTA_MMIO_FROZEN) || - (pestb & IODA_PESTB_DMA_STOPPED)) - PHBDBG(p, "Frozen PE#%x (%s - %s)\n", - i, (pestb & IODA_PESTB_DMA_STOPPED) ? "DMA" : "", - (pesta & IODA_PESTA_MMIO_FROZEN) ? "MMIO" : ""); - } - - p7ioc_phb_ioda_sel(p, IODA_TBL_PEEV, 0, true); - for (i = 0; i < 2; i++) - out_be64(p->regs + PHB_IODA_DATA0, 0); - - return OPAL_SUCCESS; -} - -/* - * Clear anything we have in PAPR Error Injection registers. Though - * the spec says the PAPR error injection should be one-shot without - * the "sticky" bit. However, that's false according to the experiments - * I had. So we have to clear it at appropriate point in kernel to - * avoid endless frozen PE. - */ -static int64_t p7ioc_papr_errinjct_reset(struct phb *phb) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - - out_be64(p->regs + PHB_PAPR_ERR_INJ_CTL, 0x0ul); - out_be64(p->regs + PHB_PAPR_ERR_INJ_ADDR, 0x0ul); - out_be64(p->regs + PHB_PAPR_ERR_INJ_MASK, 0x0ul); - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_get_presence_state(struct pci_slot *slot, uint8_t *val) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint64_t reg; - - reg = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - if (reg & PHB_PCIE_SLOTCTL2_PRSTN_STAT) - *val = OPAL_PCI_SLOT_PRESENT; - else - *val = OPAL_PCI_SLOT_EMPTY; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_get_link_state(struct pci_slot *slot, uint8_t *val) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint64_t reg64; - uint16_t state; - int64_t rc; - - /* Check if the link training is completed */ - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - if (!(reg64 & PHB_PCIE_DLP_TC_DL_LINKACT)) { - *val = 0; - return OPAL_SUCCESS; - } - - /* Grab link width from PCIe capability */ - rc = p7ioc_pcicfg_read16(&p->phb, 0, p->ecap + PCICAP_EXP_LSTAT, - &state); - if (rc < 0) { - PHBERR(p, "%s: Error %lld reading link status\n", - __func__, rc); - return OPAL_HARDWARE; - } - - if (state & PCICAP_EXP_LSTAT_DLLL_ACT) - *val = ((state & PCICAP_EXP_LSTAT_WIDTH) >> 4); - else - *val = 0; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_get_power_state(struct pci_slot *slot, uint8_t *val) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint64_t reg64; - - reg64 = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - if (reg64 & PHB_PCIE_SLOTCTL2_PWR_EN_STAT) - *val = PCI_SLOT_POWER_ON; - else - *val = PCI_SLOT_POWER_OFF; - - return OPAL_SUCCESS; -} - -static int64_t p7ioc_set_power_state(struct pci_slot *slot, uint8_t val) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint64_t reg64; - uint8_t state = PCI_SLOT_POWER_OFF; - - if (val != PCI_SLOT_POWER_OFF && val != PCI_SLOT_POWER_ON) - return OPAL_PARAMETER; - - /* If the power state has been put into the requested one */ - reg64 = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - if (reg64 & PHB_PCIE_SLOTCTL2_PWR_EN_STAT) - state = PCI_SLOT_POWER_ON; - if (state == val) - return OPAL_SUCCESS; - - /* Power on/off */ - if (val == PCI_SLOT_POWER_ON) { - reg64 &= ~(0x8c00000000000000ul); - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - reg64 |= 0x8400000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - } else { - reg64 &= ~(0x8c00000000000000ul); - reg64 |= 0x8400000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - reg64 &= ~(0x8c00000000000000ul); - reg64 |= 0x0c00000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - } - - return OPAL_SUCCESS; -} - -static void p7ioc_prepare_link_change(struct pci_slot *slot, bool up) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint64_t ci_idx = p->index + 2; - uint32_t cfg32; - - if (!up) { - /* Mask PCIE port interrupts and AER receiver error */ - out_be64(p->regs + UTL_PCIE_PORT_IRQ_EN, 0x7E00000000000000UL); - p7ioc_pcicfg_read32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, &cfg32); - cfg32 |= PCIECAP_AER_CE_RECVR_ERR; - p7ioc_pcicfg_write32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, cfg32); - - /* Mask CI port error and clear it */ - out_be64(p->ioc->regs + P7IOC_CIn_LEM_ERR_MASK(ci_idx), - 0xa4f4000000000000ul); - out_be64(p->regs + PHB_LEM_ERROR_MASK, - 0xadb650c9808dd051ul); - out_be64(p->ioc->regs + P7IOC_CIn_LEM_FIR(ci_idx), - 0x0ul); - - /* Block access to PCI-CFG space */ - p->flags |= P7IOC_PHB_CFG_BLOCKED; - } else { - /* Clear spurious errors and enable PCIE port interrupts */ - out_be64(p->regs + UTL_PCIE_PORT_STATUS, 0x00E0000000000000UL); - out_be64(p->regs + UTL_PCIE_PORT_IRQ_EN, 0xFE65000000000000UL); - - /* Clear AER receiver error status */ - p7ioc_pcicfg_write32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_STATUS, - PCIECAP_AER_CE_RECVR_ERR); - /* Unmask receiver error status in AER */ - p7ioc_pcicfg_read32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, &cfg32); - cfg32 &= ~PCIECAP_AER_CE_RECVR_ERR; - p7ioc_pcicfg_write32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, cfg32); - /* Clear and Unmask CI port and PHB errors */ - out_be64(p->ioc->regs + P7IOC_CIn_LEM_FIR(ci_idx), 0x0ul); - out_be64(p->regs + PHB_LEM_FIR_ACCUM, 0x0ul); - out_be64(p->ioc->regs + P7IOC_CIn_LEM_ERR_MASK_AND(ci_idx), - 0x0ul); - out_be64(p->regs + PHB_LEM_ERROR_MASK, 0x1249a1147f500f2cul); - - /* Don't block access to PCI-CFG space */ - p->flags &= ~P7IOC_PHB_CFG_BLOCKED; - - /* Restore slot's state */ - pci_slot_set_state(slot, P7IOC_SLOT_NORMAL); - - /* - * We might lose the bus numbers in the reset and we need - * restore the bus numbers. Otherwise, some adpaters (e.g. - * IPR) can't be probed properly by kernel. We don't need - * restore bus numbers for all kinds of resets. However, - * it's not harmful to restore the bus numbers, which makes - * the logic simplified - */ - pci_restore_bridge_buses(slot->phb, slot->pd); - if (slot->phb->ops->device_init) - pci_walk_dev(slot->phb, slot->pd, - slot->phb->ops->device_init, NULL); - } -} - -static int64_t p7ioc_poll_link(struct pci_slot *slot) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint64_t reg64; - - switch (slot->state) { - case P7IOC_SLOT_NORMAL: - case P7IOC_SLOT_LINK_START: - PHBDBG(p, "LINK: Start polling\n"); - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - reg64 &= ~PHB_PCIE_DLP_TCTX_DISABLE; - out_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL, reg64); - slot->retries = 100; - pci_slot_set_state(slot, P7IOC_SLOT_LINK_WAIT); - return pci_slot_set_sm_timeout(slot, msecs_to_tb(10)); - case P7IOC_SLOT_LINK_WAIT: - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - if (reg64 & PHB_PCIE_DLP_TC_DL_LINKACT) { - PHBDBG(p, "LINK: Up\n"); - slot->ops.prepare_link_change(slot, true); - return OPAL_SUCCESS; - } - - if (slot->retries-- == 0) { - PHBERR(p, "LINK: Timeout waiting for link up\n"); - goto out; - } - return pci_slot_set_sm_timeout(slot, msecs_to_tb(10)); - default: - PHBERR(p, "LINK: Unexpected slot state %08x\n", - slot->state); - } - -out: - pci_slot_set_state(slot, P7IOC_SLOT_NORMAL); - return OPAL_HARDWARE; -} - -static int64_t p7ioc_hreset(struct pci_slot *slot) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint8_t presence = 1; - uint16_t brctl; - uint64_t reg64; - - switch (slot->state) { - case P7IOC_SLOT_NORMAL: - PHBDBG(p, "HRESET: Starts\n"); - if (slot->ops.get_presence_state) - slot->ops.get_presence_state(slot, &presence); - if (!presence) { - PHBDBG(p, "HRESET: No device\n"); - return OPAL_SUCCESS; - } - - PHBDBG(p, "HRESET: Prepare for link down\n"); - slot->ops.prepare_link_change(slot, false); - - /* Disable link to avoid training issues */ - PHBDBG(p, "HRESET: Disable link training\n"); - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - reg64 |= PHB_PCIE_DLP_TCTX_DISABLE; - out_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL, reg64); - pci_slot_set_state(slot, P7IOC_SLOT_HRESET_TRAINING); - slot->retries = 15; - /* fall through */ - case P7IOC_SLOT_HRESET_TRAINING: - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - if (!(reg64 & PHB_PCIE_DLP_TCRX_DISABLED)) { - if (slot->retries -- == 0) { - PHBERR(p, "HRESET: Timeout disabling link training\n"); - goto out; - } - - return pci_slot_set_sm_timeout(slot, msecs_to_tb(10)); - } - /* fall through */ - case P7IOC_SLOT_HRESET_START: - PHBDBG(p, "HRESET: Assert\n"); - p7ioc_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &brctl); - brctl |= PCI_CFG_BRCTL_SECONDARY_RESET; - p7ioc_pcicfg_write16(&p->phb, 0, PCI_CFG_BRCTL, brctl); - - pci_slot_set_state(slot, P7IOC_SLOT_HRESET_DELAY); - return pci_slot_set_sm_timeout(slot, secs_to_tb(1)); - case P7IOC_SLOT_HRESET_DELAY: - PHBDBG(p, "HRESET: Deassert\n"); - p7ioc_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &brctl); - brctl &= ~PCI_CFG_BRCTL_SECONDARY_RESET; - p7ioc_pcicfg_write16(&p->phb, 0, PCI_CFG_BRCTL, brctl); - pci_slot_set_state(slot, P7IOC_SLOT_HRESET_DELAY2); - return pci_slot_set_sm_timeout(slot, msecs_to_tb(200)); - case P7IOC_SLOT_HRESET_DELAY2: - pci_slot_set_state(slot, P7IOC_SLOT_LINK_START); - return slot->ops.poll_link(slot); - default: - PHBERR(p, "HRESET: Unexpected slot state %08x\n", - slot->state); - } - -out: - pci_slot_set_state(slot, P7IOC_SLOT_NORMAL); - return OPAL_HARDWARE; -} - -static int64_t p7ioc_freset(struct pci_slot *slot) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - uint8_t presence = 1; - uint64_t reg64; - - switch (slot->state) { - case P7IOC_SLOT_NORMAL: - case P7IOC_SLOT_FRESET_START: - PHBDBG(p, "FRESET: Starts\n"); - if (slot->ops.get_presence_state) - slot->ops.get_presence_state(slot, &presence); - if (!presence) { - PHBDBG(p, "FRESET: No device\n"); - pci_slot_set_state(slot, P7IOC_SLOT_NORMAL); - return OPAL_SUCCESS; - } - - PHBDBG(p, "FRESET: Prepare for link down\n"); - slot->ops.prepare_link_change(slot, false); - - /* Check power state */ - reg64 = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - if (reg64 & PHB_PCIE_SLOTCTL2_PWR_EN_STAT) { - PHBDBG(p, "FRESET: Power on, turn off\n"); - reg64 = in_be64(p->regs + PHB_HOTPLUG_OVERRIDE); - reg64 &= ~(0x8c00000000000000ul); - reg64 |= 0x8400000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - reg64 &= ~(0x8c00000000000000ul); - reg64 |= 0x0c00000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - pci_slot_set_state(slot, P7IOC_SLOT_FRESET_POWER_OFF); - return pci_slot_set_sm_timeout(slot, secs_to_tb(2)); - } - /* fall through */ - case P7IOC_SLOT_FRESET_POWER_OFF: - PHBDBG(p, "FRESET: Power off, turn on\n"); - reg64 = in_be64(p->regs + PHB_HOTPLUG_OVERRIDE); - reg64 &= ~(0x8c00000000000000ul); - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - reg64 |= 0x8400000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg64); - pci_slot_set_state(slot, P7IOC_SLOT_FRESET_POWER_ON); - return pci_slot_set_sm_timeout(slot, secs_to_tb(2)); - case P7IOC_SLOT_FRESET_POWER_ON: - PHBDBG(p, "FRESET: Disable link training\n"); - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - reg64 |= PHB_PCIE_DLP_TCTX_DISABLE; - out_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL, reg64); - pci_slot_set_state(slot, P7IOC_SLOT_HRESET_TRAINING); - slot->retries = 200; - /* fall through */ - case P7IOC_SLOT_HRESET_TRAINING: - reg64 = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - if (!(reg64 & PHB_PCIE_DLP_TCRX_DISABLED)) { - if (slot->retries -- == 0) { - PHBERR(p, "HRESET: Timeout disabling link training\n"); - goto out; - } - - return pci_slot_set_sm_timeout(slot, msecs_to_tb(10)); - } - - PHBDBG(p, "FRESET: Assert\n"); - reg64 = in_be64(p->regs + PHB_RESET); - reg64 &= ~0x2000000000000000ul; - out_be64(p->regs + PHB_RESET, reg64); - pci_slot_set_state(slot, P7IOC_SLOT_FRESET_ASSERT); - return pci_slot_set_sm_timeout(slot, secs_to_tb(1)); - case P7IOC_SLOT_FRESET_ASSERT: - PHBDBG(p, "FRESET: Deassert\n"); - reg64 = in_be64(p->regs + PHB_RESET); - reg64 |= 0x2000000000000000ul; - out_be64(p->regs + PHB_RESET, reg64); - - pci_slot_set_state(slot, P7IOC_SLOT_LINK_START); - return slot->ops.poll_link(slot); - default: - PHBERR(p, "FRESET: Unexpected slot state %08x\n", - slot->state); - } - -out: - pci_slot_set_state(slot, P7IOC_SLOT_NORMAL); - return OPAL_HARDWARE; -} - -static int64_t p7ioc_creset(struct pci_slot *slot) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(slot->phb); - struct p7ioc *ioc = p->ioc; - uint64_t reg64; - - switch (slot->state) { - case P7IOC_SLOT_NORMAL: - PHBDBG(p, "CRESET: Starts\n"); - p->flags |= P7IOC_PHB_CFG_BLOCKED; - p7ioc_phb_reset(slot->phb); - - /* - * According to the experiment, we probably still have the - * fenced state with the corresponding PHB in the Fence WOF - * and we need clear that explicitly. Besides, the RGC might - * already have informational error and we should clear that - * explicitly as well. Otherwise, RGC XIVE#0 won't issue - * interrupt any more. - */ - reg64 = in_be64(ioc->regs + P7IOC_CHIP_FENCE_WOF); - reg64 &= ~PPC_BIT(15 + p->index * 4); - out_be64(ioc->regs + P7IOC_CHIP_FENCE_WOF, reg64); - - /* Clear informational error from RGC */ - reg64 = in_be64(ioc->regs + P7IOC_RGC_LEM_BASE + - P7IOC_LEM_WOF_OFFSET); - reg64 &= ~PPC_BIT(18); - out_be64(ioc->regs + P7IOC_RGC_LEM_BASE + - P7IOC_LEM_WOF_OFFSET, reg64); - reg64 = in_be64(ioc->regs + P7IOC_RGC_LEM_BASE + - P7IOC_LEM_FIR_OFFSET); - reg64 &= ~PPC_BIT(18); - out_be64(ioc->regs + P7IOC_RGC_LEM_BASE + - P7IOC_LEM_FIR_OFFSET, reg64); - - /* Swith to fundamental reset */ - pci_slot_set_state(slot, P7IOC_SLOT_FRESET_START); - return slot->ops.freset(slot); - default: - PHBERR(p, "CRESET: Unexpected slot state %08x\n", - slot->state); - } - - pci_slot_set_state(slot, P7IOC_SLOT_NORMAL); - return OPAL_HARDWARE; -} - -static struct pci_slot *p7ioc_phb_slot_create(struct phb *phb) -{ - struct pci_slot *slot; - - slot = pci_slot_alloc(phb, NULL); - if (!slot) - return NULL; - - /* Elementary functions */ - slot->ops.get_presence_state = p7ioc_get_presence_state; - slot->ops.get_link_state = p7ioc_get_link_state; - slot->ops.get_power_state = p7ioc_get_power_state; - slot->ops.get_attention_state = NULL; - slot->ops.get_latch_state = NULL; - slot->ops.set_power_state = p7ioc_set_power_state; - slot->ops.set_attention_state = NULL; - - /* - * For PHB slots, we have to split the fundamental reset - * into 2 steps. We might not have the first step which - * is to power off/on the slot, or it's controlled by - * individual platforms. - */ - slot->ops.prepare_link_change = p7ioc_prepare_link_change; - slot->ops.poll_link = p7ioc_poll_link; - slot->ops.hreset = p7ioc_hreset; - slot->ops.freset = p7ioc_freset; - slot->ops.creset = p7ioc_creset; - - return slot; -} - -static const struct phb_ops p7ioc_phb_ops = { - .cfg_read8 = p7ioc_pcicfg_read8, - .cfg_read16 = p7ioc_pcicfg_read16, - .cfg_read32 = p7ioc_pcicfg_read32, - .cfg_write8 = p7ioc_pcicfg_write8, - .cfg_write16 = p7ioc_pcicfg_write16, - .cfg_write32 = p7ioc_pcicfg_write32, - .choose_bus = p7ioc_choose_bus, - .get_reserved_pe_number = p7ioc_get_reserved_pe_number, - .device_init = p7ioc_device_init, - .device_remove = NULL, - .pci_reinit = p7ioc_pci_reinit, - .eeh_freeze_status = p7ioc_eeh_freeze_status, - .eeh_freeze_clear = p7ioc_eeh_freeze_clear, - .eeh_freeze_set = p7ioc_eeh_freeze_set, - .err_inject = p7ioc_err_inject, - .get_diag_data2 = p7ioc_get_diag_data, - .next_error = p7ioc_eeh_next_error, - .phb_mmio_enable = p7ioc_phb_mmio_enable, - .set_phb_mem_window = p7ioc_set_phb_mem_window, - .map_pe_mmio_window = p7ioc_map_pe_mmio_window, - .set_pe = p7ioc_set_pe, - .set_peltv = p7ioc_set_peltv, - .map_pe_dma_window = p7ioc_map_pe_dma_window, - .map_pe_dma_window_real = p7ioc_map_pe_dma_window_real, - .set_mve = p7ioc_set_mve, - .set_mve_enable = p7ioc_set_mve_enable, - .set_xive_pe = p7ioc_set_xive_pe, - .get_msi_32 = p7ioc_get_msi_32, - .get_msi_64 = p7ioc_get_msi_64, - .ioda_reset = p7ioc_ioda_reset, - .papr_errinjct_reset = p7ioc_papr_errinjct_reset, -}; - -/* p7ioc_phb_get_xive - Interrupt control from OPAL */ -static int64_t p7ioc_msi_get_xive(struct irq_source *is, uint32_t isn, - uint16_t *server, uint8_t *prio) -{ - struct p7ioc_phb *p = is->data; - uint32_t irq, fbuid = P7_IRQ_FBUID(isn); - uint64_t xive; - - if (fbuid < p->buid_msi || fbuid >= (p->buid_msi + 0x10)) - return OPAL_PARAMETER; - - irq = isn & 0xff; - xive = p->mxive_cache[irq]; - - *server = GETFIELD(IODA_XIVT_SERVER, xive); - *prio = GETFIELD(IODA_XIVT_PRIORITY, xive); - - return OPAL_SUCCESS; -} - -/* p7ioc_phb_set_xive - Interrupt control from OPAL */ -static int64_t p7ioc_msi_set_xive(struct irq_source *is, uint32_t isn, - uint16_t server, uint8_t prio) -{ - struct p7ioc_phb *p = is->data; - uint32_t irq, fbuid = P7_IRQ_FBUID(isn); - uint64_t xive, m_server, m_prio; - - if (fbuid < p->buid_msi || fbuid >= (p->buid_msi + 0x10)) - return OPAL_PARAMETER; - - /* We cache the arguments because we have to mangle - * it in order to hijack 3 bits of priority to extend - * the server number - */ - irq = isn & 0xff; - xive = p->mxive_cache[irq]; - xive = SETFIELD(IODA_XIVT_SERVER, xive, server); - xive = SETFIELD(IODA_XIVT_PRIORITY, xive, prio); - p->mxive_cache[irq] = xive; - - /* Now we mangle the server and priority */ - if (prio == 0xff) { - m_server = 0; - m_prio = 0xff; - } else { - m_server = server >> 3; - m_prio = (prio >> 3) | ((server & 7) << 5); - } - - /* We use HRT entry 0 always for now */ - p7ioc_phb_ioda_sel(p, IODA_TBL_MXIVT, irq, false); - xive = in_be64(p->regs + PHB_IODA_DATA0); - xive = SETFIELD(IODA_XIVT_SERVER, xive, m_server); - xive = SETFIELD(IODA_XIVT_PRIORITY, xive, m_prio); - out_be64(p->regs + PHB_IODA_DATA0, xive); - - return OPAL_SUCCESS; -} - -/* p7ioc_phb_get_xive - Interrupt control from OPAL */ -static int64_t p7ioc_lsi_get_xive(struct irq_source *is, uint32_t isn, - uint16_t *server, uint8_t *prio) -{ - struct p7ioc_phb *p = is->data; - uint32_t irq = (isn & 0x7); - uint32_t fbuid = P7_IRQ_FBUID(isn); - uint64_t xive; - - if (fbuid != p->buid_lsi) - return OPAL_PARAMETER; - - xive = p->lxive_cache[irq]; - *server = GETFIELD(IODA_XIVT_SERVER, xive); - *prio = GETFIELD(IODA_XIVT_PRIORITY, xive); - - return OPAL_SUCCESS; -} - -/* p7ioc_phb_set_xive - Interrupt control from OPAL */ -static int64_t p7ioc_lsi_set_xive(struct irq_source *is, uint32_t isn, - uint16_t server, uint8_t prio) -{ - struct p7ioc_phb *p = is->data; - uint32_t irq = (isn & 0x7); - uint32_t fbuid = P7_IRQ_FBUID(isn); - uint64_t xive, m_server, m_prio; - - if (fbuid != p->buid_lsi) - return OPAL_PARAMETER; - - xive = SETFIELD(IODA_XIVT_SERVER, 0ull, server); - xive = SETFIELD(IODA_XIVT_PRIORITY, xive, prio); - - /* - * We cache the arguments because we have to mangle - * it in order to hijack 3 bits of priority to extend - * the server number - */ - p->lxive_cache[irq] = xive; - - /* Now we mangle the server and priority */ - if (prio == 0xff) { - m_server = 0; - m_prio = 0xff; - } else { - m_server = server >> 3; - m_prio = (prio >> 3) | ((server & 7) << 5); - } - - /* We use HRT entry 0 always for now */ - p7ioc_phb_ioda_sel(p, IODA_TBL_LXIVT, irq, false); - xive = in_be64(p->regs + PHB_IODA_DATA0); - xive = SETFIELD(IODA_XIVT_SERVER, xive, m_server); - xive = SETFIELD(IODA_XIVT_PRIORITY, xive, m_prio); - out_be64(p->regs + PHB_IODA_DATA0, xive); - - return OPAL_SUCCESS; -} - -static void p7ioc_phb_err_interrupt(struct irq_source *is, uint32_t isn) -{ - struct p7ioc_phb *p = is->data; - uint64_t peev0, peev1; - - PHBDBG(p, "Got interrupt 0x%04x\n", isn); - - opal_pci_eeh_set_evt(p->phb.opal_id); - - /* If the PHB is broken, go away */ - if (p->broken) - return; - - /* - * Check if there's an error pending and update PHB fence - * state and return, the ER error is drowned at this point - */ - phb_lock(&p->phb); - if (p7ioc_phb_fenced(p)) { - PHBERR(p, "ER error ignored, PHB fenced\n"); - phb_unlock(&p->phb); - return; - } - - /* - * If we already had pending errors, which might be - * moved from IOC, then we needn't check PEEV to avoid - * overwriting the errors from IOC. - */ - if (!p7ioc_phb_err_pending(p)) { - phb_unlock(&p->phb); - return; - } - - /* - * We don't have pending errors from IOC, it's safe - * to check PEEV for frozen PEs. - */ - p7ioc_phb_ioda_sel(p, IODA_TBL_PEEV, 0, true); - peev0 = in_be64(p->regs + PHB_IODA_DATA0); - peev1 = in_be64(p->regs + PHB_IODA_DATA0); - if (peev0 || peev1) { - p->err.err_src = P7IOC_ERR_SRC_PHB0 + p->index; - p->err.err_class = P7IOC_ERR_CLASS_ER; - p->err.err_bit = 0; - p7ioc_phb_set_err_pending(p, true); - } - phb_unlock(&p->phb); -} - -static uint64_t p7ioc_lsi_attributes(struct irq_source *is __unused, - uint32_t isn) -{ - uint32_t irq = (isn & 0x7); - - if (irq == PHB_LSI_PCIE_ERROR) - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; - return IRQ_ATTR_TARGET_LINUX; -} - - -/* MSIs (OS owned) */ -static const struct irq_source_ops p7ioc_msi_irq_ops = { - .get_xive = p7ioc_msi_get_xive, - .set_xive = p7ioc_msi_set_xive, -}; - -/* LSIs (OS owned) */ -static const struct irq_source_ops p7ioc_lsi_irq_ops = { - .get_xive = p7ioc_lsi_get_xive, - .set_xive = p7ioc_lsi_set_xive, - .attributes = p7ioc_lsi_attributes, - .interrupt = p7ioc_phb_err_interrupt, -}; - -static void p7ioc_pcie_add_node(struct p7ioc_phb *p) -{ - - uint64_t reg[2], iob, m32b, m64b, tkill; - uint32_t lsibase, icsp = get_ics_phandle(); - struct dt_node *np; - - reg[0] = cleanup_addr((uint64_t)p->regs); - reg[1] = 0x100000; - - np = dt_new_addr(p->ioc->dt_node, "pciex", reg[0]); - if (!np) - return; - - p->phb.dt_node = np; - dt_add_property_strings(np, "compatible", "ibm,p7ioc-pciex", - "ibm,ioda-phb"); - dt_add_property_strings(np, "device_type", "pciex"); - dt_add_property(np, "reg", reg, sizeof(reg)); - dt_add_property_cells(np, "#address-cells", 3); - dt_add_property_cells(np, "#size-cells", 2); - dt_add_property_cells(np, "#interrupt-cells", 1); - dt_add_property_cells(np, "bus-range", 0, 0xff); - dt_add_property_cells(np, "clock-frequency", 0x200, 0); /* ??? */ - dt_add_property_cells(np, "interrupt-parent", icsp); - /* XXX FIXME: add slot-name */ - //dt_property_cell("bus-width", 8); /* Figure it out from VPD ? */ - - /* "ranges", we only expose IO and M32 - * - * Note: The kernel expects us to have chopped of 64k from the - * M32 size (for the 32-bit MSIs). If we don't do that, it will - * get confused (OPAL does it) - */ - iob = cleanup_addr(p->io_base); - m32b = cleanup_addr(p->m32_base + M32_PCI_START); - dt_add_property_cells(np, "ranges", - /* IO space */ - 0x01000000, 0x00000000, 0x00000000, - hi32(iob), lo32(iob), 0, PHB_IO_SIZE, - /* M32 space */ - 0x02000000, 0x00000000, M32_PCI_START, - hi32(m32b), lo32(m32b), 0,M32_PCI_SIZE - 0x10000); - - /* XXX FIXME: add opal-memwin32, dmawins, etc... */ - m64b = cleanup_addr(p->m64_base); - dt_add_property_u64s(np, "ibm,opal-m64-window", - m64b, m64b, PHB_M64_SIZE); - dt_add_property_cells(np, "ibm,opal-msi-ports", 256); - dt_add_property_cells(np, "ibm,opal-num-pes", 128); - dt_add_property_cells(np, "ibm,opal-reserved-pe", 127); - dt_add_property_cells(np, "ibm,opal-msi-ranges", - p->buid_msi << 4, 0x100); - tkill = reg[0] + PHB_TCE_KILL; - dt_add_property_cells(np, "ibm,opal-tce-kill", - hi32(tkill), lo32(tkill)); - dt_add_property_cells(np, "ibm,supported-tce-sizes", - 12, // 4K - 16, // 64K - 24, // 16M - 34); // 16G - - /* - * Linux may use this property to allocate the diag data buffer, which - * can be used for either of these structs. Pass the largest to ensure - * they can both fit in this buffer. - */ - dt_add_property_cells(np, "ibm,phb-diag-data-size", - MAX(sizeof(struct OpalIoP7IOCPhbErrorData), - sizeof(struct OpalIoP7IOCErrorData))); - - /* Add associativity properties */ - add_chip_dev_associativity(np); - - /* The interrupt maps will be generated in the RC node by the - * PCI code based on the content of this structure: - */ - lsibase = p->buid_lsi << 4; - p->phb.lstate.int_size = 2; - p->phb.lstate.int_val[0][0] = lsibase + PHB_LSI_PCIE_INTA; - p->phb.lstate.int_val[0][1] = 1; - p->phb.lstate.int_val[1][0] = lsibase + PHB_LSI_PCIE_INTB; - p->phb.lstate.int_val[1][1] = 1; - p->phb.lstate.int_val[2][0] = lsibase + PHB_LSI_PCIE_INTC; - p->phb.lstate.int_val[2][1] = 1; - p->phb.lstate.int_val[3][0] = lsibase + PHB_LSI_PCIE_INTD; - p->phb.lstate.int_val[3][1] = 1; - p->phb.lstate.int_parent[0] = icsp; - p->phb.lstate.int_parent[1] = icsp; - p->phb.lstate.int_parent[2] = icsp; - p->phb.lstate.int_parent[3] = icsp; -} - -/* p7ioc_phb_setup - Setup a p7ioc_phb data structure - * - * WARNING: This is called before the AIB register routing is - * established. If this wants to access PHB registers, it must - * use the ASB hard coded variant (slower) - */ -void p7ioc_phb_setup(struct p7ioc *ioc, uint8_t index) -{ - struct p7ioc_phb *p = &ioc->phbs[index]; - unsigned int buid_base = ioc->buid_base + PHBn_BUID_BASE(index); - struct pci_slot *slot; - - p->index = index; - p->ioc = ioc; - p->gen = 2; /* Operate in Gen2 mode by default */ - p->phb.ops = &p7ioc_phb_ops; - p->phb.phb_type = phb_type_pcie_v2; - p->regs_asb = ioc->regs + PHBn_ASB_BASE(index); - p->regs = ioc->regs + PHBn_AIB_BASE(index); - p->buid_lsi = buid_base + PHB_BUID_LSI_OFFSET; - p->buid_msi = buid_base + PHB_BUID_MSI_OFFSET; - p->io_base = ioc->mmio1_win_start + PHBn_IO_BASE(index); - p->m32_base = ioc->mmio2_win_start + PHBn_M32_BASE(index); - p->m64_base = ioc->mmio2_win_start + PHBn_M64_BASE(index); - p->phb.scan_map = 0x1; /* Only device 0 to scan */ - - /* Find P7IOC base location code in IOC */ - p->phb.base_loc_code = dt_prop_get_def(ioc->dt_node, - "ibm,io-base-loc-code", NULL); - if (!p->phb.base_loc_code) - prerror("P7IOC: Base location code not found !\n"); - - /* Create device node for PHB */ - p7ioc_pcie_add_node(p); - - /* Register OS interrupt sources */ - register_irq_source(&p7ioc_msi_irq_ops, p, p->buid_msi << 4, 256); - register_irq_source(&p7ioc_lsi_irq_ops, p, p->buid_lsi << 4, 8); - - /* Initialize IODA table caches */ - p7ioc_phb_init_ioda_cache(p); - - /* We register the PHB before we initialize it so we - * get a useful OPAL ID for it - */ - pci_register_phb(&p->phb, OPAL_DYNAMIC_PHB_ID); - slot = p7ioc_phb_slot_create(&p->phb); - if (!slot) - prlog(PR_NOTICE, "P7IOC: Cannot create PHB#%x slot\n", - p->phb.opal_id); - - /* Platform additional setup */ - if (platform.pci_setup_phb) - platform.pci_setup_phb(&p->phb, p->index); -} - -static bool p7ioc_phb_wait_dlp_reset(struct p7ioc_phb *p) -{ - unsigned int i; - uint64_t val; - - /* - * Firmware cannot access the UTL core regs or PCI config space - * until the cores are out of DL_PGRESET. - * DL_PGRESET should be polled until it is inactive with a value - * of '0'. The recommended polling frequency is once every 1ms. - * Firmware should poll at least 200 attempts before giving up. - * MMIO Stores to the link are silently dropped by the UTL core if - * the link is down. - * MMIO Loads to the link will be dropped by the UTL core and will - * eventually time-out and will return an all ones response if the - * link is down. - */ -#define DLP_RESET_ATTEMPTS 400 - - printf("P7IOC: Waiting for DLP PG reset to complete...\n"); - for (i = 0; i < DLP_RESET_ATTEMPTS; i++) { - val = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - if (!(val & PHB_PCIE_DLP_TC_DL_PGRESET)) - break; - time_wait_ms(1); - } - if (val & PHB_PCIE_DLP_TC_DL_PGRESET) { - PHBERR(p, "Timeout waiting for DLP PG reset !\n"); - return false; - } - return true; -} - -/* p7ioc_phb_init_rc - Initialize the Root Complex config space - */ -static bool p7ioc_phb_init_rc_cfg(struct p7ioc_phb *p) -{ - int64_t ecap, aercap; - - /* XXX Handle errors ? */ - - /* Init_51..51: - * - * Set primary bus to 0, secondary to 1 and subordinate to 0xff - */ - p7ioc_pcicfg_write32(&p->phb, 0, PCI_CFG_PRIMARY_BUS, 0x00ff0100); - - /* Init_52..57 - * - * IO and Memory base & limits are set to base > limit, which - * allows all inbounds. - * - * XXX This has the potential of confusing the OS which might - * think that nothing is forwarded downstream. We probably need - * to fix this to match the IO and M32 PHB windows - */ - p7ioc_pcicfg_write16(&p->phb, 0, PCI_CFG_IO_BASE, 0x0010); - p7ioc_pcicfg_write32(&p->phb, 0, PCI_CFG_MEM_BASE, 0x00000010); - p7ioc_pcicfg_write32(&p->phb, 0, PCI_CFG_PREF_MEM_BASE, 0x00000010); - - /* Init_58..: Setup bridge control to enable forwarding of CORR, FATAL, - * and NONFATAL errors - */ - p7ioc_pcicfg_write16(&p->phb, 0, PCI_CFG_BRCTL, PCI_CFG_BRCTL_SERR_EN); - - /* Init_60..61 - * - * PCIE Device control/status, enable error reporting, disable relaxed - * ordering, set MPS to 128 (see note), clear errors. - * - * Note: The doc recommends to set MPS to 4K. This has proved to have - * some issues as it requires specific claming of MRSS on devices and - * we've found devices in the field that misbehave when doing that. - * - * We currently leave it all to 128 bytes (minimum setting) at init - * time. The generic PCIe probing later on might apply a different - * value, or the kernel will, but we play it safe at early init - */ - if (p->ecap <= 0) { - ecap = pci_find_cap(&p->phb, 0, PCI_CFG_CAP_ID_EXP); - if (ecap < 0) { - PHBERR(p, "Can't locate PCI-E capability\n"); - return false; - } - p->ecap = ecap; - } else { - ecap = p->ecap; - } - - p7ioc_pcicfg_write16(&p->phb, 0, ecap + PCICAP_EXP_DEVSTAT, - PCICAP_EXP_DEVSTAT_CE | - PCICAP_EXP_DEVSTAT_NFE | - PCICAP_EXP_DEVSTAT_FE | - PCICAP_EXP_DEVSTAT_UE); - - p7ioc_pcicfg_write16(&p->phb, 0, ecap + PCICAP_EXP_DEVCTL, - PCICAP_EXP_DEVCTL_CE_REPORT | - PCICAP_EXP_DEVCTL_NFE_REPORT | - PCICAP_EXP_DEVCTL_FE_REPORT | - PCICAP_EXP_DEVCTL_UR_REPORT | - SETFIELD(PCICAP_EXP_DEVCTL_MPS, 0, PCIE_MPS_128B)); - - /* Init_62..63 - * - * Root Control Register. Enable error reporting - * - * Note: Added CRS visibility. - */ - p7ioc_pcicfg_write16(&p->phb, 0, ecap + PCICAP_EXP_RC, - PCICAP_EXP_RC_SYSERR_ON_CE | - PCICAP_EXP_RC_SYSERR_ON_NFE | - PCICAP_EXP_RC_SYSERR_ON_FE | - PCICAP_EXP_RC_CRS_VISIBLE); - - /* Init_64..65 - * - * Device Control 2. Enable ARI fwd, set timer - */ - p7ioc_pcicfg_write16(&p->phb, 0, ecap + PCICAP_EXP_DCTL2, - SETFIELD(PCICAP_EXP_DCTL2_CMPTOUT, 0, 2) | - PCICAP_EXP_DCTL2_ARI_FWD); - - /* Init_66..81 - * - * AER inits - */ - aercap = pci_find_ecap(&p->phb, 0, PCIECAP_ID_AER, NULL); - if (aercap < 0) { - /* Shouldn't happen */ - PHBERR(p, "Failed to locate AER capability in bridge\n"); - return false; - } - p->aercap = aercap; - - /* Clear all UE status */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_UE_STATUS, - 0xffffffff); - /* Disable some error reporting as per the P7IOC spec */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_UE_MASK, - PCIECAP_AER_UE_POISON_TLP | - PCIECAP_AER_UE_COMPL_TIMEOUT | - PCIECAP_AER_UE_COMPL_ABORT | - PCIECAP_AER_UE_ECRC); - /* Report some errors as fatal */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_UE_SEVERITY, - PCIECAP_AER_UE_DLP | - PCIECAP_AER_UE_SURPRISE_DOWN | - PCIECAP_AER_UE_FLOW_CTL_PROT | - PCIECAP_AER_UE_UNEXP_COMPL | - PCIECAP_AER_UE_RECV_OVFLOW | - PCIECAP_AER_UE_MALFORMED_TLP); - /* Clear all CE status */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_CE_STATUS, - 0xffffffff); - /* Disable some error reporting as per the P7IOC spec */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_CE_MASK, - PCIECAP_AER_CE_ADV_NONFATAL); - /* Enable ECRC generation & checking */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_CAPCTL, - PCIECAP_AER_CAPCTL_ECRCG_EN | - PCIECAP_AER_CAPCTL_ECRCC_EN); - /* Enable reporting in root error control */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_RERR_CMD, - PCIECAP_AER_RERR_CMD_FE | - PCIECAP_AER_RERR_CMD_NFE | - PCIECAP_AER_RERR_CMD_CE); - /* Clear root error status */ - p7ioc_pcicfg_write32(&p->phb, 0, aercap + PCIECAP_AER_RERR_STA, - 0xffffffff); - - return true; -} - -static void p7ioc_phb_init_utl(struct p7ioc_phb *p) -{ - /* Init_82..84: Clear spurious errors and assign errors to the - * right "interrupt" signal - */ - out_be64(p->regs + UTL_SYS_BUS_AGENT_STATUS, 0xffffffffffffffffUL); - out_be64(p->regs + UTL_SYS_BUS_AGENT_ERR_SEVERITY, 0x0000000000000000UL); - out_be64(p->regs + UTL_SYS_BUS_AGENT_IRQ_EN, 0xac80000000000000UL); - - /* Init_85..89: Setup buffer allocations */ - out_be64(p->regs + UTL_OUT_POST_DAT_BUF_ALLOC, 0x0400000000000000UL); - out_be64(p->regs + UTL_IN_POST_HDR_BUF_ALLOC, 0x1000000000000000UL); - out_be64(p->regs + UTL_IN_POST_DAT_BUF_ALLOC, 0x4000000000000000UL); - out_be64(p->regs + UTL_PCIE_TAGS_ALLOC, 0x0800000000000000UL); - out_be64(p->regs + UTL_GBIF_READ_TAGS_ALLOC, 0x0800000000000000UL); - - /* Init_90: PCI Express port control */ - out_be64(p->regs + UTL_PCIE_PORT_CONTROL, 0x8480000000000000UL); - - /* Init_91..93: Clean & setup port errors */ - out_be64(p->regs + UTL_PCIE_PORT_STATUS, 0xff7fffffffffffffUL); - out_be64(p->regs + UTL_PCIE_PORT_ERROR_SEV, 0x00e0000000000000UL); - out_be64(p->regs + UTL_PCIE_PORT_IRQ_EN, 0x7e65000000000000UL); - - /* Init_94 : Cleanup RC errors */ - out_be64(p->regs + UTL_RC_STATUS, 0xffffffffffffffffUL); -} - -static void p7ioc_phb_init_errors(struct p7ioc_phb *p) -{ - /* Init_98: LEM Error Mask : Temporarily disable error interrupts */ - out_be64(p->regs + PHB_LEM_ERROR_MASK, 0xffffffffffffffffUL); - - /* Init_99..107: Configure main error traps & clear old state */ - out_be64(p->regs + PHB_ERR_STATUS, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_ERR1_STATUS, 0x0000000000000000UL); - out_be64(p->regs + PHB_ERR_LEM_ENABLE, 0xffffffffefffffffUL); - out_be64(p->regs + PHB_ERR_FREEZE_ENABLE, 0x0000000061c00000UL); - out_be64(p->regs + PHB_ERR_AIB_FENCE_ENABLE, 0xffffffc58c000000UL); - out_be64(p->regs + PHB_ERR_LOG_0, 0x0000000000000000UL); - out_be64(p->regs + PHB_ERR_LOG_1, 0x0000000000000000UL); - out_be64(p->regs + PHB_ERR_STATUS_MASK, 0x0000000000000000UL); - out_be64(p->regs + PHB_ERR1_STATUS_MASK, 0x0000000000000000UL); - - /* Init_108_116: Configure MMIO error traps & clear old state */ - out_be64(p->regs + PHB_OUT_ERR_STATUS, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_OUT_ERR1_STATUS, 0x0000000000000000UL); - out_be64(p->regs + PHB_OUT_ERR_LEM_ENABLE, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_OUT_ERR_FREEZE_ENABLE, 0x0000430803000000UL); - out_be64(p->regs + PHB_OUT_ERR_AIB_FENCE_ENABLE, 0x9df3bc00f0f0700fUL); - out_be64(p->regs + PHB_OUT_ERR_LOG_0, 0x0000000000000000UL); - out_be64(p->regs + PHB_OUT_ERR_LOG_1, 0x0000000000000000UL); - out_be64(p->regs + PHB_OUT_ERR_STATUS_MASK, 0x0000000000000000UL); - out_be64(p->regs + PHB_OUT_ERR1_STATUS_MASK, 0x0000000000000000UL); - - /* Init_117_125: Configure DMA_A error traps & clear old state */ - out_be64(p->regs + PHB_INA_ERR_STATUS, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_INA_ERR1_STATUS, 0x0000000000000000UL); - out_be64(p->regs + PHB_INA_ERR_LEM_ENABLE, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_INA_ERR_FREEZE_ENABLE, 0xc00003ff01006000UL); - out_be64(p->regs + PHB_INA_ERR_AIB_FENCE_ENABLE, 0x3fff50007e559fd8UL); - out_be64(p->regs + PHB_INA_ERR_LOG_0, 0x0000000000000000UL); - out_be64(p->regs + PHB_INA_ERR_LOG_1, 0x0000000000000000UL); - out_be64(p->regs + PHB_INA_ERR_STATUS_MASK, 0x0000000000000000UL); - out_be64(p->regs + PHB_INA_ERR1_STATUS_MASK, 0x0000000000000000UL); - - /* Init_126_134: Configure DMA_B error traps & clear old state */ - out_be64(p->regs + PHB_INB_ERR_STATUS, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_INB_ERR1_STATUS, 0x0000000000000000UL); - out_be64(p->regs + PHB_INB_ERR_LEM_ENABLE, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_INB_ERR_FREEZE_ENABLE, 0x0000000000000000UL); - out_be64(p->regs + PHB_INB_ERR_AIB_FENCE_ENABLE, 0x18ff80ffff7f0000UL); - out_be64(p->regs + PHB_INB_ERR_LOG_0, 0x0000000000000000UL); - out_be64(p->regs + PHB_INB_ERR_LOG_1, 0x0000000000000000UL); - out_be64(p->regs + PHB_INB_ERR_STATUS_MASK, 0x0000000000000000UL); - out_be64(p->regs + PHB_INB_ERR1_STATUS_MASK, 0x0000000000000000UL); - - /* Init_135..138: Cleanup & configure LEM */ - out_be64(p->regs + PHB_LEM_FIR_ACCUM, 0x0000000000000000UL); - out_be64(p->regs + PHB_LEM_ACTION0, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_LEM_ACTION1, 0x0000000000000000UL); - out_be64(p->regs + PHB_LEM_WOF, 0x0000000000000000UL); -} - -/* p7ioc_phb_init - Initialize the PHB hardware - * - * This is currently only called at boot time. It will eventually - * be called at runtime, for example in some cases of error recovery - * after a PHB reset in which case we might need locks etc... - */ -int64_t p7ioc_phb_init(struct p7ioc_phb *p) -{ - uint64_t val; - - PHBDBG(p, "Initializing PHB %x...\n", p->index); - - /* - * We re-init the PHB on a creset (and a few other cases) - * so clear the broken flag - */ - p->broken = false; - - /* For some reason, the doc wants us to read the version - * register, so let's do it. We shoud probably check that - * the value makes sense... - */ - val = in_be64(p->regs_asb + PHB_VERSION); - p->rev = ((val >> 16) & 0xffff) | (val & 0xffff); - PHBDBG(p, "PHB version: %08x\n", p->rev); - - /* - * Configure AIB operations - * - * This register maps upbound commands to AIB channels. - * DMA Write=0, DMA Read=2, MMIO Load Response=1, - * Interrupt Request=1, TCE Read=3. - */ - /* Init_1: AIB TX Channel Mapping */ - out_be64(p->regs_asb + PHB_AIB_TX_CHAN_MAPPING, 0x0211300000000000UL); - - /* - * This group of steps initializes the AIB RX credits for - * the CI block’s port that is attached to this PHB. - * - * Channel 0 (Dkill): 32 command credits, 0 data credits - * (effectively infinite command credits) - * Channel 1 (DMA/TCE Read Responses): 32 command credits, 32 data - * credits (effectively infinite - * command and data credits) - * Channel 2 (Interrupt Reissue/Return): 32 command, 0 data credits - * (effectively infinite - * command credits) - * Channel 3 (MMIO Load/Stores, EOIs): 1 command, 1 data credit - */ - - /* Init_2: AIB RX Command Credit */ - out_be64(p->regs_asb + PHB_AIB_RX_CMD_CRED, 0x0020002000200001UL); - /* Init_3: AIB RX Data Credit */ - out_be64(p->regs_asb + PHB_AIB_RX_DATA_CRED, 0x0000002000000001UL); - /* Init_4: AXIB RX Credit Init Timer */ - out_be64(p->regs_asb + PHB_AIB_RX_CRED_INIT_TIMER, 0xFF00000000000000UL); - - /* - * Enable all 32 AIB and TCE tags. - * - * AIB tags are used for DMA read requests. - * TCE tags are used for every internal transaction as well as TCE - * read requests. - */ - - /* Init_5: PHB - AIB Tag Enable Register */ - out_be64(p->regs_asb + PHB_AIB_TAG_ENABLE, 0xFFFFFFFF00000000UL); - /* Init_6: PHB – TCE Tag Enable Register */ - out_be64(p->regs_asb + PHB_TCE_TAG_ENABLE, 0xFFFFFFFF00000000UL); - - /* Init_7: PCIE - System Configuration Register - * - * This is the default value out of reset. This register can be - * modified to change the following fields if needed: - * - * bits 04:09 - SYS_EC0C_MAXLINKWIDTH[5:0] - * The default link width is x8. This can be reduced - * to x1 or x4, if needed. - * - * bits 10:12 - SYS_EC04_MAX_PAYLOAD[2:0] - * - * The default max payload size is 4KB. This can be - * reduced to the allowed ranges from 128B - * to 2KB if needed. - */ - out_be64(p->regs + PHB_PCIE_SYSTEM_CONFIG, 0x422800FC20000000UL); - - /* Init_8: PHB - PCI-E Reset Register - * - * This will deassert reset for the PCI-E cores, including the - * PHY and HSS macros. The TLDLP core will begin link training - * shortly after this register is written. - * This will also assert reset for the internal scan-only error - * report macros. The error report macro reset will be deasserted - * in a later step. - * Firmware will verify in a later step whether the PCI-E link - * has been established. - * - * NOTE: We perform a PERST at the end of the init sequence so - * we could probably skip that link training. - */ - out_be64(p->regs + PHB_RESET, 0xE800000000000000UL); - - /* Init_9: BUID - * - * Only the top 5 bit of the MSI field are implemented, the bottom - * are always 0. Our buid_msi value should also be a multiple of - * 16 so it should all fit well - */ - val = SETFIELD(PHB_BUID_LSI, 0ul, P7_BUID_BASE(p->buid_lsi)); - val |= SETFIELD(PHB_BUID_MSI, 0ul, P7_BUID_BASE(p->buid_msi)); - out_be64(p->regs + PHB_BUID, val); - - /* Init_10..12: IO Space */ - out_be64(p->regs + PHB_IO_BASE_ADDR, p->io_base); - out_be64(p->regs + PHB_IO_BASE_MASK, ~(PHB_IO_SIZE - 1)); - out_be64(p->regs + PHB_IO_START_ADDR, 0); - - /* Init_13..15: M32 Space */ - out_be64(p->regs + PHB_M32_BASE_ADDR, p->m32_base + M32_PCI_START); - out_be64(p->regs + PHB_M32_BASE_MASK, ~(M32_PCI_SIZE - 1)); - out_be64(p->regs + PHB_M32_START_ADDR, M32_PCI_START); - - /* Init_16: PCIE-E Outbound Request Upper Address */ - out_be64(p->regs + PHB_M64_UPPER_BITS, 0); - - /* Init_17: PCIE-E PHB2 Configuration - * - * We enable IO, M32, 32-bit MSI and 64-bit MSI - */ - out_be64(p->regs + PHB_PHB2_CONFIG, - PHB_PHB2C_32BIT_MSI_EN | - PHB_PHB2C_IO_EN | - PHB_PHB2C_64BIT_MSI_EN | - PHB_PHB2C_M32_EN | - PHB_PHB2C_64B_TCE_EN); - - /* Init_18..xx: Reset all IODA tables */ - p7ioc_ioda_reset(&p->phb, false); - - /* Init_42..47: Clear UTL & DLP error log regs */ - out_be64(p->regs + PHB_PCIE_UTL_ERRLOG1, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_PCIE_UTL_ERRLOG2, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_PCIE_UTL_ERRLOG3, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_PCIE_UTL_ERRLOG4, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_PCIE_DLP_ERRLOG1, 0xffffffffffffffffUL); - out_be64(p->regs + PHB_PCIE_DLP_ERRLOG2, 0xffffffffffffffffUL); - - /* Init_48: Wait for DLP core to be out of reset */ - if (!p7ioc_phb_wait_dlp_reset(p)) - goto failed; - - /* Init_49 - Clear port status */ - out_be64(p->regs + UTL_PCIE_PORT_STATUS, 0xffffffffffffffffUL); - - /* Init_50..81: Init root complex config space */ - if (!p7ioc_phb_init_rc_cfg(p)) - goto failed; - - /* Init_82..94 : Init UTL */ - p7ioc_phb_init_utl(p); - - /* Init_95: PCI-E Reset, deassert reset for internal error macros */ - out_be64(p->regs + PHB_RESET, 0xe000000000000000UL); - - /* Init_96: PHB Control register. Various PHB settings: - * - * - Enable ECC for various internal RAMs - * - Enable all TCAM entries - * - Set failed DMA read requests to return Completer Abort on error - */ - out_be64(p->regs + PHB_CONTROL, 0x7f38000000000000UL); - - /* Init_97: Legacy Control register - * - * The spec sets bit 0 to enable DKill to flush the TCEs. We do not - * use that mechanism however, we require the OS to directly access - * the TCE Kill register, so we leave that bit set to 0 - */ - out_be64(p->regs + PHB_LEGACY_CTRL, 0x0000000000000000); - - /* Init_98..138 : Setup error registers */ - p7ioc_phb_init_errors(p); - - /* Init_139: Read error summary */ - val = in_be64(p->regs + PHB_ETU_ERR_SUMMARY); - if (val) { - PHBERR(p, "Errors detected during PHB init: 0x%16llx\n", val); - goto failed; - } - - /* Steps Init_140..142 have been removed from the spec. */ - - /* Init_143..144: Enable IO, MMIO, Bus master etc... and clear - * status bits - */ - p7ioc_pcicfg_write16(&p->phb, 0, PCI_CFG_STAT, - PCI_CFG_STAT_SENT_TABORT | - PCI_CFG_STAT_RECV_TABORT | - PCI_CFG_STAT_RECV_MABORT | - PCI_CFG_STAT_SENT_SERR | - PCI_CFG_STAT_RECV_PERR); - p7ioc_pcicfg_write16(&p->phb, 0, PCI_CFG_CMD, - PCI_CFG_CMD_SERR_EN | - PCI_CFG_CMD_PERR_RESP | - PCI_CFG_CMD_BUS_MASTER_EN | - PCI_CFG_CMD_MEM_EN | - PCI_CFG_CMD_IO_EN); - - /* At this point, the spec suggests doing a bus walk. However we - * haven't powered up the slots with the SHCP controller. We'll - * deal with that and link training issues later, for now, let's - * enable the full range of error detection - */ - - /* Init_145..149: Enable error interrupts and LEM */ - out_be64(p->regs + PHB_ERR_IRQ_ENABLE, 0x0000000061c00000UL); - out_be64(p->regs + PHB_OUT_ERR_IRQ_ENABLE, 0x0000430803000000UL); - out_be64(p->regs + PHB_INA_ERR_IRQ_ENABLE, 0xc00003ff01006000UL); - out_be64(p->regs + PHB_INB_ERR_IRQ_ENABLE, 0x0000000000000000UL); - out_be64(p->regs + PHB_LEM_ERROR_MASK, 0x1249a1147f500f2cUL); - - /* Init_150: Enable DMA read/write TLP address speculation */ - out_be64(p->regs + PHB_TCE_PREFETCH, 0x0000c00000000000UL); - - /* Init_151..152: Set various timeouts */ - out_be64(p->regs + PHB_TIMEOUT_CTRL1, 0x1611112010200000UL); - out_be64(p->regs + PHB_TIMEOUT_CTRL2, 0x0000561300000000UL); - - return OPAL_SUCCESS; - - failed: - PHBERR(p, "Initialization failed\n"); - p->broken = true; - - return OPAL_HARDWARE; -} - -void p7ioc_phb_reset(struct phb *phb) -{ - struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); - struct p7ioc *ioc = p->ioc; - uint64_t ci_idx, rreg; - unsigned int i; - bool fenced; - - /* Check our fence status. The fence bits we care about are - * two bits per PHB at IBM bit location 14 and 15 + 4*phb - */ - fenced = p7ioc_phb_fenced(p); - - PHBDBG(p, "PHB reset... (fenced: %d)\n", (int)fenced); - - /* - * If not fenced and already functional, let's do an IODA reset - * to clear pending DMAs and wait a bit for thing to settle. It's - * notable that the IODA table cache won't be emptied so that we - * can restore them during error recovery. - */ - if (!p->broken && !fenced) { - PHBDBG(p, " ioda reset ...\n"); - p7ioc_ioda_reset(&p->phb, false); - time_wait_ms(100); - } - - /* CI port index */ - ci_idx = p->index + 2; - - /* Reset register bits for this PHB */ - rreg = 0;/*PPC_BIT(8 + ci_idx * 2);*/ /* CI port config reset */ - rreg |= PPC_BIT(9 + ci_idx * 2); /* CI port func reset */ - rreg |= PPC_BIT(32 + p->index); /* PHBn config reset */ - - /* Mask various errors during reset and clear pending errors */ - out_be64(ioc->regs + P7IOC_CIn_LEM_ERR_MASK(ci_idx), - 0xa4f4000000000000ul); - out_be64(p->regs_asb + PHB_LEM_ERROR_MASK, 0xadb650c9808dd051ul); - out_be64(ioc->regs + P7IOC_CIn_LEM_FIR(ci_idx), 0); - - /* We need to retry in case the fence doesn't lift due to a - * problem with lost credits (HW guys). How many times ? - */ -#define MAX_PHB_RESET_RETRIES 5 - for (i = 0; i < MAX_PHB_RESET_RETRIES; i++) { - PHBDBG(p, " reset try %d...\n", i); - /* Apply reset */ - out_be64(ioc->regs + P7IOC_CCRR, rreg); - time_wait_ms(1); - out_be64(ioc->regs + P7IOC_CCRR, 0); - - /* Check if fence lifed */ - fenced = p7ioc_phb_fenced(p); - PHBDBG(p, " fenced: %d...\n", (int)fenced); - if (!fenced) - break; - } - - /* Reset failed, not much to do, maybe add an error return */ - if (fenced) { - PHBERR(p, "Reset failed, fence still set !\n"); - p->broken = true; - return; - } - - /* Wait a bit */ - time_wait_ms(100); - - /* Re-initialize the PHB */ - p7ioc_phb_init(p); - - /* Restore the CI error mask */ - out_be64(ioc->regs + P7IOC_CIn_LEM_ERR_MASK_AND(ci_idx), 0); -} - - - diff --git a/hw/p7ioc.c b/hw/p7ioc.c deleted file mode 100644 index 44ce3d8..0000000 --- a/hw/p7ioc.c +++ /dev/null @@ -1,688 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <skiboot.h> -#include <p7ioc.h> -#include <p7ioc-regs.h> -#include <cec.h> -#include <opal.h> -#include <io.h> -#include <vpd.h> -#include <interrupts.h> -#include <ccan/str/str.h> - -/* - * Determine the base address of LEM registers according to - * the indicated error source. - */ -static void *p7ioc_LEM_base(struct p7ioc *ioc, uint32_t err_src) -{ - uint32_t index; - void *base = NULL; - - switch (err_src) { - case P7IOC_ERR_SRC_RGC: - base = ioc->regs + P7IOC_RGC_LEM_BASE; - break; - case P7IOC_ERR_SRC_BI_UP: - base = ioc->regs + P7IOC_BI_UP_LEM_BASE; - break; - case P7IOC_ERR_SRC_BI_DOWN: - base = ioc->regs + P7IOC_BI_DOWN_LEM_BASE; - break; - case P7IOC_ERR_SRC_CI_P0: - case P7IOC_ERR_SRC_CI_P1: - case P7IOC_ERR_SRC_CI_P2: - case P7IOC_ERR_SRC_CI_P3: - case P7IOC_ERR_SRC_CI_P4: - case P7IOC_ERR_SRC_CI_P5: - case P7IOC_ERR_SRC_CI_P6: - case P7IOC_ERR_SRC_CI_P7: - index = err_src - P7IOC_ERR_SRC_CI_P0; - base = ioc->regs + P7IOC_CI_PORTn_LEM_BASE(index); - break; - case P7IOC_ERR_SRC_PHB0: - case P7IOC_ERR_SRC_PHB1: - case P7IOC_ERR_SRC_PHB2: - case P7IOC_ERR_SRC_PHB3: - case P7IOC_ERR_SRC_PHB4: - case P7IOC_ERR_SRC_PHB5: - index = err_src - P7IOC_ERR_SRC_PHB0; - base = ioc->regs + P7IOC_PHBn_LEM_BASE(index); - break; - case P7IOC_ERR_SRC_MISC: - base = ioc->regs + P7IOC_MISC_LEM_BASE; - break; - case P7IOC_ERR_SRC_I2C: - base = ioc->regs + P7IOC_I2C_LEM_BASE; - break; - default: - prerror("%s: Unknown error source %d\n", - __func__, err_src); - } - - return base; -} - -static void p7ioc_get_diag_common(struct p7ioc *ioc, - void *base, - struct OpalIoP7IOCErrorData *data) -{ - /* GEM */ - data->gemXfir = in_be64(ioc->regs + P7IOC_GEM_XFIR); - data->gemRfir = in_be64(ioc->regs + P7IOC_GEM_RFIR); - data->gemRirqfir = in_be64(ioc->regs + P7IOC_GEM_RIRQFIR); - data->gemMask = in_be64(ioc->regs + P7IOC_GEM_MASK); - data->gemRwof = in_be64(ioc->regs + P7IOC_GEM_RWOF); - - /* LEM */ - data->lemFir = in_be64(base + P7IOC_LEM_FIR_OFFSET); - data->lemErrMask = in_be64(base + P7IOC_LEM_ERR_MASK_OFFSET); - data->lemAction0 = in_be64(base + P7IOC_LEM_ACTION_0_OFFSET); - data->lemAction1 = in_be64(base + P7IOC_LEM_ACTION_1_OFFSET); - data->lemWof = in_be64(base + P7IOC_LEM_WOF_OFFSET); -} - -static int64_t p7ioc_get_diag_data(struct io_hub *hub, - void *diag_buffer, - uint64_t diag_buffer_len) -{ - struct p7ioc *ioc = iohub_to_p7ioc(hub); - struct OpalIoP7IOCErrorData *data = diag_buffer; - void *base; - - /* Make sure we have enough buffer */ - if (diag_buffer_len < sizeof(struct OpalIoP7IOCErrorData)) - return OPAL_PARAMETER; - - /* We need do nothing if there're no pending errors */ - if (!p7ioc_err_pending(ioc)) - return OPAL_CLOSED; - - /* - * We needn't collect diag-data for CI Port{2, ..., 7} - * and PHB{0, ..., 5} since their errors (except GXE) - * have been cached to the specific PHB. - */ - base = p7ioc_LEM_base(ioc, ioc->err.err_src); - if (!base) { - p7ioc_set_err_pending(ioc, false); - return OPAL_INTERNAL_ERROR; - } - - switch (ioc->err.err_src) { - case P7IOC_ERR_SRC_RGC: - data->type = OPAL_P7IOC_DIAG_TYPE_RGC; - p7ioc_get_diag_common(ioc, base, data); - - data->rgc.rgcStatus = in_be64(ioc->regs + 0x3E1C10); - data->rgc.rgcLdcp = in_be64(ioc->regs + 0x3E1C18); - - break; - case P7IOC_ERR_SRC_BI_UP: - data->type = OPAL_P7IOC_DIAG_TYPE_BI; - data->bi.biDownbound = 0; - p7ioc_get_diag_common(ioc, base, data); - - data->bi.biLdcp0 = in_be64(ioc->regs + 0x3C0100); - data->bi.biLdcp1 = in_be64(ioc->regs + 0x3C0108); - data->bi.biLdcp2 = in_be64(ioc->regs + 0x3C0110); - data->bi.biFenceStatus = in_be64(ioc->regs + 0x3C0130); - - break; - case P7IOC_ERR_SRC_BI_DOWN: - data->type = OPAL_P7IOC_DIAG_TYPE_BI; - data->bi.biDownbound = 1; - p7ioc_get_diag_common(ioc, base, data); - - data->bi.biLdcp0 = in_be64(ioc->regs + 0x3C0118); - data->bi.biLdcp1 = in_be64(ioc->regs + 0x3C0120); - data->bi.biLdcp2 = in_be64(ioc->regs + 0x3C0128); - data->bi.biFenceStatus = in_be64(ioc->regs + 0x3C0130); - - break; - case P7IOC_ERR_SRC_CI_P0: - case P7IOC_ERR_SRC_CI_P1: - data->type = OPAL_P7IOC_DIAG_TYPE_CI; - data->ci.ciPort = ioc->err.err_src - P7IOC_ERR_SRC_CI_P0; - p7ioc_get_diag_common(ioc, base, data); - - data->ci.ciPortStatus = in_be64(base + 0x008); - data->ci.ciPortLdcp = in_be64(base + 0x010); - break; - case P7IOC_ERR_SRC_MISC: - data->type = OPAL_P7IOC_DIAG_TYPE_MISC; - p7ioc_get_diag_common(ioc, base, data); - break; - case P7IOC_ERR_SRC_I2C: - data->type = OPAL_P7IOC_DIAG_TYPE_I2C; - p7ioc_get_diag_common(ioc, base, data); - break; - default: - p7ioc_set_err_pending(ioc, false); - return OPAL_CLOSED; - } - - /* For errors of MAL class, we need mask it */ - if (ioc->err.err_class == P7IOC_ERR_CLASS_MAL) - out_be64(base + P7IOC_LEM_ERR_MASK_OR_OFFSET, - PPC_BIT(63 - ioc->err.err_bit)); - p7ioc_set_err_pending(ioc, false); - - return OPAL_SUCCESS; -} - -static const struct io_hub_ops p7ioc_hub_ops = { - .get_diag_data = p7ioc_get_diag_data, - .reset = p7ioc_reset, -}; - -static int64_t p7ioc_rgc_get_xive(struct irq_source *is, uint32_t isn, - uint16_t *server, uint8_t *prio) -{ - struct p7ioc *ioc = is->data; - uint32_t irq = (isn & 0xf); - uint32_t fbuid = P7_IRQ_FBUID(isn); - uint64_t xive; - - if (fbuid != ioc->rgc_buid) - return OPAL_PARAMETER; - - xive = ioc->xive_cache[irq]; - *server = GETFIELD(IODA_XIVT_SERVER, xive); - *prio = GETFIELD(IODA_XIVT_PRIORITY, xive); - - return OPAL_SUCCESS; - } - -static int64_t p7ioc_rgc_set_xive(struct irq_source *is, uint32_t isn, - uint16_t server, uint8_t prio) -{ - struct p7ioc *ioc = is->data; - uint32_t irq = (isn & 0xf); - uint32_t fbuid = P7_IRQ_FBUID(isn); - uint64_t xive; - uint64_t m_server, m_prio; - - if (fbuid != ioc->rgc_buid) - return OPAL_PARAMETER; - - xive = SETFIELD(IODA_XIVT_SERVER, 0ull, server); - xive = SETFIELD(IODA_XIVT_PRIORITY, xive, prio); - ioc->xive_cache[irq] = xive; - - /* Now we mangle the server and priority */ - if (prio == 0xff) { - m_server = 0; - m_prio = 0xff; - } else { - m_server = server >> 3; - m_prio = (prio >> 3) | ((server & 7) << 5); - } - - /* Update the XIVE. Don't care HRT entry on P7IOC */ - out_be64(ioc->regs + 0x3e1820, (0x0002000000000000UL | irq)); - xive = in_be64(ioc->regs + 0x3e1830); - xive = SETFIELD(IODA_XIVT_SERVER, xive, m_server); - xive = SETFIELD(IODA_XIVT_PRIORITY, xive, m_prio); - out_be64(ioc->regs + 0x3e1830, xive); - - return OPAL_SUCCESS; -} - -/* - * The function is used to figure out the error class and error - * bit according to LEM WOF. - * - * The bits of WOF register have been classified according to - * the error severity. Of course, we should process those errors - * with higher priority. For example, there have 2 errors (GXE, INF) - * pending, we should process GXE, and INF is meaningless in face - * of GXE. - */ -static bool p7ioc_err_bit(struct p7ioc *ioc, uint64_t wof) -{ - uint64_t val, severity[P7IOC_ERR_CLASS_LAST]; - int32_t class, bit, err_bit = -1; - - /* Clear severity array */ - memset(severity, 0, sizeof(uint64_t) * P7IOC_ERR_CLASS_LAST); - - /* - * The severity array has fixed values. However, it depends - * on the damage settings for individual components. We're - * using fixed values based on the assumption that damage settings - * are fixed for now. If we change it some day, we also need - * change the severity array accordingly. Anyway, it's something - * to improve in future so that we can figure out the severity - * array from hardware registers. - */ - switch (ioc->err.err_src) { - case P7IOC_ERR_SRC_EI: - /* EI won't create interrupt yet */ - break; - case P7IOC_ERR_SRC_RGC: - severity[P7IOC_ERR_CLASS_GXE] = 0xF00086E0F4FCFFFFUL; - severity[P7IOC_ERR_CLASS_RGA] = 0x0000010000000000UL; - severity[P7IOC_ERR_CLASS_INF] = 0x0FFF781F0B030000UL; - break; - case P7IOC_ERR_SRC_BI_UP: - severity[P7IOC_ERR_CLASS_GXE] = 0xF7FFFFFF7FFFFFFFUL; - severity[P7IOC_ERR_CLASS_INF] = 0x0800000080000000UL; - break; - case P7IOC_ERR_SRC_BI_DOWN: - severity[P7IOC_ERR_CLASS_GXE] = 0xDFFFF7F35F8000BFUL; - severity[P7IOC_ERR_CLASS_INF] = 0x2000080CA07FFF40UL; - break; - case P7IOC_ERR_SRC_CI_P0: - severity[P7IOC_ERR_CLASS_GXE] = 0xF5FF000000000000UL; - severity[P7IOC_ERR_CLASS_INF] = 0x0200FFFFFFFFFFFFUL; - severity[P7IOC_ERR_CLASS_MAL] = 0x0800000000000000UL; - break; - case P7IOC_ERR_SRC_CI_P1: - severity[P7IOC_ERR_CLASS_GXE] = 0xFFFF000000000000UL; - severity[P7IOC_ERR_CLASS_INF] = 0x0000FFFFFFFFFFFFUL; - break; - case P7IOC_ERR_SRC_CI_P2: - case P7IOC_ERR_SRC_CI_P3: - case P7IOC_ERR_SRC_CI_P4: - case P7IOC_ERR_SRC_CI_P5: - case P7IOC_ERR_SRC_CI_P6: - case P7IOC_ERR_SRC_CI_P7: - severity[P7IOC_ERR_CLASS_GXE] = 0x5B0B000000000000UL; - severity[P7IOC_ERR_CLASS_PHB] = 0xA4F4000000000000UL; - severity[P7IOC_ERR_CLASS_INF] = 0x0000FFFFFFFFFFFFUL; - break; - case P7IOC_ERR_SRC_MISC: - severity[P7IOC_ERR_CLASS_GXE] = 0x0000000310000000UL; - severity[P7IOC_ERR_CLASS_PLL] = 0x0000000001C00000UL; - severity[P7IOC_ERR_CLASS_INF] = 0x555FFFF0EE3FFFFFUL; - severity[P7IOC_ERR_CLASS_MAL] = 0xAAA0000C00000000UL; - break; - case P7IOC_ERR_SRC_I2C: - severity[P7IOC_ERR_CLASS_GXE] = 0x1100000000000000UL; - severity[P7IOC_ERR_CLASS_INF] = 0xEEFFFFFFFFFFFFFFUL; - break; - case P7IOC_ERR_SRC_PHB0: - case P7IOC_ERR_SRC_PHB1: - case P7IOC_ERR_SRC_PHB2: - case P7IOC_ERR_SRC_PHB3: - case P7IOC_ERR_SRC_PHB4: - case P7IOC_ERR_SRC_PHB5: - severity[P7IOC_ERR_CLASS_PHB] = 0xADB650CB808DD051UL; - severity[P7IOC_ERR_CLASS_ER] = 0x0000A0147F50092CUL; - severity[P7IOC_ERR_CLASS_INF] = 0x52490F2000222682UL; - break; - } - - /* - * The error class (ERR_CLASS) has been defined based on - * their severity. The priority of those errors out of same - * class should be defined based on the position of corresponding - * bit in LEM (Local Error Macro) register. - */ - for (class = P7IOC_ERR_CLASS_NONE + 1; - err_bit < 0 && class < P7IOC_ERR_CLASS_LAST; - class++) { - val = wof & severity[class]; - if (!val) continue; - - for (bit = 0; bit < 64; bit++) { - if (val & PPC_BIT(bit)) { - err_bit = 63 - bit; - break; - } - } - } - - /* If we don't find the error bit, we needn't go on. */ - if (err_bit < 0) - return false; - - ioc->err.err_class = class - 1; - ioc->err.err_bit = err_bit; - return true; -} - -/* - * Check LEM to determine the detailed error information. - * The function is expected to be called while OS calls - * to OPAL API opal_pci_next_error(). Eventually, the errors - * from CI Port{2, ..., 7} or PHB{0, ..., 5} would be cached - * to the specific PHB, the left errors would be cached to - * the IOC. - */ -bool p7ioc_check_LEM(struct p7ioc *ioc, - uint16_t *pci_error_type, - uint16_t *severity) -{ - void *base; - uint64_t fir, wof, mask; - struct p7ioc_phb *p; - int32_t index; - bool ret; - - /* Make sure we have error pending on IOC */ - if (!p7ioc_err_pending(ioc)) - return false; - - /* - * The IOC probably has been put to fatal error - * state (GXE) because of failure on reading on - * GEM FIR. - */ - if (ioc->err.err_src == P7IOC_ERR_SRC_NONE && - ioc->err.err_class != P7IOC_ERR_CLASS_NONE) - goto err; - - /* - * Get the base address of LEM registers according - * to the error source. If we failed to get that, - * the error pending flag would be cleared. - */ - base = p7ioc_LEM_base(ioc, ioc->err.err_src); - if (!base) { - p7ioc_set_err_pending(ioc, false); - return false; - } - - /* IOC would be broken upon broken FIR */ - fir = in_be64(base + P7IOC_LEM_FIR_OFFSET); - if (fir == 0xffffffffffffffffUL) { - ioc->err.err_src = P7IOC_ERR_SRC_NONE; - ioc->err.err_class = P7IOC_ERR_CLASS_GXE; - goto err; - } - - /* Read on ERR_MASK and WOF. However, we needn't do for PHBn */ - wof = in_be64(base + P7IOC_LEM_WOF_OFFSET); - if (ioc->err.err_src >= P7IOC_ERR_SRC_PHB0 && - ioc->err.err_src <= P7IOC_ERR_SRC_PHB5) { - mask = 0x0ull; - } else { - mask = in_be64(base + P7IOC_LEM_ERR_MASK_OFFSET); - in_be64(base + P7IOC_LEM_ACTION_0_OFFSET); - in_be64(base + P7IOC_LEM_ACTION_1_OFFSET); - } - - /* - * We need process those unmasked error first. If we're - * failing to get the error bit, we needn't proceed. - */ - if (wof & ~mask) - wof &= ~mask; - if (!wof) { - p7ioc_set_err_pending(ioc, false); - return false; - } - - if (!p7ioc_err_bit(ioc, wof)) { - p7ioc_set_err_pending(ioc, false); - return false; - } - -err: - /* - * We run into here because of valid error. Those errors - * from CI Port{2, ..., 7} and PHB{0, ..., 5} will be cached - * to the specific PHB. However, we will cache the global - * errors (e.g. GXE) to IOC directly. For the left errors, - * they will be cached to IOC. - */ - if (((ioc->err.err_src >= P7IOC_ERR_SRC_CI_P2 && - ioc->err.err_src <= P7IOC_ERR_SRC_CI_P7) || - (ioc->err.err_src >= P7IOC_ERR_SRC_PHB0 && - ioc->err.err_src <= P7IOC_ERR_SRC_PHB5)) && - ioc->err.err_class != P7IOC_ERR_CLASS_GXE) { - index = (ioc->err.err_src >= P7IOC_ERR_SRC_PHB0 && - ioc->err.err_src <= P7IOC_ERR_SRC_PHB5) ? - (ioc->err.err_src - P7IOC_ERR_SRC_PHB0) : - (ioc->err.err_src - P7IOC_ERR_SRC_CI_P2); - p = &ioc->phbs[index]; - - if (p7ioc_phb_enabled(ioc, index)) { - p->err.err_src = ioc->err.err_src; - p->err.err_class = ioc->err.err_class; - p->err.err_bit = ioc->err.err_bit; - p7ioc_phb_set_err_pending(p, true); - p7ioc_set_err_pending(ioc, false); - - return false; - } - } - - /* - * Map the internal error class to that OS can recognize. - * Errors from PHB or the associated CI port would be - * GXE, PHB-fatal, ER, or INF. For the case, GXE will be - * cached to IOC and the left classes will be cached to - * the specific PHB. - */ - switch (ioc->err.err_class) { - case P7IOC_ERR_CLASS_GXE: - case P7IOC_ERR_CLASS_PLL: - case P7IOC_ERR_CLASS_RGA: - *pci_error_type = OPAL_EEH_IOC_ERROR; - *severity = OPAL_EEH_SEV_IOC_DEAD; - ret = true; - break; - case P7IOC_ERR_CLASS_INF: - case P7IOC_ERR_CLASS_MAL: - *pci_error_type = OPAL_EEH_IOC_ERROR; - *severity = OPAL_EEH_SEV_INF; - ret = false; - break; - default: - p7ioc_set_err_pending(ioc, false); - ret = false; - } - - return ret; -} - -/* - * Check GEM to see if there has any problematic components. - * The function is expected to be called in RGC interrupt - * handler. Also, it's notable that failure on reading on - * XFIR will cause GXE directly. - */ -static bool p7ioc_check_GEM(struct p7ioc *ioc) -{ - uint64_t xfir, rwof; - - /* - * Recov_5: Read GEM Xfir - * Recov_6: go to GXE recovery? - */ - xfir = in_be64(ioc->regs + P7IOC_GEM_XFIR); - if (xfir == 0xffffffffffffffffUL) { - ioc->err.err_src = P7IOC_ERR_SRC_NONE; - ioc->err.err_class = P7IOC_ERR_CLASS_GXE; - p7ioc_set_err_pending(ioc, true); - return true; - } - - /* - * Recov_7: Read GEM Rfir - * Recov_8: Read GEM RIRQfir - * Recov_9: Read GEM RWOF - * Recov_10: Read Fence Shadow - * Recov_11: Read Fence Shadow WOF - */ - in_be64(ioc->regs + P7IOC_GEM_RFIR); - in_be64(ioc->regs + P7IOC_GEM_RIRQFIR); - rwof = in_be64(ioc->regs + P7IOC_GEM_RWOF); - in_be64(ioc->regs + P7IOC_CHIP_FENCE_SHADOW); - in_be64(ioc->regs + P7IOC_CHIP_FENCE_WOF); - - /* - * Check GEM RWOF to see which component has been - * put into problematic state. - */ - ioc->err.err_src = P7IOC_ERR_SRC_NONE; - if (rwof & PPC_BIT(1)) ioc->err.err_src = P7IOC_ERR_SRC_RGC; - else if (rwof & PPC_BIT(2)) ioc->err.err_src = P7IOC_ERR_SRC_BI_UP; - else if (rwof & PPC_BIT(3)) ioc->err.err_src = P7IOC_ERR_SRC_BI_DOWN; - else if (rwof & PPC_BIT(4)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P0; - else if (rwof & PPC_BIT(5)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P1; - else if (rwof & PPC_BIT(6)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P2; - else if (rwof & PPC_BIT(7)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P3; - else if (rwof & PPC_BIT(8)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P4; - else if (rwof & PPC_BIT(9)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P5; - else if (rwof & PPC_BIT(10)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P6; - else if (rwof & PPC_BIT(11)) ioc->err.err_src = P7IOC_ERR_SRC_CI_P7; - else if (rwof & PPC_BIT(16)) ioc->err.err_src = P7IOC_ERR_SRC_PHB0; - else if (rwof & PPC_BIT(17)) ioc->err.err_src = P7IOC_ERR_SRC_PHB1; - else if (rwof & PPC_BIT(18)) ioc->err.err_src = P7IOC_ERR_SRC_PHB2; - else if (rwof & PPC_BIT(19)) ioc->err.err_src = P7IOC_ERR_SRC_PHB3; - else if (rwof & PPC_BIT(20)) ioc->err.err_src = P7IOC_ERR_SRC_PHB4; - else if (rwof & PPC_BIT(21)) ioc->err.err_src = P7IOC_ERR_SRC_PHB5; - else if (rwof & PPC_BIT(24)) ioc->err.err_src = P7IOC_ERR_SRC_MISC; - else if (rwof & PPC_BIT(25)) ioc->err.err_src = P7IOC_ERR_SRC_I2C; - - /* - * If we detect any problematic components, the OS is - * expected to poll that for more details through OPAL - * interface. - */ - if (ioc->err.err_src != P7IOC_ERR_SRC_NONE) { - p7ioc_set_err_pending(ioc, true); - return true; - } - - return false; -} - -static void p7ioc_rgc_interrupt(struct irq_source *is, uint32_t isn) -{ - struct p7ioc *ioc = is->data; - - printf("Got RGC interrupt 0x%04x\n", isn); - - /* We will notify OS while getting error from GEM */ - if (p7ioc_check_GEM(ioc)) - /* This is a bit hacky but works - we raise the event - on a downstream phb as the OS needs to call - opal_pci_next_error for all phbs to ensure all events - are cleared anyway. */ - opal_pci_eeh_set_evt(ioc->phbs[0].phb.opal_id); -} - -static uint64_t p7ioc_rgc_irq_attributes(struct irq_source *is __unused, - uint32_t isn __unused) -{ - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_LSI; -} - -static const struct irq_source_ops p7ioc_rgc_irq_ops = { - .get_xive = p7ioc_rgc_get_xive, - .set_xive = p7ioc_rgc_set_xive, - .attributes = p7ioc_rgc_irq_attributes, - .interrupt = p7ioc_rgc_interrupt, -}; - -static void p7ioc_create_hub(struct dt_node *np) -{ - struct p7ioc *ioc; - unsigned int i, id; - u64 bar1, bar2; - u32 pdt; - char *path; - - /* Use the BUID extension as ID and add it to device-tree */ - id = dt_prop_get_u32(np, "ibm,buid-ext"); - path = dt_get_path(np); - printf("P7IOC: Found at %s ID 0x%x\n", path, id); - free(path); - - /* Load VPD LID */ - vpd_preload(np); - vpd_iohub_load(np); - - ioc = zalloc(sizeof(struct p7ioc)); - if (!ioc) - return; - ioc->hub.hub_id = id; - ioc->hub.ops = &p7ioc_hub_ops; - ioc->dt_node = np; - - bar1 = dt_prop_get_u64(np, "ibm,gx-bar-1"); - bar2 = dt_prop_get_u64(np, "ibm,gx-bar-2"); - - ioc->regs = (void *)bar1; - - ioc->mmio1_win_start = bar1; - ioc->mmio1_win_size = MWIN1_SIZE; - ioc->mmio2_win_start = bar2; - ioc->mmio2_win_size = MWIN2_SIZE; - - ioc->buid_base = id << 9; - ioc->rgc_buid = ioc->buid_base + RGC_BUID_OFFSET; - - /* Add some DT properties */ - dt_add_property_cells(np, "ibm,opal-hubid", 0, id); - - /* XXX Fixme: how many RGC interrupts ? */ - dt_add_property_cells(np, "interrupt-parent", get_ics_phandle()); - dt_add_property_cells(np, "interrupts", ioc->rgc_buid << 4, 1); - dt_add_property_cells(np, "interrupt-base", ioc->rgc_buid << 4); - - /* XXX What about ibm,opal-mmio-real ? */ - - /* Clear the RGC XIVE cache */ - for (i = 0; i < 16; i++) - ioc->xive_cache[i] = SETFIELD(IODA_XIVT_PRIORITY, 0ull, 0xff); - - /* - * Register RGC interrupts - * - * For now I assume only 0 is... to verify with Greg or HW guys, - * we support all 16 - */ - register_irq_source(&p7ioc_rgc_irq_ops, ioc, ioc->rgc_buid << 4, 1); - - /* Check for presence detect from HDAT, we use only BR1 on P7IOC */ - pdt = dt_prop_get_u32_def(np, "ibm,br1-presence-detect", 0xffffffff); - if (pdt != 0xffffffff) - printf("P7IOC: Presence detect from HDAT : 0x%02x\n", pdt); - else { - } - ioc->phb_pdt = pdt & 0xff; - - /* Setup PHB structures (no HW access yet) */ - for (i = 0; i < P7IOC_NUM_PHBS; i++) { - if (p7ioc_phb_enabled(ioc, i)) - p7ioc_phb_setup(ioc, i); - } - - /* Now, we do the bulk of the inits */ - p7ioc_inits(ioc); - - printf("P7IOC: Initialization complete\n"); - - cec_register(&ioc->hub); -} - -void probe_p7ioc(void) -{ - struct dt_node *np; - - dt_for_each_compatible(dt_root, np, "ibm,p7ioc") - p7ioc_create_hub(np); -} - - - @@ -21,7 +21,6 @@ #include <psi.h> #include <fsp.h> #include <opal.h> -#include <gx.h> #include <interrupts.h> #include <cpu.h> #include <dio-p9.h> @@ -286,8 +285,7 @@ static void psi_spurious_fsp_irq(struct psi *psi) reg = PSIHB_XSCOM_P8_HBCSR_CLR; bit = PSIHB_XSCOM_P8_HBSCR_FSP_IRQ; } else { - reg = PSIHB_XSCOM_P7_HBCSR_CLR; - bit = PSIHB_XSCOM_P7_HBSCR_FSP_IRQ; + assert(false); } xscom_write(psi->chip_id, psi->xscom_base + reg, bit); } @@ -345,42 +343,6 @@ static void psihb_interrupt(struct irq_source *is, uint32_t isn __unused) fsp_console_poll(NULL); } -static int64_t psi_p7_set_xive(struct irq_source *is, uint32_t isn __unused, - uint16_t server, uint8_t priority) -{ - struct psi *psi = is->data; - uint64_t xivr; - - /* Populate the XIVR */ - xivr = (uint64_t)server << 40; - xivr |= (uint64_t)priority << 32; - xivr |= P7_IRQ_BUID(psi->interrupt) << 16; - - out_be64(psi->regs + PSIHB_XIVR, xivr); - - return OPAL_SUCCESS; -} - -static int64_t psi_p7_get_xive(struct irq_source *is, uint32_t isn __unused, - uint16_t *server, uint8_t *priority) -{ - struct psi *psi = is->data; - uint64_t xivr; - - /* Read & decode the XIVR */ - xivr = in_be64(psi->regs + PSIHB_XIVR); - - *server = (xivr >> 40) & 0x7ff; - *priority = (xivr >> 32) & 0xff; - - return OPAL_SUCCESS; -} - -static uint64_t psi_p7_irq_attributes(struct irq_source *is __unused, - uint32_t isn __unused) -{ - return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_FREQUENT | IRQ_ATTR_TYPE_LSI; -} static const uint32_t psi_p8_irq_to_xivr[P8_IRQ_PSI_IRQ_COUNT] = { [P8_IRQ_PSI_FSP] = PSIHB_XIVR_FSP, @@ -429,14 +391,6 @@ void psi_irq_reset(void) } } -static const struct irq_source_ops psi_p7_irq_ops = { - .get_xive = psi_p7_get_xive, - .set_xive = psi_p7_set_xive, - .interrupt = psihb_interrupt, - .attributes = psi_p7_irq_attributes, -}; - - static int64_t psi_p8_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t priority) { @@ -679,9 +633,6 @@ static void psi_tce_enable(struct psi *psi, bool enable) u64 val; switch (proc_gen) { - case proc_gen_p7: - addr = psi->regs + PSIHB_CR; - break; case proc_gen_p8: case proc_gen_p9: addr = psi->regs + PSIHB_PHBSCR; @@ -715,10 +666,6 @@ void psi_init_for_fsp(struct psi *psi) psi_tce_enable(psi, false); switch (proc_gen) { - case proc_gen_p7: - out_be64(psi->regs + PSIHB_TAR, PSI_TCE_TABLE_BASE | - PSIHB_TAR_16K_ENTRIES); - break; case proc_gen_p8: case proc_gen_p9: out_be64(psi->regs + PSIHB_TAR, PSI_TCE_TABLE_BASE | @@ -762,20 +709,6 @@ void psi_set_external_irq_policy(bool policy) psi_ext_irq_policy = policy; } -static void psi_init_p7_interrupt(struct psi *psi) -{ - /* On P7, we get a single interrupt */ - out_be64(psi->regs + PSIHB_XIVR, - P7_IRQ_BUID(psi->interrupt) << 16 | - 0xffull << 32); - - /* Configure it in the GX controller as well */ - gx_configure_psi_buid(psi->chip_id, P7_IRQ_BUID(psi->interrupt)); - - /* Register the IRQ source */ - register_irq_source(&psi_p7_irq_ops, psi, psi->interrupt, 1); -} - static void psi_init_p8_interrupts(struct psi *psi) { uint32_t irq; @@ -852,9 +785,6 @@ static void psi_init_interrupts(struct psi *psi) { /* Configure the interrupt BUID and mask it */ switch (proc_gen) { - case proc_gen_p7: - psi_init_p7_interrupt(psi); - break; case proc_gen_p8: psi_init_p8_interrupts(psi); break; @@ -935,10 +865,6 @@ static void psi_create_mm_dtnode(struct psi *psi) /* Hard wire size to 4G */ dt_add_property_u64s(np, "reg", addr, 0x100000000ull); switch (proc_gen) { - case proc_gen_p7: - dt_add_property_strings(np, "compatible", "ibm,psi", - "ibm,power7-psi"); - break; case proc_gen_p8: dt_add_property_strings(np, "compatible", "ibm,psi", "ibm,power8-psi"); @@ -971,31 +897,6 @@ static struct psi *alloc_psi(struct proc_chip *chip, uint64_t base) return psi; } -static struct psi *psi_probe_p7(struct proc_chip *chip, u64 base) -{ - struct psi *psi = NULL; - uint64_t rc, val; - - rc = xscom_read(chip->id, base + PSIHB_XSCOM_P7_HBBAR, &val); - if (rc) { - prerror("PSI: Error %llx reading PSIHB BAR on chip %d\n", - rc, chip->id); - return NULL; - } - if (val & PSIHB_XSCOM_P7_HBBAR_EN) { - psi = alloc_psi(chip, base); - if (!psi) - return NULL; - rc = val >> 36; /* Bits 0:1 = 0x00; 2:27 Bridge BAR... */ - rc <<= 20; /* ... corresponds to bits 18:43 of base addr */ - psi->regs = (void *)rc; - psi->interrupt = get_psi_interrupt(chip->id); - } else - printf("PSI[0x%03x]: Working link not found\n", chip->id); - - return psi; -} - static struct psi *psi_probe_p8(struct proc_chip *chip, u64 base) { struct psi *psi = NULL; @@ -1050,9 +951,7 @@ static bool psi_init_psihb(struct dt_node *psihb) base = dt_get_address(psihb, 0, NULL); - if (dt_node_is_compatible(psihb, "ibm,power7-psihb-x")) - psi = psi_probe_p7(chip, base); - else if (dt_node_is_compatible(psihb, "ibm,power8-psihb-x")) + if (dt_node_is_compatible(psihb, "ibm,power8-psihb-x")) psi = psi_probe_p8(chip, base); else if (dt_node_is_compatible(psihb, "ibm,power9-psihb-x")) psi = psi_probe_p9(chip, base); @@ -384,7 +384,7 @@ struct cpu_idle_states { u32 flags; }; -static struct cpu_idle_states power7_cpu_idle_states[] = { +static struct cpu_idle_states nap_only_cpu_idle_states[] = { { /* nap */ .name = "nap", .latency_ns = 4000, @@ -843,8 +843,8 @@ void add_cpu_idle_state_properties(void) } } else { - states = power7_cpu_idle_states; - nr_states = ARRAY_SIZE(power7_cpu_idle_states); + states = nap_only_cpu_idle_states; + nr_states = ARRAY_SIZE(nap_only_cpu_idle_states); } @@ -756,14 +756,6 @@ static void xscom_init_chip_info(struct proc_chip *chip) /* Identify chip */ switch(val & 0xff) { - case 0xf9: - chip->type = PROC_CHIP_P7; - assert(proc_gen == proc_gen_p7); - break; - case 0xe8: - chip->type = PROC_CHIP_P7P; - assert(proc_gen == proc_gen_p7); - break; case 0xef: chip->type = PROC_CHIP_P8_MURANO; assert(proc_gen == proc_gen_p8); @@ -864,7 +856,7 @@ void xscom_init(void) struct proc_chip *chip; const char *chip_name; static const char *chip_names[] = { - "UNKNOWN", "P7", "P7+", "P8E", "P8", "P8NVL", "P9N", "P9C", "P9P" + "UNKNOWN", "P8E", "P8", "P8NVL", "P9N", "P9C", "P9P" }; chip = get_chip(gcid); diff --git a/include/chip.h b/include/chip.h index 5231d17..f94149b 100644 --- a/include/chip.h +++ b/include/chip.h @@ -31,31 +31,11 @@ * This ID is the HW fabric ID of a chip based on the XSCOM numbering, * also known as "GCID" (Global Chip ID). * - * The format of this number is different between P7 and P8 and care must + * The format of this number is different between chip generations and care must * be taken when trying to convert between this chip ID and some other * representation such as PIR values, interrupt-server numbers etc... : * - * P7 GCID - * ------- - * - * Global chip ID is a 6 bit number: - * - * NodeID T ChipID - * | | | | - * |___|___|___|___|___|___| - * - * Where T is the "torrent" bit and is 0 for P7 chips and 1 for - * directly XSCOM'able IO chips such as Torrent - * - * This macro converts a PIR to a GCID */ -#define P7_PIR2GCID(pir) ({ \ - uint32_t _pir = pir; \ - ((_pir >> 4) & 0x38) | ((_pir >> 5) & 0x3); }) - -#define P7_PIR2COREID(pir) (((pir) >> 2) & 0x7) - -#define P7_PIR2THREADID(pir) ((pir) & 0x3) /* * P8 GCID @@ -119,8 +99,6 @@ struct p9_dio; /* Chip type */ enum proc_chip_type { PROC_CHIP_UNKNOWN, - PROC_CHIP_P7, - PROC_CHIP_P7P, PROC_CHIP_P8_MURANO, PROC_CHIP_P8_VENICE, PROC_CHIP_P8_NAPLES, diff --git a/include/gx.h b/include/gx.h deleted file mode 100644 index 4ba1661..0000000 --- a/include/gx.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Definitions relative to the P7 and P7+ GX controller - */ -#ifndef __GX_H -#define __GX_H - -#include <bitutils.h> - -/* P7 GX Mode 1 register (contains PSI BUID) */ -#define GX_P7_MODE1_REG 0x0201180A -#define GX_P7_MODE1_PSI_BUID PPC_BITMASK(18,26) -#define GX_P7_MODE1_PSI_BUID_DISABLE PPC_BIT(27) - -/* P7+ GX Mode 4 register (PSI and NX BUIDs ) */ -#define GX_P7P_MODE4_REG 0x02011811 -#define GX_P7P_MODE4_ENABLE_NX_BUID PPC_BIT(0) -#define GX_P7P_MODE4_NX_BUID_BASE PPC_BITMASK(1,9) -#define GX_P7P_MODE4_NX_BUID_MASK PPC_BITMASK(10,18) -#define GX_P7P_MODE4_PSI_BUID PPC_BITMASK(19,27) -#define GX_P7P_MODE4_PSI_BUID_DISABLE PPC_BIT(28) - -/* P7 GX TCE BAR and mask */ -#define GX_P7_GX0_TCE_BAR 0x02011845 -#define GX_P7_TCE_BAR_ADDR PPC_BITMASK(0,25) -#define GX_P7_TCE_BAR_ADDR_SHIFT PPC_BITLSHIFT(43) -#define GX_P7_TCE_BAR_ENABLE PPC_BIT(26) -#define GX_P7_GX0_TCE_MASK 0x0201184B -#define GX_P7_TCE_MASK PPC_BITMASK(0,25) -#define GX_P7_GX1_TCE_BAR 0x02011885 -#define GX_P7_GX1_TCE_MASK 0x0201188B - - -extern int gx_configure_psi_buid(uint32_t chip, uint32_t buid); -extern int gx_configure_tce_bar(uint32_t chip, uint32_t gx, uint64_t addr, - uint64_t size); - -#endif /* __GX_H */ diff --git a/include/interrupts.h b/include/interrupts.h index 2c4fa7e..7024fac 100644 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -20,128 +20,6 @@ #include <stdint.h> #include <ccan/list/list.h> -/* - * Note about interrupt numbers on P7/P7+ - * ====================================== - * - * The form of an interrupt number in the system on P7/P7+ is as follow: - * - * | Node | T| Chip|GX| BUID | Level | - * |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--| - * - * Where: - * - * - Node : The 3-bit node number - * - T : 1 for a Torrent chip, 0 otherwise - * - Chip : 2-bit chip number in a node - * - GX : GX bus identifier - * - BUID : Bus identifier (*) - * - Level : Interrupt number - * - * (*) The BUID/Level distinction is mostly historical, interrupt - * controllers such as the ICS in the PHBs "use" some of the - * low BUID bits as an extension to the interrupt number - * - * The NodeID and ChipID together form a 5-bit Processor Chip ID as - * found in the PIR or in the SPIRA data structures (without the T bit) - * - * PSI interrupt numbering scheme: - * ------------------------------- - * - * This is tentatively deduced from stuff I found in some SCOM regs - * and in the BookIV. The PSIHB can be used to specify the 9-bit BUID, - * the Level is always 0. The doc also says that it prepends the 6-bit - * PowerBus chipID (Node + T + Chip). I *assume* that it also prepends - * a 0 in place of the GX bit. - * - * OPAL seems to be arbitrarily using a BUID value of 0x3, I shall do - * the same "just in case" :-) - * - * NOTE: From grep'ing around the giant SCOM file for "Build", I found - * what looks like a register in the GX controller (Mode1 - * register) where the PSI BUID can be stored as well. From - * looking around with the FSP getscom command, it appears - * that both pHyp and OPAL set this consistently to the same - * value that appears in the PHB configuration. - * - * => This is confirmed. The NX needs a similar configuration, this - * tells the GX controller not to forward transactions for these - * BUIDs down the GX bus. - * - * PCI interrupt numbering scheme: - * ------------------------------- - * - * See IOCs - * - * NX interrupt numbering scheme (p7+): - * ------------------------------------ - * - * TBD - * - * - * Additional note about routing of interrupts in P7 and P7+ - * ========================================================= - * - * There are two on-chip sources of interrupts on these that need a - * special treatment: The PSI interrupt and the NX interrupts. - * - * The problem is that they use the same BUID space as the IO chips - * connected to the GX bus, so the GX controller needs to be told - * about these BUIDs in order to avoid forwarding them down the GX - * link (and possibly choking due to the lack of reply). - * - * The bad news is that it's all undocumented. The good news is that - * I found the info after chatting with Bill Daly (HW design) and - * looking at the SCOM register maps. - * - * The way to set that up differs between P7 and P7+: - * - * - On P7, it's in the GX_MODE1 register at SCOM 0x0201180A, which - * among other things, contains those bits: - * - * 18:26 PSI_BUID: BUID to be used to indicate the interrupt is - * for the PSI - * 27 DISABLE_PSI_BUID: set to 1 to disable the buid reservation - * for PSI - * - * So one must write the 9-bit BUID (without the top chipID) of the - * PSI interrupt in there and clear the disable bit. - * - * - On P7+ it's in the GX_MODE4 register at SCOM 0x02011811 - * - * 0 ENABLE_NX_BUID: set to 1 to enable the buid reservation for nx - * 1:9 NX_BUID_BASE: BUID BASE to be used to indicate the interrupt - * is for the nx - * 10:18 NX_BUID_MASK: BUID mask for the nx buid base - * 19:27 PSI_BUID: BUID to be used to indicate the interrupt is for - * the PSI - * 28 DISABLE_PSI_BUID: set to 1 to disable the buid reservation - * for PSI - * - * Note: The NX_BUID_MASK should have bits set to 1 that are relevant for - * the comparison to NX_BUID_BASE, ie 4 interrupts means a mask - * value of b'111111100 - */ - -#define P7_PSI_IRQ_BUID 0x3 /* 9-bit BUID for the PSI interrupts */ - -/* Extract individual components of an IRQ number */ -#define P7_IRQ_BUID(irq) (((irq) >> 4) & 0x1ff) -#define P7_IRQ_GXID(irq) (((irq) >> 13) & 0x1) -#define P7_IRQ_CHIP(irq) (((irq) >> 14) & 0x3) -#define P7_IRQ_TBIT(irq) (((irq) >> 16) & 0x1) -#define P7_IRQ_NODE(irq) (((irq) >> 17) & 0x7) - -/* Extract the "full BUID" (extension + BUID) */ -#define P7_IRQ_FBUID(irq) (((irq) >> 4) & 0xffff) - -/* BUID Extension (GX + CHIP + T + NODE) */ -#define P7_IRQ_BEXT(irq) (((irq) >> 13) & 0x7f) - -/* Strip extension from BUID */ -#define P7_BUID_BASE(buid) ((buid) & 0x1ff) - - /* Note about interrupt numbers on P8 * ================================== * diff --git a/include/mem-map.h b/include/mem-map.h index fa5cacb..fc535e5 100644 --- a/include/mem-map.h +++ b/include/mem-map.h @@ -94,11 +94,8 @@ #define SPIRA_HEAP_BASE (SKIBOOT_BASE + 0x01200000) #define SPIRA_HEAP_SIZE 0x00800000 -/* This is our PSI TCE table. It's 16K entries on P7 and 256K - * entries on P8 - */ +/* This is our PSI TCE table. It's 256K entries on P8 */ #define PSI_TCE_TABLE_BASE (SKIBOOT_BASE + 0x01a00000) -#define PSI_TCE_TABLE_SIZE_P7 0x00020000UL #define PSI_TCE_TABLE_SIZE_P8 0x00200000UL /* Total size of the above area diff --git a/include/nx.h b/include/nx.h index 0322349..dcaf20f 100644 --- a/include/nx.h +++ b/include/nx.h @@ -21,15 +21,12 @@ /* Register addresses and bit fields */ /*************************************/ -#define NX_P7_SAT(sat, offset) XSCOM_SAT(0x1, sat, offset) #define NX_P8_SAT(sat, offset) XSCOM_SAT(0xc, sat, offset) #define NX_P9_SAT(sat, offset) XSCOM_SAT(0x4, sat, offset) /* Random Number Generator */ -#define NX_P7_RNG_BAR NX_P7_SAT(0x2, 0x0c) #define NX_P8_RNG_BAR NX_P8_SAT(0x2, 0x0d) #define NX_P9_RNG_BAR NX_P9_SAT(0x2, 0x0d) -#define NX_P7_RNG_BAR_ADDR PPC_BITMASK(18, 51) #define NX_P8_RNG_BAR_ADDR PPC_BITMASK(14, 51) /* * Section 5.30 of P9 NX Workbook Version 2.42 shows RNG BAR as: @@ -44,12 +41,10 @@ #define NX_RNG_BAR_SIZE PPC_BITMASK(53, 55) #define NX_RNG_BAR_ENABLE PPC_BIT(52) -#define NX_P7_RNG_CFG NX_P7_SAT(0x2, 0x12) #define NX_P8_RNG_CFG NX_P8_SAT(0x2, 0x12) #define NX_RNG_CFG_ENABLE PPC_BIT(63) /* Symmetric Crypto */ -#define NX_P7_SYM_CFG NX_P7_SAT(0x2, 0x09) #define NX_P8_SYM_CFG NX_P8_SAT(0x2, 0x0a) #define NX_SYM_CFG_CI PPC_BITMASK(2, 14) #define NX_SYM_CFG_CT PPC_BITMASK(18, 23) @@ -57,15 +52,13 @@ #define NX_SYM_CFG_ENABLE PPC_BIT(63) /* Asymmetric Crypto */ -#define NX_P7_ASYM_CFG NX_P7_SAT(0x2, 0x0a) #define NX_P8_ASYM_CFG NX_P8_SAT(0x2, 0x0b) #define NX_ASYM_CFG_CI PPC_BITMASK(2, 14) #define NX_ASYM_CFG_CT PPC_BITMASK(18, 23) #define NX_ASYM_CFG_FC_ENABLE PPC_BITMASK(32, 52) #define NX_ASYM_CFG_ENABLE PPC_BIT(63) -/* 842 Compression. CFG is used only on P7+ and P8 */ -#define NX_P7_842_CFG NX_P7_SAT(0x2, 0x0b) +/* 842 Compression. CFG is used only on P8 */ #define NX_P8_842_CFG NX_P8_SAT(0x2, 0x0c) #define NX_842_CFG_CI PPC_BITMASK(2, 14) #define NX_842_CFG_CT PPC_BITMASK(18, 23) @@ -73,7 +66,6 @@ #define NX_842_CFG_ENABLE PPC_BIT(63) /* DMA */ -#define NX_P7_DMA_CFG NX_P7_SAT(0x1, 0x02) #define NX_P8_DMA_CFG NX_P8_SAT(0x1, 0x02) #define NX_P9_DMA_CFG NX_P9_SAT(0x1, 0x02) #define NX_DMA_CFG_GZIP_COMPRESS_MAX_RR PPC_BITMASK(8, 11) @@ -101,7 +93,6 @@ #define NX_DMA_CFG_842_OUTPUT_DATA_WR PPC_BIT(63) /* Engine Enable Register */ -#define NX_P7_EE_CFG NX_P7_SAT(0x1, 0x01) #define NX_P8_EE_CFG NX_P8_SAT(0x1, 0x01) #define NX_P9_EE_CFG NX_P9_SAT(0x1, 0x01) #define NX_EE_CFG_EFUSE PPC_BIT(0) @@ -123,7 +114,6 @@ #define NX_P9_DMA_VAS_MMIO_ADDR PPC_BITMASK(8, 38) /* PowerBus Registers */ -#define NX_P7_CRB_IQ NX_P7_SAT(0x2, 0x0e) #define NX_P8_CRB_IQ NX_P8_SAT(0x2, 0x0f) #define NX_CRB_IQ_SYM PPC_BITMASK(0, 2) #define NX_CRB_IQ_ASYM PPC_BITMASK(3, 5) @@ -165,7 +155,6 @@ #define NX_P9_ERAT_STATUS_CTRL NX_P9_SAT(0x3, 0x16) /* NX Status Register */ -#define NX_P7_STATUS NX_P7_SAT(0x1, 0x00) #define NX_P8_STATUS NX_P8_SAT(0x1, 0x00) #define NX_P9_STATUS NX_P9_SAT(0x1, 0x00) /* DMA Status register */ #define NX_STATUS_HMI_ACTIVE PPC_BIT(54) @@ -180,10 +169,8 @@ #define NX_STATUS_DMA_CH7_IDLE PPC_BIT(63) /* Channel Status Registers */ -#define NX_P7_CH_CRB(ch) NX_P7_SAT(0x1, 0x03 + ((ch) * 2)) #define NX_P8_CH_CRB(ch) NX_P8_SAT(0x1, 0x03 + ((ch) * 2)) #define NX_P9_CH_CRB(ch) NX_P9_SAT(0x1, 0x03 + ((ch) * 2)) -#define NX_P7_CH_STATUS(ch) NX_P7_SAT(0x1, 0x04 + ((ch) * 2)) #define NX_P8_CH_STATUS(ch) NX_P8_SAT(0x1, 0x04 + ((ch) * 2)) #define NX_CH_STATUS_ABORT PPC_BIT(0) #define NX_CH_STATUS_CCB_VALID PPC_BIT(4) @@ -196,7 +183,6 @@ #define NX_CH_STATUS_CRB_SJT PPC_BITMASK(50, 63) /* Kill Register */ -#define NX_P7_CRB_KILL NX_P7_SAT(0x1, 0x13) #define NX_P8_CRB_KILL NX_P8_SAT(0x1, 0x13) #define NX_P9_CRB_KILL NX_P9_SAT(0x1, 0x13) #define NX_CRB_KILL_LPID_KILL PPC_BIT(0) @@ -211,62 +197,41 @@ #define NX_CRB_KILL_ALG_CH PPC_BITMASK(56, 63) /* Fault Isolation Registers (FIR) */ -#define NX_P7_DE_FIR_DATA NX_P7_SAT(0x4, 0x00) #define NX_P8_DE_FIR_DATA NX_P8_SAT(0x4, 0x00) #define NX_P9_DE_FIR_DATA NX_P9_SAT(0x4, 0x00) -#define NX_P7_DE_FIR_DATA_CLR NX_P7_SAT(0x4, 0x01) #define NX_P8_DE_FIR_DATA_CLR NX_P8_SAT(0x4, 0x01) #define NX_P9_DE_FIR_DATA_CLR NX_P9_SAT(0x4, 0x01) -#define NX_P7_DE_FIR_DATA_SET NX_P7_SAT(0x4, 0x02) #define NX_P8_DE_FIR_DATA_SET NX_P8_SAT(0x4, 0x02) #define NX_P9_DE_FIR_DATA_SET NX_P9_SAT(0x4, 0x02) -#define NX_P7_DE_FIR_MASK NX_P7_SAT(0x4, 0x06) #define NX_P8_DE_FIR_MASK NX_P8_SAT(0x4, 0x03) #define NX_P9_DE_FIR_MASK NX_P9_SAT(0x4, 0x03) -#define NX_P7_DE_FIR_MASK_CLR NX_P7_SAT(0x4, 0x07) #define NX_P8_DE_FIR_MASK_CLR NX_P8_SAT(0x4, 0x04) #define NX_P9_DE_FIR_MASK_CLR NX_P9_SAT(0x4, 0x04) -#define NX_P7_DE_FIR_MASK_SET NX_P7_SAT(0x4, 0x08) #define NX_P8_DE_FIR_MASK_SET NX_P8_SAT(0x4, 0x05) #define NX_P9_DE_FIR_MASK_SET NX_P9_SAT(0x4, 0x05) -#define NX_P7_DE_FIR_ACTION0 NX_P7_SAT(0x4, 0x03) #define NX_P8_DE_FIR_ACTION0 NX_P8_SAT(0x4, 0x06) #define NX_P9_DE_FIR_ACTION0 NX_P9_SAT(0x4, 0x06) -#define NX_P7_DE_FIR_ACTION1 NX_P7_SAT(0x4, 0x04) #define NX_P8_DE_FIR_ACTION1 NX_P8_SAT(0x4, 0x07) #define NX_P9_DE_FIR_ACTION1 NX_P9_SAT(0x4, 0x07) -#define NX_P7_DE_FIR_WOF NX_P7_SAT(0x4, 0x05) #define NX_P8_DE_FIR_WOF NX_P8_SAT(0x4, 0x08) -#define NX_P7_PB_FIR_DATA NX_P7_SAT(0x2, 0x00) #define NX_P9_PB_FIR_DATA NX_P9_SAT(0x2, 0x00) #define NX_P8_PB_FIR_DATA NX_P8_SAT(0x2, 0x00) -#define NX_P7_PB_FIR_DATA_CLR NX_P7_SAT(0x2, 0x01) #define NX_P8_PB_FIR_DATA_CLR NX_P8_SAT(0x2, 0x01) #define NX_P9_PB_FIR_DATA_CLR NX_P9_SAT(0x2, 0x01) -#define NX_P7_PB_FIR_DATA_SET NX_P7_SAT(0x2, 0x02) #define NX_P8_PB_FIR_DATA_SET NX_P8_SAT(0x2, 0x02) #define NX_P9_PB_FIR_DATA_SET NX_P9_SAT(0x2, 0x02) -#define NX_P7_PB_FIR_MASK NX_P7_SAT(0x2, 0x06) #define NX_P8_PB_FIR_MASK NX_P8_SAT(0x2, 0x03) #define NX_P9_PB_FIR_MASK NX_P9_SAT(0x2, 0x03) -#define NX_P7_PB_FIR_MASK_CLR NX_P7_SAT(0x2, 0x07) #define NX_P8_PB_FIR_MASK_CLR NX_P8_SAT(0x2, 0x04) #define NX_P9_PB_FIR_MASK_CLR NX_P9_SAT(0x2, 0x04) -#define NX_P7_PB_FIR_MASK_SET NX_P7_SAT(0x2, 0x08) #define NX_P8_PB_FIR_MASK_SET NX_P8_SAT(0x2, 0x05) #define NX_P9_PB_FIR_MASK_SET NX_P9_SAT(0x2, 0x05) -#define NX_P7_PB_FIR_ACTION0 NX_P7_SAT(0x2, 0x03) #define NX_P8_PB_FIR_ACTION0 NX_P8_SAT(0x2, 0x06) #define NX_P9_PB_FIR_ACTION0 NX_P9_SAT(0x2, 0x06) -#define NX_P7_PB_FIR_ACTION1 NX_P7_SAT(0x2, 0x04) #define NX_P8_PB_FIR_ACTION1 NX_P8_SAT(0x2, 0x07) #define NX_P9_PB_FIR_ACTION1 NX_P9_SAT(0x2, 0x07) -#define NX_P7_PB_FIR_WOF NX_P7_SAT(0x2, 0x05) #define NX_P8_PB_FIR_WOF NX_P8_SAT(0x2, 0x08) -#define NX_FIR_MCD_PB_CMD_HANG PPC_BIT(0) /* P7 only */ #define NX_FIR_SHM_INV PPC_BIT(1) -#define NX_FIR_MCD_ARRAY_ECC_CE PPC_BIT(2) /* P7 only */ -#define NX_FIR_MCD_ARRAY_ECC_UE PPC_BIT(3) /* P7 only */ #define NX_FIR_CH0_ECC_CE PPC_BIT(4) #define NX_FIR_CH0_ECC_UE PPC_BIT(5) #define NX_FIR_CH1_ECC_CE PPC_BIT(6) @@ -296,9 +261,6 @@ #define NX_FIR_CRB_UE PPC_BIT(31) #define NX_FIR_CRB_SUE PPC_BIT(32) #define NX_FIR_DMA_RW_ECC_SUE PPC_BIT(33) -#define NX_FIR_MCD_CFG_REG_PARITY PPC_BIT(34) /* P7 only */ -#define NX_FIR_MCD_RECOVERY_INV_STATE PPC_BIT(35) /* P7 only */ -#define NX_FIR_P7_PARITY PPC_BIT(36) /* P7 only */ #define NX_FIR_CH4_ECC_CE PPC_BIT(36) /* P8 only */ #define NX_FIR_CH5_ECC_UE_2 PPC_BIT(37) /* P8 only */ #define NX_FIR_P8_PARITY PPC_BITMASK(48, 49) @@ -312,14 +274,14 @@ /* Arbitrary Coprocessor Type values */ #define NX_CT_SYM (1) -#define NX_CT_ASYM (2) /* on P7+ and P8 */ +#define NX_CT_ASYM (2) /* on P8 */ #define NX_CT_GZIP (2) /* on P9 and later */ #define NX_CT_842 (3) /* Coprocessor Instance counter * NX workbook, section 5.5.1 * "Assigning <CT,CI> Values" - * Only on P7+ and P8 + * Only on P8 */ #define NX_SYM_CFG_CI_MAX (511) #define NX_SYM_CFG_CI_LSHIFT (2) diff --git a/include/opal-api.h b/include/opal-api.h index 2981b46..0b0ae19 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -788,55 +788,6 @@ enum { OPAL_HMI_FLAGS_NEW_EVENT = (1ull << 63), /* An event has been created */ }; -enum { - OPAL_P7IOC_DIAG_TYPE_NONE = 0, - OPAL_P7IOC_DIAG_TYPE_RGC = 1, - OPAL_P7IOC_DIAG_TYPE_BI = 2, - OPAL_P7IOC_DIAG_TYPE_CI = 3, - OPAL_P7IOC_DIAG_TYPE_MISC = 4, - OPAL_P7IOC_DIAG_TYPE_I2C = 5, - OPAL_P7IOC_DIAG_TYPE_LAST = 6 -}; - -struct OpalIoP7IOCErrorData { - __be16 type; - - /* GEM */ - __be64 gemXfir; - __be64 gemRfir; - __be64 gemRirqfir; - __be64 gemMask; - __be64 gemRwof; - - /* LEM */ - __be64 lemFir; - __be64 lemErrMask; - __be64 lemAction0; - __be64 lemAction1; - __be64 lemWof; - - union { - struct OpalIoP7IOCRgcErrorData { - __be64 rgcStatus; /* 3E1C10 */ - __be64 rgcLdcp; /* 3E1C18 */ - }rgc; - struct OpalIoP7IOCBiErrorData { - __be64 biLdcp0; /* 3C0100, 3C0118 */ - __be64 biLdcp1; /* 3C0108, 3C0120 */ - __be64 biLdcp2; /* 3C0110, 3C0128 */ - __be64 biFenceStatus; /* 3C0130, 3C0130 */ - - uint8_t biDownbound; /* BI Downbound or Upbound */ - }bi; - struct OpalIoP7IOCCiErrorData { - __be64 ciPortStatus; /* 3Dn008 */ - __be64 ciPortLdcp; /* 3Dn010 */ - - uint8_t ciPort; /* Index of CI port: 0/1 */ - }ci; - }; -}; - /** * This structure defines the overlay which will be used to store PHB error * data upon request. @@ -846,13 +797,11 @@ enum { }; enum { - OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1, OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2, OPAL_PHB_ERROR_DATA_TYPE_PHB4 = 3 }; enum { - OPAL_P7IOC_NUM_PEST_REGS = 128, OPAL_PHB3_NUM_PEST_REGS = 256, OPAL_PHB4_NUM_PEST_REGS = 512 }; @@ -863,65 +812,6 @@ struct OpalIoPhbErrorCommon { __be32 len; }; -struct OpalIoP7IOCPhbErrorData { - struct OpalIoPhbErrorCommon common; - - __be32 brdgCtl; - - // P7IOC utl regs - __be32 portStatusReg; - __be32 rootCmplxStatus; - __be32 busAgentStatus; - - // P7IOC cfg regs - __be32 deviceStatus; - __be32 slotStatus; - __be32 linkStatus; - __be32 devCmdStatus; - __be32 devSecStatus; - - // cfg AER regs - __be32 rootErrorStatus; - __be32 uncorrErrorStatus; - __be32 corrErrorStatus; - __be32 tlpHdr1; - __be32 tlpHdr2; - __be32 tlpHdr3; - __be32 tlpHdr4; - __be32 sourceId; - - __be32 rsv3; - - // Record data about the call to allocate a buffer. - __be64 errorClass; - __be64 correlator; - - //P7IOC MMIO Error Regs - __be64 p7iocPlssr; // n120 - __be64 p7iocCsr; // n110 - __be64 lemFir; // nC00 - __be64 lemErrorMask; // nC18 - __be64 lemWOF; // nC40 - __be64 phbErrorStatus; // nC80 - __be64 phbFirstErrorStatus; // nC88 - __be64 phbErrorLog0; // nCC0 - __be64 phbErrorLog1; // nCC8 - __be64 mmioErrorStatus; // nD00 - __be64 mmioFirstErrorStatus; // nD08 - __be64 mmioErrorLog0; // nD40 - __be64 mmioErrorLog1; // nD48 - __be64 dma0ErrorStatus; // nD80 - __be64 dma0FirstErrorStatus; // nD88 - __be64 dma0ErrorLog0; // nDC0 - __be64 dma0ErrorLog1; // nDC8 - __be64 dma1ErrorStatus; // nE00 - __be64 dma1FirstErrorStatus; // nE08 - __be64 dma1ErrorLog0; // nE40 - __be64 dma1ErrorLog1; // nE48 - __be64 pestA[OPAL_P7IOC_NUM_PEST_REGS]; - __be64 pestB[OPAL_P7IOC_NUM_PEST_REGS]; -}; - struct OpalIoPhb3ErrorData { struct OpalIoPhbErrorCommon common; diff --git a/include/p7ioc-regs.h b/include/p7ioc-regs.h deleted file mode 100644 index 4eb10d6..0000000 --- a/include/p7ioc-regs.h +++ /dev/null @@ -1,444 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __P7IOC_REGS_H -#define __P7IOC_REGS_H - -/* - * Register definitions - * - * We only define some registers here. Ideally we should auto-generate - * the full list from the spec. For now I add them as I need them - */ - -/* RGC GEM registers */ -#define P7IOC_GEM_XFIR 0x3E0008 -#define P7IOC_GEM_RFIR 0x3E0010 -#define P7IOC_GEM_RIRQFIR 0x3E0018 -#define P7IOC_GEM_MASK 0x3E0020 -#define P7IOC_GEM_RWOF 0x3E0028 - -/* LEM register base */ -#define P7IOC_RGC_LEM_BASE 0x3E1E00 -#define P7IOC_BI_UP_LEM_BASE 0x3C0000 -#define P7IOC_BI_DOWN_LEM_BASE 0x3C0050 -#define P7IOC_CI_PORTn_LEM_BASE(n) (0x3d0200 | ((n) * 0x1000)) -#define P7IOC_PHBn_LEM_BASE(n) (0x000C00 | ((n) * 0x10000)) -#define P7IOC_MISC_LEM_BASE 0x3EA000 -#define P7IOC_I2C_LEM_BASE 0x3EB000 - -/* LEM register offset */ -#define P7IOC_LEM_FIR_OFFSET 0x00 -#define P7IOC_LEM_FIR_AND_OFFSET 0x08 -#define P7IOC_LEM_FIR_OR_OFFSET 0x10 -#define P7IOC_LEM_ERR_MASK_OFFSET 0x18 -#define P7IOC_LEM_ERR_MASK_AND_OFFSET 0x20 -#define P7IOC_LEM_ERR_MASK_OR_OFFSET 0x28 -#define P7IOC_LEM_ACTION_0_OFFSET 0x30 -#define P7IOC_LEM_ACTION_1_OFFSET 0x38 -#define P7IOC_LEM_WOF_OFFSET 0x40 - -/* HSS registers */ -#define P7IOC_HSS_BASE 0x3E8000 -#define P7IOC_HSS_STRIDE 0x200 -#define P7IOC_HSSn_CTL2_OFFSET 0x10 -#define P7IOC_HSSn_CTL3_OFFSET 0x18 -#define P7IOC_HSSn_CTL8_OFFSET 0x40 -#define P7IOC_HSSn_CTL9_OFFSET 0x48 -#define P7IOC_HSSn_CTL10_OFFSET 0x50 -#define P7IOC_HSSn_CTL11_OFFSET 0x58 -#define P7IOC_HSSn_CTL12_OFFSET 0x60 -#define P7IOC_HSSn_CTL13_OFFSET 0x68 -#define P7IOC_HSSn_CTL14_OFFSET 0x70 -#define P7IOC_HSSn_CTL15_OFFSET 0x78 -#define P7IOC_HSSn_CTL16_OFFSET 0x80 -#define P7IOC_HSSn_CTL17_OFFSET 0x88 -#define P7IOC_HSSn_CTL18_OFFSET 0x90 -#define P7IOC_HSSn_CTL19_OFFSET 0x98 -#define P7IOC_HSSn_CTL20_OFFSET 0xa0 -#define P7IOC_HSSn_CTL21_OFFSET 0xa8 -#define P7IOC_HSSn_CTL22_OFFSET 0xb0 -#define P7IOC_HSSn_CTL23_OFFSET 0xb8 - -/* CI Routing registers & helper macros */ -#define P7IOC_CI_RMATC_REG(i) (0x3D0400ul + ((i) << 4)) -#define P7IOC_CI_RMASK_REG(i) (0x3D0408ul + ((i) << 4)) - -#define P7IOC_CI_RMATC_PORT(n) PPC_BIT(n) -#define P7IOC_CI_RMATC_ADDR_VALID PPC_BIT(16) -#define P7IOC_CI_RMATC_BUID_VALID PPC_BIT(17) -#define P7IOC_CI_RMATC_TYPE_VALID PPC_BIT(18) - -/* AIB Addresses are 48-bit, the top 32 are used in - * the routing tables, we thus shift by 16 - */ -#define P7IOC_CI_RMATC_ENCODE_ADDR(addr) ((uint32_t)((addr) >> 16)) -#define P7IOC_CI_RMATC_ENCODE_BUID(buid) ((uint32_t)((buid) << 20)) -#define P7IOC_CI_RMATC_ENCODE_TYPE(type) ((uint32_t)(type)) - -/* CI port numbers */ -#define P7IOC_CI_PHB_PORT(pnum) ((pnum) + 2) -#define P7IOC_CI_UPSTREAM_PORT 0 -#define P7IOC_CI_RGC_PORT 1 - -/* Other random chip registers */ -#define P7IOC_CHIP_FENCE_SHADOW 0x3ec010 -#define P7IOC_CHIP_FENCE_WOF 0x3ec018 -#define P7IOC_CCRR 0x3e1c00 - -/* CI registers */ -#define P7IOC_CIn_BASE(n) (0x3d0000 | ((n) * 0x1000)) -#define P7IOC_CIn_LEM_FIR(n) (P7IOC_CIn_BASE(n) + 0x200) -#define P7IOC_CIn_LEM_FIR_AND(n) (P7IOC_CIn_BASE(n) + 0x208) -#define P7IOC_CIn_LEM_FIR_OR(n) (P7IOC_CIn_BASE(n) + 0x210) -#define P7IOC_CIn_LEM_ERR_MASK(n) (P7IOC_CIn_BASE(n) + 0x218) -#define P7IOC_CIn_LEM_ERR_MASK_AND(n) (P7IOC_CIn_BASE(n) + 0x220) -#define P7IOC_CIn_LEM_ERR_MASK_OR(n) (P7IOC_CIn_BASE(n) + 0x228) - -/* - * PHB registers - */ - -/* PHB Fundamental register set A */ -#define PHB_BUID 0x100 -#define PHB_BUID_LSI PPC_BITMASK(7,15) -#define PHB_BUID_MSI PPC_BITMASK(23,31) -#define PHB_DMA_CHAN_STATUS 0x110 -#define PHB_CPU_LOADSTORE_STATUS 0x120 -#define PHB_CONFIG_DATA 0x130 -#define PHB_LOCK0 0x138 -#define PHB_CONFIG_ADDRESS 0x140 -#define PHB_CA_ENABLE PPC_BIT(0) -#define PHB_CA_BUS PPC_BITMASK(4,11) -#define PHB_CA_DEV PPC_BITMASK(12,16) -#define PHB_CA_FUNC PPC_BITMASK(17,19) -#define PHB_CA_BDFN PPC_BITMASK(4,19) /* bus,dev,func */ -#define PHB_CA_REG PPC_BITMASK(20,31) -#define PHB_LOCK1 0x148 -#define PHB_PHB2_CONFIG 0x160 -#define PHB_PHB2C_64B_TCE_EN PPC_BIT(2) -#define PHB_PHB2C_32BIT_MSI_EN PPC_BIT(8) -#define PHB_PHB2C_IO_EN PPC_BIT(12) -#define PHB_PHB2C_64BIT_MSI_EN PPC_BIT(14) -#define PHB_PHB2C_M32_EN PPC_BIT(16) -#define PHB_IO_BASE_ADDR 0x170 -#define PHB_IO_BASE_MASK 0x178 -#define PHB_IO_START_ADDR 0x180 -#define PHB_M32_BASE_ADDR 0x190 -#define PHB_M32_BASE_MASK 0x198 -#define PHB_M32_START_ADDR 0x1a0 -#define PHB_M64_UPPER_BITS 0x1f0 -#define PHB_TCE_KILL 0x210 -#define PHB_TCEKILL_PAIR PPC_BIT(0) -#define PHB_TCEKILL_ADDR PPC_BITMASK(16,59) -#define PHB_TCE_PREFETCH 0x218 -#define PHB_IODA_ADDR 0x220 -#define PHB_IODA_AD_AUTOINC PPC_BIT(0) -#define PHB_IODA_AD_TSEL PPC_BITMASK(11,15) -#define PHB_IODA_AD_TADR PPC_BITMASK(48,63) -#define PHB_IODA_DATA0 0x228 -#define PHB_IODA_DATA1 0x230 -#define PHB_LOCK2 0x240 -#define PHB_XIVE_UPDATE 0x248 -#define PHB_PHB2_GEN_CAP 0x250 -#define PHB_PHB2_TCE_CAP 0x258 -#define PHB_PHB2_IRQ_CAP 0x260 -#define PHB_PHB2_EEH_CAP 0x268 -#define PHB_PAPR_ERR_INJ_CTL 0x2b0 -#define PHB_PAPR_ERR_INJ_CTL_INB PPC_BIT(0) -#define PHB_PAPR_ERR_INJ_CTL_OUTB PPC_BIT(1) -#define PHB_PAPR_ERR_INJ_CTL_STICKY PPC_BIT(2) -#define PHB_PAPR_ERR_INJ_CTL_CFG PPC_BIT(3) -#define PHB_PAPR_ERR_INJ_CTL_RD PPC_BIT(4) -#define PHB_PAPR_ERR_INJ_CTL_WR PPC_BIT(5) -#define PHB_PAPR_ERR_INJ_CTL_FREEZE PPC_BIT(6) -#define PHB_PAPR_ERR_INJ_ADDR 0x2b8 -#define PHB_PAPR_ERR_INJ_MASK 0x2c0 -#define PHB_PAPR_ERR_INJ_MASK_CFG PPC_BITMASK(4,11) -#define PHB_PAPR_ERR_INJ_MASK_MMIO PPC_BITMASK(16,39) /* 16M aligned */ -#define PHB_PAPR_ERR_INJ_MASK_IO PPC_BITMASK(16,47) /* 64K aligned */ -#define PHB_PAPR_ERR_INJ_MASK_DMA PPC_BITMASK(60,63) /* 16 window */ -#define PHB_ETU_ERR_SUMMARY 0x2c8 - -/* UTL registers */ -#define UTL_SYS_BUS_CONTROL 0x400 -#define UTL_STATUS 0x408 -#define UTL_SYS_BUS_AGENT_STATUS 0x410 -#define UTL_SYS_BUS_AGENT_ERR_SEVERITY 0x418 -#define UTL_SYS_BUS_AGENT_IRQ_EN 0x420 -#define UTL_SYS_BUS_BURST_SZ_CONF 0x440 -#define UTL_REVISION_ID 0x448 -#define UTL_OUT_POST_HDR_BUF_ALLOC 0x4c0 -#define UTL_OUT_POST_DAT_BUF_ALLOC 0x4d0 -#define UTL_IN_POST_HDR_BUF_ALLOC 0x4e0 -#define UTL_IN_POST_DAT_BUF_ALLOC 0x4f0 -#define UTL_OUT_NP_BUF_ALLOC 0x500 -#define UTL_IN_NP_BUF_ALLOC 0x510 -#define UTL_PCIE_TAGS_ALLOC 0x520 -#define UTL_GBIF_READ_TAGS_ALLOC 0x530 -#define UTL_PCIE_PORT_CONTROL 0x540 -#define UTL_PCIE_PORT_STATUS 0x548 -#define UTL_PCIE_PORT_ERROR_SEV 0x550 -#define UTL_PCIE_PORT_IRQ_EN 0x558 -#define UTL_RC_STATUS 0x560 -#define UTL_RC_ERR_SEVERITY 0x568 -#define UTL_RC_IRQ_EN 0x570 -#define UTL_EP_STATUS 0x578 -#define UTL_EP_ERR_SEVERITY 0x580 -#define UTL_EP_ERR_IRQ_EN 0x588 -#define UTL_PCI_PM_CTRL1 0x590 -#define UTL_PCI_PM_CTRL2 0x598 -#define UTL_GP_CTL1 0x5a0 -#define UTL_GP_CTL2 0x5a8 - -/* PCI-E Stack registers */ -#define PHB_PCIE_SYSTEM_CONFIG 0x600 -#define PHB_PCIE_BUS_NUMBER 0x608 -#define PHB_PCIE_SYSTEM_TEST 0x618 -#define PHB_PCIE_LINK_MANAGEMENT 0x630 -#define PHB_PCIE_DLP_TRAIN_CTL 0x640 -#define PHB_PCIE_DLP_TCTX_DISABLE PPC_BIT(1) -#define PHB_PCIE_DLP_TCRX_DISABLED PPC_BIT(16) -#define PHB_PCIE_DLP_TC_DL_LINKUP PPC_BIT(21) -#define PHB_PCIE_DLP_TC_DL_PGRESET PPC_BIT(22) -#define PHB_PCIE_DLP_TC_DL_LINKACT PPC_BIT(23) -#define PHB_PCIE_SLOP_LOOPBACK_STATUS 0x648 -#define PHB_PCIE_AER_CONTROL 0x650 -#define PHB_PCIE_AUX_POWER_CONTROL 0x658 -#define PHB_PCIE_SLOTCTL1 0x660 -#define PHB_PCIE_SLOTCTL2 0x668 -#define PHB_PCIE_SLOTCTL2_SLOTWAKE PPC_BIT(16) -#define PHB_PCIE_SLOTCTL2_PWR_EN_STAT PPC_BIT(17) -#define PHB_PCIE_SLOTCTL2_RCK_EN_STAT PPC_BIT(18) -#define PHB_PCIE_SLOTCTL2_PERST_STAT PPC_BIT(19) -#define PHB_PCIE_SLOTCTL2_PLED_S PPC_BITMASK(20,21) /* use PCIE_INDIC_* */ -#define PHB_PCIE_SLOTCTL2_ALED_S PPC_BITMASK(22,23) -#define PHB_PCIE_SLOTCTL2_PRSTN_STAT PPC_BIT(24) -#define PHB_PCIE_SLOTCTL2_PWRFLT_STAT PPC_BIT(25) -#define PHB_PCIE_UTL_CONFIG 0x670 -#define PHB_PCIE_DLP_CONTROL 0x678 -#define PHB_PCIE_UTL_ERRLOG1 0x680 -#define PHB_PCIE_UTL_ERRLOG2 0x688 -#define PHB_PCIE_UTL_ERRLOG3 0x690 -#define PHB_PCIE_UTL_ERRLOG4 0x698 -#define PHB_PCIE_DLP_ERRLOG1 0x6a0 -#define PHB_PCIE_DLP_ERRLOG2 0x6a8 -#define PHB_PCIE_UTL_ERR_INJECT 0x6c0 -#define PHB_PCIE_TLDLP_ERR_INJECT 0x6c8 -#define PHB_PCIE_STRAPPING 0x700 - -/* Fundamental register set B */ -#define PHB_VERSION 0x800 -#define PHB_RESET 0x808 -#define PHB_CONTROL 0x810 -#define PHB_AIB_RX_CRED_INIT_TIMER 0x818 -#define PHB_AIB_RX_CMD_CRED 0x820 -#define PHB_AIB_RX_DATA_CRED 0x828 -#define PHB_AIB_TX_CMD_CRED 0x830 -#define PHB_AIB_TX_DATA_CRED 0x838 -#define PHB_AIB_TX_CHAN_MAPPING 0x840 -#define PHB_AIB_TX_CRED_SYNC_CTRL 0x848 -#define PHB_LEGACY_CTRL 0x850 -#define PHB_AIB_TAG_ENABLE 0x858 -#define PHB_AIB_FENCE_CTRL 0x860 -#define PHB_TCE_TAG_ENABLE 0x868 -#define PHB_TCE_WATERMARK 0x870 -#define PHB_TIMEOUT_CTRL1 0x878 -#define PHB_TIMEOUT_CTRL2 0x880 -#define PHB_QUIESCE_DMA_G 0x888 -#define PHB_AIB_TAG_STATUS 0x900 -#define PHB_TCE_TAG_STATUS 0x908 - -/* FIR & Error registers */ -#define PHB_LEM_FIR_ACCUM 0xc00 -#define PHB_LEM_FIR_AND_MASK 0xc08 -#define PHB_LEM_FIR_OR_MASK 0xc10 -#define PHB_LEM_ERROR_MASK 0xc18 -#define PHB_LEM_ERROR_AND_MASK 0xc20 -#define PHB_LEM_ERROR_OR_MASK 0xc28 -#define PHB_LEM_ACTION0 0xc30 -#define PHB_LEM_ACTION1 0xc38 -#define PHB_LEM_WOF 0xc40 -#define PHB_ERR_STATUS 0xc80 -#define PHB_ERR1_STATUS 0xc88 -#define PHB_ERR_INJECT 0xc90 -#define PHB_ERR_LEM_ENABLE 0xc98 -#define PHB_ERR_IRQ_ENABLE 0xca0 -#define PHB_ERR_FREEZE_ENABLE 0xca8 -#define PHB_ERR_AIB_FENCE_ENABLE 0xcb0 -#define PHB_ERR_LOG_0 0xcc0 -#define PHB_ERR_LOG_1 0xcc8 -#define PHB_ERR_STATUS_MASK 0xcd0 -#define PHB_ERR1_STATUS_MASK 0xcd8 - -#define PHB_OUT_ERR_STATUS 0xd00 -#define PHB_OUT_ERR1_STATUS 0xd08 -#define PHB_OUT_ERR_INJECT 0xd10 -#define PHB_OUT_ERR_LEM_ENABLE 0xd18 -#define PHB_OUT_ERR_IRQ_ENABLE 0xd20 -#define PHB_OUT_ERR_FREEZE_ENABLE 0xd28 -#define PHB_OUT_ERR_AIB_FENCE_ENABLE 0xd30 -#define PHB_OUT_ERR_LOG_0 0xd40 -#define PHB_OUT_ERR_LOG_1 0xd48 -#define PHB_OUT_ERR_STATUS_MASK 0xd50 -#define PHB_OUT_ERR1_STATUS_MASK 0xd58 - -#define PHB_INA_ERR_STATUS 0xd80 -#define PHB_INA_ERR1_STATUS 0xd88 -#define PHB_INA_ERR_INJECT 0xd90 -#define PHB_INA_ERR_LEM_ENABLE 0xd98 -#define PHB_INA_ERR_IRQ_ENABLE 0xda0 -#define PHB_INA_ERR_FREEZE_ENABLE 0xda8 -#define PHB_INA_ERR_AIB_FENCE_ENABLE 0xdb0 -#define PHB_INA_ERR_LOG_0 0xdc0 -#define PHB_INA_ERR_LOG_1 0xdc8 -#define PHB_INA_ERR_STATUS_MASK 0xdd0 -#define PHB_INA_ERR1_STATUS_MASK 0xdd8 - -#define PHB_INB_ERR_STATUS 0xe00 -#define PHB_INB_ERR1_STATUS 0xe08 -#define PHB_INB_ERR_INJECT 0xe10 -#define PHB_INB_ERR_LEM_ENABLE 0xe18 -#define PHB_INB_ERR_IRQ_ENABLE 0xe20 -#define PHB_INB_ERR_FREEZE_ENABLE 0xe28 -#define PHB_INB_ERR_AIB_FENCE_ENABLE 0xe30 -#define PHB_INB_ERR_LOG_0 0xe40 -#define PHB_INB_ERR_LOG_1 0xe48 -#define PHB_INB_ERR_STATUS_MASK 0xe50 -#define PHB_INB_ERR1_STATUS_MASK 0xe58 - -/* Performance monitor & Debug registers */ -#define PHB_TRACE_CONTROL 0xf80 -#define PHB_PERFMON_CONFIG 0xf88 -#define PHB_PERFMON_CTR0 0xf90 -#define PHB_PERFMON_CTR1 0xf98 -#define PHB_PERFMON_CTR2 0xfa0 -#define PHB_PERFMON_CTR3 0xfa8 -#define PHB_HOTPLUG_OVERRIDE 0xfb0 - -/* - * IODA tables - */ - -#define IODA_TBL_HRT 0 -#define IODA_TBL_LIST 1 -#define IODA_TBL_LXIVT 2 -#define IODA_TBL_MIST 3 -#define IODA_TBL_MXIVT 4 -#define IODA_TBL_MVT 5 -#define IODA_TBL_PELTM 6 -#define IODA_TBL_PESTA 7 -#define IODA_TBL_PESTB 8 -#define IODA_TBL_TVT 9 -#define IODA_TBL_TCAM 10 -#define IODA_TBL_TDR 11 -#define IODA_TBL_PELTV 12 -#define IODA_TBL_M64BT 16 -#define IODA_TBL_IODT 17 -#define IODA_TBL_M32DT 18 -#define IODA_TBL_M64DT 19 -#define IODA_TBL_PEEV 20 - -/* L/M XIVT */ -#define IODA_XIVT_SERVER PPC_BITMASK(8,23) -#define IODA_XIVT_PRIORITY PPC_BITMASK(24,31) -#define IODA_XIVT_PENUM PPC_BITMASK(41,47) -#define IODA_XIVT_HUBNUM PPC_BITMASK(58,59) - -/* M64BT */ -#define IODA_M64BT_ENABLE PPC_BIT(0) -#define IODA_M64BT_BASE PPC_BITMASK(8,31) -#define IODA_M64BT_MASK PPC_BITMASK(40,63) - -/* IODT/M32DT/M64DX */ -#define IODA_XXDT_PE PPC_BITMASK(0,6) - -/* PELTM */ -#define IODA_PELTM_BUS PPC_BITMASK(0,7) -#define IODA_PELTM_DEV PPC_BITMASK(8,12) -#define IODA_PELTM_FUNC PPC_BITMASK(13,15) -#define IODA_PELTM_BUS_VALID PPC_BITMASK(16,18) -#define IODA_BUS_VALID_ANY 0 -#define IODA_BUS_VALID_3_BITS 2 -#define IODA_BUS_VALID_4_BITS 3 -#define IODA_BUS_VALID_5_BITS 4 -#define IODA_BUS_VALID_6_BITS 5 -#define IODA_BUS_VALID_7_BITS 6 -#define IODA_BUS_VALID_ALL 7 -#define IODA_PELTM_DEV_VALID PPC_BIT(19) -#define IODA_PELTM_FUNC_VALID PPC_BIT(20) - -/* TVT */ -#define IODA_TVT0_TABLE_ADDR PPC_BITMASK(0,47) -#define IODA_TVT0_BUS_VALID PPC_BITMASK(48,50) -#define IODA_TVT0_TCE_TABLE_SIZE PPC_BITMASK(51,55) -#define IODA_TVT0_BUS_NUM PPC_BITMASK(56,63) -#define IODA_TVT1_DEV_VALID PPC_BIT(2) -#define IODA_TVT1_DEV_NUM PPC_BITMASK(3,7) -#define IODA_TVT1_HUB_NUM PPC_BITMASK(10,11) -#define IODA_TVT1_FUNC_VALID PPC_BIT(12) -#define IODA_TVT1_FUNC_NUM PPC_BITMASK(13,15) -#define IODA_TVT1_IO_PSIZE PPC_BITMASK(19,23) -#define IODA_TVT1_PE_NUM PPC_BITMASK(57,63) - -/* MVT */ -#define IODA_MVT_VALID PPC_BIT(0) -#define IODA_MVT_BUS_VALID PPC_BITMASK(21,23) -#define IODA_MVT_BUS_NUM PPC_BITMASK(24,31) -#define IODA_MVT_PE_NUM PPC_BITMASK(41,47) -#define IODA_MVT_DEV_VALID PPC_BIT(50) -#define IODA_MVT_DEV_NUM PPC_BITMASK(51,55) -#define IODA_MVT_FUNC_VALID PPC_BIT(60) -#define IODA_MVT_FUNC_NUM PPC_BITMASK(61,63) - -/* PESTA */ -#define IODA_PESTA_MMIO_FROZEN PPC_BIT(0) -#define IODA_PESTA_MMIO_CAUSE PPC_BIT(2) -#define IODA_PESTA_CFG_READ PPC_BIT(3) -#define IODA_PESTA_CFG_WRITE PPC_BIT(4) -#define IODA_PESTA_TTYPE PPC_BITMASK(5,7) -#define PESTA_TTYPE_DMA_WRITE 0 -#define PESTA_TTYPE_MSI 1 -#define PESTA_TTYPE_DMA_READ 2 -#define PESTA_TTYPE_DMA_READ_RESP 3 -#define PESTA_TTYPE_MMIO_LOAD 4 -#define PESTA_TTYPE_MMIO_STORE 5 -#define PESTA_TTYPE_OTHER 7 -#define IODA_PESTA_CA_RETURN PPC_BIT(8) -#define IODA_PESTA_UTL_RTOS_TIMEOUT PPC_BIT(8) /* Same bit as CA return */ -#define IODA_PESTA_UR_RETURN PPC_BIT(9) -#define IODA_PESTA_UTL_NONFATAL PPC_BIT(10) -#define IODA_PESTA_UTL_FATAL PPC_BIT(11) -#define IODA_PESTA_TAG_REUSE_ERROR PPC_BIT(12) -#define IODA_PESTA_PARITY_UE PPC_BIT(13) -#define IODA_PESTA_UTL_CORRECTABLE PPC_BIT(14) -#define IODA_PESTA_UTL_INTERRUPT PPC_BIT(15) -#define IODA_PESTA_MMIO_XLATE PPC_BIT(16) -#define IODA_PESTA_IODA_ERROR PPC_BIT(16) /* Same bit as MMIO xlate */ -#define IODA_PESTA_TVT_EXT_ERROR PPC_BIT(17) -#define IODA_PESTA_TCE_PAGE_FAULT PPC_BIT(18) -#define IODA_PESTA_TCE_ACCESS_FAULT PPC_BIT(19) -#define IODA_PESTA_DMA_RESP_TIMEOUT PPC_BIT(20) -#define IODA_PESTA_AIB_SIZE_INVALID PPC_BIT(21) -#define IODA_PESTA_LEM_BIT PPC_BITMASK(26,31) -#define IODA_PESTA_RID PPC_BITMASK(32,47) -#define IODA_PESTA_MSI_DATA PPC_BITMASK(48,63) - -/* PESTB */ -#define IODA_PESTB_DMA_STOPPED PPC_BIT(0) -#define IODA_PESTB_FAIL_ADDR PPC_BITMASK(3,63) - -#endif /* __P7IOC_REGS_H */ diff --git a/include/p7ioc.h b/include/p7ioc.h deleted file mode 100644 index 96f9209..0000000 --- a/include/p7ioc.h +++ /dev/null @@ -1,367 +0,0 @@ -/* Copyright 2013-2014 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __P7IOC_H -#define __P7IOC_H - -#include <cec.h> -#include <pci.h> - -#include <ccan/container_of/container_of.h> - -/* - * Memory windows and BUID assignment - * - * - GX BAR assignment - * - * I don't know of any spec here, so we're going to mimmic what - * OPAL seems to be doing: - * - * - BAR 0 : 32M, disabled. We just leave it alone. - * - BAR 1 : 8G, enabled. Appears to correspond to the MMIO - * space of the IOC itself and the PCI IO space - * - BAR 2: 128G, - * - BAR 3: 128G, - * - BAR 4: 128G, all 3 contiguous, forming a single 368G region - * and is used for M32 and M64 PHB windows. - * - * - Memory map - * - * MWIN1 = BAR1 (8G) - * MWIN2 = BAR2,3,4 (384G) - * - * MWIN2 is divided into 6 * 4G regions for use by M32's (*) and - * 6 * 32G regions for use by M64's. - * - * (*) The M32 will typically be configured to only 2G or so, however - * the OS is in control of that setting, and since we have to reserve - * a power of two, we reserve the whole 4G. - * - * - RGC registers: MWIN1 + 0x00000000 - * - PHBn IO space: MWIN1 + 0x01000000 + n * 0x00800000 (8M each) - * - PHBn M32 : MWIN2 + n * 0x1_00000000 (4G each) - * - PHBn M64 : MWIN2 + (n + 1) * 0x8_00000000 (32G each) - * - * - BUID map. The RGC has interrupts, each PHB has then its own - * interrupts (errors etc...), 4 LSIs and 256 LSIs so - * respectively 1 BUID for self, 1 for LSIs and 16 for LSIs - * - * We keep all BUIDs below 0x10 reserved. They will be used for things - * like the PSI controller, the NX unit, etc.. in the P7 chip. - * - * RGC : 0x010 - * PHBn LSI : 0x040 + n * 0x40 ( 1 BUID) - * PHBn MSI : 0x060 + n * 0x40 (0x10 BUIDs) - * - * -> For routing, each PHB gets a block of 0x40 BUIDs: - * - * from 0x40 * (n + 1) to 0x7f * (n + 1) - */ - -/* Some definitions resulting from the above description - * - * Note: A better approach might be to read the GX BAR content - * and isolate the biggest contiguous windows. From there - * we could divide things algorithmically and thus be - * less sensitive to a change in the memory map by the FSP - */ -#define MWIN1_SIZE 0x200000000ul /* MWIN1 is 8G */ -#define MWIN2_SIZE 0x6000000000ul /* MWIN2 is 384G */ -#define PHB_IO_OFFSET 0x01000000ul /* Offset of PHB IO space in MWIN1 */ -#define PHB_IO_SIZE 0x00800000ul -#define PHB_M32_OFFSET 0x0ul /* Offset of PHB M32 space in MWIN2 */ -#define PHB_M32_SIZE 0x100000000ul -#define PHB_M64_OFFSET 0x800000000ul /* Offset of PHB M64 space in MWIN2 */ -#define PHB_M64_SIZE 0x800000000ul -#define RGC_BUID_OFFSET 0x10 /* Offset of RGC BUID */ -#define PHB_BUID_OFFSET 0x40 /* Offset of PHB BUID blocks */ -#define PHB_BUID_SIZE 0x40 /* Size of PHB BUID blocks */ -#define PHB_BUID_LSI_OFFSET 0x00 /* Offset of LSI in PHB BUID block */ -#define PHB_BUID_MSI_OFFSET 0x20 /* Offset of MSI in PHB BUID block */ -#define PHB_BUID_MSI_SIZE 0x10 /* Size of PHB MSI BUID block */ - -#define PHBn_IO_BASE(n) (PHB_IO_OFFSET + (n) * PHB_IO_SIZE) -#define PHBn_M32_BASE(n) (PHB_M32_OFFSET + (n) * PHB_M32_SIZE) -#define PHBn_M64_BASE(n) (PHB_M64_OFFSET + (n) * PHB_M64_SIZE) -#define PHBn_BUID_BASE(n) (PHB_BUID_OFFSET + (n) * PHB_BUID_SIZE) - -#define BUID_TO_PHB(buid) (((buid) - PHB_BUID_OFFSET) / PHB_BUID_SIZE) - -/* p7ioc has 6 PHBs */ -#define P7IOC_NUM_PHBS 6 - -/* M32 window setting at boot: - * - * To allow for DMA, we need to split the 32-bit PCI address space between - * MMIO and DMA. For now, we use a 2G/2G split with MMIO at the top. - * - * Note: The top 64K of the M32 space are used by MSIs. This is not - * visible here but need to be conveyed to the OS one way or another - * - * Note2: The space reserved in the system address space for M32 is always - * 4G. That we chose to use a smaller portion of it is not relevant to - * the upper levels. To keep things consistent, the offset we apply to - * the window start is also applied on the host side. - */ -#define M32_PCI_START 0x80000000 -#define M32_PCI_SIZE 0x80000000 - -/* PHB registers exist in both a hard coded space and a programmable - * AIB space. We program the latter to the values recommended in the - * documentation: - * - * 0x80000 + n * 0x10000 - */ -#define PHBn_ASB_BASE(n) (((n) << 16)) -#define PHBn_ASB_SIZE 0x10000ul -#define PHBn_AIB_BASE(n) (0x80000ul + ((n) << 16)) -#define PHBn_AIB_SIZE 0x10000ul - -/* - * LSI interrupts - * - * The LSI interrupt block supports 8 interrupts. 4 of them are the - * standard PCIe INTA..INTB. The rest is for additional functions - * of the PHB - */ -#define PHB_LSI_PCIE_INTA 0 -#define PHB_LSI_PCIE_INTB 1 -#define PHB_LSI_PCIE_INTC 2 -#define PHB_LSI_PCIE_INTD 3 -#define PHB_LSI_PCIE_HOTPLUG 4 -#define PHB_LSI_PCIE_PERFCTR 5 -#define PHB_LSI_PCIE_UNUSED 6 -#define PHB_LSI_PCIE_ERROR 7 - -/* P7IOC PHB slot states */ -#define P7IOC_SLOT_NORMAL PCI_SLOT_STATE_NORMAL -#define P7IOC_SLOT_LINK PCI_SLOT_STATE_LINK -#define P7IOC_SLOT_LINK_START (P7IOC_SLOT_LINK + 1) -#define P7IOC_SLOT_LINK_WAIT (P7IOC_SLOT_LINK + 2) -#define P7IOC_SLOT_HRESET PCI_SLOT_STATE_HRESET -#define P7IOC_SLOT_HRESET_START (P7IOC_SLOT_HRESET + 1) -#define P7IOC_SLOT_HRESET_TRAINING (P7IOC_SLOT_HRESET + 2) -#define P7IOC_SLOT_HRESET_DELAY (P7IOC_SLOT_HRESET + 3) -#define P7IOC_SLOT_HRESET_DELAY2 (P7IOC_SLOT_HRESET + 4) -#define P7IOC_SLOT_FRESET PCI_SLOT_STATE_FRESET -#define P7IOC_SLOT_FRESET_START (P7IOC_SLOT_FRESET + 1) -#define P7IOC_SLOT_FRESET_TRAINING (P7IOC_SLOT_FRESET + 2) -#define P7IOC_SLOT_FRESET_POWER_OFF (P7IOC_SLOT_FRESET + 3) -#define P7IOC_SLOT_FRESET_POWER_ON (P7IOC_SLOT_FRESET + 4) -#define P7IOC_SLOT_FRESET_ASSERT (P7IOC_SLOT_FRESET + 5) -#define P7IOC_SLOT_FRESET_DEASSERT (P7IOC_SLOT_FRESET + 6) -#define P7IOC_SLOT_CRESET PCI_SLOT_STATE_CRESET -#define P7IOC_SLOT_CRESET_START (P7IOC_SLOT_CRESET + 1) - -/* - * In order to support error detection and recovery on different - * types of IOCs (e.g. P5IOC, P7IOC, P8IOC), the best bet would - * be make the implementation to be 2 layers: OPAL layer and IOC - * layer. The OPAL layer just handles the general information and - * IOC layer should process much more detailed information, which - * is sensitive to itself. - */ -#define P7IOC_ERR_SRC_NONE 0 -#define P7IOC_ERR_SRC_EI 1 -#define P7IOC_ERR_SRC_RGC 2 -#define P7IOC_ERR_SRC_BI_UP 3 -#define P7IOC_ERR_SRC_BI_DOWN 4 -#define P7IOC_ERR_SRC_CI_P0 5 -#define P7IOC_ERR_SRC_CI_P1 6 -#define P7IOC_ERR_SRC_CI_P2 7 -#define P7IOC_ERR_SRC_CI_P3 8 -#define P7IOC_ERR_SRC_CI_P4 9 -#define P7IOC_ERR_SRC_CI_P5 10 -#define P7IOC_ERR_SRC_CI_P6 11 -#define P7IOC_ERR_SRC_CI_P7 12 -#define P7IOC_ERR_SRC_PHB0 13 -#define P7IOC_ERR_SRC_PHB1 14 -#define P7IOC_ERR_SRC_PHB2 15 -#define P7IOC_ERR_SRC_PHB3 16 -#define P7IOC_ERR_SRC_PHB4 17 -#define P7IOC_ERR_SRC_PHB5 18 -#define P7IOC_ERR_SRC_MISC 19 -#define P7IOC_ERR_SRC_I2C 20 -#define P7IOC_ERR_SRC_LAST 21 - -#define P7IOC_ERR_CLASS_NONE 0 -#define P7IOC_ERR_CLASS_GXE 1 -#define P7IOC_ERR_CLASS_PLL 2 -#define P7IOC_ERR_CLASS_RGA 3 -#define P7IOC_ERR_CLASS_PHB 4 -#define P7IOC_ERR_CLASS_ER 5 -#define P7IOC_ERR_CLASS_INF 6 -#define P7IOC_ERR_CLASS_MAL 7 -#define P7IOC_ERR_CLASS_LAST 8 - -/* - * P7IOC error descriptor. For errors from PHB and PE, they - * will be cached to the corresponding PHBs. However, the - * left errors (e.g. EI, CI Port0/1) will be cached to the - * IOC directly. - */ -struct p7ioc_err { - uint32_t err_src; - uint32_t err_class; - uint32_t err_bit; -}; - -struct p7ioc; - -#define P7IOC_PHB_CFG_USE_ASB 0x00000001 /* ASB to access PCI-CFG */ -#define P7IOC_PHB_CFG_BLOCKED 0x00000002 /* PCI-CFG blocked except 0 */ - -struct p7ioc_phb { - uint8_t index; /* 0..5 index inside p7ioc */ - uint8_t gen; - uint32_t flags; - bool broken; -#define P7IOC_REV_DD10 0x00a20001 -#define P7IOC_REV_DD11 0x00a20002 - uint32_t rev; /* Both major and minor have 2 bytes */ - void *regs_asb; - void *regs; /* AIB regs */ - uint32_t buid_lsi; - uint32_t buid_msi; - uint64_t io_base; - uint64_t m32_base; - uint64_t m64_base; - int64_t ecap; /* cached PCI-E cap offset */ - int64_t aercap; /* cached AER ecap offset */ - uint64_t lxive_cache[8]; - uint64_t mxive_cache[256]; - uint64_t mve_cache[256]; - uint64_t peltm_cache[128]; - uint64_t peltv_lo_cache[128]; - uint64_t peltv_hi_cache[128]; - uint64_t tve_lo_cache[128]; - uint64_t tve_hi_cache[128]; - uint64_t iod_cache[128]; - uint64_t m32d_cache[128]; - uint64_t m64b_cache[16]; - uint64_t m64d_cache[128]; - bool err_pending; - struct p7ioc_err err; - struct p7ioc *ioc; - struct phb phb; -}; - -static inline struct p7ioc_phb *phb_to_p7ioc_phb(struct phb *phb) -{ - return container_of(phb, struct p7ioc_phb, phb); -} - -static inline bool p7ioc_phb_err_pending(struct p7ioc_phb *p) -{ - return p->err_pending; -} - -static inline void p7ioc_phb_set_err_pending(struct p7ioc_phb *p, bool pending) -{ - if (!pending) { - p->err.err_src = P7IOC_ERR_SRC_NONE; - p->err.err_class = P7IOC_ERR_CLASS_NONE; - p->err.err_bit = -1; - } - - p->err_pending = pending; -} - -/* - * State structure for P7IOC IO HUB - */ -struct p7ioc { - /* Device node */ - struct dt_node *dt_node; - - /* MMIO regs */ - void *regs; - - /* Main MMIO window from GX for registers & PCI IO space */ - uint64_t mmio1_win_start; - uint64_t mmio1_win_size; - - /* Secondary MMIO window for PCI MMIO space */ - uint64_t mmio2_win_start; - uint64_t mmio2_win_size; - - /* BUID base for the PHB. This does include the top bits - * (chip, GX bus ID, etc...). This is initialized from the - * SPIRA. It does not contain the offset 0x10 for RGC - * interrupts. - * - * The OPAL-defined "interrupt-base" property will contain - * the RGC BUID, not this base value, since this is the real - * starting point of interrupts for the IOC and we don't want - * to cover the BUID 0..f gap which is reserved for P7 on-chip - * interrupt sources. - */ - uint32_t buid_base; - uint32_t rgc_buid; - - /* XIVT cache for RGC interrupts */ - uint64_t xive_cache[16]; - bool err_pending; - struct p7ioc_err err; - - /* PHB array & presence detect */ - struct p7ioc_phb phbs[P7IOC_NUM_PHBS]; - uint8_t phb_pdt; - - struct io_hub hub; -}; - -static inline struct p7ioc *iohub_to_p7ioc(struct io_hub *hub) -{ - return container_of(hub, struct p7ioc, hub); -} - -static inline bool p7ioc_err_pending(struct p7ioc *ioc) -{ - return ioc->err_pending; -} - -static inline void p7ioc_set_err_pending(struct p7ioc *ioc, bool pending) -{ - if (!pending) { - ioc->err.err_src = P7IOC_ERR_SRC_NONE; - ioc->err.err_class = P7IOC_ERR_CLASS_NONE; - ioc->err.err_bit = -1; - } - - ioc->err_pending = pending; -} - -static inline bool p7ioc_phb_enabled(struct p7ioc *ioc, unsigned int phb) -{ - return !!(ioc->phb_pdt & (0x80 >> phb)); -} - -extern int64_t p7ioc_inits(struct p7ioc *ioc); - -extern void p7ioc_phb_setup(struct p7ioc *ioc, uint8_t index); -extern int64_t p7ioc_phb_init(struct p7ioc_phb *p); - -extern bool p7ioc_check_LEM(struct p7ioc *ioc, uint16_t *pci_error_type, - uint16_t *severity); -extern int64_t p7ioc_phb_get_xive(struct p7ioc_phb *p, uint32_t isn, - uint16_t *server, uint8_t *prio); -extern int64_t p7ioc_phb_set_xive(struct p7ioc_phb *p, uint32_t isn, - uint16_t server, uint8_t prio); -extern void p7ioc_reset(struct io_hub *hub); -extern void p7ioc_phb_reset(struct phb *phb); - -#endif /* __P7IOC_H */ diff --git a/include/processor.h b/include/processor.h index edcc210..b759752 100644 --- a/include/processor.h +++ b/include/processor.h @@ -19,7 +19,7 @@ #include <bitutils.h> -/* P7 MSR bits */ +/* MSR bits */ #define MSR_SF PPC_BIT(0) /* 64-bit mode */ #define MSR_HV PPC_BIT(3) /* Hypervisor mode */ #define MSR_VEC PPC_BIT(38) /* VMX enable */ @@ -41,7 +41,6 @@ /* PIR */ #define SPR_PIR_P9_MASK 0x7fff /* Mask of implemented bits */ #define SPR_PIR_P8_MASK 0x1fff /* Mask of implemented bits */ -#define SPR_PIR_P7_MASK 0x03ff /* Mask of implemented bits */ /* SPR register definitions */ #define SPR_DSCR 0x011 /* RW: Data stream control reg */ @@ -96,12 +95,7 @@ /* Bits in LPCR */ -/* Powersave Exit Cause Enable is different for P7 and P8 */ -#define SPR_LPCR_P7_PECE PPC_BITMASK(49,51) -#define SPR_LPCR_P7_PECE0 PPC_BIT(49) /* Wake on external interrupts */ -#define SPR_LPCR_P7_PECE1 PPC_BIT(50) /* Wake on decrementer */ -#define SPR_LPCR_P7_PECE2 PPC_BIT(51) /* Wake on MCs, HMIs, etc... */ - +/* Powersave Exit Cause Enable is different on each generation */ #define SPR_LPCR_P8_PECE PPC_BITMASK(47,51) #define SPR_LPCR_P8_PECE0 PPC_BIT(47) /* Wake on priv doorbell */ #define SPR_LPCR_P8_PECE1 PPC_BIT(48) /* Wake on hv doorbell */ @@ -200,8 +194,6 @@ #define PVR_VERS_MIN(_pvr) GETFIELD(SPR_PVR_VERS_MIN, _pvr) /* PVR definitions */ -#define PVR_TYPE_P7 0x003f -#define PVR_TYPE_P7P 0x004a #define PVR_TYPE_P8E 0x004b /* Murano */ #define PVR_TYPE_P8 0x004d /* Venice */ #define PVR_TYPE_P8NVL 0x004c /* Naples */ diff --git a/include/psi.h b/include/psi.h index 79555ec..ad56ce1 100644 --- a/include/psi.h +++ b/include/psi.h @@ -54,7 +54,7 @@ #define PSIHB_CR 0x20 #define PSIHB_CR_FSP_CMD_ENABLE PPC_BIT(0) #define PSIHB_CR_FSP_MMIO_ENABLE PPC_BIT(1) -#define PSIHB_CR_TCE_ENABLE PPC_BIT(2) /* P7 only */ +#define PSIHB_CR_TCE_ENABLE PPC_BIT(2) #define PSIHB_CR_FSP_IRQ_ENABLE PPC_BIT(3) #define PSIHB_CR_FSP_ERR_RSP_ENABLE PPC_BIT(4) #define PSIHB_CR_PSI_LINK_ENABLE PPC_BIT(5) @@ -81,9 +81,6 @@ /* PSI Status / Error Mask Register */ #define PSIHB_SEMR 0x28 -/* XIVR and BUID used for PSI interrupts on P7 */ -#define PSIHB_XIVR 0x30 - /* XIVR and BUID used for PSI interrupts on P8 */ #define PSIHB_XIVR_FSP 0x30 #define PSIHB_XIVR_OCC 0x60 @@ -123,13 +120,6 @@ /* * PSI Host Bridge Registers (XSCOM) */ -#define PSIHB_XSCOM_P7_HBBAR 0x9 -#define PSIHB_XSCOM_P7_HBBAR_EN PPC_BIT(28) -#define PSIHB_XSCOM_P7_HBCSR 0xd -#define PSIHB_XSCOM_P7_HBCSR_SET 0x11 -#define PSIHB_XSCOM_P7_HBCSR_CLR 0x12 -#define PSIHB_XSCOM_P7_HBSCR_FSP_IRQ PPC_BIT(13) - #define PSIHB_XSCOM_P8_BASE 0xa #define PSIHB_XSCOM_P8_HBBAR_EN PPC_BIT(63) #define PSIHB_XSCOM_P8_HBCSR 0xe @@ -166,8 +156,6 @@ /* * Layout of the PSI DMA address space * - * On P7, we instanciate a TCE table of 16K TCEs mapping 64M - * * On P8, we use a larger mapping of 256K TCEs which provides * us with a 1G window in order to fit the trace buffers * diff --git a/include/skiboot.h b/include/skiboot.h index d70d828..1b3bacb 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -107,7 +107,6 @@ void _prlog(int log_level, const char* fmt, ...) __attribute__((format (printf, /* Processor generation */ enum proc_gen { proc_gen_unknown, - proc_gen_p7, /* P7 and P7+ */ proc_gen_p8, proc_gen_p9, }; @@ -203,7 +202,6 @@ extern void copy_sreset_vector(void); extern void copy_sreset_vector_fast_reboot(void); /* Various probe routines, to replace with an initcall system */ -extern void probe_p7ioc(void); extern void probe_phb3(void); extern void probe_phb4(void); extern int preload_capp_ucode(void); diff --git a/platforms/ibm-fsp/apollo-pci.c b/platforms/ibm-fsp/apollo-pci.c index f79b7b3..a6e8d38 100644 --- a/platforms/ibm-fsp/apollo-pci.c +++ b/platforms/ibm-fsp/apollo-pci.c @@ -17,7 +17,6 @@ #include <skiboot.h> #include <device.h> #include <fsp.h> -#include <p7ioc.h> #include <pci-cfg.h> #include <pci.h> #include <pci-slot.h> |