From nobody Fri Sep 19 02:36:45 2025 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 1C6A2C47090 for ; Wed, 30 Nov 2022 10:30:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235852AbiK3KaU (ORCPT ); Wed, 30 Nov 2022 05:30:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235584AbiK3K3y (ORCPT ); Wed, 30 Nov 2022 05:29:54 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AD1542193 for ; Wed, 30 Nov 2022 02:29:52 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id bx10so14269996wrb.0 for ; Wed, 30 Nov 2022 02:29:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=F81FRtQTN8/7lBiZFQTJl8otEU1xztcn6GaL7O0kwpk=; b=G28/KdJOjCg9+UIxofyjQV/U1xXgNCB4PJE7EMnOT0Crr+89VmtVf9IabZWFXVtC/S wPZcQIOFfeq8BQOdMdK5bsQmqGuwjhwW4SLsuYlJ/xvI+Lm4Npm5TFWxcEnJLnwfA+fb c7cLJ12el+y+ir9ivUbe9uy6ejDvbIOyq9/yyfdzLawA/FC+AUJWAVES6NcQuhXWPFG/ CFtqkRMi1f3q8eVrBzCqoLngcD/Y4ao2cWVpWBb2LIKLWbxhdrdBGBK2VOixDCSgjPPn Az0bp9YhOPnoFGQPBK1t2cO47Kb7fLaNqxb6nioB75ltmLYiQhzk+aBVURQ91O+/zo0F 7w3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=F81FRtQTN8/7lBiZFQTJl8otEU1xztcn6GaL7O0kwpk=; b=tjI0vWDRIvfYm2NMwQItl2dH0+N1UKLT/QYvJyyBtVDXLqwhAt+3F43AHEMUDMdoEA QGYTWEzdchkqv02zasM4nRACdjf5VURJjJJLa8gWG3lXLUp88SAbQ2oScUQOTsC1xWZS R0K3C5f2nJ8n8u+R5jUrLkLnnPpQwlfIWW6N/56ssD5QXCqr6e79bvm80mZ2Elz8mLff 9eQXofqI3sPIMfB5b6MZmLb3H41ka6I4F8cnIw88ZaVh9FEgT+SIzFgwP8WaHa59MB5E SAxvWvIJ2PKhKouJi/Yk1MtJ7bGJTB7QvO4g1nKicQaPmiKBrFPPyl3CAjxH9A0C3ueQ lVlA== X-Gm-Message-State: ANoB5pmHVPyjcigJfvlPRt7CGURUMklt8h6Dz/b4W22it/utfpC6LnoW 5JemfaoW+nepxiNZcfxR2V5lUjpzkq9v/+xt X-Google-Smtp-Source: AA0mqf6teHsMlC9YXM5prFxbQla9Sftnvo9EmqE7qsvGWcACpTbGZqkBLQXAZKUt++vVYUB3i4qk4g== X-Received: by 2002:adf:f84f:0:b0:236:7805:48d3 with SMTP id d15-20020adff84f000000b00236780548d3mr36727248wrq.644.1669804190602; Wed, 30 Nov 2022 02:29:50 -0800 (PST) Received: from arrakeen.starnux.net ([2a01:e0a:982:cbb0:52eb:f6ff:feb3:451a]) by smtp.gmail.com with ESMTPSA id j33-20020a05600c1c2100b003b4ff30e566sm4313570wms.3.2022.11.30.02.29.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Nov 2022 02:29:50 -0800 (PST) From: Neil Armstrong Date: Wed, 30 Nov 2022 11:29:47 +0100 Subject: [PATCH v2 3/5] remoteproc: qcom_q6v5_pas: add support for dtb co-firmware loading MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20221114-narmstrong-sm8550-upstream-remoteproc-v2-3-12bc22255474@linaro.org> References: <20221114-narmstrong-sm8550-upstream-remoteproc-v2-0-12bc22255474@linaro.org> In-Reply-To: <20221114-narmstrong-sm8550-upstream-remoteproc-v2-0-12bc22255474@linaro.org> To: Rob Herring , Bjorn Andersson , Krzysztof Kozlowski , Konrad Dybcio , Amol Maheshwari , Srinivas Kandagatla , Manivannan Sadhasivam , Mathieu Poirier , Andy Gross Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, Neil Armstrong , Abel Vesa , linux-remoteproc@vger.kernel.org X-Mailer: b4 0.10.1 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Starting from the SM8550 SoC, starting the aDSP, cDSP and MPSS will require loading a separate "Devicetree" firmware. In order to satisfy the load & authentication order required by the SM8550 SoC, the following is implemented: - "Devicetree" firmware request & load in dedicated memory - Q6V5 prepare - Power Domain & Clocks enable - "Devicetree" firmware authentication - Main firmware load in dedicated memory - Main firmware authentication - Q6V5 startup - "Devicetree" firmware metadata release - Main metadata release When booting older platforms, the "Devicetree" steps would be bypassed and the load & authentication order would still be valid. Signed-off-by: Neil Armstrong --- drivers/remoteproc/qcom_q6v5_pas.c | 134 +++++++++++++++++++++++++++++++++= ---- 1 file changed, 121 insertions(+), 13 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q= 6v5_pas.c index 6afd0941e552..4fe09c7f25bd 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -35,7 +35,9 @@ struct adsp_data { int crash_reason_smem; const char *firmware_name; + const char *dtb_firmware_name; int pas_id; + int dtb_pas_id; unsigned int minidump_id; bool has_aggre2_clk; bool auto_boot; @@ -65,20 +67,29 @@ struct qcom_adsp { =20 int proxy_pd_count; =20 + const char *dtb_firmware_name; int pas_id; + int dtb_pas_id; unsigned int minidump_id; int crash_reason_smem; bool has_aggre2_clk; bool decrypt_shutdown; const char *info_name; =20 + const struct firmware *firmware; + const struct firmware *dtb_firmware; + struct completion start_done; struct completion stop_done; =20 phys_addr_t mem_phys; + phys_addr_t dtb_mem_phys; phys_addr_t mem_reloc; + phys_addr_t dtb_mem_reloc; void *mem_region; + void *dtb_mem_region; size_t mem_size; + size_t dtb_mem_size; =20 struct qcom_rproc_glink glink_subdev; struct qcom_rproc_subdev smd_subdev; @@ -86,6 +97,7 @@ struct qcom_adsp { struct qcom_sysmon *sysmon; =20 struct qcom_scm_pas_metadata pas_metadata; + struct qcom_scm_pas_metadata dtb_pas_metadata; }; =20 static void adsp_minidump(struct rproc *rproc) @@ -160,6 +172,8 @@ static int adsp_unprepare(struct rproc *rproc) * here. */ qcom_scm_pas_metadata_release(&adsp->pas_metadata); + if (adsp->dtb_pas_id) + qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); =20 return 0; } @@ -169,20 +183,40 @@ static int adsp_load(struct rproc *rproc, const struc= t firmware *fw) struct qcom_adsp *adsp =3D (struct qcom_adsp *)rproc->priv; int ret; =20 - ret =3D qcom_mdt_pas_init(adsp->dev, fw, rproc->firmware, adsp->pas_id, - adsp->mem_phys, &adsp->pas_metadata); - if (ret) - return ret; + /* Store firmware handle to be used in adsp_start() */ + adsp->firmware =3D fw; =20 - ret =3D qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, adsp->pas_i= d, - adsp->mem_region, adsp->mem_phys, adsp->mem_size, - &adsp->mem_reloc); - if (ret) - return ret; + if (adsp->dtb_pas_id) { + ret =3D request_firmware(&adsp->dtb_firmware, adsp->dtb_firmware_name, a= dsp->dev); + if (ret) { + dev_err(adsp->dev, "request_firmware failed for %s: %d\n", + adsp->dtb_firmware_name, ret); + return ret; + } =20 - qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); + ret =3D qcom_mdt_pas_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmw= are_name, + adsp->dtb_pas_id, adsp->dtb_mem_phys, + &adsp->dtb_pas_metadata); + if (ret) + goto release_dtb_firmware; + + ret =3D qcom_mdt_load_no_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_f= irmware_name, + adsp->dtb_pas_id, adsp->dtb_mem_region, + adsp->dtb_mem_phys, adsp->dtb_mem_size, + &adsp->dtb_mem_reloc); + if (ret) + goto release_dtb_metadata; + } =20 return 0; + +release_dtb_metadata: + qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); + +release_dtb_firmware: + release_firmware(adsp->dtb_firmware); + + return ret; } =20 static int adsp_start(struct rproc *rproc) @@ -218,24 +252,55 @@ static int adsp_start(struct rproc *rproc) goto disable_cx_supply; } =20 + if (adsp->dtb_pas_id) { + ret =3D qcom_scm_pas_auth_and_reset(adsp->dtb_pas_id); + if (ret) { + dev_err(adsp->dev, + "failed to authenticate dtb image and release reset\n"); + goto disable_px_supply; + } + } + + ret =3D qcom_mdt_pas_init(adsp->dev, adsp->firmware, rproc->firmware, ads= p->pas_id, + adsp->mem_phys, &adsp->pas_metadata); + if (ret) + goto disable_px_supply; + + ret =3D qcom_mdt_load_no_init(adsp->dev, adsp->firmware, rproc->firmware,= adsp->pas_id, + adsp->mem_region, adsp->mem_phys, adsp->mem_size, + &adsp->mem_reloc); + if (ret) + goto release_pas_metadata; + + qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); + ret =3D qcom_scm_pas_auth_and_reset(adsp->pas_id); if (ret) { dev_err(adsp->dev, "failed to authenticate image and release reset\n"); - goto disable_px_supply; + goto release_pas_metadata; } =20 ret =3D qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000)); if (ret =3D=3D -ETIMEDOUT) { dev_err(adsp->dev, "start timed out\n"); qcom_scm_pas_shutdown(adsp->pas_id); - goto disable_px_supply; + goto release_pas_metadata; } =20 qcom_scm_pas_metadata_release(&adsp->pas_metadata); + if (adsp->dtb_pas_id) + qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); + + /* Remove pointer to the loaded firmware, only valid in adsp_load() & ads= p_start() */ + adsp->firmware =3D NULL; =20 return 0; =20 +release_pas_metadata: + qcom_scm_pas_metadata_release(&adsp->pas_metadata); + if (adsp->dtb_pas_id) + qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); disable_px_supply: if (adsp->px_supply) regulator_disable(adsp->px_supply); @@ -251,6 +316,9 @@ static int adsp_start(struct rproc *rproc) disable_irqs: qcom_q6v5_unprepare(&adsp->q6v5); =20 + /* Remove pointer to the loaded firmware, only valid in adsp_load() & ads= p_start() */ + adsp->firmware =3D NULL; + return ret; } =20 @@ -284,6 +352,12 @@ static int adsp_stop(struct rproc *rproc) if (ret) dev_err(adsp->dev, "failed to shutdown: %d\n", ret); =20 + if (adsp->dtb_pas_id) { + ret =3D qcom_scm_pas_shutdown(adsp->dtb_pas_id); + if (ret) + dev_err(adsp->dev, "failed to shutdown dtb: %d\n", ret); + } + handover =3D qcom_q6v5_unprepare(&adsp->q6v5); if (handover) qcom_pas_handover(&adsp->q6v5); @@ -461,6 +535,28 @@ static int adsp_alloc_memory_region(struct qcom_adsp *= adsp) return -EBUSY; } =20 + if (!adsp->dtb_pas_id) + return 0; + + node =3D of_parse_phandle(adsp->dev->of_node, "memory-region", 1); + if (!node) { + dev_err(adsp->dev, "no dtb memory-region specified\n"); + return -EINVAL; + } + + ret =3D of_address_to_resource(node, 0, &r); + if (ret) + return ret; + + adsp->dtb_mem_phys =3D adsp->dtb_mem_reloc =3D r.start; + adsp->dtb_mem_size =3D resource_size(&r); + adsp->dtb_mem_region =3D devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, a= dsp->dtb_mem_size); + if (!adsp->dtb_mem_region) { + dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n", + &r.start, adsp->dtb_mem_size); + return -EBUSY; + } + return 0; } =20 @@ -469,7 +565,7 @@ static int adsp_probe(struct platform_device *pdev) const struct adsp_data *desc; struct qcom_adsp *adsp; struct rproc *rproc; - const char *fw_name; + const char *fw_name, *dtb_fw_name =3D NULL; const struct rproc_ops *ops =3D &adsp_ops; int ret; =20 @@ -486,6 +582,14 @@ static int adsp_probe(struct platform_device *pdev) if (ret < 0 && ret !=3D -EINVAL) return ret; =20 + if (desc->dtb_firmware_name) { + dtb_fw_name =3D desc->dtb_firmware_name; + ret =3D of_property_read_string_index(pdev->dev.of_node, "firmware-name"= , 1, + &dtb_fw_name); + if (ret < 0 && ret !=3D -EINVAL) + return ret; + } + if (desc->minidump_id) ops =3D &adsp_minidump_ops; =20 @@ -507,6 +611,10 @@ static int adsp_probe(struct platform_device *pdev) adsp->has_aggre2_clk =3D desc->has_aggre2_clk; adsp->info_name =3D desc->sysmon_name; adsp->decrypt_shutdown =3D desc->decrypt_shutdown; + if (dtb_fw_name) { + adsp->dtb_firmware_name =3D dtb_fw_name; + adsp->dtb_pas_id =3D desc->dtb_pas_id; + } platform_set_drvdata(pdev, adsp); =20 ret =3D device_init_wakeup(adsp->dev, true); --=20 b4 0.10.1