[U-Boot] [PATCH v4 2/4] Tegra2: Add more clock support
Simon Glass
sjg at chromium.org
Tue Aug 30 18:23:13 CEST 2011
This adds functions to enable/disable clocks and reset to on-chip peripherals.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v2:
- Removed use of bitfield access macros
arch/arm/cpu/armv7/tegra2/Makefile | 2 +-
arch/arm/cpu/armv7/tegra2/ap20.c | 52 ++----
arch/arm/cpu/armv7/tegra2/clock.c | 158 +++++++++++++++++
arch/arm/include/asm/arch-tegra2/clk_rst.h | 112 +++++++-----
arch/arm/include/asm/arch-tegra2/clock.h | 264 ++++++++++++++++++++++++++++
board/nvidia/common/board.c | 79 +++------
6 files changed, 525 insertions(+), 142 deletions(-)
create mode 100644 arch/arm/cpu/armv7/tegra2/clock.c
create mode 100644 arch/arm/include/asm/arch-tegra2/clock.h
diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index f1ea915..b35764c 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
SOBJS := lowlevel_init.o
-COBJS := ap20.o board.o sys_info.o timer.o
+COBJS := ap20.o board.o clock.o sys_info.o timer.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
index 60dd5df..e3832e2 100644
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ b/arch/arm/cpu/armv7/tegra2/ap20.c
@@ -25,6 +25,7 @@
#include <asm/io.h>
#include <asm/arch/tegra2.h>
#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
#include <asm/arch/pmc.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/scu.h>
@@ -35,33 +36,34 @@ u32 s_first_boot = 1;
void init_pllx(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ struct clk_pll *pll = &clkrst->crc_pll[CLOCK_PLL_ID_XCPU];
u32 reg;
/* If PLLX is already enabled, just return */
- reg = readl(&clkrst->crc_pllx_base);
+ reg = readl(&pll->pll_base);
if (reg & PLL_ENABLE)
return;
/* Set PLLX_MISC */
reg = CPCON; /* CPCON[11:8] = 0001 */
- writel(reg, &clkrst->crc_pllx_misc);
+ writel(reg, &pll->pll_misc);
/* Use 12MHz clock here */
- reg = (PLL_BYPASS | PLL_DIVM);
+ reg = (PLL_BYPASS | PLL_DIVM_VALUE);
reg |= (1000 << 8); /* DIVN = 0x3E8 */
- writel(reg, &clkrst->crc_pllx_base);
+ writel(reg, &pll->pll_base);
reg |= PLL_ENABLE;
- writel(reg, &clkrst->crc_pllx_base);
+ writel(reg, &pll->pll_base);
reg &= ~PLL_BYPASS;
- writel(reg, &clkrst->crc_pllx_base);
+ writel(reg, &pll->pll_base);
}
static void enable_cpu_clock(int enable)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
- u32 reg, clk;
+ u32 clk;
/*
* NOTE:
@@ -83,10 +85,6 @@ static void enable_cpu_clock(int enable)
writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
}
- /* Fetch the register containing the main CPU complex clock enable */
- reg = readl(&clkrst->crc_clk_out_enb_l);
- reg |= CLK_ENB_CPU;
-
/*
* Read the register containing the individual CPU clock enables and
* always stop the clock to CPU 1.
@@ -103,7 +101,8 @@ static void enable_cpu_clock(int enable)
}
writel(clk, &clkrst->crc_clk_cpu_cmplx);
- writel(reg, &clkrst->crc_clk_out_enb_l);
+
+ clock_enable(PERIPH_ID_CPU);
}
static int is_cpu_powered(void)
@@ -179,7 +178,7 @@ static void enable_cpu_power_rail(void)
static void reset_A9_cpu(int reset)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
- u32 reg, cpu;
+ u32 cpu;
/*
* NOTE: Regardless of whether the request is to hold the CPU in reset
@@ -193,44 +192,27 @@ static void reset_A9_cpu(int reset)
cpu = SET_DBGRESET1 | SET_DERESET1 | SET_CPURESET1;
writel(cpu, &clkrst->crc_cpu_cmplx_set);
- reg = readl(&clkrst->crc_rst_dev_l);
if (reset) {
/* Now place CPU0 into reset */
cpu |= SET_DBGRESET0 | SET_DERESET0 | SET_CPURESET0;
writel(cpu, &clkrst->crc_cpu_cmplx_set);
-
- /* Enable master CPU reset */
- reg |= SWR_CPU_RST;
} else {
/* Take CPU0 out of reset */
cpu = CLR_DBGRESET0 | CLR_DERESET0 | CLR_CPURESET0;
writel(cpu, &clkrst->crc_cpu_cmplx_clr);
-
- /* Disable master CPU reset */
- reg &= ~SWR_CPU_RST;
}
- writel(reg, &clkrst->crc_rst_dev_l);
+ /* Enable/Disable master CPU reset */
+ reset_set_enable(PERIPH_ID_CPU, reset);
}
static void clock_enable_coresight(int enable)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
- u32 rst, clk, src;
-
- rst = readl(&clkrst->crc_rst_dev_u);
- clk = readl(&clkrst->crc_clk_out_enb_u);
-
- if (enable) {
- rst &= ~SWR_CSITE_RST;
- clk |= CLK_ENB_CSITE;
- } else {
- rst |= SWR_CSITE_RST;
- clk &= ~CLK_ENB_CSITE;
- }
+ u32 rst, src;
- writel(clk, &clkrst->crc_clk_out_enb_u);
- writel(rst, &clkrst->crc_rst_dev_u);
+ clock_set_enable(PERIPH_ID_CORESIGHT, enable);
+ reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
if (enable) {
/*
diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/armv7/tegra2/clock.c
new file mode 100644
index 0000000..67eed14
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/clock.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Tegra2 Clock control functions */
+
+#include <asm/io.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/timer.h>
+#include <asm/arch/tegra2.h>
+#include <common.h>
+
+#ifdef DEBUG
+#define assert(x) \
+ ({ if (!(x)) printf("Assertion failure '%s' %s line %d\n", \
+ #x, __FILE__, __LINE__); })
+#else
+#define assert(x)
+#endif
+
+/*
+ * Get the oscillator frequency, from the corresponding hardware configuration
+ * field.
+ */
+enum clock_osc_freq clock_get_osc_freq(void)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 reg;
+
+ reg = readl(&clkrst->crc_osc_ctrl);
+ return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+}
+
+unsigned long clock_start_pll(enum clock_pll_id clkid, u32 divm, u32 divn,
+ u32 divp, u32 cpcon, u32 lfcon)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 data;
+ struct clk_pll *pll;
+
+ assert(clock_pll_id_isvalid(clkid));
+ pll = &clkrst->crc_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
+ */
+ data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
+ writel(data, &pll->pll_misc);
+
+ data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
+ (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
+
+ if (clkid == CLOCK_PLL_ID_USB)
+ data |= divp << PLLU_VCO_FREQ_SHIFT;
+ else
+ data |= divp << PLL_DIVP_SHIFT;
+ writel(data, &pll->pll_base);
+
+ /* calculate the stable time */
+ return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
+}
+
+void clock_set_enable(enum periph_id periph_id, int enable)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
+ u32 reg;
+
+ /* Enable/disable the clock to this peripheral */
+ assert(clock_periph_id_isvalid(periph_id));
+ reg = readl(clk);
+ if (enable)
+ reg |= PERIPH_MASK(periph_id);
+ else
+ reg &= ~PERIPH_MASK(periph_id);
+ writel(reg, clk);
+}
+
+void clock_enable(enum periph_id clkid)
+{
+ clock_set_enable(clkid, 1);
+}
+
+void clock_disable(enum periph_id clkid)
+{
+ clock_set_enable(clkid, 0);
+}
+
+void reset_set_enable(enum periph_id periph_id, int enable)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
+ u32 reg;
+
+ /* Enable/disable reset to the peripheral */
+ assert(clock_periph_id_isvalid(periph_id));
+ reg = readl(reset);
+ if (enable)
+ reg |= PERIPH_MASK(periph_id);
+ else
+ reg &= ~PERIPH_MASK(periph_id);
+ writel(reg, reset);
+}
+
+void reset_periph(enum periph_id periph_id, int us_delay)
+{
+ /* Put peripheral into reset */
+ reset_set_enable(periph_id, 1);
+ udelay(us_delay);
+
+ /* Remove reset */
+ reset_set_enable(periph_id, 0);
+
+ udelay(us_delay);
+}
+
+void reset_cmplx_set_enable(int cpu, int which, int reset)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 mask;
+
+ /* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */
+ assert(cpu >= 0 && cpu < 2);
+ mask = which << cpu;
+
+ /* either enable or disable those reset for that CPU */
+ if (reset)
+ writel(mask, &clkrst->crc_cpu_cmplx_set);
+ else
+ writel(mask, &clkrst->crc_cpu_cmplx_clr);
+}
diff --git a/arch/arm/include/asm/arch-tegra2/clk_rst.h b/arch/arm/include/asm/arch-tegra2/clk_rst.h
index 36e27b5..a574c53 100644
--- a/arch/arm/include/asm/arch-tegra2/clk_rst.h
+++ b/arch/arm/include/asm/arch-tegra2/clk_rst.h
@@ -24,15 +24,34 @@
#ifndef _CLK_RST_H_
#define _CLK_RST_H_
+/* PLL registers - there are several PLLs in the clock controller */
+struct clk_pll {
+ uint pll_base; /* the control register */
+ uint pll_out; /* output control */
+ uint reserved;
+ uint pll_misc; /* other misc things */
+};
+
+/* PLL registers - there are several PLLs in the clock controller */
+struct clk_pll_simple {
+ uint pll_base; /* the control register */
+ uint pll_misc; /* other misc things */
+};
+
+/*
+ * Most PLLs use the clk_pll structure, but some have a simpler two-member
+ * structure for which we use clk_pll_simple. The reason for this non-
+ * othogonal setup is not stated.
+ */
+#define TEGRA_CLK_PLLS 6
+#define TEGRA_CLK_SIMPLE_PLLS 3 /* Number of simple PLLs */
+#define TEGRA_CLK_REGS 3 /* Number of clock enable registers */
+
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
struct clk_rst_ctlr {
- uint crc_rst_src; /* _RST_SOURCE_0, 0x00 */
- uint crc_rst_dev_l; /* _RST_DEVICES_L_0, 0x04 */
- uint crc_rst_dev_h; /* _RST_DEVICES_H_0, 0x08 */
- uint crc_rst_dev_u; /* _RST_DEVICES_U_0, 0x0C */
- uint crc_clk_out_enb_l; /* _CLK_OUT_ENB_L_0, 0x10 */
- uint crc_clk_out_enb_h; /* _CLK_OUT_ENB_H_0, 0x14 */
- uint crc_clk_out_enb_u; /* _CLK_OUT_ENB_U_0, 0x18 */
+ uint crc_rst_src; /* _RST_SOURCE_0,0x00 */
+ uint crc_rst_dev[TEGRA_CLK_REGS]; /* _RST_DEVICES_L/H/U_0 */
+ uint crc_clk_out_enb[TEGRA_CLK_REGS]; /* _CLK_OUT_ENB_L/H/U_0 */
uint crc_reserved0; /* reserved_0, 0x1C */
uint crc_cclk_brst_pol; /* _CCLK_BURST_POLICY_0,0x20 */
uint crc_super_cclk_div; /* _SUPER_CCLK_DIVIDER_0,0x24 */
@@ -52,44 +71,11 @@ struct clk_rst_ctlr {
uint crc_osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */
uint crc_reserved2[8]; /* reserved_2[8], 0x60-7C */
- uint crc_pllc_base; /* _PLLC_BASE_0, 0x80 */
- uint crc_pllc_out; /* _PLLC_OUT_0, 0x84 */
- uint crc_reserved3; /* reserved_3, 0x88 */
- uint crc_pllc_misc; /* _PLLC_MISC_0, 0x8C */
-
- uint crc_pllm_base; /* _PLLM_BASE_0, 0x90 */
- uint crc_pllm_out; /* _PLLM_OUT_0, 0x94 */
- uint crc_reserved4; /* reserved_4, 0x98 */
- uint crc_pllm_misc; /* _PLLM_MISC_0, 0x9C */
-
- uint crc_pllp_base; /* _PLLP_BASE_0, 0xA0 */
- uint crc_pllp_outa; /* _PLLP_OUTA_0, 0xA4 */
- uint crc_pllp_outb; /* _PLLP_OUTB_0, 0xA8 */
- uint crc_pllp_misc; /* _PLLP_MISC_0, 0xAC */
-
- uint crc_plla_base; /* _PLLA_BASE_0, 0xB0 */
- uint crc_plla_out; /* _PLLA_OUT_0, 0xB4 */
- uint crc_reserved5; /* reserved_5, 0xB8 */
- uint crc_plla_misc; /* _PLLA_MISC_0, 0xBC */
-
- uint crc_pllu_base; /* _PLLU_BASE_0, 0xC0 */
- uint crc_reserved6; /* _reserved_6, 0xC4 */
- uint crc_reserved7; /* _reserved_7, 0xC8 */
- uint crc_pllu_misc; /* _PLLU_MISC_0, 0xCC */
-
- uint crc_plld_base; /* _PLLD_BASE_0, 0xD0 */
- uint crc_reserved8; /* _reserved_8, 0xD4 */
- uint crc_reserved9; /* _reserved_9, 0xD8 */
- uint crc_plld_misc; /* _PLLD_MISC_0, 0xDC */
+ struct clk_pll crc_pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
- uint crc_pllx_base; /* _PLLX_BASE_0, 0xE0 */
- uint crc_pllx_misc; /* _PLLX_MISC_0, 0xE4 */
+ /* PLLs from 0xe0 to 0xf4 */
+ struct clk_pll_simple crc_pll_simple[TEGRA_CLK_SIMPLE_PLLS];
- uint crc_plle_base; /* _PLLE_BASE_0, 0xE8 */
- uint crc_plle_misc; /* _PLLE_MISC_0, 0xEC */
-
- uint crc_plls_base; /* _PLLS_BASE_0, 0xF0 */
- uint crc_plls_misc; /* _PLLS_MISC_0, 0xF4 */
uint crc_reserved10; /* _reserved_10, 0xF8 */
uint crc_reserved11; /* _reserved_11, 0xFC */
@@ -157,8 +143,8 @@ struct clk_rst_ctlr {
#define PLL_BYPASS (1 << 31)
#define PLL_ENABLE (1 << 30)
#define PLL_BASE_OVRRIDE (1 << 28)
-#define PLL_DIVP (1 << 20) /* post divider, b22:20 */
-#define PLL_DIVM 0x0C /* input divider, b4:0 */
+#define PLL_DIVP_VALUE (1 << 20) /* post divider, b22:20 */
+#define PLL_DIVM_VALUE 0x0C /* input divider, b4:0 */
#define SWR_UARTD_RST (1 << 1)
#define CLK_ENB_UARTD (1 << 1)
@@ -191,9 +177,37 @@ struct clk_rst_ctlr {
#define CPCON (1 << 8)
-#define SWR_SDMMC4_RST (1 << 15)
-#define CLK_ENB_SDMMC4 (1 << 15)
-#define SWR_SDMMC3_RST (1 << 5)
-#define CLK_ENB_SDMMC3 (1 << 5)
+/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 */
+#define CPU1_CLK_STP_SHIFT 9
+
+#define CPU0_CLK_STP_SHIFT 8
+#define CPU0_CLK_STP_MASK (1U << CPU0_CLK_STP_SHIFT)
+
+/* CLK_RST_CONTROLLER_PLLx_BASE_0 */
+#define PLL_BYPASS_SHIFT 31
+#define PLL_BYPASS_MASK (1U << PLL_BYPASS_SHIFT)
+
+#define PLL_ENABLE_SHIFT 30
+#define PLL_ENABLE_MASK (1U << PLL_ENABLE_SHIFT)
+
+#define PLL_BASE_OVRRIDE_MASK (1U << 28)
+
+#define PLL_DIVP_SHIFT 20
+
+#define PLL_DIVN_SHIFT 8
+
+#define PLL_DIVM_SHIFT 0
+
+/* CLK_RST_CONTROLLER_PLLx_MISC_0 */
+#define PLL_CPCON_SHIFT 8
+#define PLL_CPCON_MASK (15U << PLL_CPCON_SHIFT)
+
+#define PLL_LFCON_SHIFT 4
+
+#define PLLU_VCO_FREQ_SHIFT 20
+
+/* CLK_RST_CONTROLLER_OSC_CTRL_0 */
+#define OSC_FREQ_SHIFT 30
+#define OSC_FREQ_MASK (3U << OSC_FREQ_SHIFT)
#endif /* CLK_RST_H */
diff --git a/arch/arm/include/asm/arch-tegra2/clock.h b/arch/arm/include/asm/arch-tegra2/clock.h
new file mode 100644
index 0000000..81a9f02
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/clock.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Tegra2 clock control functions */
+
+#ifndef _CLOCK_H
+
+
+/* Set of oscillator frequencies supported in the internal API. */
+enum clock_osc_freq {
+ /* All in MHz, so 13_0 is 13.0MHz */
+ CLOCK_OSC_FREQ_13_0,
+ CLOCK_OSC_FREQ_19_2,
+ CLOCK_OSC_FREQ_12_0,
+ CLOCK_OSC_FREQ_26_0,
+
+ CLOCK_OSC_FREQ_COUNT,
+};
+
+/* The PLLs supported by the hardware */
+enum clock_pll_id {
+ CLOCK_PLL_ID_FIRST,
+ CLOCK_PLL_ID_CGENERAL = CLOCK_PLL_ID_FIRST,
+ CLOCK_PLL_ID_MEMORY,
+ CLOCK_PLL_ID_PERIPH,
+ CLOCK_PLL_ID_AUDIO,
+ CLOCK_PLL_ID_USB,
+ CLOCK_PLL_ID_DISPLAY,
+
+ /* now the simple ones */
+ CLOCK_PLL_ID_FIRST_SIMPLE,
+ CLOCK_PLL_ID_XCPU = CLOCK_PLL_ID_FIRST_SIMPLE,
+ CLOCK_PLL_ID_EPCI,
+ CLOCK_PLL_ID_SFROM32KHZ,
+
+ CLOCK_PLL_ID_COUNT,
+};
+
+/* The clocks supported by the hardware */
+enum periph_id {
+ PERIPH_ID_FIRST,
+
+ /* Low word: 31:0 */
+ PERIPH_ID_CPU = PERIPH_ID_FIRST,
+ PERIPH_ID_RESERVED1,
+ PERIPH_ID_RESERVED2,
+ PERIPH_ID_AC97,
+ PERIPH_ID_RTC,
+ PERIPH_ID_TMR,
+ PERIPH_ID_UART1,
+ PERIPH_ID_UART2,
+
+ /* 8 */
+ PERIPH_ID_GPIO,
+ PERIPH_ID_SDMMC2,
+ PERIPH_ID_SPDIF,
+ PERIPH_ID_I2S1,
+ PERIPH_ID_I2C1,
+ PERIPH_ID_NDFLASH,
+ PERIPH_ID_SDMMC1,
+ PERIPH_ID_SDMMC4,
+
+ /* 16 */
+ PERIPH_ID_TWC,
+ PERIPH_ID_PWC,
+ PERIPH_ID_I2S2,
+ PERIPH_ID_EPP,
+ PERIPH_ID_VI,
+ PERIPH_ID_2D,
+ PERIPH_ID_USBD,
+ PERIPH_ID_ISP,
+
+ /* 24 */
+ PERIPH_ID_3D,
+ PERIPH_ID_IDE,
+ PERIPH_ID_DISP2,
+ PERIPH_ID_DISP1,
+ PERIPH_ID_HOST1X,
+ PERIPH_ID_VCP,
+ PERIPH_ID_RESERVED30,
+ PERIPH_ID_CACHE2,
+
+ /* Middle word: 63:32 */
+ PERIPH_ID_MEM,
+ PERIPH_ID_AHBDMA,
+ PERIPH_ID_APBDMA,
+ PERIPH_ID_RESERVED35,
+ PERIPH_ID_KBC,
+ PERIPH_ID_STAT_MON,
+ PERIPH_ID_PMC,
+ PERIPH_ID_FUSE,
+
+ /* 40 */
+ PERIPH_ID_KFUSE,
+ PERIPH_ID_SBC1,
+ PERIPH_ID_SNOR,
+ PERIPH_ID_SPI1,
+ PERIPH_ID_SBC2,
+ PERIPH_ID_XIO,
+ PERIPH_ID_SBC3,
+ PERIPH_ID_DVC_I2C,
+
+ /* 48 */
+ PERIPH_ID_DSI,
+ PERIPH_ID_TVO,
+ PERIPH_ID_MIPI,
+ PERIPH_ID_HDMI,
+ PERIPH_ID_CSI,
+ PERIPH_ID_TVDAC,
+ PERIPH_ID_I2C2,
+ PERIPH_ID_UART3,
+
+ /* 56 */
+ PERIPH_ID_RESERVED56,
+ PERIPH_ID_EMC,
+ PERIPH_ID_USB2,
+ PERIPH_ID_USB3,
+ PERIPH_ID_MPE,
+ PERIPH_ID_VDE,
+ PERIPH_ID_BSEA,
+ PERIPH_ID_BSEV,
+
+ /* Upper word 95:64 */
+ PERIPH_ID_SPEEDO,
+ PERIPH_ID_UART4,
+ PERIPH_ID_UART5,
+ PERIPH_ID_I2C3,
+ PERIPH_ID_SBC4,
+ PERIPH_ID_SDMMC3,
+ PERIPH_ID_PCIE,
+ PERIPH_ID_OWR,
+
+ /* 72 */
+ PERIPH_ID_AFI,
+ PERIPH_ID_CORESIGHT,
+ PERIPH_ID_RESERVED74,
+ PERIPH_ID_AVPUCQ,
+ PERIPH_ID_RESERVED76,
+ PERIPH_ID_RESERVED77,
+ PERIPH_ID_RESERVED78,
+ PERIPH_ID_RESERVED79,
+
+ /* 80 */
+ PERIPH_ID_RESERVED80,
+ PERIPH_ID_RESERVED81,
+ PERIPH_ID_RESERVED82,
+ PERIPH_ID_RESERVED83,
+ PERIPH_ID_IRAMA,
+ PERIPH_ID_IRAMB,
+ PERIPH_ID_IRAMC,
+ PERIPH_ID_IRAMD,
+
+ /* 88 */
+ PERIPH_ID_CRAM2,
+
+ PERIPH_ID_COUNT,
+};
+
+/* Converts a clock number to a clock register: 0=L, 1=H, 2=U */
+#define PERIPH_REG(id) ((id) >> 5)
+
+/* Mask value for a clock (within PERIPH_REG(id)) */
+#define PERIPH_MASK(id) (1 << ((id) & 0x1f))
+
+/* return 1 if a PLL ID is in range */
+#define clock_pll_id_isvalid(id) ((id) >= CLOCK_PLL_ID_FIRST && \
+ (id) < CLOCK_PLL_ID_COUNT)
+
+/* return 1 if a peripheral ID is in range */
+#define clock_periph_id_isvalid(id) ((id) >= PERIPH_ID_FIRST && \
+ (id) < PERIPH_ID_COUNT)
+
+/* PLL stabilization delay in usec */
+#define CLOCK_PLL_STABLE_DELAY_US 300
+
+/* return the current oscillator clock frequency */
+enum clock_osc_freq clock_get_osc_freq(void);
+
+/*
+ * Start PLL using the provided configuration parameters.
+ *
+ * @param id clock id
+ * @param divm input divider
+ * @param divn feedback divider
+ * @param divp post divider 2^n
+ * @param cpcon charge pump setup control
+ * @param lfcon loop filter setup control
+ *
+ * @returns monotonic time in us that the PLL will be stable
+ */
+unsigned long clock_start_pll(enum clock_pll_id id, u32 divm, u32 divn,
+ u32 divp, u32 cpcon, u32 lfcon);
+
+/*
+ * Enable a clock
+ *
+ * @param id clock id
+ */
+void clock_enable(enum periph_id clkid);
+
+/*
+ * Set whether a clock is enabled or disabled.
+ *
+ * @param id clock id
+ * @param enable 1 to enable, 0 to disable
+ */
+void clock_set_enable(enum periph_id clkid, int enable);
+
+/*
+ * Reset a peripheral. This puts it in reset, waits for a delay, then takes
+ * it out of reset and waits for th delay again.
+ *
+ * @param periph_id peripheral to reset
+ * @param us_delay time to delay in microseconds
+ */
+void reset_periph(enum periph_id periph_id, int us_delay);
+
+/*
+ * Put a peripheral into or out of reset.
+ *
+ * @param periph_id peripheral to reset
+ * @param enable 1 to put into reset, 0 to take out of reset
+ */
+void reset_set_enable(enum periph_id periph_id, int enable);
+
+
+/* CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET/CLR_0 */
+enum crc_reset_id {
+ /* Things we can hold in reset for each CPU */
+ crc_rst_cpu = 1,
+ crc_rst_de = 1 << 2, /* What is de? */
+ crc_rst_watchdog = 1 << 3,
+ crc_rst_debug = 1 << 4,
+};
+
+/*
+ * Put parts of the CPU complex into or out of reset.\
+ *
+ * @param cpu cpu number (0 or 1 on Tegra2)
+ * @param which which parts of the complex to affect (OR of crc_reset_id)
+ * @param reset 1 to assert reset, 0 to de-assert
+ */
+void reset_cmplx_set_enable(int cpu, int which, int reset);
+
+#endif
+
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 8ab9440..2777b34 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -28,6 +28,7 @@
#include <asm/arch/sys_proto.h>
#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/uart.h>
#include "board.h"
@@ -76,33 +77,28 @@ int timer_init(void)
static void clock_init_uart(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ struct clk_pll *pll = &clkrst->crc_pll[CLOCK_PLL_ID_PERIPH];
u32 reg;
- reg = readl(&clkrst->crc_pllp_base);
+ reg = readl(&pll->pll_base);
if (!(reg & PLL_BASE_OVRRIDE)) {
/* Override pllp setup for 216MHz operation. */
- reg = (PLL_BYPASS | PLL_BASE_OVRRIDE | PLL_DIVP);
- reg |= (((NVRM_PLLP_FIXED_FREQ_KHZ/500) << 8) | PLL_DIVM);
- writel(reg, &clkrst->crc_pllp_base);
+ reg = (PLL_BYPASS | PLL_BASE_OVRRIDE | PLL_DIVP_VALUE);
+ reg |= (((NVRM_PLLP_FIXED_FREQ_KHZ/500) << 8) | PLL_DIVM_VALUE);
+ writel(reg, &pll->pll_base);
reg |= PLL_ENABLE;
- writel(reg, &clkrst->crc_pllp_base);
+ writel(reg, &pll->pll_base);
reg &= ~PLL_BYPASS;
- writel(reg, &clkrst->crc_pllp_base);
+ writel(reg, &pll->pll_base);
}
/* Now do the UART reset/clock enable */
#if defined(CONFIG_TEGRA2_ENABLE_UARTA)
- /* Assert Reset to UART */
- reg = readl(&clkrst->crc_rst_dev_l);
- reg |= SWR_UARTA_RST; /* SWR_UARTA_RST = 1 */
- writel(reg, &clkrst->crc_rst_dev_l);
-
- /* Enable clk to UART */
- reg = readl(&clkrst->crc_clk_out_enb_l);
- reg |= CLK_ENB_UARTA; /* CLK_ENB_UARTA = 1 */
- writel(reg, &clkrst->crc_clk_out_enb_l);
+ /* Assert UART reset and enable clock */
+ reset_set_enable(PERIPH_ID_UART1, 1);
+ clock_enable(PERIPH_ID_UART1);
/* Enable pllp_out0 to UART */
reg = readl(&clkrst->crc_clk_src_uarta);
@@ -113,20 +109,12 @@ static void clock_init_uart(void)
udelay(2);
/* De-assert reset to UART */
- reg = readl(&clkrst->crc_rst_dev_l);
- reg &= ~SWR_UARTA_RST; /* SWR_UARTA_RST = 0 */
- writel(reg, &clkrst->crc_rst_dev_l);
+ reset_set_enable(PERIPH_ID_UART1, 0);
#endif /* CONFIG_TEGRA2_ENABLE_UARTA */
#if defined(CONFIG_TEGRA2_ENABLE_UARTD)
- /* Assert Reset to UART */
- reg = readl(&clkrst->crc_rst_dev_u);
- reg |= SWR_UARTD_RST; /* SWR_UARTD_RST = 1 */
- writel(reg, &clkrst->crc_rst_dev_u);
-
- /* Enable clk to UART */
- reg = readl(&clkrst->crc_clk_out_enb_u);
- reg |= CLK_ENB_UARTD; /* CLK_ENB_UARTD = 1 */
- writel(reg, &clkrst->crc_clk_out_enb_u);
+ /* Assert UART reset and enable clock */
+ reset_set_enable(PERIPH_ID_UART4, 1);
+ clock_enable(PERIPH_ID_UART4);
/* Enable pllp_out0 to UART */
reg = readl(&clkrst->crc_clk_src_uartd);
@@ -137,9 +125,7 @@ static void clock_init_uart(void)
udelay(2);
/* De-assert reset to UART */
- reg = readl(&clkrst->crc_rst_dev_u);
- reg &= ~SWR_UARTD_RST; /* SWR_UARTD_RST = 0 */
- writel(reg, &clkrst->crc_rst_dev_u);
+ reset_set_enable(PERIPH_ID_UART4, 0);
#endif /* CONFIG_TEGRA2_ENABLE_UARTD */
}
@@ -183,16 +169,8 @@ static void clock_init_mmc(void)
u32 reg;
/* Do the SDMMC resets/clock enables */
-
- /* Assert Reset to SDMMC4 */
- reg = readl(&clkrst->crc_rst_dev_l);
- reg |= SWR_SDMMC4_RST; /* SWR_SDMMC4_RST = 1 */
- writel(reg, &clkrst->crc_rst_dev_l);
-
- /* Enable clk to SDMMC4 */
- reg = readl(&clkrst->crc_clk_out_enb_l);
- reg |= CLK_ENB_SDMMC4; /* CLK_ENB_SDMMC4 = 1 */
- writel(reg, &clkrst->crc_clk_out_enb_l);
+ reset_set_enable(PERIPH_ID_SDMMC4, 1);
+ clock_enable(PERIPH_ID_SDMMC4);
/* Enable pllp_out0 to SDMMC4 */
reg = readl(&clkrst->crc_clk_src_sdmmc4);
@@ -206,20 +184,10 @@ static void clock_init_mmc(void)
*/
udelay(2);
- /* De-assert reset to SDMMC4 */
- reg = readl(&clkrst->crc_rst_dev_l);
- reg &= ~SWR_SDMMC4_RST; /* SWR_SDMMC4_RST = 0 */
- writel(reg, &clkrst->crc_rst_dev_l);
-
- /* Assert Reset to SDMMC3 */
- reg = readl(&clkrst->crc_rst_dev_u);
- reg |= SWR_SDMMC3_RST; /* SWR_SDMMC3_RST = 1 */
- writel(reg, &clkrst->crc_rst_dev_u);
+ reset_set_enable(PERIPH_ID_SDMMC4, 1);
- /* Enable clk to SDMMC3 */
- reg = readl(&clkrst->crc_clk_out_enb_u);
- reg |= CLK_ENB_SDMMC3; /* CLK_ENB_SDMMC3 = 1 */
- writel(reg, &clkrst->crc_clk_out_enb_u);
+ reset_set_enable(PERIPH_ID_SDMMC3, 1);
+ clock_enable(PERIPH_ID_SDMMC3);
/* Enable pllp_out0 to SDMMC4, set divisor to 11 for 20MHz */
reg = readl(&clkrst->crc_clk_src_sdmmc3);
@@ -230,10 +198,7 @@ static void clock_init_mmc(void)
/* wait for 2us */
udelay(2);
- /* De-assert reset to SDMMC3 */
- reg = readl(&clkrst->crc_rst_dev_u);
- reg &= ~SWR_SDMMC3_RST; /* SWR_SDMMC3_RST = 0 */
- writel(reg, &clkrst->crc_rst_dev_u);
+ reset_set_enable(PERIPH_ID_SDMMC3, 0);
}
/*
--
1.7.3.1
More information about the U-Boot
mailing list