diff options
author | Daniel Axtens <dja@axtens.net> | 2015-11-16 15:57:36 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-11-18 11:30:44 +1100 |
commit | 0baf63f38757d356de3436ac0ab47511f98b8723 (patch) | |
tree | 46b0fa3cbfd410aab235cc36898de98427b45f63 | |
parent | 30b0074073fb419a0586c6da39852aa412869ed4 (diff) | |
download | talos-skiboot-0baf63f38757d356de3436ac0ab47511f98b8723.tar.gz talos-skiboot-0baf63f38757d356de3436ac0ab47511f98b8723.zip |
Drop support for p5ioc2
p5ioc2 is used by approximately 2 machines in the world, and has never
ever been a supported configuration.
Not only is the code virtually unused and very tricky to test, but
keeping it around is making life unnecessarily difficult:
- It's more complexity to manage for things such as PCI slot support
- It's more code for static analysis to cover, which means more time
fixing bugs that affect no-one.
- It's bloating every single install of skiboot for no benefit.
- It's reducing coverage stats, which is sad.
Drop p5ioc2.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | core/init.c | 1 | ||||
-rw-r--r-- | hdata/iohub.c | 214 | ||||
-rw-r--r-- | hdata/spira.h | 1 | ||||
-rw-r--r-- | hw/Makefile.inc | 2 | ||||
-rw-r--r-- | hw/cec.c | 11 | ||||
-rw-r--r-- | hw/p5ioc2-phb.c | 1206 | ||||
-rw-r--r-- | hw/p5ioc2.c | 298 | ||||
-rw-r--r-- | hw/p7ioc.c | 1 | ||||
-rw-r--r-- | include/cec.h | 4 | ||||
-rw-r--r-- | include/p5ioc2-regs.h | 234 | ||||
-rw-r--r-- | include/p5ioc2.h | 184 | ||||
-rw-r--r-- | include/skiboot.h | 1 |
12 files changed, 5 insertions, 2152 deletions
diff --git a/core/init.c b/core/init.c index 6d21b55b..54a5735f 100644 --- a/core/init.c +++ b/core/init.c @@ -734,7 +734,6 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu) opal_init_msg(); /* Probe IO hubs */ - probe_p5ioc2(); probe_p7ioc(); /* Probe PHB3 on P8 */ diff --git a/hdata/iohub.c b/hdata/iohub.c index 4fa256de..d599a056 100644 --- a/hdata/iohub.c +++ b/hdata/iohub.c @@ -22,7 +22,6 @@ #include <ccan/str/str.h> #include <ccan/array_size/array_size.h> #include <device.h> -#include <p5ioc2.h> #include <p7ioc.h> #include <vpd.h> #include <inttypes.h> @@ -379,213 +378,6 @@ static void io_add_p8_cec_vpd(const struct HDIF_common_hdr *sp_iohubs) io_get_lx_info(kwvpd, kwvpd_sz, 0, dt_root); } -static struct dt_node *io_add_hea(const struct cechub_io_hub *hub, - const void *sp_io) -{ - struct dt_node *np, *gnp; - uint64_t reg[2]; - unsigned int i, vpd_sz; - uint8_t kw_sz; - const void *iokid, *vpd, *ccin; - const uint8_t *mac; - const struct HDIF_child_ptr *iokids; - - /* - * We have a table of supported dauther cards looked up - * by CCIN. We don't use the 1008 slot map in the VPD. - * - * This is basically translated from BML and will do for - * now especially since we don't really support p5ioc2 - * machine, this is just for lab use - * - * This is mostly untested on 10G ... we might need more - * info about the PHY in that case - */ - const struct hea_iocard { - const char ccin[4]; - struct { - uint32_t speed; - uint16_t ports; - uint16_t phy_id; - } pg[2]; - } hea_iocards[] = { - { - .ccin = "1818", /* HV4 something */ - .pg[0] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - }, - { - .ccin = "1819", /* HV4 Titov Card */ - .pg[0] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - .pg[1] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - }, - { - .ccin = "1830", /* HV4 Sergei Card */ - .pg[0] = { .speed = 10000, .ports = 1, .phy_id = 0 }, - .pg[1] = { .speed = 10000, .ports = 1, .phy_id = 0 }, - }, - { - .ccin = "181A", /* L4 Evans Card */ - .pg[1] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - }, - { - .ccin = "181B", /* L4 Weber Card */ - .pg[0] = { .speed = 10000, .ports = 1, .phy_id = 0 }, - .pg[1] = { .speed = 10000, .ports = 1, .phy_id = 0 }, - }, - { - .ccin = "181C", /* HV4 Gibson Card */ - .pg[0] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - .pg[1] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - }, - { - .ccin = "2BC4", /* MR Riverside 2 */ - .pg[0] = { .speed = 1000, .ports = 1, .phy_id = 1 }, - .pg[1] = { .speed = 1000, .ports = 1, .phy_id = 1 }, - }, - { - .ccin = "2BC5", /* MR Lions 2 */ - .pg[0] = { .speed = 10000, .ports = 1, .phy_id = 1 }, - .pg[1] = { .speed = 10000, .ports = 1, .phy_id = 1 }, - }, - { - .ccin = "2BC6", /* MR Onion 2 */ - .pg[0] = { .speed = 10000, .ports = 1, .phy_id = 1 }, - .pg[1] = { .speed = 1000, .ports = 2, .phy_id = 1 }, - }, - { - .ccin = "266D", /* Jupiter Bonzai */ - .pg[0] = { .speed = 1000, .ports = 2, .phy_id = 1 }, - .pg[1] = { .speed = 1000, .ports = 2, .phy_id = 1 }, - }, - /* The blade use an IO KID that's a bit oddball and seems to - * represent the backplane itself, but let's use it anyway - * - * XXX Probably want a different PHY type ! - */ - { - .ccin = "531C", /* P7 Blade */ - .pg[0] = { .speed = 1000, .ports = 2, .phy_id = 0 }, - }, - }; - const struct hea_iocard *card = NULL; - - /* WARNING: This makes quite a lot of nasty assumptions - * that appear to hold true on the few machines I care - * about, which is good enough for now. We don't officially - * support p5ioc2 anyway... - */ - - /* Get first IO KID, we only support one. Real support would - * mean using the FRU ID and the SLCA to find the right "stuff" - * but at this stage it's unnecessary - */ - iokids = HDIF_child_arr(sp_io, CECHUB_CHILD_IO_KIDS); - if (!CHECK_SPPTR(iokids)) { - prerror("HEA: no IOKID in HDAT child array !\n"); - return NULL; - } - if (!iokids->count) { - prerror("HEA: IOKID count is 0 !\n"); - return NULL; - } - if (be32_to_cpu(iokids->count) > 1) { - prlog(PR_WARNING, "HEA: WARNING ! More than 1 IO KID !!! (%d)\n", - iokids->count); - } - iokid = HDIF_child(sp_io, iokids, 0, "IO KID"); - if (!iokid) { - prerror("HEA: Failed to retrieve IO KID 0 !\n"); - return NULL; - } - - /* Grab VPD */ - vpd = HDIF_get_idata(iokid, IOKID_KW_VPD, &vpd_sz); - if (!CHECK_SPPTR(vpd)) { - prerror("HEA: Failed to retrieve VPD from IO KID !\n"); - return NULL; - } - - /* Grab the MAC address */ - mac = vpd_find(vpd, vpd_sz, "VINI", "B1", &kw_sz); - if (!mac || kw_sz < 8) { - prerror("HEA: Failed to retrieve MAC Address !\n"); - return NULL; - } - - /* Grab the CCIN (card ID) */ - ccin = vpd_find(vpd, vpd_sz, "VINI", "CC", &kw_sz); - if (!ccin || kw_sz < 4) { - prerror("HEA: Failed to retrieve CCIN !\n"); - return NULL; - } - - /* Now we could try to parse the 1008 slot map etc... but instead - * we'll do like BML and grab the CCIN & use it for known cards. - * We also grab the MAC - */ - for (i = 0; i < ARRAY_SIZE(hea_iocards) && !card; i++) { - if (strncmp(hea_iocards[i].ccin, ccin, 4)) - continue; - card = &hea_iocards[i]; - } - if (!card) { - prerror("HEA: Unknown CCIN 0x%.4s!\n", (const char *)ccin); - return NULL; - } - - /* Assume base address is BAR3 + 0x4000000000 */ - reg[0] = be64_to_cpu(hub->gx_ctrl_bar3) + 0x4000000000; - reg[1] = 0xc0000000; - - prlog(PR_DEBUG, "CEC: * Adding HEA to P5IOC2, assuming GBA=0x%llx\n", - (long long)reg[0]); - np = dt_new_addr(dt_root, "ibm,hea", reg[0]); - if (!np) - return NULL; - - dt_add_property(np, "reg", reg, sizeof(reg)); - dt_add_property_strings(np, "compatible", "ibm,p5ioc2-hea"); - dt_add_property_cells(np, "#address-cells", 1); - dt_add_property_cells(np, "#size-cells", 0); - dt_add_property(np, "ibm,vpd", vpd, vpd_sz); - dt_add_property_cells(np, "#mac-address", mac[7]); - dt_add_property(np, "mac-address-base", mac, 6); - /* BUID is base + 0x30 */ - dt_add_property(np, "interrupt-controller", NULL, 0); - dt_add_property_cells(np, "interrupt-base", - ((be32_to_cpu(hub->buid_ext) << 9) | 0x30) << 4); - dt_add_property_cells(np, "interrupt-max-count", 128); - - /* Always 2 port groups */ - for (i = 0; i < 2; i++) { - unsigned int clause; - - switch(card->pg[i].speed) { - case 1000: - clause = 0x22; - break; - case 10000: - clause = 0x45; - break; - default: - /* Unused port group */ - continue; - } - gnp = dt_new_addr(np, "portgroup", i + 1); - if (!gnp) - continue; - - dt_add_property_cells(gnp, "reg", i + 1); - dt_add_property_cells(gnp, "speed", card->pg[i].speed); - /* XX FIXME */ - dt_add_property_strings(gnp, "phy-type", "mdio"); - dt_add_property_cells(gnp, "phy-mdio-addr", card->pg[i].phy_id); - dt_add_property_cells(gnp, "phy-mdio-clause", clause); - dt_add_property_cells(gnp, "subports", card->pg[i].ports); - } - return np; -} - static void io_parse_fru(const void *sp_iohubs) { unsigned int i; @@ -643,12 +435,6 @@ static void io_parse_fru(const void *sp_iohubs) hn = io_add_p7ioc(hub, sp_iohubs); io_add_common(hn, hub); break; - case CECHUB_HUB_P5IOC2: - prlog(PR_INFO, "CEC: P5IOC2 !\n"); - hn = io_add_p5ioc2(hub, sp_iohubs); - io_add_common(hn, hub); - io_add_hea(hub, sp_iohubs); - break; case CECHUB_HUB_MURANO: case CECHUB_HUB_MURANO_SEGU: prlog(PR_INFO, "CEC: Murano !\n"); diff --git a/hdata/spira.h b/hdata/spira.h index 0916fe3d..5ed93293 100644 --- a/hdata/spira.h +++ b/hdata/spira.h @@ -476,7 +476,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_P5IOC2 0x1061 /* from VPL1 */ #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 */ diff --git a/hw/Makefile.inc b/hw/Makefile.inc index 6eacb749..a9dd9f1f 100644 --- a/hw/Makefile.inc +++ b/hw/Makefile.inc @@ -4,7 +4,7 @@ SUBDIRS += hw HW_OBJS = xscom.o chiptod.o gx.o cec.o lpc.o lpc-uart.o psi.o HW_OBJS += homer.o slw.o occ.o fsi-master.o centaur.o HW_OBJS += nx.o nx-rng.o nx-crypto.o nx-842.o -HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o p5ioc2.o p5ioc2-phb.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 HW=hw/built-in.o @@ -17,7 +17,6 @@ #include <skiboot.h> #include <cec.h> #include <p7ioc.h> -#include <p5ioc2.h> #include <interrupts.h> #include <opal-api.h> @@ -53,19 +52,17 @@ void cec_reset(void) } } +/* This was only supported by p5ioc, which was dropped */ static int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, - uint64_t tce_mem_addr, - uint64_t tce_mem_size) + uint64_t tce_mem_addr __unused, + uint64_t tce_mem_size __unused) { struct io_hub *hub = cec_get_hub_by_id(hub_id); if (!hub) return OPAL_PARAMETER; - if (!hub->ops->set_tce_mem) - return OPAL_UNSUPPORTED; - - return hub->ops->set_tce_mem(hub, tce_mem_addr, tce_mem_size); + return OPAL_UNSUPPORTED; } opal_call(OPAL_PCI_SET_HUB_TCE_MEMORY, opal_pci_set_hub_tce_memory, 3); diff --git a/hw/p5ioc2-phb.c b/hw/p5ioc2-phb.c deleted file mode 100644 index 70a1a092..00000000 --- a/hw/p5ioc2-phb.c +++ /dev/null @@ -1,1206 +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 <p5ioc2.h> -#include <p5ioc2-regs.h> -#include <io.h> -#include <timebase.h> -#include <affinity.h> -#include <pci.h> -#include <pci-cfg.h> -#include <interrupts.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) - -/* - * Lock callbacks. Allows the OPAL API handlers to lock the - * PHB around calls such as config space, EEH, etc... - */ -static void p5ioc2_phb_lock(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - - lock(&p->lock); -} - -static void p5ioc2_phb_unlock(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - - unlock(&p->lock); -} - -/* - * Configuration space access - * - * The PHB lock is assumed to be already held - */ -static int64_t p5ioc2_pcicfg_address(struct p5ioc2_phb *p, uint32_t bdfn, - uint32_t offset, uint32_t size) -{ - uint32_t addr, sm = size - 1; - - if (bdfn > 0xffff) - return OPAL_PARAMETER; - /* XXX Should we enable 4K config space on PCI-X 2.0 ? */ - if ((offset > 0xff && !p->is_pcie) || offset > 0xfff) - 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 (p->is_pcie && (bdfn >> 8) == 0 && (bdfn & 0xff)) - return OPAL_HARDWARE; - - /* Prevent special operation generation */ - if (((bdfn >> 3) & 0x1f) == 0x1f) - return OPAL_HARDWARE; - - /* Check PHB state */ - if (p->state == P5IOC2_PHB_STATE_BROKEN) - return OPAL_HARDWARE; - - /* Additionally, should we prevent writes to the PHB own - * bus number register ? - */ - - addr = CAP_PCADR_ENABLE; - addr = SETFIELD(CAP_PCADR_BDFN, addr, bdfn); - addr = SETFIELD(CAP_PCADR_EXTOFF, addr, offset >> 8); - addr |= (offset & 0xff); - out_le32(p->regs + CAP_PCADR, addr); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_pcicfg_read8(struct phb *phb, uint32_t bdfn, - uint32_t offset, uint8_t *data) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - int64_t rc; - - /* Initialize data in case of error */ - *data = 0xff; - - rc = p5ioc2_pcicfg_address(p, bdfn, offset, 1); - if (rc) - return rc; - - *data = in_8(p->regs + CAP_PCDAT + (offset & 3)); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_pcicfg_read16(struct phb *phb, uint32_t bdfn, - uint32_t offset, uint16_t *data) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - int64_t rc; - - /* Initialize data in case of error */ - *data = 0xffff; - - rc = p5ioc2_pcicfg_address(p, bdfn, offset, 2); - if (rc) - return rc; - - *data = in_le16(p->regs + CAP_PCDAT + (offset & 3)); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_pcicfg_read32(struct phb *phb, uint32_t bdfn, - uint32_t offset, uint32_t *data) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - int64_t rc; - - /* Initialize data in case of error */ - *data = 0xffffffff; - - rc = p5ioc2_pcicfg_address(p, bdfn, offset, 4); - if (rc) - return rc; - - *data = in_le32(p->regs + CAP_PCDAT); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_pcicfg_write8(struct phb *phb, uint32_t bdfn, - uint32_t offset, uint8_t data) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - int64_t rc; - - rc = p5ioc2_pcicfg_address(p, bdfn, offset, 1); - if (rc) - return rc; - - out_8(p->regs + CAP_PCDAT + (offset & 3), data); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_pcicfg_write16(struct phb *phb, uint32_t bdfn, - uint32_t offset, uint16_t data) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - int64_t rc; - - rc = p5ioc2_pcicfg_address(p, bdfn, offset, 2); - if (rc) - return rc; - - out_le16(p->regs + CAP_PCDAT + (offset & 3), data); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_pcicfg_write32(struct phb *phb, uint32_t bdfn, - uint32_t offset, uint32_t data) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - int64_t rc; - - rc = p5ioc2_pcicfg_address(p, bdfn, offset, 4); - if (rc) - return rc; - - out_le32(p->regs + CAP_PCDAT, data); - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_presence_detect(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint16_t slotstat; - int64_t rc; - - if (!p->is_pcie) { - uint32_t lsr; - - lsr = in_be32(p->regs + SHPC_LOGICAL_SLOT); - if (GETFIELD(SHPC_LOGICAL_SLOT_PRSNT, lsr) - != SHPC_SLOT_STATE_EMPTY) - return OPAL_SHPC_DEV_PRESENT; - else - return OPAL_SHPC_DEV_NOT_PRESENT; - } - - rc = p5ioc2_pcicfg_read16(&p->phb, 0, p->ecap + PCICAP_EXP_SLOTSTAT, - &slotstat); - if (rc || !(slotstat & PCICAP_EXP_SLOTSTAT_PDETECTST)) - return OPAL_SHPC_DEV_NOT_PRESENT; - return OPAL_SHPC_DEV_PRESENT; -} - -static int64_t p5ioc2_link_state(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint16_t lstat; - int64_t rc; - - /* XXX Test for PHB in error state ? */ - if (!p->is_pcie) - return OPAL_SHPC_LINK_UP_x1; - - rc = p5ioc2_pcicfg_read16(&p->phb, 0, p->ecap + PCICAP_EXP_LSTAT, - &lstat); - if (rc < 0) { - /* Shouldn't happen */ - PHBERR(p, "Failed to read link status\n"); - return OPAL_HARDWARE; - } - if (!(lstat & PCICAP_EXP_LSTAT_DLLL_ACT)) - return OPAL_SHPC_LINK_DOWN; - return GETFIELD(PCICAP_EXP_LSTAT_WIDTH, lstat); -} - -static int64_t p5ioc2_power_state(struct phb *phb __unused) -{ - /* XXX FIXME */ -#if 0 - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint64_t reg = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - - /* XXX Test for PHB in error state ? */ - - if (reg & PHB_PCIE_SLOTCTL2_PWR_EN_STAT) - return OPAL_SHPC_POWER_ON; - - return OPAL_SHPC_POWER_OFF; -#else - return OPAL_SHPC_POWER_ON; -#endif -} - -/* p5ioc2_sm_slot_power_off - Slot power off state machine - */ -static int64_t p5ioc2_sm_slot_power_off(struct p5ioc2_phb *p) -{ - switch(p->state) { - default: - break; - } - - /* Unknown state, hardware error ? */ - return OPAL_HARDWARE; -} - -static int64_t p5ioc2_slot_power_off(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - - if (p->state != P5IOC2_PHB_STATE_FUNCTIONAL) - return OPAL_BUSY; - - /* run state machine */ - return p5ioc2_sm_slot_power_off(p); -} - -static int64_t p5ioc2_sm_slot_power_on(struct p5ioc2_phb *p __unused) -{ -#if 0 - uint64_t reg; - uint32_t reg32; - uint16_t brctl; - - switch(p->state) { - case P5IOC2_PHB_STATE_FUNCTIONAL: - /* Check presence */ - reg = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - if (!(reg & PHB_PCIE_SLOTCTL2_PRSTN_STAT)) { - PHBDBG(p, "Slot power on: no device\n"); - return OPAL_CLOSED; - } - - /* Adjust UTL interrupt settings to disable various - * errors that would interfere with the process - */ - out_be64(p->regs + UTL_PCIE_PORT_IRQ_EN, 0x7e00000000000000); - - /* If the power is not on, turn it on now */ - if (!(reg & PHB_PCIE_SLOTCTL2_PWR_EN_STAT)) { - reg = in_be64(p->regs + PHB_HOTPLUG_OVERRIDE); - reg &= ~(0x8c00000000000000ul); - reg |= 0x8400000000000000ul; - out_be64(p->regs + PHB_HOTPLUG_OVERRIDE, reg); - p->state = PHB_STATE_SPUP_STABILIZE_DELAY; - PHBDBG(p, "Slot power on: powering on...\n"); - return p5ioc2_set_sm_timeout(p, secs_to_tb(2)); - } - /* Power is already on */ - power_ok: - /* Ensure hot reset is deasserted */ - p5ioc2_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &brctl); - brctl &= ~PCI_CFG_BRCTL_SECONDARY_RESET; - p5ioc2_pcicfg_write16(&p->phb, 0, PCI_CFG_BRCTL, brctl); - p->retries = 40; - p->state = PHB_STATE_SPUP_WAIT_LINK; - PHBDBG(p, "Slot power on: waiting for link\n"); - /* Fall through */ - case PHB_STATE_SPUP_WAIT_LINK: - reg = in_be64(p->regs + PHB_PCIE_DLP_TRAIN_CTL); - /* Link is up ? Complete */ - - /* XXX TODO: Check link width problem and if present - * go straight to the host reset code path. - */ - if (reg & PHB_PCIE_DLP_TC_DL_LINKACT) { - /* Restore UTL interrupts */ - out_be64(p->regs + UTL_PCIE_PORT_IRQ_EN, - 0xfe65000000000000); - p->state = PHB_STATE_FUNCTIONAL; - PHBDBG(p, "Slot power on: up !\n"); - return OPAL_SUCCESS; - } - /* Retries */ - p->retries--; - if (p->retries == 0) { - /* XXX Improve logging */ - PHBERR(p,"Slot power on: Timeout waiting for link\n"); - goto error; - } - /* Check time elapsed */ - if ((p->retries % 20) != 0) - return p5ioc2_set_sm_timeout(p, msecs_to_tb(10)); - - /* >200ms, time to try a hot reset after clearing the - * link status bit (doco says to do so) - */ - out_be64(p->regs + UTL_PCIE_PORT_STATUS, 0x0080000000000000); - - /* Mask receiver error status in AER */ - p5ioc2_pcicfg_read32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, ®32); - reg32 |= PCIECAP_AER_CE_RECVR_ERR; - p5ioc2_pcicfg_write32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, reg32); - - /* Turn on host reset */ - p5ioc2_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &brctl); - brctl |= PCI_CFG_BRCTL_SECONDARY_RESET; - p5ioc2_pcicfg_write16(&p->phb, 0, PCI_CFG_BRCTL, brctl); - p->state = PHB_STATE_SPUP_HOT_RESET_DELAY; - PHBDBG(p, "Slot power on: soft reset...\n"); - return p5ioc2_set_sm_timeout(p, secs_to_tb(1)); - case PHB_STATE_SPUP_HOT_RESET_DELAY: - /* Turn off host reset */ - p5ioc2_pcicfg_read16(&p->phb, 0, PCI_CFG_BRCTL, &brctl); - brctl &= ~PCI_CFG_BRCTL_SECONDARY_RESET; - p5ioc2_pcicfg_write16(&p->phb, 0, PCI_CFG_BRCTL, brctl); - /* Clear spurious errors */ - out_be64(p->regs + UTL_PCIE_PORT_STATUS, 0x00e0000000000000); - p5ioc2_pcicfg_write32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_STATUS, - PCIECAP_AER_CE_RECVR_ERR); - /* Unmask receiver error status in AER */ - p5ioc2_pcicfg_read32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, ®32); - reg32 &= ~PCIECAP_AER_CE_RECVR_ERR; - p5ioc2_pcicfg_write32(&p->phb, 0, - p->aercap + PCIECAP_AER_CE_MASK, reg32); - /* Go back to waiting for link */ - p->state = PHB_STATE_SPUP_WAIT_LINK; - PHBDBG(p, "Slot power on: waiting for link (2)\n"); - return p5ioc2_set_sm_timeout(p, msecs_to_tb(10)); - - case PHB_STATE_SPUP_STABILIZE_DELAY: - /* Come here after the 2s delay after power up */ - p->retries = 1000; - p->state = PHB_STATE_SPUP_SLOT_STATUS; - PHBDBG(p, "Slot power on: waiting for power\n"); - /* Fall through */ - case PHB_STATE_SPUP_SLOT_STATUS: - reg = in_be64(p->regs + PHB_PCIE_SLOTCTL2); - - /* Doc says to check LED status, but we ignore that, there - * no point really and it's easier that way - */ - if (reg & PHB_PCIE_SLOTCTL2_PWR_EN_STAT) - goto power_ok; - if (p->retries-- == 0) { - /* XXX Improve error logging */ - PHBERR(p, "Timeout powering up slot\n"); - goto error; - } - return p5ioc2_set_sm_timeout(p, msecs_to_tb(10)); - default: - break; - } - - /* Unknown state, hardware error ? */ - error: - p->state = PHB_STATE_FUNCTIONAL; - return OPAL_HARDWARE; -#else - return OPAL_SUCCESS; -#endif -} - -static int64_t p5ioc2_slot_power_on(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - - if (p->state != P5IOC2_PHB_STATE_FUNCTIONAL) - return OPAL_BUSY; - - /* run state machine */ - return p5ioc2_sm_slot_power_on(p); -} - -static int64_t p5ioc2_sm_hot_reset(struct p5ioc2_phb *p) -{ - switch(p->state) { - default: - break; - } - - /* Unknown state, hardware error ? */ - return OPAL_HARDWARE; -} - -static int64_t p5ioc2_hot_reset(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - - if (p->state != P5IOC2_PHB_STATE_FUNCTIONAL) - return OPAL_BUSY; - - /* run state machine */ - return p5ioc2_sm_hot_reset(p); -} - -static int64_t p5ioc2_sm_freset(struct p5ioc2_phb *p) -{ - switch(p->state) { - default: - break; - } - - /* XXX Not implemented, return success to make - * pci.c happy, otherwise probing of slots will - * fail - */ - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_freset(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - - if (p->state != P5IOC2_PHB_STATE_FUNCTIONAL) - return OPAL_BUSY; - - /* run state machine */ - return p5ioc2_sm_freset(p); -} - -static int64_t p5ioc2_poll(struct phb *phb) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint64_t now = mftb(); - - if (p->state == P5IOC2_PHB_STATE_FUNCTIONAL) - return OPAL_SUCCESS; - - /* Check timer */ - if (p->delay_tgt_tb && - tb_compare(now, p->delay_tgt_tb) == TB_ABEFOREB) - return p->delay_tgt_tb - now; - - /* Expired (or not armed), clear it */ - p->delay_tgt_tb = 0; - -#if 0 - /* Dispatch to the right state machine */ - switch(p->state) { - case PHB_STATE_SPUP_STABILIZE_DELAY: - case PHB_STATE_SPUP_SLOT_STATUS: - case PHB_STATE_SPUP_WAIT_LINK: - case PHB_STATE_SPUP_HOT_RESET_DELAY: - return p5ioc2_sm_slot_power_on(p); - case PHB_STATE_SPDOWN_STABILIZE_DELAY: - case PHB_STATE_SPDOWN_SLOT_STATUS: - return p5ioc2_sm_slot_power_off(p); - case PHB_STATE_HRESET_DELAY: - return p5ioc2_sm_hot_reset(p); - default: - break; - } -#endif - /* Unknown state, could be a HW error */ - return OPAL_HARDWARE; -} - -static int64_t p5ioc2_eeh_freeze_status(struct phb *phb, uint64_t pe_number, - uint8_t *freeze_state, - uint16_t *pci_error_type, - uint16_t *severity, - uint64_t *phb_status __unused) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint32_t cfgrw; - - /* Defaults: not frozen */ - *freeze_state = OPAL_EEH_STOPPED_NOT_FROZEN; - *pci_error_type = OPAL_EEH_NO_ERROR; - if (severity) - *severity = OPAL_EEH_SEV_NO_ERROR; - - if (pe_number != 0) - return OPAL_PARAMETER; - - /* XXX Handle PHB status */ - /* XXX We currently only check for PE freeze, not fence */ - - cfgrw = in_be32(p->regs + CAP_PCFGRW); - if (cfgrw & CAP_PCFGRW_MMIO_FROZEN) - *freeze_state |= OPAL_EEH_STOPPED_MMIO_FREEZE; - if (cfgrw & CAP_PCFGRW_DMA_FROZEN) - *freeze_state |= OPAL_EEH_STOPPED_DMA_FREEZE; - - if (severity && - (cfgrw & (CAP_PCFGRW_MMIO_FROZEN | CAP_PCFGRW_MMIO_FROZEN))) - *severity = OPAL_EEH_SEV_PE_ER; - - /* XXX Don't bother populating pci_error_type */ - /* Should read the bits from PLSSR */ - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_eeh_next_error(struct phb *phb, uint64_t *first_frozen_pe, - uint16_t *pci_error_type, uint16_t *severity) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint32_t cfgrw; - - /* XXX Don't bother */ - *pci_error_type = OPAL_EEH_NO_ERROR; - *first_frozen_pe = 0; - - cfgrw = in_be32(p->regs + CAP_PCFGRW); - if (cfgrw & (CAP_PCFGRW_MMIO_FROZEN | CAP_PCFGRW_MMIO_FROZEN)) - *severity = OPAL_EEH_SEV_PE_ER; - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_eeh_freeze_clear(struct phb *phb, uint64_t pe_number, - uint64_t eeh_action_token) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint32_t cfgrw; - - if (pe_number != 0) - return OPAL_PARAMETER; - - /* - * This sequence isn't very well documented. We play guess - * games based on the documentation, what we do on P7IOC, - * and common sense. - * - * Basically we start from the low level (UTL), clear all - * error conditions there. Then we clear error conditions - * in the PLSSR and DMACSR. - * - * Once that's done, we unfreeze the PHB - * - * Note: Should we also clear the error bits in the config - * space ? The docs don't say anything... TODO: Check what - * OPAL does if possible or ask Milton. - */ - - /* Clear UTL error regs on PCIe */ - if (p->is_pcie) { - uint32_t err; - - err = in_be32(p->regs + UTL_SYS_BUS_AGENT_STATUS); - out_be32(p->regs + UTL_SYS_BUS_AGENT_STATUS, err); - err = in_be32(p->regs + UTL_PCIE_PORT_STATUS); - out_be32(p->regs + UTL_PCIE_PORT_STATUS, err); - err = in_be32(p->regs + UTL_RC_STATUS); - out_be32(p->regs + UTL_RC_STATUS, err); - } - - /* XXX We should probably clear the error regs in the cfg space... */ - - /* Clear PLSSR and DMACSR */ - out_be32(p->regs + CAP_DMACSR, 0); - out_be32(p->regs + CAP_PLSSR, 0); - - /* Clear freeze state as requested */ - cfgrw = in_be32(p->regs + CAP_PCFGRW); - if (eeh_action_token & OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO) { - cfgrw &= ~CAP_PCFGRW_MMIO_FROZEN; - out_be32(p->regs + CAP_PCFGRW, cfgrw); - } - if (eeh_action_token & OPAL_EEH_ACTION_CLEAR_FREEZE_DMA) { - cfgrw &= ~CAP_PCFGRW_DMA_FROZEN; - out_be32(p->regs + CAP_PCFGRW, cfgrw); - } - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_get_msi_64(struct phb *phb __unused, uint32_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 = 0x1000000000000000ul; - *message_data = xive_num; - - return OPAL_SUCCESS; -} - -static uint8_t p5ioc2_choose_bus(struct phb *phb __unused, - struct pci_device *bridge __unused, - uint8_t candidate, uint8_t *max_bus __unused, - bool *use_max) -{ - /* Use standard bus number selection */ - *use_max = false; - return candidate; -} - -/* p5ioc2_phb_ioda_reset - Reset the IODA tables - * - * This reset the IODA tables in the PHB. It is called at - * initialization time, on PHB reset, and can be called - * explicitly from OPAL - * - * Note: We don't handle EEH on p5ioc2, we use no cache - * and thus always purge - */ -static int64_t p5ioc2_ioda_reset(struct phb *phb, bool purge __unused) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - unsigned int i; - - /* Init XIVRs */ - for (i = 0; i < 16; i++) { - p->xive_cache[i] = SETFIELD(CAP_XIVR_PRIO, 0, 0xff); - out_be32(p->regs + CAP_XIVRn(i), 0x000000ff); - } - - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_set_phb_tce_memory(struct phb *phb, - uint64_t tce_mem_addr, - uint64_t tce_mem_size) -{ - struct p5ioc2_phb *p = phb_to_p5ioc2_phb(phb); - uint64_t tar; - uint32_t cfg; - - printf("PHB%d: set_tce_memory: 0x%016llx 0x%016llx\n", - p->index, tce_mem_addr, tce_mem_size); - printf("PHB%d: bridge values : 0x%016llx 0x%016llx\n", - p->index, p->ioc->tce_base, p->ioc->tce_size); - - /* First check if it fits in the memory established for - * the IO HUB - */ - if (tce_mem_addr && - (tce_mem_addr < p->ioc->tce_base || - tce_mem_addr > (p->ioc->tce_base + p->ioc->tce_size) || - (tce_mem_addr + tce_mem_size) > - (p->ioc->tce_base + p->ioc->tce_size))) { - prerror("PHB%d: TCEs not in bridge range\n", p->index); - return OPAL_PARAMETER; - } - - /* Supported sizes are power of two's naturally aligned - * and between 64K and 8M (p5ioc2 spec) - */ - if (tce_mem_addr && !is_pow2(tce_mem_size)) { - prerror("PHB%d: Size is not a power of 2\n", p->index); - return OPAL_PARAMETER; - } - if (tce_mem_addr & (tce_mem_size - 1)) { - prerror("PHB%d: Not naturally aligned\n", p->index); - return OPAL_PARAMETER; - } - if (tce_mem_addr && - (tce_mem_size < 0x10000 || tce_mem_size > 0x800000)) { - prerror("PHB%d: Size out of range\n", p->index); - return OPAL_PARAMETER; - } - - /* First we disable TCEs in the bridge */ - cfg = in_be32(p->regs + CAP_PCFGRW); - cfg &= ~CAP_PCFGRW_TCE_EN; - out_be32(p->regs + CAP_PCFGRW, cfg); - - - /* Now there's a blurb in the spec about all TARm needing - * to have the same size.. I will let that as a surprise - * for the user ... Linux does it fine and I'd rather not - * keep more state to check than I need to - */ - tar = 0; - if (tce_mem_addr) { - tar = SETFIELD(CA_TAR_HUBID, 0ul, p->ca ? 4 : 1); - tar = SETFIELD(CA_TAR_ALTHUBID, tar, p->ca ? 4 : 1); - tar = SETFIELD(CA_TAR_NUM_TCE, tar, ilog2(tce_mem_size) - 16); - tar |= tce_mem_addr; /* addr is naturally aligned */ - tar |= CA_TAR_VALID; - printf("PHB%d: Writing TAR: 0x%016llx\n", p->index, tar); - } - out_be64(p->ca_regs + CA_TARn(p->index), tar); - - /* Now set the TCE enable if we set a valid address */ - if (tce_mem_addr) { - cfg |= CAP_PCFGRW_TCE_EN; - out_be32(p->regs + CAP_PCFGRW, cfg); - } - - return OPAL_SUCCESS; -} - - -static const struct phb_ops p5ioc2_phb_ops = { - .lock = p5ioc2_phb_lock, - .unlock = p5ioc2_phb_unlock, - .cfg_read8 = p5ioc2_pcicfg_read8, - .cfg_read16 = p5ioc2_pcicfg_read16, - .cfg_read32 = p5ioc2_pcicfg_read32, - .cfg_write8 = p5ioc2_pcicfg_write8, - .cfg_write16 = p5ioc2_pcicfg_write16, - .cfg_write32 = p5ioc2_pcicfg_write32, - .choose_bus = p5ioc2_choose_bus, - .eeh_freeze_status = p5ioc2_eeh_freeze_status, - .eeh_freeze_clear = p5ioc2_eeh_freeze_clear, - .next_error = p5ioc2_eeh_next_error, - .get_msi_64 = p5ioc2_get_msi_64, - .ioda_reset = p5ioc2_ioda_reset, - .set_phb_tce_memory = p5ioc2_set_phb_tce_memory, - .presence_detect = p5ioc2_presence_detect, - .link_state = p5ioc2_link_state, - .power_state = p5ioc2_power_state, - .slot_power_off = p5ioc2_slot_power_off, - .slot_power_on = p5ioc2_slot_power_on, - .hot_reset = p5ioc2_hot_reset, - .fundamental_reset = p5ioc2_freset, - .poll = p5ioc2_poll, -}; - -/* p5ioc2_phb_get_xive - Interrupt control from OPAL */ -static int64_t p5ioc2_phb_get_xive(void *data, uint32_t isn, - uint16_t *server, uint8_t *prio) -{ - struct p5ioc2_phb *p = data; - uint32_t irq, xivr, fbuid = P7_IRQ_FBUID(isn); - - if (fbuid != p->buid) - return OPAL_PARAMETER; - irq = isn & 0xf; - - xivr = p->xive_cache[irq]; - *server = GETFIELD(CAP_XIVR_SERVER, xivr); - *prio = GETFIELD(CAP_XIVR_PRIO, xivr); - - return OPAL_SUCCESS; -} - -/* p5ioc2_phb_set_xive - Interrupt control from OPAL */ -static int64_t p5ioc2_phb_set_xive(void *data, uint32_t isn, - uint16_t server, uint8_t prio) -{ - struct p5ioc2_phb *p = data; - uint32_t irq, xivr, fbuid = P7_IRQ_FBUID(isn); - - if (fbuid != p->buid) - return OPAL_PARAMETER; - irq = isn & 0xf; - - printf("PHB%d: Set XIVE isn %04x (irq=%d) server=%x, prio=%x\n", - p->index, isn, irq, server, prio); - - xivr = SETFIELD(CAP_XIVR_SERVER, 0, server); - xivr = SETFIELD(CAP_XIVR_PRIO, xivr, prio); - p->xive_cache[irq] = xivr; - - /* Now we mangle the server and priority */ - if (prio == 0xff) { - server = 0; - prio = 0xff; - } else { - prio = (prio >> 3) | ((server & 7) << 5); - server = server >> 3; - } - - /* We use HRT entry 0 always for now */ - xivr = SETFIELD(CAP_XIVR_SERVER, 0, server); - xivr = SETFIELD(CAP_XIVR_PRIO, xivr, prio); - out_be32(p->regs + CAP_XIVRn(irq), xivr); - printf("PHB%d: wrote 0x%08x to XIVR %d\n", p->index, xivr, irq); - - return OPAL_SUCCESS; -} - -/* IRQ ops for OS interrupts (not internal) */ -static const struct irq_source_ops p5ioc2_phb_os_irq_ops = { - .get_xive = p5ioc2_phb_get_xive, - .set_xive = p5ioc2_phb_set_xive, -}; - - -static void p5ioc2_phb_init_utl(struct p5ioc2_phb *p __unused) -{ - /* XXX FIXME */ -} - -static void p5ioc2_phb_init_pcie(struct p5ioc2_phb *p) -{ - int64_t ecap, aercap; - - ecap = pci_find_cap(&p->phb, 0, PCI_CFG_CAP_ID_EXP); - if (ecap < 0) { - /* Shouldn't happen */ - prerror("P5IOC2: Failed to locate PCI-E cap in bridge\n"); - return; - } - p->ecap = ecap; - - aercap = pci_find_ecap(&p->phb, 0, PCIECAP_ID_AER, NULL); - if (aercap < 0) { - /* Shouldn't happen */ - prerror("P5IOC2: Failed to locate AER ext cap in bridge\n"); - return; - } - p->aercap = aercap; - - /* XXX plenty more to do ... */ -} - -static void p5ioc2_phb_hwinit(struct p5ioc2_phb *p) -{ - uint16_t pcicmd; - uint32_t phbid; - - printf("P5IOC2: Initializing PHB HW...\n"); - - /* Enable PHB and and disable address decoding */ - phbid = in_be32(p->ca_regs + CA_PHBIDn(p->index)); - phbid |= CA_PHBID_PHB_ENABLE; - phbid &= ~CA_PHBID_ADDRSPACE_ENABLE; - out_be32(p->ca_regs + CA_PHBIDn(p->index), phbid); - - /* Set BUID */ - out_be32(p->regs + CAP_BUID, SETFIELD(CAP_BUID_MASK, 0, - P7_BUID_BASE(p->buid))); - out_be32(p->regs + CAP_MSIBASE, P7_BUID_BASE(p->buid) << 16); - - /* Set IO and Memory mapping */ - out_be32(p->regs + CAP_IOAD_H, hi32(p->io_base + IO_PCI_START)); - out_be32(p->regs + CAP_IOAD_L, lo32(p->io_base + IO_PCI_START)); - out_be32(p->regs + CAP_IOSZ, ~(IO_PCI_SIZE - 1)); - out_be32(p->regs + CAP_IO_ST, IO_PCI_START); - out_be32(p->regs + CAP_MEM1_H, hi32(p->mm_base + MM_PCI_START)); - out_be32(p->regs + CAP_MEM1_L, lo32(p->mm_base + MM_PCI_START)); - out_be32(p->regs + CAP_MSZ1, ~(MM_PCI_SIZE - 1)); - out_be32(p->regs + CAP_MEM_ST, MM_PCI_START); - - /* Setup the MODE registers. We captures the values used - * by pHyp/OPAL - */ - out_be32(p->regs + CAP_MODE0, 0x00800010); - out_be32(p->regs + CAP_MODE1, 0x00800000); - out_be32(p->regs + CAP_MODE3, 0xFFC00050); - if (p->is_pcie) - out_be32(p->regs + CAP_MODE2, 0x00000400); - else - out_be32(p->regs + CAP_MODE2, 0x00000408); - - /* XXX Setup of the arbiter... not sure what to do here, - * probably system specific (depends on whow things are - * wired on the motherboard). I set things up based on - * the values I read on a Juno machine. We setup the BPR - * with the various timeouts etc... as well based one - * similarly captured values - */ - if (p->is_pcie) { - out_be32(p->regs + CAP_AER, 0x04000000); - out_be32(p->regs + CAP_BPR, 0x0000004f); - } else { - out_be32(p->regs + CAP_AER, 0x84000000); - out_be32(p->regs + CAP_BPR, 0x000f00ff); - } - - /* XXX Setup error reporting registers */ - - /* Clear errors in PLSSR and DMACSR */ - out_be32(p->regs + CAP_DMACSR, 0); - out_be32(p->regs + CAP_PLSSR, 0); - - /* Configure MSIs on PCIe only */ - if (p->is_pcie) { - /* XXX Check that setting ! That's what OPAL uses but - * I suspect it might not be correct. We enable a masking - * of 3 bits and no offset, which makes me think only - * some MSIs will work... not 100% certain. - */ - out_be32(p->regs + CAP_MVE0, CAP_MVE_VALID | - SETFIELD(CAP_MVE_TBL_OFF, 0, 0) | - SETFIELD(CAP_MVE_NUM_INT, 0, 0x3)); - out_be32(p->regs + CAP_MVE1, 0); - } - - /* Configuration. We keep TCEs disabled */ - out_be32(p->regs + CAP_PCFGRW, - CAP_PCFGRW_ERR_RECOV_EN | - CAP_PCFGRW_FREEZE_EN | - CAP_PCFGRW_DAC_DISABLE | - (p->is_pcie ? CAP_PCFGRW_MSI_EN : 0)); - - /* Re-enable address decode */ - phbid |= CA_PHBID_ADDRSPACE_ENABLE; - out_be32(p->ca_regs + CA_PHBIDn(p->index), phbid); - - /* PCIe specific inits */ - if (p->is_pcie) { - p5ioc2_phb_init_utl(p); - p5ioc2_phb_init_pcie(p); - } - - /* Take out reset pins on PCI-X. PCI-E will be handled via the hotplug - * controller separately - */ - if (!p->is_pcie) { - uint32_t val; - - /* Setting 1's will deassert the reset signals */ - out_be32(p->regs + CAP_CRR, CAP_CRR_RESET1 | CAP_CRR_RESET2); - - /* Set max sub bus */ - p5ioc2_pcicfg_write8(&p->phb, 0, 0x41, 0xff); - - /* XXX SHPC stuff */ - printf("P5IOC2: SHPC Slots available 1 : %08x\n", - in_be32(p->regs + 0xb20)); - printf("P5IOC2: SHPC Slots available 2 : %08x\n", - in_be32(p->regs + 0xb24)); - printf("P5IOC2: SHPC Slots config : %08x\n", - in_be32(p->regs + 0xb28)); - printf("P5IOC2: SHPC Secondary bus conf : %08x\n", - in_be32(p->regs + 0xb2c)); - - p5ioc2_pcicfg_read32(&p->phb, 0, 0, &val); - printf("P5IOC2: val0: %08x\n", val); - p5ioc2_pcicfg_read32(&p->phb, 0, 4, &val); - printf("P5IOC2: val4: %08x\n", val); - } - - /* Enable PCI command/status */ - p5ioc2_pcicfg_read16(&p->phb, 0, PCI_CFG_CMD, &pcicmd); - pcicmd |= PCI_CFG_CMD_IO_EN | PCI_CFG_CMD_MEM_EN | - PCI_CFG_CMD_BUS_MASTER_EN; - p5ioc2_pcicfg_write16(&p->phb, 0, PCI_CFG_CMD, pcicmd); - - p->state = P5IOC2_PHB_STATE_FUNCTIONAL; -} - -static void p5ioc2_pcie_add_node(struct p5ioc2_phb *p) -{ - uint64_t reg[2], mmb, iob; - uint32_t lsibase, icsp = get_ics_phandle(); - struct dt_node *np; - - reg[0] = cleanup_addr((uint64_t)p->regs); - reg[1] = 0x1000; - - 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,p5ioc2-pciex"); - 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 phb own interrupts */ - dt_add_property_cells(np, "ibm,opal-num-pes", 1); - dt_add_property_cells(np, "ibm,opal-msi-ranges", (p->buid << 4) + 5, 8); - /* XXX FIXME: add slot-name */ - iob = cleanup_addr(p->io_base + IO_PCI_START); - mmb = cleanup_addr(p->mm_base + MM_PCI_START); - dt_add_property_cells(np, "ranges", - /* IO space */ - 0x01000000, 0x00000000, 0x00000000, - hi32(iob), lo32(iob), 0, IO_PCI_SIZE, - /* M32 space */ - 0x02000000, 0x00000000, MM_PCI_START, - hi32(mmb), lo32(mmb), 0, MM_PCI_SIZE); - - /* 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 << 4; - p->phb.lstate.int_size = 1; - p->phb.lstate.int_val[0][0] = lsibase + 1; - p->phb.lstate.int_val[1][0] = lsibase + 2; - p->phb.lstate.int_val[2][0] = lsibase + 3; - p->phb.lstate.int_val[3][0] = lsibase + 4; - 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; - - /* reset clear timestamp... to add if we do a reset and want - * to avoid waiting in skiboot - */ - //dt_property_cells("reset-clear-timestamp",.... -} - -static void p5ioc2_pcix_add_node(struct p5ioc2_phb *p) -{ - uint64_t reg[2], mmb, iob; - uint32_t lsibase, icsp = get_ics_phandle(); - struct dt_node *np; - - reg[0] = cleanup_addr((uint64_t)p->regs); - reg[1] = 0x1000; - - np = dt_new_addr(p->ioc->dt_node, "pci", reg[0]); - if (!np) - return; - - p->phb.dt_node = np; - dt_add_property_strings(np, "compatible", "ibm,p5ioc2-pcix"); - dt_add_property_strings(np, "device_type", "pci"); - 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, "bus-width", 8); /* Figure out from VPD ? */ - dt_add_property_cells(np, "interrupt-parent", icsp); - /* XXX FIXME: add phb own interrupts */ - dt_add_property_cells(np, "ibm,opal-num-pes", 1); - /* XXX FIXME: add slot-name */ - iob = cleanup_addr(p->io_base + IO_PCI_START); - mmb = cleanup_addr(p->mm_base + MM_PCI_START); - dt_add_property_cells(np, "ranges", - /* IO space */ - 0x01000000, 0x00000000, 0x00000000, - hi32(iob), lo32(iob), 0, IO_PCI_SIZE, - /* M32 space */ - 0x02000000, 0x00000000, MM_PCI_START, - hi32(mmb), lo32(mmb), 0, MM_PCI_SIZE); - - /* 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 << 4; - p->phb.lstate.int_size = 1; - p->phb.lstate.int_val[0][0] = lsibase + 1; - p->phb.lstate.int_val[1][0] = lsibase + 2; - p->phb.lstate.int_val[2][0] = lsibase + 3; - p->phb.lstate.int_val[3][0] = lsibase + 4; - 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; - - /* On PCI-X we need to create an interrupt map here */ - pci_std_swizzle_irq_map(np, NULL, &p->phb.lstate, 0); -} - -void p5ioc2_phb_setup(struct p5ioc2 *ioc, struct p5ioc2_phb *p, - uint8_t ca, uint8_t index, bool active, - uint32_t buid) -{ - uint32_t phbid; - - p->index = index; - p->ca = ca; - p->ioc = ioc; - p->active = active; - p->phb.ops = &p5ioc2_phb_ops; - p->buid = buid; - p->ca_regs = ca ? ioc->ca1_regs : ioc->ca0_regs; - p->regs = p->ca_regs + CA_PHBn_REGS(index); - - printf("P5IOC2: Initializing PHB %d on CA%d, regs @%p, BUID 0x%04x\n", - p->index, p->ca, p->regs, p->buid); - - /* Memory map: described in p5ioc2.h */ - p->mm_base = ca ? ioc->ca1_mm_region : ioc->ca0_mm_region; - p->mm_base += MM_WINDOW_SIZE * index; - p->io_base = (uint64_t)p->ca_regs; - p->io_base += IO_PCI_SIZE * (index + 1); - p->state = P5IOC2_PHB_STATE_UNINITIALIZED; - - /* Query PHB type */ - phbid = in_be32(p->ca_regs + CA_PHBIDn(p->index)); - - switch(GETFIELD(CA_PHBID_PHB_TYPE, phbid)) { - case CA_PHBTYPE_PCIX1_0: - p->is_pcie = false; - p->phb.scan_map = 0x0003; - p->phb.phb_type = phb_type_pcix_v1; - printf("P5IOC2: PHB is PCI/PCI-X 1.0\n"); - break; - case CA_PHBTYPE_PCIX2_0: - p->is_pcie = false; - p->phb.scan_map = 0x0003; - p->phb.phb_type = phb_type_pcix_v2; - printf("P5IOC2: PHB is PCI/PCI-X 2.0\n"); - break; - case CA_PHBTYPE_PCIE_G1: - p->is_pcie = true; - p->phb.scan_map = 0x0001; - p->phb.phb_type = phb_type_pcie_v1; - printf("P5IOC2: PHB is PCI Express Gen 1\n"); - break; - case CA_PHBTYPE_PCIE_G2: - p->is_pcie = true; - p->phb.scan_map = 0x0001; - p->phb.phb_type = phb_type_pcie_v2; - printf("P5IOC2: PHB is PCI Express Gen 2\n"); - break; - default: - printf("P5IOC2: Unknown PHB type ! phbid=%08x\n", phbid); - p->is_pcie = true; - p->phb.scan_map = 0x0001; - p->phb.phb_type = phb_type_pcie_v1; - } - - /* Find P5IOC2 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("P5IOC2: Base location code not found !\n"); - - /* Add device nodes */ - if (p->is_pcie) - p5ioc2_pcie_add_node(p); - else - p5ioc2_pcix_add_node(p); - - /* Initialize PHB HW */ - p5ioc2_phb_hwinit(p); - - /* Register all 16 interrupt sources for now as OS visible - * - * If we ever add some EEH, we might take out the error interrupts - * and register them as OPAL internal interrupts instead - */ - register_irq_source(&p5ioc2_phb_os_irq_ops, p, p->buid << 4, 16); - - /* We cannot query the PHB type yet as the registers aren't routed - * so we'll do that in the inits, at which point we'll establish - * the scan map - */ - - /* 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); - - /* Platform additional setup */ - if (platform.pci_setup_phb) - platform.pci_setup_phb(&p->phb, p->index); -} - diff --git a/hw/p5ioc2.c b/hw/p5ioc2.c deleted file mode 100644 index ec9b7dad..00000000 --- a/hw/p5ioc2.c +++ /dev/null @@ -1,298 +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 <p5ioc2.h> -#include <p5ioc2-regs.h> -#include <cec.h> -#include <gx.h> -#include <opal.h> -#include <interrupts.h> -#include <device.h> -#include <timebase.h> -#include <vpd.h> -#include <ccan/str/str.h> - - -static int64_t p5ioc2_set_tce_mem(struct io_hub *hub, uint64_t address, - uint64_t size) -{ - struct p5ioc2 *ioc = iohub_to_p5ioc2(hub); - int64_t rc; - - printf("P5IOC2: set_tce_mem(0x%016llx size 0x%llx)\n", - address, size); - - /* The address passed must be naturally aligned */ - if (address && !is_pow2(size)) - return OPAL_PARAMETER; - if (address & (size - 1)) - return OPAL_PARAMETER; - - ioc->tce_base = address; - ioc->tce_size = size; - - rc = gx_configure_tce_bar(ioc->host_chip, ioc->gx_bus, - address, size); - if (rc) - return OPAL_INTERNAL_ERROR; - return OPAL_SUCCESS; -} - -static int64_t p5ioc2_get_diag_data(struct io_hub *hub __unused, - void *diag_buffer __unused, - uint64_t diag_buffer_len __unused) -{ - /* XXX Not yet implemented */ - return OPAL_UNSUPPORTED; -} - -static const struct io_hub_ops p5ioc2_hub_ops = { - .set_tce_mem = p5ioc2_set_tce_mem, - .get_diag_data = p5ioc2_get_diag_data, -}; - -static void p5ioc2_inits(struct p5ioc2 *ioc) -{ - uint64_t val; - unsigned int p, n; - - printf("P5IOC2: Initializing hub...\n"); - - /* - * BML base inits - */ - /* mask off interrupt presentation timeout in FIRMC */ - out_be64(ioc->regs + (P5IOC2_FIRMC | P5IOC2_REG_OR), - 0x0000080000000000UL); - - /* turn off display alter mode */ - out_be64(ioc->regs + (P5IOC2_CTL | P5IOC2_REG_AND), - 0xffffff7fffffffffUL); - - /* setup hub and clustering interrupts BUIDs to 1 and 2 */ - out_be64(ioc->regs + P5IOC2_SBUID, 0x0001000200000000UL); - - /* setup old style MSI BUID (should be unused but set it up anyway) */ - out_be32(ioc->regs + P5IOC2_BUCO, 0xf); - - /* Set XIXO bit 0 needed for "enhanced" TCEs or else TCE - * fetches appear as normal memory reads on GX causing - * P7 to checkstop when a TCE DKill collides with them. - */ - out_be64(ioc->regs + P5IOC2_XIXO, in_be64(ioc->regs + P5IOC2_XIXO) - | P5IOC2_XIXO_ENH_TCE); - - /* Clear routing tables */ - for (n = 0; n < 16; n++) { - for (p = 0; p < 8; p++) - out_be64(ioc->regs + P5IOC2_TxRTE(p,n), 0); - } - for (n = 0; n < 32; n++) - out_be64(ioc->regs + P5IOC2_BUIDRTE(n), 0); - - /* - * Setup routing. We use the same setup that pHyp appears - * to do (after inspecting the various registers with SCOM) - * - * We assume the BARs are already setup by the FSP such - * that BAR0 is 128G (8G region size) and BAR6 is - * 256M (16M region size). - * - * The routing is based on what pHyp and BML do, each Calgary - * get one slice of BAR6 and two slices of BAR0 - */ - /* BAR 0 segments 0 & 1 -> CA0 */ - out_be64(ioc->regs + P5IOC2_TxRTE(0,0), - P5IOC2_TxRTE_VALID | P5IOC2_CA0_RIO_ID); - out_be64(ioc->regs + P5IOC2_TxRTE(0,1), - P5IOC2_TxRTE_VALID | P5IOC2_CA0_RIO_ID); - - /* BAR 0 segments 2 & 3 -> CA1 */ - out_be64(ioc->regs + P5IOC2_TxRTE(0,2), - P5IOC2_TxRTE_VALID | P5IOC2_CA1_RIO_ID); - out_be64(ioc->regs + P5IOC2_TxRTE(0,3), - P5IOC2_TxRTE_VALID | P5IOC2_CA1_RIO_ID); - - /* BAR 6 segments 0 -> CA0 */ - out_be64(ioc->regs + P5IOC2_TxRTE(6,0), - P5IOC2_TxRTE_VALID | P5IOC2_CA0_RIO_ID); - - /* BAR 6 segments 1 -> CA0 */ - out_be64(ioc->regs + P5IOC2_TxRTE(6,1), - P5IOC2_TxRTE_VALID | P5IOC2_CA1_RIO_ID); - - /* - * BUID routing, we send entries 1 to CA0 and 2 to CA1 - * just like pHyp and make sure the base and mask are - * both clear in SID to we route the whole 512 block - */ - val = in_be64(ioc->regs + P5IOC2_SID); - val = SETFIELD(P5IOC2_SID_BUID_BASE, val, 0); - val = SETFIELD(P5IOC2_SID_BUID_MASK, val, 0); - out_be64(ioc->regs + P5IOC2_SID, val); - out_be64(ioc->regs + P5IOC2_BUIDRTE(1), - P5IOC2_BUIDRTE_VALID | P5IOC2_BUIDRTE_RR_RET | - P5IOC2_CA0_RIO_ID); - out_be64(ioc->regs + P5IOC2_BUIDRTE(2), - P5IOC2_BUIDRTE_VALID | P5IOC2_BUIDRTE_RR_RET | - P5IOC2_CA1_RIO_ID); -} - -static void p5ioc2_ca_init(struct p5ioc2 *ioc, int ca) -{ - void *regs = ca ? ioc->ca1_regs : ioc->ca0_regs; - uint64_t val; - - printf("P5IOC2: Initializing Calgary %d...\n", ca); - - /* Setup device BUID */ - val = SETFIELD(CA_DEVBUID_MASK, 0ul, ca ? P5IOC2_CA1_BUID : P5IOC2_CA0_BUID); - out_be32(regs + CA_DEVBUID, val); - - /* Setup HubID in TARm (and keep TCE clear, Linux will init that) - * - * BML and pHyp sets the values to 1 for CA0 and 4 for CA1. We - * keep the TAR valid bit clear as well. - */ - val = SETFIELD(CA_TAR_HUBID, 0ul, ca ? 4 : 1); - val = SETFIELD(CA_TAR_ALTHUBID, val, ca ? 4 : 1); - out_be64(regs + CA_TAR0, val); - out_be64(regs + CA_TAR1, val); - out_be64(regs + CA_TAR2, val); - out_be64(regs + CA_TAR3, val); - - /* Bridge config register. We set it up to the same value as observed - * under pHyp on a Juno machine. The difference from the IPL value is - * that TCE buffers are enabled, discard timers are increased and - * we disable response status to avoid errors. - */ - //out_be64(regs + CA_CCR, 0x5045DDDED2000000); - // disable memlimit: - out_be64(regs + CA_CCR, 0x5005DDDED2000000UL); - - /* The system memory base/limit etc... setup will be done when the - * user enables TCE via OPAL calls - */ -} - -static void p5ioc2_create_hub(struct dt_node *np) -{ - struct p5ioc2 *ioc; - unsigned int i, id, irq; - 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("P5IOC2: Found at %s ID 0x%x\n", path, id); - free(path); - dt_add_property_cells(np, "ibm,opal-hubid", 0, id); - - /* Load VPD LID */ - vpd_preload(np); - vpd_iohub_load(np); - - ioc = zalloc(sizeof(struct p5ioc2)); - if (!ioc) - return; - ioc->hub.hub_id = id; - ioc->hub.ops = &p5ioc2_hub_ops; - ioc->dt_node = np; - - /* We assume SBAR == GX0 + some hard coded offset */ - ioc->regs = (void *)dt_get_address(np, 0, NULL); - - /* For debugging... */ - for (i = 0; i < 8; i++) - printf("P5IOC2: BAR%d = 0x%016llx M=0x%16llx\n", i, - in_be64(ioc->regs + P5IOC2_BAR(i)), - in_be64(ioc->regs + P5IOC2_BARM(i))); - - ioc->host_chip = dt_get_chip_id(np); - - ioc->gx_bus = dt_prop_get_u32(np, "ibm,gx-index"); - - /* Rather than reading the BARs in P5IOC2, we "know" that - * BAR6 matches GX BAR 1 and BAR0 matches GX BAR 2. This - * is a bit fishy but will work for the few machines this - * is intended to work on - */ - ioc->bar6 = dt_prop_get_u64(np, "ibm,gx-bar-1"); - ioc->bar0 = dt_prop_get_u64(np, "ibm,gx-bar-2"); - - printf("DT BAR6 = 0x%016llx\n", ioc->bar6); - printf("DT BAR0 = 0x%016llx\n", ioc->bar0); - - /* We setup the corresponding Calgary register bases and memory - * regions. Note: those cannot be used until the routing has - * been setup by inits - */ - ioc->ca0_regs = (void *)ioc->bar6 + P5IOC2_CA0_REG_OFFSET; - ioc->ca1_regs = (void *)ioc->bar6 + P5IOC2_CA1_REG_OFFSET; - ioc->ca0_mm_region = ioc->bar0 + P5IOC2_CA0_MM_OFFSET; - ioc->ca1_mm_region = ioc->bar0 + P5IOC2_CA1_MM_OFFSET; - - /* Base of our BUIDs, will be refined later */ - ioc->buid_base = id << 9; - - /* Add interrupts: XXX These are the hub interrupts, we should add the - * calgary ones as well... but we don't handle any of them currently - * anyway. - */ - irq = (ioc->buid_base + 1) << 4; - dt_add_property_cells(np, "interrupts", irq, irq + 1); - dt_add_property_cells(np, "interrupt-base", irq); - - - /* Now, we do the bulk of the inits */ - p5ioc2_inits(ioc); - p5ioc2_ca_init(ioc, 0); - p5ioc2_ca_init(ioc, 1); - - /* So how do we know what PHBs to create ? Let's try all of them - * and we'll see if that causes problems. TODO: Use VPD ! - */ - for (i = 0; i < 4; i++) - p5ioc2_phb_setup(ioc, &ioc->ca0_phbs[i], 0, i, true, - ioc->buid_base + P5IOC2_CA0_BUID + i + 1); - for (i = 0; i < 4; i++) - p5ioc2_phb_setup(ioc, &ioc->ca1_phbs[i], 1, i, true, - ioc->buid_base + P5IOC2_CA1_BUID + i + 1); - - /* Reset delay... synchronous, hope we never do that as a - * result of an OPAL callback. We shouldn't really need this - * here and may fold it in the generic slot init sequence but - * it's not like we care much about that p5ioc2 code... - * - * This is mostly to give devices a chance to settle after - * having lifted the reset pin on PCI-X. - */ - time_wait_ms(1000); - - printf("P5IOC2: Initialization complete\n"); - - cec_register(&ioc->hub); -} - -void probe_p5ioc2(void) -{ - struct dt_node *np; - - dt_for_each_compatible(dt_root, np, "ibm,p5ioc2") - p5ioc2_create_hub(np); -} - @@ -186,7 +186,6 @@ static int64_t p7ioc_get_diag_data(struct io_hub *hub, } static const struct io_hub_ops p7ioc_hub_ops = { - .set_tce_mem = NULL, /* No set_tce_mem for p7ioc, we use FMTC */ .get_diag_data = p7ioc_get_diag_data, .reset = p7ioc_reset, }; diff --git a/include/cec.h b/include/cec.h index 87cdc0e5..97da17a8 100644 --- a/include/cec.h +++ b/include/cec.h @@ -26,10 +26,6 @@ struct io_hub; struct io_hub_ops { - /* OPAL_PCI_SET_HUB_TCE_MEMORY (p5ioc2 only) */ - int64_t (*set_tce_mem)(struct io_hub *hub, uint64_t address, - uint64_t size); - /* OPAL_PCI_GET_HUB_DIAG_DATA */ int64_t (*get_diag_data)(struct io_hub *hub, void *diag_buffer, uint64_t diag_buffer_len); diff --git a/include/p5ioc2-regs.h b/include/p5ioc2-regs.h deleted file mode 100644 index 1628f7af..00000000 --- a/include/p5ioc2-regs.h +++ /dev/null @@ -1,234 +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 __P5IOC2_REGS_H -#define __P5IOC2_REGS_H - -/* - * IO HUB registers - * - * Most (all) of those registers support an AND access - * at address + 0x1000 and an OR access at address + 0x2000 - */ -#define P5IOC2_REG_AND 0x1000 -#define P5IOC2_REG_OR 0x2000 - -/* Internal BARs */ -#define P5IOC2_BAR0 0x0100 -#define P5IOC2_BAR1 0x0108 -#define P5IOC2_BAR2 0x0110 -#define P5IOC2_BAR3 0x0118 -#define P5IOC2_BAR4 0x0120 -#define P5IOC2_BAR5 0x0128 -#define P5IOC2_BAR6 0x0130 -#define P5IOC2_BAR7 0x0138 -#define P5IOC2_BARM0 0x0180 -#define P5IOC2_BARM1 0x0188 -#define P5IOC2_BARM2 0x0190 -#define P5IOC2_BARM3 0x0198 -#define P5IOC2_BARM4 0x01a0 -#define P5IOC2_BARM5 0x01a8 -#define P5IOC2_BARM6 0x01b0 -#define P5IOC2_BARM7 0x01b8 -#define P5IOC2_BAR(n) (0x100 + ((n) << 3)) -#define P5IOC2_BARM(n) (0x180 + ((n) << 3)) - -/* Routing table */ -#define P5IOC2_TxRTE(x,n) (0x200 + ((x) << 7) + ((n) << 3)) -#define P5IOC2_TxRTE_VALID PPC_BIT(47) - -/* BUID routing table */ -#define P5IOC2_BUIDRTE(n) (0x600 + ((n) << 3)) -#define P5IOC2_BUIDRTE_VALID PPC_BIT(47) -#define P5IOC2_BUIDRTE_RR_EOI PPC_BIT(48) -#define P5IOC2_BUIDRTE_RR_RET PPC_BIT(49) - -/* Others */ -#define P5IOC2_FIRMC 0x0008 /* FIR Mask Checkstop */ -#define P5IOC2_CTL 0x0030 /* Control register part 1 */ -#define P5IOC2_CTL2 0x00c8 /* Control register part 2 */ -#define P5IOC2_DIRA 0x0090 /* Cache dir. address */ -#define P5IOC2_DIRD 0x0098 /* Cache dir. data */ -#define P5IOC2_IBASE 0x0048 /* Interrupt base address */ -#define P5IOC2_IRBM 0x00d8 /* Interrupt re-issue broadcast mask */ -#define P5IOC2_SID 0x0038 /* P5IOC2 ID register */ -#define P5IOC2_SID_BUID_BASE PPC_BITMASK(14,22) -#define P5IOC2_SID_BUID_MASK PPC_BITMASK(27,30) -#define P5IOC2_SBUID 0x00f8 /* P5IOC2 HUB BUID */ - -/* XIPM area */ -#define P5IOC2_BUCO 0x40008 -#define P5IOC2_MIIP 0x40000 -#define P5IOC2_XINM 0x40010 - -/* Xin/Xout area */ -#define P5IOC2_XIXO 0xf0030 -#define P5IOC2_XIXO_ENH_TCE PPC_BIT(0) - -/* - * Calgary registers - * - * CA0 is PCI-X and CA1 is PCIE, though the type can be discovered - * from registers so we'll simply let it do so - */ - -#define CA_CCR 0x108 -#define CA_DEVBUID 0x118 -#define CA_DEVBUID_MASK PPC_BITMASK32(7,15) -#define CA_TAR0 0x580 -#define CA_TAR_HUBID PPC_BITMASK(0,5) -#define CA_TAR_ALTHUBID PPC_BITMASK(6,11) -#define CA_TAR_TCE_ADDR PPC_BITMASK(16,48) -#define CA_TAR_VALID PPC_BIT(60) -#define CA_TAR_NUM_TCE PPC_BITMASK(61,63) -#define CA_TAR1 0x588 -#define CA_TAR2 0x590 -#define CA_TAR3 0x598 -#define CA_TARn(n) (0x580 + ((n) << 3)) - -#define CA_PHBID0 0x650 -#define CA_PHBID_PHB_ENABLE PPC_BIT32(0) -#define CA_PHBID_ADDRSPACE_ENABLE PPC_BIT32(1) -#define CA_PHBID_PHB_TYPE PPC_BITMASK32(4,7) -#define CA_PHBTYPE_PCIX1_0 0 -#define CA_PHBTYPE_PCIX2_0 1 -#define CA_PHBTYPE_PCIE_G1 4 -#define CA_PHBTYPE_PCIE_G2 5 -/* PCI-X bits */ -#define CA_PHBID_XMODE_EMBEDDED PPC_BIT32(8) -#define CA_PHBID_XBUS_64BIT PPC_BIT32(9) -#define CA_PHBID_XBUS_266MHZ PPC_BIT32(10) -/* PCI-E bits */ -#define CA_PHBID_EWIDTH PPC_BITMASK32(8,10) -#define CA_PHB_EWIDTH_X4 0 -#define CA_PHB_EWIDTH_X8 1 -#define CA_PHB_EWIDTH_X16 2 -#define CA_PHBID1 0x658 -#define CA_PHBID2 0x660 -#define CA_PHBID3 0x668 -#define CA_PHBIDn(n) (0x650 + ((n) << 3)) - -/* PHB n reg base inside CA */ -#define CA_PHBn_REGS(n) (0x8000 + ((n) << 12)) - -/* - * P5IOC2 PHB registers - */ -#define CAP_BUID 0x100 -#define CAP_BUID_MASK PPC_BITMASK32(7,15) -#define CAP_MSIBASE 0x108 /* Undocumented ! */ -#define CAP_DMACSR 0x110 -#define CAP_PLSSR 0x120 -#define CAP_PCADR 0x140 -#define CAP_PCADR_ENABLE PPC_BIT32(0) -#define CAP_PCADR_FUNC PPC_BITMASK32(21,23) -#define CAP_PCADR_BDFN PPC_BITMASK32(8,23) /* bus,dev,func */ -#define CAP_PCADR_EXTOFF PPC_BITMASK32(4,7) -#define CAP_PCDAT 0x130 -#define CAP_PCFGRW 0x160 -#define CAP_PCFGRW_ERR_RECOV_EN PPC_BIT32(1) -#define CAP_PCFGRW_TCE_EN PPC_BIT32(2) -#define CAP_PCFGRW_FREEZE_EN PPC_BIT32(3) -#define CAP_PCFGRW_MMIO_FROZEN PPC_BIT32(4) -#define CAP_PCFGRW_DMA_FROZEN PPC_BIT32(5) -#define CAP_PCFGRW_ENHANCED_CFG_EN PPC_BIT32(6) -#define CAP_PCFGRW_DAC_DISABLE PPC_BIT32(7) -#define CAP_PCFGRW_2ND_MEM_SPACE_EN PPC_BIT32(9) -#define CAP_PCFGRW_MASK_PLSSR_IRQ PPC_BIT32(10) -#define CAP_PCFGRW_MASK_CSR_IRQ PPC_BIT32(11) -#define CAP_PCFGRW_IO_SPACE_DIABLE PPC_BIT32(12) -#define CAP_PCFGRW_SZ_MASK_IS_LIMIT PPC_BIT32(13) -#define CAP_PCFGRW_MSI_EN PPC_BIT32(14) -#define CAP_IOAD_L 0x170 -#define CAP_IOAD_H 0x180 -#define CAP_MEM1_L 0x190 -#define CAP_MEM1_H 0x1a0 -#define CAP_IOSZ 0x1b0 -#define CAP_MSZ1 0x1c0 -#define CAP_MEM_ST 0x1d0 -#define CAP_IO_ST 0x1e0 -#define CAP_AER 0x200 -#define CAP_BPR 0x210 -#define CAP_CRR 0x270 -#define CAP_CRR_RESET1 PPC_BIT32(0) -#define CAP_CRR_RESET2 PPC_BIT32(1) -#define CAP_XIVR0 0x400 -#define CAP_XIVR_PRIO 0x000000ff -#define CAP_XIVR_SERVER 0x0000ff00 -#define CAP_XIVRn(n) (0x400 + ((n) << 4)) -#define CAP_MVE0 0x500 -#define CAP_MVE_VALID PPC_BIT32(0) -#define CAP_MVE_TBL_OFF PPC_BITMASK32(13,15) -#define CAP_MVE_NUM_INT PPC_BITMASK32(18,19) -#define CAP_MVE1 0x510 -#define CAP_MODE0 0x880 -#define CAP_MODE1 0x890 -#define CAP_MODE2 0x8a0 -#define CAP_MODE3 0x8b0 - -/* - * SHPC Registers - */ -#define SHPC_LOGICAL_SLOT 0xb40 -#define SHPC_LOGICAL_SLOT_STATE 0x00000003 -#define SHPC_SLOT_STATE_POWER_ONLY 1 -#define SHPC_SLOT_STATE_ENABLED 2 -#define SHPC_SLOT_STATE_DISABLED 3 -#define SHPC_LOGICAL_SLOT_PRSNT 0x000000c00 -#define SHPC_SLOT_PRSTN_7_5W 0 -#define SHPC_SLOT_PRSTN_25W 1 -#define SHPC_SLOT_STATE_15W 2 -#define SHPC_SLOT_STATE_EMPTY 3 - -/* UTL registers */ -#define UTL_SYS_BUS_CONTROL 0xc00 -#define UTL_STATUS 0xc04 -#define UTL_SYS_BUS_AGENT_STATUS 0xc08 -#define UTL_SYS_BUS_AGENT_ERR_EN 0xc0c -#define UTL_SYS_BUS_AGENT_IRQ_EN 0xc10 -#define UTL_SYS_BUS_BURST_SZ_CONF 0xc20 -#define UTL_REVISION_ID 0xc24 -#define UTL_TX_NON_POST_DEBUG_STAT1 0xc30 -#define UTL_TX_NON_POST_DEBUG_STAT2 0xc34 -#define UTL_GBIF_READ_REQ_DEBUG 0xc38 -#define UTL_GBIF_WRITE_REQ_DEBUG 0xc3c -#define UTL_GBIF_TX_COMP_DEBUG 0xc40 -#define UTL_GBIF_RX_COMP_DEBUG 0xc44 -#define UTL_OUT_POST_HDR_BUF_ALLOC 0xc60 -#define UTL_OUT_POST_DAT_BUF_ALLOC 0xc68 -#define UTL_IN_POST_HDR_BUF_ALLOC 0xc70 -#define UTL_IN_POST_DAT_BUF_ALLOC 0xc78 -#define UTL_OUT_NP_BUF_ALLOC 0xc80 -#define UTL_IN_NP_BUF_ALLOC 0xc88 -#define UTL_PCIE_TAGS_ALLOC 0xc90 -#define UTL_GBIF_READ_TAGS_ALLOC 0xc98 -#define UTL_PCIE_PORT_CONTROL 0xca0 -#define UTL_PCIE_PORT_STATUS 0xca4 -#define UTL_PCIE_PORT_ERR_EN 0xca8 -#define UTL_PCIE_PORT_IRQ_EN 0xcac -#define UTL_RC_STATUS 0xcb0 -#define UTL_RC_ERR_EN 0xcb4 -#define UTL_RC_IRQ_EN 0xcb8 -#define UTL_PCI_PM_CONTROL 0xcc8 -#define UTL_PCIE_PORT_ID 0xccc -#define UTL_TLP_DEBUG 0xcd0 -#define UTL_VC_CTL_DEBUG 0xcd4 -#define UTL_NP_BUFFER_DEBUG 0xcd8 -#define UTL_POSTED_BUFFER_DEBUG 0xcdc -#define UTL_TX_FIFO_DEBUG 0xce0 -#define UTL_TLP_COMPL_DEBUG 0xce4 - -#endif /* __P5IOC2_REGS_H */ diff --git a/include/p5ioc2.h b/include/p5ioc2.h deleted file mode 100644 index fb9ed1bb..00000000 --- a/include/p5ioc2.h +++ /dev/null @@ -1,184 +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 __P5IOC2_H -#define __P5IOC2_H - -#include <stdint.h> -#include <cec.h> -#include <io.h> -#include <cec.h> -#include <pci.h> -#include <lock.h> -#include <device.h> - -#include <ccan/container_of/container_of.h> - -/* - * Various definitions which are the result of various - * things we have hard wired (routing etc...) - */ - -/* It looks like our registers are at an offset from GX BAR 0 ... */ -#define P5IOC2_REGS_OFFSET 0x01F00000 - -#define P5IOC2_CA0_REG_OFFSET 0 /* From BAR6, R0 */ -#define P5IOC2_CA1_REG_OFFSET 0x01000000 /* From BAR6, R1 */ -#define P5IOC2_CA0_MM_OFFSET 0 /* From BAR0, R0 and 1 */ -#define P5IOC2_CA1_MM_OFFSET 0x400000000ul /* From BAR0, R1 and 2 */ -#define P5IOC2_CA_PHB_COUNT 4 -#define P5IOC2_CA0_RIO_ID 2 -#define P5IOC2_CA1_RIO_ID 3 -#define P5IOC2_CA0_BUID 0x10 -#define P5IOC2_CA1_BUID 0x20 - -/* - * Our memory space is slightly different than pHyp - * (or even BML). We do as follow: - * - * - IO space is in the Calgary MMIO, at (phb_index +1) * 1M - * (pHyp seems to mangle the IO space location) and is always - * 1M in size mapping to PCI 0 - * - * - Memory space is in the BAR0 mapped region. Each PHB gets - * allocated a 4G window at base + (phb_index * 4G). It uses - * a portion of that space based on the chosen size of the - * MMIO space, typically 2G. - */ -#define MM_WINDOW_SIZE 0x100000000ul -#define MM_PCI_START 0x80000000 -#define MM_PCI_SIZE 0x80000000 -#define IO_PCI_START 0x00000000 -#define IO_PCI_SIZE 0x00100000 - -/* - * CAn interrupts - * - * Within Calgary BUID space - */ -#define P5IOC2_CA_HOST_IRQ 0 -#define P5IOC2_CA_SPCN_IRQ 1 -#define P5IOC2_CA_PERF_IRQ 2 - -/* - * The PHB states are similar to P7IOC, see the explanation - * in p7ioc.h - */ -enum p5ioc2_phb_state { - /* First init state */ - P5IOC2_PHB_STATE_UNINITIALIZED, - - /* During PHB HW inits */ - P5IOC2_PHB_STATE_INITIALIZING, - - /* Set if the PHB is for some reason unusable */ - P5IOC2_PHB_STATE_BROKEN, - - /* Normal PHB functional state */ - P5IOC2_PHB_STATE_FUNCTIONAL, -}; - -/* - * Structure for a PHB - */ - -struct p5ioc2; - -struct p5ioc2_phb { - bool active; /* Is this PHB functional ? */ - bool is_pcie; - uint8_t ca; /* CA0 or CA1 */ - uint8_t index; /* 0..3 index inside CA */ - void *ca_regs; /* Calgary regs */ - void *regs; /* PHB regs */ - struct lock lock; - uint32_t buid; - uint64_t mm_base; - uint64_t io_base; - int64_t ecap; /* cached PCI-E cap offset */ - int64_t aercap; /* cached AER ecap offset */ - enum p5ioc2_phb_state state; - uint64_t delay_tgt_tb; - uint64_t retries; - uint64_t xive_cache[16]; - struct p5ioc2 *ioc; - struct phb phb; -}; - -static inline struct p5ioc2_phb *phb_to_p5ioc2_phb(struct phb *phb) -{ - return container_of(phb, struct p5ioc2_phb, phb); -} - -extern void p5ioc2_phb_setup(struct p5ioc2 *ioc, struct p5ioc2_phb *p, - uint8_t ca, uint8_t index, bool active, - uint32_t buid); - -/* - * State structure for P5IOC2 IO HUB - */ -struct p5ioc2 { - /* Device node */ - struct dt_node *dt_node; - - /* MMIO regs for the chip */ - void *regs; - - /* BAR6 (matches GX BAR 1) is used for internal Calgary MMIO and - * for PCI IO space. - */ - uint64_t bar6; - - /* BAR0 (matches GX BAR 2) is used for PCI memory space */ - uint64_t bar0; - - /* Calgary 0 and 1 registers. We assume their BBAR values as such - * that CA0 is at bar6 and CA1 at bar6 + 16M - */ - void* ca0_regs; - void* ca1_regs; - - /* The large MM regions assigned off bar0 to CA0 and CA1 for use - * by their PHBs (16G each) - */ - uint64_t ca0_mm_region; - uint64_t ca1_mm_region; - - /* BUID base for the PHB. This does include the top bits - * (chip, GX bus ID, etc...). This is initialized from the - * SPIRA. - */ - uint32_t buid_base; - - /* TCE region set by the user */ - uint64_t tce_base; - uint64_t tce_size; - - /* Calgary 0 and 1 PHBs */ - struct p5ioc2_phb ca0_phbs[P5IOC2_CA_PHB_COUNT]; - struct p5ioc2_phb ca1_phbs[P5IOC2_CA_PHB_COUNT]; - - uint32_t host_chip; - uint32_t gx_bus; - struct io_hub hub; -}; - -static inline struct p5ioc2 *iohub_to_p5ioc2(struct io_hub *hub) -{ - return container_of(hub, struct p5ioc2, hub); -} - -#endif /* __P5IOC2_H */ diff --git a/include/skiboot.h b/include/skiboot.h index e26ad2e0..a85fafcf 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -197,7 +197,6 @@ extern void init_shared_sprs(void); extern void init_replicated_sprs(void); /* Various probe routines, to replace with an initcall system */ -extern void probe_p5ioc2(void); extern void probe_p7ioc(void); extern void probe_phb3(void); extern int phb3_preload_capp_ucode(void); |