Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.
Added PLL variables (dividers mask/shift, lock enable/detect, etc.) to new pllinfo struct for each Soc/PLL. PLLA/C/D/E/M/P/U/X. Used pllinfo struct in all clock functions, validated on T210. Should be equivalent to prior code on T124/114/30/20. Thanks to Marcel Ziswiler for corrections to the T20/T30 values. Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com> Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com> Signed-off-by: Tom Warren <twarren@nvidia.com>
This commit is contained in:
		
							parent
							
								
									3e8650c0f9
								
							
						
					
					
						commit
						722e000ccd
					
				|  | @ -249,17 +249,6 @@ struct clk_rst_ctlr { | |||
| #define PLL_LOCK_SHIFT		27 | ||||
| #define PLL_LOCK_MASK		(1U << PLL_LOCK_SHIFT) | ||||
| 
 | ||||
| #define PLL_DIVP_SHIFT		20 | ||||
| #define PLL_DIVP_MASK		(7U << PLL_DIVP_SHIFT) | ||||
| /* Special case for T210 PLLU DIVP */ | ||||
| #define PLLU_DIVP_SHIFT		16 | ||||
| 
 | ||||
| #define PLL_DIVN_SHIFT		8 | ||||
| #define PLL_DIVN_MASK		(0x3ffU << PLL_DIVN_SHIFT) | ||||
| 
 | ||||
| #define PLL_DIVM_SHIFT		0 | ||||
| #define PLL_DIVM_MASK		(0x1f << PLL_DIVM_SHIFT) | ||||
| 
 | ||||
| /* CLK_RST_CONTROLLER_PLLx_OUTx_0 */ | ||||
| #define PLL_OUT_RSTN		(1 << 0) | ||||
| #define PLL_OUT_CLKEN		(1 << 1) | ||||
|  | @ -272,24 +261,6 @@ struct clk_rst_ctlr { | |||
| #define PLL_DCCON_SHIFT		20 | ||||
| #define PLL_DCCON_MASK		(1U << PLL_DCCON_SHIFT) | ||||
| 
 | ||||
| #define PLL_LOCK_ENABLE_SHIFT	18 | ||||
| #define PLL_LOCK_ENABLE_MASK	(1U << PLL_LOCK_ENABLE_SHIFT) | ||||
| 
 | ||||
| #define PLL_CPCON_SHIFT		8 | ||||
| #define PLL_CPCON_MASK		(15U << PLL_CPCON_SHIFT) | ||||
| 
 | ||||
| #define PLL_LFCON_SHIFT		4 | ||||
| #define PLL_LFCON_MASK		(15U << PLL_LFCON_SHIFT) | ||||
| 
 | ||||
| /* CPCON/LFCON replaced by KCP/KVCO in T210 PLLU */ | ||||
| #define PLLU_KVCO_SHIFT		24 | ||||
| #define PLLU_KVCO_MASK		(3U << PLLU_KVCO_SHIFT) | ||||
| #define PLLU_KCP_SHIFT		25 | ||||
| #define PLLU_KCP_MASK		(1U << PLLU_KCP_SHIFT) | ||||
| 
 | ||||
| #define PLLU_VCO_FREQ_SHIFT	20 | ||||
| #define PLLU_VCO_FREQ_MASK	(1U << PLLU_VCO_FREQ_SHIFT) | ||||
| 
 | ||||
| #define PLLP_OUT1_OVR		(1 << 2) | ||||
| #define PLLP_OUT2_OVR		(1 << 18) | ||||
| #define PLLP_OUT3_OVR		(1 << 2) | ||||
|  | @ -475,4 +446,7 @@ enum { | |||
| #define PLLDP_SS_CFG_UNDOCUMENTED	(1 << 24) | ||||
| #define PLLDP_SS_CFG_DITHER		(1 << 28) | ||||
| 
 | ||||
| /* CLK_RST_PLLD_MISC */ | ||||
| #define PLLD_CLKENABLE			30 | ||||
| 
 | ||||
| #endif	/* _TEGRA_CLK_RST_H_ */ | ||||
|  |  | |||
|  | @ -338,6 +338,27 @@ void arch_timer_init(void); | |||
| 
 | ||||
| void tegra30_set_up_pllp(void); | ||||
| 
 | ||||
| /* Number of PLL-based clocks (i.e. not OSC or 32KHz) */ | ||||
| #define CLOCK_ID_PLL_COUNT	(CLOCK_ID_COUNT - 2) | ||||
| 
 | ||||
| struct clk_pll_info { | ||||
| 	u32	m_shift:5;	/* DIVM_SHIFT */ | ||||
| 	u32	n_shift:5;	/* DIVN_SHIFT */ | ||||
| 	u32	p_shift:5;	/* DIVP_SHIFT */ | ||||
| 	u32	kcp_shift:5;	/* KCP/cpcon SHIFT */ | ||||
| 	u32	kvco_shift:5;	/* KVCO/lfcon SHIFT */ | ||||
| 	u32	lock_ena:6;	/* LOCK_ENABLE/EN_LOCKDET shift */ | ||||
| 	u32	rsvd:1; | ||||
| 	u32	m_mask:10;	/* DIVM_MASK */ | ||||
| 	u32	n_mask:12;	/* DIVN_MASK */ | ||||
| 	u32	p_mask:10;	/* DIVP_MASK or VCO_MASK */ | ||||
| 	u32	kcp_mask:10;	/* KCP/CPCON MASK */ | ||||
| 	u32	kvco_mask:10;	/* KVCO/LFCON MASK */ | ||||
| 	u32	lock_det:6;	/* LOCK_DETECT/LOCKED shift */ | ||||
| 	u32	rsvd2:6; | ||||
| }; | ||||
| extern struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT]; | ||||
| 
 | ||||
| /**
 | ||||
|  * Enable output clock for external peripherals | ||||
|  * | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ enum clock_id { | |||
| 	CLOCK_ID_XCPU = CLOCK_ID_FIRST_SIMPLE, | ||||
| 	CLOCK_ID_EPCI, | ||||
| 	CLOCK_ID_SFROM32KHZ, | ||||
| 	CLOCK_ID_DP, | ||||
| 
 | ||||
| 	/* These are the base clocks (inputs to the Tegra SoC) */ | ||||
| 	CLOCK_ID_32KHZ, | ||||
|  |  | |||
|  | @ -101,6 +101,7 @@ int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn, | |||
| 		u32 *divp, u32 *cpcon, u32 *lfcon) | ||||
| { | ||||
| 	struct clk_pll *pll = get_pll(clkid); | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid]; | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	assert(clkid != CLOCK_ID_USB); | ||||
|  | @ -109,17 +110,14 @@ int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn, | |||
| 	if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB) | ||||
| 		return -1; | ||||
| 	data = readl(&pll->pll_base); | ||||
| 	*divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; | ||||
| 	*divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT; | ||||
| 	*divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; | ||||
| 	*divm = (data >> pllinfo->m_shift) & pllinfo->m_mask; | ||||
| 	*divn = (data >> pllinfo->n_shift) & pllinfo->n_mask; | ||||
| 	*divp = (data >> pllinfo->p_shift) & pllinfo->p_mask; | ||||
| 	data = readl(&pll->pll_misc); | ||||
| 	*cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT; | ||||
| 	*lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT; | ||||
| #if defined(CONFIG_TEGRA210) | ||||
| 	/* T210 PLLU uses KCP/KVCO instead of CPCON/LFCON */ | ||||
| 	*cpcon = (data & PLLU_KCP_MASK) >> PLLU_KCP_SHIFT; | ||||
| 	*lfcon = (data & PLLU_KVCO_MASK) >> PLLU_KVCO_SHIFT; | ||||
| #endif | ||||
| 	/* NOTE: On T210, cpcon/lfcon no longer exist, moved to KCP/KVCO */ | ||||
| 	*cpcon = (data >> pllinfo->kcp_shift) & pllinfo->kcp_mask; | ||||
| 	*lfcon = (data >> pllinfo->kvco_shift) & pllinfo->kvco_mask; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -127,41 +125,25 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn, | |||
| 		u32 divp, u32 cpcon, u32 lfcon) | ||||
| { | ||||
| 	struct clk_pll *pll = NULL; | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid]; | ||||
| 	u32 misc_data, data; | ||||
| 
 | ||||
