aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/include/xscom.h
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/include/xscom.h')
-rw-r--r--roms/skiboot/include/xscom.h300
1 files changed, 300 insertions, 0 deletions
diff --git a/roms/skiboot/include/xscom.h b/roms/skiboot/include/xscom.h
new file mode 100644
index 000000000..a6bb7e400
--- /dev/null
+++ b/roms/skiboot/include/xscom.h
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2013-2019 IBM Corp. */
+
+#ifndef __XSCOM_H
+#define __XSCOM_H
+
+#include <stdint.h>
+#include <processor.h>
+#include <cpu.h>
+
+/*
+ * SCOM "partID" definitions:
+ *
+ * All Ids are 32-bits long, top nibble is reserved for the
+ * 'type' field:
+ * 0x0 = Processor Chip
+ * 0x8 = Memory Buffer (Centaur) Chip
+ * 0x4 = EX/Core Chiplet
+ *
+ * Processor Chip = Logical Fabric Id = PIR>>7
+ * 0b0000.0000.0000.0000.0000.0000.00NN.NCCC
+ * N=Node, C=Chip
+ * Centaur Chip = Associated Processor Chip with memory channel
+ * appended and flag set
+ * 0b1000.0000.0000.0000.0000.00NN.NCCC.MMMM
+ * N=Node, C=Chip, M=Memory Channel
+ * Processor EX/Core chiplet = PIR >> 3 with flag set.
+ * On P8:
+ * 0b0100.0000.0000.0000.0000.00NN.NCCC.PPPP
+ * On P9:
+ * 0b0100.0000.0000.0000.0000.0NNN.CCCP.PPPP
+ * N=Node, C=Chip, P=Processor core
+ */
+
+/*
+ * SCOM Address definition extracted from HWPs for documentation
+ * purposes
+ *
+ * "Normal" (legacy) format
+ *
+ * 111111 11112222 22222233 33333333 44444444 44555555 55556666
+ * 01234567 89012345 67890123 45678901 23456789 01234567 89012345 67890123
+ * -------- -------- -------- -------- -------- -------- -------- --------
+ * 00000000 00000000 00000000 00000000 0MCCCCCC ????PPPP 00LLLLLL LLLLLLLL
+ * || | |
+ * || | `-> Local Address*
+ * || |
+ * || `-> Port
+ * ||
+ * |`-> Chiplet ID**
+ * |
+ * `-> Multicast bit
+ *
+ * * Local address is composed of "00" + 4-bit ring + 10-bit ID
+ * The 10-bit ID is usually 4-bit sat_id and 6-bit reg_id
+ *
+ * ** Chiplet ID turns into multicast operation type and group number
+ * if the multicast bit is set
+ *
+ * "Indirect" format
+ *
+ *
+ * 111111 11112222 22222233 33333333 44444444 44555555 55556666
+ * 01234567 89012345 67890123 45678901 23456789 01234567 89012345 67890123
+ * -------- -------- -------- -------- -------- -------- -------- --------
+ * 10000000 0000IIII IIIIIGGG GGGLLLLL 0MCCCCCC ????PPPP 00LLLLLL LLLLLLLL
+ * | | | || | |
+ * | | | || | `-> Local Address*
+ * | | | || |
+ * | | | || `-> Port
+ * | | | ||
+ * | | | |`-> Chiplet ID**
+ * | | | |
+ * | | | `-> Multicast bit
+ * | | |
+ * | | `-> Lane ID
+ * | |
+ * | `-> RX or TX Group ID
+ * |
+ * `-> Indirect Register Address
+ *
+ * * Local address is composed of "00" + 4-bit ring + 4-bit sat_id + "111111"
+ *
+ * ** Chiplet ID turns into multicast operation type and group number
+ * if the multicast bit is set
+ */
+
+/*
+ * Generate a local address from a given ring/satellite/offset
+ * combination:
+ *
+ * Ring Satellite offset
+ * +---------+---------+-------------+
+ * | 4 | 4 | 6 |
+ * +---------+---------+-------------+
+ */
+#define XSCOM_SAT(_r, _s, _o) \
+ (((_r) << 10) | ((_s) << 6) | (_o))
+
+/*
+ * Additional useful definitions for P8
+ */
+#define P8_EX_PCB_SLAVE_BASE 0x100F0000
+
+#define XSCOM_ADDR_P8_EX_SLAVE(core, offset) \
+ (P8_EX_PCB_SLAVE_BASE | (((core) & 0xF) << 24) | ((offset) & 0xFFFF))
+
+#define XSCOM_ADDR_P8_EX(core, addr) \
+ ((((core) & 0xF) << 24) | (addr))
+
+/*
+ * Additional useful definitions for P9
+ *
+ * Note: In all of these, the core numbering is the
+ * *normal* (small) core number.
+ */
+
+/*
+ * An EQ is a quad. The Pervasive spec also uses the term "EP"
+ * to refer to an EQ and it's two child EX chiplets, but
+ * nothing else does
+ */
+#define XSCOM_ADDR_P9_EQ(core, addr) \
+ (((((core) & 0x1c) + 0x40) << 22) | (addr))
+#define XSCOM_ADDR_P9_EQ_SLAVE(core, addr) \
+ XSCOM_ADDR_P9_EQ(core, (addr) | 0xf0000)
+
+/* An EX is a pair of cores. They are accessed via their corresponding EQs
+ * with bit 0x400 indicating which of the 2 EX to address
+ */
+#define XSCOM_ADDR_P9_EX(core, addr) \
+ (XSCOM_ADDR_P9_EQ(core, addr | (((core) & 2) << 9)))
+
+/* An EC is an individual core and has its own XSCOM addressing */
+#define XSCOM_ADDR_P9_EC(core, addr) \
+ (((((core) & 0x1F) + 0x20) << 24) | (addr))
+#define XSCOM_ADDR_P9_EC_SLAVE(core, addr) \
+ XSCOM_ADDR_P9_EC(core, (addr) | 0xf0000)
+
+/*
+ * Additional useful definitions for P10
+ */
+
+/*
+ * POWER10 pervasive structure
+ * Chip has 8 EQ chiplets (aka super-chiplets), and other nest chiplets.
+ * Each EQ contains 4 EX regions.
+ * Each EX contains an ECL2, L3, MMA.
+ * Each ECL2 contains an EC (core), L2, and NCU.
+ *
+ * Each EQ has a Quad Management Engine (QME), responsible for power management
+ * for the cores, among other things.
+ *
+ * POWER10 XSCOM address format:
+ *
+ * | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16-31|
+ * MC=0 |WR|MC|SLAVE ADDR |PIB MASTER |PORT NUMBER|LOCAL|
+ * MC=1 |WR|MC|MC TYPE |MC GROUP|PIB MASTER |PORT NUMBER|LOCAL|
+ *
+ * * Port is also known as PSCOM endpoint.
+ *
+ * WR is set by the xscom access functions (XSCOM_DATA_IND_READ bit)
+ * MC is always 0 (skiboot does not use multicast scoms).
+ *
+ * For unicast:
+ * EQ0-7 is addressed from 0x20 to 0x27 in the top 8 bits.
+ * L3 is on port 1
+ * NCU is on port 1
+ * ECL2 (core+L2) is on port 2 (XXX P10 scoms html doc suggests port 1?)
+ * QME is on port E.
+ *
+ * EQ chiplets (aka super chiplet) local address format:
+ *
+ * | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|
+ * |C0|C1|C2|C3|RING ID |SAT ID |REGISTER ID |
+ *
+ * EX0-4 are selected with one-hot encoding (C0-3)
+ *
+ * QME per-core register access address format:
+ * | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|
+ * |C0|C1|C2|C3| 1| 0| 0| 0|PER-CORE REGISTER ID |
+ *
+ * NCU - ring 6 (port 1)
+ * L3 - ring 3 (port 1) (XXX P10 scoms html doc suggests ring 6)
+ * L2 - ring 0 (port 2) (XXX P10 scoms html doc suggests ring 4)
+ * EC (PC unit) - rings 2-5 (port 2)
+ *
+ * Other chiplets:
+ *
+ * | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|
+ * | 1|RING ID |SAT ID |REGISTER ID |
+ */
+
+#define P10_CORE_EQ_CHIPLET(core) (0x20 + ((core) >> 2))
+#define P10_CORE_PROC(core) ((core) & 0x3)
+
+#define XSCOM_P10_EQ(chiplet) ((chiplet) << 24)
+
+#define XSCOM_P10_QME(chiplet) \
+ (XSCOM_P10_EQ(chiplet) | (0xE << 16))
+
+#define XSCOM_P10_QME_CORE(chiplet, proc) \
+ (XSCOM_P10_QME(chiplet) | ((1 << (3 - proc)) << 12))
+
+#define XSCOM_P10_EC(chiplet, proc) \
+ (XSCOM_P10_EQ(chiplet) | (0x2 << 16) | ((1 << (3 - proc)) << 12))
+
+#define XSCOM_P10_NCU(chiplet, proc) \
+ (XSCOM_P10_EQ(chiplet) | (0x1 << 16) | ((1 << (3 - proc)) << 12))
+
+#define XSCOM_ADDR_P10_EQ(core, addr) \
+ (XSCOM_P10_EQ(P10_CORE_EQ_CHIPLET(core)) | (addr))
+
+#define XSCOM_ADDR_P10_QME(core, addr) \
+ (XSCOM_P10_QME(P10_CORE_EQ_CHIPLET(core)) | (addr))
+
+#define XSCOM_ADDR_P10_QME_CORE(core, addr) \
+ (XSCOM_P10_QME_CORE(P10_CORE_EQ_CHIPLET(core), P10_CORE_PROC(core)) | (addr))
+
+#define XSCOM_ADDR_P10_EC(core, addr) \
+ (XSCOM_P10_EC(P10_CORE_EQ_CHIPLET(core), P10_CORE_PROC(core)) | (addr))
+
+#define XSCOM_ADDR_P10_NCU(core, addr) \
+ (XSCOM_P10_NCU(P10_CORE_EQ_CHIPLET(core), P10_CORE_PROC(core)) | (addr))
+
+/* Definitions relating to indirect XSCOMs shared with centaur */
+#define XSCOM_ADDR_IND_FLAG PPC_BIT(0)
+#define XSCOM_ADDR_IND_ADDR PPC_BITMASK(12,31)
+#define XSCOM_ADDR_IND_DATA PPC_BITMASK(48,63)
+
+#define XSCOM_DATA_IND_READ PPC_BIT(0)
+#define XSCOM_DATA_IND_COMPLETE PPC_BIT(32)
+#define XSCOM_DATA_IND_ERR PPC_BITMASK(33,35)
+#define XSCOM_DATA_IND_DATA PPC_BITMASK(48,63)
+#define XSCOM_DATA_IND_FORM1_DATA PPC_BITMASK(12,63)
+
+/* HB folks say: try 10 time for now */
+#define XSCOM_IND_MAX_RETRIES 10
+
+/* Max number of retries when XSCOM remains busy */
+#define XSCOM_BUSY_MAX_RETRIES 3000
+
+/* Max number of retries for xscom clearing recovery. */
+#define XSCOM_CLEAR_MAX_RETRIES 10
+
+/* Retry count after which to reset XSCOM, if still busy */
+#define XSCOM_BUSY_RESET_THRESHOLD 1000
+
+/*
+ * Error handling:
+ *
+ * Error codes TBD, 0 = success
+ */
+
+/* Use only in select places where multiple SCOMs are time/latency sensitive */
+extern void _xscom_lock(void);
+extern int _xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val, bool take_lock);
+extern int _xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val, bool take_lock);
+extern void _xscom_unlock(void);
+
+
+/* Targeted SCOM access */
+static inline int xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val)
+{
+ return _xscom_read(partid, pcb_addr, val, true);
+}
+static inline int xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val) {
+ return _xscom_write(partid, pcb_addr, val, true);
+}
+extern int xscom_write_mask(uint32_t partid, uint64_t pcb_addr, uint64_t val, uint64_t mask);
+
+/* This chip SCOM access */
+extern int xscom_readme(uint64_t pcb_addr, uint64_t *val);
+extern int xscom_writeme(uint64_t pcb_addr, uint64_t val);
+extern void xscom_init(void);
+
+/* Mark XSCOM lock as being in console path */
+extern void xscom_used_by_console(void);
+
+/* Returns true if XSCOM can be used. Typically this returns false if
+ * the current CPU holds the XSCOM lock (to avoid re-entrancy from error path).
+ */
+extern bool xscom_ok(void);
+
+extern int64_t xscom_read_cfam_chipid(uint32_t partid, uint32_t *chip_id);
+extern int64_t xscom_trigger_xstop(void);
+
+
+struct scom_controller {
+ uint32_t part_id;
+ void *private;
+ int64_t (*read)(struct scom_controller *, uint32_t chip, uint64_t reg, uint64_t *val);
+ int64_t (*write)(struct scom_controller *, uint32_t chip, uint64_t reg, uint64_t val);
+
+ struct list_node link;
+};
+
+int64_t scom_register(struct scom_controller *new);
+
+#endif /* __XSCOM_H */