blob: 1d9324a9ab776219597ce4c708e64835ec0668dd [file] [log] [blame]
Dinh Nguyen9bbd2132015-06-02 22:52:48 -05001/*
2 * Copyright Altera Corporation (C) 2014-2015
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6#include <common.h>
7#include <div64.h>
8#include <watchdog.h>
9#include <asm/arch/fpga_manager.h>
10#include <asm/arch/sdram.h>
Dinh Nguyen9bbd2132015-06-02 22:52:48 -050011#include <asm/arch/system_manager.h>
12#include <asm/io.h>
13
Marek Vasutd04941c2015-07-12 15:59:10 +020014/*
15 * FIXME: This path is temporary until the SDRAM driver gets
16 * a proper thorough cleanup.
17 */
18#include "../../../board/altera/socfpga/qts/sdram_config.h"
19
Dinh Nguyen9bbd2132015-06-02 22:52:48 -050020DECLARE_GLOBAL_DATA_PTR;
21
Marek Vasut42f7ebb2015-07-26 10:37:54 +020022struct sdram_prot_rule {
23 u64 sdram_start; /* SDRAM start address */
24 u64 sdram_end; /* SDRAM end address */
25 u32 rule; /* SDRAM protection rule number: 0-19 */
26 int valid; /* Rule valid or not? 1 - valid, 0 not*/
27
28 u32 security;
29 u32 portmask;
30 u32 result;
31 u32 lo_prot_id;
32 u32 hi_prot_id;
33};
34
Dinh Nguyen9bbd2132015-06-02 22:52:48 -050035static struct socfpga_system_manager *sysmgr_regs =
36 (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
37static struct socfpga_sdr_ctrl *sdr_ctrl =
Marek Vasut17fdc912015-07-12 20:05:54 +020038 (struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -050039
Marek Vasut04ae4482015-08-01 20:30:10 +020040static struct socfpga_sdram_config {
41 u32 ctrl_cfg;
42 u32 dram_timing1;
43 u32 dram_timing2;
44 u32 dram_timing3;
45 u32 dram_timing4;
46 u32 lowpwr_timing;
Marek Vasutdc3b91d2015-08-01 20:58:44 +020047 u32 dram_odt;
Marek Vasut04ae4482015-08-01 20:30:10 +020048 u32 dram_addrw;
Marek Vasutdc3b91d2015-08-01 20:58:44 +020049 u32 dram_if_width;
50 u32 dram_dev_width;
51 u32 dram_intr;
52 u32 lowpwr_eq;
Marek Vasut04ae4482015-08-01 20:30:10 +020053 u32 static_cfg;
Marek Vasutdc3b91d2015-08-01 20:58:44 +020054 u32 ctrl_width;
55 u32 cport_width;
56 u32 cport_wmap;
57 u32 cport_rmap;
58 u32 rfifo_cmap;
59 u32 wfifo_cmap;
60 u32 cport_rdwr;
61 u32 port_cfg;
62 u32 fpgaport_rst;
Marek Vasut04ae4482015-08-01 20:30:10 +020063 u32 fifo_cfg;
Marek Vasutdc3b91d2015-08-01 20:58:44 +020064 u32 mp_priority;
Marek Vasut04ae4482015-08-01 20:30:10 +020065 u32 mp_weight0;
66 u32 mp_weight1;
67 u32 mp_weight2;
68 u32 mp_weight3;
69 u32 mp_pacing0;
70 u32 mp_pacing1;
71 u32 mp_pacing2;
72 u32 mp_pacing3;
73 u32 mp_threshold0;
74 u32 mp_threshold1;
75 u32 mp_threshold2;
Marek Vasutdc3b91d2015-08-01 20:58:44 +020076 u32 phy_ctrl0;
Marek Vasut04ae4482015-08-01 20:30:10 +020077} sdram_config = {
78 .ctrl_cfg =
79 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE <<
80 SDR_CTRLGRP_CTRLCFG_MEMTYPE_LSB) |
81 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMBL <<
82 SDR_CTRLGRP_CTRLCFG_MEMBL_LSB) |
Marek Vasut764aa9a2015-08-01 21:16:20 +020083 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER <<
84 SDR_CTRLGRP_CTRLCFG_ADDRORDER_LSB) |
Marek Vasut04ae4482015-08-01 20:30:10 +020085 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCEN <<
86 SDR_CTRLGRP_CTRLCFG_ECCEN_LSB) |
87 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCCORREN <<
88 SDR_CTRLGRP_CTRLCFG_ECCCORREN_LSB) |
89 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_REORDEREN <<
90 SDR_CTRLGRP_CTRLCFG_REORDEREN_LSB) |
91 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_STARVELIMIT <<
92 SDR_CTRLGRP_CTRLCFG_STARVELIMIT_LSB) |
93 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_DQSTRKEN <<
94 SDR_CTRLGRP_CTRLCFG_DQSTRKEN_LSB) |
95 (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_NODMPINS <<
96 SDR_CTRLGRP_CTRLCFG_NODMPINS_LSB),
97 .dram_timing1 =
98 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCWL <<
99 SDR_CTRLGRP_DRAMTIMING1_TCWL_LSB) |
100 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_AL <<
101 SDR_CTRLGRP_DRAMTIMING1_TAL_LSB) |
102 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCL <<
103 SDR_CTRLGRP_DRAMTIMING1_TCL_LSB) |
104 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRRD <<
105 SDR_CTRLGRP_DRAMTIMING1_TRRD_LSB) |
106 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TFAW <<
107 SDR_CTRLGRP_DRAMTIMING1_TFAW_LSB) |
108 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRFC <<
109 SDR_CTRLGRP_DRAMTIMING1_TRFC_LSB),
110 .dram_timing2 =
111 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TREFI <<
112 SDR_CTRLGRP_DRAMTIMING2_TREFI_LSB) |
113 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRCD <<
114 SDR_CTRLGRP_DRAMTIMING2_TRCD_LSB) |
115 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRP <<
116 SDR_CTRLGRP_DRAMTIMING2_TRP_LSB) |
117 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWR <<
118 SDR_CTRLGRP_DRAMTIMING2_TWR_LSB) |
119 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWTR <<
120 SDR_CTRLGRP_DRAMTIMING2_TWTR_LSB),
121 .dram_timing3 =
122 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRTP <<
123 SDR_CTRLGRP_DRAMTIMING3_TRTP_LSB) |
124 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRAS <<
125 SDR_CTRLGRP_DRAMTIMING3_TRAS_LSB) |
126 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRC <<
127 SDR_CTRLGRP_DRAMTIMING3_TRC_LSB) |
128 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TMRD <<
129 SDR_CTRLGRP_DRAMTIMING3_TMRD_LSB) |
130 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TCCD <<
131 SDR_CTRLGRP_DRAMTIMING3_TCCD_LSB),
132 .dram_timing4 =
133 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING4_SELFRFSHEXIT <<
134 SDR_CTRLGRP_DRAMTIMING4_SELFRFSHEXIT_LSB) |
135 (CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING4_PWRDOWNEXIT <<
136 SDR_CTRLGRP_DRAMTIMING4_PWRDOWNEXIT_LSB),
137 .lowpwr_timing =
138 (CONFIG_HPS_SDR_CTRLCFG_LOWPWRTIMING_AUTOPDCYCLES <<
139 SDR_CTRLGRP_LOWPWRTIMING_AUTOPDCYCLES_LSB) |
140 (CONFIG_HPS_SDR_CTRLCFG_LOWPWRTIMING_CLKDISABLECYCLES <<
141 SDR_CTRLGRP_LOWPWRTIMING_CLKDISABLECYCLES_LSB),
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200142 .dram_odt =
143 (CONFIG_HPS_SDR_CTRLCFG_DRAMODT_READ <<
144 SDR_CTRLGRP_DRAMODT_READ_LSB) |
145 (CONFIG_HPS_SDR_CTRLCFG_DRAMODT_WRITE <<
146 SDR_CTRLGRP_DRAMODT_WRITE_LSB),
Marek Vasut04ae4482015-08-01 20:30:10 +0200147 .dram_addrw =
148 (CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS <<
149 SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB) |
Marek Vasut764aa9a2015-08-01 21:16:20 +0200150 (CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS <<
151 SDR_CTRLGRP_DRAMADDRW_ROWBITS_LSB) |
Marek Vasut04ae4482015-08-01 20:30:10 +0200152 (CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS <<
153 SDR_CTRLGRP_DRAMADDRW_BANKBITS_LSB) |
154 ((CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS - 1) <<
155 SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB),
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200156 .dram_if_width =
157 (CONFIG_HPS_SDR_CTRLCFG_DRAMIFWIDTH_IFWIDTH <<
158 SDR_CTRLGRP_DRAMIFWIDTH_IFWIDTH_LSB),
159 .dram_dev_width =
160 (CONFIG_HPS_SDR_CTRLCFG_DRAMDEVWIDTH_DEVWIDTH <<
161 SDR_CTRLGRP_DRAMDEVWIDTH_DEVWIDTH_LSB),
162 .dram_intr =
163 (CONFIG_HPS_SDR_CTRLCFG_DRAMINTR_INTREN <<
164 SDR_CTRLGRP_DRAMINTR_INTREN_LSB),
165 .lowpwr_eq =
166 (CONFIG_HPS_SDR_CTRLCFG_LOWPWREQ_SELFRFSHMASK <<
167 SDR_CTRLGRP_LOWPWREQ_SELFRFSHMASK_LSB),
Marek Vasut04ae4482015-08-01 20:30:10 +0200168 .static_cfg =
169 (CONFIG_HPS_SDR_CTRLCFG_STATICCFG_MEMBL <<
170 SDR_CTRLGRP_STATICCFG_MEMBL_LSB) |
171 (CONFIG_HPS_SDR_CTRLCFG_STATICCFG_USEECCASDATA <<
172 SDR_CTRLGRP_STATICCFG_USEECCASDATA_LSB),
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200173 .ctrl_width =
174 (CONFIG_HPS_SDR_CTRLCFG_CTRLWIDTH_CTRLWIDTH <<
175 SDR_CTRLGRP_CTRLWIDTH_CTRLWIDTH_LSB),
176 .cport_width =
177 (CONFIG_HPS_SDR_CTRLCFG_CPORTWIDTH_CPORTWIDTH <<
178 SDR_CTRLGRP_CPORTWIDTH_CMDPORTWIDTH_LSB),
179 .cport_wmap =
180 (CONFIG_HPS_SDR_CTRLCFG_CPORTWMAP_CPORTWMAP <<
181 SDR_CTRLGRP_CPORTWMAP_CPORTWFIFOMAP_LSB),
182 .cport_rmap =
183 (CONFIG_HPS_SDR_CTRLCFG_CPORTRMAP_CPORTRMAP <<
184 SDR_CTRLGRP_CPORTRMAP_CPORTRFIFOMAP_LSB),
185 .rfifo_cmap =
186 (CONFIG_HPS_SDR_CTRLCFG_RFIFOCMAP_RFIFOCMAP <<
187 SDR_CTRLGRP_RFIFOCMAP_RFIFOCPORTMAP_LSB),
188 .wfifo_cmap =
189 (CONFIG_HPS_SDR_CTRLCFG_WFIFOCMAP_WFIFOCMAP <<
190 SDR_CTRLGRP_WFIFOCMAP_WFIFOCPORTMAP_LSB),
191 .cport_rdwr =
192 (CONFIG_HPS_SDR_CTRLCFG_CPORTRDWR_CPORTRDWR <<
193 SDR_CTRLGRP_CPORTRDWR_CPORTRDWR_LSB),
194 .port_cfg =
195 (CONFIG_HPS_SDR_CTRLCFG_PORTCFG_AUTOPCHEN <<
196 SDR_CTRLGRP_PORTCFG_AUTOPCHEN_LSB),
197 .fpgaport_rst = CONFIG_HPS_SDR_CTRLCFG_FPGAPORTRST,
Marek Vasut04ae4482015-08-01 20:30:10 +0200198 .fifo_cfg =
199 (CONFIG_HPS_SDR_CTRLCFG_FIFOCFG_SYNCMODE <<
200 SDR_CTRLGRP_FIFOCFG_SYNCMODE_LSB) |
201 (CONFIG_HPS_SDR_CTRLCFG_FIFOCFG_INCSYNC <<
202 SDR_CTRLGRP_FIFOCFG_INCSYNC_LSB),
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200203 .mp_priority =
204 (CONFIG_HPS_SDR_CTRLCFG_MPPRIORITY_USERPRIORITY <<
205 SDR_CTRLGRP_MPPRIORITY_USERPRIORITY_LSB),
Marek Vasut04ae4482015-08-01 20:30:10 +0200206 .mp_weight0 =
207 (CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_0_STATICWEIGHT_31_0 <<
208 SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_STATICWEIGHT_31_0_LSB),
209 .mp_weight1 =
210 (CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_STATICWEIGHT_49_32 <<
211 SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_STATICWEIGHT_49_32_LSB) |
212 (CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_SUMOFWEIGHT_13_0 <<
213 SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_SUMOFWEIGHTS_13_0_LSB),
214 .mp_weight2 =
215 (CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_2_SUMOFWEIGHT_45_14 <<
216 SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_SUMOFWEIGHTS_45_14_LSB),
217 .mp_weight3 =
218 (CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_3_SUMOFWEIGHT_63_46 <<
219 SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_SUMOFWEIGHTS_63_46_LSB),
220 .mp_pacing0 =
221 (CONFIG_HPS_SDR_CTRLCFG_MPPACING_0_THRESHOLD1_31_0 <<
222 SDR_CTRLGRP_MPPACING_MPPACING_0_THRESHOLD1_31_0_LSB),
223 .mp_pacing1 =
224 (CONFIG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD1_59_32 <<
225 SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD1_59_32_LSB) |
226 (CONFIG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD2_3_0 <<
227 SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD2_3_0_LSB),
228 .mp_pacing2 =
229 (CONFIG_HPS_SDR_CTRLCFG_MPPACING_2_THRESHOLD2_35_4 <<
230 SDR_CTRLGRP_MPPACING_MPPACING_2_THRESHOLD2_35_4_LSB),
231 .mp_pacing3 =
232 (CONFIG_HPS_SDR_CTRLCFG_MPPACING_3_THRESHOLD2_59_36 <<
233 SDR_CTRLGRP_MPPACING_MPPACING_3_THRESHOLD2_59_36_LSB),
234 .mp_threshold0 =
235 (CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0 <<
236 SDR_CTRLGRP_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0_LSB),
237 .mp_threshold1 =
238 (CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32 <<
239 SDR_CTRLGRP_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32_LSB),
240 .mp_threshold2 =
241 (CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64 <<
242 SDR_CTRLGRP_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64_LSB),
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200243 .phy_ctrl0 = CONFIG_HPS_SDR_CTRLCFG_PHYCTRL_PHYCTRL_0,
Marek Vasut04ae4482015-08-01 20:30:10 +0200244};
245
Marek Vasutf3671692015-08-01 19:20:19 +0200246/**
247 * get_errata_rows() - Up the number of DRAM rows to cover entire address space
Marek Vasut764aa9a2015-08-01 21:16:20 +0200248 * @cfg: SDRAM controller configuration data
Marek Vasutf3671692015-08-01 19:20:19 +0200249 *
250 * SDRAM Failure happens when accessing non-existent memory. Artificially
251 * increase the number of rows so that the memory controller thinks it has
252 * 4GB of RAM. This function returns such amount of rows.
253 */
Marek Vasut764aa9a2015-08-01 21:16:20 +0200254static int get_errata_rows(struct socfpga_sdram_config *cfg)
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500255{
Marek Vasutf3671692015-08-01 19:20:19 +0200256 /* Define constant for 4G memory - used for SDRAM errata workaround */
257#define MEMSIZE_4G (4ULL * 1024ULL * 1024ULL * 1024ULL)
258 const unsigned long long memsize = MEMSIZE_4G;
Marek Vasut764aa9a2015-08-01 21:16:20 +0200259 const unsigned int cs =
260 ((cfg->dram_addrw & SDR_CTRLGRP_DRAMADDRW_CSBITS_MASK) >>
261 SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB) + 1;
262 const unsigned int rows =
263 (cfg->dram_addrw & SDR_CTRLGRP_DRAMADDRW_ROWBITS_MASK) >>
264 SDR_CTRLGRP_DRAMADDRW_ROWBITS_LSB;
265 const unsigned int banks =
266 (cfg->dram_addrw & SDR_CTRLGRP_DRAMADDRW_BANKBITS_MASK) >>
267 SDR_CTRLGRP_DRAMADDRW_BANKBITS_LSB;
268 const unsigned int cols =
269 (cfg->dram_addrw & SDR_CTRLGRP_DRAMADDRW_COLBITS_MASK) >>
270 SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB;
Marek Vasutf3671692015-08-01 19:20:19 +0200271 const unsigned int width = 8;
272
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500273 unsigned long long newrows;
Marek Vasutf3671692015-08-01 19:20:19 +0200274 int bits, inewrowslog2;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500275
276 debug("workaround rows - memsize %lld\n", memsize);
277 debug("workaround rows - cs %d\n", cs);
278 debug("workaround rows - width %d\n", width);
279 debug("workaround rows - rows %d\n", rows);
280 debug("workaround rows - banks %d\n", banks);
281 debug("workaround rows - cols %d\n", cols);
282
Marek Vasut791d20e2015-08-01 18:54:34 +0200283 newrows = lldiv(memsize, cs * (width / 8));
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500284 debug("rows workaround - term1 %lld\n", newrows);
285
Marek Vasut791d20e2015-08-01 18:54:34 +0200286 newrows = lldiv(newrows, (1 << banks) * (1 << cols));
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500287 debug("rows workaround - term2 %lld\n", newrows);
288
Marek Vasut791d20e2015-08-01 18:54:34 +0200289 /*
290 * Compute the hamming weight - same as number of bits set.
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500291 * Need to see if result is ordinal power of 2 before
292 * attempting log2 of result.
293 */
Marek Vasut58d86142015-08-01 18:46:55 +0200294 bits = generic_hweight32(newrows);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500295
296 debug("rows workaround - bits %d\n", bits);
297
298 if (bits != 1) {
299 printf("SDRAM workaround failed, bits set %d\n", bits);
300 return rows;
301 }
302
303 if (newrows > UINT_MAX) {
304 printf("SDRAM workaround rangecheck failed, %lld\n", newrows);
305 return rows;
306 }
307
Marek Vasut791d20e2015-08-01 18:54:34 +0200308 inewrowslog2 = __ilog2(newrows);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500309
Marek Vasut791d20e2015-08-01 18:54:34 +0200310 debug("rows workaround - ilog2 %d, %lld\n", inewrowslog2, newrows);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500311
312 if (inewrowslog2 == -1) {
Marek Vasut791d20e2015-08-01 18:54:34 +0200313 printf("SDRAM workaround failed, newrows %lld\n", newrows);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500314 return rows;
315 }
316
317 return inewrowslog2;
318}
319
320/* SDRAM protection rules vary from 0-19, a total of 20 rules. */
321static void sdram_set_rule(struct sdram_prot_rule *prule)
322{
323 uint32_t lo_addr_bits;
324 uint32_t hi_addr_bits;
325 int ruleno = prule->rule;
326
327 /* Select the rule */
328 writel(ruleno, &sdr_ctrl->prot_rule_rdwr);
329
330 /* Obtain the address bits */
331 lo_addr_bits = (uint32_t)(((prule->sdram_start) >> 20ULL) & 0xFFF);
332 hi_addr_bits = (uint32_t)((((prule->sdram_end-1) >> 20ULL)) & 0xFFF);
333
334 debug("sdram set rule start %x, %lld\n", lo_addr_bits,
335 prule->sdram_start);
336 debug("sdram set rule end %x, %lld\n", hi_addr_bits,
337 prule->sdram_end);
338
339 /* Set rule addresses */
340 writel(lo_addr_bits | (hi_addr_bits << 12), &sdr_ctrl->prot_rule_addr);
341
342 /* Set rule protection ids */
343 writel(prule->lo_prot_id | (prule->hi_prot_id << 12),
344 &sdr_ctrl->prot_rule_id);
345
346 /* Set the rule data */
347 writel(prule->security | (prule->valid << 2) |
348 (prule->portmask << 3) | (prule->result << 13),
349 &sdr_ctrl->prot_rule_data);
350
351 /* write the rule */
352 writel(ruleno | (1L << 5), &sdr_ctrl->prot_rule_rdwr);
353
354 /* Set rule number to 0 by default */
355 writel(0, &sdr_ctrl->prot_rule_rdwr);
356}
357
358static void sdram_get_rule(struct sdram_prot_rule *prule)
359{
360 uint32_t addr;
361 uint32_t id;
362 uint32_t data;
363 int ruleno = prule->rule;
364
365 /* Read the rule */
366 writel(ruleno, &sdr_ctrl->prot_rule_rdwr);
367 writel(ruleno | (1L << 6), &sdr_ctrl->prot_rule_rdwr);
368
369 /* Get the addresses */
370 addr = readl(&sdr_ctrl->prot_rule_addr);
371 prule->sdram_start = (addr & 0xFFF) << 20;
372 prule->sdram_end = ((addr >> 12) & 0xFFF) << 20;
373
374 /* Get the configured protection IDs */
375 id = readl(&sdr_ctrl->prot_rule_id);
376 prule->lo_prot_id = id & 0xFFF;
377 prule->hi_prot_id = (id >> 12) & 0xFFF;
378
379 /* Get protection data */
380 data = readl(&sdr_ctrl->prot_rule_data);
381
382 prule->security = data & 0x3;
383 prule->valid = (data >> 2) & 0x1;
384 prule->portmask = (data >> 3) & 0x3FF;
385 prule->result = (data >> 13) & 0x1;
386}
387
388static void sdram_set_protection_config(uint64_t sdram_start, uint64_t sdram_end)
389{
390 struct sdram_prot_rule rule;
391 int rules;
392
393 /* Start with accepting all SDRAM transaction */
394 writel(0x0, &sdr_ctrl->protport_default);
395
396 /* Clear all protection rules for warm boot case */
397 memset(&rule, 0, sizeof(struct sdram_prot_rule));
398
399 for (rules = 0; rules < 20; rules++) {
400 rule.rule = rules;
401 sdram_set_rule(&rule);
402 }
403
404 /* new rule: accept SDRAM */
405 rule.sdram_start = sdram_start;
406 rule.sdram_end = sdram_end;
407 rule.lo_prot_id = 0x0;
408 rule.hi_prot_id = 0xFFF;
409 rule.portmask = 0x3FF;
410 rule.security = 0x3;
411 rule.result = 0;
412 rule.valid = 1;
413 rule.rule = 0;
414
415 /* set new rule */
416 sdram_set_rule(&rule);
417
418 /* default rule: reject everything */
419 writel(0x3ff, &sdr_ctrl->protport_default);
420}
421
422static void sdram_dump_protection_config(void)
423{
424 struct sdram_prot_rule rule;
425 int rules;
426
427 debug("SDRAM Prot rule, default %x\n",
428 readl(&sdr_ctrl->protport_default));
429
430 for (rules = 0; rules < 20; rules++) {
431 sdram_get_rule(&rule);
432 debug("Rule %d, rules ...\n", rules);
433 debug(" sdram start %llx\n", rule.sdram_start);
434 debug(" sdram end %llx\n", rule.sdram_end);
435 debug(" low prot id %d, hi prot id %d\n",
436 rule.lo_prot_id,
437 rule.hi_prot_id);
438 debug(" portmask %x\n", rule.portmask);
439 debug(" security %d\n", rule.security);
440 debug(" result %d\n", rule.result);
441 debug(" valid %d\n", rule.valid);
442 }
443}
444
445/* Function to write to register and verify the write */
446static unsigned sdram_write_verify(unsigned int *addr, unsigned reg_value)
447{
448#ifndef SDRAM_MMR_SKIP_VERIFY
449 unsigned reg_value1;
450#endif
451 debug(" Write - Address ");
452 debug("0x%08x Data 0x%08x\n", (u32)addr, reg_value);
453 /* Write to register */
454 writel(reg_value, addr);
455#ifndef SDRAM_MMR_SKIP_VERIFY
456 debug(" Read and verify...");
457 /* Read back the wrote value */
458 reg_value1 = readl(addr);
459 /* Indicate failure if value not matched */
460 if (reg_value1 != reg_value) {
461 debug("FAIL - Address 0x%08x Expected 0x%08x Data 0x%08x\n",
462 (u32)addr, reg_value, reg_value1);
463 return 1;
464 }
465 debug("correct!\n");
466#endif /* SDRAM_MMR_SKIP_VERIFY */
467 return 0;
468}
469
Marek Vasut9d6b0122015-08-01 21:24:31 +0200470static u32 sdr_get_ctrlcfg(struct socfpga_sdram_config *cfg)
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500471{
Marek Vasut764aa9a2015-08-01 21:16:20 +0200472 const u32 csbits =
473 ((cfg->dram_addrw & SDR_CTRLGRP_DRAMADDRW_CSBITS_MASK) >>
474 SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB) + 1;
475 u32 addrorder =
476 (cfg->ctrl_cfg & SDR_CTRLGRP_CTRLCFG_ADDRORDER_MASK) >>
477 SDR_CTRLGRP_CTRLCFG_ADDRORDER_LSB;
478
Marek Vasut04ae4482015-08-01 20:30:10 +0200479 u32 ctrl_cfg = cfg->ctrl_cfg;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500480
Marek Vasut067c8532015-08-01 19:33:40 +0200481 /*
482 * SDRAM Failure When Accessing Non-Existent Memory
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500483 * Set the addrorder field of the SDRAM control register
484 * based on the CSBITs setting.
485 */
Marek Vasut764aa9a2015-08-01 21:16:20 +0200486 if (csbits == 1) {
487 if (addrorder != 0)
Marek Vasut067c8532015-08-01 19:33:40 +0200488 debug("INFO: Changing address order to 0 (chip, row, bank, column)\n");
Marek Vasut764aa9a2015-08-01 21:16:20 +0200489 addrorder = 0;
490 } else if (csbits == 2) {
491 if (addrorder != 2)
Marek Vasut067c8532015-08-01 19:33:40 +0200492 debug("INFO: Changing address order to 2 (row, chip, bank, column)\n");
Marek Vasut764aa9a2015-08-01 21:16:20 +0200493 addrorder = 2;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500494 }
495
Marek Vasut764aa9a2015-08-01 21:16:20 +0200496 ctrl_cfg &= ~SDR_CTRLGRP_CTRLCFG_ADDRORDER_MASK;
Marek Vasut067c8532015-08-01 19:33:40 +0200497 ctrl_cfg |= addrorder << SDR_CTRLGRP_CTRLCFG_ADDRORDER_LSB;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500498
Marek Vasut9d6b0122015-08-01 21:24:31 +0200499 return ctrl_cfg;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500500}
501
Marek Vasut9d6b0122015-08-01 21:24:31 +0200502static u32 sdr_get_addr_rw(struct socfpga_sdram_config *cfg)
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500503{
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500504 /*
505 * SDRAM Failure When Accessing Non-Existent Memory
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500506 * Set SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB to
507 * log2(number of chip select bits). Since there's only
508 * 1 or 2 chip selects, log2(1) => 0, and log2(2) => 1,
509 * which is the same as "chip selects" - 1.
510 */
Marek Vasut764aa9a2015-08-01 21:16:20 +0200511 const int rows = get_errata_rows(cfg);
512 u32 dram_addrw = cfg->dram_addrw & ~SDR_CTRLGRP_DRAMADDRW_ROWBITS_MASK;
Marek Vasut04ae4482015-08-01 20:30:10 +0200513
Marek Vasut9d6b0122015-08-01 21:24:31 +0200514 return dram_addrw | (rows << SDR_CTRLGRP_DRAMADDRW_ROWBITS_LSB);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500515}
516
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500517/* Function to initialize SDRAM MMR */
518unsigned sdram_mmr_init_full(unsigned int sdr_phy_reg)
519{
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500520 unsigned long status = 0;
Marek Vasut04ae4482015-08-01 20:30:10 +0200521 struct socfpga_sdram_config *cfg = &sdram_config;
Marek Vasut764aa9a2015-08-01 21:16:20 +0200522 const unsigned int rows =
523 (cfg->dram_addrw & SDR_CTRLGRP_DRAMADDRW_ROWBITS_MASK) >>
524 SDR_CTRLGRP_DRAMADDRW_ROWBITS_LSB;
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500525
Marek Vasut9d6b0122015-08-01 21:24:31 +0200526 const u32 ctrl_cfg = sdr_get_ctrlcfg(cfg);
527 const u32 dram_addrw = sdr_get_addr_rw(cfg);
528
Marek Vasut764aa9a2015-08-01 21:16:20 +0200529 writel(rows, &sysmgr_regs->iswgrp_handoff[4]);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500530
Marek Vasut9d6b0122015-08-01 21:24:31 +0200531 debug("\nConfiguring CTRLCFG\n");
532 writel(ctrl_cfg, &sdr_ctrl->ctrl_cfg);
Marek Vasut076470e2015-08-01 21:21:21 +0200533
534 debug("Configuring DRAMTIMING1\n");
535 writel(cfg->dram_timing1, &sdr_ctrl->dram_timing1);
536
537 debug("Configuring DRAMTIMING2\n");
538 writel(cfg->dram_timing2, &sdr_ctrl->dram_timing2);
539
540 debug("Configuring DRAMTIMING3\n");
541 writel(cfg->dram_timing3, &sdr_ctrl->dram_timing3);
542
543 debug("Configuring DRAMTIMING4\n");
544 writel(cfg->dram_timing4, &sdr_ctrl->dram_timing4);
545
546 debug("Configuring LOWPWRTIMING\n");
547 writel(cfg->lowpwr_timing, &sdr_ctrl->lowpwr_timing);
548
Marek Vasut9d6b0122015-08-01 21:24:31 +0200549 debug("Configuring DRAMADDRW\n");
550 writel(dram_addrw, &sdr_ctrl->dram_addrw);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500551
552 debug("Configuring DRAMIFWIDTH\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200553 writel(cfg->dram_if_width, &sdr_ctrl->dram_if_width);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500554
555 debug("Configuring DRAMDEVWIDTH\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200556 writel(cfg->dram_dev_width, &sdr_ctrl->dram_dev_width);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500557
558 debug("Configuring LOWPWREQ\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200559 writel(cfg->lowpwr_eq, &sdr_ctrl->lowpwr_eq);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500560
561 debug("Configuring DRAMINTR\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200562 writel(cfg->dram_intr, &sdr_ctrl->dram_intr);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500563
Marek Vasut076470e2015-08-01 21:21:21 +0200564 debug("Configuring STATICCFG\n");
565 writel(cfg->static_cfg, &sdr_ctrl->static_cfg);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500566
567 debug("Configuring CTRLWIDTH\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200568 writel(cfg->ctrl_width, &sdr_ctrl->ctrl_width);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500569
570 debug("Configuring PORTCFG\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200571 writel(cfg->port_cfg, &sdr_ctrl->port_cfg);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500572
Marek Vasut076470e2015-08-01 21:21:21 +0200573 debug("Configuring FIFOCFG\n");
574 writel(cfg->fifo_cfg, &sdr_ctrl->fifo_cfg);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500575
576 debug("Configuring MPPRIORITY\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200577 writel(cfg->mp_priority, &sdr_ctrl->mp_priority);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500578
Marek Vasut076470e2015-08-01 21:21:21 +0200579 debug("Configuring MPWEIGHT_MPWEIGHT_0\n");
580 writel(cfg->mp_weight0, &sdr_ctrl->mp_weight0);
581 writel(cfg->mp_weight1, &sdr_ctrl->mp_weight1);
582 writel(cfg->mp_weight2, &sdr_ctrl->mp_weight2);
583 writel(cfg->mp_weight3, &sdr_ctrl->mp_weight3);
584
585 debug("Configuring MPPACING_MPPACING_0\n");
586 writel(cfg->mp_pacing0, &sdr_ctrl->mp_pacing0);
587 writel(cfg->mp_pacing1, &sdr_ctrl->mp_pacing1);
588 writel(cfg->mp_pacing2, &sdr_ctrl->mp_pacing2);
589 writel(cfg->mp_pacing3, &sdr_ctrl->mp_pacing3);
590
591 debug("Configuring MPTHRESHOLDRST_MPTHRESHOLDRST_0\n");
592 writel(cfg->mp_threshold0, &sdr_ctrl->mp_threshold0);
593 writel(cfg->mp_threshold1, &sdr_ctrl->mp_threshold1);
594 writel(cfg->mp_threshold2, &sdr_ctrl->mp_threshold2);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500595
596 debug("Configuring PHYCTRL_PHYCTRL_0\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200597 writel(cfg->phy_ctrl0, &sdr_ctrl->phy_ctrl0);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500598
599 debug("Configuring CPORTWIDTH\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200600 writel(cfg->cport_width, &sdr_ctrl->cport_width);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500601
602 debug("Configuring CPORTWMAP\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200603 writel(cfg->cport_wmap, &sdr_ctrl->cport_wmap);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500604
605 debug("Configuring CPORTRMAP\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200606 writel(cfg->cport_rmap, &sdr_ctrl->cport_rmap);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500607
608 debug("Configuring RFIFOCMAP\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200609 writel(cfg->rfifo_cmap, &sdr_ctrl->rfifo_cmap);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500610
611 debug("Configuring WFIFOCMAP\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200612 writel(cfg->wfifo_cmap, &sdr_ctrl->wfifo_cmap);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500613
614 debug("Configuring CPORTRDWR\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200615 writel(cfg->cport_rdwr, &sdr_ctrl->cport_rdwr);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500616
617 debug("Configuring DRAMODT\n");
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200618 writel(cfg->dram_odt, &sdr_ctrl->dram_odt);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500619
620 /* saving this value to SYSMGR.ISWGRP.HANDOFF.FPGA2SDR */
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200621 writel(cfg->fpgaport_rst, &sysmgr_regs->iswgrp_handoff[3]);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500622
623 /* only enable if the FPGA is programmed */
624 if (fpgamgr_test_fpga_ready()) {
625 if (sdram_write_verify(&sdr_ctrl->fpgaport_rst,
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200626 cfg->fpgaport_rst) == 1) {
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500627 status = 1;
628 return 1;
629 }
630 }
631
632 /* Restore the SDR PHY Register if valid */
633 if (sdr_phy_reg != 0xffffffff)
634 writel(sdr_phy_reg, &sdr_ctrl->phy_ctrl0);
635
Marek Vasutdc3b91d2015-08-01 20:58:44 +0200636 /* Final step - apply configuration changes */
637 debug("Configuring STATICCFG\n");
638 clrsetbits_le32(&sdr_ctrl->static_cfg,
639 SDR_CTRLGRP_STATICCFG_APPLYCFG_MASK,
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500640 1 << SDR_CTRLGRP_STATICCFG_APPLYCFG_LSB);
Dinh Nguyen9bbd2132015-06-02 22:52:48 -0500641
642 sdram_set_protection_config(0, sdram_calculate_size());
643
644 sdram_dump_protection_config();
645
646 return status;
647}
648
649/*
650 * To calculate SDRAM device size based on SDRAM controller parameters.
651 * Size is specified in bytes.
652 *
653 * NOTE:
654 * This function is compiled and linked into the preloader and
655 * Uboot (there may be others). So if this function changes, the Preloader
656 * and UBoot must be updated simultaneously.
657 */
658unsigned long sdram_calculate_size(void)
659{
660 unsigned long temp;
661 unsigned long row, bank, col, cs, width;
662
663 temp = readl(&sdr_ctrl->dram_addrw);
664 col = (temp & SDR_CTRLGRP_DRAMADDRW_COLBITS_MASK) >>
665 SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB;
666
667 /* SDRAM Failure When Accessing Non-Existent Memory
668 * Use ROWBITS from Quartus/QSys to calculate SDRAM size
669 * since the FB specifies we modify ROWBITs to work around SDRAM
670 * controller issue.
671 *
672 * If the stored handoff value for rows is 0, it probably means
673 * the preloader is older than UBoot. Use the
674 * #define from the SOCEDS Tools per Crucible review
675 * uboot-socfpga-204. Note that this is not a supported
676 * configuration and is not tested. The customer
677 * should be using preloader and uboot built from the
678 * same tag.
679 */
680 row = readl(&sysmgr_regs->iswgrp_handoff[4]);
681 if (row == 0)
682 row = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS;
683 /* If the stored handoff value for rows is greater than
684 * the field width in the sdr.dramaddrw register then
685 * something is very wrong. Revert to using the the #define
686 * value handed off by the SOCEDS tool chain instead of
687 * using a broken value.
688 */
689 if (row > 31)
690 row = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS;
691
692 bank = (temp & SDR_CTRLGRP_DRAMADDRW_BANKBITS_MASK) >>
693 SDR_CTRLGRP_DRAMADDRW_BANKBITS_LSB;
694
695 /* SDRAM Failure When Accessing Non-Existent Memory
696 * Use CSBITs from Quartus/QSys to calculate SDRAM size
697 * since the FB specifies we modify CSBITs to work around SDRAM
698 * controller issue.
699 */
700 cs = (temp & SDR_CTRLGRP_DRAMADDRW_CSBITS_MASK) >>
701 SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB;
702 cs += 1;
703
704 cs = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS;
705
706 width = readl(&sdr_ctrl->dram_if_width);
707 /* ECC would not be calculated as its not addressible */
708 if (width == SDRAM_WIDTH_32BIT_WITH_ECC)
709 width = 32;
710 if (width == SDRAM_WIDTH_16BIT_WITH_ECC)
711 width = 16;
712
713 /* calculate the SDRAM size base on this info */
714 temp = 1 << (row + bank + col);
715 temp = temp * cs * (width / 8);
716
717 debug("sdram_calculate_memory returns %ld\n", temp);
718
719 return temp;
720}