aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/imgtec/pistachio/Makefile.inc1
-rw-r--r--src/soc/imgtec/pistachio/ddr2_init.c114
-rw-r--r--src/soc/imgtec/pistachio/ddr3_init.c513
-rw-r--r--src/soc/imgtec/pistachio/include/soc/ddr_init.h1
-rw-r--r--src/soc/imgtec/pistachio/include/soc/ddr_private_reg.h138
5 files changed, 655 insertions, 112 deletions
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 <arch/cpu.h>
#include <arch/io.h>
-#include <delay.h>
#include <soc/ddr_init.h>
+#include <soc/ddr_private_reg.h>
#include <stdint.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_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 <stdint.h>
+#include <arch/io.h>
+#include <soc/ddr_init.h>
+#include <soc/ddr_private_reg.h>
+
+/*
+ * 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 <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_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