diff mbox

[U-Boot,v4,06/13] drivers: ddr: Add DDR2 SDRAM controller driver for Microchip PIC32.

Message ID 1453975222-11787-7-git-send-email-purna.mandal@microchip.com
State Accepted
Delegated to: Daniel Schwierzeck
Headers show

Commit Message

Purna Chandra Mandal Jan. 28, 2016, 10 a.m. UTC
This driver initializes PIC32 DDR2 SDRAM controller and internal DDR2 Phy module.
DDR2 controller operates in half-rate mode (upto 533MHZ frequency).

Signed-off-by: Paul Thacker <paul.thacker@microchip.com>
Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Simon Glass <sjg@chromium.org>


---

Changes in v4: None
Changes in v3:
- annotating fixed table with const
- fix camel-case in ddr2 timing parameters
- fix cmd index parameter of host_load_cmd().
- fix compilation warning

Changes in v2:
- move ddr2 initialization from board/microchip/ to drivers/ddr/microchip

 arch/mips/mach-pic32/include/mach/ddr.h |  32 ++++
 drivers/Makefile                        |   1 +
 drivers/ddr/microchip/Makefile          |   6 +
 drivers/ddr/microchip/ddr2.c            | 278 ++++++++++++++++++++++++++++++++
 drivers/ddr/microchip/ddr2_regs.h       | 148 +++++++++++++++++
 drivers/ddr/microchip/ddr2_timing.h     |  65 ++++++++
 6 files changed, 530 insertions(+)
 create mode 100644 arch/mips/mach-pic32/include/mach/ddr.h
 create mode 100644 drivers/ddr/microchip/Makefile
 create mode 100644 drivers/ddr/microchip/ddr2.c
 create mode 100644 drivers/ddr/microchip/ddr2_regs.h
 create mode 100644 drivers/ddr/microchip/ddr2_timing.h
diff mbox

Patch

diff --git a/arch/mips/mach-pic32/include/mach/ddr.h b/arch/mips/mach-pic32/include/mach/ddr.h
new file mode 100644
index 0000000..00abfa3
--- /dev/null
+++ b/arch/mips/mach-pic32/include/mach/ddr.h
@@ -0,0 +1,32 @@ 
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_PIC32_DDR_H
+#define __MICROCHIP_PIC32_DDR_H
+
+/* called by initdram() function */
+void ddr2_phy_init(void);
+void ddr2_ctrl_init(void);
+phys_size_t ddr2_calculate_size(void);
+
+/* Maximum number of agents */
+#define NUM_AGENTS		5
+
+/* Board can provide agent specific parameters for arbitration by
+ * filling struct ddr2_arbiter_params for all the agents and
+ * implementing board_get_ddr_arbiter_params() to return the filled
+ * structure.
+ */
+struct ddr2_arbiter_params {
+	u32 min_limit;	/* min bursts to execute per arbitration */
+	u32 req_period; /* request period threshold for accepted cmds */
+	u32 min_cmd_acpt; /* min number of accepted cmds */
+};
+
+const struct ddr2_arbiter_params *board_get_ddr_arbiter_params(void);
+
+#endif /* __MICROCHIP_PIC32_DDR_H */
diff --git a/drivers/Makefile b/drivers/Makefile
index 6294048..e7eab66 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -69,4 +69,5 @@  obj-y += soc/
 obj-$(CONFIG_REMOTEPROC) += remoteproc/
 obj-y += thermal/
 
+obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
 endif
