From nobody Sat Apr 11 06:37:37 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF09AC32757 for ; Mon, 15 Aug 2022 19:33:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245254AbiHOTdh (ORCPT ); Mon, 15 Aug 2022 15:33:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55582 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344928AbiHOT13 (ORCPT ); Mon, 15 Aug 2022 15:27:29 -0400 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B59E5B78F; Mon, 15 Aug 2022 11:43:19 -0700 (PDT) Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27FI55v3026647; Mon, 15 Aug 2022 18:43:11 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=3QYVAqVw8SxZs5e2sW8RYQ/entVpPqjtUdvzI4O67Sg=; b=JfnsY0FIVgyLpxrJnqZF3nsV8aDV6lQEu3S47AbL6EK71FZDaTsA0FPT/cLfqmN7+aAt /nxoUCyWysDd2/RGKbnwjyq0dvUQWfKT6zp43/FD/sXTgmiv9JO7KmsVuc2oCbkO414i uzpZVFmwHqBBZwTdCtVF1EdEPXOC4GHit+YRBcyxRihplLiKba++34RP8luIzU59FDad fHXu5lwKUdrb5MTEVx32GPe3/N3VMhSkOQ6pLJQLJZeeIHpe26d+5ayqoovYg47sTAvp c1ZwGjN5uh71eohtAnIh+45bzFQw+ahyh5je/J6nY6vu4kkRp/q9OzQlf2tLhFHrY+x2 Ig== Received: from nalasppmta02.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3hx420p408-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 15 Aug 2022 18:43:10 +0000 Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA02.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 27FIh90c031946 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 15 Aug 2022 18:43:09 GMT Received: from jhugo-lnx.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.22; Mon, 15 Aug 2022 11:43:08 -0700 From: Jeffrey Hugo To: , , , , CC: , , , , , , Jeffrey Hugo Subject: [RFC PATCH 04/14] drm/qaic: Add MHI controller Date: Mon, 15 Aug 2022 12:42:26 -0600 Message-ID: <1660588956-24027-5-git-send-email-quic_jhugo@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1660588956-24027-1-git-send-email-quic_jhugo@quicinc.com> References: <1660588956-24027-1-git-send-email-quic_jhugo@quicinc.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: ARpUWzlXLSxCd8ZW-dQlpFW97L52h5ey X-Proofpoint-ORIG-GUID: ARpUWzlXLSxCd8ZW-dQlpFW97L52h5ey X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-15_08,2022-08-15_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 bulkscore=0 clxscore=1015 lowpriorityscore=0 mlxlogscore=999 impostorscore=0 adultscore=0 mlxscore=0 spamscore=0 priorityscore=1501 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2208150070 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" A QAIC device contains a MHI interface with a number of different channels for controlling different aspects of the device. The MHI controller works with the MHI bus to enable and drive that interface. Change-Id: I77363193b1a2dece7abab287a6acef3cac1b4e1b Signed-off-by: Jeffrey Hugo --- drivers/gpu/drm/qaic/mhi_controller.c | 575 ++++++++++++++++++++++++++++++= ++++ drivers/gpu/drm/qaic/mhi_controller.h | 18 ++ 2 files changed, 593 insertions(+) create mode 100644 drivers/gpu/drm/qaic/mhi_controller.c create mode 100644 drivers/gpu/drm/qaic/mhi_controller.h diff --git a/drivers/gpu/drm/qaic/mhi_controller.c b/drivers/gpu/drm/qaic/m= hi_controller.c new file mode 100644 index 0000000..e88e0fe --- /dev/null +++ b/drivers/gpu/drm/qaic/mhi_controller.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights res= erved. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mhi_controller.h" +#include "qaic.h" + +#define MAX_RESET_TIME_SEC 25 + +static unsigned int mhi_timeout =3D 2000; /* 2 sec default */ +module_param(mhi_timeout, uint, 0600); + +static struct mhi_channel_config aic100_channels[] =3D { + { + .name =3D "QAIC_LOOPBACK", + .num =3D 0, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_LOOPBACK", + .num =3D 1, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_SAHARA", + .num =3D 2, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_SBL, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_SAHARA", + .num =3D 3, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_SBL, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_DIAG", + .num =3D 4, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_DIAG", + .num =3D 5, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_SSR", + .num =3D 6, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_SSR", + .num =3D 7, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_QDSS", + .num =3D 8, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_QDSS", + .num =3D 9, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_CONTROL", + .num =3D 10, + .num_elements =3D 128, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_CONTROL", + .num =3D 11, + .num_elements =3D 128, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_LOGGING", + .num =3D 12, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_SBL, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_LOGGING", + .num =3D 13, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_SBL, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_STATUS", + .num =3D 14, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_STATUS", + .num =3D 15, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_TELEMETRY", + .num =3D 16, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_TELEMETRY", + .num =3D 17, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_DEBUG", + .num =3D 18, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_DEBUG", + .num =3D 19, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .name =3D "QAIC_TIMESYNC", + .num =3D 20, + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_TO_DEVICE, + .ee_mask =3D MHI_CH_EE_SBL | MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, + { + .num =3D 21, + .name =3D "QAIC_TIMESYNC", + .num_elements =3D 32, + .local_elements =3D 0, + .event_ring =3D 0, + .dir =3D DMA_FROM_DEVICE, + .ee_mask =3D MHI_CH_EE_SBL | MHI_CH_EE_AMSS, + .pollcfg =3D 0, + .doorbell =3D MHI_DB_BRST_DISABLE, + .lpm_notify =3D false, + .offload_channel =3D false, + .doorbell_mode_switch =3D false, + .auto_queue =3D false, + .wake_capable =3D false, + }, +}; + +static struct mhi_event_config aic100_events[] =3D { + { + .num_elements =3D 32, + .irq_moderation_ms =3D 0, + .irq =3D 0, + .channel =3D U32_MAX, + .priority =3D 1, + .mode =3D MHI_DB_BRST_DISABLE, + .data_type =3D MHI_ER_CTRL, + .hardware_event =3D false, + .client_managed =3D false, + .offload_channel =3D false, + }, +}; + +static struct mhi_controller_config aic100_config =3D { + .max_channels =3D 128, + .timeout_ms =3D 0, /* controlled by mhi_timeout */ + .buf_len =3D 0, + .num_channels =3D ARRAY_SIZE(aic100_channels), + .ch_cfg =3D aic100_channels, + .num_events =3D ARRAY_SIZE(aic100_events), + .event_cfg =3D aic100_events, + .use_bounce_buf =3D false, + .m2_no_db =3D false, +}; + +static int mhi_read_reg(struct mhi_controller *mhi_cntl, void __iomem *add= r, u32 *out) +{ + u32 tmp =3D readl_relaxed(addr); + + if (tmp =3D=3D U32_MAX) + return -EIO; + + *out =3D tmp; + + return 0; +} + +static void mhi_write_reg(struct mhi_controller *mhi_cntl, void __iomem *a= ddr, + u32 val) +{ + writel_relaxed(val, addr); +} + +static int mhi_runtime_get(struct mhi_controller *mhi_cntl) +{ + return 0; +} + +static void mhi_runtime_put(struct mhi_controller *mhi_cntl) +{ +} + +static void mhi_status_cb(struct mhi_controller *mhi_cntl, enum mhi_callba= ck reason) +{ + struct qaic_device *qdev =3D pci_get_drvdata(to_pci_dev(mhi_cntl->cntrl_d= ev)); + + /* this event occurs in atomic context */ + if (reason =3D=3D MHI_CB_FATAL_ERROR) + pci_err(qdev->pdev, "Fatal error received from device. Attempting to re= cover\n"); + /* this event occurs in non-atomic context */ + if (reason =3D=3D MHI_CB_SYS_ERROR && !qdev->in_reset) + qaic_dev_reset_clean_local_state(qdev, true); +} + +static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntl) +{ + char time_sec =3D 1; + int current_ee; + int ret; + + /* Reset the device to bring the device in PBL EE */ + mhi_soc_reset(mhi_cntl); + + /* + * Keep checking the execution environment(EE) after every 1 second + * interval. + */ + do { + msleep(1000); + current_ee =3D mhi_get_exec_env(mhi_cntl); + } while (current_ee !=3D MHI_EE_PBL && time_sec++ <=3D MAX_RESET_TIME_SEC= ); + + /* If the device is in PBL EE retry power up */ + if (current_ee =3D=3D MHI_EE_PBL) + ret =3D mhi_async_power_up(mhi_cntl); + else + ret =3D -EIO; + + return ret; +} + +struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_de= v, + void __iomem *mhi_bar, + int mhi_irq) +{ + struct mhi_controller *mhi_cntl; + int ret; + + mhi_cntl =3D kzalloc(sizeof(*mhi_cntl), GFP_KERNEL); + if (!mhi_cntl) + return ERR_PTR(-ENOMEM); + + mhi_cntl->cntrl_dev =3D &pci_dev->dev; + + /* + * Covers the entire possible physical ram region. Remote side is + * going to calculate a size of this range, so subtract 1 to prevent + * rollover. + */ + mhi_cntl->iova_start =3D 0; + mhi_cntl->iova_stop =3D PHYS_ADDR_MAX - 1; + + mhi_cntl->status_cb =3D mhi_status_cb; + mhi_cntl->runtime_get =3D mhi_runtime_get; + mhi_cntl->runtime_put =3D mhi_runtime_put; + mhi_cntl->read_reg =3D mhi_read_reg; + mhi_cntl->write_reg =3D mhi_write_reg; + mhi_cntl->regs =3D mhi_bar; + mhi_cntl->reg_len =3D SZ_4K; + mhi_cntl->nr_irqs =3D 1; + mhi_cntl->irq =3D kmalloc(sizeof(*mhi_cntl->irq), GFP_KERNEL); + + if (!mhi_cntl->irq) { + kfree(mhi_cntl); + return ERR_PTR(-ENOMEM); + } + + mhi_cntl->irq[0] =3D mhi_irq; + + mhi_cntl->fw_image =3D "qcom/aic100/sbl.bin"; + + /* use latest configured timeout */ + aic100_config.timeout_ms =3D mhi_timeout; + ret =3D mhi_register_controller(mhi_cntl, &aic100_config); + if (ret) { + pci_err(pci_dev, "mhi_register_controller failed %d\n", ret); + kfree(mhi_cntl->irq); + kfree(mhi_cntl); + return ERR_PTR(ret); + } + + ret =3D mhi_prepare_for_power_up(mhi_cntl); + if (ret) { + pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret); + mhi_unregister_controller(mhi_cntl); + kfree(mhi_cntl->irq); + kfree(mhi_cntl); + return ERR_PTR(ret); + } + + ret =3D mhi_async_power_up(mhi_cntl); + /* + * If EIO is returned it is possible that device is in SBL EE, which is + * undesired. SOC reset the device and try to power up again. + */ + if (ret =3D=3D -EIO && MHI_EE_SBL =3D=3D mhi_get_exec_env(mhi_cntl)) { + pci_err(pci_dev, "Device is not expected to be SBL EE. SOC resetting the= device to put it in PBL EE and again trying mhi async power up. Error %d\n= ", + ret); + ret =3D mhi_reset_and_async_power_up(mhi_cntl); + } + + if (ret) { + pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret); + mhi_unprepare_after_power_down(mhi_cntl); + mhi_unregister_controller(mhi_cntl); + kfree(mhi_cntl->irq); + kfree(mhi_cntl); + return ERR_PTR(ret); + } + + return mhi_cntl; +} + +void qaic_mhi_free_controller(struct mhi_controller *mhi_cntl, bool link_u= p) +{ + mhi_power_down(mhi_cntl, link_up); + mhi_unprepare_after_power_down(mhi_cntl); + mhi_unregister_controller(mhi_cntl); + kfree(mhi_cntl->irq); + kfree(mhi_cntl); +} + +void qaic_mhi_start_reset(struct mhi_controller *mhi_cntl) +{ + mhi_power_down(mhi_cntl, true); +} + +void qaic_mhi_reset_done(struct mhi_controller *mhi_cntl) +{ + struct pci_dev *pci_dev =3D container_of(mhi_cntl->cntrl_dev, + struct pci_dev, dev); + int ret; + + ret =3D mhi_async_power_up(mhi_cntl); + if (ret) + pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret); +} diff --git a/drivers/gpu/drm/qaic/mhi_controller.h b/drivers/gpu/drm/qaic/m= hi_controller.h new file mode 100644 index 0000000..5a739bb --- /dev/null +++ b/drivers/gpu/drm/qaic/mhi_controller.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef MHICONTROLLERQAIC_H_ +#define MHICONTROLLERQAIC_H_ + +struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_de= v, + void __iomem *mhi_bar, + int mhi_irq); + +void qaic_mhi_free_controller(struct mhi_controller *mhi_cntl, bool link_u= p); + +void qaic_mhi_start_reset(struct mhi_controller *mhi_cntl); +void qaic_mhi_reset_done(struct mhi_controller *mhi_cntl); + +#endif /* MHICONTROLLERQAIC_H_ */ --=20 2.7.4