123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- /*
- * Copyright : (C) 2023 Phytium Information Technology, Inc.
- * All Rights Reserved.
- *
- * This program is OPEN SOURCE software: you can redistribute it and/or modify it
- * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
- * either version 1.0 of the License, or (at your option) any later version.
- *
- * This program 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 Phytium Public License for more details.
- *
- *
- * FilePath: fpsci.c
- * Created Date: 2023-06-21 10:36:53
- * Last Modified: 2023-06-30 13:32:06
- * Description: This file is for
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ---------- -------- ---------------------------------
- * 1.0 huanghe 2023-06-21 first release
- */
- #include <stdio.h>
- #include "fsmcc.h" /* 根据你的平台和编译环境来确定这个路径 */
- #include "fpsci.h"
- #include "fassert.h"
- #include "fcompiler.h"
- #include "fcpu_info.h"
- #include "rtdbg.h"
- /* 定义PSCI 函数值 */
- #define FPSCI_0_2_FN32_BASE 0x84000000
- #define FPSCI_0_2_FN64_BASE 0xC4000000
- #define FPSCI_VERSION (FPSCI_0_2_FN32_BASE + 0x000)
- #define FPSCI_FEATURES (FPSCI_0_2_FN32_BASE + 0x00a)
- #define FPSCI_CPU_SUSPEND_AARCH32 (FPSCI_0_2_FN32_BASE + 0x001)
- #define FPSCI_CPU_SUSPEND_AARCH64 (FPSCI_0_2_FN64_BASE + 0x001)
- #define FPSCI_CPU_OFF (FPSCI_0_2_FN32_BASE + 0x002)
- #define FPSCI_CPU_ON_AARCH32 (FPSCI_0_2_FN32_BASE + 0x003)
- #define FPSCI_CPU_ON_AARCH64 (FPSCI_0_2_FN64_BASE + 0x003)
- #define FPSCI_FAFFINITY_INFO_AARCH32 (FPSCI_0_2_FN32_BASE + 0x004)
- #define FPSCI_FAFFINITY_INFO_AARCH64 (FPSCI_0_2_FN64_BASE + 0x004)
- #define FPSCI_SYSTEM_OFF (FPSCI_0_2_FN32_BASE + 0x008)
- #define FPSCI_SYSTEM_RESET (FPSCI_0_2_FN32_BASE + 0x009)
- #define FPSCI_SYSTEM_SUSPEND (FPSCI_0_2_FN32_BASE + 0x00E)
- /* 定义每个PSCI函数ID的位标记 */
- #define FPSCI_PSCI_VERSION_BIT (1 << 0)
- #define FPSCI_PSCI_FEATURES_BIT (1 << 1)
- #define FPSCI_CPU_SUSPEND_AARCH32_BIT (1 << 2)
- #define FPSCI_CPU_SUSPEND_AARCH64_BIT (1 << 3)
- #define FPSCI_CPU_OFF_BIT (1 << 4)
- #define FPSCI_CPU_ON_AARCH32_BIT (1 << 5)
- #define FPSCI_CPU_ON_AARCH64_BIT (1 << 6)
- #define FPSCI_AFFINITY_INFO_AARCH32_BIT (1 << 7)
- #define FPSCI_AFFINITY_INFO_AARCH64_BIT (1 << 8)
- #define FPSCI_SYSTEM_OFF_BIT (1 << 9)
- #define FPSCI_SYSTEM_RESET_BIT (1 << 10)
- static int fpsci_ringt_bit_flg = 0;
- /* 定义函数指针 */
- typedef void (*FPsciInvokeFun)(unsigned long arg0, unsigned long arg1,
- unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5,
- unsigned long arg6, unsigned long arg7,
- struct FSmcccRes *res);
- /* 为函数指针初始化为默认的函数 */
- FPsciInvokeFun f_psci_invoke = FSmcccSmcCall;
- /**
- * @name: FPsciVersion
- * @msg: Get the version of the PSCI implementation.
- * @return {int}: The version information of the PSCI implementation.
- * @note: This function returns the version information obtained from the PSCI VERSION function.
- */
- int FPsciVersion(void)
- {
- struct FSmcccRes res;
- FASSERT((*f_psci_invoke));
- (*f_psci_invoke)(FPSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
- return res.a0;
- }
- /**
- * @name: FPsciFeatures
- * @msg: Check whether a PSCI function is supported.
- * @param {u32} psci_fid: The function ID of the PSCI function to be checked.
- * @return {int}: 1 if the function is supported; 0 otherwise.
- * @note: This function returns whether the PSCI function represented by psci_fid is supported or not.
- */
- int FPsciFeatures(u32 psci_fid)
- {
- struct FSmcccRes res;
- FASSERT((*f_psci_invoke));
- (*f_psci_invoke)(FPSCI_FEATURES, psci_fid, 0, 0, 0, 0, 0, 0, &res);
- return res.a0 == FPSCI_SUCCESS ? 1 : 0;
- }
- /**
- * @name: FPsciCpuSuspend
- * @msg: Suspend execution on a particular CPU.
- * @param {u32} power_state: The power state to be entered.
- * @param {unsigned long} entry_point_address: The address to be executed upon waking up.
- * @param {unsigned long} context_id: The context-specific identifier.
- * @return {int}: The status code of the operation, as defined by the PSCI specification.
- * @note: This function suspends the execution on a particular CPU and returns a status code indicating whether the operation was successful or not.
- */
- int FPsciCpuSuspend(u32 power_state, unsigned long entry_point_address, unsigned long context_id)
- {
- struct FSmcccRes res;
- FASSERT((fpsci_ringt_bit_flg & FPSCI_CPU_SUSPEND_AARCH32_BIT) != 0);
- FASSERT((*f_psci_invoke));
- (*f_psci_invoke)(FPSCI_CPU_SUSPEND_AARCH32, power_state, entry_point_address, context_id, 0, 0, 0, 0, &res);
- return res.a0;
- }
- /**
- * @name: FPsciCpuOn
- * @msg: Power on a particular CPU.
- * @param {unsigned long} target_cpu: The target CPU to be powered on.
- * @param {unsigned long} entry_point_address: The address to be executed upon waking up.
- * @param {unsigned long} context_id: The context-specific identifier.
- * @return {int}: The status code of the operation, as defined by the PSCI specification.
- * @note: This function powers on a particular CPU and returns a status code indicating whether the operation was successful or not.
- */
- int FPsciCpuOn(unsigned long target_cpu, unsigned long entry_point_address, unsigned long context_id)
- {
- struct FSmcccRes res;
- unsigned long cpu_on_id ;
- #if defined(FAARCH64_USE)
- cpu_on_id = FPSCI_CPU_ON_AARCH64 ;
- #else
- cpu_on_id = FPSCI_CPU_ON_AARCH32;
- #endif
- FASSERT((fpsci_ringt_bit_flg & (FPSCI_CPU_ON_AARCH32_BIT | FPSCI_CPU_ON_AARCH64_BIT)) != 0);
- FASSERT((*f_psci_invoke));
- (*f_psci_invoke)(cpu_on_id, target_cpu, entry_point_address, context_id, 0, 0, 0, 0, &res);
- return res.a0;
- }
- /**
- * @name: FPsciCpuOff
- * @msg: This is a wrapper for the PSCI CPU Off interface, intended to turn off the current CPU.
- * @return: Returns the 'a0' field of the 'FSmcccRes' structure, indicating the result of the call. A return value of 0 (PSCI_SUCCESS) indicates success, any other value indicates an error occurred.
- * @note: A core that is powered down by CPU_OFF can only be powered up again in response to a CPU_ON.
- */
- int FPsciCpuOff(void)
- {
- struct FSmcccRes res;
- FASSERT((fpsci_ringt_bit_flg & FPSCI_CPU_OFF_BIT) != 0);
- FASSERT((*f_psci_invoke));
- (*f_psci_invoke)(FPSCI_CPU_OFF, 0, 0, 0, 0, 0, 0, 0, &res);
- return res.a0;
- }
- /**
- * @name: FPsciAffinityInfo
- * @msg: Get the power state of a particular affinity level.
- * @param {unsigned long} target_affinity: The target affinity level.
- * @param {u32} lowest_affinity_level: The lowest affinity level.
- * @return {int}: The power state of the specified affinity level, as defined by the PSCI specification.
- * @note: This function returns the power state of a particular affinity level.
- */
- int FPsciAffinityInfo(unsigned long target_affinity, u32 lowest_affinity_level)
- {
- struct FSmcccRes res;
- FASSERT((fpsci_ringt_bit_flg & (FPSCI_AFFINITY_INFO_AARCH32_BIT | FPSCI_AFFINITY_INFO_AARCH64_BIT)) != 0);
- FASSERT((*f_psci_invoke));
- unsigned long cpu_on_id ;
- #if defined(FAARCH64_USE)
- cpu_on_id = FPSCI_CPU_ON_AARCH64 ;
- #else
- cpu_on_id = FPSCI_CPU_ON_AARCH32;
- #endif
- (*f_psci_invoke)(FPSCI_FAFFINITY_INFO_AARCH32, target_affinity, lowest_affinity_level, 0, 0, 0, 0, 0, &res);
- return res.a0;
- }
- /**
- * @name: FPsciSystemReset
- * @msg: Reset the system.
- * @param {u32} reset_type: The type of the system reset (cold/warm).
- * @note: This function resets the system. The reset type is specified by the parameter reset_type.
- */
- void FPsciSystemReset(u32 reset_type)
- {
- struct FSmcccRes res;
- FASSERT((fpsci_ringt_bit_flg & FPSCI_SYSTEM_RESET_BIT) != 0);
- FASSERT((*f_psci_invoke));
- (*f_psci_invoke)(FPSCI_SYSTEM_RESET, reset_type, 0, 0, 0, 0, 0, 0, &res);
- }
- /**
- * @name: FPsciCheckFeatures
- * @msg: This function checks for the availability of various PSCI features and sets the corresponding bits in the 'fpsci_ringt_bit_flg' global flag accordingly.
- * @return: This function does not return a value.
- */
- static void FPsciCheckFeatures(void)
- {
- LOG_I("Checking PSCI features...\r\n");
- fpsci_ringt_bit_flg = 0 ;
- if (FPsciFeatures(FPSCI_CPU_SUSPEND_AARCH32))
- {
- fpsci_ringt_bit_flg |= FPSCI_CPU_SUSPEND_AARCH32_BIT;
- LOG_I("CPU_SUSPEND_AARCH32 supported.\r\n");
- }
- else
- {
- LOG_E("CPU_SUSPEND_AARCH32 not supported.\r\n");
- }
- if (FPsciFeatures(FPSCI_CPU_OFF))
- {
- fpsci_ringt_bit_flg |= FPSCI_CPU_OFF_BIT;
- LOG_I("CPU_OFF supported.\r\n");
- }
- else
- {
- LOG_E("CPU_OFF not supported.\r\n");
- }
- #if defined(FAARCH64_USE)
- if (FPsciFeatures(FPSCI_CPU_ON_AARCH64))
- {
- fpsci_ringt_bit_flg |= FPSCI_CPU_ON_AARCH64_BIT;
- LOG_I("CPU_ON_AARCH64 supported.\r\n");
- }
- else
- {
- LOG_E("CPU_ON_AARCH64 not supported.\r\n");
- }
- #else
- if (FPsciFeatures(FPSCI_CPU_ON_AARCH32))
- {
- fpsci_ringt_bit_flg |= FPSCI_CPU_ON_AARCH32_BIT;
- LOG_I("CPU_ON_AARCH32 supported.\r\n");
- }
- else
- {
- LOG_E("CPU_ON_AARCH32 not supported.\r\n");
- }
- #endif
- #if defined(FAARCH64_USE)
- if (FPsciFeatures(FPSCI_FAFFINITY_INFO_AARCH64))
- {
- fpsci_ringt_bit_flg |= FPSCI_AFFINITY_INFO_AARCH64_BIT;
- LOG_I("AFFINITY_INFO_AARCH64 supported.\r\n");
- }
- else
- {
- LOG_E("AFFINITY_INFO_AARCH64 not supported.\r\n");
- }
- #else
- if (FPsciFeatures(FPSCI_FAFFINITY_INFO_AARCH32))
- {
- fpsci_ringt_bit_flg |= FPSCI_AFFINITY_INFO_AARCH32_BIT;
- LOG_I("FPSCI_AFFINITY_INFO_AARCH32 supported.\r\n");
- }
- else
- {
- LOG_E("AFFINITY_INFO_AARCH32 not supported.\r\n");
- }
- #endif
- if (FPsciFeatures(FPSCI_SYSTEM_OFF))
- {
- fpsci_ringt_bit_flg |= FPSCI_SYSTEM_OFF_BIT;
- LOG_I("SYSTEM_OFF supported.\r\n");
- }
- else
- {
- LOG_E("SYSTEM_OFF not supported.\r\n");
- }
- if (FPsciFeatures(FPSCI_SYSTEM_RESET))
- {
- fpsci_ringt_bit_flg |= FPSCI_SYSTEM_RESET_BIT;
- LOG_I("SYSTEM_RESET supported.\r\n");
- }
- else
- {
- LOG_E("SYSTEM_RESET not supported.\r\n");
- }
- }
- /**
- * @name: FPsci_CpuOn
- * @msg: Power up a core
- * @in param cpu_id_mask: cpu id mask
- * @in param bootaddr: a 32-bit entry point physical address (or IPA).
- * @return int
- */
- int FPsciCpuMaskOn(s32 cpu_id_mask, uintptr bootaddr)
- {
- FError ret ;
- u64 cluster = 0;
- ret = GetCpuAffinityByMask(cpu_id_mask, &cluster);
- if (ret != ERR_SUCCESS)
- {
- return FPSCI_INVALID_PARAMS;
- }
- return FPsciCpuOn(cluster, (unsigned long)bootaddr, 0) ;
- }
- static void FSmccInit(int method)
- {
- if (method == 1)
- {
- f_psci_invoke = FSmcccHvcCall;
- }
- else
- {
- f_psci_invoke = FSmcccSmcCall;
- }
- }
- int FPsciInit(void)
- {
- int psci_version = 0;
- FSmccInit(0);
- psci_version = FPsciVersion() ;
- LOG_I("major is 0x%x,minor is 0x%x \r\n", FPSCI_MAJOR_VERSION(psci_version), FPSCI_MINOR_VERSION(psci_version)) ;
- FPsciCheckFeatures();
- return 0;
- }
|