1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2013 Atmel Corporation
3*4882a593Smuzhiyun * Bo Shen <voice.shen@atmel.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2015 Atmel Corporation
6*4882a593Smuzhiyun * Wenyou Yang <wenyou.yang@atmel.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun #include <asm/arch/atmel_mpddrc.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define SAMA5D3_MPDDRC_VERSION 0x140
16*4882a593Smuzhiyun
atmel_mpddr_op(const struct atmel_mpddr * mpddr,int mode,u32 ram_address)17*4882a593Smuzhiyun static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
18*4882a593Smuzhiyun int mode,
19*4882a593Smuzhiyun u32 ram_address)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun writel(mode, &mpddr->mr);
22*4882a593Smuzhiyun writel(0, ram_address);
23*4882a593Smuzhiyun }
24*4882a593Smuzhiyun
ddr2_decodtype_is_seq(const unsigned int base,u32 cr)25*4882a593Smuzhiyun static int ddr2_decodtype_is_seq(const unsigned int base, u32 cr)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
28*4882a593Smuzhiyun u16 version = readl(&mpddr->version) & 0xffff;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun if ((version >= SAMA5D3_MPDDRC_VERSION) &&
31*4882a593Smuzhiyun (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED))
32*4882a593Smuzhiyun return 0;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun return 1;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun
ddr2_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)38*4882a593Smuzhiyun int ddr2_init(const unsigned int base,
39*4882a593Smuzhiyun const unsigned int ram_address,
40*4882a593Smuzhiyun const struct atmel_mpddrc_config *mpddr_value)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun u32 ba_off, cr;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* Compute bank offset according to NC in configuration register */
47*4882a593Smuzhiyun ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
48*4882a593Smuzhiyun if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
49*4882a593Smuzhiyun ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* Program the memory device type into the memory device register */
54*4882a593Smuzhiyun writel(mpddr_value->md, &mpddr->md);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Program the configuration register */
57*4882a593Smuzhiyun writel(mpddr_value->cr, &mpddr->cr);
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* Program the timing register */
60*4882a593Smuzhiyun writel(mpddr_value->tpr0, &mpddr->tpr0);
61*4882a593Smuzhiyun writel(mpddr_value->tpr1, &mpddr->tpr1);
62*4882a593Smuzhiyun writel(mpddr_value->tpr2, &mpddr->tpr2);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* Issue a NOP command */
65*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* A 200 us is provided to precede any signal toggle */
68*4882a593Smuzhiyun udelay(200);
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* Issue a NOP command */
71*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* Issue an all banks precharge command */
74*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* Issue an extended mode register set(EMRS2) to choose operation */
77*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
78*4882a593Smuzhiyun ram_address + (0x2 << ba_off));
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* Issue an extended mode register set(EMRS3) to set EMSR to 0 */
81*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
82*4882a593Smuzhiyun ram_address + (0x3 << ba_off));
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /*
85*4882a593Smuzhiyun * Issue an extended mode register set(EMRS1) to enable DLL and
86*4882a593Smuzhiyun * program D.I.C (output driver impedance control)
87*4882a593Smuzhiyun */
88*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
89*4882a593Smuzhiyun ram_address + (0x1 << ba_off));
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun /* Enable DLL reset */
92*4882a593Smuzhiyun cr = readl(&mpddr->cr);
93*4882a593Smuzhiyun writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* A mode register set(MRS) cycle is issued to reset DLL */
96*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* Issue an all banks precharge command */
99*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /* Two auto-refresh (CBR) cycles are provided */
102*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
103*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /* Disable DLL reset */
106*4882a593Smuzhiyun cr = readl(&mpddr->cr);
107*4882a593Smuzhiyun writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* A mode register set (MRS) cycle is issued to disable DLL reset */
110*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* Set OCD calibration in default state */
113*4882a593Smuzhiyun cr = readl(&mpddr->cr);
114*4882a593Smuzhiyun writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /*
117*4882a593Smuzhiyun * An extended mode register set (EMRS1) cycle is issued
118*4882a593Smuzhiyun * to OCD default value
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
121*4882a593Smuzhiyun ram_address + (0x1 << ba_off));
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /* OCD calibration mode exit */
124*4882a593Smuzhiyun cr = readl(&mpddr->cr);
125*4882a593Smuzhiyun writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun * An extended mode register set (EMRS1) cycle is issued
129*4882a593Smuzhiyun * to enable OCD exit
130*4882a593Smuzhiyun */
131*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
132*4882a593Smuzhiyun ram_address + (0x1 << ba_off));
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* A nornal mode command is provided */
135*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* Perform a write access to any DDR2-SDRAM address */
138*4882a593Smuzhiyun writel(0, ram_address);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* Write the refresh rate */
141*4882a593Smuzhiyun writel(mpddr_value->rtr, &mpddr->rtr);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun return 0;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
ddr3_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)146*4882a593Smuzhiyun int ddr3_init(const unsigned int base,
147*4882a593Smuzhiyun const unsigned int ram_address,
148*4882a593Smuzhiyun const struct atmel_mpddrc_config *mpddr_value)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
151*4882a593Smuzhiyun u32 ba_off;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Compute bank offset according to NC in configuration register */
154*4882a593Smuzhiyun ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
155*4882a593Smuzhiyun if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
156*4882a593Smuzhiyun ba_off += ((mpddr_value->cr &
157*4882a593Smuzhiyun ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* Program the memory device type */
162*4882a593Smuzhiyun writel(mpddr_value->md, &mpddr->md);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /*
165*4882a593Smuzhiyun * Program features of the DDR3-SDRAM device and timing parameters
166*4882a593Smuzhiyun */
167*4882a593Smuzhiyun writel(mpddr_value->cr, &mpddr->cr);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun writel(mpddr_value->tpr0, &mpddr->tpr0);
170*4882a593Smuzhiyun writel(mpddr_value->tpr1, &mpddr->tpr1);
171*4882a593Smuzhiyun writel(mpddr_value->tpr2, &mpddr->tpr2);
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* A NOP command is issued to the DDR3-SRAM */
174*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* A pause of at least 500us must be observed before a single toggle. */
177*4882a593Smuzhiyun udelay(500);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* A NOP command is issued to the DDR3-SDRAM */
180*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /*
183*4882a593Smuzhiyun * An Extended Mode Register Set (EMRS2) cycle is issued to choose
184*4882a593Smuzhiyun * between commercial or high temperature operations.
185*4882a593Smuzhiyun */
186*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
187*4882a593Smuzhiyun ram_address + (0x2 << ba_off));
188*4882a593Smuzhiyun /*
189*4882a593Smuzhiyun * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
190*4882a593Smuzhiyun * the Extended Mode Register to 0.
191*4882a593Smuzhiyun */
192*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
193*4882a593Smuzhiyun ram_address + (0x3 << ba_off));
194*4882a593Smuzhiyun /*
195*4882a593Smuzhiyun * An Extended Mode Register Set (EMRS1) cycle is issued to disable and
196*4882a593Smuzhiyun * to program O.D.S. (Output Driver Strength).
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
199*4882a593Smuzhiyun ram_address + (0x1 << ba_off));
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun * Write a one to the DLL bit (enable DLL reset) in the MPDDRC
203*4882a593Smuzhiyun * Configuration Register.
204*4882a593Smuzhiyun */
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* A Mode Register Set (MRS) cycle is issued to reset DLL. */
207*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun udelay(50);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /*
212*4882a593Smuzhiyun * A Calibration command (MRS) is issued to calibrate RTT and RON
213*4882a593Smuzhiyun * values for the Process Voltage Temperature (PVT).
214*4882a593Smuzhiyun */
215*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* A Normal Mode command is provided. */
218*4882a593Smuzhiyun atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /* Perform a write access to any DDR3-SDRAM address. */
221*4882a593Smuzhiyun writel(0, ram_address);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /*
224*4882a593Smuzhiyun * Write the refresh rate into the COUNT field in the MPDDRC
225*4882a593Smuzhiyun * Refresh Timer Register (MPDDRC_RTR):
226*4882a593Smuzhiyun */
227*4882a593Smuzhiyun writel(mpddr_value->rtr, &mpddr->rtr);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return 0;
230*4882a593Smuzhiyun }
231