History

Merge tag 'qcom-drivers-for-5.6' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers

Qualcomm driver updates for v5.6 * SCM major refactoring and cleanup * Properly flag active only power domains as active only * Add SC7180 and SM8150 RPMH power domains * Return EPROBE_DEFER from QMI if packet family is not yet available * tag 'qcom-drivers-for-5.6' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (27 commits) firmware: qcom_scm: Dynamically support SMCCC and legacy conventions firmware: qcom_scm: Remove thin wrappers firmware: qcom_scm: Order functions, definitions by service/command firmware: qcom_scm-32: Add device argument to atomic calls firmware: qcom_scm-32: Create common legacy atomic call firmware: qcom_scm-32: Move SMCCC register filling to qcom_scm_call firmware: qcom_scm-32: Use qcom_scm_desc in non-atomic calls firmware: qcom_scm-32: Add funcnum IDs firmware: qcom_scm-32: Use SMC arch wrappers firmware: qcom_scm-64: Improve SMC convention detection firmware: qcom_scm-64: Move SMC register filling to qcom_scm_call_smccc firmware: qcom_scm-64: Add SCM results struct firmware: qcom_scm-64: Move svc/cmd/owner into qcom_scm_desc firmware: qcom_scm-64: Make SMC macros less magical firmware: qcom_scm: Remove unused qcom_scm_get_version firmware: qcom_scm: Apply consistent naming scheme to command IDs firmware: qcom_scm: Rename macros and structures soc: qcom: rpmhpd: Set 'active_only' for active only power domains firmware: scm: Add stubs for OCMEM and restore_sec_cfg_available dt-bindings: power: rpmpd: Convert rpmpd bindings to yaml ...

Olof Johansson committed 6 years ago

Commit 333505a2 parents a9e3e12 9a434ce16 files · +1504 −1741Browse files

Unified · Split

16 files
  1. Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml +1 −1
  2. Documentation/devicetree/bindings/power/qcom,rpmpd.txt +0 −148
  3. Documentation/devicetree/bindings/power/qcom,rpmpd.yaml +170 −0
  4. drivers/firmware/Kconfig +0 −8
  5. drivers/firmware/Makefile +1 −4
  6. drivers/firmware/qcom_scm-32.c +0 −671
  7. drivers/firmware/qcom_scm-64.c +0 −579
  8. drivers/firmware/qcom_scm-legacy.c +242 −0
  9. drivers/firmware/qcom_scm-smc.c +151 −0
  10. drivers/firmware/qcom_scm.c +669 −185
  11. drivers/firmware/qcom_scm.h +101 −77
  12. drivers/soc/qcom/Kconfig +15 −15
  13. drivers/soc/qcom/qmi_interface.c +6 −2
  14. drivers/soc/qcom/rpmhpd.c +56 −0
  15. include/dt-bindings/power/qcom-rpmpd.h +24 −0
  16. include/linux/qcom_scm.h +68 −51
Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml+1−1
@@ -47,7 +47,7 @@ examples: · 46 unmodified lines
47 - |47 - |
48 #include <dt-bindings/interrupt-controller/arm-gic.h>48 #include <dt-bindings/interrupt-controller/arm-gic.h>
49 49
50 cache-controller@1100000 {50 system-cache-controller@1100000 {
51 compatible = "qcom,sdm845-llcc";51 compatible = "qcom,sdm845-llcc";
52 reg = <0x1100000 0x200000>, <0x1300000 0x50000> ;52 reg = <0x1100000 0x200000>, <0x1300000 0x50000> ;
53 reg-names = "llcc_base", "llcc_broadcast_base";53 reg-names = "llcc_base", "llcc_broadcast_base";
Documentation/devicetree/bindings/power/qcom,rpmpd.txt+0−148
@@ -1,148 +0,0 @@
1Qualcomm RPM/RPMh Power domains
2
3For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
4which then translates it into a corresponding voltage on a rail
5
6Required Properties:
7 - compatible: Should be one of the following
8 * qcom,msm8976-rpmpd: RPM Power domain for the msm8976 family of SoC
9 * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC
10 * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC
11 * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC
12 * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC
13 - #power-domain-cells: number of cells in Power domain specifier
14 must be 1.
15 - operating-points-v2: Phandle to the OPP table for the Power domain.
16 Refer to Documentation/devicetree/bindings/power/power_domain.txt
17 and Documentation/devicetree/bindings/opp/opp.txt for more details
18
19Refer to <dt-bindings/power/qcom-rpmpd.h> for the level values for
20various OPPs for different platforms as well as Power domain indexes
21
22Example: rpmh power domain controller and OPP table
23
24#include <dt-bindings/power/qcom-rpmhpd.h>
25
26opp-level values specified in the OPP tables for RPMh power domains
27should use the RPMH_REGULATOR_LEVEL_* constants from
28<dt-bindings/power/qcom-rpmhpd.h>
29
30 rpmhpd: power-controller {
31 compatible = "qcom,sdm845-rpmhpd";
32 #power-domain-cells = <1>;
33 operating-points-v2 = <&rpmhpd_opp_table>;
34
35 rpmhpd_opp_table: opp-table {
36 compatible = "operating-points-v2";
37
38 rpmhpd_opp_ret: opp1 {
39 opp-level = <RPMH_REGULATOR_LEVEL_RETENTION>;
40 };
41
42 rpmhpd_opp_min_svs: opp2 {
43 opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
44 };
45
46 rpmhpd_opp_low_svs: opp3 {
47 opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
48 };
49
50 rpmhpd_opp_svs: opp4 {
51 opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
52 };
53
54 rpmhpd_opp_svs_l1: opp5 {
55 opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
56 };
57
58 rpmhpd_opp_nom: opp6 {
59 opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
60 };
61
62 rpmhpd_opp_nom_l1: opp7 {
63 opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
64 };
65
66 rpmhpd_opp_nom_l2: opp8 {
67 opp-level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
68 };
69
70 rpmhpd_opp_turbo: opp9 {
71 opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
72 };
73
74 rpmhpd_opp_turbo_l1: opp10 {
75 opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
76 };
77 };
78 };
79
80Example: rpm power domain controller and OPP table
81
82 rpmpd: power-controller {
83 compatible = "qcom,msm8996-rpmpd";
84 #power-domain-cells = <1>;
85 operating-points-v2 = <&rpmpd_opp_table>;
86
87 rpmpd_opp_table: opp-table {
88 compatible = "operating-points-v2";
89
90 rpmpd_opp_low: opp1 {
91 opp-level = <1>;
92 };
93
94 rpmpd_opp_ret: opp2 {
95 opp-level = <2>;
96 };
97
98 rpmpd_opp_svs: opp3 {
99 opp-level = <3>;
100 };
101
102 rpmpd_opp_normal: opp4 {
103 opp-level = <4>;
104 };
105
106 rpmpd_opp_high: opp5 {
107 opp-level = <5>;
108 };
109
110 rpmpd_opp_turbo: opp6 {
111 opp-level = <6>;
112 };
113 };
114 };
115
116Example: Client/Consumer device using OPP table
117
118 leaky-device0@12350000 {
119 compatible = "foo,i-leak-current";
120 reg = <0x12350000 0x1000>;
121 power-domains = <&rpmhpd SDM845_MX>;
122 operating-points-v2 = <&leaky_opp_table>;
123 };
124
125
126 leaky_opp_table: opp-table {
127 compatible = "operating-points-v2";
128
129 opp1 {
130 opp-hz = /bits/ 64 <144000>;
131 required-opps = <&rpmhpd_opp_low>;
132 };
133
134 opp2 {
135 opp-hz = /bits/ 64 <400000>;
136 required-opps = <&rpmhpd_opp_ret>;
137 };
138
139 opp3 {
140 opp-hz = /bits/ 64 <20000000>;
141 required-opps = <&rpmpd_opp_svs>;
142 };
143
144 opp4 {
145 opp-hz = /bits/ 64 <25000000>;
146 required-opps = <&rpmpd_opp_normal>;
147 };
148 };
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml+170−0
@@ -0,0 +1,170 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/power/qcom,rpmpd.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Qualcomm RPM/RPMh Power domains
8
9maintainers:
10 - Rajendra Nayak <rnayak@codeaurora.org>
11
12description:
13 For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
14 which then translates it into a corresponding voltage on a rail.
15
16properties:
17 compatible:
18 enum:
19 - qcom,msm8976-rpmpd
20 - qcom,msm8996-rpmpd
21 - qcom,msm8998-rpmpd
22 - qcom,qcs404-rpmpd
23 - qcom,sc7180-rpmhpd
24 - qcom,sdm845-rpmhpd
25 - qcom,sm8150-rpmhpd
26
27 '#power-domain-cells':
28 const: 1
29
30 operating-points-v2: true
31
32 opp-table:
33 type: object
34
35required:
36 - compatible
37 - '#power-domain-cells'
38 - operating-points-v2
39
40additionalProperties: false
41
42examples:
43 - |
44
45 // Example 1 (rpmh power domain controller and OPP table):
46
47 #include <dt-bindings/power/qcom-rpmpd.h>
48
49 rpmhpd: power-controller {
50 compatible = "qcom,sdm845-rpmhpd";
51 #power-domain-cells = <1>;
52 operating-points-v2 = <&rpmhpd_opp_table>;
53
54 rpmhpd_opp_table: opp-table {
55 compatible = "operating-points-v2";
56
57 rpmhpd_opp_ret: opp1 {
58 opp-level = <RPMH_REGULATOR_LEVEL_RETENTION>;
59 };
60
61 rpmhpd_opp_min_svs: opp2 {
62 opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
63 };
64
65 rpmhpd_opp_low_svs: opp3 {
66 opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
67 };
68
69 rpmhpd_opp_svs: opp4 {
70 opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
71 };
72
73 rpmhpd_opp_svs_l1: opp5 {
74 opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
75 };
76
77 rpmhpd_opp_nom: opp6 {
78 opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
79 };
80
81 rpmhpd_opp_nom_l1: opp7 {
82 opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
83 };
84
85 rpmhpd_opp_nom_l2: opp8 {
86 opp-level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
87 };
88
89 rpmhpd_opp_turbo: opp9 {
90 opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
91 };
92
93 rpmhpd_opp_turbo_l1: opp10 {
94 opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
95 };
96 };
97 };
98
99 - |
100
101 // Example 2 (rpm power domain controller and OPP table):
102
103 rpmpd: power-controller {
104 compatible = "qcom,msm8996-rpmpd";
105 #power-domain-cells = <1>;
106 operating-points-v2 = <&rpmpd_opp_table>;
107
108 rpmpd_opp_table: opp-table {
109 compatible = "operating-points-v2";
110
111 rpmpd_opp_low: opp1 {
112 opp-level = <1>;
113 };
114
115 rpmpd_opp_ret: opp2 {
116 opp-level = <2>;
117 };
118
119 rpmpd_opp_svs: opp3 {
120 opp-level = <3>;
121 };
122
123 rpmpd_opp_normal: opp4 {
124 opp-level = <4>;
125 };
126
127 rpmpd_opp_high: opp5 {
128 opp-level = <5>;
129 };
130
131 rpmpd_opp_turbo: opp6 {
132 opp-level = <6>;
133 };
134 };
135 };
136
137 - |
138
139 // Example 3 (Client/Consumer device using OPP table):
140
141 leaky-device0@12350000 {
142 compatible = "foo,i-leak-current";
143 reg = <0x12350000 0x1000>;
144 power-domains = <&rpmhpd 0>;
145 operating-points-v2 = <&leaky_opp_table>;
146 };
147
148 leaky_opp_table: opp-table {
149 compatible = "operating-points-v2";
150 opp1 {
151 opp-hz = /bits/ 64 <144000>;
152 required-opps = <&rpmhpd_opp_low>;
153 };
154
155 opp2 {
156 opp-hz = /bits/ 64 <400000>;
157 required-opps = <&rpmhpd_opp_ret>;
158 };
159
160 opp3 {
161 opp-hz = /bits/ 64 <20000000>;
162 required-opps = <&rpmpd_opp_svs>;
163 };
164
165 opp4 {
166 opp-hz = /bits/ 64 <25000000>;
167 required-opps = <&rpmpd_opp_normal>;
168 };
169 };
170...
drivers/firmware/Kconfig+0−8
@@ -239,14 +239,6 @@ config QCOM_SCM · 238 unmodified lines
239 depends on ARM || ARM64239 depends on ARM || ARM64
240 select RESET_CONTROLLER240 select RESET_CONTROLLER
241 241
242config QCOM_SCM_32
243 def_bool y
244 depends on QCOM_SCM && ARM
245
246config QCOM_SCM_64
247 def_bool y
248 depends on QCOM_SCM && ARM64
249
250config QCOM_SCM_DOWNLOAD_MODE_DEFAULT242config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
251 bool "Qualcomm download mode enabled by default"243 bool "Qualcomm download mode enabled by default"
252 depends on QCOM_SCM244 depends on QCOM_SCM
drivers/firmware/Makefile+1−4
@@ -17,10 +17,7 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o · 16 unmodified lines
17obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o17obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
18obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o18obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
19obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o19obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
20obj-$(CONFIG_QCOM_SCM) += qcom_scm.o20obj-$(CONFIG_QCOM_SCM) += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
21obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o
22obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
23CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
24obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o21obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
25obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o22obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
26obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o23obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
drivers/firmware/qcom_scm-32.c+0−671
@@ -1,671 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2010,2015, The Linux Foundation. All rights reserved.
3 * Copyright (C) 2015 Linaro Ltd.
4 */
5
6#include <linux/slab.h>
7#include <linux/io.h>
8#include <linux/module.h>
9#include <linux/mutex.h>
10#include <linux/errno.h>
11#include <linux/err.h>
12#include <linux/qcom_scm.h>
13#include <linux/dma-mapping.h>
14
15#include "qcom_scm.h"
16
17#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
18#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
19#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
20#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
21
22#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
23#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
24#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
25#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
26
27struct qcom_scm_entry {
28 int flag;
29 void *entry;
30};
31
32static struct qcom_scm_entry qcom_scm_wb[] = {
33 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
34 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
35 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
36 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
37};
38
39static DEFINE_MUTEX(qcom_scm_lock);
40
41/**
42 * struct qcom_scm_command - one SCM command buffer
43 * @len: total available memory for command and response
44 * @buf_offset: start of command buffer
45 * @resp_hdr_offset: start of response buffer
46 * @id: command to be executed
47 * @buf: buffer returned from qcom_scm_get_command_buffer()
48 *
49 * An SCM command is laid out in memory as follows:
50 *
51 * ------------------- <--- struct qcom_scm_command
52 * | command header |
53 * ------------------- <--- qcom_scm_get_command_buffer()
54 * | command buffer |
55 * ------------------- <--- struct qcom_scm_response and
56 * | response header | qcom_scm_command_to_response()
57 * ------------------- <--- qcom_scm_get_response_buffer()
58 * | response buffer |
59 * -------------------
60 *
61 * There can be arbitrary padding between the headers and buffers so
62 * you should always use the appropriate qcom_scm_get_*_buffer() routines
63 * to access the buffers in a safe manner.
64 */
65struct qcom_scm_command {
66 __le32 len;
67 __le32 buf_offset;
68 __le32 resp_hdr_offset;
69 __le32 id;
70 __le32 buf[0];
71};
72
73/**
74 * struct qcom_scm_response - one SCM response buffer
75 * @len: total available memory for response
76 * @buf_offset: start of response data relative to start of qcom_scm_response
77 * @is_complete: indicates if the command has finished processing
78 */
79struct qcom_scm_response {
80 __le32 len;
81 __le32 buf_offset;
82 __le32 is_complete;
83};
84
85/**
86 * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
87 * @cmd: command
88 *
89 * Returns a pointer to a response for a command.
90 */
91static inline struct qcom_scm_response *qcom_scm_command_to_response(
92 const struct qcom_scm_command *cmd)
93{
94 return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
95}
96
97/**
98 * qcom_scm_get_command_buffer() - Get a pointer to a command buffer
99 * @cmd: command
100 *
101 * Returns a pointer to the command buffer of a command.
102 */
103static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd)
104{
105 return (void *)cmd->buf;
106}
107
108/**
109 * qcom_scm_get_response_buffer() - Get a pointer to a response buffer
110 * @rsp: response
111 *
112 * Returns a pointer to a response buffer of a response.
113 */
114static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp)
115{
116 return (void *)rsp + le32_to_cpu(rsp->buf_offset);
117}
118
119static u32 smc(u32 cmd_addr)
120{
121 int context_id;
122 register u32 r0 asm("r0") = 1;
123 register u32 r1 asm("r1") = (u32)&context_id;
124 register u32 r2 asm("r2") = cmd_addr;
125 do {
126 asm volatile(
127 __asmeq("%0", "r0")
128 __asmeq("%1", "r0")
129 __asmeq("%2", "r1")
130 __asmeq("%3", "r2")
131#ifdef REQUIRES_SEC
132 ".arch_extension sec\n"
133#endif
134 "smc #0 @ switch to secure world\n"
135 : "=r" (r0)
136 : "r" (r0), "r" (r1), "r" (r2)
137 : "r3", "r12");
138 } while (r0 == QCOM_SCM_INTERRUPTED);
139
140 return r0;
141}
142
143/**
144 * qcom_scm_call() - Send an SCM command
145 * @dev: struct device
146 * @svc_id: service identifier
147 * @cmd_id: command identifier
148 * @cmd_buf: command buffer
149 * @cmd_len: length of the command buffer
150 * @resp_buf: response buffer
151 * @resp_len: length of the response buffer
152 *
153 * Sends a command to the SCM and waits for the command to finish processing.
154 *
155 * A note on cache maintenance:
156 * Note that any buffers that are expected to be accessed by the secure world
157 * must be flushed before invoking qcom_scm_call and invalidated in the cache
158 * immediately after qcom_scm_call returns. Cache maintenance on the command
159 * and response buffers is taken care of by qcom_scm_call; however, callers are
160 * responsible for any other cached buffers passed over to the secure world.
161 */
162static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
163 const void *cmd_buf, size_t cmd_len, void *resp_buf,
164 size_t resp_len)
165{
166 int ret;
167 struct qcom_scm_command *cmd;
168 struct qcom_scm_response *rsp;
169 size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;
170 dma_addr_t cmd_phys;
171
172 cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
173 if (!cmd)
174 return -ENOMEM;
175
176 cmd->len = cpu_to_le32(alloc_len);
177 cmd->buf_offset = cpu_to_le32(sizeof(*cmd));
178 cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len);
179
180 cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
181 if (cmd_buf)
182 memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
183
184 rsp = qcom_scm_command_to_response(cmd);
185
186 cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
187 if (dma_mapping_error(dev, cmd_phys)) {
188 kfree(cmd);
189 return -ENOMEM;
190 }
191
192 mutex_lock(&qcom_scm_lock);
193 ret = smc(cmd_phys);
194 if (ret < 0)
195 ret = qcom_scm_remap_error(ret);
196 mutex_unlock(&qcom_scm_lock);
197 if (ret)
198 goto out;
199
200 do {
201 dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len,
202 sizeof(*rsp), DMA_FROM_DEVICE);
203 } while (!rsp->is_complete);
204
205 if (resp_buf) {
206 dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len +
207 le32_to_cpu(rsp->buf_offset),
208 resp_len, DMA_FROM_DEVICE);
209 memcpy(resp_buf, qcom_scm_get_response_buffer(rsp),
210 resp_len);
211 }
212out:
213 dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
214 kfree(cmd);
215 return ret;
216}
217
218#define SCM_CLASS_REGISTER (0x2 << 8)
219#define SCM_MASK_IRQS BIT(5)
220#define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \
221 SCM_CLASS_REGISTER | \
222 SCM_MASK_IRQS | \
223 (n & 0xf))
224
225/**
226 * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument
227 * @svc_id: service identifier
228 * @cmd_id: command identifier
229 * @arg1: first argument
230 *
231 * This shall only be used with commands that are guaranteed to be
232 * uninterruptable, atomic and SMP safe.
233 */
234static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
235{
236 int context_id;
237
238 register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1);
239 register u32 r1 asm("r1") = (u32)&context_id;
240 register u32 r2 asm("r2") = arg1;
241
242 asm volatile(
243 __asmeq("%0", "r0")
244 __asmeq("%1", "r0")
245 __asmeq("%2", "r1")
246 __asmeq("%3", "r2")
247#ifdef REQUIRES_SEC
248 ".arch_extension sec\n"
249#endif
250 "smc #0 @ switch to secure world\n"
251 : "=r" (r0)
252 : "r" (r0), "r" (r1), "r" (r2)
253 : "r3", "r12");
254 return r0;
255}
256
257/**
258 * qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments
259 * @svc_id: service identifier
260 * @cmd_id: command identifier
261 * @arg1: first argument
262 * @arg2: second argument
263 *
264 * This shall only be used with commands that are guaranteed to be
265 * uninterruptable, atomic and SMP safe.
266 */
267static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
268{
269 int context_id;
270
271 register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2);
272 register u32 r1 asm("r1") = (u32)&context_id;
273 register u32 r2 asm("r2") = arg1;
274 register u32 r3 asm("r3") = arg2;
275
276 asm volatile(
277 __asmeq("%0", "r0")
278 __asmeq("%1", "r0")
279 __asmeq("%2", "r1")
280 __asmeq("%3", "r2")
281 __asmeq("%4", "r3")
282#ifdef REQUIRES_SEC
283 ".arch_extension sec\n"
284#endif
285 "smc #0 @ switch to secure world\n"
286 : "=r" (r0)
287 : "r" (r0), "r" (r1), "r" (r2), "r" (r3)
288 : "r12");
289 return r0;
290}
291
292u32 qcom_scm_get_version(void)
293{
294 int context_id;
295 static u32 version = -1;
296 register u32 r0 asm("r0");
297 register u32 r1 asm("r1");
298
299 if (version != -1)
300 return version;
301
302 mutex_lock(&qcom_scm_lock);
303
304 r0 = 0x1 << 8;
305 r1 = (u32)&context_id;
306 do {
307 asm volatile(
308 __asmeq("%0", "r0")
309 __asmeq("%1", "r1")
310 __asmeq("%2", "r0")
311 __asmeq("%3", "r1")
312#ifdef REQUIRES_SEC
313 ".arch_extension sec\n"
314#endif
315 "smc #0 @ switch to secure world\n"
316 : "=r" (r0), "=r" (r1)
317 : "r" (r0), "r" (r1)
318 : "r2", "r3", "r12");
319 } while (r0 == QCOM_SCM_INTERRUPTED);
320
321 version = r1;
322 mutex_unlock(&qcom_scm_lock);
323
324 return version;
325}
326EXPORT_SYMBOL(qcom_scm_get_version);
327
328/**
329 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
330 * @entry: Entry point function for the cpus
331 * @cpus: The cpumask of cpus that will use the entry point
332 *
333 * Set the cold boot address of the cpus. Any cpu outside the supported
334 * range would be removed from the cpu present mask.
335 */
336int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
337{
338 int flags = 0;
339 int cpu;
340 int scm_cb_flags[] = {
341 QCOM_SCM_FLAG_COLDBOOT_CPU0,
342 QCOM_SCM_FLAG_COLDBOOT_CPU1,
343 QCOM_SCM_FLAG_COLDBOOT_CPU2,
344 QCOM_SCM_FLAG_COLDBOOT_CPU3,
345 };
346
347 if (!cpus || (cpus && cpumask_empty(cpus)))
348 return -EINVAL;
349
350 for_each_cpu(cpu, cpus) {
351 if (cpu < ARRAY_SIZE(scm_cb_flags))
352 flags |= scm_cb_flags[cpu];
353 else
354 set_cpu_present(cpu, false);
355 }
356
357 return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
358 flags, virt_to_phys(entry));
359}
360
361/**
362 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
363 * @entry: Entry point function for the cpus
364 * @cpus: The cpumask of cpus that will use the entry point
365 *
366 * Set the Linux entry point for the SCM to transfer control to when coming
367 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
368 */
369int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
370 const cpumask_t *cpus)
371{
372 int ret;
373 int flags = 0;
374 int cpu;
375 struct {
376 __le32 flags;
377 __le32 addr;
378 } cmd;
379
380 /*
381 * Reassign only if we are switching from hotplug entry point
382 * to cpuidle entry point or vice versa.
383 */
384 for_each_cpu(cpu, cpus) {
385 if (entry == qcom_scm_wb[cpu].entry)
386 continue;
387 flags |= qcom_scm_wb[cpu].flag;
388 }
389
390 /* No change in entry function */
391 if (!flags)
392 return 0;
393
394 cmd.addr = cpu_to_le32(virt_to_phys(entry));
395 cmd.flags = cpu_to_le32(flags);
396 ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
397 &cmd, sizeof(cmd), NULL, 0);
398 if (!ret) {
399 for_each_cpu(cpu, cpus)
400 qcom_scm_wb[cpu].entry = entry;
401 }
402
403 return ret;
404}
405
406/**
407 * qcom_scm_cpu_power_down() - Power down the cpu
408 * @flags - Flags to flush cache
409 *
410 * This is an end point to power down cpu. If there was a pending interrupt,
411 * the control would return from this function, otherwise, the cpu jumps to the
412 * warm boot entry point set for this cpu upon reset.
413 */
414void __qcom_scm_cpu_power_down(u32 flags)
415{
416 qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC,
417 flags & QCOM_SCM_FLUSH_FLAG_MASK);
418}
419
420int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
421{
422 int ret;
423 __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
424 __le32 ret_val = 0;
425
426 ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
427 &svc_cmd, sizeof(svc_cmd), &ret_val,
428 sizeof(ret_val));
429 if (ret)
430 return ret;
431
432 return le32_to_cpu(ret_val);
433}
434
435int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
436 u32 req_cnt, u32 *resp)
437{
438 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
439 return -ERANGE;
440
441 return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
442 req, req_cnt * sizeof(*req), resp, sizeof(*resp));
443}
444
445int __qcom_scm_ocmem_lock(struct device *dev, u32 id, u32 offset, u32 size,
446 u32 mode)
447{
448 struct ocmem_tz_lock {
449 __le32 id;
450 __le32 offset;
451 __le32 size;
452 __le32 mode;
453 } request;
454
455 request.id = cpu_to_le32(id);
456 request.offset = cpu_to_le32(offset);
457 request.size = cpu_to_le32(size);
458 request.mode = cpu_to_le32(mode);
459
460 return qcom_scm_call(dev, QCOM_SCM_OCMEM_SVC, QCOM_SCM_OCMEM_LOCK_CMD,
461 &request, sizeof(request), NULL, 0);
462}
463
464int __qcom_scm_ocmem_unlock(struct device *dev, u32 id, u32 offset, u32 size)
465{
466 struct ocmem_tz_unlock {
467 __le32 id;
468 __le32 offset;
469 __le32 size;
470 } request;
471
472 request.id = cpu_to_le32(id);
473 request.offset = cpu_to_le32(offset);
474 request.size = cpu_to_le32(size);
475
476 return qcom_scm_call(dev, QCOM_SCM_OCMEM_SVC, QCOM_SCM_OCMEM_UNLOCK_CMD,
477 &request, sizeof(request), NULL, 0);
478}
479
480void __qcom_scm_init(void)
481{
482}
483
484bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral)
485{
486 __le32 out;
487 __le32 in;
488 int ret;
489
490 in = cpu_to_le32(peripheral);
491 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
492 QCOM_SCM_PAS_IS_SUPPORTED_CMD,
493 &in, sizeof(in),
494 &out, sizeof(out));
495
496 return ret ? false : !!out;
497}
498
499int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
500 dma_addr_t metadata_phys)
501{
502 __le32 scm_ret;
503 int ret;
504 struct {
505 __le32 proc;
506 __le32 image_addr;
507 } request;
508
509 request.proc = cpu_to_le32(peripheral);
510 request.image_addr = cpu_to_le32(metadata_phys);
511
512 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
513 QCOM_SCM_PAS_INIT_IMAGE_CMD,
514 &request, sizeof(request),
515 &scm_ret, sizeof(scm_ret));
516
517 return ret ? : le32_to_cpu(scm_ret);
518}
519
520int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
521 phys_addr_t addr, phys_addr_t size)
522{
523 __le32 scm_ret;
524 int ret;
525 struct {
526 __le32 proc;
527 __le32 addr;
528 __le32 len;
529 } request;
530
531 request.proc = cpu_to_le32(peripheral);
532 request.addr = cpu_to_le32(addr);
533 request.len = cpu_to_le32(size);
534
535 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
536 QCOM_SCM_PAS_MEM_SETUP_CMD,
537 &request, sizeof(request),
538 &scm_ret, sizeof(scm_ret));
539
540 return ret ? : le32_to_cpu(scm_ret);
541}
542
543int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
544{
545 __le32 out;
546 __le32 in;
547 int ret;
548
549 in = cpu_to_le32(peripheral);
550 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
551 QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
552 &in, sizeof(in),
553 &out, sizeof(out));
554
555 return ret ? : le32_to_cpu(out);
556}
557
558int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
559{
560 __le32 out;
561 __le32 in;
562 int ret;
563
564 in = cpu_to_le32(peripheral);
565 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
566 QCOM_SCM_PAS_SHUTDOWN_CMD,
567 &in, sizeof(in),
568 &out, sizeof(out));
569
570 return ret ? : le32_to_cpu(out);
571}
572
573int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
574{
575 __le32 out;
576 __le32 in = cpu_to_le32(reset);
577 int ret;
578
579 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET,
580 &in, sizeof(in),
581 &out, sizeof(out));
582
583 return ret ? : le32_to_cpu(out);
584}
585
586int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
587{
588 return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE,
589 enable ? QCOM_SCM_SET_DLOAD_MODE : 0, 0);
590}
591
592int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
593{
594 struct {
595 __le32 state;
596 __le32 id;
597 } req;
598 __le32 scm_ret = 0;
599 int ret;
600
601 req.state = cpu_to_le32(state);
602 req.id = cpu_to_le32(id);
603
604 ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE,
605 &req, sizeof(req), &scm_ret, sizeof(scm_ret));
606
607 return ret ? : le32_to_cpu(scm_ret);
608}
609
610int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
611 size_t mem_sz, phys_addr_t src, size_t src_sz,
612 phys_addr_t dest, size_t dest_sz)
613{
614 return -ENODEV;
615}
616
617int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
618 u32 spare)
619{
620 struct msm_scm_sec_cfg {
621 __le32 id;
622 __le32 ctx_bank_num;
623 } cfg;
624 int ret, scm_ret = 0;
625
626 cfg.id = cpu_to_le32(device_id);
627 cfg.ctx_bank_num = cpu_to_le32(spare);
628
629 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
630 &cfg, sizeof(cfg), &scm_ret, sizeof(scm_ret));
631
632 if (ret || scm_ret)
633 return ret ? ret : -EINVAL;
634
635 return 0;
636}
637
638int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
639 size_t *size)
640{
641 return -ENODEV;
642}
643
644int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
645 u32 spare)
646{
647 return -ENODEV;
648}
649
650int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
651 unsigned int *val)
652{
653 int ret;
654
655 ret = qcom_scm_call_atomic1(QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ, addr);
656 if (ret >= 0)
657 *val = ret;
658
659 return ret < 0 ? ret : 0;
660}
661
662int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val)
663{
664 return qcom_scm_call_atomic2(QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE,
665 addr, val);
666}
667
668int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable)
669{
670 return -ENODEV;
671}
drivers/firmware/qcom_scm-64.c+0−579
@@ -1,579 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 */
4
5#include <linux/io.h>
6#include <linux/errno.h>
7#include <linux/delay.h>
8#include <linux/mutex.h>
9#include <linux/slab.h>
10#include <linux/types.h>
11#include <linux/qcom_scm.h>
12#include <linux/arm-smccc.h>
13#include <linux/dma-mapping.h>
14
15#include "qcom_scm.h"
16
17#define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
18
19#define MAX_QCOM_SCM_ARGS 10
20#define MAX_QCOM_SCM_RETS 3
21
22enum qcom_scm_arg_types {
23 QCOM_SCM_VAL,
24 QCOM_SCM_RO,
25 QCOM_SCM_RW,
26 QCOM_SCM_BUFVAL,
27};
28
29#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
30 (((a) & 0x3) << 4) | \
31 (((b) & 0x3) << 6) | \
32 (((c) & 0x3) << 8) | \
33 (((d) & 0x3) << 10) | \
34 (((e) & 0x3) << 12) | \
35 (((f) & 0x3) << 14) | \
36 (((g) & 0x3) << 16) | \
37 (((h) & 0x3) << 18) | \
38 (((i) & 0x3) << 20) | \
39 (((j) & 0x3) << 22) | \
40 ((num) & 0xf))
41
42#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
43
44/**
45 * struct qcom_scm_desc
46 * @arginfo: Metadata describing the arguments in args[]
47 * @args: The array of arguments for the secure syscall
48 * @res: The values returned by the secure syscall
49 */
50struct qcom_scm_desc {
51 u32 arginfo;
52 u64 args[MAX_QCOM_SCM_ARGS];
53};
54
55static u64 qcom_smccc_convention = -1;
56static DEFINE_MUTEX(qcom_scm_lock);
57
58#define QCOM_SCM_EBUSY_WAIT_MS 30
59#define QCOM_SCM_EBUSY_MAX_RETRY 20
60
61#define N_EXT_QCOM_SCM_ARGS 7
62#define FIRST_EXT_ARG_IDX 3
63#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
64
65static void __qcom_scm_call_do(const struct qcom_scm_desc *desc,
66 struct arm_smccc_res *res, u32 fn_id,
67 u64 x5, u32 type)
68{
69 u64 cmd;
70 struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 };
71
72 cmd = ARM_SMCCC_CALL_VAL(type, qcom_smccc_convention,
73 ARM_SMCCC_OWNER_SIP, fn_id);
74
75 quirk.state.a6 = 0;
76
77 do {
78 arm_smccc_smc_quirk(cmd, desc->arginfo, desc->args[0],
79 desc->args[1], desc->args[2], x5,
80 quirk.state.a6, 0, res, &quirk);
81
82 if (res->a0 == QCOM_SCM_INTERRUPTED)
83 cmd = res->a0;
84
85 } while (res->a0 == QCOM_SCM_INTERRUPTED);
86}
87
88static void qcom_scm_call_do(const struct qcom_scm_desc *desc,
89 struct arm_smccc_res *res, u32 fn_id,
90 u64 x5, bool atomic)
91{
92 int retry_count = 0;
93
94 if (atomic) {
95 __qcom_scm_call_do(desc, res, fn_id, x5, ARM_SMCCC_FAST_CALL);
96 return;
97 }
98
99 do {
100 mutex_lock(&qcom_scm_lock);
101
102 __qcom_scm_call_do(desc, res, fn_id, x5,
103 ARM_SMCCC_STD_CALL);
104
105 mutex_unlock(&qcom_scm_lock);
106
107 if (res->a0 == QCOM_SCM_V2_EBUSY) {
108 if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
109 break;
110 msleep(QCOM_SCM_EBUSY_WAIT_MS);
111 }
112 } while (res->a0 == QCOM_SCM_V2_EBUSY);
113}
114
115static int ___qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
116 const struct qcom_scm_desc *desc,
117 struct arm_smccc_res *res, bool atomic)
118{
119 int arglen = desc->arginfo & 0xf;
120 int i;
121 u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
122 u64 x5 = desc->args[FIRST_EXT_ARG_IDX];
123 dma_addr_t args_phys = 0;
124 void *args_virt = NULL;
125 size_t alloc_len;
126 gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
127
128 if (unlikely(arglen > N_REGISTER_ARGS)) {
129 alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
130 args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag);
131
132 if (!args_virt)
133 return -ENOMEM;
134
135 if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
136 __le32 *args = args_virt;
137
138 for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
139 args[i] = cpu_to_le32(desc->args[i +
140 FIRST_EXT_ARG_IDX]);
141 } else {
142 __le64 *args = args_virt;
143
144 for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
145 args[i] = cpu_to_le64(desc->args[i +
146 FIRST_EXT_ARG_IDX]);
147 }
148
149 args_phys = dma_map_single(dev, args_virt, alloc_len,
150 DMA_TO_DEVICE);
151
152 if (dma_mapping_error(dev, args_phys)) {
153 kfree(args_virt);
154 return -ENOMEM;
155 }
156
157 x5 = args_phys;
158 }
159
160 qcom_scm_call_do(desc, res, fn_id, x5, atomic);
161
162 if (args_virt) {
163 dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
164 kfree(args_virt);
165 }
166
167 if ((long)res->a0 < 0)
168 return qcom_scm_remap_error(res->a0);
169
170 return 0;
171}
172
173/**
174 * qcom_scm_call() - Invoke a syscall in the secure world
175 * @dev: device
176 * @svc_id: service identifier
177 * @cmd_id: command identifier
178 * @desc: Descriptor structure containing arguments and return values
179 *
180 * Sends a command to the SCM and waits for the command to finish processing.
181 * This should *only* be called in pre-emptible context.
182 */
183static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
184 const struct qcom_scm_desc *desc,
185 struct arm_smccc_res *res)
186{
187 might_sleep();
188 return ___qcom_scm_call(dev, svc_id, cmd_id, desc, res, false);
189}
190
191/**
192 * qcom_scm_call_atomic() - atomic variation of qcom_scm_call()
193 * @dev: device
194 * @svc_id: service identifier
195 * @cmd_id: command identifier
196 * @desc: Descriptor structure containing arguments and return values
197 * @res: Structure containing results from SMC/HVC call
198 *
199 * Sends a command to the SCM and waits for the command to finish processing.
200 * This can be called in atomic context.
201 */
202static int qcom_scm_call_atomic(struct device *dev, u32 svc_id, u32 cmd_id,
203 const struct qcom_scm_desc *desc,
204 struct arm_smccc_res *res)
205{
206 return ___qcom_scm_call(dev, svc_id, cmd_id, desc, res, true);
207}
208
209/**
210 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
211 * @entry: Entry point function for the cpus
212 * @cpus: The cpumask of cpus that will use the entry point
213 *
214 * Set the cold boot address of the cpus. Any cpu outside the supported
215 * range would be removed from the cpu present mask.
216 */
217int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
218{
219 return -ENOTSUPP;
220}
221
222/**
223 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
224 * @dev: Device pointer
225 * @entry: Entry point function for the cpus
226 * @cpus: The cpumask of cpus that will use the entry point
227 *
228 * Set the Linux entry point for the SCM to transfer control to when coming
229 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
230 */
231int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
232 const cpumask_t *cpus)
233{
234 return -ENOTSUPP;
235}
236
237/**
238 * qcom_scm_cpu_power_down() - Power down the cpu
239 * @flags - Flags to flush cache
240 *
241 * This is an end point to power down cpu. If there was a pending interrupt,
242 * the control would return from this function, otherwise, the cpu jumps to the
243 * warm boot entry point set for this cpu upon reset.
244 */
245void __qcom_scm_cpu_power_down(u32 flags)
246{
247}
248
249int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
250{
251 int ret;
252 struct qcom_scm_desc desc = {0};
253 struct arm_smccc_res res;
254
255 desc.arginfo = QCOM_SCM_ARGS(1);
256 desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) |
257 (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
258
259 ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
260 &desc, &res);
261
262 return ret ? : res.a1;
263}
264
265int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
266 u32 req_cnt, u32 *resp)
267{
268 int ret;
269 struct qcom_scm_desc desc = {0};
270 struct arm_smccc_res res;
271
272 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
273 return -ERANGE;
274
275 desc.args[0] = req[0].addr;
276 desc.args[1] = req[0].val;
277 desc.args[2] = req[1].addr;
278 desc.args[3] = req[1].val;
279 desc.args[4] = req[2].addr;
280 desc.args[5] = req[2].val;
281 desc.args[6] = req[3].addr;
282 desc.args[7] = req[3].val;
283 desc.args[8] = req[4].addr;
284 desc.args[9] = req[4].val;
285 desc.arginfo = QCOM_SCM_ARGS(10);
286
287 ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc,
288 &res);
289 *resp = res.a1;
290
291 return ret;
292}
293
294int __qcom_scm_ocmem_lock(struct device *dev, uint32_t id, uint32_t offset,
295 uint32_t size, uint32_t mode)
296{
297 return -ENOTSUPP;
298}
299
300int __qcom_scm_ocmem_unlock(struct device *dev, uint32_t id, uint32_t offset,
301 uint32_t size)
302{
303 return -ENOTSUPP;
304}
305
306void __qcom_scm_init(void)
307{
308 u64 cmd;
309 struct arm_smccc_res res;
310 u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD);
311
312 /* First try a SMC64 call */
313 cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
314 ARM_SMCCC_OWNER_SIP, function);
315
316 arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)),
317 0, 0, 0, 0, 0, &res);
318
319 if (!res.a0 && res.a1)
320 qcom_smccc_convention = ARM_SMCCC_SMC_64;
321 else
322 qcom_smccc_convention = ARM_SMCCC_SMC_32;
323}
324
325bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral)
326{
327 int ret;
328 struct qcom_scm_desc desc = {0};
329 struct arm_smccc_res res;
330
331 desc.args[0] = peripheral;
332 desc.arginfo = QCOM_SCM_ARGS(1);
333
334 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
335 QCOM_SCM_PAS_IS_SUPPORTED_CMD,
336 &desc, &res);
337
338 return ret ? false : !!res.a1;
339}
340
341int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
342 dma_addr_t metadata_phys)
343{
344 int ret;
345 struct qcom_scm_desc desc = {0};
346 struct arm_smccc_res res;
347
348 desc.args[0] = peripheral;
349 desc.args[1] = metadata_phys;
350 desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
351
352 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
353 &desc, &res);
354
355 return ret ? : res.a1;
356}
357
358int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
359 phys_addr_t addr, phys_addr_t size)
360{
361 int ret;
362 struct qcom_scm_desc desc = {0};
363 struct arm_smccc_res res;
364
365 desc.args[0] = peripheral;
366 desc.args[1] = addr;
367 desc.args[2] = size;
368 desc.arginfo = QCOM_SCM_ARGS(3);
369
370 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
371 &desc, &res);
372
373 return ret ? : res.a1;
374}
375
376int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
377{
378 int ret;
379 struct qcom_scm_desc desc = {0};
380 struct arm_smccc_res res;
381
382 desc.args[0] = peripheral;
383 desc.arginfo = QCOM_SCM_ARGS(1);
384
385 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
386 QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
387 &desc, &res);
388
389 return ret ? : res.a1;
390}
391
392int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
393{
394 int ret;
395 struct qcom_scm_desc desc = {0};
396 struct arm_smccc_res res;
397
398 desc.args[0] = peripheral;
399 desc.arginfo = QCOM_SCM_ARGS(1);
400
401 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
402 &desc, &res);
403
404 return ret ? : res.a1;
405}
406
407int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
408{
409 struct qcom_scm_desc desc = {0};
410 struct arm_smccc_res res;
411 int ret;
412
413 desc.args[0] = reset;
414 desc.args[1] = 0;
415 desc.arginfo = QCOM_SCM_ARGS(2);
416
417 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET, &desc,
418 &res);
419
420 return ret ? : res.a1;
421}
422
423int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
424{
425 struct qcom_scm_desc desc = {0};
426 struct arm_smccc_res res;
427 int ret;
428
429 desc.args[0] = state;
430 desc.args[1] = id;
431 desc.arginfo = QCOM_SCM_ARGS(2);
432
433 ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE,
434 &desc, &res);
435
436 return ret ? : res.a1;
437}
438
439int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
440 size_t mem_sz, phys_addr_t src, size_t src_sz,
441 phys_addr_t dest, size_t dest_sz)
442{
443 int ret;
444 struct qcom_scm_desc desc = {0};
445 struct arm_smccc_res res;
446
447 desc.args[0] = mem_region;
448 desc.args[1] = mem_sz;
449 desc.args[2] = src;
450 desc.args[3] = src_sz;
451 desc.args[4] = dest;
452 desc.args[5] = dest_sz;
453 desc.args[6] = 0;
454
455 desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL,
456 QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO,
457 QCOM_SCM_VAL, QCOM_SCM_VAL);
458
459 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
460 QCOM_MEM_PROT_ASSIGN_ID,
461 &desc, &res);
462
463 return ret ? : res.a1;
464}
465
466int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
467{
468 struct qcom_scm_desc desc = {0};
469 struct arm_smccc_res res;
470 int ret;
471
472 desc.args[0] = device_id;
473 desc.args[1] = spare;
474 desc.arginfo = QCOM_SCM_ARGS(2);
475
476 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
477 &desc, &res);
478
479 return ret ? : res.a1;
480}
481
482int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
483 size_t *size)
484{
485 struct qcom_scm_desc desc = {0};
486 struct arm_smccc_res res;
487 int ret;
488
489 desc.args[0] = spare;
490 desc.arginfo = QCOM_SCM_ARGS(1);
491
492 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
493 QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res);
494
495 if (size)
496 *size = res.a1;
497
498 return ret ? : res.a2;
499}
500
501int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
502 u32 spare)
503{
504 struct qcom_scm_desc desc = {0};
505 struct arm_smccc_res res;
506 int ret;
507
508 desc.args[0] = addr;
509 desc.args[1] = size;
510 desc.args[2] = spare;
511 desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
512 QCOM_SCM_VAL);
513
514 ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
515 QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res);
516
517 /* the pg table has been initialized already, ignore the error */
518 if (ret == -EPERM)
519 ret = 0;
520
521 return ret;
522}
523
524int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
525{
526 struct qcom_scm_desc desc = {0};
527 struct arm_smccc_res res;
528
529 desc.args[0] = QCOM_SCM_SET_DLOAD_MODE;
530 desc.args[1] = enable ? QCOM_SCM_SET_DLOAD_MODE : 0;
531 desc.arginfo = QCOM_SCM_ARGS(2);
532
533 return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE,
534 &desc, &res);
535}
536
537int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
538 unsigned int *val)
539{
540 struct qcom_scm_desc desc = {0};
541 struct arm_smccc_res res;
542 int ret;
543
544 desc.args[0] = addr;
545 desc.arginfo = QCOM_SCM_ARGS(1);
546
547 ret = qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ,
548 &desc, &res);
549 if (ret >= 0)
550 *val = res.a1;
551
552 return ret < 0 ? ret : 0;
553}
554
555int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val)
556{
557 struct qcom_scm_desc desc = {0};
558 struct arm_smccc_res res;
559
560 desc.args[0] = addr;
561 desc.args[1] = val;
562 desc.arginfo = QCOM_SCM_ARGS(2);
563
564 return qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE,
565 &desc, &res);
566}
567
568int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en)
569{
570 struct qcom_scm_desc desc = {0};
571 struct arm_smccc_res res;
572
573 desc.args[0] = QCOM_SCM_CONFIG_ERRATA1_CLIENT_ALL;
574 desc.args[1] = en;
575 desc.arginfo = QCOM_SCM_ARGS(2);
576
577 return qcom_scm_call_atomic(dev, QCOM_SCM_SVC_SMMU_PROGRAM,
578 QCOM_SCM_CONFIG_ERRATA1, &desc, &res);
579}
drivers/firmware/qcom_scm-legacy.c+242−0
@@ -0,0 +1,242 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved.
3 * Copyright (C) 2015 Linaro Ltd.
4 */
5
6#include <linux/slab.h>
7#include <linux/io.h>
8#include <linux/module.h>
9#include <linux/mutex.h>
10#include <linux/errno.h>
11#include <linux/err.h>
12#include <linux/qcom_scm.h>
13#include <linux/arm-smccc.h>
14#include <linux/dma-mapping.h>
15
16#include "qcom_scm.h"
17
18static DEFINE_MUTEX(qcom_scm_lock);
19
20
21/**
22 * struct arm_smccc_args
23 * @args: The array of values used in registers in smc instruction
24 */
25struct arm_smccc_args {
26 unsigned long args[8];
27};
28
29
30/**
31 * struct scm_legacy_command - one SCM command buffer
32 * @len: total available memory for command and response
33 * @buf_offset: start of command buffer
34 * @resp_hdr_offset: start of response buffer
35 * @id: command to be executed
36 * @buf: buffer returned from scm_legacy_get_command_buffer()
37 *
38 * An SCM command is laid out in memory as follows:
39 *
40 * ------------------- <--- struct scm_legacy_command
41 * | command header |
42 * ------------------- <--- scm_legacy_get_command_buffer()
43 * | command buffer |
44 * ------------------- <--- struct scm_legacy_response and
45 * | response header | scm_legacy_command_to_response()
46 * ------------------- <--- scm_legacy_get_response_buffer()
47 * | response buffer |
48 * -------------------
49 *
50 * There can be arbitrary padding between the headers and buffers so
51 * you should always use the appropriate scm_legacy_get_*_buffer() routines
52 * to access the buffers in a safe manner.
53 */
54struct scm_legacy_command {
55 __le32 len;
56 __le32 buf_offset;
57 __le32 resp_hdr_offset;
58 __le32 id;
59 __le32 buf[0];
60};
61
62/**
63 * struct scm_legacy_response - one SCM response buffer
64 * @len: total available memory for response
65 * @buf_offset: start of response data relative to start of scm_legacy_response
66 * @is_complete: indicates if the command has finished processing
67 */
68struct scm_legacy_response {
69 __le32 len;
70 __le32 buf_offset;
71 __le32 is_complete;
72};
73
74/**
75 * scm_legacy_command_to_response() - Get a pointer to a scm_legacy_response
76 * @cmd: command
77 *
78 * Returns a pointer to a response for a command.
79 */
80static inline struct scm_legacy_response *scm_legacy_command_to_response(
81 const struct scm_legacy_command *cmd)
82{
83 return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
84}
85
86/**
87 * scm_legacy_get_command_buffer() - Get a pointer to a command buffer
88 * @cmd: command
89 *
90 * Returns a pointer to the command buffer of a command.
91 */
92static inline void *scm_legacy_get_command_buffer(
93 const struct scm_legacy_command *cmd)
94{
95 return (void *)cmd->buf;
96}
97
98/**
99 * scm_legacy_get_response_buffer() - Get a pointer to a response buffer
100 * @rsp: response
101 *
102 * Returns a pointer to a response buffer of a response.
103 */
104static inline void *scm_legacy_get_response_buffer(
105 const struct scm_legacy_response *rsp)
106{
107 return (void *)rsp + le32_to_cpu(rsp->buf_offset);
108}
109
110static void __scm_legacy_do(const struct arm_smccc_args *smc,
111 struct arm_smccc_res *res)
112{
113 do {
114 arm_smccc_smc(smc->args[0], smc->args[1], smc->args[2],
115 smc->args[3], smc->args[4], smc->args[5],
116 smc->args[6], smc->args[7], res);
117 } while (res->a0 == QCOM_SCM_INTERRUPTED);
118}
119
120/**
121 * qcom_scm_call() - Sends a command to the SCM and waits for the command to
122 * finish processing.
123 *
124 * A note on cache maintenance:
125 * Note that any buffers that are expected to be accessed by the secure world
126 * must be flushed before invoking qcom_scm_call and invalidated in the cache
127 * immediately after qcom_scm_call returns. Cache maintenance on the command
128 * and response buffers is taken care of by qcom_scm_call; however, callers are
129 * responsible for any other cached buffers passed over to the secure world.
130 */
131int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
132 struct qcom_scm_res *res)
133{
134 u8 arglen = desc->arginfo & 0xf;
135 int ret = 0, context_id;
136 unsigned int i;
137 struct scm_legacy_command *cmd;
138 struct scm_legacy_response *rsp;
139 struct arm_smccc_args smc = {0};
140 struct arm_smccc_res smc_res;
141 const size_t cmd_len = arglen * sizeof(__le32);
142 const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32);
143 size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;
144 dma_addr_t cmd_phys;
145 __le32 *arg_buf;
146 const __le32 *res_buf;
147
148 cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
149 if (!cmd)
150 return -ENOMEM;
151
152 cmd->len = cpu_to_le32(alloc_len);
153 cmd->buf_offset = cpu_to_le32(sizeof(*cmd));
154 cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len);
155 cmd->id = cpu_to_le32(SCM_LEGACY_FNID(desc->svc, desc->cmd));
156
157 arg_buf = scm_legacy_get_command_buffer(cmd);
158 for (i = 0; i < arglen; i++)
159 arg_buf[i] = cpu_to_le32(desc->args[i]);
160
161 rsp = scm_legacy_command_to_response(cmd);
162
163 cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
164 if (dma_mapping_error(dev, cmd_phys)) {
165 kfree(cmd);
166 return -ENOMEM;
167 }
168
169 smc.args[0] = 1;
170 smc.args[1] = (unsigned long)&context_id;
171 smc.args[2] = cmd_phys;
172
173 mutex_lock(&qcom_scm_lock);
174 __scm_legacy_do(&smc, &smc_res);
175 if (smc_res.a0)
176 ret = qcom_scm_remap_error(smc_res.a0);
177 mutex_unlock(&qcom_scm_lock);
178 if (ret)
179 goto out;
180
181 do {
182 dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len,
183 sizeof(*rsp), DMA_FROM_DEVICE);
184 } while (!rsp->is_complete);
185
186 dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len +
187 le32_to_cpu(rsp->buf_offset),
188 resp_len, DMA_FROM_DEVICE);
189
190 if (res) {
191 res_buf = scm_legacy_get_response_buffer(rsp);
192 for (i = 0; i < MAX_QCOM_SCM_RETS; i++)
193 res->result[i] = le32_to_cpu(res_buf[i]);
194 }
195out:
196 dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
197 kfree(cmd);
198 return ret;
199}
200
201#define SCM_LEGACY_ATOMIC_N_REG_ARGS 5
202#define SCM_LEGACY_ATOMIC_FIRST_REG_IDX 2
203#define SCM_LEGACY_CLASS_REGISTER (0x2 << 8)
204#define SCM_LEGACY_MASK_IRQS BIT(5)
205#define SCM_LEGACY_ATOMIC_ID(svc, cmd, n) \
206 ((SCM_LEGACY_FNID(svc, cmd) << 12) | \
207 SCM_LEGACY_CLASS_REGISTER | \
208 SCM_LEGACY_MASK_IRQS | \
209 (n & 0xf))
210
211/**
212 * qcom_scm_call_atomic() - Send an atomic SCM command with up to 5 arguments
213 * and 3 return values
214 * @desc: SCM call descriptor containing arguments
215 * @res: SCM call return values
216 *
217 * This shall only be used with commands that are guaranteed to be
218 * uninterruptable, atomic and SMP safe.
219 */
220int scm_legacy_call_atomic(struct device *unused,
221 const struct qcom_scm_desc *desc,
222 struct qcom_scm_res *res)
223{
224 int context_id;
225 struct arm_smccc_res smc_res;
226 size_t arglen = desc->arginfo & 0xf;
227
228 BUG_ON(arglen > SCM_LEGACY_ATOMIC_N_REG_ARGS);
229
230 arm_smccc_smc(SCM_LEGACY_ATOMIC_ID(desc->svc, desc->cmd, arglen),
231 (unsigned long)&context_id,
232 desc->args[0], desc->args[1], desc->args[2],
233 desc->args[3], desc->args[4], 0, &smc_res);
234
235 if (res) {
236 res->result[0] = smc_res.a1;
237 res->result[1] = smc_res.a2;
238 res->result[2] = smc_res.a3;
239 }
240
241 return smc_res.a0;
242}
drivers/firmware/qcom_scm-smc.c+151−0
@@ -0,0 +1,151 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2015,2019 The Linux Foundation. All rights reserved.
3 */
4
5#include <linux/io.h>
6#include <linux/errno.h>
7#include <linux/delay.h>
8#include <linux/mutex.h>
9#include <linux/slab.h>
10#include <linux/types.h>
11#include <linux/qcom_scm.h>
12#include <linux/arm-smccc.h>
13#include <linux/dma-mapping.h>
14
15#include "qcom_scm.h"
16
17/**
18 * struct arm_smccc_args
19 * @args: The array of values used in registers in smc instruction
20 */
21struct arm_smccc_args {
22 unsigned long args[8];
23};
24
25static DEFINE_MUTEX(qcom_scm_lock);
26
27#define QCOM_SCM_EBUSY_WAIT_MS 30
28#define QCOM_SCM_EBUSY_MAX_RETRY 20
29
30#define SCM_SMC_N_REG_ARGS 4
31#define SCM_SMC_FIRST_EXT_IDX (SCM_SMC_N_REG_ARGS - 1)
32#define SCM_SMC_N_EXT_ARGS (MAX_QCOM_SCM_ARGS - SCM_SMC_N_REG_ARGS + 1)
33#define SCM_SMC_FIRST_REG_IDX 2
34#define SCM_SMC_LAST_REG_IDX (SCM_SMC_FIRST_REG_IDX + SCM_SMC_N_REG_ARGS - 1)
35
36static void __scm_smc_do_quirk(const struct arm_smccc_args *smc,
37 struct arm_smccc_res *res)
38{
39 unsigned long a0 = smc->args[0];
40 struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 };
41
42 quirk.state.a6 = 0;
43
44 do {
45 arm_smccc_smc_quirk(a0, smc->args[1], smc->args[2],
46 smc->args[3], smc->args[4], smc->args[5],
47 quirk.state.a6, smc->args[7], res, &quirk);
48
49 if (res->a0 == QCOM_SCM_INTERRUPTED)
50 a0 = res->a0;
51
52 } while (res->a0 == QCOM_SCM_INTERRUPTED);
53}
54
55static void __scm_smc_do(const struct arm_smccc_args *smc,
56 struct arm_smccc_res *res, bool atomic)
57{
58 int retry_count = 0;
59
60 if (atomic) {
61 __scm_smc_do_quirk(smc, res);
62 return;
63 }
64
65 do {
66 mutex_lock(&qcom_scm_lock);
67
68 __scm_smc_do_quirk(smc, res);
69
70 mutex_unlock(&qcom_scm_lock);
71
72 if (res->a0 == QCOM_SCM_V2_EBUSY) {
73 if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
74 break;
75 msleep(QCOM_SCM_EBUSY_WAIT_MS);
76 }
77 } while (res->a0 == QCOM_SCM_V2_EBUSY);
78}
79
80int scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
81 struct qcom_scm_res *res, bool atomic)
82{
83 int arglen = desc->arginfo & 0xf;
84 int i;
85 dma_addr_t args_phys = 0;
86 void *args_virt = NULL;
87 size_t alloc_len;
88 gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
89 u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL;
90 u32 qcom_smccc_convention =
91 (qcom_scm_convention == SMC_CONVENTION_ARM_32) ?
92 ARM_SMCCC_SMC_32 : ARM_SMCCC_SMC_64;
93 struct arm_smccc_res smc_res;
94 struct arm_smccc_args smc = {0};
95
96 smc.args[0] = ARM_SMCCC_CALL_VAL(
97 smccc_call_type,
98 qcom_smccc_convention,
99 desc->owner,
100 SCM_SMC_FNID(desc->svc, desc->cmd));
101 smc.args[1] = desc->arginfo;
102 for (i = 0; i < SCM_SMC_N_REG_ARGS; i++)
103 smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i];
104
105 if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
106 alloc_len = SCM_SMC_N_EXT_ARGS * sizeof(u64);
107 args_virt = kzalloc(PAGE_ALIGN(alloc_len), flag);
108
109 if (!args_virt)
110 return -ENOMEM;
111
112 if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
113 __le32 *args = args_virt;
114
115 for (i = 0; i < SCM_SMC_N_EXT_ARGS; i++)
116 args[i] = cpu_to_le32(desc->args[i +
117 SCM_SMC_FIRST_EXT_IDX]);
118 } else {
119 __le64 *args = args_virt;
120
121 for (i = 0; i < SCM_SMC_N_EXT_ARGS; i++)
122 args[i] = cpu_to_le64(desc->args[i +
123 SCM_SMC_FIRST_EXT_IDX]);
124 }
125
126 args_phys = dma_map_single(dev, args_virt, alloc_len,
127 DMA_TO_DEVICE);
128
129 if (dma_mapping_error(dev, args_phys)) {
130 kfree(args_virt);
131 return -ENOMEM;
132 }
133
134 smc.args[SCM_SMC_LAST_REG_IDX] = args_phys;
135 }
136
137 __scm_smc_do(&smc, &smc_res, atomic);
138
139 if (args_virt) {
140 dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
141 kfree(args_virt);
142 }
143
144 if (res) {
145 res->result[0] = smc_res.a1;
146 res->result[1] = smc_res.a2;
147 res->result[2] = smc_res.a3;
148 }
149
150 return (long)smc_res.a0 ? qcom_scm_remap_error(smc_res.a0) : 0;
151}
drivers/firmware/qcom_scm.c+669−185
@@ -1,8 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0-only1// SPDX-License-Identifier: GPL-2.0-only
2/*2/* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved.
3 * Qualcomm SCM driver
4 *
5 * Copyright (c) 2010,2015, The Linux Foundation. All rights reserved.
6 * Copyright (C) 2015 Linaro Ltd.3 * Copyright (C) 2015 Linaro Ltd.
7 */4 */
8#include <linux/platform_device.h>5#include <linux/platform_device.h>
@@ -19,6 +16,7 @@ · 10 unmodified lines
19#include <linux/of_platform.h>16#include <linux/of_platform.h>
20#include <linux/clk.h>17#include <linux/clk.h>
21#include <linux/reset-controller.h>18#include <linux/reset-controller.h>
19#include <linux/arm-smccc.h>
22 20
23#include "qcom_scm.h"21#include "qcom_scm.h"
24 22
@@ -52,6 +50,35 @@ struct qcom_scm_mem_map_info { · 27 unmodified lines
52 __le64 mem_size;50 __le64 mem_size;
53};51};
54 52
53#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
54#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
55#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
56#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
57
58#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
59#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
60#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
61#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
62
63struct qcom_scm_wb_entry {
64 int flag;
65 void *entry;
66};
67
68static struct qcom_scm_wb_entry qcom_scm_wb[] = {
69 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
70 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
71 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
72 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
73};
74
75static const char *qcom_scm_convention_names[] = {
76 [SMC_CONVENTION_UNKNOWN] = "unknown",
77 [SMC_CONVENTION_ARM_32] = "smc arm 32",
78 [SMC_CONVENTION_ARM_64] = "smc arm 64",
79 [SMC_CONVENTION_LEGACY] = "smc legacy",
80};
81
55static struct qcom_scm *__scm;82static struct qcom_scm *__scm;
56 83
57static int qcom_scm_clk_enable(void)84static int qcom_scm_clk_enable(void)
@@ -87,149 +114,308 @@ static void qcom_scm_clk_disable(void) · 29 unmodified lines
87 clk_disable_unprepare(__scm->bus_clk);114 clk_disable_unprepare(__scm->bus_clk);
88}115}
89 116
90/**117static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
91 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus118 u32 cmd_id);
92 * @entry: Entry point function for the cpus119
93 * @cpus: The cpumask of cpus that will use the entry point120enum qcom_scm_convention qcom_scm_convention;
94 *121static bool has_queried __read_mostly;
95 * Set the cold boot address of the cpus. Any cpu outside the supported122static DEFINE_SPINLOCK(query_lock);
96 * range would be removed from the cpu present mask.123
97 */124static void __query_convention(void)
98int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
99{125{
100 return __qcom_scm_set_cold_boot_addr(entry, cpus);126 unsigned long flags;
127 struct qcom_scm_desc desc = {
128 .svc = QCOM_SCM_SVC_INFO,
129 .cmd = QCOM_SCM_INFO_IS_CALL_AVAIL,
130 .args[0] = SCM_SMC_FNID(QCOM_SCM_SVC_INFO,
131 QCOM_SCM_INFO_IS_CALL_AVAIL) |
132 (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT),
133 .arginfo = QCOM_SCM_ARGS(1),
134 .owner = ARM_SMCCC_OWNER_SIP,
135 };
136 struct qcom_scm_res res;
137 int ret;
138
139 spin_lock_irqsave(&query_lock, flags);
140 if (has_queried)
141 goto out;
142
143 qcom_scm_convention = SMC_CONVENTION_ARM_64;
144 // Device isn't required as there is only one argument - no device
145 // needed to dma_map_single to secure world
146 ret = scm_smc_call(NULL, &desc, &res, true);
147 if (!ret && res.result[0] == 1)
148 goto out;
149
150 qcom_scm_convention = SMC_CONVENTION_ARM_32;
151 ret = scm_smc_call(NULL, &desc, &res, true);
152 if (!ret && res.result[0] == 1)
153 goto out;
154
155 qcom_scm_convention = SMC_CONVENTION_LEGACY;
156out:
157 has_queried = true;
158 spin_unlock_irqrestore(&query_lock, flags);
159 pr_info("qcom_scm: convention: %s\n",
160 qcom_scm_convention_names[qcom_scm_convention]);
101}161}
102EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
103 162
104/**163static inline enum qcom_scm_convention __get_convention(void)
105 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
106 * @entry: Entry point function for the cpus
107 * @cpus: The cpumask of cpus that will use the entry point
108 *
109 * Set the Linux entry point for the SCM to transfer control to when coming
110 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
111 */
112int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
113{164{
114 return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);165 if (unlikely(!has_queried))
166 __query_convention();
167 return qcom_scm_convention;
115}168}
116EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
117 169
118/**170/**
119 * qcom_scm_cpu_power_down() - Power down the cpu171 * qcom_scm_call() - Invoke a syscall in the secure world
120 * @flags - Flags to flush cache172 * @dev: device
173 * @svc_id: service identifier
174 * @cmd_id: command identifier
175 * @desc: Descriptor structure containing arguments and return values
121 *176 *
122 * This is an end point to power down cpu. If there was a pending interrupt,177 * Sends a command to the SCM and waits for the command to finish processing.
123 * the control would return from this function, otherwise, the cpu jumps to the178 * This should *only* be called in pre-emptible context.
124 * warm boot entry point set for this cpu upon reset.
125 */179 */
126void qcom_scm_cpu_power_down(u32 flags)180static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc,
181 struct qcom_scm_res *res)
127{182{
128 __qcom_scm_cpu_power_down(flags);183 might_sleep();
184 switch (__get_convention()) {
185 case SMC_CONVENTION_ARM_32:
186 case SMC_CONVENTION_ARM_64:
187 return scm_smc_call(dev, desc, res, false);
188 case SMC_CONVENTION_LEGACY:
189 return scm_legacy_call(dev, desc, res);
190 default:
191 pr_err("Unknown current SCM calling convention.\n");
192 return -EINVAL;
193 }
129}194}
130EXPORT_SYMBOL(qcom_scm_cpu_power_down);
131 195
132/**196/**
133 * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.197 * qcom_scm_call_atomic() - atomic variation of qcom_scm_call()
198 * @dev: device
199 * @svc_id: service identifier
200 * @cmd_id: command identifier
201 * @desc: Descriptor structure containing arguments and return values
202 * @res: Structure containing results from SMC/HVC call
134 *203 *
135 * Return true if HDCP is supported, false if not.204 * Sends a command to the SCM and waits for the command to finish processing.
205 * This can be called in atomic context.
136 */206 */
137bool qcom_scm_hdcp_available(void)207static int qcom_scm_call_atomic(struct device *dev,
208 const struct qcom_scm_desc *desc,
209 struct qcom_scm_res *res)
138{210{
139 int ret = qcom_scm_clk_enable();211 switch (__get_convention()) {
140 212 case SMC_CONVENTION_ARM_32:
141 if (ret)213 case SMC_CONVENTION_ARM_64:
142 return ret;214 return scm_smc_call(dev, desc, res, true);
215 case SMC_CONVENTION_LEGACY:
216 return scm_legacy_call_atomic(dev, desc, res);
217 default:
218 pr_err("Unknown current SCM calling convention.\n");
219 return -EINVAL;
220 }
221}
143 222
144 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,223static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
145 QCOM_SCM_CMD_HDCP);224 u32 cmd_id)
225{
226 int ret;
227 struct qcom_scm_desc desc = {
228 .svc = QCOM_SCM_SVC_INFO,
229 .cmd = QCOM_SCM_INFO_IS_CALL_AVAIL,
230 .owner = ARM_SMCCC_OWNER_SIP,
231 };
232 struct qcom_scm_res res;
233
234 desc.arginfo = QCOM_SCM_ARGS(1);
235 switch (__get_convention()) {
236 case SMC_CONVENTION_ARM_32:
237 case SMC_CONVENTION_ARM_64:
238 desc.args[0] = SCM_SMC_FNID(svc_id, cmd_id) |
239 (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
240 break;
241 case SMC_CONVENTION_LEGACY:
242 desc.args[0] = SCM_LEGACY_FNID(svc_id, cmd_id);
243 break;
244 default:
245 pr_err("Unknown SMC convention being used\n");
246 return -EINVAL;
247 }
146 248
147 qcom_scm_clk_disable();249 ret = qcom_scm_call(dev, &desc, &res);
148 250
149 return ret > 0 ? true : false;251 return ret ? : res.result[0];
150}252}
151EXPORT_SYMBOL(qcom_scm_hdcp_available);
152 253
153/**254/**
154 * qcom_scm_hdcp_req() - Send HDCP request.255 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
155 * @req: HDCP request array256 * @entry: Entry point function for the cpus
156 * @req_cnt: HDCP request array count257 * @cpus: The cpumask of cpus that will use the entry point
157 * @resp: response buffer passed to SCM
158 *258 *
159 * Write HDCP register(s) through SCM.259 * Set the Linux entry point for the SCM to transfer control to when coming
260 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
160 */261 */
161int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)262int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
162{263{
163 int ret = qcom_scm_clk_enable();264 int ret;
265 int flags = 0;
266 int cpu;
267 struct qcom_scm_desc desc = {
268 .svc = QCOM_SCM_SVC_BOOT,
269 .cmd = QCOM_SCM_BOOT_SET_ADDR,
270 .arginfo = QCOM_SCM_ARGS(2),
271 };
164 272
165 if (ret)273 /*
166 return ret;274 * Reassign only if we are switching from hotplug entry point
275 * to cpuidle entry point or vice versa.
276 */
277 for_each_cpu(cpu, cpus) {
278 if (entry == qcom_scm_wb[cpu].entry)
279 continue;
280 flags |= qcom_scm_wb[cpu].flag;
281 }
282
283 /* No change in entry function */
284 if (!flags)
285 return 0;
286
287 desc.args[0] = flags;
288 desc.args[1] = virt_to_phys(entry);
289
290 ret = qcom_scm_call(__scm->dev, &desc, NULL);
291 if (!ret) {
292 for_each_cpu(cpu, cpus)
293 qcom_scm_wb[cpu].entry = entry;
294 }
167 295
168 ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
169 qcom_scm_clk_disable();
170 return ret;296 return ret;
171}297}
172EXPORT_SYMBOL(qcom_scm_hdcp_req);298EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
173 299
174/**300/**
175 * qcom_scm_pas_supported() - Check if the peripheral authentication service is301 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
176 * available for the given peripherial302 * @entry: Entry point function for the cpus
177 * @peripheral: peripheral id303 * @cpus: The cpumask of cpus that will use the entry point
178 *304 *
179 * Returns true if PAS is supported for this peripheral, otherwise false.305 * Set the cold boot address of the cpus. Any cpu outside the supported
306 * range would be removed from the cpu present mask.
180 */307 */
181bool qcom_scm_pas_supported(u32 peripheral)308int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
182{309{
183 int ret;310 int flags = 0;
311 int cpu;
312 int scm_cb_flags[] = {
313 QCOM_SCM_FLAG_COLDBOOT_CPU0,
314 QCOM_SCM_FLAG_COLDBOOT_CPU1,
315 QCOM_SCM_FLAG_COLDBOOT_CPU2,
316 QCOM_SCM_FLAG_COLDBOOT_CPU3,
317 };
318 struct qcom_scm_desc desc = {
319 .svc = QCOM_SCM_SVC_BOOT,
320 .cmd = QCOM_SCM_BOOT_SET_ADDR,
321 .arginfo = QCOM_SCM_ARGS(2),
322 .owner = ARM_SMCCC_OWNER_SIP,
323 };
324
325 if (!cpus || (cpus && cpumask_empty(cpus)))
326 return -EINVAL;
184 327
185 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,328 for_each_cpu(cpu, cpus) {
186 QCOM_SCM_PAS_IS_SUPPORTED_CMD);329 if (cpu < ARRAY_SIZE(scm_cb_flags))
187 if (ret <= 0)330 flags |= scm_cb_flags[cpu];
188 return false;331 else
332 set_cpu_present(cpu, false);
333 }
334
335 desc.args[0] = flags;
336 desc.args[1] = virt_to_phys(entry);
189 337
190 return __qcom_scm_pas_supported(__scm->dev, peripheral);338 return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
191}339}
192EXPORT_SYMBOL(qcom_scm_pas_supported);340EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
193 341
194/**342/**
195 * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available343 * qcom_scm_cpu_power_down() - Power down the cpu
344 * @flags - Flags to flush cache
345 *
346 * This is an end point to power down cpu. If there was a pending interrupt,
347 * the control would return from this function, otherwise, the cpu jumps to the
348 * warm boot entry point set for this cpu upon reset.
196 */349 */
197bool qcom_scm_ocmem_lock_available(void)350void qcom_scm_cpu_power_down(u32 flags)
198{351{
199 return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_OCMEM_SVC,352 struct qcom_scm_desc desc = {
200 QCOM_SCM_OCMEM_LOCK_CMD);353 .svc = QCOM_SCM_SVC_BOOT,
354 .cmd = QCOM_SCM_BOOT_TERMINATE_PC,
355 .args[0] = flags & QCOM_SCM_FLUSH_FLAG_MASK,
356 .arginfo = QCOM_SCM_ARGS(1),
357 .owner = ARM_SMCCC_OWNER_SIP,
358 };
359
360 qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
201}361}
202EXPORT_SYMBOL(qcom_scm_ocmem_lock_available);362EXPORT_SYMBOL(qcom_scm_cpu_power_down);
203 363
204/**364int qcom_scm_set_remote_state(u32 state, u32 id)
205 * qcom_scm_ocmem_lock() - call OCMEM lock interface to assign an OCMEM
206 * region to the specified initiator
207 *
208 * @id: tz initiator id
209 * @offset: OCMEM offset
210 * @size: OCMEM size
211 * @mode: access mode (WIDE/NARROW)
212 */
213int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, u32 size,
214 u32 mode)
215{365{
216 return __qcom_scm_ocmem_lock(__scm->dev, id, offset, size, mode);366 struct qcom_scm_desc desc = {
367 .svc = QCOM_SCM_SVC_BOOT,
368 .cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE,
369 .arginfo = QCOM_SCM_ARGS(2),
370 .args[0] = state,
371 .args[1] = id,
372 .owner = ARM_SMCCC_OWNER_SIP,
373 };
374 struct qcom_scm_res res;
375 int ret;
376
377 ret = qcom_scm_call(__scm->dev, &desc, &res);
378
379 return ret ? : res.result[0];
217}380}
218EXPORT_SYMBOL(qcom_scm_ocmem_lock);381EXPORT_SYMBOL(qcom_scm_set_remote_state);
219 382
220/**383static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
221 * qcom_scm_ocmem_unlock() - call OCMEM unlock interface to release an OCMEM
222 * region from the specified initiator
223 *
224 * @id: tz initiator id
225 * @offset: OCMEM offset
226 * @size: OCMEM size
227 */
228int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size)
229{384{
230 return __qcom_scm_ocmem_unlock(__scm->dev, id, offset, size);385 struct qcom_scm_desc desc = {
386 .svc = QCOM_SCM_SVC_BOOT,
387 .cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE,
388 .arginfo = QCOM_SCM_ARGS(2),
389 .args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE,
390 .owner = ARM_SMCCC_OWNER_SIP,
391 };
392
393 desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0;
394
395 return qcom_scm_call(__scm->dev, &desc, NULL);
396}
397
398static void qcom_scm_set_download_mode(bool enable)
399{
400 bool avail;
401 int ret = 0;
402
403 avail = __qcom_scm_is_call_available(__scm->dev,
404 QCOM_SCM_SVC_BOOT,
405 QCOM_SCM_BOOT_SET_DLOAD_MODE);
406 if (avail) {
407 ret = __qcom_scm_set_dload_mode(__scm->dev, enable);
408 } else if (__scm->dload_mode_addr) {
409 ret = qcom_scm_io_writel(__scm->dload_mode_addr,
410 enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0);
411 } else {
412 dev_err(__scm->dev,
413 "No available mechanism for setting download mode\n");
414 }
415
416 if (ret)
417 dev_err(__scm->dev, "failed to set download mode: %d\n", ret);
231}418}
232EXPORT_SYMBOL(qcom_scm_ocmem_unlock);
233 419
234/**420/**
235 * qcom_scm_pas_init_image() - Initialize peripheral authentication service421 * qcom_scm_pas_init_image() - Initialize peripheral authentication service
@@ -248,6 +434,14 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) · 12 unmodified lines
248 dma_addr_t mdata_phys;434 dma_addr_t mdata_phys;
249 void *mdata_buf;435 void *mdata_buf;
250 int ret;436 int ret;
437 struct qcom_scm_desc desc = {
438 .svc = QCOM_SCM_SVC_PIL,
439 .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE,
440 .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW),
441 .args[0] = peripheral,
442 .owner = ARM_SMCCC_OWNER_SIP,
443 };
444 struct qcom_scm_res res;
251 445
252 /*446 /*
253 * During the scm call memory protection will be enabled for the meta447 * During the scm call memory protection will be enabled for the meta
@@ -266,14 +460,16 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) · 12 unmodified lines
266 if (ret)460 if (ret)
267 goto free_metadata;461 goto free_metadata;
268 462
269 ret = __qcom_scm_pas_init_image(__scm->dev, peripheral, mdata_phys);463 desc.args[1] = mdata_phys;
464
465 ret = qcom_scm_call(__scm->dev, &desc, &res);
270 466
271 qcom_scm_clk_disable();467 qcom_scm_clk_disable();
272 468
273free_metadata:469free_metadata:
274 dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);470 dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
275 471
276 return ret;472 return ret ? : res.result[0];
277}473}
278EXPORT_SYMBOL(qcom_scm_pas_init_image);474EXPORT_SYMBOL(qcom_scm_pas_init_image);
279 475
@@ -289,15 +485,25 @@ EXPORT_SYMBOL(qcom_scm_pas_init_image); · 9 unmodified lines
289int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)485int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
290{486{
291 int ret;487 int ret;
488 struct qcom_scm_desc desc = {
489 .svc = QCOM_SCM_SVC_PIL,
490 .cmd = QCOM_SCM_PIL_PAS_MEM_SETUP,
491 .arginfo = QCOM_SCM_ARGS(3),
492 .args[0] = peripheral,
493 .args[1] = addr,
494 .args[2] = size,
495 .owner = ARM_SMCCC_OWNER_SIP,
496 };
497 struct qcom_scm_res res;
292 498
293 ret = qcom_scm_clk_enable();499 ret = qcom_scm_clk_enable();
294 if (ret)500 if (ret)
295 return ret;501 return ret;
296 502
297 ret = __qcom_scm_pas_mem_setup(__scm->dev, peripheral, addr, size);503 ret = qcom_scm_call(__scm->dev, &desc, &res);
298 qcom_scm_clk_disable();504 qcom_scm_clk_disable();
299 505
300 return ret;506 return ret ? : res.result[0];
301}507}
302EXPORT_SYMBOL(qcom_scm_pas_mem_setup);508EXPORT_SYMBOL(qcom_scm_pas_mem_setup);
303 509
@@ -311,15 +517,23 @@ EXPORT_SYMBOL(qcom_scm_pas_mem_setup); · 7 unmodified lines
311int qcom_scm_pas_auth_and_reset(u32 peripheral)517int qcom_scm_pas_auth_and_reset(u32 peripheral)
312{518{
313 int ret;519 int ret;
520 struct qcom_scm_desc desc = {
521 .svc = QCOM_SCM_SVC_PIL,
522 .cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET,
523 .arginfo = QCOM_SCM_ARGS(1),
524 .args[0] = peripheral,
525 .owner = ARM_SMCCC_OWNER_SIP,
526 };
527 struct qcom_scm_res res;
314 528
315 ret = qcom_scm_clk_enable();529 ret = qcom_scm_clk_enable();
316 if (ret)530 if (ret)
317 return ret;531 return ret;
318 532
319 ret = __qcom_scm_pas_auth_and_reset(__scm->dev, peripheral);533 ret = qcom_scm_call(__scm->dev, &desc, &res);
320 qcom_scm_clk_disable();534 qcom_scm_clk_disable();
321 535
322 return ret;536 return ret ? : res.result[0];
323}537}
324EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);538EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);
325 539
@@ -332,18 +546,75 @@ EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset); · 6 unmodified lines
332int qcom_scm_pas_shutdown(u32 peripheral)546int qcom_scm_pas_shutdown(u32 peripheral)
333{547{
334 int ret;548 int ret;
549 struct qcom_scm_desc desc = {
550 .svc = QCOM_SCM_SVC_PIL,
551 .cmd = QCOM_SCM_PIL_PAS_SHUTDOWN,
552 .arginfo = QCOM_SCM_ARGS(1),
553 .args[0] = peripheral,
554 .owner = ARM_SMCCC_OWNER_SIP,
555 };
556 struct qcom_scm_res res;
335 557
336 ret = qcom_scm_clk_enable();558 ret = qcom_scm_clk_enable();
337 if (ret)559 if (ret)
338 return ret;560 return ret;
339 561
340 ret = __qcom_scm_pas_shutdown(__scm->dev, peripheral);562 ret = qcom_scm_call(__scm->dev, &desc, &res);
563
341 qcom_scm_clk_disable();564 qcom_scm_clk_disable();
342 565
343 return ret;566 return ret ? : res.result[0];
344}567}
345EXPORT_SYMBOL(qcom_scm_pas_shutdown);568EXPORT_SYMBOL(qcom_scm_pas_shutdown);
346 569
570/**
571 * qcom_scm_pas_supported() - Check if the peripheral authentication service is
572 * available for the given peripherial
573 * @peripheral: peripheral id
574 *
575 * Returns true if PAS is supported for this peripheral, otherwise false.
576 */
577bool qcom_scm_pas_supported(u32 peripheral)
578{
579 int ret;
580 struct qcom_scm_desc desc = {
581 .svc = QCOM_SCM_SVC_PIL,
582 .cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED,
583 .arginfo = QCOM_SCM_ARGS(1),
584 .args[0] = peripheral,
585 .owner = ARM_SMCCC_OWNER_SIP,
586 };
587 struct qcom_scm_res res;
588
589 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
590 QCOM_SCM_PIL_PAS_IS_SUPPORTED);
591 if (ret <= 0)
592 return false;
593
594 ret = qcom_scm_call(__scm->dev, &desc, &res);
595
596 return ret ? false : !!res.result[0];
597}
598EXPORT_SYMBOL(qcom_scm_pas_supported);
599
600static int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
601{
602 struct qcom_scm_desc desc = {
603 .svc = QCOM_SCM_SVC_PIL,
604 .cmd = QCOM_SCM_PIL_PAS_MSS_RESET,
605 .arginfo = QCOM_SCM_ARGS(2),
606 .args[0] = reset,
607 .args[1] = 0,
608 .owner = ARM_SMCCC_OWNER_SIP,
609 };
610 struct qcom_scm_res res;
611 int ret;
612
613 ret = qcom_scm_call(__scm->dev, &desc, &res);
614
615 return ret ? : res.result[0];
616}
617
347static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev,618static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev,
348 unsigned long idx)619 unsigned long idx)
349{620{
@@ -367,6 +638,43 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = { · 17 unmodified lines
367 .deassert = qcom_scm_pas_reset_deassert,638 .deassert = qcom_scm_pas_reset_deassert,
368};639};
369 640
641int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)
642{
643 struct qcom_scm_desc desc = {
644 .svc = QCOM_SCM_SVC_IO,
645 .cmd = QCOM_SCM_IO_READ,
646 .arginfo = QCOM_SCM_ARGS(1),
647 .args[0] = addr,
648 .owner = ARM_SMCCC_OWNER_SIP,
649 };
650 struct qcom_scm_res res;
651 int ret;
652
653
654 ret = qcom_scm_call(__scm->dev, &desc, &res);
655 if (ret >= 0)
656 *val = res.result[0];
657
658 return ret < 0 ? ret : 0;
659}
660EXPORT_SYMBOL(qcom_scm_io_readl);
661
662int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)
663{
664 struct qcom_scm_desc desc = {
665 .svc = QCOM_SCM_SVC_IO,
666 .cmd = QCOM_SCM_IO_WRITE,
667 .arginfo = QCOM_SCM_ARGS(2),
668 .args[0] = addr,
669 .args[1] = val,
670 .owner = ARM_SMCCC_OWNER_SIP,
671 };
672
673
674 return qcom_scm_call(__scm->dev, &desc, NULL);
675}
676EXPORT_SYMBOL(qcom_scm_io_writel);
677
370/**678/**
371 * qcom_scm_restore_sec_cfg_available() - Check if secure environment679 * qcom_scm_restore_sec_cfg_available() - Check if secure environment
372 * supports restore security config interface.680 * supports restore security config interface.
@@ -376,108 +684,106 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = { · 3 unmodified lines
376bool qcom_scm_restore_sec_cfg_available(void)684bool qcom_scm_restore_sec_cfg_available(void)
377{685{
378 return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP,686 return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP,
379 QCOM_SCM_RESTORE_SEC_CFG);687 QCOM_SCM_MP_RESTORE_SEC_CFG);
380}688}
381EXPORT_SYMBOL(qcom_scm_restore_sec_cfg_available);689EXPORT_SYMBOL(qcom_scm_restore_sec_cfg_available);
382 690
383int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)691int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
384{692{
385 return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare);693 struct qcom_scm_desc desc = {
386}694 .svc = QCOM_SCM_SVC_MP,
387EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);695 .cmd = QCOM_SCM_MP_RESTORE_SEC_CFG,
388 696 .arginfo = QCOM_SCM_ARGS(2),
389int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)697 .args[0] = device_id,
390{698 .args[1] = spare,
391 return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size);699 .owner = ARM_SMCCC_OWNER_SIP,
392}700 };
393EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);701 struct qcom_scm_res res;
394 702 int ret;
395int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
396{
397 return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare);
398}
399EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
400 703
401int qcom_scm_qsmmu500_wait_safe_toggle(bool en)704 ret = qcom_scm_call(__scm->dev, &desc, &res);
402{
403 return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en);
404}
405EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle);
406 705
407int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)706 return ret ? : res.result[0];
408{
409 return __qcom_scm_io_readl(__scm->dev, addr, val);
410}707}
411EXPORT_SYMBOL(qcom_scm_io_readl);708EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
412 709
413int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)710int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
414{711{
415 return __qcom_scm_io_writel(__scm->dev, addr, val);712 struct qcom_scm_desc desc = {
416}713 .svc = QCOM_SCM_SVC_MP,
417EXPORT_SYMBOL(qcom_scm_io_writel);714 .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE,
715 .arginfo = QCOM_SCM_ARGS(1),
716 .args[0] = spare,
717 .owner = ARM_SMCCC_OWNER_SIP,
718 };
719 struct qcom_scm_res res;
720 int ret;
418 721
419static void qcom_scm_set_download_mode(bool enable)722 ret = qcom_scm_call(__scm->dev, &desc, &res);
420{
421 bool avail;
422 int ret = 0;
423 723
424 avail = __qcom_scm_is_call_available(__scm->dev,724 if (size)
425 QCOM_SCM_SVC_BOOT,725 *size = res.result[0];
426 QCOM_SCM_SET_DLOAD_MODE);
427 if (avail) {
428 ret = __qcom_scm_set_dload_mode(__scm->dev, enable);
429 } else if (__scm->dload_mode_addr) {
430 ret = __qcom_scm_io_writel(__scm->dev, __scm->dload_mode_addr,
431 enable ? QCOM_SCM_SET_DLOAD_MODE : 0);
432 } else {
433 dev_err(__scm->dev,
434 "No available mechanism for setting download mode\n");
435 }
436 726
437 if (ret)727 return ret ? : res.result[1];
438 dev_err(__scm->dev, "failed to set download mode: %d\n", ret);
439}728}
729EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
440 730
441static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)731int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
442{732{
443 struct device_node *tcsr;733 struct qcom_scm_desc desc = {
444 struct device_node *np = dev->of_node;734 .svc = QCOM_SCM_SVC_MP,
445 struct resource res;735 .cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT,
446 u32 offset;736 .arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
737 QCOM_SCM_VAL),
738 .args[0] = addr,
739 .args[1] = size,
740 .args[2] = spare,
741 .owner = ARM_SMCCC_OWNER_SIP,
742 };
447 int ret;743 int ret;
448 744
449 tcsr = of_parse_phandle(np, "qcom,dload-mode", 0);745 desc.args[0] = addr;
450 if (!tcsr)746 desc.args[1] = size;
451 return 0;747 desc.args[2] = spare;
452 748 desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
453 ret = of_address_to_resource(tcsr, 0, &res);749 QCOM_SCM_VAL);
454 of_node_put(tcsr);
455 if (ret)
456 return ret;
457
458 ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset);
459 if (ret < 0)
460 return ret;
461 750
462 *addr = res.start + offset;751 ret = qcom_scm_call(__scm->dev, &desc, NULL);
463 752
464 return 0;753 /* the pg table has been initialized already, ignore the error */
465}754 if (ret == -EPERM)
755 ret = 0;
466 756
467/**757 return ret;
468 * qcom_scm_is_available() - Checks if SCM is available
469 */
470bool qcom_scm_is_available(void)
471{
472 return !!__scm;
473}758}
474EXPORT_SYMBOL(qcom_scm_is_available);759EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
475 760
476int qcom_scm_set_remote_state(u32 state, u32 id)761static int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
762 size_t mem_sz, phys_addr_t src, size_t src_sz,
763 phys_addr_t dest, size_t dest_sz)
477{764{
478 return __qcom_scm_set_remote_state(__scm->dev, state, id);765 int ret;
766 struct qcom_scm_desc desc = {
767 .svc = QCOM_SCM_SVC_MP,
768 .cmd = QCOM_SCM_MP_ASSIGN,
769 .arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL,
770 QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO,
771 QCOM_SCM_VAL, QCOM_SCM_VAL),
772 .args[0] = mem_region,
773 .args[1] = mem_sz,
774 .args[2] = src,
775 .args[3] = src_sz,
776 .args[4] = dest,
777 .args[5] = dest_sz,
778 .args[6] = 0,
779 .owner = ARM_SMCCC_OWNER_SIP,
780 };
781 struct qcom_scm_res res;
782
783 ret = qcom_scm_call(dev, &desc, &res);
784
785 return ret ? : res.result[0];
479}786}
480EXPORT_SYMBOL(qcom_scm_set_remote_state);
481 787
482/**788/**
483 * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership789 * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership
@@ -561,6 +867,184 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, · 77 unmodified lines
561}867}
562EXPORT_SYMBOL(qcom_scm_assign_mem);868EXPORT_SYMBOL(qcom_scm_assign_mem);
563 869
870/**
871 * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available
872 */
873bool qcom_scm_ocmem_lock_available(void)
874{
875 return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_OCMEM,
876 QCOM_SCM_OCMEM_LOCK_CMD);
877}
878EXPORT_SYMBOL(qcom_scm_ocmem_lock_available);
879
880/**
881 * qcom_scm_ocmem_lock() - call OCMEM lock interface to assign an OCMEM
882 * region to the specified initiator
883 *
884 * @id: tz initiator id
885 * @offset: OCMEM offset
886 * @size: OCMEM size
887 * @mode: access mode (WIDE/NARROW)
888 */
889int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, u32 size,
890 u32 mode)
891{
892 struct qcom_scm_desc desc = {
893 .svc = QCOM_SCM_SVC_OCMEM,
894 .cmd = QCOM_SCM_OCMEM_LOCK_CMD,
895 .args[0] = id,
896 .args[1] = offset,
897 .args[2] = size,
898 .args[3] = mode,
899 .arginfo = QCOM_SCM_ARGS(4),
900 };
901
902 return qcom_scm_call(__scm->dev, &desc, NULL);
903}
904EXPORT_SYMBOL(qcom_scm_ocmem_lock);
905
906/**
907 * qcom_scm_ocmem_unlock() - call OCMEM unlock interface to release an OCMEM
908 * region from the specified initiator
909 *
910 * @id: tz initiator id
911 * @offset: OCMEM offset
912 * @size: OCMEM size
913 */
914int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size)
915{
916 struct qcom_scm_desc desc = {
917 .svc = QCOM_SCM_SVC_OCMEM,
918 .cmd = QCOM_SCM_OCMEM_UNLOCK_CMD,
919 .args[0] = id,
920 .args[1] = offset,
921 .args[2] = size,
922 .arginfo = QCOM_SCM_ARGS(3),
923 };
924
925 return qcom_scm_call(__scm->dev, &desc, NULL);
926}
927EXPORT_SYMBOL(qcom_scm_ocmem_unlock);
928
929/**
930 * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
931 *
932 * Return true if HDCP is supported, false if not.
933 */
934bool qcom_scm_hdcp_available(void)
935{
936 int ret = qcom_scm_clk_enable();
937
938 if (ret)
939 return ret;
940
941 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
942 QCOM_SCM_HDCP_INVOKE);
943
944 qcom_scm_clk_disable();
945
946 return ret > 0 ? true : false;
947}
948EXPORT_SYMBOL(qcom_scm_hdcp_available);
949
950/**
951 * qcom_scm_hdcp_req() - Send HDCP request.
952 * @req: HDCP request array
953 * @req_cnt: HDCP request array count
954 * @resp: response buffer passed to SCM
955 *
956 * Write HDCP register(s) through SCM.
957 */
958int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
959{
960 int ret;
961 struct qcom_scm_desc desc = {
962 .svc = QCOM_SCM_SVC_HDCP,
963 .cmd = QCOM_SCM_HDCP_INVOKE,
964 .arginfo = QCOM_SCM_ARGS(10),
965 .args = {
966 req[0].addr,
967 req[0].val,
968 req[1].addr,
969 req[1].val,
970 req[2].addr,
971 req[2].val,
972 req[3].addr,
973 req[3].val,
974 req[4].addr,
975 req[4].val
976 },
977 .owner = ARM_SMCCC_OWNER_SIP,
978 };
979 struct qcom_scm_res res;
980
981 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
982 return -ERANGE;
983
984 ret = qcom_scm_clk_enable();
985 if (ret)
986 return ret;
987
988 ret = qcom_scm_call(__scm->dev, &desc, &res);
989 *resp = res.result[0];
990
991 qcom_scm_clk_disable();
992
993 return ret;
994}
995EXPORT_SYMBOL(qcom_scm_hdcp_req);
996
997int qcom_scm_qsmmu500_wait_safe_toggle(bool en)
998{
999 struct qcom_scm_desc desc = {
1000 .svc = QCOM_SCM_SVC_SMMU_PROGRAM,
1001 .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1,
1002 .arginfo = QCOM_SCM_ARGS(2),
1003 .args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL,
1004 .args[1] = en,
1005 .owner = ARM_SMCCC_OWNER_SIP,
1006 };
1007
1008
1009 return qcom_scm_call_atomic(__scm->dev, &desc, NULL);
1010}
1011EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle);
1012
1013static int qcom_scm_find_dload_address(struct device *dev, u64 *addr)
1014{
1015 struct device_node *tcsr;
1016 struct device_node *np = dev->of_node;
1017 struct resource res;
1018 u32 offset;
1019 int ret;
1020
1021 tcsr = of_parse_phandle(np, "qcom,dload-mode", 0);
1022 if (!tcsr)
1023 return 0;
1024
1025 ret = of_address_to_resource(tcsr, 0, &res);
1026 of_node_put(tcsr);
1027 if (ret)
1028 return ret;
1029
1030 ret = of_property_read_u32_index(np, "qcom,dload-mode", 1, &offset);
1031 if (ret < 0)
1032 return ret;
1033
1034 *addr = res.start + offset;
1035
1036 return 0;
1037}
1038
1039/**
1040 * qcom_scm_is_available() - Checks if SCM is available
1041 */
1042bool qcom_scm_is_available(void)
1043{
1044 return !!__scm;
1045}
1046EXPORT_SYMBOL(qcom_scm_is_available);
1047
564static int qcom_scm_probe(struct platform_device *pdev)1048static int qcom_scm_probe(struct platform_device *pdev)
565{1049{
566 struct qcom_scm *scm;1050 struct qcom_scm *scm;
@@ -631,7 +1115,7 @@ static int qcom_scm_probe(struct platform_device *pdev) · 64 unmodified lines
631 __scm = scm;1115 __scm = scm;
632 __scm->dev = &pdev->dev;1116 __scm->dev = &pdev->dev;
633 1117
634 __qcom_scm_init();1118 __query_convention();
635 1119
636 /*1120 /*
637 * If requested enable "download mode", from this point on warmboot1121 * If requested enable "download mode", from this point on warmboot
drivers/firmware/qcom_scm.h+101−77
@@ -1,71 +1,116 @@
1/* SPDX-License-Identifier: GPL-2.0-only */1/* SPDX-License-Identifier: GPL-2.0-only */
2/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.2/* Copyright (c) 2010-2015,2019 The Linux Foundation. All rights reserved.
3 */3 */
4#ifndef __QCOM_SCM_INT_H4#ifndef __QCOM_SCM_INT_H
5#define __QCOM_SCM_INT_H5#define __QCOM_SCM_INT_H
6 6
7#define QCOM_SCM_SVC_BOOT 0x17enum qcom_scm_convention {
8#define QCOM_SCM_BOOT_ADDR 0x18 SMC_CONVENTION_UNKNOWN,
9#define QCOM_SCM_SET_DLOAD_MODE 0x109 SMC_CONVENTION_LEGACY,
10#define QCOM_SCM_BOOT_ADDR_MC 0x1110 SMC_CONVENTION_ARM_32,
11#define QCOM_SCM_SET_REMOTE_STATE 0xa11 SMC_CONVENTION_ARM_64,
12extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id);12};
13extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable);13
14 14extern enum qcom_scm_convention qcom_scm_convention;
15#define QCOM_SCM_FLAG_HLOS 0x0115
16#define QCOM_SCM_FLAG_COLDBOOT_MC 0x0216#define MAX_QCOM_SCM_ARGS 10
17#define QCOM_SCM_FLAG_WARMBOOT_MC 0x0417#define MAX_QCOM_SCM_RETS 3
18extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,18
19 const cpumask_t *cpus);19enum qcom_scm_arg_types {
20extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);20 QCOM_SCM_VAL,
21 21 QCOM_SCM_RO,
22#define QCOM_SCM_CMD_TERMINATE_PC 0x222 QCOM_SCM_RW,
23 QCOM_SCM_BUFVAL,
24};
25
26#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
27 (((a) & 0x3) << 4) | \
28 (((b) & 0x3) << 6) | \
29 (((c) & 0x3) << 8) | \
30 (((d) & 0x3) << 10) | \
31 (((e) & 0x3) << 12) | \
32 (((f) & 0x3) << 14) | \
33 (((g) & 0x3) << 16) | \
34 (((h) & 0x3) << 18) | \
35 (((i) & 0x3) << 20) | \
36 (((j) & 0x3) << 22) | \
37 ((num) & 0xf))
38
39#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
40
41
42/**
43 * struct qcom_scm_desc
44 * @arginfo: Metadata describing the arguments in args[]
45 * @args: The array of arguments for the secure syscall
46 */
47struct qcom_scm_desc {
48 u32 svc;
49 u32 cmd;
50 u32 arginfo;
51 u64 args[MAX_QCOM_SCM_ARGS];
52 u32 owner;
53};
54
55/**
56 * struct qcom_scm_res
57 * @result: The values returned by the secure syscall
58 */
59struct qcom_scm_res {
60 u64 result[MAX_QCOM_SCM_RETS];
61};
62
63#define SCM_SMC_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
64extern int scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
65 struct qcom_scm_res *res, bool atomic);
66
67#define SCM_LEGACY_FNID(s, c) (((s) << 10) | ((c) & 0x3ff))
68extern int scm_legacy_call_atomic(struct device *dev,
69 const struct qcom_scm_desc *desc,
70 struct qcom_scm_res *res);
71extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
72 struct qcom_scm_res *res);
73
74#define QCOM_SCM_SVC_BOOT 0x01
75#define QCOM_SCM_BOOT_SET_ADDR 0x01
76#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
77#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10
78#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
23#define QCOM_SCM_FLUSH_FLAG_MASK 0x379#define QCOM_SCM_FLUSH_FLAG_MASK 0x3
24#define QCOM_SCM_CMD_CORE_HOTPLUGGED 0x10
25extern void __qcom_scm_cpu_power_down(u32 flags);
26 80
27#define QCOM_SCM_SVC_IO 0x581#define QCOM_SCM_SVC_PIL 0x02
28#define QCOM_SCM_IO_READ 0x182#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01
29#define QCOM_SCM_IO_WRITE 0x283#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x02
30extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val);84#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x05
31extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val);85#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
86#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
87#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
88
89#define QCOM_SCM_SVC_IO 0x05
90#define QCOM_SCM_IO_READ 0x01
91#define QCOM_SCM_IO_WRITE 0x02
92
93#define QCOM_SCM_SVC_INFO 0x06
94#define QCOM_SCM_INFO_IS_CALL_AVAIL 0x01
32 95
33#define QCOM_SCM_SVC_INFO 0x696#define QCOM_SCM_SVC_MP 0x0c
34#define QCOM_IS_CALL_AVAIL_CMD 0x197#define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02
35extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,98#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03
36 u32 cmd_id);99#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04
100#define QCOM_SCM_MP_ASSIGN 0x16
101
102#define QCOM_SCM_SVC_OCMEM 0x0f
103#define QCOM_SCM_OCMEM_LOCK_CMD 0x01
104#define QCOM_SCM_OCMEM_UNLOCK_CMD 0x02
37 105
38#define QCOM_SCM_SVC_HDCP 0x11106#define QCOM_SCM_SVC_HDCP 0x11
39#define QCOM_SCM_CMD_HDCP 0x01107#define QCOM_SCM_HDCP_INVOKE 0x01
40extern int __qcom_scm_hdcp_req(struct device *dev,
41 struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
42 108
43extern void __qcom_scm_init(void);109#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15
110#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03
111#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02
44 112
45#define QCOM_SCM_OCMEM_SVC 0xf113extern void __qcom_scm_init(void);
46#define QCOM_SCM_OCMEM_LOCK_CMD 0x1
47#define QCOM_SCM_OCMEM_UNLOCK_CMD 0x2
48
49extern int __qcom_scm_ocmem_lock(struct device *dev, u32 id, u32 offset,
50 u32 size, u32 mode);
51extern int __qcom_scm_ocmem_unlock(struct device *dev, u32 id, u32 offset,
52 u32 size);
53
54#define QCOM_SCM_SVC_PIL 0x2
55#define QCOM_SCM_PAS_INIT_IMAGE_CMD 0x1
56#define QCOM_SCM_PAS_MEM_SETUP_CMD 0x2
57#define QCOM_SCM_PAS_AUTH_AND_RESET_CMD 0x5
58#define QCOM_SCM_PAS_SHUTDOWN_CMD 0x6
59#define QCOM_SCM_PAS_IS_SUPPORTED_CMD 0x7
60#define QCOM_SCM_PAS_MSS_RESET 0xa
61extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral);
62extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
63 dma_addr_t metadata_phys);
64extern int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
65 phys_addr_t addr, phys_addr_t size);
66extern int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral);
67extern int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral);
68extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset);
69 114
70/* common error codes */115/* common error codes */
71#define QCOM_SCM_V2_EBUSY -12116#define QCOM_SCM_V2_EBUSY -12
@@ -94,25 +139,4 @@ static inline int qcom_scm_remap_error(int err) · 22 unmodified lines
94 return -EINVAL;139 return -EINVAL;
95}140}
96 141
97#define QCOM_SCM_SVC_MP 0xc
98#define QCOM_SCM_RESTORE_SEC_CFG 2
99extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
100 u32 spare);
101#define QCOM_SCM_IOMMU_SECURE_PTBL_SIZE 3
102#define QCOM_SCM_IOMMU_SECURE_PTBL_INIT 4
103#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15
104#define QCOM_SCM_CONFIG_ERRATA1 0x3
105#define QCOM_SCM_CONFIG_ERRATA1_CLIENT_ALL 0x2
106extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
107 size_t *size);
108extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr,
109 u32 size, u32 spare);
110extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev,
111 bool enable);
112#define QCOM_MEM_PROT_ASSIGN_ID 0x16
113extern int __qcom_scm_assign_mem(struct device *dev,
114 phys_addr_t mem_region, size_t mem_sz,
115 phys_addr_t src, size_t src_sz,
116 phys_addr_t dest, size_t dest_sz);
117
118#endif142#endif
drivers/soc/qcom/Kconfig+15−15
@@ -45,13 +45,13 @@ config QCOM_GLINK_SSR · 44 unmodified lines
45 neighboring subsystems going up or down.45 neighboring subsystems going up or down.
46 46
47config QCOM_GSBI47config QCOM_GSBI
48 tristate "QCOM General Serial Bus Interface"48 tristate "QCOM General Serial Bus Interface"
49 depends on ARCH_QCOM || COMPILE_TEST49 depends on ARCH_QCOM || COMPILE_TEST
50 select MFD_SYSCON50 select MFD_SYSCON
51 help51 help
52 Say y here to enable GSBI support. The GSBI provides control52 Say y here to enable GSBI support. The GSBI provides control
53 functions for connecting the underlying serial UART, SPI, and I2C53 functions for connecting the underlying serial UART, SPI, and I2C
54 devices to the output pins.54 devices to the output pins.
55 55
56config QCOM_LLCC56config QCOM_LLCC
57 tristate "Qualcomm Technologies, Inc. LLCC driver"57 tristate "Qualcomm Technologies, Inc. LLCC driver"
@@ -71,10 +71,10 @@ config QCOM_OCMEM · 13 unmodified lines
71 depends on ARCH_QCOM71 depends on ARCH_QCOM
72 select QCOM_SCM72 select QCOM_SCM
73 help73 help
74 The On Chip Memory (OCMEM) allocator allows various clients to74 The On Chip Memory (OCMEM) allocator allows various clients to
75 allocate memory from OCMEM based on performance, latency and power75 allocate memory from OCMEM based on performance, latency and power
76 requirements. This is typically used by the GPU, camera/video, and76 requirements. This is typically used by the GPU, camera/video, and
77 audio components on some Snapdragon SoCs.77 audio components on some Snapdragon SoCs.
78 78
79config QCOM_PM79config QCOM_PM
80 bool "Qualcomm Power Management"80 bool "Qualcomm Power Management"
@@ -198,8 +198,8 @@ config QCOM_APR · 117 unmodified lines
198 depends on ARCH_QCOM || COMPILE_TEST198 depends on ARCH_QCOM || COMPILE_TEST
199 depends on RPMSG199 depends on RPMSG
200 help200 help
201 Enable APR IPC protocol support between201 Enable APR IPC protocol support between
202 application processor and QDSP6. APR is202 application processor and QDSP6. APR is
203 used by audio driver to configure QDSP6203 used by audio driver to configure QDSP6
204 ASM, ADM and AFE modules.204 ASM, ADM and AFE modules.
205endmenu205endmenu
drivers/soc/qcom/qmi_interface.c+6−2
@@ -655,8 +655,12 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size, · 654 unmodified lines
655 655
656 qmi->sock = qmi_sock_create(qmi, &qmi->sq);656 qmi->sock = qmi_sock_create(qmi, &qmi->sq);
657 if (IS_ERR(qmi->sock)) {657 if (IS_ERR(qmi->sock)) {
658 pr_err("failed to create QMI socket\n");658 if (PTR_ERR(qmi->sock) == -EAFNOSUPPORT) {
659 ret = PTR_ERR(qmi->sock);659 ret = -EPROBE_DEFER;
660 } else {
661 pr_err("failed to create QMI socket\n");
662 ret = PTR_ERR(qmi->sock);
663 }
660 goto err_destroy_wq;664 goto err_destroy_wq;
661 }665 }
662 666
drivers/soc/qcom/rpmhpd.c+56−0
@@ -93,6 +93,7 @@ static struct rpmhpd sdm845_mx = { · 92 unmodified lines
93 93
94static struct rpmhpd sdm845_mx_ao = {94static struct rpmhpd sdm845_mx_ao = {
95 .pd = { .name = "mx_ao", },95 .pd = { .name = "mx_ao", },
96 .active_only = true,
96 .peer = &sdm845_mx,97 .peer = &sdm845_mx,
97 .res_name = "mx.lvl",98 .res_name = "mx.lvl",
98};99};
@@ -107,6 +108,7 @@ static struct rpmhpd sdm845_cx = { · 8 unmodified lines
107 108
108static struct rpmhpd sdm845_cx_ao = {109static struct rpmhpd sdm845_cx_ao = {
109 .pd = { .name = "cx_ao", },110 .pd = { .name = "cx_ao", },
111 .active_only = true,
110 .peer = &sdm845_cx,112 .peer = &sdm845_cx,
111 .parent = &sdm845_mx_ao.pd,113 .parent = &sdm845_mx_ao.pd,
112 .res_name = "cx.lvl",114 .res_name = "cx.lvl",
@@ -129,8 +131,62 @@ static const struct rpmhpd_desc sdm845_desc = { · 16 unmodified lines
129 .num_pds = ARRAY_SIZE(sdm845_rpmhpds),131 .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
130};132};
131 133
134/* SM8150 RPMH powerdomains */
135
136static struct rpmhpd sm8150_mmcx_ao;
137static struct rpmhpd sm8150_mmcx = {
138 .pd = { .name = "mmcx", },
139 .peer = &sm8150_mmcx_ao,
140 .res_name = "mmcx.lvl",
141};
142
143static struct rpmhpd sm8150_mmcx_ao = {
144 .pd = { .name = "mmcx_ao", },
145 .active_only = true,
146 .peer = &sm8150_mmcx,
147 .res_name = "mmcx.lvl",
148};
149
150static struct rpmhpd *sm8150_rpmhpds[] = {
151 [SM8150_MSS] = &sdm845_mss,
152 [SM8150_EBI] = &sdm845_ebi,
153 [SM8150_LMX] = &sdm845_lmx,
154 [SM8150_LCX] = &sdm845_lcx,
155 [SM8150_GFX] = &sdm845_gfx,
156 [SM8150_MX] = &sdm845_mx,
157 [SM8150_MX_AO] = &sdm845_mx_ao,
158 [SM8150_CX] = &sdm845_cx,
159 [SM8150_CX_AO] = &sdm845_cx_ao,
160 [SM8150_MMCX] = &sm8150_mmcx,
161 [SM8150_MMCX_AO] = &sm8150_mmcx_ao,
162};
163
164static const struct rpmhpd_desc sm8150_desc = {
165 .rpmhpds = sm8150_rpmhpds,
166 .num_pds = ARRAY_SIZE(sm8150_rpmhpds),
167};
168
169/* SC7180 RPMH powerdomains */
170static struct rpmhpd *sc7180_rpmhpds[] = {
171 [SC7180_CX] = &sdm845_cx,
172 [SC7180_CX_AO] = &sdm845_cx_ao,
173 [SC7180_GFX] = &sdm845_gfx,
174 [SC7180_MX] = &sdm845_mx,
175 [SC7180_MX_AO] = &sdm845_mx_ao,
176 [SC7180_LMX] = &sdm845_lmx,
177 [SC7180_LCX] = &sdm845_lcx,
178 [SC7180_MSS] = &sdm845_mss,
179};
180
181static const struct rpmhpd_desc sc7180_desc = {
182 .rpmhpds = sc7180_rpmhpds,
183 .num_pds = ARRAY_SIZE(sc7180_rpmhpds),
184};
185
132static const struct of_device_id rpmhpd_match_table[] = {186static const struct of_device_id rpmhpd_match_table[] = {
187 { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
133 { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },188 { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
189 { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc },
134 { }190 { }
135};191};
136 192
include/dt-bindings/power/qcom-rpmpd.h+24−0
@@ -15,12 +15,36 @@ · 14 unmodified lines
15#define SDM845_GFX 715#define SDM845_GFX 7
16#define SDM845_MSS 816#define SDM845_MSS 8
17 17
18/* SM8150 Power Domain Indexes */
19#define SM8150_MSS 0
20#define SM8150_EBI 1
21#define SM8150_LMX 2
22#define SM8150_LCX 3
23#define SM8150_GFX 4
24#define SM8150_MX 5
25#define SM8150_MX_AO 6
26#define SM8150_CX 7
27#define SM8150_CX_AO 8
28#define SM8150_MMCX 9
29#define SM8150_MMCX_AO 10
30
31/* SC7180 Power Domain Indexes */
32#define SC7180_CX 0
33#define SC7180_CX_AO 1
34#define SC7180_GFX 2
35#define SC7180_MX 3
36#define SC7180_MX_AO 4
37#define SC7180_LMX 5
38#define SC7180_LCX 6
39#define SC7180_MSS 7
40
18/* SDM845 Power Domain performance levels */41/* SDM845 Power Domain performance levels */
19#define RPMH_REGULATOR_LEVEL_RETENTION 1642#define RPMH_REGULATOR_LEVEL_RETENTION 16
20#define RPMH_REGULATOR_LEVEL_MIN_SVS 4843#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
21#define RPMH_REGULATOR_LEVEL_LOW_SVS 6444#define RPMH_REGULATOR_LEVEL_LOW_SVS 64
22#define RPMH_REGULATOR_LEVEL_SVS 12845#define RPMH_REGULATOR_LEVEL_SVS 128
23#define RPMH_REGULATOR_LEVEL_SVS_L1 19246#define RPMH_REGULATOR_LEVEL_SVS_L1 192
47#define RPMH_REGULATOR_LEVEL_SVS_L2 224
24#define RPMH_REGULATOR_LEVEL_NOM 25648#define RPMH_REGULATOR_LEVEL_NOM 256
25#define RPMH_REGULATOR_LEVEL_NOM_L1 32049#define RPMH_REGULATOR_LEVEL_NOM_L1 320
26#define RPMH_REGULATOR_LEVEL_NOM_L2 33650#define RPMH_REGULATOR_LEVEL_NOM_L2 336
include/linux/qcom_scm.h+68−51
@@ -1,5 +1,5 @@
1/* SPDX-License-Identifier: GPL-2.0-only */1/* SPDX-License-Identifier: GPL-2.0-only */
2/* Copyright (c) 2010-2015, 2018, The Linux Foundation. All rights reserved.2/* Copyright (c) 2010-2015, 2018-2019 The Linux Foundation. All rights reserved.
3 * Copyright (C) 2015 Linaro Ltd.3 * Copyright (C) 2015 Linaro Ltd.
4 */4 */
5#ifndef __QCOM_SCM_H5#ifndef __QCOM_SCM_H
@@ -55,77 +55,94 @@ enum qcom_scm_sec_dev_id { · 49 unmodified lines
55#define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC)55#define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC)
56 56
57#if IS_ENABLED(CONFIG_QCOM_SCM)57#if IS_ENABLED(CONFIG_QCOM_SCM)
58extern bool qcom_scm_is_available(void);
59
58extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);60extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
59extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);61extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
60extern bool qcom_scm_is_available(void);62extern void qcom_scm_cpu_power_down(u32 flags);
61extern bool qcom_scm_hdcp_available(void);63extern int qcom_scm_set_remote_state(u32 state, u32 id);
62extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,64
63 u32 *resp);
64extern bool qcom_scm_ocmem_lock_available(void);
65extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
66 u32 size, u32 mode);
67extern int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset,
68 u32 size);
69extern bool qcom_scm_pas_supported(u32 peripheral);
70extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,65extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
71 size_t size);66 size_t size);
72extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,67extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
73 phys_addr_t size);68 phys_addr_t size);
74extern int qcom_scm_pas_auth_and_reset(u32 peripheral);69extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
75extern int qcom_scm_pas_shutdown(u32 peripheral);70extern int qcom_scm_pas_shutdown(u32 peripheral);
76extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,71extern bool qcom_scm_pas_supported(u32 peripheral);
77 unsigned int *src,72
78 const struct qcom_scm_vmperm *newvm,73extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
79 unsigned int dest_cnt);74extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
80extern void qcom_scm_cpu_power_down(u32 flags);75
81extern u32 qcom_scm_get_version(void);
82extern int qcom_scm_set_remote_state(u32 state, u32 id);
83extern bool qcom_scm_restore_sec_cfg_available(void);76extern bool qcom_scm_restore_sec_cfg_available(void);
84extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);77extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
85extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);78extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);
86extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);79extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
80extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
81 unsigned int *src,
82 const struct qcom_scm_vmperm *newvm,
83 unsigned int dest_cnt);
84
85extern bool qcom_scm_ocmem_lock_available(void);
86extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
87 u32 size, u32 mode);
88extern int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset,
89 u32 size);
90
91extern bool qcom_scm_hdcp_available(void);
92extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
93 u32 *resp);
94
87extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en);95extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en);
88extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
89extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
90#else96#else
91 97
92#include <linux/errno.h>98#include <linux/errno.h>
93 99
94static inline
95int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
96{
97 return -ENODEV;
98}
99static inline
100int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
101{
102 return -ENODEV;
103}
104static inline bool qcom_scm_is_available(void) { return false; }100static inline bool qcom_scm_is_available(void) { return false; }
105static inline bool qcom_scm_hdcp_available(void) { return false; }101
106static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,102static inline int qcom_scm_set_cold_boot_addr(void *entry,
107 u32 *resp) { return -ENODEV; }103 const cpumask_t *cpus) { return -ENODEV; }
108static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; }104static inline int qcom_scm_set_warm_boot_addr(void *entry,
105 const cpumask_t *cpus) { return -ENODEV; }
106static inline void qcom_scm_cpu_power_down(u32 flags) {}
107static inline u32 qcom_scm_set_remote_state(u32 state,u32 id)
108 { return -ENODEV; }
109
109static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,110static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
110 size_t size) { return -ENODEV; }111 size_t size) { return -ENODEV; }
111static inline int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,112static inline int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
112 phys_addr_t size) { return -ENODEV; }113 phys_addr_t size) { return -ENODEV; }
113static inline int114static inline int qcom_scm_pas_auth_and_reset(u32 peripheral)
114qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; }115 { return -ENODEV; }
115static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; }116static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; }
117static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; }
118
119static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)
120 { return -ENODEV; }
121static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)
122 { return -ENODEV; }
123
124static inline bool qcom_scm_restore_sec_cfg_available(void) { return false; }
125static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
126 { return -ENODEV; }
127static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
128 { return -ENODEV; }
129static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
130 { return -ENODEV; }
116static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,131static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
117 unsigned int *src,132 unsigned int *src, const struct qcom_scm_vmperm *newvm,
118 const struct qcom_scm_vmperm *newvm,133 unsigned int dest_cnt) { return -ENODEV; }
119 unsigned int dest_cnt) { return -ENODEV; }134
120static inline void qcom_scm_cpu_power_down(u32 flags) {}135static inline bool qcom_scm_ocmem_lock_available(void) { return false; }
121static inline u32 qcom_scm_get_version(void) { return 0; }136static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
122static inline u32137 u32 size, u32 mode) { return -ENODEV; }
123qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; }138static inline int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id,
124static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; }139 u32 offset, u32 size) { return -ENODEV; }
125static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; }140
126static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; }141static inline bool qcom_scm_hdcp_available(void) { return false; }
127static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; }142static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
128static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; }143 u32 *resp) { return -ENODEV; }
129static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; }144
145static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en)
146 { return -ENODEV; }
130#endif147#endif
131#endif148#endif