2 * BCM47XX Sonics SiliconBackplane SDRAM/MEMC core initialization
4 * Copyright 2004, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
25 /* #define DEBUG_SBSDRAM 1 */
28 * Write to prog space so we can see it in
39 #define TRACE(num, reg) sw reg,(num << 4)(k0)
41 #define TRACE(num, reg)
45 * Register usage within this file:
47 * top ncdlsearch test_mem Xdr_do_init sb_reset_core
49 * v1: corerev - - corerev -
50 * a0: coreptr coreptr - coreptr coreptr
51 * a1: x x x sdr/ddr flag
56 * t2: - wr/strm off wr/strm
57 * t3: - rd/strd rd/strd
63 * s1: wrsum/clkdsum - -
64 * s2: rdsum/pass_countmax - -
65 * s3: gsum/strmmax - -
66 * s4: wrlim/stdmmax - -
67 * s5: rdlim/clkdmax - -
68 * s6: glim/clkdlim - -
72 * k0: trace trace trace - -
73 * k1: trace trace trace - -
87 /* Save return address */
92 /* Scan for an SDRAM controller (a0) */
93 li a0,KSEG1ADDR(SB_ENUM_BASE)
94 1: lw v1,(SBCONFIGOFF + SBIDHIGH)(a0)
95 and a1,v1,SBIDH_CC_MASK
96 srl a1,a1,SBIDH_CC_SHIFT
97 beq a1,SB_MEMC,foundctrl
99 beq a1,SB_SOCRAM,foundctrl
101 beq a1,SB_SDRAM,foundctrl
104 bne a1,(SBIDH_CC_MASK >> SBIDH_CC_SHIFT),1b
107 /* No SDRAM controller */
112 /* If we are already in RAM, just go and size it */
115 1: li t0,PHYSADDR_MASK
118 blt t0,t1,memprio_szmem
121 /* For socram we don't need any nvram parms, just do a core reset */
122 bne a1,SB_SOCRAM,read_nvram
126 /* and size memory */
131 /* Find NVRAM (a2) */
132 li t0,KSEG1ADDR(SB_ENUM_BASE) # Is there a chipcommon core?
133 lw t1,(SBCONFIGOFF + SBIDHIGH)(t0)
134 and t1,t1,SBIDH_CC_MASK
135 srl t1,t1,SBIDH_CC_SHIFT
139 /* It is a chipcommon core: */
140 /* 1: Isolate memc's corerev in v1 */
141 and t2,v1,SBIDH_RCE_MASK
142 srl t2,t2,SBIDH_RCE_SHIFT
143 and v1,v1,SBIDH_RC_MASK
146 /* 1.5: 5365a0 lies about its revision, it is really 1 */
150 lw t1,CC_CHIPID(t0) # Get chipid
151 andi t1,CID_ID_MASK # Check chipid
152 bne t1,BCM5365_CHIP_ID,1f
156 /* 2: use the 32MB window */
157 1: li t2,KSEG1ADDR(SB_FLASH2 - NVRAM_SPACE)
163 /* else use the 4MB window */
164 li t2,KSEG1ADDR(SB_FLASH1 - NVRAM_SPACE)
181 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
182 li a2,KSEG1ADDR(SB_FLASH1 + 0x1000)
187 li a2,KSEG1ADDR(SB_FLASH1 + 0x400)
196 /* Get SDRAM parameters (t0, t1, t2) from NVRAM (a2) */
197 lw t0,8(a2) # SDRAM init
200 andi t1,t2,0xffff # SDRAM config
201 srl t2,16 # SDRAM refresh
202 lw t3,16(a2) # SDRAM ncdl
205 /* Initialize SDRAM controller: sdram core */
206 beq a1,SB_SDRAM,sdram_init
208 /* else it is a memc core */
211 bnez a2,1f # Already have the parms in
214 /* No nvram parms: assume DDRM16MX16X2 */
218 li t3,MEMC_DDR1_NCDL # If rev1 (4712):
225 andi a3,t0,MEMC_CONFIG_DDR # Is it ddr or sdr?
226 beqz a3,memc_sdr_init
229 /* Initialize DDR SDRAM */
231 beqz t3,ddr_find_ncdl # Do we have ncdl values? (0s)
235 bne t3,t4,break_ddr_ncdl
241 #define pass_count s0
254 /* Initialize counter & accumulators */
260 /* Initialize with default values */
267 lw dll,MEMC_NCDLCTL(a0)
271 beqz dll,memprio_szmem /* If zero, leave the default values */
274 move wrlim,dll /* dll value is lim for wr, rd and g */
281 addi step,dll,15 /* step = (dll + 16 - 1) / 16 */
285 sub wr,zero,dll /* Negate dll as initial value */
289 /* Inner loop: call ddr_do_init to re-initialize and the test mem */
310 TRACE(0xa, pass_count)
353 /* All done, calculate average values and program them */
355 TRACE(0x13, pass_count)
362 div zero,wrsum,pass_count
365 div zero,rdsum,pass_count
368 div zero,gsum,pass_count
374 /* No passing values, panic! (use defaults) */
376 li t3,MEMC_DDR1_NCDL # If rev1:
384 andi t4,t3,0xff # t4: g
385 srl t2,t3,16 # t2: wr
401 beqz t3,sdr_find_ncdl # Do we have ncdl values?
405 bne t3,t4,break_sdr_ncdl
411 #define pass_count s0
413 #define pass_countmax s2
425 #define CLKDLIM_IC 256
427 /* Initialize counter & saved values */
428 move pass_countmax,zero
433 and strm,t0,0x2000 /* Test for internal clock (Using strm as a temp) */
437 li clkdlim,CLKDLIM_IC
439 move strm,zero /* strm loop */
447 /* Inner loop: call sdr_do_init to re-initialize and the test mem */
465 add clkdsum,clkdsum,clkd
466 TRACE(0x1e, pass_count)
472 bnez pass_count,clkdout # End of passing range, leave clkd loop
477 blt clkd,clkdlim,clkdloop
481 /* If no passing values, skip to next strm */
482 beqz pass_count,nextstrm
485 /* If this is a new max, Save the values */
486 ble pass_count,pass_countmax,nextstrd
489 move pass_countmax,pass_count
490 div zero,clkdsum,pass_count
494 TRACE(0x20, pass_count)
501 blt strd,STRDLIM,strdloop
506 blt strm,STRMLIM,strmloop
509 /* All done, program the new ncdl values */
511 TRACE(0x24, pass_count)
516 beqz pass_countmax,1f
525 /* No passing values, panic! (use defaults) */
527 li t3,MEMC_SDR1_NCDL # If rev1:
535 andi t4,t3,0xff # t4: cd
536 srl t2,t3,16 # t2: sm
537 andi t2,t2,3 # sm is 2 bits only
539 andi t3,t3,0xf # sd is 4 bits
549 bnez a2,1f # Already have the parms in t0, t1, t2
552 /* Use default SDRAM parameters */
557 /* Initialize SDRAM */
562 sw t1, 4(a0) # SDRAM config
568 sw a1, 0(a0) # 1st refresh of power up sequence
569 sw a1, 0(a0) # 2nd refresh of power up sequence
570 sw a1, 0(a0) # 3rd refresh of power up sequence
571 sw a1, 0(a0) # 4th refresh of power up sequence
572 sw a1, 0(a0) # 5th refresh of power up sequence
573 sw a1, 0(a0) # 6th refresh of power up sequence
574 sw a1, 0(a0) # 7th refresh of power up sequence
575 sw a1, 0(a0) # 8th refresh of power up sequence
576 sw t0, 0(a0) # SDRAM init
577 sw t2, 8(a0) # SDRAM refresh
580 /* Change the memory priority inversion counter value */
581 /* Determine memory size and return */
585 lw t0, MEMC_PRIORINV(a0)
589 sw t0, MEMC_PRIORINV(a0)
591 li t0,KSEG1ADDR(SB_ENUM_BASE) # is there a chipcommon core?
592 lw t1,(SBCONFIGOFF + SBIDHIGH)(t0)
593 and t1,t1,SBIDH_CC_MASK
594 srl t1,t1,SBIDH_CC_SHIFT
597 lw t1,CC_CHIPID(t0) # is this BCM4785 chip?
598 and t1,t1,CID_ID_MASK
599 bne t1,BCM4785_CHIP_ID,0f
601 lw t0,MEMC_PRIORINV(a0) # change PriorInvTim to 2
604 sw t0,MEMC_PRIORINV(a0)
606 0: lw t0,(SBCONFIGOFF + SBIDHIGH)(a0)
607 and t1,t0,SBIDH_CC_MASK
608 srl t1,t1,SBIDH_CC_SHIFT
609 bne t1,SB_SOCRAM,szmem_alias
612 /* The socram core tells us how much memory there is */
613 lw t1,SR_COREINFO(a0)
614 and t0,t0,SBIDH_RC_MASK /* Find corerev */
617 /* Its corerev >= 1 */
618 and t2,t1,SRCI_SRNB_MASK /* Find number of blocks */
619 srl t2,t2,SRCI_SRNB_SHIFT
620 and t1,t1,SRCI_SRBSZ_MASK /* Find block size */
621 addi t1,t1,SR_BSZ_BASE
629 and t1,t1,SRCI_MS0_MASK
630 add t1,t1,SR_MS0_BASE
650 bne v0,(128 << 20),1b
652 /* Didn't find an alias, must be 128MB */
662 * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
663 * Returns success (1) or failure (0) in v0
664 * Uses a1, a2, a3 & t5
667 /* Use t4 to generate a semi-random address in the second KB */
673 /* First set: 0 & its negation */
687 /* Second set: 0xaaaaaaaa & its negation */
701 /* Third set: 0x12345678 & its negation */
715 /* Fourth set: the ncdl & its negation */
732 /* Fifth set: the CPU count register & its negation */
754 /* Do an init of the memc core for ddr
755 * a0: memc core pointer
756 * t0: memc config value
757 * t1: memc mode value
758 * t2: memc wr ncdl value
759 * t3: memc rd ncdl value
760 * t4: memc g ncdl value
762 * Uses a1, a2, t7, t8, t9 (here and by calling sb_core_reset)
766 /* Save return address */
772 li a1,MEMC_CONFIG_INIT
774 lui a2, 0x8 # set DQMGate for memc rev 4 or more
776 sw a1,MEMC_CONFIG(a0)
778 li a1,MEMC_DRAMTIM25_INIT # Assume CAS latency of 2.5
779 andi t8,t1,0xf0 # Find out the CAS latency
782 li a1,MEMC_DRAMTIM2_INIT # CAS latency is 2
784 sw a1,MEMC_DRAMTIM(a0)
787 li t8,KSEG1ADDR(SB_ENUM_BASE) # Get package options
788 lw a1,CC_CHIPID(t8) # Get chipid
789 li t9,CID_PKG_MASK # Check package options
791 srl a1,a1,CID_PKG_SHIFT
792 addi t8,SBCONFIGOFF # Get corerev for chipcommon
796 srl t8,SBIDH_RCE_SHIFT
800 bge t8,10,1f # If ccrev is >= 10 use 4bit pkg opt
802 ori a1,8 # else add a bit to the 3bit field
804 beq a1,HDLSIM_PKG_ID,hdlsim # Special case for hdl sim:
807 li t8,KSEG1ADDR(SB_ENUM_BASE) # Get chipid again
809 li t9,BCM5350_CHIP_ID # 5350 ChipID
812 bne t8,t9,notsim # if not 5350keep going
815 bne a1,(8 | HDLSIM5350_PKG_ID),notsim # If 5350, is it (3/4-bit) vsim?
817 #endif /* !BCM_ATE */
820 li a1,MEMC_RDNCDLCOR_SIMINIT # Fixed 0xf6 rdncdl and no inits
821 sw a1,MEMC_RDNCDLCOR(a0) # of wrncdl, dqsgate and miscdly.
827 notsim: andi t8,t3,0xff
828 sll a1,t8,8 # Replicate rd ncdl 4 times
832 li a1,MEMC_RDNCDLCOR_INIT
834 sw a1,MEMC_RDNCDLCOR(a0)
836 li a1,MEMC_1_WRNCDLCOR_INIT # If rev1:
840 li a1,MEMC_WRNCDLCOR_INIT
844 sw a1,MEMC_WRNCDLCOR(a0)
846 li a1,MEMC_DQSGATENCDL_INIT
849 sw a1,MEMC_DQSGATENCDL(a0)
851 li a1,MEMC_1_MISCDLYCTL_INIT # If rev1:
855 li a1,MEMC_MISCDLYCTL_INIT
857 sw a1,MEMC_MISCDLYCTL(a0)
858 #endif /* !BCM_ATE */
861 li a1,MEMC_NCDLCTL_INIT
862 sw a1,MEMC_NCDLCTL(a0)
864 li a1,MEMC_CONTROL_INIT0
865 sw a1,MEMC_CONTROL(a0)
867 li a1,MEMC_CONTROL_INIT1
868 sw a1,MEMC_CONTROL(a0)
870 li a1,MEMC_MODEBUF_INIT0
871 sw a1,MEMC_MODEBUF(a0)
873 li a1,MEMC_CONTROL_INIT2
874 sw a1,MEMC_CONTROL(a0)
876 li a1,MEMC_MODEBUF_INIT1
878 sw a1,MEMC_MODEBUF(a0)
880 li a1,MEMC_CONTROL_INIT3
881 sw a1,MEMC_CONTROL(a0)
883 li a1,MEMC_CONTROL_INIT4
884 sw a1,MEMC_CONTROL(a0)
886 li a1,MEMC_CONTROL_INIT5
887 sw a1,MEMC_CONTROL(a0)
888 lw a1,MEMC_CONTROL(a0)
889 lw a1,MEMC_CONTROL(a0)
890 lw a1,MEMC_CONTROL(a0)
892 li a1,MEMC_CONTROL_INIT5
893 sw a1,MEMC_CONTROL(a0)
894 lw a1,MEMC_CONTROL(a0)
895 lw a1,MEMC_CONTROL(a0)
896 lw a1,MEMC_CONTROL(a0)
898 li a1,MEMC_REFRESH_INIT
899 sw a1,MEMC_REFRESH(a0)
901 li a1,MEMC_MODEBUF_INIT2
903 sw a1,MEMC_MODEBUF(a0)
905 li a1,MEMC_CONTROL_INIT6
906 sw a1,MEMC_CONTROL(a0)
908 li a1,MEMC_CONTROL_INIT7
909 sw a1,MEMC_CONTROL(a0)
911 /* Wait for SDRAM controller to refresh.
915 1: lw a1,(SBCONFIGOFF + SBIDLOW)(a0)
916 lw a1,(SBCONFIGOFF + SBIDHIGH)(a0)
924 /* Do an init of the memc core for sdr
925 * a0: memc core pointer
926 * t0: memc config value
927 * t1: memc mode value
928 * t2: memc strobe mode ncdl value
929 * t3: memc strobe delay ncdl value
930 * t4: memc clock delay ncdl value
932 * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
936 /* Save return address */
942 /* Initialize SDRAM */
943 li a1,MEMC_SD_CONFIG_INIT
945 sw a1,MEMC_CONFIG(a0)
947 li a1,MEMC_SD_DRAMTIM3_INIT # Assume CAS latency of 3
948 andi t8,t1,0xf0 # Find out the CAS latency
951 li a1,MEMC_SD_DRAMTIM2_INIT # CAS latency is 2
953 sw a1,MEMC_DRAMTIM(a0)
956 ble t8,MEMC_CD_THRESHOLD,1f # if (cd <= MEMC_CD_THRESHOLD) rd = cd
959 li t8,MEMC_CD_THRESHOLD # else rd = MEMC_CD_THRESHOLD
962 sll a1,t8,8 # .. replicate it 4 times
966 li a1,MEMC_SD_RDNCDLCOR_INIT
968 sw a1,MEMC_RDNCDLCOR(a0)
970 li a1,MEMC_SD1_WRNCDLCOR_INIT # rev1
974 li a1,MEMC_SD_WRNCDLCOR_INIT # rev0, 2
977 ble t4,MEMC_CD_THRESHOLD,2f # if (cd <= MEMC_CD_THRESHOLD) wr = 0
980 andi t8,t4,0xff # else wr = cd - MEMC_CD_THRESHOLD
981 sub t8,t8,MEMC_CD_THRESHOLD
984 2: # t8 is now wr, a0 is extra bits
986 sw a1,MEMC_WRNCDLCOR(a0)
993 li a1,MEMC_SD1_MISCDLYCTL_INIT
994 beq v1,1,3f # If rev1:
997 li a1,MEMC_SD_MISCDLYCTL_INIT
1000 sw a1,MEMC_MISCDLYCTL(a0)
1002 li a1,MEMC_SD_CONTROL_INIT0
1003 sw a1,MEMC_CONTROL(a0)
1005 li a1,MEMC_SD_CONTROL_INIT1
1006 sw a1,MEMC_CONTROL(a0)
1008 li a1,MEMC_SD_CONTROL_INIT2
1009 sw a1,MEMC_CONTROL(a0)
1010 lw a1,MEMC_CONTROL(a0)
1011 lw a1,MEMC_CONTROL(a0)
1012 lw a1,MEMC_CONTROL(a0)
1014 li a1,MEMC_SD_CONTROL_INIT2
1015 sw a1,MEMC_CONTROL(a0)
1016 lw a1,MEMC_CONTROL(a0)
1017 lw a1,MEMC_CONTROL(a0)
1018 lw a1,MEMC_CONTROL(a0)
1020 li a1,MEMC_SD_CONTROL_INIT2
1021 sw a1,MEMC_CONTROL(a0)
1022 lw a1,MEMC_CONTROL(a0)
1023 lw a1,MEMC_CONTROL(a0)
1024 lw a1,MEMC_CONTROL(a0)
1026 li a1,MEMC_SD_REFRESH_INIT
1027 sw a1,MEMC_REFRESH(a0)
1029 li a1,MEMC_SD_MODEBUF_INIT
1031 sw a1,MEMC_MODEBUF(a0)
1033 li a1,MEMC_SD_CONTROL_INIT3
1034 sw a1,MEMC_CONTROL(a0)
1036 li a1,MEMC_SD_CONTROL_INIT4
1037 sw a1,MEMC_CONTROL(a0)
1040 1: lw a1,(SBCONFIGOFF + SBIDLOW)(a0)
1041 lw a1,(SBCONFIGOFF + SBIDHIGH)(a0)
1049 /* Special sb_core_reset that makes sure the first time
1050 * clock is enabled, address line 6 is in the state specified
1054 * a1: 0x40 if a6 needs to be 1, 0 otherwise
1062 /* Save return address */
1069 /* Figure out our address */
1072 h0: add t8,ra,24 # This is (h1 - h0)
1074 bne t8,a1,alt_core_reset
1077 /* Set reset while enabling the clock */
1078 li t8,(SBTML_FGC | SBTML_CLK | SBTML_RESET)
1079 h1: sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1083 /* Now pad to 0x40: We want (h2 - h1) == 0x40 and there
1084 * are 5 instructions inbetween them.
1089 /* Set reset while enabling the clock */
1090 li t8,(SBTML_FGC | SBTML_CLK | SBTML_RESET)
1091 h2: sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1094 /* Read back and delay */
1095 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1096 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1097 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1100 li t8, (SBTML_FGC | SBTML_CLK)
1101 sw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1103 /* Read back and delay */
1104 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1105 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1106 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1108 /* Leave clock enabled */
1110 sw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1112 /* Read back and delay */
1113 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1114 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1115 lw t8, (SBCONFIGOFF + SBTMSTATELOW)(a0)
1122 and ra,ra,PHYSADDR_MASK