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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
#ifndef __ASM_MACH_AR2312_PBL_MACROS_H
#define __ASM_MACH_AR2312_PBL_MACROS_H
#include <asm/regdef.h>
#include <mach/ar2312_regs.h>
.macro pbl_ar2312_pll
.set push
.set noreorder
mfc0 k0, CP0_STATUS
li k1, ST0_NMI
and k1, k1, k0
bnez k1, pllskip
nop
/* Clear any prior AHB errors by reading both addr registers */
li t0, KSEG1 | AR2312_PROCADDR
lw zero, 0(t0)
li t0, KSEG1 | AR2312_DMAADDR
lw zero, 0(t0)
pbl_sleep t2, 4000
li t0, KSEG1 | AR2312_CLOCKCTL2
lw t1, (t0)
bgez t1, pllskip /* upper bit guaranteed non-0 at reset */
nop
/* For Viper 0xbc003064 register has to be programmed with 0x91000 to
* get 180Mhz Processor clock
* Set /2 clocking and turn OFF AR2312_CLOCKCTL2_STATUS_PLL_BYPASS.
* Processor RESETs at this point; the CLOCKCTL registers retain
* their new values across the reset.
*/
li t0, KSEG1 | AR2312_CLOCKCTL1
li t1, AR2313_CLOCKCTL1_SELECTION
sw t1, (t0)
li t0, KSEG1 | AR2312_CLOCKCTL2
li t1, AR2312_CLOCKCTL2_WANT_RESET
sw t1, (t0) /* reset CPU */
1: b 1b /* NOTREACHED */
nop
pllskip:
.set pop
.endm
.macro pbl_ar2312_rst_uart0
.set push
.set noreorder
li a0, KSEG1 | AR2312_RESET
lw t0, 0(a0)
and t0, ~AR2312_RESET_APB
or t0, AR2312_RESET_UART0
sw t0, 0(a0)
lw zero, 0(a0) /* flush */
and t0, ~AR2312_RESET_UART0
sw t0, 0(a0)
lw zero, 0(a0) /* flush */
1: /* Use internal clocking */
li a0, KSEG1 | AR2312_CLOCKCTL0
lw t0, 0(a0)
and t0, ~AR2312_CLOCKCTL_UART0
sw t0, 0(a0)
.set pop
.endm
.macro pbl_ar2312_x16_sdram
.set push
.set noreorder
li a0, KSEG1 | AR2312_MEM_CFG0
li a1, KSEG1 | AR2312_MEM_CFG1
li a2, KSEG1 | AR2312_MEM_REF
li a3, MEM_CFG1_E0 | (MEM_CFG1_AC_128 << MEM_CFG1_AC0_S)
/* Set the I and M bits to issue an SDRAM nop */
ori t0, a3, MEM_CFG1_M | MEM_CFG1_I
sw t0, 0(a1) /* AR2312_MEM_CFG1 */
pbl_sleep t2, 50
/* Reset the M bit to issue an SDRAM PRE-ALL */
ori t0, a3, MEM_CFG1_I
sw t0, 0(a1) /* AR2312_MEM_CFG1 */
sync
/* Generate a refresh every 16 clocks (spec says 10) */
li t0, 16 /* very fast refresh for now */
sw t0, 0(a2) /* AR2312_MEM_REF */
pbl_sleep t2, 5
/* Set command write mode, and read SDRAM */
ori t0, a3, MEM_CFG1_M
sw t0, 0(a1) /* AR2312_MEM_CFG1 */
sync
li t0, KSEG1 | AR2312_SDRAM0
or t0, 0x23000 /* 16bit burst */
lw zero, 0(t0)
/* Program configuration register */
li t0, MEM_CFG0_C | MEM_CFG0_C2 | MEM_CFG0_R1 | \
MEM_CFG0_B0 | MEM_CFG0_X
sw t0, 0(a0) /* AR2312_MEM_CFG0 */
sync
li t0, AR2312_SDRAM_MEMORY_REFRESH_VALUE
sw t0, 0(a2) /* AR2312_MEM_REF */
sync
/* Clear I and M and set cfg1 to the normal operational value */
sw a3, 0(a1) /* AR2312_MEM_CFG1 */
sync
pbl_sleep t2, 10
/* Now we need to set size of RAM to prevent some wired errors.
* Since I do not have access to any board with two SDRAM chips, or
* any was registered in the wild - we will support only one. */
/* So, lets find the beef */
li a0, KSEG1 | AR2312_MEM_CFG1
li a1, KSEG1 | AR2312_SDRAM0
li a2, 0xdeadbeef
li t0, 0x200000
li t1, MEM_CFG1_AC_2
/* We will write some magic word to the beginning of RAM,
* and see if it appears somewhere else. If yes, we made
* a travel around the world. */
/* But first of all save original state of the first RAM word. */
lw a3, 0(a1)
sw a2, 0(a1)
find_the_beef:
or t2, a1, t0
lw t3, 0(t2)
beq a2, t3, 1f
nop
sll t0, 1
add t1, 1
/* we should have some limit here. */
blt t1, MEM_CFG1_AC_64, find_the_beef
nop
b make_beefsteak
nop
/* additional paranoid check */
1:
sw zero, 0(a1)
lw t3, 0(t2)
bne zero, t3, find_the_beef
nop
make_beefsteak:
/* create new config for AR2312_MEM_CFG1 and overwrite it */
sll t1, MEM_CFG1_AC0_S
or t2, t1, MEM_CFG1_E0
sw t2, 0(a0) /* AR2312_MEM_CFG1 */
/* restore original state of the first RAM word */
sw a3, 0(a1)
.set pop
.endm
#endif /* __ASM_MACH_AR2312_PBL_MACROS_H */
|