xref: /rk3399_rockchip-uboot/drivers/ddr/fsl/fsl_mmdc.c (revision cbe7706ab8aab06c18edaa9b120371f9c8012728)
1b9e745bbSShengzhou Liu /*
2b9e745bbSShengzhou Liu  * Copyright 2016 Freescale Semiconductor, Inc.
3b9e745bbSShengzhou Liu  *
4b9e745bbSShengzhou Liu  * SPDX-License-Identifier:     GPL-2.0+
5b9e745bbSShengzhou Liu  */
6b9e745bbSShengzhou Liu 
7b9e745bbSShengzhou Liu /*
8b9e745bbSShengzhou Liu  * Generic driver for Freescale MMDC(Multi Mode DDR Controller).
9b9e745bbSShengzhou Liu  */
10b9e745bbSShengzhou Liu 
11b9e745bbSShengzhou Liu #include <common.h>
12b9e745bbSShengzhou Liu #include <fsl_mmdc.h>
13b9e745bbSShengzhou Liu #include <asm/io.h>
14b9e745bbSShengzhou Liu 
set_wait_for_bits_clear(void * ptr,u32 value,u32 bits)15b9e745bbSShengzhou Liu static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
16b9e745bbSShengzhou Liu {
17b9e745bbSShengzhou Liu 	int timeout = 1000;
18b9e745bbSShengzhou Liu 
19b9e745bbSShengzhou Liu 	out_be32(ptr, value);
20b9e745bbSShengzhou Liu 
21b9e745bbSShengzhou Liu 	while (in_be32(ptr) & bits) {
22b9e745bbSShengzhou Liu 		udelay(100);
23b9e745bbSShengzhou Liu 		timeout--;
24b9e745bbSShengzhou Liu 	}
25b9e745bbSShengzhou Liu 	if (timeout <= 0)
26b9e745bbSShengzhou Liu 		printf("Error: %p wait for clear timeout.\n", ptr);
27b9e745bbSShengzhou Liu }
28b9e745bbSShengzhou Liu 
mmdc_init(const struct fsl_mmdc_info * priv)29*1fdcc8dfSYork Sun void mmdc_init(const struct fsl_mmdc_info *priv)
30b9e745bbSShengzhou Liu {
31b9e745bbSShengzhou Liu 	struct mmdc_regs *mmdc = (struct mmdc_regs *)CONFIG_SYS_FSL_DDR_ADDR;
32b9e745bbSShengzhou Liu 	unsigned int tmp;
33b9e745bbSShengzhou Liu 
34b9e745bbSShengzhou Liu 	/* 1. set configuration request */
35b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ);
36b9e745bbSShengzhou Liu 
37b9e745bbSShengzhou Liu 	/* 2. configure the desired timing parameters */
38*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdotc, priv->mdotc);
39*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdcfg0, priv->mdcfg0);
40*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdcfg1, priv->mdcfg1);
41*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdcfg2, priv->mdcfg2);
42b9e745bbSShengzhou Liu 
43b9e745bbSShengzhou Liu 	/* 3. configure DDR type and other miscellaneous parameters */
44*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdmisc, priv->mdmisc);
45b9e745bbSShengzhou Liu 	out_be32(&mmdc->mpmur0,	MMDC_MPMUR0_FRC_MSR);
46*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdrwd, priv->mdrwd);
47*1fdcc8dfSYork Sun 	out_be32(&mmdc->mpodtctrl, priv->mpodtctrl);
48b9e745bbSShengzhou Liu 
49b9e745bbSShengzhou Liu 	/* 4. configure the required delay while leaving reset */
50*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdor, priv->mdor);
51b9e745bbSShengzhou Liu 
52b9e745bbSShengzhou Liu 	/* 5. configure DDR physical parameters */
53b9e745bbSShengzhou Liu 	/* set row/column address width, burst length, data bus width */
54*1fdcc8dfSYork Sun 	tmp = priv->mdctl & ~(MDCTL_SDE0 | MDCTL_SDE1);
55b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdctl, tmp);
56b9e745bbSShengzhou Liu 	/* configure address space partition */
57*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdasp, priv->mdasp);
58b9e745bbSShengzhou Liu 
59b9e745bbSShengzhou Liu 	/* 6. perform a ZQ calibration - not needed here, doing in #8b */
60b9e745bbSShengzhou Liu 
61b9e745bbSShengzhou Liu 	/* 7. enable MMDC with the desired chip select */
62b9e745bbSShengzhou Liu #if (CONFIG_CHIP_SELECTS_PER_CTRL == 1)
63b9e745bbSShengzhou Liu 		out_be32(&mmdc->mdctl, tmp | MDCTL_SDE0);
64b9e745bbSShengzhou Liu #elif (CONFIG_CHIP_SELECTS_PER_CTRL == 2)
65b9e745bbSShengzhou Liu 		out_be32(&mmdc->mdctl, tmp | MDCTL_SDE0 | MDCTL_SDE1);
66b9e745bbSShengzhou Liu #endif
67b9e745bbSShengzhou Liu 
68b9e745bbSShengzhou Liu 	/* 8a. dram init sequence: update MRs for ZQ, ODT, PRE, etc */
69b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(8) | MDSCR_ENABLE_CON_REQ |
70b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_2);
71b9e745bbSShengzhou Liu 
72b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(0) | MDSCR_ENABLE_CON_REQ |
73b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
74b9e745bbSShengzhou Liu 
75b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
76b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
77b9e745bbSShengzhou Liu 
78b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_MSB_MR_OP(0x19) |
79b9e745bbSShengzhou Liu 				CMD_ADDR_LSB_MR_ADDR(0x30) |
80b9e745bbSShengzhou Liu 				MDSCR_ENABLE_CON_REQ |
81b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0);
82b9e745bbSShengzhou Liu 
83b9e745bbSShengzhou Liu 	/* 8b. ZQ calibration */
84b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_MSB_MR_OP(0x4) | MDSCR_ENABLE_CON_REQ |
85b9e745bbSShengzhou Liu 				CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0);
86b9e745bbSShengzhou Liu 
87*1fdcc8dfSYork Sun 	set_wait_for_bits_clear(&mmdc->mpzqhwctrl, priv->mpzqhwctrl,
88b9e745bbSShengzhou Liu 				MPZQHWCTRL_ZQ_HW_FORCE);
89b9e745bbSShengzhou Liu 
90b9e745bbSShengzhou Liu 	/* 9a. calibrations now, wr lvl */
91b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(0x84) |
92b9e745bbSShengzhou Liu 				MDSCR_ENABLE_CON_REQ |
93b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
94b9e745bbSShengzhou Liu 
95b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  MDSCR_ENABLE_CON_REQ | MDSCR_WL_EN |
96b9e745bbSShengzhou Liu 				CMD_NORMAL);
97b9e745bbSShengzhou Liu 
98b9e745bbSShengzhou Liu 	set_wait_for_bits_clear(&mmdc->mpwlgcr, MPWLGCR_HW_WL_EN,
99b9e745bbSShengzhou Liu 				MPWLGCR_HW_WL_EN);
100b9e745bbSShengzhou Liu 
101b9e745bbSShengzhou Liu 	mdelay(1);
102b9e745bbSShengzhou Liu 
103b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
104b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
105b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ);
106b9e745bbSShengzhou Liu 
107b9e745bbSShengzhou Liu 	mdelay(1);
108b9e745bbSShengzhou Liu 
109b9e745bbSShengzhou Liu 	/* 9b. read DQS gating calibration */
110b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ |
111b9e745bbSShengzhou Liu 				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0);
112b9e745bbSShengzhou Liu 
113b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
114b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
115b9e745bbSShengzhou Liu 
116b9e745bbSShengzhou Liu 	out_be32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN);
117b9e745bbSShengzhou Liu 
118b9e745bbSShengzhou Liu 	/* set absolute read delay offset */
119*1fdcc8dfSYork Sun 	if (priv->mprddlctl)
120*1fdcc8dfSYork Sun 		out_be32(&mmdc->mprddlctl, priv->mprddlctl);
121*1fdcc8dfSYork Sun 	else
122b9e745bbSShengzhou Liu 		out_be32(&mmdc->mprddlctl, MMDC_MPRDDLCTL_DEFAULT_DELAY);
123*1fdcc8dfSYork Sun 
124b9e745bbSShengzhou Liu 	set_wait_for_bits_clear(&mmdc->mpdgctrl0,
125b9e745bbSShengzhou Liu 				AUTO_RD_DQS_GATING_CALIBRATION_EN,
126b9e745bbSShengzhou Liu 				AUTO_RD_DQS_GATING_CALIBRATION_EN);
127b9e745bbSShengzhou Liu 
128b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG |
129b9e745bbSShengzhou Liu 				CMD_BANK_ADDR_3);
130b9e745bbSShengzhou Liu 
131b9e745bbSShengzhou Liu 	/* 9c. read calibration */
132b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ |
133b9e745bbSShengzhou Liu 				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0);
134b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
135b9e745bbSShengzhou Liu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
136b9e745bbSShengzhou Liu 	out_be32(&mmdc->mppdcmpr2,  MPPDCMPR2_MPR_COMPARE_EN);
137b9e745bbSShengzhou Liu 	set_wait_for_bits_clear(&mmdc->mprddlhwctl,
138b9e745bbSShengzhou Liu 				MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN,
139b9e745bbSShengzhou Liu 				MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN);
140b9e745bbSShengzhou Liu 
141b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr,  MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG |
142b9e745bbSShengzhou Liu 				CMD_BANK_ADDR_3);
143b9e745bbSShengzhou Liu 
144b9e745bbSShengzhou Liu 	/* 10. configure power-down, self-refresh entry, exit parameters */
145*1fdcc8dfSYork Sun 	out_be32(&mmdc->mdpdc, priv->mdpdc);
146b9e745bbSShengzhou Liu 	out_be32(&mmdc->mapsr, MMDC_MAPSR_PWR_SAV_CTRL_STAT);
147b9e745bbSShengzhou Liu 
148b9e745bbSShengzhou Liu 	/* 11. ZQ config again? do nothing here */
149b9e745bbSShengzhou Liu 
150b9e745bbSShengzhou Liu 	/* 12. refresh scheme */
151*1fdcc8dfSYork Sun 	set_wait_for_bits_clear(&mmdc->mdref, priv->mdref,
152b9e745bbSShengzhou Liu 				MDREF_START_REFRESH);
153b9e745bbSShengzhou Liu 
154b9e745bbSShengzhou Liu 	/* 13. disable CON_REQ */
155b9e745bbSShengzhou Liu 	out_be32(&mmdc->mdscr, MDSCR_DISABLE_CFG_REQ);
156b9e745bbSShengzhou Liu }
157