[Skiboot-stable] [PATCH skiboot-op940.x] platform/mihawk: support dynamic PCIe slot table
Joy Chu
joy_chu at wistron.com
Wed Apr 1 21:12:28 AEDT 2020
[ Upstream commit 68260957 ]
Slot table auto-detection for different riser cards by using IPMI OEM command to communicate with BMC.
Signed-off-by: Joy Chu <joy_chu at wistron.com>
Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
platforms/astbmc/mihawk.c | 228 +++++++++++++++++++++++++++++++++++---
1 file changed, 212 insertions(+), 16 deletions(-)
diff --git a/platforms/astbmc/mihawk.c b/platforms/astbmc/mihawk.c
index ee820135..8971b407 100644
--- a/platforms/astbmc/mihawk.c
+++ b/platforms/astbmc/mihawk.c
@@ -15,8 +15,16 @@
#include <pci.h>
#include <pci-cfg.h>
+#include <timebase.h>
+
#include "astbmc.h"
+/* IPMI message code for Riser-F query (OEM). */
+#define IPMI_RISERF_QUERY IPMI_CODE(0x32, 0x01)
+
+static bool mihawk_riserF_found = false;
+static bool bmc_query_waiting = false;
+
#define OPAL_ID_SLOT2 0x01
#define OPAL_ID_SLOT4 0x03
#define OPAL_ID_SLOT7 0x31
@@ -151,7 +159,7 @@ static const struct platform_ocapi mihawk_ocapi = {
.ocapi_slot_label = mihawk_ocapi_slot_label,
};
-static const struct slot_table_entry P1E1A_x8_PLX8748_down[] = {
+static const struct slot_table_entry P1E1A_x8_PLX8748_RiserA_down[] = {
SW_PLUGGABLE("Slot7", 0x10),
SW_PLUGGABLE("Slot8", 0x8),
SW_PLUGGABLE("Slot10", 0x9),
@@ -159,25 +167,25 @@ static const struct slot_table_entry P1E1A_x8_PLX8748_down[] = {
{ .etype = st_end }
};
-static const struct slot_table_entry P1E1A_x8_PLX8748_up[] = {
+static const struct slot_table_entry P1E1A_x8_PLX8748_RiserA_up[] = {
{
.etype = st_builtin_dev,
.location = ST_LOC_DEVFN(0,0),
- .children = P1E1A_x8_PLX8748_down,
+ .children = P1E1A_x8_PLX8748_RiserA_down,
},
{ .etype = st_end }
};
-static const struct slot_table_entry p1phb1_slot[] = {
+static const struct slot_table_entry p1phb1_rA_slot[] = {
{
.etype = st_builtin_dev,
.location = ST_LOC_DEVFN(0,0),
- .children = P1E1A_x8_PLX8748_up,
+ .children = P1E1A_x8_PLX8748_RiserA_up,
},
{ .etype = st_end },
};
-static const struct slot_table_entry P0E1A_x8_PLX8748_down[] = {
+static const struct slot_table_entry P0E1A_x8_PLX8748_RiserA_down[] = {
SW_PLUGGABLE("Slot2", 0x10),
SW_PLUGGABLE("Slot3", 0x8),
SW_PLUGGABLE("Slot5", 0x9),
@@ -185,20 +193,120 @@ static const struct slot_table_entry P0E1A_x8_PLX8748_down[] = {
{ .etype = st_end }
};
-static const struct slot_table_entry P0E1A_x8_PLX8748_up[] = {
+static const struct slot_table_entry P0E1A_x8_PLX8748_RiserA_up[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P0E1A_x8_PLX8748_RiserA_down,
+ },
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry p0phb1_rA_slot[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P0E1A_x8_PLX8748_RiserA_up,
+ },
+ { .etype = st_end },
+};
+
+static const struct slot_table_entry P1E1A_x8_PLX8748_RiserF_down[] = {
+ SW_PLUGGABLE("Slot7", 0x10),
+ SW_PLUGGABLE("Slot10", 0x9),
+
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry P1E1A_x8_PLX8748_RiserF_up[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P1E1A_x8_PLX8748_RiserF_down,
+ },
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry p1phb1_rF_slot[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P1E1A_x8_PLX8748_RiserF_up,
+ },
+ { .etype = st_end },
+};
+
+static const struct slot_table_entry P0E1A_x8_PLX8748_RiserF_down[] = {
+ SW_PLUGGABLE("Slot2", 0x10),
+ SW_PLUGGABLE("Slot5", 0x9),
+
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry P0E1A_x8_PLX8748_RiserF_up[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P0E1A_x8_PLX8748_RiserF_down,
+ },
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry p0phb1_rF_slot[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P0E1A_x8_PLX8748_RiserF_up,
+ },
+ { .etype = st_end },
+};
+
+static const struct slot_table_entry P1E2_x16_Switch_down[] = {
+ SW_PLUGGABLE("Slot8", 0x1),
+ SW_PLUGGABLE("Slot9", 0x0),
+
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry P1E2_x16_Switch_up[] = {
{
.etype = st_builtin_dev,
.location = ST_LOC_DEVFN(0,0),
- .children = P0E1A_x8_PLX8748_down,
+ .children = P1E2_x16_Switch_down,
},
{ .etype = st_end }
};
-static const struct slot_table_entry p0phb1_slot[] = {
+static const struct slot_table_entry p1phb3_switch_slot[] = {
{
.etype = st_builtin_dev,
.location = ST_LOC_DEVFN(0,0),
- .children = P0E1A_x8_PLX8748_up,
+ .children = P1E2_x16_Switch_up,
+ },
+ { .etype = st_end },
+};
+
+static const struct slot_table_entry P0E2_x16_Switch_down[] = {
+ SW_PLUGGABLE("Slot3", 0x1),
+ SW_PLUGGABLE("Slot4", 0x0),
+
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry P0E2_x16_Switch_up[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P0E2_x16_Switch_down,
+ },
+ { .etype = st_end }
+};
+
+static const struct slot_table_entry p0phb3_switch_slot[] = {
+ {
+ .etype = st_builtin_dev,
+ .location = ST_LOC_DEVFN(0,0),
+ .children = P0E2_x16_Switch_up,
},
{ .etype = st_end },
};
@@ -208,22 +316,38 @@ ST_PLUGGABLE(p0phb3_slot, "Slot4");
ST_PLUGGABLE(p1phb0_slot, "Slot6");
ST_PLUGGABLE(p1phb3_slot, "Slot9");
-static const struct slot_table_entry mihawk_phb_table[] = {
+static const struct slot_table_entry mihawk_riserA_phb_table[] = {
/* ==== CPU0 ==== */
ST_PHB_ENTRY(0, 0, p0phb0_slot), /* P0E0_x16_Slot1 */
- ST_PHB_ENTRY(0, 1, p0phb1_slot), /* P0E1A_x8_PLX8748-1_Slot2-3-5 */
+ ST_PHB_ENTRY(0, 1, p0phb1_rA_slot), /* P0E1A_x8_PLX8748-1_Slot2-3-5 */
//ST_PHB_ENTRY(0, 2, p0phb2_slot), /* P0E1B_x8_USBTI7340 */
ST_PHB_ENTRY(0, 3, p0phb3_slot), /* P0E2_x16_Slot4 */
/* ==== CPU1 ==== */
ST_PHB_ENTRY(8, 0, p1phb0_slot), /* P1E0_x16_Slot6 */
- ST_PHB_ENTRY(8, 1, p1phb1_slot), /* P1E1A_x8_PLX8748-2_Slot7-8-10 */
+ ST_PHB_ENTRY(8, 1, p1phb1_rA_slot), /* P1E1A_x8_PLX8748-2_Slot7-8-10 */
//ST_PHB_ENTRY(8, 2, p1phb2_slot), /* P1E1B_x8_NA */
ST_PHB_ENTRY(8, 3, p1phb3_slot), /* P1E2_x16_Slot9 */
{ .etype = st_end },
};
+static const struct slot_table_entry mihawk_riserF_phb_table[] = {
+ /* ==== CPU0 ==== */
+ ST_PHB_ENTRY(0, 0, p0phb0_slot), /* P0E0_x16_Slot1 */
+ ST_PHB_ENTRY(0, 1, p0phb1_rF_slot), /* P0E1A_x8_PLX8748-1_Slot2-5 */
+ //ST_PHB_ENTRY(0, 2, p0phb2_slot), /* P0E1B_x8_USBTI7340 */
+ ST_PHB_ENTRY(0, 3, p0phb3_switch_slot),/* P0E2_x16_SWITCH_Slot3-4 */
+
+ /* ==== CPU1 ==== */
+ ST_PHB_ENTRY(8, 0, p1phb0_slot), /* P1E0_x16_Slot6 */
+ ST_PHB_ENTRY(8, 1, p1phb1_rF_slot), /* P1E1A_x8_PLX8748-2_Slot7-10 */
+ //ST_PHB_ENTRY(8, 2, p1phb2_slot), /* P1E1B_x8_NA */
+ ST_PHB_ENTRY(8, 3, p1phb3_switch_slot),/* P1E2_x16_SWITCH_Slot8-9 */
+
+ { .etype = st_end },
+};
+
#define NPU_BASE 0x5011000
#define NPU_SIZE 0x2c
#define NPU_INDIRECT0 0x8000000009010c3fUL /* OB0 - no OB3 on Mihawk */
@@ -342,15 +466,87 @@ static bool mihawk_probe(void)
mihawk_create_npu();
mihawk_create_ocapi_i2c_bus();
- slot_table_init(mihawk_phb_table);
-
return true;
}
+static void mihawk_riser_query_complete(struct ipmi_msg *msg)
+{
+ uint8_t *riser_state;
+
+ if (msg->cc != IPMI_CC_NO_ERROR) {
+ prlog(PR_ERR, "Mihawk: IPMI riser query returned error. cmd=0x%02x,"
+ " netfn=0x%02x, rc=0x%x\n", msg->cmd, msg->netfn, msg->cc);
+ bmc_query_waiting = false;
+ ipmi_free_msg(msg);
+ return;
+ }
+
+ prlog(PR_DEBUG, "Mihawk: IPMI Got riser query result. p0:%02x, p1:%02x\n"
+ , msg->data[0], msg->data[1]);
+
+ riser_state = (uint8_t*)msg->user_data;
+ lwsync();
+ *riser_state = msg->data[0] << 4 | msg->data[1];
+
+ bmc_query_waiting = false;
+ ipmi_free_msg(msg);
+}
+
+static void mihawk_init(void)
+{
+ struct ipmi_msg *ipmi_msg;
+ uint8_t riser_state = 0;
+ int timeout_ms = 3000;
+
+ astbmc_init();
+
+ /*
+ * We use IPMI to ask BMC if Riser-F is installed and set up the
+ * corresponding slot table.
+ */
+ ipmi_msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE,
+ IPMI_RISERF_QUERY,
+ mihawk_riser_query_complete,
+ &riser_state, NULL, 0, 2);
+
+ if (!ipmi_msg) {
+ prlog(PR_ERR, "Mihawk: Couldn't create ipmi msg.");
+ } else {
+ ipmi_msg->error = mihawk_riser_query_complete;
+ ipmi_queue_msg(ipmi_msg);
+ bmc_query_waiting = true;
+
+ prlog(PR_DEBUG, "Mihawk: Requesting IPMI_RISERF_QUERY (netfn "
+ "%02x, cmd %02x)\n", ipmi_msg->netfn, ipmi_msg->cmd);
+
+ while (bmc_query_waiting) {
+ time_wait_ms(10);
+ timeout_ms -= 10;
+
+ if (timeout_ms == 0)
+ break;
+ }
+
+ ipmi_free_msg(ipmi_msg);
+ }
+
+ prlog(PR_DEBUG, "Mihawk: IPMI_RISERF_QUERY finish. riser_state: %02x"
+ ", waiting: %d\n", riser_state, bmc_query_waiting);
+
+ if (riser_state != 0) {
+ mihawk_riserF_found = true;
+ slot_table_init(mihawk_riserF_phb_table);
+ prlog(PR_DEBUG, "Mihawk: Detect Riser-F via IPMI\n");
+ } else {
+ slot_table_init(mihawk_riserA_phb_table);
+ prlog(PR_DEBUG, "Mihawk: No Riser-F found, use Riser-A table\n");
+ }
+}
+
DECLARE_PLATFORM(mihawk) = {
.name = "Mihawk",
.probe = mihawk_probe,
- .init = astbmc_init,
+ .init = mihawk_init,
.start_preload_resource = flash_start_preload_resource,
.resource_loaded = flash_resource_loaded,
.bmc = &bmc_plat_ast2500_openbmc,
--
2.17.1
---------------------------------------------------------------------------------------------------------------------------------------------------------------
This email contains confidential or legally privileged information and is for the sole use of its intended recipient.
Any unauthorized review, use, copying or distribution of this email or the content of this email is strictly prohibited.
If you are not the intended recipient, you may reply to the sender and should delete this e-mail immediately.
---------------------------------------------------------------------------------------------------------------------------------------------------------------
More information about the Skiboot-stable
mailing list