Tegra: clocks: Add 38.4MHz OSC support for T210 use
Subsystems (5)
PATCH 1/2 Tegra: clocks: Add 38.4MHz OSC support for T210 use
Added 38.4MHz/48MHz entries to pll_x_table for CPU PLL. Needs to be measured - should be close to 700MHz (1.4G/2).
Note that some freqs aren't in the PLLU table in T210 TRM (13, 26MHz), so I used the 12MHz table entry for them. They shouldn't be selected since they're not viable T210 OSC freqs.
Since there are now 2 new OSC defines, all tables (pll_x_table, PLLU) had to increase by two entries, but since 38.4/48MHz are not viable osc freqs on T20/30/114, etc, they're just set to 0.
--- arch/arm/include/asm/arch-tegra/clock.h | 2 ++ arch/arm/mach-tegra/clock.c | 13 +++++++++---- arch/arm/mach-tegra/cpu.c | 12 ++++++++++++ arch/arm/mach-tegra/tegra210/clock.c | 8 ++++++-- drivers/usb/host/ehci-tegra.c | 18 +++++++++++++----- 5 files changed, 42 insertions(+), 11 deletions(-)
arch/arm/include/asm/arch-tegra/clock.h +2 -0
@@ -16,6 +16,8 @@ enum clock_osc_freq {CLOCK_OSC_FREQ_19_2 ,CLOCK_OSC_FREQ_12_0 ,CLOCK_OSC_FREQ_26_0 , +CLOCK_OSC_FREQ_38_4 , +CLOCK_OSC_FREQ_48_0 , CLOCK_OSC_FREQ_COUNT, };
arch/arm/mach-tegra/clock.c +9 -4
@@ -44,6 +44,8 @@ static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {19200000 ,12000000 ,26000000 , +38400000 , + 48000000, };/* return 1 if a peripheral ID is in range */
@@ -620,17 +622,20 @@ int clock_verify(void)void clock_init (void ) { + pll_rate[CLOCK_ID_CGENERAL ] =clock_get_rate (CLOCK_ID_CGENERAL ); pll_rate[CLOCK_ID_MEMORY ] =clock_get_rate (CLOCK_ID_MEMORY ); pll_rate[CLOCK_ID_PERIPH ] =clock_get_rate (CLOCK_ID_PERIPH ); - pll_rate[CLOCK_ID_CGENERAL ] =clock_get_rate (CLOCK_ID_CGENERAL ); + pll_rate[CLOCK_ID_USB ] =clock_get_rate (CLOCK_ID_USB ); pll_rate[CLOCK_ID_DISPLAY ] =clock_get_rate (CLOCK_ID_DISPLAY ); - pll_rate[CLOCK_ID_OSC ] =clock_get_rate (CLOCK_ID_OSC ); - pll_rate[CLOCK_ID_SFROM32KHZ ] =32768 ; pll_rate[CLOCK_ID_XCPU ] =clock_get_rate (CLOCK_ID_XCPU ); + pll_rate[CLOCK_ID_SFROM32KHZ ] =32768 ; + pll_rate[CLOCK_ID_OSC ] =clock_get_rate (CLOCK_ID_OSC ); +debug ("Osc = %d\n" , pll_rate[CLOCK_ID_OSC ]); +debug ("PLLC = %d\n" , pll_rate[CLOCK_ID_CGENERAL ]);debug ("PLLM = %d\n" , pll_rate[CLOCK_ID_MEMORY ]);debug ("PLLP = %d\n" , pll_rate[CLOCK_ID_PERIPH ]); -debug ("PLLC = %d\n" , pll_rate[CLOCK_ID_CGENERAL ]); +debug ("PLLU = %d\n" , pll_rate[CLOCK_ID_USB ]);debug ("PLLD = %d\n" , pll_rate[CLOCK_ID_DISPLAY ]);debug ("PLLX = %d\n" , pll_rate[CLOCK_ID_XCPU ]); }
arch/arm/mach-tegra/cpu.c +12 -0
@@ -67,6 +67,8 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 625, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ { .n = 1000, .m = 12, .p = 0, .cpcon = 12 }, /* OSC: 12.0 MHz */ { .n = 1000, .m = 26, .p = 0, .cpcon = 12 }, /* OSC: 26.0 MHz */ + { .n = 0, .m = 0, .p = 0, .cpcon = 0 }, /* OSC: 38.4 MHz (N/A) */ + { .n = 0, .m = 0, .p = 0, .cpcon = 0 }, /* OSC: 48.0 MHz (N/A) */ },/* * T25: 1.2 GHz
@@ -83,6 +85,8 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 750, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ { .n = 600, .m = 6, .p = 0, .cpcon = 12 }, /* OSC: 12.0 MHz */ { .n = 600, .m = 13, .p = 0, .cpcon = 12 }, /* OSC: 26.0 MHz */ + { .n = 0, .m = 0, .p = 0, .cpcon = 0 }, /* OSC: 38.4 MHz (N/A) */ + { .n = 0, .m = 0, .p = 0, .cpcon = 0 }, /* OSC: 48.0 MHz (N/A) */ },/* * T30: 600 MHz
@@ -99,6 +103,8 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 500, .m = 16, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ { .n = 600, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 12.0 MHz */ { .n = 600, .m = 26, .p = 0, .cpcon = 8 }, /* OSC: 26.0 MHz */ + { .n = 0, .m = 0, .p = 0, .cpcon = 0 }, /* OSC: 38.4 MHz (N/A) */ + { .n = 0, .m = 0, .p = 0, .cpcon = 0 }, /* OSC: 48.0 MHz (N/A) */ },/* * T114: 700 MHz
@@ -114,6 +120,8 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ + { .n = 0, .m = 0, .p = 0 }, /* OSC: 38.4 MHz (N/A) */ + { .n = 0, .m = 0, .p = 0 }, /* OSC: 48.0 MHz (N/A) */ },/*
@@ -130,6 +138,8 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ + { .n = 0, .m = 0, .p = 0 }, /* OSC: 38.4 MHz (N/A) */ + { .n = 0, .m = 0, .p = 0 }, /* OSC: 48.0 MHz (N/A) */ },/*
@@ -146,6 +156,8 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz = 700.8 MHz*/ { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz = 696 MHz*/ { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz = 702 MHz*/ + { .n = 36, .m = 1, .p = 1 }, /* OSC: 38.4 MHz = 691.2 MHz */ + { .n = 58, .m = 2, .p = 1 }, /* OSC: 48.0 MHz = 696 MHz */ }, };
arch/arm/mach-tegra/tegra210/clock.c +6 -2
@@ -649,8 +649,8 @@ enum clock_osc_freq clock_get_osc_freq(void)*/ if (reg ==5 ) {debug ("OSC_FREQ is 38.4MHz (%d) ...\n" , reg); -/* Map it to 19.2MHz for now. 38.4MHz OSC support TBD */ -return 1 ; +/* Map it to the 5th CLOCK_OSC_ enum, i.e. 4 */ +return 4 ; }/*
@@ -930,6 +930,10 @@ void clock_early_init(void)clock_set_rate (CLOCK_ID_CGENERAL ,125 ,4 ,0 ,0 );clock_set_rate (CLOCK_ID_DISPLAY ,96 ,2 ,0 ,12 );break ; +case CLOCK_OSC_FREQ_38_4 : +clock_set_rate (CLOCK_ID_CGENERAL ,125 ,8 ,0 ,0 ); +clock_set_rate (CLOCK_ID_DISPLAY ,96 ,4 ,0 ,0 ); +break ;default :/* * These are not supported. It is too early to print a
drivers/usb/host/ehci-tegra.c +13 -5
@@ -131,7 +131,9 @@ static const unsigned T20_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } + { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 }, + { 0x000, 0x00, 0x00, 0x0, 0, 0x00, 0x00, 0x00, 0x00, 0x0000, 0 }, + { 0x000, 0x00, 0x00, 0x0, 0, 0x00, 0x00, 0x00, 0x00, 0x0000, 0 } }; static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = {
@@ -139,7 +141,9 @@ static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { { 0x3C0, 0x0D, 0x00, 0xC, 1, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 5 }, { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 7 }, { 0x3C0, 0x0C, 0x00, 0xC, 1, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 1, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } + { 0x3C0, 0x1A, 0x00, 0xC, 1, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 }, + { 0x000, 0x00, 0x00, 0x0, 0, 0x00, 0x00, 0x00, 0x00, 0x0000, 0 }, + { 0x000, 0x00, 0x00, 0x0, 0, 0x00, 0x00, 0x00, 0x00, 0x0000, 0 } }; static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = {
@@ -147,16 +151,20 @@ static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { { 0x3C0, 0x0D, 0x00, 0xC, 2, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 6 }, { 0x0C8, 0x04, 0x00, 0x3, 2, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 8 }, { 0x3C0, 0x0C, 0x00, 0xC, 2, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 2, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 0xB } + { 0x3C0, 0x1A, 0x00, 0xC, 2, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 11 }, + { 0x000, 0x00, 0x00, 0x0, 0, 0x00, 0x00, 0x00, 0x00, 0x0000, 0 }, + { 0x000, 0x00, 0x00, 0x0, 0, 0x00, 0x00, 0x00, 0x00, 0x0000, 0 } };/* NOTE: 13/26MHz settings are N/A for T210, so dupe 12MHz settings for now */ static const unsigned T210_usb_pll[CLOCK_OSC_FREQ_COUNT ][PARAM_COUNT ] = {/* DivN, DivM, DivP, KCP, KVCO, Delays Debounce, Bias */ - {0x028 ,0x01 ,0x01 ,0x0 ,0 ,0x02 ,0x2F ,0x08 ,0x76 ,30000 ,5 }, + {0x028 ,0x01 ,0x01 ,0x0 ,0 ,0x02 ,0x2F ,0x08 ,0x76 ,32500 ,5 }, {0x019 ,0x01 ,0x01 ,0x0 ,0 ,0x03 ,0x4B ,0x0C ,0xBB ,48000 ,8 }, {0x028 ,0x01 ,0x01 ,0x0 ,0 ,0x02 ,0x2F ,0x08 ,0x76 ,30000 ,5 }, - {0x028 ,0x01 ,0x01 ,0x0 ,0 ,0x02 ,0x2F ,0x08 ,0x76 ,30000 ,5 }, + {0x028 ,0x01 ,0x01 ,0x0 ,0 ,0x02 ,0x2F ,0x08 ,0x76 ,65000 ,5 }, + {0x019 ,0x02 ,0x01 ,0x0 ,0 ,0x05 ,0x96 ,0x18 ,0x177 ,96000 ,15 }, + {0x028 ,0x04 ,0x01 ,0x0 ,0 ,0x04 ,0x66 ,0x09 ,0xFE ,120000 ,20 } };/* UTMIP Idle Wait Delay */
Signature · 1 line
1.8.2.1.610.g562af5b
PATCH 2/2 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 but needs test.
Corrections to divm mask vs shift and T20/30 divN masks thanks to Marcel Ziswiler.
--- arch/arm/include/asm/arch-tegra/clk_rst.h | 32 +------ arch/arm/include/asm/arch-tegra/clock.h | 21 +++++ arch/arm/include/asm/arch-tegra210/clock-tables.h | 1 + arch/arm/mach-tegra/clock.c | 108 ++++++++-------------- arch/arm/mach-tegra/cpu.c | 18 ++-- arch/arm/mach-tegra/tegra114/clock.c | 57 +++++++++--- arch/arm/mach-tegra/tegra114/cpu.c | 39 +++----- arch/arm/mach-tegra/tegra124/clock.c | 44 ++++++++- arch/arm/mach-tegra/tegra124/cpu.c | 31 +++---- arch/arm/mach-tegra/tegra20/clock.c | 32 +++++++ arch/arm/mach-tegra/tegra210/clock.c | 31 ++++++- arch/arm/mach-tegra/tegra30/clock.c | 45 ++++++--- 12 files changed, 285 insertions(+), 174 deletions(-)
arch/arm/include/asm/arch-tegra/clk_rst.h +3 -29
@@ -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_ */
arch/arm/include/asm/arch-tegra/clock.h +21 -0
@@ -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 *
arch/arm/include/asm/arch-tegra210/clock-tables.h +1 -0
@@ -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,
arch/arm/mach-tegra/clock.c +41 -67
168 lines not on this page · raw message
arch/arm/mach-tegra/cpu.c +12 -6
@@ -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 at 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);
arch/arm/mach-tegra/tegra114/clock.c +42 -15
82 lines not on this page · raw message
arch/arm/mach-tegra/tegra114/cpu.c +15 -24
@@ -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 */
arch/arm/mach-tegra/tegra124/clock.c +40 -4
68 lines not on this page · raw message
arch/arm/mach-tegra/tegra124/cpu.c +15 -16
@@ -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__); }
arch/arm/mach-tegra/tegra20/clock.c +32 -0
@@ -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+ */
@@ -355,6 +357,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { };/* +* 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 =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 =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. */
arch/arm/mach-tegra/tegra210/clock.c +30 -1
@@ -631,6 +631,34 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { };/* +* 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 * to the old T20 freqs. Support for the higher oscillators is TBD.
@@ -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 ); }
arch/arm/mach-tegra/tegra30/clock.c +33 -12
56 lines not on this page · raw message
Signature · 1 line
1.8.2.1.610.g562af5b
PATCH 2/2 Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.
Quoted 10 lines · Tom Warren
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 but needs test.
Corrections to divm mask vs shift and T20/30 divN masks thanks to Marcel Ziswiler.
Signed-off-by Tom Warren <[email protected]>
While this boots on Colibri T20/T30 as well as Apalis T30 there is still something askew on T20 as e.g. USB Ethernet is more than 6 times slower than before. T30 on the other hand seems to work fine. I will try to find some time to investigate further.
PATCH 2/2 Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.
Marcel,
Quoted 19 lines
-----Original Message-----
From: Marcel Ziswiler [mailto:marcel at ziswiler.com]
Sent: Tuesday, August 04, 2015 1:33 AM
To: Tom Warren; u-boot at lists.denx.de
Cc: tomcwarren3959 at gmail.com; Stephen Warren; Thierry Reding; sjg at chromium.org
Subject: Re: [PATCH 2/2] Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.Quoted 9 lines · Tom Warren
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 but needs test.
Corrections to divm mask vs shift and T20/30 divN masks thanks to Marcel Ziswiler.
Quoted 6 lines
Quoted 1 line
Signed-off-by Tom Warren <[email protected]>While this boots on Colibri T20/T30 as well as Apalis T30 there is still something askew on T20 as e.g. USB Ethernet is more than 6 times slower than before. T30 on the other hand seems to work fine. I will try to find some time to investigate further.
Thanks. My T20/T30 boards are moth-balled, so I don't test on them. T210 USB is fine. If you can provide CAR register dumps (0x60006000 - 0x60006FFF) on T20 I can take a look.
Appreciate any testing you can do. This won't go in to u-boot-tegra until you are satisified.
Tom
--
nvpublic
PATCH 2/2 Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.
Quoted 4 lines · Tom Warren
Thanks. My T20/T30 boards are moth-balled, so I don't test on them. T210 USB is fine.
If you can provide CAR register dumps (0x60006000-0x60006FFF) on T20 I can take a look.
I had a look at it. Looks like you missed the cpcon stuff for PLLX both on T20 as well as T30 but while the former's PLLX won't even lock any more the later seems to still lock OK. Nonetheless I will send a patch to fix this for both shortly.
Quoted 2 lines
Appreciate any testing you can do. This won't go in to u-boot-tegra until you are satisified.
Your patience with us remaining T20/T30 users is highly appreciated as we still hope to be selling those Colibris for another 10 resp. 13 years!
PATCH 2/2 Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.
In reply to Tom WarrenHi,
Quoted 10 lines · Tom Warren
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 but needs test.
Corrections to divm mask vs shift and T20/30 divN masks thanks to Marcel Ziswiler.
Signed-off-by Tom Warren <[email protected]>
Quoted 14 lines
--- arch/arm/include/asm/arch-tegra/clk_rst.h | 32 +------ arch/arm/include/asm/arch-tegra/clock.h | 21 +++++ arch/arm/include/asm/arch-tegra210/clock-tables.h | 1 + arch/arm/mach-tegra/clock.c | 108 ++++++++-------------- arch/arm/mach-tegra/cpu.c | 18 ++-- arch/arm/mach-tegra/tegra114/clock.c | 57 +++++++++--- arch/arm/mach-tegra/tegra114/cpu.c | 39 +++----- arch/arm/mach-tegra/tegra124/clock.c | 44 ++++++++- arch/arm/mach-tegra/tegra124/cpu.c | 31 +++---- arch/arm/mach-tegra/tegra20/clock.c | 32 +++++++ arch/arm/mach-tegra/tegra210/clock.c | 31 ++++++- arch/arm/mach-tegra/tegra30/clock.c | 45 ++++++--- 12 files changed, 285 insertions(+), 174 deletions(-)
This breaks the display on Nyan.
I think I found two problems - I'll send out a patch.
Regards,
Simon
PATCH 1/2 Tegra: clocks: Add 38.4MHz OSC support for T210 use
In reply to Tom WarrenQuoted 10 lines · Tom Warren
Added 38.4MHz/48MHz entries to
pll_x_tablefor CPU PLL. Needs to be measured - should be close to 700MHz (1.4G/2).Note that some freqs aren't in the PLLU table in T210 TRM (13, 26MHz), so I used the 12MHz table entry for them. They shouldn't be selected since they're not viable T210 OSC freqs.
Since there are now 2 new OSC defines, all tables (
pll_x_table, PLLU) had to increase by two entries, but since 38.4/48MHz are not viable osc freqs on T20/30/114, etc, they're just set to 0.
I didn't look at all of the numbers in detail, but these patches look like a step in the right direction, so the series,
(tested upstream this time)