diff --git a/drivers/ddr/microchip/Makefile b/drivers/ddr/microchip/Makefile
new file mode 100644
index 0000000..305c48b
--- /dev/null
+++ b/drivers/ddr/microchip/Makefile
@@ -0,0 +1,6 @@ 
+#
+# Copyright (C) 2015 Microchip Technology Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+obj-$(CONFIG_MACH_PIC32) += ddr2.o
diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c
new file mode 100644
index 0000000..6056418
--- /dev/null
+++ b/drivers/ddr/microchip/ddr2.c
@@ -0,0 +1,278 @@ 
+/*
+ * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+#include <common.h>
+#include <wait_bit.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <mach/pic32.h>
+#include <mach/ddr.h>
+
+#include "ddr2_regs.h"
+#include "ddr2_timing.h"
+
+/* init DDR2 Phy */
+void ddr2_phy_init(void)
+{
+	struct ddr2_phy_regs *ddr2_phy;
+	u32 pad_ctl;
+
+	ddr2_phy = ioremap(PIC32_DDR2P_BASE, sizeof(*ddr2_phy));
+
+	/* PHY_DLL_RECALIB */
+	writel(DELAY_START_VAL(3) | DISABLE_RECALIB(0) |
+	       RECALIB_CNT(0x10), &ddr2_phy->dll_recalib);
+
+	/* PHY_PAD_CTRL */
+	pad_ctl = ODT_SEL | ODT_EN | DRIVE_SEL(0) |
+		  ODT_PULLDOWN(2) | ODT_PULLUP(3) |
+		  EXTRA_OEN_CLK(0) | NOEXT_DLL |
+		  DLR_DFT_WRCMD | HALF_RATE |
+		  DRVSTR_PFET(0xe) | DRVSTR_NFET(0xe) |
+		  RCVR_EN | PREAMBLE_DLY(2);
+	writel(pad_ctl, &ddr2_phy->pad_ctrl);
+
+	/* SCL_CONFIG_0 */
+	writel(SCL_BURST8 | SCL_DDR_CONNECTED | SCL_RCAS_LAT(RL) |
+	       SCL_ODTCSWW, &ddr2_phy->scl_config_1);
+
+	/* SCL_CONFIG_1 */
+	writel(SCL_CSEN | SCL_WCAS_LAT(WL), &ddr2_phy->scl_config_2);
+
+	/* SCL_LAT */
+	writel(SCL_CAPCLKDLY(3) | SCL_DDRCLKDLY(4), &ddr2_phy->scl_latency);
+}
+
+/* start phy self calibration logic */
+static int ddr2_phy_calib_start(void)
+{
+	struct ddr2_phy_regs *ddr2_phy;
+
+	ddr2_phy = ioremap(PIC32_DDR2P_BASE, sizeof(*ddr2_phy));
+
+	/* DDR Phy SCL Start */
+	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
+
+	/* Wait for SCL for data byte to pass */
+	return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS,
+			    true, CONFIG_SYS_HZ, false);
+}
+
+/* DDR2 Controller initialization */
+
+/* Target Agent Arbiter */
+static void ddr_set_arbiter(struct ddr2_ctrl_regs *ctrl,
+			    const struct ddr2_arbiter_params *const param)
+{
+	int i;
+
+	for (i = 0; i < NUM_AGENTS; i++) {
+		/* set min burst size */
+		writel(i * MIN_LIM_WIDTH, &ctrl->tsel);
+		writel(param->min_limit, &ctrl->minlim);
+
+		/* set request period (4 * req_period clocks) */
+		writel(i * RQST_PERIOD_WIDTH, &ctrl->tsel);
+		writel(param->req_period, &ctrl->reqprd);
+
+		/* set number of burst accepted */
+		writel(i * MIN_CMDACPT_WIDTH, &ctrl->tsel);
+		writel(param->min_cmd_acpt, &ctrl->mincmd);
+	}
+}
+
+const struct ddr2_arbiter_params *__weak board_get_ddr_arbiter_params(void)
+{
+	/* default arbiter parameters */
+	static const struct ddr2_arbiter_params arb_params[] = {
+		{ .min_limit = 0x1f, .req_period = 0xff, .min_cmd_acpt = 0x04,},
+		{ .min_limit = 0x1f, .req_period = 0xff, .min_cmd_acpt = 0x10,},
+		{ .min_limit = 0x1f, .req_period = 0xff, .min_cmd_acpt = 0x10,},
+		{ .min_limit = 0x04, .req_period = 0xff, .min_cmd_acpt = 0x04,},
+		{ .min_limit = 0x04, .req_period = 0xff, .min_cmd_acpt = 0x04,},
+	};
+
+	return &arb_params[0];
+}
+
+static void host_load_cmd(struct ddr2_ctrl_regs *ctrl, u32 cmd_idx,
+			  u32 hostcmd2, u32 hostcmd1, u32 delay)
+{
+	u32 hc_delay;
+
+	hc_delay = max_t(u32, DIV_ROUND_UP(delay, T_CK), 2) - 2;
+	writel(hostcmd1, &ctrl->cmd10[cmd_idx]);
+	writel((hostcmd2 & 0x7ff) | (hc_delay << 11), &ctrl->cmd20[cmd_idx]);
+}
+
+/* init DDR2 Controller */
+void ddr2_ctrl_init(void)
+{
+	u32 wr2prech, rd2prech, wr2rd, wr2rd_cs;
+	u32 ras2ras, ras2cas, prech2ras, temp;
+	const struct ddr2_arbiter_params *arb_params;
+	struct ddr2_ctrl_regs *ctrl;
+
+	ctrl = ioremap(PIC32_DDR2C_BASE, sizeof(*ctrl));
+
+	/* PIC32 DDR2 controller always work in HALF_RATE */
+	writel(HALF_RATE_MODE, &ctrl->memwidth);
+
+	/* Set arbiter configuration per target */
+	arb_params = board_get_ddr_arbiter_params();
+	ddr_set_arbiter(ctrl, arb_params);
+
+	/* Address Configuration, model {CS, ROW, BA, COL} */
+	writel((ROW_ADDR_RSHIFT | (BA_RSHFT << 8) | (CS_ADDR_RSHIFT << 16) |
+	       (COL_HI_RSHFT << 24) | (SB_PRI << 29)  |
+	       (EN_AUTO_PRECH << 30)), &ctrl->memcfg0);
+
+	writel(ROW_ADDR_MASK, &ctrl->memcfg1);
+	writel(COL_HI_MASK, &ctrl->memcfg2);
+	writel(COL_LO_MASK, &ctrl->memcfg3);
+	writel(BA_MASK | (CS_ADDR_MASK << 8), &ctrl->memcfg4);
+
+	/* Refresh Config */
+	writel(REFCNT_CLK(DIV_ROUND_UP(T_RFI, T_CK_CTRL) - 2) |
+	       REFDLY_CLK(DIV_ROUND_UP(T_RFC_MIN, T_CK_CTRL) - 2) |
+	       MAX_PEND_REF(7),
+	       &ctrl->refcfg);
+
+	/* Power Config */
+	writel(ECC_EN(0) | ERR_CORR_EN(0) | EN_AUTO_PWR_DN(0) |
+	       EN_AUTO_SELF_REF(3) | PWR_DN_DLY(8) |
+	       SELF_REF_DLY(17) | PRECH_PWR_DN_ONLY(0),
+	       &ctrl->pwrcfg);
+
+	/* Delay Config */
+	wr2rd = max_t(u32, DIV_ROUND_UP(T_WTR, T_CK_CTRL),
+		      DIV_ROUND_UP(T_WTR_TCK, 2)) + WL + BL;
+	wr2rd_cs = max_t(u32, wr2rd - 1, 3);
+	wr2prech = DIV_ROUND_UP(T_WR, T_CK_CTRL) + WL + BL;
+	rd2prech = max_t(u32, DIV_ROUND_UP(T_RTP, T_CK_CTRL),
+			 DIV_ROUND_UP(T_RTP_TCK, 2)) + BL - 2;
+	ras2ras = max_t(u32, DIV_ROUND_UP(T_RRD, T_CK_CTRL),
+			DIV_ROUND_UP(T_RRD_TCK, 2)) - 1;
+	ras2cas = DIV_ROUND_UP(T_RCD, T_CK_CTRL) - 1;
+	prech2ras = DIV_ROUND_UP(T_RP, T_CK_CTRL) - 1;
+
+	writel(((wr2rd & 0x0f) |
+	       ((wr2rd_cs & 0x0f) << 4) |
+	       ((BL - 1) << 8) |
+	       (BL << 12) |
+	       ((BL - 1) << 16) |
+	       ((BL - 1) << 20) |
+	       ((BL + 2) << 24) |
+	       ((RL - WL + 3) << 28)), &ctrl->dlycfg0);
+
+	writel(((T_CKE_TCK - 1) |
+	       (((DIV_ROUND_UP(T_DLLK, 2) - 2) & 0xff) << 8) |
+	       ((T_CKE_TCK - 1) << 16) |
+	       ((max_t(u32, T_XP_TCK, T_CKE_TCK) - 1) << 20) |
+	       ((wr2prech >> 4) << 26) |
+	       ((wr2rd >> 4) << 27) |
+	       ((wr2rd_cs >> 4) << 28) |
+	       (((RL + 5) >> 4) << 29) |
+	       ((DIV_ROUND_UP(T_DLLK, 2) >> 8) << 30)), &ctrl->dlycfg1);
+
+	writel((DIV_ROUND_UP(T_RP, T_CK_CTRL) |
+	       (rd2prech << 8) |
+	       ((wr2prech & 0x0f) << 12) |
+	       (ras2ras << 16) |
+	       (ras2cas << 20) |
+	       (prech2ras << 24) |
+	       ((RL + 3) << 28)), &ctrl->dlycfg2);
+
+	writel(((DIV_ROUND_UP(T_RAS_MIN, T_CK_CTRL) - 1) |
+	       ((DIV_ROUND_UP(T_RC, T_CK_CTRL) - 1) << 8) |
+	       ((DIV_ROUND_UP(T_FAW, T_CK_CTRL) - 1) << 16)),
+	       &ctrl->dlycfg3);
+
+	/* ODT Config */
+	writel(0x0, &ctrl->odtcfg);
+	writel(BIT(16), &ctrl->odtencfg);
+	writel(ODTRDLY(RL - 3) | ODTWDLY(WL - 3) | ODTRLEN(2) | ODTWLEN(3),
+	       &ctrl->odtcfg);
+
+	/* Transfer Configuration */
+	writel(NXTDATRQDLY(2) | NXDATAVDLY(4) | RDATENDLY(2) |
+	       MAX_BURST(3) | (7 << 28) | BIG_ENDIAN(0),
+	       &ctrl->xfercfg);
+
+	/* DRAM Initialization */
+	/* CKE high after reset and wait 400 nsec */
+	host_load_cmd(ctrl, 0, 0, IDLE_NOP, 400000);
+
+	/* issue precharge all command */
+	host_load_cmd(ctrl, 1, 0x04, PRECH_ALL_CMD, T_RP + T_CK);
+
+	/* initialize EMR2 */
+	host_load_cmd(ctrl, 2, 0x200, LOAD_MODE_CMD, T_MRD_TCK * T_CK);
+
+	/* initialize EMR3 */
+	host_load_cmd(ctrl, 3, 0x300, LOAD_MODE_CMD, T_MRD_TCK * T_CK);
+
+	/*
+	 * RDQS disable, DQSB enable, OCD exit, 150 ohm termination,
+	 * AL=0, DLL enable
+	 */
+	host_load_cmd(ctrl, 4, 0x100,
+		      LOAD_MODE_CMD | (0x40 << 24), T_MRD_TCK * T_CK);
+	/*
+	 * PD fast exit, WR REC = T_WR in clocks -1,
+	 * DLL reset, CAS = RL, burst = 4
+	 */
+	temp = ((DIV_ROUND_UP(T_WR, T_CK) - 1) << 1) | 1;
+	host_load_cmd(ctrl, 5, temp, LOAD_MODE_CMD | (RL << 28) | (2 << 24),
+		      T_MRD_TCK * T_CK);
+
+	/* issue precharge all command */
+	host_load_cmd(ctrl, 6, 4, PRECH_ALL_CMD, T_RP + T_CK);
+
+	/* issue refresh command */
+	host_load_cmd(ctrl, 7, 0, REF_CMD, T_RFC_MIN);
+
+	/* issue refresh command */
+	host_load_cmd(ctrl, 8, 0, REF_CMD, T_RFC_MIN);
+
+	/* Mode register programming as before without DLL reset */
+	host_load_cmd(ctrl, 9, temp, LOAD_MODE_CMD | (RL << 28) | (3 << 24),
+		      T_MRD_TCK * T_CK);
+
+	/* extended mode register same as before with OCD default */
+	host_load_cmd(ctrl, 10, 0x103, LOAD_MODE_CMD | (0xc << 24),
+		      T_MRD_TCK * T_CK);
+
+	/* extended mode register same as before with OCD exit */
+	host_load_cmd(ctrl, 11, 0x100, LOAD_MODE_CMD | (0x4 << 28),
+		      140 * T_CK);
+
+	writel(CMD_VALID | NUMHOSTCMD(11), &ctrl->cmdissue);
+
+	/* start memory initialization */
+	writel(INIT_START, &ctrl->memcon);
+
+	/* wait for all host cmds to be transmitted */
+	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
+		     CONFIG_SYS_HZ, false);
+
+	/* inform all cmds issued, ready for normal operation */
+	writel(INIT_START | INIT_DONE, &ctrl->memcon);
+
+	/* perform phy caliberation */
+	if (ddr2_phy_calib_start())
+		printf("ddr2: phy calib failed\n");
+}
+
+phys_size_t ddr2_calculate_size(void)
+{
+	u32 temp;
+
+	temp = 1 << (COL_BITS + BA_BITS + ROW_BITS);
+	/* 16-bit data width between controller and DIMM */
+	temp = temp * CS_BITS * (16 / 8);
+	return (phys_size_t)temp;
+}
diff --git a/drivers/ddr/microchip/ddr2_regs.h b/drivers/ddr/microchip/ddr2_regs.h
new file mode 100644
index 0000000..0f4b159
--- /dev/null
+++ b/drivers/ddr/microchip/ddr2_regs.h
@@ -0,0 +1,148 @@ 
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_DDR2_REGS_H
+#define __MICROCHIP_DDR2_REGS_H
+
+#include <linux/bitops.h>
+
+/* DDR2 Controller */
+struct ddr2_ctrl_regs {
+	u32 tsel;
+	u32 minlim;
+	u32 reqprd;
+	u32 mincmd;
+	u32 memcon;
+	u32 memcfg0;
+	u32 memcfg1;
+	u32 memcfg2;
+	u32 memcfg3;
+	u32 memcfg4;
+	u32 refcfg;
+	u32 pwrcfg;
+	u32 dlycfg0;
+	u32 dlycfg1;
+	u32 dlycfg2;
+	u32 dlycfg3;
+	u32 odtcfg;
+	u32 xfercfg;
+	u32 cmdissue;
+	u32 odtencfg;
+	u32 memwidth;
+	u32 unused[11];
+	u32 cmd10[16];
+	u32 cmd20[16];
+};
+
+/* Arbiter Config */
+#define MIN_LIM_WIDTH		5
+#define RQST_PERIOD_WIDTH	8
+#define MIN_CMDACPT_WIDTH	8
+
+/* Refresh Config */
+#define REFCNT_CLK(x)		(x)
+#define REFDLY_CLK(x)		((x) << 16)
+#define MAX_PEND_REF(x)		((x) << 24)
+
+/* Power Config */
+#define PRECH_PWR_DN_ONLY(x)	((x) << 22)
+#define SELF_REF_DLY(x)		((x) << 12)
+#define PWR_DN_DLY(x)		((x) << 4)
+#define EN_AUTO_SELF_REF(x)	((x) << 3)
+#define EN_AUTO_PWR_DN(x)	((x) << 2)
+#define ERR_CORR_EN(x)		((x) << 1)
+#define ECC_EN(x)		(x)
+
+/* Memory Width */
+#define HALF_RATE_MODE		BIT(3)
+
+/* Delay Config */
+#define ODTWLEN(x)	((x) << 20)
+#define ODTRLEN(x)	((x) << 16)
+#define ODTWDLY(x)	((x) << 12)
+#define ODTRDLY(x)	((x) << 8)
+
+/* Xfer Config */
+#define BIG_ENDIAN(x)	((x) << 31)
+#define MAX_BURST(x)	((x) << 24)
+#define RDATENDLY(x)	((x) << 16)
+#define NXDATAVDLY(x)	((x) << 4)
+#define NXTDATRQDLY(x)	((x) << 0)
+
+/* Host Commands */
+#define IDLE_NOP	0x00ffffff
+#define PRECH_ALL_CMD	0x00fff401
+#define REF_CMD		0x00fff801
+#define LOAD_MODE_CMD	0x00fff001
+#define CKE_LOW		0x00ffeffe
+
+#define NUM_HOST_CMDS	12
+
+/* Host CMD Issue */
+#define CMD_VALID	BIT(4)
+#define NUMHOSTCMD(x)	(x)
+
+/* Memory Control */
+#define INIT_DONE	BIT(1)
+#define INIT_START	BIT(0)
+
+/* Address Control */
+#define EN_AUTO_PRECH		0
+#define SB_PRI			1
+
+/* DDR2 Phy Register */
+struct ddr2_phy_regs {
+	u32 scl_start;
+	u32 unused1[2];
+	u32 scl_latency;
+	u32 unused2[2];
+	u32 scl_config_1;
+	u32 scl_config_2;
+	u32 pad_ctrl;
+	u32 dll_recalib;
+};
+
+/* PHY PAD CONTROL */
+#define ODT_SEL			BIT(0)
+#define ODT_EN			BIT(1)
+#define DRIVE_SEL(x)		((x) << 2)
+#define ODT_PULLDOWN(x)		((x) << 4)
+#define ODT_PULLUP(x)		((x) << 6)
+#define EXTRA_OEN_CLK(x)	((x) << 8)
+#define NOEXT_DLL		BIT(9)
+#define DLR_DFT_WRCMD		BIT(13)
+#define HALF_RATE		BIT(14)
+#define DRVSTR_PFET(x)		((x) << 16)
+#define DRVSTR_NFET(x)		((x) << 20)
+#define RCVR_EN			BIT(28)
+#define PREAMBLE_DLY(x)		((x) << 29)
+
+/* PHY DLL RECALIBRATE */
+#define RECALIB_CNT(x)		((x) << 8)
+#define DISABLE_RECALIB(x)	((x) << 26)
+#define DELAY_START_VAL(x)	((x) << 28)
+
+/* PHY SCL CONFIG1 */
+#define SCL_BURST8		BIT(0)
+#define SCL_DDR_CONNECTED		BIT(1)
+#define SCL_RCAS_LAT(x)		((x) << 4)
+#define SCL_ODTCSWW		BIT(24)
+
+/* PHY SCL CONFIG2 */
+#define SCL_CSEN		BIT(0)
+#define SCL_WCAS_LAT(x)		((x) << 8)
+
+/* PHY SCL Latency */
+#define SCL_CAPCLKDLY(x)	((x) << 0)
+#define SCL_DDRCLKDLY(x)	((x) << 4)
+
+/* PHY SCL START */
+#define SCL_START		BIT(28)
+#define SCL_EN			BIT(26)
+#define SCL_LUBPASS		(BIT(1) | BIT(0))
+
+#endif	/* __MICROCHIP_DDR2_REGS_H */
diff --git a/drivers/ddr/microchip/ddr2_timing.h b/drivers/ddr/microchip/ddr2_timing.h
new file mode 100644
index 0000000..5895f9d
--- /dev/null
+++ b/drivers/ddr/microchip/ddr2_timing.h
@@ -0,0 +1,65 @@ 
+/*
+ * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#ifndef __MICROCHIP_DDR2_TIMING_H
+#define __MICROCHIP_DDR2_TIMING_H
+
+/* MPLL freq is 400MHz */
+#define T_CK		2500    /* 2500 psec */
+#define T_CK_CTRL	(T_CK * 2)
+
+/* Burst length in cycles */
+#define BL		2
+/* default CAS latency for all speed grades */
+#define RL		5
+/* default write latency for all speed grades = CL-1 */
+#define WL		4
+
+/* From Micron MT47H64M16HR-3 data sheet */
+#define T_RFC_MIN	127500	/* psec */
+#define T_WR		15000	/* psec */
+#define T_RP		12500	/* psec */
+#define T_RCD		12500	/* psec */
+#define T_RRD		7500	/* psec */
+/* T_RRD_TCK is minimum of 2 clk periods, regardless of freq */
+#define T_RRD_TCK	2
+#define T_WTR		7500	/* psec */
+/* T_WTR_TCK is minimum of 2 clk periods, regardless of freq */
+#define T_WTR_TCK	2
+#define T_RTP		7500	/* psec */
+#define T_RTP_TCK	(BL / 2)
+#define T_XP_TCK	2	/* clocks */
+#define T_CKE_TCK	3	/* clocks */
+#define T_XSNR		(T_RFC_MIN + 10000) /* psec */
+#define T_DLLK		200     /* clocks */
+#define T_RAS_MIN	45000   /* psec */
+#define T_RC		57500   /* psec */
+#define T_FAW		35000   /* psec */
+#define T_MRD_TCK	2       /* clocks */
+#define T_RFI		7800000 /* psec */
+
+/* DDR Addressing */
+#define COL_BITS	10
+#define BA_BITS		3
+#define ROW_BITS	13
+#define CS_BITS		1
+
+/* DDR Addressing scheme: {CS, ROW, BA, COL} */
+#define COL_HI_RSHFT	0
+#define COL_HI_MASK	0
+#define COL_LO_MASK	((1 << COL_BITS) - 1)
+
+#define BA_RSHFT	COL_BITS
+#define BA_MASK		((1 << BA_BITS) - 1)
+
+#define ROW_ADDR_RSHIFT	(BA_RSHFT + BA_BITS)
+#define ROW_ADDR_MASK	((1 << ROW_BITS) - 1)
+
+#define CS_ADDR_RSHIFT	0
+#define CS_ADDR_MASK	0
+
+#endif	/* __MICROCHIP_DDR2_TIMING_H */