xref: /optee_os/core/arch/riscv/kernel/sbi.c (revision 0ae5ef34a082abbd4f2e3248ce09e091b2e95b21)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2022 NXP
4  */
5 
6 #include <riscv.h>
7 #include <sbi.h>
8 
9 struct sbiret {
10 	long error;
11 	long value;
12 };
13 
14 #define _sbi_ecall(ext, fid, arg0, arg1, arg2, arg3, arg4, arg5, ...) ({  \
15 	register unsigned long a0 asm("a0") = (unsigned long)arg0; \
16 	register unsigned long a1 asm("a1") = (unsigned long)arg1; \
17 	register unsigned long a2 asm("a2") = (unsigned long)arg2; \
18 	register unsigned long a3 asm("a3") = (unsigned long)arg3; \
19 	register unsigned long a4 asm("a4") = (unsigned long)arg4; \
20 	register unsigned long a5 asm("a5") = (unsigned long)arg5; \
21 	register unsigned long a6 asm("a6") = (unsigned long)fid;  \
22 	register unsigned long a7 asm("a7") = (unsigned long)ext;  \
23 	asm volatile ("ecall" \
24 		: "+r" (a0), "+r" (a1) \
25 		: "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r"(a6), "r"(a7) \
26 		: "memory"); \
27 	(struct sbiret){ .error = a0, .value = a1 }; \
28 })
29 
30 #define sbi_ecall(...) _sbi_ecall(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0)
31 
32 /**
33  * sbi_probe_extension() - Check if an SBI extension ID is supported or not.
34  * @extid: The extension ID to be probed.
35  *
36  * Return: 1 or an extension specific nonzero value if yes, 0 otherwise.
37  */
38 int sbi_probe_extension(int extid)
39 {
40 	struct sbiret ret = { };
41 
42 	ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid);
43 	if (!ret.error)
44 		return ret.value;
45 
46 	return 0;
47 }
48 
49 /**
50  * sbi_console_putchar() - Writes given character to the console device.
51  * @ch: The data to be written to the console.
52  */
53 void sbi_console_putchar(int ch)
54 {
55 	sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch);
56 }
57 
58 /**
59  * sbi_dbcn_write_byte() - Write byte to debug console
60  * @ch:         Byte to be written
61  *
62  * Return:      SBI error code (SBI_SUCCESS = 0 on success)
63  */
64 int sbi_dbcn_write_byte(unsigned char ch)
65 {
66 	struct sbiret ret = { };
67 
68 	ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE, ch);
69 	return ret.error;
70 }
71 
72 /**
73  * sbi_hsm_hart_start() - Start target hart at OP-TEE entry in S-mode
74  * @hartid:     Target hart ID
75  * @start_addr: Physical address of OP-TEE entry
76  * @arg:        opaque parameter, typically used as the physical
77  *              address of device-tree passed via @arg->a1
78  *
79  * Return:      SBI error code (SBI_SUCCESS = 0 on success)
80  */
81 int sbi_hsm_hart_start(uint32_t hartid, paddr_t start_addr, unsigned long arg)
82 {
83 	struct sbiret ret = { };
84 
85 	ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START, hartid, start_addr,
86 			arg);
87 
88 	return ret.error;
89 }
90 
91 /**
92  * sbi_hsm_hart_get_status() - Get the current HSM state of given hart
93  * @hartid:         Target hart ID
94  * @status:         Pointer to store HSM state
95  *
96  * Return:          SBI error code (SBI_SUCCESS = 0 on success)
97  */
98 int sbi_hsm_hart_get_status(uint32_t hartid, enum sbi_hsm_hart_state *status)
99 {
100 	struct sbiret ret = { };
101 
102 	ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, hartid);
103 
104 	if (ret.error)
105 		return ret.error;
106 
107 	*status = ret.value;
108 	return SBI_SUCCESS;
109 }
110