[Skiboot] [PATCH v2 02/12] opal: Identify chip role for a given topology.
Mahesh J Salgaonkar
mahesh at linux.vnet.ibm.com
Sat Jun 6 04:07:18 AEST 2015
From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
This patch introduces a topology config structure that holds enough
information related to both (primary and secondary) TOD topologies.
Currently this patch populates chip id and chip role for a given topology.
The subsequent patches is going to use this information to improve TOD
topology failover recovery.
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
Changes in V2:
- Fixed review comments. Removed double underscore from print_topo_info()
hw/chiptod.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/hw/chiptod.c b/hw/chiptod.c
index 8706810..fc62268 100644
--- a/hw/chiptod.c
+++ b/hw/chiptod.c
@@ -26,6 +26,13 @@
#include <timebase.h>
#include <opal-api.h>
+/* -- TOD primary/secondary master/slave control register -- */
+#define TOD_PSMS_CTRL 0x00040007
+#define TOD_PSMSC_PM_TOD_SELECT PPC_BIT(1) /* Primary Master TOD */
+#define TOD_PSMSC_PM_DRAW_SELECT PPC_BIT(2) /* Primary Master Drawer */
+#define TOD_PSMSC_SM_TOD_SELECT PPC_BIT(9) /* Secondary Master TOD */
+#define TOD_PSMSC_SM_DRAW_SELECT PPC_BIT(10) /* Secondary Master Draw */
+
/* -- TOD primary/secondary master/slave status register -- */
#define TOD_STATUS 0x00040008
#define TOD_ST_TOPOLOGY_SELECT PPC_BITMASK(0, 2)
@@ -96,10 +103,31 @@ enum chiptod_topology {
chiptod_topo_secondary = 1,
};
+enum chiptod_chip_role {
+ chiptod_chip_role_UNKNOWN = -1,
+ chiptod_chip_role_MDMT = 0, /* Master Drawer Master TOD */
+ chiptod_chip_role_MDST, /* Master Drawer Slave TOD */
+ chiptod_chip_role_SDMT, /* Slave Drawer Master TOD */
+ chiptod_chip_role_SDST, /* Slave Drawer Slave TOD */
+};
+
+struct chiptod_chip_config_info {
+ int32_t id; /* chip id */
+ enum chiptod_chip_role role; /* Chip role */
+};
+
static int32_t chiptod_primary = -1;
static int32_t chiptod_secondary = -1;
static enum chiptod_topology current_topology = chiptod_topo_unknown;
+/*
+ * chiptod_topology_info holds primary/secondary chip configuration info.
+ * This info is initialized during chiptod_init(). This is an array of two:
+ * [0] = [chiptod_topo_primary] = Primary topology config info
+ * [1] = [chiptod_topo_secondary] = Secondary topology config info
+ */
+static struct chiptod_chip_config_info chiptod_topology_info[2];
+
/* The base TFMR value is the same for the whole machine
* for now as far as I can tell
*/
@@ -112,6 +140,15 @@ static uint64_t base_tfmr;
*/
static struct lock chiptod_lock = LOCK_UNLOCKED;
+static void print_topo_info(enum chiptod_topology topo)
+{
+ const char *role[] = { "Unknown", "MDMT", "MDST", "SDMT", "SDST" };
+
+ prlog(PR_DEBUG, "CHIPTOD: chip id: %d, Role: %s\n",
+ chiptod_topology_info[topo].id,
+ role[chiptod_topology_info[topo].role + 1]);
+}
+
static void print_topology_info(void)
{
const char *topo[] = { "Primary", "Secondary" };
@@ -121,6 +158,10 @@ static void print_topology_info(void)
prlog(PR_DEBUG, "CHIPTOD: TOD Topology in Use: %s\n",
topo[current_topology]);
+ prlog(PR_DEBUG, "CHIPTOD: Primary configuration:\n");
+ print_topo_info(chiptod_topo_primary);
+ prlog(PR_DEBUG, "CHIPTOD: Secondary configuration:\n");
+ print_topo_info(chiptod_topo_secondary);
}
static enum chiptod_topology query_current_topology(void)
@@ -143,6 +184,61 @@ static enum chiptod_topology query_current_topology(void)
return chiptod_topo_secondary;
}
+static enum chiptod_chip_role
+chiptod_get_chip_role(enum chiptod_topology topology, int32_t chip_id)
+{
+ uint64_t tod_ctrl;
+ enum chiptod_chip_role role = chiptod_chip_role_UNKNOWN;
+
+ if (chip_id < 0)
+ return role;
+
+ if (xscom_read(chip_id, TOD_PSMS_CTRL, &tod_ctrl) != 0) {
+ prerror("CHIPTOD: XSCOM error reading TOD_PSMS_CTRL\n");
+ return chiptod_chip_role_UNKNOWN;
+ }
+
+ switch (topology) {
+ case chiptod_topo_primary:
+ if (tod_ctrl & TOD_PSMSC_PM_DRAW_SELECT) {
+ if (tod_ctrl & TOD_PSMSC_PM_TOD_SELECT)
+ role = chiptod_chip_role_MDMT;
+ else
+ role = chiptod_chip_role_MDST;
+ } else {
+ if (tod_ctrl & TOD_PSMSC_PM_TOD_SELECT)
+ role = chiptod_chip_role_SDMT;
+ else
+ role = chiptod_chip_role_SDST;
+ }
+ break;
+ case chiptod_topo_secondary:
+ if (tod_ctrl & TOD_PSMSC_SM_DRAW_SELECT) {
+ if (tod_ctrl & TOD_PSMSC_SM_TOD_SELECT)
+ role = chiptod_chip_role_MDMT;
+ else
+ role = chiptod_chip_role_MDST;
+ } else {
+ if (tod_ctrl & TOD_PSMSC_SM_TOD_SELECT)
+ role = chiptod_chip_role_SDMT;
+ else
+ role = chiptod_chip_role_SDST;
+ }
+ break;
+ case chiptod_topo_unknown:
+ default:
+ break;
+ }
+ return role;
+}
+
+static void chiptod_update_topology(enum chiptod_topology topo)
+{
+ int32_t chip_id = chiptod_topology_info[topo].id;
+
+ chiptod_topology_info[topo].role = chiptod_get_chip_role(topo, chip_id);
+}
+
static void chiptod_setup_base_tfmr(void)
{
struct dt_node *cpu = this_cpu()->node;
@@ -992,6 +1088,14 @@ static void chiptod_init_topology_info(void)
/* Find and update current topology in use. */
current_topology = query_current_topology();
+ /* Initialized primary topology chip config info */
+ chiptod_topology_info[chiptod_topo_primary].id = chiptod_primary;
+ chiptod_update_topology(chiptod_topo_primary);
+
+ /* Initialized secondary topology chip config info */
+ chiptod_topology_info[chiptod_topo_secondary].id = chiptod_secondary;
+ chiptod_update_topology(chiptod_topo_secondary);
+
print_topology_info();
}
More information about the Skiboot
mailing list