[U-Boot] [PATCH 1/1] tegra2: move tegra2 SoC code to arch/arm/cpu/tegra2-common
Allen Martin
amartin at nvidia.com
Wed Apr 18 20:17:01 CEST 2012
In preparation for splitting out the armv4t code from tegra2, move the
tegra2 SoC code to arch/arm/cpu/tegra2-common. This code will be
compiled armv4t for the arm7tdmi and armv7 for the cortex A9.
Signed-off-by: Allen Martin <amartin at nvidia.com>
---
Makefile | 3 +
arch/arm/cpu/armv7/tegra2/Makefile | 12 +-
arch/arm/cpu/armv7/tegra2/ap20.c | 324 ---------
arch/arm/cpu/armv7/tegra2/ap20.h | 102 ---
arch/arm/cpu/armv7/tegra2/board.c | 151 ----
arch/arm/cpu/armv7/tegra2/clock.c | 1052 ----------------------------
arch/arm/cpu/armv7/tegra2/funcmux.c | 184 -----
arch/arm/cpu/armv7/tegra2/lowlevel_init.S | 41 --
arch/arm/cpu/armv7/tegra2/pinmux.c | 572 ---------------
arch/arm/cpu/armv7/tegra2/sys_info.c | 35 -
arch/arm/cpu/armv7/tegra2/timer.c | 111 ---
arch/arm/cpu/tegra2-common/Makefile | 56 ++
arch/arm/cpu/tegra2-common/ap20.c | 324 +++++++++
arch/arm/cpu/tegra2-common/ap20.h | 102 +++
arch/arm/cpu/tegra2-common/board.c | 151 ++++
arch/arm/cpu/tegra2-common/clock.c | 1052 ++++++++++++++++++++++++++++
arch/arm/cpu/tegra2-common/funcmux.c | 184 +++++
arch/arm/cpu/tegra2-common/lowlevel_init.S | 41 ++
arch/arm/cpu/tegra2-common/pinmux.c | 572 +++++++++++++++
arch/arm/cpu/tegra2-common/sys_info.c | 35 +
arch/arm/cpu/tegra2-common/timer.c | 111 +++
spl/Makefile | 4 +
22 files changed, 2637 insertions(+), 2582 deletions(-)
delete mode 100644 arch/arm/cpu/armv7/tegra2/ap20.c
delete mode 100644 arch/arm/cpu/armv7/tegra2/ap20.h
delete mode 100644 arch/arm/cpu/armv7/tegra2/board.c
delete mode 100644 arch/arm/cpu/armv7/tegra2/clock.c
delete mode 100644 arch/arm/cpu/armv7/tegra2/funcmux.c
delete mode 100644 arch/arm/cpu/armv7/tegra2/lowlevel_init.S
delete mode 100644 arch/arm/cpu/armv7/tegra2/pinmux.c
delete mode 100644 arch/arm/cpu/armv7/tegra2/sys_info.c
delete mode 100644 arch/arm/cpu/armv7/tegra2/timer.c
create mode 100644 arch/arm/cpu/tegra2-common/Makefile
create mode 100644 arch/arm/cpu/tegra2-common/ap20.c
create mode 100644 arch/arm/cpu/tegra2-common/ap20.h
create mode 100644 arch/arm/cpu/tegra2-common/board.c
create mode 100644 arch/arm/cpu/tegra2-common/clock.c
create mode 100644 arch/arm/cpu/tegra2-common/funcmux.c
create mode 100644 arch/arm/cpu/tegra2-common/lowlevel_init.S
create mode 100644 arch/arm/cpu/tegra2-common/pinmux.c
create mode 100644 arch/arm/cpu/tegra2-common/sys_info.c
create mode 100644 arch/arm/cpu/tegra2-common/timer.c
diff --git a/Makefile b/Makefile
index 4ddf8d6..6639de0 100644
--- a/Makefile
+++ b/Makefile
@@ -319,6 +319,9 @@ endif
ifeq ($(SOC),exynos)
LIBS += $(CPUDIR)/s5p-common/libs5p-common.o
endif
+ifeq ($(SOC),tegra2)
+LIBS += $(OBJTREE)/arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
LIBS := $(addprefix $(obj),$(sort $(LIBS)))
.PHONY : $(LIBS)
diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index e9ac6c9..34452c4 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -22,23 +22,15 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
-
-# The AVP is ARMv4T architecture so we must use special compiler
-# flags for any startup files it might use.
-CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t
-CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t
-
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
-SOBJS := lowlevel_init.o
-COBJS-y := ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
COBJS := $(COBJS-y)
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
all: $(obj).depend $(LIB)
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
deleted file mode 100644
index b749821..0000000
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-* (C) Copyright 2010-2011
-* NVIDIA Corporation <www.nvidia.com>
-*
-* 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
-*/
-
-#include "ap20.h"
-#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>
-#include <common.h>
-
-/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
-static int ap20_cpu_is_cortexa9(void)
-{
- u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
- return id == (PG_UP_TAG_0_PID_CPU & 0xff);
-}
-
-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_ID_XCPU];
- u32 reg;
-
- /* If PLLX is already enabled, just return */
- if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
- return;
-
- /* Set PLLX_MISC */
- writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
-
- /* Use 12MHz clock here */
- reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
- reg |= 1000 << PLL_DIVN_SHIFT;
- writel(reg, &pll->pll_base);
-
- reg |= PLL_ENABLE_MASK;
- writel(reg, &pll->pll_base);
-
- reg &= ~PLL_BYPASS_MASK;
- 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 clk;
-
- /*
- * NOTE:
- * Regardless of whether the request is to enable or disable the CPU
- * clock, every processor in the CPU complex except the master (CPU 0)
- * will have it's clock stopped because the AVP only talks to the
- * master. The AVP does not know (nor does it need to know) that there
- * are multiple processors in the CPU complex.
- */
-
- if (enable) {
- /* Initialize PLLX */
- init_pllx();
-
- /* Wait until all clocks are stable */
- udelay(PLL_STABILIZATION_DELAY);
-
- writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
- writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
- }
-
- /*
- * Read the register containing the individual CPU clock enables and
- * always stop the clock to CPU 1.
- */
- clk = readl(&clkrst->crc_clk_cpu_cmplx);
- clk |= 1 << CPU1_CLK_STP_SHIFT;
-
- /* Stop/Unstop the CPU clock */
- clk &= ~CPU0_CLK_STP_MASK;
- clk |= !enable << CPU0_CLK_STP_SHIFT;
- writel(clk, &clkrst->crc_clk_cpu_cmplx);
-
- clock_enable(PERIPH_ID_CPU);
-}
-
-static int is_cpu_powered(void)
-{
- struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
-
- return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
-}
-
-static void remove_cpu_io_clamps(void)
-{
- struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
- u32 reg;
-
- /* Remove the clamps on the CPU I/O signals */
- reg = readl(&pmc->pmc_remove_clamping);
- reg |= CPU_CLMP;
- writel(reg, &pmc->pmc_remove_clamping);
-
- /* Give I/O signals time to stabilize */
- udelay(IO_STABILIZATION_DELAY);
-}
-
-static void powerup_cpu(void)
-{
- struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
- u32 reg;
- int timeout = IO_STABILIZATION_DELAY;
-
- if (!is_cpu_powered()) {
- /* Toggle the CPU power state (OFF -> ON) */
- reg = readl(&pmc->pmc_pwrgate_toggle);
- reg &= PARTID_CP;
- reg |= START_CP;
- writel(reg, &pmc->pmc_pwrgate_toggle);
-
- /* Wait for the power to come up */
- while (!is_cpu_powered()) {
- if (timeout-- == 0)
- printf("CPU failed to power up!\n");
- else
- udelay(10);
- }
-
- /*
- * Remove the I/O clamps from CPU power partition.
- * Recommended only on a Warm boot, if the CPU partition gets
- * power gated. Shouldn't cause any harm when called after a
- * cold boot according to HW, probably just redundant.
- */
- remove_cpu_io_clamps();
- }
-}
-
-static void enable_cpu_power_rail(void)
-{
- struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
- u32 reg;
-
- reg = readl(&pmc->pmc_cntrl);
- reg |= CPUPWRREQ_OE;
- writel(reg, &pmc->pmc_cntrl);
-
- /*
- * The TI PMU65861C needs a 3.75ms delay between enabling
- * the power rail and enabling the CPU clock. This delay
- * between SM1EN and SM1 is for switching time + the ramp
- * up of the voltage to the CPU (VDD_CPU from PMU).
- */
- udelay(3750);
-}
-
-static void reset_A9_cpu(int reset)
-{
- /*
- * NOTE: Regardless of whether the request is to hold the CPU in reset
- * or take it out of reset, every processor in the CPU complex
- * except the master (CPU 0) will be held in reset because the
- * AVP only talks to the master. The AVP does not know that there
- * are multiple processors in the CPU complex.
- */
-
- /* Hold CPU 1 in reset, and CPU 0 if asked */
- reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
- reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
- reset);
-
- /* Enable/Disable master CPU reset */
- reset_set_enable(PERIPH_ID_CPU, reset);
-}
-
-static void clock_enable_coresight(int enable)
-{
- u32 rst, src;
-
- clock_set_enable(PERIPH_ID_CORESIGHT, enable);
- reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
-
- if (enable) {
- /*
- * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
- * 1.5, giving an effective frequency of 144MHz.
- * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
- * (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
- */
- src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
- clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
-
- /* Unlock the CPU CoreSight interfaces */
- rst = 0xC5ACCE55;
- writel(rst, CSITE_CPU_DBG0_LAR);
- writel(rst, CSITE_CPU_DBG1_LAR);
- }
-}
-
-void start_cpu(u32 reset_vector)
-{
- /* Enable VDD_CPU */
- enable_cpu_power_rail();
-
- /* Hold the CPUs in reset */
- reset_A9_cpu(1);
-
- /* Disable the CPU clock */
- enable_cpu_clock(0);
-
- /* Enable CoreSight */
- clock_enable_coresight(1);
-
- /*
- * Set the entry point for CPU execution from reset,
- * if it's a non-zero value.
- */
- if (reset_vector)
- writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
-
- /* Enable the CPU clock */
- enable_cpu_clock(1);
-
- /* If the CPU doesn't already have power, power it up */
- powerup_cpu();
-
- /* Take the CPU out of reset */
- reset_A9_cpu(0);
-}
-
-
-void halt_avp(void)
-{
- for (;;) {
- writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
- | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
- FLOW_CTLR_HALT_COP_EVENTS);
- }
-}
-
-void enable_scu(void)
-{
- struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
- u32 reg;
-
- /* If SCU already setup/enabled, return */
- if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE)
- return;
-
- /* Invalidate all ways for all processors */
- writel(0xFFFF, &scu->scu_inv_all);
-
- /* Enable SCU - bit 0 */
- reg = readl(&scu->scu_ctrl);
- reg |= SCU_CTRL_ENABLE;
- writel(reg, &scu->scu_ctrl);
-}
-
-void init_pmc_scratch(void)
-{
- struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
- int i;
-
- /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
- for (i = 0; i < 23; i++)
- writel(0, &pmc->pmc_scratch1+i);
-
- /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
- writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
-}
-
-void tegra2_start(void)
-{
- struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-
- /* If we are the AVP, start up the first Cortex-A9 */
- if (!ap20_cpu_is_cortexa9()) {
- /* enable JTAG */
- writel(0xC0, &pmt->pmt_cfg_ctl);
-
- /*
- * If we are ARM7 - give it a different stack. We are about to
- * start up the A9 which will want to use this one.
- */
- asm volatile("mov sp, %0\n"
- : : "r"(AVP_EARLY_BOOT_STACK_LIMIT));
-
- start_cpu((u32)_start);
- halt_avp();
- /* not reached */
- }
-
- /* Init PMC scratch memory */
- init_pmc_scratch();
-
- enable_scu();
-
- /* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */
- asm volatile(
- "mrc p15, 0, r0, c1, c0, 1\n"
- "orr r0, r0, #0x41\n"
- "mcr p15, 0, r0, c1, c0, 1\n");
-
- /* FIXME: should have ap20's L2 disabled too? */
-}
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.h b/arch/arm/cpu/armv7/tegra2/ap20.h
deleted file mode 100644
index a4b4d73..0000000
--- a/arch/arm/cpu/armv7/tegra2/ap20.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * (C) Copyright 2010-2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * 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
- */
-#include <asm/types.h>
-
-/* Stabilization delays, in usec */
-#define PLL_STABILIZATION_DELAY (300)
-#define IO_STABILIZATION_DELAY (1000)
-
-#define NVBL_PLLP_KHZ (216000)
-
-#define PLLX_ENABLED (1 << 30)
-#define CCLK_BURST_POLICY 0x20008888
-#define SUPER_CCLK_DIVIDER 0x80000000
-
-/* Calculate clock fractional divider value from ref and target frequencies */
-#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
-
-/* Calculate clock frequency value from reference and clock divider value */
-#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
-
-/* AVP/CPU ID */
-#define PG_UP_TAG_0_PID_CPU 0x55555555 /* CPU aka "a9" aka "mpcore" */
-#define PG_UP_TAG_0 0x0
-
-#define CORESIGHT_UNLOCK 0xC5ACCE55;
-
-/* AP20-Specific Base Addresses */
-
-/* AP20 Base physical address of SDRAM. */
-#define AP20_BASE_PA_SDRAM 0x00000000
-/* AP20 Base physical address of internal SRAM. */
-#define AP20_BASE_PA_SRAM 0x40000000
-/* AP20 Size of internal SRAM (256KB). */
-#define AP20_BASE_PA_SRAM_SIZE 0x00040000
-/* AP20 Base physical address of flash. */
-#define AP20_BASE_PA_NOR_FLASH 0xD0000000
-/* AP20 Base physical address of boot information table. */
-#define AP20_BASE_PA_BOOT_INFO AP20_BASE_PA_SRAM
-
-/*
- * Super-temporary stacks for EXTREMELY early startup. The values chosen for
- * these addresses must be valid on ALL SOCs because this value is used before
- * we are able to differentiate between the SOC types.
- *
- * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
- * stack is placed below the AVP stack. Once the CPU stack has been moved,
- * the AVP is free to use the IRAM the CPU stack previously occupied if
- * it should need to do so.
- *
- * NOTE: In multi-processor CPU complex configurations, each processor will have
- * its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
- * limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
- * stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
- * CPU.
- */
-
-/* Common AVP early boot stack limit */
-#define AVP_EARLY_BOOT_STACK_LIMIT \
- (AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
-/* Common AVP early boot stack size */
-#define AVP_EARLY_BOOT_STACK_SIZE 0x1000
-/* Common CPU early boot stack limit */
-#define CPU_EARLY_BOOT_STACK_LIMIT \
- (AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
-/* Common CPU early boot stack size */
-#define CPU_EARLY_BOOT_STACK_SIZE 0x1000
-
-#define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100)
-#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0)
-#define CSITE_CPU_DBG1_LAR (NV_PA_CSITE_BASE + 0x12FB0)
-
-#define FLOW_CTLR_HALT_COP_EVENTS (NV_PA_FLOW_BASE + 4)
-#define FLOW_MODE_STOP 2
-#define HALT_COP_EVENT_JTAG (1 << 28)
-#define HALT_COP_EVENT_IRQ_1 (1 << 11)
-#define HALT_COP_EVENT_FIQ_1 (1 << 9)
-
-/* Start up the tegra2 SOC */
-void tegra2_start(void);
-
-/* This is the main entry into U-Boot, used by the Cortex-A9 */
-extern void _start(void);
diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/armv7/tegra2/board.c
deleted file mode 100644
index a797e6f..0000000
--- a/arch/arm/cpu/armv7/tegra2/board.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * 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
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include "ap20.h"
-#include <asm/arch/clock.h>
-#include <asm/arch/funcmux.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/tegra2.h>
-#include <asm/arch/pmc.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-enum {
- /* UARTs which we can enable */
- UARTA = 1 << 0,
- UARTB = 1 << 1,
- UARTD = 1 << 3,
- UART_COUNT = 4,
-};
-
-/*
- * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0,
- * so we are using this value to identify memory size.
- */
-
-unsigned int query_sdram_size(void)
-{
- struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
- u32 reg;
-
- reg = readl(&pmc->pmc_scratch20);
- debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
-
- /* bits 31:28 in OdmData are used for RAM size */
- switch ((reg) >> 28) {
- case 1:
- return 0x10000000; /* 256 MB */
- case 2:
- default:
- return 0x20000000; /* 512 MB */
- case 3:
- return 0x40000000; /* 1GB */
- }
-}
-
-int dram_init(void)
-{
- /* We do not initialise DRAM here. We just query the size */
- gd->ram_size = query_sdram_size();
- return 0;
-}
-
-#ifdef CONFIG_DISPLAY_BOARDINFO
-int checkboard(void)
-{
- printf("Board: %s\n", sysinfo.board_string);
- return 0;
-}
-#endif /* CONFIG_DISPLAY_BOARDINFO */
-
-#ifdef CONFIG_ARCH_CPU_INIT
-/*
- * Note this function is executed by the ARM7TDMI AVP. It does not return
- * in this case. It is also called once the A9 starts up, but does nothing in
- * that case.
- */
-int arch_cpu_init(void)
-{
- /* Fire up the Cortex A9 */
- tegra2_start();
-
- /* We didn't do this init in start.S, so do it now */
- cpu_init_cp15();
-
- /* Initialize essential common plls */
- clock_early_init();
-
- return 0;
-}
-#endif
-
-/**
- * Set up the specified uarts
- *
- * @param uarts_ids Mask containing UARTs to init (UARTx)
- */
-static void setup_uarts(int uart_ids)
-{
- static enum periph_id id_for_uart[] = {
- PERIPH_ID_UART1,
- PERIPH_ID_UART2,
- PERIPH_ID_UART3,
- PERIPH_ID_UART4,
- };
- size_t i;
-
- for (i = 0; i < UART_COUNT; i++) {
- if (uart_ids & (1 << i)) {
- enum periph_id id = id_for_uart[i];
-
- funcmux_select(id, FUNCMUX_DEFAULT);
- clock_ll_start_uart(id);
- }
- }
-}
-
-void board_init_uart_f(void)
-{
- int uart_ids = 0; /* bit mask of which UART ids to enable */
-
-#ifdef CONFIG_TEGRA2_ENABLE_UARTA
- uart_ids |= UARTA;
-#endif
-#ifdef CONFIG_TEGRA2_ENABLE_UARTB
- uart_ids |= UARTB;
-#endif
-#ifdef CONFIG_TEGRA2_ENABLE_UARTD
- uart_ids |= UARTD;
-#endif
- setup_uarts(uart_ids);
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
- /* Enable D-cache. I-cache is already enabled in start.S */
- dcache_enable();
-}
-#endif
diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/armv7/tegra2/clock.c
deleted file mode 100644
index 39376ab..0000000
--- a/arch/arm/cpu/armv7/tegra2/clock.c
+++ /dev/null
@@ -1,1052 +0,0 @@
-/*
- * 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>
-#include <div64.h>
-#include <fdtdec.h>
-
-/*
- * This is our record of the current clock rate of each clock. We don't
- * fill all of these in since we are only really interested in clocks which
- * we use as parents.
- */
-static unsigned pll_rate[CLOCK_ID_COUNT];
-
-/*
- * The oscillator frequency is fixed to one of four set values. Based on this
- * the other clocks are set up appropriately.
- */
-static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
- 13000000,
- 19200000,
- 12000000,
- 26000000,
-};
-
-/*
- * Clock types that we can use as a source. The Tegra2 has muxes for the
- * peripheral clocks, and in most cases there are four options for the clock
- * source. This gives us a clock 'type' and exploits what commonality exists
- * in the device.
- *
- * Letters are obvious, except for T which means CLK_M, and S which means the
- * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
- * datasheet) and PLL_M are different things. The former is the basic
- * clock supplied to the SOC from an external oscillator. The latter is the
- * memory clock PLL.
- *
- * See definitions in clock_id in the header file.
- */
-enum clock_type_id {
- CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */
- CLOCK_TYPE_MCPA, /* and so on */
- CLOCK_TYPE_MCPT,
- CLOCK_TYPE_PCM,
- CLOCK_TYPE_PCMT,
- CLOCK_TYPE_PCMT16, /* CLOCK_TYPE_PCMT with 16-bit divider */
- CLOCK_TYPE_PCXTS,
- CLOCK_TYPE_PDCT,
-
- CLOCK_TYPE_COUNT,
- CLOCK_TYPE_NONE = -1, /* invalid clock type */
-};
-
-/* return 1 if a peripheral ID is in range */
-#define clock_type_id_isvalid(id) ((id) >= 0 && \
- (id) < CLOCK_TYPE_COUNT)
-
-char pllp_valid = 1; /* PLLP is set up correctly */
-
-enum {
- CLOCK_MAX_MUX = 4 /* number of source options for each clock */
-};
-
-/*
- * Clock source mux for each clock type. This just converts our enum into
- * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS
- * is special as it has 5 sources. Since it also has a different number of
- * bits in its register for the source, we just handle it with a special
- * case in the code.
- */
-#define CLK(x) CLOCK_ID_ ## x
-static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
- { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC) },
- { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO) },
- { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC) },
- { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE) },
- { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) },
- { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) },
- { CLK(PERIPH), CLK(CGENERAL), CLK(XCPU), CLK(OSC) },
- { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC) },
-};
-
-/*
- * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is
- * not in the header file since it is for purely internal use - we want
- * callers to use the PERIPH_ID for all access to peripheral clocks to avoid
- * confusion bewteen PERIPH_ID_... and PERIPHC_...
- *
- * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be
- * confusing.
- *
- * Note to SOC vendors: perhaps define a unified numbering for peripherals and
- * use it for reset, clock enable, clock source/divider and even pinmuxing
- * if you can.
- */
-enum periphc_internal_id {
- /* 0x00 */
- PERIPHC_I2S1,
- PERIPHC_I2S2,
- PERIPHC_SPDIF_OUT,
- PERIPHC_SPDIF_IN,
- PERIPHC_PWM,
- PERIPHC_SPI1,
- PERIPHC_SPI2,
- PERIPHC_SPI3,
-
- /* 0x08 */
- PERIPHC_XIO,
- PERIPHC_I2C1,
- PERIPHC_DVC_I2C,
- PERIPHC_TWC,
- PERIPHC_0c,
- PERIPHC_10, /* PERIPHC_SPI1, what is this really? */
- PERIPHC_DISP1,
- PERIPHC_DISP2,
-
- /* 0x10 */
- PERIPHC_CVE,
- PERIPHC_IDE0,
- PERIPHC_VI,
- PERIPHC_1c,
- PERIPHC_SDMMC1,
- PERIPHC_SDMMC2,
- PERIPHC_G3D,
- PERIPHC_G2D,
-
- /* 0x18 */
- PERIPHC_NDFLASH,
- PERIPHC_SDMMC4,
- PERIPHC_VFIR,
- PERIPHC_EPP,
- PERIPHC_MPE,
- PERIPHC_MIPI,
- PERIPHC_UART1,
- PERIPHC_UART2,
-
- /* 0x20 */
- PERIPHC_HOST1X,
- PERIPHC_21,
- PERIPHC_TVO,
- PERIPHC_HDMI,
- PERIPHC_24,
- PERIPHC_TVDAC,
- PERIPHC_I2C2,
- PERIPHC_EMC,
-
- /* 0x28 */
- PERIPHC_UART3,
- PERIPHC_29,
- PERIPHC_VI_SENSOR,
- PERIPHC_2b,
- PERIPHC_2c,
- PERIPHC_SPI4,
- PERIPHC_I2C3,
- PERIPHC_SDMMC3,
-
- /* 0x30 */
- PERIPHC_UART4,
- PERIPHC_UART5,
- PERIPHC_VDE,
- PERIPHC_OWR,
- PERIPHC_NOR,
- PERIPHC_CSITE,
-
- PERIPHC_COUNT,
-
- PERIPHC_NONE = -1,
-};
-
-/* return 1 if a periphc_internal_id is in range */
-#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
- (id) < PERIPHC_COUNT)
-
-/*
- * Clock type for each peripheral clock source. We put the name in each
- * record just so it is easy to match things up
- */
-#define TYPE(name, type) type
-static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
- /* 0x00 */
- TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT),
- TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT),
- TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
- TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM),
- TYPE(PERIPHC_PWM, CLOCK_TYPE_PCXTS),
- TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_SPI22, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_SPI3, CLOCK_TYPE_PCMT),
-
- /* 0x08 */
- TYPE(PERIPHC_XIO, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16),
- TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16),
- TYPE(PERIPHC_TWC, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_DISP1, CLOCK_TYPE_PDCT),
- TYPE(PERIPHC_DISP2, CLOCK_TYPE_PDCT),
-
- /* 0x10 */
- TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT),
- TYPE(PERIPHC_IDE0, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA),
- TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA),
-
- /* 0x18 */
- TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA),
- TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA),
- TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT),
-
- /* 0x20 */
- TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT),
- TYPE(PERIPHC_HDMI, CLOCK_TYPE_PDCT),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
- TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16),
- TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT),
-
- /* 0x28 */
- TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
- TYPE(PERIPHC_SPI4, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16),
- TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT),
-
- /* 0x30 */
- TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT),
- TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT),
-};
-
-/*
- * This array translates a periph_id to a periphc_internal_id
- *
- * Not present/matched up:
- * uint vi_sensor; _VI_SENSOR_0, 0x1A8
- * SPDIF - which is both 0x08 and 0x0c
- *
- */
-#define NONE(name) (-1)
-#define OFFSET(name, value) PERIPHC_ ## name
-static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
- /* Low word: 31:0 */
- NONE(CPU),
- NONE(RESERVED1),
- NONE(RESERVED2),
- NONE(AC97),
- NONE(RTC),
- NONE(TMR),
- PERIPHC_UART1,
- PERIPHC_UART2, /* and vfir 0x68 */
-
- /* 0x08 */
- NONE(GPIO),
- PERIPHC_SDMMC2,
- NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */
- PERIPHC_I2S1,
- PERIPHC_I2C1,
- PERIPHC_NDFLASH,
- PERIPHC_SDMMC1,
- PERIPHC_SDMMC4,
-
- /* 0x10 */
- PERIPHC_TWC,
- PERIPHC_PWM,
- PERIPHC_I2S2,
- PERIPHC_EPP,
- PERIPHC_VI,
- PERIPHC_G2D,
- NONE(USBD),
- NONE(ISP),
-
- /* 0x18 */
- PERIPHC_G3D,
- PERIPHC_IDE0,
- PERIPHC_DISP2,
- PERIPHC_DISP1,
- PERIPHC_HOST1X,
- NONE(VCP),
- NONE(RESERVED30),
- NONE(CACHE2),
-
- /* Middle word: 63:32 */
- NONE(MEM),
- NONE(AHBDMA),
- NONE(APBDMA),
- NONE(RESERVED35),
- NONE(KBC),
- NONE(STAT_MON),
- NONE(PMC),
- NONE(FUSE),
-
- /* 0x28 */
- NONE(KFUSE),
- NONE(SBC1), /* SBC1, 0x34, is this SPI1? */
- PERIPHC_NOR,
- PERIPHC_SPI1,
- PERIPHC_SPI2,
- PERIPHC_XIO,
- PERIPHC_SPI3,
- PERIPHC_DVC_I2C,
-
- /* 0x30 */
- NONE(DSI),
- PERIPHC_TVO, /* also CVE 0x40 */
- PERIPHC_MIPI,
- PERIPHC_HDMI,
- PERIPHC_CSITE,
- PERIPHC_TVDAC,
- PERIPHC_I2C2,
- PERIPHC_UART3,
-
- /* 0x38 */
- NONE(RESERVED56),
- PERIPHC_EMC,
- NONE(USB2),
- NONE(USB3),
- PERIPHC_MPE,
- PERIPHC_VDE,
- NONE(BSEA),
- NONE(BSEV),
-
- /* Upper word 95:64 */
- NONE(SPEEDO),
- PERIPHC_UART4,
- PERIPHC_UART5,
- PERIPHC_I2C3,
- PERIPHC_SPI4,
- PERIPHC_SDMMC3,
- NONE(PCIE),
- PERIPHC_OWR,
-
- /* 0x48 */
- NONE(AFI),
- NONE(CORESIGHT),
- NONE(RESERVED74),
- NONE(AVPUCQ),
- NONE(RESERVED76),
- NONE(RESERVED77),
- NONE(RESERVED78),
- NONE(RESERVED79),
-
- /* 0x50 */
- NONE(RESERVED80),
- NONE(RESERVED81),
- NONE(RESERVED82),
- NONE(RESERVED83),
- NONE(IRAMA),
- NONE(IRAMB),
- NONE(IRAMC),
- NONE(IRAMD),
-
- /* 0x58 */
- NONE(CRAM2),
-};
-
-/*
- * 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;
-}
-
-/* Returns a pointer to the registers of the given pll */
-static struct clk_pll *get_pll(enum clock_id clkid)
-{
- struct clk_rst_ctlr *clkrst =
- (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-
- assert(clock_id_isvalid(clkid));
- return &clkrst->crc_pll[clkid];
-}
-
-unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
- u32 divp, u32 cpcon, u32 lfcon)
-{
- struct clk_pll *pll = get_pll(clkid);
- u32 data;
-
- /*
- * 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_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;
-}
-
-/* return 1 if a peripheral ID is in range and valid */
-static int clock_periph_id_isvalid(enum periph_id id)
-{
- if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT)
- printf("Peripheral id %d out of range\n", id);
- else {
- switch (id) {
- case PERIPH_ID_RESERVED1:
- case PERIPH_ID_RESERVED2:
- case PERIPH_ID_RESERVED30:
- case PERIPH_ID_RESERVED35:
- case PERIPH_ID_RESERVED56:
- case PERIPH_ID_RESERVED74:
- case PERIPH_ID_RESERVED76:
- case PERIPH_ID_RESERVED77:
- case PERIPH_ID_RESERVED78:
- case PERIPH_ID_RESERVED79:
- case PERIPH_ID_RESERVED80:
- case PERIPH_ID_RESERVED81:
- case PERIPH_ID_RESERVED82:
- case PERIPH_ID_RESERVED83:
- printf("Peripheral id %d is reserved\n", id);
- break;
- default:
- return 1;
- }
- }
- return 0;
-}
-
-/* Returns a pointer to the clock source register for a peripheral */
-static u32 *get_periph_source_reg(enum periph_id periph_id)
-{
- struct clk_rst_ctlr *clkrst =
- (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
- enum periphc_internal_id internal_id;
-
- assert(clock_periph_id_isvalid(periph_id));
- internal_id = periph_id_to_internal_id[periph_id];
- assert(internal_id != -1);
- return &clkrst->crc_clk_src[internal_id];
-}
-
-void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
- unsigned divisor)
-{
- u32 *reg = get_periph_source_reg(periph_id);
- u32 value;
-
- value = readl(reg);
-
- value &= ~OUT_CLK_SOURCE_MASK;
- value |= source << OUT_CLK_SOURCE_SHIFT;
-
- value &= ~OUT_CLK_DIVISOR_MASK;
- value |= divisor << OUT_CLK_DIVISOR_SHIFT;
-
- writel(value, reg);
-}
-
-void clock_ll_set_source(enum periph_id periph_id, unsigned source)
-{
- u32 *reg = get_periph_source_reg(periph_id);
-
- clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
- source << OUT_CLK_SOURCE_SHIFT);
-}
-
-/**
- * Given the parent's rate and the required rate for the children, this works
- * out the peripheral clock divider to use, in 7.1 binary format.
- *
- * @param divider_bits number of divider bits (8 or 16)
- * @param parent_rate clock rate of parent clock in Hz
- * @param rate required clock rate for this clock
- * @return divider which should be used
- */
-static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
- unsigned long rate)
-{
- u64 divider = parent_rate * 2;
- unsigned max_divider = 1 << divider_bits;
-
- divider += rate - 1;
- do_div(divider, rate);
-
- if ((s64)divider - 2 < 0)
- return 0;
-
- if ((s64)divider - 2 >= max_divider)
- return -1;
-
- return divider - 2;
-}
-
-/**
- * Given the parent's rate and the divider in 7.1 format, this works out the
- * resulting peripheral clock rate.
- *
- * @param parent_rate clock rate of parent clock in Hz
- * @param divider which should be used in 7.1 format
- * @return effective clock rate of peripheral
- */
-static unsigned long get_rate_from_divider(unsigned long parent_rate,
- int divider)
-{
- u64 rate;
-
- rate = (u64)parent_rate * 2;
- do_div(rate, divider + 2);
- return rate;
-}
-
-unsigned long clock_get_periph_rate(enum periph_id periph_id,
- enum clock_id parent)
-{
- u32 *reg = get_periph_source_reg(periph_id);
-
- return get_rate_from_divider(pll_rate[parent],
- (readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
-}
-
-/**
- * Find the best available 7.1 format divisor given a parent clock rate and
- * required child clock rate. This function assumes that a second-stage
- * divisor is available which can divide by powers of 2 from 1 to 256.
- *
- * @param divider_bits number of divider bits (8 or 16)
- * @param parent_rate clock rate of parent clock in Hz
- * @param rate required clock rate for this clock
- * @param extra_div value for the second-stage divisor (not set if this
- * function returns -1.
- * @return divider which should be used, or -1 if nothing is valid
- *
- */
-static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
- unsigned long rate, int *extra_div)
-{
- int shift;
- int best_divider = -1;
- int best_error = rate;
-
- /* try dividers from 1 to 256 and find closest match */
- for (shift = 0; shift <= 8 && best_error > 0; shift++) {
- unsigned divided_parent = parent_rate >> shift;
- int divider = clk_get_divider(divider_bits, divided_parent,
- rate);
- unsigned effective_rate = get_rate_from_divider(divided_parent,
- divider);
- int error = rate - effective_rate;
-
- /* Given a valid divider, look for the lowest error */
- if (divider != -1 && error < best_error) {
- best_error = error;
- *extra_div = 1 << shift;
- best_divider = divider;
- }
- }
-
- /* return what we found - *extra_div will already be set */
- return best_divider;
-}
-
-/**
- * Given a peripheral ID and the required source clock, this returns which
- * value should be programmed into the source mux for that peripheral.
- *
- * There is special code here to handle the one source type with 5 sources.
- *
- * @param periph_id peripheral to start
- * @param source PLL id of required parent clock
- * @param mux_bits Set to number of bits in mux register: 2 or 4
- * @param divider_bits Set to number of divider bits (8 or 16)
- * @return mux value (0-4, or -1 if not found)
- */
-static int get_periph_clock_source(enum periph_id periph_id,
- enum clock_id parent, int *mux_bits, int *divider_bits)
-{
- enum clock_type_id type;
- enum periphc_internal_id internal_id;
- int mux;
-
- assert(clock_periph_id_isvalid(periph_id));
-
- internal_id = periph_id_to_internal_id[periph_id];
- assert(periphc_internal_id_isvalid(internal_id));
-
- type = clock_periph_type[internal_id];
- assert(clock_type_id_isvalid(type));
-
- /*
- * Special cases here for the clock with a 4-bit source mux and I2C
- * with its 16-bit divisor
- */
- if (type == CLOCK_TYPE_PCXTS)
- *mux_bits = 4;
- else
- *mux_bits = 2;
- if (type == CLOCK_TYPE_PCMT16)
- *divider_bits = 16;
- else
- *divider_bits = 8;
-
- for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
- if (clock_source[type][mux] == parent)
- return mux;
-
- /*
- * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS
- * which is not in our table. If not, then they are asking for a
- * source which this peripheral can't access through its mux.
- */
- assert(type == CLOCK_TYPE_PCXTS);
- assert(parent == CLOCK_ID_SFROM32KHZ);
- if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ)
- return 4; /* mux value for this clock */
-
- /* if we get here, either us or the caller has made a mistake */
- printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
- parent);
- return -1;
-}
-
-/**
- * Adjust peripheral PLL to use the given divider and source.
- *
- * @param periph_id peripheral to adjust
- * @param source Source number (0-3 or 0-7)
- * @param mux_bits Number of mux bits (2 or 4)
- * @param divider Required divider in 7.1 or 15.1 format
- * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
- * for this peripheral)
- */
-static int adjust_periph_pll(enum periph_id periph_id, int source,
- int mux_bits, unsigned divider)
-{
- u32 *reg = get_periph_source_reg(periph_id);
-
- clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
- divider << OUT_CLK_DIVISOR_SHIFT);
- udelay(1);
-
- /* work out the source clock and set it */
- if (source < 0)
- return -1;
- if (mux_bits == 4) {
- clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
- source << OUT_CLK_SOURCE4_SHIFT);
- } else {
- clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
- source << OUT_CLK_SOURCE_SHIFT);
- }
- udelay(2);
- return 0;
-}
-
-unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
- enum clock_id parent, unsigned rate, int *extra_div)
-{
- unsigned effective_rate;
- int mux_bits, divider_bits, source;
- int divider;
-
- /* work out the source clock and set it */
- source = get_periph_clock_source(periph_id, parent, &mux_bits,
- ÷r_bits);
-
- if (extra_div)
- divider = find_best_divider(divider_bits, pll_rate[parent],
- rate, extra_div);
- else
- divider = clk_get_divider(divider_bits, pll_rate[parent],
- rate);
- assert(divider >= 0);
- if (adjust_periph_pll(periph_id, source, mux_bits, divider))
- return -1U;
- debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
- get_periph_source_reg(periph_id),
- readl(get_periph_source_reg(periph_id)));
-
- /* Check what we ended up with. This shouldn't matter though */
- effective_rate = clock_get_periph_rate(periph_id, parent);
- if (extra_div)
- effective_rate /= *extra_div;
- if (rate != effective_rate)
- debug("Requested clock rate %u not honored (got %u)\n",
- rate, effective_rate);
- return effective_rate;
-}
-
-unsigned clock_start_periph_pll(enum periph_id periph_id,
- enum clock_id parent, unsigned rate)
-{
- unsigned effective_rate;
-
- reset_set_enable(periph_id, 1);
- clock_enable(periph_id);
-
- effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
- NULL);
-
- reset_set_enable(periph_id, 0);
- return effective_rate;
-}
-
-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);
-}
-
-unsigned clock_get_rate(enum clock_id clkid)
-{
- struct clk_pll *pll;
- u32 base;
- u32 divm;
- u64 parent_rate;
- u64 rate;
-
- parent_rate = osc_freq[clock_get_osc_freq()];
- if (clkid == CLOCK_ID_OSC)
- return parent_rate;
-
- pll = get_pll(clkid);
- base = readl(&pll->pll_base);
-
- /* Oh for bf_unpack()... */
- rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
- divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
- if (clkid == CLOCK_ID_USB)
- divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
- else
- divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
- do_div(rate, divm);
- return rate;
-}
-
-/**
- * Set the output frequency you want for each PLL clock.
- * PLL output frequencies are programmed by setting their N, M and P values.
- * The governing equations are:
- * VCO = (Fi / m) * n, Fo = VCO / (2^p)
- * where Fo is the output frequency from the PLL.
- * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
- * 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
- * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
- *
- * @param n PLL feedback divider(DIVN)
- * @param m PLL input divider(DIVN)
- * @param p post divider(DIVP)
- * @param cpcon base PLL charge pump(CPCON)
- * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
- * be overriden), 1 if PLL is already correct
- */
-static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
-{
- u32 base_reg;
- u32 misc_reg;
- struct clk_pll *pll;
-
- pll = get_pll(clkid);
-
- base_reg = readl(&pll->pll_base);
-
- /* Set BYPASS, m, n and p to PLL_BASE */
- base_reg &= ~PLL_DIVM_MASK;
- base_reg |= m << PLL_DIVM_SHIFT;
-
- base_reg &= ~PLL_DIVN_MASK;
- base_reg |= n << PLL_DIVN_SHIFT;
-
- base_reg &= ~PLL_DIVP_MASK;
- base_reg |= p << PLL_DIVP_SHIFT;
-
- if (clkid == CLOCK_ID_PERIPH) {
- /*
- * If the PLL is already set up, check that it is correct
- * and record this info for clock_verify() to check.
- */
- if (base_reg & PLL_BASE_OVRRIDE_MASK) {
- base_reg |= PLL_ENABLE_MASK;
- if (base_reg != readl(&pll->pll_base))
- pllp_valid = 0;
- return pllp_valid ? 1 : -1;
- }
- base_reg |= PLL_BASE_OVRRIDE_MASK;
- }
-
- base_reg |= PLL_BYPASS_MASK;
- writel(base_reg, &pll->pll_base);
-
- /* Set cpcon to PLL_MISC */
- misc_reg = readl(&pll->pll_misc);
- misc_reg &= ~PLL_CPCON_MASK;
- misc_reg |= cpcon << PLL_CPCON_SHIFT;
- writel(misc_reg, &pll->pll_misc);
-
- /* Enable PLL */
- base_reg |= PLL_ENABLE_MASK;
- writel(base_reg, &pll->pll_base);
-
- /* Disable BYPASS */
- base_reg &= ~PLL_BYPASS_MASK;
- writel(base_reg, &pll->pll_base);
-
- return 0;
-}
-
-void clock_ll_start_uart(enum periph_id periph_id)
-{
- /* Assert UART reset and enable clock */
- reset_set_enable(periph_id, 1);
- clock_enable(periph_id);
- clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
-
- /* wait for 2us */
- udelay(2);
-
- /* De-assert reset to UART */
- reset_set_enable(periph_id, 0);
-}
-
-#ifdef CONFIG_OF_CONTROL
-/*
- * Convert a device tree clock ID to our peripheral ID. They are mostly
- * the same but we are very cautious so we check that a valid clock ID is
- * provided.
- *
- * @param clk_id Clock ID according to tegra2 device tree binding
- * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
- */
-static enum periph_id clk_id_to_periph_id(int clk_id)
-{
- if (clk_id > 95)
- return PERIPH_ID_NONE;
-
- switch (clk_id) {
- case 1:
- case 2:
- case 7:
- case 10:
- case 20:
- case 30:
- case 35:
- case 49:
- case 56:
- case 74:
- case 76:
- case 77:
- case 78:
- case 79:
- case 80:
- case 81:
- case 82:
- case 83:
- case 91:
- case 95:
- return PERIPH_ID_NONE;
- default:
- return clk_id;
- }
-}
-
-int clock_decode_periph_id(const void *blob, int node)
-{
- enum periph_id id;
- u32 cell[2];
- int err;
-
- err = fdtdec_get_int_array(blob, node, "clocks", cell,
- ARRAY_SIZE(cell));
- if (err)
- return -1;
- id = clk_id_to_periph_id(cell[1]);
- assert(clock_periph_id_isvalid(id));
- return id;
-}
-#endif /* CONFIG_OF_CONTROL */
-
-int clock_verify(void)
-{
- struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
- u32 reg = readl(&pll->pll_base);
-
- if (!pllp_valid) {
- printf("Warning: PLLP %x is not correct\n", reg);
- return -1;
- }
- debug("PLLX %x is correct\n", reg);
- return 0;
-}
-
-void clock_early_init(void)
-{
- /*
- * PLLP output frequency set to 216MHz
- * PLLC output frequency set to 600Mhz
- *
- * TODO: Can we calculate these values instead of hard-coding?
- */
- switch (clock_get_osc_freq()) {
- case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
- clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8);
- clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
- break;
-
- case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
- clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8);
- clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
- break;
-
- case CLOCK_OSC_FREQ_13_0:
- case CLOCK_OSC_FREQ_19_2:
- default:
- /*
- * These are not supported. It is too early to print a
- * message and the UART likely won't work anyway due to the
- * oscillator being wrong.
- */
- break;
- }
-}
-
-void clock_init(void)
-{
- 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_OSC] = clock_get_rate(CLOCK_ID_OSC);
- pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
- debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
- debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
- debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
-}
diff --git a/arch/arm/cpu/armv7/tegra2/funcmux.c b/arch/arm/cpu/armv7/tegra2/funcmux.c
deleted file mode 100644
index c1d2dfe..0000000
--- a/arch/arm/cpu/armv7/tegra2/funcmux.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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 high-level function multiplexing */
-#include <common.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/funcmux.h>
-#include <asm/arch/pinmux.h>
-
-int funcmux_select(enum periph_id id, int config)
-{
- int bad_config = config != FUNCMUX_DEFAULT;
-
- switch (id) {
- case PERIPH_ID_UART1:
- if (config == FUNCMUX_UART1_IRRX_IRTX) {
- pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
- pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
- pinmux_tristate_disable(PINGRP_IRRX);
- pinmux_tristate_disable(PINGRP_IRTX);
- /*
- * Tegra appears to boot with function UARTA pre-
- * selected on mux group SDB. If two mux groups are
- * both set to the same function, it's unclear which
- * group's pins drive the RX signals into the HW.
- * For UARTA, SDB certainly overrides group IRTX in
- * practice. To solve this, configure some alternative
- * function on SDB to avoid the conflict. Also, tri-
- * state the group to avoid driving any signal onto it
- * until we know what's connected.
- */
- pinmux_tristate_enable(PINGRP_SDB);
- pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
- }
- break;
-
- case PERIPH_ID_UART2:
- if (config == FUNCMUX_UART2_IRDA) {
- pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
- pinmux_tristate_disable(PINGRP_UAD);
- }
- break;
-
- case PERIPH_ID_UART4:
- if (config == FUNCMUX_UART4_GMC) {
- pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
- pinmux_tristate_disable(PINGRP_GMC);
- }
- break;
-
- case PERIPH_ID_DVC_I2C:
- /* there is only one selection, pinmux_config is ignored */
- if (config == FUNCMUX_DVC_I2CP) {
- pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
- pinmux_tristate_disable(PINGRP_I2CP);
- }
- break;
-
- case PERIPH_ID_I2C1:
- /* support pinmux_config of 0 for now, */
- if (config == FUNCMUX_I2C1_RM) {
- pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
- pinmux_tristate_disable(PINGRP_RM);
- }
- break;
- case PERIPH_ID_I2C2: /* I2C2 */
- switch (config) {
- case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
- pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
- /* PTA to HDMI */
- pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
- pinmux_tristate_disable(PINGRP_DDC);
- break;
- case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
- pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
- /* set DDC_SEL to RSVDx (RSVD2 works for now) */
- pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
- pinmux_tristate_disable(PINGRP_PTA);
- bad_config = 0;
- break;
- }
- break;
- case PERIPH_ID_I2C3: /* I2C3 */
- /* support pinmux_config of 0 for now */
- if (config == FUNCMUX_I2C3_DTF) {
- pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
- pinmux_tristate_disable(PINGRP_DTF);
- }
- break;
-
- case PERIPH_ID_SDMMC2:
- if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
- pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
- pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);
-
- pinmux_tristate_disable(PINGRP_DTA);
- pinmux_tristate_disable(PINGRP_DTD);
- }
- break;
-
- case PERIPH_ID_SDMMC3:
- switch (config) {
- case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
- pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
- pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
- pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
- pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);
-
- pinmux_tristate_disable(PINGRP_SLXA);
- pinmux_tristate_disable(PINGRP_SLXC);
- pinmux_tristate_disable(PINGRP_SLXD);
- pinmux_tristate_disable(PINGRP_SLXK);
- /* fall through */
-
- case FUNCMUX_SDMMC3_SDB_4BIT:
- pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
- pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
- pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);
-
- pinmux_tristate_disable(PINGRP_SDB);
- pinmux_tristate_disable(PINGRP_SDC);
- pinmux_tristate_disable(PINGRP_SDD);
- bad_config = 0;
- break;
- }
- break;
-
- case PERIPH_ID_SDMMC4:
- switch (config) {
- case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
- pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
- pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);
-
- pinmux_tristate_disable(PINGRP_ATC);
- pinmux_tristate_disable(PINGRP_ATD);
- break;
-
- case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
- pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
- pinmux_tristate_disable(PINGRP_GME);
- /* fall through */
-
- case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
- pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
- pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
-
- pinmux_tristate_disable(PINGRP_ATB);
- pinmux_tristate_disable(PINGRP_GMA);
- bad_config = 0;
- break;
- }
- break;
-
- default:
- debug("%s: invalid periph_id %d", __func__, id);
- return -1;
- }
-
- if (bad_config) {
- debug("%s: invalid config %d for periph_id %d", __func__,
- config, id);
- return -1;
- }
-
- return 0;
-}
diff --git a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S b/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
deleted file mode 100644
index 6b86647..0000000
--- a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SoC-specific setup info
- *
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * 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
- */
-
-#include <config.h>
-#include <version.h>
-
- .align 5
-.global reset_cpu
-reset_cpu:
- ldr r1, rstctl @ get addr for global reset
- @ reg
- ldr r3, [r1]
- orr r3, r3, #0x10
- str r3, [r1] @ force reset
- mov r0, r0
-_loop_forever:
- b _loop_forever
-rstctl:
- .word PRM_RSTCTRL
diff --git a/arch/arm/cpu/armv7/tegra2/pinmux.c b/arch/arm/cpu/armv7/tegra2/pinmux.c
deleted file mode 100644
index b053f90..0000000
--- a/arch/arm/cpu/armv7/tegra2/pinmux.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * 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 pin multiplexing functions */
-
-#include <asm/io.h>
-#include <asm/arch/tegra2.h>
-#include <asm/arch/pinmux.h>
-#include <common.h>
-
-
-/*
- * This defines the order of the pin mux control bits in the registers. For
- * some reason there is no correspendence between the tristate, pin mux and
- * pullup/pulldown registers.
- */
-enum pmux_ctlid {
- /* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */
- MUXCTL_UAA,
- MUXCTL_UAB,
- MUXCTL_UAC,
- MUXCTL_UAD,
- MUXCTL_UDA,
- MUXCTL_RESERVED5,
- MUXCTL_ATE,
- MUXCTL_RM,
-
- MUXCTL_ATB,
- MUXCTL_RESERVED9,
- MUXCTL_ATD,
- MUXCTL_ATC,
- MUXCTL_ATA,
- MUXCTL_KBCF,
- MUXCTL_KBCE,
- MUXCTL_SDMMC1,
-
- /* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */
- MUXCTL_GMA,
- MUXCTL_GMC,
- MUXCTL_HDINT,
- MUXCTL_SLXA,
- MUXCTL_OWC,
- MUXCTL_SLXC,
- MUXCTL_SLXD,
- MUXCTL_SLXK,
-
- MUXCTL_UCA,
- MUXCTL_UCB,
- MUXCTL_DTA,
- MUXCTL_DTB,
- MUXCTL_RESERVED28,
- MUXCTL_DTC,
- MUXCTL_DTD,
- MUXCTL_DTE,
-
- /* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */
- MUXCTL_DDC,
- MUXCTL_CDEV1,
- MUXCTL_CDEV2,
- MUXCTL_CSUS,
- MUXCTL_I2CP,
- MUXCTL_KBCA,
- MUXCTL_KBCB,
- MUXCTL_KBCC,
-
- MUXCTL_IRTX,
- MUXCTL_IRRX,
- MUXCTL_DAP1,
- MUXCTL_DAP2,
- MUXCTL_DAP3,
- MUXCTL_DAP4,
- MUXCTL_GMB,
- MUXCTL_GMD,
-
- /* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */
- MUXCTL_GME,
- MUXCTL_GPV,
- MUXCTL_GPU,
- MUXCTL_SPDO,
- MUXCTL_SPDI,
- MUXCTL_SDB,
- MUXCTL_SDC,
- MUXCTL_SDD,
-
- MUXCTL_SPIH,
- MUXCTL_SPIG,
- MUXCTL_SPIF,
- MUXCTL_SPIE,
- MUXCTL_SPID,
- MUXCTL_SPIC,
- MUXCTL_SPIB,
- MUXCTL_SPIA,
-
- /* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */
- MUXCTL_LPW0,
- MUXCTL_LPW1,
- MUXCTL_LPW2,
- MUXCTL_LSDI,
- MUXCTL_LSDA,
- MUXCTL_LSPI,
- MUXCTL_LCSN,
- MUXCTL_LDC,
-
- MUXCTL_LSCK,
- MUXCTL_LSC0,
- MUXCTL_LSC1,
- MUXCTL_LHS,
- MUXCTL_LVS,
- MUXCTL_LM0,
- MUXCTL_LM1,
- MUXCTL_LVP0,
-
- /* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */
- MUXCTL_LD0,
- MUXCTL_LD1,
- MUXCTL_LD2,
- MUXCTL_LD3,
- MUXCTL_LD4,
- MUXCTL_LD5,
- MUXCTL_LD6,
- MUXCTL_LD7,
-
- MUXCTL_LD8,
- MUXCTL_LD9,
- MUXCTL_LD10,
- MUXCTL_LD11,
- MUXCTL_LD12,
- MUXCTL_LD13,
- MUXCTL_LD14,
- MUXCTL_LD15,
-
- /* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */
- MUXCTL_LD16,
- MUXCTL_LD17,
- MUXCTL_LHP1,
- MUXCTL_LHP2,
- MUXCTL_LVP1,
- MUXCTL_LHP0,
- MUXCTL_RESERVED102,
- MUXCTL_LPP,
-
- MUXCTL_LDI,
- MUXCTL_PMC,
- MUXCTL_CRTP,
- MUXCTL_PTA,
- MUXCTL_RESERVED108,
- MUXCTL_KBCD,
- MUXCTL_GPU7,
- MUXCTL_DTF,
-
- MUXCTL_NONE = -1,
-};
-
-/*
- * And this defines the order of the pullup/pulldown controls which are again
- * in a different order
- */
-enum pmux_pullid {
- /* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */
- PUCTL_ATA,
- PUCTL_ATB,
- PUCTL_ATC,
- PUCTL_ATD,
- PUCTL_ATE,
- PUCTL_DAP1,
- PUCTL_DAP2,
- PUCTL_DAP3,
-
- PUCTL_DAP4,
- PUCTL_DTA,
- PUCTL_DTB,
- PUCTL_DTC,
- PUCTL_DTD,
- PUCTL_DTE,
- PUCTL_DTF,
- PUCTL_GPV,
-
- /* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */
- PUCTL_RM,
- PUCTL_I2CP,
- PUCTL_PTA,
- PUCTL_GPU7,
- PUCTL_KBCA,
- PUCTL_KBCB,
- PUCTL_KBCC,
- PUCTL_KBCD,
-
- PUCTL_SPDI,
- PUCTL_SPDO,
- PUCTL_GPSLXAU,
- PUCTL_CRTP,
- PUCTL_SLXC,
- PUCTL_SLXD,
- PUCTL_SLXK,
-
- /* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */
- PUCTL_CDEV1,
- PUCTL_CDEV2,
- PUCTL_SPIA,
- PUCTL_SPIB,
- PUCTL_SPIC,
- PUCTL_SPID,
- PUCTL_SPIE,
- PUCTL_SPIF,
-
- PUCTL_SPIG,
- PUCTL_SPIH,
- PUCTL_IRTX,
- PUCTL_IRRX,
- PUCTL_GME,
- PUCTL_RESERVED45,
- PUCTL_XM2D,
- PUCTL_XM2C,
-
- /* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */
- PUCTL_UAA,
- PUCTL_UAB,
- PUCTL_UAC,
- PUCTL_UAD,
- PUCTL_UCA,
- PUCTL_UCB,
- PUCTL_LD17,
- PUCTL_LD19_18,
-
- PUCTL_LD21_20,
- PUCTL_LD23_22,
- PUCTL_LS,
- PUCTL_LC,
- PUCTL_CSUS,
- PUCTL_DDRC,
- PUCTL_SDC,
- PUCTL_SDD,
-
- /* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */
- PUCTL_KBCF,
- PUCTL_KBCE,
- PUCTL_PMCA,
- PUCTL_PMCB,
- PUCTL_PMCC,
- PUCTL_PMCD,
- PUCTL_PMCE,
- PUCTL_CK32,
-
- PUCTL_UDA,
- PUCTL_SDMMC1,
- PUCTL_GMA,
- PUCTL_GMB,
- PUCTL_GMC,
- PUCTL_GMD,
- PUCTL_DDC,
- PUCTL_OWC,
-
- PUCTL_NONE = -1
-};
-
-struct tegra_pingroup_desc {
- const char *name;
- enum pmux_func funcs[4];
- enum pmux_func func_safe;
- enum pmux_vddio vddio;
- enum pmux_ctlid ctl_id;
- enum pmux_pullid pull_id;
-};
-
-
-/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */
-#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5)
-
-/* Mask value for a tristate (within TRISTATE_REG(id)) */
-#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f))
-
-/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */
-#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4)
-
-/* Converts a PUCTL id to a shift position */
-#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f)
-
-/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */
-#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4)
-
-/* Converts a MUXCTL id to a shift position */
-#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f)
-
-/* Convenient macro for defining pin group properties */
-#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd) \
- { \
- .vddio = PMUX_VDDIO_ ## vdd, \
- .funcs = { \
- PMUX_FUNC_ ## f0, \
- PMUX_FUNC_ ## f1, \
- PMUX_FUNC_ ## f2, \
- PMUX_FUNC_ ## f3, \
- }, \
- .func_safe = PMUX_FUNC_ ## f_safe, \
- .ctl_id = mux, \
- .pull_id = pupd \
- }
-
-/* A normal pin group where the mux name and pull-up name match */
-#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe) \
- PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \
- MUXCTL_ ## pg_name, PUCTL_ ## pg_name)
-
-/* A pin group where the pull-up name doesn't have a 1-1 mapping */
-#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd) \
- PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \
- MUXCTL_ ## pg_name, PUCTL_ ## pupd)
-
-/* A pin group number which is not used */
-#define PIN_RESERVED \
- PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE)
-
-const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
- PIN(ATA, NAND, IDE, NAND, GMI, RSVD, IDE),
- PIN(ATB, NAND, IDE, NAND, GMI, SDIO4, IDE),
- PIN(ATC, NAND, IDE, NAND, GMI, SDIO4, IDE),
- PIN(ATD, NAND, IDE, NAND, GMI, SDIO4, IDE),
- PIN(CDEV1, AUDIO, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC),
- PIN(CDEV2, AUDIO, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, OSC),
- PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK,
- PLLC_OUT1),
- PIN(DAP1, AUDIO, DAP1, RSVD, GMI, SDIO2, DAP1),
-
- PIN(DAP2, AUDIO, DAP2, TWC, RSVD, GMI, DAP2),
- PIN(DAP3, BB, DAP3, RSVD, RSVD, RSVD, DAP3),
- PIN(DAP4, UART, DAP4, RSVD, GMI, RSVD, DAP4),
- PIN(DTA, VI, RSVD, SDIO2, VI, RSVD, RSVD4),
- PIN(DTB, VI, RSVD, RSVD, VI, SPI1, RSVD1),
- PIN(DTC, VI, RSVD, RSVD, VI, RSVD, RSVD1),
- PIN(DTD, VI, RSVD, SDIO2, VI, RSVD, RSVD1),
- PIN(DTE, VI, RSVD, RSVD, VI, SPI1, RSVD1),
-
- PINP(GPU, UART, PWM, UARTA, GMI, RSVD, RSVD4,
- GPSLXAU),
- PIN(GPV, SD, PCIE, RSVD, RSVD, RSVD, PCIE),
- PIN(I2CP, SYS, I2C, RSVD, RSVD, RSVD, RSVD4),
- PIN(IRTX, UART, UARTA, UARTB, GMI, SPI4, UARTB),
- PIN(IRRX, UART, UARTA, UARTB, GMI, SPI4, UARTB),
- PIN(KBCB, SYS, KBC, NAND, SDIO2, MIO, KBC),
- PIN(KBCA, SYS, KBC, NAND, SDIO2, EMC_TEST0_DLL, KBC),
- PINP(PMC, SYS, PWR_ON, PWR_INTR, RSVD, RSVD, PWR_ON, NONE),
-
- PIN(PTA, NAND, I2C2, HDMI, GMI, RSVD, RSVD4),
- PIN(RM, UART, I2C, RSVD, RSVD, RSVD, RSVD4),
- PIN(KBCE, SYS, KBC, NAND, OWR, RSVD, KBC),
- PIN(KBCF, SYS, KBC, NAND, TRACE, MIO, KBC),
- PIN(GMA, NAND, UARTE, SPI3, GMI, SDIO4, SPI3),
- PIN(GMC, NAND, UARTD, SPI4, GMI, SFLASH, SPI4),
- PIN(SDMMC1, BB, SDIO1, RSVD, UARTE, UARTA, RSVD2),
- PIN(OWC, SYS, OWR, RSVD, RSVD, RSVD, OWR),
-
- PIN(GME, NAND, RSVD, DAP5, GMI, SDIO4, GMI),
- PIN(SDC, SD, PWM, TWC, SDIO3, SPI3, TWC),
- PIN(SDD, SD, UARTA, PWM, SDIO3, SPI3, PWM),
- PIN_RESERVED,
- PINP(SLXA, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, CRTP),
- PIN(SLXC, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4),
- PIN(SLXD, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4),
- PIN(SLXK, SD, PCIE, SPI4, SDIO3, SPI2, PCIE),
-
- PIN(SPDI, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2),
- PIN(SPDO, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2),
- PIN(SPIA, AUDIO, SPI1, SPI2, SPI3, GMI, GMI),
- PIN(SPIB, AUDIO, SPI1, SPI2, SPI3, GMI, GMI),
- PIN(SPIC, AUDIO, SPI1, SPI2, SPI3, GMI, GMI),
- PIN(SPID, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI),
- PIN(SPIE, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI),
- PIN(SPIF, AUDIO, SPI3, SPI1, SPI2, RSVD, RSVD4),
-
- PIN(SPIG, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT),
- PIN(SPIH, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT),
- PIN(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS),
- PIN(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS),
- PIN(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4),
- PIN(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF),
- PIN(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4),
- PIN(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4),
-
- PIN_RESERVED,
- PIN(ATE, NAND, IDE, NAND, GMI, RSVD, IDE),
- PIN(KBCC, SYS, KBC, NAND, TRACE, EMC_TEST1_DLL, KBC),
- PIN_RESERVED,
- PIN_RESERVED,
- PIN(GMB, NAND, IDE, NAND, GMI, GMI_INT, GMI),
- PIN(GMD, NAND, RSVD, NAND, GMI, SFLASH, GMI),
- PIN(DDC, LCD, I2C2, RSVD, RSVD, RSVD, RSVD4),
-
- /* 64 */
- PINP(LD0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD1, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD2, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD3, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD4, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD5, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD6, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD7, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
-
- PINP(LD8, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD9, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD10, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD11, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD12, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD13, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD14, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD15, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
-
- PINP(LD16, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
- PINP(LD17, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD17),
- PINP(LHP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20),
- PINP(LHP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18),
- PINP(LHP2, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18),
- PINP(LVP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LC),
- PINP(LVP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20),
- PINP(HDINT, LCD, HDMI, RSVD, RSVD, RSVD, HDMI , LC),
-
- PINP(LM0, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LC),
- PINP(LM1, LCD, DISPA, DISPB, RSVD, CRT, RSVD3, LC),
- PINP(LVS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC),
- PINP(LSC0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC),
- PINP(LSC1, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
- PINP(LSCK, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
- PINP(LDC, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS),
- PINP(LCSN, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LS),
-
- /* 96 */
- PINP(LSPI, LCD, DISPA, DISPB, XIO, HDMI, DISPA, LC),
- PINP(LSDA, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
- PINP(LSDI, LCD, DISPA, DISPB, SPI3, RSVD, DISPA, LS),
- PINP(LPW0, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
- PINP(LPW1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS),
- PINP(LPW2, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
- PINP(LDI, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22),
- PINP(LHS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC),
-
- PINP(LPP, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22),
- PIN_RESERVED,
- PIN(KBCD, SYS, KBC, NAND, SDIO2, MIO, KBC),
- PIN(GPU7, SYS, RTCK, RSVD, RSVD, RSVD, RTCK),
- PIN(DTF, VI, I2C3, RSVD, VI, RSVD, RSVD4),
- PIN(UDA, BB, SPI1, RSVD, UARTD, ULPI, RSVD2),
- PIN(CRTP, LCD, CRT, RSVD, RSVD, RSVD, RSVD),
- PINP(SDB, SD, UARTA, PWM, SDIO3, SPI2, PWM, NONE),
-
- /* these pin groups only have pullup and pull down control */
- PINALL(CK32, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(DDRC, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(PMCA, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(PMCB, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(PMCC, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(PMCD, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(PMCE, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
- PINALL(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
- PUCTL_NONE),
-};
-
-void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
-{
- struct pmux_tri_ctlr *pmt =
- (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
- u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)];
- u32 reg;
-
- reg = readl(tri);
- if (enable)
- reg |= TRISTATE_MASK(pin);
- else
- reg &= ~TRISTATE_MASK(pin);
- writel(reg, tri);
-}
-
-void pinmux_tristate_enable(enum pmux_pingrp pin)
-{
- pinmux_set_tristate(pin, 1);
-}
-
-void pinmux_tristate_disable(enum pmux_pingrp pin)
-{
- pinmux_set_tristate(pin, 0);
-}
-
-void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
-{
- struct pmux_tri_ctlr *pmt =
- (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
- enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id;
- u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)];
- u32 mask_bit;
- u32 reg;
- mask_bit = PULL_SHIFT(pull_id);
-
- reg = readl(pull);
- reg &= ~(0x3 << mask_bit);
- reg |= pupd << mask_bit;
- writel(reg, pull);
-}
-
-void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
-{
- struct pmux_tri_ctlr *pmt =
- (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
- enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id;
- u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)];
- u32 mask_bit;
- int i, mux = -1;
- u32 reg;
-
- assert(pmux_func_isvalid(func));
-
- /* Handle special values */
- if (func >= PMUX_FUNC_RSVD1) {
- mux = (func - PMUX_FUNC_RSVD1) & 0x3;
- } else {
- /* Search for the appropriate function */
- for (i = 0; i < 4; i++) {
- if (tegra_soc_pingroups[pin].funcs[i] == func) {
- mux = i;
- break;
- }
- }
- }
- assert(mux != -1);
-
- mask_bit = MUXCTL_SHIFT(mux_id);
- reg = readl(muxctl);
- reg &= ~(0x3 << mask_bit);
- reg |= mux << mask_bit;
- writel(reg, muxctl);
-}
-
-void pinmux_config_pingroup(struct pingroup_config *config)
-{
- enum pmux_pingrp pin = config->pingroup;
-
- pinmux_set_func(pin, config->func);
- pinmux_set_pullupdown(pin, config->pull);
- pinmux_set_tristate(pin, config->tristate);
-}
-
-void pinmux_config_table(struct pingroup_config *config, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- pinmux_config_pingroup(&config[i]);
-}
diff --git a/arch/arm/cpu/armv7/tegra2/sys_info.c b/arch/arm/cpu/armv7/tegra2/sys_info.c
deleted file mode 100644
index 6d11dc1..0000000
--- a/arch/arm/cpu/armv7/tegra2/sys_info.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * 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
- */
-
-#include <common.h>
-
-#ifdef CONFIG_DISPLAY_CPUINFO
-/* Print CPU information */
-int print_cpuinfo(void)
-{
- puts("TEGRA2\n");
-
- /* TBD: Add printf of major/minor rev info, stepping, etc. */
- return 0;
-}
-#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c
deleted file mode 100644
index b12b12c..0000000
--- a/arch/arm/cpu/armv7/tegra2/timer.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * (C) Copyright 2008
- * Texas Instruments
- *
- * Richard Woodruff <r-woodruff2 at ti.com>
- * Syed Moahmmed Khasim <khasim at ti.com>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger at sysgo.de>
- * Alex Zuepke <azu at sysgo.de>
- *
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <garyj at denx.de>
- *
- * 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
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/tegra2.h>
-#include <asm/arch/timer.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/* counter runs at 1MHz */
-#define TIMER_CLK 1000000
-#define TIMER_LOAD_VAL 0xffffffff
-
-/* timer without interrupts */
-ulong get_timer(ulong base)
-{
- return get_timer_masked() - base;
-}
-
-/* delay x useconds */
-void __udelay(unsigned long usec)
-{
- long tmo = usec * (TIMER_CLK / 1000) / 1000;
- unsigned long now, last = timer_get_us();
-
- while (tmo > 0) {
- now = timer_get_us();
- if (last > now) /* count up timer overflow */
- tmo -= TIMER_LOAD_VAL - last + now;
- else
- tmo -= now - last;
- last = now;
- }
-}
-
-ulong get_timer_masked(void)
-{
- ulong now;
-
- /* current tick value */
- now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
-
- if (now >= gd->lastinc) /* normal mode (non roll) */
- /* move stamp forward with absolute diff ticks */
- gd->tbl += (now - gd->lastinc);
- else /* we have rollover of incrementer */
- gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ))
- - gd->lastinc) + now;
- gd->lastinc = now;
- return gd->tbl;
-}
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-unsigned long long get_ticks(void)
-{
- return get_timer(0);
-}
-
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
- return CONFIG_SYS_HZ;
-}
-
-unsigned long timer_get_us(void)
-{
- struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
-
- return readl(&timer_base->cntr_1us);
-}
diff --git a/arch/arm/cpu/tegra2-common/Makefile b/arch/arm/cpu/tegra2-common/Makefile
new file mode 100644
index 0000000..8de59cf
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/Makefile
@@ -0,0 +1,56 @@
+#
+# (C) Copyright 2010,2011 Nvidia Corporation.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+# The AVP is ARMv4T architecture so we must use special compiler
+# flags for any startup files it might use.
+CFLAGS_arch/arm/cpu/tegra2-common/ap20.o += -march=armv4t
+CFLAGS_arch/arm/cpu/tegra2-common/clock.o += -march=armv4t
+
+LIB = $(obj)lib$(SOC)-common.o
+
+SOBJS += lowlevel_init.o
+COBJS-y += ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+$(obj).depend:
+ echo wtf
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/tegra2-common/ap20.c b/arch/arm/cpu/tegra2-common/ap20.c
new file mode 100644
index 0000000..b749821
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/ap20.c
@@ -0,0 +1,324 @@
+/*
+* (C) Copyright 2010-2011
+* NVIDIA Corporation <www.nvidia.com>
+*
+* 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
+*/
+
+#include "ap20.h"
+#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>
+#include <common.h>
+
+/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
+static int ap20_cpu_is_cortexa9(void)
+{
+ u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
+ return id == (PG_UP_TAG_0_PID_CPU & 0xff);
+}
+
+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_ID_XCPU];
+ u32 reg;
+
+ /* If PLLX is already enabled, just return */
+ if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
+ return;
+
+ /* Set PLLX_MISC */
+ writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
+
+ /* Use 12MHz clock here */
+ reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
+ reg |= 1000 << PLL_DIVN_SHIFT;
+ writel(reg, &pll->pll_base);
+
+ reg |= PLL_ENABLE_MASK;
+ writel(reg, &pll->pll_base);
+
+ reg &= ~PLL_BYPASS_MASK;
+ 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 clk;
+
+ /*
+ * NOTE:
+ * Regardless of whether the request is to enable or disable the CPU
+ * clock, every processor in the CPU complex except the master (CPU 0)
+ * will have it's clock stopped because the AVP only talks to the
+ * master. The AVP does not know (nor does it need to know) that there
+ * are multiple processors in the CPU complex.
+ */
+
+ if (enable) {
+ /* Initialize PLLX */
+ init_pllx();
+
+ /* Wait until all clocks are stable */
+ udelay(PLL_STABILIZATION_DELAY);
+
+ writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+ writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
+ }
+
+ /*
+ * Read the register containing the individual CPU clock enables and
+ * always stop the clock to CPU 1.
+ */
+ clk = readl(&clkrst->crc_clk_cpu_cmplx);
+ clk |= 1 << CPU1_CLK_STP_SHIFT;
+
+ /* Stop/Unstop the CPU clock */
+ clk &= ~CPU0_CLK_STP_MASK;
+ clk |= !enable << CPU0_CLK_STP_SHIFT;
+ writel(clk, &clkrst->crc_clk_cpu_cmplx);
+
+ clock_enable(PERIPH_ID_CPU);
+}
+
+static int is_cpu_powered(void)
+{
+ struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+
+ return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
+}
+
+static void remove_cpu_io_clamps(void)
+{
+ struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+ u32 reg;
+
+ /* Remove the clamps on the CPU I/O signals */
+ reg = readl(&pmc->pmc_remove_clamping);
+ reg |= CPU_CLMP;
+ writel(reg, &pmc->pmc_remove_clamping);
+
+ /* Give I/O signals time to stabilize */
+ udelay(IO_STABILIZATION_DELAY);
+}
+
+static void powerup_cpu(void)
+{
+ struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+ u32 reg;
+ int timeout = IO_STABILIZATION_DELAY;
+
+ if (!is_cpu_powered()) {
+ /* Toggle the CPU power state (OFF -> ON) */
+ reg = readl(&pmc->pmc_pwrgate_toggle);
+ reg &= PARTID_CP;
+ reg |= START_CP;
+ writel(reg, &pmc->pmc_pwrgate_toggle);
+
+ /* Wait for the power to come up */
+ while (!is_cpu_powered()) {
+ if (timeout-- == 0)
+ printf("CPU failed to power up!\n");
+ else
+ udelay(10);
+ }
+
+ /*
+ * Remove the I/O clamps from CPU power partition.
+ * Recommended only on a Warm boot, if the CPU partition gets
+ * power gated. Shouldn't cause any harm when called after a
+ * cold boot according to HW, probably just redundant.
+ */
+ remove_cpu_io_clamps();
+ }
+}
+
+static void enable_cpu_power_rail(void)
+{
+ struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+ u32 reg;
+
+ reg = readl(&pmc->pmc_cntrl);
+ reg |= CPUPWRREQ_OE;
+ writel(reg, &pmc->pmc_cntrl);
+
+ /*
+ * The TI PMU65861C needs a 3.75ms delay between enabling
+ * the power rail and enabling the CPU clock. This delay
+ * between SM1EN and SM1 is for switching time + the ramp
+ * up of the voltage to the CPU (VDD_CPU from PMU).
+ */
+ udelay(3750);
+}
+
+static void reset_A9_cpu(int reset)
+{
+ /*
+ * NOTE: Regardless of whether the request is to hold the CPU in reset
+ * or take it out of reset, every processor in the CPU complex
+ * except the master (CPU 0) will be held in reset because the
+ * AVP only talks to the master. The AVP does not know that there
+ * are multiple processors in the CPU complex.
+ */
+
+ /* Hold CPU 1 in reset, and CPU 0 if asked */
+ reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
+ reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
+ reset);
+
+ /* Enable/Disable master CPU reset */
+ reset_set_enable(PERIPH_ID_CPU, reset);
+}
+
+static void clock_enable_coresight(int enable)
+{
+ u32 rst, src;
+
+ clock_set_enable(PERIPH_ID_CORESIGHT, enable);
+ reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
+
+ if (enable) {
+ /*
+ * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
+ * 1.5, giving an effective frequency of 144MHz.
+ * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
+ * (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
+ */
+ src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
+ clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
+
+ /* Unlock the CPU CoreSight interfaces */
+ rst = 0xC5ACCE55;
+ writel(rst, CSITE_CPU_DBG0_LAR);
+ writel(rst, CSITE_CPU_DBG1_LAR);
+ }
+}
+
+void start_cpu(u32 reset_vector)
+{
+ /* Enable VDD_CPU */
+ enable_cpu_power_rail();
+
+ /* Hold the CPUs in reset */
+ reset_A9_cpu(1);
+
+ /* Disable the CPU clock */
+ enable_cpu_clock(0);
+
+ /* Enable CoreSight */
+ clock_enable_coresight(1);
+
+ /*
+ * Set the entry point for CPU execution from reset,
+ * if it's a non-zero value.
+ */
+ if (reset_vector)
+ writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+ /* Enable the CPU clock */
+ enable_cpu_clock(1);
+
+ /* If the CPU doesn't already have power, power it up */
+ powerup_cpu();
+
+ /* Take the CPU out of reset */
+ reset_A9_cpu(0);
+}
+
+
+void halt_avp(void)
+{
+ for (;;) {
+ writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
+ | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
+ FLOW_CTLR_HALT_COP_EVENTS);
+ }
+}
+
+void enable_scu(void)
+{
+ struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
+ u32 reg;
+
+ /* If SCU already setup/enabled, return */
+ if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE)
+ return;
+
+ /* Invalidate all ways for all processors */
+ writel(0xFFFF, &scu->scu_inv_all);
+
+ /* Enable SCU - bit 0 */
+ reg = readl(&scu->scu_ctrl);
+ reg |= SCU_CTRL_ENABLE;
+ writel(reg, &scu->scu_ctrl);
+}
+
+void init_pmc_scratch(void)
+{
+ struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+ int i;
+
+ /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
+ for (i = 0; i < 23; i++)
+ writel(0, &pmc->pmc_scratch1+i);
+
+ /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
+ writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
+}
+
+void tegra2_start(void)
+{
+ struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+
+ /* If we are the AVP, start up the first Cortex-A9 */
+ if (!ap20_cpu_is_cortexa9()) {
+ /* enable JTAG */
+ writel(0xC0, &pmt->pmt_cfg_ctl);
+
+ /*
+ * If we are ARM7 - give it a different stack. We are about to
+ * start up the A9 which will want to use this one.
+ */
+ asm volatile("mov sp, %0\n"
+ : : "r"(AVP_EARLY_BOOT_STACK_LIMIT));
+
+ start_cpu((u32)_start);
+ halt_avp();
+ /* not reached */
+ }
+
+ /* Init PMC scratch memory */
+ init_pmc_scratch();
+
+ enable_scu();
+
+ /* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */
+ asm volatile(
+ "mrc p15, 0, r0, c1, c0, 1\n"
+ "orr r0, r0, #0x41\n"
+ "mcr p15, 0, r0, c1, c0, 1\n");
+
+ /* FIXME: should have ap20's L2 disabled too? */
+}
diff --git a/arch/arm/cpu/tegra2-common/ap20.h b/arch/arm/cpu/tegra2-common/ap20.h
new file mode 100644
index 0000000..a4b4d73
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/ap20.h
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2010-2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * 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
+ */
+#include <asm/types.h>
+
+/* Stabilization delays, in usec */
+#define PLL_STABILIZATION_DELAY (300)
+#define IO_STABILIZATION_DELAY (1000)
+
+#define NVBL_PLLP_KHZ (216000)
+
+#define PLLX_ENABLED (1 << 30)
+#define CCLK_BURST_POLICY 0x20008888
+#define SUPER_CCLK_DIVIDER 0x80000000
+
+/* Calculate clock fractional divider value from ref and target frequencies */
+#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
+
+/* Calculate clock frequency value from reference and clock divider value */
+#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
+
+/* AVP/CPU ID */
+#define PG_UP_TAG_0_PID_CPU 0x55555555 /* CPU aka "a9" aka "mpcore" */
+#define PG_UP_TAG_0 0x0
+
+#define CORESIGHT_UNLOCK 0xC5ACCE55;
+
+/* AP20-Specific Base Addresses */
+
+/* AP20 Base physical address of SDRAM. */
+#define AP20_BASE_PA_SDRAM 0x00000000
+/* AP20 Base physical address of internal SRAM. */
+#define AP20_BASE_PA_SRAM 0x40000000
+/* AP20 Size of internal SRAM (256KB). */
+#define AP20_BASE_PA_SRAM_SIZE 0x00040000
+/* AP20 Base physical address of flash. */
+#define AP20_BASE_PA_NOR_FLASH 0xD0000000
+/* AP20 Base physical address of boot information table. */
+#define AP20_BASE_PA_BOOT_INFO AP20_BASE_PA_SRAM
+
+/*
+ * Super-temporary stacks for EXTREMELY early startup. The values chosen for
+ * these addresses must be valid on ALL SOCs because this value is used before
+ * we are able to differentiate between the SOC types.
+ *
+ * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
+ * stack is placed below the AVP stack. Once the CPU stack has been moved,
+ * the AVP is free to use the IRAM the CPU stack previously occupied if
+ * it should need to do so.
+ *
+ * NOTE: In multi-processor CPU complex configurations, each processor will have
+ * its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
+ * limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
+ * stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
+ * CPU.
+ */
+
+/* Common AVP early boot stack limit */
+#define AVP_EARLY_BOOT_STACK_LIMIT \
+ (AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
+/* Common AVP early boot stack size */
+#define AVP_EARLY_BOOT_STACK_SIZE 0x1000
+/* Common CPU early boot stack limit */
+#define CPU_EARLY_BOOT_STACK_LIMIT \
+ (AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
+/* Common CPU early boot stack size */
+#define CPU_EARLY_BOOT_STACK_SIZE 0x1000
+
+#define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100)
+#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0)
+#define CSITE_CPU_DBG1_LAR (NV_PA_CSITE_BASE + 0x12FB0)
+
+#define FLOW_CTLR_HALT_COP_EVENTS (NV_PA_FLOW_BASE + 4)
+#define FLOW_MODE_STOP 2
+#define HALT_COP_EVENT_JTAG (1 << 28)
+#define HALT_COP_EVENT_IRQ_1 (1 << 11)
+#define HALT_COP_EVENT_FIQ_1 (1 << 9)
+
+/* Start up the tegra2 SOC */
+void tegra2_start(void);
+
+/* This is the main entry into U-Boot, used by the Cortex-A9 */
+extern void _start(void);
diff --git a/arch/arm/cpu/tegra2-common/board.c b/arch/arm/cpu/tegra2-common/board.c
new file mode 100644
index 0000000..a797e6f
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/board.c
@@ -0,0 +1,151 @@
+/*
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include "ap20.h"
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/pmc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+ /* UARTs which we can enable */
+ UARTA = 1 << 0,
+ UARTB = 1 << 1,
+ UARTD = 1 << 3,
+ UART_COUNT = 4,
+};
+
+/*
+ * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0,
+ * so we are using this value to identify memory size.
+ */
+
+unsigned int query_sdram_size(void)
+{
+ struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+ u32 reg;
+
+ reg = readl(&pmc->pmc_scratch20);
+ debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
+
+ /* bits 31:28 in OdmData are used for RAM size */
+ switch ((reg) >> 28) {
+ case 1:
+ return 0x10000000; /* 256 MB */
+ case 2:
+ default:
+ return 0x20000000; /* 512 MB */
+ case 3:
+ return 0x40000000; /* 1GB */
+ }
+}
+
+int dram_init(void)
+{
+ /* We do not initialise DRAM here. We just query the size */
+ gd->ram_size = query_sdram_size();
+ return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+ printf("Board: %s\n", sysinfo.board_string);
+ return 0;
+}
+#endif /* CONFIG_DISPLAY_BOARDINFO */
+
+#ifdef CONFIG_ARCH_CPU_INIT
+/*
+ * Note this function is executed by the ARM7TDMI AVP. It does not return
+ * in this case. It is also called once the A9 starts up, but does nothing in
+ * that case.
+ */
+int arch_cpu_init(void)
+{
+ /* Fire up the Cortex A9 */
+ tegra2_start();
+
+ /* We didn't do this init in start.S, so do it now */
+ cpu_init_cp15();
+
+ /* Initialize essential common plls */
+ clock_early_init();
+
+ return 0;
+}
+#endif
+
+/**
+ * Set up the specified uarts
+ *
+ * @param uarts_ids Mask containing UARTs to init (UARTx)
+ */
+static void setup_uarts(int uart_ids)
+{
+ static enum periph_id id_for_uart[] = {
+ PERIPH_ID_UART1,
+ PERIPH_ID_UART2,
+ PERIPH_ID_UART3,
+ PERIPH_ID_UART4,
+ };
+ size_t i;
+
+ for (i = 0; i < UART_COUNT; i++) {
+ if (uart_ids & (1 << i)) {
+ enum periph_id id = id_for_uart[i];
+
+ funcmux_select(id, FUNCMUX_DEFAULT);
+ clock_ll_start_uart(id);
+ }
+ }
+}
+
+void board_init_uart_f(void)
+{
+ int uart_ids = 0; /* bit mask of which UART ids to enable */
+
+#ifdef CONFIG_TEGRA2_ENABLE_UARTA
+ uart_ids |= UARTA;
+#endif
+#ifdef CONFIG_TEGRA2_ENABLE_UARTB
+ uart_ids |= UARTB;
+#endif
+#ifdef CONFIG_TEGRA2_ENABLE_UARTD
+ uart_ids |= UARTD;
+#endif
+ setup_uarts(uart_ids);
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+ /* Enable D-cache. I-cache is already enabled in start.S */
+ dcache_enable();
+}
+#endif
diff --git a/arch/arm/cpu/tegra2-common/clock.c b/arch/arm/cpu/tegra2-common/clock.c
new file mode 100644
index 0000000..39376ab
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/clock.c
@@ -0,0 +1,1052 @@
+/*
+ * 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>
+#include <div64.h>
+#include <fdtdec.h>
+
+/*
+ * This is our record of the current clock rate of each clock. We don't
+ * fill all of these in since we are only really interested in clocks which
+ * we use as parents.
+ */
+static unsigned pll_rate[CLOCK_ID_COUNT];
+
+/*
+ * The oscillator frequency is fixed to one of four set values. Based on this
+ * the other clocks are set up appropriately.
+ */
+static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
+ 13000000,
+ 19200000,
+ 12000000,
+ 26000000,
+};
+
+/*
+ * Clock types that we can use as a source. The Tegra2 has muxes for the
+ * peripheral clocks, and in most cases there are four options for the clock
+ * source. This gives us a clock 'type' and exploits what commonality exists
+ * in the device.
+ *
+ * Letters are obvious, except for T which means CLK_M, and S which means the
+ * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
+ * datasheet) and PLL_M are different things. The former is the basic
+ * clock supplied to the SOC from an external oscillator. The latter is the
+ * memory clock PLL.
+ *
+ * See definitions in clock_id in the header file.
+ */
+enum clock_type_id {
+ CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */
+ CLOCK_TYPE_MCPA, /* and so on */
+ CLOCK_TYPE_MCPT,
+ CLOCK_TYPE_PCM,
+ CLOCK_TYPE_PCMT,
+ CLOCK_TYPE_PCMT16, /* CLOCK_TYPE_PCMT with 16-bit divider */
+ CLOCK_TYPE_PCXTS,
+ CLOCK_TYPE_PDCT,
+
+ CLOCK_TYPE_COUNT,
+ CLOCK_TYPE_NONE = -1, /* invalid clock type */
+};
+
+/* return 1 if a peripheral ID is in range */
+#define clock_type_id_isvalid(id) ((id) >= 0 && \
+ (id) < CLOCK_TYPE_COUNT)
+
+char pllp_valid = 1; /* PLLP is set up correctly */
+
+enum {
+ CLOCK_MAX_MUX = 4 /* number of source options for each clock */
+};
+
+/*
+ * Clock source mux for each clock type. This just converts our enum into
+ * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS
+ * is special as it has 5 sources. Since it also has a different number of
+ * bits in its register for the source, we just handle it with a special
+ * case in the code.
+ */
+#define CLK(x) CLOCK_ID_ ## x
+static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
+ { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC) },
+ { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO) },
+ { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC) },
+ { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE) },
+ { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) },
+ { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) },
+ { CLK(PERIPH), CLK(CGENERAL), CLK(XCPU), CLK(OSC) },
+ { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC) },
+};
+
+/*
+ * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is
+ * not in the header file since it is for purely internal use - we want
+ * callers to use the PERIPH_ID for all access to peripheral clocks to avoid
+ * confusion bewteen PERIPH_ID_... and PERIPHC_...
+ *
+ * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be
+ * confusing.
+ *
+ * Note to SOC vendors: perhaps define a unified numbering for peripherals and
+ * use it for reset, clock enable, clock source/divider and even pinmuxing
+ * if you can.
+ */
+enum periphc_internal_id {
+ /* 0x00 */
+ PERIPHC_I2S1,
+ PERIPHC_I2S2,
+ PERIPHC_SPDIF_OUT,
+ PERIPHC_SPDIF_IN,
+ PERIPHC_PWM,
+ PERIPHC_SPI1,
+ PERIPHC_SPI2,
+ PERIPHC_SPI3,
+
+ /* 0x08 */
+ PERIPHC_XIO,
+ PERIPHC_I2C1,
+ PERIPHC_DVC_I2C,
+ PERIPHC_TWC,
+ PERIPHC_0c,
+ PERIPHC_10, /* PERIPHC_SPI1, what is this really? */
+ PERIPHC_DISP1,
+ PERIPHC_DISP2,
+
+ /* 0x10 */
+ PERIPHC_CVE,
+ PERIPHC_IDE0,
+ PERIPHC_VI,
+ PERIPHC_1c,
+ PERIPHC_SDMMC1,
+ PERIPHC_SDMMC2,
+ PERIPHC_G3D,
+ PERIPHC_G2D,
+
+ /* 0x18 */
+ PERIPHC_NDFLASH,
+ PERIPHC_SDMMC4,
+ PERIPHC_VFIR,
+ PERIPHC_EPP,
+ PERIPHC_MPE,
+ PERIPHC_MIPI,
+ PERIPHC_UART1,
+ PERIPHC_UART2,
+
+ /* 0x20 */
+ PERIPHC_HOST1X,
+ PERIPHC_21,
+ PERIPHC_TVO,
+ PERIPHC_HDMI,
+ PERIPHC_24,
+ PERIPHC_TVDAC,
+ PERIPHC_I2C2,
+ PERIPHC_EMC,
+
+ /* 0x28 */
+ PERIPHC_UART3,
+ PERIPHC_29,
+ PERIPHC_VI_SENSOR,
+ PERIPHC_2b,
+ PERIPHC_2c,
+ PERIPHC_SPI4,
+ PERIPHC_I2C3,
+ PERIPHC_SDMMC3,
+
+ /* 0x30 */
+ PERIPHC_UART4,
+ PERIPHC_UART5,
+ PERIPHC_VDE,
+ PERIPHC_OWR,
+ PERIPHC_NOR,
+ PERIPHC_CSITE,
+
+ PERIPHC_COUNT,
+
+ PERIPHC_NONE = -1,
+};
+
+/* return 1 if a periphc_internal_id is in range */
+#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
+ (id) < PERIPHC_COUNT)
+
+/*
+ * Clock type for each peripheral clock source. We put the name in each
+ * record just so it is easy to match things up
+ */
+#define TYPE(name, type) type
+static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
+ /* 0x00 */
+ TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT),
+ TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT),
+ TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
+ TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM),
+ TYPE(PERIPHC_PWM, CLOCK_TYPE_PCXTS),
+ TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_SPI22, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_SPI3, CLOCK_TYPE_PCMT),
+
+ /* 0x08 */
+ TYPE(PERIPHC_XIO, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16),
+ TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16),
+ TYPE(PERIPHC_TWC, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_DISP1, CLOCK_TYPE_PDCT),
+ TYPE(PERIPHC_DISP2, CLOCK_TYPE_PDCT),
+
+ /* 0x10 */
+ TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT),
+ TYPE(PERIPHC_IDE0, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA),
+ TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA),
+
+ /* 0x18 */
+ TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA),
+ TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA),
+ TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT),
+
+ /* 0x20 */
+ TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT),
+ TYPE(PERIPHC_HDMI, CLOCK_TYPE_PDCT),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
+ TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16),
+ TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT),
+
+ /* 0x28 */
+ TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
+ TYPE(PERIPHC_SPI4, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16),
+ TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT),
+
+ /* 0x30 */
+ TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT),
+ TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT),
+};
+
+/*
+ * This array translates a periph_id to a periphc_internal_id
+ *
+ * Not present/matched up:
+ * uint vi_sensor; _VI_SENSOR_0, 0x1A8
+ * SPDIF - which is both 0x08 and 0x0c
+ *
+ */
+#define NONE(name) (-1)
+#define OFFSET(name, value) PERIPHC_ ## name
+static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
+ /* Low word: 31:0 */
+ NONE(CPU),
+ NONE(RESERVED1),
+ NONE(RESERVED2),
+ NONE(AC97),
+ NONE(RTC),
+ NONE(TMR),
+ PERIPHC_UART1,
+ PERIPHC_UART2, /* and vfir 0x68 */
+
+ /* 0x08 */
+ NONE(GPIO),
+ PERIPHC_SDMMC2,
+ NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */
+ PERIPHC_I2S1,
+ PERIPHC_I2C1,
+ PERIPHC_NDFLASH,
+ PERIPHC_SDMMC1,
+ PERIPHC_SDMMC4,
+
+ /* 0x10 */
+ PERIPHC_TWC,
+ PERIPHC_PWM,
+ PERIPHC_I2S2,
+ PERIPHC_EPP,
+ PERIPHC_VI,
+ PERIPHC_G2D,
+ NONE(USBD),
+ NONE(ISP),
+
+ /* 0x18 */
+ PERIPHC_G3D,
+ PERIPHC_IDE0,
+ PERIPHC_DISP2,
+ PERIPHC_DISP1,
+ PERIPHC_HOST1X,
+ NONE(VCP),
+ NONE(RESERVED30),
+ NONE(CACHE2),
+
+ /* Middle word: 63:32 */
+ NONE(MEM),
+ NONE(AHBDMA),
+ NONE(APBDMA),
+ NONE(RESERVED35),
+ NONE(KBC),
+ NONE(STAT_MON),
+ NONE(PMC),
+ NONE(FUSE),
+
+ /* 0x28 */
+ NONE(KFUSE),
+ NONE(SBC1), /* SBC1, 0x34, is this SPI1? */
+ PERIPHC_NOR,
+ PERIPHC_SPI1,
+ PERIPHC_SPI2,
+ PERIPHC_XIO,
+ PERIPHC_SPI3,
+ PERIPHC_DVC_I2C,
+
+ /* 0x30 */
+ NONE(DSI),
+ PERIPHC_TVO, /* also CVE 0x40 */
+ PERIPHC_MIPI,
+ PERIPHC_HDMI,
+ PERIPHC_CSITE,
+ PERIPHC_TVDAC,
+ PERIPHC_I2C2,
+ PERIPHC_UART3,
+
+ /* 0x38 */
+ NONE(RESERVED56),
+ PERIPHC_EMC,
+ NONE(USB2),
+ NONE(USB3),
+ PERIPHC_MPE,
+ PERIPHC_VDE,
+ NONE(BSEA),
+ NONE(BSEV),
+
+ /* Upper word 95:64 */
+ NONE(SPEEDO),
+ PERIPHC_UART4,
+ PERIPHC_UART5,
+ PERIPHC_I2C3,
+ PERIPHC_SPI4,
+ PERIPHC_SDMMC3,
+ NONE(PCIE),
+ PERIPHC_OWR,
+
+ /* 0x48 */
+ NONE(AFI),
+ NONE(CORESIGHT),
+ NONE(RESERVED74),
+ NONE(AVPUCQ),
+ NONE(RESERVED76),
+ NONE(RESERVED77),
+ NONE(RESERVED78),
+ NONE(RESERVED79),
+
+ /* 0x50 */
+ NONE(RESERVED80),
+ NONE(RESERVED81),
+ NONE(RESERVED82),
+ NONE(RESERVED83),
+ NONE(IRAMA),
+ NONE(IRAMB),
+ NONE(IRAMC),
+ NONE(IRAMD),
+
+ /* 0x58 */
+ NONE(CRAM2),
+};
+
+/*
+ * 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;
+}
+
+/* Returns a pointer to the registers of the given pll */
+static struct clk_pll *get_pll(enum clock_id clkid)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+
+ assert(clock_id_isvalid(clkid));
+ return &clkrst->crc_pll[clkid];
+}
+
+unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
+ u32 divp, u32 cpcon, u32 lfcon)
+{
+ struct clk_pll *pll = get_pll(clkid);
+ u32 data;
+
+ /*
+ * 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_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;
+}
+
+/* return 1 if a peripheral ID is in range and valid */
+static int clock_periph_id_isvalid(enum periph_id id)
+{
+ if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT)
+ printf("Peripheral id %d out of range\n", id);
+ else {
+ switch (id) {
+ case PERIPH_ID_RESERVED1:
+ case PERIPH_ID_RESERVED2:
+ case PERIPH_ID_RESERVED30:
+ case PERIPH_ID_RESERVED35:
+ case PERIPH_ID_RESERVED56:
+ case PERIPH_ID_RESERVED74:
+ case PERIPH_ID_RESERVED76:
+ case PERIPH_ID_RESERVED77:
+ case PERIPH_ID_RESERVED78:
+ case PERIPH_ID_RESERVED79:
+ case PERIPH_ID_RESERVED80:
+ case PERIPH_ID_RESERVED81:
+ case PERIPH_ID_RESERVED82:
+ case PERIPH_ID_RESERVED83:
+ printf("Peripheral id %d is reserved\n", id);
+ break;
+ default:
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Returns a pointer to the clock source register for a peripheral */
+static u32 *get_periph_source_reg(enum periph_id periph_id)
+{
+ struct clk_rst_ctlr *clkrst =
+ (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ enum periphc_internal_id internal_id;
+
+ assert(clock_periph_id_isvalid(periph_id));
+ internal_id = periph_id_to_internal_id[periph_id];
+ assert(internal_id != -1);
+ return &clkrst->crc_clk_src[internal_id];
+}
+
+void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
+ unsigned divisor)
+{
+ u32 *reg = get_periph_source_reg(periph_id);
+ u32 value;
+
+ value = readl(reg);
+
+ value &= ~OUT_CLK_SOURCE_MASK;
+ value |= source << OUT_CLK_SOURCE_SHIFT;
+
+ value &= ~OUT_CLK_DIVISOR_MASK;
+ value |= divisor << OUT_CLK_DIVISOR_SHIFT;
+
+ writel(value, reg);
+}
+
+void clock_ll_set_source(enum periph_id periph_id, unsigned source)
+{
+ u32 *reg = get_periph_source_reg(periph_id);
+
+ clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
+ source << OUT_CLK_SOURCE_SHIFT);
+}
+
+/**
+ * Given the parent's rate and the required rate for the children, this works
+ * out the peripheral clock divider to use, in 7.1 binary format.
+ *
+ * @param divider_bits number of divider bits (8 or 16)
+ * @param parent_rate clock rate of parent clock in Hz
+ * @param rate required clock rate for this clock
+ * @return divider which should be used
+ */
+static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
+ unsigned long rate)
+{
+ u64 divider = parent_rate * 2;
+ unsigned max_divider = 1 << divider_bits;
+
+ divider += rate - 1;
+ do_div(divider, rate);
+
+ if ((s64)divider - 2 < 0)
+ return 0;
+
+ if ((s64)divider - 2 >= max_divider)
+ return -1;
+
+ return divider - 2;
+}
+
+/**
+ * Given the parent's rate and the divider in 7.1 format, this works out the
+ * resulting peripheral clock rate.
+ *
+ * @param parent_rate clock rate of parent clock in Hz
+ * @param divider which should be used in 7.1 format
+ * @return effective clock rate of peripheral
+ */
+static unsigned long get_rate_from_divider(unsigned long parent_rate,
+ int divider)
+{
+ u64 rate;
+
+ rate = (u64)parent_rate * 2;
+ do_div(rate, divider + 2);
+ return rate;
+}
+
+unsigned long clock_get_periph_rate(enum periph_id periph_id,
+ enum clock_id parent)
+{
+ u32 *reg = get_periph_source_reg(periph_id);
+
+ return get_rate_from_divider(pll_rate[parent],
+ (readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
+}
+
+/**
+ * Find the best available 7.1 format divisor given a parent clock rate and
+ * required child clock rate. This function assumes that a second-stage
+ * divisor is available which can divide by powers of 2 from 1 to 256.
+ *
+ * @param divider_bits number of divider bits (8 or 16)
+ * @param parent_rate clock rate of parent clock in Hz
+ * @param rate required clock rate for this clock
+ * @param extra_div value for the second-stage divisor (not set if this
+ * function returns -1.
+ * @return divider which should be used, or -1 if nothing is valid
+ *
+ */
+static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
+ unsigned long rate, int *extra_div)
+{
+ int shift;
+ int best_divider = -1;
+ int best_error = rate;
+
+ /* try dividers from 1 to 256 and find closest match */
+ for (shift = 0; shift <= 8 && best_error > 0; shift++) {
+ unsigned divided_parent = parent_rate >> shift;
+ int divider = clk_get_divider(divider_bits, divided_parent,
+ rate);
+ unsigned effective_rate = get_rate_from_divider(divided_parent,
+ divider);
+ int error = rate - effective_rate;
+
+ /* Given a valid divider, look for the lowest error */
+ if (divider != -1 && error < best_error) {
+ best_error = error;
+ *extra_div = 1 << shift;
+ best_divider = divider;
+ }
+ }
+
+ /* return what we found - *extra_div will already be set */
+ return best_divider;
+}
+
+/**
+ * Given a peripheral ID and the required source clock, this returns which
+ * value should be programmed into the source mux for that peripheral.
+ *
+ * There is special code here to handle the one source type with 5 sources.
+ *
+ * @param periph_id peripheral to start
+ * @param source PLL id of required parent clock
+ * @param mux_bits Set to number of bits in mux register: 2 or 4
+ * @param divider_bits Set to number of divider bits (8 or 16)
+ * @return mux value (0-4, or -1 if not found)
+ */
+static int get_periph_clock_source(enum periph_id periph_id,
+ enum clock_id parent, int *mux_bits, int *divider_bits)
+{
+ enum clock_type_id type;
+ enum periphc_internal_id internal_id;
+ int mux;
+
+ assert(clock_periph_id_isvalid(periph_id));
+
+ internal_id = periph_id_to_internal_id[periph_id];
+ assert(periphc_internal_id_isvalid(internal_id));
+
+ type = clock_periph_type[internal_id];
+ assert(clock_type_id_isvalid(type));
+
+ /*
+ * Special cases here for the clock with a 4-bit source mux and I2C
+ * with its 16-bit divisor
+ */
+ if (type == CLOCK_TYPE_PCXTS)
+ *mux_bits = 4;
+ else
+ *mux_bits = 2;
+ if (type == CLOCK_TYPE_PCMT16)
+ *divider_bits = 16;
+ else
+ *divider_bits = 8;
+
+ for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
+ if (clock_source[type][mux] == parent)
+ return mux;
+
+ /*
+ * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS
+ * which is not in our table. If not, then they are asking for a
+ * source which this peripheral can't access through its mux.
+ */
+ assert(type == CLOCK_TYPE_PCXTS);
+ assert(parent == CLOCK_ID_SFROM32KHZ);
+ if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ)
+ return 4; /* mux value for this clock */
+
+ /* if we get here, either us or the caller has made a mistake */
+ printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
+ parent);
+ return -1;
+}
+
+/**
+ * Adjust peripheral PLL to use the given divider and source.
+ *
+ * @param periph_id peripheral to adjust
+ * @param source Source number (0-3 or 0-7)
+ * @param mux_bits Number of mux bits (2 or 4)
+ * @param divider Required divider in 7.1 or 15.1 format
+ * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
+ * for this peripheral)
+ */
+static int adjust_periph_pll(enum periph_id periph_id, int source,
+ int mux_bits, unsigned divider)
+{
+ u32 *reg = get_periph_source_reg(periph_id);
+
+ clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
+ divider << OUT_CLK_DIVISOR_SHIFT);
+ udelay(1);
+
+ /* work out the source clock and set it */
+ if (source < 0)
+ return -1;
+ if (mux_bits == 4) {
+ clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
+ source << OUT_CLK_SOURCE4_SHIFT);
+ } else {
+ clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
+ source << OUT_CLK_SOURCE_SHIFT);
+ }
+ udelay(2);
+ return 0;
+}
+
+unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
+ enum clock_id parent, unsigned rate, int *extra_div)
+{
+ unsigned effective_rate;
+ int mux_bits, divider_bits, source;
+ int divider;
+
+ /* work out the source clock and set it */
+ source = get_periph_clock_source(periph_id, parent, &mux_bits,
+ ÷r_bits);
+
+ if (extra_div)
+ divider = find_best_divider(divider_bits, pll_rate[parent],
+ rate, extra_div);
+ else
+ divider = clk_get_divider(divider_bits, pll_rate[parent],
+ rate);
+ assert(divider >= 0);
+ if (adjust_periph_pll(periph_id, source, mux_bits, divider))
+ return -1U;
+ debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
+ get_periph_source_reg(periph_id),
+ readl(get_periph_source_reg(periph_id)));
+
+ /* Check what we ended up with. This shouldn't matter though */
+ effective_rate = clock_get_periph_rate(periph_id, parent);
+ if (extra_div)
+ effective_rate /= *extra_div;
+ if (rate != effective_rate)
+ debug("Requested clock rate %u not honored (got %u)\n",
+ rate, effective_rate);
+ return effective_rate;
+}
+
+unsigned clock_start_periph_pll(enum periph_id periph_id,
+ enum clock_id parent, unsigned rate)
+{
+ unsigned effective_rate;
+
+ reset_set_enable(periph_id, 1);
+ clock_enable(periph_id);
+
+ effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
+ NULL);
+
+ reset_set_enable(periph_id, 0);
+ return effective_rate;
+}
+
+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);
+}
+
+unsigned clock_get_rate(enum clock_id clkid)
+{
+ struct clk_pll *pll;
+ u32 base;
+ u32 divm;
+ u64 parent_rate;
+ u64 rate;
+
+ parent_rate = osc_freq[clock_get_osc_freq()];
+ if (clkid == CLOCK_ID_OSC)
+ return parent_rate;
+
+ pll = get_pll(clkid);
+ base = readl(&pll->pll_base);
+
+ /* Oh for bf_unpack()... */
+ rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
+ divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
+ if (clkid == CLOCK_ID_USB)
+ divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
+ else
+ divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+ do_div(rate, divm);
+ return rate;
+}
+
+/**
+ * Set the output frequency you want for each PLL clock.
+ * PLL output frequencies are programmed by setting their N, M and P values.
+ * The governing equations are:
+ * VCO = (Fi / m) * n, Fo = VCO / (2^p)
+ * where Fo is the output frequency from the PLL.
+ * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
+ * 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
+ * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
+ *
+ * @param n PLL feedback divider(DIVN)
+ * @param m PLL input divider(DIVN)
+ * @param p post divider(DIVP)
+ * @param cpcon base PLL charge pump(CPCON)
+ * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
+ * be overriden), 1 if PLL is already correct
+ */
+static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
+{
+ u32 base_reg;
+ u32 misc_reg;
+ struct clk_pll *pll;
+
+ pll = get_pll(clkid);
+
+ base_reg = readl(&pll->pll_base);
+
+ /* Set BYPASS, m, n and p to PLL_BASE */
+ base_reg &= ~PLL_DIVM_MASK;
+ base_reg |= m << PLL_DIVM_SHIFT;
+
+ base_reg &= ~PLL_DIVN_MASK;
+ base_reg |= n << PLL_DIVN_SHIFT;
+
+ base_reg &= ~PLL_DIVP_MASK;
+ base_reg |= p << PLL_DIVP_SHIFT;
+
+ if (clkid == CLOCK_ID_PERIPH) {
+ /*
+ * If the PLL is already set up, check that it is correct
+ * and record this info for clock_verify() to check.
+ */
+ if (base_reg & PLL_BASE_OVRRIDE_MASK) {
+ base_reg |= PLL_ENABLE_MASK;
+ if (base_reg != readl(&pll->pll_base))
+ pllp_valid = 0;
+ return pllp_valid ? 1 : -1;
+ }
+ base_reg |= PLL_BASE_OVRRIDE_MASK;
+ }
+
+ base_reg |= PLL_BYPASS_MASK;
+ writel(base_reg, &pll->pll_base);
+
+ /* Set cpcon to PLL_MISC */
+ misc_reg = readl(&pll->pll_misc);
+ misc_reg &= ~PLL_CPCON_MASK;
+ misc_reg |= cpcon << PLL_CPCON_SHIFT;
+ writel(misc_reg, &pll->pll_misc);
+
+ /* Enable PLL */
+ base_reg |= PLL_ENABLE_MASK;
+ writel(base_reg, &pll->pll_base);
+
+ /* Disable BYPASS */
+ base_reg &= ~PLL_BYPASS_MASK;
+ writel(base_reg, &pll->pll_base);
+
+ return 0;
+}
+
+void clock_ll_start_uart(enum periph_id periph_id)
+{
+ /* Assert UART reset and enable clock */
+ reset_set_enable(periph_id, 1);
+ clock_enable(periph_id);
+ clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
+
+ /* wait for 2us */
+ udelay(2);
+
+ /* De-assert reset to UART */
+ reset_set_enable(periph_id, 0);
+}
+
+#ifdef CONFIG_OF_CONTROL
+/*
+ * Convert a device tree clock ID to our peripheral ID. They are mostly
+ * the same but we are very cautious so we check that a valid clock ID is
+ * provided.
+ *
+ * @param clk_id Clock ID according to tegra2 device tree binding
+ * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
+ */
+static enum periph_id clk_id_to_periph_id(int clk_id)
+{
+ if (clk_id > 95)
+ return PERIPH_ID_NONE;
+
+ switch (clk_id) {
+ case 1:
+ case 2:
+ case 7:
+ case 10:
+ case 20:
+ case 30:
+ case 35:
+ case 49:
+ case 56:
+ case 74:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 91:
+ case 95:
+ return PERIPH_ID_NONE;
+ default:
+ return clk_id;
+ }
+}
+
+int clock_decode_periph_id(const void *blob, int node)
+{
+ enum periph_id id;
+ u32 cell[2];
+ int err;
+
+ err = fdtdec_get_int_array(blob, node, "clocks", cell,
+ ARRAY_SIZE(cell));
+ if (err)
+ return -1;
+ id = clk_id_to_periph_id(cell[1]);
+ assert(clock_periph_id_isvalid(id));
+ return id;
+}
+#endif /* CONFIG_OF_CONTROL */
+
+int clock_verify(void)
+{
+ struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
+ u32 reg = readl(&pll->pll_base);
+
+ if (!pllp_valid) {
+ printf("Warning: PLLP %x is not correct\n", reg);
+ return -1;
+ }
+ debug("PLLX %x is correct\n", reg);
+ return 0;
+}
+
+void clock_early_init(void)
+{
+ /*
+ * PLLP output frequency set to 216MHz
+ * PLLC output frequency set to 600Mhz
+ *
+ * TODO: Can we calculate these values instead of hard-coding?
+ */
+ switch (clock_get_osc_freq()) {
+ case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
+ clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8);
+ clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
+ break;
+
+ case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
+ clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8);
+ clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
+ break;
+
+ case CLOCK_OSC_FREQ_13_0:
+ case CLOCK_OSC_FREQ_19_2:
+ default:
+ /*
+ * These are not supported. It is too early to print a
+ * message and the UART likely won't work anyway due to the
+ * oscillator being wrong.
+ */
+ break;
+ }
+}
+
+void clock_init(void)
+{
+ 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_OSC] = clock_get_rate(CLOCK_ID_OSC);
+ pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
+ debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
+ debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
+ debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
+}
diff --git a/arch/arm/cpu/tegra2-common/funcmux.c b/arch/arm/cpu/tegra2-common/funcmux.c
new file mode 100644
index 0000000..c1d2dfe
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/funcmux.c
@@ -0,0 +1,184 @@
+/*
+ * 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 high-level function multiplexing */
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/pinmux.h>
+
+int funcmux_select(enum periph_id id, int config)
+{
+ int bad_config = config != FUNCMUX_DEFAULT;
+
+ switch (id) {
+ case PERIPH_ID_UART1:
+ if (config == FUNCMUX_UART1_IRRX_IRTX) {
+ pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
+ pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
+ pinmux_tristate_disable(PINGRP_IRRX);
+ pinmux_tristate_disable(PINGRP_IRTX);
+ /*
+ * Tegra appears to boot with function UARTA pre-
+ * selected on mux group SDB. If two mux groups are
+ * both set to the same function, it's unclear which
+ * group's pins drive the RX signals into the HW.
+ * For UARTA, SDB certainly overrides group IRTX in
+ * practice. To solve this, configure some alternative
+ * function on SDB to avoid the conflict. Also, tri-
+ * state the group to avoid driving any signal onto it
+ * until we know what's connected.
+ */
+ pinmux_tristate_enable(PINGRP_SDB);
+ pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
+ }
+ break;
+
+ case PERIPH_ID_UART2:
+ if (config == FUNCMUX_UART2_IRDA) {
+ pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
+ pinmux_tristate_disable(PINGRP_UAD);
+ }
+ break;
+
+ case PERIPH_ID_UART4:
+ if (config == FUNCMUX_UART4_GMC) {
+ pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
+ pinmux_tristate_disable(PINGRP_GMC);
+ }
+ break;
+
+ case PERIPH_ID_DVC_I2C:
+ /* there is only one selection, pinmux_config is ignored */
+ if (config == FUNCMUX_DVC_I2CP) {
+ pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
+ pinmux_tristate_disable(PINGRP_I2CP);
+ }
+ break;
+
+ case PERIPH_ID_I2C1:
+ /* support pinmux_config of 0 for now, */
+ if (config == FUNCMUX_I2C1_RM) {
+ pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
+ pinmux_tristate_disable(PINGRP_RM);
+ }
+ break;
+ case PERIPH_ID_I2C2: /* I2C2 */
+ switch (config) {
+ case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */
+ pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
+ /* PTA to HDMI */
+ pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
+ pinmux_tristate_disable(PINGRP_DDC);
+ break;
+ case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */
+ pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
+ /* set DDC_SEL to RSVDx (RSVD2 works for now) */
+ pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
+ pinmux_tristate_disable(PINGRP_PTA);
+ bad_config = 0;
+ break;
+ }
+ break;
+ case PERIPH_ID_I2C3: /* I2C3 */
+ /* support pinmux_config of 0 for now */
+ if (config == FUNCMUX_I2C3_DTF) {
+ pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
+ pinmux_tristate_disable(PINGRP_DTF);
+ }
+ break;
+
+ case PERIPH_ID_SDMMC2:
+ if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
+ pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
+ pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);
+
+ pinmux_tristate_disable(PINGRP_DTA);
+ pinmux_tristate_disable(PINGRP_DTD);
+ }
+ break;
+
+ case PERIPH_ID_SDMMC3:
+ switch (config) {
+ case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
+ pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
+ pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
+ pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
+ pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);
+
+ pinmux_tristate_disable(PINGRP_SLXA);
+ pinmux_tristate_disable(PINGRP_SLXC);
+ pinmux_tristate_disable(PINGRP_SLXD);
+ pinmux_tristate_disable(PINGRP_SLXK);
+ /* fall through */
+
+ case FUNCMUX_SDMMC3_SDB_4BIT:
+ pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
+ pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
+ pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);
+
+ pinmux_tristate_disable(PINGRP_SDB);
+ pinmux_tristate_disable(PINGRP_SDC);
+ pinmux_tristate_disable(PINGRP_SDD);
+ bad_config = 0;
+ break;
+ }
+ break;
+
+ case PERIPH_ID_SDMMC4:
+ switch (config) {
+ case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
+ pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
+ pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);
+
+ pinmux_tristate_disable(PINGRP_ATC);
+ pinmux_tristate_disable(PINGRP_ATD);
+ break;
+
+ case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
+ pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
+ pinmux_tristate_disable(PINGRP_GME);
+ /* fall through */
+
+ case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
+ pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
+ pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
+
+ pinmux_tristate_disable(PINGRP_ATB);
+ pinmux_tristate_disable(PINGRP_GMA);
+ bad_config = 0;
+ break;
+ }
+ break;
+
+ default:
+ debug("%s: invalid periph_id %d", __func__, id);
+ return -1;
+ }
+
+ if (bad_config) {
+ debug("%s: invalid config %d for periph_id %d", __func__,
+ config, id);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/arch/arm/cpu/tegra2-common/lowlevel_init.S b/arch/arm/cpu/tegra2-common/lowlevel_init.S
new file mode 100644
index 0000000..6b86647
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/lowlevel_init.S
@@ -0,0 +1,41 @@
+/*
+ * SoC-specific setup info
+ *
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+
+ .align 5
+.global reset_cpu
+reset_cpu:
+ ldr r1, rstctl @ get addr for global reset
+ @ reg
+ ldr r3, [r1]
+ orr r3, r3, #0x10
+ str r3, [r1] @ force reset
+ mov r0, r0
+_loop_forever:
+ b _loop_forever
+rstctl:
+ .word PRM_RSTCTRL
diff --git a/arch/arm/cpu/tegra2-common/pinmux.c b/arch/arm/cpu/tegra2-common/pinmux.c
new file mode 100644
index 0000000..b053f90
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/pinmux.c
@@ -0,0 +1,572 @@
+/*
+ * 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 pin multiplexing functions */
+
+#include <asm/io.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/pinmux.h>
+#include <common.h>
+
+
+/*
+ * This defines the order of the pin mux control bits in the registers. For
+ * some reason there is no correspendence between the tristate, pin mux and
+ * pullup/pulldown registers.
+ */
+enum pmux_ctlid {
+ /* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */
+ MUXCTL_UAA,
+ MUXCTL_UAB,
+ MUXCTL_UAC,
+ MUXCTL_UAD,
+ MUXCTL_UDA,
+ MUXCTL_RESERVED5,
+ MUXCTL_ATE,
+ MUXCTL_RM,
+
+ MUXCTL_ATB,
+ MUXCTL_RESERVED9,
+ MUXCTL_ATD,
+ MUXCTL_ATC,
+ MUXCTL_ATA,
+ MUXCTL_KBCF,
+ MUXCTL_KBCE,
+ MUXCTL_SDMMC1,
+
+ /* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */
+ MUXCTL_GMA,
+ MUXCTL_GMC,
+ MUXCTL_HDINT,
+ MUXCTL_SLXA,
+ MUXCTL_OWC,
+ MUXCTL_SLXC,
+ MUXCTL_SLXD,
+ MUXCTL_SLXK,
+
+ MUXCTL_UCA,
+ MUXCTL_UCB,
+ MUXCTL_DTA,
+ MUXCTL_DTB,
+ MUXCTL_RESERVED28,
+ MUXCTL_DTC,
+ MUXCTL_DTD,
+ MUXCTL_DTE,
+
+ /* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */
+ MUXCTL_DDC,
+ MUXCTL_CDEV1,
+ MUXCTL_CDEV2,
+ MUXCTL_CSUS,
+ MUXCTL_I2CP,
+ MUXCTL_KBCA,
+ MUXCTL_KBCB,
+ MUXCTL_KBCC,
+
+ MUXCTL_IRTX,
+ MUXCTL_IRRX,
+ MUXCTL_DAP1,
+ MUXCTL_DAP2,
+ MUXCTL_DAP3,
+ MUXCTL_DAP4,
+ MUXCTL_GMB,
+ MUXCTL_GMD,
+
+ /* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */
+ MUXCTL_GME,
+ MUXCTL_GPV,
+ MUXCTL_GPU,
+ MUXCTL_SPDO,
+ MUXCTL_SPDI,
+ MUXCTL_SDB,
+ MUXCTL_SDC,
+ MUXCTL_SDD,
+
+ MUXCTL_SPIH,
+ MUXCTL_SPIG,
+ MUXCTL_SPIF,
+ MUXCTL_SPIE,
+ MUXCTL_SPID,
+ MUXCTL_SPIC,
+ MUXCTL_SPIB,
+ MUXCTL_SPIA,
+
+ /* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */
+ MUXCTL_LPW0,
+ MUXCTL_LPW1,
+ MUXCTL_LPW2,
+ MUXCTL_LSDI,
+ MUXCTL_LSDA,
+ MUXCTL_LSPI,
+ MUXCTL_LCSN,
+ MUXCTL_LDC,
+
+ MUXCTL_LSCK,
+ MUXCTL_LSC0,
+ MUXCTL_LSC1,
+ MUXCTL_LHS,
+ MUXCTL_LVS,
+ MUXCTL_LM0,
+ MUXCTL_LM1,
+ MUXCTL_LVP0,
+
+ /* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */
+ MUXCTL_LD0,
+ MUXCTL_LD1,
+ MUXCTL_LD2,
+ MUXCTL_LD3,
+ MUXCTL_LD4,
+ MUXCTL_LD5,
+ MUXCTL_LD6,
+ MUXCTL_LD7,
+
+ MUXCTL_LD8,
+ MUXCTL_LD9,
+ MUXCTL_LD10,
+ MUXCTL_LD11,
+ MUXCTL_LD12,
+ MUXCTL_LD13,
+ MUXCTL_LD14,
+ MUXCTL_LD15,
+
+ /* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */
+ MUXCTL_LD16,
+ MUXCTL_LD17,
+ MUXCTL_LHP1,
+ MUXCTL_LHP2,
+ MUXCTL_LVP1,
+ MUXCTL_LHP0,
+ MUXCTL_RESERVED102,
+ MUXCTL_LPP,
+
+ MUXCTL_LDI,
+ MUXCTL_PMC,
+ MUXCTL_CRTP,
+ MUXCTL_PTA,
+ MUXCTL_RESERVED108,
+ MUXCTL_KBCD,
+ MUXCTL_GPU7,
+ MUXCTL_DTF,
+
+ MUXCTL_NONE = -1,
+};
+
+/*
+ * And this defines the order of the pullup/pulldown controls which are again
+ * in a different order
+ */
+enum pmux_pullid {
+ /* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */
+ PUCTL_ATA,
+ PUCTL_ATB,
+ PUCTL_ATC,
+ PUCTL_ATD,
+ PUCTL_ATE,
+ PUCTL_DAP1,
+ PUCTL_DAP2,
+ PUCTL_DAP3,
+
+ PUCTL_DAP4,
+ PUCTL_DTA,
+ PUCTL_DTB,
+ PUCTL_DTC,
+ PUCTL_DTD,
+ PUCTL_DTE,
+ PUCTL_DTF,
+ PUCTL_GPV,
+
+ /* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */
+ PUCTL_RM,
+ PUCTL_I2CP,
+ PUCTL_PTA,
+ PUCTL_GPU7,
+ PUCTL_KBCA,
+ PUCTL_KBCB,
+ PUCTL_KBCC,
+ PUCTL_KBCD,
+
+ PUCTL_SPDI,
+ PUCTL_SPDO,
+ PUCTL_GPSLXAU,
+ PUCTL_CRTP,
+ PUCTL_SLXC,
+ PUCTL_SLXD,
+ PUCTL_SLXK,
+
+ /* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */
+ PUCTL_CDEV1,
+ PUCTL_CDEV2,
+ PUCTL_SPIA,
+ PUCTL_SPIB,
+ PUCTL_SPIC,
+ PUCTL_SPID,
+ PUCTL_SPIE,
+ PUCTL_SPIF,
+
+ PUCTL_SPIG,
+ PUCTL_SPIH,
+ PUCTL_IRTX,
+ PUCTL_IRRX,
+ PUCTL_GME,
+ PUCTL_RESERVED45,
+ PUCTL_XM2D,
+ PUCTL_XM2C,
+
+ /* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */
+ PUCTL_UAA,
+ PUCTL_UAB,
+ PUCTL_UAC,
+ PUCTL_UAD,
+ PUCTL_UCA,
+ PUCTL_UCB,
+ PUCTL_LD17,
+ PUCTL_LD19_18,
+
+ PUCTL_LD21_20,
+ PUCTL_LD23_22,
+ PUCTL_LS,
+ PUCTL_LC,
+ PUCTL_CSUS,
+ PUCTL_DDRC,
+ PUCTL_SDC,
+ PUCTL_SDD,
+
+ /* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */
+ PUCTL_KBCF,
+ PUCTL_KBCE,
+ PUCTL_PMCA,
+ PUCTL_PMCB,
+ PUCTL_PMCC,
+ PUCTL_PMCD,
+ PUCTL_PMCE,
+ PUCTL_CK32,
+
+ PUCTL_UDA,
+ PUCTL_SDMMC1,
+ PUCTL_GMA,
+ PUCTL_GMB,
+ PUCTL_GMC,
+ PUCTL_GMD,
+ PUCTL_DDC,
+ PUCTL_OWC,
+
+ PUCTL_NONE = -1
+};
+
+struct tegra_pingroup_desc {
+ const char *name;
+ enum pmux_func funcs[4];
+ enum pmux_func func_safe;
+ enum pmux_vddio vddio;
+ enum pmux_ctlid ctl_id;
+ enum pmux_pullid pull_id;
+};
+
+
+/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */
+#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5)
+
+/* Mask value for a tristate (within TRISTATE_REG(id)) */
+#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f))
+
+/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */
+#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4)
+
+/* Converts a PUCTL id to a shift position */
+#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f)
+
+/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */
+#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4)
+
+/* Converts a MUXCTL id to a shift position */
+#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f)
+
+/* Convenient macro for defining pin group properties */
+#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd) \
+ { \
+ .vddio = PMUX_VDDIO_ ## vdd, \
+ .funcs = { \
+ PMUX_FUNC_ ## f0, \
+ PMUX_FUNC_ ## f1, \
+ PMUX_FUNC_ ## f2, \
+ PMUX_FUNC_ ## f3, \
+ }, \
+ .func_safe = PMUX_FUNC_ ## f_safe, \
+ .ctl_id = mux, \
+ .pull_id = pupd \
+ }
+
+/* A normal pin group where the mux name and pull-up name match */
+#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe) \
+ PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \
+ MUXCTL_ ## pg_name, PUCTL_ ## pg_name)
+
+/* A pin group where the pull-up name doesn't have a 1-1 mapping */
+#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd) \
+ PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \
+ MUXCTL_ ## pg_name, PUCTL_ ## pupd)
+
+/* A pin group number which is not used */
+#define PIN_RESERVED \
+ PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE)
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
+ PIN(ATA, NAND, IDE, NAND, GMI, RSVD, IDE),
+ PIN(ATB, NAND, IDE, NAND, GMI, SDIO4, IDE),
+ PIN(ATC, NAND, IDE, NAND, GMI, SDIO4, IDE),
+ PIN(ATD, NAND, IDE, NAND, GMI, SDIO4, IDE),
+ PIN(CDEV1, AUDIO, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC),
+ PIN(CDEV2, AUDIO, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, OSC),
+ PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK,
+ PLLC_OUT1),
+ PIN(DAP1, AUDIO, DAP1, RSVD, GMI, SDIO2, DAP1),
+
+ PIN(DAP2, AUDIO, DAP2, TWC, RSVD, GMI, DAP2),
+ PIN(DAP3, BB, DAP3, RSVD, RSVD, RSVD, DAP3),
+ PIN(DAP4, UART, DAP4, RSVD, GMI, RSVD, DAP4),
+ PIN(DTA, VI, RSVD, SDIO2, VI, RSVD, RSVD4),
+ PIN(DTB, VI, RSVD, RSVD, VI, SPI1, RSVD1),
+ PIN(DTC, VI, RSVD, RSVD, VI, RSVD, RSVD1),
+ PIN(DTD, VI, RSVD, SDIO2, VI, RSVD, RSVD1),
+ PIN(DTE, VI, RSVD, RSVD, VI, SPI1, RSVD1),
+
+ PINP(GPU, UART, PWM, UARTA, GMI, RSVD, RSVD4,
+ GPSLXAU),
+ PIN(GPV, SD, PCIE, RSVD, RSVD, RSVD, PCIE),
+ PIN(I2CP, SYS, I2C, RSVD, RSVD, RSVD, RSVD4),
+ PIN(IRTX, UART, UARTA, UARTB, GMI, SPI4, UARTB),
+ PIN(IRRX, UART, UARTA, UARTB, GMI, SPI4, UARTB),
+ PIN(KBCB, SYS, KBC, NAND, SDIO2, MIO, KBC),
+ PIN(KBCA, SYS, KBC, NAND, SDIO2, EMC_TEST0_DLL, KBC),
+ PINP(PMC, SYS, PWR_ON, PWR_INTR, RSVD, RSVD, PWR_ON, NONE),
+
+ PIN(PTA, NAND, I2C2, HDMI, GMI, RSVD, RSVD4),
+ PIN(RM, UART, I2C, RSVD, RSVD, RSVD, RSVD4),
+ PIN(KBCE, SYS, KBC, NAND, OWR, RSVD, KBC),
+ PIN(KBCF, SYS, KBC, NAND, TRACE, MIO, KBC),
+ PIN(GMA, NAND, UARTE, SPI3, GMI, SDIO4, SPI3),
+ PIN(GMC, NAND, UARTD, SPI4, GMI, SFLASH, SPI4),
+ PIN(SDMMC1, BB, SDIO1, RSVD, UARTE, UARTA, RSVD2),
+ PIN(OWC, SYS, OWR, RSVD, RSVD, RSVD, OWR),
+
+ PIN(GME, NAND, RSVD, DAP5, GMI, SDIO4, GMI),
+ PIN(SDC, SD, PWM, TWC, SDIO3, SPI3, TWC),
+ PIN(SDD, SD, UARTA, PWM, SDIO3, SPI3, PWM),
+ PIN_RESERVED,
+ PINP(SLXA, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, CRTP),
+ PIN(SLXC, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4),
+ PIN(SLXD, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4),
+ PIN(SLXK, SD, PCIE, SPI4, SDIO3, SPI2, PCIE),
+
+ PIN(SPDI, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2),
+ PIN(SPDO, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2),
+ PIN(SPIA, AUDIO, SPI1, SPI2, SPI3, GMI, GMI),
+ PIN(SPIB, AUDIO, SPI1, SPI2, SPI3, GMI, GMI),
+ PIN(SPIC, AUDIO, SPI1, SPI2, SPI3, GMI, GMI),
+ PIN(SPID, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI),
+ PIN(SPIE, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI),
+ PIN(SPIF, AUDIO, SPI3, SPI1, SPI2, RSVD, RSVD4),
+
+ PIN(SPIG, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT),
+ PIN(SPIH, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT),
+ PIN(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS),
+ PIN(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS),
+ PIN(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4),
+ PIN(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF),
+ PIN(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4),
+ PIN(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4),
+
+ PIN_RESERVED,
+ PIN(ATE, NAND, IDE, NAND, GMI, RSVD, IDE),
+ PIN(KBCC, SYS, KBC, NAND, TRACE, EMC_TEST1_DLL, KBC),
+ PIN_RESERVED,
+ PIN_RESERVED,
+ PIN(GMB, NAND, IDE, NAND, GMI, GMI_INT, GMI),
+ PIN(GMD, NAND, RSVD, NAND, GMI, SFLASH, GMI),
+ PIN(DDC, LCD, I2C2, RSVD, RSVD, RSVD, RSVD4),
+
+ /* 64 */
+ PINP(LD0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD1, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD2, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD3, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD4, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD5, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD6, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD7, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+
+ PINP(LD8, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD9, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD10, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD11, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD12, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD13, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD14, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD15, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+
+ PINP(LD16, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17),
+ PINP(LD17, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD17),
+ PINP(LHP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20),
+ PINP(LHP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18),
+ PINP(LHP2, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18),
+ PINP(LVP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LC),
+ PINP(LVP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20),
+ PINP(HDINT, LCD, HDMI, RSVD, RSVD, RSVD, HDMI , LC),
+
+ PINP(LM0, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LC),
+ PINP(LM1, LCD, DISPA, DISPB, RSVD, CRT, RSVD3, LC),
+ PINP(LVS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC),
+ PINP(LSC0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC),
+ PINP(LSC1, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
+ PINP(LSCK, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
+ PINP(LDC, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS),
+ PINP(LCSN, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LS),
+
+ /* 96 */
+ PINP(LSPI, LCD, DISPA, DISPB, XIO, HDMI, DISPA, LC),
+ PINP(LSDA, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
+ PINP(LSDI, LCD, DISPA, DISPB, SPI3, RSVD, DISPA, LS),
+ PINP(LPW0, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
+ PINP(LPW1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS),
+ PINP(LPW2, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS),
+ PINP(LDI, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22),
+ PINP(LHS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC),
+
+ PINP(LPP, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22),
+ PIN_RESERVED,
+ PIN(KBCD, SYS, KBC, NAND, SDIO2, MIO, KBC),
+ PIN(GPU7, SYS, RTCK, RSVD, RSVD, RSVD, RTCK),
+ PIN(DTF, VI, I2C3, RSVD, VI, RSVD, RSVD4),
+ PIN(UDA, BB, SPI1, RSVD, UARTD, ULPI, RSVD2),
+ PIN(CRTP, LCD, CRT, RSVD, RSVD, RSVD, RSVD),
+ PINP(SDB, SD, UARTA, PWM, SDIO3, SPI2, PWM, NONE),
+
+ /* these pin groups only have pullup and pull down control */
+ PINALL(CK32, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(DDRC, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(PMCA, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(PMCB, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(PMCC, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(PMCD, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(PMCE, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+ PINALL(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE,
+ PUCTL_NONE),
+};
+
+void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
+{
+ struct pmux_tri_ctlr *pmt =
+ (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+ u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)];
+ u32 reg;
+
+ reg = readl(tri);
+ if (enable)
+ reg |= TRISTATE_MASK(pin);
+ else
+ reg &= ~TRISTATE_MASK(pin);
+ writel(reg, tri);
+}
+
+void pinmux_tristate_enable(enum pmux_pingrp pin)
+{
+ pinmux_set_tristate(pin, 1);
+}
+
+void pinmux_tristate_disable(enum pmux_pingrp pin)
+{
+ pinmux_set_tristate(pin, 0);
+}
+
+void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
+{
+ struct pmux_tri_ctlr *pmt =
+ (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+ enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id;
+ u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)];
+ u32 mask_bit;
+ u32 reg;
+ mask_bit = PULL_SHIFT(pull_id);
+
+ reg = readl(pull);
+ reg &= ~(0x3 << mask_bit);
+ reg |= pupd << mask_bit;
+ writel(reg, pull);
+}
+
+void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
+{
+ struct pmux_tri_ctlr *pmt =
+ (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+ enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id;
+ u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)];
+ u32 mask_bit;
+ int i, mux = -1;
+ u32 reg;
+
+ assert(pmux_func_isvalid(func));
+
+ /* Handle special values */
+ if (func >= PMUX_FUNC_RSVD1) {
+ mux = (func - PMUX_FUNC_RSVD1) & 0x3;
+ } else {
+ /* Search for the appropriate function */
+ for (i = 0; i < 4; i++) {
+ if (tegra_soc_pingroups[pin].funcs[i] == func) {
+ mux = i;
+ break;
+ }
+ }
+ }
+ assert(mux != -1);
+
+ mask_bit = MUXCTL_SHIFT(mux_id);
+ reg = readl(muxctl);
+ reg &= ~(0x3 << mask_bit);
+ reg |= mux << mask_bit;
+ writel(reg, muxctl);
+}
+
+void pinmux_config_pingroup(struct pingroup_config *config)
+{
+ enum pmux_pingrp pin = config->pingroup;
+
+ pinmux_set_func(pin, config->func);
+ pinmux_set_pullupdown(pin, config->pull);
+ pinmux_set_tristate(pin, config->tristate);
+}
+
+void pinmux_config_table(struct pingroup_config *config, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ pinmux_config_pingroup(&config[i]);
+}
diff --git a/arch/arm/cpu/tegra2-common/sys_info.c b/arch/arm/cpu/tegra2-common/sys_info.c
new file mode 100644
index 0000000..6d11dc1
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/sys_info.c
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * 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
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+/* Print CPU information */
+int print_cpuinfo(void)
+{
+ puts("TEGRA2\n");
+
+ /* TBD: Add printf of major/minor rev info, stepping, etc. */
+ return 0;
+}
+#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/tegra2-common/timer.c b/arch/arm/cpu/tegra2-common/timer.c
new file mode 100644
index 0000000..b12b12c
--- /dev/null
+++ b/arch/arm/cpu/tegra2-common/timer.c
@@ -0,0 +1,111 @@
+/*
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * (C) Copyright 2008
+ * Texas Instruments
+ *
+ * Richard Woodruff <r-woodruff2 at ti.com>
+ * Syed Moahmmed Khasim <khasim at ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ * Alex Zuepke <azu at sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj at denx.de>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* counter runs at 1MHz */
+#define TIMER_CLK 1000000
+#define TIMER_LOAD_VAL 0xffffffff
+
+/* timer without interrupts */
+ulong get_timer(ulong base)
+{
+ return get_timer_masked() - base;
+}
+
+/* delay x useconds */
+void __udelay(unsigned long usec)
+{
+ long tmo = usec * (TIMER_CLK / 1000) / 1000;
+ unsigned long now, last = timer_get_us();
+
+ while (tmo > 0) {
+ now = timer_get_us();
+ if (last > now) /* count up timer overflow */
+ tmo -= TIMER_LOAD_VAL - last + now;
+ else
+ tmo -= now - last;
+ last = now;
+ }
+}
+
+ulong get_timer_masked(void)
+{
+ ulong now;
+
+ /* current tick value */
+ now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
+
+ if (now >= gd->lastinc) /* normal mode (non roll) */
+ /* move stamp forward with absolute diff ticks */
+ gd->tbl += (now - gd->lastinc);
+ else /* we have rollover of incrementer */
+ gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ))
+ - gd->lastinc) + now;
+ gd->lastinc = now;
+ return gd->tbl;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ return CONFIG_SYS_HZ;
+}
+
+unsigned long timer_get_us(void)
+{
+ struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
+
+ return readl(&timer_base->cntr_1us);
+}
diff --git a/spl/Makefile b/spl/Makefile
index ea7d475..6d3241f 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -62,6 +62,10 @@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
endif
+ifneq ($(CONFIG_TEGRA2),)
+LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
+
START := $(addprefix $(SPLTREE)/,$(START))
LIBS := $(addprefix $(SPLTREE)/,$(sort $(LIBS-y)))
--
1.7.5.4
More information about the U-Boot
mailing list