Files
thead-opensbi/platform/generic/light_c910.c
thead_admin d35408efb1 Linux_SDK_V1.3.3
Signed-off-by: thead_admin <occ_thead@service.alibaba.com>
2024-01-12 21:53:40 +08:00

256 lines
6.8 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 <ben.lh@alibaba-inc.com>
*/
#include <platform_override.h>
#include <thead_c9xx.h>
#include <aonsys_reg_define.h>
#include <apsys_reg_define.h>
#include <aprst_reg_define.h>
#include <sbi/riscv_asm.h>
#include <sbi/riscv_io.h>
#include <sbi/sbi_bitops.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_hsm.h>
#include <sbi/sbi_ipi.h>
#include <sbi/sbi_scratch.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/fdt/fdt_helper.h>
#define INDICATOR_0_MAGIC_NUM 0x5a5a5a5a
#define INDICATOR_1_MAGIC_NUM 0x12345678
#define INDICATOR_2_MAGIC_NUM 0x32fde438
#define INDICATOR_3_MAGIC_NUM 0x8ab4c52c
/* system lowpoer mode */
#define LP_HW_VAD (1 << 16)
#define LP_STANDBY (2 << 16)
/* redefine CSR register */
#define CSR_MXSTATUS THEAD_C9XX_CSR_MXSTATUS
#define CSR_MHCR THEAD_C9XX_CSR_MHCR
#define CSR_MCCR2 THEAD_C9XX_CSR_MCCR2
#define CSR_MHINT THEAD_C9XX_CSR_MHINT
#define CSR_MHINT2_E THEAD_C9XX_CSR_MHINT2
#define CSR_MHINT4 THEAD_C9XX_CSR_MHINT4
#define CSR_MSMPR THEAD_C9XX_CSR_MSMPR
#define CSR_SMPEN CSR_MSMPR
/* CSR_MHCR */
#define MHCR_IE _UL(0x00000001)
#define MHCR_DE _UL(0x00000002)
/* CSR_MHINT */
#define MHINT_DPLD _UL(0x00000004)
#define MHINT_IPLD _UL(0x00000100)
#define MHINT_L2PLD _UL(0x00008000)
/* CSR_MSMPR */
#define MSMPR_MSPEN _UL(0x00000001)
#define CONFIG_SYS_CACHELINE_SIZE 64
static unsigned long csr_mstatus;
static unsigned long csr_mie;
static unsigned long csr_mhcr;
static unsigned long csr_mhint;
static unsigned long csr_msmpen;
static int hotplug_flag = 0;
extern void __thead_pre_start_warm(void);
extern void *_data_start, *_data_end, *_bss_start, *_bss_end, *_fw_end;
static void light_set_lpmode(int mode)
{
writel(mode, (volatile void *)REG_AON_CHIP_LP_MODE);
}
static void light_mastercore_entryboot_set()
{
u32 t;
writel(INDICATOR_0_MAGIC_NUM, (volatile void *)REG_AON_STR_INDICATOR_0);
writel(INDICATOR_1_MAGIC_NUM, (volatile void *)REG_AON_STR_INDICATOR_1);
writel(INDICATOR_2_MAGIC_NUM, (volatile void *)REG_AON_STR_INDICATOR_2);
writel(INDICATOR_3_MAGIC_NUM, (volatile void *)REG_AON_STR_INDICATOR_3);
/* brom->spl entry addr */
writel(0xFF, (volatile void *)REG_AON_RESERVED_REG_0);
writel(0xE0000000, (volatile void *)REG_AON_RESERVED_REG_1);
/* spl->opensbi entry addr */
t = (ulong)&__thead_pre_start_warm;
writel(t, (volatile void *)REG_AON_RESERVED_REG_2);
t = (u64)(ulong)&__thead_pre_start_warm >> 32;
writel(t, (volatile void *)REG_AON_RESERVED_REG_3);
}
static void light_auxcore_entryboot_set()
{
u32 t;
/* spl->opensbi entry addr */
t = (ulong)&__thead_pre_start_warm;
writel(t, (volatile void *)REG_C910_CORE0_RVBA_L);
writel(t, (volatile void *)REG_C910_CORE1_RVBA_L);
writel(t, (volatile void *)REG_C910_CORE2_RVBA_L);
writel(t, (volatile void *)REG_C910_CORE3_RVBA_L);
t = (u64)(ulong)&__thead_pre_start_warm >> 32;
writel(t, (volatile void *)REG_C910_CORE0_RVBA_H);
writel(t, (volatile void *)REG_C910_CORE1_RVBA_H);
writel(t, (volatile void *)REG_C910_CORE2_RVBA_H);
writel(t, (volatile void *)REG_C910_CORE3_RVBA_H);
}
void cpu_performance_disable(void)
{
csr_write(CSR_SMPEN, 0x0);
csr_write(CSR_MHINT2_E, 0x0);
csr_write(CSR_MHINT4, 0x0);
csr_write(CSR_MCCR2, 0x02490009);
csr_write(CSR_MHCR, 0x11ff);
csr_write(CSR_MXSTATUS, 0xc0638000);
csr_write(CSR_MHINT, 0x24000);
}
static void light_mastercore_save(void)
{
/* a) disable all irq */
csr_mstatus = csr_read_clear(CSR_MSTATUS, MSTATUS_MIE | MSTATUS_SIE);
csr_mie = csr_read_clear(CSR_MIE, MIP_MSIP | MIP_MTIP | MIP_MEIP | \
MIP_SSIP | MIP_STIP | MIP_SEIP );
hotplug_flag = 1;
/* b) close prefetch */
csr_mhint = csr_read_clear(CSR_MHINT, MHINT_L2PLD | MHINT_IPLD | MHINT_DPLD);
/* c) inv&clr d-call all */
dcache_ciall();
sync_is();
/* d) close dcache */
csr_mhcr = csr_read_clear(CSR_MHCR, MHCR_DE);
/* e) close smpen */
csr_msmpen = csr_read_clear(CSR_MSMPR, MSMPR_MSPEN);
/* f) fence iorw,iorw*/
mb();
/* g) sleepmode reg */
light_set_lpmode(LP_STANDBY);
/* set mastercore bootrom jump entry */
light_mastercore_entryboot_set();
cpu_performance_disable();
/* h) wfi */
wfi();
__thead_pre_start_warm();
}
static void light_auxcore_save(void)
{
/* a) disable all irq */
csr_mstatus = csr_read_clear(CSR_MSTATUS, MSTATUS_MIE | MSTATUS_SIE);
csr_mie = csr_read_clear(CSR_MIE, MIP_MSIP | MIP_MTIP | MIP_MEIP | \
MIP_SSIP | MIP_STIP | MIP_SEIP );
hotplug_flag = 1;
/* b) close prefetch */
csr_mhint = csr_read_clear(CSR_MHINT, MHINT_L2PLD | MHINT_IPLD | MHINT_DPLD);
/* c) inv&clr d-call all */
dcache_ciall();
sync_is();
/* d) close dcache */
csr_mhcr = csr_read_clear(CSR_MHCR, MHCR_DE);
/* e) close smpen */
csr_msmpen = csr_read_clear(CSR_MSMPR, MSMPR_MSPEN);
/* f) fence iorw,iorw*/
mb();
/* g) sleepmode reg */
/* h) wfi : when test hotplug just comment wfi to continue run */
wfi();
}
static void light_auxcore_restore(u32 hartid)
{
u32 val;
/* set auxcore bootrom jump entry after warm reset*/
light_auxcore_entryboot_set();
if (hotplug_flag) {
val = readl((volatile void *)REG_C910_SWRST);
val &= ~(1 << (hartid + 1));
writel(val, (volatile void *)REG_C910_SWRST);
val |= (1 << (hartid + 1));
writel(val, (volatile void *)REG_C910_SWRST);
}
}
static int light_hart_start(u32 hartid, ulong saddr)
{
sbi_printf("core:%d %s: line:%d enter\n",current_hartid(), __func__, __LINE__);
/* send ipi to triger already plugout core which will be waiting in sbi_hsm_hart_wait
* after reset.
*/
light_auxcore_restore(hartid);
sbi_printf("core:%d %s: line:%d exit\n", current_hartid(), __func__, __LINE__);
return 0;
}
static int light_hart_stop(void)
{
sbi_printf("core:%d %s: line:%d enter\n",current_hartid(), __func__, __LINE__);
light_auxcore_save();
sbi_printf("core:%d %s: line:%d exit\n", current_hartid(), __func__, __LINE__);
return 0;
}
static int light_hart_suspend(u32 suspend_type, ulong raddr)
{
sbi_printf("core:%d %s: line:%d enter\n",current_hartid(), __func__, __LINE__);
/* Use the generic code for retentive suspend. */
if (!(suspend_type & SBI_HSM_SUSP_NON_RET_BIT))
return SBI_ENOTSUPP;
light_mastercore_save();
sbi_printf("core:%d %s: line:%d exit\n", current_hartid(), __func__, __LINE__);
return 0;
}
static const struct sbi_hsm_device light_ppu = {
.name = "light-ppu",
.hart_start = light_hart_start,
.hart_stop = light_hart_stop,
.hart_suspend = light_hart_suspend,
};
static int light_final_init(bool cold_boot, const struct fdt_match *match)
{
sbi_printf("core:%d %s: line:%d enter. cold_boot:%d\n",current_hartid(), __func__, __LINE__, cold_boot);
sbi_hsm_set_device(&light_ppu);
return 0;
}
static const struct fdt_match ligth_match[] = {
{ .compatible = "thead,light" },
{ },
};
const struct platform_override light = {
.match_table = ligth_match,
.final_init = light_final_init,
};