2 * BCM47XX Sonics SiliconBackplane SDRAM/MEMC core initialization
4 * Copyright (C) 2009, 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.
12 * $Id: sbsdram.S,v 1.43.2.2 2008/11/14 18:18:20 Exp $
24 /* #define DEBUG_SBSDRAM 1 */
27 * Write to prog space so we can see it in
38 #define LATRACE(num, reg) \
39 sw reg,((num & 0xff) << 4)(k0)
43 #define LATRACE(num, reg)
44 #endif /* DEBUG_SBSDRAM */
45 /* Debug macro - write a number to a chipc reg - use it with caution,
46 * it changes k0 and k1 registers.
53 * Register usage within this file:
55 * top ncdlsearch test_mem Xdr_do_init sb_reset_core
57 * v1: corerev - - corerev -
58 * a0: coreptr coreptr - coreptr coreptr
59 * a1: x x x sdr/ddr flag
64 * t2: - wr/strm off wr/strm
65 * t3: - rd/strd rd/strd
71 * s1: wrsum/clkdsum - -
72 * s2: rdsum/pass_countmax - -
73 * s3: gsum/strmmax - -
74 * s4: wrlim/stdmmax - -
75 * s5: rdlim/clkdmax - -
76 * s6: glim/clkdlim - -
80 * k0: trace trace trace - -
81 * k1: trace trace trace - -
98 /* Save return address */
101 /* Scan for a memory controller */
103 1: lw v1,(SBCONFIGOFF + SBIDHIGH)(a0)
104 and a1,v1,SBIDH_CC_MASK
105 srl a1,a1,SBIDH_CC_SHIFT
106 beq a1,MEMC_CORE_ID,foundctrl
108 beq a1,SOCRAM_CORE_ID,foundctrl
111 bne a1,(SBIDH_CC_MASK >> SBIDH_CC_SHIFT),1b
114 /* No memory controller */
121 /* If we are already in RAM, just go and size it */
124 1: li t0,PHYSADDR_MASK
127 blt t0,t1,memprio_szmem
130 /* For socram we don't need any nvram parms, just do a core reset */
132 bne a1,SOCRAM_CORE_ID,read_nvram
137 /* and size memory */
143 /* Find NVRAM (a2) */
144 /* 1: Isolate memc's corerev in v1 */
145 and t2,v1,SBIDH_RCE_MASK
146 srl t2,t2,SBIDH_RCE_SHIFT
147 and v1,v1,SBIDH_RC_MASK
150 /* 1.5: 5365a0 lies about its revision, it is really 1 */
155 li t0,KSEG1ADDR(SI_ENUM_BASE) # Is there a chipcommon core?
156 lw t1,CC_CHIPID(t0) # Get chipid
157 andi t1,CID_ID_MASK # Check chipid
158 bne t1,BCM5365_CHIP_ID,1f
162 /* 2: find_nvram, use the 32MB window */
163 1: li t2,KSEG1ADDR(SI_FLASH2 - NVRAM_SPACE)
178 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
179 li a2,KSEG1ADDR(SI_FLASH1 + 0x1000)
185 li a2,KSEG1ADDR(SI_FLASH1 + 0x400)
191 b memc_init # No NVRAM
195 /* 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 memc core */
207 bnez a2,1f # Already have the parms in
210 /* No nvram parms: assume DDRM16MX16X2 */
214 li t3,MEMC_DDR1_NCDL # If rev1 (4712):
221 andi a3,t0,MEMC_CONFIG_DDR # Is it ddr or sdr?
223 beqz a3,memc_sdr_init
226 /* Initialize DDR SDRAM */
228 beqz t3,ddr_find_ncdl # Do we have ncdl values? (0s)
232 bne t3,t4,break_ddr_ncdl
239 #define pass_count s0
252 /* Initialize counter & accumulators */
258 /* Initialize with default values */
265 lw dll,MEMC_NCDLCTL(a0)
269 beqz dll,memprio_szmem /* If zero, leave the default values */
272 move wrlim,dll /* dll value is lim for wr, rd and g */
279 addi step,dll,15 /* step = (dll + 16 - 1) / 16 */
283 sub wr,zero,dll /* Negate dll as initial value */
287 /* Inner loop: call ddr_do_init to re-initialize and the test mem */
308 LATRACE(0x15, pass_count)
351 /* All done, calculate average values and program them */
353 LATRACE(0x1e, pass_count)
360 div zero,wrsum,pass_count
363 div zero,rdsum,pass_count
366 div zero,gsum,pass_count
372 /* No passing values, panic! (use defaults) */
374 li t3,MEMC_DDR1_NCDL # If rev1:
383 andi t4,t3,0xff # t4: g
384 srl t2,t3,16 # t2: wr
400 beqz t3,sdr_find_ncdl # Do we have ncdl values?
404 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 LATRACE(0x2b, pass_count)
467 LATRACE(0x2c, clkdsum)
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 LATRACE(0x2d, pass_count)
495 LATRACE(0x2e, clkdmax)
496 LATRACE(0x2f, strdmax)
497 LATRACE(0x30, strmmax)
501 blt strd,STRDLIM,strdloop
506 blt strm,STRMLIM,strmloop
509 /* All done, program the new ncdl values */
511 LATRACE(0x31, pass_count)
512 LATRACE(0x32, clkdmax)
513 LATRACE(0x33, strdmax)
514 LATRACE(0x34, strmmax)
516 beqz pass_countmax,1f
525 /* No passing values, panic! (use defaults) */
527 li t3,MEMC_SDR1_NCDL # If rev1:
536 andi t4,t3,0xff # t4: cd
537 srl t2,t3,16 # t2: sm
538 andi t2,t2,3 # sm is 2 bits only
540 andi t3,t3,0xf # sd is 4 bits
546 /* Change the memory priority inversion counter value */
547 /* If an SOCRAM, determine memory size and return */
552 lw t0, MEMC_PRIORINV(a0)
556 sw t0, MEMC_PRIORINV(a0)
558 li t0,KSEG1ADDR(SI_ENUM_BASE) # is there a chipcommon core?
559 lw t1,(SBCONFIGOFF + SBIDHIGH)(t0)
560 and t1,t1,SBIDH_CC_MASK
561 srl t1,t1,SBIDH_CC_SHIFT
564 lw t1,CC_CHIPID(t0) # is this BCM4785 chip?
565 and t1,t1,CID_ID_MASK
566 bne t1,BCM4785_CHIP_ID,0f
568 lw t0,MEMC_PRIORINV(a0) # change PriorInvTim to 2
571 sw t0,MEMC_PRIORINV(a0)
574 lw t0,(SBCONFIGOFF + SBIDHIGH)(a0)
575 and t1,t0,SBIDH_CC_MASK
576 srl t1,t1,SBIDH_CC_SHIFT
577 beq t1,SOCRAM_CORE_ID,1f
582 /* The socram core tells us how much memory there is */
584 lw t1,SR_COREINFO(a0)
585 and t0,t0,SBIDH_RC_MASK /* Find corerev */
588 /* Its corerev >= 1 */
589 and t2,t1,SRCI_SRNB_MASK /* Find number of blocks */
590 srl t2,t2,SRCI_SRNB_SHIFT
591 and t1,t1,SRCI_SRBSZ_MASK /* Find block size */
592 addi t1,t1,SR_BSZ_BASE
600 and t1,t1,SRCI_MS0_MASK
601 add t1,t1,SR_MS0_BASE
610 * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
611 * Returns success (1) or failure (0) in v0
612 * Uses a1, a2, a3 & t5
615 /* Use t4 to generate a semi-random address in the second KB */
621 /* First set: 0 & its negation */
635 /* Second set: 0xaaaaaaaa & its negation */
649 /* Third set: 0x12345678 & its negation */
663 /* Fourth set: the ncdl & its negation */
680 /* Fifth set: the CPU count register & its negation */
702 /* Do an init of the memc core for ddr
703 * a0: memc core pointer
704 * t0: memc config value
705 * t1: memc mode value
706 * t2: memc wr ncdl value
707 * t3: memc rd ncdl value
708 * t4: memc g ncdl value
710 * Uses a1, a2, t7, t8, t9 (here and by calling sb_core_reset)
715 /* Save return address */
721 li a1,MEMC_CONFIG_INIT
723 lui a2, 0x8 # set DQMGate for memc rev 4 or more
725 sw a1,MEMC_CONFIG(a0)
727 li a1,MEMC_DRAMTIM25_INIT # Assume CAS latency of 2.5
728 andi t8,t1,0xf0 # Find out the CAS latency
731 li a1,MEMC_DRAMTIM2_INIT # CAS latency is 2
733 sw a1,MEMC_DRAMTIM(a0)
736 li t8,KSEG1ADDR(SI_ENUM_BASE) # Get package options
737 lw a1,CC_CHIPID(t8) # Get chipid
738 li t9,CID_PKG_MASK # Check package options
740 srl a1,a1,CID_PKG_SHIFT
741 addi t8,SBCONFIGOFF # Get corerev for chipcommon
745 srl t8,SBIDH_RCE_SHIFT
749 bge t8,10,1f # If ccrev is >= 10 use 4bit pkg opt
751 ori a1,8 # else add a bit to the 3bit field
753 beq a1,HDLSIM_PKG_ID,hdlsim # Special case for hdl sim:
756 li t8,KSEG1ADDR(SI_ENUM_BASE) # Get chipid again
758 li t9,BCM5350_CHIP_ID # 5350 ChipID
761 bne t8,t9,notsim # if not 5350keep going
764 bne a1,(8 | HDLSIM5350_PKG_ID),notsim # If 5350, is it (3/4-bit) vsim?
766 #endif /* !BCM_ATE */
769 li a1,MEMC_RDNCDLCOR_SIMINIT # Fixed 0xf6 rdncdl and no inits
770 sw a1,MEMC_RDNCDLCOR(a0) # of wrncdl, dqsgate and miscdly.
776 notsim: andi t8,t3,0xff
777 sll a1,t8,8 # Replicate rd ncdl 4 times
781 li a1,MEMC_RDNCDLCOR_INIT
783 sw a1,MEMC_RDNCDLCOR(a0)
785 li a1,MEMC_1_WRNCDLCOR_INIT # If rev1:
789 li a1,MEMC_WRNCDLCOR_INIT
793 sw a1,MEMC_WRNCDLCOR(a0)
795 li a1,MEMC_DQSGATENCDL_INIT
798 sw a1,MEMC_DQSGATENCDL(a0)
800 li a1,MEMC_1_MISCDLYCTL_INIT # If rev1:
804 li a1,MEMC_MISCDLYCTL_INIT
806 sw a1,MEMC_MISCDLYCTL(a0)
807 #endif /* !BCM_ATE */
810 li a1,MEMC_NCDLCTL_INIT
811 sw a1,MEMC_NCDLCTL(a0)
813 li a1,MEMC_CONTROL_INIT0
814 sw a1,MEMC_CONTROL(a0)
816 li a1,MEMC_CONTROL_INIT1
817 sw a1,MEMC_CONTROL(a0)
819 li a1,MEMC_MODEBUF_INIT0
820 sw a1,MEMC_MODEBUF(a0)
822 li a1,MEMC_CONTROL_INIT2
823 sw a1,MEMC_CONTROL(a0)
825 li a1,MEMC_MODEBUF_INIT1
827 sw a1,MEMC_MODEBUF(a0)
829 li a1,MEMC_CONTROL_INIT3
830 sw a1,MEMC_CONTROL(a0)
832 li a1,MEMC_CONTROL_INIT4
833 sw a1,MEMC_CONTROL(a0)
835 li a1,MEMC_CONTROL_INIT5
836 sw a1,MEMC_CONTROL(a0)
837 lw a1,MEMC_CONTROL(a0)
838 lw a1,MEMC_CONTROL(a0)
839 lw a1,MEMC_CONTROL(a0)
841 li a1,MEMC_CONTROL_INIT5
842 sw a1,MEMC_CONTROL(a0)
843 lw a1,MEMC_CONTROL(a0)
844 lw a1,MEMC_CONTROL(a0)
845 lw a1,MEMC_CONTROL(a0)
847 li a1,MEMC_REFRESH_INIT
848 sw a1,MEMC_REFRESH(a0)
850 li a1,MEMC_MODEBUF_INIT2
852 sw a1,MEMC_MODEBUF(a0)
854 li a1,MEMC_CONTROL_INIT6
855 sw a1,MEMC_CONTROL(a0)
857 li a1,MEMC_CONTROL_INIT7
858 sw a1,MEMC_CONTROL(a0)
860 /* Wait for SDRAM controller to refresh.
864 1: lw a1,(SBCONFIGOFF + SBIDLOW)(a0)
865 lw a1,(SBCONFIGOFF + SBIDHIGH)(a0)
873 /* Do an init of the memc core for sdr
874 * a0: memc core pointer
875 * t0: memc config value
876 * t1: memc mode value
877 * t2: memc strobe mode ncdl value
878 * t3: memc strobe delay ncdl value
879 * t4: memc clock delay ncdl value
881 * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
886 /* Save return address */
892 /* Initialize for SDR SDRAM */
893 li a1,MEMC_SD_CONFIG_INIT
895 sw a1,MEMC_CONFIG(a0)
897 li a1,MEMC_SD_DRAMTIM3_INIT # Assume CAS latency of 3
898 andi t8,t1,0xf0 # Find out the CAS latency
901 li a1,MEMC_SD_DRAMTIM2_INIT # CAS latency is 2
903 sw a1,MEMC_DRAMTIM(a0)
906 ble t8,MEMC_CD_THRESHOLD,1f # if (cd <= MEMC_CD_THRESHOLD) rd = cd
909 li t8,MEMC_CD_THRESHOLD # else rd = MEMC_CD_THRESHOLD
912 sll a1,t8,8 # .. replicate it 4 times
916 li a1,MEMC_SD_RDNCDLCOR_INIT
918 sw a1,MEMC_RDNCDLCOR(a0)
920 li a1,MEMC_SD1_WRNCDLCOR_INIT # rev1
924 li a1,MEMC_SD_WRNCDLCOR_INIT # rev0, 2
927 ble t4,MEMC_CD_THRESHOLD,2f # if (cd <= MEMC_CD_THRESHOLD) wr = 0
930 andi t8,t4,0xff # else wr = cd - MEMC_CD_THRESHOLD
931 sub t8,t8,MEMC_CD_THRESHOLD
934 2: # t8 is now wr, a0 is extra bits
936 sw a1,MEMC_WRNCDLCOR(a0)
943 li a1,MEMC_SD1_MISCDLYCTL_INIT
944 beq v1,1,3f # If rev1:
947 li a1,MEMC_SD_MISCDLYCTL_INIT
950 sw a1,MEMC_MISCDLYCTL(a0)
952 li a1,MEMC_SD_CONTROL_INIT0
953 sw a1,MEMC_CONTROL(a0)
955 li a1,MEMC_SD_CONTROL_INIT1
956 sw a1,MEMC_CONTROL(a0)
958 li a1,MEMC_SD_CONTROL_INIT2
959 sw a1,MEMC_CONTROL(a0)
960 lw a1,MEMC_CONTROL(a0)
961 lw a1,MEMC_CONTROL(a0)
962 lw a1,MEMC_CONTROL(a0)
964 li a1,MEMC_SD_CONTROL_INIT2
965 sw a1,MEMC_CONTROL(a0)
966 lw a1,MEMC_CONTROL(a0)
967 lw a1,MEMC_CONTROL(a0)
968 lw a1,MEMC_CONTROL(a0)
970 li a1,MEMC_SD_CONTROL_INIT2
971 sw a1,MEMC_CONTROL(a0)
972 lw a1,MEMC_CONTROL(a0)
973 lw a1,MEMC_CONTROL(a0)
974 lw a1,MEMC_CONTROL(a0)
976 li a1,MEMC_SD_REFRESH_INIT
977 sw a1,MEMC_REFRESH(a0)
979 li a1,MEMC_SD_MODEBUF_INIT
981 sw a1,MEMC_MODEBUF(a0)
983 li a1,MEMC_SD_CONTROL_INIT3
984 sw a1,MEMC_CONTROL(a0)
986 li a1,MEMC_SD_CONTROL_INIT4
987 sw a1,MEMC_CONTROL(a0)
990 1: lw a1,(SBCONFIGOFF + SBIDLOW)(a0)
991 lw a1,(SBCONFIGOFF + SBIDHIGH)(a0)
999 /* Special sb_core_reset that makes sure the first time
1000 * clock is enabled, address line 6 is in the state specified
1004 * a1: 0x40 if a6 needs to be 1, 0 otherwise
1012 /* Save return address */
1019 /* Figure out our address */
1022 h0: add t8,ra,24 # This is (h1 - h0)
1024 bne t8,a1,alt_core_reset
1027 /* Set reset while enabling the clock */
1028 li t8,(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET)
1029 h1: sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1033 /* Now pad to 0x40: We want (h2 - h1) == 0x40 and there
1034 * are 5 instructions inbetween them.
1039 /* Set reset while enabling the clock */
1040 li t8,(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET)
1041 h2: sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1044 /* Read back and delay */
1045 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1046 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1047 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1050 li t8,((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)
1051 sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1053 /* Read back and delay */
1054 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1055 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1056 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1058 /* Leave clock enabled */
1059 li t8,(SICF_CLOCK_EN << SBTML_SICF_SHIFT)
1060 sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1062 /* Read back and delay */
1063 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1064 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1065 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1072 and ra,ra,PHYSADDR_MASK