diff options
author | Philippe Bergheaud <felix@linux.vnet.ibm.com> | 2016-04-01 14:27:57 +0200 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-04-27 15:06:11 +1000 |
commit | c27ead751a1cd6541e98dc2b490ac453613e8d69 (patch) | |
tree | 8e33f6615917bc1a5b35c36deeeeb7c623d29f5d | |
parent | 451b69d489112ef61d99199bec6c5eaf3a946127 (diff) | |
download | skiboot-c27ead751a1cd6541e98dc2b490ac453613e8d69.zip skiboot-c27ead751a1cd6541e98dc2b490ac453613e8d69.tar.gz skiboot-c27ead751a1cd6541e98dc2b490ac453613e8d69.tar.bz2 |
phb3: Load CAPP ucode to both CAPP units on Naples
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@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | hw/phb3.c | 30 | ||||
-rw-r--r-- | include/capp.h | 7 | ||||
-rw-r--r-- | include/chip.h | 2 | ||||
-rw-r--r-- | include/phb3.h | 11 |
4 files changed, 40 insertions, 10 deletions
@@ -2358,6 +2358,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; @@ -2390,12 +2393,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; @@ -2423,6 +2430,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 *) @@ -2438,22 +2446,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; @@ -2463,11 +2475,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; } @@ -3387,7 +3399,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); |