aboutsummaryrefslogtreecommitdiff
path: root/hw/npu2-opencapi.c
diff options
context:
space:
mode:
authorAndrew Donnellan <andrew.donnellan@au1.ibm.com>2018-09-14 13:46:25 +1000
committerStewart Smith <stewart@linux.ibm.com>2018-09-17 21:39:01 -0500
commitb6cc82cb39c4d891799f4d7a9f8e76fdf8a16125 (patch)
treec4d041ba07a43591e72eebcbaecd02fca217717e /hw/npu2-opencapi.c
parent68415d5e38ef04e647ad36d59f90c008a0414f56 (diff)
downloadskiboot-b6cc82cb39c4d891799f4d7a9f8e76fdf8a16125.zip
skiboot-b6cc82cb39c4d891799f4d7a9f8e76fdf8a16125.tar.gz
skiboot-b6cc82cb39c4d891799f4d7a9f8e76fdf8a16125.tar.bz2
hw/npu2, platform: Add NPU2 platform device detection callback
There is no standardised way to determine the presence and type of devices connected to an NPU on POWER9. Currently, we hardcode device types based on platform type (as no platform currently supports both OpenCAPI and NVLink), and for OpenCAPI platforms we use I2C to detect presence. Witherspoon (and potentially other platforms later on) supports both NVLink and OpenCAPI, and additionally uses SXM2 connectors which can carry more than one link, rather than the SlimSAS connectors used for OpenCAPI on Zaius and ZZ. This necessitates some special handling. Add a platform callback for NPU device detection. In a later patch, we will use this to implement Witherspoon-specific device detection. For now, add a Witherspoon stub that sets all links to NVLink (i.e. current behaviour). Move the existing I2C-based presence detection for OpenCAPI devices on Zaius/ZZ into common code, which we use by default for platforms which do not define a callback. Clean up the use of the ibm,npu-link-type property, which will now be exposed solely for debugging and not consumed internally. Signed-off-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Reviewed-by: Frederic Barrat <fbarrat@linux.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'hw/npu2-opencapi.c')
-rw-r--r--hw/npu2-opencapi.c93
1 files changed, 14 insertions, 79 deletions
diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c
index b0103cf..7033d07 100644
--- a/hw/npu2-opencapi.c
+++ b/hw/npu2-opencapi.c
@@ -52,14 +52,6 @@
#include <i2c.h>
#include <nvram.h>
-#define OCAPIDBG(dev, fmt, a...) prlog(PR_DEBUG, "OCAPI[%d:%d]: " fmt, \
- dev->npu->chip_id, dev->brick_index, ## a)
-#define OCAPIINF(dev, fmt, a...) prlog(PR_INFO, "OCAPI[%d:%d]: " fmt, \
- dev->npu->chip_id, dev->brick_index, ## a)
-#define OCAPIERR(dev, fmt, a...) prlog(PR_ERR, "OCAPI[%d:%d]: " fmt, \
- dev->npu->chip_id, dev->brick_index, ## a)
-
-
#define NPU_IRQ_LEVELS 35
#define NPU_IRQ_LEVELS_XSL 23
#define MAX_PE_HANDLE ((1 << 15) - 1)
@@ -842,7 +834,7 @@ static void assert_reset(struct npu2_dev *dev)
* register and a pin is in output mode if its value is 0
*/
data = ~pin;
- rc = i2c_request_send(dev->i2c_port_id_ocapi,
+ rc = i2c_request_send(dev->npu->i2c_port_id_ocapi,
platform.ocapi->i2c_reset_addr, SMBUS_WRITE,
0x3, 1,
&data, sizeof(data), 120);
@@ -851,7 +843,7 @@ static void assert_reset(struct npu2_dev *dev)
/* register 1 controls the signal, reset is active low */
data = ~pin;
- rc = i2c_request_send(dev->i2c_port_id_ocapi,
+ rc = i2c_request_send(dev->npu->i2c_port_id_ocapi,
platform.ocapi->i2c_reset_addr, SMBUS_WRITE,
0x1, 1,
&data, sizeof(data), 120);
@@ -874,7 +866,7 @@ static void deassert_reset(struct npu2_dev *dev)
int rc;
data = 0xFF;
- rc = i2c_request_send(dev->i2c_port_id_ocapi,
+ rc = i2c_request_send(dev->npu->i2c_port_id_ocapi,
platform.ocapi->i2c_reset_addr, SMBUS_WRITE,
0x1, 1,
&data, sizeof(data), 120);
@@ -888,43 +880,6 @@ static void deassert_reset(struct npu2_dev *dev)
}
}
-static bool i2c_presence_detect(struct npu2_dev *dev)
-{
- uint8_t state, data;
- int rc;
-
- /*
- * Opencapi presence detection is done through i2c
- *
- * Lagrange platforms (ZZ, Zaius) use the same default mechanism.
- * Witherspoon will need a specific implementation, TBD.
- */
- rc = i2c_request_send(dev->i2c_port_id_ocapi,
- platform.ocapi->i2c_presence_addr,
- SMBUS_READ, 0, 1,
- &state, 1, 120);
- if (rc) {
- OCAPIERR(dev, "error detecting link presence: %d\n", rc);
- return true; /* assume link exists */
- }
-
- OCAPIDBG(dev, "I2C presence detect: 0x%x\n", state);
-
- switch (dev->brick_index) { // TODO(ajd): Link or brick index?
- case 2:
- data = platform.ocapi->i2c_presence_odl0;
- break;
- case 3:
- data = platform.ocapi->i2c_presence_odl1;
- break;
- default:
- OCAPIERR(dev, "presence detection on invalid link\n");
- return true;
- }
- /* Presence detect bits are active low */
- return !(state & data);
-}
-
static void reset_odl(uint32_t gcid, struct npu2_dev *dev)
{
uint64_t reg, config_xscom;
@@ -1015,17 +970,18 @@ static void start_training(uint32_t gcid, struct npu2_dev *dev)
xscom_write(gcid, config_xscom, reg);
}
-static int64_t npu2_opencapi_get_presence_state(struct pci_slot *slot,
+static int64_t npu2_opencapi_get_presence_state(struct pci_slot __unused *slot,
uint8_t *val)
{
- bool present;
- struct npu2_dev *dev = phb_to_npu2_dev_ocapi(slot->phb);
-
- if (platform.ocapi->force_presence)
- present = true;
- else
- present = i2c_presence_detect(dev);
- *val = present;
+ /*
+ * Presence detection for OpenCAPI is currently done at the start of
+ * NPU initialisation, and we only create slots if a device is present.
+ * As such we will never be asked to get the presence of a slot that's
+ * empty.
+ *
+ * This may change if we ever support hotplug down the track.
+ */
+ *val = true;
return OPAL_SUCCESS;
}
@@ -1578,9 +1534,8 @@ static void setup_debug_training_state(struct npu2_dev *dev)
static void setup_device(struct npu2_dev *dev)
{
- struct dt_node *dn_phb, *dn;
+ struct dt_node *dn_phb;
struct pci_slot *slot;
- char port_name[17];
uint64_t mm_win[2];
/* Populate PHB device node */
@@ -1626,23 +1581,6 @@ static void setup_device(struct npu2_dev *dev)
dev->bdfn = 0;
dev->train_need_fence = false;
dev->train_fenced = false;
- /* Find I2C port for handling device reset */
- snprintf(port_name, sizeof(port_name), "p8_%08x_e%dp%d",
- dev->npu->chip_id, platform.ocapi->i2c_engine,
- platform.ocapi->i2c_port);
- prlog(PR_DEBUG, "OCAPI: Looking for I2C port %s\n", port_name);
-
- dt_for_each_compatible(dt_root, dn, "ibm,power9-i2c-port") {
- if (streq(port_name, dt_prop_get(dn, "ibm,port-name"))) {
- dev->i2c_port_id_ocapi = dt_prop_get_u32(dn, "ibm,opal-id");
- break;
- }
- }
-
- if (!dev->i2c_port_id_ocapi) {
- prlog(PR_ERR, "OCAPI: Couldn't find I2C port %s\n", port_name);
- goto failed;
- }
/* TODO: Procedure 13.1.3.7 - AFU Memory Range BARs */
/* Procedure 13.1.3.8 - AFU MMIO Range BARs */
@@ -1667,9 +1605,6 @@ static void setup_device(struct npu2_dev *dev)
}
pci_register_phb(&dev->phb_ocapi, OPAL_DYNAMIC_PHB_ID);
return;
-failed:
- dt_add_property_string(dn_phb, "status", "error");
- return;
}
static void read_nvram_training_state(void)