1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020 Western Digital Corporation or its affiliates.
5  *
6  * Authors:
7  *   Anup Patel <anup.patel@wdc.com>
8  *   Atish Patra <atish.patra@wdc.com>
9  */
10 
11 #include <sbi/sbi_ecall.h>
12 #include <sbi/sbi_ecall_interface.h>
13 #include <sbi/sbi_error.h>
14 #include <sbi/sbi_version.h>
15 #include <sbi/riscv_asm.h>
16 
sbi_ecall_base_probe(struct sbi_scratch * scratch,unsigned long extid,unsigned long * out_val)17 static int sbi_ecall_base_probe(struct sbi_scratch *scratch,
18 				unsigned long extid,
19 				unsigned long *out_val)
20 {
21 	struct sbi_ecall_extension *ext;
22 
23 	ext = sbi_ecall_find_extension(extid);
24 	if (!ext) {
25 		*out_val = 0;
26 		return 0;
27 	}
28 
29 	if (ext->probe)
30 		return ext->probe(scratch, extid, out_val);
31 
32 	*out_val = 1;
33 	return 0;
34 }
35 
sbi_ecall_base_handler(struct sbi_scratch * scratch,unsigned long extid,unsigned long funcid,unsigned long * args,unsigned long * out_val,struct sbi_trap_info * out_trap)36 static int sbi_ecall_base_handler(struct sbi_scratch *scratch,
37 				  unsigned long extid, unsigned long funcid,
38 				  unsigned long *args, unsigned long *out_val,
39 				  struct sbi_trap_info *out_trap)
40 {
41 	int ret = 0;
42 
43 	switch (funcid) {
44 	case SBI_EXT_BASE_GET_SPEC_VERSION:
45 		*out_val = (SBI_ECALL_VERSION_MAJOR <<
46 			   SBI_SPEC_VERSION_MAJOR_OFFSET) &
47 			   (SBI_SPEC_VERSION_MAJOR_MASK <<
48 			    SBI_SPEC_VERSION_MAJOR_OFFSET);
49 		*out_val = *out_val | SBI_ECALL_VERSION_MINOR;
50 		break;
51 	case SBI_EXT_BASE_GET_IMP_ID:
52 		*out_val = SBI_OPENSBI_IMPID;
53 		break;
54 	case SBI_EXT_BASE_GET_IMP_VERSION:
55 		*out_val = OPENSBI_VERSION;
56 		break;
57 	case SBI_EXT_BASE_GET_MVENDORID:
58 		*out_val = csr_read(CSR_MVENDORID);
59 		break;
60 	case SBI_EXT_BASE_GET_MARCHID:
61 		*out_val = csr_read(CSR_MARCHID);
62 		break;
63 	case SBI_EXT_BASE_GET_MIMPID:
64 		*out_val = csr_read(CSR_MIMPID);
65 		break;
66 	case SBI_EXT_BASE_PROBE_EXT:
67 		ret = sbi_ecall_base_probe(scratch, args[0], out_val);
68 		break;
69 	default:
70 		ret = SBI_ENOTSUPP;
71 	}
72 
73 	return ret;
74 }
75 
76 struct sbi_ecall_extension ecall_base = {
77 	.extid_start = SBI_EXT_BASE,
78 	.extid_end = SBI_EXT_BASE,
79 	.handle = sbi_ecall_base_handler,
80 };
81