| 	if (clkid < (enum clock_id)TEGRA_CLK_PLLS) | ||||
| 		pll = get_pll(clkid); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We cheat by treating all PLL (except PLLU) in the same fashion. | ||||
| 	 * This works only because: | ||||
| 	 * - same fields are always mapped at same offsets, except DCCON | ||||
| 	 * - DCCON is always 0, doesn't conflict | ||||
| 	 * - M,N, P of PLLP values are ignored for PLLP | ||||
| 	 * NOTE: Above is no longer true with T210 - TBD: FIX THIS | ||||
| 	 * pllinfo has the m/n/p and kcp/kvco mask and shift | ||||
| 	 * values for all of the PLLs used in U-Boot, with any | ||||
| 	 * SoC differences accounted for. | ||||
| 	 */ | ||||
| 	misc_data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT); | ||||
| 	misc_data = readl(&pll->pll_misc);	/* preserve EN_LOCKDET, etc. */ | ||||
| 	misc_data &= ~(pllinfo->kcp_mask << pllinfo->kcp_shift) | (cpcon << pllinfo->kcp_shift); | ||||
| 	misc_data &= ~(pllinfo->kvco_mask << pllinfo->kvco_shift) | (lfcon << pllinfo->kvco_shift); | ||||
| 
 | ||||
