| /***************************************************************************** |
| * Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. |
| * |
| * Unless you and Broadcom execute a separate written software license |
| * agreement governing use of this software, this software is licensed to you |
| * under the terms of the GNU General Public License version 2, available at |
| * http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). |
| * |
| * Notwithstanding the above, under no circumstances may you combine this |
| * software in any way with any other Broadcom software provided under a |
| * license other than the GPL, without Broadcom's express prior written |
| * consent. |
| *****************************************************************************/ |
| |
| /* ---- Include Files ---------------------------------------------------- */ |
| #include <linux/types.h> |
| #include <mach/csp/chipcHw_def.h> |
| #include <mach/csp/chipcHw_inline.h> |
| #include <mach/csp/intcHw_reg.h> |
| #include <asm/cacheflush.h> |
| |
| /* ---- Private Constants and Types --------------------------------------- */ |
| /* ---- Private Variables ------------------------------------------------- */ |
| void chipcHw_reset_run_from_aram(void); |
| |
| typedef void (*RUNFUNC) (void); |
| |
| /****************************************************************************/ |
| /** |
| * @brief warmReset |
| * |
| * @note warmReset configures the clocks which are not reset back to the state |
| * required to execute on reset. To do so we need to copy the code into internal |
| * memory to change the ARM clock while we are not executing from DDR. |
| */ |
| /****************************************************************************/ |
| void chipcHw_reset(uint32_t mask) |
| { |
| int i = 0; |
| RUNFUNC runFunc = (RUNFUNC) (unsigned long)MM_ADDR_IO_ARAM; |
| |
| /* Disable all interrupts */ |
| intcHw_irq_disable(INTCHW_INTC0, 0xffffffff); |
| intcHw_irq_disable(INTCHW_INTC1, 0xffffffff); |
| intcHw_irq_disable(INTCHW_SINTC, 0xffffffff); |
| |
| { |
| REG_LOCAL_IRQ_SAVE; |
| if (mask & chipcHw_REG_SOFT_RESET_CHIP_SOFT) { |
| chipcHw_softReset(chipcHw_REG_SOFT_RESET_CHIP_SOFT); |
| } |
| /* Bypass the PLL clocks before reboot */ |
| writel(readl(&pChipcHw->UARTClock) | chipcHw_REG_PLL_CLOCK_BYPASS_SELECT, |
| &pChipcHw->UARTClock); |
| writel(readl(&pChipcHw->SPIClock) | chipcHw_REG_PLL_CLOCK_BYPASS_SELECT, |
| &pChipcHw->SPIClock); |
| |
| /* Copy the chipcHw_warmReset_run_from_aram function into ARAM */ |
| do { |
| writel(((uint32_t *) &chipcHw_reset_run_from_aram)[i], ((uint32_t __iomem *) MM_IO_BASE_ARAM) + i); |
| i++; |
| } while (readl(((uint32_t __iomem*) MM_IO_BASE_ARAM) + i - 1) != 0xe1a0f00f); /* 0xe1a0f00f == asm ("mov r15, r15"); */ |
| |
| flush_cache_all(); |
| |
| /* run the function from ARAM */ |
| runFunc(); |
| |
| /* Code will never get here, but include it to balance REG_LOCAL_IRQ_SAVE above */ |
| REG_LOCAL_IRQ_RESTORE; |
| } |
| } |
| |
| /* This function must run from internal memory */ |
| void chipcHw_reset_run_from_aram(void) |
| { |
| /* Make sure, pipeline is filled with instructions coming from ARAM */ |
| __asm (" nop \n\t" |
| " nop \n\t" |
| #if defined(__KERNEL__) && !defined(STANDALONE) |
| " MRC p15,#0x0,r0,c1,c0,#0 \n\t" |
| " BIC r0,r0,#0xd \n\t" |
| " MCR p15,#0x0,r0,c1,c0,#0 \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| #endif |
| " nop \n\t" |
| " nop \n\t" |
| /* Bypass the ARM clock and switch to XTAL clock */ |
| " MOV r2,#0x80000000 \n\t" |
| " LDR r3,[r2,#8] \n\t" |
| " ORR r3,r3,#0x20000 \n\t" |
| " STR r3,[r2,#8] \n\t" |
| |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| " nop \n\t" |
| /* Issue reset */ |
| " MOV r3,#0x2 \n\t" |
| " STR r3,[r2,#0x80] \n\t" |
| /* End here */ |
| " MOV pc,pc \n\t"); |
| /* 0xe1a0f00f == asm ("mov r15, r15"); */ |
| } |