summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c
blob: f95ce913fa1e4aec3f1f77467e1d3bad2da7ab6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*****************************************************************************
* 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"); */
}