OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [ebsa285/] [v2_0/] [src/] [mem285.S] - Blame information for rev 459

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
// #========================================================================
2
// #
3
// #    mem285.S
4
// #
5
// #    StrongARM EBSA-285 memory setup
6
// #
7
// #========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
// #========================================================================
41
// ######DESCRIPTIONBEGIN####
42
// #
43
// # Author(s):     Red Hat, hmt
44
// # Contributors:  Red Hat, hmt
45
// # Date:          1999-07-05
46
// # Purpose:       StrongARM EBSA-285 SDRAM initialization
47
// # Description:   SDRAM Initialization for Intel(R) SA-110 21285 Companion
48
// #                Chip
49
// #                Intel is a Registered Trademark of Intel Corporation.
50
// #                Other Brands and Trademarks are the property of their
51
// #                respective owners.
52
// #
53
// #####DESCRIPTIONEND####
54
// #
55
// #========================================================================
56
 
57
//      .file "mem285.S"
58
        .title "SDRAM Init for Intel(R) SA-110 21285 Companion Chip"
59
 
60
#include 
61
 
62
#include 
63
 
64
        .text
65
        .align     4
66
 
67
#define ARRAY_0_MODE_REGISTER     (SA110_SDRAM_ARRAY_0_MODE_REGISTER_BASE)
68
#define ARRAY_1_MODE_REGISTER     (SA110_SDRAM_ARRAY_1_MODE_REGISTER_BASE)
69
 
70
#define MODE_REGISTER_STEP (ARRAY_1_MODE_REGISTER - ARRAY_0_MODE_REGISTER)
71
 
72
        // [6:4] /CAS Latency is 2 (2)
73
        // [ 3 ] Burst Type is 0, Sequential
74
        // [2:0] Burst Length is 2, meaning 4
75
#define SDRAM_MODE_REGISTER_SETUP 0x22
76
        // Shifted left 2 because this is a word-address-offset!
77
#define SDRAM_MODE_REGISTER_SETUP_OFFSET ((SDRAM_MODE_REGISTER_SETUP) << 2)
78
 
79
 
80
#define SDRAM_TIMING_VALUE        (SA110_SDRAM_ROW_PRECHARGE_2_CYCLES    | \
81
                                   SA110_SDRAM_LAST_DATA_IN_3_CYCLES     | \
82
                                   SA110_SDRAM_RAS_TO_CAS_DELAY_2_CYCLES | \
83
                                   SA110_SDRAM_CAS_LATENCY_2_CYCLES      | \
84
                                   SA110_SDRAM_ROW_CYCLE_TIME_4_CYCLES   | \
85
                                   SA110_SDRAM_COMMAND_DRIVE_SAME_CYCLE)
86
 
87
#define SDRAM_TIMING_VALUE_MIN    (SDRAM_TIMING_VALUE                    | \
88
                                   SA110_SDRAM_REFRESH_INTERVAL_MIN)
89
 
90
#define SDRAM_TIMING_VALUE_NORMAL (SDRAM_TIMING_VALUE                    | \
91
                                   SA110_SDRAM_REFRESH_INTERVAL_NORMAL)
92
 
93
 
94
 
95
        /*
96
         * This subroutine sizes and configures up to four banks of SDRAM DIMMs.
97
         * It runs early without a stack.
98
         *
99
         * R0 - R9 are destroyed. All others preserved.
100
         * Except r11 which is also destroyed.
101
         *
102
         */
103
        .global __mem285_init
104
__mem285_init:
105
 
106
        /*
107
         * First we find out whether the SDRAMs are already initialized,
108
         * and if so, leave them alone.  RAM start implies just do the
109
         * sizing sums to return top of memory.
110
         */
111
        ldr     r0, =SA110_CONTROL_STATUS_BASE
112
 
113
#ifndef CYG_HAL_STARTUP_RAM
114
        // This is conditional even in ROM start for
115
        // a) testing ROM images eg. stubs in RAM really
116
        // b) cooperation with eg. POST code, so we are not really at reset
117
        ldr     r0, =SA110_CONTROL_STATUS_BASE
