aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2017-03-23 17:15:08 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-03-24 12:51:29 +1100
commit74311a97190d33e3753dc09a5fe6064120c8363a (patch)
tree981bf00892543d34b9331a533dfd554bfd30c4d5
parentded2533b5b31252639ac354521127a239df39e30 (diff)
downloadskiboot-74311a97190d33e3753dc09a5fe6064120c8363a.zip
skiboot-74311a97190d33e3753dc09a5fe6064120c8363a.tar.gz
skiboot-74311a97190d33e3753dc09a5fe6064120c8363a.tar.bz2
xscom: Add indirect form 1 scoms
Add code to perform indirect form 1 scoms. POWER8 does form 0 only. POWER9 adds form 1. The form is determined from the address only. Hardware only allows writes for form 1. Only hostboot uses these scoms during IPL, so they are unused by skiboot currently. Signed-off-by: Michael Neuling <mikey@neuling.org> Reviewed-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--hw/xscom.c49
-rw-r--r--include/xscom.h1
2 files changed, 48 insertions, 2 deletions
diff --git a/hw/xscom.c b/hw/xscom.c
index b0bc260..9fb7da6 100644
--- a/hw/xscom.c
+++ b/hw/xscom.c
@@ -317,7 +317,8 @@ static int __xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val)
/*
* Indirect XSCOM access functions
*/
-static int xscom_indirect_read(uint32_t gcid, uint64_t pcb_addr, uint64_t *val)
+static int xscom_indirect_read_form0(uint32_t gcid, uint64_t pcb_addr,
+ uint64_t *val)
{
uint32_t addr;
uint64_t data;
@@ -360,7 +361,23 @@ static int xscom_indirect_read(uint32_t gcid, uint64_t pcb_addr, uint64_t *val)
return rc;
}
-static int xscom_indirect_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val)
+static int xscom_indirect_form(uint64_t pcb_addr)
+{
+ return (pcb_addr >> 60) & 1;
+}
+
+static int xscom_indirect_read(uint32_t gcid, uint64_t pcb_addr, uint64_t *val)
+{
+ uint64_t form = xscom_indirect_form(pcb_addr);
+
+ if ((proc_gen == proc_gen_p9) && (form == 1))
+ return OPAL_UNSUPPORTED;
+
+ return xscom_indirect_read_form0(gcid, pcb_addr, val);
+}
+
+static int xscom_indirect_write_form0(uint32_t gcid, uint64_t pcb_addr,
+ uint64_t val)
{
uint32_t addr;
uint64_t data;
@@ -402,6 +419,34 @@ static int xscom_indirect_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val)
return rc;
}
+static int xscom_indirect_write_form1(uint32_t gcid, uint64_t pcb_addr,
+ uint64_t val)
+{
+ uint32_t addr;
+ uint64_t data;
+
+ if (proc_gen < proc_gen_p9)
+ return OPAL_UNSUPPORTED;
+ if (val & ~(XSCOM_DATA_IND_FORM1_DATA))
+ return OPAL_PARAMETER;
+
+ /* Mangle address and data for form1 */
+ addr = (pcb_addr & 0x000ffffffff);
+ data = (pcb_addr & 0xfff00000000) << 20;
+ data |= val;
+ return __xscom_write(gcid, addr, data);
+}
+
+static int xscom_indirect_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val)
+{
+ uint64_t form = xscom_indirect_form(pcb_addr);
+
+ if ((proc_gen == proc_gen_p9) && (form == 1))
+ return xscom_indirect_write_form1(gcid, pcb_addr, val);
+
+ return xscom_indirect_write_form0(gcid, pcb_addr, val);
+}
+
static uint32_t xscom_decode_chiplet(uint32_t partid, uint64_t *pcb_addr)
{
uint32_t gcid = (partid & 0x0fffffff) >> 4;
diff --git a/include/xscom.h b/include/xscom.h
index bad9140..871d210 100644
--- a/include/xscom.h
+++ b/include/xscom.h
@@ -192,6 +192,7 @@
#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