From patchwork Fri Mar 31 16:52:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lombard X-Patchwork-Id: 745719 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vvnfF1rPVz9s0Z for ; Sat, 1 Apr 2017 03:54:29 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3vvnfF0m5yzDqK8 for ; Sat, 1 Apr 2017 03:54:29 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3vvnd53blNzDqJ8 for ; Sat, 1 Apr 2017 03:53:29 +1100 (AEDT) Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v2VGiNSn135252 for ; Fri, 31 Mar 2017 12:53:21 -0400 Received: from e06smtp15.uk.ibm.com (e06smtp15.uk.ibm.com [195.75.94.111]) by mx0b-001b2d01.pphosted.com with ESMTP id 29htb8svkd-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Fri, 31 Mar 2017 12:53:20 -0400 Received: from localhost by e06smtp15.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 31 Mar 2017 17:53:18 +0100 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp15.uk.ibm.com (192.168.101.145) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 31 Mar 2017 17:53:16 +0100 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v2VGqnxf40435872; Fri, 31 Mar 2017 16:52:49 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 860F3A404D; Fri, 31 Mar 2017 17:52:15 +0100 (BST) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C0DBBA4055; Fri, 31 Mar 2017 17:52:14 +0100 (BST) Received: from lombard-w520.ibm.com (unknown [9.167.246.39]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 31 Mar 2017 17:52:14 +0100 (BST) From: Christophe Lombard To: skiboot@lists.ozlabs.org, fbarrat@linux.vnet.ibm.com, imunsie@au1.ibm.com, andrew.donnellan@au1.ibm.com, christophe_lombard@fr.ibm.com Date: Fri, 31 Mar 2017 18:52:39 +0200 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490979160-14535-1-git-send-email-clombard@linux.vnet.ibm.com> References: <1490979160-14535-1-git-send-email-clombard@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17033116-0020-0000-0000-00000336D41A X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17033116-0021-0000-0000-0000410FF9F7 Message-Id: <1490979160-14535-5-git-send-email-clombard@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-03-31_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1702020001 definitions=main-1703310153 Subject: [Skiboot] [PATCH V2 4/5] capi: Load capp microcode X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" CAPP microcode flash download and CAPP upload for PHB4. A new file 'capp.c' is created to receive common capp code for PHB3 and PHB4. Signed-off-by: Christophe Lombard --- core/init.c | 2 +- hw/Makefile.inc | 2 +- hw/capp.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/fsp/fsp.c | 2 + hw/phb3.c | 205 ++++-------------------------------------------- hw/phb4.c | 28 ++++++- include/capp.h | 18 ++++- include/skiboot.h | 3 +- 8 files changed, 288 insertions(+), 201 deletions(-) create mode 100644 hw/capp.c diff --git a/core/init.c b/core/init.c index 6b8137c..9144847 100644 --- a/core/init.c +++ b/core/init.c @@ -935,7 +935,7 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) pci_nvram_init(); phb3_preload_vpd(); - phb3_preload_capp_ucode(); + preload_capp_ucode(); start_preload_kernel(); /* NX init */ diff --git a/hw/Makefile.inc b/hw/Makefile.inc index b0a8b7c..44f0872 100644 --- a/hw/Makefile.inc +++ b/hw/Makefile.inc @@ -6,7 +6,7 @@ HW_OBJS += nx.o nx-rng.o nx-crypto.o nx-842.o HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o prd.o HW_OBJS += dts.o lpc-rtc.o npu.o npu-hw-procedures.o xive.o phb4.o -HW_OBJS += fake-nvram.o lpc-mbox.o npu2.o npu2-hw-procedures.o +HW_OBJS += fake-nvram.o lpc-mbox.o npu2.o npu2-hw-procedures.o capp.o HW=hw/built-in.o # FIXME hack this for now diff --git a/hw/capp.c b/hw/capp.c new file mode 100644 index 0000000..f3b5850 --- /dev/null +++ b/hw/capp.c @@ -0,0 +1,229 @@ +/* Copyright 2013-2017 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include + +#define PHBERR(opal_id, chip_id, index, fmt, a...) \ + prlog(PR_ERR, "PHB#%04x[%d:%d]: " fmt, \ + opal_id, chip_id, \ + index, ## a) + +static struct { + uint32_t ec_level; + struct capp_lid_hdr *lid; + size_t size; + int load_result; +} capp_ucode_info = { 0, NULL, 0, false }; + +#define CAPP_UCODE_MAX_SIZE 0x20000 + +struct lock capi_lock = LOCK_UNLOCKED; + +bool capp_ucode_loaded(struct proc_chip *chip, unsigned int index) +{ + return (chip->capp_ucode_loaded & (1 << index)); +} + +int preload_capp_ucode(void) +{ + struct dt_node *p; + struct proc_chip *chip; + uint32_t index; + uint64_t rc; + int ret; + + p = dt_find_compatible_node(dt_root, NULL, "ibm,power8-pbcq"); + + if (!p) { + p = dt_find_compatible_node(dt_root, NULL, "ibm,power9-pbcq"); + if (!p) { + prlog(PR_INFO, "CAPI: WARNING: no compat thing found\n"); + return OPAL_SUCCESS; + } + } + + chip = get_chip(dt_get_chip_id(p)); + + rc = xscom_read_cfam_chipid(chip->id, &index); + if (rc) { + prerror("CAPP: Error reading cfam chip-id\n"); + ret = OPAL_HARDWARE; + return ret; + } + /* Keep ChipID and Major/Minor EC. Mask out the Location Code. */ + index = index & 0xf0fff; + + /* Assert that we're preloading */ + assert(capp_ucode_info.lid == NULL); + capp_ucode_info.load_result = OPAL_EMPTY; + + capp_ucode_info.ec_level = index; + + /* Is the ucode preloaded like for BML? */ + if (dt_has_node_property(p, "ibm,capp-ucode", NULL)) { + capp_ucode_info.lid = (struct capp_lid_hdr *)(u64) + dt_prop_get_u32(p, "ibm,capp-ucode"); + ret = OPAL_SUCCESS; + goto end; + } + /* If we successfully download the ucode, we leave it around forever */ + capp_ucode_info.size = CAPP_UCODE_MAX_SIZE; + capp_ucode_info.lid = malloc(CAPP_UCODE_MAX_SIZE); + if (!capp_ucode_info.lid) { + prerror("CAPP: Can't allocate space for ucode lid\n"); + ret = OPAL_NO_MEM; + goto end; + } + + prlog(PR_INFO, "CAPI: Preloading ucode %x\n", capp_ucode_info.ec_level); + + ret = start_preload_resource(RESOURCE_ID_CAPP, index, + capp_ucode_info.lid, + &capp_ucode_info.size); + + if (ret != OPAL_SUCCESS) + prerror("CAPI: Failed to preload resource %d\n", ret); + +end: + return ret; +} + +static int64_t capp_lid_download(void) +{ + int64_t ret; + + if (capp_ucode_info.load_result != OPAL_EMPTY) + return capp_ucode_info.load_result; + + capp_ucode_info.load_result = wait_for_resource_loaded( + RESOURCE_ID_CAPP, + capp_ucode_info.ec_level); + + if (capp_ucode_info.load_result != OPAL_SUCCESS) { + prerror("CAPP: Error loading ucode lid. index=%x\n", + capp_ucode_info.ec_level); + ret = OPAL_RESOURCE; + free(capp_ucode_info.lid); + capp_ucode_info.lid = NULL; + goto end; + } + + ret = OPAL_SUCCESS; +end: + return ret; +} + +int64_t capp_load_ucode(unsigned int chip_id, uint32_t opal_id, + unsigned int index, u64 lid_eyecatcher, uint32_t reg_offset, + uint64_t apc_master_addr, uint64_t apc_master_write, + uint64_t snp_array_addr, uint64_t snp_array_write) +{ + struct proc_chip *chip = get_chip(chip_id); + struct capp_ucode_lid *ucode; + struct capp_ucode_data *data; + struct capp_lid_hdr *lid; + uint64_t rc, val, addr; + uint32_t chunk_count, offset; + int i; + + if (capp_ucode_loaded(chip, index)) + return OPAL_SUCCESS; + + rc = capp_lid_download(); + if (rc) + return rc; + + prlog(PR_INFO, "CHIP%i: CAPP ucode lid loaded at %p\n", + chip_id, capp_ucode_info.lid); + + lid = capp_ucode_info.lid; + /* + * If lid header is present (on FSP machines), it'll tell us where to + * find the ucode. Otherwise this is the ucode. + */ + ucode = (struct capp_ucode_lid *)lid; + if (be64_to_cpu(lid->eyecatcher) == lid_eyecatcher) { + if (be64_to_cpu(lid->version) != 0x1) { + PHBERR(opal_id, chip_id, index, + "capi ucode lid header invalid\n"); + return OPAL_HARDWARE; + } + ucode = (struct capp_ucode_lid *) + ((char *)ucode + be64_to_cpu(lid->ucode_offset)); + } + + /* 'CAPPULID' in ASCII */ + if ((be64_to_cpu(ucode->eyecatcher) != 0x43415050554C4944) || + (be64_to_cpu(ucode->version != 1))) { + PHBERR(opal_id, chip_id, index, + "CAPP: ucode header invalid\n"); + return OPAL_HARDWARE; + } + + offset = 0; + while (offset < be64_to_cpu(ucode->data_size)) { + data = (struct capp_ucode_data *) + ((char *)&ucode->data + offset); + chunk_count = be32_to_cpu(data->hdr.chunk_count); + offset += sizeof(struct capp_ucode_data_hdr) + chunk_count * 8; + + /* 'CAPPUCOD' in ASCII */ + if (be64_to_cpu(data->hdr.eyecatcher) != 0x4341505055434F44) { + PHBERR(opal_id, chip_id, index, + "CAPP: ucode data header invalid:%i\n", + offset); + return OPAL_HARDWARE; + } + + switch (data->hdr.reg) { + case apc_master_cresp: + xscom_write(chip_id, apc_master_addr + reg_offset, + 0); + addr = apc_master_write; + break; + case apc_master_uop_table: + xscom_write(chip_id, apc_master_addr + reg_offset, + 0x180ULL << 52); + addr = apc_master_write; + break; + case snp_ttype: + xscom_write(chip_id, snp_array_addr + reg_offset, + 0x5000ULL << 48); + addr = snp_array_write; + break; + case snp_uop_table: + xscom_write(chip_id, snp_array_addr + reg_offset, + 0x4000ULL << 48); + addr = snp_array_write; + break; + default: + continue; + } + + for (i = 0; i < chunk_count; i++) { + val = be64_to_cpu(data->data[i]); + xscom_write(chip_id, addr + reg_offset, val); + } + } + + chip->capp_ucode_loaded |= (1 << index); + + return OPAL_SUCCESS; +} diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c index a0c5a78..4b269de 100644 --- a/hw/fsp/fsp.c +++ b/hw/fsp/fsp.c @@ -2312,6 +2312,7 @@ int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id, #define CAPP_IDX_MURANO_DD20 0x200ef #define CAPP_IDX_MURANO_DD21 0x201ef #define CAPP_IDX_NAPLES_DD10 0x100d3 +#define CAPP_IDX_NIMBUS_DD10 0x100d1 static struct { enum resource_id id; @@ -2325,6 +2326,7 @@ static struct { { RESOURCE_ID_CAPP, CAPP_IDX_VENICE_DD10, 0x80a02003 }, { RESOURCE_ID_CAPP, CAPP_IDX_VENICE_DD20, 0x80a02004 }, { RESOURCE_ID_CAPP, CAPP_IDX_NAPLES_DD10, 0x80a02005 }, + { RESOURCE_ID_CAPP, CAPP_IDX_NIMBUS_DD10, 0x80a02006 }, }; static void fsp_start_fetching_next_lid(void); diff --git a/hw/phb3.c b/hw/phb3.c index 271cd09..a8f5890 100644 --- a/hw/phb3.c +++ b/hw/phb3.c @@ -2438,139 +2438,21 @@ static int64_t phb3_freset(struct pci_slot *slot) return OPAL_HARDWARE; } -struct lock capi_lock = LOCK_UNLOCKED; -static struct { - uint32_t ec_level; - struct capp_lid_hdr *lid; - size_t size; - int load_result; -} capp_ucode_info = { 0, NULL, 0, false }; - -#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; - - if (capp_ucode_info.load_result != OPAL_EMPTY) - return capp_ucode_info.load_result; - - capp_ucode_info.load_result = wait_for_resource_loaded( - RESOURCE_ID_CAPP, - capp_ucode_info.ec_level); - - if (capp_ucode_info.load_result != OPAL_SUCCESS) { - prerror("CAPP: Error loading ucode lid. index=%x\n", - capp_ucode_info.ec_level); - ret = OPAL_RESOURCE; - free(capp_ucode_info.lid); - capp_ucode_info.lid = NULL; - goto end; - } - - ret = OPAL_SUCCESS; -end: - return ret; -} - -static int64_t capp_load_ucode(struct phb3 *p) +static int64_t load_capp_ucode(struct phb3 *p) { - struct proc_chip *chip = get_chip(p->chip_id); - struct capp_ucode_lid *ucode; - struct capp_ucode_data *data; - struct capp_lid_hdr *lid; - uint64_t rc, val, addr; - uint32_t chunk_count, offset, reg_offset; - int i; - - if (CAPP_UCODE_LOADED(chip, p)) - return OPAL_SUCCESS; + int64_t rc; - /* 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; - - prlog(PR_INFO, "CHIP%i: CAPP ucode lid loaded at %p\n", - p->chip_id, capp_ucode_info.lid); - lid = capp_ucode_info.lid; - /* - * If lid header is present (on FSP machines), it'll tell us where to - * find the ucode. Otherwise this is the ucode. - */ - ucode = (struct capp_ucode_lid *)lid; - if (be64_to_cpu(lid->eyecatcher) == 0x434150504c494448) { - if (be64_to_cpu(lid->version) != 0x1) { - PHBERR(p, "capi ucode lid header invalid\n"); - return OPAL_HARDWARE; - } - ucode = (struct capp_ucode_lid *) - ((char *)ucode + be64_to_cpu(lid->ucode_offset)); - } - - if ((be64_to_cpu(ucode->eyecatcher) != 0x43415050554C4944) || - (ucode->version != 1)) { - PHBERR(p, "CAPP: ucode header invalid\n"); - 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 *) - ((char *)&ucode->data + offset); - chunk_count = be32_to_cpu(data->hdr.chunk_count); - offset += sizeof(struct capp_ucode_data_hdr) + chunk_count * 8; - - if (be64_to_cpu(data->hdr.eyecatcher) != 0x4341505055434F44) { - PHBERR(p, "CAPP: ucode data header invalid:%i\n", - offset); - return OPAL_HARDWARE; - } - - switch (data->hdr.reg) { - case apc_master_cresp: - 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 + 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 + 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 + reg_offset, - 0x4000ULL << 48); - addr = CAPP_SNP_ARRAY_WRITE_REG; - break; - default: - continue; - } - - for (i = 0; i < chunk_count; i++) { - val = be64_to_cpu(data->data[i]); - xscom_write(p->chip_id, addr + reg_offset, val); - } - } - - chip->capp_ucode_loaded |= (1 << p->index); - return OPAL_SUCCESS; + /* 0x434150504c494448 = 'CAPPLIDH' in ASCII */ + rc = capp_load_ucode(p->chip_id, p->phb.opal_id, p->index, + 0x434150504c494448, PHB3_CAPP_REG_OFFSET(p), + CAPP_APC_MASTER_ARRAY_ADDR_REG, + CAPP_APC_MASTER_ARRAY_WRITE_REG, + CAPP_SNP_ARRAY_ADDR_REG, + CAPP_SNP_ARRAY_WRITE_REG); + return rc; } static void do_capp_recovery_scoms(struct phb3 *p) @@ -2583,7 +2465,7 @@ static void do_capp_recovery_scoms(struct phb3 *p) offset = PHB3_CAPP_REG_OFFSET(p); /* disable snoops */ xscom_write(p->chip_id, SNOOP_CAPI_CONFIG + offset, 0); - capp_load_ucode(p); + load_capp_ucode(p); /* clear err rpt reg*/ xscom_write(p->chip_id, CAPP_ERR_RPT_CLR + offset, 0); /* clear capp fir */ @@ -3743,7 +3625,7 @@ static int64_t phb3_set_capi_mode(struct phb *phb, uint64_t mode, uint32_t offset; u8 mask; - if (!CAPP_UCODE_LOADED(chip, p)) { + if (!capp_ucode_loaded(chip, p->index)) { PHBERR(p, "CAPP: ucode not loaded\n"); return OPAL_RESOURCE; } @@ -4823,7 +4705,7 @@ static void phb3_create(struct dt_node *np) phb3_init_hw(p, true); /* Load capp microcode into capp unit */ - capp_load_ucode(p); + load_capp_ucode(p); opal_add_host_sync_notifier(phb3_host_sync_reset, p); @@ -5020,67 +4902,6 @@ static void phb3_probe_pbcq(struct dt_node *pbcq) add_chip_dev_associativity(np); } -int phb3_preload_capp_ucode(void) -{ - struct dt_node *p; - struct proc_chip *chip; - uint32_t index; - uint64_t rc; - int ret; - - p = dt_find_compatible_node(dt_root, NULL, "ibm,power8-pbcq"); - - if (!p) { - printf("CAPI: WARNING: no compat thing found\n"); - return OPAL_SUCCESS; - } - - chip = get_chip(dt_get_chip_id(p)); - - rc = xscom_read_cfam_chipid(chip->id, &index); - if (rc) { - prerror("CAPP: Error reading cfam chip-id\n"); - ret = OPAL_HARDWARE; - return ret; - } - /* Keep ChipID and Major/Minor EC. Mask out the Location Code. */ - index = index & 0xf0fff; - - /* Assert that we're preloading */ - assert(capp_ucode_info.lid == NULL); - capp_ucode_info.load_result = OPAL_EMPTY; - - capp_ucode_info.ec_level = index; - - /* Is the ucode preloaded like for BML? */ - if (dt_has_node_property(p, "ibm,capp-ucode", NULL)) { - capp_ucode_info.lid = (struct capp_lid_hdr *)(u64) - dt_prop_get_u32(p, "ibm,capp-ucode"); - ret = OPAL_SUCCESS; - goto end; - } - /* If we successfully download the ucode, we leave it around forever */ - capp_ucode_info.size = CAPP_UCODE_MAX_SIZE; - capp_ucode_info.lid = malloc(CAPP_UCODE_MAX_SIZE); - if (!capp_ucode_info.lid) { - prerror("CAPP: Can't allocate space for ucode lid\n"); - ret = OPAL_NO_MEM; - goto end; - } - - printf("CAPI: Preloading ucode %x\n", capp_ucode_info.ec_level); - - ret = start_preload_resource(RESOURCE_ID_CAPP, index, - capp_ucode_info.lid, - &capp_ucode_info.size); - - if (ret != OPAL_SUCCESS) - prerror("CAPI: Failed to preload resource %d\n", ret); - -end: - return ret; -} - void phb3_preload_vpd(void) { const struct dt_property *prop; diff --git a/hw/phb4.c b/hw/phb4.c index e6f29bc..ab1785b 100644 --- a/hw/phb4.c +++ b/hw/phb4.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1963,7 +1964,22 @@ static int64_t phb4_freset(struct pci_slot *slot) return OPAL_HARDWARE; } -extern struct lock capi_lock; +static int64_t load_capp_ucode(struct phb4 *p) +{ + int64_t rc; + + if (p->index != CAPP0_PHB_INDEX && p->index != CAPP1_PHB_INDEX) + return OPAL_HARDWARE; + + /* 0x4341505050534C4C = 'CAPPPSLL' in ASCII */ + rc = capp_load_ucode(p->chip_id, p->phb.opal_id, p->index, + 0x4341505050534C4C, PHB4_CAPP_REG_OFFSET(p), + CAPP_APC_MASTER_ARRAY_ADDR_REG, + CAPP_APC_MASTER_ARRAY_WRITE_REG, + CAPP_SNP_ARRAY_ADDR_REG, + CAPP_SNP_ARRAY_WRITE_REG); + return rc; +} static void do_capp_recovery_scoms(struct phb4 *p) { @@ -1975,7 +1991,7 @@ static void do_capp_recovery_scoms(struct phb4 *p) offset = PHB4_CAPP_REG_OFFSET(p); /* disable snoops */ xscom_write(p->chip_id, SNOOP_CAPI_CONFIG + offset, 0); - + load_capp_ucode(p); /* clear err rpt reg*/ xscom_write(p->chip_id, CAPP_ERR_RPT_CLR + offset, 0); /* clear capp fir */ @@ -2707,6 +2723,11 @@ static int64_t phb4_set_capi_mode(struct phb *phb, uint64_t mode, uint64_t reg; uint32_t offset; + if (!capp_ucode_loaded(chip, p->index)) { + PHBERR(p, "CAPP: ucode not loaded\n"); + return OPAL_RESOURCE; + } + lock(&capi_lock); chip->capp_phb4_attached_mask |= 1 << p->index; unlock(&capi_lock); @@ -3684,6 +3705,9 @@ static void phb4_create(struct dt_node *np) /* Get the HW up and running */ phb4_init_hw(p, true); + /* Load capp microcode into capp unit */ + load_capp_ucode(p); + /* Register all interrupt sources with XIVE */ xive_register_hw_source(p->base_msi, p->num_irqs - 8, 16, p->int_mmio, XIVE_SRC_SHIFT_BUG, diff --git a/include/capp.h b/include/capp.h index d0c28c9..c1aa8d2 100644 --- a/include/capp.h +++ b/include/capp.h @@ -17,8 +17,12 @@ #ifndef __CAPP_H #define __CAPP_H +/* + * eyecatcher PHB3: 'CAPPLIDH' in ASCII + * eyecatcher PHB4: 'CAPPPSLL' in ASCII + */ struct capp_lid_hdr { - be64 eyecatcher; /* 'CAPPLIDH' in ASCII */ + be64 eyecatcher; be64 version; be64 lid_no; be64 pad; @@ -27,7 +31,7 @@ struct capp_lid_hdr { }; struct capp_ucode_data_hdr { - be64 eyecatcher; /* 'CAPPUCOD' in ASCII */ + be64 eyecatcher; /* 'CAPPUCOD' in ASCII */ u8 version; u8 reg; u8 reserved[2]; @@ -47,7 +51,6 @@ struct capp_ucode_lid { struct capp_ucode_data data; /* This repeats */ }; - enum capp_reg { apc_master_cresp = 0x1, apc_master_uop_table = 0x2, @@ -62,4 +65,13 @@ enum capp_reg { apc_master_powerbus_ctrl = 0xB }; +struct proc_chip; +extern struct lock capi_lock; +extern bool capp_ucode_loaded(struct proc_chip *chip, unsigned int index); + +extern int64_t capp_load_ucode(unsigned int chip_id, uint32_t opal_id, + unsigned int index, u64 lid_eyecatcher, uint32_t reg_offset, + uint64_t apc_master_addr, uint64_t apc_master_write, + uint64_t snp_array_addr, uint64_t snp_array_write); + #endif /* __CAPP_H */ diff --git a/include/skiboot.h b/include/skiboot.h index 8bc767a..76064b2 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -212,9 +212,8 @@ extern void setup_reset_vector(void); extern void probe_p7ioc(void); extern void probe_phb3(void); extern void probe_phb4(void); -extern int phb3_preload_capp_ucode(void); extern void phb3_preload_vpd(void); -extern int phb4_preload_capp_ucode(void); +extern int preload_capp_ucode(void); extern void phb4_preload_vpd(void); extern void probe_npu(void); extern void probe_npu2(void);