/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2025 MIPS * */ #include #include #include #include #include #include #include #include const struct p8700_cm_info *p8700_cm_info; void mips_p8700_pmp_set(unsigned int n, unsigned long flags, unsigned long prot, unsigned long addr, unsigned long log2len) { int pmacfg_csr, pmacfg_shift; unsigned long cfgmask; unsigned long pmacfg, cca; pmacfg_csr = (CSR_MIPSPMACFG0 + (n >> 2)) & ~1; pmacfg_shift = (n & 7) << 3; cfgmask = ~(0xffUL << pmacfg_shift); /* Read pmacfg to change cacheability */ pmacfg = (csr_read_num(pmacfg_csr) & cfgmask); cca = (flags & SBI_DOMAIN_MEMREGION_MMIO) ? CCA_CACHE_DISABLE : CCA_CACHE_ENABLE | PMA_SPECULATION; pmacfg |= ((cca << pmacfg_shift) & ~cfgmask); csr_write_num(pmacfg_csr, pmacfg); } void mips_p8700_power_up_other_cluster(u32 hartid) { unsigned int cl = cpu_cluster(hartid); /* Power up CM in cluster */ write_cpc_pwrup_ctl(hartid, 1); /* Wait for the CM to start up */ for (int i = 100; i > 0; i--) { u32 stat = read_cpc_cm_stat_conf(hartid); stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE); if (stat == CPC_Cx_STAT_CONF_SEQ_STATE_U5) return; cpu_relax(); } sbi_printf("ERROR: Fail to power up cluster %u\n", cl); } extern void mips_warm_boot(void); struct mips_boot_params { u32 hartid; u32 target_state; }; static bool mips_hart_reached_state(void *arg) { struct mips_boot_params *p = arg; u32 stat = read_cpc_co_stat_conf(p->hartid); stat = EXT(stat, CPC_Cx_STAT_CONF_SEQ_STATE); return stat == p->target_state; } int mips_p8700_hart_start(u32 hartid, ulong saddr) { /* Hart 0 is the boot hart, and we don't use the CPC cmd to start. */ if (hartid == 0) return SBI_ENOTSUPP; /* Change reset base to mips_warm_boot */ write_gcr_co_reset_base(hartid, (unsigned long)mips_warm_boot); if (cpu_hart(hartid) == 0) { unsigned int const timeout_ms = 10; bool booted; struct mips_boot_params p = { .hartid = hartid, .target_state = CPC_Cx_STAT_CONF_SEQ_STATE_U6, }; /* Ensure its coherency is disabled */ write_gcr_co_coherence(hartid, 0); /* Start cluster cl core co hart 0 */ write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid)); /* Reset cluster cl core co hart 0 */ write_cpc_co_cmd(hartid, CPC_Cx_CMD_RESET); booted = sbi_timer_waitms_until(mips_hart_reached_state, &p, timeout_ms); if (!booted) { sbi_printf("ERROR: failed to boot hart 0x%x in %d ms\n", hartid, timeout_ms); return -SBI_ETIMEDOUT; } } else { write_cpc_co_vp_run(hartid, 1 << cpu_hart(hartid)); } return 0; } int mips_p8700_hart_stop() { u32 hartid = current_hartid(); /* Hart 0 is the boot hart, and we don't use the CPC cmd to stop. */ if (hartid == 0) return SBI_ENOTSUPP; write_cpc_co_vp_stop(hartid, 1 << cpu_hart(hartid)); return 0; } int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match) { const struct p8700_cm_info *data = match->data; if (!data) { sbi_printf("Missing CM info for %s\n", match->compatible); return SBI_EINVAL; } p8700_cm_info = data; return SBI_OK; }