mirror of
https://github.com/riscv-software-src/opensbi
synced 2025-11-05 06:20:21 +00:00
platform: generic: spacemit: add K1
Add initial platform support for the SpacemiT K1 SoC, including early/final init hooks, cold boot handling, and CCI-550 snoop/DVM enablement. Co-authored-by: Troy Mitchell <troy.mitchell@linux.spacemit.com> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com> Signed-off-by: Xianbin Zhu <xianbin.zhu@linux.spacemit.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/all/15169E392597D319+aOcKujCl8mz4XK4L@kernel.org/ [1] Link: https://lore.kernel.org/r/20250925-smt-k1-8-cores-v3-1-0885a8a70f8e@linux.spacemit.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
parent
e3eb59a396
commit
1f84ec2ac2
@ -83,6 +83,10 @@ config PLATFORM_MIPS_P8700
|
||||
bool "MIPS P8700 support"
|
||||
default n
|
||||
|
||||
config PLATFORM_SPACEMIT_K1
|
||||
bool "Spacemit K1 support"
|
||||
default n
|
||||
|
||||
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
|
||||
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
|
||||
|
||||
|
||||
98
platform/generic/include/spacemit/k1.h
Normal file
98
platform/generic/include/spacemit/k1.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef __RISCV_SPACEMIT_K1_H__
|
||||
#define __RISCV_SPACEMIT_K1_H__
|
||||
|
||||
#define CSR_MSETUP 0x7c0
|
||||
#define CSR_MHCR 0x7c1
|
||||
#define CSR_MRAOP 0x7c2
|
||||
#define CSR_MHINT 0x7c5
|
||||
#define CSR_ML2SETUP 0x7f0
|
||||
|
||||
/* decache enable */
|
||||
#define MSETUP_DE BIT(0)
|
||||
/* icache enable */
|
||||
#define MSETUP_IE BIT(1)
|
||||
/* branch prediction enable */
|
||||
#define MSETUP_BPE BIT(4)
|
||||
/* prefetch functionality enable */
|
||||
#define MSETUP_PFE BIT(5)
|
||||
/* misaligned memory access enable */
|
||||
#define MSETUP_MME BIT(6)
|
||||
/* ECC enable */
|
||||
#define MSETUP_ECCE BIT(16)
|
||||
|
||||
/* icache invalidation */
|
||||
#define MRAOP_ICACHE_INVALID GENMASK(1, 0)
|
||||
|
||||
#define PMU_AP_BASE 0xd4282800
|
||||
|
||||
#define PMU_AP_CORE0_WAKEUP_OFFSET (PMU_AP_BASE + 0x12c)
|
||||
#define PMU_AP_CORE4_WAKEUP_OFFSET (PMU_AP_BASE + 0x324)
|
||||
#define PMU_AP_CLUSTER0_WAKEUP_OFFSET(index) (PMU_AP_CORE0_WAKEUP_OFFSET + index * 4)
|
||||
#define PMU_AP_CLUSTER1_WAKEUP_OFFSET(index) (PMU_AP_CORE4_WAKEUP_OFFSET + index * 4)
|
||||
|
||||
#define PMU_AP_CORE0_IDLE_CFG_OFFSET (PMU_AP_BASE + 0x124)
|
||||
#define PMU_AP_CORE4_IDLE_CFG_OFFSET (PMU_AP_BASE + 0x304)
|
||||
#define PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(index) (PMU_AP_CORE0_IDLE_CFG_OFFSET + index * 4)
|
||||
#define PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(index) (PMU_AP_CORE4_IDLE_CFG_OFFSET + index * 4)
|
||||
|
||||
#define PMU_AP_CORE0_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(0)
|
||||
#define PMU_AP_CORE1_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(1)
|
||||
#define PMU_AP_CORE2_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(2)
|
||||
#define PMU_AP_CORE3_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(3)
|
||||
#define PMU_AP_CORE4_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(0)
|
||||
#define PMU_AP_CORE5_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(1)
|
||||
#define PMU_AP_CORE6_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(2)
|
||||
#define PMU_AP_CORE7_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(3)
|
||||
|
||||
#define PMU_AP_CORE0_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(0)
|
||||
#define PMU_AP_CORE1_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(1)
|
||||
#define PMU_AP_CORE2_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(2)
|
||||
#define PMU_AP_CORE3_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(3)
|
||||
#define PMU_AP_CORE4_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(0)
|
||||
#define PMU_AP_CORE5_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(1)
|
||||
#define PMU_AP_CORE6_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(2)
|
||||
#define PMU_AP_CORE7_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(3)
|
||||
|
||||
/* power down */
|
||||
#define PMU_AP_IDLE_PWRDWN BIT(0)
|
||||
/* sram power down */
|
||||
#define PMU_AP_IDLE_SRAM_PWRDWN BIT(1)
|
||||
/* enable wake up the memory controller */
|
||||
#define PMU_AP_IDLE_WAKE_MCE BIT(3)
|
||||
/* disable memory controller software req */
|
||||
#define PMU_AP_IDLE_MC_SW_REQ BIT(4)
|
||||
|
||||
#define PMU_AP_IDLE_PWRDOWN_MASK (PMU_AP_IDLE_PWRDWN | PMU_AP_IDLE_SRAM_PWRDWN | \
|
||||
PMU_AP_IDLE_WAKE_MCE | PMU_AP_IDLE_MC_SW_REQ)
|
||||
/* cci */
|
||||
#define C0_RVBADDR_LO_ADDR 0xd4282db0
|
||||
#define C0_RVBADDR_HI_ADDR 0xd4282db4
|
||||
#define C1_RVBADDR_LO_ADDR 0xd4282eb0
|
||||
#define C1_RVBADDR_HI_ADDR 0xd4282c04
|
||||
|
||||
#define CCI_550_PLATFORM_CCI_ADDR 0xd8500000
|
||||
|
||||
/* relative to cci base */
|
||||
#define CCI_550_STATUS 0x000c
|
||||
/* status register bits */
|
||||
#define CCI_550_STATUS_CHANGE_PENDING BIT(0)
|
||||
|
||||
/* slave interface registers */
|
||||
#define CCI_550_SLAVE_IFACE0_OFFSET 0x1000
|
||||
#define CCI_550_SLAVE_IFACE_OFFSET(idx) (CCI_550_SLAVE_IFACE0_OFFSET + ((0x1000) * (idx)))
|
||||
|
||||
/* relative to slave interface base */
|
||||
#define CCI_550_SNOOP_CTRL 0x0000
|
||||
/* snoop control register bits */
|
||||
#define CCI_550_SNOOP_CTRL_ENABLE_SNOOPS BIT(0)
|
||||
#define CCI_550_SNOOP_CTRL_ENABLE_DVMS BIT(1)
|
||||
|
||||
/* clusters and CPU mapping */
|
||||
#define PLATFORM_MAX_CPUS 8
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
|
||||
#define CPU_TO_CLUSTER(cpu) ((cpu) / PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
|
||||
#define PLAT_CCI_CLUSTER0_IFACE_IX 0
|
||||
#define PLAT_CCI_CLUSTER1_IFACE_IX 1
|
||||
|
||||
#endif
|
||||
113
platform/generic/spacemit/k1.c
Normal file
113
platform/generic/spacemit/k1.c
Normal file
@ -0,0 +1,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(scratch->warmboot_addr >> 32, (unsigned int *)C0_RVBADDR_HI_ADDR);
|
||||
|
||||
writel(scratch->warmboot_addr, (unsigned int *)C1_RVBADDR_LO_ADDR);
|
||||
writel(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,
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user