2 * BCM47XX Sonics SiliconBackplane SDRAM/MEMC core initialization
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: sbsdram.S,v 1.45 2008-11-14 17:51:32 $
30 /* #define DEBUG_SBSDRAM 1 */
33 * Write to prog space so we can see it in
44 #define LATRACE(num, reg) \
45 sw reg,((num & 0xff) << 4)(k0)
49 #define LATRACE(num, reg)
50 #endif /* DEBUG_SBSDRAM */
51 /* Debug macro - write a number to a chipc reg - use it with caution,
52 * it changes k0 and k1 registers.
59 #define TRACEINIT(x) \
60 li k0,KSEG1ADDR(0x18000040); \
79 * Register usage within this file:
81 * top ncdlsearch test_mem Xdr_do_init sb_reset_core
83 * v1: corerev - - corerev -
84 * a0: coreptr coreptr - coreptr coreptr
85 * a1: x x x sdr/ddr flag
90 * t2: - wr/strm off wr/strm
91 * t3: - rd/strd rd/strd
97 * s1: wrsum/clkdsum - -
98 * s2: rdsum/pass_countmax - -
99 * s3: gsum/strmmax - -
100 * s4: wrlim/stdmmax - -
101 * s5: rdlim/clkdmax - -
102 * s6: glim/clkdlim - -
106 * k0: trace trace trace - -
107 * k1: trace trace trace - -
124 /* Save return address */
127 /* Scan for a memory controller */
129 1: lw v1,(SBCONFIGOFF + SBIDHIGH)(a0)
130 and a1,v1,SBIDH_CC_MASK
131 srl a1,a1,SBIDH_CC_SHIFT
132 beq a1,MEMC_CORE_ID,foundctrl
134 beq a1,SOCRAM_CORE_ID,foundctrl
137 bne a1,(SBIDH_CC_MASK >> SBIDH_CC_SHIFT),1b
140 /* No memory controller */
147 /* If we are already in RAM, just go and size it */
150 1: li t0,PHYSADDR_MASK
153 blt t0,t1,memprio_szmem
156 /* For socram we don't need any nvram parms, just do a core reset */
158 bne a1,SOCRAM_CORE_ID,read_nvram
163 /* and size memory */
169 /* Find NVRAM (a2) */
170 /* 1: Isolate memc's corerev in v1 */
171 and t2,v1,SBIDH_RCE_MASK
172 srl t2,t2,SBIDH_RCE_SHIFT
173 and v1,v1,SBIDH_RC_MASK
176 /* 1.5: 5365a0 lies about its revision, it is really 1 */
181 li t0,KSEG1ADDR(SI_ENUM_BASE) # Is there a chipcommon core?
182 lw t1,CC_CHIPID(t0) # Get chipid
183 andi t1,CID_ID_MASK # Check chipid
184 bne t1,BCM5365_CHIP_ID,1f
188 /* 2: find_nvram, use the 32MB window */
189 1: li t2,KSEG1ADDR(SI_FLASH2 - MAX_NVRAM_SPACE)
204 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
205 li a2,KSEG1ADDR(SI_FLASH1 + 0x1000)
211 li a2,KSEG1ADDR(SI_FLASH1 + 0x400)
217 b memc_init # No NVRAM
221 /* Get SDRAM parameters (t0, t1, t2) from NVRAM (a2) */
223 lw t0,8(a2) # SDRAM init
226 andi t1,t2,0xffff # SDRAM config
227 srl t2,16 # SDRAM refresh
228 lw t3,16(a2) # SDRAM ncdl
231 /* Initialize memc core */
233 bnez a2,1f # Already have the parms in
236 /* No nvram parms: assume DDRM16MX16X2 */
240 li t3,MEMC_DDR1_NCDL # If rev1 (4712):
247 andi a3,t0,MEMC_CONFIG_DDR # Is it ddr or sdr?
249 beqz a3,memc_sdr_init
252 /* Initialize DDR SDRAM */
254 beqz t3,ddr_find_ncdl # Do we have ncdl values? (0s)
258 bne t3,t4,break_ddr_ncdl
265 #define pass_count s0
278 /* Initialize counter & accumulators */
284 /* Initialize with default values */
291 lw dll,MEMC_NCDLCTL(a0)
295 beqz dll,memprio_szmem /* If zero, leave the default values */
298 move wrlim,dll /* dll value is lim for wr, rd and g */
305 addi step,dll,15 /* step = (dll + 16 - 1) / 16 */
309 sub wr,zero,dll /* Negate dll as initial value */
313 /* Inner loop: call ddr_do_init to re-initialize and the test mem */
334 LATRACE(0x15, pass_count)
377 /* All done, calculate average values and program them */
379 LATRACE(0x1e, pass_count)
386 div zero,wrsum,pass_count
389 div zero,rdsum,pass_count
392 div zero,gsum,pass_count
398 /* No passing values, panic! (use defaults) */
400 li t3,MEMC_DDR1_NCDL # If rev1:
409 andi t4,t3,0xff # t4: g
410 srl t2,t3,16 # t2: wr
426 beqz t3,sdr_find_ncdl # Do we have ncdl values?
430 bne t3,t4,break_sdr_ncdl
437 #define pass_count s0
439 #define pass_countmax s2
451 #define CLKDLIM_IC 256
453 /* Initialize counter & saved values */
454 move pass_countmax,zero
459 and strm,t0,0x2000 /* Test for internal clock (Using strm as a temp) */
463 li clkdlim,CLKDLIM_IC
465 move strm,zero /* strm loop */
473 /* Inner loop: call sdr_do_init to re-initialize and the test mem */
491 add clkdsum,clkdsum,clkd
492 LATRACE(0x2b, pass_count)
493 LATRACE(0x2c, clkdsum)
498 bnez pass_count,clkdout # End of passing range, leave clkd loop
503 blt clkd,clkdlim,clkdloop
507 /* If no passing values, skip to next strm */
508 beqz pass_count,nextstrm
511 /* If this is a new max, Save the values */
512 ble pass_count,pass_countmax,nextstrd
515 move pass_countmax,pass_count
516 div zero,clkdsum,pass_count
520 LATRACE(0x2d, pass_count)
521 LATRACE(0x2e, clkdmax)
522 LATRACE(0x2f, strdmax)
523 LATRACE(0x30, strmmax)
527 blt strd,STRDLIM,strdloop
532 blt strm,STRMLIM,strmloop
535 /* All done, program the new ncdl values */
537 LATRACE(0x31, pass_count)
538 LATRACE(0x32, clkdmax)
539 LATRACE(0x33, strdmax)
540 LATRACE(0x34, strmmax)
542 beqz pass_countmax,1f
551 /* No passing values, panic! (use defaults) */
553 li t3,MEMC_SDR1_NCDL # If rev1:
562 andi t4,t3,0xff # t4: cd
563 srl t2,t3,16 # t2: sm
564 andi t2,t2,3 # sm is 2 bits only
566 andi t3,t3,0xf # sd is 4 bits
572 /* Change the memory priority inversion counter value */
573 /* If an SOCRAM, determine memory size and return */
578 lw t0, MEMC_PRIORINV(a0)
582 sw t0, MEMC_PRIORINV(a0)
584 li t0,KSEG1ADDR(SI_ENUM_BASE) # is there a chipcommon core?
585 lw t1,(SBCONFIGOFF + SBIDHIGH)(t0)
586 and t1,t1,SBIDH_CC_MASK
587 srl t1,t1,SBIDH_CC_SHIFT
590 lw t1,CC_CHIPID(t0) # is this BCM4785 chip?
591 and t1,t1,CID_ID_MASK
592 bne t1,BCM4785_CHIP_ID,0f
594 lw t0,MEMC_PRIORINV(a0) # change PriorInvTim to 2
597 sw t0,MEMC_PRIORINV(a0)
600 lw t0,(SBCONFIGOFF + SBIDHIGH)(a0)
601 and t1,t0,SBIDH_CC_MASK
602 srl t1,t1,SBIDH_CC_SHIFT
603 beq t1,SOCRAM_CORE_ID,1f
608 /* The socram core tells us how much memory there is */
610 lw t1,SR_COREINFO(a0)
611 and t0,t0,SBIDH_RC_MASK /* Find corerev */
614 /* Its corerev >= 1 */
615 and t2,t1,SRCI_SRNB_MASK /* Find number of blocks */
616 srl t2,t2,SRCI_SRNB_SHIFT
617 and t1,t1,SRCI_SRBSZ_MASK /* Find block size */
618 addi t1,t1,SR_BSZ_BASE
626 and t1,t1,SRCI_MS0_MASK
627 add t1,t1,SR_MS0_BASE
636 * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
637 * Returns success (1) or failure (0) in v0
638 * Uses a1, a2, a3 & t5
641 /* Use t4 to generate a semi-random address in the second KB */
647 /* First set: 0 & its negation */
661 /* Second set: 0xaaaaaaaa & its negation */
675 /* Third set: 0x12345678 & its negation */
689 /* Fourth set: the ncdl & its negation */
706 /* Fifth set: the CPU count register & its negation */
728 /* Do an init of the memc core for ddr
729 * a0: memc core pointer
730 * t0: memc config value
731 * t1: memc mode value
732 * t2: memc wr ncdl value
733 * t3: memc rd ncdl value
734 * t4: memc g ncdl value
736 * Uses a1, a2, t7, t8, t9 (here and by calling sb_core_reset)
741 /* Save return address */
747 li a1,MEMC_CONFIG_INIT
749 lui a2, 0x8 # set DQMGate for memc rev 4 or more
751 sw a1,MEMC_CONFIG(a0)
753 li a1,MEMC_DRAMTIM25_INIT # Assume CAS latency of 2.5
754 andi t8,t1,0xf0 # Find out the CAS latency
757 li a1,MEMC_DRAMTIM2_INIT # CAS latency is 2
759 sw a1,MEMC_DRAMTIM(a0)
762 li t8,KSEG1ADDR(SI_ENUM_BASE) # Get package options
763 lw a1,CC_CHIPID(t8) # Get chipid
764 li t9,CID_PKG_MASK # Check package options
766 srl a1,a1,CID_PKG_SHIFT
767 addi t8,SBCONFIGOFF # Get corerev for chipcommon
771 srl t8,SBIDH_RCE_SHIFT
775 bge t8,10,1f # If ccrev is >= 10 use 4bit pkg opt
777 ori a1,8 # else add a bit to the 3bit field
779 beq a1,HDLSIM_PKG_ID,hdlsim # Special case for hdl sim:
782 li t8,KSEG1ADDR(SI_ENUM_BASE) # Get chipid again
784 li t9,BCM5350_CHIP_ID # 5350 ChipID
787 bne t8,t9,notsim # if not 5350keep going
790 bne a1,(8 | HDLSIM5350_PKG_ID),notsim # If 5350, is it (3/4-bit) vsim?
792 #endif /* !BCM_ATE */
795 li a1,MEMC_RDNCDLCOR_SIMINIT # Fixed 0xf6 rdncdl and no inits
796 sw a1,MEMC_RDNCDLCOR(a0) # of wrncdl, dqsgate and miscdly.
802 notsim: andi t8,t3,0xff
803 sll a1,t8,8 # Replicate rd ncdl 4 times
807 li a1,MEMC_RDNCDLCOR_INIT
809 sw a1,MEMC_RDNCDLCOR(a0)
811 li a1,MEMC_1_WRNCDLCOR_INIT # If rev1:
815 li a1,MEMC_WRNCDLCOR_INIT
819 sw a1,MEMC_WRNCDLCOR(a0)
821 li a1,MEMC_DQSGATENCDL_INIT
824 sw a1,MEMC_DQSGATENCDL(a0)
826 li a1,MEMC_1_MISCDLYCTL_INIT # If rev1:
830 li a1,MEMC_MISCDLYCTL_INIT
832 sw a1,MEMC_MISCDLYCTL(a0)
833 #endif /* !BCM_ATE */
836 li a1,MEMC_NCDLCTL_INIT
837 sw a1,MEMC_NCDLCTL(a0)
839 li a1,MEMC_CONTROL_INIT0
840 sw a1,MEMC_CONTROL(a0)
842 li a1,MEMC_CONTROL_INIT1
843 sw a1,MEMC_CONTROL(a0)
845 li a1,MEMC_MODEBUF_INIT0
846 sw a1,MEMC_MODEBUF(a0)
848 li a1,MEMC_CONTROL_INIT2
849 sw a1,MEMC_CONTROL(a0)
851 li a1,MEMC_MODEBUF_INIT1
853 sw a1,MEMC_MODEBUF(a0)
855 li a1,MEMC_CONTROL_INIT3
856 sw a1,MEMC_CONTROL(a0)
858 li a1,MEMC_CONTROL_INIT4
859 sw a1,MEMC_CONTROL(a0)
861 li a1,MEMC_CONTROL_INIT5
862 sw a1,MEMC_CONTROL(a0)
863 lw a1,MEMC_CONTROL(a0)
864 lw a1,MEMC_CONTROL(a0)
865 lw a1,MEMC_CONTROL(a0)
867 li a1,MEMC_CONTROL_INIT5
868 sw a1,MEMC_CONTROL(a0)
869 lw a1,MEMC_CONTROL(a0)
870 lw a1,MEMC_CONTROL(a0)
871 lw a1,MEMC_CONTROL(a0)
873 li a1,MEMC_REFRESH_INIT
874 sw a1,MEMC_REFRESH(a0)
876 li a1,MEMC_MODEBUF_INIT2
878 sw a1,MEMC_MODEBUF(a0)
880 li a1,MEMC_CONTROL_INIT6
881 sw a1,MEMC_CONTROL(a0)
883 li a1,MEMC_CONTROL_INIT7
884 sw a1,MEMC_CONTROL(a0)
886 /* Wait for SDRAM controller to refresh.
890 1: lw a1,(SBCONFIGOFF + SBIDLOW)(a0)
891 lw a1,(SBCONFIGOFF + SBIDHIGH)(a0)
899 /* Do an init of the memc core for sdr
900 * a0: memc core pointer
901 * t0: memc config value
902 * t1: memc mode value
903 * t2: memc strobe mode ncdl value
904 * t3: memc strobe delay ncdl value
905 * t4: memc clock delay ncdl value
907 * Uses a1, t7, t8, t9 (here and by calling sb_core_reset)
912 /* Save return address */
918 /* Initialize for SDR SDRAM */
919 li a1,MEMC_SD_CONFIG_INIT
921 sw a1,MEMC_CONFIG(a0)
923 li a1,MEMC_SD_DRAMTIM3_INIT # Assume CAS latency of 3
924 andi t8,t1,0xf0 # Find out the CAS latency
927 li a1,MEMC_SD_DRAMTIM2_INIT # CAS latency is 2
929 sw a1,MEMC_DRAMTIM(a0)
932 ble t8,MEMC_CD_THRESHOLD,1f # if (cd <= MEMC_CD_THRESHOLD) rd = cd
935 li t8,MEMC_CD_THRESHOLD # else rd = MEMC_CD_THRESHOLD
938 sll a1,t8,8 # .. replicate it 4 times
942 li a1,MEMC_SD_RDNCDLCOR_INIT
944 sw a1,MEMC_RDNCDLCOR(a0)
946 li a1,MEMC_SD1_WRNCDLCOR_INIT # rev1
950 li a1,MEMC_SD_WRNCDLCOR_INIT # rev0, 2
953 ble t4,MEMC_CD_THRESHOLD,2f # if (cd <= MEMC_CD_THRESHOLD) wr = 0
956 andi t8,t4,0xff # else wr = cd - MEMC_CD_THRESHOLD
957 sub t8,t8,MEMC_CD_THRESHOLD
960 2: # t8 is now wr, a0 is extra bits
962 sw a1,MEMC_WRNCDLCOR(a0)
969 li a1,MEMC_SD1_MISCDLYCTL_INIT
970 beq v1,1,3f # If rev1:
973 li a1,MEMC_SD_MISCDLYCTL_INIT
976 sw a1,MEMC_MISCDLYCTL(a0)
978 li a1,MEMC_SD_CONTROL_INIT0
979 sw a1,MEMC_CONTROL(a0)
981 li a1,MEMC_SD_CONTROL_INIT1
982 sw a1,MEMC_CONTROL(a0)
984 li a1,MEMC_SD_CONTROL_INIT2
985 sw a1,MEMC_CONTROL(a0)
986 lw a1,MEMC_CONTROL(a0)
987 lw a1,MEMC_CONTROL(a0)
988 lw a1,MEMC_CONTROL(a0)
990 li a1,MEMC_SD_CONTROL_INIT2
991 sw a1,MEMC_CONTROL(a0)
992 lw a1,MEMC_CONTROL(a0)
993 lw a1,MEMC_CONTROL(a0)
994 lw a1,MEMC_CONTROL(a0)
996 li a1,MEMC_SD_CONTROL_INIT2
997 sw a1,MEMC_CONTROL(a0)
998 lw a1,MEMC_CONTROL(a0)
999 lw a1,MEMC_CONTROL(a0)
1000 lw a1,MEMC_CONTROL(a0)
1002 li a1,MEMC_SD_REFRESH_INIT
1003 sw a1,MEMC_REFRESH(a0)
1005 li a1,MEMC_SD_MODEBUF_INIT
1007 sw a1,MEMC_MODEBUF(a0)
1009 li a1,MEMC_SD_CONTROL_INIT3
1010 sw a1,MEMC_CONTROL(a0)
1012 li a1,MEMC_SD_CONTROL_INIT4
1013 sw a1,MEMC_CONTROL(a0)
1016 1: lw a1,(SBCONFIGOFF + SBIDLOW)(a0)
1017 lw a1,(SBCONFIGOFF + SBIDHIGH)(a0)
1025 /* Special sb_core_reset that makes sure the first time
1026 * clock is enabled, address line 6 is in the state specified
1030 * a1: 0x40 if a6 needs to be 1, 0 otherwise
1038 /* Save return address */
1045 /* Figure out our address */
1048 h0: add t8,ra,24 # This is (h1 - h0)
1050 bne t8,a1,alt_core_reset
1053 /* Set reset while enabling the clock */
1054 li t8,(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET)
1055 h1: sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1059 /* Now pad to 0x40: We want (h2 - h1) == 0x40 and there
1060 * are 5 instructions inbetween them.
1065 /* Set reset while enabling the clock */
1066 li t8,(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | SBTML_RESET)
1067 h2: sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1070 /* Read back and delay */
1071 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1072 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1073 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1076 li t8,((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)
1077 sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1079 /* Read back and delay */
1080 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1081 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1082 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1084 /* Leave clock enabled */
1085 li t8,(SICF_CLOCK_EN << SBTML_SICF_SHIFT)
1086 sw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1088 /* Read back and delay */
1089 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1090 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1091 lw t8,(SBCONFIGOFF + SBTMSTATELOW)(a0)
1098 and ra,ra,PHYSADDR_MASK