| #if defined(CONFIG_TEGRA210) | ||||
| 	/* T210 PLLU uses KCP/KVCO instead of cpcon/lfcon */ | ||||
| 	if (clkid == CLOCK_ID_USB) { | ||||
| 		/* preserve EN_LOCKDET, set by default */ | ||||
| 		misc_data = readl(&pll->pll_misc); | ||||
| 		misc_data |= (cpcon << PLLU_KCP_SHIFT) | | ||||
| 			(lfcon << PLLU_KVCO_SHIFT); | ||||
| 	} | ||||
| #endif | ||||
| 	data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) | | ||||
| 			(0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT); | ||||
| 	data = (divm << pllinfo->m_shift) | (divn << pllinfo->n_shift); | ||||
| 	data |= divp << pllinfo->p_shift; | ||||
| 	data |= (1 << PLL_ENABLE_SHIFT);	/* BYPASS s/b 0 already */ | ||||
| 
 | ||||
| 	if (clkid == CLOCK_ID_USB) | ||||
| #if defined(CONFIG_TEGRA210) | ||||
| 		data |= divp << PLLU_DIVP_SHIFT; | ||||
| #else | ||||
| 		data |= divp << PLLU_VCO_FREQ_SHIFT; | ||||
| #endif | ||||
| 	else | ||||
| 		data |= divp << PLL_DIVP_SHIFT; | ||||
| 	if (pll) { | ||||
| 		writel(misc_data, &pll->pll_misc); | ||||
| 		writel(data, &pll->pll_base); | ||||
|  | @ -473,10 +455,9 @@ void reset_cmplx_set_enable(int cpu, int which, int reset) | |||
| unsigned clock_get_rate(enum clock_id clkid) | ||||
| { | ||||
| 	struct clk_pll *pll; | ||||
| 	u32 base; | ||||
| 	u32 divm; | ||||
| 	u64 parent_rate; | ||||
| 	u64 rate; | ||||
| 	u32 base, divm; | ||||
| 	u64 parent_rate, rate; | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid]; | ||||
| 
 | ||||
| 	parent_rate = osc_freq[clock_get_osc_freq()]; | ||||
| 	if (clkid == CLOCK_ID_OSC) | ||||
|  | @ -487,13 +468,13 @@ unsigned clock_get_rate(enum clock_id clkid) | |||
| 		return 0; | ||||
| 	base = readl(&pll->pll_base); | ||||
| 
 | ||||
| 	/* Oh for bf_unpack()... */ | ||||
| 	rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT); | ||||
| 	divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; | ||||
| 	if (clkid == CLOCK_ID_USB) | ||||
| 		divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT; | ||||
| 	else | ||||
| 		divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; | ||||
| 	rate = parent_rate * ((base >> pllinfo->n_shift) & pllinfo->n_mask); | ||||
| 	divm = (base >> pllinfo->m_shift) & pllinfo->m_mask; | ||||
| 	/*
 | ||||
| 	 * PLLU uses p_mask/p_shift for VCO on all but T210, | ||||
| 	 * T210 uses normal DIVP. Handled in pllinfo table. | ||||
| 	 */ | ||||
| 	divm <<= (base >> pllinfo->p_shift) & pllinfo->p_mask; | ||||
| 	do_div(rate, divm); | ||||
| 	return rate; | ||||
| } | ||||
|  | @ -517,23 +498,23 @@ unsigned clock_get_rate(enum clock_id clkid) | |||
|  */ | ||||
| int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) | ||||
| { | ||||
| 	u32 base_reg; | ||||
| 	u32 misc_reg; | ||||
| 	u32 base_reg, misc_reg; | ||||
| 	struct clk_pll *pll; | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid]; | ||||
| 
 | ||||
| 	pll = get_pll(clkid); | ||||
| 
 | ||||
| 	base_reg = readl(&pll->pll_base); | ||||
| 
 | ||||
| 	/* Set BYPASS, m, n and p to PLL_BASE */ | ||||
| 	base_reg &= ~PLL_DIVM_MASK; | ||||
| 	base_reg |= m << PLL_DIVM_SHIFT; | ||||
| 	base_reg &= ~(pllinfo->m_mask << pllinfo->m_shift); | ||||
| 	base_reg |= m << pllinfo->m_shift; | ||||
| 
 | ||||
