Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: qcom_scm: disable SDI if required

IPQ5018 has SDI (Secure Debug Image) enabled by TZ by default, and that
means that WDT being asserted or just trying to reboot will hang the board
in the debug mode and only pulling the power and repowering will help.
Some IPQ4019 boards like Google WiFI have it enabled as well.

Luckily, SDI can be disabled via an SCM call.

So, lets use the boolean DT property to identify boards that have SDI
enabled by default and use the SCM call to disable SDI during SCM probe.
It is important to disable it as soon as possible as we might have a WDT
assertion at any time which would then leave the board in debug mode,
thus disabling it during SCM removal is not enough.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Guru Das Srinagesh <quic_gurus@quicinc.com>
Link: https://lore.kernel.org/r/20230816164641.3371878-2-robimarko@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Robert Marko and committed by
Bjorn Andersson
ff4aa3bc 92dab9ea

+31
+30
drivers/firmware/qcom_scm.c
··· 451 451 } 452 452 EXPORT_SYMBOL_GPL(qcom_scm_set_remote_state); 453 453 454 + static int qcom_scm_disable_sdi(void) 455 + { 456 + int ret; 457 + struct qcom_scm_desc desc = { 458 + .svc = QCOM_SCM_SVC_BOOT, 459 + .cmd = QCOM_SCM_BOOT_SDI_CONFIG, 460 + .args[0] = 1, /* Disable watchdog debug */ 461 + .args[1] = 0, /* Disable SDI */ 462 + .arginfo = QCOM_SCM_ARGS(2), 463 + .owner = ARM_SMCCC_OWNER_SIP, 464 + }; 465 + struct qcom_scm_res res; 466 + 467 + ret = qcom_scm_clk_enable(); 468 + if (ret) 469 + return ret; 470 + ret = qcom_scm_call(__scm->dev, &desc, &res); 471 + 472 + qcom_scm_clk_disable(); 473 + 474 + return ret ? : res.result[0]; 475 + } 476 + 454 477 static int __qcom_scm_set_dload_mode(struct device *dev, bool enable) 455 478 { 456 479 struct qcom_scm_desc desc = { ··· 1872 1849 */ 1873 1850 if (download_mode) 1874 1851 qcom_scm_set_download_mode(true); 1852 + 1853 + 1854 + /* 1855 + * Disable SDI if indicated by DT that it is enabled by default. 1856 + */ 1857 + if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled")) 1858 + qcom_scm_disable_sdi(); 1875 1859 1876 1860 /* 1877 1861 * Initialize the QSEECOM interface.
+1
drivers/firmware/qcom_scm.h
··· 80 80 #define QCOM_SCM_SVC_BOOT 0x01 81 81 #define QCOM_SCM_BOOT_SET_ADDR 0x01 82 82 #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 83 + #define QCOM_SCM_BOOT_SDI_CONFIG 0x09 83 84 #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 84 85 #define QCOM_SCM_BOOT_SET_ADDR_MC 0x11 85 86 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a