Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
0007  */
0008 
0009 #include <linux/init.h>
0010 #include <linux/memblock.h>
0011 #include <linux/smp.h>
0012 #include <asm/bootinfo.h>
0013 #include <asm/bmips.h>
0014 #include <asm/smp-ops.h>
0015 #include <asm/mipsregs.h>
0016 #include <bcm63xx_board.h>
0017 #include <bcm63xx_cpu.h>
0018 #include <bcm63xx_io.h>
0019 #include <bcm63xx_regs.h>
0020 
0021 void __init prom_init(void)
0022 {
0023     u32 reg, mask;
0024 
0025     bcm63xx_cpu_init();
0026 
0027     /* stop any running watchdog */
0028     bcm_wdt_writel(WDT_STOP_1, WDT_CTL_REG);
0029     bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG);
0030 
0031     /* disable all hardware blocks clock for now */
0032     if (BCMCPU_IS_3368())
0033         mask = CKCTL_3368_ALL_SAFE_EN;
0034     else if (BCMCPU_IS_6328())
0035         mask = CKCTL_6328_ALL_SAFE_EN;
0036     else if (BCMCPU_IS_6338())
0037         mask = CKCTL_6338_ALL_SAFE_EN;
0038     else if (BCMCPU_IS_6345())
0039         mask = CKCTL_6345_ALL_SAFE_EN;
0040     else if (BCMCPU_IS_6348())
0041         mask = CKCTL_6348_ALL_SAFE_EN;
0042     else if (BCMCPU_IS_6358())
0043         mask = CKCTL_6358_ALL_SAFE_EN;
0044     else if (BCMCPU_IS_6362())
0045         mask = CKCTL_6362_ALL_SAFE_EN;
0046     else if (BCMCPU_IS_6368())
0047         mask = CKCTL_6368_ALL_SAFE_EN;
0048     else
0049         mask = 0;
0050 
0051     reg = bcm_perf_readl(PERF_CKCTL_REG);
0052     reg &= ~mask;
0053     bcm_perf_writel(reg, PERF_CKCTL_REG);
0054 
0055     /* do low level board init */
0056     board_prom_init();
0057 
0058     /* set up SMP */
0059     if (!register_bmips_smp_ops()) {
0060         /*
0061          * BCM6328 might not have its second CPU enabled, while BCM3368
0062          * and BCM6358 need special handling for their shared TLB, so
0063          * disable SMP for now.
0064          */
0065         if (BCMCPU_IS_6328()) {
0066             reg = bcm_readl(BCM_6328_OTP_BASE +
0067                     OTP_USER_BITS_6328_REG(3));
0068 
0069             if (reg & OTP_6328_REG3_TP1_DISABLED)
0070                 bmips_smp_enabled = 0;
0071         } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
0072             bmips_smp_enabled = 0;
0073         }
0074 
0075         if (!bmips_smp_enabled)
0076             return;
0077 
0078         /*
0079          * The bootloader has set up the CPU1 reset vector at
0080          * 0xa000_0200.
0081          * This conflicts with the special interrupt vector (IV).
0082          * The bootloader has also set up CPU1 to respond to the wrong
0083          * IPI interrupt.
0084          * Here we will start up CPU1 in the background and ask it to
0085          * reconfigure itself then go back to sleep.
0086          */
0087         memcpy((void *)0xa0000200, bmips_smp_movevec, 0x20);
0088         __sync();
0089         set_c0_cause(C_SW0);
0090         cpumask_set_cpu(1, &bmips_booted_mask);
0091 
0092         /*
0093          * FIXME: we really should have some sort of hazard barrier here
0094          */
0095     }
0096 }