| 	base_reg &= ~PLL_DIVN_MASK; | ||||
| 	base_reg |= n << PLL_DIVN_SHIFT; | ||||
| 	base_reg &= ~(pllinfo->n_mask << pllinfo->n_shift); | ||||
| 	base_reg |= n << pllinfo->n_shift; | ||||
| 
 | ||||
| 	base_reg &= ~PLL_DIVP_MASK; | ||||
| 	base_reg |= p << PLL_DIVP_SHIFT; | ||||
| 	base_reg &= ~(pllinfo->p_mask << pllinfo->p_shift); | ||||
| 	base_reg |= p << pllinfo->p_shift; | ||||
| 
 | ||||
| 	if (clkid == CLOCK_ID_PERIPH) { | ||||
| 		/*
 | ||||
|  | @ -552,17 +533,10 @@ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) | |||
| 	base_reg |= PLL_BYPASS_MASK; | ||||
| 	writel(base_reg, &pll->pll_base); | ||||
| 
 | ||||
| 	/* Set cpcon to PLL_MISC */ | ||||
| 	/* Set cpcon (KCP) to PLL_MISC */ | ||||
| 	misc_reg = readl(&pll->pll_misc); | ||||
| #if !defined(CONFIG_TEGRA210) | ||||
| 	misc_reg &= ~PLL_CPCON_MASK; | ||||
| 	misc_reg |= cpcon << PLL_CPCON_SHIFT; | ||||
| #else | ||||
| 	/* T210 uses KCP instead, use the most common bit shift (PLLA/U/D2) */ | ||||
| 	misc_reg &= ~PLLU_KCP_MASK; | ||||
| 	misc_reg |= cpcon << PLLU_KCP_SHIFT; | ||||
| #endif | ||||
| 
 | ||||
| 	misc_reg &= ~(pllinfo->kcp_mask << pllinfo->kcp_shift); | ||||
| 	misc_reg |= cpcon << pllinfo->kcp_shift; | ||||
| 	writel(misc_reg, &pll->pll_misc); | ||||
| 
 | ||||
| 	/* Enable PLL */ | ||||
|  |  | |||
|  | @ -181,6 +181,7 @@ static inline void pllx_set_iddq(void) | |||
| int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, | ||||
| 		u32 divp, u32 cpcon) | ||||
| { | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU]; | ||||
| 	int chip = tegra_get_chip(); | ||||
| 	u32 reg; | ||||
| 	debug("%s entry\n", __func__); | ||||
|  | @ -194,17 +195,21 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, | |||
| 	pllx_set_iddq(); | ||||
| 
 | ||||
| 	/* Set BYPASS, m, n and p to PLLX_BASE */ | ||||
| 	reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT); | ||||
| 	reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT)); | ||||
| 	reg = PLL_BYPASS_MASK | (divm << pllinfo->m_shift); | ||||
| 	reg |= (divn << pllinfo->n_shift) | (divp << pllinfo->p_shift); | ||||
| 	writel(reg, &pll->pll_base); | ||||
| 
 | ||||
| 	/* Set cpcon to PLLX_MISC */ | ||||
| 	if (chip == CHIPID_TEGRA20 || chip == CHIPID_TEGRA30) | ||||
| 		reg = (cpcon << PLL_CPCON_SHIFT); | ||||
| 		reg = (cpcon << pllinfo->kcp_shift); | ||||
| 	else | ||||
| 		reg = 0; | ||||
| 
 | ||||
| 	/* Set dccon to PLLX_MISC if freq > 600MHz */ | ||||
| 	/*
 | ||||
| 	 * TODO(twarren@nvidia.com) Check which SoCs use DCCON | ||||
| 	 * and add to pllinfo table if needed! | ||||
| 	 */ | ||||
| 	 /* Set dccon to PLLX_MISC if freq > 600MHz */ | ||||
| 	if (divn > 600) | ||||
| 		reg |= (1 << PLL_DCCON_SHIFT); | ||||
| 	writel(reg, &pll->pll_misc); | ||||
|  | @ -215,9 +220,10 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, | |||
| 	writel(reg, &pll->pll_base); | ||||
| 	debug("%s: base = 0x%08X\n", __func__, reg); | ||||
| 
 | ||||
