This enables kernel developers to enable "download mode", a mechanism for
entering a debug state to "download" memory content following a unexpected
warm-restart; e.g. security violation by accessing a protected register.
Bjorn Andersson (3):
firmware: qcom: scm: Expose secure IO service
firmware: qcom: scm: Expose download-mode control
arm64: dts: qcom: Specify dload address for msm8916 and msm8996
.../devicetree/bindings/firmware/qcom,scm.txt | 2 +
arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +
arch/arm64/boot/dts/qcom/msm8996.dtsi | 7 ++
drivers/firmware/Kconfig | 11 +++
drivers/firmware/qcom_scm-32.c | 24 +++++++
drivers/firmware/qcom_scm-64.c | 44 ++++++++++++
drivers/firmware/qcom_scm.c | 81 ++++++++++++++++++++++
drivers/firmware/qcom_scm.h | 8 +++
include/linux/qcom_scm.h | 4 ++
9 files changed, 183 insertions(+)
--
2.12.0
On msm8916 and msm8996 boards a secure io-write is used to write the
magic for selecting "download mode", specify this address in the
DeviceTree.
Note that qcom_scm.download_mode=1 must be specified on the kernel
command line for the kernel to attempt selecting download mode.
Signed-off-by: Bjorn Andersson <[email protected]>
---
arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 ++
arch/arm64/boot/dts/qcom/msm8996.dtsi | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 039991f80831..b7197f2e7209 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -241,6 +241,8 @@
clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
clock-names = "core", "bus", "iface";
#reset-cells = <1>;
+
+ qcom,dload-mode = <&tcsr>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 8f085716e258..2eee6a33f22b 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -261,6 +261,8 @@
firmware {
scm {
compatible = "qcom,scm-msm8996";
+
+ qcom,dload-mode = <&tcsr>;
};
};
@@ -287,6 +289,11 @@
reg = <0x740000 0x20000>;
};
+ tcsr: syscon@1937000 {
+ compatible = "qcom,tcsr-msm8996", "syscon";
+ reg = <0x7a0000 0x18000>;
+ };
+
intc: interrupt-controller@9bc0000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
--
2.12.0
In order to aid post-mortem debugging the Qualcomm platforms provides a
"memory download mode", where the boot loader will provide an interface
for custom tools to "download" the content of RAM to a host machine.
The mode is triggered by writing a magic value somehwere in RAM, that is
read in the boot code path after a warm-restart. Two mechanism for
setting this magic value are supported in modern platforms; a direct SCM
call to enable the mode or through a secure io write of a magic value.
In order for a normal reboot not to trigger "download mode" the magic
must be cleared during a clean reboot.
Download mode has to be enabled by including qcom_scm.download_mode=1 on
the command line.
Signed-off-by: Bjorn Andersson <[email protected]>
---
Changes since v2:
- Define memory address by reference to TCSR
- Provide Kconfig option for defaulting to enabled
- Provided some comment in the code
Changes since v1:
- Specify DT propert being two-cell
- Correct handling of scm-call return code
.../devicetree/bindings/firmware/qcom,scm.txt | 2 +
drivers/firmware/Kconfig | 11 ++++
drivers/firmware/qcom_scm-32.c | 6 ++
drivers/firmware/qcom_scm-64.c | 13 ++++
drivers/firmware/qcom_scm.c | 69 ++++++++++++++++++++++
drivers/firmware/qcom_scm.h | 2 +
6 files changed, 103 insertions(+)
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
index 20f26fbce875..838dba841797 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -18,6 +18,8 @@ Required properties:
* Core, iface, and bus clocks required for "qcom,scm"
- clock-names: Must contain "core" for the core clock, "iface" for the interface
clock and "bus" for the bus clock per the requirements of the compatible.
+- qcom,dload-mode: phandle reference to the TCSR hardware block containing the
+ download mode control register (optional)
Example for MSM8916:
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6e4ed5a9c6fd..ed23c77d6361 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -215,6 +215,17 @@ config QCOM_SCM_64
def_bool y
depends on QCOM_SCM && ARM64
+config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
+ bool "Qualcomm Download mode enabled by default"
+ depends on QCOM_SCM
+ help
+ A device with "download mode" enabled will upon an unexpected
+ warm-restart enter a special debug mode that allows the user to
+ "download" memory content over USB for offline postmortem analysis.
+ The feature can be enabled/disabled on the kernel command line.
+
+ Say Y here to enable "download mode" by default.
+
config TI_SCI_PROTOCOL
tristate "TI System Control Interface (TISCI) Message Protocol"
depends on TI_MESSAGE_MANAGER
diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 11fdb1584823..68b2033bc30e 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -561,6 +561,12 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
return ret ? : le32_to_cpu(out);
}
+int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
+{
+ return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE,
+ enable ? QCOM_SCM_SET_DLOAD_MODE : 0, 0);
+}
+
int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
{
struct {
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index bf50fb59852e..3fea6f563ca9 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -440,6 +440,19 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
return ret;
}
+int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
+{
+ struct qcom_scm_desc desc = {0};
+ struct arm_smccc_res res;
+
+ desc.args[0] = QCOM_SCM_SET_DLOAD_MODE;
+ desc.args[1] = enable ? QCOM_SCM_SET_DLOAD_MODE : 0;
+ desc.arginfo = QCOM_SCM_ARGS(2);
+
+ return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE,
+ &desc, &res);
+}
+
int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
unsigned int *val)
{
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index e18d63935648..88472cde8936 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -19,15 +19,20 @@
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/dma-mapping.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/qcom_scm.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
#include <linux/reset-controller.h>
#include "qcom_scm.h"
+static bool download_mode = IS_ENABLED(CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT);
+module_param(download_mode, bool, 0);
+
#define SCM_HAS_CORE_CLK BIT(0)
#define SCM_HAS_IFACE_CLK BIT(1)
#define SCM_HAS_BUS_CLK BIT(2)
@@ -38,6 +43,8 @@ struct qcom_scm {
struct clk *iface_clk;
struct clk *bus_clk;
struct reset_controller_dev reset;
+
+ u64 dload_mode_addr;
};
static struct qcom_scm *__scm;
@@ -345,6 +352,48 @@ int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)
}
EXPORT_SYMBOL(qcom_scm_io_writel);
+static void qcom_scm_set_download_mode(bool enable)
+{
+ bool avail;
+ int ret = 0;
+
+ avail = __qcom_scm_is_call_available(__scm->dev,
+ QCOM_SCM_SVC_BOOT,
+ QCOM_SCM_SET_DLOAD_MODE);
+ if (avail) {
+ ret = __qcom_scm_set_dload_mode(__scm->dev, enable);
+ } else if (__scm->dload_mode_addr) {
+ ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr,
+ enable ? QCOM_SCM_SET_DLOAD_MODE : 0);
+ } else {
+ dev_err(__scm->dev,
+ "No available mechanism for setting download mode\n");
+ }
+
+ if (ret)
+ dev_err(__scm->dev, "failed to set download mode: %d\n", ret);
+}
+
+static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)
+{
+ struct device_node *tcsr;
+ struct resource res;
+ int ret;
+
+ tcsr = of_parse_phandle(dev->of_node, "qcom,dload-mode", 0);
+ if (!tcsr)
+ return 0;
+
+ ret = of_address_to_resource(tcsr, 0, &res);
+ of_node_put(tcsr);
+ if (ret)
+ return ret;
+
+ *addr = res.start;
+
+ return 0;
+}
+
/**
* qcom_scm_is_available() - Checks if SCM is available
*/
@@ -370,6 +419,10 @@ static int qcom_scm_probe(struct platform_device *pdev)
if (!scm)
return -ENOMEM;
+ ret = qcom_scm_find_dload_address(&pdev->dev, &scm->dload_mode_addr);
+ if (ret < 0)
+ return ret;
+
clks = (unsigned long)of_device_get_match_data(&pdev->dev);
if (clks & SCM_HAS_CORE_CLK) {
scm->core_clk = devm_clk_get(&pdev->dev, "core");
@@ -418,9 +471,24 @@ static int qcom_scm_probe(struct platform_device *pdev)
__qcom_scm_init();
+ /*
+ * If requested enable "download mode", from this point on warmboot
+ * will cause the the boot stages to enter download mode, unless
+ * disabled below by a clean shutdown/reboot.
+ */
+ if (download_mode)
+ qcom_scm_set_download_mode(true);
+
return 0;
}
+static void qcom_scm_shutdown(struct platform_device *pdev)
+{
+ /* Clean shutdown, disable download mode to allow normal restart */
+ if (download_mode)
+ qcom_scm_set_download_mode(false);
+}
+
static const struct of_device_id qcom_scm_dt_match[] = {
{ .compatible = "qcom,scm-apq8064",
/* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */
@@ -448,6 +516,7 @@ static struct platform_driver qcom_scm_driver = {
.of_match_table = qcom_scm_dt_match,
},
.probe = qcom_scm_probe,
+ .shutdown = qcom_scm_shutdown,
};
static int __init qcom_scm_init(void)
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index a60e4b9b1394..83f171c23943 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -14,9 +14,11 @@
#define QCOM_SCM_SVC_BOOT 0x1
#define QCOM_SCM_BOOT_ADDR 0x1
+#define QCOM_SCM_SET_DLOAD_MODE 0x10
#define QCOM_SCM_BOOT_ADDR_MC 0x11
#define QCOM_SCM_SET_REMOTE_STATE 0xa
extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id);
+extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable);
#define QCOM_SCM_FLAG_HLOS 0x01
#define QCOM_SCM_FLAG_COLDBOOT_MC 0x02
--
2.12.0
The secure IO service provides operations for reading and writing secure
memory from non-secure mode, expose this API through SCM.
Reviewed-by: Stephen Boyd <[email protected]>
Signed-off-by: Bjorn Andersson <[email protected]>
---
Changes since v2:
- Picked up Stephen's r-b
Changes since v1:
- Correct scm-call return value handling
- Make scm_io_readl() return data by reference
drivers/firmware/qcom_scm-32.c | 18 ++++++++++++++++++
drivers/firmware/qcom_scm-64.c | 31 +++++++++++++++++++++++++++++++
drivers/firmware/qcom_scm.c | 12 ++++++++++++
drivers/firmware/qcom_scm.h | 6 ++++++
include/linux/qcom_scm.h | 4 ++++
5 files changed, 71 insertions(+)
diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 93e3b96b6dfa..11fdb1584823 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -596,3 +596,21 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
{
return -ENODEV;
}
+
+int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
+ unsigned int *val)
+{
+ int ret;
+
+ ret = qcom_scm_call_atomic1(QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, addr);
+ if (ret >= 0)
+ *val = ret;
+
+ return ret < 0 ? ret : 0;
+}
+
+int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val)
+{
+ return qcom_scm_call_atomic2(QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE,
+ addr, val);
+}
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index 6e6d561708e2..bf50fb59852e 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -439,3 +439,34 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
return ret;
}
+
+int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
+ unsigned int *val)
+{
+ struct qcom_scm_desc desc = {0};
+ struct arm_smccc_res res;
+ int ret;
+
+ desc.args[0] = addr;
+ desc.arginfo = QCOM_SCM_ARGS(1);
+
+ ret = qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ,
+ &desc, &res);
+ if (ret >= 0)
+ *val = res.a1;
+
+ return ret < 0 ? ret : 0;
+}
+
+int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val)
+{
+ struct qcom_scm_desc desc = {0};
+ struct arm_smccc_res res;
+
+ desc.args[0] = addr;
+ desc.args[1] = val;
+ desc.arginfo = QCOM_SCM_ARGS(2);
+
+ return qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE,
+ &desc, &res);
+}
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index bb16510d75ba..e18d63935648 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -333,6 +333,18 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
}
EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
+int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)
+{
+ return __qcom_scm_io_readl(__scm->dev, addr, val);
+}
+EXPORT_SYMBOL(qcom_scm_io_readl);
+
+int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)
+{
+ return __qcom_scm_io_writel(__scm->dev, addr, val);
+}
+EXPORT_SYMBOL(qcom_scm_io_writel);
+
/**
* qcom_scm_is_available() - Checks if SCM is available
*/
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 9bea691f30fb..a60e4b9b1394 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -30,6 +30,12 @@ extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
#define QCOM_SCM_CMD_CORE_HOTPLUGGED 0x10
extern void __qcom_scm_cpu_power_down(u32 flags);
+#define QCOM_SCM_SVC_IO 0x5
+#define QCOM_SCM_IO_READ 0x1
+#define QCOM_SCM_IO_WRITE 0x2
+extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val);
+extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val);
+
#define QCOM_SCM_SVC_INFO 0x6
#define QCOM_IS_CALL_AVAIL_CMD 0x1
extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index e5380471c2cd..e8357f570695 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -43,6 +43,8 @@ extern int qcom_scm_set_remote_state(u32 state, u32 id);
extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);
extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
+extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
+extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
#else
static inline
int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
@@ -73,5 +75,7 @@ qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; }
static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; }
static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; }
static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; }
+static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; }
+static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; }
#endif
#endif
--
2.12.0
On 08/09/2017 01:10 PM, Bjorn Andersson wrote:
> On msm8916 and msm8996 boards a secure io-write is used to write the
> magic for selecting "download mode", specify this address in the
> DeviceTree.
>
> Note that qcom_scm.download_mode=1 must be specified on the kernel
> command line for the kernel to attempt selecting download mode.
>
> Signed-off-by: Bjorn Andersson <[email protected]>
> ---
> arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 ++
> arch/arm64/boot/dts/qcom/msm8996.dtsi | 7 +++++++
> 2 files changed, 9 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 039991f80831..b7197f2e7209 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -241,6 +241,8 @@
> clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
> clock-names = "core", "bus", "iface";
> #reset-cells = <1>;
> +
> + qcom,dload-mode = <&tcsr>;
> };
> };
>
> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> index 8f085716e258..2eee6a33f22b 100644
> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> @@ -261,6 +261,8 @@
> firmware {
> scm {
> compatible = "qcom,scm-msm8996";
> +
> + qcom,dload-mode = <&tcsr>;
We don't need an offset into tcsr?
> };
> };
>
> @@ -287,6 +289,11 @@
> reg = <0x740000 0x20000>;
> };
>
> + tcsr: syscon@1937000 {
This doesn't match reg property.
> + compatible = "qcom,tcsr-msm8996", "syscon";
> + reg = <0x7a0000 0x18000>;
> + };
> +
> intc: interrupt-controller@9bc0000 {
> compatible = "arm,gic-v3";
> #interrupt-cells = <3>;
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 08/09/2017 01:10 PM, Bjorn Andersson wrote:
> In order to aid post-mortem debugging the Qualcomm platforms provides a
s/provides/provide/
> "memory download mode", where the boot loader will provide an interface
> for custom tools to "download" the content of RAM to a host machine.
>
> The mode is triggered by writing a magic value somehwere in RAM, that is
s/somehwere/somewhere/
> read in the boot code path after a warm-restart. Two mechanism for
> setting this magic value are supported in modern platforms; a direct SCM
> call to enable the mode or through a secure io write of a magic value.
>
> In order for a normal reboot not to trigger "download mode" the magic
> must be cleared during a clean reboot.
>
> Download mode has to be enabled by including qcom_scm.download_mode=1 on
> the command line.
>
> Signed-off-by: Bjorn Andersson <[email protected]>
> ---
>
> Changes since v2:
> - Define memory address by reference to TCSR
> - Provide Kconfig option for defaulting to enabled
> - Provided some comment in the code
>
> Changes since v1:
> - Specify DT propert being two-cell
> - Correct handling of scm-call return code
>
> .../devicetree/bindings/firmware/qcom,scm.txt | 2 +
> drivers/firmware/Kconfig | 11 ++++
> drivers/firmware/qcom_scm-32.c | 6 ++
> drivers/firmware/qcom_scm-64.c | 13 ++++
> drivers/firmware/qcom_scm.c | 69 ++++++++++++++++++++++
> drivers/firmware/qcom_scm.h | 2 +
> 6 files changed, 103 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> index 20f26fbce875..838dba841797 100644
> --- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> @@ -18,6 +18,8 @@ Required properties:
> * Core, iface, and bus clocks required for "qcom,scm"
> - clock-names: Must contain "core" for the core clock, "iface" for the interface
> clock and "bus" for the bus clock per the requirements of the compatible.
> +- qcom,dload-mode: phandle reference to the TCSR hardware block containing the
> + download mode control register (optional)
>
> Example for MSM8916:
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index 6e4ed5a9c6fd..ed23c77d6361 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -215,6 +215,17 @@ config QCOM_SCM_64
> def_bool y
> depends on QCOM_SCM && ARM64
>
> +config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
> + bool "Qualcomm Download mode enabled by default"
Decapitalize download?
> + depends on QCOM_SCM
> + help
> + A device with "download mode" enabled will upon an unexpected
> + warm-restart enter a special debug mode that allows the user to
> + "download" memory content over USB for offline postmortem analysis.
> + The feature can be enabled/disabled on the kernel command line.
> +
> + Say Y here to enable "download mode" by default.
> +
otherwise
Reviewed-by: Stephen Boyd <[email protected]>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On Wed 09 Aug 14:50 PDT 2017, Stephen Boyd wrote:
> On 08/09/2017 01:10 PM, Bjorn Andersson wrote:
> > On msm8916 and msm8996 boards a secure io-write is used to write the
> > magic for selecting "download mode", specify this address in the
> > DeviceTree.
> >
> > Note that qcom_scm.download_mode=1 must be specified on the kernel
> > command line for the kernel to attempt selecting download mode.
> >
> > Signed-off-by: Bjorn Andersson <[email protected]>
> > ---
> > arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 ++
> > arch/arm64/boot/dts/qcom/msm8996.dtsi | 7 +++++++
> > 2 files changed, 9 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > index 039991f80831..b7197f2e7209 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> > @@ -241,6 +241,8 @@
> > clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
> > clock-names = "core", "bus", "iface";
> > #reset-cells = <1>;
> > +
> > + qcom,dload-mode = <&tcsr>;
> > };
> > };
> >
> > diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > index 8f085716e258..2eee6a33f22b 100644
> > --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> > @@ -261,6 +261,8 @@
> > firmware {
> > scm {
> > compatible = "qcom,scm-msm8996";
> > +
> > + qcom,dload-mode = <&tcsr>;
>
> We don't need an offset into tcsr?
>
Of course we do, this only worked with my previous (and incorrect) tcsr
definition - not the one I ended up including in the patch.
Thanks,
Bjorn