118
        ldr     r1, [r0, #SA110_SDRAM_TIMING_o]
119
        ldr     r2, =SDRAM_TIMING_VALUE_NORMAL
120
        cmps    r1, r2
121
        movne   r11, #0
122
        bne     12f
123
#endif  // ! defined CYG_HAL_STARTUP_RAM
124
 
125
        // Add up the sizes and return in r0:
126
        mov     r1, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_0_o
127
        mov     r2, #0
128
        mov     r3, #1
129
    1:
130
        ldr     r4, [r0, r1]
131
        ands    r4, r4, #7              // if zero, no mem here
132
        addne   r2, r2, r3, asl r4      // tot up array sizes (in 1/2 Megs)
133
        add     r1, r1, #4
134
        cmps    r1, #(SA110_SDRAM_ADDRESS_SIZE_ARRAY_3_o + 4)
135
        blt     1b
136
 
137
        mov     r0, r2, asl #19         // get size into Mb
138
        mov     pc, lr
139
 
140
#ifndef CYG_HAL_STARTUP_RAM
141
 
142
    12:
143
        /*
144
         * Write to the SDRAM Timing Register in the 21285.  Disable
145
         * refresh totally.
146
         */
147
        mov     r1, #0
148
        str     r1, [r0, #SA110_SDRAM_TIMING_o]
149
 
150
        // Disable each array
151
        mov     r1, #0
152
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_0_o]
153
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_1_o]
154
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_2_o]
155
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_3_o]
156
 
157
        // Wait for 8 refresh cycles to complete
158
        mov     r1, #(9 * 32)
159
    1:  subs    r1, r1, #1
160
        bpl     1b
161
 
162
        /*
163
         * Force an all-banks recharge on all four SDRAM arrays
164
         *
165
         * This code came from the SA-IOP ver 1.0 (3-16-98) spec pg 22
166
         *
167
         * You must access all four arrays regardless of whether there is
168
         * memory there because the 21285 counts the precharge accesses and
169
         * inhibits access to the SDRAM until all four have been done.
170
         *
171
         * An all banks rechargs is initiated by a read from any address
172
         * in the mode register space.
173
         */
174
 
175
        mov     r1, #3
176
        mov     r0, #ARRAY_0_MODE_REGISTER
177
   1:
178
        ldr     r2, [r0]
179
        add     r0, r0, #MODE_REGISTER_STEP
180
        subs    r1, r1, #1
181
        bpl     1b
182
 
183
        /*
184
         * Now we need to write to the SDRAM Mode Register.
185
         * The address is important, not the data.  The mode register
186
         * should be configured for a burst size of 4 with linear addressing
187
         */
188
        mov     r1, #3
189
        mov     r0, #ARRAY_0_MODE_REGISTER
190
   1:
191
        str     r0, [r0, #SDRAM_MODE_REGISTER_SETUP_OFFSET]
192
        add     r0, r0, #MODE_REGISTER_STEP
193
        subs    r1, r1, #1
194
        bpl     1b
195
 
196
        /*
197
         * Write to the SDRAM Timing Register in the 21285.  Set the
198
         * refresh interval to the minimum because we have to wait for
199
         * 8 refresh cycles to complete before we can rely on the SDRAMs
200
         * to be operating normally
201
         */
202
        ldr     r0, =SA110_CONTROL_STATUS_BASE
203
        ldr     r1, =SDRAM_TIMING_VALUE_MIN
204
        str     r1, [r0, #SA110_SDRAM_TIMING_o]
205
 
206
        // Disable each array
207
        mov     r1, #0
208
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_0_o]
209
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_1_o]
210
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_2_o]
211
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_3_o]
212
 
213
        // Wait for 8 refresh cycles to complete
214
        mov     r1, #(9 * 32)
215
    1:  subs    r1, r1, #1
216
        bpl     1b
217
 
218
        // Now reset the Refresh interval to a sensible value
219
        ldr     r1, =SDRAM_TIMING_VALUE_NORMAL
220
        str     r1, [r0, #SA110_SDRAM_TIMING_o]
221
 
222
        /* start out assuming 64M part with MUX mode 2 */
223
        mov     r1, #(SA110_SDRAM_SIZE_64MB | SA110_SDRAM_MUX_MODE2)
224
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_0_o]
225
        add     r1, r1, #(64 << 20) // Add 64Mb
226
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_1_o]
227
        add     r1, r1, #(64 << 20) // Add 64Mb again
228
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_2_o]
229
        add     r1, r1, #(64 << 20) // Add 64Mb and again
230
        str     r1, [r0, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_3_o]
231
 
232
        /*
233
         * First, try to figure out which banks are populated and
234
         * the real mux mode for those banks.
235
         *
236
         * At this point:
237
         *   r0 - Base of control/status registers
238
         *
239
         * Register usage:
240
         *   r8 - offset to SDRAM addr/size register
241
         *   r5 - pattern
242
         *   r4 - inverse pattern
243
         *   r3 - scratch/mux mode output
244
         *   r2 - scratch offset
245
         *   r1 - base address of 64M block in consideration
246
         *   r0 - base address of control register sets
247
         */
248
        mov     r8, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_0_o
249
        mov     r1, #0
250
 
251
        ldr     r5, =0x12345678
252
        mvn     r4, r5
253
 
254
    20:
255
        str     r5, [r1]      // Offset 0 should work regardless