| 	/* Set lock_enable to PLLX_MISC */ | ||||
| 	/* Set lock_enable to PLLX_MISC if lock_ena is valid (i.e. 0-31) */ | ||||
| 	reg = readl(&pll->pll_misc); | ||||
| 	reg |= PLL_LOCK_ENABLE_MASK; | ||||
| 	if (pllinfo->lock_ena < 32) | ||||
| 		reg |= (1 << pllinfo->lock_ena); | ||||
| 	writel(reg, &pll->pll_misc); | ||||
| 	debug("%s: misc = 0x%08X\n", __func__, reg); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,8 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved. | ||||
|  * (C) Copyright 2010-2015 | ||||
|  * NVIDIA Corporation <www.nvidia.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU General Public License, | ||||
|  * version 2, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * SPDX-License-Identifier:     GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| /* Tegra114 Clock control functions */ | ||||
|  | @ -434,6 +425,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { | |||
| 	NONE(EMC1), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * PLL divider shift/mask tables for all PLL IDs. | ||||
|  */ | ||||
| struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = { | ||||
| 	/*
 | ||||
| 	 * T114: some deviations from T2x/T30. | ||||
| 	 * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.) | ||||
| 	 *       If lock_ena or lock_det are >31, they're not used in that PLL. | ||||
| 	 */ | ||||
| 
 | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },	/* PLLC */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLM */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLP */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLA */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLU */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLD */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },	/* PLLX */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLE */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLS (RESERVED) */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Get the oscillator frequency, from the corresponding hardware configuration | ||||
|  * field. Note that T30/T114 support 3 new higher freqs, but we map back | ||||
|  | @ -603,6 +624,8 @@ void clock_early_init(void) | |||
| { | ||||
| 	struct clk_rst_ctlr *clkrst = | ||||
| 		(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	struct clk_pll_info *pllinfo; | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	tegra30_set_up_pllp(); | ||||
| 
 | ||||
|  | @ -639,11 +662,15 @@ void clock_early_init(void) | |||
| 	writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]); | ||||
| 
 | ||||
| 	/* PLLC_MISC: Set LOCK_ENABLE */ | ||||
| 	writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc); | ||||
| 	pllinfo = &tegra_pll_info_table[CLOCK_ID_CGENERAL]; | ||||
| 	setbits_le32(&clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc, (1 << pllinfo->lock_ena)); | ||||
| 	udelay(2); | ||||
| 
 | ||||
| 	/* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */ | ||||
| 	writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); | ||||
| 	/* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1, and enable lock */ | ||||
| 	pllinfo = &tegra_pll_info_table[CLOCK_ID_DISPLAY]; | ||||
| 	data = (12 << pllinfo->kcp_shift) | (1 << pllinfo->kvco_shift); | ||||
| 	data |= (1 << PLLD_CLKENABLE) | (1 << pllinfo->lock_ena); | ||||
| 	writel(data, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); | ||||
| 	udelay(2); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,8 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved. | ||||
|  * (C) Copyright 2010-2014 | ||||
|  * NVIDIA Corporation <www.nvidia.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU General Public License, | ||||
|  * version 2, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * SPDX-License-Identifier:     GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| #include <common.h> | ||||
|  | @ -31,7 +22,7 @@ static void enable_cpu_power_rail(void) | |||
| 	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	u32 reg; | ||||
| 
 | ||||
| 	debug("enable_cpu_power_rail entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */ | ||||
| 	pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6); | ||||
|  | @ -61,14 +52,15 @@ static void enable_cpu_power_rail(void) | |||
| static void enable_cpu_clocks(void) | ||||
| { | ||||
| 	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU]; | ||||
| 	u32 reg; | ||||
| 
 | ||||
| 	debug("enable_cpu_clocks entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* Wait for PLL-X to lock */ | ||||
| 	do { | ||||
| 		reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); | ||||
| 	} while ((reg & PLL_LOCK_MASK) == 0); | ||||
| 	} while ((reg & (1 << pllinfo->lock_det)) == 0); | ||||
| 
 | ||||
| 	/* Wait until all clocks are stable */ | ||||
| 	udelay(PLL_STABILIZATION_DELAY); | ||||
|  | @ -87,7 +79,7 @@ static void remove_cpu_resets(void) | |||
| 	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	u32 reg; | ||||
| 
 | ||||
| 	debug("remove_cpu_resets entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 	/* Take the slow non-CPU partition out of reset */ | ||||
| 	reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr); | ||||
| 	writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpulp_cmplx_clr); | ||||
|  | @ -111,7 +103,7 @@ static void remove_cpu_resets(void) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * The T114 requires some special clock initialization, including setting up | ||||
|  * Tegra114 requires some special clock initialization, including setting up | ||||
|  * the DVC I2C, turning on MSELECT and selecting the G CPU cluster | ||||
|  */ | ||||
| void t114_init_clocks(void) | ||||
|  | @ -121,7 +113,7 @@ void t114_init_clocks(void) | |||
| 	struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	debug("t114_init_clocks entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* Set active CPU cluster to G */ | ||||
| 	clrbits_le32(&flow->cluster_control, 1); | ||||
|  | @ -189,7 +181,7 @@ void t114_init_clocks(void) | |||
| 	reset_set_enable(PERIPH_ID_MC1, 0); | ||||
| 	reset_set_enable(PERIPH_ID_DVFS, 0); | ||||
| 
 | ||||
| 	debug("t114_init_clocks exit\n"); | ||||
| 	debug("%s exit\n", __func__); | ||||
| } | ||||
| 
 | ||||
