[Skiboot] [PATCH V4 2/6] phb3: Load CAPP ucode to both CAPP units on Naples
Philippe Bergheaud
felix at linux.vnet.ibm.com
Fri Apr 1 23:27:57 AEDT 2016
Venice and Murano have only one capp unit, that can be mapped to phb0,
phb1 or phb2. Naples has two capp units, that are statically mapped,
capp unit 0 on phb0 and capp unit 1 on phb1. The capp ucode must be
loaded once onto each capp unit.
This patch replaces the boolean chip->capp_ucode_loaded by a bitmap,
and sets the bit corresponding to the phb index to indicate that ucode
has been loaded. The macro CAPP_UCODE_LOADED(chip, phb) returns the value
of the phb index bit.
The xscom register addresses of capp unit 0 are identical to the register
addresses of the single capp unit of Venice and Murano. The addresses of
the Naples capp unit 1 are equal to the addresses of capp unit 0 + 0x180.
This patch introduces the macro PHB3_CAPP_REG_OFFSET(p), that returns the
following xscom register address offsets:
0x0 for the Venice capp unit
0x0 for the Murano capp unit
0x0 for Naples capp unit 0
0x180 for Naples capp unit 1
The offset is added to the register address at each xscom_write, in order
to operate on the right capp unit.
Signed-off-by: Philippe Bergheaud <felix at linux.vnet.ibm.com>
---
V2: after Mikey's review
- Longer description
- Incorrect else statement suppressed
- Coding style reworked
- Parenthesis added around macro arguments
V3:
- Parenthesis around macro arguments (again)
- capp_ucode_loaded always used as a bitmap
- New macro PHB3_IS_NAPLES(p)
- New macro PHB3_MAX_CAPP_PHB_INDEX(p)
- s/CAPP_REG_OFFSET(phb_rev, phb_index)/PHB3_CAPP_REG_OFFSET(p)/
V4:
- s/PHB3_MAX_CAPP_PHB_INDEX/PHB3_CAPP_MAX_PHB_INDEX/
- Added a comment to clarify this macro logic
hw/phb3.c | 30 +++++++++++++++++++++---------
include/capp.h | 7 +++++++
include/chip.h | 2 +-
include/phb3.h | 11 +++++++++++
4 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/hw/phb3.c b/hw/phb3.c
index adff5bc..b3276f9 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -2314,6 +2314,9 @@ static struct {
#define CAPP_UCODE_MAX_SIZE 0x20000
+#define CAPP_UCODE_LOADED(chip, p) \
+ ((chip)->capp_ucode_loaded & (1 << (p)->index))
+
static int64_t capp_lid_download(void)
{
int64_t ret;
@@ -2346,12 +2349,16 @@ static int64_t capp_load_ucode(struct phb3 *p)
struct capp_ucode_data *data;
struct capp_lid_hdr *lid;
uint64_t rc, val, addr;
- uint32_t chunk_count, offset;
+ uint32_t chunk_count, offset, reg_offset;
int i;
- if (chip->capp_ucode_loaded)
+ if (CAPP_UCODE_LOADED(chip, p))
return OPAL_SUCCESS;
+ /* Return if PHB not attached to a CAPP unit */
+ if (p->index > PHB3_CAPP_MAX_PHB_INDEX(p))
+ return OPAL_HARDWARE;
+
rc = capp_lid_download();
if (rc)
return rc;
@@ -2379,6 +2386,7 @@ static int64_t capp_load_ucode(struct phb3 *p)
return OPAL_HARDWARE;
}
+ reg_offset = PHB3_CAPP_REG_OFFSET(p);
offset = 0;
while (offset < be64_to_cpu(ucode->data_size)) {
data = (struct capp_ucode_data *)
@@ -2394,22 +2402,26 @@ static int64_t capp_load_ucode(struct phb3 *p)
switch (data->hdr.reg) {
case apc_master_cresp:
- xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG,
+ xscom_write(p->chip_id,
+ CAPP_APC_MASTER_ARRAY_ADDR_REG + reg_offset,
0);
addr = CAPP_APC_MASTER_ARRAY_WRITE_REG;
break;
case apc_master_uop_table:
- xscom_write(p->chip_id, CAPP_APC_MASTER_ARRAY_ADDR_REG,
+ xscom_write(p->chip_id,
+ CAPP_APC_MASTER_ARRAY_ADDR_REG + reg_offset,
0x180ULL << 52);
addr = CAPP_APC_MASTER_ARRAY_WRITE_REG;
break;
case snp_ttype:
- xscom_write(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG,
+ xscom_write(p->chip_id,
+ CAPP_SNP_ARRAY_ADDR_REG + reg_offset,
0x5000ULL << 48);
addr = CAPP_SNP_ARRAY_WRITE_REG;
break;
case snp_uop_table:
- xscom_write(p->chip_id, CAPP_SNP_ARRAY_ADDR_REG,
+ xscom_write(p->chip_id,
+ CAPP_SNP_ARRAY_ADDR_REG + reg_offset,
0x4000ULL << 48);
addr = CAPP_SNP_ARRAY_WRITE_REG;
break;
@@ -2419,11 +2431,11 @@ static int64_t capp_load_ucode(struct phb3 *p)
for (i = 0; i < chunk_count; i++) {
val = be64_to_cpu(data->data[i]);
- xscom_write(p->chip_id, addr, val);
+ xscom_write(p->chip_id, addr + reg_offset, val);
}
}
- chip->capp_ucode_loaded = true;
+ chip->capp_ucode_loaded |= (1 << p->index);
return OPAL_SUCCESS;
}
@@ -3343,7 +3355,7 @@ static int64_t phb3_set_capi_mode(struct phb *phb, uint64_t mode,
int i;
u8 mask;
- if (!chip->capp_ucode_loaded) {
+ if (!CAPP_UCODE_LOADED(chip, p)) {
PHBERR(p, "CAPP: ucode not loaded\n");
return OPAL_RESOURCE;
}
diff --git a/include/capp.h b/include/capp.h
index d9275ec..f5494e7 100644
--- a/include/capp.h
+++ b/include/capp.h
@@ -80,3 +80,10 @@ enum capp_reg {
#define FLUSH_UOP_CONFIG1 0x2013803
#define FLUSH_UOP_CONFIG2 0x2013804
#define SNOOP_CAPI_CONFIG 0x201301A
+
+/*
+ * Naples has two CAPP units, statically mapped:
+ * CAPP0 attached to PHB0, and CAPP1 attached to PHB1.
+ * The addresses of CAPP1 XSCOMS registers are 0x180 away.
+ */
+#define CAPP1_REG_OFFSET 0x180
diff --git a/include/chip.h b/include/chip.h
index 9e50f7a..72b85df 100644
--- a/include/chip.h
+++ b/include/chip.h
@@ -160,7 +160,7 @@ struct proc_chip {
/* Must hold capi_lock to change */
u8 capp_phb3_attached_mask;
- bool capp_ucode_loaded;
+ u8 capp_ucode_loaded;
/* Used by hw/centaur.c */
struct centaur_chip *centaurs;
diff --git a/include/phb3.h b/include/phb3.h
index 44ac52b..5728650 100644
--- a/include/phb3.h
+++ b/include/phb3.h
@@ -314,6 +314,17 @@ struct phb3 {
struct phb phb;
};
+#define PHB3_IS_NAPLES(p) ((p)->rev == PHB3_REV_NAPLES_DD10)
+
+/*
+ * Venice/Murano have one CAPP unit, that can be attached to PHB0,1 or 2.
+ * Naples has two CAPP units: CAPP0 attached to PHB0, CAPP1 attached to PHB1.
+ */
+#define PHB3_CAPP_MAX_PHB_INDEX(p) (PHB3_IS_NAPLES(p) ? 1 : 2)
+
+#define PHB3_CAPP_REG_OFFSET(p) \
+ ((p)->index && PHB3_IS_NAPLES(p) ? CAPP1_REG_OFFSET : 0x0)
+
static inline struct phb3 *phb_to_phb3(struct phb *phb)
{
return container_of(phb, struct phb3, phb);
--
2.1.0
More information about the Skiboot
mailing list