tegra20: move tegra20 SoC code to arch/arm/cpu/tegra20-common
authorAllen Martin <amartin@nvidia.com>
Fri, 31 Aug 2012 08:30:01 +0000 (08:30 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sat, 1 Sep 2012 12:58:21 +0000 (14:58 +0200)
In preparation for splitting out the armv4t code from tegra20, move
the tegra20 SoC code to arch/arm/cpu/tegra20-common.  This code will
be compiled armv4t for the arm7tdmi and armv7 for the cortex A9.

Signed-off-by: Allen Martin <amartin@nvidia.com>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Tom Warren <twarren@nvidia.com>
34 files changed:
Makefile
arch/arm/cpu/armv7/tegra20/Makefile
arch/arm/cpu/armv7/tegra20/ap20.c [deleted file]
arch/arm/cpu/armv7/tegra20/board.c [deleted file]
arch/arm/cpu/armv7/tegra20/clock.c [deleted file]
arch/arm/cpu/armv7/tegra20/crypto.c [deleted file]
arch/arm/cpu/armv7/tegra20/crypto.h [deleted file]
arch/arm/cpu/armv7/tegra20/emc.c [deleted file]
arch/arm/cpu/armv7/tegra20/funcmux.c [deleted file]
arch/arm/cpu/armv7/tegra20/lowlevel_init.S [deleted file]
arch/arm/cpu/armv7/tegra20/pinmux.c [deleted file]
arch/arm/cpu/armv7/tegra20/pmu.c [deleted file]
arch/arm/cpu/armv7/tegra20/sys_info.c [deleted file]
arch/arm/cpu/armv7/tegra20/timer.c [deleted file]
arch/arm/cpu/armv7/tegra20/warmboot.c [deleted file]
arch/arm/cpu/armv7/tegra20/warmboot_avp.c [deleted file]
arch/arm/cpu/armv7/tegra20/warmboot_avp.h [deleted file]
arch/arm/cpu/tegra20-common/Makefile [new file with mode: 0644]
arch/arm/cpu/tegra20-common/ap20.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/board.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/clock.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/crypto.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/crypto.h [new file with mode: 0644]
arch/arm/cpu/tegra20-common/emc.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/funcmux.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/lowlevel_init.S [new file with mode: 0644]
arch/arm/cpu/tegra20-common/pinmux.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/pmu.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/sys_info.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/timer.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/warmboot.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/warmboot_avp.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/warmboot_avp.h [new file with mode: 0644]
spl/Makefile

index 913360cacd7e17ea4cda1d1c567e2cd9cfc4160e..a080838e0b671485e130a95cf4a8729121a4ce2b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -319,6 +319,9 @@ endif
 ifeq ($(SOC),exynos)
 LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
 endif
+ifeq ($(SOC),tegra20)
+LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
 
 LIBS := $(addprefix $(obj),$(sort $(LIBS-y)))
 .PHONY : $(LIBS)
index da626465be32ae2bf9b25d6578d4fec6ad1a1815..5f4035d79c9b5a9a6137488f6ff607dfe624b7f9 100644 (file)
 # 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/tegra20/ap20.o += -march=armv4t
-CFLAGS_arch/arm/cpu/armv7/tegra20/clock.o += -march=armv4t
-CFLAGS_arch/arm/cpu/armv7/tegra20/warmboot_avp.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_TEGRA_CLOCK_SCALING) += emc.o
-COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
-COBJS-$(CONFIG_TEGRA20_LP0) += crypto.o warmboot.o warmboot_avp.o
 COBJS-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.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/tegra20/ap20.c b/arch/arm/cpu/armv7/tegra20/ap20.c
