1*c1e65709SSungmin Han // SPDX-License-Identifier: BSD-2-Clause
2*c1e65709SSungmin Han /*
3*c1e65709SSungmin Han * Copyright (c) 2024, Telechips Inc.
4*c1e65709SSungmin Han */
5*c1e65709SSungmin Han
6*c1e65709SSungmin Han #include <drivers/openedges_omc.h>
7*c1e65709SSungmin Han #include <initcall.h>
8*c1e65709SSungmin Han #include <kernel/interrupt.h>
9*c1e65709SSungmin Han #include <kernel/panic.h>
10*c1e65709SSungmin Han #include <mm/core_memprot.h>
11*c1e65709SSungmin Han #include <trace.h>
12*c1e65709SSungmin Han
13*c1e65709SSungmin Han #define NSEC_ALL_ACCESS UINT32_MAX
14*c1e65709SSungmin Han
tzc_protect_teeos(void)15*c1e65709SSungmin Han static void tzc_protect_teeos(void)
16*c1e65709SSungmin Han {
17*c1e65709SSungmin Han struct omc_region_config cfg = {
18*c1e65709SSungmin Han .filters = GENMASK_32(TZC_OMC_FILTERS - 1, 0),
19*c1e65709SSungmin Han .base = CFG_TZDRAM_START - DRAM0_BASE,
20*c1e65709SSungmin Han .top = (CFG_TZDRAM_START + CFG_TZDRAM_SIZE - 1) - DRAM0_BASE,
21*c1e65709SSungmin Han .ns_device_access = 0,
22*c1e65709SSungmin Han .flags = OMC_FLAG_RELATIVE_ADDR,
23*c1e65709SSungmin Han };
24*c1e65709SSungmin Han
25*c1e65709SSungmin Han omc_configure_region(TZC_TEEOS_REGION_NUM, &cfg);
26*c1e65709SSungmin Han }
27*c1e65709SSungmin Han
tzc_it_handler(struct itr_handler * h)28*c1e65709SSungmin Han static enum itr_return tzc_it_handler(struct itr_handler *h)
29*c1e65709SSungmin Han {
30*c1e65709SSungmin Han uint8_t filter = UINT8_MAX;
31*c1e65709SSungmin Han enum itr_return ret = ITRR_NONE;
32*c1e65709SSungmin Han
33*c1e65709SSungmin Han switch (h->it) {
34*c1e65709SSungmin Han case TZC_OMC_INT_0:
35*c1e65709SSungmin Han filter = 0;
36*c1e65709SSungmin Han break;
37*c1e65709SSungmin Han #if defined(TZC_OMC_INT_1)
38*c1e65709SSungmin Han case TZC_OMC_INT_1:
39*c1e65709SSungmin Han filter = 1;
40*c1e65709SSungmin Han break;
41*c1e65709SSungmin Han #endif
42*c1e65709SSungmin Han #if defined(TZC_OMC_INT_2)
43*c1e65709SSungmin Han case TZC_OMC_INT_2:
44*c1e65709SSungmin Han filter = 2;
45*c1e65709SSungmin Han break;
46*c1e65709SSungmin Han #endif
47*c1e65709SSungmin Han #if defined(TZC_OMC_INT_3)
48*c1e65709SSungmin Han case TZC_OMC_INT_3:
49*c1e65709SSungmin Han filter = 3;
50*c1e65709SSungmin Han break;
51*c1e65709SSungmin Han #endif
52*c1e65709SSungmin Han default:
53*c1e65709SSungmin Han break;
54*c1e65709SSungmin Han }
55*c1e65709SSungmin Han
56*c1e65709SSungmin Han if (filter != UINT8_MAX) {
57*c1e65709SSungmin Han EMSG("OMC(%"PRIu8") TZC permission failure", filter);
58*c1e65709SSungmin Han omc_fail_dump(filter);
59*c1e65709SSungmin Han omc_int_clear(filter);
60*c1e65709SSungmin Han
61*c1e65709SSungmin Han ret = ITRR_HANDLED;
62*c1e65709SSungmin Han }
63*c1e65709SSungmin Han
64*c1e65709SSungmin Han return ret;
65*c1e65709SSungmin Han }
66*c1e65709SSungmin Han
67*c1e65709SSungmin Han static struct itr_handler tzc_itr_handler[] = {
68*c1e65709SSungmin Han {
69*c1e65709SSungmin Han .it = TZC_OMC_INT_0,
70*c1e65709SSungmin Han .handler = tzc_it_handler,
71*c1e65709SSungmin Han },
72*c1e65709SSungmin Han #if defined(TZC_OMC_INT_1)
73*c1e65709SSungmin Han {
74*c1e65709SSungmin Han .it = TZC_OMC_INT_1,
75*c1e65709SSungmin Han .handler = tzc_it_handler,
76*c1e65709SSungmin Han },
77*c1e65709SSungmin Han #endif
78*c1e65709SSungmin Han #if defined(TZC_OMC_INT_2)
79*c1e65709SSungmin Han {
80*c1e65709SSungmin Han .it = TZC_OMC_INT_2,
81*c1e65709SSungmin Han .handler = tzc_it_handler,
82*c1e65709SSungmin Han },
83*c1e65709SSungmin Han #endif
84*c1e65709SSungmin Han #if defined(TZC_OMC_INT_3)
85*c1e65709SSungmin Han {
86*c1e65709SSungmin Han .it = TZC_OMC_INT_3,
87*c1e65709SSungmin Han .handler = tzc_it_handler,
88*c1e65709SSungmin Han },
89*c1e65709SSungmin Han #endif
90*c1e65709SSungmin Han };
91*c1e65709SSungmin Han
tzc_configure(void)92*c1e65709SSungmin Han static TEE_Result tzc_configure(void)
93*c1e65709SSungmin Han {
94*c1e65709SSungmin Han vaddr_t va = 0;
95*c1e65709SSungmin Han uint8_t filter = 0;
96*c1e65709SSungmin Han struct omc_region_config cfg = {
97*c1e65709SSungmin Han .filters = GENMASK_32(TZC_OMC_FILTERS - 1, 0),
98*c1e65709SSungmin Han .base = 0,
99*c1e65709SSungmin Han .top = UINT64_MAX,
100*c1e65709SSungmin Han .ns_device_access = NSEC_ALL_ACCESS,
101*c1e65709SSungmin Han .flags = 0,
102*c1e65709SSungmin Han };
103*c1e65709SSungmin Han
104*c1e65709SSungmin Han DMSG("Initializing TZC");
105*c1e65709SSungmin Han
106*c1e65709SSungmin Han va = (vaddr_t)phys_to_virt_io(TZC_OMC_BASE,
107*c1e65709SSungmin Han TZC_OMC_FILTERS * TZC_OMC_FILTER_OFFS);
108*c1e65709SSungmin Han if (!va)
109*c1e65709SSungmin Han panic();
110*c1e65709SSungmin Han
111*c1e65709SSungmin Han omc_init(va, TZC_OMC_FILTER_OFFS, TZC_OMC_FILTERS);
112*c1e65709SSungmin Han omc_configure_region(0, &cfg);
113*c1e65709SSungmin Han tzc_protect_teeos();
114*c1e65709SSungmin Han
115*c1e65709SSungmin Han for (filter = 0; filter < ARRAY_SIZE(tzc_itr_handler); filter++) {
116*c1e65709SSungmin Han interrupt_add_handler_with_chip(interrupt_get_main_chip(),
117*c1e65709SSungmin Han &tzc_itr_handler[filter]);
118*c1e65709SSungmin Han interrupt_enable(interrupt_get_main_chip(),
119*c1e65709SSungmin Han tzc_itr_handler[filter].it);
120*c1e65709SSungmin Han }
121*c1e65709SSungmin Han omc_set_action(OMC_ACTION_INT);
122*c1e65709SSungmin Han
123*c1e65709SSungmin Han return TEE_SUCCESS;
124*c1e65709SSungmin Han }
125*c1e65709SSungmin Han service_init(tzc_configure);
126