nt9856x/BSP/linux-kernel/arch/arm/plat-novatek/plat-na51055/pll_preset.c
2023-03-28 15:07:53 +08:00

167 lines
5.0 KiB
C
Executable File

/**
NVT pll preset function
This file will preset PLL value
@file pll_preset.c
@ingroup
@note
Copyright Novatek Microelectronics Corp. 2016. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/clk-provider.h>
#include <plat/nvt-sramctl.h>
#include <plat/top.h>
#include <plat/efuse_protected.h>
static void disable_cnn(void)
{
struct clk* turnoff_clk;
turnoff_clk = clk_get(NULL, "f0d60000.ai");
if (!IS_ERR(turnoff_clk)) {
clk_prepare_enable(turnoff_clk);
clk_disable_unprepare(turnoff_clk);
clk_set_phase(turnoff_clk, 1);
nvt_enable_sram_shutdown(CNN2_SD);
clk_put(turnoff_clk);
} else
pr_err("*** %s Get CNN2 Clock error\n", __func__);
turnoff_clk = clk_get(NULL, "f0cb0000.ai");
if (!IS_ERR(turnoff_clk)) {
clk_prepare_enable(turnoff_clk);
clk_disable_unprepare(turnoff_clk);
nvt_enable_sram_shutdown(CNN_SD);
clk_put(turnoff_clk);
} else
pr_err("*** %s Get CNN Clock error\n", __func__);
turnoff_clk = clk_get(NULL, "f0d50000.ai");
if (!IS_ERR(turnoff_clk)) {
clk_prepare_enable(turnoff_clk);
clk_disable_unprepare(turnoff_clk);
nvt_enable_sram_shutdown(NUE2_SD);
clk_put(turnoff_clk);
} else
pr_err("*** %s Get NUE2 Clock error\n", __func__);
turnoff_clk = clk_get(NULL, "f0c60000.ai");
if (!IS_ERR(turnoff_clk)) {
clk_prepare_enable(turnoff_clk);
clk_disable_unprepare(turnoff_clk);
nvt_enable_sram_shutdown(NUE_SD);
clk_put(turnoff_clk);
} else
pr_err("*** %s Get NUE Clock error\n", __func__);
}
static void check_cpu_freq(void)
{
if (nvt_get_chip_id() == CHIP_NA51084) {
struct clk* pll8_clk;
unsigned long cpu_clk;
pll8_clk = clk_get(NULL, "pll8");
cpu_clk = clk_get_rate(pll8_clk);
cpu_clk *= 8;
//1. cpu_clk > 1.35GHz set as 1.35GHz
if (cpu_clk > (UINT32)1350000000) {
if (efuse_check_available_extend(EFUSE_ABILITY_CPU_PLL_FREQ , 1350000000) == TRUE) {
pr_err("cpu clock exceeds limitation with %ld, reset to 1.35 GHz\n", cpu_clk);
clk_set_rate(pll8_clk, 1350000000 / 8);
} else {
if (efuse_check_available_extend(EFUSE_ABILITY_CPU_PLL_FREQ , 1200000000) == TRUE) {
pr_err("cpu clock exceeds limitation with %ld, reset to 1.2 GHz\n", cpu_clk);
clk_set_rate(pll8_clk, 1200000000 / 8);
} else {
pr_err("cpu clock exceeds limitation with %ld, reset to 1 GHz\n", cpu_clk);
clk_set_rate(pll8_clk, 1000000000 / 8);
}
}
//2. 1.2GHz < cpu_clk <= 1.35GHz (only overclock can usage)
} else if (cpu_clk <= (UINT32)1350000000 && cpu_clk > 1200000000) {
if (efuse_check_available_extend(EFUSE_ABILITY_CPU_PLL_FREQ , cpu_clk) == FALSE) {
if (efuse_check_available_extend(EFUSE_ABILITY_CPU_PLL_FREQ , 1200000000) == TRUE) {
pr_err("cpu clock exceeds limitation with %ld, reset to 1.2 GHz\n", cpu_clk);
clk_set_rate(pll8_clk, 1200000000 / 8);
} else {
pr_err("cpu clock exceeds limitation with %ld, reset to 1 GHz\n", cpu_clk);
clk_set_rate(pll8_clk, 1000000000 / 8);
}
} else {
// over clock > 1.2G is available
//pr_info("over clock > 1.2G OK %ldHz\r\n", cpu_clk);
}
} else if (cpu_clk <= (UINT32)1200000000 && cpu_clk > 1000000000) {
if (efuse_check_available_extend(EFUSE_ABILITY_CPU_PLL_FREQ , cpu_clk) == FALSE) {
pr_err("cpu clock exceeds limitation with %ld, reset to 1 GHz\n", cpu_clk);
clk_set_rate(pll8_clk, 1000000000 / 8);
} else {
// over clock > 1.05G is available
//pr_info("over clock > 1.05G OK %ldHz\r\n", cpu_clk);
}
}
// if (efuse_check_available_extend(EFUSE_ABILITY_CPU_PLL_FREQ , cpu_clk) == FALSE) {
// pr_err("cpu clock exceeds limitation with %ld, reset to 1.05 GHz\n", cpu_clk);
// clk_set_rate(pll8_clk, 1050000000 / 8);
// }
}
}
static int __init nvt_preset_pll(void)
{
struct device_node *node, *pll;
struct clk* pll_clk;
char pll_name[10] = {};
u32 value[3] = {};
node = of_find_node_by_path("/pll_preset@0");
if (node) {
for_each_child_of_node(node, pll) {
if (!of_property_read_u32_array(pll, "pll_config", value, 3)) {
if (value[1]) {
if (value[0] == 24)
snprintf(pll_name, 10, "pllf320");
else
snprintf(pll_name, 10, "pll%d", value[0]);
pll_clk = clk_get(NULL, pll_name);
if (!IS_ERR(pll_clk))
clk_set_rate(pll_clk, value[1]);
else
pr_err("*** %s Get PLL%d Clock error\n", __func__, value[0]);
}
if (value[2]) {
if (value[0] == 24)
snprintf(pll_name, 10, "pllf320");
else
snprintf(pll_name, 10, "pll%d", value[0]);
pll_clk = clk_get(NULL, pll_name);
if (!IS_ERR(pll_clk)) {
if (!__clk_is_enabled(pll_clk))
clk_prepare_enable(pll_clk);
} else
pr_err("*** %s Get PLL%d Clock error\n", __func__, value[0]);
}
}
}
} else
pr_err("*** %s not get dts node ***\n", __func__);
disable_cnn();
check_cpu_freq();
return 0;
}
arch_initcall_sync(nvt_preset_pll);