256
        str     r4, [r1, #4]  // put something else on the data bus
257
        ldr     r3, [r1]      // read back original
258
        cmps    r3, r5
259
 
260
        // If we didn't read pattern, then no memory present
261
        movne   r3, #0
262
        strne   r3, [r0, r8]            // write to addr/size register
263
        bne     49f                     // straight to next loop
264
 
265
        /*
266
         * This bank is populated, so try to determine mux mode.
267
         * All banks are currently set for mux mode 2.
268
         */
269
 
270
        // A21 having no effect distinguishes the need for mux mode 0.
271
        str     r5, [r1]
272
        mov     r2, #(1 << 21)
273
        str     r4, [r1, r2]   // Store bad value at A21 mirror address
274
                                 // expect to trash value at r1 if mode 0
275
        ldr     r3, [r1]
276
        cmps    r3, r5
277
        // If we don't read back pattern, then its mux mode 0
278
 
279
        // Force to 32M size to include A18 when sizing:
280
        movne   r3, #(SA110_SDRAM_SIZE_32MB | SA110_SDRAM_MUX_MODE0)
281
        bne     2f
282
 
283
        // A23 having effect distinguishes the need for mux mode 2.
284
        str     r5, [r1]
285
        mov     r2, #(1 << 23)
286
        str     r4, [r1, r2]   // Store bad value at A23 mirror address
287
                               // expect to preserve value at r1 if mode 2
288
        ldr     r3, [r1]
289
        cmps    r3, r5
290
        // if pattern still there, then mode 2
291
        moveq   r3, #(SA110_SDRAM_SIZE_64MB | SA110_SDRAM_MUX_MODE2)
292
        beq     2f
293
 
294
        // A22 having effect distinguishes the need for mux mode 4.
295
        str     r5, [r1]
296
        mov     r2, #(1 << 22)
297
        str     r4, [r1, r2]   // Store bad value at A22 mirror address
298
                               // expect to preserve value at r1 if mode 4
299
        ldr     r3, [r1]
300
        cmps    r3, r5
301
        // if pattern A still there, then mode 4
302
        moveq   r3, #(SA110_SDRAM_SIZE_64MB | SA110_SDRAM_MUX_MODE4)
303
        beq     2f
304
 
305
        /*
306
         * At this point it is either mode 1 or 3. There is no clear cut
307
         * test to differentiate the two, so make a best guess now, then
308
         * correct later (if necessary) while sizing the bank.
309
         */
310
 
311
        // NB the bank is still in mux mode 2, so A24 is fed to the wire for
312
        // A22 (mode 1) or no-connection (mode 3); so:
313
        // A24 having effect distinguishes the need for mux mode 1
314
        // A24 having no effect distinguishes the need for mux mode 3
315
        str     r5, [r1]
316
        mov     r2, #(1 << 24)
317
        str     r4, [r1, r2]
318
        ldr     r3, [r1]
319
        cmps    r3, r5
320
        // If pattern, try mode 1
321
        moveq   r3, #(SA110_SDRAM_SIZE_64MB | SA110_SDRAM_MUX_MODE1)
322
        // otherwise, try mode 3
323
        movne   r3, #(SA110_SDRAM_SIZE_64MB | SA110_SDRAM_MUX_MODE3)
324
 
325
        bne 2f
326
 
327
    2:
328
        orr     r3, r3, r1                      // add in base address
329
        str     r3, [r0, r8]                    // write to addr/size register
330
 
331
        /*
332
         * Now that mux mode for this array is (hopefully) setup, we can try
333
         * to size this SDRAM array.
334
         *
335
         * Register usage:
336
         *    r8 - offset to current size/mode register
337
         *    r1 - offset to current base (in 64M blocks)
338
         *    r0 - base address of control register sets
339
         */
340
 
341
        mov     r4, #(63 << 20)         // 63Mb to start with
342
    1:  str     r4, [r1, r4]
343
        subs    r4, r4, #(1 << 20)      // go down in increments of 1Mb
344
        bpl     1b
345
 
346
        str     r4, [r1, #4]            // change pattern on data bus
347
 
348
        // search for first unexpected data in ascending order
349
        mov     r4, #0
350
    1:
351
        ldr     r5, [r1, r4]
352
        cmps    r5, r4
353
        bne     23f                     // different so end of array
354
        add     r4, r4, #(1 << 20)      // go up in increments of 1Mb
355
        cmps    r4, #(64 << 20)
356
        blt     1b
357
        // fall-through assumes it is a 64Mb device
358
   23:
359
        movs    r4, r4, lsr #20         // get a plain number of Mb
360
        // if this gave a zero, maybe we were mistaken about the RAM
361
        // working earlier: disable this bank.
362
        streq   r4, [r0, r8]            // write to addr/size register
363
        beq     49f                     // straight to next loop
364
 
365
        // apparently, mode 3 devices *must* be 8Mb; if we got a different
366
        // answer, set it to mode 1 and go back to try again:
367
        cmps    r4, #8
368
        beq     4f
369
 
370
        // skip if 8Mb; we are happy
371
        ldr     r3, [r0, r8]            // read in the mode we set
372
        and     r3, r3, #SA110_SDRAM_MUX_MODE_MASK
373
        cmp     r3, #SA110_SDRAM_MUX_MODE3
374
        // Must be misconfigured mux mode. Set to mode 1 and retry
375
        moveq   r3, #(SA110_SDRAM_SIZE_64MB | SA110_SDRAM_MUX_MODE1)
376
        beq     2b
377
        // not mux mode 3; drop though OK
378
 
379
    4:
380
        // convert MB size to register size val
381
        mov     r5, #0
382
        mov     r3, r4
383
    5:  movs    r3, r3, lsr #1
384
        add     r5, r5, #1
385
        bcc     5b
386
 
387
        // Double check that the size was a power of 2
388
        mov     r6, #1
389
        mov     r6, r6, lsl r5          // should get Mb count back doubled
390
        cmps    r6, r4, lsl #1          // compare with doubled
391
        movne   r5, #0                  // disable this bank
392
        ldr     r3, [r0, r8]            // Load current setting
393
        bic     r3, r3, #7
394
        orr     r3, r3, r5              // insert the correct size code
395
        str     r3, [r0, r8]            // into the control register
396
 
397
   49:
398
        add     r8, r8, #4                      // next addr/size register
399
        add     r1, r1, #(64<<20)               // next array
400
        cmps    r1, #(256<<20)                  // top address + 1 bank
401
        blt     20b
402
        // END of main loop to size all 4 DRAM banks
403
 
404
        /*
405
         * At this point, the size values are all in the control registers.
406
         *
407
         * We want to set memory up to be contiguous. Since the
408
         * banks' base address needs to be naturally aligned, we
409
         * need to sort the bank sizes from large to small.
410
         *
411
         * Register usage:
412
         *   r0 - base address of control register sets
413
         *   r1 - bitmap of which slots we have covered in toto
414
         *   r2 - cumulative base address of mapped SDRAM
415
         *   r3 - biggest size code this pass
416
         *   r4 - bit index of current slot
417
         *   r5 - bit index of biggest slot found this pass
418
         *   r6 - scratch control reg contents
419
         *   r7 - scratch size code
420
         *   r8 - address of current slot's control register
421
         *   r9 - address of biggest slot found's control register
422
         */
423
        mov     r1, #0                  // bitmap of which we have covered
424
        mov     r2, #0                  // cumulative base address
425
        // do... until there are no more slots to deal with
426
    70:
427
        mov     r3, #0                  // biggest this pass
428
        mov     r4, #1                  // bit index of current slot
429
        mov     r5, #0                  // bit index of biggest slot found
430
        mov     r8, #SA110_SDRAM_ADDRESS_SIZE_ARRAY_0_o
431
        mov     r9, #0                  // address of biggest slot found
432
        // Foreach slot we have not yet dealt with
433
    75:
434
        tst     r4, r1
435
        bne     88f
436
        ldr     r6, [r0, r8]
437
        and     r7, r6, #7
438
        cmps    r7, r3
439
        movgt   r3, r7                  // save biggest's size
440
        movgt   r5, r4                  // save biggest's index
441
        movgt   r9, r8                  // save biggest's reg address
442
    88:
443
        mov     r4, r4, asl #1
444
        add     r8, r8, #4
445
        cmps    r4, #0x10
446
        blt     75b                     // next slot
447
        // Did we find a largest slot?
448
        cmps    r5, #0
449
        beq     95f     // No!  Finished
450
 
451
        orr     r1, r1, r5              // can forget r4 and r5 now
452
        ldr     r6, [r0, r9]            // get the control register
453
        bic     r6, r6, #0x0ff00000     // clear base address bits
454
        orr     r6, r6, r2              // insert base address to use
455
        str     r6, [r0, r9]            // store the new control register
456
        mov     r6, #1
457
        mov     r6, r6, asl r3
458
        mov     r6, r6, asl #19         // 1 << (size-code + 19) is size
459
        add     r2, r2, r6              // increment the cumulating address
460
 
461
        b       70b                     // go look for the next one
462
 
463
    95: // all done!
464
        // at this point, r2 contains the top of memory.
465
        // (r11 is the value from last time or zero if first time)
466
 
467
        cmps    r11, r2                 // Same answer as last time?
468
        movne   r11, r2                 // if not, save memsize
469
        bne     12b                     // ...and try again.
470
 
471
        mov     r0, r2
472
        mov     pc, lr
473
#endif // ! defined CYG_HAL_STARTUP_RAM
474
//FUNC_END __mem285_init
475
 
476
/* EOF mem285.S */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.