aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/centaur.c109
-rw-r--r--hw/xscom.c12
-rw-r--r--include/xscom.h12
3 files changed, 118 insertions, 15 deletions
diff --git a/hw/centaur.c b/hw/centaur.c
index 3df1291..5e594c1 100644
--- a/hw/centaur.c
+++ b/hw/centaur.c
@@ -82,7 +82,7 @@ static int64_t centaur_fsiscom_complete(struct centaur_chip *centaur)
if (stat == 0xffffffffu) {
cent_log(PR_ERR, centaur, "Chip appears to be dead !\n");
centaur->valid = false;
-
+
/* Here, hostboot grabs a pile of FFDC from the FSI layer,
* we could do that too ...
*/
@@ -215,6 +215,103 @@ struct centaur_chip *get_centaur(uint32_t part_id)
return centaur;
}
+/*
+ * Indirect XSCOM access functions. Copied from xscom.c, at a
+ * latter date, we should merge these properly.
+ */
+static void centaur_xscom_handle_ind_error(struct centaur_chip *centaur,
+ uint64_t data, uint64_t pcb_addr,
+ bool is_write)
+{
+ unsigned int stat = GETFIELD(XSCOM_DATA_IND_ERR, data);
+ bool timeout = !(data & XSCOM_DATA_IND_COMPLETE);
+
+ /* XXX: Create error log entry ? */
+ if (timeout)
+ cent_log(PR_ERR, centaur,
+ "inddirect %s timeout, pcb_addr=0x%llx stat=0x%x\n",
+ is_write ? "write" : "read", pcb_addr, stat);
+ else
+ cent_log(PR_ERR, centaur,
+ "indirect %s error, pcb_addr=0x%llx stat=0x%x\n",
+ is_write ? "write" : "read", pcb_addr, stat);
+}
+
+static int centaur_xscom_ind_read(struct centaur_chip *centaur,
+ uint64_t pcb_addr, uint64_t *val)
+{
+ uint32_t addr;
+ uint64_t data;
+ int rc, retries;
+
+ /* Write indirect address */
+ addr = pcb_addr & 0x7fffffff;
+ data = XSCOM_DATA_IND_READ |
+ (pcb_addr & XSCOM_ADDR_IND_ADDR);
+ rc = centaur_fsiscom_write(centaur, addr, data);
+ if (rc)
+ goto bail;
+
+ /* Wait for completion */
+ for (retries = 0; retries < XSCOM_IND_MAX_RETRIES; retries++) {
+ rc = centaur_fsiscom_read(centaur, addr, &data);
+ if (rc)
+ goto bail;
+ if ((data & XSCOM_DATA_IND_COMPLETE) &&
+ ((data & XSCOM_DATA_IND_ERR) == 0)) {
+ *val = data & XSCOM_DATA_IND_DATA;
+ break;
+ }
+ if ((data & XSCOM_DATA_IND_COMPLETE) ||
+ (retries >= XSCOM_IND_MAX_RETRIES)) {
+ centaur_xscom_handle_ind_error(centaur, data, pcb_addr,
+ false);
+ rc = OPAL_HARDWARE;
+ goto bail;
+ }
+ }
+ bail:
+ if (rc)
+ *val = (uint64_t)-1;
+ return rc;
+}
+
+static int centaur_xscom_ind_write(struct centaur_chip *centaur,
+ uint64_t pcb_addr, uint64_t val)
+{
+ uint32_t addr;
+ uint64_t data;
+ int rc, retries;
+
+ /* Write indirect address & data */
+ addr = pcb_addr & 0x7fffffff;
+ data = pcb_addr & XSCOM_ADDR_IND_ADDR;
+ data |= val & XSCOM_ADDR_IND_DATA;
+
+ rc = centaur_fsiscom_write(centaur, addr, data);
+ if (rc)
+ goto bail;
+
+ /* Wait for completion */
+ for (retries = 0; retries < XSCOM_IND_MAX_RETRIES; retries++) {
+ rc = centaur_fsiscom_read(centaur, addr, &data);
+ if (rc)
+ goto bail;
+ if ((data & XSCOM_DATA_IND_COMPLETE) &&
+ ((data & XSCOM_DATA_IND_ERR) == 0))
+ break;
+ if ((data & XSCOM_DATA_IND_COMPLETE) ||
+ (retries >= XSCOM_IND_MAX_RETRIES)) {
+ centaur_xscom_handle_ind_error(centaur, data, pcb_addr,
+ true);
+ rc = OPAL_HARDWARE;
+ goto bail;
+ }
+ }
+ bail:
+ return rc;
+}
+
int64_t centaur_xscom_read(uint32_t id, uint64_t pcb_addr, uint64_t *val)
{
struct centaur_chip *centaur = get_centaur(id);
@@ -224,7 +321,10 @@ int64_t centaur_xscom_read(uint32_t id, uint64_t pcb_addr, uint64_t *val)
return OPAL_PARAMETER;
lock(&centaur->lock);
- rc = centaur_fsiscom_read(centaur, pcb_addr, val);
+ if (pcb_addr & XSCOM_ADDR_IND_FLAG)
+ rc = centaur_xscom_ind_read(centaur, pcb_addr, val);
+ else
+ rc = centaur_fsiscom_read(centaur, pcb_addr, val);
unlock(&centaur->lock);
return rc;
@@ -239,7 +339,10 @@ int64_t centaur_xscom_write(uint32_t id, uint64_t pcb_addr, uint64_t val)
return OPAL_PARAMETER;
lock(&centaur->lock);
- rc = centaur_fsiscom_write(centaur, pcb_addr, val);
+ if (pcb_addr & XSCOM_ADDR_IND_FLAG)
+ rc = centaur_xscom_ind_write(centaur, pcb_addr, val);
+ else
+ rc = centaur_fsiscom_write(centaur, pcb_addr, val);
unlock(&centaur->lock);
return rc;
diff --git a/hw/xscom.c b/hw/xscom.c
index f803615..c8e13be 100644
--- a/hw/xscom.c
+++ b/hw/xscom.c
@@ -29,18 +29,6 @@
SPR_HMER_XSCOM_DONE | \
SPR_HMER_XSCOM_STATUS))
-#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)
-
-/* HB folks say: try 10 time for now */
-#define XSCOM_IND_MAX_RETRIES 10
-
DEFINE_LOG_ENTRY(OPAL_RC_XSCOM_RW, OPAL_PLATFORM_ERR_EVT, OPAL_XSCOM,
OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
OPAL_NA);
diff --git a/include/xscom.h b/include/xscom.h
index 6e47c0d..933af6a 100644
--- a/include/xscom.h
+++ b/include/xscom.h
@@ -154,6 +154,18 @@
#define EX_PM_IDLE_ST_HIST_PM_STATE_MASK PPC_BITMASK(0, 2)
#define EX_PM_IDLE_ST_HIST_PM_STATE_LSH PPC_BITLSHIFT(2)
+/* 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)
+
+/* HB folks say: try 10 time for now */
+#define XSCOM_IND_MAX_RETRIES 10
/*
* Error handling: