aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Kconfig4
-rw-r--r--drivers/firmware/Makefile2
-rw-r--r--drivers/firmware/dmi_scan.c56
-rw-r--r--drivers/firmware/efi/libstub/arm-stub.c7
-rw-r--r--drivers/firmware/efi/libstub/efistub.h2
-rw-r--r--drivers/firmware/efi/libstub/fdt.c7
-rw-r--r--drivers/firmware/pcdp.c4
-rw-r--r--drivers/firmware/qcom_scm.c494
8 files changed, 538 insertions, 38 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 41983883cef4..6517132e5d8b 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -132,6 +132,10 @@ config ISCSI_IBFT
132 detect iSCSI boot parameters dynamically during system boot, say Y. 132 detect iSCSI boot parameters dynamically during system boot, say Y.
133 Otherwise, say N. 133 Otherwise, say N.
134 134
135config QCOM_SCM
136 bool
137 depends on ARM || ARM64
138
135source "drivers/firmware/google/Kconfig" 139source "drivers/firmware/google/Kconfig"
136source "drivers/firmware/efi/Kconfig" 140source "drivers/firmware/efi/Kconfig"
137 141
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 5373dc5b6011..3fdd3912709a 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_DMIID) += dmi-id.o
11obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o 11obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
12obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o 12obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
13obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o 13obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
14obj-$(CONFIG_QCOM_SCM) += qcom_scm.o
15CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
14 16
15obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ 17obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
16obj-$(CONFIG_EFI) += efi/ 18obj-$(CONFIG_EFI) += efi/
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 69fac068669f..6e45a43ffe84 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -17,7 +17,9 @@
17 */ 17 */
18static const char dmi_empty_string[] = " "; 18static const char dmi_empty_string[] = " ";
19 19
20static u16 __initdata dmi_ver; 20static u32 dmi_ver __initdata;
21static u32 dmi_len;
22static u16 dmi_num;
21/* 23/*
22 * Catch too early calls to dmi_check_system(): 24 * Catch too early calls to dmi_check_system():
23 */ 25 */
@@ -78,7 +80,7 @@ static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
78 * We have to be cautious here. We have seen BIOSes with DMI pointers 80 * We have to be cautious here. We have seen BIOSes with DMI pointers
79 * pointing to completely the wrong place for example 81 * pointing to completely the wrong place for example
80 */ 82 */
81static void dmi_table(u8 *buf, u32 len, int num, 83static void dmi_table(u8 *buf,
82 void (*decode)(const struct dmi_header *, void *), 84 void (*decode)(const struct dmi_header *, void *),
83 void *private_data) 85 void *private_data)
84{ 86{
@@ -86,10 +88,13 @@ static void dmi_table(u8 *buf, u32 len, int num,
86 int i = 0; 88 int i = 0;
87 89
88 /* 90 /*
89 * Stop when we see all the items the table claimed to have 91 * Stop when we have seen all the items the table claimed to have
90 * OR we run off the end of the table (also happens) 92 * (SMBIOS < 3.0 only) OR we reach an end-of-table marker OR we run
93 * off the end of the table (should never happen but sometimes does
94 * on bogus implementations.)
91 */ 95 */
92 while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { 96 while ((!dmi_num || i < dmi_num) &&
97 (data - buf + sizeof(struct dmi_header)) <= dmi_len) {
93 const struct dmi_header *dm = (const struct dmi_header *)data; 98 const struct dmi_header *dm = (const struct dmi_header *)data;
94 99
95 /* 100 /*
@@ -98,9 +103,9 @@ static void dmi_table(u8 *buf, u32 len, int num,
98 * table in dmi_decode or dmi_string 103 * table in dmi_decode or dmi_string
99 */ 104 */
100 data += dm->length; 105 data += dm->length;
101 while ((data - buf < len - 1) && (data[0] || data[1])) 106 while ((data - buf < dmi_len - 1) && (data[0] || data[1]))
102 data++; 107 data++;
103 if (data - buf < len - 1) 108 if (data - buf < dmi_len - 1)
104 decode(dm, private_data); 109 decode(dm, private_data);
105 110
106 /* 111 /*
@@ -115,8 +120,6 @@ static void dmi_table(u8 *buf, u32 len, int num,
115} 120}
116 121
117static phys_addr_t dmi_base; 122static phys_addr_t dmi_base;
118static u32 dmi_len;
119static u16 dmi_num;
120 123
121static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, 124static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
122 void *)) 125 void *))
@@ -127,7 +130,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
127 if (buf == NULL) 130 if (buf == NULL)
128 return -1; 131 return -1;
129 132
130 dmi_table(buf, dmi_len, dmi_num, decode, NULL); 133 dmi_table(buf, decode, NULL);
131 134
132 add_device_randomness(buf, dmi_len); 135 add_device_randomness(buf, dmi_len);
133 136
@@ -198,7 +201,7 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
198 * the UUID are supposed to be little-endian encoded. The specification 201 * the UUID are supposed to be little-endian encoded. The specification
199 * says that this is the defacto standard. 202 * says that this is the defacto standard.
200 */ 203 */
201 if (dmi_ver >= 0x0206) 204 if (dmi_ver >= 0x020600)
202 sprintf(s, "%pUL", d); 205 sprintf(s, "%pUL", d);
203 else 206 else
204 sprintf(s, "%pUB", d); 207 sprintf(s, "%pUB", d);
@@ -470,7 +473,7 @@ static void __init dmi_format_ids(char *buf, size_t len)
470 */ 473 */
471static int __init dmi_present(const u8 *buf) 474static int __init dmi_present(const u8 *buf)
472{ 475{
473 int smbios_ver; 476 u32 smbios_ver;
474 477
475 if (memcmp(buf, "_SM_", 4) == 0 && 478 if (memcmp(buf, "_SM_", 4) == 0 &&
476 buf[5] < 32 && dmi_checksum(buf, buf[5])) { 479 buf[5] < 32 && dmi_checksum(buf, buf[5])) {
@@ -503,14 +506,16 @@ static int __init dmi_present(const u8 *buf)
503 if (dmi_walk_early(dmi_decode) == 0) { 506 if (dmi_walk_early(dmi_decode) == 0) {
504 if (smbios_ver) { 507 if (smbios_ver) {
505 dmi_ver = smbios_ver; 508 dmi_ver = smbios_ver;
506 pr_info("SMBIOS %d.%d present.\n", 509 pr_info("SMBIOS %d.%d%s present.\n",
507 dmi_ver >> 8, dmi_ver & 0xFF); 510 dmi_ver >> 8, dmi_ver & 0xFF,
511 (dmi_ver < 0x0300) ? "" : ".x");
508 } else { 512 } else {
509 dmi_ver = (buf[14] & 0xF0) << 4 | 513 dmi_ver = (buf[14] & 0xF0) << 4 |
510 (buf[14] & 0x0F); 514 (buf[14] & 0x0F);
511 pr_info("Legacy DMI %d.%d present.\n", 515 pr_info("Legacy DMI %d.%d present.\n",
512 dmi_ver >> 8, dmi_ver & 0xFF); 516 dmi_ver >> 8, dmi_ver & 0xFF);
513 } 517 }
518 dmi_ver <<= 8;
514 dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); 519 dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
515 printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string); 520 printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
516 return 0; 521 return 0;
@@ -528,25 +533,16 @@ static int __init dmi_smbios3_present(const u8 *buf)
528{ 533{
529 if (memcmp(buf, "_SM3_", 5) == 0 && 534 if (memcmp(buf, "_SM3_", 5) == 0 &&
530 buf[6] < 32 && dmi_checksum(buf, buf[6])) { 535 buf[6] < 32 && dmi_checksum(buf, buf[6])) {
531 dmi_ver = get_unaligned_be16(buf + 7); 536 dmi_ver = get_unaligned_be32(buf + 6);
537 dmi_ver &= 0xFFFFFF;
538 dmi_num = 0; /* No longer specified */
532 dmi_len = get_unaligned_le32(buf + 12); 539 dmi_len = get_unaligned_le32(buf + 12);
533 dmi_base = get_unaligned_le64(buf + 16); 540 dmi_base = get_unaligned_le64(buf + 16);
534 541
535 /*
536 * The 64-bit SMBIOS 3.0 entry point no longer has a field
537 * containing the number of structures present in the table.
538 * Instead, it defines the table size as a maximum size, and
539 * relies on the end-of-table structure type (#127) to be used
540 * to signal the end of the table.
541 * So let's define dmi_num as an upper bound as well: each
542 * structure has a 4 byte header, so dmi_len / 4 is an upper
543 * bound for the number of structures in the table.
544 */
545 dmi_num = dmi_len / 4;
546
547 if (dmi_walk_early(dmi_decode) == 0) { 542 if (dmi_walk_early(dmi_decode) == 0) {
548 pr_info("SMBIOS %d.%d present.\n", 543 pr_info("SMBIOS %d.%d.%d present.\n",
549 dmi_ver >> 8, dmi_ver & 0xFF); 544 dmi_ver >> 16, (dmi_ver >> 8) & 0xFF,
545 dmi_ver & 0xFF);
550 dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); 546 dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
551 pr_debug("DMI: %s\n", dmi_ids_string); 547 pr_debug("DMI: %s\n", dmi_ids_string);
552 return 0; 548 return 0;
@@ -901,7 +897,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *),
901 if (buf == NULL) 897 if (buf == NULL)
902 return -1; 898 return -1;
903 899
904 dmi_table(buf, dmi_len, dmi_num, decode, private_data); 900 dmi_table(buf, decode, private_data);
905 901
906 dmi_unmap(buf); 902 dmi_unmap(buf);
907 return 0; 903 return 0;
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index dcae482a9a17..e29560e6b40b 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -175,7 +175,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
175 unsigned long initrd_addr; 175 unsigned long initrd_addr;
176 u64 initrd_size = 0; 176 u64 initrd_size = 0;
177 unsigned long fdt_addr = 0; /* Original DTB */ 177 unsigned long fdt_addr = 0; /* Original DTB */
178 u64 fdt_size = 0; /* We don't get size from configuration table */ 178 unsigned long fdt_size = 0;
179 char *cmdline_ptr = NULL; 179 char *cmdline_ptr = NULL;
180 int cmdline_size = 0; 180 int cmdline_size = 0;
181 unsigned long new_fdt_addr; 181 unsigned long new_fdt_addr;
@@ -239,8 +239,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
239 } else { 239 } else {
240 status = handle_cmdline_files(sys_table, image, cmdline_ptr, 240 status = handle_cmdline_files(sys_table, image, cmdline_ptr,
241 "dtb=", 241 "dtb=",
242 ~0UL, (unsigned long *)&fdt_addr, 242 ~0UL, &fdt_addr, &fdt_size);
243 (unsigned long *)&fdt_size);
244 243
245 if (status != EFI_SUCCESS) { 244 if (status != EFI_SUCCESS) {
246 pr_efi_err(sys_table, "Failed to load device tree!\n"); 245 pr_efi_err(sys_table, "Failed to load device tree!\n");
@@ -252,7 +251,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
252 pr_efi(sys_table, "Using DTB from command line\n"); 251 pr_efi(sys_table, "Using DTB from command line\n");
253 } else { 252 } else {
254 /* Look for a device tree configuration table entry. */ 253 /* Look for a device tree configuration table entry. */
255 fdt_addr = (uintptr_t)get_fdt(sys_table); 254 fdt_addr = (uintptr_t)get_fdt(sys_table, &fdt_size);
256 if (fdt_addr) 255 if (fdt_addr)
257 pr_efi(sys_table, "Using DTB from configuration table\n"); 256 pr_efi(sys_table, "Using DTB from configuration table\n");
258 } 257 }
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 47437b16b186..e334a01cf92f 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -41,7 +41,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
41 unsigned long fdt_addr, 41 unsigned long fdt_addr,
42 unsigned long fdt_size); 42 unsigned long fdt_size);
43 43
44void *get_fdt(efi_system_table_t *sys_table); 44void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size);
45 45
46void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, 46void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
47 unsigned long desc_size, efi_memory_desc_t *runtime_map, 47 unsigned long desc_size, efi_memory_desc_t *runtime_map,
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 91da56c4fd54..ef5d764e2a27 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -323,7 +323,7 @@ fail:
323 return EFI_LOAD_ERROR; 323 return EFI_LOAD_ERROR;
324} 324}
325 325
326void *get_fdt(efi_system_table_t *sys_table) 326void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size)
327{ 327{
328 efi_guid_t fdt_guid = DEVICE_TREE_GUID; 328 efi_guid_t fdt_guid = DEVICE_TREE_GUID;
329 efi_config_table_t *tables; 329 efi_config_table_t *tables;
@@ -336,6 +336,11 @@ void *get_fdt(efi_system_table_t *sys_table)
336 for (i = 0; i < sys_table->nr_tables; i++) 336 for (i = 0; i < sys_table->nr_tables; i++)
337 if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) { 337 if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
338 fdt = (void *) tables[i].table; 338 fdt = (void *) tables[i].table;
339 if (fdt_check_header(fdt) != 0) {
340 pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n");
341 return NULL;
342 }
343 *fdt_size = fdt_totalsize(fdt);
339 break; 344 break;
340 } 345 }
341 346
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index a330492e06f9..75273a251603 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,7 +15,7 @@
15#include <linux/console.h> 15#include <linux/console.h>
16#include <linux/efi.h> 16#include <linux/efi.h>
17#include <linux/serial.h> 17#include <linux/serial.h>
18#include <linux/serial_8250.h> 18#include <linux/serial_core.h>
19#include <asm/vga.h> 19#include <asm/vga.h>
20#include "pcdp.h" 20#include "pcdp.h"
21 21
@@ -43,7 +43,7 @@ setup_serial_console(struct pcdp_uart *uart)
43 } 43 }
44 44
45 add_preferred_console("uart", 8250, &options[9]); 45 add_preferred_console("uart", 8250, &options[9]);
46 return setup_early_serial8250_console(options); 46 return setup_earlycon(options);
47#else 47#else
48 return -ENODEV; 48 return -ENODEV;
49#endif 49#endif
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
new file mode 100644
index 000000000000..994b50fd997c
--- /dev/null
+++ b/drivers/firmware/qcom_scm.c
@@ -0,0 +1,494 @@
1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 * Copyright (C) 2015 Linaro Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA.
17 */
18
19#include <linux/slab.h>
20#include <linux/io.h>
21#include <linux/module.h>
22#include <linux/mutex.h>
23#include <linux/errno.h>
24#include <linux/err.h>
25#include <linux/qcom_scm.h>
26
27#include <asm/outercache.h>
28#include <asm/cacheflush.h>
29
30
31#define QCOM_SCM_ENOMEM -5
32#define QCOM_SCM_EOPNOTSUPP -4
33#define QCOM_SCM_EINVAL_ADDR -3
34#define QCOM_SCM_EINVAL_ARG -2
35#define QCOM_SCM_ERROR -1
36#define QCOM_SCM_INTERRUPTED 1
37
38#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
39#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
40#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
41#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
42
43#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
44#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
45#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
46#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
47
48struct qcom_scm_entry {
49 int flag;
50 void *entry;
51};
52
53static struct qcom_scm_entry qcom_scm_wb[] = {
54 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
55 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
56 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
57 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
58};
59
60static DEFINE_MUTEX(qcom_scm_lock);
61
62/**
63 * struct qcom_scm_command - one SCM command buffer
64 * @len: total available memory for command and response
65 * @buf_offset: start of command buffer
66 * @resp_hdr_offset: start of response buffer
67 * @id: command to be executed
68 * @buf: buffer returned from qcom_scm_get_command_buffer()
69 *
70 * An SCM command is laid out in memory as follows:
71 *
72 * ------------------- <--- struct qcom_scm_command
73 * | command header |
74 * ------------------- <--- qcom_scm_get_command_buffer()
75 * | command buffer |
76 * ------------------- <--- struct qcom_scm_response and
77 * | response header | qcom_scm_command_to_response()
78 * ------------------- <--- qcom_scm_get_response_buffer()
79 * | response buffer |
80 * -------------------
81 *
82 * There can be arbitrary padding between the headers and buffers so
83 * you should always use the appropriate qcom_scm_get_*_buffer() routines
84 * to access the buffers in a safe manner.
85 */
86struct qcom_scm_command {
87 __le32 len;
88 __le32 buf_offset;
89 __le32 resp_hdr_offset;
90 __le32 id;
91 __le32 buf[0];
92};
93
94/**
95 * struct qcom_scm_response - one SCM response buffer
96 * @len: total available memory for response
97 * @buf_offset: start of response data relative to start of qcom_scm_response
98 * @is_complete: indicates if the command has finished processing
99 */
100struct qcom_scm_response {
101 __le32 len;
102 __le32 buf_offset;
103 __le32 is_complete;
104};
105
106/**
107 * alloc_qcom_scm_command() - Allocate an SCM command
108 * @cmd_size: size of the command buffer
109 * @resp_size: size of the response buffer
110 *
111 * Allocate an SCM command, including enough room for the command
112 * and response headers as well as the command and response buffers.
113 *
114 * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
115 */
116static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
117{
118 struct qcom_scm_command *cmd;
119 size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
120 resp_size;
121 u32 offset;
122
123 cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
124 if (cmd) {
125 cmd->len = cpu_to_le32(len);
126 offset = offsetof(struct qcom_scm_command, buf);
127 cmd->buf_offset = cpu_to_le32(offset);
128 cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
129 }
130 return cmd;
131}
132
133/**
134 * free_qcom_scm_command() - Free an SCM command
135 * @cmd: command to free
136 *
137 * Free an SCM command.
138 */
139static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
140{
141 kfree(cmd);
142}
143
144/**
145 * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
146 * @cmd: command
147 *
148 * Returns a pointer to a response for a command.
149 */
150static inline struct qcom_scm_response *qcom_scm_command_to_response(
151 const struct qcom_scm_command *cmd)
152{
153 return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
154}
155
156/**
157 * qcom_scm_get_command_buffer() - Get a pointer to a command buffer
158 * @cmd: command
159 *
160 * Returns a pointer to the command buffer of a command.
161 */
162static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd)
163{
164 return (void *)cmd->buf;
165}
166
167/**
168 * qcom_scm_get_response_buffer() - Get a pointer to a response buffer
169 * @rsp: response
170 *
171 * Returns a pointer to a response buffer of a response.
172 */
173static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp)
174{
175 return (void *)rsp + le32_to_cpu(rsp->buf_offset);
176}
177
178static int qcom_scm_remap_error(int err)
179{
180 pr_err("qcom_scm_call failed with error code %d\n", err);
181 switch (err) {
182 case QCOM_SCM_ERROR:
183 return -EIO;
184 case QCOM_SCM_EINVAL_ADDR:
185 case QCOM_SCM_EINVAL_ARG:
186 return -EINVAL;
187 case QCOM_SCM_EOPNOTSUPP:
188 return -EOPNOTSUPP;
189 case QCOM_SCM_ENOMEM:
190 return -ENOMEM;
191 }
192 return -EINVAL;
193}
194
195static u32 smc(u32 cmd_addr)
196{
197 int context_id;
198 register u32 r0 asm("r0") = 1;
199 register u32 r1 asm("r1") = (u32)&context_id;
200 register u32 r2 asm("r2") = cmd_addr;
201 do {
202 asm volatile(
203 __asmeq("%0", "r0")
204 __asmeq("%1", "r0")
205 __asmeq("%2", "r1")
206 __asmeq("%3", "r2")
207#ifdef REQUIRES_SEC
208 ".arch_extension sec\n"
209#endif
210 "smc #0 @ switch to secure world\n"
211 : "=r" (r0)
212 : "r" (r0), "r" (r1), "r" (r2)
213 : "r3");
214 } while (r0 == QCOM_SCM_INTERRUPTED);
215
216 return r0;
217}
218
219static int __qcom_scm_call(const struct qcom_scm_command *cmd)
220{
221 int ret;
222 u32 cmd_addr = virt_to_phys(cmd);
223
224 /*
225 * Flush the command buffer so that the secure world sees
226 * the correct data.
227 */
228 __cpuc_flush_dcache_area((void *)cmd, cmd->len);
229 outer_flush_range(cmd_addr, cmd_addr + cmd->len);
230
231 ret = smc(cmd_addr);
232 if (ret < 0)
233 ret = qcom_scm_remap_error(ret);
234
235 return ret;
236}
237
238static void qcom_scm_inv_range(unsigned long start, unsigned long end)
239{
240 u32 cacheline_size, ctr;
241
242 asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
243 cacheline_size = 4 << ((ctr >> 16) & 0xf);
244
245 start = round_down(start, cacheline_size);
246 end = round_up(end, cacheline_size);
247 outer_inv_range(start, end);
248 while (start < end) {
249 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
250 : "memory");
251 start += cacheline_size;
252 }
253 dsb();
254 isb();
255}
256
257/**
258 * qcom_scm_call() - Send an SCM command
259 * @svc_id: service identifier
260 * @cmd_id: command identifier
261 * @cmd_buf: command buffer
262 * @cmd_len: length of the command buffer
263 * @resp_buf: response buffer
264 * @resp_len: length of the response buffer
265 *
266 * Sends a command to the SCM and waits for the command to finish processing.
267 *
268 * A note on cache maintenance:
269 * Note that any buffers that are expected to be accessed by the secure world
270 * must be flushed before invoking qcom_scm_call and invalidated in the cache
271 * immediately after qcom_scm_call returns. Cache maintenance on the command
272 * and response buffers is taken care of by qcom_scm_call; however, callers are
273 * responsible for any other cached buffers passed over to the secure world.
274 */
275static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
276 size_t cmd_len, void *resp_buf, size_t resp_len)
277{
278 int ret;
279 struct qcom_scm_command *cmd;
280 struct qcom_scm_response *rsp;
281 unsigned long start, end;
282
283 cmd = alloc_qcom_scm_command(cmd_len, resp_len);
284 if (!cmd)
285 return -ENOMEM;
286
287 cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
288 if (cmd_buf)
289 memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
290
291 mutex_lock(&qcom_scm_lock);
292 ret = __qcom_scm_call(cmd);
293 mutex_unlock(&qcom_scm_lock);
294 if (ret)
295 goto out;
296
297 rsp = qcom_scm_command_to_response(cmd);
298 start = (unsigned long)rsp;
299
300 do {
301 qcom_scm_inv_range(start, start + sizeof(*rsp));
302 } while (!rsp->is_complete);
303
304 end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
305 qcom_scm_inv_range(start, end);
306
307 if (resp_buf)
308 memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
309out:
310 free_qcom_scm_command(cmd);
311 return ret;
312}
313
314#define SCM_CLASS_REGISTER (0x2 << 8)
315#define SCM_MASK_IRQS BIT(5)
316#define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \
317 SCM_CLASS_REGISTER | \
318 SCM_MASK_IRQS | \
319 (n & 0xf))
320
321/**
322 * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument
323 * @svc_id: service identifier
324 * @cmd_id: command identifier
325 * @arg1: first argument
326 *
327 * This shall only be used with commands that are guaranteed to be
328 * uninterruptable, atomic and SMP safe.
329 */
330static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
331{
332 int context_id;
333
334 register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1);
335 register u32 r1 asm("r1") = (u32)&context_id;
336 register u32 r2 asm("r2") = arg1;
337
338 asm volatile(
339 __asmeq("%0", "r0")
340 __asmeq("%1", "r0")
341 __asmeq("%2", "r1")
342 __asmeq("%3", "r2")
343#ifdef REQUIRES_SEC
344 ".arch_extension sec\n"
345#endif
346 "smc #0 @ switch to secure world\n"
347 : "=r" (r0)
348 : "r" (r0), "r" (r1), "r" (r2)
349 : "r3");
350 return r0;
351}
352
353u32 qcom_scm_get_version(void)
354{
355 int context_id;
356 static u32 version = -1;
357 register u32 r0 asm("r0");
358 register u32 r1 asm("r1");
359
360 if (version != -1)
361 return version;
362
363 mutex_lock(&qcom_scm_lock);
364
365 r0 = 0x1 << 8;
366 r1 = (u32)&context_id;
367 do {
368 asm volatile(
369 __asmeq("%0", "r0")
370 __asmeq("%1", "r1")
371 __asmeq("%2", "r0")
372 __asmeq("%3", "r1")
373#ifdef REQUIRES_SEC
374 ".arch_extension sec\n"
375#endif
376 "smc #0 @ switch to secure world\n"
377 : "=r" (r0), "=r" (r1)
378 : "r" (r0), "r" (r1)
379 : "r2", "r3");
380 } while (r0 == QCOM_SCM_INTERRUPTED);
381
382 version = r1;
383 mutex_unlock(&qcom_scm_lock);
384
385 return version;
386}
387EXPORT_SYMBOL(qcom_scm_get_version);
388
389#define QCOM_SCM_SVC_BOOT 0x1
390#define QCOM_SCM_BOOT_ADDR 0x1
391/*
392 * Set the cold/warm boot address for one of the CPU cores.
393 */
394static int qcom_scm_set_boot_addr(u32 addr, int flags)
395{
396 struct {
397 __le32 flags;
398 __le32 addr;
399 } cmd;
400
401 cmd.addr = cpu_to_le32(addr);
402 cmd.flags = cpu_to_le32(flags);
403 return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
404 &cmd, sizeof(cmd), NULL, 0);
405}
406
407/**
408 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
409 * @entry: Entry point function for the cpus
410 * @cpus: The cpumask of cpus that will use the entry point
411 *
412 * Set the cold boot address of the cpus. Any cpu outside the supported
413 * range would be removed from the cpu present mask.
414 */
415int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
416{
417 int flags = 0;
418 int cpu;
419 int scm_cb_flags[] = {
420 QCOM_SCM_FLAG_COLDBOOT_CPU0,
421 QCOM_SCM_FLAG_COLDBOOT_CPU1,
422 QCOM_SCM_FLAG_COLDBOOT_CPU2,
423 QCOM_SCM_FLAG_COLDBOOT_CPU3,
424 };
425
426 if (!cpus || (cpus && cpumask_empty(cpus)))
427 return -EINVAL;
428
429 for_each_cpu(cpu, cpus) {
430 if (cpu < ARRAY_SIZE(scm_cb_flags))
431 flags |= scm_cb_flags[cpu];
432 else
433 set_cpu_present(cpu, false);
434 }
435
436 return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
437}
438EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
439
440/**
441 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
442 * @entry: Entry point function for the cpus
443 * @cpus: The cpumask of cpus that will use the entry point
444 *
445 * Set the Linux entry point for the SCM to transfer control to when coming
446 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
447 */
448int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
449{
450 int ret;
451 int flags = 0;
452 int cpu;
453
454 /*
455 * Reassign only if we are switching from hotplug entry point
456 * to cpuidle entry point or vice versa.
457 */
458 for_each_cpu(cpu, cpus) {
459 if (entry == qcom_scm_wb[cpu].entry)
460 continue;
461 flags |= qcom_scm_wb[cpu].flag;
462 }
463
464 /* No change in entry function */
465 if (!flags)
466 return 0;
467
468 ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
469 if (!ret) {
470 for_each_cpu(cpu, cpus)
471 qcom_scm_wb[cpu].entry = entry;
472 }
473
474 return ret;
475}
476EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
477
478#define QCOM_SCM_CMD_TERMINATE_PC 0x2
479#define QCOM_SCM_FLUSH_FLAG_MASK 0x3
480
481/**
482 * qcom_scm_cpu_power_down() - Power down the cpu
483 * @flags - Flags to flush cache
484 *
485 * This is an end point to power down cpu. If there was a pending interrupt,
486 * the control would return from this function, otherwise, the cpu jumps to the
487 * warm boot entry point set for this cpu upon reset.
488 */
489void qcom_scm_cpu_power_down(u32 flags)
490{
491 qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC,
492 flags & QCOM_SCM_FLUSH_FLAG_MASK);
493}
494EXPORT_SYMBOL(qcom_scm_cpu_power_down);