summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/init.c1
-rw-r--r--hdata/iohub.c214
-rw-r--r--hdata/spira.h1
-rw-r--r--hw/Makefile.inc2
-rw-r--r--hw/cec.c11
-rw-r--r--hw/p5ioc2-phb.c1206
-rw-r--r--hw/p5ioc2.c298
-rw-r--r--hw/p7ioc.c1
-rw-r--r--include/cec.h4
-rw-r--r--include/p5ioc2-regs.h234
-rw-r--r--include/p5ioc2.h184
-rw-r--r--include/skiboot.h1
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
diff --git a/hw/cec.c b/hw/cec.c
index 23d6362d..1743f4d8 100644
--- a/hw/cec.c
+++ b/hw/cec.c
@@ -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, &reg32);
- 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, &reg32);
- 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);
-}
-
diff --git a/hw/p7ioc.c b/hw/p7ioc.c
index 95941422..85a0a512 100644
--- a/hw/p7ioc.c
+++ b/hw/p7ioc.c
@@ -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);
OpenPOWER on IntegriCloud