| static bool is_partition_powered(u32 partid) | ||||
|  | @ -238,10 +230,9 @@ static void power_partition(u32 partid) | |||
| 
 | ||||
| void powerup_cpus(void) | ||||
| { | ||||
| 	debug("powerup_cpus entry\n"); | ||||
| 
 | ||||
| 	/* We boot to the fast cluster */ | ||||
| 	debug("powerup_cpus entry: G cluster\n"); | ||||
| 	debug("%s entry: G cluster\n", __func__); | ||||
| 
 | ||||
| 	/* Power up the fast cluster rail partition */ | ||||
| 	power_partition(CRAIL); | ||||
| 
 | ||||
|  | @ -256,7 +247,7 @@ void start_cpu(u32 reset_vector) | |||
| { | ||||
| 	u32 imme, inst; | ||||
| 
 | ||||
| 	debug("start_cpu entry, reset_vector = %x\n", reset_vector); | ||||
| 	debug("%s entry, reset_vector = %x\n", __func__, reset_vector); | ||||
| 
 | ||||
| 	t114_init_clocks(); | ||||
| 
 | ||||
|  | @ -302,7 +293,7 @@ void start_cpu(u32 reset_vector) | |||
| 	inst |= 0xea000000; | ||||
| 	writel(inst, 0x4003fffc); | ||||
| 
 | ||||
| 	/* Write to orignal location for compatibility */ | ||||
| 	/* Write to original location for compatibility */ | ||||
| 	writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); | ||||
| 
 | ||||
| 	/* If the CPU(s) don't already have power, power 'em up */ | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /*
 | ||||
|  * (C) Copyright 2013 | ||||
|  * (C) Copyright 2013-2015 | ||||
|  * NVIDIA Corporation <www.nvidia.com> | ||||
|  * | ||||
|  * SPDX-License-Identifier:     GPL-2.0+ | ||||
|  | @ -565,6 +565,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { | |||
| 	NONE(X_RESERVED31), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * PLL divider shift/mask tables for all PLL IDs. | ||||
|  */ | ||||
| struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = { | ||||
| 	/*
 | ||||
| 	 * T124: same as T114, some deviations from T2x/T30. | ||||
| 	 * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.) | ||||
| 	 *       If lock_ena or lock_det are >31, they're not used in that PLL. | ||||
| 	 */ | ||||
| 
 | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },	/* PLLC */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLM */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLP */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLA */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLU */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLD */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },	/* PLLX */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLE */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLS (RESERVED) */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Get the oscillator frequency, from the corresponding hardware configuration | ||||
|  * field. Note that Tegra30+ support 3 new higher freqs, but we map back | ||||
|  | @ -772,6 +802,8 @@ void clock_early_init(void) | |||
| { | ||||
| 	struct clk_rst_ctlr *clkrst = | ||||
| 		(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	struct clk_pll_info *pllinfo; | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	tegra30_set_up_pllp(); | ||||
| 
 | ||||
|  | @ -808,11 +840,15 @@ void clock_early_init(void) | |||
| 	writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]); | ||||
| 
 | ||||
| 	/* PLLC_MISC: Set LOCK_ENABLE */ | ||||
| 	writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc); | ||||
| 	pllinfo = &tegra_pll_info_table[CLOCK_ID_CGENERAL]; | ||||
| 	setbits_le32(&clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc, (1 << pllinfo->lock_ena)); | ||||
| 	udelay(2); | ||||
| 
 | ||||
| 	/* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */ | ||||
| 	writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); | ||||
| 	/* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1, and enable lock */ | ||||
| 	pllinfo = &tegra_pll_info_table[CLOCK_ID_DISPLAY]; | ||||
| 	data = (12 << pllinfo->kcp_shift) | (1 << pllinfo->kvco_shift); | ||||
| 	data |= (1 << PLLD_CLKENABLE) | (1 << pllinfo->lock_ena); | ||||
| 	writel(data, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); | ||||
| 	udelay(2); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ static void enable_cpu_power_rail(void) | |||
| { | ||||
| 	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; | ||||
| 
 | ||||
| 	debug("enable_cpu_power_rail entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */ | ||||
| 	pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6); | ||||
|  | @ -45,15 +45,16 @@ static void enable_cpu_power_rail(void) | |||
| static void enable_cpu_clocks(void) | ||||
| { | ||||
| 	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU]; | ||||
| 	u32 reg; | ||||
| 
 | ||||
| 	debug("enable_cpu_clocks entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* Wait for PLL-X to lock */ | ||||
| 	do { | ||||
| 		reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); | ||||
| 		debug("%s: PLLX base = 0x%08X\n", __func__, reg); | ||||
| 	} while ((reg & PLL_LOCK_MASK) == 0); | ||||
| 	} while ((reg & (1 << pllinfo->lock_det)) == 0); | ||||
| 
 | ||||