deleted file mode 100644 (file)
index 8b6afbc..0000000
+++ /dev/null
@@ -1,388 +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/io.h>
-#include <asm/arch/tegra20.h>
-#include <asm/arch/ap20.h>
-#include <asm/arch/clk_rst.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/fuse.h>
-#include <asm/arch/gp_padctrl.h>
-#include <asm/arch/pmc.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/scu.h>
-#include <asm/arch/warmboot.h>
-#include <common.h>
-
-int tegra_get_chip_type(void)
-{
-       struct apb_misc_gp_ctlr *gp;
-       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA20_FUSE_BASE;
-       uint tegra_sku_id, rev;
-
-       /*
-        * This is undocumented, Chip ID is bits 15:8 of the register
-        * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for
-        * Tegra30
-        */
-       gp = (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
-       rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
-
-       tegra_sku_id = readl(&fuse->sku_info) & 0xff;
-
-       switch (rev) {
-       case CHIPID_TEGRA20:
-               switch (tegra_sku_id) {
-               case SKU_ID_T20:
-                       return TEGRA_SOC_T20;
-               case SKU_ID_T25SE:
-               case SKU_ID_AP25:
-               case SKU_ID_T25:
-               case SKU_ID_AP25E:
-               case SKU_ID_T25E:
-                       return TEGRA_SOC_T25;
-               }
-               break;
-       }
-       /* unknown sku id */
-       return TEGRA_SOC_UNKNOWN;
-}
-
-/* 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_simple *pll =
-               &clkrst->crc_pll_simple[CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE];
-       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 *)TEGRA20_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 *)TEGRA20_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 *)TEGRA20_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 *)TEGRA20_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);
-}
-
-static u32 get_odmdata(void)
-{
-       /*
-        * ODMDATA is stored in the BCT in IRAM by the BootROM.
-        * The BCT start and size are stored in the BIT in IRAM.
-        * Read the data @ bct_start + (bct_size - 12). This works
-        * on T20 and T30 BCTs, which are locked down. If this changes
-        * in new chips (T114, etc.), we can revisit this algorithm.
-        */
-
-       u32 bct_start, odmdata;
-
-       bct_start = readl(AP20_BASE_PA_SRAM + NVBOOTINFOTABLE_BCTPTR);
-       odmdata = readl(bct_start + BCT_ODMDATA_OFFSET);
-
-       return odmdata;
-}
-
-void init_pmc_scratch(void)
-{
-       struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
-       u32 odmdata;
-       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. */
-       odmdata = get_odmdata();
-       writel(odmdata, &pmc->pmc_scratch20);
-
-#ifdef CONFIG_TEGRA20_LP0
-       /* save Sdram params to PMC 2, 4, and 24 for WB0 */
-       warmboot_save_sdram_params();
-#endif
-}
-
-void tegra20_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/tegra20/board.c b/arch/arm/cpu/armv7/tegra20/board.c
deleted file mode 100644 (file)
index e595ff9..0000000
+++ /dev/null
@@ -1,167 +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 <asm/arch/ap20.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/funcmux.h>
-#include <asm/arch/pmc.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/tegra20.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 *)TEGRA20_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 */
-       tegra20_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
-
-static int uart_configs[] = {
-#if defined(CONFIG_TEGRA20_UARTA_UAA_UAB)
-       FUNCMUX_UART1_UAA_UAB,
-#elif defined(CONFIG_TEGRA20_UARTA_GPU)
-       FUNCMUX_UART1_GPU,
-#elif defined(CONFIG_TEGRA20_UARTA_SDIO1)
-       FUNCMUX_UART1_SDIO1,
-#else
-       FUNCMUX_UART1_IRRX_IRTX,
-#endif
-       FUNCMUX_UART2_IRDA,
-       -1,
-       FUNCMUX_UART4_GMC,
-       -1,
-};
-
-/**
- * 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, uart_configs[i]);
-                       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_TEGRA20_ENABLE_UARTA
-       uart_ids |= UARTA;
-#endif
-#ifdef CONFIG_TEGRA20_ENABLE_UARTB
-       uart_ids |= UARTB;
-#endif
-#ifdef CONFIG_TEGRA20_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/tegra20/clock.c b/arch/arm/cpu/armv7/tegra20/clock.c
deleted file mode 100644 (file)
index 2403874..0000000
+++ /dev/null
@@ -1,1087 +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
- */
-
-/* Tegra20 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/tegra20.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 Tegra20 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;
-}
-
-int clock_get_osc_bypass(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_XOBP_MASK) >> OSC_XOBP_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_is_pll(clkid));
-       return &clkrst->crc_pll[clkid];
-}
-
-int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
-               u32 *divp, u32 *cpcon, u32 *lfcon)
-{
-       struct clk_pll *pll = get_pll(clkid);
-       u32 data;
-
-       assert(clkid != CLOCK_ID_USB);
-
-       /* Safety check, adds to code size but is small */
-       if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
-               return -1;
-       data = readl(&pll->pll_base);
-       *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
-       *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
-       *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
-       data = readl(&pll->pll_misc);
-       *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
-       *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
-
-       return 0;
-}
-
-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,
-                                        &divider_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. Tegra20 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 tegra20 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: /* OSC is 13Mhz */
-               clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8);
-               clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
-               break;
-       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/tegra20/crypto.c b/arch/arm/cpu/armv7/tegra20/crypto.c
deleted file mode 100644 (file)
index 5f0b240..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (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/errno.h>
-#include "crypto.h"
-#include "aes.h"
-
-static u8 zero_key[16];
-
-#define AES_CMAC_CONST_RB 0x87  /* from RFC 4493, Figure 2.2 */
-
-enum security_op {
-       SECURITY_SIGN           = 1 << 0,       /* Sign the data */
-       SECURITY_ENCRYPT        = 1 << 1,       /* Encrypt the data */
-};
-
-static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
-{
-       u32 i;
-
-       debug("%s [%d] @0x%08x", name, num_bytes, (u32)data);
-       for (i = 0; i < num_bytes; i++) {
-               if (i % 16 == 0)
-                       debug(" = ");
-               debug("%02x", data[i]);
-               if ((i+1) % 16 != 0)
-                       debug(" ");
-       }
-       debug("\n");
-}
-
-/**
- * Apply chain data to the destination using EOR
- *
- * Each array is of length AES_AES_KEY_LENGTH.
- *
- * \param cbc_chain_data       Chain data
- * \param src                  Source data
- * \param dst                  Destination data, which is modified here
- */
-static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst)
-{
-       int i;
-
-       for (i = 0; i < 16; i++)
-               *dst++ = *src++ ^ *cbc_chain_data++;
-}
-
-/**
- * Encrypt some data with AES.
- *
- * \param key_schedule         Expanded key to use
- * \param src                  Source data to encrypt
- * \param dst                  Destination buffer
- * \param num_aes_blocks       Number of AES blocks to encrypt
- */
-static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst,
-                          u32 num_aes_blocks)
-{
-       u8 tmp_data[AES_KEY_LENGTH];
-       u8 *cbc_chain_data;
-       u32 i;
-
-       cbc_chain_data = zero_key;      /* Convenient array of 0's for IV */
-
-       for (i = 0; i < num_aes_blocks; i++) {
-               debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
-               debug_print_vector("AES Src", AES_KEY_LENGTH, src);
-
-               /* Apply the chain data */
-               apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
-               debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
-
-               /* encrypt the AES block */
-               aes_encrypt(tmp_data, key_schedule, dst);
-               debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
-
-               /* Update pointers for next loop. */
-               cbc_chain_data = dst;
-               src += AES_KEY_LENGTH;
-               dst += AES_KEY_LENGTH;
-       }
-}
-
-/**
- * Shift a vector left by one bit
- *
- * \param in   Input vector
- * \param out  Output vector
- * \param size Length of vector in bytes
- */
-static void left_shift_vector(u8 *in, u8 *out, int size)
-{
-       int carry = 0;
-       int i;
-
-       for (i = size - 1; i >= 0; i--) {
-               out[i] = (in[i] << 1) | carry;
-               carry = in[i] >> 7;     /* get most significant bit */
-       }
-}
-
-/**
- * Sign a block of data, putting the result into dst.
- *
- * \param key                  Input AES key, length AES_KEY_LENGTH
- * \param key_schedule         Expanded key to use
- * \param src                  Source data of length 'num_aes_blocks' blocks
- * \param dst                  Destination buffer, length AES_KEY_LENGTH
- * \param num_aes_blocks       Number of AES blocks to encrypt
- */
-static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst,
-                       u32 num_aes_blocks)
-{
-       u8 tmp_data[AES_KEY_LENGTH];
-       u8 left[AES_KEY_LENGTH];
-       u8 k1[AES_KEY_LENGTH];
-       u8 *cbc_chain_data;
-       unsigned i;
-
-       cbc_chain_data = zero_key;      /* Convenient array of 0's for IV */
-
-       /* compute K1 constant needed by AES-CMAC calculation */
-       for (i = 0; i < AES_KEY_LENGTH; i++)
-               tmp_data[i] = 0;
-
-       encrypt_object(key_schedule, tmp_data, left, 1);
-       debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left);
-
-       left_shift_vector(left, k1, sizeof(left));
-       debug_print_vector("L", AES_KEY_LENGTH, left);
-
-       if ((left[0] >> 7) != 0) /* get MSB of L */
-               k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB;
-       debug_print_vector("K1", AES_KEY_LENGTH, k1);
-
-       /* compute the AES-CMAC value */
-       for (i = 0; i < num_aes_blocks; i++) {
-               /* Apply the chain data */
-               apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
-
-               /* for the final block, XOR K1 into the IV */
-               if (i == num_aes_blocks - 1)
-                       apply_cbc_chain_data(tmp_data, k1, tmp_data);
-
-               /* encrypt the AES block */
-               aes_encrypt(tmp_data, key_schedule, dst);
-
-               debug("sign_obj: block %d of %d\n", i, num_aes_blocks);
-               debug_print_vector("AES-CMAC Src", AES_KEY_LENGTH, src);
-               debug_print_vector("AES-CMAC Xor", AES_KEY_LENGTH, tmp_data);
-               debug_print_vector("AES-CMAC Dst", AES_KEY_LENGTH, dst);
-
-               /* Update pointers for next loop. */
-               cbc_chain_data = dst;
-               src += AES_KEY_LENGTH;
-       }
-
-       debug_print_vector("AES-CMAC Hash", AES_KEY_LENGTH, dst);
-}
-
-/**
- * Encrypt and sign a block of data (depending on security mode).
- *
- * \param key          Input AES key, length AES_KEY_LENGTH
- * \param oper         Security operations mask to perform (enum security_op)
- * \param src          Source data
- * \param length       Size of source data
- * \param sig_dst      Destination address for signature, AES_KEY_LENGTH bytes
- */
-static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src,
-                           u32 length, u8 *sig_dst)
-{
-       u32 num_aes_blocks;
-       u8 key_schedule[AES_EXPAND_KEY_LENGTH];
-
-       debug("encrypt_and_sign: length = %d\n", length);
-       debug_print_vector("AES key", AES_KEY_LENGTH, key);
-
-       /*
-        * The only need for a key is for signing/checksum purposes, so
-        * if not encrypting, expand a key of 0s.
-        */
-       aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule);
-
-       num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH;
-
-       if (oper & SECURITY_ENCRYPT) {
-               /* Perform this in place, resulting in src being encrypted. */
-               debug("encrypt_and_sign: begin encryption\n");
-               encrypt_object(key_schedule, src, src, num_aes_blocks);
-               debug("encrypt_and_sign: end encryption\n");
-       }
-
-       if (oper & SECURITY_SIGN) {
-               /* encrypt the data, overwriting the result in signature. */
-               debug("encrypt_and_sign: begin signing\n");
-               sign_object(key, key_schedule, src, sig_dst, num_aes_blocks);
-               debug("encrypt_and_sign: end signing\n");
-       }
-
-       return 0;
-}
-
-int sign_data_block(u8 *source, unsigned length, u8 *signature)
-{
-       return encrypt_and_sign(zero_key, SECURITY_SIGN, source,
-                               length, signature);
-}
diff --git a/arch/arm/cpu/armv7/tegra20/crypto.h b/arch/arm/cpu/armv7/tegra20/crypto.h
deleted file mode 100644 (file)
index aff67e7..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (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
- */
-
-#ifndef _CRYPTO_H_
-#define _CRYPTO_H_
-
-/**
- * Sign a block of data
- *
- * \param source       Source data
- * \param length       Size of source data
- * \param signature    Destination address for signature, AES_KEY_LENGTH bytes
- */
-int sign_data_block(u8 *source, unsigned length, u8 *signature);
-
-#endif /* #ifndef _CRYPTO_H_ */
diff --git a/arch/arm/cpu/armv7/tegra20/emc.c b/arch/arm/cpu/armv7/tegra20/emc.c
deleted file mode 100644 (file)
index ffc05e4..0000000
+++ /dev/null
@@ -1,286 +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
- */
-
-#include <common.h>
-#include <fdtdec.h>
-#include <asm/io.h>
-#include <asm/arch/ap20.h>
-#include <asm/arch/apb_misc.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/emc.h>
-#include <asm/arch/tegra20.h>
-
-/*
- * The EMC registers have shadow registers.  When the EMC clock is updated
- * in the clock controller, the shadow registers are copied to the active
- * registers, allowing glitchless memory bus frequency changes.
- * This function updates the shadow registers for a new clock frequency,
- * and relies on the clock lock on the emc clock to avoid races between
- * multiple frequency changes
- */
-
-/*
- * This table defines the ordering of the registers provided to
- * tegra_set_mmc()
- * TODO: Convert to fdt version once available
- */
-static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
-       0x2c,   /* RC */
-       0x30,   /* RFC */
-       0x34,   /* RAS */
-       0x38,   /* RP */
-       0x3c,   /* R2W */
-       0x40,   /* W2R */
-       0x44,   /* R2P */
-       0x48,   /* W2P */
-       0x4c,   /* RD_RCD */
-       0x50,   /* WR_RCD */
-       0x54,   /* RRD */
-       0x58,   /* REXT */
-       0x5c,   /* WDV */
-       0x60,   /* QUSE */
-       0x64,   /* QRST */
-       0x68,   /* QSAFE */
-       0x6c,   /* RDV */
-       0x70,   /* REFRESH */
-       0x74,   /* BURST_REFRESH_NUM */
-       0x78,   /* PDEX2WR */
-       0x7c,   /* PDEX2RD */
-       0x80,   /* PCHG2PDEN */
-       0x84,   /* ACT2PDEN */
-       0x88,   /* AR2PDEN */
-       0x8c,   /* RW2PDEN */
-       0x90,   /* TXSR */
-       0x94,   /* TCKE */
-       0x98,   /* TFAW */
-       0x9c,   /* TRPAB */
-       0xa0,   /* TCLKSTABLE */
-       0xa4,   /* TCLKSTOP */
-       0xa8,   /* TREFBW */
-       0xac,   /* QUSE_EXTRA */
-       0x114,  /* FBIO_CFG6 */
-       0xb0,   /* ODT_WRITE */
-       0xb4,   /* ODT_READ */
-       0x104,  /* FBIO_CFG5 */
-       0x2bc,  /* CFG_DIG_DLL */
-       0x2c0,  /* DLL_XFORM_DQS */
-       0x2c4,  /* DLL_XFORM_QUSE */
-       0x2e0,  /* ZCAL_REF_CNT */
-       0x2e4,  /* ZCAL_WAIT_CNT */
-       0x2a8,  /* AUTO_CAL_INTERVAL */
-       0x2d0,  /* CFG_CLKTRIM_0 */
-       0x2d4,  /* CFG_CLKTRIM_1 */
-       0x2d8,  /* CFG_CLKTRIM_2 */
-};
-
-struct emc_ctlr *emc_get_controller(const void *blob)
-{
-       fdt_addr_t addr;
-       int node;
-
-       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
-       if (node > 0) {
-               addr = fdtdec_get_addr(blob, node, "reg");
-               if (addr != FDT_ADDR_T_NONE)
-                       return (struct emc_ctlr *)addr;
-       }
-       return NULL;
-}
-
-/* Error codes we use */
-enum {
-       ERR_NO_EMC_NODE = -10,
-       ERR_NO_EMC_REG,
-       ERR_NO_FREQ,
-       ERR_FREQ_NOT_FOUND,
-       ERR_BAD_REGS,
-       ERR_NO_RAM_CODE,
-       ERR_RAM_CODE_NOT_FOUND,
-};
-
-/**
- * Find EMC tables for the given ram code.
- *
- * The tegra EMC binding has two options, one using the ram code and one not.
- * We detect which is in use by looking for the nvidia,use-ram-code property.
- * If this is not present, then the EMC tables are directly below 'node',
- * otherwise we select the correct emc-tables subnode based on the 'ram_code'
- * value.
- *
- * @param blob         Device tree blob
- * @param node         EMC node (nvidia,tegra20-emc compatible string)
- * @param ram_code     RAM code to select (0-3, or -1 if unknown)
- * @return 0 if ok, otherwise a -ve ERR_ code (see enum above)
- */
-static int find_emc_tables(const void *blob, int node, int ram_code)
-{
-       int need_ram_code;
-       int depth;
-       int offset;
-
-       /* If we are using RAM codes, scan through the tables for our code */
-       need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code");
-       if (!need_ram_code)
-               return node;
-       if (ram_code == -1) {
-               debug("%s: RAM code required but not supplied\n", __func__);
-               return ERR_NO_RAM_CODE;
-       }
-
-       offset = node;
-       depth = 0;
-       do {
-               /*
-                * Sadly there is no compatible string so we cannot use
-                * fdtdec_next_compatible_subnode().
-                */
-               offset = fdt_next_node(blob, offset, &depth);
-               if (depth <= 0)
-                       break;
-
-               /* Make sure this is a direct subnode */
-               if (depth != 1)
-                       continue;
-               if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL)))
-                       continue;
-
-               if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1)
-                               == ram_code)
-                       return offset;
-       } while (1);
-
-       debug("%s: Could not find tables for RAM code %d\n", __func__,
-             ram_code);
-       return ERR_RAM_CODE_NOT_FOUND;
-}
-
-/**
- * Decode the EMC node of the device tree, returning a pointer to the emc
- * controller and the table to be used for the given rate.
- *
- * @param blob Device tree blob
- * @param rate Clock speed of memory controller in Hz (=2x memory bus rate)
- * @param emcp Returns address of EMC controller registers
- * @param tablep Returns pointer to table to program into EMC. There are
- *             TEGRA_EMC_NUM_REGS entries, destined for offsets as per the
- *             emc_reg_addr array.
- * @return 0 if ok, otherwise a -ve error code which will allow someone to
- * figure out roughly what went wrong by looking at this code.
- */
-static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp,
-                     const u32 **tablep)
-{
-       struct apb_misc_pp_ctlr *pp =
-               (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE;
-       int ram_code;
-       int depth;
-       int node;
-
-       ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK)
-                       >> RAM_CODE_SHIFT;
-       /*
-        * The EMC clock rate is twice the bus rate, and the bus rate is
-        * measured in kHz
-        */
-       rate = rate / 2 / 1000;
-
-       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
-       if (node < 0) {
-               debug("%s: No EMC node found in FDT\n", __func__);
-               return ERR_NO_EMC_NODE;
-       }
-       *emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg");
-       if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) {
-               debug("%s: No EMC node reg property\n", __func__);
-               return ERR_NO_EMC_REG;
-       }
-
-       /* Work out the parent node which contains our EMC tables */
-       node = find_emc_tables(blob, node, ram_code & 3);
-       if (node < 0)
-               return node;
-
-       depth = 0;
-       for (;;) {
-               int node_rate;
-
-               node = fdtdec_next_compatible_subnode(blob, node,
-                               COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth);
-               if (node < 0)
-                       break;
-               node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1);
-               if (node_rate == -1) {
-                       debug("%s: Missing clock-frequency\n", __func__);
-                       return ERR_NO_FREQ; /* we expect this property */
-               }
-
-               if (node_rate == rate)
-                       break;
-       }
-       if (node < 0) {
-               debug("%s: No node found for clock frequency %d\n", __func__,
-                     rate);
-               return ERR_FREQ_NOT_FOUND;
-       }
-
-       *tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers",
-                                     TEGRA_EMC_NUM_REGS);
-       if (!*tablep) {
-               debug("%s: node '%s' array missing / wrong size\n", __func__,
-                     fdt_get_name(blob, node, NULL));
-               return ERR_BAD_REGS;
-       }
-
-       /* All seems well */
-       return 0;
-}
-
-int tegra_set_emc(const void *blob, unsigned rate)
-{
-       struct emc_ctlr *emc;
-       const u32 *table;
-       int err, i;
-
-       err = decode_emc(blob, rate, &emc, &table);
-       if (err) {
-               debug("Warning: no valid EMC (%d), memory timings unset\n",
-                      err);
-               return err;
-       }
-
-       debug("%s: Table found, setting EMC values as follows:\n", __func__);
-       for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) {
-               u32 value = fdt32_to_cpu(table[i]);
-               u32 addr = (uintptr_t)emc + emc_reg_addr[i];
-
-               debug("   %#x: %#x\n", addr, value);
-               writel(value, addr);
-       }
-
-       /* trigger emc with new settings */
-       clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY,
-                               clock_get_rate(CLOCK_ID_MEMORY), NULL);
-       debug("EMC clock set to %lu\n",
-             clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY));
-
-       return 0;
-}
diff --git a/arch/arm/cpu/armv7/tegra20/funcmux.c b/arch/arm/cpu/armv7/tegra20/funcmux.c
deleted file mode 100644 (file)
index 8cfed64..0000000
+++ /dev/null
@@ -1,249 +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
- */
-
-/* Tegra20 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:
-               switch (config) {
-               case 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);
-                       break;
-               case FUNCMUX_UART1_UAA_UAB:
-                       pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA);
-                       pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA);
-                       pinmux_tristate_disable(PINGRP_UAA);
-                       pinmux_tristate_disable(PINGRP_UAB);
-                       bad_config = 0;
-                       break;
-               case FUNCMUX_UART1_GPU:
-                       pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA);
-                       pinmux_tristate_disable(PINGRP_GPU);
-                       bad_config = 0;
-                       break;
-               case FUNCMUX_UART1_SDIO1:
-                       pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA);
-                       pinmux_tristate_disable(PINGRP_SDIO1);
-                       bad_config = 0;
-                       break;
-               }
-               if (!bad_config) {
-                       /*
-                        * 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_SDMMC1:
-               if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
-                       pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1);
-                       pinmux_tristate_disable(PINGRP_SDIO1);
-               }
-               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;
-
-       case PERIPH_ID_KBC:
-               if (config == FUNCMUX_DEFAULT) {
-                       enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB,
-                               PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE,
-                               PINGRP_KBCF};
-                       int i;
-
-                       for (i = 0; i < ARRAY_SIZE(grp); i++) {
-                               pinmux_tristate_disable(grp[i]);
-                               pinmux_set_func(grp[i], PMUX_FUNC_KBC);
-                               pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
-                       }
-               }
-               break;
-
-       case PERIPH_ID_USB2:
-               if (config == FUNCMUX_USB2_ULPI) {
-                       pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI);
-                       pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI);
-                       pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI);
-
-                       pinmux_tristate_disable(PINGRP_UAA);
-                       pinmux_tristate_disable(PINGRP_UAB);
-                       pinmux_tristate_disable(PINGRP_UDA);
-               }
-               break;
-
-       case PERIPH_ID_SPI1:
-               if (config == FUNCMUX_SPI1_GMC_GMD) {
-                       pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH);
-                       pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH);
-
-                       pinmux_tristate_disable(PINGRP_GMC);
-                       pinmux_tristate_disable(PINGRP_GMD);
-               }
-               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/tegra20/lowlevel_init.S b/arch/arm/cpu/armv7/tegra20/lowlevel_init.S
deleted file mode 100644 (file)
index d117f23..0000000
+++ /dev/null
@@ -1,42 +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>
-#include <linux/linkage.h>
-
-       .align  5
-ENTRY(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
-ENDPROC(reset_cpu)
diff --git a/arch/arm/cpu/armv7/tegra20/pinmux.c b/arch/arm/cpu/armv7/tegra20/pinmux.c
deleted file mode 100644 (file)
index 70e84df..0000000
+++ /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
- */
-
-/* Tegra20 pin multiplexing functions */
-
-#include <asm/io.h>
-#include <asm/arch/tegra20.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/tegra20/pmu.c b/arch/arm/cpu/armv7/tegra20/pmu.c
deleted file mode 100644 (file)
index 53505e9..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (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 <tps6586x.h>
-#include <asm/io.h>
-#include <asm/arch/ap20.h>
-#include <asm/arch/tegra20.h>
-#include <asm/arch/tegra_i2c.h>
-#include <asm/arch/sys_proto.h>
-
-#define VDD_CORE_NOMINAL_T25   0x17    /* 1.3v */
-#define VDD_CPU_NOMINAL_T25    0x10    /* 1.125v */
-
-#define VDD_CORE_NOMINAL_T20   0x16    /* 1.275v */
-#define VDD_CPU_NOMINAL_T20    0x0f    /* 1.1v */
-
-#define VDD_RELATION           0x02    /*  50mv */
-#define VDD_TRANSITION_STEP    0x06    /* 150mv */
-#define VDD_TRANSITION_RATE    0x06    /* 3.52mv/us */
-
-int pmu_set_nominal(void)
-{
-       int core, cpu, bus;
-
-       /* by default, the table has been filled with T25 settings */
-       switch (tegra_get_chip_type()) {
-       case TEGRA_SOC_T20:
-               core = VDD_CORE_NOMINAL_T20;
-               cpu = VDD_CPU_NOMINAL_T20;
-               break;
-       case TEGRA_SOC_T25:
-               core = VDD_CORE_NOMINAL_T25;
-               cpu = VDD_CPU_NOMINAL_T25;
-               break;
-       default:
-               debug("%s: Unknown chip type\n", __func__);
-               return -1;
-       }
-
-       bus = tegra_i2c_get_dvc_bus_num();
-       if (bus == -1) {
-               debug("%s: Cannot find DVC I2C bus\n", __func__);
-               return -1;
-       }
-       tps6586x_init(bus);
-       tps6586x_set_pwm_mode(TPS6586X_PWM_SM1);
-       return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP,
-                               VDD_TRANSITION_RATE, VDD_RELATION);
-}
diff --git a/arch/arm/cpu/armv7/tegra20/sys_info.c b/arch/arm/cpu/armv7/tegra20/sys_info.c
deleted file mode 100644 (file)
index 1a0bb56..0000000
+++ /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("TEGRA20\n");
-
-       /* TBD: Add printf of major/minor rev info, stepping, etc. */
-       return 0;
-}
-#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/armv7/tegra20/timer.c b/arch/arm/cpu/armv7/tegra20/timer.c
deleted file mode 100644 (file)
index 562e414..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- *
- * (C) Copyright 2008
- * Texas Instruments
- *
- * Richard Woodruff <r-woodruff2@ti.com>
- * Syed Moahmmed Khasim <khasim@ti.com>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- * Alex Zuepke <azu@sysgo.de>
- *
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <garyj@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/tegra20.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/armv7/tegra20/warmboot.c b/arch/arm/cpu/armv7/tegra20/warmboot.c
deleted file mode 100644 (file)
index 809ea01..0000000
+++ /dev/null
@@ -1,386 +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 <asm/errno.h>
-#include <asm/arch/ap20.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/tegra20.h>
-#include <asm/arch/fuse.h>
-#include <asm/arch/emc.h>
-#include <asm/arch/gp_padctrl.h>
-#include <asm/arch/warmboot.h>
-#include <asm/arch/sdram_param.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifndef CONFIG_TEGRA_CLOCK_SCALING
-#error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA20_LP0"
-#endif
-
-/*
- * This is the place in SRAM where the SDRAM parameters are stored. There
- * are 4 blocks, one for each RAM code
- */
-#define SDRAM_PARAMS_BASE      (AP20_BASE_PA_SRAM + 0x188)
-
-/* TODO: If we later add support for the Misc GP controller, refactor this */
-union xm2cfga_reg {
-       struct {
-               u32 reserved0:2;
-               u32 hsm_en:1;
-               u32 reserved1:2;
-               u32 preemp_en:1;
-               u32 vref_en:1;
-               u32 reserved2:5;
-               u32 cal_drvdn:5;
-               u32 reserved3:3;
-               u32 cal_drvup:5;
-               u32 reserved4:3;
-               u32 cal_drvdn_slwr:2;
-               u32 cal_drvup_slwf:2;
-       };
-       u32 word;
-};
-
-union xm2cfgd_reg {
-       struct {
-               u32 reserved0:2;
-               u32 hsm_en:1;
-               u32 schmt_en:1;
-               u32 lpmd:2;
-               u32 vref_en:1;
-               u32 reserved1:5;
-               u32 cal_drvdn:5;
-               u32 reserved2:3;
-               u32 cal_drvup:5;
-               u32 reserved3:3;
-               u32 cal_drvdn_slwr:2;
-               u32 cal_drvup_slwf:2;
-       };
-       u32 word;
-};
-
-/*
- * TODO: This register is not documented in the TRM yet. We could move this
- * into the EMC and give it a proper interface, but not while it is
- * undocumented.
- */
-union fbio_spare_reg {
-       struct {
-               u32 reserved:24;
-               u32 cfg_wb0:8;
-       };
-       u32 word;
-};
-
-/* We pack the resume information into these unions for later */
-union scratch2_reg {
-       struct {
-               u32 pllm_base_divm:5;
-               u32 pllm_base_divn:10;
-               u32 pllm_base_divp:3;
-               u32 pllm_misc_lfcon:4;
-               u32 pllm_misc_cpcon:4;
-               u32 gp_xm2cfga_padctrl_preemp:1;
-               u32 gp_xm2cfgd_padctrl_schmt:1;
-               u32 osc_ctrl_xobp:1;
-               u32 memory_type:3;
-       };
-       u32 word;
-};
-
-union scratch4_reg {
-       struct {
-               u32 emc_clock_divider:8;
-               u32 pllm_stable_time:8;
-               u32 pllx_stable_time:8;
-               u32 emc_fbio_spare_cfg_wb0:8;
-       };
-       u32 word;
-};
-
-union scratch24_reg {
-       struct {
-               u32 emc_auto_cal_wait:8;
-               u32 emc_pin_program_wait:8;
-               u32 warmboot_wait:8;
-               u32 reserved:8;
-       };
-       u32 word;
-};
-
-int warmboot_save_sdram_params(void)
-{
-       u32 ram_code;
-       struct sdram_params sdram;
-       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
-       struct apb_misc_gp_ctlr *gp =
-                       (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
-       struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob);
-       union scratch2_reg scratch2;
-       union scratch4_reg scratch4;
-       union scratch24_reg scratch24;
-       union xm2cfga_reg xm2cfga;
-       union xm2cfgd_reg xm2cfgd;
-       union fbio_spare_reg fbio_spare;
-
-       /* get ram code that is used as index to array sdram_params in BCT */
-       ram_code = (readl(&pmt->pmt_strap_opt_a) >>
-                       STRAP_OPT_A_RAM_CODE_SHIFT) & 3;
-       memcpy(&sdram,
-              (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code),
-              sizeof(sdram));
-
-       xm2cfga.word = readl(&gp->xm2cfga);
-       xm2cfgd.word = readl(&gp->xm2cfgd);
-
-       scratch2.word = 0;
-       scratch2.osc_ctrl_xobp = clock_get_osc_bypass();
-
-       /* Get the memory PLL settings */
-       {
-               u32 divm, divn, divp, cpcon, lfcon;
-
-               if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp,
-                                       &cpcon, &lfcon))
-                       return -1;
-               scratch2.pllm_base_divm = divm;
-               scratch2.pllm_base_divn = divn;
-               scratch2.pllm_base_divp = divp;
-               scratch2.pllm_misc_cpcon = cpcon;
-               scratch2.pllm_misc_lfcon = lfcon;
-       }
-
-       scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en;
-       scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en;
-       scratch2.memory_type = sdram.memory_type;
-       writel(scratch2.word, &pmc->pmc_scratch2);
-
-       /* collect data from various sources for pmc_scratch4 */
-       fbio_spare.word = readl(&emc->fbio_spare);
-       scratch4.word = 0;
-       scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0;
-       scratch4.emc_clock_divider = sdram.emc_clock_divider;
-       scratch4.pllm_stable_time = -1;
-       scratch4.pllx_stable_time = -1;
-       writel(scratch4.word, &pmc->pmc_scratch4);
-
-       /* collect various data from sdram for pmc_scratch24 */
-       scratch24.word = 0;
-       scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait;
-       scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait;
-       scratch24.warmboot_wait = sdram.warm_boot_wait;
-       writel(scratch24.word, &pmc->pmc_scratch24);
-
-       return 0;
-}
-
-static u32 get_major_version(void)
-{
-       u32 major_id;
-       struct apb_misc_gp_ctlr *gp =
-               (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
-
-       major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >>
-                       HIDREV_MAJORPREV_SHIFT;
-       return major_id;
-}
-
-static int is_production_mode_fuse_set(struct fuse_regs *fuse)
-{
-       return readl(&fuse->production_mode);
-}
-
-static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
-{
-       return readl(&fuse->security_mode);
-}
-
-static int is_failure_analysis_mode(struct fuse_regs *fuse)
-{
-       return readl(&fuse->fa);
-}
-
-static int ap20_is_odm_production_mode(void)
-{
-       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA20_FUSE_BASE;
-
-       if (!is_failure_analysis_mode(fuse) &&
-           is_odm_production_mode_fuse_set(fuse))
-               return 1;
-       else
-               return 0;
-}
-
-static int ap20_is_production_mode(void)
-{
-       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA20_FUSE_BASE;
-
-       if (get_major_version() == 0)
-               return 1;
-
-       if (!is_failure_analysis_mode(fuse) &&
-           is_production_mode_fuse_set(fuse) &&
-           !is_odm_production_mode_fuse_set(fuse))
-               return 1;
-       else
-               return 0;
-}
-
-static enum fuse_operating_mode fuse_get_operation_mode(void)
-{
-       u32 chip_id;
-       struct apb_misc_gp_ctlr *gp =
-               (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
-
-       chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >>
-                       HIDREV_CHIPID_SHIFT;
-       if (chip_id == CHIPID_TEGRA20) {
-               if (ap20_is_odm_production_mode()) {
-                       printf("!! odm_production_mode is not supported !!\n");
-                       return MODE_UNDEFINED;
-               } else
-                       if (ap20_is_production_mode())
-                               return MODE_PRODUCTION;
-                       else
-                               return MODE_UNDEFINED;
-       }
-       return MODE_UNDEFINED;
-}
-
-static void determine_crypto_options(int *is_encrypted, int *is_signed,
-                                    int *use_zero_key)
-{
-       switch (fuse_get_operation_mode()) {
-       case MODE_PRODUCTION:
-               *is_encrypted = 0;
-               *is_signed = 1;
-               *use_zero_key = 1;
-               break;
-       case MODE_UNDEFINED:
-       default:
-               *is_encrypted = 0;
-               *is_signed = 0;
-               *use_zero_key  = 0;
-               break;
-       }
-}
-
-static int sign_wb_code(u32 start, u32 length, int use_zero_key)
-{
-       int err;
-       u8 *source;             /* Pointer to source */
-       u8 *hash;
-
-       /* Calculate AES block parameters. */
-       source = (u8 *)(start + offsetof(struct wb_header, random_aes_block));
-       length -= offsetof(struct wb_header, random_aes_block);
-       hash = (u8 *)(start + offsetof(struct wb_header, hash));
-       err = sign_data_block(source, length, hash);
-
-       return err;
-}
-
-int warmboot_prepare_code(u32 seg_address, u32 seg_length)
-{
-       int err = 0;
-       u32 length;                     /* length of the signed/encrypt code */
-       struct wb_header *dst_header;   /* Pointer to dest WB header */
-       int is_encrypted;               /* Segment is encrypted */
-       int is_signed;                  /* Segment is signed */
-       int use_zero_key;               /* Use key of all zeros */
-
-       /* Determine crypto options. */
-       determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key);
-
-       /* Get the actual code limits. */
-       length = roundup(((u32)wb_end - (u32)wb_start), 16);
-
-       /*
-        * The region specified by seg_address must be in SDRAM and must be
-        * nonzero in length.
-        */
-       if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE ||
-               seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) {
-               err = -EFAULT;
-               goto fail;
-       }
-
-       /* Things must be 16-byte aligned. */
-       if ((seg_length & 0xF) || (seg_address & 0xF)) {
-               err = -EINVAL;
-               goto fail;
-       }
-
-       /* Will the code fit? (destination includes wb_header + wb code) */
-       if (seg_length < (length + sizeof(struct wb_header))) {
-               err = -EINVAL;
-               goto fail;
-       }
-
-       dst_header = (struct wb_header *)seg_address;
-       memset((char *)dst_header, 0, sizeof(struct wb_header));
-
-       /* Populate the random_aes_block as requested. */
-       {
-               u32 *aes_block = (u32 *)&(dst_header->random_aes_block);
-               u32 *end = (u32 *)(((u32)aes_block) +
-                                  sizeof(dst_header->random_aes_block));
-
-               do {
-                       *aes_block++ = 0;
-               } while (aes_block < end);
-       }
-
-       /* Populate the header. */
-       dst_header->length_insecure = length + sizeof(struct wb_header);
-       dst_header->length_secure = length + sizeof(struct wb_header);
-       dst_header->destination = AP20_WB_RUN_ADDRESS;
-       dst_header->entry_point = AP20_WB_RUN_ADDRESS;
-       dst_header->code_length = length;
-
-       if (is_encrypted) {
-               printf("!!!! Encryption is not supported !!!!\n");
-               dst_header->length_insecure = 0;
-               err = -EACCES;
-               goto fail;
-       } else
-               /* copy the wb code directly following dst_header. */
-               memcpy((char *)(dst_header+1), (char *)wb_start, length);
-
-       if (is_signed)
-               err = sign_wb_code(seg_address, dst_header->length_insecure,
-                                  use_zero_key);
-
-fail:
-       if (err)
-               printf("Warning: warmboot code copy failed (error=%d)\n", err);
-
-       return err;
-}
diff --git a/arch/arm/cpu/armv7/tegra20/warmboot_avp.c b/arch/arm/cpu/armv7/tegra20/warmboot_avp.c
deleted file mode 100644 (file)
index cd01908..0000000
+++ /dev/null
@@ -1,250 +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 <asm/arch/ap20.h>
-#include <asm/arch/clk_rst.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/flow.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/pmc.h>
-#include <asm/arch/tegra20.h>
-#include <asm/arch/warmboot.h>
-#include "warmboot_avp.h"
-
-#define DEBUG_RESET_CORESIGHT
-
-void wb_start(void)
-{
-       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
-       struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
-       struct clk_rst_ctlr *clkrst =
-                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       union osc_ctrl_reg osc_ctrl;
-       union pllx_base_reg pllx_base;
-       union pllx_misc_reg pllx_misc;
-       union scratch3_reg scratch3;
-       u32 reg;
-
-       /* enable JTAG & TBE */
-       writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl);
-
-       /* Are we running where we're supposed to be? */
-       asm volatile (
-               "adr    %0, wb_start;"  /* reg: wb_start address */
-               : "=r"(reg)             /* output */
-                                       /* no input, no clobber list */
-       );
-
-       if (reg != AP20_WB_RUN_ADDRESS)
-               goto do_reset;
-
-       /* Are we running with AVP? */
-       if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP)
-               goto do_reset;
-
-#ifdef DEBUG_RESET_CORESIGHT
-       /* Assert CoreSight reset */
-       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
-       reg |= SWR_CSITE_RST;
-       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
-#endif
-
-       /* TODO: Set the drive strength - maybe make this a board parameter? */
-       osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
-       osc_ctrl.xofs = 4;
-       osc_ctrl.xoe = 1;
-       writel(osc_ctrl.word, &clkrst->crc_osc_ctrl);
-
-       /* Power up the CPU complex if necessary */
-       if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) {
-               reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START;
-               writel(reg, &pmc->pmc_pwrgate_toggle);
-               while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU))
-                       ;
-       }
-
-       /* Remove the I/O clamps from the CPU power partition. */
-       reg = readl(&pmc->pmc_remove_clamping);
-       reg |= CPU_CLMP;
-       writel(reg, &pmc->pmc_remove_clamping);
-
-       reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP;
-       writel(reg, &flow->halt_cop_events);
-
-       /* Assert CPU complex reset */
-       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
-       reg |= CPU_RST;
-       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
-
-       /* Hold both CPUs in reset */
-       reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 |
-             CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1;
-       writel(reg, &clkrst->crc_cpu_cmplx_set);
-
-       /* Halt CPU1 at the flow controller for uni-processor configurations */
-       writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
-
-       /*
-        * Set the CPU reset vector. SCRATCH41 contains the physical
-        * address of the CPU-side restoration code.
-        */
-       reg = readl(&pmc->pmc_scratch41);
-       writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR);
-
-       /* Select CPU complex clock source */
-       writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
-
-       /* Start the CPU0 clock and stop the CPU1 clock */
-       reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN |
-             CPU_CMPLX_CPU1_CLK_STP_STOP;
-       writel(reg, &clkrst->crc_clk_cpu_cmplx);
-
-       /* Enable the CPU complex clock */
-       reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
-       reg |= CLK_ENB_CPU;
-       writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
-
-       /* Make sure the resets were held for at least 2 microseconds */
-       reg = readl(TIMER_USEC_CNTR);
-       while (readl(TIMER_USEC_CNTR) <= (reg + 2))
-               ;
-
-#ifdef DEBUG_RESET_CORESIGHT
-       /*
-        * De-assert CoreSight reset.
-        * NOTE: We're leaving the CoreSight clock on the oscillator for
-        *      now. It will be restored to its original clock source
-        *      when the CPU-side restoration code runs.
-        */
-       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
-       reg &= ~SWR_CSITE_RST;
-       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
-#endif
-
-       /* Unlock the CPU CoreSight interfaces */
-       reg = 0xC5ACCE55;
-       writel(reg, CSITE_CPU_DBG0_LAR);
-       writel(reg, CSITE_CPU_DBG1_LAR);
-
-       /*
-        * Sample the microsecond timestamp again. This is the time we must
-        * use when returning from LP0 for PLL stabilization delays.
-        */
-       reg = readl(TIMER_USEC_CNTR);
-       writel(reg, &pmc->pmc_scratch1);
-
-       pllx_base.word = 0;
-       pllx_misc.word = 0;
-       scratch3.word = readl(&pmc->pmc_scratch3);
-
-       /* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */
-       reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1;
-
-       /*
-        * According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and
-        * USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz.
-        *
-        * reg is used to calculate the pllx freq, which is used to determine if
-        * to set dccon or not.
-        */
-       if (reg > 26)
-               reg = 19;
-
-       /* PLLX_BASE.PLLX_DIVM */
-       if (scratch3.pllx_base_divm == reg)
-               reg = 0;
-       else
-               reg = 1;
-
-       /* PLLX_BASE.PLLX_DIVN */
-       pllx_base.divn = scratch3.pllx_base_divn;
-       reg = scratch3.pllx_base_divn << reg;
-
-       /* PLLX_BASE.PLLX_DIVP */
-       pllx_base.divp = scratch3.pllx_base_divp;
-       reg = reg >> scratch3.pllx_base_divp;
-
-       pllx_base.bypass = 1;
-
-       /* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */
-       if (reg > 600)
-               pllx_misc.dccon = 1;
-
-       /* PLLX_MISC_LFCON */
-       pllx_misc.lfcon = scratch3.pllx_misc_lfcon;
-
-       /* PLLX_MISC_CPCON */
-       pllx_misc.cpcon = scratch3.pllx_misc_cpcon;
-
-       writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc);
-       writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
-
-       pllx_base.enable = 1;
-       writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
-       pllx_base.bypass = 0;
-       writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
-
-       writel(0, flow->halt_cpu_events);
-
-       reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0;
-       writel(reg, &clkrst->crc_cpu_cmplx_clr);
-
-       reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE |
-             PLLM_OUT1_RATIO_VAL_8;
-       writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out);
-
-       reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 |
-             SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 |
-             SCLK_SYS_STATE_IDLE;
-       writel(reg, &clkrst->crc_sclk_brst_pol);
-
-       /* avp_resume: no return after the write */
-       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
-       reg &= ~CPU_RST;
-       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
-
-       /* avp_halt: */
-avp_halt:
-       reg = EVENT_MODE_STOP | EVENT_JTAG;
-       writel(reg, flow->halt_cop_events);
-       goto avp_halt;
-
-do_reset:
-       /*
-        * Execution comes here if something goes wrong. The chip is reset and
-        * a cold boot is performed.
-        */
-       writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
-       goto do_reset;
-}
-
-/*
- * wb_end() is a dummy function, and must be directly following wb_start(),
- * and is used to calculate the size of wb_start().
- */
-void wb_end(void)
-{
-}
diff --git a/arch/arm/cpu/armv7/tegra20/warmboot_avp.h b/arch/arm/cpu/armv7/tegra20/warmboot_avp.h
deleted file mode 100644 (file)
index 4b71c07..0000000
+++ /dev/null
@@ -1,81 +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
- */
-
-#ifndef _WARMBOOT_AVP_H_
-#define _WARMBOOT_AVP_H_
-
-#define TEGRA_DEV_L                    0
-#define TEGRA_DEV_H                    1
-#define TEGRA_DEV_U                    2
-
-#define SIMPLE_PLLX                    (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
-#define SIMPLE_PLLE                    (CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE)
-
-#define TIMER_USEC_CNTR                        (NV_PA_TMRUS_BASE + 0)
-#define TIMER_USEC_CFG                 (NV_PA_TMRUS_BASE + 4)
-
-#define USEC_CFG_DIVISOR_MASK          0xffff
-
-#define CONFIG_CTL_TBE                 (1 << 7)
-#define CONFIG_CTL_JTAG                        (1 << 6)
-
-#define CPU_RST                                (1 << 0)
-#define CLK_ENB_CPU                    (1 << 0)
-#define SWR_TRIG_SYS_RST               (1 << 2)
-#define SWR_CSITE_RST                  (1 << 9)
-
-#define PWRGATE_STATUS_CPU             (1 << 0)
-#define PWRGATE_TOGGLE_PARTID_CPU      (0 << 0)
-#define PWRGATE_TOGGLE_START           (1 << 8)
-
-#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4  (3 << 0)
-#define CPU_CMPLX_CPU0_CLK_STP_STOP    (1 << 8)
-#define CPU_CMPLX_CPU0_CLK_STP_RUN     (0 << 8)
-#define CPU_CMPLX_CPU1_CLK_STP_STOP    (1 << 9)
-#define CPU_CMPLX_CPU1_CLK_STP_RUN     (0 << 9)
-
-#define CPU_CMPLX_CPURESET0            (1 << 0)
-#define CPU_CMPLX_CPURESET1            (1 << 1)
-#define CPU_CMPLX_DERESET0             (1 << 4)
-#define CPU_CMPLX_DERESET1             (1 << 5)
-#define CPU_CMPLX_DBGRESET0            (1 << 12)
-#define CPU_CMPLX_DBGRESET1            (1 << 13)
-
-#define PLLM_OUT1_RSTN_RESET_DISABLE   (1 << 0)
-#define PLLM_OUT1_CLKEN_ENABLE         (1 << 1)
-#define PLLM_OUT1_RATIO_VAL_8          (8 << 8)
-
-#define SCLK_SYS_STATE_IDLE            (1 << 28)
-#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1   (7 << 12)
-#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1   (7 << 8)
-#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1   (7 << 4)
-#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1  (7 << 0)
-
-#define EVENT_ZERO_VAL_20              (20 << 0)
-#define EVENT_MSEC                     (1 << 24)
-#define EVENT_JTAG                     (1 << 28)
-#define EVENT_MODE_STOP                        (2 << 29)
-
-#define CCLK_PLLP_BURST_POLICY         0x20004444
-
-#endif
diff --git a/arch/arm/cpu/tegra20-common/Makefile b/arch/arm/cpu/tegra20-common/Makefile
new file mode 100644 (file)
index 0000000..60be2a6
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# (C) Copyright 2010,2011 Nvidia Corporation.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@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/tegra20-common/ap20.o += -march=armv4t
+CFLAGS_arch/arm/cpu/tegra20-common/clock.o += -march=armv4t
+CFLAGS_arch/arm/cpu/tegra20-common/warmboot_avp.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
+COBJS-$(CONFIG_TEGRA20_LP0) += warmboot.o crypto.o warmboot_avp.o
+COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
+COBJS-$(CONFIG_TEGRA_PMU) += pmu.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))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/tegra20-common/ap20.c b/arch/arm/cpu/tegra20-common/ap20.c
new file mode 100644 (file)
index 0000000..8b6afbc
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+* (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/io.h>
+#include <asm/arch/tegra20.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/fuse.h>
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/scu.h>
+#include <asm/arch/warmboot.h>
+#include <common.h>
+
+int tegra_get_chip_type(void)
+{
+       struct apb_misc_gp_ctlr *gp;
+       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA20_FUSE_BASE;
+       uint tegra_sku_id, rev;
+
+       /*
+        * This is undocumented, Chip ID is bits 15:8 of the register
+        * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for
+        * Tegra30
+        */
+       gp = (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
+       rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
+
+       tegra_sku_id = readl(&fuse->sku_info) & 0xff;
+
+       switch (rev) {
+       case CHIPID_TEGRA20:
+               switch (tegra_sku_id) {
+               case SKU_ID_T20:
+                       return TEGRA_SOC_T20;
+               case SKU_ID_T25SE:
+               case SKU_ID_AP25:
+               case SKU_ID_T25:
+               case SKU_ID_AP25E:
+               case SKU_ID_T25E:
+                       return TEGRA_SOC_T25;
+               }
+               break;
+       }
+       /* unknown sku id */
+       return TEGRA_SOC_UNKNOWN;
+}
+
+/* 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_simple *pll =
+               &clkrst->crc_pll_simple[CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE];
+       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 *)TEGRA20_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 *)TEGRA20_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 *)TEGRA20_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 *)TEGRA20_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);
+}
+
+static u32 get_odmdata(void)
+{
+       /*
+        * ODMDATA is stored in the BCT in IRAM by the BootROM.
+        * The BCT start and size are stored in the BIT in IRAM.
+        * Read the data @ bct_start + (bct_size - 12). This works
+        * on T20 and T30 BCTs, which are locked down. If this changes
+        * in new chips (T114, etc.), we can revisit this algorithm.
+        */
+
+       u32 bct_start, odmdata;
+
+       bct_start = readl(AP20_BASE_PA_SRAM + NVBOOTINFOTABLE_BCTPTR);
+       odmdata = readl(bct_start + BCT_ODMDATA_OFFSET);
+
+       return odmdata;
+}
+
+void init_pmc_scratch(void)
+{
+       struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+       u32 odmdata;
+       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. */
+       odmdata = get_odmdata();
+       writel(odmdata, &pmc->pmc_scratch20);
+
+#ifdef CONFIG_TEGRA20_LP0
+       /* save Sdram params to PMC 2, 4, and 24 for WB0 */
+       warmboot_save_sdram_params();
+#endif
+}
+
+void tegra20_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/tegra20-common/board.c b/arch/arm/cpu/tegra20-common/board.c
new file mode 100644 (file)
index 0000000..e595ff9
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *  (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 <asm/arch/ap20.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/tegra20.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 *)TEGRA20_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 */
+       tegra20_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
+
+static int uart_configs[] = {
+#if defined(CONFIG_TEGRA20_UARTA_UAA_UAB)
+       FUNCMUX_UART1_UAA_UAB,
+#elif defined(CONFIG_TEGRA20_UARTA_GPU)
+       FUNCMUX_UART1_GPU,
+#elif defined(CONFIG_TEGRA20_UARTA_SDIO1)
+       FUNCMUX_UART1_SDIO1,
+#else
+       FUNCMUX_UART1_IRRX_IRTX,
+#endif
+       FUNCMUX_UART2_IRDA,
+       -1,
+       FUNCMUX_UART4_GMC,
+       -1,
+};
+
+/**
+ * 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, uart_configs[i]);
+                       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_TEGRA20_ENABLE_UARTA
+       uart_ids |= UARTA;
+#endif
+#ifdef CONFIG_TEGRA20_ENABLE_UARTB
+       uart_ids |= UARTB;
+#endif
+#ifdef CONFIG_TEGRA20_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/tegra20-common/clock.c b/arch/arm/cpu/tegra20-common/clock.c
new file mode 100644 (file)
index 0000000..2403874
--- /dev/null
@@ -0,0 +1,1087 @@
+/*
+ * 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
+ */
+
+/* Tegra20 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/tegra20.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 Tegra20 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;
+}
+
+int clock_get_osc_bypass(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_XOBP_MASK) >> OSC_XOBP_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_is_pll(clkid));
+       return &clkrst->crc_pll[clkid];
+}
+
+int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
+               u32 *divp, u32 *cpcon, u32 *lfcon)
+{
+       struct clk_pll *pll = get_pll(clkid);
+       u32 data;
+
+       assert(clkid != CLOCK_ID_USB);
+
+       /* Safety check, adds to code size but is small */
+       if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
+               return -1;
+       data = readl(&pll->pll_base);
+       *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
+       *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
+       *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+       data = readl(&pll->pll_misc);
+       *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
+       *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
+
+       return 0;
+}
+
+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,
+                                        &divider_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. Tegra20 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 tegra20 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: /* OSC is 13Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
+               break;
+       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/tegra20-common/crypto.c b/arch/arm/cpu/tegra20-common/crypto.c
new file mode 100644 (file)
index 0000000..5f0b240
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (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/errno.h>
+#include "crypto.h"
+#include "aes.h"
+
+static u8 zero_key[16];
+
+#define AES_CMAC_CONST_RB 0x87  /* from RFC 4493, Figure 2.2 */
+
+enum security_op {
+       SECURITY_SIGN           = 1 << 0,       /* Sign the data */
+       SECURITY_ENCRYPT        = 1 << 1,       /* Encrypt the data */
+};
+
+static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
+{
+       u32 i;
+
+       debug("%s [%d] @0x%08x", name, num_bytes, (u32)data);
+       for (i = 0; i < num_bytes; i++) {
+               if (i % 16 == 0)
+                       debug(" = ");
+               debug("%02x", data[i]);
+               if ((i+1) % 16 != 0)
+                       debug(" ");
+       }
+       debug("\n");
+}
+
+/**
+ * Apply chain data to the destination using EOR
+ *
+ * Each array is of length AES_AES_KEY_LENGTH.
+ *
+ * \param cbc_chain_data       Chain data
+ * \param src                  Source data
+ * \param dst                  Destination data, which is modified here
+ */
+static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst)
+{
+       int i;
+
+       for (i = 0; i < 16; i++)
+               *dst++ = *src++ ^ *cbc_chain_data++;
+}
+
+/**
+ * Encrypt some data with AES.
+ *
+ * \param key_schedule         Expanded key to use
+ * \param src                  Source data to encrypt
+ * \param dst                  Destination buffer
+ * \param num_aes_blocks       Number of AES blocks to encrypt
+ */
+static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst,
+                          u32 num_aes_blocks)
+{
+       u8 tmp_data[AES_KEY_LENGTH];
+       u8 *cbc_chain_data;
+       u32 i;
+
+       cbc_chain_data = zero_key;      /* Convenient array of 0's for IV */
+
+       for (i = 0; i < num_aes_blocks; i++) {
+               debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
+               debug_print_vector("AES Src", AES_KEY_LENGTH, src);
+
+               /* Apply the chain data */
+               apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
+               debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
+
+               /* encrypt the AES block */
+               aes_encrypt(tmp_data, key_schedule, dst);
+               debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
+
+               /* Update pointers for next loop. */
+               cbc_chain_data = dst;
+               src += AES_KEY_LENGTH;
+               dst += AES_KEY_LENGTH;
+       }
+}
+
+/**
+ * Shift a vector left by one bit
+ *
+ * \param in   Input vector
+ * \param out  Output vector
+ * \param size Length of vector in bytes
+ */
+static void left_shift_vector(u8 *in, u8 *out, int size)
+{
+       int carry = 0;
+       int i;
+
+       for (i = size - 1; i >= 0; i--) {
+               out[i] = (in[i] << 1) | carry;
+               carry = in[i] >> 7;     /* get most significant bit */
+       }
+}
+
+/**
+ * Sign a block of data, putting the result into dst.
+ *
+ * \param key                  Input AES key, length AES_KEY_LENGTH
+ * \param key_schedule         Expanded key to use
+ * \param src                  Source data of length 'num_aes_blocks' blocks
+ * \param dst                  Destination buffer, length AES_KEY_LENGTH
+ * \param num_aes_blocks       Number of AES blocks to encrypt
+ */
+static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst,
+                       u32 num_aes_blocks)
+{
+       u8 tmp_data[AES_KEY_LENGTH];
+       u8 left[AES_KEY_LENGTH];
+       u8 k1[AES_KEY_LENGTH];
+       u8 *cbc_chain_data;
+       unsigned i;
+
+       cbc_chain_data = zero_key;      /* Convenient array of 0's for IV */
+
+       /* compute K1 constant needed by AES-CMAC calculation */
+       for (i = 0; i < AES_KEY_LENGTH; i++)
+               tmp_data[i] = 0;
+
+       encrypt_object(key_schedule, tmp_data, left, 1);
+       debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left);
+
+       left_shift_vector(left, k1, sizeof(left));
+       debug_print_vector("L", AES_KEY_LENGTH, left);
+
+       if ((left[0] >> 7) != 0) /* get MSB of L */
+               k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB;
+       debug_print_vector("K1", AES_KEY_LENGTH, k1);
+
+       /* compute the AES-CMAC value */
+       for (i = 0; i < num_aes_blocks; i++) {
+               /* Apply the chain data */
+               apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
+
+               /* for the final block, XOR K1 into the IV */
+               if (i == num_aes_blocks - 1)
+                       apply_cbc_chain_data(tmp_data, k1, tmp_data);
+
+               /* encrypt the AES block */
+               aes_encrypt(tmp_data, key_schedule, dst);
+
+               debug("sign_obj: block %d of %d\n", i, num_aes_blocks);
+               debug_print_vector("AES-CMAC Src", AES_KEY_LENGTH, src);
+               debug_print_vector("AES-CMAC Xor", AES_KEY_LENGTH, tmp_data);
+               debug_print_vector("AES-CMAC Dst", AES_KEY_LENGTH, dst);
+
+               /* Update pointers for next loop. */
+               cbc_chain_data = dst;
+               src += AES_KEY_LENGTH;
+       }
+
+       debug_print_vector("AES-CMAC Hash", AES_KEY_LENGTH, dst);
+}
+
+/**
+ * Encrypt and sign a block of data (depending on security mode).
+ *
+ * \param key          Input AES key, length AES_KEY_LENGTH
+ * \param oper         Security operations mask to perform (enum security_op)
+ * \param src          Source data
+ * \param length       Size of source data
+ * \param sig_dst      Destination address for signature, AES_KEY_LENGTH bytes
+ */
+static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src,
+                           u32 length, u8 *sig_dst)
+{
+       u32 num_aes_blocks;
+       u8 key_schedule[AES_EXPAND_KEY_LENGTH];
+
+       debug("encrypt_and_sign: length = %d\n", length);
+       debug_print_vector("AES key", AES_KEY_LENGTH, key);
+
+       /*
+        * The only need for a key is for signing/checksum purposes, so
+        * if not encrypting, expand a key of 0s.
+        */
+       aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule);
+
+       num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH;
+
+       if (oper & SECURITY_ENCRYPT) {
+               /* Perform this in place, resulting in src being encrypted. */
+               debug("encrypt_and_sign: begin encryption\n");
+               encrypt_object(key_schedule, src, src, num_aes_blocks);
+               debug("encrypt_and_sign: end encryption\n");
+       }
+
+       if (oper & SECURITY_SIGN) {
+               /* encrypt the data, overwriting the result in signature. */
+               debug("encrypt_and_sign: begin signing\n");
+               sign_object(key, key_schedule, src, sig_dst, num_aes_blocks);
+               debug("encrypt_and_sign: end signing\n");
+       }
+
+       return 0;
+}
+
+int sign_data_block(u8 *source, unsigned length, u8 *signature)
+{
+       return encrypt_and_sign(zero_key, SECURITY_SIGN, source,
+                               length, signature);
+}
diff --git a/arch/arm/cpu/tegra20-common/crypto.h b/arch/arm/cpu/tegra20-common/crypto.h
new file mode 100644 (file)
index 0000000..aff67e7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (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
+ */
+
+#ifndef _CRYPTO_H_
+#define _CRYPTO_H_
+
+/**
+ * Sign a block of data
+ *
+ * \param source       Source data
+ * \param length       Size of source data
+ * \param signature    Destination address for signature, AES_KEY_LENGTH bytes
+ */
+int sign_data_block(u8 *source, unsigned length, u8 *signature);
+
+#endif /* #ifndef _CRYPTO_H_ */
diff --git a/arch/arm/cpu/tegra20-common/emc.c b/arch/arm/cpu/tegra20-common/emc.c
new file mode 100644 (file)
index 0000000..ffc05e4
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * 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
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/apb_misc.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/emc.h>
+#include <asm/arch/tegra20.h>
+
+/*
+ * The EMC registers have shadow registers.  When the EMC clock is updated
+ * in the clock controller, the shadow registers are copied to the active
+ * registers, allowing glitchless memory bus frequency changes.
+ * This function updates the shadow registers for a new clock frequency,
+ * and relies on the clock lock on the emc clock to avoid races between
+ * multiple frequency changes
+ */
+
+/*
+ * This table defines the ordering of the registers provided to
+ * tegra_set_mmc()
+ * TODO: Convert to fdt version once available
+ */
+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+       0x2c,   /* RC */
+       0x30,   /* RFC */
+       0x34,   /* RAS */
+       0x38,   /* RP */
+       0x3c,   /* R2W */
+       0x40,   /* W2R */
+       0x44,   /* R2P */
+       0x48,   /* W2P */
+       0x4c,   /* RD_RCD */
+       0x50,   /* WR_RCD */
+       0x54,   /* RRD */
+       0x58,   /* REXT */
+       0x5c,   /* WDV */
+       0x60,   /* QUSE */
+       0x64,   /* QRST */
+       0x68,   /* QSAFE */
+       0x6c,   /* RDV */
+       0x70,   /* REFRESH */
+       0x74,   /* BURST_REFRESH_NUM */
+       0x78,   /* PDEX2WR */
+       0x7c,   /* PDEX2RD */
+       0x80,   /* PCHG2PDEN */
+       0x84,   /* ACT2PDEN */
+       0x88,   /* AR2PDEN */
+       0x8c,   /* RW2PDEN */
+       0x90,   /* TXSR */
+       0x94,   /* TCKE */
+       0x98,   /* TFAW */
+       0x9c,   /* TRPAB */
+       0xa0,   /* TCLKSTABLE */
+       0xa4,   /* TCLKSTOP */
+       0xa8,   /* TREFBW */
+       0xac,   /* QUSE_EXTRA */
+       0x114,  /* FBIO_CFG6 */
+       0xb0,   /* ODT_WRITE */
+       0xb4,   /* ODT_READ */
+       0x104,  /* FBIO_CFG5 */
+       0x2bc,  /* CFG_DIG_DLL */
+       0x2c0,  /* DLL_XFORM_DQS */
+       0x2c4,  /* DLL_XFORM_QUSE */
+       0x2e0,  /* ZCAL_REF_CNT */
+       0x2e4,  /* ZCAL_WAIT_CNT */
+       0x2a8,  /* AUTO_CAL_INTERVAL */
+       0x2d0,  /* CFG_CLKTRIM_0 */
+       0x2d4,  /* CFG_CLKTRIM_1 */
+       0x2d8,  /* CFG_CLKTRIM_2 */
+};
+
+struct emc_ctlr *emc_get_controller(const void *blob)
+{
+       fdt_addr_t addr;
+       int node;
+
+       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
+       if (node > 0) {
+               addr = fdtdec_get_addr(blob, node, "reg");
+               if (addr != FDT_ADDR_T_NONE)
+                       return (struct emc_ctlr *)addr;
+       }
+       return NULL;
+}
+
+/* Error codes we use */
+enum {
+       ERR_NO_EMC_NODE = -10,
+       ERR_NO_EMC_REG,
+       ERR_NO_FREQ,
+       ERR_FREQ_NOT_FOUND,
+       ERR_BAD_REGS,
+       ERR_NO_RAM_CODE,
+       ERR_RAM_CODE_NOT_FOUND,
+};
+
+/**
+ * Find EMC tables for the given ram code.
+ *
+ * The tegra EMC binding has two options, one using the ram code and one not.
+ * We detect which is in use by looking for the nvidia,use-ram-code property.
+ * If this is not present, then the EMC tables are directly below 'node',
+ * otherwise we select the correct emc-tables subnode based on the 'ram_code'
+ * value.
+ *
+ * @param blob         Device tree blob
+ * @param node         EMC node (nvidia,tegra20-emc compatible string)
+ * @param ram_code     RAM code to select (0-3, or -1 if unknown)
+ * @return 0 if ok, otherwise a -ve ERR_ code (see enum above)
+ */
+static int find_emc_tables(const void *blob, int node, int ram_code)
+{
+       int need_ram_code;
+       int depth;
+       int offset;
+
+       /* If we are using RAM codes, scan through the tables for our code */
+       need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code");
+       if (!need_ram_code)
+               return node;
+       if (ram_code == -1) {
+               debug("%s: RAM code required but not supplied\n", __func__);
+               return ERR_NO_RAM_CODE;
+       }
+
+       offset = node;
+       depth = 0;
+       do {
+               /*
+                * Sadly there is no compatible string so we cannot use
+                * fdtdec_next_compatible_subnode().
+                */
+               offset = fdt_next_node(blob, offset, &depth);
+               if (depth <= 0)
+                       break;
+
+               /* Make sure this is a direct subnode */
+               if (depth != 1)
+                       continue;
+               if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL)))
+                       continue;
+
+               if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1)
+                               == ram_code)
+                       return offset;
+       } while (1);
+
+       debug("%s: Could not find tables for RAM code %d\n", __func__,
+             ram_code);
+       return ERR_RAM_CODE_NOT_FOUND;
+}
+
+/**
+ * Decode the EMC node of the device tree, returning a pointer to the emc
+ * controller and the table to be used for the given rate.
+ *
+ * @param blob Device tree blob
+ * @param rate Clock speed of memory controller in Hz (=2x memory bus rate)
+ * @param emcp Returns address of EMC controller registers
+ * @param tablep Returns pointer to table to program into EMC. There are
+ *             TEGRA_EMC_NUM_REGS entries, destined for offsets as per the
+ *             emc_reg_addr array.
+ * @return 0 if ok, otherwise a -ve error code which will allow someone to
+ * figure out roughly what went wrong by looking at this code.
+ */
+static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp,
+                     const u32 **tablep)
+{
+       struct apb_misc_pp_ctlr *pp =
+               (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE;
+       int ram_code;
+       int depth;
+       int node;
+
+       ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK)
+                       >> RAM_CODE_SHIFT;
+       /*
+        * The EMC clock rate is twice the bus rate, and the bus rate is
+        * measured in kHz
+        */
+       rate = rate / 2 / 1000;
+
+       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
+       if (node < 0) {
+               debug("%s: No EMC node found in FDT\n", __func__);
+               return ERR_NO_EMC_NODE;
+       }
+       *emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg");
+       if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) {
+               debug("%s: No EMC node reg property\n", __func__);
+               return ERR_NO_EMC_REG;
+       }
+
+       /* Work out the parent node which contains our EMC tables */
+       node = find_emc_tables(blob, node, ram_code & 3);
+       if (node < 0)
+               return node;
+
+       depth = 0;
+       for (;;) {
+               int node_rate;
+
+               node = fdtdec_next_compatible_subnode(blob, node,
+                               COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth);
+               if (node < 0)
+                       break;
+               node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1);
+               if (node_rate == -1) {
+                       debug("%s: Missing clock-frequency\n", __func__);
+                       return ERR_NO_FREQ; /* we expect this property */
+               }
+
+               if (node_rate == rate)
+                       break;
+       }
+       if (node < 0) {
+               debug("%s: No node found for clock frequency %d\n", __func__,
+                     rate);
+               return ERR_FREQ_NOT_FOUND;
+       }
+
+       *tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers",
+                                     TEGRA_EMC_NUM_REGS);
+       if (!*tablep) {
+               debug("%s: node '%s' array missing / wrong size\n", __func__,
+                     fdt_get_name(blob, node, NULL));
+               return ERR_BAD_REGS;
+       }
+
+       /* All seems well */
+       return 0;
+}
+
+int tegra_set_emc(const void *blob, unsigned rate)
+{
+       struct emc_ctlr *emc;
+       const u32 *table;
+       int err, i;
+
+       err = decode_emc(blob, rate, &emc, &table);
+       if (err) {
+               debug("Warning: no valid EMC (%d), memory timings unset\n",
+                      err);
+               return err;
+       }
+
+       debug("%s: Table found, setting EMC values as follows:\n", __func__);
+       for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) {
+               u32 value = fdt32_to_cpu(table[i]);
+               u32 addr = (uintptr_t)emc + emc_reg_addr[i];
+
+               debug("   %#x: %#x\n", addr, value);
+               writel(value, addr);
+       }
+
+       /* trigger emc with new settings */
+       clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY,
+                               clock_get_rate(CLOCK_ID_MEMORY), NULL);
+       debug("EMC clock set to %lu\n",
+             clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY));
+
+       return 0;
+}
diff --git a/arch/arm/cpu/tegra20-common/funcmux.c b/arch/arm/cpu/tegra20-common/funcmux.c
new file mode 100644 (file)
index 0000000..8cfed64
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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
+ */
+
+/* Tegra20 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:
+               switch (config) {
+               case 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);
+                       break;
+               case FUNCMUX_UART1_UAA_UAB:
+                       pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA);
+                       pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA);
+                       pinmux_tristate_disable(PINGRP_UAA);
+                       pinmux_tristate_disable(PINGRP_UAB);
+                       bad_config = 0;
+                       break;
+               case FUNCMUX_UART1_GPU:
+                       pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA);
+                       pinmux_tristate_disable(PINGRP_GPU);
+                       bad_config = 0;
+                       break;
+               case FUNCMUX_UART1_SDIO1:
+                       pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA);
+                       pinmux_tristate_disable(PINGRP_SDIO1);
+                       bad_config = 0;
+                       break;
+               }
+               if (!bad_config) {
+                       /*
+                        * 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_SDMMC1:
+               if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
+                       pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1);
+                       pinmux_tristate_disable(PINGRP_SDIO1);
+               }
+               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;
+
+       case PERIPH_ID_KBC:
+               if (config == FUNCMUX_DEFAULT) {
+                       enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB,
+                               PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE,
+                               PINGRP_KBCF};
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(grp); i++) {
+                               pinmux_tristate_disable(grp[i]);
+                               pinmux_set_func(grp[i], PMUX_FUNC_KBC);
+                               pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
+                       }
+               }
+               break;
+
+       case PERIPH_ID_USB2:
+               if (config == FUNCMUX_USB2_ULPI) {
+                       pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI);
+                       pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI);
+                       pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI);
+
+                       pinmux_tristate_disable(PINGRP_UAA);
+                       pinmux_tristate_disable(PINGRP_UAB);
+                       pinmux_tristate_disable(PINGRP_UDA);
+               }
+               break;
+
+       case PERIPH_ID_SPI1:
+               if (config == FUNCMUX_SPI1_GMC_GMD) {
+                       pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH);
+                       pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH);
+
+                       pinmux_tristate_disable(PINGRP_GMC);
+                       pinmux_tristate_disable(PINGRP_GMD);
+               }
+               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/tegra20-common/lowlevel_init.S b/arch/arm/cpu/tegra20-common/lowlevel_init.S
new file mode 100644 (file)
index 0000000..d117f23
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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>
+#include <linux/linkage.h>
+
+       .align  5
+ENTRY(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
+ENDPROC(reset_cpu)
diff --git a/arch/arm/cpu/tegra20-common/pinmux.c b/arch/arm/cpu/tegra20-common/pinmux.c
new file mode 100644 (file)
index 0000000..70e84df
--- /dev/null
@@ -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
+ */
+
+/* Tegra20 pin multiplexing functions */
+
+#include <asm/io.h>
+#include <asm/arch/tegra20.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/tegra20-common/pmu.c b/arch/arm/cpu/tegra20-common/pmu.c
new file mode 100644 (file)
index 0000000..53505e9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (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 <tps6586x.h>
+#include <asm/io.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/tegra20.h>
+#include <asm/arch/tegra_i2c.h>
+#include <asm/arch/sys_proto.h>
+
+#define VDD_CORE_NOMINAL_T25   0x17    /* 1.3v */
+#define VDD_CPU_NOMINAL_T25    0x10    /* 1.125v */
+
+#define VDD_CORE_NOMINAL_T20   0x16    /* 1.275v */
+#define VDD_CPU_NOMINAL_T20    0x0f    /* 1.1v */
+
+#define VDD_RELATION           0x02    /*  50mv */
+#define VDD_TRANSITION_STEP    0x06    /* 150mv */
+#define VDD_TRANSITION_RATE    0x06    /* 3.52mv/us */
+
+int pmu_set_nominal(void)
+{
+       int core, cpu, bus;
+
+       /* by default, the table has been filled with T25 settings */
+       switch (tegra_get_chip_type()) {
+       case TEGRA_SOC_T20:
+               core = VDD_CORE_NOMINAL_T20;
+               cpu = VDD_CPU_NOMINAL_T20;
+               break;
+       case TEGRA_SOC_T25:
+               core = VDD_CORE_NOMINAL_T25;
+               cpu = VDD_CPU_NOMINAL_T25;
+               break;
+       default:
+               debug("%s: Unknown chip type\n", __func__);
+               return -1;
+       }
+
+       bus = tegra_i2c_get_dvc_bus_num();
+       if (bus == -1) {
+               debug("%s: Cannot find DVC I2C bus\n", __func__);
+               return -1;
+       }
+       tps6586x_init(bus);
+       tps6586x_set_pwm_mode(TPS6586X_PWM_SM1);
+       return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP,
+                               VDD_TRANSITION_RATE, VDD_RELATION);
+}
diff --git a/arch/arm/cpu/tegra20-common/sys_info.c b/arch/arm/cpu/tegra20-common/sys_info.c
new file mode 100644 (file)
index 0000000..1a0bb56
--- /dev/null
@@ -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("TEGRA20\n");
+
+       /* TBD: Add printf of major/minor rev info, stepping, etc. */
+       return 0;
+}
+#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/tegra20-common/timer.c b/arch/arm/cpu/tegra20-common/timer.c
new file mode 100644 (file)
index 0000000..562e414
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * (C) Copyright 2010,2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * (C) Copyright 2008
+ * Texas Instruments
+ *
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Syed Moahmmed Khasim <khasim@ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@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/tegra20.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/tegra20-common/warmboot.c b/arch/arm/cpu/tegra20-common/warmboot.c
new file mode 100644 (file)
index 0000000..809ea01
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * (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 <asm/errno.h>
+#include <asm/arch/ap20.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/tegra20.h>
+#include <asm/arch/fuse.h>
+#include <asm/arch/emc.h>
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch/warmboot.h>
+#include <asm/arch/sdram_param.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_TEGRA_CLOCK_SCALING
+#error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA20_LP0"
+#endif
+
+/*
+ * This is the place in SRAM where the SDRAM parameters are stored. There
+ * are 4 blocks, one for each RAM code
+ */
+#define SDRAM_PARAMS_BASE      (AP20_BASE_PA_SRAM + 0x188)
+
+/* TODO: If we later add support for the Misc GP controller, refactor this */
+union xm2cfga_reg {
+       struct {
+               u32 reserved0:2;
+               u32 hsm_en:1;
+               u32 reserved1:2;
+               u32 preemp_en:1;
+               u32 vref_en:1;
+               u32 reserved2:5;
+               u32 cal_drvdn:5;
+               u32 reserved3:3;
+               u32 cal_drvup:5;
+               u32 reserved4:3;
+               u32 cal_drvdn_slwr:2;
+               u32 cal_drvup_slwf:2;
+       };
+       u32 word;
+};
+
+union xm2cfgd_reg {
+       struct {
+               u32 reserved0:2;
+               u32 hsm_en:1;
+               u32 schmt_en:1;
+               u32 lpmd:2;
+               u32 vref_en:1;
+               u32 reserved1:5;
+               u32 cal_drvdn:5;
+               u32 reserved2:3;
+               u32 cal_drvup:5;
+               u32 reserved3:3;
+               u32 cal_drvdn_slwr:2;
+               u32 cal_drvup_slwf:2;
+       };
+       u32 word;
+};
+
+/*
+ * TODO: This register is not documented in the TRM yet. We could move this
+ * into the EMC and give it a proper interface, but not while it is
+ * undocumented.
+ */
+union fbio_spare_reg {
+       struct {
+               u32 reserved:24;
+               u32 cfg_wb0:8;
+       };
+       u32 word;
+};
+
+/* We pack the resume information into these unions for later */
+union scratch2_reg {
+       struct {
+               u32 pllm_base_divm:5;
+               u32 pllm_base_divn:10;
+               u32 pllm_base_divp:3;
+               u32 pllm_misc_lfcon:4;
+               u32 pllm_misc_cpcon:4;
+               u32 gp_xm2cfga_padctrl_preemp:1;
+               u32 gp_xm2cfgd_padctrl_schmt:1;
+               u32 osc_ctrl_xobp:1;
+               u32 memory_type:3;
+       };
+       u32 word;
+};
+
+union scratch4_reg {
+       struct {
+               u32 emc_clock_divider:8;
+               u32 pllm_stable_time:8;
+               u32 pllx_stable_time:8;
+               u32 emc_fbio_spare_cfg_wb0:8;
+       };
+       u32 word;
+};
+
+union scratch24_reg {
+       struct {
+               u32 emc_auto_cal_wait:8;
+               u32 emc_pin_program_wait:8;
+               u32 warmboot_wait:8;
+               u32 reserved:8;
+       };
+       u32 word;
+};
+
+int warmboot_save_sdram_params(void)
+{
+       u32 ram_code;
+       struct sdram_params sdram;
+       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+       struct apb_misc_gp_ctlr *gp =
+                       (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
+       struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob);
+       union scratch2_reg scratch2;
+       union scratch4_reg scratch4;
+       union scratch24_reg scratch24;
+       union xm2cfga_reg xm2cfga;
+       union xm2cfgd_reg xm2cfgd;
+       union fbio_spare_reg fbio_spare;
+
+       /* get ram code that is used as index to array sdram_params in BCT */
+       ram_code = (readl(&pmt->pmt_strap_opt_a) >>
+                       STRAP_OPT_A_RAM_CODE_SHIFT) & 3;
+       memcpy(&sdram,
+              (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code),
+              sizeof(sdram));
+
+       xm2cfga.word = readl(&gp->xm2cfga);
+       xm2cfgd.word = readl(&gp->xm2cfgd);
+
+       scratch2.word = 0;
+       scratch2.osc_ctrl_xobp = clock_get_osc_bypass();
+
+       /* Get the memory PLL settings */
+       {
+               u32 divm, divn, divp, cpcon, lfcon;
+
+               if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp,
+                                       &cpcon, &lfcon))
+                       return -1;
+               scratch2.pllm_base_divm = divm;
+               scratch2.pllm_base_divn = divn;
+               scratch2.pllm_base_divp = divp;
+               scratch2.pllm_misc_cpcon = cpcon;
+               scratch2.pllm_misc_lfcon = lfcon;
+       }
+
+       scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en;
+       scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en;
+       scratch2.memory_type = sdram.memory_type;
+       writel(scratch2.word, &pmc->pmc_scratch2);
+
+       /* collect data from various sources for pmc_scratch4 */
+       fbio_spare.word = readl(&emc->fbio_spare);
+       scratch4.word = 0;
+       scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0;
+       scratch4.emc_clock_divider = sdram.emc_clock_divider;
+       scratch4.pllm_stable_time = -1;
+       scratch4.pllx_stable_time = -1;
+       writel(scratch4.word, &pmc->pmc_scratch4);
+
+       /* collect various data from sdram for pmc_scratch24 */
+       scratch24.word = 0;
+       scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait;
+       scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait;
+       scratch24.warmboot_wait = sdram.warm_boot_wait;
+       writel(scratch24.word, &pmc->pmc_scratch24);
+
+       return 0;
+}
+
+static u32 get_major_version(void)
+{
+       u32 major_id;
+       struct apb_misc_gp_ctlr *gp =
+               (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
+
+       major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >>
+                       HIDREV_MAJORPREV_SHIFT;
+       return major_id;
+}
+
+static int is_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+       return readl(&fuse->production_mode);
+}
+
+static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+       return readl(&fuse->security_mode);
+}
+
+static int is_failure_analysis_mode(struct fuse_regs *fuse)
+{
+       return readl(&fuse->fa);
+}
+
+static int ap20_is_odm_production_mode(void)
+{
+       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA20_FUSE_BASE;
+
+       if (!is_failure_analysis_mode(fuse) &&
+           is_odm_production_mode_fuse_set(fuse))
+               return 1;
+       else
+               return 0;
+}
+
+static int ap20_is_production_mode(void)
+{
+       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA20_FUSE_BASE;
+
+       if (get_major_version() == 0)
+               return 1;
+
+       if (!is_failure_analysis_mode(fuse) &&
+           is_production_mode_fuse_set(fuse) &&
+           !is_odm_production_mode_fuse_set(fuse))
+               return 1;
+       else
+               return 0;
+}
+
+static enum fuse_operating_mode fuse_get_operation_mode(void)
+{
+       u32 chip_id;
+       struct apb_misc_gp_ctlr *gp =
+               (struct apb_misc_gp_ctlr *)TEGRA20_APB_MISC_GP_BASE;
+
+       chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >>
+                       HIDREV_CHIPID_SHIFT;
+       if (chip_id == CHIPID_TEGRA20) {
+               if (ap20_is_odm_production_mode()) {
+                       printf("!! odm_production_mode is not supported !!\n");
+                       return MODE_UNDEFINED;
+               } else
+                       if (ap20_is_production_mode())
+                               return MODE_PRODUCTION;
+                       else
+                               return MODE_UNDEFINED;
+       }
+       return MODE_UNDEFINED;
+}
+
+static void determine_crypto_options(int *is_encrypted, int *is_signed,
+                                    int *use_zero_key)
+{
+       switch (fuse_get_operation_mode()) {
+       case MODE_PRODUCTION:
+               *is_encrypted = 0;
+               *is_signed = 1;
+               *use_zero_key = 1;
+               break;
+       case MODE_UNDEFINED:
+       default:
+               *is_encrypted = 0;
+               *is_signed = 0;
+               *use_zero_key  = 0;
+               break;
+       }
+}
+
+static int sign_wb_code(u32 start, u32 length, int use_zero_key)
+{
+       int err;
+       u8 *source;             /* Pointer to source */
+       u8 *hash;
+
+       /* Calculate AES block parameters. */
+       source = (u8 *)(start + offsetof(struct wb_header, random_aes_block));
+       length -= offsetof(struct wb_header, random_aes_block);
+       hash = (u8 *)(start + offsetof(struct wb_header, hash));
+       err = sign_data_block(source, length, hash);
+
+       return err;
+}
+
+int warmboot_prepare_code(u32 seg_address, u32 seg_length)
+{
+       int err = 0;
+       u32 length;                     /* length of the signed/encrypt code */
+       struct wb_header *dst_header;   /* Pointer to dest WB header */
+       int is_encrypted;               /* Segment is encrypted */
+       int is_signed;                  /* Segment is signed */
+       int use_zero_key;               /* Use key of all zeros */
+
+       /* Determine crypto options. */
+       determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key);
+
+       /* Get the actual code limits. */
+       length = roundup(((u32)wb_end - (u32)wb_start), 16);
+
+       /*
+        * The region specified by seg_address must be in SDRAM and must be
+        * nonzero in length.
+        */
+       if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE ||
+               seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) {
+               err = -EFAULT;
+               goto fail;
+       }
+
+       /* Things must be 16-byte aligned. */
+       if ((seg_length & 0xF) || (seg_address & 0xF)) {
+               err = -EINVAL;
+               goto fail;
+       }
+
+       /* Will the code fit? (destination includes wb_header + wb code) */
+       if (seg_length < (length + sizeof(struct wb_header))) {
+               err = -EINVAL;
+               goto fail;
+       }
+
+       dst_header = (struct wb_header *)seg_address;
+       memset((char *)dst_header, 0, sizeof(struct wb_header));
+
+       /* Populate the random_aes_block as requested. */
+       {
+               u32 *aes_block = (u32 *)&(dst_header->random_aes_block);
+               u32 *end = (u32 *)(((u32)aes_block) +
+                                  sizeof(dst_header->random_aes_block));
+
+               do {
+                       *aes_block++ = 0;
+               } while (aes_block < end);
+       }
+
+       /* Populate the header. */
+       dst_header->length_insecure = length + sizeof(struct wb_header);
+       dst_header->length_secure = length + sizeof(struct wb_header);
+       dst_header->destination = AP20_WB_RUN_ADDRESS;
+       dst_header->entry_point = AP20_WB_RUN_ADDRESS;
+       dst_header->code_length = length;
+
+       if (is_encrypted) {
+               printf("!!!! Encryption is not supported !!!!\n");
+               dst_header->length_insecure = 0;
+               err = -EACCES;
+               goto fail;
+       } else
+               /* copy the wb code directly following dst_header. */
+               memcpy((char *)(dst_header+1), (char *)wb_start, length);
+
+       if (is_signed)
+               err = sign_wb_code(seg_address, dst_header->length_insecure,
+                                  use_zero_key);
+
+fail:
+       if (err)
+               printf("Warning: warmboot code copy failed (error=%d)\n", err);
+
+       return err;
+}
diff --git a/arch/arm/cpu/tegra20-common/warmboot_avp.c b/arch/arm/cpu/tegra20-common/warmboot_avp.c
new file mode 100644 (file)
index 0000000..cd01908
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * (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 <asm/arch/ap20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/flow.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/tegra20.h>
+#include <asm/arch/warmboot.h>
+#include "warmboot_avp.h"
+
+#define DEBUG_RESET_CORESIGHT
+
+void wb_start(void)
+{
+       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE;
+       struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       union osc_ctrl_reg osc_ctrl;
+       union pllx_base_reg pllx_base;
+       union pllx_misc_reg pllx_misc;
+       union scratch3_reg scratch3;
+       u32 reg;
+
+       /* enable JTAG & TBE */
+       writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl);
+
+       /* Are we running where we're supposed to be? */
+       asm volatile (
+               "adr    %0, wb_start;"  /* reg: wb_start address */
+               : "=r"(reg)             /* output */
+                                       /* no input, no clobber list */
+       );
+
+       if (reg != AP20_WB_RUN_ADDRESS)
+               goto do_reset;
+
+       /* Are we running with AVP? */
+       if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP)
+               goto do_reset;
+
+#ifdef DEBUG_RESET_CORESIGHT
+       /* Assert CoreSight reset */
+       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
+       reg |= SWR_CSITE_RST;
+       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
+#endif
+
+       /* TODO: Set the drive strength - maybe make this a board parameter? */
+       osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
+       osc_ctrl.xofs = 4;
+       osc_ctrl.xoe = 1;
+       writel(osc_ctrl.word, &clkrst->crc_osc_ctrl);
+
+       /* Power up the CPU complex if necessary */
+       if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) {
+               reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START;
+               writel(reg, &pmc->pmc_pwrgate_toggle);
+               while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU))
+                       ;
+       }
+
+       /* Remove the I/O clamps from the CPU power partition. */
+       reg = readl(&pmc->pmc_remove_clamping);
+       reg |= CPU_CLMP;
+       writel(reg, &pmc->pmc_remove_clamping);
+
+       reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP;
+       writel(reg, &flow->halt_cop_events);
+
+       /* Assert CPU complex reset */
+       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
+       reg |= CPU_RST;
+       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
+
+       /* Hold both CPUs in reset */
+       reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 |
+             CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1;
+       writel(reg, &clkrst->crc_cpu_cmplx_set);
+
+       /* Halt CPU1 at the flow controller for uni-processor configurations */
+       writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
+
+       /*
+        * Set the CPU reset vector. SCRATCH41 contains the physical
+        * address of the CPU-side restoration code.
+        */
+       reg = readl(&pmc->pmc_scratch41);
+       writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+       /* Select CPU complex clock source */
+       writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+
+       /* Start the CPU0 clock and stop the CPU1 clock */
+       reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN |
+             CPU_CMPLX_CPU1_CLK_STP_STOP;
+       writel(reg, &clkrst->crc_clk_cpu_cmplx);
+
+       /* Enable the CPU complex clock */
+       reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
+       reg |= CLK_ENB_CPU;
+       writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
+
+       /* Make sure the resets were held for at least 2 microseconds */
+       reg = readl(TIMER_USEC_CNTR);
+       while (readl(TIMER_USEC_CNTR) <= (reg + 2))
+               ;
+
+#ifdef DEBUG_RESET_CORESIGHT
+       /*
+        * De-assert CoreSight reset.
+        * NOTE: We're leaving the CoreSight clock on the oscillator for
+        *      now. It will be restored to its original clock source
+        *      when the CPU-side restoration code runs.
+        */
+       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
+       reg &= ~SWR_CSITE_RST;
+       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
+#endif
+
+       /* Unlock the CPU CoreSight interfaces */
+       reg = 0xC5ACCE55;
+       writel(reg, CSITE_CPU_DBG0_LAR);
+       writel(reg, CSITE_CPU_DBG1_LAR);
+
+       /*
+        * Sample the microsecond timestamp again. This is the time we must
+        * use when returning from LP0 for PLL stabilization delays.
+        */
+       reg = readl(TIMER_USEC_CNTR);
+       writel(reg, &pmc->pmc_scratch1);
+
+       pllx_base.word = 0;
+       pllx_misc.word = 0;
+       scratch3.word = readl(&pmc->pmc_scratch3);
+
+       /* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */
+       reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1;
+
+       /*
+        * According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and
+        * USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz.
+        *
+        * reg is used to calculate the pllx freq, which is used to determine if
+        * to set dccon or not.
+        */
+       if (reg > 26)
+               reg = 19;
+
+       /* PLLX_BASE.PLLX_DIVM */
+       if (scratch3.pllx_base_divm == reg)
+               reg = 0;
+       else
+               reg = 1;
+
+       /* PLLX_BASE.PLLX_DIVN */
+       pllx_base.divn = scratch3.pllx_base_divn;
+       reg = scratch3.pllx_base_divn << reg;
+
+       /* PLLX_BASE.PLLX_DIVP */
+       pllx_base.divp = scratch3.pllx_base_divp;
+       reg = reg >> scratch3.pllx_base_divp;
+
+       pllx_base.bypass = 1;
+
+       /* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */
+       if (reg > 600)
+               pllx_misc.dccon = 1;
+
+       /* PLLX_MISC_LFCON */
+       pllx_misc.lfcon = scratch3.pllx_misc_lfcon;
+
+       /* PLLX_MISC_CPCON */
+       pllx_misc.cpcon = scratch3.pllx_misc_cpcon;
+
+       writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc);
+       writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+
+       pllx_base.enable = 1;
+       writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+       pllx_base.bypass = 0;
+       writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+
+       writel(0, flow->halt_cpu_events);
+
+       reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0;
+       writel(reg, &clkrst->crc_cpu_cmplx_clr);
+
+       reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE |
+             PLLM_OUT1_RATIO_VAL_8;
+       writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out);
+
+       reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 |
+             SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 |
+             SCLK_SYS_STATE_IDLE;
+       writel(reg, &clkrst->crc_sclk_brst_pol);
+
+       /* avp_resume: no return after the write */
+       reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
+       reg &= ~CPU_RST;
+       writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
+
+       /* avp_halt: */
+avp_halt:
+       reg = EVENT_MODE_STOP | EVENT_JTAG;
+       writel(reg, flow->halt_cop_events);
+       goto avp_halt;
+
+do_reset:
+       /*
+        * Execution comes here if something goes wrong. The chip is reset and
+        * a cold boot is performed.
+        */
+       writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
+       goto do_reset;
+}
+
+/*
+ * wb_end() is a dummy function, and must be directly following wb_start(),
+ * and is used to calculate the size of wb_start().
+ */
+void wb_end(void)
+{
+}
diff --git a/arch/arm/cpu/tegra20-common/warmboot_avp.h b/arch/arm/cpu/tegra20-common/warmboot_avp.h
new file mode 100644 (file)
index 0000000..4b71c07
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * (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
+ */
+
+#ifndef _WARMBOOT_AVP_H_
+#define _WARMBOOT_AVP_H_
+
+#define TEGRA_DEV_L                    0
+#define TEGRA_DEV_H                    1
+#define TEGRA_DEV_U                    2
+
+#define SIMPLE_PLLX                    (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
+#define SIMPLE_PLLE                    (CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE)
+
+#define TIMER_USEC_CNTR                        (NV_PA_TMRUS_BASE + 0)
+#define TIMER_USEC_CFG                 (NV_PA_TMRUS_BASE + 4)
+
+#define USEC_CFG_DIVISOR_MASK          0xffff
+
+#define CONFIG_CTL_TBE                 (1 << 7)
+#define CONFIG_CTL_JTAG                        (1 << 6)
+
+#define CPU_RST                                (1 << 0)
+#define CLK_ENB_CPU                    (1 << 0)
+#define SWR_TRIG_SYS_RST               (1 << 2)
+#define SWR_CSITE_RST                  (1 << 9)
+
+#define PWRGATE_STATUS_CPU             (1 << 0)
+#define PWRGATE_TOGGLE_PARTID_CPU      (0 << 0)
+#define PWRGATE_TOGGLE_START           (1 << 8)
+
+#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4  (3 << 0)
+#define CPU_CMPLX_CPU0_CLK_STP_STOP    (1 << 8)
+#define CPU_CMPLX_CPU0_CLK_STP_RUN     (0 << 8)
+#define CPU_CMPLX_CPU1_CLK_STP_STOP    (1 << 9)
+#define CPU_CMPLX_CPU1_CLK_STP_RUN     (0 << 9)
+
+#define CPU_CMPLX_CPURESET0            (1 << 0)
+#define CPU_CMPLX_CPURESET1            (1 << 1)
+#define CPU_CMPLX_DERESET0             (1 << 4)
+#define CPU_CMPLX_DERESET1             (1 << 5)
+#define CPU_CMPLX_DBGRESET0            (1 << 12)
+#define CPU_CMPLX_DBGRESET1            (1 << 13)
+
+#define PLLM_OUT1_RSTN_RESET_DISABLE   (1 << 0)
+#define PLLM_OUT1_CLKEN_ENABLE         (1 << 1)
+#define PLLM_OUT1_RATIO_VAL_8          (8 << 8)
+
+#define SCLK_SYS_STATE_IDLE            (1 << 28)
+#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1   (7 << 12)
+#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1   (7 << 8)
+#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1   (7 << 4)
+#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1  (7 << 0)
+
+#define EVENT_ZERO_VAL_20              (20 << 0)
+#define EVENT_MSEC                     (1 << 24)
+#define EVENT_JTAG                     (1 << 28)
+#define EVENT_MODE_STOP                        (2 << 29)
+
+#define CCLK_PLLP_BURST_POLICY         0x20004444
+
+#endif
index 2cf7bdad630053010e1869c70750abab32ada4ed..8946d827e4111f7e0f981e32760113313f6126ca 100644 (file)
@@ -61,6 +61,10 @@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
 endif
 
+ifeq ($(SOC),tegra20)
+LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
+endif
+
 START := $(addprefix $(SPLTREE)/,$(START))
 LIBS := $(addprefix $(SPLTREE)/,$(sort $(LIBS-y)))