]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/mpc7448hpc2/asm_init.S
Merge remote-tracking branch 'u-boot-imx/master'
[karo-tx-uboot.git] / board / freescale / mpc7448hpc2 / asm_init.S
1 /*
2  * (C) Copyright 2004-05;  Tundra Semiconductor Corp.
3  *
4  * Added automatic detect of SDC settings
5  * Copyright (c) 2005 Freescale Semiconductor, Inc.
6  * Maintainer tie-fei.zang@freescale.com
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 /*
12  * FILENAME: asm_init.s
13  *
14  * Originator: Alex Bounine
15  *
16  * DESCRIPTION:
17  * Initialization code for the Tundra Tsi108 bridge chip
18  *
19  */
20
21 #include <config.h>
22 #include <version.h>
23
24 #include <ppc_asm.tmpl>
25 #include <ppc_defs.h>
26 #include <asm/processor.h>
27
28 #include <tsi108.h>
29
30 /*
31  * Build Configuration Options
32  */
33
34 /* #define DISABLE_PBM          disables usage of PB Master */
35 /* #define SDC_HARDCODED_INIT   config SDRAM controller with hardcoded values */
36 /* #define SDC_AUTOPRECH_EN     enable SDRAM auto precharge */
37
38 /*
39  * Hardcoded SDC settings
40  */
41
42 #ifdef SDC_HARDCODED_INIT
43
44 /* Micron MT9HTF6472AY-40EA1 : Unbuffered, 512MB, 400, CL3, Single Rank */
45
46 #define VAL_SD_REFRESH  (0x61A)
47 #define VAL_SD_TIMING   (0x0308336b)
48 #define VAL_SD_D0_CTRL  (0x07100021)    /* auto-precharge disabled */
49 #define VAL_SD_D0_BAR   (0x0FE00000)    /* 512MB @ 0x00000000 */
50 #define VAL_SD_D1_CTRL  (0x07100021)    /* auto-precharge disabled */
51 #define VAL_SD_D1_BAR   (0x0FE00200)    /* 512MB @ 0x20000000 */
52
53 #endif /* SDC_HARDCODED_INIT */
54
55 /*
56  CPU Configuration:
57
58  CPU Address and Data Parity enables.
59
60 #define CPU_AP
61 #define CPU_DP
62 */
63
64 /*
65  * Macros
66  * !!! Attention !!! Macros LOAD_PTR, LOAD_U32 and LOAD_MEM defined below are
67  * expected to work correctly for the CSR space within 32KB range.
68  *
69  * LOAD_PTR and LOAD_U32 - load specified register with a 32 bit constant.
70  * These macros are absolutely identical except their names. This difference
71  * is provided intentionally for better readable code.
72  */
73
74 #define LOAD_PTR(reg,const32) \
75         addis reg,r0,const32@h; ori reg,reg,const32@l
76
77 #define LOAD_U32(reg,const32) \
78         addis reg,r0,const32@h; ori reg,reg,const32@l
79
80 /* LOADMEM initializes a register with the contents of a specified 32-bit
81  * memory location, usually a CSR value.
82  */
83
84 #define LOAD_MEM(reg,addr32) \
85         addis reg,r0,addr32@ha; lwz reg,addr32@l(reg)
86
87 #ifndef SDC_HARDCODED_INIT
88 sdc_clk_sync:
89         /* MHz: 0,0,183,100,133,167,200,233 */
90         .long   0, 0, 6, 10, 8, 6, 5, 4         /* nSec */
91 #endif
92
93 /*
94  * board_asm_init() - early initialization function. Coded to be portable to
95  * dual-CPU configuration.
96  * Checks CPU number and performs board HW initialization if called for CPU0.
97  * Registers used: r3,r4,r5,r6,r19,r29
98  *
99  * NOTE: For dual-CPU configuration only CPU0 is allowed to configure Tsi108
100  * and the rest of the board. Current implementation demonstrates two
101  * possible ways to identify CPU number:
102  * - for MPC74xx platform: uses MSSCR0[ID] bit as defined in UM.
103  * - for PPC750FX/GX boards: uses WHO_AM_I bit reported by Tsi108.
104  */
105
106         .globl board_asm_init
107 board_asm_init:
108         mflr    r19     /* Save LR to be able return later. */
109         bl      icache_enable   /* Enable icache to reduce reads from flash. */
110
111 /* Initialize pointer to Tsi108 register space */
112
113         LOAD_PTR(r29,CONFIG_SYS_TSI108_CSR_RST_BASE)/* r29 - pointer to tsi108 CSR space */
114         ori r4,r29,TSI108_PB_REG_OFFSET
115
116 /* Check Processor Version Number */
117
118         mfspr   r3, PVR
119         rlwinm  r3,r3,16,16,23  /* get ((Processor Version Number) & 0xFF00) */
120
121         cmpli   0,0,r3,0x8000   /* MPC74xx */
122         bne     cont_brd_init
123
124         /*
125          * For MPC744x/5x enable extended BATs[4-7]
126          * Sri: Set HIGH_BAT_EN and XBSEN, and SPD =1
127          * to disable prefetch
128          */
129
130         mfspr   r5, HID0
131         oris    r5, r5, 0x0080  /* Set HID0[HIGH_BAT_EN] bit #8 */
132         ori     r5, r5, 0x0380  /* Set SPD,XBSEN,SGE bits #22,23,24 */
133         mtspr   HID0, r5
134         isync
135         sync
136
137         /* Adding code to disable external interventions in MPX bus mode */
138         mfspr   r3, 1014
139         oris    r3, r3, 0x0100  /* Set the EIDIS bit in MSSCR0:  bit 7 */
140         mtspr   1014, r3
141         isync
142         sync
143
144         /* Sri: code to enable FP unit */
145         mfmsr   r3
146         ori     r3, r3, 0x2000
147         mtmsr   r3
148         isync
149         sync
150
151         /* def CONFIG_DUAL_CPU
152          * For MPC74xx processor, use MSSCR0[ID] bit to identify CPU number.
153          */
154 #if(1)
155         mfspr   r3,1014         /* read MSSCR0 */
156         rlwinm. r3,r3,27,31,31  /* get processor ID number */
157         mtspr   SPRN_PIR,r3     /* Save CPU ID */
158         sync
159         bne     init_done
160         b       do_tsi108_init
161
162 cont_brd_init:
163
164         /* An alternative method of checking the processor number (in addition
165          * to configuration using MSSCR0[ID] bit on MPC74xx).
166          * Good for IBM PPC750FX/GX.
167          */
168
169         lwz     r3,PB_BUS_MS_SELECT(r4) /* read PB_ID register */
170         rlwinm. r3,r3,24,31,31          /* get processor ID number */
171         bne init_done
172 #else
173
174 cont_brd_init:
175
176 #endif /* CONFIG_DUAL_CPU */
177
178         /* Initialize Tsi108 chip */
179
180 do_tsi108_init:
181
182         /*
183          * Adjust HLP/Flash parameters. By default after reset the HLP port is
184          * set to support slow devices. Better performance can be achived when
185          * an optimal parameters are used for specific EPROM device.
186          * NOTE: This should be performed ASAP for the emulation platform
187          * because it has 5MHz HLP clocking.
188          */
189
190 #ifdef CONFIG_TSI108EMU
191         ori     r4,r29,TSI108_HLP_REG_OFFSET
192         LOAD_U32(r5,0x434422c0)
193         stw     r5,0x08(r4)     /* set HLP B0_CTRL0 */
194         sync
195         LOAD_U32(r5,0xd0012000)
196         stw     r5,0x0c(r4)             /* set HLP B0_CTRL1 */
197         sync
198 #endif
199
200         /* Initialize PB interface. */
201
202         ori r4,r29,TSI108_PB_REG_OFFSET
203
204 #if (CONFIG_SYS_TSI108_CSR_BASE != CONFIG_SYS_TSI108_CSR_RST_BASE)
205         /* Relocate (if required) Tsi108 registers. Set new value for
206          * PB_REG_BAR:
207          * Note we are in the 32-bit address mode.
208          */
209         LOAD_U32(r5,(CONFIG_SYS_TSI108_CSR_BASE | 0x01)) /* PB_REG_BAR: BA + EN */
210         stw     r5,PB_REG_BAR(r4)
211         andis.  r29,r5,0xFFFF
212         sync
213         ori     r4,r29,TSI108_PB_REG_OFFSET
214 #endif
215
216         /* Set PB Slave configuration register */
217
218         LOAD_U32(r5,0x00002481) /* PB_SCR: TEA enabled,AACK delay = 1 */
219         lwz     r3, PB_RSR(r4)  /* get PB bus mode */
220         xori    r3,r3,0x0001    /* mask PB_BMODE: r3 -> (0 = 60X, 1 = MPX) */
221         rlwimi  r5,r3,14,17,17  /* for MPX: set DTI_MODE bit */
222         stw     r5,PB_SCR(r4)
223         sync
224
225         /* Configure PB Arbiter */
226
227         lwz     r5,PB_ARB_CTRL(r4)      /* Read PB Arbiter Control Register */
228         li      r3, 0x00F0              /* ARB_PIPELINE_DEP mask */
229 #ifdef DISABLE_PBM
230         ori     r3,r3,0x1000    /* add PBM_EN to clear (enabled by default) */
231 #endif
232         andc    r5,r5,r3        /* Clear the masked bit fields */
233         ori     r5,r5,0x0001    /* Set pipeline depth */
234         stw     r5,PB_ARB_CTRL(r4)
235
236 #if (0) /* currently using the default settings for PBM after reset */
237         LOAD_U32(r5,0x)         /* value for PB_MCR */
238         stw     r5,PB_MCR(r4)
239         sync
240
241         LOAD_U32(r5,0x)         /* value for PB_MCMD */
242         stw     r5,PB_MCMD(r4)
243         sync
244 #endif
245
246         /* Disable or enable PVT based on processor bus frequency
247          * 1. Read CG_PWRUP_STATUS register field bits 18,17,16
248          * 2. See if the value is < or > 133mhz (18:16 = 100)
249          * 3. If > enable PVT
250          */
251
252         LOAD_U32(r3,0xC0002234)
253         lwz     r3,0(r3)
254         rlwinm  r3,r3,16,29,31
255
256         cmpi    0,0,r3,0x0004
257         bgt     sdc_init
258
259 #ifndef CONFIG_TSI108EMU
260         /* FIXME: Disable PB calibration control for any real Tsi108 board */
261         li      r5,0x0101       /* disable calibration control */
262         stw     r5,PB_PVT_CTRL2(r4)
263         sync
264 #endif
265
266         /* Initialize SDRAM controller. */
267
268 sdc_init:
269
270 #ifndef SDC_HARDCODED_INIT
271         /* get SDC clock prior doing sdram controller autoconfig */
272         ori     r4,r29,TSI108_CLK_REG_OFFSET    /* r4 - ptr to CG registers */
273         lwz     r3, CG_PWRUP_STATUS(r4)         /* get CG configuration */
274         rlwinm  r3,r3,12,29,31                  /* r3 - SD clk */
275         lis     r5,sdc_clk_sync@h
276         ori     r5,r5,sdc_clk_sync@l
277         /* Sri:  At this point check if r3 = 001. If yes,
278          * the memory frequency should be same as the
279          * MPX bus frequency
280          */
281         cmpi    0,0,r3,0x0001
282         bne     get_nsec
283         lwz     r6, CG_PWRUP_STATUS(r4)
284         rlwinm  r6,r6,16,29,31
285         mr      r3,r6
286
287 get_nsec:
288         rlwinm  r3,r3,2,0,31
289         lwzx    r9,r5,r3        /* get SD clk rate in nSec */
290         /* ATTN: r9 will be used by SPD routine */
291 #endif /* !SDC_HARDCODED_INIT */
292
293         ori     r4,r29,TSI108_SD_REG_OFFSET /* r4 - ptr to SDRAM registers */
294
295         /* Initialize SDRAM controller. SDRAM Size = 512MB, One DIMM. */
296
297         LOAD_U32(r5,0x00)
298         stw     r5,SD_INT_ENABLE(r4) /* Ensure that interrupts are disabled */
299 #ifdef ENABLE_SDRAM_ECC
300         li      r5, 0x01
301 #endif /* ENABLE_SDRAM_ECC */
302         stw     r5,SD_ECC_CTRL(r4)      /* Enable/Disable ECC */
303         sync
304
305 #ifdef SDC_HARDCODED_INIT /* config sdram controller with hardcoded values */
306
307         /* First read the CG_PWRUP_STATUS register to get the
308          * memory speed from bits 22,21,20
309          */
310
311         LOAD_U32(r3,0xC0002234)
312         lwz     r3,0(r3)
313         rlwinm  r3,r3,12,29,31
314
315         /* Now first check for 166, then 200, or default */
316
317         cmpi    0,0,r3,0x0005
318         bne     check_for_200mhz
319
320         /* set values for 166 Mhz memory speed
321          * Set refresh rate and timing parameters
322          */
323         LOAD_U32(r5,0x00000515)
324         stw     r5,SD_REFRESH(r4)
325         LOAD_U32(r5,0x03073368)
326         stw     r5,SD_TIMING(r4)
327         sync
328
329         /* Initialize DIMM0 control and BAR registers */
330         LOAD_U32(r5,VAL_SD_D0_CTRL)     /* auto-precharge disabled */
331 #ifdef SDC_AUTOPRECH_EN
332         oris    r5,r5,0x0001            /* set auto precharge EN bit */
333 #endif
334         stw     r5,SD_D0_CTRL(r4)
335         LOAD_U32(r5,VAL_SD_D0_BAR)
336         stw     r5,SD_D0_BAR(r4)
337         sync
338
339         /* Initialize DIMM1 control and BAR registers
340          * (same as dimm 0, next 512MB, disabled)
341          */
342         LOAD_U32(r5,VAL_SD_D1_CTRL)     /* auto-precharge disabled */
343 #ifdef SDC_AUTOPRECH_EN
344         oris    r5,r5,0x0001    /* set auto precharge EN bit */
345 #endif
346         stw     r5,SD_D1_CTRL(r4)
347         LOAD_U32(r5,VAL_SD_D1_BAR)
348         stw     r5,SD_D1_BAR(r4)
349         sync
350
351         b       sdc_init_done
352
353 check_for_200mhz:
354
355         cmpi    0,0,r3,0x0006
356         bne     set_default_values
357
358         /* set values for 200Mhz memory speed
359          * Set refresh rate and timing parameters
360          */
361         LOAD_U32(r5,0x0000061a)
362         stw     r5,SD_REFRESH(r4)
363         LOAD_U32(r5,0x03083348)
364         stw     r5,SD_TIMING(r4)
365         sync
366
367         /* Initialize DIMM0 control and BAR registers */
368         LOAD_U32(r5,VAL_SD_D0_CTRL)     /* auto-precharge disabled */
369 #ifdef SDC_AUTOPRECH_EN
370         oris    r5,r5,0x0001            /* set auto precharge EN bit */
371 #endif
372         stw     r5,SD_D0_CTRL(r4)
373         LOAD_U32(r5,VAL_SD_D0_BAR)
374         stw     r5,SD_D0_BAR(r4)
375         sync
376
377         /* Initialize DIMM1 control and BAR registers
378          * (same as dimm 0, next 512MB, disabled)
379          */
380         LOAD_U32(r5,VAL_SD_D1_CTRL)     /* auto-precharge disabled */
381 #ifdef SDC_AUTOPRECH_EN
382         oris    r5,r5,0x0001            /* set auto precharge EN bit */
383 #endif
384         stw     r5,SD_D1_CTRL(r4)
385         LOAD_U32(r5,VAL_SD_D1_BAR)
386         stw     r5,SD_D1_BAR(r4)
387         sync
388
389         b       sdc_init_done
390
391 set_default_values:
392
393         /* Set refresh rate and timing parameters */
394         LOAD_U32(r5,VAL_SD_REFRESH)
395         stw     r5,SD_REFRESH(r4)
396         LOAD_U32(r5,VAL_SD_TIMING)
397         stw     r5,SD_TIMING(r4)
398         sync
399
400         /* Initialize DIMM0 control and BAR registers */
401         LOAD_U32(r5,VAL_SD_D0_CTRL)     /* auto-precharge disabled */
402 #ifdef SDC_AUTOPRECH_EN
403         oris    r5,r5,0x0001            /* set auto precharge EN bit */
404 #endif
405         stw     r5,SD_D0_CTRL(r4)
406         LOAD_U32(r5,VAL_SD_D0_BAR)
407         stw     r5,SD_D0_BAR(r4)
408         sync
409
410         /* Initialize DIMM1 control and BAR registers
411          * (same as dimm 0, next 512MB, disabled)
412          */
413         LOAD_U32(r5,VAL_SD_D1_CTRL)     /* auto-precharge disabled */
414 #ifdef SDC_AUTOPRECH_EN
415         oris    r5,r5,0x0001            /* set auto precharge EN bit */
416 #endif
417         stw     r5,SD_D1_CTRL(r4)
418         LOAD_U32(r5,VAL_SD_D1_BAR)
419         stw     r5,SD_D1_BAR(r4)
420         sync
421 #else /* !SDC_HARDCODED_INIT */
422         bl      tsi108_sdram_spd        /* automatically detect SDC settings */
423 #endif /* SDC_HARDCODED_INIT */
424
425 sdc_init_done:
426
427 #ifdef DISABLE_PBM
428         LOAD_U32(r5,0x00000030)         /* PB_EN + OCN_EN */
429 #else
430         LOAD_U32(r5,0x00000230)         /* PB_EN + OCN_EN + PB/OCN=80/20 */
431 #endif /* DISABLE_PBM */
432
433 #ifdef CONFIG_TSI108EMU
434         oris    r5,r5,0x0010            /* set EMULATION_MODE bit */
435 #endif
436
437         stw     r5,SD_CTRL(r4)
438         eieio
439         sync
440
441         /* Enable SDRAM access */
442
443         oris    r5,r5,0x8000            /* start SDC: set SD_CTRL[ENABLE] bit */
444         stw     r5,SD_CTRL(r4)
445         sync
446
447 wait_init_complete:
448         lwz     r5,SD_STATUS(r4)
449         andi.   r5,r5,0x0001
450         /* wait until SDRAM initialization is complete */
451         beq     wait_init_complete
452
453         /* Map SDRAM into the processor bus address space */
454
455         ori     r4,r29,TSI108_PB_REG_OFFSET
456
457         /* Setup BARs associated with direct path PB<->SDRAM */
458
459         /* PB_SDRAM_BAR1:
460          * provides a direct path to the main system memory (cacheable SDRAM)
461          */
462
463         /* BA=0,Size=512MB, ENable, No Addr.Translation */
464         LOAD_U32(r5, 0x00000011)
465         stw     r5,PB_SDRAM_BAR1(r4)
466         sync
467
468         /* Make sure that PB_SDRAM_BAR1 decoder is set
469          * (to allow following immediate read from SDRAM)
470          */
471         lwz     r5,PB_SDRAM_BAR1(r4)
472         sync
473
474         /* PB_SDRAM_BAR2:
475          * provides non-cacheable alias (via the direct path) to main
476          * system memory.
477          * Size = 512MB, ENable, Addr.Translation - ON,
478          * BA = 0x0_40000000, TA = 0x0_00000000
479          */
480
481         LOAD_U32(r5, 0x40010011)
482         stw     r5,PB_SDRAM_BAR2(r4)
483         sync
484
485         /* Make sure that PB_SDRAM_BAR2 decoder is set
486          * (to allow following immediate read from SDRAM)
487          */
488         lwz     r5,PB_SDRAM_BAR2(r4)
489         sync
490
491 init_done:
492
493         /* All done. Restore LR and return. */
494         mtlr    r19
495         blr
496
497 #if (0)
498         /*
499          * init_cpu1
500          * This routine enables CPU1 on the dual-processor system.
501          * Now there is only one processor in the system
502          */
503
504         .global enable_cpu1
505 enable_cpu1:
506
507         lis     r3,Tsi108_Base@ha       /* Get Grendel CSR Base Addr */
508         addi    r3,r3,Tsi108_Base@l
509         lwz     r3,0(r3)                /* R3 = CSR Base Addr */
510         ori     r4,r3,TSI108_PB_REG_OFFSET
511         lwz     r3,PB_ARB_CTRL(r4)      /* Read PB Arbiter Control Register */
512         ori     r3,r3,0x0200            /* Set M1_EN bit */
513         stw     r3,PB_ARB_CTRL(r4)
514
515         blr
516 #endif
517
518         /*
519          * enable_EI
520          * Enable CPU core external interrupt
521          */
522
523         .global enable_EI
524 enable_EI:
525         mfmsr   r3
526         ori     r3,r3,0x8000    /* set EE bit */
527         mtmsr   r3
528         blr
529
530         /*
531          * disable_EI
532          * Disable CPU core external interrupt
533          */
534
535         .global disable_EI
536 disable_EI:
537         mfmsr   r3
538         li      r4,-32768       /* aka "li  r4,0x8000" */
539         andc    r3,r3,r4        /* clear EE bit */
540         mtmsr   r3
541         blr
542
543 #ifdef ENABLE_SDRAM_ECC
544         /* enables SDRAM ECC  */
545
546         .global enable_ECC
547 enable_ECC:
548         ori     r4,r29,TSI108_SD_REG_OFFSET
549         lwz     r3,SD_ECC_CTRL(r4)      /* Read SDRAM ECC Control Register */
550         ori     r3,r3,0x0001            /* Set ECC_EN bit */
551         stw     r3,SD_ECC_CTRL(r4)
552         blr
553
554         /*
555          * clear_ECC_err
556          * Clears all pending SDRAM ECC errors
557          * (normally after SDRAM scrubbing/initialization)
558          */
559
560         .global clear_ECC_err
561 clear_ECC_err:
562         ori r4,r29,TSI108_SD_REG_OFFSET
563         ori r3,r0,0x0030        /* ECC_UE_INT + ECC_CE_INT bits */
564         stw r3,SD_INT_STATUS(r4)
565         blr
566
567 #endif /* ENABLE_SDRAM_ECC */
568
569 #ifndef SDC_HARDCODED_INIT
570
571         /* SDRAM SPD Support */
572 #define SD_I2C_CTRL1    (0x400)
573 #define SD_I2C_CTRL2    (0x404)
574 #define SD_I2C_RD_DATA  (0x408)
575 #define SD_I2C_WR_DATA  (0x40C)
576
577         /*
578          * SDRAM SPD Support Macros
579          */
580
581 #define SPD_DIMM0       (0x00000100)
582 #define SPD_DIMM1       (0x00000200)    /* SPD_DIMM1 was 0x00000000 */
583
584 #define SPD_RDIMM                       (0x01)
585 #define SPD_UDIMM                       (0x02)
586
587 #define SPD_CAS_3                       0x8
588 #define SPD_CAS_4                       0x10
589 #define SPD_CAS_5                       0x20
590
591 #define ERR_NO_DIMM_FOUND               (0xdb0)
592 #define ERR_TRAS_FAIL                   (0xdb1)
593 #define ERR_TRCD_FAIL                   (0xdb2)
594 #define ERR_TRP_FAIL                    (0xdb3)
595 #define ERR_TWR_FAIL                    (0xdb4)
596 #define ERR_UNKNOWN_PART                (0xdb5)
597 #define ERR_NRANK_INVALID               (0xdb6)
598 #define ERR_DIMM_SIZE                   (0xdb7)
599 #define ERR_ADDR_MODE                   (0xdb8)
600 #define ERR_RFRSH_RATE                  (0xdb9)
601 #define ERR_DIMM_TYPE                   (0xdba)
602 #define ERR_CL_VALUE                    (0xdbb)
603 #define ERR_TRFC_FAIL                   (0xdbc)
604
605 /* READ_SPD requirements:
606  * byte - byte address in SPD device (0 - 255)
607  * r3 = will return data read from I2C Byte location
608  * r4 - unchanged (SDC base addr)
609  * r5 - clobbered in routine (I2C status)
610  * r10 - number of DDR slot where first SPD device is detected
611  */
612
613 #define READ_SPD(byte_num)              \
614         addis   r3, 0, byte_num@l;      \
615         or      r3, r3, r10;            \
616         ori     r3, r3, 0x0A;           \
617         stw     r3, SD_I2C_CTRL1(r4);   \
618         li      r3, I2C_CNTRL2_START;   \
619         stw     r3, SD_I2C_CTRL2(r4);   \
620         eieio;                          \
621         sync;                           \
622         li      r3, 0x100;              \
623 1:;                                     \
624         addic.  r3, r3, -1;             \
625         bne     1b;                     \
626 2:;                                     \
627         lwz     r5, SD_I2C_CTRL2(r4);   \
628         rlwinm. r3,r5,0,23,23;          \
629         bne     2b;                     \
630         rlwinm. r3,r5,0,3,3;            \
631         lwz     r3,SD_I2C_RD_DATA(r4)
632
633 #define SPD_MIN_RFRSH   (0x80)
634 #define SPD_MAX_RFRSH   (0x85)
635
636 refresh_rates:  /* in nSec */
637         .long   15625   /* Normal (0x80) */
638         .long   3900    /* Reduced 0.25x (0x81) */
639         .long   7800    /* Reduced 0.5x (0x82) */
640         .long   31300   /* Extended 2x (0x83) */
641         .long   62500   /* Extended 4x (0x84) */
642         .long   125000  /* Extended 8x (0x85) */
643
644 /*
645  * tsi108_sdram_spd
646  *
647  * Inittializes SDRAM Controller using DDR2 DIMM Serial Presence Detect data
648  * Uses registers: r4 - SDC base address (not changed)
649  *                                 r9 - SDC clocking period in nSec
650  * Changes registers: r3,r5,r6,r7,r8,r10,r11
651  */
652
653 tsi108_sdram_spd:
654
655         li      r10,SPD_DIMM0
656         xor     r11,r11,r11             /* DIMM Base Address: starts from 0 */
657
658 do_first_dimm:
659
660         /* Program Refresh Rate Register */
661
662         READ_SPD(12)                    /* get Refresh Rate */
663         beq     check_next_slot
664         li      r5, ERR_RFRSH_RATE
665         cmpi    0,0,r3,SPD_MIN_RFRSH
666         ble     spd_fail
667         cmpi    0,0,r3,SPD_MAX_RFRSH
668         bgt     spd_fail
669         addi    r3,r3,-SPD_MIN_RFRSH
670         rlwinm  r3,r3,2,0,31
671         lis     r5,refresh_rates@h
672         ori     r5,r5,refresh_rates@l
673         lwzx    r5,r5,r3                /* get refresh rate in nSec */
674         divwu   r5,r5,r9                /* calculate # of SDC clocks */
675         stw     r5,SD_REFRESH(r4)       /* Set refresh rate */
676         sync
677
678         /* Program SD Timing Register */
679
680         li      r7, 0           /* clear r7 prior parameter collection */
681
682         READ_SPD(20)            /* get DIMM type: Registered or Unbuffered */
683         beq     spd_read_fail
684         li      r5, ERR_DIMM_TYPE
685         cmpi    0,0,r3,SPD_UDIMM
686         beq     do_cl
687         cmpi    0,0,r3,SPD_RDIMM
688         bne     spd_fail
689         oris    r7,r7,0x1000    /* set SD_TIMING[DIMM_TYPE] bit */
690
691 do_cl:
692         READ_SPD(18)            /* Get CAS Latency */
693         beq     spd_read_fail
694         li      r5,ERR_CL_VALUE
695         andi.   r6,r3,SPD_CAS_3
696         beq     cl_4
697         li      r6,3
698         b       set_cl
699 cl_4:
700         andi.   r6,r3,SPD_CAS_4
701         beq     cl_5
702         li      r6,4
703         b       set_cl
704 cl_5:
705         andi.   r6,r3,SPD_CAS_5
706         beq     spd_fail
707         li      r6,5
708 set_cl:
709         rlwimi  r7,r6,24,5,7
710
711         READ_SPD(30)            /* Get tRAS */
712         beq     spd_read_fail
713         divwu   r6,r3,r9
714         mullw   r8,r6,r9
715         subf.   r8,r8,r3
716         beq     set_tras
717         addi    r6,r6,1
718 set_tras:
719         li r5,ERR_TRAS_FAIL
720         cmpi    0,0,r6,0x0F     /* max supported value */
721         bgt     spd_fail
722         rlwimi  r7,r6,16,12,15
723
724         READ_SPD(29)    /* Get tRCD */
725         beq     spd_read_fail
726         /* right shift tRCD by 2 bits as per DDR2 spec */
727         rlwinm  r3,r3,30,2,31
728         divwu   r6,r3,r9
729         mullw   r8,r6,r9
730         subf.   r8,r8,r3
731         beq     set_trcd
732         addi    r6,r6,1
733 set_trcd:
734         li      r5,ERR_TRCD_FAIL
735         cmpi    0,0,r6,0x07     /* max supported value */
736         bgt     spd_fail
737         rlwimi  r7,r6,12,17,19
738
739         READ_SPD(27)    /* Get tRP value */
740         beq     spd_read_fail
741         rlwinm  r3,r3,30,2,31   /* right shift tRP by 2 bits as per DDR2 spec */
742         divwu   r6,r3,r9
743         mullw   r8,r6,r9
744         subf.   r8,r8,r3
745         beq     set_trp
746         addi    r6,r6,1
747 set_trp:
748         li      r5,ERR_TRP_FAIL
749         cmpi    0,0,r6,0x07     /* max supported value */
750         bgt     spd_fail
751         rlwimi  r7,r6,8,21,23
752
753         READ_SPD(36)    /* Get tWR value */
754         beq     spd_read_fail
755         rlwinm  r3,r3,30,2,31   /* right shift tWR by 2 bits as per DDR2 spec */
756         divwu   r6,r3,r9
757         mullw   r8,r6,r9
758         subf.   r8,r8,r3
759         beq     set_twr
760         addi    r6,r6,1
761 set_twr:
762         addi    r6,r6,-1        /* Tsi108 SDC always gives one extra clock */
763         li      r5,ERR_TWR_FAIL
764         cmpi    0,0,r6,0x07     /* max supported value */
765         bgt     spd_fail
766         rlwimi  r7,r6,5,24,26
767
768         READ_SPD(42)    /* Get tRFC */
769         beq     spd_read_fail
770         li      r5, ERR_TRFC_FAIL
771         /* Tsi108 spec: tRFC=(tRFC + 1)/2 */
772         addi    r3,r3,1
773         rlwinm. r3,r3,31,1,31   /* divide by 2 */
774         beq     spd_fail
775         divwu   r6,r3,r9
776         mullw   r8,r6,r9
777         subf.   r8,r8,r3
778         beq     set_trfc
779         addi    r6,r6,1
780 set_trfc:
781         cmpi    0,0,r6,0x1F     /* max supported value */
782         bgt     spd_fail
783         rlwimi  r7,r6,0,27,31
784
785         stw     r7,SD_TIMING(r4)
786         sync
787
788         /*
789          * The following two registers are set on per-DIMM basis.
790          * The SD_REFRESH and SD_TIMING settings are common for both DIMMS
791          */
792
793 do_each_dimm:
794
795         /* Program SDRAM DIMM Control Register */
796
797         li      r7, 0           /* clear r7 prior parameter collection */
798
799         READ_SPD(13)            /* Get Primary SDRAM Width */
800         beq     spd_read_fail
801         cmpi    0,0,r3,4        /* Check for 4-bit SDRAM */
802         beq     do_nbank
803         oris    r7,r7,0x0010    /* Set MEM_WIDTH bit */
804
805 do_nbank:
806         READ_SPD(17)            /* Get Number of banks on SDRAM device */
807         beq     spd_read_fail
808         /* Grendel only distinguish betw. 4 or 8-bank memory parts */
809         li      r5,ERR_UNKNOWN_PART     /* non-supported memory part */
810         cmpi    0,0,r3,4
811         beq     do_nrank
812         cmpi    0,0,r3,8
813         bne     spd_fail
814         ori     r7,r7,0x1000
815
816 do_nrank:
817         READ_SPD(5)             /* Get # of Ranks */
818         beq     spd_read_fail
819         li      r5,ERR_NRANK_INVALID
820         andi.   r6,r3,0x7       /* Use bits [2..0] only */
821         beq     do_addr_mode
822         cmpi    0,0,r6,1
823         bgt     spd_fail
824         rlwimi  r7,r6,8,23,23
825
826 do_addr_mode:
827         READ_SPD(4)             /* Get # of Column Addresses */
828         beq     spd_read_fail
829         li      r5, ERR_ADDR_MODE
830         andi.   r3,r3,0x0f      /* cut off reserved bits */
831         cmpi    0,0,r3,8
832         ble     spd_fail
833         cmpi    0,0,r3,15
834         bgt     spd_fail
835         addi    r6,r3,-8        /* calculate ADDR_MODE parameter */
836         rlwimi  r7,r6,4,24,27   /* set ADDR_MODE field */
837
838 set_dimm_ctrl:
839 #ifdef SDC_AUTOPRECH_EN
840         oris    r7,r7,0x0001    /* set auto precharge EN bit */
841 #endif
842         ori     r7,r7,1         /* set ENABLE bit */
843         cmpi    0,0,r10,SPD_DIMM0
844         bne     1f
845         stw     r7,SD_D0_CTRL(r4)
846         sync
847         b       set_dimm_bar
848 1:
849         stw     r7,SD_D1_CTRL(r4)
850         sync
851
852
853         /* Program SDRAM DIMMx Base Address Register */
854
855 set_dimm_bar:
856         READ_SPD(5)             /* get # of Ranks */
857         beq     spd_read_fail
858         andi.   r7,r3,0x7
859         addi    r7,r7,1
860         READ_SPD(31)            /* Read DIMM rank density */
861         beq     spd_read_fail
862         rlwinm  r5,r3,27,29,31
863         rlwinm  r6,r3,3,24,28
864         or      r5,r6,r5        /* r5 = Normalized Rank Density byte */
865         lis     r8, 0x0080      /* 128MB >> 4 */
866         mullw   r8,r8,r5        /* r8 = (rank_size >> 4) */
867         mullw   r8,r8,r7        /* r8 = (DIMM_size >> 4) */
868         neg     r7,r8
869         rlwinm  r7,r7,28,4,31
870         or      r7,r7,r11       /* set ADDR field */
871         rlwinm  r8,r8,12,20,31
872         add     r11,r11,r8      /* set Base Addr for next DIMM */
873
874         cmpi    0,0,r10,SPD_DIMM0
875         bne     set_dimm1_size
876         stw     r7,SD_D0_BAR(r4)
877         sync
878         li      r10,SPD_DIMM1
879         READ_SPD(0)
880         bne do_each_dimm
881         b spd_done
882
883 set_dimm1_size:
884         stw     r7,SD_D1_BAR(r4)
885         sync
886 spd_done:
887         blr
888
889 check_next_slot:
890         cmpi    0,0,r10,SPD_DIMM1
891         beq     spd_read_fail
892         li      r10,SPD_DIMM1
893         b       do_first_dimm
894 spd_read_fail:
895         ori     r3,r0,0xdead
896         b       err_hung
897 spd_fail:
898         li      r3,0x0bad
899         sync
900 err_hung:       /* hang here for debugging */
901         nop
902         nop
903         b       err_hung
904
905 #endif /* !SDC_HARDCODED_INIT */