| 	debug("%s: PLLX locked, delay for stable clocks\n", __func__); | ||||
| 	/* Wait until all clocks are stable */ | ||||
|  | @ -83,7 +84,7 @@ static void remove_cpu_resets(void) | |||
| 	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	u32 reg; | ||||
| 
 | ||||
| 	debug("remove_cpu_resets entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* Take the slow and fast partitions out of reset */ | ||||
| 	reg = CLR_NONCPURESET; | ||||
|  | @ -105,7 +106,7 @@ static void remove_cpu_resets(void) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * The Tegra124 requires some special clock initialization, including setting up | ||||
|  * Tegra124 requires some special clock initialization, including setting up | ||||
|  * the DVC I2C, turning on MSELECT and selecting the G CPU cluster | ||||
|  */ | ||||
| void tegra124_init_clocks(void) | ||||
|  | @ -116,7 +117,7 @@ void tegra124_init_clocks(void) | |||
| 			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	debug("tegra124_init_clocks entry\n"); | ||||
| 	debug("%s entry\n", __func__); | ||||
| 
 | ||||
| 	/* Set active CPU cluster to G */ | ||||
| 	clrbits_le32(&flow->cluster_control, 1); | ||||
|  | @ -188,7 +189,7 @@ void tegra124_init_clocks(void) | |||
| 	reset_set_enable(PERIPH_ID_MSELECT, 0); | ||||
| 	reset_set_enable(PERIPH_ID_DVFS, 0); | ||||
| 
 | ||||
| 	debug("tegra124_init_clocks exit\n"); | ||||
| 	debug("%s exit\n", __func__); | ||||
| } | ||||
| 
 | ||||
| static bool is_partition_powered(u32 partid) | ||||
|  | @ -223,31 +224,29 @@ static void power_partition(u32 partid) | |||
| 
 | ||||
| void powerup_cpus(void) | ||||
| { | ||||
| 	debug("powerup_cpus entry\n"); | ||||
| 
 | ||||
| 	/* We boot to the fast cluster */ | ||||
| 	debug("powerup_cpus entry: G cluster\n"); | ||||
| 	debug("%s entry: G cluster\n", __func__); | ||||
| 
 | ||||
| 	/* Power up the fast cluster rail partition */ | ||||
| 	debug("powerup_cpus: CRAIL\n"); | ||||
| 	debug("%s: CRAIL\n", __func__); | ||||
| 	power_partition(CRAIL); | ||||
| 
 | ||||
| 	/* Power up the fast cluster non-CPU partition */ | ||||
| 	debug("powerup_cpus: C0NC\n"); | ||||
| 	debug("%s: C0NC\n", __func__); | ||||
| 	power_partition(C0NC); | ||||
| 
 | ||||
| 	/* Power up the fast cluster CPU0 partition */ | ||||
| 	debug("powerup_cpus: CE0\n"); | ||||
| 	debug("%s: CE0\n", __func__); | ||||
| 	power_partition(CE0); | ||||
| 
 | ||||
| 	debug("powerup_cpus: done\n"); | ||||
| 	debug("%s: done\n", __func__); | ||||
| } | ||||
| 
 | ||||
| void start_cpu(u32 reset_vector) | ||||
| { | ||||
| 	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; | ||||
| 
 | ||||
| 	debug("start_cpu entry, reset_vector = %x\n", reset_vector); | ||||
| 	debug("%s entry, reset_vector = %x\n", __func__, reset_vector); | ||||
| 
 | ||||
| 	tegra124_init_clocks(); | ||||
| 
 | ||||
|  | @ -261,5 +260,5 @@ void start_cpu(u32 reset_vector) | |||
| 	remove_cpu_resets(); | ||||
| 	writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); | ||||
| 	powerup_cpus(); | ||||
| 	debug("start_cpu exit, should continue @ reset_vector\n"); | ||||
| 	debug("%s exit, should continue @ reset_vector\n", __func__); | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2011 The Chromium OS Authors. | ||||
|  * (C) Copyright 2010-2015 | ||||
|  * NVIDIA Corporation <www.nvidia.com> | ||||
|  * | ||||
|  * SPDX-License-Identifier:	GPL-2.0+ | ||||
|  */ | ||||
|  | @ -354,6 +356,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { | |||
| 	NONE(CRAM2), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * PLL divider shift/mask tables for all PLL IDs. | ||||
|  */ | ||||
| struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = { | ||||
| 	/*
 | ||||
| 	 * T20 and T25 | ||||
| 	 * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.) | ||||
| 	 *       If lock_ena or lock_det are >31, they're not used in that PLL. | ||||
| 	 */ | ||||
| 
 | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },	/* PLLC */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLM */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLP */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLA */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLU */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLD */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 0, .kvco_mask = 0 },	/* PLLX */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLE */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 0, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLS */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Get the oscillator frequency, from the corresponding hardware configuration | ||||
