1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 SiFive Inc.
*/
#include <libfdt.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_scratch.h>
#include <sbi_utils/cache/fdt_cache.h>
#include <sbi_utils/cache/fdt_cmo_helper.h>
#include <sbi_utils/fdt/fdt_helper.h>
static unsigned long flc_offset;
#define get_hart_flc(_s) \
sbi_scratch_read_type(_s, struct cache_device *, flc_offset)
#define set_hart_flc(_s, _p) \
sbi_scratch_write_type(_s, struct cache_device *, flc_offset, _p)
int fdt_cmo_private_flc_flush_all(void)
{
struct cache_device *flc = get_hart_flc(sbi_scratch_thishart_ptr());
if (!flc || !flc->cpu_private)
return SBI_ENODEV;
return cache_flush_all(flc);
}
int fdt_cmo_llc_flush_all(void)
{
struct cache_device *llc = get_hart_flc(sbi_scratch_thishart_ptr());
if (!llc)
return SBI_ENODEV;
while (llc->next)
llc = llc->next;
return cache_flush_all(llc);
}
int fdt_cmo_private_flc_enable(bool enable)
{
struct cache_device *flc = get_hart_flc(sbi_scratch_thishart_ptr());
if (!flc || !flc->cpu_private)
return SBI_ENODEV;
return cache_enable(flc, enable);
}
int fdt_cmo_llc_enable(bool enable)
{
struct cache_device *llc = get_hart_flc(sbi_scratch_thishart_ptr());
if (!llc)
return SBI_ENODEV;
while (llc->next)
llc = llc->next;
return cache_enable(llc, enable);
}
static int fdt_cmo_cold_init(const void *fdt)
{
struct sbi_scratch *scratch;
struct cache_device *dev;
int cpu_offset, cpus_offset, rc;
u32 hartid;
cpus_offset = fdt_path_offset(fdt, "/cpus");
if (cpus_offset < 0)
return SBI_EINVAL;
fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) {
rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
if (rc)
continue;
scratch = sbi_hartid_to_scratch(hartid);
if (!scratch)
continue;
rc = fdt_next_cache_get(fdt, cpu_offset, &dev);
if (rc && rc != SBI_ENOENT)
return rc;
if (rc == SBI_ENOENT)
dev = NULL;
set_hart_flc(scratch, dev);
}
return SBI_OK;
}
static int fdt_cmo_warm_init(void)
{
struct cache_device *cur = get_hart_flc(sbi_scratch_thishart_ptr());
int rc;
while (cur) {
if (cur->ops && cur->ops->warm_init) {
rc = cur->ops->warm_init(cur);
if (rc)
return rc;
}
cur = cur->next;
}
return SBI_OK;
}
int fdt_cmo_init(bool cold_boot)
{
const void *fdt = fdt_get_address();
int rc;
if (cold_boot) {
flc_offset = sbi_scratch_alloc_type_offset(struct cache_device *);
if (!flc_offset)
return SBI_ENOMEM;
rc = fdt_cmo_cold_init(fdt);
if (rc)
return rc;
}
rc = fdt_cmo_warm_init();
if (rc)
return rc;
return SBI_OK;
}
|