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
|
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 SpacemiT
* Authors:
* Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
* Troy Mitchell <troy.mitchell@linux.spacemit.com>
*/
#include <platform_override.h>
#include <sbi/riscv_io.h>
#include <sbi/sbi_hsm.h>
#include <spacemit/k1.h>
/* only use 0-1 cluster in SpacemiT K1 */
static const int cci_map[] = {
PLAT_CCI_CLUSTER0_IFACE_IX,
PLAT_CCI_CLUSTER1_IFACE_IX,
};
static void cci_enable_snoop_dvm_reqs(unsigned int master_id)
{
int slave_if_id = cci_map[master_id];
/*
* Enable Snoops and DVM messages, no need for Read/Modify/Write as
* rest of bits are write ignore
*/
writel(CCI_550_SNOOP_CTRL_ENABLE_DVMS | CCI_550_SNOOP_CTRL_ENABLE_SNOOPS,
(void *)(u64)CCI_550_PLATFORM_CCI_ADDR +
CCI_550_SLAVE_IFACE_OFFSET(slave_if_id) + CCI_550_SNOOP_CTRL);
/*
* Wait for the completion of the write to the Snoop Control Register
* before testing the change_pending bit
*/
mb();
/* Wait for the dust to settle down */
while ((readl((void *)(u64)CCI_550_PLATFORM_CCI_ADDR + CCI_550_STATUS) &
CCI_550_STATUS_CHANGE_PENDING))
;
}
static void spacemit_k1_pre_init(void)
{
unsigned int clusterid, cluster_enabled = 0;
struct sbi_scratch *scratch;
int i;
scratch = sbi_scratch_thishart_ptr();
writel(scratch->warmboot_addr, (unsigned int *)C0_RVBADDR_LO_ADDR);
writel((u64)scratch->warmboot_addr >> 32, (unsigned int *)C0_RVBADDR_HI_ADDR);
writel(scratch->warmboot_addr, (unsigned int *)C1_RVBADDR_LO_ADDR);
writel((u64)scratch->warmboot_addr >> 32, (unsigned int *)C1_RVBADDR_HI_ADDR);
for (i = 0; i < PLATFORM_MAX_CPUS; i++) {
clusterid = CPU_TO_CLUSTER(i);
if (!(cluster_enabled & (1 << clusterid))) {
cluster_enabled |= 1 << clusterid;
cci_enable_snoop_dvm_reqs(clusterid);
}
}
}
/*
* Platform early initialization.
*/
static int spacemit_k1_early_init(bool cold_boot)
{
int rc;
rc = generic_early_init(cold_boot);
if (rc)
return rc;
csr_set(CSR_MSETUP, MSETUP_DE | MSETUP_IE | MSETUP_BPE |
MSETUP_PFE | MSETUP_MME | MSETUP_ECCE);
if (cold_boot)
spacemit_k1_pre_init();
return 0;
}
static bool spacemit_cold_boot_allowed(u32 hartid)
{
csr_set(CSR_ML2SETUP, 1 << (hartid % PLATFORM_MAX_CPUS_PER_CLUSTER));
return !hartid;
}
static int spacemit_k1_platform_init(const void *fdt, int nodeoff,
const struct fdt_match *match)
{
generic_platform_ops.early_init = spacemit_k1_early_init;
generic_platform_ops.cold_boot_allowed = spacemit_cold_boot_allowed;
return 0;
}
static const struct fdt_match spacemit_k1_match[] = {
{ .compatible = "spacemit,k1" },
{ /* sentinel */ }
};
const struct fdt_driver spacemit_k1 = {
.match_table = spacemit_k1_match,
.init = spacemit_k1_platform_init,
};
|