167 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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);
 |