From 7aad08218f25d4eed674bc172995f38291ebfb5e Mon Sep 17 00:00:00 2001 From: James Deng Date: Mon, 15 Apr 2024 11:42:57 +0800 Subject: Update for v1.0beta3.1 --- debian/.gitignore | 1 + debian/README.source | 7 + debian/bin/git-snapshot | 18 ++ debian/control | 24 +++ debian/copyright | 177 ++++++++++++++++++ debian/opensbi-spacemit.docs | 2 + debian/opensbi-spacemit.install | 1 + debian/opensbi-spacemit.lintian-overrides | 9 + debian/opensbi-spacemit.postinst | 45 +++++ debian/rules | 27 +++ debian/source/format | 1 + debian/upstream/metadata | 5 + debian/watch | 3 + include/sbi/riscv_encoding.h | 1 + include/sbi_utils/irqchip/fdt_irqchip_plic.h | 2 - lib/sbi/sbi_console.c | 7 + lib/sbi/sbi_hart.c | 6 + lib/utils/Kconfig | 7 + lib/utils/arm_scmi/css/common/css_pm.c | 3 +- lib/utils/irqchip/fdt_irqchip_plic.c | 5 - lib/utils/psci/psci_common.c | 52 +++++ lib/utils/psci/psci_main.c | 82 ++++++-- lib/utils/psci/psci_private.h | 4 + .../spacemit/plat/k1x/underly_implement.c | 61 +++++- lib/utils/psci/spacemit/plat/plat_pm.c | 25 ++- platform/generic/spacemit/spacemit_k1.c | 175 +++++++++++------ 26 files changed, 659 insertions(+), 91 deletions(-) create mode 100644 debian/.gitignore create mode 100644 debian/README.source create mode 100755 debian/bin/git-snapshot create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/opensbi-spacemit.docs create mode 100644 debian/opensbi-spacemit.install create mode 100644 debian/opensbi-spacemit.lintian-overrides create mode 100755 debian/opensbi-spacemit.postinst create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/upstream/metadata create mode 100644 debian/watch diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 000000000000..6d10dce740f7 --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1 @@ +changelog diff --git a/debian/README.source b/debian/README.source new file mode 100644 index 000000000000..bd33e1488fcf --- /dev/null +++ b/debian/README.source @@ -0,0 +1,7 @@ +Upstream git snapshots are produced with: + + ./debian/bin/git-snapshot COMMIT + +Which produces an upstream version based on "git describe" output. + + -- Vagrant Cascadian , Thu, 30 May 2019 15:02:49 -0700 diff --git a/debian/bin/git-snapshot b/debian/bin/git-snapshot new file mode 100755 index 000000000000..6db5eb241d78 --- /dev/null +++ b/debian/bin/git-snapshot @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +commit="$1" +test -z "$commit" && echo "invalid commit" && exit 1 +package=opensbi +archive=tar.gz +version=$(git describe "$commit" | sed -e 's,-,+,' -e 's,-g,.,' -e 's,^v,,g') +output=../${package}_${version}.orig.${archive} +test -f "${output}" && echo "already present: ${output}" && exit 1 + +git archive \ + --format=${archive} \ + --prefix=${package}-${version}/ \ + --output=${output} \ + ${commit} && \ + echo "successfully created: ${output}" diff --git a/debian/control b/debian/control new file mode 100644 index 000000000000..6c4a1747b5f3 --- /dev/null +++ b/debian/control @@ -0,0 +1,24 @@ +Source: opensbi-spacemit +Section: misc +Priority: optional +Maintainer: Vagrant Cascadian +Uploaders: Karsten Merker +Build-Depends: debhelper-compat (=13), + python3, + u-boot-tools, +Standards-Version: 4.6.2 +Rules-Requires-Root: no +Vcs-Browser: https://salsa.debian.org/opensbi-team/opensbi +Vcs-Git: https://salsa.debian.org/opensbi-team/opensbi.git +Homepage: https://github.com/riscv-software-src/opensbi + +Package: opensbi-spacemit +Architecture: all +Multi-Arch: foreign +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: RISC-V Open Source Supervisor Binary Interface + An open-source reference implementation of the RISC-V SBI + specifications for platform-specific firmwares executing in M-mode. + . + The following firmware platforms are provided: + generic diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000000..cfbcf75e0649 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,177 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: opensbi +Source: https://github.com/riscv-software-src/opensbi + +Files: * +Copyright: 2019-2020 Western Digital Corporation or its affiliates and + other contributors. + 2019-2022 Western Digital Corporation or its affiliates. + 2021 Christoph Müllner + 2021 YADRO + 2021 Cobham Gaisler AB. + 2021 Gabriel Somlo + 2021-2022 SiFive + 2021-2022 Samuel Holland + 2022 Ventana Micro Systems Inc. + 2022 Andes Technology Corporation + 2022 StarFive Technology Co., Ltd. + 2022 Renesas Electronics Corporation + 2023 RISC-V International +License: BSD-2-clause + +Files: include/sbi_utils/sys/htif.h + lib/utils/sys/htif.c +Copyright: 2010-2020, The Regents of the University of California +License: BSD-3-clause + +Files: debian/* +Copyright: 2019-2022 Vagrant Cascadian +License: BSD-2-clause + +Files: platform/generic/renesas/rzfive/rzfive.c +Copyright: 2022 Renesas Electronics Corp. +License: GPL-2 + +Files: platform/fpga/ariane/* +Copyright: 2019 FORTH-ICS/CARV +License: BSD-2-clause + +Files: lib/utils/libfdt/* +Copyright: 2006-2012 David Gibson, IBM Corporation. + 2012 Kim Phillips, Freescale Semiconductor. + 2014 David Gibson + 2016 Free Electrons + 2016 NextThing Co. + 2018 embedded brains GmbH +License: BSD-2-clause or GPL-2+ + +Files: lib/utils/libfdt/objects.mk +Copyright: 2019 Western Digital Corporation or its affiliates. +License: BSD-2-clause + +Files: + lib/utils/libquad/divdi3.c + lib/utils/libquad/moddi3.c + lib/utils/libquad/qdivrem.c + lib/utils/libquad/quad.h + lib/utils/libquad/udivdi3.c + lib/utils/libquad/umoddi3.c +Copyright: + 1992, 1993 The Regents of the University of California. +License: BSD-3-clause + +Files: + lib/utils/libquad/include/limits.h + lib/utils/libquad/include/sys/cdefs.h + lib/utils/libquad/include/sys/types.h + lib/utils/libquad/objects.mk +Copyright: 2021 Jessica Clarke +License: BSD-2-clause + +Files: + include/sbi_utils/fdt/* + lib/utils/fdt/* +Copyright: + 2020 Bin Meng + 2021 Western Digital Corporation or its affiliates. +License: BSD-2-clause + +Files: scripts/Kconfiglib/* +Copyright: 2011-2019, Ulf Magnusson +License: ISC + +License: BSD-2-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: BSD-3-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + . + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + . + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + . + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +License: GPL-2+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU General Public + License Version 2.0 can be found in + `/usr/share/common-licenses/GPL-2'. + +License: GPL-2 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU General Public + License Version 2.0 can be found in + `/usr/share/common-licenses/GPL-2'. + +License: ISC + Permission to use, copy, modify, and/or distribute this software for + any purpose with or without fee is hereby granted, provided that the + above copyright notice and this permission notice appear in all + copies. diff --git a/debian/opensbi-spacemit.docs b/debian/opensbi-spacemit.docs new file mode 100644 index 000000000000..85f6f20d235f --- /dev/null +++ b/debian/opensbi-spacemit.docs @@ -0,0 +1,2 @@ +docs/ +CONTRIBUTORS.md diff --git a/debian/opensbi-spacemit.install b/debian/opensbi-spacemit.install new file mode 100644 index 000000000000..d1897d557a11 --- /dev/null +++ b/debian/opensbi-spacemit.install @@ -0,0 +1 @@ +build/platform/generic/firmware/fw_*.itb /usr/lib/riscv64-linux-gnu/opensbi/generic/ diff --git a/debian/opensbi-spacemit.lintian-overrides b/debian/opensbi-spacemit.lintian-overrides new file mode 100644 index 000000000000..8b6168d15e45 --- /dev/null +++ b/debian/opensbi-spacemit.lintian-overrides @@ -0,0 +1,9 @@ +# These are binary firmware for use with qemu. +opensbi binary: arch-independent-package-contains-binary-or-object *usr/lib/*/opensbi/*/fw_*.elf* + +# Needs to be statically linked. +opensbi binary: statically-linked-binary *usr/lib/*/opensbi/*/fw_*.elf* + +# Binary firmwares being installed into multi-arch directory for +# future-proofing if riscv32 becomes a thing. +opensbi binary: triplet-dir-and-architecture-mismatch is for riscv64 instead of all *usr/lib/riscv64-linux-gnu/* diff --git a/debian/opensbi-spacemit.postinst b/debian/opensbi-spacemit.postinst new file mode 100755 index 000000000000..1f6feca80674 --- /dev/null +++ b/debian/opensbi-spacemit.postinst @@ -0,0 +1,45 @@ +#!/bin/sh +set -e + +case "$1" in +configure) + target="" + if grep -q '^spacemit' /sys/firmware/devicetree/base/model; then + target="spacemit" + else + exit 0 + fi + + for x in $(cat /proc/cmdline); do + case $x in + root=*) + ROOT=${x#root=} + ;; + esac + done + + if [ -n $ROOT ]; then + case $ROOT in + "/dev/mmcblk0"*) + OPENSBI=/dev/mmcblk0p3 + ;; + "/dev/mmcblk2"*) + OPENSBI=/dev/mmcblk2p3 + ;; + *) + echo "Unsupported root=$ROOT" + exit 0 + ;; + esac + else + echo "Missing root= in cmdline" + exit 0 + fi + + if [ -n "$target" ] && [ -e $OPENSBI ]; then + dd if=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb of=$OPENSBI bs=1 && sync + fi + ;; +esac + +exit 0 diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000000..ab9cc10c406c --- /dev/null +++ b/debian/rules @@ -0,0 +1,27 @@ +#!/usr/bin/make -f +# Always set CROSS_COMPILE, which also works for native builds. +export CROSS_COMPILE=riscv64-unknown-linux-gnu- +export ARCH=riscv + +# Enable verbose build by default, disable when terse is specified. +ifeq (,$(filter terse,$(DEB_BUILD_OPTIONS))) +VERBOSE=1 +else +VERBOSE=0 +endif + +%: + dh $@ + +override_dh_auto_build: + make \ + V=$(VERBOSE) \ + PLATFORM_DEFCONFIG=k1_defconfig \ + PLATFORM=generic ; \ + +override_dh_installdocs: + dh_installdocs --exclude=doxygen.cfg + +override_dh_install: + chmod -x build/platform/generic/firmware/fw_*.bin + dh_install diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 000000000000..163aaf8d82b6 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/upstream/metadata b/debian/upstream/metadata new file mode 100644 index 000000000000..f716ba77edcd --- /dev/null +++ b/debian/upstream/metadata @@ -0,0 +1,5 @@ +--- +Bug-Database: https://github.com/riscv-software-src/opensbi/issues +Bug-Submit: https://github.com/riscv-software-src/opensbi/issues/new +Repository: https://github.com/riscv-software-src/opensbi.git +Repository-Browse: https://github.com/riscv-software-src/opensbi diff --git a/debian/watch b/debian/watch new file mode 100644 index 000000000000..508d476a75c0 --- /dev/null +++ b/debian/watch @@ -0,0 +1,3 @@ +version=4 +opts=filenamemangle=s/\/(.*)v/@PACKAGE@-/ \ + https://github.com/riscv-software-src/@PACKAGE@/tags .*/v@ANY_VERSION@.tar.gz diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index 54e09d44528b..5abb8e4c776b 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -709,6 +709,7 @@ #define CSR_MIPH 0x354 #define CSR_TCMCFG 0x5DB +#define CSR_FEATURECTL 0xbf9 /* ===== Trap/Exception Causes ===== */ diff --git a/include/sbi_utils/irqchip/fdt_irqchip_plic.h b/include/sbi_utils/irqchip/fdt_irqchip_plic.h index b892b0bc70f8..df645dd00ee3 100644 --- a/include/sbi_utils/irqchip/fdt_irqchip_plic.h +++ b/include/sbi_utils/irqchip/fdt_irqchip_plic.h @@ -28,8 +28,6 @@ void fdt_plic_context_save(bool smode, u32 *enable, u32 *threshold, u32 num); void fdt_plic_context_restore(bool smode, const u32 *enable, u32 threshold, u32 num); -void fdt_plic_context_exit(void); - void thead_plic_restore(void); #endif diff --git a/lib/sbi/sbi_console.c b/lib/sbi/sbi_console.c index 168dffd06429..9d917ec78927 100644 --- a/lib/sbi/sbi_console.c +++ b/lib/sbi/sbi_console.c @@ -422,6 +422,7 @@ int sbi_snprintf(char *out, u32 out_sz, const char *format, ...) return retval; } +#ifdef CONFIG_ENABLE_LOGGING int sbi_printf(const char *format, ...) { va_list args; @@ -435,6 +436,12 @@ int sbi_printf(const char *format, ...) return retval; } +#else +int sbi_printf(const char *format, ...) +{ + return 0; +} +#endif int sbi_dprintf(const char *format, ...) { diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 3a3265df7f20..a3f752d27105 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -819,6 +819,12 @@ sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1, } csr_write(CSR_TCMCFG, 1); + /* + * update 0xfb9 csr: + * bit9: for emprove fence operation + * bit23 for disable vector load/store dual-issue + */ + csr_set(CSR_FEATURECTL, (1<<9)|(1<<23)); register unsigned long a0 asm("a0") = arg0; register unsigned long a1 asm("a1") = arg1; diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig index 3ac04ab1ab4f..dab9bf956598 100644 --- a/lib/utils/Kconfig +++ b/lib/utils/Kconfig @@ -24,4 +24,11 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig" source "$(OPENSBI_SRC_DIR)/lib/utils/psci/Kconfig" +config ENABLE_LOGGING + bool "Enable Logging" + default n + help + Enables or disables logging throughout the system. + Enable this option to allow the system to print log messages. + endmenu diff --git a/lib/utils/arm_scmi/css/common/css_pm.c b/lib/utils/arm_scmi/css/common/css_pm.c index 8d17b6be442f..83908c747d8d 100644 --- a/lib/utils/arm_scmi/css/common/css_pm.c +++ b/lib/utils/arm_scmi/css/common/css_pm.c @@ -114,8 +114,7 @@ static void css_power_down_common(const psci_power_state_t *target_state) static int css_pwr_domain_off_early(const psci_power_state_t *target_state) { /* the ipi's pending is cleared before */ - /* disable the plic irq */ - fdt_plic_context_exit(); + csr_clear(CSR_MIE, MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | MIP_SEIP | MIP_MEIP); /* clear the external irq pending */ csr_clear(CSR_MIP, MIP_MEIP); csr_clear(CSR_MIP, MIP_SEIP); diff --git a/lib/utils/irqchip/fdt_irqchip_plic.c b/lib/utils/irqchip/fdt_irqchip_plic.c index 0a2d61b0beca..829c5ee20341 100644 --- a/lib/utils/irqchip/fdt_irqchip_plic.c +++ b/lib/utils/irqchip/fdt_irqchip_plic.c @@ -85,11 +85,6 @@ static int irqchip_plic_warm_init(void) plic_get_hart_scontext(scratch)); } -void fdt_plic_context_exit(void) -{ - irqchip_plic_warm_init(); -} - static int irqchip_plic_update_hartid_table(void *fdt, int nodeoff, struct plic_data *pd) { diff --git a/lib/utils/psci/psci_common.c b/lib/utils/psci/psci_common.c index f4b4bee03ec4..0a8ebd1319fd 100644 --- a/lib/utils/psci/psci_common.c +++ b/lib/utils/psci/psci_common.c @@ -870,3 +870,55 @@ void riscv_pwr_state_to_psci(unsigned int rstate, unsigned int *pstate) if (rstate & (PSTATE_PWR_LVL_MASK << RSTATE_PWR_LVL_SHIFT)) *pstate |= (rstate & (PSTATE_PWR_LVL_MASK << RSTATE_PWR_LVL_SHIFT)); } + +/******************************************************************************* + * This function verifies that all the other cores in the system have been + * turned OFF and the current CPU is the last running CPU in the system. + * Returns true, if the current CPU is the last ON CPU or false otherwise. + ******************************************************************************/ +bool psci_is_last_on_cpu(void) +{ + unsigned int cpu_idx; + unsigned int hartid = current_hartid(); + int my_idx = plat_core_pos_by_mpidr(hartid); + + for (cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) { + if (cpu_idx == my_idx) { + if (psci_get_aff_info_state() != AFF_STATE_ON) { + sbi_printf("%s:%d\n", __func__, __LINE__); + sbi_hart_hang(); + } + continue; + } + + if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF) { + sbi_printf("core=%u other than current core=%u %s\n", + cpu_idx, my_idx, "running in the system"); + return false; + } + } + + return true; +} + +/****************************************************************************** + * This function retrieves the `psci_power_state_t` for system suspend from + * the platform. + *****************************************************************************/ +void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info) +{ + /* + * Assert that the required pm_ops hook is implemented to ensure that + * the capability detected during psci_setup() is valid. + */ + if (psci_plat_pm_ops->get_sys_suspend_power_state == NULL) { + sbi_printf("%s:%d\n", __func__, __LINE__); + sbi_hart_hang(); + } + + /* + * Query the platform for the power_state required for system suspend + */ + psci_plat_pm_ops->get_sys_suspend_power_state(state_info); +} + diff --git a/lib/utils/psci/psci_main.c b/lib/utils/psci/psci_main.c index f2441f57e16e..a3ce138c00cc 100644 --- a/lib/utils/psci/psci_main.c +++ b/lib/utils/psci/psci_main.c @@ -9,34 +9,32 @@ /******************************************************************************* * PSCI frontend api for servicing SMCs. Described in the PSCI spec. ******************************************************************************/ -int psci_cpu_on(u_register_t target_cpu, - uintptr_t entrypoint) - +int psci_cpu_on(u_register_t target_cpu, uintptr_t entrypoint) { - int rc; + int rc; - /* Determine if the cpu exists of not */ - rc = psci_validate_mpidr(target_cpu); - if (rc != PSCI_E_SUCCESS) - return PSCI_E_INVALID_PARAMS; + /* Determine if the cpu exists of not */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; - /* - * To turn this cpu on, specify which power - * levels need to be turned on - */ - return psci_cpu_on_start(target_cpu, entrypoint); + /* + * To turn this cpu on, specify which power + * levels need to be turned on + */ + return psci_cpu_on_start(target_cpu, entrypoint); } int psci_affinity_info(u_register_t target_affinity, unsigned int lowest_affinity_level) { - int ret; - unsigned int target_idx; + int ret; + unsigned int target_idx; psci_cpu_data_t *svc_cpu_data; struct sbi_scratch *scratch = sbi_hartid_to_scratch(target_affinity); svc_cpu_data = sbi_scratch_offset_ptr(scratch, psci_delta_off); - /* We dont support level higher than PSCI_CPU_PWR_LVL */ + /* We dont support level higher than PSCI_CPU_PWR_LVL */ if (lowest_affinity_level > PSCI_CPU_PWR_LVL) return PSCI_E_INVALID_PARAMS; @@ -186,3 +184,55 @@ int psci_cpu_suspend(unsigned int power_state, return rc; } +int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id) +{ + int rc; + psci_power_state_t state_info; + /* entry_point_info_t ep; */ + + /* Check if the current CPU is the last ON CPU in the system */ + if (!psci_is_last_on_cpu()) + return PSCI_E_DENIED; + + /* Validate the entry point and get the entry_point_info */ +/** + * rc = psci_validate_entry_point(&ep, entrypoint, context_id); + * if (rc != PSCI_E_SUCCESS) + * return rc; + */ + + /* Query the psci_power_state for system suspend */ + psci_query_sys_suspend_pwrstate(&state_info); + + /* + * Check if platform allows suspend to Highest power level + * (System level) + */ + if (psci_find_target_suspend_lvl(&state_info) < PLAT_MAX_PWR_LVL) + return PSCI_E_DENIED; + + /* Ensure that the psci_power_state makes sense */ + if (psci_validate_suspend_req(&state_info, PSTATE_TYPE_POWERDOWN) + != PSCI_E_SUCCESS) { + sbi_printf("%s:%d\n", __func__, __LINE__); + sbi_hart_hang(); + } + + if (is_local_state_off( + state_info.pwr_domain_state[PLAT_MAX_PWR_LVL]) == 0) { + sbi_printf("%s:%d\n", __func__, __LINE__); + sbi_hart_hang(); + } + + /* + * Do what is needed to enter the system suspend state. This function + * might return if the power down was abandoned for any reason, e.g. + * arrival of an interrupt + */ + rc = psci_cpu_suspend_start(/* &ep */entrypoint, + PLAT_MAX_PWR_LVL, + &state_info, + PSTATE_TYPE_POWERDOWN); + + return rc; +} diff --git a/lib/utils/psci/psci_private.h b/lib/utils/psci/psci_private.h index d1cd2ba84742..c768d3f379ab 100644 --- a/lib/utils/psci/psci_private.h +++ b/lib/utils/psci/psci_private.h @@ -142,6 +142,10 @@ int psci_cpu_suspend_start(/* const entry_point_info_t *ep */ uintptr_t entrypoi void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info); void riscv_pwr_state_to_psci(unsigned int rstate, unsigned int *pstate); +bool psci_is_last_on_cpu(void); +void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info); +int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id); + /* Helper function to identify a CPU standby request in PSCI Suspend call */ static inline bool is_cpu_standby_req(unsigned int is_power_down_state, unsigned int retn_lvl) diff --git a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c index 9976b5774039..279e6d5dc741 100644 --- a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c +++ b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c @@ -27,10 +27,20 @@ #define PMU_ACPR_CLUSTER0_REG (0xd4051090) #define PMU_ACPR_CLUSTER1_REG (0xd4051094) +#define PMU_ACPR_UNKONW_REG (0xd4050038) + #define CPU_PWR_DOWN_VALUE (0x3) #define CLUSTER_PWR_DOWN_VALUE (0x3) #define CLUSTER_AXISDO_OFFSET (31) +#define CLUSTER_DDRSD_OFFSET (27) +#define CLUSTER_APBSD_OFFSET (26) +#define CLUSTER_VCXOSD_OFFSET (19) +#define CLUSTER_BIT29_OFFSET (29) +#define CLUSTER_BIT14_OFFSET (14) +#define CLUSTER_BIT30_OFFSET (30) +#define CLUSTER_BIT25_OFFSET (25) +#define CLUSTER_BIT13_OFFSET (13) struct pmu_cap_wakeup { unsigned int pmu_cap_core0_wakeup; @@ -39,7 +49,7 @@ struct pmu_cap_wakeup { unsigned int pmu_cap_core3_wakeup; }; -/* D1P */ +/* D1P & D2 ? */ void spacemit_top_on(u_register_t mpidr) { unsigned int *cluster0_acpr = NULL; @@ -49,15 +59,31 @@ void spacemit_top_on(u_register_t mpidr) cluster1_acpr = (unsigned int *)PMU_ACPR_CLUSTER1_REG; unsigned int value = readl(cluster0_acpr); - value &= ~(1 << CLUSTER_AXISDO_OFFSET); + value &= ~((1 << CLUSTER_AXISDO_OFFSET) | + (1 << CLUSTER_DDRSD_OFFSET) | + (1 << CLUSTER_APBSD_OFFSET) | + (1 << CLUSTER_VCXOSD_OFFSET) | + (1 << CLUSTER_BIT29_OFFSET) | + (1 << CLUSTER_BIT14_OFFSET) | + (1 << CLUSTER_BIT30_OFFSET) | + (1 << CLUSTER_BIT25_OFFSET) | + (1 << CLUSTER_BIT13_OFFSET)); writel(value, cluster0_acpr); value = readl(cluster1_acpr); - value &= ~(1 << CLUSTER_AXISDO_OFFSET); + value &= ~((1 << CLUSTER_AXISDO_OFFSET) | + (1 << CLUSTER_DDRSD_OFFSET) | + (1 << CLUSTER_APBSD_OFFSET) | + (1 << CLUSTER_VCXOSD_OFFSET) | + (1 << CLUSTER_BIT29_OFFSET) | + (1 << CLUSTER_BIT14_OFFSET) | + (1 << CLUSTER_BIT30_OFFSET) | + (1 << CLUSTER_BIT25_OFFSET) | + (1 << CLUSTER_BIT13_OFFSET)); writel(value, cluster1_acpr); } -/* D1P */ +/* D1P & D2 ? */ void spacemit_top_off(u_register_t mpidr) { unsigned int *cluster0_acpr = NULL; @@ -67,12 +93,35 @@ void spacemit_top_off(u_register_t mpidr) cluster1_acpr = (unsigned int *)PMU_ACPR_CLUSTER1_REG; unsigned int value = readl(cluster0_acpr); - value |= (1 << CLUSTER_AXISDO_OFFSET); + value |= (1 << CLUSTER_AXISDO_OFFSET) | + (1 << CLUSTER_DDRSD_OFFSET) | + (1 << CLUSTER_APBSD_OFFSET) | + (1 << CLUSTER_VCXOSD_OFFSET) | + (1 << CLUSTER_BIT29_OFFSET) | + (1 << CLUSTER_BIT14_OFFSET) | + (1 << CLUSTER_BIT30_OFFSET) | + (1 << CLUSTER_BIT25_OFFSET) | + (1 << CLUSTER_BIT13_OFFSET); writel(value, cluster0_acpr); value = readl(cluster1_acpr); - value |= (1 << CLUSTER_AXISDO_OFFSET); + value |= (1 << CLUSTER_AXISDO_OFFSET) | + (1 << CLUSTER_DDRSD_OFFSET) | + (1 << CLUSTER_APBSD_OFFSET) | + (1 << CLUSTER_VCXOSD_OFFSET) | + (1 << CLUSTER_BIT29_OFFSET) | + (1 << CLUSTER_BIT14_OFFSET) | + (1 << CLUSTER_BIT30_OFFSET) | + (1 << CLUSTER_BIT25_OFFSET) | + (1 << CLUSTER_BIT13_OFFSET); writel(value, cluster1_acpr); + + value = readl((unsigned int *)PMU_ACPR_UNKONW_REG); + value |= (1 << 2); + writel(value, (unsigned int *)PMU_ACPR_UNKONW_REG); + + /* for wakeup debug */ + writel(0xffff, (unsigned int *)0xd4051030); } /* M2 */ diff --git a/lib/utils/psci/spacemit/plat/plat_pm.c b/lib/utils/psci/spacemit/plat/plat_pm.c index 464a56a277ef..da6f958157fa 100644 --- a/lib/utils/psci/spacemit/plat/plat_pm.c +++ b/lib/utils/psci/spacemit/plat/plat_pm.c @@ -16,6 +16,9 @@ #define SYSTEM_PWR_STATE(state) \ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) +/* reserved for future used */ +/* unsigned long __plic_regsave_offset_ptr; */ + static int spacemit_pwr_domain_on(u_register_t mpidr) { /* wakeup the cpu */ @@ -54,8 +57,7 @@ static void spacemit_pwr_domain_on_finish(const psci_power_state_t *target_state static int spacemit_pwr_domain_off_early(const psci_power_state_t *target_state) { /* the ipi's pending is cleared before */ - /* disable the plic irq */ - fdt_plic_context_exit(); + csr_clear(CSR_MIE, MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | MIP_SEIP | MIP_MEIP); /* clear the external irq pending */ csr_clear(CSR_MIP, MIP_MEIP); csr_clear(CSR_MIP, MIP_SEIP); @@ -70,9 +72,9 @@ static int spacemit_pwr_domain_off_early(const psci_power_state_t *target_state) static void spacemit_pwr_domain_off(const psci_power_state_t *target_state) { - unsigned int hartid = current_hartid(); + unsigned int hartid = current_hartid(); - if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { #if defined(CONFIG_PLATFORM_SPACEMIT_K1X) /* disable the tcm */ csr_write(CSR_TCMCFG, 0); @@ -82,11 +84,11 @@ static void spacemit_pwr_domain_off(const psci_power_state_t *target_state) } if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { + /* D1P */ spacemit_top_off(hartid); } spacemit_assert_cpu(hartid); - } static void spacemit_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) @@ -183,7 +185,7 @@ static void spacemit_pwr_domain_suspend(const psci_power_state_t *target_state) } if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { - /* D1P */ + /* D1P & D2 */ spacemit_top_off(hartid); } @@ -223,7 +225,7 @@ static void spacemit_pwr_domain_suspend_finish(const psci_power_state_t *target_ } if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) { - /* D1P */ + /* D1P & D2 */ spacemit_top_on(hartid); } @@ -236,6 +238,14 @@ static void spacemit_pwr_domain_suspend_pwrdown_early(const psci_power_state_t * csr_clear(CSR_MIE, MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | MIP_SEIP | MIP_MEIP); } +static void spacemit_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + static const plat_psci_ops_t spacemit_psci_ops = { .cpu_standby = NULL, .pwr_domain_on = spacemit_pwr_domain_on, @@ -248,6 +258,7 @@ static const plat_psci_ops_t spacemit_psci_ops = { .pwr_domain_suspend = spacemit_pwr_domain_suspend, .pwr_domain_suspend_pwrdown_early = spacemit_pwr_domain_suspend_pwrdown_early, .pwr_domain_suspend_finish = spacemit_pwr_domain_suspend_finish, + .get_sys_suspend_power_state = spacemit_get_sys_suspend_power_state, }; int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops) diff --git a/platform/generic/spacemit/spacemit_k1.c b/platform/generic/spacemit/spacemit_k1.c index 8664e05e7910..38794c2dfbb5 100644 --- a/platform/generic/spacemit/spacemit_k1.c +++ b/platform/generic/spacemit/spacemit_k1.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include <../../../lib/utils/psci/psci_private.h> #include @@ -29,63 +30,110 @@ extern struct sbi_platform platform; +/* reserved for future use */ +/* extern unsigned long __plic_regsave_offset_ptr; */ + PLAT_CCI_MAP static void wakeup_other_core(void) { - int i; - u32 hartid, clusterid, cluster_enabled = 0; - unsigned int cur_hartid = current_hartid(); - struct sbi_scratch *scratch = sbi_hartid_to_scratch(cur_hartid); + int i; + u32 hartid, clusterid, cluster_enabled = 0; + unsigned int cur_hartid = current_hartid(); + struct sbi_scratch *scratch = sbi_hartid_to_scratch(cur_hartid); #if defined(CONFIG_PLATFORM_SPACEMIT_K1X) - /* set other cpu's boot-entry */ - writel(scratch->warmboot_addr & 0xffffffff, (u32 *)C0_RVBADDR_LO_ADDR); - writel((scratch->warmboot_addr >> 32) & 0xffffffff, (u32 *)C0_RVBADDR_HI_ADDR); + /* set other cpu's boot-entry */ + writel(scratch->warmboot_addr & 0xffffffff, (u32 *)C0_RVBADDR_LO_ADDR); + writel((scratch->warmboot_addr >> 32) & 0xffffffff, (u32 *)C0_RVBADDR_HI_ADDR); - writel(scratch->warmboot_addr & 0xffffffff, (u32 *)C1_RVBADDR_LO_ADDR); - writel((scratch->warmboot_addr >> 32) & 0xffffffff, (u32 *)C1_RVBADDR_HI_ADDR); + writel(scratch->warmboot_addr & 0xffffffff, (u32 *)C1_RVBADDR_LO_ADDR); + writel((scratch->warmboot_addr >> 32) & 0xffffffff, (u32 *)C1_RVBADDR_HI_ADDR); #elif defined(CONFIG_PLATFORM_SPACEMIT_K1PRO) - for (i = 0; i < platform.hart_count; i++) { - hartid = platform.hart_index2id[i]; + for (i = 0; i < platform.hart_count; i++) { + hartid = platform.hart_index2id[i]; unsigned long core_index = MPIDR_AFFLVL1_VAL(hartid) * PLATFORM_MAX_CPUS_PER_CLUSTER - + MPIDR_AFFLVL0_VAL(hartid); + + MPIDR_AFFLVL0_VAL(hartid); writel(scratch->warmboot_addr & 0xffffffff, (u32 *)(CORE0_RVBADDR_LO_ADDR + core_index * CORE_RVBADDR_STEP)); writel((scratch->warmboot_addr >> 32) & 0xffffffff, (u32 *)(CORE0_RVBADDR_HI_ADDR + core_index * CORE_RVBADDR_STEP)); - } + } #endif #ifdef CONFIG_ARM_PSCI_SUPPORT - unsigned char *cpu_topology = plat_get_power_domain_tree_desc(); + unsigned char *cpu_topology = plat_get_power_domain_tree_desc(); #endif - // hart0 is already boot up - for (i = 0; i < platform.hart_count; i++) { - hartid = platform.hart_index2id[i]; + // hart0 is already boot up + for (i = 0; i < platform.hart_count; i++) { + hartid = platform.hart_index2id[i]; - clusterid = MPIDR_AFFLVL1_VAL(hartid); + clusterid = MPIDR_AFFLVL1_VAL(hartid); - /* we only enable snoop of cluster0 */ - if (0 == (cluster_enabled & (1 << clusterid))) { - cluster_enabled |= 1 << clusterid; - if (0 == clusterid) { - cci_enable_snoop_dvm_reqs(clusterid); - } + /* we only enable snoop of cluster0 */ + if (0 == (cluster_enabled & (1 << clusterid))) { + cluster_enabled |= 1 << clusterid; + if (0 == clusterid) { + cci_enable_snoop_dvm_reqs(clusterid); + } #ifdef CONFIG_ARM_PSCI_SUPPORT - cpu_topology[CLUSTER_INDEX_IN_CPU_TOPOLOGY]++; + cpu_topology[CLUSTER_INDEX_IN_CPU_TOPOLOGY]++; #endif - } + } #ifdef CONFIG_ARM_PSCI_SUPPORT - /* we only support 2 cluster by now */ - if (clusterid == PLATFORM_CLUSTER_COUNT - 1) - cpu_topology[CLUSTER1_INDEX_IN_CPU_TOPOLOGY]++; - else - cpu_topology[CLUSTER0_INDEX_IN_CPU_TOPOLOGY]++; + /* we only support 2 cluster by now */ + if (clusterid == PLATFORM_CLUSTER_COUNT - 1) + cpu_topology[CLUSTER1_INDEX_IN_CPU_TOPOLOGY]++; + else + cpu_topology[CLUSTER0_INDEX_IN_CPU_TOPOLOGY]++; #endif - } + } + +/** + * // reserved for future used + * // get the number of plic registers + * u32 *regnum_pos; + * int noff = -1, fdtlen, regnum, regsize; + * const fdt32_t *fdtval; + * void *fdt = fdt_get_address(); + * const struct fdt_match match_table = { .compatible = "riscv,plic0", }; + * + * noff = fdt_find_match(fdt, noff, &match_table, NULL); + * if (noff >= 0) { + * fdtval = fdt_getprop(fdt, noff, "riscv,ndev", &fdtlen); + * if (fdtlen > 0) { + * regnum = fdt32_to_cpu(*fdtval); + * regsize = + * // regnum + regsize + * sizeof(u32) + sizeof(u32) + + * // plic priority regisrer + * sizeof(u8) * regnum + + * // plic enable register + * (sizeof(u32) * (regnum / 32 + 1) + + * // plic threshold regisrer + * sizeof (u32) * 1) * 2; // smode and machine mode + * + * __plic_regsave_offset_ptr = sbi_scratch_alloc_offset(regsize); + * if (__plic_regsave_offset_ptr == 0) { + * sbi_hart_hang(); + * } + * } + * } + * + * if (__plic_regsave_offset_ptr) { + * for (i = 0; i < platform.hart_count; i++) { + * hartid = platform.hart_index2id[i]; + * scratch = sbi_hartid_to_scratch(hartid); + * u32 *regnum_pos = sbi_scratch_offset_ptr(scratch, __plic_regsave_offset_ptr); + * + * regnum_pos[0] = regnum; + * regnum_pos[1] = regsize; + * csi_dcache_clean_invalid_range((uintptr_t)regnum_pos, regsize); + * } + * } + */ } /* @@ -93,24 +141,24 @@ static void wakeup_other_core(void) */ static int spacemit_k1_early_init(bool cold_boot, const struct fdt_match *match) { - if (cold_boot) { - /* initiate cci */ - cci_init(PLATFORM_CCI_ADDR, cci_map, array_size(cci_map)); - /* enable dcache */ - csi_enable_dcache(); - /* wakeup other core ? */ - wakeup_other_core(); - /* initialize */ + if (cold_boot) { + /* initiate cci */ + cci_init(PLATFORM_CCI_ADDR, cci_map, array_size(cci_map)); + /* enable dcache */ + csi_enable_dcache(); + /* wakeup other core ? */ + wakeup_other_core(); + /* initialize */ #ifdef CONFIG_ARM_SCMI_PROTOCOL_SUPPORT - plat_arm_pwrc_setup(); + plat_arm_pwrc_setup(); #endif - } else { + } else { #ifdef CONFIG_ARM_PSCI_SUPPORT - psci_warmboot_entrypoint(); + psci_warmboot_entrypoint(); #endif - } + } - return 0; + return 0; } #ifdef CONFIG_ARM_PSCI_SUPPORT @@ -127,14 +175,12 @@ static int spacemit_hart_start(unsigned int hartid, unsigned long saddr) static int spacemit_hart_stop(void) { psci_cpu_off(); - return 0; } static int spacemit_hart_suspend(unsigned int suspend_type) { psci_cpu_suspend(suspend_type, 0, 0); - return 0; } @@ -150,6 +196,27 @@ static const struct sbi_hsm_device spacemit_hsm_ops = { .hart_suspend = spacemit_hart_suspend, .hart_resume = spacemit_hart_resume, }; + +static int spacemit_system_suspend_check(u32 sleep_type) +{ + return sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND ? 0 : SBI_EINVAL; +} + +static int spacemit_system_suspend(u32 sleep_type, unsigned long mmode_resume_addr) +{ + if (sleep_type != SBI_SUSP_SLEEP_TYPE_SUSPEND) + return SBI_EINVAL; + + psci_system_suspend(mmode_resume_addr, 0); + + return SBI_OK; +} + +static struct sbi_system_suspend_device spacemit_system_suspend_ops = { + .name = "spacemit-system-suspend", + .system_suspend_check = spacemit_system_suspend_check, + .system_suspend = spacemit_system_suspend, +}; #endif /* @@ -158,14 +225,16 @@ static const struct sbi_hsm_device spacemit_hsm_ops = { static int spacemit_k1_final_init(bool cold_boot, const struct fdt_match *match) { #ifdef CONFIG_ARM_PSCI_SUPPORT - /* for clod boot, we build the cpu topology structure */ - if (cold_boot) { - sbi_hsm_set_device(&spacemit_hsm_ops); - return psci_setup(); - } + /* for clod boot, we build the cpu topology structure */ + if (cold_boot) { + sbi_hsm_set_device(&spacemit_hsm_ops); + /* register system-suspend ops */ + sbi_system_suspend_set_device(&spacemit_system_suspend_ops); + return psci_setup(); + } #endif - return 0; + return 0; } static bool spacemit_cold_boot_allowed(u32 hartid, const struct fdt_match *match) -- 2.35.3