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