tegra2: trivially enable 13 mhz crystal frequency
[oweals/u-boot.git] / arch / arm / cpu / armv7 / tegra2 / ap20.c
index e3832e23f347ead5292947a1c9ec2c9be33cc201..698bfd0e171c94c5ad63f77e4d9b80f7406a7c39 100644 (file)
 * MA 02111-1307 USA
 */
 
-#include "ap20.h"
 #include <asm/io.h>
 #include <asm/arch/tegra2.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>
 
-u32 s_first_boot = 1;
+int tegra_get_chip_type(void)
+{
+       struct apb_misc_gp_ctlr *gp;
+       struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_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 *)TEGRA2_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_TEGRA2:
+               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 *pll = &clkrst->crc_pll[CLOCK_PLL_ID_XCPU];
+       struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU];
        u32 reg;
 
        /* If PLLX is already enabled, just return */
-       reg = readl(&pll->pll_base);
-       if (reg & PLL_ENABLE)
+       if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
                return;
 
        /* Set PLLX_MISC */
-       reg = CPCON;                            /* CPCON[11:8]  = 0001 */
-       writel(reg, &pll->pll_misc);
+       writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
 
        /* Use 12MHz clock here */
-       reg = (PLL_BYPASS | PLL_DIVM_VALUE);
-       reg |= (1000 << 8);                     /* DIVN = 0x3E8 */
+       reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
+       reg |= 1000 << PLL_DIVN_SHIFT;
        writel(reg, &pll->pll_base);
 
-       reg |= PLL_ENABLE;
+       reg |= PLL_ENABLE_MASK;
        writel(reg, &pll->pll_base);
 
-       reg &= ~PLL_BYPASS;
+       reg &= ~PLL_BYPASS_MASK;
        writel(reg, &pll->pll_base);
 }
 
@@ -90,16 +130,11 @@ static void enable_cpu_clock(int enable)
         * 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;
-       }
+       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);
@@ -107,14 +142,14 @@ static void enable_cpu_clock(int enable)
 
 static int is_cpu_powered(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
 
        return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
 }
 
 static void remove_cpu_io_clamps(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
        u32 reg;
 
        /* Remove the clamps on the CPU I/O signals */
@@ -128,7 +163,7 @@ static void remove_cpu_io_clamps(void)
 
 static void powerup_cpu(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
        u32 reg;
        int timeout = IO_STABILIZATION_DELAY;
 
@@ -159,7 +194,7 @@ static void powerup_cpu(void)
 
 static void enable_cpu_power_rail(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
        u32 reg;
 
        reg = readl(&pmc->pmc_cntrl);
@@ -177,9 +212,6 @@ static void enable_cpu_power_rail(void)
 
 static void reset_A9_cpu(int reset)
 {
-       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 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
@@ -188,19 +220,10 @@ static void reset_A9_cpu(int reset)
        *        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);
-
-       if (reset) {
-               /* Now place CPU0 into reset */
-               cpu |= SET_DBGRESET0 | SET_DERESET0 | SET_CPURESET0;
-               writel(cpu, &clkrst->crc_cpu_cmplx_set);
-       } else {
-               /* Take CPU0 out of reset */
-               cpu = CLR_DBGRESET0 | CLR_DERESET0 | CLR_CPURESET0;
-               writel(cpu, &clkrst->crc_cpu_cmplx_clr);
-       }
+       /* 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);
@@ -208,7 +231,6 @@ static void reset_A9_cpu(int reset)
 
 static void clock_enable_coresight(int enable)
 {
-       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
        u32 rst, src;
 
        clock_set_enable(PERIPH_ID_CORESIGHT, enable);
@@ -222,7 +244,7 @@ static void clock_enable_coresight(int enable)
                 *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
                 */
                src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
-               writel(src, &clkrst->crc_clk_src_csite);
+               clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
 
                /* Unlock the CPU CoreSight interfaces */
                rst = 0xC5ACCE55;
@@ -292,7 +314,7 @@ void enable_scu(void)
 
 void init_pmc_scratch(void)
 {
-       struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
        int i;
 
        /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */
@@ -301,40 +323,44 @@ void init_pmc_scratch(void)
 
        /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
        writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
+
+#ifdef CONFIG_TEGRA2_LP0
+       /* save Sdram params to PMC 2, 4, and 24 for WB0 */
+       warmboot_save_sdram_params();
+#endif
 }
 
-void cpu_start(void)
+void tegra2_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 we are the AVP, start up the first Cortex-A9 */
+       if (!ap20_cpu_is_cortexa9()) {
+               /* 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.
+                * If we are ARM7 - give it a different stack. We are about to
+                * start up the A9 which will want to use this one.
                 */
-               s_first_boot = 0;
-               cold_boot();
+               asm volatile("mov       sp, %0\n"
+                       : : "r"(AVP_EARLY_BOOT_STACK_LIMIT));
+
+               start_cpu((u32)_start);
+               halt_avp();
+               /* not reached */
        }
-}
 
-void tegra2_start()
-{
-       if (s_first_boot) {
-               /* Init Debug UART Port (115200 8n1) */
-               uart_init();
+       /* Init PMC scratch memory */
+       init_pmc_scratch();
 
-               /* Init PMC scratch memory */
-               init_pmc_scratch();
-       }
+       enable_scu();
 
-#ifdef CONFIG_ENABLE_CORTEXA9
-       /* take the mpcore out of reset */
-       cpu_start();
+       /* 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");
 
-       /* configure cache */
-       cache_configure();
-#endif
+       /* FIXME: should have ap20's L2 disabled too? */
 }