|  * field. T20 has 4 frequencies that it supports. | ||||
|  |  | |||
|  | @ -630,6 +630,34 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { | |||
| 	NONE(Y_RESERVED31), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * PLL divider shift/mask tables for all PLL IDs. | ||||
|  */ | ||||
| struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = { | ||||
| 	/*
 | ||||
| 	 * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLC, etc.) | ||||
| 	 *       If lock_ena or lock_det are >31, they're not used in that PLL (PLLC, etc.) | ||||
| 	 */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 10, .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F, | ||||
| 	  .lock_ena = 32,  .lock_det = 27, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },	/* PLLC */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F, | ||||
| 	  .lock_ena = 4,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLM */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 10, .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 0, .kcp_mask = 3, .kvco_shift = 2, .kvco_mask = 1 },	/* PLLP */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F, | ||||
| 	  .lock_ena = 28, .lock_det = 27, .kcp_shift = 25, .kcp_mask = 3, .kvco_shift = 24, .kvco_mask = 1 },	/* PLLA */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 16, .p_mask = 0x1F, | ||||
| 	  .lock_ena = 29, .lock_det = 27, .kcp_shift = 25, .kcp_mask = 3, .kvco_shift = 24, .kvco_mask = 1 },	/* PLLU */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 11, .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 23, .kcp_mask = 3, .kvco_shift = 22, .kvco_mask = 1 },	/* PLLD */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLX */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLE */ | ||||
| 	{ .m_shift = 0, .m_mask = 0, .n_shift = 0, .n_mask = 0, .p_shift = 0, .p_mask = 0, | ||||
| 	  .lock_ena = 0, .lock_det = 0, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },	/* PLLS (gone)*/ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Get the oscillator frequency, from the corresponding hardware configuration | ||||
|  * field. Note that Tegra30+ support 3 new higher freqs, but we map back | ||||
|  | @ -903,6 +931,7 @@ void clock_early_init(void) | |||
| { | ||||
| 	struct clk_rst_ctlr *clkrst = | ||||
| 		(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | ||||
| 	struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_DISPLAY]; | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	tegra210_setup_pllp(); | ||||
|  | @ -957,7 +986,7 @@ void clock_early_init(void) | |||
| 	udelay(2); | ||||
| 
 | ||||
| 	/* PLLD_MISC: Set CLKENABLE and LOCK_DETECT bits */ | ||||
| 	data = (1 << PLLD_ENABLE_CLK) | (1 << PLLD_EN_LCKDET); | ||||
| 	data = (1 << PLLD_ENABLE_CLK) | (1 << pllinfo->lock_ena); | ||||
| 	writel(data, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc); | ||||
| 	udelay(2); | ||||
| } | ||||
|  |  | |||
|  | @ -1,17 +1,8 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved. | ||||
|  * (C) Copyright 2010-2015 | ||||
|  * NVIDIA Corporation <www.nvidia.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU General Public License, | ||||
|  * version 2, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * SPDX-License-Identifier:     GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| /* Tegra30 Clock control functions */ | ||||
|  | @ -414,6 +405,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { | |||
| 	NONE(EX_RESERVED47), | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * PLL divider shift/mask tables for all PLL IDs. | ||||
|  */ | ||||
| struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = { | ||||
| 	/*
 | ||||
| 	 * T30: some deviations from T2x. | ||||
| 	 * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.) | ||||
| 	 *       If lock_ena or lock_det are >31, they're not used in that PLL. | ||||
| 	 */ | ||||
| 
 | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },	/* PLLC */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLM */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLP */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLA */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLU */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLD */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 0, .kvco_mask = 0 },	/* PLLX */ | ||||
| 	{ .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0, | ||||
| 	  .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },	/* PLLE */ | ||||
| 	{ .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07, | ||||
| 	  .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },	/* PLLS (RESERVED) */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Get the oscillator frequency, from the corresponding hardware configuration | ||||
|  * field. Note that T30 supports 3 new higher freqs, but we map back | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue