From 722e000ccd7226c5cd071590b5361620eb0b126c Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 25 Jun 2015 09:50:44 -0700 Subject: 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 Tested-by: Marcel Ziswiler Signed-off-by: Tom Warren --- arch/arm/mach-tegra/tegra114/clock.c | 57 ++++++++++++++++++++++++++---------- arch/arm/mach-tegra/tegra114/cpu.c | 39 ++++++++++-------------- 2 files changed, 57 insertions(+), 39 deletions(-) (limited to 'arch/arm/mach-tegra/tegra114') diff --git a/arch/arm/mach-tegra/tegra114/clock.c b/arch/arm/mach-tegra/tegra114/clock.c index d5194e11b5..f1831d385d 100644 --- a/arch/arm/mach-tegra/tegra114/clock.c +++ b/arch/arm/mach-tegra/tegra114/clock.c @@ -1,17 +1,8 @@ /* - * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * (C) Copyright 2010-2015 + * NVIDIA Corporation * - * 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 . + * 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); } diff --git a/arch/arm/mach-tegra/tegra114/cpu.c b/arch/arm/mach-tegra/tegra114/cpu.c index 18dc1af1b4..272a2ea281 100644 --- a/arch/arm/mach-tegra/tegra114/cpu.c +++ b/arch/arm/mach-tegra/tegra114/cpu.c @@ -1,17 +1,8 @@ /* - * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + * (C) Copyright 2010-2014 + * NVIDIA Corporation * - * 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 . + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -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 */ -- cgit v1.2.1