From 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:13:47 +0200 Subject: Adding upstream version 2.8.0+dfsg. Signed-off-by: Daniel Baumann --- .../drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c | 253 +++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c (limited to 'plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c') diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..4cc2203 --- /dev/null +++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "mt_cpu_pm.h" +#include "mt_cpu_pm_cpc.h" +#include "mt_smp.h" +#include + +struct mtk_cpc_dev { + int auto_off; + unsigned int auto_thres_tick; +}; + +static struct mtk_cpc_dev cpc; + +static int mtk_cpc_last_core_prot(int prot_req, int resp_reg, int resp_ofs) +{ + unsigned int staus; + unsigned int retry = 0; + + while (retry < RETRY_CNT_MAX) { + retry++; + + mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req); + + udelay(1); + + staus = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK; + + if (staus == PROT_SUCCESS) { + return CPC_SUCCESS; + } else if (staus == PROT_GIVEUP) { + return CPC_ERR_FAIL; + } + } + + return CPC_ERR_TIMEOUT; +} + +static int mtk_cpu_pm_mcusys_prot_aquire(void) +{ + return mtk_cpc_last_core_prot(MCUSYS_PROT_SET, CPC_MCUSYS_LAST_CORE_RESP, MCUSYS_RESP_OFS); +} + +static void mtk_cpu_pm_mcusys_prot_release(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR); +} + +int mtk_cpu_pm_cluster_prot_aquire(void) +{ + return mtk_cpc_last_core_prot(CPUSYS_PROT_SET, CPC_MCUSYS_MP_LAST_CORE_RESP, + CPUSYS_RESP_OFS); +} + +void mtk_cpu_pm_cluster_prot_release(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR); +} + +static void mtk_cpc_cluster_cnt_backup(void) +{ + /* single cluster */ + uint32_t backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP); + uint32_t curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER); + + if ((curr_cnt & 0x7fff) == 0) { + curr_cnt = (curr_cnt >> 16) & 0x7fff; + } else { + curr_cnt = curr_cnt & 0x7fff; + } + + mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt); + mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, 0x3); +} + +static inline void mtk_cpc_mcusys_off_enable(bool enable) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, enable ? 1 : 0); +} + +void mtk_cpc_mcusys_off_reflect(void) +{ + mtk_cpc_mcusys_off_enable(false); + mtk_cpu_pm_mcusys_prot_release(); +} + +int mtk_cpc_mcusys_off_prepare(void) +{ + if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) { + return CPC_ERR_FAIL; + } + + mtk_cpc_cluster_cnt_backup(); + mtk_cpc_mcusys_off_enable(true); + + return CPC_SUCCESS; +} + +void mtk_cpc_core_on_hint_set(int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu)); +} + +void mtk_cpc_core_on_hint_clr(int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); +} + +static void mtk_cpc_dump_timestamp(void) +{ + unsigned int id; + + for (id = 0; id < CPC_TRACE_ID_NUM; id++) { + mmio_write_32(CPC_MCUSYS_TRACE_SEL, id); + + memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id), + (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA, + CPC_TRACE_SIZE); + } +} + +void mtk_cpc_time_sync(void) +{ + uint64_t kt; + uint32_t systime_l, systime_h; + + kt = sched_clock(); + systime_l = mmio_read_32(CNTSYS_L_REG); + systime_h = mmio_read_32(CNTSYS_H_REG); + + /* sync kernel timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt); + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32)); + + /* sync system timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l); + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h); +} + +static void mtk_cpc_config(unsigned int cfg, unsigned int data) +{ + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + if (data) { + mmio_setbits_32(CPC_MCUSYS_CPC_DBG_SETTING, CPC_PROF_EN); + } else { + mmio_clrbits_32(CPC_MCUSYS_CPC_DBG_SETTING, CPC_PROF_EN); + } + break; + case CPC_SMC_CONFIG_AUTO_OFF: + if (data) { + mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_AUTO_OFF_EN); + cpc.auto_off = 1; + } else { + mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_AUTO_OFF_EN); + cpc.auto_off = 0; + } + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + cpc.auto_thres_tick = US_TO_TICKS(data); + mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick); + break; + case CPC_SMC_CONFIG_CNT_CLR: + mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, 0x3); + break; + case CPC_SMC_CONFIG_TIME_SYNC: + mtk_cpc_time_sync(); + break; + default: + break; + } +} + +static unsigned int mtk_cpc_read_config(unsigned int cfg) +{ + unsigned int res = 0; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? 1 : 0; + break; + case CPC_SMC_CONFIG_AUTO_OFF: + res = cpc.auto_off; + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + res = TICKS_TO_US(cpc.auto_thres_tick); + break; + case CPC_SMC_CONFIG_CNT_CLR: + default: + break; + } + + return res; +} + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2) +{ + uint64_t res = 0; + + switch (act) { + case CPC_SMC_EVENT_CPC_CONFIG: + mtk_cpc_config((unsigned int)arg1, (unsigned int)arg2); + break; + case CPC_SMC_EVENT_READ_CONFIG: + res = mtk_cpc_read_config((unsigned int)arg1); + break; + case CPC_SMC_EVENT_GIC_DPG_SET: + /* isolated_status = x2; */ + default: + break; + } + + return res; +} + +uint64_t mtk_cpc_trace_dump(uint64_t act, uint64_t arg1, uint64_t arg2) +{ + switch (act) { + case CPC_SMC_EVENT_DUMP_TRACE_DATA: + mtk_cpc_dump_timestamp(); + break; + default: + break; + } + + return 0; +} + +void mtk_cpc_init(void) +{ +#if CONFIG_MTK_SMP_EN + mt_smp_init(); +#endif + mmio_setbits_32(CPC_MCUSYS_CPC_DBG_SETTING, (CPC_DBG_EN | CPC_CALC_EN)); + + cpc.auto_off = 1; + mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, (CPC_OFF_PRE_EN | + ((cpc.auto_off > 0) ? CPC_AUTO_OFF_EN : 0))); + + mtk_cpc_config(CPC_SMC_CONFIG_AUTO_OFF_THRES, 8000); + + /* enable CPC */ + mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); + mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN); +} -- cgit v1.2.3