aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/arch/cris/arch-v10/lib/dram_init.S
blob: fd7437577938580963ac311379f77d5ddf593852 (plain) (blame)
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
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * DRAM/SDRAM initialization - alter with care
 * This file is intended to be included from other assembler files
 *
 * Note: This file may not modify r9 because r9 is used to carry
 *       information from the decompressor to the kernel
 *
 * Copyright (C) 2000-2012 Axis Communications AB
 *
 */

/* Just to be certain the config file is included, we include it here
 * explicitly instead of depending on it being included in the file that
 * uses this code.
 */


	;; WARNING! The registers r8 and r9 are used as parameters carrying
	;; information from the decompressor (if the kernel was compressed).
	;; They should not be used in the code below.

	move.d   CONFIG_ETRAX_DEF_R_WAITSTATES, $r0
	move.d   $r0, [R_WAITSTATES]

	move.d   CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0
	move.d   $r0, [R_BUS_CONFIG]

#ifndef CONFIG_ETRAX_SDRAM
	move.d   CONFIG_ETRAX_DEF_R_DRAM_CONFIG, $r0
	move.d   $r0, [R_DRAM_CONFIG]

	move.d   CONFIG_ETRAX_DEF_R_DRAM_TIMING, $r0
	move.d   $r0, [R_DRAM_TIMING]
#else
	;; Samsung SDRAMs seem to require to be initialized twice to work properly.
	moveq    2, $r6	
_sdram_init:

	; Refer to ETRAX 100LX Designers Reference for a description of SDRAM initialization

	; Bank configuration
	move.d   CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, $r0
	move.d   $r0, [R_SDRAM_CONFIG]

	; Calculate value of mrs_data
	; CAS latency = 2 && bus_width = 32 => 0x40
	; CAS latency = 3 && bus_width = 32 => 0x60
	; CAS latency = 2 && bus_width = 16 => 0x20
	; CAS latency = 3 && bus_width = 16 => 0x30

	; Check if value is already supplied in kernel config
	move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r2
	and.d    0x00ff0000, $r2
	bne	 _set_timing
	lsrq     16, $r2

	move.d   0x40, $r2       ; Assume 32 bits and CAS latency = 2
	move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1
	move.d   $r1, $r3
	and.d    0x03, $r1       ; Get CAS latency
	and.d    0x1000, $r3     ; 50 or 100 MHz?
	beq      _speed_50
	nop
_speed_100:
	cmp.d    0x00, $r1	; CAS latency = 2?
	beq      _bw_check
	nop
	or.d     0x20, $r2	; CAS latency = 3
	ba       _bw_check
	nop
_speed_50:
	cmp.d    0x01, $r1	; CAS latency = 2?
	beq      _bw_check
	nop
	or.d     0x20, $r2       ; CAS latency = 3
_bw_check:
	move.d   CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, $r1
	and.d    0x800000, $r1	; DRAM width is bit 23
	bne      _set_timing
	nop
	lsrq     1, $r2		;  16 bits. Shift down value.

	; Set timing parameters. Starts master clock
_set_timing:
	move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1
	and.d    0x8000f9ff, $r1 ; Make sure mrs data and command is 0
	or.d     0x80000000, $r1	; Make sure sdram enable bit is set
	move.d   $r1, $r5
	or.d     0x0000c000, $r1 ; ref = disable
	lslq     16, $r2		; mrs data starts at bit 16
	or.d     $r2, $r1
	move.d   $r1, [R_SDRAM_TIMING]

	; Wait 200us
	move.d   10000, $r2
1:	bne      1b
	subq     1, $r2

	; Issue initialization command sequence
	move.d   _sdram_commands_start, $r2
	and.d    0x000fffff, $r2 ; Make sure commands are read from flash
	move.d   _sdram_commands_end,  $r3
	and.d    0x000fffff, $r3
1:	clear.d  $r4
	move.b   [$r2+], $r4
	lslq     9, $r4	; Command starts at bit 9
	or.d     $r1, $r4
	move.d   $r4, [R_SDRAM_TIMING]
	nop		; Wait five nop cycles between each command
	nop
	nop
	nop
	nop
	cmp.d    $r2, $r3
	bne      1b
	nop
	move.d   $r5, [R_SDRAM_TIMING]
	subq     1, $r6
	bne      _sdram_init
	nop
	ba       _sdram_commands_end
	nop

_sdram_commands_start:
	.byte   3	; Precharge
	.byte   0       ; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   2	; refresh
	.byte   0	; nop
	.byte   1	; mrs
	.byte   0	; nop
_sdram_commands_end:
#endif