Skip to content

Commit f94bfb8

Browse files
committed
platform: Add xuantie_pmc for PMC test
This is an example implementation of power management using C907 PMC, which mainly implements sbi_hsm_device, sbi_system_reset_device and sbi_system_suspend_device defined by opensbi. DTS example: ``` { model = "xuantie,dummy"; compatible = "xuantie,dummy"; pmc: xuantie_pmc@26900000 { compatible = "xuantie,pmc"; status = "okay"; reg = <0x00000000 0x26900000 0x00000000 0x00001000>; }; } ``` Signed-off-by: Chen Pei <cp0613@linux.alibaba.com>
1 parent a9994da commit f94bfb8

File tree

5 files changed

+278
-0
lines changed

5 files changed

+278
-0
lines changed

platform/generic/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ config PLATFORM_THEAD
6565
select THEAD_C9XX_PMU
6666
default n
6767

68+
config PLATFORM_XUANTIE
69+
bool "XuanTie 9xx support"
70+
default n
71+
6872
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
6973
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
7074

platform/generic/configs/defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
66
CONFIG_PLATFORM_SOPHGO_SG2042=y
77
CONFIG_PLATFORM_STARFIVE_JH7110=y
88
CONFIG_PLATFORM_THEAD=y
9+
CONFIG_PLATFORM_XUANTIE=y
910
CONFIG_FDT_GPIO=y
1011
CONFIG_FDT_GPIO_DESIGNWARE=y
1112
CONFIG_FDT_GPIO_SIFIVE=y
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#
2+
# SPDX-License-Identifier: BSD-2-Clause
3+
#
4+
5+
carray-platform_override_modules-$(CONFIG_PLATFORM_XUANTIE) += xuantie_pmc
6+
platform-objs-$(CONFIG_PLATFORM_XUANTIE) += xuantie/xuantie_pmc.o
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*
2+
* SPDX-License-Identifier: BSD-2-Clause
3+
*/
4+
5+
#include <libfdt.h>
6+
#include <platform_override.h>
7+
#include <thead/c9xx_encoding.h>
8+
#include <thead/c9xx_pmu.h>
9+
#include <sbi/riscv_asm.h>
10+
#include <sbi/riscv_io.h>
11+
#include <sbi/sbi_bitops.h>
12+
#include <sbi/sbi_ecall_interface.h>
13+
#include <sbi/sbi_error.h>
14+
#include <sbi/sbi_hsm.h>
15+
#include <sbi/sbi_system.h>
16+
#include <sbi/sbi_pmu.h>
17+
#include <sbi/sbi_scratch.h>
18+
#include <sbi/sbi_console.h>
19+
#include <sbi/sbi_platform.h>
20+
#include <sbi_utils/fdt/fdt_fixup.h>
21+
#include <sbi_utils/fdt/fdt_helper.h>
22+
#include <sbi_utils/irqchip/fdt_irqchip_plic.h>
23+
24+
#include "xuantie_pmc.h"
25+
26+
static struct xuantie_pmc_data pmc = { 0 };
27+
static unsigned long zsb_addr = 0;
28+
29+
static inline void xuantie_riscv_cfg_init(void)
30+
{
31+
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
32+
33+
if (!zsb_addr) {
34+
zsb_addr = scratch->next_addr - 0x00008000;
35+
}
36+
}
37+
38+
static inline int pmc_set_command(struct xuantie_pmc_data *pmc, u32 hartid, u32 blkid, u32 val)
39+
{
40+
u64 pmc_base, blk_sw_mode_ctl;
41+
42+
if (pmc) {
43+
pmc_base = pmc->pmc_addr + 0x1000 * hartid;
44+
blk_sw_mode_ctl = 0x100 + 0x4 * blkid;
45+
writel(val, (void *)(uintptr_t)(pmc_base + blk_sw_mode_ctl));
46+
return 0;
47+
} else
48+
return SBI_EINVAL;
49+
}
50+
51+
static inline void xuantie_hart_poweroff(u32 hartid, bool is_dynamic)
52+
{
53+
if (is_dynamic) {
54+
/* cpu_idle power down, set trans bit to dynamic mode */
55+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE, PMC_TRANS_MODE_DYNAMIC | PMC_BLK_MODE_CONFIG_OFF);
56+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE_VFPU, PMC_TRANS_MODE_DYNAMIC | PMC_BLK_LOW_POWER_STATE_OFF);
57+
} else {
58+
/* cpu_hotplug power down, set trans bit to direct mode */
59+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE, PMC_TRANS_MODE_DIRECT | PMC_BLK_MODE_CONFIG_OFF);
60+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE_VFPU, PMC_TRANS_MODE_DIRECT | PMC_BLK_LOW_POWER_STATE_OFF);
61+
}
62+
63+
/* close the prefetch */
64+
csr_clear(THEAD_C9XX_CSR_MHINT, 0x1 << 2);
65+
66+
/* clean and invalid core's dcache */
67+
asm volatile(XUANTIE_DCACHE_INVAL_CLEAN_ALL);
68+
69+
/* close the dcache */
70+
csr_clear(THEAD_C9XX_CSR_MHCR, 0x1 << 1);
71+
72+
/* close the snoop */
73+
csr_clear(THEAD_C9XX_CSR_MSMPR, 0x1 << 0);
74+
75+
/* sync.s */
76+
asm volatile(XUANTIE_SYNC_S);
77+
78+
wfi();
79+
}
80+
81+
static int xuantie_hart_suspend(u32 suspend_type)
82+
{
83+
u32 hartid = current_hartid();
84+
85+
/* Use the generic code for retentive suspend. */
86+
if (!(suspend_type & SBI_HSM_SUSP_NON_RET_BIT))
87+
return SBI_ENOTSUPP;
88+
89+
xuantie_hart_poweroff(hartid, true);
90+
91+
return 0;
92+
}
93+
94+
static void xuantie_hart_resume(void)
95+
{
96+
u32 hartid = current_hartid();
97+
98+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE, PMC_TRANS_MODE_DIRECT | PMC_BLK_MODE_CONFIG_ON);
99+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE_VFPU, PMC_TRANS_MODE_DIRECT | PMC_BLK_LOW_POWER_STATE_RET);
100+
}
101+
102+
int xuantie_hart_start(u32 hartid, ulong saddr)
103+
{
104+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE, PMC_TRANS_MODE_DIRECT | PMC_BLK_MODE_CONFIG_ON);
105+
pmc_set_command(&pmc, hartid, PMC_BLK_CORE_VFPU, PMC_TRANS_MODE_DIRECT | PMC_BLK_LOW_POWER_STATE_RET);
106+
107+
return 0;
108+
}
109+
110+
int xuantie_hart_stop(void)
111+
{
112+
u32 hartid = current_hartid();
113+
114+
xuantie_hart_poweroff(hartid, false);
115+
116+
return 0;
117+
}
118+
119+
static const struct sbi_hsm_device xuantie_hsm = {
120+
.name = "xuantie-hsm",
121+
.hart_suspend = xuantie_hart_suspend,
122+
.hart_resume = xuantie_hart_resume,
123+
.hart_start = xuantie_hart_start,
124+
.hart_stop = xuantie_hart_stop,
125+
};
126+
127+
static int xuantie_system_suspend_check(u32 sleep_type)
128+
{
129+
return sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND ? 0 : SBI_EINVAL;
130+
}
131+
132+
static int xuantie_system_suspend(u32 sleep_type, unsigned long mmode_resume_addr)
133+
{
134+
u32 hartid = current_hartid();
135+
136+
if (sleep_type != SBI_SUSP_SLEEP_TYPE_SUSPEND)
137+
return SBI_EINVAL;
138+
139+
/* cpu poweroff after wfi */
140+
xuantie_hart_poweroff(hartid, true);
141+
142+
return 0;
143+
}
144+
145+
static struct sbi_system_suspend_device xuantie_system_suspend_dev = {
146+
.name = "xuantie-system-suspend",
147+
.system_suspend_check = xuantie_system_suspend_check,
148+
.system_suspend = xuantie_system_suspend,
149+
};
150+
151+
static int xuantie_system_reset_check(u32 type, u32 reason)
152+
{
153+
switch (type) {
154+
case SBI_SRST_RESET_TYPE_SHUTDOWN:
155+
return 1;
156+
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
157+
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
158+
return 255;
159+
}
160+
161+
return 0;
162+
}
163+
164+
static void xuantie_system_reset(u32 type, u32 reason)
165+
{
166+
}
167+
168+
static struct sbi_system_reset_device xuantie_reset = {
169+
.name = "xuantie-reset",
170+
.system_reset_check = xuantie_system_reset_check,
171+
.system_reset = xuantie_system_reset
172+
};
173+
174+
static int xuantie_pmc_test_device_init(void)
175+
{
176+
int nodeoffset, rc;
177+
void *fdt = fdt_get_address();
178+
179+
nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,pmc");
180+
if (nodeoffset < 0)
181+
return nodeoffset;
182+
183+
rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, (uint64_t *)&pmc.pmc_addr, NULL);
184+
if (rc)
185+
return SBI_ENODEV;
186+
187+
if (!fdt_node_is_enabled(fdt, nodeoffset))
188+
return SBI_ENODEV;
189+
190+
sbi_system_reset_add_device(&xuantie_reset);
191+
sbi_hsm_set_device(&xuantie_hsm);
192+
sbi_system_suspend_set_device(&xuantie_system_suspend_dev);
193+
194+
return 0;
195+
}
196+
197+
static int xuantie_final_init(bool cold_boot, const struct fdt_match *match)
198+
{
199+
if (cold_boot) {
200+
xuantie_riscv_cfg_init();
201+
xuantie_pmc_test_device_init();
202+
}
203+
204+
return 0;
205+
}
206+
207+
static const struct fdt_match xuantie_pmc_match[] = {
208+
{ .compatible = "xuantie,dummy" },
209+
{ },
210+
};
211+
212+
const struct platform_override xuantie_pmc = {
213+
.match_table = xuantie_pmc_match,
214+
.final_init = xuantie_final_init,
215+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* SPDX-License-Identifier: BSD-3-Clause
3+
*/
4+
5+
#ifndef __XUANTIE_PMC_H__
6+
#define __XUANTIE_PMC_H__
7+
8+
#include <sbi/sbi_types.h>
9+
10+
/* clang-format off */
11+
12+
#define XUANTIE_DCACHE_INVAL_CLEAN_ALL ".long 0x0030000b"
13+
#define XUANTIE_SYNC_S ".long 0x0190000b"
14+
15+
/*
16+
core PMC: blk1 = VFPU; blk2 = MPU
17+
cluster PMC: blk1 = l2cache
18+
*/
19+
#define PMC_BLK_CORE 0
20+
#define PMC_BLK_CORE_VFPU 1
21+
#define PMC_BLK_CORE_MPU 2
22+
#define PMC_BLK_CLUSTER 0
23+
#define PMC_BLK_CLUSTER_L2 1
24+
25+
#define PMC_TRANS_MODE_SHIFT 4
26+
#define PMC_TRANS_MODE_DIRECT (_UL(1) << PMC_TRANS_MODE_SHIFT)
27+
#define PMC_TRANS_MODE_DYNAMIC (_UL(0) << PMC_TRANS_MODE_SHIFT)
28+
/*pmc_blk_mode_config (basic type)*/
29+
#define PMC_BLK_MODE_CONFIG_0 0 // OFF pstate enable
30+
#define PMC_BLK_MODE_CONFIG_1 1
31+
#define PMC_BLK_MODE_CONFIG_2 2
32+
#define PMC_BLK_MODE_CONFIG_3 3
33+
#define PMC_BLK_MODE_CONFIG_4 4
34+
#define PMC_BLK_MODE_CONFIG_5 5
35+
#define PMC_BLK_MODE_CONFIG_6 6
36+
#define PMC_BLK_MODE_CONFIG_7 7
37+
#define PMC_BLK_MODE_CONFIG_8 8 // ON pstate enable
38+
#define PMC_BLK_MODE_CONFIG_9 9
39+
#define PMC_BLK_MODE_CONFIG_ON PMC_BLK_MODE_CONFIG_8
40+
#define PMC_BLK_MODE_CONFIG_OFF PMC_BLK_MODE_CONFIG_0
41+
/*pmc_blk_mode_config (pe type)*/
42+
#define PMC_BLK_LOW_POWER_STATE_OFF 0
43+
#define PMC_BLK_LOW_POWER_STATE_RET 1
44+
45+
46+
/* clang-format on */
47+
48+
struct xuantie_pmc_data {
49+
unsigned long pmc_addr;
50+
};
51+
52+
#endif /* __XUANTIE_PMC_H__ */

0 commit comments

Comments
 (0)