summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/nvidia/tegra132/Kconfig4
-rw-r--r--src/soc/nvidia/tegra132/clock.c41
-rw-r--r--src/soc/nvidia/tegra132/clst_clk.h61
-rw-r--r--src/soc/nvidia/tegra132/include/soc/addressmap.h3
-rw-r--r--src/soc/nvidia/tegra132/include/soc/clock.h2
-rw-r--r--src/soc/nvidia/tegra132/ramstage.c3
6 files changed, 112 insertions, 2 deletions
diff --git a/src/soc/nvidia/tegra132/Kconfig b/src/soc/nvidia/tegra132/Kconfig
index 638fb65729..b746037f78 100644
--- a/src/soc/nvidia/tegra132/Kconfig
+++ b/src/soc/nvidia/tegra132/Kconfig
@@ -113,4 +113,8 @@ config BOOTROM_SDRAM_INIT
help
Use during Ryu LPDDR3 bringup
+# Default to 700MHz. This value is based on nv bootloader setting.
+config PLLX_KHZ
+ int
+ default 700000
endif
diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c
index a8cabe5d82..fb8e85feee 100644
--- a/src/soc/nvidia/tegra132/clock.c
+++ b/src/soc/nvidia/tegra132/clock.c
@@ -22,12 +22,14 @@
#include <stdlib.h>
#include <arch/clock.h>
#include "clk_rst.h"
+#include "clst_clk.h"
#include "flow.h"
#include "maincpu.h"
#include "pmc.h"
#include "sysctr.h"
static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
+static struct clst_clk_ctlr *clst_clk = (void *)TEGRA_CLUSTER_CLOCK_BASE;
static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE;
static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE;
static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE;
@@ -474,6 +476,45 @@ void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
udelay(IO_STABILIZATION_DELAY);
}
+void clock_cpu0_config(void)
+{
+ u32 reg;
+ u32 osc = clock_get_osc_bits();
+ u32 timeout = 0;
+
+ /* disable IDDQ */
+ reg = readl(&clst_clk->pllx_misc3);
+ reg &= ~PLLX_IDDQ;
+ writel(reg, &clst_clk->pllx_misc3);
+
+ /* init pllx */
+ init_pll(&clst_clk->pllx_base, &clst_clk->pllx_misc,
+ osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE);
+
+ /*
+ * Change CPU clock source to PLLX_OUT0_LJ
+ * when above pllx programming has taken effect.
+ */
+ do {
+ if (readl(&clst_clk->misc_ctrl) & CLK_SWITCH_MATCH) {
+ write32((CC_CCLK_BRST_POL_PLLX_OUT0_LJ << 28),
+ &clst_clk->cclk_brst_pol);
+ break;
+ }
+
+ /* wait and try again */
+ if (timeout >= CLK_SWITCH_TIMEOUT_US) {
+ printk(BIOS_ERR, "%s: PLLX programming timeout. "
+ "Switching cpu clock has falied.\n",
+ __func__);
+ break;
+ }
+ udelay(10);
+ timeout += 10;
+
+ } while (1);
+}
+
void clock_halt_avp(void)
{
for (;;)
diff --git a/src/soc/nvidia/tegra132/clst_clk.h b/src/soc/nvidia/tegra132/clst_clk.h
new file mode 100644
index 0000000000..151ead6341
--- /dev/null
+++ b/src/soc/nvidia/tegra132/clst_clk.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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/>.
+ */
+
+#ifndef _TEGRA132_CLST_CLK_H_
+#define _TEGRA132_CLST_CLK_H_
+
+/* Cluster Clock (CLUSTER_CLOCKS_PUBLIC_) regs */
+struct __attribute__ ((__packed__)) clst_clk_ctlr {
+ u32 pllx_base; /* _PLLX_BASE, 0x000 */
+ u32 pllx_misc; /* _PLLX_MISC, 0x004 */
+ u32 pllx_misc1; /* _PLLX_MISC_1, 0x008 */
+ u32 pllx_misc2; /* _PLLX_MISC_2, 0x00c */
+ u32 pllx_misc3; /* _PLLX_MISC_3, 0x010 */
+ u32 pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG, 0x014 */
+ u32 pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG, 0x018 */
+ u32 pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS, 0x01c */
+ u32 cclk_brst_pol; /* _CCLK_BURST_POLICY, 0x020 */
+ u32 super_cclk_div; /* _SUPER_CCLK_DIVIDER, 0x024 */
+ u32 _rsv1[10]; /* 0x028-04c */
+ u32 shaper; /* _SHAPER, 0x050 */
+ u32 shaper1; /* _SHAPER_1, 0x054 */
+ u32 _rsv2[80]; /* 0x058-194 */
+ u32 misc_ctrl; /* _MISC_CTRL, 0x198 */
+};
+check_member(clst_clk_ctlr, misc_ctrl, 0x198);
+
+/* CC_CCLK_BRST_POL */
+enum {
+ CC_CCLK_BRST_POL_PLLX_OUT0_LJ = 0x8,
+};
+
+/* CC_SUPER_CCLK_DIVIDER */
+enum {
+ CC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB = 1 << 31
+};
+
+/* PLLX_MISC3 */
+enum {
+ PLLX_IDDQ = 1 << 3,
+};
+
+/* MISC_CTRL */
+enum {
+ CLK_SWITCH_MATCH = 1 << 5,
+};
+
+#define CLK_SWITCH_TIMEOUT_US 1000
+#endif /* _TEGRA132_CLST_CLK_H_ */
diff --git a/src/soc/nvidia/tegra132/include/soc/addressmap.h b/src/soc/nvidia/tegra132/include/soc/addressmap.h
index 52e4d54356..f5f72db7e4 100644
--- a/src/soc/nvidia/tegra132/include/soc/addressmap.h
+++ b/src/soc/nvidia/tegra132/include/soc/addressmap.h
@@ -70,7 +70,8 @@ enum {
TEGRA_FUSE_BASE = TEGRA_APB_MISC_BASE + 0xF800,
TEGRA_MC_BASE = 0x70019000,
TEGRA_EMC_BASE = 0x7001B000,
- TEGRA_CSITE_BASE = 0x70040000,
+ TEGRA_CLUSTER_CLOCK_BASE = 0x70040000,
+ TEGRA_CSITE_BASE = 0x70800000,
TEGRA_SYSCTR0_BASE = 0x700F0000,
TEGRA_USBD_BASE = 0x7D000000,
TEGRA_USB2_BASE = 0x7D004000,
diff --git a/src/soc/nvidia/tegra132/include/soc/clock.h b/src/soc/nvidia/tegra132/include/soc/clock.h
index 6f69fefbc6..5259c18011 100644
--- a/src/soc/nvidia/tegra132/include/soc/clock.h
+++ b/src/soc/nvidia/tegra132/include/soc/clock.h
@@ -285,7 +285,7 @@ void clock_external_output(int clk_id);
void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90,
u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source,
u32 same_freq);
-void clock_cpu0_config_and_reset(void * entry);
+void clock_cpu0_config(void);
void clock_halt_avp(void);
void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x);
void clock_reset_l(u32 l);
diff --git a/src/soc/nvidia/tegra132/ramstage.c b/src/soc/nvidia/tegra132/ramstage.c
index b3b4db2c86..40d80ff8b8 100644
--- a/src/soc/nvidia/tegra132/ramstage.c
+++ b/src/soc/nvidia/tegra132/ramstage.c
@@ -20,10 +20,13 @@
#include <arch/stages.h>
#include <soc/addressmap.h>
#include "mmu_operations.h"
+#include <soc/clock.h>
void arm64_soc_init(void)
{
trustzone_region_init();
tegra132_mmu_init();
+
+ clock_cpu0_config();
}