summaryrefslogtreecommitdiffstats
path: root/arch/mips/mach-ar231x/include/mach/pbl_macros.h
blob: cb72dbe46696c9ac48e5c6848ff8cd4f8c3f128e (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
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 */