mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 01:54:22 +00:00

rk3576 is an Octa-core soc with Cortex-a53/a72 inside. This patch supports the following functions: 1. basic platform setup 2. power up/off cpus 3. suspend/resume cpus 4. suspend/resume system 5. reset system 6. power off system Change-Id: I67a019822bd4af13e4a3cdd09cf06202f4922cc4 Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
1353 lines
41 KiB
C
1353 lines
41 KiB
C
// SPDX-License-Identifier: BSD-3-Clause
|
|
/*
|
|
* Copyright (c) 2025, Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include <drivers/delay_timer.h>
|
|
#include <drivers/scmi.h>
|
|
#include <lib/mmio.h>
|
|
#include <lib/spinlock.h>
|
|
#include <platform_def.h>
|
|
|
|
#include <plat_private.h>
|
|
#include <rk3576_clk.h>
|
|
#include <rockchip_sip_svc.h>
|
|
#include <scmi_clock.h>
|
|
#include <soc.h>
|
|
|
|
enum pll_type_sel {
|
|
PLL_SEL_AUTO, /* all plls (normal pll or pvtpll) */
|
|
PLL_SEL_PVT,
|
|
PLL_SEL_NOR,
|
|
PLL_SEL_AUTO_NOR /* all normal plls (apll/gpll/npll) */
|
|
};
|
|
|
|
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
|
|
|
#define RK3576_PVTPLL_RING_EN 0x00
|
|
#define RK3576_PVTPLL_RING0_LENGTH 0x04
|
|
#define RK3576_PVTPLL_RING1_LENGTH 0x08
|
|
#define RK3576_PVTPLL_RING2_LENGTH 0x0c
|
|
#define RK3576_PVTPLL_RING3_LENGTH 0x10
|
|
#define RK3576_PVTPLL_GCK_CFG 0x20
|
|
#define RK3576_PVTPLL_GCK_LEN 0x24
|
|
#define RK3576_PVTPLL_GCK_DIV 0x28
|
|
#define RK3576_PVTPLL_GCK_CAL_CNT 0x2c
|
|
#define RK3576_PVTPLL_GCK_REF_VAL 0x30
|
|
#define RK3576_PVTPLL_GCK_CFG_VAL 0x34
|
|
#define RK3576_PVTPLL_GCK_THR 0x38
|
|
#define RK3576_PVTPLL_GFREE_CON 0x3c
|
|
#define RK3576_PVTPLL_ADC_CFG 0x40
|
|
#define RK3576_PVTPLL_ADC_CAL_CNT 0x48
|
|
#define RK3576_PVTPLL_GCK_CNT 0x50
|
|
#define RK3576_PVTPLL_GCK_CNT_AVG 0x54
|
|
#define RK3576_PVTPLL_GCK_STATE 0x5c
|
|
#define RK3576_PVTPLL_ADC_CNT 0x60
|
|
#define RK3576_PVTPLL_ADC_CNT_AVG 0x68
|
|
#define RK3576_PVTPLL_VERSION 0x70
|
|
#define RK3576_PVTPLL_MAX_LENGTH 0x3f
|
|
|
|
#define GPLL_RATE 1188000000
|
|
#define CPLL_RATE 1000000000
|
|
#define SPLL_RATE 702000000
|
|
#define AUPLL_RATE 786431952
|
|
|
|
#define MAX_RATE_TABLE 16
|
|
|
|
#define CLKDIV_6BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x3fU, shift)
|
|
#define CLKDIV_5BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x1fU, shift)
|
|
#define CLKDIV_4BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0xfU, shift)
|
|
#define CLKDIV_3BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x7U, shift)
|
|
#define CLKDIV_2BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x3U, shift)
|
|
#define CLKDIV_1BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x1U, shift)
|
|
|
|
#define CPU_PLL_PATH_SLOWMODE BITS_WITH_WMASK(0U, 0x3U, 0)
|
|
#define CPU_PLL_PATH_NORMAL BITS_WITH_WMASK(1U, 0x3U, 0)
|
|
#define CPU_PLL_PATH_DEEP_SLOW BITS_WITH_WMASK(2U, 0x3U, 0)
|
|
|
|
#define CRU_PLL_POWER_DOWN BIT_WITH_WMSK(13)
|
|
#define CRU_PLL_POWER_UP WMSK_BIT(13)
|
|
|
|
/* clk_core:
|
|
* from normal pll(core_i: gpll or apll) path or direct pass from apll
|
|
*/
|
|
|
|
/* cpul clk path */
|
|
#define CPUL_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(1U, 0x3U, 12)
|
|
#define CPUL_CLK_PATH_NOR_LPLL BITS_WITH_WMASK(0U, 0x3U, 12)
|
|
#define CPUL_CLK_PATH_NOR_PVTPLL BITS_WITH_WMASK(2U, 0x3U, 12)
|
|
|
|
#define CPUL_CLK_PATH_LPLL BITS_WITH_WMASK(0U, 0x3U, 6)
|
|
#define CPUL_CLK_PATH_DIR_LPLL BITS_WITH_WMASK(2U, 0x3U, 6)
|
|
#define CPUL_CLK_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x3U, 6)
|
|
|
|
#define CPUL_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 13)
|
|
#define CPUL_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(0x1, 0x1U, 13)
|
|
|
|
/* cpub clk path */
|
|
#define CPUB_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(1U, 0x3U, 12)
|
|
#define CPUB_CLK_PATH_NOR_BPLL BITS_WITH_WMASK(0U, 0x3U, 12)
|
|
#define CPUB_CLK_PATH_NOR_PVTPLL BITS_WITH_WMASK(2U, 0x3U, 12)
|
|
|
|
#define CPUB_CLK_PATH_BPLL BITS_WITH_WMASK(0U, 0x3U, 14)
|
|
#define CPUB_CLK_PATH_DIR_BPLL BITS_WITH_WMASK(2U, 0x3U, 14)
|
|
#define CPUB_CLK_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x3U, 14)
|
|
|
|
#define CPUB_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 5)
|
|
#define CPUB_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(0x1, 0x1U, 5)
|
|
|
|
#define CPUB_PCLK_PATH_100M BITS_WITH_WMASK(0U, 0x3U, 0)
|
|
#define CPUB_PCLK_PATH_50M BITS_WITH_WMASK(1U, 0x3U, 0)
|
|
#define CPUB_PCLK_PATH_24M BITS_WITH_WMASK(2U, 0x3U, 0)
|
|
|
|
/* cci clk path */
|
|
#define SCLK_CCI_PATH_XIN BITS_WITH_WMASK(0U, 0x3U, 12)
|
|
#define SCLK_CCI_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x3U, 12)
|
|
#define SCLK_CCI_PATH_NOR_LPLL BITS_WITH_WMASK(3U, 0x3U, 12)
|
|
#define SCLK_CCI_PATH_NOR_GPLL BITS_WITH_WMASK(2U, 0x3U, 12)
|
|
|
|
#define CCI_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 14)
|
|
#define CCI_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 14)
|
|
|
|
/* npu clk path */
|
|
#define NPU_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(0U, 0x7U, 7)
|
|
#define NPU_CLK_PATH_NOR_CPLL BITS_WITH_WMASK(1U, 0x7U, 7)
|
|
#define NPU_CLK_PATH_NOR_AUPLL BITS_WITH_WMASK(2U, 0x7U, 7)
|
|
#define NPU_CLK_PATH_NOR_SPLL BITS_WITH_WMASK(3U, 0x7U, 7)
|
|
|
|
#define NPU_CLK_PATH_NOR_PLL WMSK_BIT(15)
|
|
#define NPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(15)
|
|
#define NPU_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 9)
|
|
#define NPU_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 9)
|
|
|
|
/* gpu clk path */
|
|
#define GPU_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(0U, 0x7U, 5)
|
|
#define GPU_CLK_PATH_NOR_CPLL BITS_WITH_WMASK(1U, 0x7U, 5)
|
|
#define GPU_CLK_PATH_NOR_AUPLL BITS_WITH_WMASK(2U, 0x7U, 5)
|
|
#define GPU_CLK_PATH_NOR_SPLL BITS_WITH_WMASK(3U, 0x7U, 5)
|
|
#define GPU_CLK_PATH_NOR_LPLL BITS_WITH_WMASK(4U, 0x7U, 5)
|
|
#define GPU_CLK_PATH_NOR_PLL WMSK_BIT(8)
|
|
#define GPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(8)
|
|
#define GPU_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 9)
|
|
#define GPU_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 9)
|
|
|
|
#define PVTPLL_NEED(type, length) (((type) == PLL_SEL_PVT || \
|
|
(type) == PLL_SEL_AUTO) && \
|
|
(length))
|
|
/*
|
|
* [0]: set intermediate rate
|
|
* [1]: scaling up rate or scaling down rate
|
|
* [1]: add length for pvtpll
|
|
* [2:5]: length
|
|
* [2]: use low length for pvtpll
|
|
* [3:5]: reserved
|
|
*/
|
|
#define OPP_RATE_MASK 0x3f
|
|
#define OPP_INTERMEDIATE_RATE BIT(0)
|
|
#define OPP_SCALING_UP_RATE BIT(1)
|
|
#define OPP_ADD_LENGTH BIT(1)
|
|
#define OPP_LENGTH_MASK GENMASK_32(5, 2)
|
|
#define OPP_LENGTH_SHIFT 2
|
|
#define OPP_LENGTH_LOW BIT(2)
|
|
|
|
#define PRATE(x) static const unsigned long const x[]
|
|
#define PINFO(x) static const uint32_t const x[]
|
|
|
|
PRATE(p_24m) = { OSC_HZ };
|
|
PRATE(p_100m_24m) = { 100 * MHz, OSC_HZ };
|
|
PRATE(p_350m_175m_116m_24m) = { 350 * MHz, 175 * MHz, 116 * MHz, OSC_HZ };
|
|
PRATE(p_175m_116m_58m_24m) = { 175 * MHz, 116 * MHz, 58 * MHz, OSC_HZ };
|
|
PRATE(p_116m_58m_24m) = { 116 * MHz, 58 * MHz, OSC_HZ };
|
|
PRATE(p_pclk_secure_s) = { PCLK_SECURE_S };
|
|
PRATE(p_hclk_secure_s) = { HCLK_SECURE_S };
|
|
PRATE(p_aclk_secure_s) = { ACLK_SECURE_S };
|
|
PRATE(p_hclk_vo0_s) = { HCLK_VO0_S };
|
|
PRATE(p_pclk_vo0_s) = { PCLK_VO0_S };
|
|
PRATE(p_hclk_vo1_s) = { HCLK_VO1_S };
|
|
PRATE(p_pclk_vo1_s) = { PCLK_VO1_S };
|
|
|
|
PINFO(clk_stimer0_root_info) = { 0x27214004, 6, 1, 0, 0, 0, 0x27214028, 9 };
|
|
PINFO(clk_stimer1_root_info) = { 0x27214004, 7, 1, 0, 0, 0, 0x2721402c, 1 };
|
|
PINFO(pclk_secure_s_info) = { 0x27214004, 4, 2, 0, 0, 0, 0x27214028, 2 };
|
|
PINFO(hclk_secure_s_info) = { 0x27214004, 2, 2, 0, 0, 0, 0x27214028, 1 };
|
|
PINFO(aclk_secure_s_info) = { 0x27214004, 0, 2, 0, 0, 0, 0x27214028, 0 };
|
|
PINFO(clk_pka_crypto_s_info) = { 0x27214004, 11, 2, 0, 0, 0, 0x27214030, 11 };
|
|
PINFO(hclk_vo1_s_info) = { 0x27214010, 0, 2, 0, 0, 0, 0x27214038, 1 };
|
|
PINFO(pclk_vo1_s_info) = { 0x27214010, 2, 2, 0, 0, 0, 0x27214038, 4 };
|
|
PINFO(hclk_vo0_s_info) = { 0x27214018, 0, 2, 0, 0, 0, 0x2721403c, 1 };
|
|
PINFO(pclk_vo0_s_info) = { 0x27214018, 2, 2, 0, 0, 0, 0x2721403c, 4 };
|
|
PINFO(pclk_klad_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 7 };
|
|
PINFO(hclk_crypto_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 8 };
|
|
PINFO(hclk_klad_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 9 };
|
|
PINFO(aclk_crypto_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 12 };
|
|
PINFO(hclk_trng_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 0 };
|
|
PINFO(pclk_otpc_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 3 };
|
|
PINFO(clk_otpc_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 4 };
|
|
PINFO(pclk_wdt_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 9 };
|
|
PINFO(tclk_wdt_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 10 };
|
|
PINFO(pclk_hdcp1_trng_info) = { 0, 0, 0, 0, 0, 0, 0x27214038, 0 };
|
|
PINFO(hclk_hdcp_key1_info) = { 0, 0, 0, 0, 0, 0, 0x27214038, 3 };
|
|
PINFO(pclk_hdcp0_trng_info) = { 0, 0, 0, 0, 0, 0, 0x2721403c, 0 };
|
|
PINFO(hclk_hdcp_key0_info) = { 0, 0, 0, 0, 0, 0, 0x2721403c, 3 };
|
|
PINFO(pclk_edp_s_info) = { 0, 0, 0, 0, 0, 0, 0x2721403c, 5 };
|
|
|
|
struct pvtpll_table {
|
|
unsigned int rate;
|
|
uint32_t length;
|
|
uint32_t length_frac;
|
|
uint32_t length_low;
|
|
uint32_t length_low_frac;
|
|
uint32_t ring_sel;
|
|
uint32_t volt_sel_thr;
|
|
};
|
|
|
|
struct sys_clk_info_t {
|
|
struct pvtpll_table *cpul_table;
|
|
struct pvtpll_table *cci_table;
|
|
struct pvtpll_table *cpub_table;
|
|
struct pvtpll_table *gpu_table;
|
|
struct pvtpll_table *npu_table;
|
|
unsigned int cpul_rate_count;
|
|
unsigned int cci_rate_count;
|
|
unsigned int cpub_rate_count;
|
|
unsigned int gpu_rate_count;
|
|
unsigned int npu_rate_count;
|
|
unsigned long cpul_rate;
|
|
unsigned long cci_rate;
|
|
unsigned long cpub_rate;
|
|
unsigned long gpu_rate;
|
|
unsigned long npu_rate;
|
|
};
|
|
|
|
struct otp_opp_info {
|
|
uint16_t min_freq;
|
|
uint16_t max_freq;
|
|
uint8_t volt;
|
|
uint8_t length;
|
|
} __packed;
|
|
|
|
#define RK3576_SCMI_CLOCK(_id, _name, _data, _table, _cnt, _is_s) \
|
|
rk_scmi_clock_t _name = { \
|
|
.id = _id, \
|
|
.name = #_name, \
|
|
.clk_ops = _data, \
|
|
.rate_table = _table, \
|
|
.rate_cnt = _cnt, \
|
|
.is_security = _is_s, \
|
|
}
|
|
|
|
#define RK3576_SCMI_CLOCK_COM(_id, _name, _parent_table, _info, _data, \
|
|
_table, is_d, _is_s) \
|
|
rk_scmi_clock_t _name = { \
|
|
.id = _id, \
|
|
.name = #_name, \
|
|
.parent_table = _parent_table, \
|
|
.info = _info, \
|
|
.clk_ops = _data, \
|
|
.rate_table = _table, \
|
|
.rate_cnt = ARRAY_SIZE(_table), \
|
|
.is_dynamic_prate = is_d, \
|
|
.is_security = _is_s, \
|
|
}
|
|
|
|
#define ROCKCHIP_PVTPLL(_rate, _sel, _len, _len_frac) \
|
|
{ \
|
|
.rate = _rate##U, \
|
|
.ring_sel = _sel, \
|
|
.length = _len, \
|
|
.length_frac = _len_frac, \
|
|
}
|
|
|
|
static struct pvtpll_table rk3576_cpul_pvtpll_table[] = {
|
|
/* rate_hz, ring_sel, length, length_frac */
|
|
ROCKCHIP_PVTPLL(2016000000, 0, 6, 0),
|
|
ROCKCHIP_PVTPLL(1920000000, 0, 6, 1),
|
|
ROCKCHIP_PVTPLL(1800000000, 0, 6, 1),
|
|
ROCKCHIP_PVTPLL(1608000000, 0, 6, 1),
|
|
ROCKCHIP_PVTPLL(1416000000, 0, 8, 0),
|
|
ROCKCHIP_PVTPLL(1200000000, 0, 11, 0),
|
|
ROCKCHIP_PVTPLL(1008000000, 0, 17, 0),
|
|
ROCKCHIP_PVTPLL(816000000, 0, 26, 0),
|
|
ROCKCHIP_PVTPLL(600000000, 0, 0, 0),
|
|
ROCKCHIP_PVTPLL(408000000, 0, 0, 0),
|
|
{ /* sentinel */ },
|
|
};
|
|
|
|
static struct pvtpll_table rk3576_cci_pvtpll_table[] = {
|
|
/* cpul_rate_hz, ring_sel, length, length_frac */
|
|
ROCKCHIP_PVTPLL(2016000000 / 2, 0, 27, 0),
|
|
ROCKCHIP_PVTPLL(1920000000 / 2, 0, 28, 0),
|
|
ROCKCHIP_PVTPLL(1800000000 / 2, 0, 28, 0),
|
|
ROCKCHIP_PVTPLL(1608000000 / 2, 0, 30, 0),
|
|
ROCKCHIP_PVTPLL(1416000000 / 2, 0, 34, 0),
|
|
ROCKCHIP_PVTPLL(1200000000 / 2, 0, 34, 0),
|
|
{ /* sentinel */ },
|
|
};
|
|
|
|
static struct pvtpll_table rk3576_cpub_pvtpll_table[] = {
|
|
/* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
|
|
ROCKCHIP_PVTPLL(2208000000, 0, 4, 3),
|
|
ROCKCHIP_PVTPLL(2112000000, 0, 5, 0),
|
|
ROCKCHIP_PVTPLL(2016000000, 0, 5, 0),
|
|
ROCKCHIP_PVTPLL(1800000000, 0, 5, 0),
|
|
ROCKCHIP_PVTPLL(1608000000, 0, 5, 0),
|
|
ROCKCHIP_PVTPLL(1416000000, 0, 7, 0),
|
|
ROCKCHIP_PVTPLL(1200000000, 0, 11, 0),
|
|
ROCKCHIP_PVTPLL(1008000000, 0, 17, 0),
|
|
ROCKCHIP_PVTPLL(816000000, 0, 26, 0),
|
|
ROCKCHIP_PVTPLL(600000000, 0, 0, 0),
|
|
ROCKCHIP_PVTPLL(408000000, 0, 0, 0),
|
|
{ /* sentinel */ },
|
|
};
|
|
|
|
static struct pvtpll_table rk3576_gpu_pvtpll_table[] = {
|
|
/* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
|
|
ROCKCHIP_PVTPLL(900000000, 0, 20, 0),
|
|
ROCKCHIP_PVTPLL(800000000, 0, 21, 0),
|
|
ROCKCHIP_PVTPLL(700000000, 0, 21, 0),
|
|
ROCKCHIP_PVTPLL(600000000, 0, 23, 0),
|
|
ROCKCHIP_PVTPLL(500000000, 0, 32, 0),
|
|
ROCKCHIP_PVTPLL(400000000, 0, 48, 0),
|
|
ROCKCHIP_PVTPLL(300000000, 0, 63, 0),
|
|
ROCKCHIP_PVTPLL(200000000, 0, 0, 0),
|
|
{ /* sentinel */ },
|
|
};
|
|
|
|
static struct pvtpll_table rk3576_npu_pvtpll_table[] = {
|
|
/* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
|
|
ROCKCHIP_PVTPLL(950000000, 0, 16, 0),
|
|
ROCKCHIP_PVTPLL(900000000, 0, 17, 0),
|
|
ROCKCHIP_PVTPLL(800000000, 0, 18, 0),
|
|
ROCKCHIP_PVTPLL(700000000, 0, 22, 0),
|
|
ROCKCHIP_PVTPLL(600000000, 0, 25, 0),
|
|
ROCKCHIP_PVTPLL(500000000, 0, 35, 0),
|
|
ROCKCHIP_PVTPLL(400000000, 0, 46, 0),
|
|
ROCKCHIP_PVTPLL(300000000, 0, 63, 0),
|
|
ROCKCHIP_PVTPLL(200000000, 0, 0, 0),
|
|
{ /* sentinel */ },
|
|
};
|
|
|
|
static unsigned long rk3576_cpul_rates[] = {
|
|
408000000, 600000000, 816000000, 1008000000,
|
|
1200000000, 1416000000, 1608000000, 1800000000,
|
|
2016000000, 2208000000, 2304000063
|
|
};
|
|
|
|
static unsigned long rk3576_cpub_rates[] = {
|
|
408000000, 600000000, 816000000, 1008000000,
|
|
1200000000, 1416000000, 1608000000, 1800000000,
|
|
2016000000, 2208000000, 2304000000, 2400000063
|
|
};
|
|
|
|
static unsigned long rk3576_gpu_rates[] = {
|
|
200000000, 300000000, 400000000, 500000000,
|
|
600000000, 700000000, 800000000, 900000000,
|
|
1000000063
|
|
};
|
|
|
|
static unsigned long rk3576_npu_rates[] = {
|
|
200000000, 300000000, 400000000, 500000000,
|
|
600000000, 700000000, 800000000, 900000000,
|
|
1000000063
|
|
};
|
|
|
|
static unsigned long rk3576_common_rates[] = {
|
|
400000, 24000000, 58000000, 100000000, 116000000, 175000000, 350000000,
|
|
};
|
|
|
|
static unsigned long rk3576_aclk_secure_s_rates[] = {
|
|
116000000, 175000000, 350000000,
|
|
};
|
|
|
|
static int aclk_crypto_s_enable;
|
|
static int aclk_klad_enable;
|
|
static spinlock_t crypto_lock;
|
|
static bool cpub_suspended;
|
|
|
|
static struct sys_clk_info_t sys_clk_info;
|
|
static int clk_scmi_cci_set_rate(rk_scmi_clock_t *clock, unsigned long rate);
|
|
|
|
static struct pvtpll_table *rkclk_get_pvtpll_config(struct pvtpll_table *table,
|
|
unsigned int count,
|
|
unsigned int freq_hz)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (freq_hz == table[i].rate)
|
|
return &table[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static int clk_scmi_set_low_length(struct pvtpll_table *pvtpll, unsigned int count)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (pvtpll[i].length_low) {
|
|
pvtpll[i].length = pvtpll[i].length_low;
|
|
pvtpll[i].length_frac = pvtpll[i].length_low_frac;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clk_cpul_set_rate(unsigned long rate, enum pll_type_sel type)
|
|
{
|
|
struct pvtpll_table *pvtpll;
|
|
int div;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cpul_table,
|
|
sys_clk_info.cpul_rate_count, rate);
|
|
if (pvtpll == NULL)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
/*
|
|
* |-\
|
|
* -----lpll-----| \
|
|
* | \ |-\
|
|
* -----gpll-----|mux|--litcore unclean src--[div]--[autocs]--| \
|
|
* | / | \
|
|
* --pvtpll src--| / --pvtpll src--|mux|--litcore--
|
|
* |-/ | /
|
|
* --litcore clean src--| /
|
|
* |-/
|
|
*/
|
|
if (PVTPLL_NEED(type, pvtpll->length)) {
|
|
/* set ring sel and length */
|
|
mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_LEN,
|
|
0x1dff0000 |
|
|
(pvtpll->ring_sel << 10) |
|
|
(pvtpll->length << 2) |
|
|
(pvtpll->length_frac));
|
|
/* set cal cnt = 24, T = 1us */
|
|
mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
|
|
/* enable pvtpll */
|
|
mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
|
|
/* start pvtpll */
|
|
mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
|
|
|
|
/* set pvtpll_src parent from 24MHz/32KHz to pvtpll */
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
|
|
CPUL_PVTPLL_PATH_PVTPLL);
|
|
|
|
/* set litcore unclean_src parent to pvtpll_src */
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
|
|
CPUL_CLK_PATH_NOR_PVTPLL);
|
|
/*
|
|
* set litcore parent from pvtpll_src to unclean_src,
|
|
* because autocs is on litcore unclean_src.
|
|
*/
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
|
|
CPUL_CLK_PATH_LPLL);
|
|
/* set litcore unclean_src div to 0 */
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
|
|
CLKDIV_5BITS_SHF(0, 7));
|
|
|
|
return 0;
|
|
}
|
|
/* set litcore unclean_src div */
|
|
div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
|
|
CLKDIV_5BITS_SHF(div, 7));
|
|
/* set litcore unclean_src parent to gpll */
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
|
|
CPUL_CLK_PATH_NOR_GPLL);
|
|
/* set litcore parent to unclean_src */
|
|
mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
|
|
CPUL_CLK_PATH_LPLL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clk_scmi_cpul_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
|
|
{
|
|
int ret;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
ret = clk_cpul_set_rate(rate, PLL_SEL_AUTO);
|
|
if (ret == 0) {
|
|
sys_clk_info.cpul_rate = rate;
|
|
ret = clk_scmi_cci_set_rate(clock, rate / 2);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static unsigned long rk3576_lpll_get_rate(void)
|
|
{
|
|
unsigned int m, p, s, k;
|
|
uint64_t rate64 = 24000000, postdiv;
|
|
int mode;
|
|
|
|
mode = mmio_read_32(LITTLE_CRU_BASE + CRU_MODE_CON) &
|
|
0x3;
|
|
|
|
if (mode == 0)
|
|
return rate64;
|
|
|
|
m = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(16)) >>
|
|
CRU_PLLCON0_M_SHIFT) &
|
|
CRU_PLLCON0_M_MASK;
|
|
p = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(17)) >>
|
|
CRU_PLLCON1_P_SHIFT) &
|
|
CRU_PLLCON1_P_MASK;
|
|
s = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(17)) >>
|
|
CRU_PLLCON1_S_SHIFT) &
|
|
CRU_PLLCON1_S_MASK;
|
|
k = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(18)) >>
|
|
CRU_PLLCON2_K_SHIFT) &
|
|
CRU_PLLCON2_K_MASK;
|
|
|
|
rate64 *= m;
|
|
rate64 = rate64 / p;
|
|
|
|
if (k != 0) {
|
|
/* fractional mode */
|
|
uint64_t frac_rate64 = 24000000 * k;
|
|
|
|
postdiv = p * 65536;
|
|
frac_rate64 = frac_rate64 / postdiv;
|
|
rate64 += frac_rate64;
|
|
}
|
|
rate64 = rate64 >> s;
|
|
|
|
return (unsigned long)rate64;
|
|
}
|
|
|
|
static unsigned long clk_scmi_cpul_get_rate(rk_scmi_clock_t *clock)
|
|
{
|
|
int src, div;
|
|
|
|
src = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1)) & 0x00c0;
|
|
src = src >> 6;
|
|
if (src == 1)
|
|
return sys_clk_info.cpul_rate;
|
|
|
|
src = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0)) & 0x3000;
|
|
src = src >> 12;
|
|
div = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(6)) & 0x0f80;
|
|
div = div >> 7;
|
|
switch (src) {
|
|
case 0:
|
|
return rk3576_lpll_get_rate();
|
|
case 1:
|
|
/* Make the return rate is equal to the set rate */
|
|
if (sys_clk_info.cpul_rate != 0)
|
|
return sys_clk_info.cpul_rate;
|
|
else
|
|
return GPLL_RATE / (div + 1);
|
|
case 2:
|
|
return sys_clk_info.cpul_rate;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int clk_scmi_cpul_set_status(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int clk_cpub_set_rate(unsigned long rate, enum pll_type_sel type)
|
|
{
|
|
struct pvtpll_table *pvtpll;
|
|
int div;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cpub_table,
|
|
sys_clk_info.cpub_rate_count, rate);
|
|
if (pvtpll == NULL)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
/*
|
|
* |-\
|
|
* -----bpll-----| \
|
|
* | \ |-\
|
|
* -----gpll-----|mux|--bigcore unclean src--[div]--[autocs]--| \
|
|
* | / | \
|
|
* --pvtpll src--| / --pvtpll src--|mux|--bigcore--
|
|
* |-/ | /
|
|
* --bigcore clean src--| /
|
|
* |-/
|
|
*/
|
|
if (PVTPLL_NEED(type, pvtpll->length) != 0) {
|
|
/* set ring sel and length */
|
|
mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_LEN,
|
|
0x1dff0000 |
|
|
(pvtpll->ring_sel << 10) |
|
|
(pvtpll->length << 2) |
|
|
(pvtpll->length_frac));
|
|
/* set cal cnt = 24, T = 1us */
|
|
mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
|
|
/* enable pvtpll */
|
|
mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
|
|
/* start pvtpll */
|
|
mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
|
|
|
|
/* set pvtpll_src parent from 24MHz/32KHz to pvtpll */
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(2),
|
|
CPUB_PVTPLL_PATH_PVTPLL);
|
|
|
|
/* set bigcore unclean_src parent to pvtpll_src */
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
|
|
CPUB_CLK_PATH_NOR_PVTPLL);
|
|
/*
|
|
* set bigcore parent from pvtpll_src to unclean_src,
|
|
* because autocs is on bigcore unclean_src.
|
|
*/
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
|
|
CPUB_CLK_PATH_BPLL);
|
|
|
|
/* set bigcore unclean_src div to 0 */
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
|
|
CLKDIV_5BITS_SHF(0, 7));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* set bigcore unclean_src div */
|
|
div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
|
|
CLKDIV_5BITS_SHF(div, 7));
|
|
/* set bigcore unclean_src parent to gpll */
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
|
|
CPUB_CLK_PATH_NOR_GPLL);
|
|
/* set bigcore parent to unclean_src */
|
|
mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
|
|
CPUB_CLK_PATH_BPLL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clk_scmi_cpub_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
|
|
{
|
|
int ret;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
if ((rate & OPP_LENGTH_LOW) != 0) {
|
|
clk_scmi_set_low_length(sys_clk_info.cpub_table,
|
|
sys_clk_info.cpub_rate_count);
|
|
return 0;
|
|
}
|
|
|
|
ret = clk_cpub_set_rate(rate, PLL_SEL_AUTO);
|
|
if (ret == 0)
|
|
sys_clk_info.cpub_rate = rate;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static unsigned long rk3576_bpll_get_rate(void)
|
|
{
|
|
unsigned int m, p, s, k;
|
|
uint64_t rate64 = 24000000, postdiv;
|
|
int mode;
|
|
|
|
mode = mmio_read_32(CRU_BASE + CRU_MODE_CON) &
|
|
0x3;
|
|
|
|
if (mode == 0)
|
|
return rate64;
|
|
|
|
m = (mmio_read_32(CRU_BASE + CRU_PLL_CON(0)) >>
|
|
CRU_PLLCON0_M_SHIFT) &
|
|
CRU_PLLCON0_M_MASK;
|
|
p = (mmio_read_32(CRU_BASE + CRU_PLL_CON(1)) >>
|
|
CRU_PLLCON1_P_SHIFT) &
|
|
CRU_PLLCON1_P_MASK;
|
|
s = (mmio_read_32(CRU_BASE + CRU_PLL_CON(1)) >>
|
|
CRU_PLLCON1_S_SHIFT) &
|
|
CRU_PLLCON1_S_MASK;
|
|
k = (mmio_read_32(CRU_BASE + CRU_PLL_CON(2)) >>
|
|
CRU_PLLCON2_K_SHIFT) &
|
|
CRU_PLLCON2_K_MASK;
|
|
|
|
rate64 *= m;
|
|
rate64 = rate64 / p;
|
|
|
|
if (k != 0) {
|
|
/* fractional mode */
|
|
uint64_t frac_rate64 = 24000000 * k;
|
|
|
|
postdiv = p * 65536;
|
|
frac_rate64 = frac_rate64 / postdiv;
|
|
rate64 += frac_rate64;
|
|
}
|
|
rate64 = rate64 >> s;
|
|
|
|
return (unsigned long)rate64;
|
|
}
|
|
|
|
static unsigned long clk_scmi_cpub_get_rate(rk_scmi_clock_t *clock)
|
|
{
|
|
int value, src, div;
|
|
|
|
if (cpub_suspended != 0)
|
|
return sys_clk_info.cpub_rate;
|
|
|
|
value = mmio_read_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1));
|
|
src = (value & 0xc000) >> 14;
|
|
if (src == 1)
|
|
return sys_clk_info.cpub_rate;
|
|
|
|
value = mmio_read_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1));
|
|
src = (value & 0x3000) >> 12;
|
|
div = (value & 0x0f80) >> 7;
|
|
switch (src) {
|
|
case 0:
|
|
return rk3576_bpll_get_rate();
|
|
case 1:
|
|
/* Make the return rate is equal to the set rate */
|
|
if (sys_clk_info.cpub_rate != 0)
|
|
return sys_clk_info.cpub_rate;
|
|
else
|
|
return GPLL_RATE / (div + 1);
|
|
case 2:
|
|
return sys_clk_info.cpub_rate;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int clk_scmi_cpub_set_status(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned long clk_scmi_cci_get_rate(rk_scmi_clock_t *clock)
|
|
{
|
|
int src, div;
|
|
|
|
src = mmio_read_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4)) & 0x3000;
|
|
src = src >> 12;
|
|
if (src == 1)
|
|
return sys_clk_info.cci_rate;
|
|
|
|
div = mmio_read_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4)) & 0xf80;
|
|
div = div >> 7;
|
|
switch (src) {
|
|
case 0:
|
|
return OSC_HZ;
|
|
case 1:
|
|
return sys_clk_info.cci_rate;
|
|
case 2:
|
|
return GPLL_RATE / (div + 1);
|
|
case 3:
|
|
return rk3576_lpll_get_rate() / (div + 1);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int clk_cci_set_rate(unsigned long rate, enum pll_type_sel type)
|
|
{
|
|
struct pvtpll_table *pvtpll;
|
|
uint32_t pvtpll_en = 0;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cci_table,
|
|
sys_clk_info.cci_rate_count, rate);
|
|
|
|
/* set pvtpll */
|
|
if ((pvtpll != 0) && (PVTPLL_NEED(type, pvtpll->length) != 0)) {
|
|
/* set ring sel and length */
|
|
mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_LEN,
|
|
0x1dff0000 |
|
|
(pvtpll->ring_sel << 10) |
|
|
(pvtpll->length << 2) |
|
|
(pvtpll->length_frac));
|
|
/* set cal cnt = 24, T = 1us */
|
|
mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
|
|
/* enable pvtpll */
|
|
pvtpll_en = mmio_read_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG);
|
|
if (pvtpll_en && 0x22 != 0x22)
|
|
mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
|
|
/* start pvtpll */
|
|
mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
|
|
|
|
/* set cci mux pvtpll */
|
|
mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
|
|
CCI_PVTPLL_PATH_PVTPLL);
|
|
mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
|
|
SCLK_CCI_PATH_PVTPLL);
|
|
mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
|
|
CLKDIV_5BITS_SHF(0, 7));
|
|
sys_clk_info.cci_rate = rate;
|
|
return 0;
|
|
}
|
|
sys_clk_info.cci_rate = 594000000;
|
|
/* set cci div */
|
|
mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
|
|
CLKDIV_5BITS_SHF(1, 7));
|
|
/* set cci mux gpll */
|
|
mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
|
|
SCLK_CCI_PATH_NOR_GPLL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clk_scmi_cci_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
|
|
{
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
return clk_cci_set_rate(rate, PLL_SEL_AUTO);
|
|
}
|
|
|
|
static int clk_scmi_cci_set_status(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned long clk_scmi_gpu_get_rate(rk_scmi_clock_t *clock)
|
|
{
|
|
int div, src;
|
|
|
|
if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x100) != 0)
|
|
return sys_clk_info.gpu_rate;
|
|
|
|
div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x1f;
|
|
src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x00e0;
|
|
src = src >> 5;
|
|
switch (src) {
|
|
case 0:
|
|
/* Make the return rate is equal to the set rate */
|
|
if (sys_clk_info.gpu_rate != 0)
|
|
return sys_clk_info.gpu_rate;
|
|
else
|
|
return GPLL_RATE / (div + 1);
|
|
case 1:
|
|
return CPLL_RATE / (div + 1);
|
|
case 2:
|
|
return AUPLL_RATE / (div + 1);
|
|
case 3:
|
|
return SPLL_RATE / (div + 1);
|
|
case 4:
|
|
return rk3576_lpll_get_rate() / (div + 1);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int clk_gpu_set_rate(unsigned long rate, enum pll_type_sel type)
|
|
{
|
|
struct pvtpll_table *pvtpll;
|
|
int div;
|
|
|
|
pvtpll = rkclk_get_pvtpll_config(sys_clk_info.gpu_table,
|
|
sys_clk_info.gpu_rate_count, rate);
|
|
if (pvtpll == NULL)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
if (PVTPLL_NEED(type, pvtpll->length) != 0) {
|
|
/* set ring sel and length */
|
|
mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_LEN,
|
|
0x1dff0000 |
|
|
(pvtpll->ring_sel << 10) |
|
|
(pvtpll->length << 2) |
|
|
(pvtpll->length_frac));
|
|
/* set cal cnt = 24, T = 1us */
|
|
mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
|
|
/* enable pvtpll */
|
|
mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
|
|
/* start pvtpll */
|
|
mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
|
|
/* set gpu mux pvtpll */
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
|
|
GPU_PVTPLL_PATH_PVTPLL);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
|
|
GPU_CLK_PATH_PVTPLL);
|
|
return 0;
|
|
}
|
|
|
|
/* set gpu div */
|
|
div = DIV_ROUND_UP(GPLL_RATE, rate);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
|
|
CLKDIV_5BITS_SHF(div - 1, 0));
|
|
/* set gpu mux gpll */
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
|
|
GPU_CLK_PATH_NOR_GPLL);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
|
|
GPU_CLK_PATH_NOR_PLL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clk_scmi_gpu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
|
|
{
|
|
int ret;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
if ((rate & OPP_LENGTH_LOW) != 0) {
|
|
clk_scmi_set_low_length(sys_clk_info.gpu_table,
|
|
sys_clk_info.gpu_rate_count);
|
|
return 0;
|
|
}
|
|
|
|
ret = clk_gpu_set_rate(rate, PLL_SEL_AUTO);
|
|
if (ret == 0)
|
|
sys_clk_info.gpu_rate = rate;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int clk_scmi_gpu_set_status(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned long clk_scmi_npu_get_rate(rk_scmi_clock_t *clock)
|
|
{
|
|
int div, src, div_src;
|
|
|
|
if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x8000) != 0)
|
|
return sys_clk_info.npu_rate;
|
|
|
|
div_src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x07c;
|
|
div_src = div_src >> 2;
|
|
src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x0180;
|
|
src = src >> 7;
|
|
div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x7c00;
|
|
div = div >> 10;
|
|
switch (src) {
|
|
case 0:
|
|
/* Make the return rate is equal to the set rate */
|
|
if (sys_clk_info.npu_rate != 0)
|
|
return sys_clk_info.npu_rate;
|
|
else
|
|
return GPLL_RATE / (div_src + 1) / (div + 1);
|
|
case 1:
|
|
return CPLL_RATE / (div_src + 1) / (div + 1);
|
|
case 2:
|
|
return AUPLL_RATE / (div_src + 1) / (div + 1);
|
|
case 3:
|
|
return SPLL_RATE / (div_src + 1) / (div + 1);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int clk_npu_set_rate(unsigned long rate, enum pll_type_sel type)
|
|
{
|
|
struct pvtpll_table *pvtpll;
|
|
int div;
|
|
|
|
pvtpll = rkclk_get_pvtpll_config(sys_clk_info.npu_table,
|
|
sys_clk_info.npu_rate_count, rate);
|
|
if (pvtpll == NULL)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
if (PVTPLL_NEED(type, pvtpll->length) != 0) {
|
|
/* set ring sel and length */
|
|
mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_LEN,
|
|
0x1dff0000 |
|
|
(pvtpll->ring_sel << 10) |
|
|
(pvtpll->length << 2) |
|
|
(pvtpll->length_frac));
|
|
/* set cal cnt = 24, T = 1us */
|
|
mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
|
|
/* enable pvtpll */
|
|
mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
|
|
/* start pvtpll */
|
|
mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
|
|
/* set npu mux pvtpll */
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
NPU_PVTPLL_PATH_PVTPLL);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
NPU_CLK_PATH_PVTPLL);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
CLKDIV_5BITS_SHF(0, 10));
|
|
return 0;
|
|
}
|
|
|
|
/* set npu div */
|
|
div = DIV_ROUND_UP(GPLL_RATE, rate);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
CLKDIV_5BITS_SHF(div - 1, 2));
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
CLKDIV_5BITS_SHF(0, 10));
|
|
/* set npu mux gpll */
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
NPU_CLK_PATH_NOR_GPLL);
|
|
mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
|
|
NPU_CLK_PATH_NOR_PLL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int clk_scmi_npu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
|
|
{
|
|
int ret;
|
|
|
|
if (rate == 0)
|
|
return SCMI_INVALID_PARAMETERS;
|
|
|
|
if ((rate & OPP_LENGTH_LOW) != 0) {
|
|
clk_scmi_set_low_length(sys_clk_info.npu_table,
|
|
sys_clk_info.npu_rate_count);
|
|
return 0;
|
|
}
|
|
|
|
ret = clk_npu_set_rate(rate, PLL_SEL_AUTO);
|
|
if (ret == 0)
|
|
sys_clk_info.npu_rate = rate;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int clk_scmi_npu_set_status(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int clk_scmi_crypto_set_status(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
spin_lock(&crypto_lock);
|
|
|
|
if (clock->id == ACLK_CRYPTO_S)
|
|
aclk_crypto_s_enable = status;
|
|
else
|
|
aclk_klad_enable = status;
|
|
|
|
if ((aclk_crypto_s_enable != 0) || (aclk_klad_enable != 0))
|
|
clk_scmi_common_set_status(clock, 1);
|
|
else
|
|
clk_scmi_common_set_status(clock, 0);
|
|
|
|
spin_unlock(&crypto_lock);
|
|
return 0;
|
|
}
|
|
|
|
static int clk_scmi_common_set_status_critical(rk_scmi_clock_t *clock, bool status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static const struct rk_clk_ops clk_scmi_cpul_ops = {
|
|
.get_rate = clk_scmi_cpul_get_rate,
|
|
.set_rate = clk_scmi_cpul_set_rate,
|
|
.set_status = clk_scmi_cpul_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_cci_ops = {
|
|
.get_rate = clk_scmi_cci_get_rate,
|
|
.set_rate = clk_scmi_cci_set_rate,
|
|
.set_status = clk_scmi_cci_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_cpub_ops = {
|
|
.get_rate = clk_scmi_cpub_get_rate,
|
|
.set_rate = clk_scmi_cpub_set_rate,
|
|
.set_status = clk_scmi_cpub_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_gpu_ops = {
|
|
.get_rate = clk_scmi_gpu_get_rate,
|
|
.set_rate = clk_scmi_gpu_set_rate,
|
|
.set_status = clk_scmi_gpu_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_npu_ops = {
|
|
.get_rate = clk_scmi_npu_get_rate,
|
|
.set_rate = clk_scmi_npu_set_rate,
|
|
.set_status = clk_scmi_npu_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_ops_com_critical = {
|
|
.get_rate = clk_scmi_common_get_rate,
|
|
.set_rate = clk_scmi_common_set_rate,
|
|
.set_status = clk_scmi_common_set_status_critical,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_ops_com = {
|
|
.get_rate = clk_scmi_common_get_rate,
|
|
.set_rate = clk_scmi_common_set_rate,
|
|
.set_status = clk_scmi_common_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_ops_gate = {
|
|
.get_rate = clk_scmi_common_get_rate,
|
|
.set_status = clk_scmi_common_set_status,
|
|
};
|
|
|
|
static const struct rk_clk_ops clk_scmi_ops_crypto = {
|
|
.get_rate = clk_scmi_common_get_rate,
|
|
.set_status = clk_scmi_crypto_set_status,
|
|
};
|
|
|
|
RK3576_SCMI_CLOCK(ARMCLK_L, scmi_armclkl, &clk_scmi_cpul_ops, rk3576_cpul_rates, ARRAY_SIZE(rk3576_cpul_rates), false);
|
|
RK3576_SCMI_CLOCK(ACLK_CCI_ROOT, scmi_aclk_cci, &clk_scmi_cci_ops, rk3576_cpul_rates, ARRAY_SIZE(rk3576_cpul_rates), false);
|
|
RK3576_SCMI_CLOCK(ARMCLK_B, scmi_armclkb, &clk_scmi_cpub_ops, rk3576_cpub_rates, ARRAY_SIZE(rk3576_cpub_rates), false);
|
|
RK3576_SCMI_CLOCK(CLK_GPU, scmi_clk_gpu, &clk_scmi_gpu_ops, rk3576_gpu_rates, ARRAY_SIZE(rk3576_gpu_rates), false);
|
|
RK3576_SCMI_CLOCK(CLK_RKNN_DSU0, scmi_clk_npu, &clk_scmi_npu_ops, rk3576_npu_rates, ARRAY_SIZE(rk3576_npu_rates), false);
|
|
RK3576_SCMI_CLOCK_COM(CLK_STIMER0_ROOT, clk_stimer0_root, p_100m_24m, clk_stimer0_root_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(CLK_STIMER1_ROOT, clk_stimer1_root, p_100m_24m, clk_stimer1_root_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_SECURE_S, pclk_secure_s, p_116m_58m_24m, pclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_SECURE_S, hclk_secure_s, p_175m_116m_58m_24m, hclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(ACLK_SECURE_S, aclk_secure_s, p_350m_175m_116m_24m, aclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_aclk_secure_s_rates, false, false);
|
|
RK3576_SCMI_CLOCK_COM(CLK_PKA_CRYPTO_S, clk_pka_crypto_s, p_350m_175m_116m_24m, clk_pka_crypto_s_info, &clk_scmi_ops_com, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_VO1_S, hclk_vo1_s, p_175m_116m_58m_24m, hclk_vo1_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_VO1_S, pclk_vo1_s, p_116m_58m_24m, pclk_vo1_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_VO0_S, hclk_vo0_s, p_175m_116m_58m_24m, hclk_vo0_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_VO0_S, pclk_vo0_s, p_116m_58m_24m, pclk_vo0_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_KLAD, pclk_klad, p_pclk_secure_s, pclk_klad_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_CRYPTO_S, hclk_crypto_s, p_hclk_secure_s, hclk_crypto_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_KLAD, hclk_klad, p_hclk_secure_s, hclk_klad_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(ACLK_CRYPTO_S, aclk_crypto_s, p_aclk_secure_s, aclk_crypto_s_info, &clk_scmi_ops_crypto, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_TRNG_S, hclk_trng_s, p_hclk_secure_s, hclk_trng_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_OTPC_S, plk_otpc_s, p_pclk_secure_s, pclk_otpc_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(CLK_OTPC_S, clk_otpc_s, p_24m, clk_otpc_s_info, &clk_scmi_ops_gate, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_WDT_S, pclk_wdt_s, p_pclk_secure_s, pclk_wdt_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(TCLK_WDT_S, tclk_wdt_s, p_24m, tclk_wdt_s_info, &clk_scmi_ops_gate, rk3576_common_rates, false, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_HDCP0_TRNG, pclk_hdcp0_trng, p_pclk_vo0_s, pclk_hdcp0_trng_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_HDCP1_TRNG, pclk_hdcp1_trng, p_pclk_vo1_s, pclk_hdcp1_trng_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_HDCP_KEY0, hclk_hdcp_key0, p_hclk_vo0_s, hclk_hdcp_key0_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(HCLK_HDCP_KEY1, hclk_hdcp_key1, p_hclk_vo1_s, hclk_hdcp_key1_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(PCLK_EDP_S, pclk_edp_s, p_pclk_vo0_s, pclk_edp_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
|
|
RK3576_SCMI_CLOCK_COM(ACLK_KLAD, aclk_klad, p_aclk_secure_s, aclk_crypto_s_info, &clk_scmi_ops_crypto, rk3576_common_rates, true, true);
|
|
|
|
rk_scmi_clock_t *clock_table[] = {
|
|
[ARMCLK_L] = &scmi_armclkl,
|
|
[ACLK_CCI_ROOT] = &scmi_aclk_cci,
|
|
[ARMCLK_B] = &scmi_armclkb,
|
|
[CLK_GPU] = &scmi_clk_gpu,
|
|
[CLK_RKNN_DSU0] = &scmi_clk_npu,
|
|
[CLK_STIMER0_ROOT] = &clk_stimer0_root,
|
|
[CLK_STIMER1_ROOT] = &clk_stimer1_root,
|
|
[PCLK_SECURE_S] = &pclk_secure_s,
|
|
[HCLK_SECURE_S] = &hclk_secure_s,
|
|
[ACLK_SECURE_S] = &aclk_secure_s,
|
|
[CLK_PKA_CRYPTO_S] = &clk_pka_crypto_s,
|
|
[HCLK_VO1_S] = &hclk_vo1_s,
|
|
[PCLK_VO1_S] = &pclk_vo1_s,
|
|
[HCLK_VO0_S] = &hclk_vo0_s,
|
|
[PCLK_VO0_S] = &pclk_vo0_s,
|
|
[PCLK_KLAD] = &pclk_klad,
|
|
[HCLK_CRYPTO_S] = &hclk_crypto_s,
|
|
[HCLK_KLAD] = &hclk_klad,
|
|
[ACLK_CRYPTO_S] = &aclk_crypto_s,
|
|
[HCLK_TRNG_S] = &hclk_trng_s,
|
|
[PCLK_OTPC_S] = &plk_otpc_s,
|
|
[CLK_OTPC_S] = &clk_otpc_s,
|
|
[PCLK_WDT_S] = &pclk_wdt_s,
|
|
[TCLK_WDT_S] = &tclk_wdt_s,
|
|
[PCLK_HDCP0_TRNG] = &pclk_hdcp0_trng,
|
|
[PCLK_HDCP1_TRNG] = &pclk_hdcp1_trng,
|
|
[HCLK_HDCP_KEY0] = &hclk_hdcp_key0,
|
|
[HCLK_HDCP_KEY1] = &hclk_hdcp_key1,
|
|
[PCLK_EDP_S] = &pclk_edp_s,
|
|
[ACLK_KLAD] = &aclk_klad,
|
|
};
|
|
|
|
size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
|
|
{
|
|
return CLK_NR_CLKS;
|
|
}
|
|
|
|
rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused,
|
|
uint32_t clock_id)
|
|
{
|
|
rk_scmi_clock_t *table = NULL;
|
|
|
|
if (clock_id < ARRAY_SIZE(clock_table)) {
|
|
table = clock_table[clock_id];
|
|
if (table == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
if ((table != NULL) && (table->is_security == 0))
|
|
return table;
|
|
else
|
|
return NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void pvtplls_cpub_suspend(void)
|
|
{
|
|
clk_cpub_set_rate(408000000, PLL_SEL_NOR);
|
|
cpub_suspended = true;
|
|
}
|
|
|
|
void pvtplls_cpub_resume(void)
|
|
{
|
|
cpub_suspended = false;
|
|
clk_cpub_set_rate(sys_clk_info.cpub_rate, PLL_SEL_AUTO);
|
|
}
|
|
|
|
void pvtplls_suspend(void)
|
|
{
|
|
clk_cpul_set_rate(408000000, PLL_SEL_NOR);
|
|
clk_cci_set_rate(408000000, PLL_SEL_NOR);
|
|
clk_cpub_set_rate(408000000, PLL_SEL_NOR);
|
|
}
|
|
|
|
void pvtplls_resume(void)
|
|
{
|
|
clk_cpul_set_rate(sys_clk_info.cpul_rate, PLL_SEL_AUTO);
|
|
clk_cci_set_rate(sys_clk_info.cci_rate, PLL_SEL_AUTO);
|
|
clk_cpub_set_rate(sys_clk_info.cpub_rate, PLL_SEL_AUTO);
|
|
}
|
|
|
|
void sys_reset_pvtplls_prepare(void)
|
|
{
|
|
clk_gpu_set_rate(200000000, PLL_SEL_NOR);
|
|
clk_npu_set_rate(200000000, PLL_SEL_NOR);
|
|
clk_cpul_set_rate(408000000, PLL_SEL_NOR);
|
|
clk_cci_set_rate(408000000, PLL_SEL_NOR);
|
|
clk_cpub_set_rate(408000000, PLL_SEL_NOR);
|
|
}
|
|
|
|
int rockchip_opteed_clk_set_rate(uint64_t clk_idx, uint64_t rate)
|
|
{
|
|
rk_scmi_clock_t *table;
|
|
|
|
if (clk_idx > CLK_NR_CLKS) {
|
|
INFO("%s: clk-%ld, %ld not supported\n", __func__, clk_idx, rate);
|
|
return SCMI_INVALID_PARAMETERS;
|
|
}
|
|
|
|
table = rockchip_scmi_get_clock(0, clk_idx);
|
|
if (table != NULL)
|
|
table->clk_ops->set_rate(table, rate);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int rockchip_opteed_clk_get_rate(uint64_t clk_idx, uint64_t *rate)
|
|
{
|
|
rk_scmi_clock_t *table;
|
|
|
|
if (clk_idx > CLK_NR_CLKS) {
|
|
INFO("%s: clk-%ld not supported\n", __func__, clk_idx);
|
|
return SCMI_INVALID_PARAMETERS;
|
|
}
|
|
|
|
table = rockchip_scmi_get_clock(0, clk_idx);
|
|
if (table != NULL)
|
|
*rate = (uint64_t)table->clk_ops->get_rate(table);
|
|
return 0;
|
|
}
|
|
|
|
int rockchip_opteed_clk_enable(uint64_t clk_idx, uint64_t enable)
|
|
{
|
|
rk_scmi_clock_t *table;
|
|
|
|
if (clk_idx > CLK_NR_CLKS) {
|
|
INFO("%s: clk-%ld, %ld not supported\n", __func__, clk_idx, enable);
|
|
return SCMI_INVALID_PARAMETERS;
|
|
}
|
|
|
|
table = rockchip_scmi_get_clock(0, clk_idx);
|
|
if (table != NULL) {
|
|
if (enable != 0) {
|
|
table->clk_ops->set_status(table, enable);
|
|
table->enable_count++;
|
|
} else {
|
|
if (table->enable_count == 0)
|
|
return 0;
|
|
if (--table->enable_count > 0)
|
|
return 0;
|
|
table->clk_ops->set_status(table, enable);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define RK3576_CPUB_OPP_INFO_OFFSET 48
|
|
#define RK3576_CPUL_OPP_INFO_OFFSET 54
|
|
#define RK3576_CCI_OPP_INFO_OFFSET 60
|
|
#define RK3576_NPU_OPP_INFO_OFFSET 66
|
|
#define RK3576_GPU_OPP_INFO_OFFSET 72
|
|
|
|
static void rockchip_init_pvtpll_table(void)
|
|
{
|
|
sys_clk_info.cpul_table = rk3576_cpul_pvtpll_table;
|
|
sys_clk_info.cpul_rate_count = ARRAY_SIZE(rk3576_cpul_pvtpll_table);
|
|
sys_clk_info.cci_table = rk3576_cci_pvtpll_table;
|
|
sys_clk_info.cci_rate_count = ARRAY_SIZE(rk3576_cci_pvtpll_table);
|
|
sys_clk_info.cpub_table = rk3576_cpub_pvtpll_table;
|
|
sys_clk_info.cpub_rate_count = ARRAY_SIZE(rk3576_cpub_pvtpll_table);
|
|
sys_clk_info.gpu_table = rk3576_gpu_pvtpll_table;
|
|
sys_clk_info.gpu_rate_count = ARRAY_SIZE(rk3576_gpu_pvtpll_table);
|
|
sys_clk_info.npu_table = rk3576_npu_pvtpll_table;
|
|
sys_clk_info.npu_rate_count = ARRAY_SIZE(rk3576_npu_pvtpll_table);
|
|
}
|
|
|
|
void rockchip_clock_init(void)
|
|
{
|
|
rockchip_init_pvtpll_table();
|
|
}
|
|
|
|
static int pvtpll_get_clk(uint64_t clock_id, struct pvtpll_table **table,
|
|
unsigned int *count)
|
|
{
|
|
switch (clock_id) {
|
|
case ARMCLK_L:
|
|
*table = sys_clk_info.cpul_table;
|
|
*count = sys_clk_info.cpul_rate_count;
|
|
break;
|
|
case ARMCLK_B:
|
|
*table = sys_clk_info.cpub_table;
|
|
*count = sys_clk_info.cpub_rate_count;
|
|
break;
|
|
case CLK_GPU:
|
|
*table = sys_clk_info.gpu_table;
|
|
*count = sys_clk_info.gpu_rate_count;
|
|
break;
|
|
case CLK_RKNN_DSU0:
|
|
*table = sys_clk_info.npu_table;
|
|
*count = sys_clk_info.npu_rate_count;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
if ((*table == NULL) || (*count == 0))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int pvtpll_volt_sel_adjust(uint64_t clock_id, uint64_t volt_sel)
|
|
{
|
|
struct pvtpll_table *table = NULL;
|
|
uint32_t delta_len = 0;
|
|
unsigned int count = 0;
|
|
int i;
|
|
|
|
if (pvtpll_get_clk(clock_id, &table, &count) != 0)
|
|
return -1;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (table[i].volt_sel_thr == 0)
|
|
continue;
|
|
if (volt_sel >= table[i].volt_sel_thr) {
|
|
delta_len = volt_sel - table[i].volt_sel_thr + 1;
|
|
table[i].length += delta_len;
|
|
if (table[i].length > RK3576_PVTPLL_MAX_LENGTH)
|
|
table[i].length = RK3576_PVTPLL_MAX_LENGTH;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|