summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra114
diff options
context:
space:
mode:
authorTom Warren <twarren@nvidia.com>2015-06-25 16:50:44 (GMT)
committerTom Warren <twarren@nvidia.com>2015-08-05 22:22:51 (GMT)
commit722e000ccd7226c5cd071590b5361620eb0b126c (patch)
tree257ddcaf4039dd6722e743e8a1f4035c2f85387f /arch/arm/mach-tegra/tegra114
parent3e8650c0f9cc7fb29bd75c11d0173768fcc80203 (diff)
downloadu-boot-722e000ccd7226c5cd071590b5361620eb0b126c.tar.xz
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>
Diffstat (limited to 'arch/arm/mach-tegra/tegra114')
-rw-r--r--arch/arm/mach-tegra/tegra114/clock.c57
-rw-r--r--arch/arm/mach-tegra/tegra114/cpu.c39
2 files changed, 57 insertions, 39 deletions
diff --git a/arch/arm/mach-tegra/tegra114/clock.c b/arch/arm/mach-tegra/tegra114/clock.c
index d5194e1..f1831d3 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 <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 */
@@ -435,6 +426,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] = {
+ /*
+ * 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
* to the old T20 freqs. Support for the higher oscillators is TBD.
@@ -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 18dc1af..272a2ea 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 <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 */