diff options
-rw-r--r-- | src/soc/imgtec/pistachio/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/imgtec/pistachio/ddr2_init.c | 669 | ||||
-rw-r--r-- | src/soc/imgtec/pistachio/include/soc/ddr_init.h | 25 | ||||
-rw-r--r-- | src/soc/imgtec/pistachio/romstage.c | 10 |
4 files changed, 704 insertions, 1 deletions
diff --git a/src/soc/imgtec/pistachio/Makefile.inc b/src/soc/imgtec/pistachio/Makefile.inc index 6dc18f3b5e..0a3d456de3 100644 --- a/src/soc/imgtec/pistachio/Makefile.inc +++ b/src/soc/imgtec/pistachio/Makefile.inc @@ -38,6 +38,7 @@ ramstage-y += monotonic_timer.c ramstage-y += soc.c romstage-y += cbmem.c +romstage-y += ddr2_init.c romstage-y += romstage.c romstage-y += monotonic_timer.c diff --git a/src/soc/imgtec/pistachio/ddr2_init.c b/src/soc/imgtec/pistachio/ddr2_init.c new file mode 100644 index 0000000000..0ffa2bc21f --- /dev/null +++ b/src/soc/imgtec/pistachio/ddr2_init.c @@ -0,0 +1,669 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <stdint.h> +#include <arch/cpu.h> +#include <delay.h> +#include <arch/io.h> +#include <soc/ddr_init.h> +#include <timer.h> + +#define MAX_WAIT_MICROS 100000 + +#define TOPLEVEL_REGS 0xB8149000 + +#define DDR_CTRL_OFFSET (0x0020) +#define DDR_CLK_EN_MASK (0x00000002) +#define DDR_CLK_EN_SHIFT (1) +#define DDR_CLK_EN_LENGTH (1) + +#define DDR_PCTL 0xB8180000 +#define DDR_PCTL_TOGCNT1U_OFFSET (0x00C0) +#define DDR_PCTL_TINIT_OFFSET (0x00C4) +#define DDR_PCTL_TRSTH_OFFSET (0x00C8) +#define DDR_PCTL_TOGG_CNTR_100NS_OFFSET (0x00CC) +#define DDR_PCTL_MCFG_OFFSET (0x0080) +#define DDR_PCTL_MCFG1_OFFSET (0x007C) +#define DDR_PCTL_MSTAT_OFFSET (0x0088) +#define DDR_PCTL_DFISTAT0_OFFSET (0x02C0) +#define DDR_PCTL_POWCTL_OFFSET (0x0044) +#define DDR_PCTL_POWSTAT_OFFSET (0x0048) +#define DDR_PCTL_DTUAWDT_OFFSET (0x00B0) +#define DDR_PCTL_TREFI_OFFSET (0x00D0) +#define DDR_PCTL_TMRD_OFFSET (0x00D4) +#define DDR_PCTL_TRFC_OFFSET (0x00D8) +#define DDR_PCTL_TRP_OFFSET (0x00DC) +#define DDR_PCTL_TAL_OFFSET (0x00E4) +#define DDR_PCTL_TCL_OFFSET (0x00E8) +#define DDR_PCTL_TCWL_OFFSET (0x00EC) +#define DDR_PCTL_TRAS_OFFSET (0x00F0) +#define DDR_PCTL_TRC_OFFSET (0x00F4) +#define DDR_PCTL_TRCD_OFFSET (0x00F8) +#define DDR_PCTL_TRRD_OFFSET (0x00FC) +#define DDR_PCTL_TRTP_OFFSET (0x0100) +#define DDR_PCTL_TWR_OFFSET (0x0104) +#define DDR_PCTL_TWTR_OFFSET (0x0108) +#define DDR_PCTL_TEXSR_OFFSET (0x010C) +#define DDR_PCTL_TXP_OFFSET (0x0110) +#define DDR_PCTL_TDQS_OFFSET (0x0120) +#define DDR_PCTL_TXPDLL_OFFSET (0x0114) +#define DDR_PCTL_TRTW_OFFSET (0x00E0) +#define DDR_PCTL_TCKE_OFFSET (0x012C) +#define DDR_PCTL_TMOD_OFFSET (0x0130) +#define DDR_PCTL_TCKESR_OFFSET (0x0140) +#define DDR_PCTL_SCFG_OFFSET (0x0000) +#define DDR_PCTL_DFIWRLAT_OFFSET (0x0254) +#define DDR_PCTL_DFITRDDATAEN_OFFSET (0x0260) +#define DDR_PCTL_DFITPHYWRDATA_OFFSET (0x0250) +#define DDR_PCTL_DFITPHYRDLAT_OFFSET (0x0264) +#define DDR_PCTL_SCTL_OFFSET (0x0004) +#define DDR_PCTL_STAT_OFFSET (0x0008) +#define DDR_PCTL_DFISTCFG0_OFFSET (0x02C4) +#define DDR_PCTL_DFISTCFG1_OFFSET (0x02C8) +#define DDR_PCTL_DFISTCFG2_OFFSET (0x02D8) +#define DDR_PCTL_DFILPCFG0_OFFSET (0x02F0) +#define DDR_PCTL_DFIODTCFG_OFFSET (0x0244) +#define DDR_PCTL_DFIODTCFG1_OFFSET (0x0248) +#define DDR_PCTL_MCMD_OFFSET (0x0040) +#define DDR_PCTL_DFIUPDCFG_OFFSET (0x0290) +#define DDR_PCTL_CCFG_OFFSET (0x0480) +#define DDR_PCTL_DCFG_OFFSET (0x0484) +#define DDR_PCTL_PCFG0_OFFSET (0x0400) +#define DDR_PCTL_DTUWACTL_OFFSET (0x0200) +#define DDR_PCTL_DTURACTL_OFFSET (0x0204) +#define DDR_PCTL_DTUCFG_OFFSET (0x0208) +#define DDR_PCTL_DTUECTL_OFFSET (0x020C) +#define DDR_PCTL_DTUWD0_OFFSET (0x0210) +#define DDR_PCTL_DTUWD1_OFFSET (0x0214) +#define DDR_PCTL_DTUWD2_OFFSET (0x0218) +#define DDR_PCTL_DTUWD3_OFFSET (0x021C) +#define DDR_PCTL_CCFG1_OFFSET (0x048C) + +#define DDR_PHY 0xB8180800 +#define DDRPHY_DCR_OFFSET (0x0030) +#define DDRPHY_MR_OFFSET (0x0040) +#define DDRPHY_EMR_OFFSET (0x0044) +#define DDRPHY_EMR2_OFFSET (0x0048) +#define DDRPHY_DSGCR_OFFSET (0x002C) +#define DDRPHY_DTPR0_OFFSET (0x0034) +#define DDRPHY_DTPR1_OFFSET (0x0038) +#define DDRPHY_DTPR2_OFFSET (0x003C) +#define DDRPHY_PTR0_OFFSET (0x0018) +#define DDRPHY_PTR1_OFFSET (0x001C) +#define DDRPHY_PGSR_OFFSET (0x000C) +#define DDRPHY_PIR_OFFSET (0x0004) +#define DDRPHY_BISTRR_OFFSET (0x0100) +#define DDRPHY_BISTWCR_OFFSET (0x010C) +#define DDRPHY_BISTAR0_OFFSET (0x0114) +#define DDRPHY_BISTAR1_OFFSET (0x0118) +#define DDRPHY_BISTAR2_OFFSET (0x011C) +#define DDRPHY_BISTGSR_OFFSET (0x0124) +#define DDRPHY_BISTUDPR_OFFSET (0x0120) +#define DDRPHY_DLLGCR_OFFSET (0x0010) + +#define BL8 1 +#define UMCTL_INIT 0 + +#define DDR_TIMEOUT_VALUE_US 100000 + +static int wait_for_completion(u32 reg, u32 exp_val) +{ + struct stopwatch sw; + + stopwatch_init_usecs_expire(&sw, DDR_TIMEOUT_VALUE_US); + while (read32(reg) != exp_val) { + if (stopwatch_expired(&sw)) + return DDR_TIMEOUT; + } + return 0; +} + +/* + * Configuration for the Winbond W972GG6JB-25 part using + * Synopsys DDR uMCTL and DDR Phy + */ +int init_ddr2(void) +{ + + u32 exp_val; + u32 mr, md_dllrst, emr, emr2, emr3; + + /* + * Reset the AXI bridge and DDR Controller in case any spurious + * writes have already happened to DDR - note must be done together, + * not sequentially + */ + write32(TOPLEVEL_REGS + DDR_CTRL_OFFSET, 0x00000000); + write32(TOPLEVEL_REGS + DDR_CTRL_OFFSET, 0x0000000F); + + /* + * Dummy read to fence the access between the reset above + * and thw DDR controller writes below + */ + read32(TOPLEVEL_REGS + DDR_CTRL_OFFSET); + + /* Timings for 400MHz + * therefore 200MHz (5ns) uMCTL (Internal) Rate + */ + + /* TOGCNT1U: Toggle Counter 1U Register: 1us 200h C8h */ + write32(DDR_PCTL + DDR_PCTL_TOGCNT1U_OFFSET, 0x000000C8); + /* TINIT: t_init Timing Register: at least 200us 200h C8h */ + write32(DDR_PCTL + DDR_PCTL_TINIT_OFFSET, 0x000000C8); + /* TRSTH: Reset High Time Register DDR3 ONLY */ + write32(DDR_PCTL + DDR_PCTL_TRSTH_OFFSET, 0x00000000); + /* TOGCNT100N: Toggle Counter 100N Register: 20d, 14h*/ + write32(DDR_PCTL + DDR_PCTL_TOGG_CNTR_100NS_OFFSET, 0x00000014); + /* DTUAWDT DTU Address Width Register + * 1:0 column_addr_width Def 10 - 7 3 10 bits + * 4:3 bank_addr_width Def 3 - 2 1 3 bits (8 bank) + * 7:6 row_addr_width Def 14 - 13 1 3 bits + * 10:9 number_ranks Def 1 - 1 0 0 1 Rank + */ + write32(DDR_PCTL + DDR_PCTL_DTUAWDT_OFFSET, 0x0000004B); + /* MCFG + * 0 BL 0 = 4 1 = 8 + * 1 RDRIMM 0 + * 2 BL8 Burst Terminate 0 + * 3 2T = 0 + * 4 Multi Rank 0 + * 5 DDR3 En 0 + * 6 LPDDR S4 En + * 7 BST En 0, 1 for LPDDR2/3 + * 15:8 Power down Idle, passed by argument + * 16 Power Down Type, passed by argument + * 17 Power Down Exit 0 = slow, 1 = fast, pba + * 19:18 tFAW 45ns = 9 clk 5*2 -1 1h + * 21:20 mDDR/LPDDR2 BL 0 + * 23:22 mDDR/LPDDR2 Enable 0 + * 31:24 mDDR/LPDDR2/3 Dynamic Clock Stop 0 + */ + write32(DDR_PCTL + DDR_PCTL_MCFG_OFFSET, + 0x00060000 | (BL8 ? 0x1 : 0x0)); + /* MCFG1: Memory Configuration-1 Register + * c7:0 sr_idle Self Refresh Idle Entery 32 * nclks 14h, set 0 for BUB + * 10:8 Fine tune MCFG.19:18 -1 + * 15:11 Reserved + * 23:16 Hardware Idle Period NA 0 + * 30:24 Reserved + * 31 c_active_in_pin exit auto clk stop NA 0 + */ + write32(DDR_PCTL + DDR_PCTL_MCFG1_OFFSET, 0x00000100); + /* DCR DRAM Config + * 2:0 SDRAM => DDR2 2 + * 3 DDR 8 Bank 1 + * 6:4 Primary DQ DDR3 Only 0 + * 7 Multi-Purpose Register DDR3 Only 0 + * 9:8 DDRTYPE LPDDR2 00 + * 26:10 Reserved + * 27 NOSRA No Simultaneous Rank Access 0 + * 28 DDR 2T 0 + * 29 UDIMM NA 0 + * 30 RDIMM NA 0 + * 31 TPD LPDDR2 0 + */ + write32(DDR_PHY + DDRPHY_DCR_OFFSET, 0x0000000A); + /* Generate to use with PHY and PCTL */ + md_dllrst = 0x0B62 | (BL8 ? 0x1 : 0x0); + /* Generate to use with PHY and PCTL + * 2:0 BL 8 011 + * 3 BT Sequential 0 Interleaved 1 = 0 + * 6:4 CL 6 + * 7 TM Normal 0 + * 8 DLL Reset 1 (self Clearing) + * 11:9 WR 15 ns 6 (101) + * 12 PD Slow 1 Fast 0 0 + */ + mr = 0x0A62 | (BL8 ? 0x1 : 0x0); + /* MR0 : MR Register, bits 12:0 imported dfrom MR + * 12:0 md_dllrst + * c15:13 RSVD RSVD + * 31:16 Reserved + */ + write32(DDR_PHY + DDRPHY_MR_OFFSET, 0x00000000 | mr); + /* Generate to use with PHY and PCTL + * 0 DE DLL Enable 0 Disable 1 + * 1 DIC Output Driver Imp Ctl 0 Full, 1 Half + * 6,2 ODT 0 Disable, 1 75R, 2 150R, 3 50R = 1 + * 5:3 AL = 0 + * 9:7 OCD = 0 + * 10 DQS 0 diff, 1 single = 0 + * 11 RDQS NA 0 + * 12 QOFF Normal mode 0 + */ + emr = 0x4; + /* MR1 : EMR Register + * 12:0 EMR1 + * 15:13 RSVD + * 31:16 Reserved + */ + write32(DDR_PHY + DDRPHY_EMR_OFFSET, 0x00000000 | emr); + + /* Generate to use with PHY and PCTL + * 2:0 PASR, NA 000 + * 3 DDC NA 0 + * 6:4 RSVD + * 7 SFR 0 + */ + emr2 = 0x0; + /* MR2 : EMR2 Register + * 7:0 EMR2 + * 15:8 RSVD + * 31:16 Reserved + */ + write32(DDR_PHY + DDRPHY_EMR2_OFFSET, 0x00000000 | emr2); + emr3 = 0x0; + /* DSGCR + * 0 PUREN Def 1 + * 1 BDISEN Def 1 + * 2 ZUEN Def 1 + * 3 LPIOPD DEf 1 0 + * 4 LPDLLPD DEf 1 0 + * 7:5 DQSGX DQS Extention 000 + * 10:8 DQSGE DQS Early Gate + * 11 NOBUB No Bubbles, adds latency 0 + * 12 FXDLAT Fixed Read Latency 0 + * 15:13 Reserved + * 19:16 CKEPDD CKE Power Down 0000 + * 23:20 ODTPDD ODT Power Down 0000 + * 24 NL2PD Power Down Non LPDDR2 pins 0 + * 25 NL2OE Output Enable Non LPDDR2 pins 1 + * 26 TPDPD LPDDR Only 0 + * 27 TPDOE LPDDR Only 0 + * 28 CKOE Output Enable Clk's 1 + * 29 ODTOE Output Enable ODT 1 + * 30 RSTOE RST# Output Enable 1 + * 31 CKEOE CKE Output Enable 1 + */ + write32(DDR_PHY + DDRPHY_DSGCR_OFFSET, 0xF2000007); + /* DTPR0 : DRAM Timing Params 0 + * 1:0 tMRD 2 + * 4:2 tRTP 3 + * 7:5 tWTR 3 + * 11:8 tRP 6 + * 15:12 tRCD 6 + * 20:16 tRAS 18 + * 24:21 tRRD 4 + * 30:25 tRC 24 (23) + * 31 tCCD 0 BL/2 Cas to Cas + */ + write32(DDR_PHY + DDRPHY_DTPR0_OFFSET, 0x3092666E); + /* DTPR1 : DRAM Timing Params 1 + * 1:0 ODT On/Off Del Std 0 + * 2 tRTW Rd2Wr Del 0 std 1 +1 0 + * 8:3 tFAW 4 Bank Act 45ns = 18 18 + * 10:9 tMOD DDR3 Only 0 + * 11 tRTODT DDR3 Only 0 + * 15:12 Reserved + * 23:16 tRFC 195ns 78 def 131 78d + * 26:24 tDQSCK LPDDR2 only 1 + * 29:27 tDQSCKmax 1 + * 31:30 Reserved + */ + write32(DDR_PHY + DDRPHY_DTPR1_OFFSET, 0x094E0092); + /* DTPR2 : DRAM Timing Params 2 + * 9:0 tXS exit SR def 200, 200d + * 14:10 tXP PD Exit Del 8 3 + * 18:15 tCKE CKE Min pulse 3 + * 28:19 tDLLK DLL Lock time 200d + * 32:29 Reserved + */ + write32(DDR_PHY + DDRPHY_DTPR2_OFFSET, 0x06418CC8); + /* PTR0 : PHY Timing Params 0 + * 5:0 tDLLRST Def 27 + * 17:6 tDLLLOCK Def 2750 + * 21:18 tITMSRST Def 8 + * 31:22 Reserved 0 + */ + write32(DDR_PHY + DDRPHY_PTR0_OFFSET, 0x0022AF9B); + /* PTR1 : PHY Timing Params 1 + * 18:0 : tDINITO DRAM Init time 200us 80,000 Dec 0x13880 + * 29:19 : tDINIT1 DRAM Init time 400ns 160 Dec 0xA0 + */ + write32(DDR_PHY + DDRPHY_PTR1_OFFSET, 0x05013880); + + /* PGSR : Wait for INIT/DLL/Z Done from Power on Reset */ + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, 0x00000007)) + return DDR_TIMEOUT; + + if (UMCTL_INIT == 1) { + /* PIR : Trigger INIT/DLL/Z following soft reset of DLL & ITM */ + write32(DDR_PHY + DDRPHY_PIR_OFFSET, 0x0000001F); + + /* PGSR : Wait for INIT?DLL?Z Done from SOFT Reset */ + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, + 0x00000007)) + return DDR_TIMEOUT; + + /* PIR : use uMCTL for DRAM Init */ + write32(DDR_PHY + DDRPHY_PIR_OFFSET, 0x00040001); + + /* PGSR : Wait for DRAM Init Done */ + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, + 0x0000000F)) + return DDR_TIMEOUT; + + } else { + /* PIR : use uMCTL for DRAM Init */ + write32(DDR_PHY + DDRPHY_PIR_OFFSET, 0x000001DF); + /* PGSR : Wait for DRAM Init Done */ + + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, + 0x0000001F)) + return DDR_TIMEOUT; + } + + /* DF1STAT0 : wait for DFI_INIT_COMPLETE */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_DFISTAT0_OFFSET, + 0x00000001)) + return DDR_TIMEOUT; + + /* POWCTL : Start the memory Power Up seq*/ + write32(DDR_PCTL + DDR_PCTL_POWCTL_OFFSET, 0x00000001); + + /* POWSTAT : wait for POWER_UP_DONE */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_POWSTAT_OFFSET, + 0x00000001)) + return DDR_TIMEOUT; + + /* + * TREFI : t_refi Timing Register 1X + * 12:0 t_refi 7.8us in 100ns 0x4E + * 15:13 Reserved 0 + * 18:16 num_add_ref 0 + * 30:19 Reserved 0 + * 31 Update 1 + */ + write32(DDR_PCTL + DDR_PCTL_TREFI_OFFSET, 0x8000004E); + /* TMRD : t_mrd Timing Register -- Range 2 to 3 */ + write32(DDR_PCTL + DDR_PCTL_TMRD_OFFSET, 0x00000002); + /* + * TRFC : t_rfc Timing Register -- Range 15 to 131 + * 195ns / 2.5ns 78 x4E + */ + write32(DDR_PCTL + DDR_PCTL_TRFC_OFFSET, 0x0000004E); + /* TRP : t_rp Timing Register -- Range 3 to 7 + * 4:0 tRP 12.5 / 2.5 = 5 6 For Now 6-6-6 + * 17:16 rpea_extra tRPall 8 bank 1 + */ + write32(DDR_PCTL + DDR_PCTL_TRP_OFFSET, 0x00010006); + /* TAL : Additive Latency Register -- AL in MR1 */ + write32(DDR_PCTL + DDR_PCTL_TAL_OFFSET, 0x00000000); + /* DFITPHYWRLAT : Write cmd to dfi_wrdata_en */ + write32(DDR_PCTL + DDR_PCTL_DFIWRLAT_OFFSET, 0x00000002); + /* DFITRDDATAEN : Read cmd to dfi_rddata_en */ + write32(DDR_PCTL + DDR_PCTL_DFITRDDATAEN_OFFSET, 0x00000002); + /* TCL : CAS Latency Timing Register -- CASL in MR0 6-6-6 */ + write32(DDR_PCTL + DDR_PCTL_TCL_OFFSET, 0x00000006); + /* TCWL : CAS Write Latency Register --CASL-1 */ + write32(DDR_PCTL + DDR_PCTL_TCWL_OFFSET, 0x00000005); + /* + * TRAS : Activate to Precharge cmd time + * Range 8 to 24: 45ns / 2.5ns = 18d + */ + write32(DDR_PCTL + DDR_PCTL_TRAS_OFFSET, 0x00000012); + /* + * TRC : Min. ROW cylce time + * Range 11 to 31: 57.5ns / 2.5ns = 23d Playing safe 24 + */ + write32(DDR_PCTL + DDR_PCTL_TRC_OFFSET, 0x00000018); + /* + * TRCD : Row to Column Delay + * Range 3 to 7 (TCL = TRCD): 2.5ns / 2.5ns = 5 but running 6-6-6 6 + */ + write32(DDR_PCTL + DDR_PCTL_TRCD_OFFSET, 0x00000006); + /* TRRD : Row to Row delay -- Range 2 to 6: 2K Page 10ns / 2.5ns = 4*/ + write32(DDR_PCTL + DDR_PCTL_TRRD_OFFSET, 0x00000004); + /* TRTP : Read to Precharge time -- Range 2 to 4: 7.3ns / 2.5ns = 3 */ + write32(DDR_PCTL + DDR_PCTL_TRTP_OFFSET, 0x00000003); + /* TWR : Write recovery time -- WR in MR0: 15ns / 2.5ns = 6 + */ + write32(DDR_PCTL + DDR_PCTL_TWR_OFFSET, 0x00000006); + /* + * TWTR : Write to read turn around time + * Range 2 to 4: 7.3ns / 2.5ns = 3 + */ + write32(DDR_PCTL + DDR_PCTL_TWTR_OFFSET, 0x00000003); + /* TEXSR : Exit Self Refresh to first valid cmd: tXS 200*/ + write32(DDR_PCTL + DDR_PCTL_TEXSR_OFFSET, 0x000000C8); + /* + * TXP : Exit Power Down to first valid cmd + * tXP 2, Settingto 3 to match PHY + */ + write32(DDR_PCTL + DDR_PCTL_TXP_OFFSET, 0x00000003); + /* + * TDQS : t_dqs Timing Register + * DQS additional turn around Rank 2 Rank (1 Rank) Def 1 + */ + write32(DDR_PCTL + DDR_PCTL_TDQS_OFFSET, 0x00000001); + /*TRTW : Read to Write turn around time Def 2 + * Actual gap t_bl + t_rtw + */ + write32(DDR_PCTL + DDR_PCTL_TRTW_OFFSET, 0x00000002); + /* TCKE : CKE min pulse width DEf 3 */ + write32(DDR_PCTL + DDR_PCTL_TCKE_OFFSET, 0x00000003); + /* + * TXPDLL : Slow Exit Power Down to first valid cmd delay + * tXARDS 10+AL = 10 + */ + write32(DDR_PCTL + DDR_PCTL_TXPDLL_OFFSET, 0x0000000A); + /* + * TCKESR : Min CKE Low width for Self refresh entry to exit + * t_ckesr = 0 DDR2 + */ + write32(DDR_PCTL + DDR_PCTL_TCKESR_OFFSET, 0x00000000); + /* SCFG : State Configuration Register (Enabling Self Refresh) + * 0 LP_en Leave Off for Bring Up 0 + * 5:1 Reserved + * 6 Synopsys Internal Only 0 + * 7 Enale PHY indication of LP Opportunity 1 + * 11:8 bbflags_timing max UPCTL_TCU_SED_P - tRP (16 - 6) Use 4 + * 16:12 Additional delay on accertion of ac_pdd 4 + * 31:17 Reserved + */ + write32(DDR_PCTL + DDR_PCTL_SCFG_OFFSET, 0x00004480); + /* + * DFITPHYWRDATA : dfi_wrdata_en to drive wr data + * DFI Clks wrdata_en to wrdata Def 1 + */ + write32(DDR_PCTL + DDR_PCTL_DFITPHYWRDATA_OFFSET, 0x00000000); + /* + * DFITPHYRDLAT : dfi_rddata_en to dfi_rddata_valid + * DFI clks max rddata_en to rddata_valid Def 15 + */ + write32(DDR_PCTL + DDR_PCTL_DFITPHYRDLAT_OFFSET, 0x00000008); + /* MCMD : PREA, Addr 0 Bank 0 Rank 0 Del 0 + * 3:0 cmd_opcode PREA 00001 + * 16:4 cmd_addr 0 + * 19:17 bank_addr 0 + * 23:20 rank_sel 0 0001 + * 27:24 cmddelay 0 + * 30:24 Reserved + */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100001); + + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00100001)) + return DDR_TIMEOUT; + + /* SCTL : UPCTL switch INIT CONFIG State */ + write32(DDR_PCTL + DDR_PCTL_SCTL_OFFSET, 0x00000001); + + /* STAT : Wait for Switch INIT to Config State */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_STAT_OFFSET, 0x00000001)) + return DDR_TIMEOUT; + + /* DFISTCFG0 : Drive various DFI signals appropriately + * 0 dfi_init_start 0 + * 1 dfi_freq_ratio_en 1 + * 2 dfi_data_byte_disable_en 1 + */ + write32(DDR_PCTL + DDR_PCTL_DFISTCFG0_OFFSET, 0x00000003); + /* DFISTCFG1 : Enable various DFI support + * 0 dfi_dram_clk_disable_en 1 + * 1 dfi_dram_clk_disable_en_pdp only lPDDR 0 + */ + write32(DDR_PCTL + DDR_PCTL_DFISTCFG1_OFFSET, 0x00000001); + /* DFISTCFG2 : Enable Parity and asoc interrupt + * 0 dfi_parity_in Enable 1 + * 1 Interrupt on dfi_parity_error 1 + */ + write32(DDR_PCTL + DDR_PCTL_DFISTCFG2_OFFSET, 0x00000003); + /* DFILPCFG0 : DFI Low Power Interface Configuration + * 0 Enable DFI LP IF during PD 1 + * 3:1 Reserved + * 7:4 DFI tlp_wakeup time 0 + * 8 Enable DFI LP IF during SR 1 + * 11:9 Reserved + * 15:12 dfi_lp_wakeup in SR 0 + * 19:16 tlp_resp DFI 2.1 recomend 7 + * 23:20 Reserved + * 24 Enable DFI LP in Deep Power Down 0 + * 27:25 Reserved + * 31:28 DFI LP Deep Power Down Value 0 + */ + write32(DDR_PCTL + DDR_PCTL_DFILPCFG0_OFFSET, 0x00070101); + /* DFIODTCFG : DFI ODT Configuration + * Only Enabled on Rank0 Writes + * 0 rank0_odt_read_nsel 0 + * 1 rank0_odt_read_sel 0 + * 2 rank0_odt_write_nsel 0 + * 3 rank0_odt_write_sel 1 + */ + write32(DDR_PCTL + DDR_PCTL_DFIODTCFG_OFFSET, 0x00000008); + + /* DFIODTCFG1 : DFI ODT Configuration + * 4:0 odt_lat_w 4 + * 12:8 odt_lat_r 0 Def + * 4:0 odt_len_bl8_w 6 Def + * 12:8 odt_len_bl8_r 6 Def + */ + write32(DDR_PCTL + DDR_PCTL_DFIODTCFG1_OFFSET, 0x06060004); + + if (UMCTL_INIT == 1) { + /* MCMD : Deselect command */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100000); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x00100000)) + return DDR_TIMEOUT; + + /* MCMD : Precharge ALL Banks */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100001); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x00100001)) + return DDR_TIMEOUT; + + /* MCMD : MRS Cmd, EMR2 -- High Temp Self refresh Disable */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80140003 | (emr2 << 4)); + exp_val = (0x00140003 | (emr2 << 4)); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + exp_val)) + return DDR_TIMEOUT; + + /* MCMD : MRS cmd, EMR3 */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80160003 | (emr3 << 4)); + exp_val = (0x00160003 | (emr3 << 4)); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + exp_val)) + return DDR_TIMEOUT; + + /* MCMD : MRS Cmd, EMR-- DLL Enable */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80120003 | (emr << 4)); + exp_val = (0x00120003 | (emr << 4)); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + exp_val)) + return DDR_TIMEOUT; + + /* MCMD : MRS Cmd, MR--DLL Reset */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + (0x80100003 | (md_dllrst << 4))); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80000000)) + return DDR_TIMEOUT; + + /* MCMD : Precharge ALL Banks */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100001); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x00100001)) + return DDR_TIMEOUT; + + /* MCMD : Refresh Command */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100002); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x00100002)) + return DDR_TIMEOUT; + + /* MCMD : Refresh Command */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100002); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x00100002)) + return DDR_TIMEOUT; + + /* MCMD : MRS Cmd, MR0-- Initialize Device Operation */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80100003 | (mr << 4)); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x0)) + return DDR_TIMEOUT; + + /* MCMD : MRS Cmd, MR1-- Set OCD Calibration Default */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80123803 | (emr << 4)); + exp_val = (0x00123803 | (emr << 4)); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + exp_val)) + return DDR_TIMEOUT; + + /* MCMD : MRS Cmd, MR1-- Exit OCD calibration Mode */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + 0x80120003 | (emr << 4)); + exp_val = (0x00120003 | (emr << 4)); + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, + exp_val)) + return DDR_TIMEOUT; + } + + /* DCFG : DRAM Density 256 Mb 16 Bit IO Width + * 1:0 Devicw Width 1 x8, 2 x16, 3 x32 2 + * 5:2 Density 2Gb = 5 + * 6 Dram Type (MDDR/LPDDR2) Only 0 + * 7 Reserved 0 + * 10:8 Address Map R/B/C = 0 + * 31:11 Reserved + */ + write32(DDR_PCTL + DDR_PCTL_DCFG_OFFSET, 0x00000016); + + /* PCFG_0 : Port 0 AXI config */ + if (BL8 == 1) + write32(DDR_PCTL + DDR_PCTL_PCFG0_OFFSET, 0x000800A0); + else + write32(DDR_PCTL + DDR_PCTL_PCFG0_OFFSET, 0x000400A0); + + /* SCTL : UPCTL switch Config to ACCESS State */ + write32(DDR_PCTL + DDR_PCTL_SCTL_OFFSET, 0x00000002); + /* STAT : Wait for switch CFG -> GO State */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_STAT_OFFSET, 0x3)) + return DDR_TIMEOUT; + + return 0; +} diff --git a/src/soc/imgtec/pistachio/include/soc/ddr_init.h b/src/soc/imgtec/pistachio/include/soc/ddr_init.h new file mode 100644 index 0000000000..1dbec6ce3e --- /dev/null +++ b/src/soc/imgtec/pistachio/include/soc/ddr_init.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SOC_IMGTEC_PISTACHIO_DDR_INIT_H__ +#define __SOC_IMGTEC_PISTACHIO_DDR_INIT_H__ + +#define DDR_TIMEOUT -1 + +int init_ddr2(void); + +#endif diff --git a/src/soc/imgtec/pistachio/romstage.c b/src/soc/imgtec/pistachio/romstage.c index 3fcf23d461..a10db1682f 100644 --- a/src/soc/imgtec/pistachio/romstage.c +++ b/src/soc/imgtec/pistachio/romstage.c @@ -21,9 +21,17 @@ #include <program_loading.h> #include <console/console.h> +#include <halt.h> +#include <soc/ddr_init.h> void main(void) { + int error; console_init(); - run_ramstage(); + error = init_ddr2(); + + if (!error) { + run_ramstage(); + } + halt(); } |