1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2020, Linaro Limited
4 */
5
6 #include <console.h>
7 #include <io.h>
8 #include <kernel/tee_misc.h>
9 #include <mm/core_memprot.h>
10 #include <sm/optee_smc.h>
11 #include <sm/sm.h>
12
13 #include "rzn1_regauth.h"
14
15 #define RZN1_OEM_CONSOLE_PUTC 0x01
16 #define RZN1_OEM_SYSREG_AUTH 0x10
17
18 static const struct regauth_t regauth_pass = {.rmask = ~0U, .wmask = ~0U};
19
get_regauth(unsigned long paddr)20 static const struct regauth_t *get_regauth(unsigned long paddr)
21 {
22 unsigned int idx = 0;
23 unsigned int len = ARRAY_SIZE(regauth);
24
25 while (idx < len) {
26 if (core_is_buffer_inside(paddr, sizeof(uint32_t),
27 regauth[idx].paddr,
28 regauth[idx].size))
29 return ®auth[idx];
30 idx++;
31 }
32
33 return NULL;
34 }
35
oem_sysreg(uint32_t addr,uint32_t mask,uint32_t * pvalue)36 static uint32_t oem_sysreg(uint32_t addr, uint32_t mask, uint32_t *pvalue)
37 {
38 vaddr_t reg = 0;
39 const struct regauth_t *auth = get_regauth(addr);
40
41 /* Allow operations on registers not in the list */
42 if (!auth)
43 auth = ®auth_pass;
44
45 reg = core_mmu_get_va(addr, MEM_AREA_IO_SEC, sizeof(uint32_t));
46
47 if (mask) {
48 /* Write operation */
49 mask &= auth->wmask;
50 if (!reg || !mask)
51 DMSG("Blocking write of 0x%"PRIx32" to register 0x%"
52 PRIx32" (0x%"PRIxVA")", *pvalue, addr, reg);
53 else if (mask == ~0UL)
54 io_write32(reg, *pvalue);
55 else
56 io_mask32(reg, *pvalue, mask);
57 } else {
58 /* Read operation */
59 if (!reg || !auth->rmask)
60 DMSG("Blocking read of register 0x%"PRIx32" (0x%"
61 PRIxVA")", addr, reg);
62 else
63 *pvalue = io_read32(reg) & auth->rmask;
64 }
65
66 return 0;
67 }
68
oem_service(struct sm_ctx * ctx __unused,struct thread_smc_args * args)69 static enum sm_handler_ret oem_service(struct sm_ctx *ctx __unused,
70 struct thread_smc_args *args)
71 {
72 switch (OPTEE_SMC_FUNC_NUM(args->a0)) {
73 case RZN1_OEM_SYSREG_AUTH:
74 args->a0 = oem_sysreg(args->a1, args->a2, &args->a3);
75 args->a1 = args->a3;
76 break;
77 case RZN1_OEM_CONSOLE_PUTC:
78 console_putc(args->a1);
79 break;
80 default:
81 return SM_HANDLER_PENDING_SMC;
82 }
83
84 return SM_HANDLER_SMC_HANDLED;
85 }
86
sm_platform_handler(struct sm_ctx * ctx)87 enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx)
88 {
89 struct thread_smc_args *args = (void *)&ctx->nsec.r0;
90
91 if (!OPTEE_SMC_IS_FAST_CALL(args->a0))
92 return SM_HANDLER_PENDING_SMC;
93
94 switch (OPTEE_SMC_OWNER_NUM(args->a0)) {
95 case OPTEE_SMC_OWNER_OEM:
96 return oem_service(ctx, args);
97 default:
98 return SM_HANDLER_PENDING_SMC;
99 }
100 }
101