]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/contrib/octeon-sdk/cvmx-llm.c
MFC: 217169
[FreeBSD/releng/8.2.git] / sys / contrib / octeon-sdk / cvmx-llm.c
1 /***********************license start***************
2  *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
3  *  reserved.
4  *
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions are
8  *  met:
9  *
10  *      * Redistributions of source code must retain the above copyright
11  *        notice, this list of conditions and the following disclaimer.
12  *
13  *      * Redistributions in binary form must reproduce the above
14  *        copyright notice, this list of conditions and the following
15  *        disclaimer in the documentation and/or other materials provided
16  *        with the distribution.
17  *
18  *      * Neither the name of Cavium Networks nor the names of
19  *        its contributors may be used to endorse or promote products
20  *        derived from this software without specific prior written
21  *        permission.
22  *
23  *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24  *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25  *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26  *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27  *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28  *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29  *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30  *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31  *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
32  *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
33  *
34  *
35  *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36  *
37  ***********************license end**************************************/
38
39
40
41
42
43
44 /**
45  * @file
46  *
47  * Configuration functions for low latency memory.
48  *
49  * <hr>$Revision: 41586 $<hr>
50  */
51 #include "cvmx-config.h"
52 #include "cvmx.h"
53 #include "cvmx-llm.h"
54 #include "cvmx-sysinfo.h"
55 #include "cvmx-csr-db.h"
56
57 #define MIN(a,b) (((a)<(b))?(a):(b))
58
59 typedef struct
60 {
61     uint32_t dfa_memcfg0_base;
62     uint32_t dfa_memcfg1_base;
63     uint32_t mrs_dat_p0bunk0;
64     uint32_t mrs_dat_p0bunk1;
65     uint32_t mrs_dat_p1bunk0;
66     uint32_t mrs_dat_p1bunk1;
67     uint8_t  p0_ena;
68     uint8_t  p1_ena;
69     uint8_t  bunkport;
70 } rldram_csr_config_t;
71
72
73
74
75
76 int rld_csr_config_generate(llm_descriptor_t *llm_desc_ptr, rldram_csr_config_t *cfg_ptr);
77
78
79 void print_rld_cfg(rldram_csr_config_t *cfg_ptr);
80 void write_rld_cfg(rldram_csr_config_t *cfg_ptr);
81 static void cn31xx_dfa_memory_init(void);
82
83 static uint32_t process_address_map_str(uint32_t mrs_dat, char *addr_str);
84
85
86
87 #ifndef CVMX_LLM_NUM_PORTS
88 #warning WARNING: default CVMX_LLM_NUM_PORTS used.  Defaults deprecated, please set in executive-config.h
89 #define CVMX_LLM_NUM_PORTS 1
90 #endif
91
92
93 #if (CVMX_LLM_NUM_PORTS != 1) && (CVMX_LLM_NUM_PORTS != 2)
94 #error "Invalid CVMX_LLM_NUM_PORTS value: must be 1 or 2\n"
95 #endif
96
97 int cvmx_llm_initialize()
98 {
99     if (cvmx_llm_initialize_desc(NULL) < 0)
100         return -1;
101
102     return 0;
103 }
104
105
106 int cvmx_llm_get_default_descriptor(llm_descriptor_t *llm_desc_ptr)
107 {
108     cvmx_sysinfo_t *sys_ptr;
109     sys_ptr = cvmx_sysinfo_get();
110
111     if (!llm_desc_ptr)
112         return -1;
113
114     memset(llm_desc_ptr, 0, sizeof(llm_descriptor_t));
115
116     llm_desc_ptr->cpu_hz = sys_ptr->cpu_clock_hz;
117
118     if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBT3000)
119     { // N3K->RLD0 Address Swizzle
120         strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
121         strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
122         // N3K->RLD1 Address Swizzle
123         strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
124         strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
125         /* NOTE: The ebt3000 has a strange RLDRAM configuration for validation purposes.  It is not recommended to have
126         ** different amounts of memory on different ports as that renders some memory unusable */
127         llm_desc_ptr->rld0_bunks = 2;
128         llm_desc_ptr->rld1_bunks = 2;
129         llm_desc_ptr->rld0_mbytes = 128;          // RLD0: 4x 32Mx9
130         llm_desc_ptr->rld1_mbytes = 64;           // RLD1: 2x 16Mx18
131     }
132     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBT5800)
133     {
134         strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
135         strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
136         strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
137         strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
138         llm_desc_ptr->rld0_bunks = 2;
139         llm_desc_ptr->rld1_bunks = 2;
140         llm_desc_ptr->rld0_mbytes = 128;
141         llm_desc_ptr->rld1_mbytes = 128;
142         llm_desc_ptr->max_rld_clock_mhz = 400;  /* CN58XX needs a max clock speed for selecting optimal divisor */
143     }
144     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3000)
145     {
146         strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
147         strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
148         strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
149         strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
150         llm_desc_ptr->rld0_bunks = 2;
151         llm_desc_ptr->rld1_bunks = 2;
152         llm_desc_ptr->rld0_mbytes = 128;
153         llm_desc_ptr->rld1_mbytes = 128;
154     }
155     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_NAC38)
156     {
157         if (sys_ptr->board_rev_major == 1 && sys_ptr->board_rev_minor == 0)
158         {
159             strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
160             strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
161             strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
162             strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
163             llm_desc_ptr->rld0_bunks = 2;
164             llm_desc_ptr->rld1_bunks = 2;
165             llm_desc_ptr->rld0_mbytes = 128;
166             llm_desc_ptr->rld1_mbytes = 128;
167         }
168         else
169         {   /* Asus new recommendation  */
170             strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 09 11 04 06 05 08 15 20 16 18 12 13 00 01 07 02 19 17 10 14 03");
171             strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 11 09 00 01 07 02 19 17 10 14 03 13 04 06 05 08 15 20 16 18 12");
172             strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 08 13 14 00 04 12 16 11 19 10 07 02 01 05 03 06 17 18 20 09 15");
173             strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 13 08 01 05 03 06 17 18 20 09 15 02 14 00 04 12 16 11 19 10 07");
174             llm_desc_ptr->rld0_bunks = 2;
175             llm_desc_ptr->rld1_bunks = 2;
176             llm_desc_ptr->rld0_mbytes = 128;
177             llm_desc_ptr->rld1_mbytes = 128;
178         }
179     }
180     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_THUNDER)
181     {
182
183         if (sys_ptr->board_rev_major >= 4)
184         {
185             strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 13 11 01 02 07 19 03 18 10 12 20 06 04 08 17 05 14 16 00 09 15");
186             strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 11 13 04 08 17 05 14 16 00 09 15 06 01 02 07 19 03 18 10 12 20");
187             strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 02 19 18 17 16 09 14 13 20 11 10 01 08 03 06 15 04 07 05 12 00");
188             strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 19 02 08 03 06 15 04 07 05 12 00 01 18 17 16 09 14 13 20 11 10");
189         }
190         else
191         {
192             strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
193             strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
194             strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
195             strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
196         }
197
198         llm_desc_ptr->rld0_bunks = 2;
199         llm_desc_ptr->rld1_bunks = 2;
200         llm_desc_ptr->rld0_mbytes = 128;
201         llm_desc_ptr->rld1_mbytes = 128;
202     }
203     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_NICPRO2)
204     {
205         strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
206         strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
207         strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
208         strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
209         llm_desc_ptr->rld0_bunks = 2;
210         llm_desc_ptr->rld1_bunks = 2;
211         llm_desc_ptr->rld0_mbytes = 256;
212         llm_desc_ptr->rld1_mbytes = 256;
213         llm_desc_ptr->max_rld_clock_mhz = 400;  /* CN58XX needs a max clock speed for selecting optimal divisor */
214     }
215     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3100)
216     {
217         /* CN31xx DFA memory is DDR based, so it is completely different from the CN38XX DFA memory */
218         llm_desc_ptr->rld0_bunks = 1;
219         llm_desc_ptr->rld0_mbytes = 256;
220     }
221     else if (sys_ptr->board_type == CVMX_BOARD_TYPE_KBP)
222     {
223         strcpy(llm_desc_ptr->addr_rld0_fb_str, "");
224         strcpy(llm_desc_ptr->addr_rld0_bb_str, "");
225         llm_desc_ptr->rld0_bunks = 0;
226         llm_desc_ptr->rld0_mbytes = 0;
227         strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
228         strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
229         llm_desc_ptr->rld1_bunks = 2;
230         llm_desc_ptr->rld1_mbytes = 64;
231     }
232     else
233     {
234         cvmx_dprintf("No default LLM configuration available for board %s (%d)\n", cvmx_board_type_to_string(sys_ptr->board_type),  sys_ptr->board_type);
235         return -1;
236     }
237
238     return(0);
239 }
240
241 int cvmx_llm_initialize_desc(llm_descriptor_t *llm_desc_ptr)
242 {
243     cvmx_sysinfo_t *sys_ptr;
244     sys_ptr = cvmx_sysinfo_get();
245     llm_descriptor_t default_llm_desc;
246
247     memset(&default_llm_desc, 0, sizeof(default_llm_desc));
248     if (sys_ptr->board_type == CVMX_BOARD_TYPE_SIM)
249     {
250         cvmx_dprintf("Skipping llm configuration for simulator.\n");
251         return 0;
252     }
253
254     if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3100)
255     {
256         /* CN31xx DFA memory is DDR based, so it is completely different from the CN38XX DFA memory
257         ** config descriptors are not supported yet.*/
258         cvmx_dprintf("Warning: preliminary DFA memory configuration\n");
259         cn31xx_dfa_memory_init();
260         return(256*1024*1024);
261     }
262
263     /* If no descriptor passed, generate default descriptor based on board type.
264     ** Fail if no default available for given board type
265     */
266     if (!llm_desc_ptr)
267     {
268         /* Get default descriptor */
269         if (0 > cvmx_llm_get_default_descriptor(&default_llm_desc))
270             return -1;
271
272         /* Disable second port depending on CVMX config */
273         if (CVMX_LLM_NUM_PORTS == 1)
274           default_llm_desc.rld0_bunks = 0;        // For single port: Force RLD0(P1) to appear EMPTY
275
276         cvmx_dprintf("Using default LLM configuration for board %s (%d)\n", cvmx_board_type_to_string(sys_ptr->board_type),  sys_ptr->board_type);
277
278         llm_desc_ptr = &default_llm_desc;
279     }
280
281
282
283     rldram_csr_config_t ebt3000_rld_cfg;
284     if (!rld_csr_config_generate(llm_desc_ptr, &ebt3000_rld_cfg))
285     {
286         cvmx_dprintf("Configuring %d llm port(s).\n", !!llm_desc_ptr->rld0_bunks + !!llm_desc_ptr->rld1_bunks);
287         write_rld_cfg(&ebt3000_rld_cfg);
288     }
289     else
290     {
291         cvmx_dprintf("Error creating rldram configuration\n");
292         return(-1);
293     }
294
295     /* Compute how much memory is configured
296     ** Memory is interleaved, so if one port has more than the other some memory is not usable */
297
298     /* If both ports are enabled, handle the case where one port has more than the other.
299     ** This is an unusual and not recommended configuration that exists on the ebt3000 board */
300     if (!!llm_desc_ptr->rld0_bunks && !!llm_desc_ptr->rld1_bunks)
301         llm_desc_ptr->rld0_mbytes = llm_desc_ptr->rld1_mbytes = MIN(llm_desc_ptr->rld0_mbytes, llm_desc_ptr->rld1_mbytes);
302
303     return(((!!llm_desc_ptr->rld0_bunks) * llm_desc_ptr->rld0_mbytes
304           + (!!llm_desc_ptr->rld1_bunks) * llm_desc_ptr->rld1_mbytes) * 1024*1024);
305 }
306
307 //======================
308 // SUPPORT FUNCTIONS:
309 //======================
310 //======================================================================
311 // Extracts srcvec[srcbitpos] and places it in return int (bit[0])
312 int bit_extract ( int srcvec,         // source word (to extract)
313                   int srcbitpos       // source bit position
314                 )
315 {
316     return(((1 << srcbitpos) & srcvec) >> srcbitpos);
317 }
318 //======================================================================
319 // Inserts srcvec[0] into dstvec[dstbitpos] (without affecting other bits)
320 int bit_insert ( int srcvec,           // srcvec[0] = bit to be inserted
321                  int dstbitpos,        // Bit position to insert into returned int
322                  int dstvec            // dstvec (destination vector)
323                )
324 {
325     return((srcvec << dstbitpos) | dstvec);      // Shift bit to insert into bit position/OR with accumulated number
326 }
327 //======================================================================
328
329 int rld_csr_config_generate(llm_descriptor_t *llm_desc_ptr, rldram_csr_config_t *cfg_ptr)
330 {
331     char *addr_rld0_fb_str;
332     char *addr_rld0_bb_str;
333     char *addr_rld1_fb_str;
334     char *addr_rld1_bb_str;
335     int eclk_ps;
336     int mtype = 0;                           // MTYPE (0: RLDRAM/1: FCRAM
337     int trcmin = 20;                         // tRC(min) - from RLDRAM data sheet
338     int trc_cyc;                             // TRC(cyc)
339     int trc_mod;
340     int trl_cyc;                             // TRL(cyc)
341     int twl_cyc;                             // TWL(cyc)
342     int tmrsc_cyc = 6;                       // tMRSC(cyc)  [2-7]
343     int mclk_ps;                             // DFA Memory Clock(in ps) = 2x eclk
344     int rldcfg = 99;                         // RLDRAM-II CFG (1,2,3)
345     int mrs_odt = 0;                         // RLDRAM MRS A[9]=ODT (default)
346     int mrs_impmatch = 0;                    // RLDRAM MRS A[8]=Impedance Matching (default)
347     int mrs_dllrst = 1;                      // RLDRAM MRS A[7]=DLL Reset (default)
348     uint32_t mrs_dat;
349     int mrs_dat_p0bunk0 = 0;                 // MRS Register Data After Address Map (for Port0 Bunk0)
350     int mrs_dat_p0bunk1 = 0;                 // MRS Register Data After Address Map (for Port0 Bunk1)
351     int mrs_dat_p1bunk0 = 0;                 // MRS Register Data After Address Map (for Port1 Bunk0)
352     int mrs_dat_p1bunk1 = 0;                 // MRS Register Data After Address Map (for Port1 Bunk1)
353     int p0_ena = 0;                          // DFA Port#0 Enabled
354     int p1_ena = 0;                          // DFA Port#1 Enabled
355     int memport = 0;                       // Memory(MB) per Port [MAX=512]
356     int membunk;                             // Memory(MB) per Bunk
357     int bunkport = 0;                        // Bunks/Port [1/2]
358     int pbunk = 0;                               // Physical Bunk(or Rank) encoding for address bit
359     int tref_ms = 32;                        // tREF(ms) (RLDRAM-II overall device refresh interval
360     int trefi_ns;                            // tREFI(ns) = tREF(ns)/#rows/bank
361     int rows = 8;                            // #rows/bank (K) typically 8K
362     int ref512int;
363     int ref512mod;
364     int tskw_cyc = 0;
365     int fprch = 1;
366     int bprch = 0;
367     int dfa_memcfg0_base = 0;
368     int dfa_memcfg1_base = 0;
369     int tbl = 1;                             // tBL (1: 2-burst /2: 4-burst)
370     int rw_dly;
371     int wr_dly;
372     int r2r = 1;
373     int sil_lat = 1;
374     int clkdiv = 2;  /* CN38XX is fixed at 2, CN58XX supports 2,3,4 */
375     int clkdiv_enc = 0x0;  /* Encoded clock divisor, only used for CN58XX */
376
377     if (!llm_desc_ptr)
378         return -1;
379
380     /* Setup variables from descriptor */
381
382     addr_rld0_fb_str = llm_desc_ptr->addr_rld0_fb_str;
383     addr_rld0_bb_str = llm_desc_ptr->addr_rld0_bb_str;
384     addr_rld1_fb_str = llm_desc_ptr->addr_rld1_fb_str;
385     addr_rld1_bb_str = llm_desc_ptr->addr_rld1_bb_str;
386
387     p0_ena = !!llm_desc_ptr->rld1_bunks;        // NOTE: P0 == RLD1
388     p1_ena = !!llm_desc_ptr->rld0_bunks;        // NOTE: P1 == RLD0
389
390     // Massage the code, so that if the user had imbalanced memory per-port (or imbalanced bunks/port), we
391     // at least try to configure 'workable' memory.
392     if (p0_ena && p1_ena)  // IF BOTH PORTS Enabled (imbalanced memory), select smaller of BOTH
393     {
394         memport = MIN(llm_desc_ptr->rld0_mbytes, llm_desc_ptr->rld1_mbytes);
395         bunkport = MIN(llm_desc_ptr->rld0_bunks, llm_desc_ptr->rld1_bunks);
396     }
397     else if (p0_ena) // P0=RLD1 Enabled
398     {
399         memport = llm_desc_ptr->rld1_mbytes;
400         bunkport = llm_desc_ptr->rld1_bunks;
401     }
402     else if (p1_ena) // P1=RLD0 Enabled
403     {
404         memport = llm_desc_ptr->rld0_mbytes;
405         bunkport = llm_desc_ptr->rld0_bunks;
406     }
407     else
408         return -1;
409
410     uint32_t eclk_mhz = llm_desc_ptr->cpu_hz/1000000;
411
412
413
414     /* Tweak skew based on cpu clock */
415     if (eclk_mhz <= 367)
416     {
417         tskw_cyc = 0;
418     }
419     else
420     {
421         tskw_cyc = 1;
422     }
423
424     /* Determine clock divider ratio (only required for CN58XX) */
425     if (OCTEON_IS_MODEL(OCTEON_CN58XX))
426     {
427         uint32_t max_llm_clock_mhz = llm_desc_ptr->max_rld_clock_mhz;
428         if (!max_llm_clock_mhz)
429         {
430             max_llm_clock_mhz = 400;  /* Default to 400 MHz */
431             cvmx_dprintf("Warning, using default max_rld_clock_mhz of: %lu MHz\n", (unsigned long)max_llm_clock_mhz);
432         }
433
434         /* Compute the divisor, and round up */
435         clkdiv = eclk_mhz/max_llm_clock_mhz;
436         if (clkdiv * max_llm_clock_mhz < eclk_mhz)
437             clkdiv++;
438
439         if (clkdiv > 4)
440         {
441             cvmx_dprintf("ERROR: CN58XX LLM clock divisor out of range\n");
442             goto TERMINATE;
443         }
444         if (clkdiv < 2)
445             clkdiv = 2;
446
447         cvmx_dprintf("Using llm clock divisor: %d, llm clock is: %lu MHz\n", clkdiv, (unsigned long)eclk_mhz/clkdiv);
448         /* Translate divisor into bit encoding for register */
449         /* 0 -> div 2
450         ** 1 -> reserved
451         ** 2 -> div 3
452         ** 3 -> div 4
453         */
454         if (clkdiv == 2)
455             clkdiv_enc = 0;
456         else
457             clkdiv_enc = clkdiv - 1;
458
459     /* Odd divisor needs sil_lat to be 2 */
460         if (clkdiv == 0x3)
461             sil_lat = 2;
462
463         /* Increment tskw for high clock speeds */
464         if ((unsigned long)eclk_mhz/clkdiv > 375)
465             tskw_cyc += 1;
466     }
467
468     eclk_ps = (1000000+(eclk_mhz-1)) / eclk_mhz;  // round up if nonzero remainder
469     //=======================================================================
470
471     //=======================================================================
472     // Now, Query User for DFA Memory Type
473     if (mtype != 0)
474     {
475         goto TERMINATE;         // Complete this code for FCRAM usage on N3K-P2
476     }
477     //=======================================================================
478     // Query what the tRC(min) value is from the data sheets
479     //=======================================================================
480     // Now determine the Best CFG based on Memory clock(ps) and tRCmin(ns)
481     mclk_ps = eclk_ps * clkdiv;
482     trc_cyc = ((trcmin * 1000)/mclk_ps);
483     trc_mod = ((trcmin * 1000) % mclk_ps);
484     // If remainder exists, bump up to the next integer multiple
485     if (trc_mod != 0)
486     {
487         trc_cyc = trc_cyc + 1;
488     }
489     // If tRC is now ODD, then bump it to the next EVEN integer (RLDRAM-II does not support odd tRC values at this time).
490     if (trc_cyc & 1)
491     {
492         trc_cyc = trc_cyc + 1;           // Bump it to an even #
493     }
494     // RLDRAM CFG Range Check: If the computed trc_cyc is less than 4, then set it to min CFG1 [tRC=4]
495     if (trc_cyc < 4)
496     {
497         trc_cyc = 4;             // If computed trc_cyc < 4 then clamp to 4
498     }
499     else if (trc_cyc > 8)
500     {    // If the computed trc_cyc > 8, then report an error (because RLDRAM cannot support a tRC>8
501         goto TERMINATE;
502     }
503     // Assuming all is ok(up to here)
504     // At this point the tRC_cyc has been clamped  between 4 and 8 (and is even), So it can only be 4,6,8 which are
505     // the RLDRAM valid CFG range values.
506     trl_cyc = trc_cyc;                 // tRL = tRC (for RLDRAM=II)
507     twl_cyc = trl_cyc + 1;             // tWL = tRL + 1 (for RLDRAM-II)
508     // NOTE: RLDRAM-II (as of 4/25/05) only have 3 supported CFG encodings:
509     if (trc_cyc == 4)
510     {
511         rldcfg = 1;           // CFG #1 (tRL=4/tRC=4/tWL=5)
512     }
513     else if (trc_cyc == 6)
514     {
515         rldcfg = 2;           // CFG #2 (tRL=6/tRC=6/tWL=7)
516     }
517     else if (trc_cyc == 8)
518     {
519         rldcfg = 3;           // CFG #3 (tRL=8/tRC=8/tWL=9)
520     }
521     else
522     {
523         goto TERMINATE;
524     }
525     //=======================================================================
526     mrs_dat = ( (mrs_odt << 9) | (mrs_impmatch << 8) | (mrs_dllrst << 7) | rldcfg );
527     //=======================================================================
528     // If there is only a single bunk, then skip over address mapping queries (which are not required)
529     if (bunkport == 1)
530     {
531         goto CALC_PBUNK;
532     }
533
534     /* Process the address mappings */
535     /* Note that that RLD0 pins corresponds to Port#1, and
536     **                RLD1 pins corresponds to Port#0.
537     */
538     mrs_dat_p1bunk0 = process_address_map_str(mrs_dat, addr_rld0_fb_str);
539     mrs_dat_p1bunk1 = process_address_map_str(mrs_dat, addr_rld0_bb_str);
540     mrs_dat_p0bunk0 = process_address_map_str(mrs_dat, addr_rld1_fb_str);
541     mrs_dat_p0bunk1 = process_address_map_str(mrs_dat, addr_rld1_bb_str);
542
543
544     //=======================================================================
545     CALC_PBUNK:
546     // Determine the PBUNK field (based on Memory/Bunk)
547     // This determines the addr bit used to distinguish when crossing a bunk.
548     // NOTE: For RLDRAM, the bunk bit is extracted from 'a' programmably selected high
549     // order addr bit. [linear address per-bunk]
550     if (bunkport == 2)
551     {
552         membunk = (memport / 2);
553     }
554     else
555     {
556         membunk = memport;
557     }
558     if (membunk == 16)
559     {       // 16MB/bunk MA[19]
560         pbunk = 0;
561     }
562     else if (membunk == 32)
563     {  // 32MB/bunk MA[20]
564         pbunk = 1;
565     }
566     else if (membunk == 64)
567     {  // 64MB/bunk MA[21]
568         pbunk = 2;
569     }
570     else if (membunk == 128)
571     { // 128MB/bunk MA[22]
572         pbunk = 3;
573     }
574     else if (membunk == 256)
575     { // 256MB/bunk MA[23]
576         pbunk = 4;
577     }
578     else if (membunk == 512)
579     { // 512MB/bunk
580         if (cvmx_octeon_is_pass1() == 1)
581         {
582             goto TERMINATE;
583         }
584     }
585     //=======================================================================
586     //=======================================================================
587     //=======================================================================
588     // Now determine N3K REFINT
589     trefi_ns = (tref_ms * 1000 * 1000) / (rows * 1024);
590     ref512int = ((trefi_ns * 1000) / (eclk_ps * 512));
591     ref512mod = ((trefi_ns * 1000) % (eclk_ps * 512));
592     //=======================================================================
593     // Ask about tSKW
594 #if 0
595     if (tskw_ps ==  0)
596     {
597         tskw_cyc = 0;
598     }
599     else
600     { // CEILING function
601         tskw_cyc = (tskw_ps / eclk_ps);
602         tskw_mod = (tskw_ps % eclk_ps);
603         if (tskw_mod != 0)
604         {  // If there's a remainder - then bump to next (+1)
605             tskw_cyc = tskw_cyc + 1;
606         }
607     }
608 #endif
609     if (tskw_cyc > 3)
610     {
611         goto TERMINATE;
612     }
613
614     tbl = 1;        // BLEN=2 (ALWAYs for RLDRAM)
615     //=======================================================================
616     // RW_DLY = (ROUND_UP{[[(TRL+TBL)*2 + tSKW + BPRCH] + 1] / 2}) - tWL
617     rw_dly = ((((trl_cyc + tbl) * 2 + tskw_cyc + bprch) + 1) / 2);
618     if (rw_dly & 1)
619     { // If it's ODD then round up
620         rw_dly = rw_dly + 1;
621     }
622     rw_dly = rw_dly - twl_cyc +1 ;
623     if (rw_dly < 0)
624     { // range check - is it positive
625         goto TERMINATE;
626     }
627     //=======================================================================
628     // WR_DLY = (ROUND_UP[[(tWL + tBL)*2 - tSKW + FPRCH] / 2]) - tRL
629     wr_dly = (((twl_cyc + tbl) * 2 - tskw_cyc + fprch) / 2);
630     if (wr_dly & 1)
631     { // If it's ODD then round up
632         wr_dly = wr_dly + 1;
633     }
634     wr_dly = wr_dly - trl_cyc + 1;
635     if (wr_dly < 0)
636     { // range check - is it positive
637         goto TERMINATE;
638     }
639
640
641     dfa_memcfg0_base = 0;
642     dfa_memcfg0_base = ( p0_ena |
643                          (p1_ena << 1) |
644                          (mtype << 3) |
645                          (sil_lat << 4) |
646                          (rw_dly << 6) |
647                          (wr_dly << 10) |
648                          (fprch << 14) |
649                          (bprch << 16) |
650                          (0 << 18) |         // BLEN=0(2-burst for RLDRAM)
651                          (pbunk << 19) |
652                          (r2r << 22) |       // R2R=1
653                          (clkdiv_enc << 28 )
654                        );
655
656
657     dfa_memcfg1_base = 0;
658     dfa_memcfg1_base = ( ref512int |
659                          (tskw_cyc << 4) |
660                          (trl_cyc << 8) |
661                          (twl_cyc << 12) |
662                          (trc_cyc << 16) |
663                          (tmrsc_cyc << 20)
664                        );
665
666
667
668
669     cfg_ptr->dfa_memcfg0_base = dfa_memcfg0_base;
670     cfg_ptr->dfa_memcfg1_base = dfa_memcfg1_base;
671     cfg_ptr->mrs_dat_p0bunk0 =  mrs_dat_p0bunk0;
672     cfg_ptr->mrs_dat_p1bunk0 =  mrs_dat_p1bunk0;
673     cfg_ptr->mrs_dat_p0bunk1 =  mrs_dat_p0bunk1;
674     cfg_ptr->mrs_dat_p1bunk1 =  mrs_dat_p1bunk1;
675     cfg_ptr->p0_ena =           p0_ena;
676     cfg_ptr->p1_ena =           p1_ena;
677     cfg_ptr->bunkport =         bunkport;
678     //=======================================================================
679
680     return(0);
681     TERMINATE:
682     return(-1);
683
684 }
685
686
687
688 static uint32_t process_address_map_str(uint32_t mrs_dat, char *addr_str)
689 {
690     int count = 0;
691     int amap [23];
692     uint32_t new_mrs_dat = 0;
693
694 //    cvmx_dprintf("mrs_dat: 0x%x, str: %x\n", mrs_dat, addr_str);
695     char *charptr = strtok(addr_str," ");
696     while ((charptr != NULL) & (count <= 22))
697     {
698         amap[22-count] = atoi(charptr);         // Assign the AMAP Array
699         charptr = strtok(NULL," ");             // Get Next char string (which represents next addr bit mapping)
700         count++;
701     }
702     // Now do the bit swap of MRSDAT (based on address mapping)
703     uint32_t mrsdat_bit;
704     for (count=0;count<=22;count++)
705     {
706         mrsdat_bit = bit_extract(mrs_dat, count);
707         new_mrs_dat = bit_insert(mrsdat_bit, amap[count], new_mrs_dat);
708     }
709
710     return new_mrs_dat;
711 }
712
713
714 //#define PRINT_LLM_CONFIG
715 #ifdef PRINT_LLM_CONFIG
716 #define ll_printf printf
717 #else
718 #define ll_printf(...)
719 #define cvmx_csr_db_decode(...)
720 #endif
721
722 static void cn31xx_dfa_memory_init(void)
723 {
724     if (OCTEON_IS_MODEL(OCTEON_CN31XX))
725     {
726         cvmx_dfa_ddr2_cfg_t  dfaCfg;
727         cvmx_dfa_eclkcfg_t   dfaEcklCfg;
728         cvmx_dfa_ddr2_addr_t dfaAddr;
729         cvmx_dfa_ddr2_tmg_t  dfaTmg;
730         cvmx_dfa_ddr2_pll_t  dfaPll;
731         int mem_freq_hz = 533*1000000;
732         int ref_freq_hz = cvmx_sysinfo_get()->dfa_ref_clock_hz;
733         if (!ref_freq_hz)
734             ref_freq_hz = 33*1000000;
735
736         cvmx_dprintf ("Configuring DFA memory for %d MHz operation.\n",mem_freq_hz/1000000);
737
738           /* Turn on the DFA memory port. */
739         dfaCfg.u64 = cvmx_read_csr (CVMX_DFA_DDR2_CFG);
740         dfaCfg.s.prtena = 1;
741         cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64);
742
743           /* Start the PLL alignment sequence */
744         dfaPll.u64 = 0;
745         dfaPll.s.pll_ratio  = mem_freq_hz/ref_freq_hz         /*400Mhz / 33MHz*/;
746         dfaPll.s.pll_div2   = 1              /*400 - 1 */;
747         dfaPll.s.pll_bypass = 0;
748         cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64);
749
750         dfaPll.s.pll_init = 1;
751         cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64);
752
753         cvmx_wait (RLD_INIT_DELAY); //want 150uS
754         dfaPll.s.qdll_ena = 1;
755         cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64);
756
757         cvmx_wait (RLD_INIT_DELAY); //want 10us
758         dfaEcklCfg.u64 = 0;
759         dfaEcklCfg.s.dfa_frstn = 1;
760         cvmx_write_csr (CVMX_DFA_ECLKCFG, dfaEcklCfg.u64);
761
762           /* Configure the DFA Memory */
763         dfaCfg.s.silo_hc = 1 /*400 - 1 */;
764         dfaCfg.s.silo_qc = 0 /*400 - 0 */;
765         dfaCfg.s.tskw    = 1 /*400 - 1 */;
766         dfaCfg.s.ref_int = 0x820 /*533 - 0x820  400 - 0x618*/;
767         dfaCfg.s.trfc    = 0x1A  /*533 - 0x23   400 - 0x1A*/;
768         dfaCfg.s.fprch   = 0; /* 1 more conservative*/
769         dfaCfg.s.bprch   = 0; /* 1 */
770         cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64);
771
772         dfaEcklCfg.u64 = cvmx_read_csr (CVMX_DFA_ECLKCFG);
773         dfaEcklCfg.s.maxbnk = 1;
774         cvmx_write_csr (CVMX_DFA_ECLKCFG, dfaEcklCfg.u64);
775
776         dfaAddr.u64 = cvmx_read_csr (CVMX_DFA_DDR2_ADDR);
777         dfaAddr.s.num_cols    = 0x1;
778         dfaAddr.s.num_colrows = 0x2;
779         dfaAddr.s.num_rnks    = 0x1;
780         cvmx_write_csr (CVMX_DFA_DDR2_ADDR, dfaAddr.u64);
781
782         dfaTmg.u64 =  cvmx_read_csr (CVMX_DFA_DDR2_TMG);
783         dfaTmg.s.ddr2t    = 0;
784         dfaTmg.s.tmrd     = 0x2;
785         dfaTmg.s.caslat   = 0x4 /*400 - 0x3, 500 - 0x4*/;
786         dfaTmg.s.pocas    = 0;
787         dfaTmg.s.addlat   = 0;
788         dfaTmg.s.trcd     = 4   /*400 - 3, 500 - 4*/;
789         dfaTmg.s.trrd     = 2;
790         dfaTmg.s.tras     = 0xB /*400 - 8, 500 - 0xB*/;
791         dfaTmg.s.trp      = 4   /*400 - 3, 500 - 4*/;
792         dfaTmg.s.twr      = 4   /*400 - 3, 500 - 4*/;
793         dfaTmg.s.twtr     = 2   /*400 - 2 */;
794         dfaTmg.s.tfaw     = 0xE /*400 - 0xA, 500 - 0xE*/;
795         dfaTmg.s.r2r_slot = 0;
796         dfaTmg.s.dic      = 0;  /*400 - 0 */
797         dfaTmg.s.dqsn_ena = 0;
798         dfaTmg.s.odt_rtt  = 0;
799         cvmx_write_csr (CVMX_DFA_DDR2_TMG, dfaTmg.u64);
800
801           /* Turn on the DDR2 interface and wait a bit for the hardware to setup. */
802         dfaCfg.s.init = 1;
803         cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64);
804         cvmx_wait(RLD_INIT_DELAY); // want at least 64K cycles
805     }
806 }
807
808 void write_rld_cfg(rldram_csr_config_t *cfg_ptr)
809 {
810     cvmx_dfa_memcfg0_t    memcfg0;
811     cvmx_dfa_memcfg2_t    memcfg2;
812
813     memcfg0.u64 = cfg_ptr->dfa_memcfg0_base;
814
815     if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)))
816     {
817         uint32_t dfa_memcfg0;
818
819         if (OCTEON_IS_MODEL (OCTEON_CN58XX)) {
820               // Set RLDQK90_RST and RDLCK_RST to reset all three DLLs.
821             memcfg0.s.rldck_rst    = 1;
822             memcfg0.s.rldqck90_rst = 1;
823             cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64);
824             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  clk/qk90 reset\n", (uint32_t) memcfg0.u64);
825             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64);
826
827               // Clear RDLCK_RST while asserting RLDQK90_RST to bring RLDCK DLL out of reset.
828             memcfg0.s.rldck_rst    = 0;
829             memcfg0.s.rldqck90_rst = 1;
830             cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64);
831             cvmx_wait(4000000);  /* Wait  */
832             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  qk90 reset\n", (uint32_t) memcfg0.u64);
833             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64);
834
835               // Clear both RDLCK90_RST and RLDQK90_RST to bring the RLDQK90 DLL out of reset.
836             memcfg0.s.rldck_rst    = 0;
837             memcfg0.s.rldqck90_rst = 0;
838             cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64);
839             cvmx_wait(4000000);  /* Wait  */
840             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  DLL out of reset\n", (uint32_t) memcfg0.u64);
841             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64);
842         }
843
844         //=======================================================================
845         // Now print out the sequence of events:
846         cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
847         ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  port enables\n", cfg_ptr->dfa_memcfg0_base);
848         cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
849         cvmx_wait(4000000);  /* Wait  */
850
851         cvmx_write_csr(CVMX_DFA_MEMCFG1, cfg_ptr->dfa_memcfg1_base);
852         ll_printf("CVMX_DFA_MEMCFG1: 0x%08x\n", cfg_ptr->dfa_memcfg1_base);
853         cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG1 & ~(1ull<<63), cfg_ptr->dfa_memcfg1_base);
854
855         if (cfg_ptr->p0_ena ==1)
856         {
857             cvmx_write_csr(CVMX_DFA_MEMRLD,  cfg_ptr->mrs_dat_p0bunk0);
858             ll_printf("CVMX_DFA_MEMRLD : 0x%08x  p0_ena memrld\n", cfg_ptr->mrs_dat_p0bunk0);
859             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p0bunk0);
860
861             dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
862                             (1 << 23) |   // P0_INIT
863                             (1 << 25)     // BUNK_INIT[1:0]=Bunk#0
864                           );
865
866             cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
867             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  p0_init/bunk_init\n", dfa_memcfg0);
868             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
869             cvmx_wait(RLD_INIT_DELAY);
870             ll_printf("Delay.....\n");
871             cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
872             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  back to base\n", cfg_ptr->dfa_memcfg0_base);
873             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
874         }
875
876         if (cfg_ptr->p1_ena ==1)
877         {
878             cvmx_write_csr(CVMX_DFA_MEMRLD,  cfg_ptr->mrs_dat_p1bunk0);
879             ll_printf("CVMX_DFA_MEMRLD : 0x%08x  p1_ena memrld\n", cfg_ptr->mrs_dat_p1bunk0);
880             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p1bunk0);
881
882             dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
883                             (1 << 24) |   // P1_INIT
884                             (1 << 25)     // BUNK_INIT[1:0]=Bunk#0
885                           );
886             cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
887             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  p1_init/bunk_init\n", dfa_memcfg0);
888             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
889             cvmx_wait(RLD_INIT_DELAY);
890             ll_printf("Delay.....\n");
891             cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
892             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  back to base\n", cfg_ptr->dfa_memcfg0_base);
893             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
894         }
895
896         // P0 Bunk#1
897         if ((cfg_ptr->p0_ena ==1) && (cfg_ptr->bunkport == 2))
898         {
899             cvmx_write_csr(CVMX_DFA_MEMRLD,  cfg_ptr->mrs_dat_p0bunk1);
900             ll_printf("CVMX_DFA_MEMRLD : 0x%08x  p0_ena memrld\n", cfg_ptr->mrs_dat_p0bunk1);
901             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p0bunk1);
902
903             dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
904                             (1 << 23) |   // P0_INIT
905                             (2 << 25)     // BUNK_INIT[1:0]=Bunk#1
906                           );
907             cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
908             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  p0_init/bunk_init\n", dfa_memcfg0);
909             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
910             cvmx_wait(RLD_INIT_DELAY);
911             ll_printf("Delay.....\n");
912
913             if (cfg_ptr->p1_ena == 1)
914             { // Re-arm Px_INIT if P1-B1 init is required
915                 cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
916                 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  px_init rearm\n", cfg_ptr->dfa_memcfg0_base);
917                 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
918             }
919         }
920
921         if ((cfg_ptr->p1_ena == 1) && (cfg_ptr->bunkport == 2))
922         {
923             cvmx_write_csr(CVMX_DFA_MEMRLD,  cfg_ptr->mrs_dat_p1bunk1);
924             ll_printf("CVMX_DFA_MEMRLD : 0x%08x  p1_ena memrld\n", cfg_ptr->mrs_dat_p1bunk1);
925             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p1bunk1);
926
927             dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
928                             (1 << 24) |   // P1_INIT
929                             (2 << 25)     // BUNK_INIT[1:0]=10
930                           );
931             cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
932             ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  p1_init/bunk_init\n", dfa_memcfg0);
933             cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
934         }
935         cvmx_wait(4000000);  // 1/100S, 0.01S, 10mS
936         ll_printf("Delay.....\n");
937
938           /* Enable bunks */
939         dfa_memcfg0 = cfg_ptr->dfa_memcfg0_base |((cfg_ptr->bunkport >= 1) << 25) | ((cfg_ptr->bunkport == 2) << 26);
940         cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
941         ll_printf("CVMX_DFA_MEMCFG0: 0x%08x  enable bunks\n", dfa_memcfg0);
942         cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
943         cvmx_wait(RLD_INIT_DELAY);
944         ll_printf("Delay.....\n");
945
946           /* Issue a Silo reset by toggling SILRST in memcfg2. */
947         memcfg2.u64 = cvmx_read_csr (CVMX_DFA_MEMCFG2);
948         memcfg2.s.silrst = 1;
949         cvmx_write_csr (CVMX_DFA_MEMCFG2, memcfg2.u64);
950         ll_printf("CVMX_DFA_MEMCFG2: 0x%08x  silo reset start\n", (uint32_t) memcfg2.u64);
951         memcfg2.s.silrst = 0;
952         cvmx_write_csr (CVMX_DFA_MEMCFG2, memcfg2.u64);
953         ll_printf("CVMX_DFA_MEMCFG2: 0x%08x  silo reset done\n", (uint32_t) memcfg2.u64);
954     }
955 }
956