aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2015-09-30 15:47:03 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-10-01 11:03:52 +1000
commit0896e73b1a0ec72aad5c464b4fdb6a826b9a3160 (patch)
tree5ecdbfc605de7c3002688b0d298e5e6284e3d93e
parent902e1a67c3a245c7cd52d8bf6a53fdafe13afd6e (diff)
downloadskiboot-0896e73b1a0ec72aad5c464b4fdb6a826b9a3160.zip
skiboot-0896e73b1a0ec72aad5c464b4fdb6a826b9a3160.tar.gz
skiboot-0896e73b1a0ec72aad5c464b4fdb6a826b9a3160.tar.bz2
centaur: Add indirect XSCOM support
It works just like P8, we copy the code for now rather than make it somewhat common due to our locking differences and to limit the risk close to release. We can refactor later. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-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: