From patchwork Thu Apr 19 08:28:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasant Hegde X-Patchwork-Id: 900671 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40RXHR4tbtz9s1P for ; Thu, 19 Apr 2018 18:30:27 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40RXHR3hV1zF26H for ; Thu, 19 Apr 2018 18:30:27 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=hegdevasant@linux.vnet.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 40RXFv0gZJzF24G for ; Thu, 19 Apr 2018 18:29:06 +1000 (AEST) Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3J8S284118386 for ; Thu, 19 Apr 2018 04:29:04 -0400 Received: from e06smtp10.uk.ibm.com (e06smtp10.uk.ibm.com [195.75.94.106]) by mx0a-001b2d01.pphosted.com with ESMTP id 2hennp5e2t-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Thu, 19 Apr 2018 04:29:03 -0400 Received: from localhost by e06smtp10.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 19 Apr 2018 09:29:01 +0100 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp10.uk.ibm.com (192.168.101.140) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 19 Apr 2018 09:28:59 +0100 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3J8SwMM57802978; Thu, 19 Apr 2018 08:28:58 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CD24C11C050; Thu, 19 Apr 2018 09:20:52 +0100 (BST) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8F2A011C04A; Thu, 19 Apr 2018 09:20:51 +0100 (BST) Received: from hegdevasant.in.ibm.com (unknown [9.199.177.27]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTP; Thu, 19 Apr 2018 09:20:51 +0100 (BST) From: Vasant Hegde To: skiboot@lists.ozlabs.org Date: Thu, 19 Apr 2018 13:58:43 +0530 X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180419082844.27941-1-hegdevasant@linux.vnet.ibm.com> References: <20180419082844.27941-1-hegdevasant@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041908-0040-0000-0000-00000430AC03 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041908-0041-0000-0000-00002634C168 Message-Id: <20180419082844.27941-2-hegdevasant@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-19_02:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804190074 Subject: [Skiboot] [PATCH v8 1/2] hdata: Add 'primary' property to master chip xscom node X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.26 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" Needed for SBE communication as some of the SBE MBOX commands has to be sent to SBE on master chip only. Signed-off-by: Vasant Hegde --- hdata/spira.c | 5 ++++- hdata/spira.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hdata/spira.c b/hdata/spira.c index 360b7c776..0176ad61a 100644 --- a/hdata/spira.c +++ b/hdata/spira.c @@ -1,4 +1,4 @@ -/* Copyright 2013-2017 IBM Corp. +/* Copyright 2013-2018 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -578,6 +578,9 @@ static bool add_xscom_sppcrd(uint64_t xscom_base) parse_i2c_devs(hdif, SPPCRD_IDATA_HOST_I2C, np); add_vas_node(np, i); add_ecid_data(hdif, np); + + if (be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASTER_PROC) + dt_add_property(np, "primary", NULL, 0); } /* diff --git a/hdata/spira.h b/hdata/spira.h index d4731946c..ef2aec257 100644 --- a/hdata/spira.h +++ b/hdata/spira.h @@ -1122,6 +1122,7 @@ struct sppcrd_chip_info { #define CHIP_VERIFY_USABLE_FAILURES 1 #define CHIP_VERIFY_NOT_INSTALLED 2 #define CHIP_VERIFY_UNUSABLE 3 +#define CHIP_VERIFY_MASTER_PROC PPC_BIT32(4) __be32 nx_state; __be32 pore_state; __be32 xscom_id; From patchwork Thu Apr 19 08:28:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasant Hegde X-Patchwork-Id: 900672 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40RXHj415jz9s1P for ; Thu, 19 Apr 2018 18:30:41 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40RXHh5rD5zF26J for ; Thu, 19 Apr 2018 18:30:40 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com; envelope-from=hegdevasant@linux.vnet.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com 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 40RXFw5gkyzF24G for ; Thu, 19 Apr 2018 18:29:08 +1000 (AEST) Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3J8ORHl065495 for ; Thu, 19 Apr 2018 04:29:06 -0400 Received: from e06smtp13.uk.ibm.com (e06smtp13.uk.ibm.com [195.75.94.109]) by mx0b-001b2d01.pphosted.com with ESMTP id 2hennjdjjt-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Thu, 19 Apr 2018 04:29:05 -0400 Received: from localhost by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 19 Apr 2018 09:29:04 +0100 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 19 Apr 2018 09:29:01 +0100 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3J8T1d948955640; Thu, 19 Apr 2018 08:29:01 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 60A4011C05B; Thu, 19 Apr 2018 09:20:55 +0100 (BST) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2105211C050; Thu, 19 Apr 2018 09:20:54 +0100 (BST) Received: from hegdevasant.in.ibm.com (unknown [9.199.177.27]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTP; Thu, 19 Apr 2018 09:20:53 +0100 (BST) From: Vasant Hegde To: skiboot@lists.ozlabs.org Date: Thu, 19 Apr 2018 13:58:44 +0530 X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180419082844.27941-1-hegdevasant@linux.vnet.ibm.com> References: <20180419082844.27941-1-hegdevasant@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041908-0012-0000-0000-000005CC88E4 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041908-0013-0000-0000-00001948DF1E Message-Id: <20180419082844.27941-3-hegdevasant@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-19_02:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804190074 Subject: [Skiboot] [PATCH v8 2/2] Add SBE driver support X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.26 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" SBE (Self Boot Engine) on P9 has two different jobs: - Boot the chip up to the point the core is functional - Provide various services like timer, scom, stash MPIPL, etc., at runtime OPAL can communicate to SBE via a set of data and control registers provided by the PSU block in P9 chip. - Four 8 byte registers for Host to send command packets to SBE - Four 8 byte registers for SBE to send response packets to Host - Two doorbell registers (1 on each side) to alert either party when data is placed in above mentioned data register Protocol constraints: Only one command is accepted in the command buffer until the response for the command is enqueued in the response buffer by SBE. Usage: We will use SBE for various purposes like timer, MPIPL, etc. This patch implements the SBE MBOX spec for OPAL to communicate with SBE. Design consideration: - Each chip has SBE. We need to track SBE messages per chip. Hence added per chip sbe structure and list of messages to that chip - SBE accepts only one command at a time. Hence serialized MBOX commands. - OPAL gets interrupted once SBE sets doorbell register - OPAL has to clear doorbell register after reading response - Every command class has timeout option. Timed out messages are discarded - SBE MBOX commands can be classified into four types : - Those that must be sent to the master only (ex: sending MDST/MDDT info) - Those that must be sent to slaves only (ex: continue MPIPL) - Those that must be sent to all chips (ex: close insecure window) - Those that can be sent to any chip (ex: timer) Signed-off-by: Vasant Hegde --- core/init.c | 7 + hw/psi.c | 2 +- hw/sbe-p9.c | 655 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- include/chip.h | 4 + include/sbe-p9.h | 206 ++++++++++++++++- 5 files changed, 853 insertions(+), 21 deletions(-) diff --git a/core/init.c b/core/init.c index b91e34b34..a15530252 100644 --- a/core/init.c +++ b/core/init.c @@ -50,6 +50,7 @@ #include #include #include +#include enum proc_gen proc_gen; unsigned int pcie_max_link_speed; @@ -1027,6 +1028,12 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) */ chiptod_init(); + /* + * SBE uses TB value for scheduling timer. Hence init after + * chiptod init + */ + p9_sbe_init(); + /* Initialize i2c */ p8_i2c_init(); diff --git a/hw/psi.c b/hw/psi.c index 70095a63d..f7d8cd9a4 100644 --- a/hw/psi.c +++ b/hw/psi.c @@ -605,7 +605,7 @@ static void psihb_p9_interrupt(struct irq_source *is, uint32_t isn) printf("PSI: DIO irq received\n"); break; case P9_PSI_IRQ_PSU: - sbe_interrupt(psi->chip_id); + p9_sbe_interrupt(psi->chip_id); break; } } diff --git a/hw/sbe-p9.c b/hw/sbe-p9.c index c9c3febf8..cf77359bc 100644 --- a/hw/sbe-p9.c +++ b/hw/sbe-p9.c @@ -1,4 +1,4 @@ -/* Copyright 2017 IBM Corp. +/* Copyright 2017-2018 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,36 @@ * limitations under the License. */ +/* + * P9 OPAL - SBE communication driver + * + * P9 chip has Self Boot Engine (SBE). OPAL uses SBE for various purpose like + * timer, scom, MPIPL, etc,. Every chip has SBE. OPAL can communicate to SBE + * on all chips. Based on message type it selects appropriate SBE (ex: schedule + * timer on any chip). + * + * OPAL communicates to SBE via a set of data and control registers provided by + * the PSU block in P9 chip. + * - Four 8 byte registers for Host to send command packets to SBE. + * - Four 8 byte registers for SBE to send response packets to Host. + * - Two doorbell registers (1 on each side) to alert either party + * when data is placed in above mentioned data registers. Once Host/SBE reads + * incoming data, it should clear doorbell register. Interrupt is disabled + * as soon as doorbell register is cleared. + * + * OPAL - SBE message format: + * - OPAL communicates to SBE via set of well defined commands. + * - Reg0 contains message header (command class, subclass, flags etc). + * - Reg1-3 contains actual data. If data is big then it uses indirect method + * (data is passed via memory and memory address/size is passed in Reg1-3). + * - Every message has defined timeout. SBE must respond within specified + * time. Otherwise OPAL discards message and sends error message to caller. + * + * Constraints: + * - Only one command is accepted in the command buffer until the response for + * the command is enqueued in the response buffer by SBE. + */ + #define pr_fmt(fmt) "SBE: " fmt #include @@ -23,39 +53,630 @@ #include #include #include -#include #include #include -void sbe_interrupt(uint32_t chip_id) +enum p9_sbe_mbox_state { + sbe_mbox_idle = 0, /* Ready to send message */ + sbe_mbox_send, /* Message sent, waiting for ack/response */ + sbe_mbox_rr, /* SBE in R/R */ +}; + +struct p9_sbe { + /* Chip ID to send message */ + u32 chip_id; + + /* List to hold SBE queue messages */ + struct list_head msg_list; + + struct lock lock; + + enum p9_sbe_mbox_state state; + + /* SBE MBOX message sequence number */ + u16 cur_seq; +}; + +/* Default SBE chip ID */ +static int sbe_default_chip_id = -1; + +#define SBE_STATUS_PRI_SHIFT 0x30 +#define SBE_STATUS_SEC_SHIFT 0x20 + +/* Forward declaration */ +static void p9_sbe_timeout_poll_one(struct p9_sbe *sbe); + +/* bit 0-15 : Primary status code */ +static inline u16 p9_sbe_get_primary_rc(struct p9_sbe_msg *resp) +{ + return (resp->reg[0] >> SBE_STATUS_PRI_SHIFT); +} + +static inline void p9_sbe_set_primary_rc(struct p9_sbe_msg *resp, u64 rc) +{ + resp->reg[0] |= (rc << SBE_STATUS_PRI_SHIFT); +} + +static u64 p9_sbe_rreg(u32 chip_id, u64 reg) { + u64 data = 0; int rc; - u64 data; + + rc = xscom_read(chip_id, reg, &data); + if (rc != OPAL_SUCCESS) { + prlog(PR_DEBUG, "XSCOM error %d reading reg 0x%llx\n", rc, reg); + return 0xffffffff; + } + + return be64_to_cpu(data); +} + +static void p9_sbe_reg_dump(u32 chip_id) +{ +#define SBE_DUMP_REG_ONE(chip_id, x) \ + prlog(PR_DEBUG, " %20s: %016llx\n", #x, p9_sbe_rreg(chip_id, x)) + + prlog(PR_DEBUG, "MBOX register dump for chip : %x\n", chip_id); + SBE_DUMP_REG_ONE(chip_id, PSU_SBE_DOORBELL_REG_RW); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG0); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG1); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG2); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG3); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_DOORBELL_REG_RW); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG4); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG5); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG6); + SBE_DUMP_REG_ONE(chip_id, PSU_HOST_SBE_MBOX_REG7); +} + +void p9_sbe_freemsg(struct p9_sbe_msg *msg) +{ + if (msg && msg->resp) + free(msg->resp); + free(msg); +} + +static void p9_sbe_fillmsg(struct p9_sbe_msg *msg, u16 cmd, + u16 ctrl_flag, u64 reg1, u64 reg2, u64 reg3) +{ + bool response = !!(ctrl_flag & SBE_CMD_CTRL_RESP_REQ); + u16 flag; + + /* + * Always set ack required flag. SBE will interrupt OPAL once it read + * message from mailbox register. If OPAL is expecting response, then + * it will update message timeout, otherwise it will send next message. + */ + flag = ctrl_flag | SBE_CMD_CTRL_ACK_REQ; + + /* Seqence ID is filled by p9_sbe_queue_msg() */ + msg->reg[0] = ((u64)flag << 32) | cmd; + msg->reg[1] = reg1; + msg->reg[2] = reg2; + msg->reg[3] = reg3; + msg->state = sbe_msg_unused; + msg->response = response; +} + +static struct p9_sbe_msg *p9_sbe_allocmsg(bool alloc_resp) +{ + struct p9_sbe_msg *msg; + + msg = zalloc(sizeof(struct p9_sbe_msg)); + if (!msg) { + prlog(PR_ERR, "Failed to allocate SBE message\n"); + return NULL; + } + if (alloc_resp) { + msg->resp = zalloc(sizeof(struct p9_sbe_msg)); + if (!msg->resp) { + prlog(PR_ERR, "Failed to allocate SBE resp message\n"); + free(msg); + return NULL; + } + } + + return msg; +} + +/* + * Handles "command with direct data" format only. + * + * Note: All mbox messages of our interest uses direct data format. If we need + * indirect data format then we may have to enhance this function. + */ +struct p9_sbe_msg *p9_sbe_mkmsg(u16 cmd, u16 ctrl_flag, + u64 reg1, u64 reg2, u64 reg3) +{ + struct p9_sbe_msg *msg; + + msg = p9_sbe_allocmsg(!!(ctrl_flag & SBE_CMD_CTRL_RESP_REQ)); + if (!msg) + return NULL; + + p9_sbe_fillmsg(msg, cmd, ctrl_flag, reg1, reg2, reg3); + return msg; +} + +static inline bool p9_sbe_mbox_busy(struct p9_sbe *sbe) +{ + return (sbe->state != sbe_mbox_idle); +} + +static inline bool p9_sbe_msg_busy(struct p9_sbe_msg *msg) +{ + switch (msg->state) { + case sbe_msg_queued: + /* fall through */ + case sbe_msg_sent: + case sbe_msg_wresp: + return true; + default: /* + sbe_msg_unused, sbe_msg_done, + sbe_msg_timeout, sbe_msg_error */ + break; + } + return false; +} + +static inline struct p9_sbe *p9_sbe_get_sbe(u32 chip_id) +{ struct proc_chip *chip; - chip = get_chip(chip_id); - if (chip == NULL) + /* Default to SBE on master chip */ + if (chip_id == -1) { + if (sbe_default_chip_id == -1) + return NULL; + + chip = get_chip(sbe_default_chip_id); + } else { + chip = get_chip(chip_id); + } + if (chip == NULL || chip->sbe == NULL) + return NULL; + + return chip->sbe; +} + +static int p9_sbe_msg_send(struct p9_sbe *sbe, struct p9_sbe_msg *msg) +{ + int rc, i; + u64 addr, *data; + + addr = PSU_HOST_SBE_MBOX_REG0; + data = &msg->reg[0]; + + for (i = 0; i < NR_HOST_SBE_MBOX_REG; i++) { + rc = xscom_write(sbe->chip_id, addr, *data); + if (rc) + return rc; + + addr++; + data++; + } + + rc = xscom_write(sbe->chip_id, PSU_SBE_DOORBELL_REG_OR, + HOST_SBE_MSG_WAITING); + if (rc != OPAL_SUCCESS) + return rc; + + prlog(PR_TRACE, "Message queued [chip id = 0x%x]:\n\t Reg0 : %016llx" + "\n\t Reg1 : %016llx\n\t Reg2 : %016llx\n\t Reg3 : %016llx\n", + sbe->chip_id, msg->reg[0], msg->reg[1], msg->reg[2], msg->reg[3]); + + msg->timeout = mftb() + msecs_to_tb(SBE_CMD_TIMEOUT_MAX); + sbe->state = sbe_mbox_send; + msg->state = sbe_msg_sent; + return rc; +} + +static int p9_sbe_msg_receive(u32 chip_id, struct p9_sbe_msg *resp) +{ + int i; + int rc = OPAL_SUCCESS; + u64 addr, *data; + + addr = PSU_HOST_SBE_MBOX_REG4; + data = &resp->reg[0]; + + for (i = 0; i < NR_HOST_SBE_MBOX_REG; i++) { + rc = xscom_read(chip_id, addr, data); + if (rc) + return rc; + + addr++; + data++; + } + return rc; +} + +/* WARNING: This will drop sbe->lock */ +static void p9_sbe_msg_complete(struct p9_sbe *sbe, struct p9_sbe_msg *msg, + enum p9_sbe_msg_state msg_state) +{ + void (*comp)(struct p9_sbe_msg *msg); + + prlog(PR_TRACE, "Completing msg [chip id = %x], reg0 : 0x%llx\n", + sbe->chip_id, msg->reg[0]); + + comp = msg->complete; + list_del(&msg->link); + sync(); + msg->state = msg_state; + + if (comp) { + unlock(&sbe->lock); + comp(msg); + lock(&sbe->lock); + } +} + +/* WARNING: This will drop sbe->lock */ +static void p9_sbe_send_complete(struct p9_sbe *sbe) +{ + struct p9_sbe_msg *msg; + + if (list_empty(&sbe->msg_list)) + return; + + msg = list_top(&sbe->msg_list, struct p9_sbe_msg, link); + /* Need response */ + if (msg->response) { + msg->state = sbe_msg_wresp; + } else { + sbe->state = sbe_mbox_idle; + p9_sbe_msg_complete(sbe, msg, sbe_msg_done); + } +} + +/* WARNING: This will drop sbe->lock */ +static void p9_sbe_process_queue(struct p9_sbe *sbe) +{ + int rc, retry_cnt = 0; + struct p9_sbe_msg *msg = NULL; + + if (p9_sbe_mbox_busy(sbe)) + return; + + while (!list_empty(&sbe->msg_list)) { + msg = list_top(&sbe->msg_list, struct p9_sbe_msg, link); + /* Send message */ + rc = p9_sbe_msg_send(sbe, msg); + if (rc == OPAL_SUCCESS) + return; + + prlog(PR_ERR, "Failed to send message to SBE [chip id = %x]\n", + sbe->chip_id); + if (msg->resp) { + p9_sbe_set_primary_rc(msg->resp, + SBE_STATUS_PRI_GENERIC_ERR); + } + p9_sbe_msg_complete(sbe, msg, sbe_msg_error); + + /* + * Repeatedly failed to send message to SBE. Lets stop + * sending message. + */ + if (retry_cnt++ >= 3) { + prlog(PR_ERR, "Temporarily stopped sending " + "message to SBE\n"); + return; + } + } +} + +/* + * WARNING: + * Only one command is accepted in the command buffer until response + * to the command is enqueued in the response buffer by SBE. + * + * Head of msg_list contains in-flight message. Hence we should always + * add new message to tail of the list. + */ +int p9_sbe_queue_msg(u32 chip_id, struct p9_sbe_msg *msg, + void (*comp)(struct p9_sbe_msg *msg)) +{ + struct p9_sbe *sbe; + + if (!msg) + return OPAL_PARAMETER; + + sbe = p9_sbe_get_sbe(chip_id); + if (!sbe) + return OPAL_HARDWARE; + + lock(&sbe->lock); + /* Set completion and update sequence number */ + msg->complete = comp; + msg->state = sbe_msg_queued; + msg->reg[0] = msg->reg[0] | ((u64)sbe->cur_seq << 16); + sbe->cur_seq++; + + /* Reset sequence number */ + if (sbe->cur_seq == 0xffff) + sbe->cur_seq = 1; + + /* Add message to queue */ + list_add_tail(&sbe->msg_list, &msg->link); + p9_sbe_process_queue(sbe); + unlock(&sbe->lock); + + return OPAL_SUCCESS; +} + +int p9_sbe_sync_msg(u32 chip_id, struct p9_sbe_msg *msg, bool autofree) +{ + int rc; + struct p9_sbe *sbe; + + rc = p9_sbe_queue_msg(chip_id, msg, NULL); + if (rc) + goto free_msg; + + sbe = p9_sbe_get_sbe(chip_id); + if (!sbe) { + rc = OPAL_HARDWARE; + goto free_msg; + } + + while (p9_sbe_msg_busy(msg)) { + cpu_relax(); + p9_sbe_timeout_poll_one(sbe); + } + + if (msg->state == sbe_msg_done) + rc = SBE_STATUS_PRI_SUCCESS; + else + rc = SBE_STATUS_PRI_GENERIC_ERR; + + if (msg->response && msg->resp) + rc = p9_sbe_get_primary_rc(msg->resp); + +free_msg: + if (autofree) + p9_sbe_freemsg(msg); + + return rc; +} + +/* Remove SBE message from queue. It will not remove inflight message */ +int p9_sbe_cancelmsg(u32 chip_id, struct p9_sbe_msg *msg) +{ + struct p9_sbe *sbe; + + sbe = p9_sbe_get_sbe(chip_id); + if (!sbe) + return OPAL_PARAMETER; + + lock(&sbe->lock); + if (msg->state != sbe_msg_queued) { + unlock(&sbe->lock); + return OPAL_BUSY; + } + + list_del(&msg->link); + msg->state = sbe_msg_done; + unlock(&sbe->lock); + return OPAL_SUCCESS; +} + +static void p9_sbe_handle_response(u32 chip_id, struct p9_sbe_msg *msg) +{ + u16 send_seq, resp_seq; + int rc; + + if (msg == NULL || msg->resp == NULL) + return; + + memset(msg->resp, 0, sizeof(struct p9_sbe_msg)); + + rc = p9_sbe_msg_receive(chip_id, msg->resp); + if (rc != OPAL_SUCCESS) { + prlog(PR_ERR, "Failed to read response message " + "[chip id = %x]\n", chip_id); + p9_sbe_set_primary_rc(msg->resp, SBE_STATUS_PRI_GENERIC_ERR); + return; + } + + /* Validate sequence number */ + send_seq = (msg->reg[0] >> 16) & 0xffff; + resp_seq = (msg->resp->reg[0] >> 16) & 0xffff; + if (send_seq != resp_seq) { + /* + * XXX Handle SBE R/R. + * Lets send sequence error to caller until SBE reset works. + */ + prlog(PR_ERR, "Invalid sequence id [chip id = %x]\n", chip_id); + p9_sbe_set_primary_rc(msg->resp, SBE_STATUS_PRI_SEQ_ERR); return; + } +} + +static void __p9_sbe_interrupt(struct p9_sbe *sbe) +{ + bool has_response = false; + int rc; + u64 data = 0, val; + struct p9_sbe_msg *msg = NULL; /* Read doorbell register */ - rc = xscom_read(chip_id, PSU_HOST_DOORBELL_REG_RW, &data); + rc = xscom_read(sbe->chip_id, PSU_HOST_DOORBELL_REG_RW, &data); if (rc) { prlog(PR_ERR, "Failed to read SBE to Host doorbell register " - "[chip id = %x]\n", chip_id); - goto clr_interrupt; + "[chip id = %x]\n", sbe->chip_id); + p9_sbe_reg_dump(sbe->chip_id); + return; } - /* SBE passtrhough command, call prd handler */ - if (data & SBE_HOST_PASSTHROUGH) { - prd_sbe_passthrough(chip_id); + /* Called from poller path, nothing to process */ + if (!data) + return; + + /* Read SBE response before clearing doorbell register */ + if (data & SBE_HOST_RESPONSE_WAITING) { + if (!list_empty(&sbe->msg_list)) { + msg = list_top(&sbe->msg_list, struct p9_sbe_msg, link); + p9_sbe_handle_response(sbe->chip_id, msg); + has_response = true; + } } -clr_interrupt: - /* Clears all the bits */ - rc = xscom_write(chip_id, PSU_HOST_DOORBELL_REG_AND, - SBE_HOST_RESPONSE_CLEAR); + /* Clear doorbell register */ + val = SBE_HOST_RESPONSE_MASK & ~data; + rc = xscom_write(sbe->chip_id, PSU_HOST_DOORBELL_REG_AND, val); if (rc) { prlog(PR_ERR, "Failed to clear SBE to Host doorbell " - "register [chip id = %x]\n", chip_id); + "interrupt [chip id = %x]\n", sbe->chip_id); + return; + } + + /* SBE came back from reset */ + if (data & SBE_HOST_RESET) { + prlog(PR_NOTICE, "Back from reset [chip id = %x]\n", sbe->chip_id); + /* Reset SBE MBOX state */ + sbe->state = sbe_mbox_idle; + + /* Reset message state */ + if (!list_empty(&sbe->msg_list)) { + msg = list_top(&sbe->msg_list, struct p9_sbe_msg, link); + msg->state = sbe_msg_queued; + } + goto next_msg; + } + + /* SBE passthrough command, call prd handler */ + if (data & SBE_HOST_PASSTHROUGH) { + prd_sbe_passthrough(sbe->chip_id); + } + + /* Process ACK message before response */ + if (data & SBE_HOST_MSG_READ) { + p9_sbe_send_complete(sbe); } + + /* Got response */ + if (has_response) { + /* Reset SBE MBOX state */ + sbe->state = sbe_mbox_idle; + p9_sbe_msg_complete(sbe, msg, sbe_msg_done); + } + +next_msg: + p9_sbe_process_queue(sbe); +} + +void p9_sbe_interrupt(uint32_t chip_id) +{ + struct proc_chip *chip; + struct p9_sbe *sbe; + + chip = get_chip(chip_id); + if (chip == NULL || chip->sbe == NULL) + return; + + sbe = chip->sbe; + lock(&sbe->lock); + __p9_sbe_interrupt(sbe); + unlock(&sbe->lock); +} + +static void p9_sbe_timeout_poll_one(struct p9_sbe *sbe) +{ + struct p9_sbe_msg *msg; + + if (list_empty_nocheck(&sbe->msg_list)) + return; + + lock(&sbe->lock); + + /* + * In some cases there will be a delay in calling OPAL interrupt + * handler routine (opal_handle_interrupt). In such cases its + * possible that SBE has responded, but OPAL didn't act on that. + * Hence check for SBE response. + */ + __p9_sbe_interrupt(sbe); + + if (list_empty(&sbe->msg_list)) + goto out; + + /* + * For some reason OPAL didn't sent message to SBE. + * Lets try to send message again. + */ + if (!p9_sbe_mbox_busy(sbe)) { + p9_sbe_process_queue(sbe); + goto out; + } + + msg = list_top(&sbe->msg_list, struct p9_sbe_msg, link); + if (tb_compare(mftb(), msg->timeout) != TB_AAFTERB) + goto out; + + /* Message timeout */ + prlog(PR_ERR, "Message timeout [chip id = %x], cmd = %llx, " + "subcmd = %llx\n", sbe->chip_id, + (msg->reg[0] >> 8) & 0xff, msg->reg[0] & 0xff); + p9_sbe_reg_dump(sbe->chip_id); + if (msg->resp) { + p9_sbe_set_primary_rc(msg->resp, + SBE_STATUS_PRI_GENERIC_ERR); + } + + /* XXX Handle SBE R/R. Reset SBE state until SBE R/R works. */ + sbe->state = sbe_mbox_idle; + p9_sbe_msg_complete(sbe, msg, sbe_msg_timeout); + p9_sbe_process_queue(sbe); + +out: + unlock(&sbe->lock); +} + +static void p9_sbe_timeout_poll(void *user_data __unused) +{ + struct p9_sbe *sbe; + struct proc_chip *chip; + + for_each_chip(chip) { + if (chip->sbe == NULL) + continue; + sbe = chip->sbe; + p9_sbe_timeout_poll_one(sbe); + } +} + +void p9_sbe_init(void) +{ + struct dt_node *xn; + struct proc_chip *chip; + struct p9_sbe *sbe; + + if (proc_gen < proc_gen_p9) + return; + + dt_for_each_compatible(dt_root, xn, "ibm,xscom") { + sbe = zalloc(sizeof(struct p9_sbe)); + assert(sbe); + sbe->chip_id = dt_get_chip_id(xn); + sbe->cur_seq = 1; + sbe->state = sbe_mbox_idle; + list_head_init(&sbe->msg_list); + init_lock(&sbe->lock); + + chip = get_chip(sbe->chip_id); + assert(chip); + chip->sbe = sbe; + + if (dt_has_node_property(xn, "primary", NULL)) { + sbe_default_chip_id = sbe->chip_id; + prlog(PR_DEBUG, "Master chip id : %x\n", sbe->chip_id); + } + } + + if (sbe_default_chip_id == -1) { + prlog(PR_ERR, "Master chip ID not found.\n"); + return; + } + + /* Initiate SBE timeout poller */ + opal_add_poller(p9_sbe_timeout_poll, NULL); } diff --git a/include/chip.h b/include/chip.h index 43b5ea55b..059033e27 100644 --- a/include/chip.h +++ b/include/chip.h @@ -113,6 +113,7 @@ struct mfsi; struct xive; struct lpcm; struct vas; +struct p9_sbe; /* Chip type */ enum proc_chip_type { @@ -218,6 +219,9 @@ struct proc_chip { /* location code of this chip */ const uint8_t *loc_code; + + /* Used by hw/sbe-p9.c */ + struct p9_sbe *sbe; }; extern uint32_t pir_to_chip_id(uint32_t pir); diff --git a/include/sbe-p9.h b/include/sbe-p9.h index cca210024..329afff80 100644 --- a/include/sbe-p9.h +++ b/include/sbe-p9.h @@ -1,4 +1,4 @@ -/* Copyright 2017 IBM Corp. +/* Copyright 2017-2018 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,14 +21,214 @@ #include #include +/* Worst case command timeout value (90 sec) */ +#define SBE_CMD_TIMEOUT_MAX (90 * 1000) + +/* Primary response status code */ +#define SBE_STATUS_PRI_SUCCESS 0x00 +#define SBE_STATUS_PRI_INVALID_CMD 0x01 +#define SBE_STATUS_PRI_INVALID_DATA 0x02 +#define SBE_STATUS_PRI_SEQ_ERR 0x03 +#define SBE_STATUS_PRI_INTERNAL_ERR 0x04 +#define SBE_STATUS_PRI_UNSECURE_ACCESS 0x05 +#define SBE_STATUS_PRI_GENERIC_ERR 0xFE + +/* Secondary response status code */ +#define SBE_STATUS_SEC_SUCCESS 0x00 +#define SBE_STATUS_SEC_CMD_CLASS_UNSUPPORTED 0x01 +#define SBE_STATUS_SEC_CMD_UNSUPPORTED 0x02 +#define SBE_STATUS_SEC_INV_ADDR 0x03 +#define SBE_STATUS_SEC_INV_TARGET_TYPE 0x04 +#define SBE_STATUS_SEC_INV_CHIPLET_ID 0x05 +#define SBE_STATUS_SEC_TARGET_NOT_PRESENT 0x06 +#define SBE_STATUS_SEC_TARGET_NOT_FUNC 0x07 +#define SBE_STATUS_SEC_CMD_NOT_ALLOW 0x08 +#define SBE_STATUS_SEC_FUNC_NOT_SUPPORTED 0x09 +#define SBE_STATUS_SEC_GENERIC_ERR 0x0A +#define SBE_STATUS_SEC_BLACKLIST_REG 0x0B +#define SBE_STATUS_SEC_OS_FAILURE 0x0C +#define SBE_STATUS_SEC_MBX_REG_FAILURE 0x0D +#define SBE_STATUS_SEC_INSUFFICIENT_DATA 0x0E +#define SBE_STATUS_SEC_EXCESS_DATA 0x0F +#define SBE_STATUS_SEC_HW_TIMEOUT 0x10 +#define SBE_STATUS_SEC_PCBPIB_ERR 0x11 +#define SBE_STATUS_SEC_FIFO_PARITY_ERR 0x12 +#define SBE_STATUS_SEC_TIMER_EXPIRED 0x13 +#define SBE_STATUS_SEC_BLACKLISTED_MEM 0x14 +#define SBE_STATUS_SEC_UNSEC_REGION_NOT_FOUND 0x15 +#define SBE_STATUS_SEC_UNSEC_REGION_EXCEEDED 0x16 +#define SBE_STATUS_SEC_UNSEC_REGION_AMEND 0x17 +#define SBE_STATUS_SEC_INPUT_BUF_OVERFLOW 0x18 +#define SBE_STATUS_SEC_INVALID_PARAMS 0x19 +#define SBE_STATUS_SEC_BLACKLISTED_CMD 0x20 + +/* Number of MBOX register on each side */ +#define NR_HOST_SBE_MBOX_REG 0x04 + +/* + * SBE MBOX register address + * Reg 0 - 3 : Host to send command packets to SBE + * Reg 4 - 7 : SBE to send response packets to Host + */ +#define PSU_HOST_SBE_MBOX_REG0 0x000D0050 +#define PSU_HOST_SBE_MBOX_REG1 0x000D0051 +#define PSU_HOST_SBE_MBOX_REG2 0x000D0052 +#define PSU_HOST_SBE_MBOX_REG3 0x000D0053 +#define PSU_HOST_SBE_MBOX_REG4 0x000D0054 +#define PSU_HOST_SBE_MBOX_REG5 0x000D0055 +#define PSU_HOST_SBE_MBOX_REG6 0x000D0056 +#define PSU_HOST_SBE_MBOX_REG7 0x000D0057 +#define PSU_SBE_DOORBELL_REG_RW 0x000D0060 +#define PSU_SBE_DOORBELL_REG_AND 0x000D0061 +#define PSU_SBE_DOORBELL_REG_OR 0x000D0062 #define PSU_HOST_DOORBELL_REG_RW 0x000D0063 #define PSU_HOST_DOORBELL_REG_AND 0x000D0064 #define PSU_HOST_DOORBELL_REG_OR 0x000D0065 +/* + * Doorbell register to trigger SBE interrupt. Set by OPAL to inform + * the SBE about a waiting message in the Host/SBE mailbox registers + */ +#define HOST_SBE_MSG_WAITING PPC_BIT(0) + +/* + * Doorbell register for host bridge interrupt. Set by the SBE to inform + * host about a response message in the Host/SBE mailbox registers + */ +#define SBE_HOST_RESPONSE_WAITING PPC_BIT(0) +#define SBE_HOST_MSG_READ PPC_BIT(1) +#define SBE_HOST_STOP15_EXIT PPC_BIT(2) +#define SBE_HOST_RESET PPC_BIT(3) #define SBE_HOST_PASSTHROUGH PPC_BIT(4) -#define SBE_HOST_RESPONSE_CLEAR 0x00 +#define SBE_HOST_TIMER_EXPIRY PPC_BIT(14) +#define SBE_HOST_RESPONSE_MASK (PPC_BITMASK(0, 4) | SBE_HOST_TIMER_EXPIRY) + +/* SBE Target Type */ +#define SBE_TARGET_TYPE_PROC 0x00 +#define SBE_TARGET_TYPE_EX 0x01 +#define SBE_TARGET_TYPE_PERV 0x02 +#define SBE_TARGET_TYPE_MCS 0x03 +#define SBE_TARGET_TYPE_EQ 0x04 +#define SBE_TARGET_TYPE_CORE 0x05 + +/* SBE MBOX command class */ +#define SBE_MCLASS_FIRST 0xD1 +#define SBE_MCLASS_CORE_STATE 0xD1 +#define SBE_MCLASS_SCOM 0xD2 +#define SBE_MCLASS_RING 0xD3 +#define SBE_MCLASS_TIMER 0xD4 +#define SBE_MCLASS_MPIPL 0xD5 +#define SBE_MCLASS_SECURITY 0xD6 +#define SBE_MCLASS_GENERIC 0xD7 +#define SBE_MCLASS_LAST 0xD7 + +/* + * Commands are provided in xxyy form where: + * - xx : command class + * - yy : command + * + * Both request and response message uses same seq ID, + * command class and command. + */ +#define SBE_CMD_CTRL_DEADMAN_LOOP 0xD101 +#define SBE_CMD_MULTI_SCOM 0xD201 +#define SBE_CMD_PUT_RING_FORM_IMAGE 0xD301 +#define SBE_CMD_CONTROL_TIMER 0xD401 +#define SBE_CMD_GET_ARCHITECTED_REG 0xD501 +#define SBE_CMD_CLR_ARCHITECTED_REG 0xD502 +#define SBE_CMD_SET_UNSEC_MEM_WINDOW 0xD601 +#define SBE_CMD_GET_SBE_FFDC 0xD701 +#define SBE_CMD_GET_CAPABILITY 0xD702 +#define SBE_CMD_READ_SBE_SEEPROM 0xD703 +#define SBE_CMD_SET_FFDC_ADDR 0xD704 +#define SBE_CMD_QUIESCE_SBE 0xD705 +#define SBE_CMD_SET_FABRIC_ID_MAP 0xD706 +#define SBE_CMD_STASH_MPIPL_CONFIG 0xD707 + +/* SBE MBOX control flags */ + +/* Generic flags */ +#define SBE_CMD_CTRL_RESP_REQ 0x0100 +#define SBE_CMD_CTRL_ACK_REQ 0x0200 + +/* Deadman loop */ +#define CTRL_DEADMAN_LOOP_START 0x0001 +#define CTRL_DEADMAN_LOOP_STOP 0x0002 + +/* Control timer */ +#define CONTROL_TIMER_START 0x0001 +#define CONTROL_TIMER_STOP 0x0002 + +/* SBE message state */ +enum p9_sbe_msg_state { + sbe_msg_unused = 0, /* Free */ + sbe_msg_queued, /* Queued to SBE list */ + sbe_msg_sent, /* Sent to SBE */ + sbe_msg_wresp, /* Waiting for response */ + sbe_msg_done, /* Complete */ + sbe_msg_timeout, /* Message timeout */ + sbe_msg_error, /* Failed to send message to SBE */ +}; + +/* SBE message */ +struct p9_sbe_msg { + /* + * Reg[0] : + * word0 : + * direct cmd : reserved << 16 | ctrl flag + * indirect cmd: mem_addr_size_dword + * response : primary status << 16 | secondary status + * + * word1 : seq id << 16 | cmd class << 8 | cmd + * + * WARNING: + * - Don't populate reg[0].seq (byte 4,5). This will be populated by + * p9_sbe_queue_msg(). + */ + u64 reg[4]; + + /* cmd timout : mftb() + msecs_to_tb(SBE_CMD_TIMEOUT_MAX) */ + u64 timeout; + + /* Completion function */ + void (*complete)(struct p9_sbe_msg *msg); + void *user_data; + + /* Current msg state */ + enum p9_sbe_msg_state state; + + /* Set if the message expects a response */ + bool response; + + /* Response will be filled by driver when response received */ + struct p9_sbe_msg *resp; + + /* Internal queuing */ + struct list_node link; +} __packed; + + +/* Allocate and populate p9_sbe_msg structure */ +extern struct p9_sbe_msg *p9_sbe_mkmsg(u16 cmd, u16 ctrl_flag, u64 reg1, + u64 reg2, u64 reg3) __warn_unused_result; + +/* Free p9_sbe_msg structure */ +extern void p9_sbe_freemsg(struct p9_sbe_msg *msg); + +/* Add new message to sbe queue */ +extern int p9_sbe_queue_msg(uint32_t chip_id, struct p9_sbe_msg *msg, + void (*comp)(struct p9_sbe_msg *msg)) __warn_unused_result; + +/* Synchronously send message to SBE */ +extern int p9_sbe_sync_msg(u32 chip_id, struct p9_sbe_msg *msg, bool autofree); + +/* Remove message from SBE queue, it will not remove inflight message */ +extern int p9_sbe_cancelmsg(u32 chip_id, struct p9_sbe_msg *msg); + +/* Initialize the SBE mailbox driver */ +extern void p9_sbe_init(void); /* SBE interrupt */ -extern void sbe_interrupt(uint32_t chip_id); +extern void p9_sbe_interrupt(uint32_t chip_id); #endif /* __SBE_P9_H */