summaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/arm1136/mx31/devices.c4
-rw-r--r--arch/arm/cpu/arm1136/mx31/generic.c59
-rw-r--r--arch/arm/cpu/arm1136/mx31/timer.c40
-rw-r--r--arch/arm/cpu/arm920t/a320/Makefile1
-rw-r--r--arch/arm/cpu/arm920t/a320/ftsmc020.c51
-rw-r--r--arch/arm/cpu/arm920t/a320/timer.c25
-rw-r--r--arch/arm/cpu/arm926ejs/armada100/cpu.c16
-rw-r--r--arch/arm/cpu/arm926ejs/mx25/generic.c2
-rw-r--r--arch/arm/cpu/arm926ejs/orion5x/Makefile2
-rw-r--r--arch/arm/cpu/arm926ejs/orion5x/cpu.c2
-rw-r--r--arch/arm/cpu/arm926ejs/orion5x/dram.c4
-rw-r--r--arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S2
-rw-r--r--arch/arm/cpu/arm926ejs/orion5x/timer.c2
-rw-r--r--arch/arm/cpu/arm926ejs/pantheon/cpu.c12
-rw-r--r--arch/arm/cpu/arm926ejs/start.S2
-rw-r--r--arch/arm/cpu/arm946es/start.S2
-rw-r--r--arch/arm/cpu/armv7/mx5/soc.c28
-rw-r--r--arch/arm/cpu/armv7/omap3/clock.c20
-rw-r--r--arch/arm/cpu/armv7/omap3/lowlevel_init.S22
-rw-r--r--arch/arm/cpu/armv7/omap3/mem.c32
-rw-r--r--arch/arm/cpu/armv7/start.S14
-rw-r--r--arch/arm/cpu/armv7/tegra2/Makefile2
-rw-r--r--arch/arm/cpu/armv7/tegra2/ap20.c358
-rw-r--r--arch/arm/cpu/armv7/tegra2/ap20.h104
-rw-r--r--arch/arm/cpu/armv7/tegra2/lowlevel_init.S94
-rw-r--r--arch/arm/cpu/pxa/Makefile1
-rw-r--r--arch/arm/cpu/pxa/cpu.c10
-rw-r--r--arch/arm/cpu/pxa/i2c.c469
28 files changed, 787 insertions, 593 deletions
diff --git a/arch/arm/cpu/arm1136/mx31/devices.c b/arch/arm/cpu/arm1136/mx31/devices.c
index 1f4ca7e..1e7d48f 100644
--- a/arch/arm/cpu/arm1136/mx31/devices.c
+++ b/arch/arm/cpu/arm1136/mx31/devices.c
@@ -24,8 +24,8 @@
*/
#include <common.h>
-#include <asm/arch/mx31-regs.h>
-#include <asm/arch/mx31.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
#ifdef CONFIG_SYS_MX31_UART1
void mx31_uart1_hw_init(void)
diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c
index 8bd23ee..18572b9 100644
--- a/arch/arm/cpu/arm1136/mx31/generic.c
+++ b/arch/arm/cpu/arm1136/mx31/generic.c
@@ -22,7 +22,7 @@
*/
#include <common.h>
-#include <asm/arch/mx31-regs.h>
+#include <asm/arch/imx-regs.h>
#include <asm/io.h>
static u32 mx31_decode_pll(u32 reg, u32 infreq)
@@ -106,11 +106,64 @@ void mx31_set_pad(enum iomux_pins pin, u32 config)
}
+struct mx3_cpu_type mx31_cpu_type[] = {
+ { .srev = 0x00, .v = "1.0" },
+ { .srev = 0x10, .v = "1.1" },
+ { .srev = 0x11, .v = "1.1" },
+ { .srev = 0x12, .v = "1.15" },
+ { .srev = 0x13, .v = "1.15" },
+ { .srev = 0x14, .v = "1.2" },
+ { .srev = 0x15, .v = "1.2" },
+ { .srev = 0x28, .v = "2.0" },
+ { .srev = 0x29, .v = "2.0" },
+};
+
+char *get_cpu_rev(void)
+{
+ u32 i, srev;
+
+ /* read SREV register from IIM module */
+ struct iim_regs *iim = (struct iim_regs *)MX31_IIM_BASE_ADDR;
+ srev = readl(&iim->iim_srev);
+
+ for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
+ if (srev == mx31_cpu_type[i].srev)
+ return mx31_cpu_type[i].v;
+ return "unknown";
+}
+
+char *get_reset_cause(void)
+{
+ /* read RCSR register from CCM module */
+ struct clock_control_regs *ccm =
+ (struct clock_control_regs *)CCM_BASE;
+
+ u32 cause = readl(&ccm->rcsr) & 0x07;
+
+ switch (cause) {
+ case 0x0000:
+ return "POR";
+ break;
+ case 0x0001:
+ return "RST";
+ break;
+ case 0x0002:
+ return "WDOG";
+ break;
+ case 0x0006:
+ return "JTAG";
+ break;
+ default:
+ return "unknown reset";
+ }
+}
+
#if defined(CONFIG_DISPLAY_CPUINFO)
int print_cpuinfo (void)
{
- printf("CPU: Freescale i.MX31 at %d MHz\n",
- mx31_get_mcu_main_clk() / 1000000);
+ printf("CPU: Freescale i.MX31 rev %s at %d MHz.",
+ get_cpu_rev(), mx31_get_mcu_main_clk() / 1000000);
+ printf("Reset cause: %s\n", get_reset_cause());
return 0;
}
#endif
diff --git a/arch/arm/cpu/arm1136/mx31/timer.c b/arch/arm/cpu/arm1136/mx31/timer.c
index f6be3b9..c4bc3b3 100644
--- a/arch/arm/cpu/arm1136/mx31/timer.c
+++ b/arch/arm/cpu/arm1136/mx31/timer.c
@@ -22,8 +22,10 @@
*/
#include <common.h>
-#include <asm/arch/mx31-regs.h>
+#include <asm/arch/imx-regs.h>
#include <div64.h>
+#include <watchdog.h>
+#include <asm/io.h>
#define TIMER_BASE 0x53f90000 /* General purpose timer 1 */
@@ -165,5 +167,39 @@ void __udelay (unsigned long usec)
void reset_cpu (ulong addr)
{
- __REG16(WDOG_BASE) = 4;
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE;
+ wdog->wcr = WDOG_ENABLE;
+ while (1)
+ ;
}
+
+#ifdef CONFIG_HW_WATCHDOG
+void mxc_hw_watchdog_enable(void)
+{
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE;
+ u16 secs;
+
+ /*
+ * The timer watchdog can be set between
+ * 0.5 and 128 Seconds. If not defined
+ * in configuration file, sets 64 Seconds
+ */
+#ifdef CONFIG_SYS_WD_TIMER_SECS
+ secs = (CONFIG_SYS_WD_TIMER_SECS << 1) & 0xFF;
+ if (!secs) secs = 1;
+#else
+ secs = 64;
+#endif
+ writew(readw(&wdog->wcr) | (secs << WDOG_WT_SHIFT) | WDOG_ENABLE,
+ &wdog->wcr);
+}
+
+
+void mxc_hw_watchdog_reset(void)
+{
+ struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE;
+
+ writew(0x5555, &wdog->wsr);
+ writew(0xAAAA, &wdog->wsr);
+}
+#endif
diff --git a/arch/arm/cpu/arm920t/a320/Makefile b/arch/arm/cpu/arm920t/a320/Makefile
index 31da706..50eb265 100644
--- a/arch/arm/cpu/arm920t/a320/Makefile
+++ b/arch/arm/cpu/arm920t/a320/Makefile
@@ -27,7 +27,6 @@ LIB = $(obj)lib$(SOC).o
SOBJS += reset.o
COBJS += timer.o
-COBJS += ftsmc020.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/arch/arm/cpu/arm920t/a320/ftsmc020.c b/arch/arm/cpu/arm920t/a320/ftsmc020.c
deleted file mode 100644
index 7646537..0000000
--- a/arch/arm/cpu/arm920t/a320/ftsmc020.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * (C) Copyright 2009 Faraday Technology
- * Po-Yu Chuang <ratbert@faraday-tech.com>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <config.h>
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/ftsmc020.h>
-
-struct ftsmc020_config {
- unsigned int config;
- unsigned int timing;
-};
-
-static struct ftsmc020_config config[] = CONFIG_SYS_FTSMC020_CONFIGS;
-
-static struct ftsmc020 *smc = (struct ftsmc020 *)CONFIG_FTSMC020_BASE;
-
-static void ftsmc020_setup_bank(unsigned int bank, struct ftsmc020_config *cfg)
-{
- if (bank > 3) {
- printf("bank # %u invalid\n", bank);
- return;
- }
-
- writel(cfg->config, &smc->bank[bank].cr);
- writel(cfg->timing, &smc->bank[bank].tpr);
-}
-
-void ftsmc020_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(config); i++)
- ftsmc020_setup_bank(i, &config[i]);
-}
diff --git a/arch/arm/cpu/arm920t/a320/timer.c b/arch/arm/cpu/arm920t/a320/timer.c
index d2e316f..95cb8fd 100644
--- a/arch/arm/cpu/arm920t/a320/timer.c
+++ b/arch/arm/cpu/arm920t/a320/timer.c
@@ -19,21 +19,19 @@
#include <common.h>
#include <asm/io.h>
-#include <asm/arch/ftpmu010.h>
-#include <asm/arch/fttmr010.h>
+#include <faraday/ftpmu010.h>
+#include <faraday/fttmr010.h>
static ulong timestamp;
static ulong lastdec;
static struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
-static struct ftpmu010 *pmu = (struct ftpmu010 *)CONFIG_FTPMU010_BASE;
#define TIMER_CLOCK 32768
#define TIMER_LOAD_VAL 0xffffffff
int timer_init(void)
{
- unsigned int oscc;
unsigned int cr;
debug("%s()\n", __func__);
@@ -41,23 +39,8 @@ int timer_init(void)
/* disable timers */
writel(0, &tmr->cr);
- /*
- * use 32768Hz oscillator for RTC, WDT, TIMER
- */
-
- /* enable the 32768Hz oscillator */
- oscc = readl(&pmu->OSCC);
- oscc &= ~(FTPMU010_OSCC_OSCL_OFF | FTPMU010_OSCC_OSCL_TRI);
- writel(oscc, &pmu->OSCC);
-
- /* wait until ready */
- while (!(readl(&pmu->OSCC) & FTPMU010_OSCC_OSCL_STABLE))
- ;
-
- /* select 32768Hz oscillator */
- oscc = readl(&pmu->OSCC);
- oscc |= FTPMU010_OSCC_OSCL_RTCLSEL;
- writel(oscc, &pmu->OSCC);
+ /* use 32768Hz oscillator for RTC, WDT, TIMER */
+ ftpmu010_32768osc_enable();
/* setup timer */
writel(TIMER_LOAD_VAL, &tmr->timer3_load);
diff --git a/arch/arm/cpu/arm926ejs/armada100/cpu.c b/arch/arm/cpu/arm926ejs/armada100/cpu.c
index 62aa175..c21938e 100644
--- a/arch/arm/cpu/arm926ejs/armada100/cpu.c
+++ b/arch/arm/cpu/arm926ejs/armada100/cpu.c
@@ -62,6 +62,16 @@ int arch_cpu_init(void)
/* Enable GPIO clock */
writel(APBC_APBCLK, &apb1clkres->gpio);
+#ifdef CONFIG_I2C_MV
+ /* Enable general I2C clock */
+ writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0);
+ writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0);
+
+ /* Enable power I2C clock */
+ writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1);
+ writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1);
+#endif
+
/*
* Enable Functional and APB clock at 14.7456MHz
* for configured UART console
@@ -90,3 +100,9 @@ int print_cpuinfo(void)
return 0;
}
#endif
+
+#ifdef CONFIG_I2C_MV
+void i2c_clk_enable(void)
+{
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/mx25/generic.c b/arch/arm/cpu/arm926ejs/mx25/generic.c
index c6e1146..76e4b5c 100644
--- a/arch/arm/cpu/arm926ejs/mx25/generic.c
+++ b/arch/arm/cpu/arm926ejs/mx25/generic.c
@@ -145,7 +145,7 @@ int cpu_mmc_init (bd_t * bis)
}
#ifdef CONFIG_MXC_UART
-void mx25_uart_init_pins (void)
+void mx25_uart1_init_pins(void)
{
struct iomuxc_mux_ctl *muxctl;
struct iomuxc_pad_ctl *padctl;
diff --git a/arch/arm/cpu/arm926ejs/orion5x/Makefile b/arch/arm/cpu/arm926ejs/orion5x/Makefile
index e5a9994..a4298b4 100644
--- a/arch/arm/cpu/arm926ejs/orion5x/Makefile
+++ b/arch/arm/cpu/arm926ejs/orion5x/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Albert ARIBAUD <albert.aribaud@free.fr>
+# Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
#
# Based on original Kirkwood support which is
# (C) Copyright 2009
diff --git a/arch/arm/cpu/arm926ejs/orion5x/cpu.c b/arch/arm/cpu/arm926ejs/orion5x/cpu.c
index 1894b52..05bd45c 100644
--- a/arch/arm/cpu/arm926ejs/orion5x/cpu.c
+++ b/arch/arm/cpu/arm926ejs/orion5x/cpu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Albert ARIBAUD <albert.aribaud@free.fr>
+ * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
*
* Based on original Kirkwood support which is
* (C) Copyright 2009
diff --git a/arch/arm/cpu/arm926ejs/orion5x/dram.c b/arch/arm/cpu/arm926ejs/orion5x/dram.c
index b749282..3e1ff7d 100644
--- a/arch/arm/cpu/arm926ejs/orion5x/dram.c
+++ b/arch/arm/cpu/arm926ejs/orion5x/dram.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Albert ARIBAUD <albert.aribaud@free.fr>
+ * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
*
* Based on original Kirkwood support which is
* (C) Copyright 2009
@@ -38,7 +38,7 @@ u32 orion5x_sdram_bar(enum memory_bank bank)
{
struct orion5x_ddr_addr_decode_registers *winregs =
(struct orion5x_ddr_addr_decode_registers *)
- ORION5X_CPU_WIN_BASE;
+ ORION5X_DRAM_BASE;
u32 result = 0;
u32 enable = 0x01 & winregs[bank].size;
diff --git a/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S b/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S
index 0523bd4..a2de3cf 100644
--- a/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S
+++ b/arch/arm/cpu/arm926ejs/orion5x/lowlevel_init.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Albert ARIBAUD <albert.aribaud@free.fr>
+ * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
*
* (C) Copyright 2009
* Marvell Semiconductor <www.marvell.com>
diff --git a/arch/arm/cpu/arm926ejs/orion5x/timer.c b/arch/arm/cpu/arm926ejs/orion5x/timer.c
index bbab226..9d45260 100644
--- a/arch/arm/cpu/arm926ejs/orion5x/timer.c
+++ b/arch/arm/cpu/arm926ejs/orion5x/timer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Albert ARIBAUD <albert.aribaud@free.fr>
+ * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
*
* Based on original Kirkwood support which is
* Copyright (C) Marvell International Ltd. and its affiliates
diff --git a/arch/arm/cpu/arm926ejs/pantheon/cpu.c b/arch/arm/cpu/arm926ejs/pantheon/cpu.c
index 9ddc77c..8b2eafa 100644
--- a/arch/arm/cpu/arm926ejs/pantheon/cpu.c
+++ b/arch/arm/cpu/arm926ejs/pantheon/cpu.c
@@ -59,6 +59,12 @@ int arch_cpu_init(void)
/* Enable GPIO clock */
writel(APBC_APBCLK, &apbclkres->gpio);
+#ifdef CONFIG_I2C_MV
+ /* Enable I2C clock */
+ writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apbclkres->twsi);
+ writel(APBC_FNCLK | APBC_APBCLK, &apbclkres->twsi);
+#endif
+
icache_enable();
return 0;
@@ -76,3 +82,9 @@ int print_cpuinfo(void)
return 0;
}
#endif
+
+#ifdef CONFIG_I2C_MV
+void i2c_clk_enable(void)
+{
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S
index fefcfa2..0940937 100644
--- a/arch/arm/cpu/arm926ejs/start.S
+++ b/arch/arm/cpu/arm926ejs/start.S
@@ -10,7 +10,7 @@
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
- * Copyright (c) 2010 Albert Aribaud <albert.aribaud@free.fr>
+ * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/arch/arm/cpu/arm946es/start.S b/arch/arm/cpu/arm946es/start.S
index 00914f4..0054b22 100644
--- a/arch/arm/cpu/arm946es/start.S
+++ b/arch/arm/cpu/arm946es/start.S
@@ -10,7 +10,7 @@
* Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
- * Copyright (c) 2010 Albert Aribaud <albert.aribaud@free.fr>
+ * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/arch/arm/cpu/armv7/mx5/soc.c b/arch/arm/cpu/armv7/mx5/soc.c
index 09500b3..6f4e8db 100644
--- a/arch/arm/cpu/armv7/mx5/soc.c
+++ b/arch/arm/cpu/armv7/mx5/soc.c
@@ -77,6 +77,33 @@ u32 get_cpu_rev(void)
return system_rev;
}
+static char *get_reset_cause(void)
+{
+ u32 cause;
+ struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+
+ cause = readl(&src_regs->srsr);
+ writel(cause, &src_regs->srsr);
+
+ switch (cause) {
+ case 0x00001:
+ return "POR";
+ case 0x00004:
+ return "CSU";
+ case 0x00008:
+ return "IPP USER";
+ case 0x00010:
+ return "WDOG";
+ case 0x00020:
+ return "JTAG HIGH-Z";
+ case 0x00040:
+ return "JTAG SW";
+ case 0x10000:
+ return "WARM BOOT";
+ default:
+ return "unknown reset";
+ }
+}
#if defined(CONFIG_DISPLAY_CPUINFO)
int print_cpuinfo(void)
@@ -89,6 +116,7 @@ int print_cpuinfo(void)
(cpurev & 0x000F0) >> 4,
(cpurev & 0x0000F) >> 0,
mxc_get_clock(MXC_ARM_CLK) / 1000000);
+ printf("Reset cause: %s\n", get_reset_cause());
return 0;
}
#endif
diff --git a/arch/arm/cpu/armv7/omap3/clock.c b/arch/arm/cpu/armv7/omap3/clock.c
index 2238c52..3d38d08 100644
--- a/arch/arm/cpu/armv7/omap3/clock.c
+++ b/arch/arm/cpu/armv7/omap3/clock.c
@@ -278,6 +278,25 @@ static void dpll4_init_34xx(u32 sil_index, u32 clk_index)
wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY);
}
+static void dpll5_init_34xx(u32 sil_index, u32 clk_index)
+{
+ struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
+ dpll_param *ptr = (dpll_param *) get_per2_dpll_param();
+
+ /* Moving it to the right sysclk base */
+ ptr = ptr + clk_index;
+
+ /* PER2 DPLL (DPLL5) */
+ sr32(&prcm_base->clken2_pll, 0, 3, PLL_STOP);
+ wait_on_value(1, 0, &prcm_base->idlest2_ckgen, LDELAY);
+ sr32(&prcm_base->clksel5_pll, 0, 5, ptr->m2); /* set M2 (usbtll_fck) */
+ sr32(&prcm_base->clksel4_pll, 8, 11, ptr->m); /* set m (11-bit multiplier) */
+ sr32(&prcm_base->clksel4_pll, 0, 7, ptr->n); /* set n (7-bit divider)*/
+ sr32(&prcm_base->clken_pll, 4, 4, ptr->fsel); /* FREQSEL */
+ sr32(&prcm_base->clken2_pll, 0, 3, PLL_LOCK); /* lock mode */
+ wait_on_value(1, 1, &prcm_base->idlest2_ckgen, LDELAY);
+}
+
static void mpu_init_34xx(u32 sil_index, u32 clk_index)
{
struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
@@ -587,6 +606,7 @@ void prcm_init(void)
dpll3_init_34xx(sil_index, clk_index);
dpll4_init_34xx(sil_index, clk_index);
+ dpll5_init_34xx(sil_index, clk_index);
iva_init_34xx(sil_index, clk_index);
mpu_init_34xx(sil_index, clk_index);
diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
index 109481e..1458072 100644
--- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
@@ -360,6 +360,28 @@ get_per_dpll_param:
adr r0, per_dpll_param
mov pc, lr
+/* PER2 DPLL values */
+per2_dpll_param:
+/* 12MHz */
+.word PER2_M_12, PER2_N_12, PER2_FSEL_12, PER2_M2_12
+
+/* 13MHz */
+.word PER2_M_13, PER2_N_13, PER2_FSEL_13, PER2_M2_13
+
+/* 19.2MHz */
+.word PER2_M_19P2, PER2_N_19P2, PER2_FSEL_19P2, PER2_M2_19P2
+
+/* 26MHz */
+.word PER2_M_26, PER2_N_26, PER2_FSEL_26, PER2_M2_26
+
+/* 38.4MHz */
+.word PER2_M_38P4, PER2_N_38P4, PER2_FSEL_38P4, PER2_M2_38P4
+
+.globl get_per2_dpll_param
+get_per2_dpll_param:
+ adr r0, per2_dpll_param
+ mov pc, lr
+
/*
* Tables for 36XX/37XX devices
*
diff --git a/arch/arm/cpu/armv7/omap3/mem.c b/arch/arm/cpu/armv7/omap3/mem.c
index bd914b0..a01c303 100644
--- a/arch/arm/cpu/armv7/omap3/mem.c
+++ b/arch/arm/cpu/armv7/omap3/mem.c
@@ -31,16 +31,6 @@
#include <asm/arch/sys_proto.h>
#include <command.h>
-/*
- * Only One NAND allowed on board at a time.
- * The GPMC CS Base for the same
- */
-unsigned int boot_flash_base;
-unsigned int boot_flash_off;
-unsigned int boot_flash_sec;
-unsigned int boot_flash_type;
-volatile unsigned int boot_flash_env_addr;
-
struct gpmc *gpmc_cfg;
#if defined(CONFIG_CMD_NAND)
@@ -134,10 +124,6 @@ void gpmc_init(void)
const u32 *gpmc_config = NULL;
u32 base = 0;
u32 size = 0;
-#if defined(CONFIG_ENV_IS_IN_NAND) || defined(CONFIG_ENV_IS_IN_ONENAND)
- u32 f_off = CONFIG_SYS_MONITOR_LEN;
- u32 f_sec = 0;
-#endif
#endif
u32 config = 0;
@@ -162,15 +148,6 @@ void gpmc_init(void)
base = PISMO1_NAND_BASE;
size = PISMO1_NAND_SIZE;
enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size);
-#if defined(CONFIG_ENV_IS_IN_NAND)
- f_off = SMNAND_ENV_OFFSET;
- f_sec = (128 << 10); /* 128 KiB */
- /* env setup */
- boot_flash_base = base;
- boot_flash_off = f_off;
- boot_flash_sec = f_sec;
- boot_flash_env_addr = f_off;
-#endif
#endif
#if defined(CONFIG_CMD_ONENAND)
@@ -178,14 +155,5 @@ void gpmc_init(void)
base = PISMO1_ONEN_BASE;
size = PISMO1_ONEN_SIZE;
enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size);
-#if defined(CONFIG_ENV_IS_IN_ONENAND)
- f_off = ONENAND_ENV_OFFSET;
- f_sec = (128 << 10); /* 128 KiB */
- /* env setup */
- boot_flash_base = base;
- boot_flash_off = f_off;
- boot_flash_sec = f_sec;
- boot_flash_env_addr = f_off;
-#endif
#endif
}
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index d83d501..2929fc7 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -70,6 +70,18 @@ _end_vect:
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
+#ifdef CONFIG_TEGRA2
+/*
+ * Tegra2 uses 2 separate CPUs - the AVP (ARM7TDMI) and the CPU (dual A9s).
+ * U-Boot runs on the AVP first, setting things up for the CPU (PLLs,
+ * muxes, clocks, clamps, etc.). Then the AVP halts, and expects the CPU
+ * to pick up its reset vector, which points here.
+ */
+.globl _armboot_start
+_armboot_start:
+ .word _start
+#endif
+
/*
* These are defined in the board-specific linker script.
*/
@@ -115,7 +127,7 @@ reset:
orr r0, r0, #0xd3
msr cpsr,r0
-#if (CONFIG_OMAP34XX)
+#if defined(CONFIG_OMAP34XX)
/* Copy vectors to mask ROM indirect addr */
adr r0, _start @ r0 <- current position of code
add r0, r0, #4 @ skip reset vector
diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index 687c887..f1ea915 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
SOBJS := lowlevel_init.o
-COBJS := board.o sys_info.o timer.o
+COBJS := ap20.o board.o sys_info.o timer.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
new file mode 100644
index 0000000..60dd5df
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/ap20.c
@@ -0,0 +1,358 @@
+/*
+* (C) Copyright 2010-2011
+* NVIDIA Corporation <www.nvidia.com>
+*
+* See file CREDITS for list of people who contributed to this
+* project.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+* MA 02111-1307 USA
+*/
+
+#include "ap20.h"
+#include <asm/io.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/scu.h>
+#include <common.h>
+
+u32 s_first_boot = 1;
+
+void init_pllx(void)
+{
+ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 reg;
+
+ /* If PLLX is already enabled, just return */
+ reg = readl(&clkrst->crc_pllx_base);
+ if (reg & PLL_ENABLE)
+ return;
+
+ /* Set PLLX_MISC */
+ reg = CPCON; /* CPCON[11:8] = 0001 */
+ writel(reg, &clkrst->crc_pllx_misc);
+
+ /* Use 12MHz clock here */
+ reg = (PLL_BYPASS | PLL_DIVM);
+ reg |= (1000 << 8); /* DIVN = 0x3E8 */
+ writel(reg, &clkrst->crc_pllx_base);
+
+ reg |= PLL_ENABLE;
+ writel(reg, &clkrst->crc_pllx_base);
+
+ reg &= ~PLL_BYPASS;
+ writel(reg, &clkrst->crc_pllx_base);
+}
+
+static void enable_cpu_clock(int enable)
+{
+ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 reg, clk;
+
+ /*
+ * 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);
+ }
+
+ /* Fetch the register containing the main CPU complex clock enable */
+ reg = readl(&clkrst->crc_clk_out_enb_l);
+ reg |= CLK_ENB_CPU;
+
+ /*
+ * Read the register containing the individual CPU clock enables and
+ * always stop the clock to CPU 1.
+ */
+ clk = readl(&clkrst->crc_clk_cpu_cmplx);
+ clk |= CPU1_CLK_STP;
+
+ if (enable) {
+ /* Unstop the CPU clock */
+ clk &= ~CPU0_CLK_STP;
+ } else {
+ /* Stop the CPU clock */
+ clk |= CPU0_CLK_STP;
+ }
+
+ writel(clk, &clkrst->crc_clk_cpu_cmplx);
+ writel(reg, &clkrst->crc_clk_out_enb_l);
+}
+
+static int is_cpu_powered(void)
+{
+ struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_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 *)NV_PA_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 *)NV_PA_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 *)NV_PA_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)
+{
+ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 reg, cpu;
+
+ /*
+ * 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 */
+ cpu = SET_DBGRESET1 | SET_DERESET1 | SET_CPURESET1;
+ writel(cpu, &clkrst->crc_cpu_cmplx_set);
+
+ reg = readl(&clkrst->crc_rst_dev_l);
+ if (reset) {
+ /* Now place CPU0 into reset */
+ cpu |= SET_DBGRESET0 | SET_DERESET0 | SET_CPURESET0;
+ writel(cpu, &clkrst->crc_cpu_cmplx_set);
+
+ /* Enable master CPU reset */
+ reg |= SWR_CPU_RST;
+ } else {
+ /* Take CPU0 out of reset */
+ cpu = CLR_DBGRESET0 | CLR_DERESET0 | CLR_CPURESET0;
+ writel(cpu, &clkrst->crc_cpu_cmplx_clr);
+
+ /* Disable master CPU reset */
+ reg &= ~SWR_CPU_RST;
+ }
+
+ writel(reg, &clkrst->crc_rst_dev_l);
+}
+
+static void clock_enable_coresight(int enable)
+{
+ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+ u32 rst, clk, src;
+
+ rst = readl(&clkrst->crc_rst_dev_u);
+ clk = readl(&clkrst->crc_clk_out_enb_u);
+
+ if (enable) {
+ rst &= ~SWR_CSITE_RST;
+ clk |= CLK_ENB_CSITE;
+ } else {
+ rst |= SWR_CSITE_RST;
+ clk &= ~CLK_ENB_CSITE;
+ }
+
+ writel(clk, &clkrst->crc_clk_out_enb_u);
+ writel(rst, &clkrst->crc_rst_dev_u);
+
+ 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);
+ writel(src, &clkrst->crc_clk_src_csite);
+
+ /* Unlock the CPU CoreSight interfaces */
+ rst = 0xC5ACCE55;
+ writel(rst, CSITE_CPU_DBG0_LAR);
+ writel(rst, CSITE_CPU_DBG1_LAR);
+ }
+}
+
+void start_cpu(u32 reset_vector)
+{
+ /* Enable VDD_CPU */
+ enable_cpu_power_rail();
+
+ /* Hold the CPUs in reset */
+ reset_A9_cpu(1);
+
+ /* Disable the CPU clock */
+ enable_cpu_clock(0);
+
+ /* Enable CoreSight */
+ clock_enable_coresight(1);
+
+ /*
+ * Set the entry point for CPU execution from reset,
+ * if it's a non-zero value.
+ */
+ if (reset_vector)
+ writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+ /* Enable the CPU clock */
+ enable_cpu_clock(1);
+
+ /* If the CPU doesn't already have power, power it up */
+ powerup_cpu();
+
+ /* Take the CPU out of reset */
+ reset_A9_cpu(0);
+}
+
+
+void halt_avp(void)
+{
+ for (;;) {
+ writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
+ | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
+ FLOW_CTLR_HALT_COP_EVENTS);
+ }
+}
+
+void enable_scu(void)
+{
+ struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE;
+ u32 reg;
+
+ /* If SCU already setup/enabled, return */
+ if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE)
+ return;
+
+ /* Invalidate all ways for all processors */
+ writel(0xFFFF, &scu->scu_inv_all);
+
+ /* Enable SCU - bit 0 */
+ reg = readl(&scu->scu_ctrl);
+ reg |= SCU_CTRL_ENABLE;
+ writel(reg, &scu->scu_ctrl);
+}
+
+void init_pmc_scratch(void)
+{
+ struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+ int i;
+
+ /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
+ for (i = 0; i < 23; i++)
+ writel(0, &pmc->pmc_scratch1+i);
+
+ /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
+ writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
+}
+
+void cpu_start(void)
+{
+ struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+
+ /* enable JTAG */
+ writel(0xC0, &pmt->pmt_cfg_ctl);
+
+ if (s_first_boot) {
+ /*
+ * Need to set this before cold-booting,
+ * otherwise we'll end up in an infinite loop.
+ */
+ s_first_boot = 0;
+ cold_boot();
+ }
+}
+
+void tegra2_start()
+{
+ if (s_first_boot) {
+ /* Init Debug UART Port (115200 8n1) */
+ uart_init();
+
+ /* Init PMC scratch memory */
+ init_pmc_scratch();
+ }
+
+#ifdef CONFIG_ENABLE_CORTEXA9
+ /* take the mpcore out of reset */
+ cpu_start();
+
+ /* configure cache */
+ cache_configure();
+#endif
+}
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.h b/arch/arm/cpu/armv7/tegra2/ap20.h
new file mode 100644
index 0000000..49fe340
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/ap20.h
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2010-2011
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <asm/types.h>
+
+/* Stabilization delays, in usec */
+#define PLL_STABILIZATION_DELAY (300)
+#define IO_STABILIZATION_DELAY (1000)
+
+#define NVBL_PLLP_KHZ (216000)
+
+#define PLLX_ENABLED (1 << 30)
+#define CCLK_BURST_POLICY 0x20008888
+#define SUPER_CCLK_DIVIDER 0x80000000
+
+/* Calculate clock fractional divider value from ref and target frequencies */
+#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
+
+/* Calculate clock frequency value from reference and clock divider value */
+#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
+
+/* AVP/CPU ID */
+#define PG_UP_TAG_0_PID_CPU 0x55555555 /* CPU aka "a9" aka "mpcore" */
+#define PG_UP_TAG_0 0x0
+
+#define CORESIGHT_UNLOCK 0xC5ACCE55;
+
+/* AP20-Specific Base Addresses */
+
+/* AP20 Base physical address of SDRAM. */
+#define AP20_BASE_PA_SDRAM 0x00000000
+/* AP20 Base physical address of internal SRAM. */
+#define AP20_BASE_PA_SRAM 0x40000000
+/* AP20 Size of internal SRAM (256KB). */
+#define AP20_BASE_PA_SRAM_SIZE 0x00040000
+/* AP20 Base physical address of flash. */
+#define AP20_BASE_PA_NOR_FLASH 0xD0000000
+/* AP20 Base physical address of boot information table. */
+#define AP20_BASE_PA_BOOT_INFO AP20_BASE_PA_SRAM
+
+/*
+ * Super-temporary stacks for EXTREMELY early startup. The values chosen for
+ * these addresses must be valid on ALL SOCs because this value is used before
+ * we are able to differentiate between the SOC types.
+ *
+ * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
+ * stack is placed below the AVP stack. Once the CPU stack has been moved,
+ * the AVP is free to use the IRAM the CPU stack previously occupied if
+ * it should need to do so.
+ *
+ * NOTE: In multi-processor CPU complex configurations, each processor will have
+ * its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
+ * limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
+ * stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
+ * CPU.
+ */
+
+/* Common AVP early boot stack limit */
+#define AVP_EARLY_BOOT_STACK_LIMIT \
+ (AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
+/* Common AVP early boot stack size */
+#define AVP_EARLY_BOOT_STACK_SIZE 0x1000
+/* Common CPU early boot stack limit */
+#define CPU_EARLY_BOOT_STACK_LIMIT \
+ (AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
+/* Common CPU early boot stack size */
+#define CPU_EARLY_BOOT_STACK_SIZE 0x1000
+
+#define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100)
+#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0)
+#define CSITE_CPU_DBG1_LAR (NV_PA_CSITE_BASE + 0x12FB0)
+
+#define FLOW_CTLR_HALT_COP_EVENTS (NV_PA_FLOW_BASE + 4)
+#define FLOW_MODE_STOP 2
+#define HALT_COP_EVENT_JTAG (1 << 28)
+#define HALT_COP_EVENT_IRQ_1 (1 << 11)
+#define HALT_COP_EVENT_FIQ_1 (1 << 9)
+
+/* Prototypes */
+
+void tegra2_start(void);
+void uart_init(void);
+void udelay(unsigned long);
+void cold_boot(void);
+void cache_configure(void);
diff --git a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S b/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
index 7f15746..f24a2ff 100644
--- a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/tegra2/lowlevel_init.S
@@ -26,6 +26,7 @@
#include <config.h>
#include <version.h>
+
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE @ sdram load addr from config file
@@ -58,8 +59,101 @@ lowlevel_init:
mov pc, lr @ back to arch calling code
+
+.globl startup_cpu
+startup_cpu:
+ @ Initialize the AVP, clocks, and memory controller
+ @ SDRAM is guaranteed to be on at this point
+
+ ldr r0, =cold_boot @ R0 = reset vector for CPU
+ bl start_cpu @ start the CPU
+
+ @ Transfer control to the AVP code
+ bl halt_avp
+
+ @ Should never get here
+_loop_forever2:
+ b _loop_forever2
+
+.globl cache_configure
+cache_configure:
+ stmdb r13!,{r14}
+ @ invalidate instruction cache
+ mov r1, #0
+ mcr p15, 0, r1, c7, c5, 0
+
+ @ invalidate the i&d tlb entries
+ mcr p15, 0, r1, c8, c5, 0
+ mcr p15, 0, r1, c8, c6, 0
+
+ @ enable instruction cache
+ mrc p15, 0, r1, c1, c0, 0
+ orr r1, r1, #(1<<12)
+ mcr p15, 0, r1, c1, c0, 0
+
+ bl enable_scu
+
+ @ enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg
+ mrc p15, 0, r0, c1, c0, 1
+ orr r0, r0, #0x41
+ mcr p15, 0, r0, c1, c0, 1
+
+ @ Now flush the Dcache
+ mov r0, #0
+ @ 256 cache lines
+ mov r1, #256
+
+invalidate_loop:
+ add r1, r1, #-1
+ mov r0, r1, lsl #5
+ @ invalidate d-cache using line (way0)
+ mcr p15, 0, r0, c7, c6, 2
+
+ orr r2, r0, #(1<<30)
+ @ invalidate d-cache using line (way1)
+ mcr p15, 0, r2, c7, c6, 2
+
+ orr r2, r0, #(2<<30)
+ @ invalidate d-cache using line (way2)
+ mcr p15, 0, r2, c7, c6, 2
+
+ orr r2, r0, #(3<<30)
+ @ invalidate d-cache using line (way3)
+ mcr p15, 0, r2, c7, c6, 2
+ cmp r1, #0
+ bne invalidate_loop
+
+ @ FIXME: should have ap20's L2 disabled too?
+invalidate_done:
+ ldmia r13!,{pc}
+
+.globl cold_boot
+cold_boot:
+ msr cpsr_c, #0xD3
+ @ Check current processor: CPU or AVP?
+ @ If CPU, go to CPU boot code, else continue on AVP path
+
+ ldr r0, =NV_PA_PG_UP_BASE
+ ldr r1, [r0]
+ ldr r2, =PG_UP_TAG_AVP
+
+ @ are we the CPU?
+ ldr sp, CPU_STACK
+ cmp r1, r2
+ @ yep, we are the CPU
+ bne _armboot_start
+
+ @ AVP initialization follows this path
+ ldr sp, AVP_STACK
+ @ Init AVP and start CPU
+ b startup_cpu
+
@ the literal pools origin
.ltorg
SRAM_STACK:
.word LOW_LEVEL_SRAM_STACK
+AVP_STACK:
+ .word EARLY_AVP_STACK
+CPU_STACK:
+ .word EARLY_CPU_STACK
diff --git a/arch/arm/cpu/pxa/Makefile b/arch/arm/cpu/pxa/Makefile
index 49a6ed3..e8b59a3 100644
--- a/arch/arm/cpu/pxa/Makefile
+++ b/arch/arm/cpu/pxa/Makefile
@@ -28,7 +28,6 @@ LIB = $(obj)lib$(CPU).o
START = start.o
COBJS += cpu.o
-COBJS += i2c.o
COBJS += pxafb.o
COBJS += timer.o
COBJS += usb.o
diff --git a/arch/arm/cpu/pxa/cpu.c b/arch/arm/cpu/pxa/cpu.c
index 7d49cbb..9970a4b 100644
--- a/arch/arm/cpu/pxa/cpu.c
+++ b/arch/arm/cpu/pxa/cpu.c
@@ -318,3 +318,13 @@ int arch_cpu_init(void)
pxa_clock_setup();
return 0;
}
+
+void i2c_clk_enable(void)
+{
+ /* set the global I2C clock on */
+#ifdef CONFIG_CPU_MONAHANS
+ writel(readl(CKENB) | (CKENB_4_I2C), CKENB);
+#else
+ writel(readl(CKEN) | CKEN14_I2C, CKEN);
+#endif
+}
diff --git a/arch/arm/cpu/pxa/i2c.c b/arch/arm/cpu/pxa/i2c.c
deleted file mode 100644
index 7aa49ae..0000000
--- a/arch/arm/cpu/pxa/i2c.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * (C) Copyright 2000
- * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
- *
- * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- *
- * (C) Copyright 2003 Pengutronix e.K.
- * Robert Schwebel <r.schwebel@pengutronix.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
- *
- * Back ported to the 8xx platform (from the 8260 platform) by
- * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
- */
-
-/* FIXME: this file is PXA255 specific! What about other XScales? */
-
-#include <common.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_HARD_I2C
-
-/*
- * - CONFIG_SYS_I2C_SPEED
- * - I2C_PXA_SLAVE_ADDR
- */
-
-#include <asm/arch/hardware.h>
-#include <asm/arch/pxa-regs.h>
-#include <i2c.h>
-
-/*#define DEBUG_I2C 1 /###* activate local debugging output */
-#define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */
-
-#if (CONFIG_SYS_I2C_SPEED == 400000)
-#define I2C_ICR_INIT (ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
-#else
-#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
-#endif
-
-#define I2C_ISR_INIT 0x7FF
-
-#ifdef DEBUG_I2C
-#define PRINTD(x) printf x
-#else
-#define PRINTD(x)
-#endif
-
-
-/* Shall the current transfer have a start/stop condition? */
-#define I2C_COND_NORMAL 0
-#define I2C_COND_START 1
-#define I2C_COND_STOP 2
-
-/* Shall the current transfer be ack/nacked or being waited for it? */
-#define I2C_ACKNAK_WAITACK 1
-#define I2C_ACKNAK_SENDACK 2
-#define I2C_ACKNAK_SENDNAK 4
-
-/* Specify who shall transfer the data (master or slave) */
-#define I2C_READ 0
-#define I2C_WRITE 1
-
-/* All transfers are described by this data structure */
-struct i2c_msg {
- u8 condition;
- u8 acknack;
- u8 direction;
- u8 data;
-};
-
-
-/**
- * i2c_pxa_reset: - reset the host controller
- *
- */
-
-static void i2c_reset( void )
-{
- writel(readl(ICR) & ~ICR_IUE, ICR); /* disable unit */
- writel(readl(ICR) | ICR_UR, ICR); /* reset the unit */
- udelay(100);
- writel(readl(ICR) & ~ICR_IUE, ICR); /* disable unit */
-#ifdef CONFIG_CPU_MONAHANS
- /* | CKENB_1_PWM1 | CKENB_0_PWM0); */
- writel(readl(CKENB) | (CKENB_4_I2C), CKENB);
-#else /* CONFIG_CPU_MONAHANS */
- /* set the global I2C clock on */
- writel(readl(CKEN) | CKEN14_I2C, CKEN);
-#endif
- writel(I2C_PXA_SLAVE_ADDR, ISAR); /* set our slave address */
- writel(I2C_ICR_INIT, ICR); /* set control reg values */
- writel(I2C_ISR_INIT, ISR); /* set clear interrupt bits */
- writel(readl(ICR) | ICR_IUE, ICR); /* enable unit */
- udelay(100);
-}
-
-
-/**
- * i2c_isr_set_cleared: - wait until certain bits of the I2C status register
- * are set and cleared
- *
- * @return: 1 in case of success, 0 means timeout (no match within 10 ms).
- */
-static int i2c_isr_set_cleared( unsigned long set_mask, unsigned long cleared_mask )
-{
- int timeout = 10000;
-
- while( ((ISR & set_mask)!=set_mask) || ((ISR & cleared_mask)!=0) ){
- udelay( 10 );
- if( timeout-- < 0 ) return 0;
- }
-
- return 1;
-}
-
-
-/**
- * i2c_transfer: - Transfer one byte over the i2c bus
- *
- * This function can tranfer a byte over the i2c bus in both directions.
- * It is used by the public API functions.
- *
- * @return: 0: transfer successful
- * -1: message is empty
- * -2: transmit timeout
- * -3: ACK missing
- * -4: receive timeout
- * -5: illegal parameters
- * -6: bus is busy and couldn't be aquired
- */
-int i2c_transfer(struct i2c_msg *msg)
-{
- int ret;
-
- if (!msg)
- goto transfer_error_msg_empty;
-
- switch(msg->direction) {
-
- case I2C_WRITE:
-
- /* check if bus is not busy */
- if (!i2c_isr_set_cleared(0,ISR_IBB))
- goto transfer_error_bus_busy;
-
- /* start transmission */
- writel(readl(ICR) & ~ICR_START, ICR);
- writel(readl(ICR) & ~ICR_STOP, ICR);
- writel(msg->data, IDBR);
- if (msg->condition == I2C_COND_START)
- writel(readl(ICR) | ICR_START, ICR);
- if (msg->condition == I2C_COND_STOP)
- writel(readl(ICR) | ICR_STOP, ICR);
- if (msg->acknack == I2C_ACKNAK_SENDNAK)
- writel(readl(ICR) | ICR_ACKNAK, ICR);
- if (msg->acknack == I2C_ACKNAK_SENDACK)
- writel(readl(ICR) & ~ICR_ACKNAK, ICR);
- writel(readl(ICR) & ~ICR_ALDIE, ICR);
- writel(readl(ICR) | ICR_TB, ICR);
-
- /* transmit register empty? */
- if (!i2c_isr_set_cleared(ISR_ITE,0))
- goto transfer_error_transmit_timeout;
-
- /* clear 'transmit empty' state */
- writel(readl(ISR) | ISR_ITE, ISR);
-
- /* wait for ACK from slave */
- if (msg->acknack == I2C_ACKNAK_WAITACK)
- if (!i2c_isr_set_cleared(0,ISR_ACKNAK))
- goto transfer_error_ack_missing;
- break;
-
- case I2C_READ:
-
- /* check if bus is not busy */
- if (!i2c_isr_set_cleared(0,ISR_IBB))
- goto transfer_error_bus_busy;
-
- /* start receive */
- writel(readl(ICR) & ~ICR_START, ICR);
- writel(readl(ICR) & ~ICR_STOP, ICR);
- if (msg->condition == I2C_COND_START)
- writel(readl(ICR) | ICR_START, ICR);
- if (msg->condition == I2C_COND_STOP)
- writel(readl(ICR) | ICR_STOP, ICR);
- if (msg->acknack == I2C_ACKNAK_SENDNAK)
- writel(readl(ICR) | ICR_ACKNAK, ICR);
- if (msg->acknack == I2C_ACKNAK_SENDACK)
- writel(readl(ICR) & ~ICR_ACKNAK, ICR);
- writel(readl(ICR) & ~ICR_ALDIE, ICR);
- writel(readl(ICR) | ICR_TB, ICR);
-
- /* receive register full? */
- if (!i2c_isr_set_cleared(ISR_IRF,0))
- goto transfer_error_receive_timeout;
-
- msg->data = readl(IDBR);
-
- /* clear 'receive empty' state */
- writel(readl(ISR) | ISR_IRF, ISR);
-
- break;
-
- default:
-
- goto transfer_error_illegal_param;
-
- }
-
- return 0;
-
-transfer_error_msg_empty:
- PRINTD(("i2c_transfer: error: 'msg' is empty\n"));
- ret = -1; goto i2c_transfer_finish;
-
-transfer_error_transmit_timeout:
- PRINTD(("i2c_transfer: error: transmit timeout\n"));
- ret = -2; goto i2c_transfer_finish;
-
-transfer_error_ack_missing:
- PRINTD(("i2c_transfer: error: ACK missing\n"));
- ret = -3; goto i2c_transfer_finish;
-
-transfer_error_receive_timeout:
- PRINTD(("i2c_transfer: error: receive timeout\n"));
- ret = -4; goto i2c_transfer_finish;
-
-transfer_error_illegal_param:
- PRINTD(("i2c_transfer: error: illegal parameters\n"));
- ret = -5; goto i2c_transfer_finish;
-
-transfer_error_bus_busy:
- PRINTD(("i2c_transfer: error: bus is busy\n"));
- ret = -6; goto i2c_transfer_finish;
-
-i2c_transfer_finish:
- PRINTD(("i2c_transfer: ISR: 0x%04x\n",ISR));
- i2c_reset();
- return ret;
-
-}
-
-/* ------------------------------------------------------------------------ */
-/* API Functions */
-/* ------------------------------------------------------------------------ */
-
-void i2c_init(int speed, int slaveaddr)
-{
-#ifdef CONFIG_SYS_I2C_INIT_BOARD
- /* call board specific i2c bus reset routine before accessing the */
- /* environment, which might be in a chip on that bus. For details */
- /* about this problem see doc/I2C_Edge_Conditions. */
- i2c_init_board();
-#endif
-}
-
-
-/**
- * i2c_probe: - Test if a chip answers for a given i2c address
- *
- * @chip: address of the chip which is searched for
- * @return: 0 if a chip was found, -1 otherwhise
- */
-
-int i2c_probe(uchar chip)
-{
- struct i2c_msg msg;
-
- i2c_reset();
-
- msg.condition = I2C_COND_START;
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = (chip << 1) + 1;
- if (i2c_transfer(&msg)) return -1;
-
- msg.condition = I2C_COND_STOP;
- msg.acknack = I2C_ACKNAK_SENDNAK;
- msg.direction = I2C_READ;
- msg.data = 0x00;
- if (i2c_transfer(&msg)) return -1;
-
- return 0;
-}
-
-
-/**
- * i2c_read: - Read multiple bytes from an i2c device
- *
- * The higher level routines take into account that this function is only
- * called with len < page length of the device (see configuration file)
- *
- * @chip: address of the chip which is to be read
- * @addr: i2c data address within the chip
- * @alen: length of the i2c data address (1..2 bytes)
- * @buffer: where to write the data
- * @len: how much byte do we want to read
- * @return: 0 in case of success
- */
-
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- struct i2c_msg msg;
- u8 addr_bytes[3]; /* lowest...highest byte of data address */
- int ret;
-
- PRINTD(("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n",chip,addr,alen,len));
-
- i2c_reset();
-
- /* dummy chip address write */
- PRINTD(("i2c_read: dummy chip address write\n"));
- msg.condition = I2C_COND_START;
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = (chip << 1);
- msg.data &= 0xFE;
- if ((ret=i2c_transfer(&msg))) return -1;
-
- /*
- * send memory address bytes;
- * alen defines how much bytes we have to send.
- */
- /*addr &= ((1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)-1); */
- addr_bytes[0] = (u8)((addr >> 0) & 0x000000FF);
- addr_bytes[1] = (u8)((addr >> 8) & 0x000000FF);
- addr_bytes[2] = (u8)((addr >> 16) & 0x000000FF);
-
- while (--alen >= 0) {
-
- PRINTD(("i2c_read: send memory word address byte %1d\n",alen));
- msg.condition = I2C_COND_NORMAL;
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = addr_bytes[alen];
- if ((ret=i2c_transfer(&msg))) return -1;
- }
-
-
- /* start read sequence */
- PRINTD(("i2c_read: start read sequence\n"));
- msg.condition = I2C_COND_START;
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = (chip << 1);
- msg.data |= 0x01;
- if ((ret=i2c_transfer(&msg))) return -1;
-
- /* read bytes; send NACK at last byte */
- while (len--) {
-
- if (len==0) {
- msg.condition = I2C_COND_STOP;
- msg.acknack = I2C_ACKNAK_SENDNAK;
- } else {
- msg.condition = I2C_COND_NORMAL;
- msg.acknack = I2C_ACKNAK_SENDACK;
- }
-
- msg.direction = I2C_READ;
- msg.data = 0x00;
- if ((ret=i2c_transfer(&msg))) return -1;
-
- *buffer = msg.data;
- PRINTD(("i2c_read: reading byte (0x%08x)=0x%02x\n",(unsigned int)buffer,*buffer));
- buffer++;
-
- }
-
- i2c_reset();
-
- return 0;
-}
-
-
-/**
- * i2c_write: - Write multiple bytes to an i2c device
- *
- * The higher level routines take into account that this function is only
- * called with len < page length of the device (see configuration file)
- *
- * @chip: address of the chip which is to be written
- * @addr: i2c data address within the chip
- * @alen: length of the i2c data address (1..2 bytes)
- * @buffer: where to find the data to be written
- * @len: how much byte do we want to read
- * @return: 0 in case of success
- */
-
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- struct i2c_msg msg;
- u8 addr_bytes[3]; /* lowest...highest byte of data address */
-
- PRINTD(("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n",chip,addr,alen,len));
-
- i2c_reset();
-
- /* chip address write */
- PRINTD(("i2c_write: chip address write\n"));
- msg.condition = I2C_COND_START;
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = (chip << 1);
- msg.data &= 0xFE;
- if (i2c_transfer(&msg)) return -1;
-
- /*
- * send memory address bytes;
- * alen defines how much bytes we have to send.
- */
- addr_bytes[0] = (u8)((addr >> 0) & 0x000000FF);
- addr_bytes[1] = (u8)((addr >> 8) & 0x000000FF);
- addr_bytes[2] = (u8)((addr >> 16) & 0x000000FF);
-
- while (--alen >= 0) {
-
- PRINTD(("i2c_write: send memory word address\n"));
- msg.condition = I2C_COND_NORMAL;
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = addr_bytes[alen];
- if (i2c_transfer(&msg)) return -1;
- }
-
- /* write bytes; send NACK at last byte */
- while (len--) {
-
- PRINTD(("i2c_write: writing byte (0x%08x)=0x%02x\n",(unsigned int)buffer,*buffer));
-
- if (len==0)
- msg.condition = I2C_COND_STOP;
- else
- msg.condition = I2C_COND_NORMAL;
-
- msg.acknack = I2C_ACKNAK_WAITACK;
- msg.direction = I2C_WRITE;
- msg.data = *(buffer++);
-
- if (i2c_transfer(&msg)) return -1;
-
- }
-
- i2c_reset();
-
- return 0;
-
-}
-
-#endif /* CONFIG_HARD_I2C */