diff --git a/src/soc/imgtec/pistachio/Makefile.inc b/src/soc/imgtec/pistachio/Makefile.inc index c7bf1ec1ca..df9fbcfb06 100644 --- a/src/soc/imgtec/pistachio/Makefile.inc +++ b/src/soc/imgtec/pistachio/Makefile.inc @@ -40,6 +40,7 @@ ramstage-y += soc.c romstage-y += cbmem.c romstage-y += ddr2_init.c +romstage-y += ddr3_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 index dd09321fb0..ce10ab550d 100644 --- a/src/soc/imgtec/pistachio/ddr2_init.c +++ b/src/soc/imgtec/pistachio/ddr2_init.c @@ -18,122 +18,12 @@ * Foundation, Inc. */ -#include #include -#include #include +#include #include -#include -#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_PGCR_OFFSET (0x0008) -#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 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; -} +#define BL8 0 /* * Configuration for the Winbond W972GG6JB-25 part using diff --git a/src/soc/imgtec/pistachio/ddr3_init.c b/src/soc/imgtec/pistachio/ddr3_init.c new file mode 100644 index 0000000000..a8758f72c8 --- /dev/null +++ b/src/soc/imgtec/pistachio/ddr3_init.c @@ -0,0 +1,513 @@ +/* + * 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 +#include +#include +#include + +/* + * Configuration for the Winbond W631GG6KB part using + * Synopsys DDR uMCTL and DDR Phy + */ +int init_ddr3(void) +{ + uint32_t temp_rw_val; + + temp_rw_val = read32(TOPLEVEL_REGS + DDR_CTRL_OFFSET); + /* Set CLK_EN = 1 */ + temp_rw_val |= 0x2; + write32(TOPLEVEL_REGS + DDR_CTRL_OFFSET, temp_rw_val); + read32(TOPLEVEL_REGS + DDR_CTRL_OFFSET); + /* + * Reset the AXI bridge and DDR Controller in case any spurious + * writes have already happened to DDR + */ + /* Drive the 3 resets low */ + write32(TOPLEVEL_REGS + DDR_CTRL_OFFSET, 0x00000002); + read32(TOPLEVEL_REGS + DDR_CTRL_OFFSET); + read32(TOPLEVEL_REGS + DDR_CTRL_OFFSET); + + /* And release */ + write32(TOPLEVEL_REGS + DDR_CTRL_OFFSET, 0x0000000F); + /* Dummy read to fence the access between the reset above and + * the 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, 0x000001F4); + /* 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 1 -> 8 fixed + * 1 RDRIMM 0 + * 2 BL8 Burst Terminate 0 + * 3 2T = 0 + * 4 Multi Rank 0 + * 5 DDR3 En 1 + * 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, 0x00060021); + /* 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 => DDR3 3 + * 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, 0x0000000B); + /* Generate to use with PHY and PCTL + * MR0 : DDR3 mode register 0 + * 1:0 BL 8 fixed 00 + * 3 BT Sequential 0 Interleaved 1 = 0 + * 6:4,2 CL 6 + * 7 TM Normal 0 + * 8 DLL Reset 1 (self Clearing) + * 11:9 WR 15 ns 6 (010) + * 12 PD Slow 1 Fast 0 0 + * 15:13 RSVD RSVD + * 31:16 Reserved + */ + write32(DDR_PHY + DDRPHY_MR_OFFSET, 0x00001420); + /* MR1 : DDR3 mode register 1 + * Generate to use with PHY and PCTL + * 0 DE DLL Enable 0 Disable 1 + * 5,1 DIC Output Driver RZQ/6 + * 9,6,2 ODT RZQ/4 + * 4:3 AL = 0 + * 7 write leveling enabled 0 + * 10 DQS 0 diff, 1 single = 0 + * 11 TDQS NA 0 + * 12 QOFF Normal mode 0 + * 15:13 RSVD + * 31:16 Reserved + */ + write32(DDR_PHY + DDRPHY_EMR_OFFSET, 0x00000004); + /* MR2 : DDR3 mode register 2 + * Generate to use with PHY and PCTL + * 2:0 PASR, NA 000 + * 3 CWL 000 (5) tck = 22.5ns + * 6 auto self-refresh 1 + * 7 SRT normal 0 + * 8 RSVD + * 10:9 dynamic ODT 10 RZQ/2 + * 31:11 Reserved + */ + write32(DDR_PHY + DDRPHY_EMR2_OFFSET, 0x00000440); + /* MR3: DDR3 mode register 3 + * 1:0 MPRLOC 00 + * 2 MPR 0 + */ + write32(DDR_PHY + DDRPHY_EMR3_OFFSET, 0x00000000); + /* DTAR : Data Training Register + * 11:0 Data Training Column Address + * 27:12 Data Training Row Address + * 30:28 Data Training Bank Address + * 31 Data Training Use MPR (DDR3 Only) + */ + write32(DDR_PHY + DDRPHY_DTAR_OFFSET, 0x00000000); + /* 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 1 + * 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 1 + * 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, 0xFA000807); + /* DTPR0 : DRAM Timing Params 0 + * 1:0 tMRD 0 + * 4:2 tRTP 2 + * 7:5 tWTR 4 + * 11:8 tRP 6 + * 15:12 tRCD 6 + * 20:16 tRAS 15 + * 24:21 tRRD 4 for x16 + * 30:25 tRC 21 + * 31 tCCD 0 BL/2 Cas to Cas + */ + write32(DDR_PHY + DDRPHY_DTPR0_OFFSET, 0x2A8F6688); + /* 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 20 Clk + * 10:9 tMOD DDR3 Only 15 + * 11 tRTODT DDR3 Only 0 + * 15:12 Reserved + * 23:16 tRFC 160ns 64 ref 131 + * 26:24 tDQSCK LPDDR2 only 1 + * 29:27 tDQSCKmax 1 + * 31:30 Reserved + */ + write32(DDR_PHY + DDRPHY_DTPR1_OFFSET, 0x094006A0); + /* DTPR2 : DRAM Timing Params 2 + * 9:0 tXS exit SR def 512d + * 14:10 tXP PD Exit Del 8 5 + * 18:15 tCKE CKE Min pulse 5 + * 28:19 tDLLK DLL Lock time 512d + * 32:29 Reserved + */ + write32(DDR_PHY + DDRPHY_DTPR2_OFFSET, 0x10029600); + /* 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 500us 200,000 Dec 0x30D40 + * 29:19 : tDINIT1 DRAM Init time tRFC + 10ns 68 + */ + write32(DDR_PHY + DDRPHY_PTR1_OFFSET, 0x02230D40); + /* DQS gating configuration: passive windowing mode */ + /* + * PGCR: PHY General cofiguration register + * 0 ITM DDR mode: 0 + * 1 DQS gading configuration: passive windowing 1 + * 2 DQS drift compensation: not supported in passive windowing 0 + * 4:3 DQS drift limit 0 + * 8:5 Digital test output select 0 + * 11:9 CK Enable: one bit for each 3 CK pair: 0x7 + * 13:12 CK Disable values: 0x2 + * 14 CK Invert 0 + * 15 IO loopback 0 + * 17:16 I/O DDR mode 0 + * 21:18 Ranks enable by training: 0xF + * 23:22 Impedance clock divider select 0x2 + * 24 Power down disable 1 + * 28:25 Refresh during training 0 + * 29 loopback DQS shift 0 + * 30 loopback DQS gating 0 + * 31 loopback mode 0 + */ + write32(DDR_PHY + DDRPHY_PGCR_OFFSET, 0x01BC2E02); + + /* PGSR : Wait for INIT/DLL/Z Done from Power on Reset */ + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, 0x00000007)) + return DDR_TIMEOUT; + /* PIR : PHY controlled init */ + write32(DDR_PHY + DDRPHY_PIR_OFFSET, 0x0000001F); + /* PGSR : Wait for DRAM Init Done */ + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, 0x00000007)) + return DDR_TIMEOUT; + /* PIR : controller DRAM initialization */ + 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; + /********************************************************************/ + /* 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, 0x80000001); + /* 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 4*/ + write32(DDR_PCTL + DDR_PCTL_TMRD_OFFSET, 0x00000004); + /* + * 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 DDR3 - value 0 + */ + write32(DDR_PCTL + DDR_PCTL_TRP_OFFSET, 0x00000006); + /* TAL : Additive Latency Register -- AL in MR1 */ + write32(DDR_PCTL + DDR_PCTL_TAL_OFFSET, 0x00000000); + /* 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 15 45ns / 2.5ns = 18d */ + write32(DDR_PCTL + DDR_PCTL_TRAS_OFFSET, 0x0000000F); + /* TRC : Min. ROW cylce time 21 + * 57.5ns / 2.5ns = 23d Playing safe 24 + */ + write32(DDR_PCTL + DDR_PCTL_TRC_OFFSET, 0x00000015); + /* TRCD : Row to Column Delay # Range 3 to 7 (TCL = TRCD) + * 12.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 + * Largest 4 or 7.5ns / 2.5ns = 4 + */ + write32(DDR_PCTL + DDR_PCTL_TRTP_OFFSET, 0x00000004); + /* 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 + * Largest 4 or 7.5ns / 2.5ns = 4 + */ + write32(DDR_PCTL + DDR_PCTL_TWTR_OFFSET, 0x00000004); + /* TEXSR : Exit Self Refresh to first valid cmd: tXS 512 */ + write32(DDR_PCTL + DDR_PCTL_TEXSR_OFFSET, 0x00000200); + /* 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, 0x00000004); + /* TMOD : MRS to any Non-MRS command -- Range 0 to 31 */ + write32(DDR_PCTL + DDR_PCTL_TMOD_OFFSET, 0x0000000F); + /* TZQCS : SDRAM ZQ Calibration Short Period */ + write32(DDR_PCTL + DDR_PCTL_TZQCS_OFFSET, 0x00000040); + /* TZQCL : SDRAM ZQ Calibration Long Period */ + write32(DDR_PCTL + DDR_PCTL_TZQCL_OFFSET, 0x00000200); + /* 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); + /* TREFI_MEM_DDR3 */ + write32(DDR_PCTL + DDR_PCTL_TREFI_MEM_DDR3_OFFSET, 0x00000C30); + + /* 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); + /* + * 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); + /* DFISTCFG0 : Drive various DFI signals appropriately + * 0 dfi_init_start 1 + * 1 dfi_freq_ratio_en 1 + * 2 dfi_data_byte_disable_en 1 + */ + write32(DDR_PCTL + DDR_PCTL_DFISTCFG0_OFFSET, 0x00000007); + /* 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 0 + * 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, 0x060600000); + + /* Memory initilization */ + /* 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 + */ + /* MCMD: MR2 */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80004403); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00004403)) + return DDR_TIMEOUT; + /* MCMD: MR3 */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80000003); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00000003)) + return DDR_TIMEOUT; + /* MCMD: MR1 */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80000043); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00000043)) + return DDR_TIMEOUT; + /* MCMD: MR0 */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80015203); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00015203)) + return DDR_TIMEOUT; + /* MCMD: ZQS cmd, long 5 short 4 */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80104005); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00104005)) + return DDR_TIMEOUT; + /* MCMD: deselect command */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x80100000); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x00100000)) + return DDR_TIMEOUT; + /* MCMD: deselect command */ + write32(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x8010000A); + /* MRS cmd wait for completion */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_MCMD_OFFSET, 0x0010000A)) + 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 = 1 + * 31:11 Reserved + */ + write32(DDR_PCTL + DDR_PCTL_DCFG_OFFSET, 0x00000116); + /* PCFG_0 : Port 0 AXI config */ + write32(DDR_PCTL + DDR_PCTL_PCFG0_OFFSET, 0x000800A0); + /* 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; + /* STAT : Wait for Switch INIT to Config State */ + write32(DDR_PCTL + DDR_PCTL_CMDTSTATEN_OFFSET, 0x00000001); + /* STAT : Wait for Switch INIT to Config State */ + if (wait_for_completion(DDR_PCTL + DDR_PCTL_CMDTSTAT_OFFSET, + 0x00000001)) + return DDR_TIMEOUT; + /* Use PHY for DRAM init */ + write32(DDR_PHY + DDRPHY_PIR_OFFSET, 0x00000181); + /* STAT : Wait for Switch INIT to Config State */ + if (wait_for_completion(DDR_PHY + DDRPHY_PGSR_OFFSET, 0x00000001F)) + return DDR_TIMEOUT; + /* 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 index 1dbec6ce3e..d8b5b19bae 100644 --- a/src/soc/imgtec/pistachio/include/soc/ddr_init.h +++ b/src/soc/imgtec/pistachio/include/soc/ddr_init.h @@ -21,5 +21,6 @@ #define DDR_TIMEOUT -1 int init_ddr2(void); +int init_ddr3(void); #endif diff --git a/src/soc/imgtec/pistachio/include/soc/ddr_private_reg.h b/src/soc/imgtec/pistachio/include/soc/ddr_private_reg.h new file mode 100644 index 0000000000..a0f661b8fd --- /dev/null +++ b/src/soc/imgtec/pistachio/include/soc/ddr_private_reg.h @@ -0,0 +1,138 @@ +/* + * 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_PRIVATE_REG_H__ +#define __SOC_IMGTEC_PISTACHIO_DDR_PRIVATE_REG_H__ + +#include + +#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_SCFG_OFFSET (0x0000) +#define DDR_PCTL_SCTL_OFFSET (0x0004) +#define DDR_PCTL_STAT_OFFSET (0x0008) +#define DDR_PCTL_MCMD_OFFSET (0x0040) +#define DDR_PCTL_POWCTL_OFFSET (0x0044) +#define DDR_PCTL_POWSTAT_OFFSET (0x0048) +#define DDR_PCTL_CMDTSTAT_OFFSET (0x004C) +#define DDR_PCTL_CMDTSTATEN_OFFSET (0x0050) +#define DDR_PCTL_MCFG1_OFFSET (0x007C) +#define DDR_PCTL_MCFG_OFFSET (0x0080) +#define DDR_PCTL_MSTAT_OFFSET (0x0088) +#define DDR_PCTL_DTUAWDT_OFFSET (0x00B0) +#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_TREFI_OFFSET (0x00D0) +#define DDR_PCTL_TMRD_OFFSET (0x00D4) +#define DDR_PCTL_TRFC_OFFSET (0x00D8) +#define DDR_PCTL_TRP_OFFSET (0x00DC) +#define DDR_PCTL_TRTW_OFFSET (0x00E0) +#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_TXPDLL_OFFSET (0x0114) +#define DDR_PCTL_TZQCS_OFFSET (0x0118) +#define DDR_PCTL_TDQS_OFFSET (0x0120) +#define DDR_PCTL_TCKE_OFFSET (0x012C) +#define DDR_PCTL_TMOD_OFFSET (0x0130) +#define DDR_PCTL_TZQCL_OFFSET (0x0138) +#define DDR_PCTL_TCKESR_OFFSET (0x0140) +#define DDR_PCTL_TREFI_MEM_DDR3_OFFSET (0x0148) +#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_DFIODTCFG_OFFSET (0x0244) +#define DDR_PCTL_DFIODTCFG1_OFFSET (0x0248) +#define DDR_PCTL_DFITPHYWRDATA_OFFSET (0x0250) +#define DDR_PCTL_DFIWRLAT_OFFSET (0x0254) +#define DDR_PCTL_DFITRDDATAEN_OFFSET (0x0260) +#define DDR_PCTL_DFITPHYRDLAT_OFFSET (0x0264) +#define DDR_PCTL_DFIUPDCFG_OFFSET (0x0290) +#define DDR_PCTL_DFISTAT0_OFFSET (0x02C0) +#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_PCFG0_OFFSET (0x0400) +#define DDR_PCTL_CCFG_OFFSET (0x0480) +#define DDR_PCTL_DCFG_OFFSET (0x0484) +#define DDR_PCTL_CCFG1_OFFSET (0x048C) + +#define DDR_PHY 0xB8180800 +#define DDRPHY_PIR_OFFSET (0x0004) +#define DDRPHY_PGCR_OFFSET (0x0008) +#define DDRPHY_PGSR_OFFSET (0x000C) +#define DDRPHY_DLLGCR_OFFSET (0x0010) +#define DDRPHY_PTR0_OFFSET (0x0018) +#define DDRPHY_PTR1_OFFSET (0x001C) +#define DDRPHY_DSGCR_OFFSET (0x002C) +#define DDRPHY_DCR_OFFSET (0x0030) +#define DDRPHY_DTPR0_OFFSET (0x0034) +#define DDRPHY_DTPR1_OFFSET (0x0038) +#define DDRPHY_DTPR2_OFFSET (0x003C) +#define DDRPHY_MR_OFFSET (0x0040) +#define DDRPHY_EMR_OFFSET (0x0044) +#define DDRPHY_EMR2_OFFSET (0x0048) +#define DDRPHY_EMR3_OFFSET (0x004C) +#define DDRPHY_DTAR_OFFSET (0x0054) +#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_BISTUDPR_OFFSET (0x0120) +#define DDRPHY_BISTGSR_OFFSET (0x0124) + +#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; +} + +#endif