1 /***********************license start***************
2 * Copyright (c) 2011 Cavium Inc. ([email protected]). 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 Inc. 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 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
26 * countries.
27
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39
40
41 /**
42 * @file
43 *
44 * Helper utilities for qlm.
45 *
46 * <hr>$Revision: 70129 $<hr>
47 */
48 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
49 #include <asm/octeon/cvmx.h>
50 #include <asm/octeon/cvmx-bootmem.h>
51 #include <asm/octeon/cvmx-helper-jtag.h>
52 #include <asm/octeon/cvmx-qlm.h>
53 #include <asm/octeon/cvmx-gmxx-defs.h>
54 #include <asm/octeon/cvmx-sriox-defs.h>
55 #include <asm/octeon/cvmx-sriomaintx-defs.h>
56 #include <asm/octeon/cvmx-pciercx-defs.h>
57 #else
58 #if !defined(__FreeBSD__) || !defined(_KERNEL)
59 #include "executive-config.h"
60 #include "cvmx-config.h"
61 #include "cvmx.h"
62 #include "cvmx-bootmem.h"
63 #include "cvmx-helper-jtag.h"
64 #include "cvmx-qlm.h"
65 #else
66 #include "cvmx.h"
67 #include "cvmx-bootmem.h"
68 #include "cvmx-helper-jtag.h"
69 #include "cvmx-qlm.h"
70 #endif
71
72 #endif
73
74 /**
75 * The JTAG chain for CN52XX and CN56XX is 4 * 268 bits long, or 1072.
76 * CN5XXX full chain shift is:
77 * new data => lane 3 => lane 2 => lane 1 => lane 0 => data out
78 * The JTAG chain for CN63XX is 4 * 300 bits long, or 1200.
79 * The JTAG chain for CN68XX is 4 * 304 bits long, or 1216.
80 * The JTAG chain for CN66XX/CN61XX/CNF71XX is 4 * 304 bits long, or 1216.
81 * CN6XXX full chain shift is:
82 * new data => lane 0 => lane 1 => lane 2 => lane 3 => data out
83 * Shift LSB first, get LSB out
84 */
85 extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn52xx[];
86 extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn56xx[];
87 extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn63xx[];
88 extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn66xx[];
89 extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn68xx[];
90
91 #define CVMX_QLM_JTAG_UINT32 40
92 #ifdef CVMX_BUILD_FOR_LINUX_HOST
93 extern void octeon_remote_read_mem(void *buffer, uint64_t physical_address, int length);
94 extern void octeon_remote_write_mem(uint64_t physical_address, const void *buffer, int length);
95 uint32_t __cvmx_qlm_jtag_xor_ref[5][CVMX_QLM_JTAG_UINT32];
96 #else
97 typedef uint32_t qlm_jtag_uint32_t[CVMX_QLM_JTAG_UINT32];
98 CVMX_SHARED qlm_jtag_uint32_t *__cvmx_qlm_jtag_xor_ref;
99 #endif
100
101
102 /**
103 * Return the number of QLMs supported by the chip
104 *
105 * @return Number of QLMs
106 */
cvmx_qlm_get_num(void)107 int cvmx_qlm_get_num(void)
108 {
109 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
110 return 5;
111 else if (OCTEON_IS_MODEL(OCTEON_CN66XX))
112 return 3;
113 else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
114 return 3;
115 else if (OCTEON_IS_MODEL(OCTEON_CN61XX))
116 return 3;
117 else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
118 return 4;
119 else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
120 return 2;
121
122 //cvmx_dprintf("Warning: cvmx_qlm_get_num: This chip does not have QLMs\n");
123 return 0;
124 }
125
126 /**
127 * Return the qlm number based on the interface
128 *
129 * @param interface Interface to look up
130 */
cvmx_qlm_interface(int interface)131 int cvmx_qlm_interface(int interface)
132 {
133 if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
134 return (interface == 0) ? 2 : 0;
135 } else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) {
136 return 2 - interface;
137 } else {
138 /* Must be cn68XX */
139 switch(interface) {
140 case 1:
141 return 0;
142 default:
143 return interface;
144 }
145 }
146 }
147
148 /**
149 * Return number of lanes for a given qlm
150 *
151 * @return Number of lanes
152 */
cvmx_qlm_get_lanes(int qlm)153 int cvmx_qlm_get_lanes(int qlm)
154 {
155 if (OCTEON_IS_MODEL(OCTEON_CN61XX) && qlm == 1)
156 return 2;
157 else if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
158 return 2;
159
160 return 4;
161 }
162
163 /**
164 * Get the QLM JTAG fields based on Octeon model on the supported chips.
165 *
166 * @return qlm_jtag_field_t structure
167 */
cvmx_qlm_jtag_get_field(void)168 const __cvmx_qlm_jtag_field_t *cvmx_qlm_jtag_get_field(void)
169 {
170 /* Figure out which JTAG chain description we're using */
171 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
172 return __cvmx_qlm_jtag_field_cn68xx;
173 else if (OCTEON_IS_MODEL(OCTEON_CN66XX)
174 || OCTEON_IS_MODEL(OCTEON_CN61XX)
175 || OCTEON_IS_MODEL(OCTEON_CNF71XX))
176 return __cvmx_qlm_jtag_field_cn66xx;
177 else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
178 return __cvmx_qlm_jtag_field_cn63xx;
179 else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
180 return __cvmx_qlm_jtag_field_cn56xx;
181 else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
182 return __cvmx_qlm_jtag_field_cn52xx;
183 else
184 {
185 //cvmx_dprintf("cvmx_qlm_jtag_get_field: Needs update for this chip\n");
186 return NULL;
187 }
188 }
189
190 /**
191 * Get the QLM JTAG length by going through qlm_jtag_field for each
192 * Octeon model that is supported
193 *
194 * @return return the length.
195 */
cvmx_qlm_jtag_get_length(void)196 int cvmx_qlm_jtag_get_length(void)
197 {
198 const __cvmx_qlm_jtag_field_t *qlm_ptr = cvmx_qlm_jtag_get_field();
199 int length = 0;
200
201 /* Figure out how many bits are in the JTAG chain */
202 while (qlm_ptr != NULL && qlm_ptr->name)
203 {
204 if (qlm_ptr->stop_bit > length)
205 length = qlm_ptr->stop_bit + 1;
206 qlm_ptr++;
207 }
208 return length;
209 }
210
211 /**
212 * Initialize the QLM layer
213 */
cvmx_qlm_init(void)214 void cvmx_qlm_init(void)
215 {
216 int qlm;
217 int qlm_jtag_length;
218 char *qlm_jtag_name = "cvmx_qlm_jtag";
219 int qlm_jtag_size = CVMX_QLM_JTAG_UINT32 * 8 * 4;
220 static uint64_t qlm_base = 0;
221 const cvmx_bootmem_named_block_desc_t *desc;
222
223 #ifndef CVMX_BUILD_FOR_LINUX_HOST
224 /* Skip actual JTAG accesses on simulator */
225 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
226 return;
227 #endif
228
229 qlm_jtag_length = cvmx_qlm_jtag_get_length();
230
231 if (4 * qlm_jtag_length > (int)sizeof(__cvmx_qlm_jtag_xor_ref[0]) * 8)
232 {
233 cvmx_dprintf("ERROR: cvmx_qlm_init: JTAG chain larger than XOR ref size\n");
234 return;
235 }
236
237 /* No need to initialize the initial JTAG state if cvmx_qlm_jtag
238 named block is already created. */
239 if ((desc = cvmx_bootmem_find_named_block(qlm_jtag_name)) != NULL)
240 {
241 #ifdef CVMX_BUILD_FOR_LINUX_HOST
242 char buffer[qlm_jtag_size];
243
244 octeon_remote_read_mem(buffer, desc->base_addr, qlm_jtag_size);
245 memcpy(__cvmx_qlm_jtag_xor_ref, buffer, qlm_jtag_size);
246 #else
247 __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(desc->base_addr);
248 #endif
249 /* Initialize the internal JTAG */
250 cvmx_helper_qlm_jtag_init();
251 return;
252 }
253
254 /* Create named block to store the initial JTAG state. */
255 qlm_base = cvmx_bootmem_phy_named_block_alloc(qlm_jtag_size, 0, 0, 128, qlm_jtag_name, CVMX_BOOTMEM_FLAG_END_ALLOC);
256
257 if (qlm_base == -1ull)
258 {
259 cvmx_dprintf("ERROR: cvmx_qlm_init: Error in creating %s named block\n", qlm_jtag_name);
260 return;
261 }
262
263 #ifndef CVMX_BUILD_FOR_LINUX_HOST
264 __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(qlm_base);
265 #endif
266 memset(__cvmx_qlm_jtag_xor_ref, 0, qlm_jtag_size);
267
268 /* Initialize the internal JTAG */
269 cvmx_helper_qlm_jtag_init();
270
271 /* Read the XOR defaults for the JTAG chain */
272 for (qlm=0; qlm<cvmx_qlm_get_num(); qlm++)
273 {
274 int i;
275 /* Capture the reset defaults */
276 cvmx_helper_qlm_jtag_capture(qlm);
277 /* Save the reset defaults. This will shift out too much data, but
278 the extra zeros don't hurt anything */
279 for (i=0; i<CVMX_QLM_JTAG_UINT32; i++)
280 __cvmx_qlm_jtag_xor_ref[qlm][i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0);
281 }
282
283 #ifdef CVMX_BUILD_FOR_LINUX_HOST
284 /* Update the initial state for oct-remote utils. */
285 {
286 char buffer[qlm_jtag_size];
287
288 memcpy(buffer, &__cvmx_qlm_jtag_xor_ref, qlm_jtag_size);
289 octeon_remote_write_mem(qlm_base, buffer, qlm_jtag_size);
290 }
291 #endif
292
293 /* Apply speed tweak as a workaround for errata G-16094. */
294 __cvmx_qlm_speed_tweak();
295 __cvmx_qlm_pcie_idle_dac_tweak();
296 }
297
298 /**
299 * Lookup the bit information for a JTAG field name
300 *
301 * @param name Name to lookup
302 *
303 * @return Field info, or NULL on failure
304 */
__cvmx_qlm_lookup_field(const char * name)305 static const __cvmx_qlm_jtag_field_t *__cvmx_qlm_lookup_field(const char *name)
306 {
307 const __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field();
308 while (ptr->name)
309 {
310 if (strcmp(name, ptr->name) == 0)
311 return ptr;
312 ptr++;
313 }
314 cvmx_dprintf("__cvmx_qlm_lookup_field: Illegal field name %s\n", name);
315 return NULL;
316 }
317
318 /**
319 * Get a field in a QLM JTAG chain
320 *
321 * @param qlm QLM to get
322 * @param lane Lane in QLM to get
323 * @param name String name of field
324 *
325 * @return JTAG field value
326 */
cvmx_qlm_jtag_get(int qlm,int lane,const char * name)327 uint64_t cvmx_qlm_jtag_get(int qlm, int lane, const char *name)
328 {
329 const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name);
330 int qlm_jtag_length = cvmx_qlm_jtag_get_length();
331 int num_lanes = cvmx_qlm_get_lanes(qlm);
332
333 if (!field)
334 return 0;
335
336 /* Capture the current settings */
337 cvmx_helper_qlm_jtag_capture(qlm);
338 /* Shift past lanes we don't care about. CN6XXX shifts lane 3 first */
339 cvmx_helper_qlm_jtag_shift_zeros(qlm, qlm_jtag_length * (num_lanes-1-lane)); /* Shift to the start of the field */
340 cvmx_helper_qlm_jtag_shift_zeros(qlm, field->start_bit);
341 /* Shift out the value and return it */
342 return cvmx_helper_qlm_jtag_shift(qlm, field->stop_bit - field->start_bit + 1, 0);
343 }
344
345 /**
346 * Set a field in a QLM JTAG chain
347 *
348 * @param qlm QLM to set
349 * @param lane Lane in QLM to set, or -1 for all lanes
350 * @param name String name of field
351 * @param value Value of the field
352 */
cvmx_qlm_jtag_set(int qlm,int lane,const char * name,uint64_t value)353 void cvmx_qlm_jtag_set(int qlm, int lane, const char *name, uint64_t value)
354 {
355 int i, l;
356 uint32_t shift_values[CVMX_QLM_JTAG_UINT32];
357 int num_lanes = cvmx_qlm_get_lanes(qlm);
358 const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name);
359 int qlm_jtag_length = cvmx_qlm_jtag_get_length();
360 int total_length = qlm_jtag_length * num_lanes;
361 int bits = 0;
362
363 if (!field)
364 return;
365
366 /* Get the current state */
367 cvmx_helper_qlm_jtag_capture(qlm);
368 for (i=0; i<CVMX_QLM_JTAG_UINT32; i++)
369 shift_values[i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0);
370
371 /* Put new data in our local array */
372 for (l=0; l<num_lanes; l++)
373 {
374 uint64_t new_value = value;
375 int bits;
376 if ((l != lane) && (lane != -1))
377 continue;
378 for (bits = field->start_bit + (num_lanes-1-l)*qlm_jtag_length;
379 bits <= field->stop_bit + (num_lanes-1-l)*qlm_jtag_length;
380 bits++)
381 {
382 if (new_value & 1)
383 shift_values[bits/32] |= 1<<(bits&31);
384 else
385 shift_values[bits/32] &= ~(1<<(bits&31));
386 new_value>>=1;
387 }
388 }
389
390 /* Shift out data and xor with reference */
391 while (bits < total_length)
392 {
393 uint32_t shift = shift_values[bits/32] ^ __cvmx_qlm_jtag_xor_ref[qlm][bits/32];
394 int width = total_length - bits;
395 if (width > 32)
396 width = 32;
397 cvmx_helper_qlm_jtag_shift(qlm, width, shift);
398 bits += 32;
399 }
400
401 /* Update the new data */
402 cvmx_helper_qlm_jtag_update(qlm);
403 /* Always give the QLM 1ms to settle after every update. This may not
404 always be needed, but some of the options make significant
405 electrical changes */
406 cvmx_wait_usec(1000);
407 }
408
409 /**
410 * Errata G-16094: QLM Gen2 Equalizer Default Setting Change.
411 * CN68XX pass 1.x and CN66XX pass 1.x QLM tweak. This function tweaks the
412 * JTAG setting for a QLMs to run better at 5 and 6.25Ghz.
413 */
__cvmx_qlm_speed_tweak(void)414 void __cvmx_qlm_speed_tweak(void)
415 {
416 cvmx_mio_qlmx_cfg_t qlm_cfg;
417 int num_qlms = 0;
418 int qlm;
419
420 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X))
421 num_qlms = 5;
422 else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X))
423 num_qlms = 3;
424 else
425 return;
426
427 /* Loop through the QLMs */
428 for (qlm = 0; qlm < num_qlms; qlm++)
429 {
430 /* Read the QLM speed */
431 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
432
433 /* If the QLM is at 6.25Ghz or 5Ghz then program JTAG */
434 if ((qlm_cfg.s.qlm_spd == 5) || (qlm_cfg.s.qlm_spd == 12) ||
435 (qlm_cfg.s.qlm_spd == 0) || (qlm_cfg.s.qlm_spd == 6) ||
436 (qlm_cfg.s.qlm_spd == 11))
437 {
438 cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 0x1);
439 cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 0x8);
440 }
441 }
442 }
443
444 /**
445 * Errata G-16174: QLM Gen2 PCIe IDLE DAC change.
446 * CN68XX pass 1.x, CN66XX pass 1.x and CN63XX pass 1.0-2.2 QLM tweak.
447 * This function tweaks the JTAG setting for a QLMs for PCIe to run better.
448 */
__cvmx_qlm_pcie_idle_dac_tweak(void)449 void __cvmx_qlm_pcie_idle_dac_tweak(void)
450 {
451 int num_qlms = 0;
452 int qlm;
453
454 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X))
455 num_qlms = 5;
456 else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X))
457 num_qlms = 3;
458 else if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) ||
459 OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X))
460 num_qlms = 3;
461 else
462 return;
463
464 /* Loop through the QLMs */
465 for (qlm = 0; qlm < num_qlms; qlm++)
466 cvmx_qlm_jtag_set(qlm, -1, "idle_dac", 0x2);
467 }
468
469 #ifndef CVMX_BUILD_FOR_LINUX_HOST
470 /**
471 * Get the speed (Gbaud) of the QLM in Mhz.
472 *
473 * @param qlm QLM to examine
474 *
475 * @return Speed in Mhz
476 */
cvmx_qlm_get_gbaud_mhz(int qlm)477 int cvmx_qlm_get_gbaud_mhz(int qlm)
478 {
479 if (OCTEON_IS_MODEL(OCTEON_CN63XX))
480 {
481 if (qlm == 2)
482 {
483 cvmx_gmxx_inf_mode_t inf_mode;
484 inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
485 switch (inf_mode.s.speed)
486 {
487 case 0: return 5000; /* 5 Gbaud */
488 case 1: return 2500; /* 2.5 Gbaud */
489 case 2: return 2500; /* 2.5 Gbaud */
490 case 3: return 1250; /* 1.25 Gbaud */
491 case 4: return 1250; /* 1.25 Gbaud */
492 case 5: return 6250; /* 6.25 Gbaud */
493 case 6: return 5000; /* 5 Gbaud */
494 case 7: return 2500; /* 2.5 Gbaud */
495 case 8: return 3125; /* 3.125 Gbaud */
496 case 9: return 2500; /* 2.5 Gbaud */
497 case 10: return 1250; /* 1.25 Gbaud */
498 case 11: return 5000; /* 5 Gbaud */
499 case 12: return 6250; /* 6.25 Gbaud */
500 case 13: return 3750; /* 3.75 Gbaud */
501 case 14: return 3125; /* 3.125 Gbaud */
502 default: return 0; /* Disabled */
503 }
504 }
505 else
506 {
507 cvmx_sriox_status_reg_t status_reg;
508 status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm));
509 if (status_reg.s.srio)
510 {
511 cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;
512 sriomaintx_port_0_ctl2.u32 = cvmx_read_csr(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm));
513 switch (sriomaintx_port_0_ctl2.s.sel_baud)
514 {
515 case 1: return 1250; /* 1.25 Gbaud */
516 case 2: return 2500; /* 2.5 Gbaud */
517 case 3: return 3125; /* 3.125 Gbaud */
518 case 4: return 5000; /* 5 Gbaud */
519 case 5: return 6250; /* 6.250 Gbaud */
520 default: return 0; /* Disabled */
521 }
522 }
523 else
524 {
525 cvmx_pciercx_cfg032_t pciercx_cfg032;
526 pciercx_cfg032.u32 = cvmx_read_csr(CVMX_PCIERCX_CFG032(qlm));
527 switch (pciercx_cfg032.s.ls)
528 {
529 case 1:
530 return 2500;
531 case 2:
532 return 5000;
533 case 4:
534 return 8000;
535 default:
536 {
537 cvmx_mio_rst_boot_t mio_rst_boot;
538 mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
539 if ((qlm == 0) && mio_rst_boot.s.qlm0_spd == 0xf)
540 return 0;
541 if ((qlm == 1) && mio_rst_boot.s.qlm1_spd == 0xf)
542 return 0;
543 return 5000; /* Best guess I can make */
544 }
545 }
546 }
547 }
548 }
549 else if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
550 {
551 cvmx_mio_qlmx_cfg_t qlm_cfg;
552
553 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
554 switch (qlm_cfg.s.qlm_spd)
555 {
556 case 0: return 5000; /* 5 Gbaud */
557 case 1: return 2500; /* 2.5 Gbaud */
558 case 2: return 2500; /* 2.5 Gbaud */
559 case 3: return 1250; /* 1.25 Gbaud */
560 case 4: return 1250; /* 1.25 Gbaud */
561 case 5: return 6250; /* 6.25 Gbaud */
562 case 6: return 5000; /* 5 Gbaud */
563 case 7: return 2500; /* 2.5 Gbaud */
564 case 8: return 3125; /* 3.125 Gbaud */
565 case 9: return 2500; /* 2.5 Gbaud */
566 case 10: return 1250; /* 1.25 Gbaud */
567 case 11: return 5000; /* 5 Gbaud */
568 case 12: return 6250; /* 6.25 Gbaud */
569 case 13: return 3750; /* 3.75 Gbaud */
570 case 14: return 3125; /* 3.125 Gbaud */
571 default: return 0; /* Disabled */
572 }
573 }
574 return 0;
575 }
576 #endif
577
578 /*
579 * Read QLM and return status based on CN66XX.
580 * @return Return 1 if QLM is SGMII
581 * 2 if QLM is XAUI
582 * 3 if QLM is PCIe gen2 / gen1
583 * 4 if QLM is SRIO 1x4 short / long
584 * 5 if QLM is SRIO 2x2 short / long
585 * 6 if QLM is SRIO 4x1 short / long
586 * 7 if QLM is PCIe 1x2 gen2 / gen1
587 * 8 if QLM is PCIe 2x1 gen2 / gen1
588 * 9 if QLM is ILK
589 * 10 if QLM is RXAUI
590 * -1 otherwise
591 */
cvmx_qlm_get_status(int qlm)592 int cvmx_qlm_get_status(int qlm)
593 {
594 cvmx_mio_qlmx_cfg_t qlmx_cfg;
595
596 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
597 {
598 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
599 /* QLM is disabled when QLM SPD is 15. */
600 if (qlmx_cfg.s.qlm_spd == 15)
601 return -1;
602
603 switch (qlmx_cfg.s.qlm_cfg)
604 {
605 case 0: /* PCIE */
606 return 3;
607 case 1: /* ILK */
608 return 9;
609 case 2: /* SGMII */
610 return 1;
611 case 3: /* XAUI */
612 return 2;
613 case 7: /* RXAUI */
614 return 10;
615 default: return -1;
616 }
617 }
618 else if (OCTEON_IS_MODEL(OCTEON_CN66XX))
619 {
620 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
621 /* QLM is disabled when QLM SPD is 15. */
622 if (qlmx_cfg.s.qlm_spd == 15)
623 return -1;
624
625 switch (qlmx_cfg.s.qlm_cfg)
626 {
627 case 0x9: /* SGMII */
628 return 1;
629 case 0xb: /* XAUI */
630 return 2;
631 case 0x0: /* PCIE gen2 */
632 case 0x8: /* PCIE gen2 (alias) */
633 case 0x2: /* PCIE gen1 */
634 case 0xa: /* PCIE gen1 (alias) */
635 return 3;
636 case 0x1: /* SRIO 1x4 short */
637 case 0x3: /* SRIO 1x4 long */
638 return 4;
639 case 0x4: /* SRIO 2x2 short */
640 case 0x6: /* SRIO 2x2 long */
641 return 5;
642 case 0x5: /* SRIO 4x1 short */
643 case 0x7: /* SRIO 4x1 long */
644 if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
645 return 6;
646 default:
647 return -1;
648 }
649 }
650 else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
651 {
652 cvmx_sriox_status_reg_t status_reg;
653 /* For now skip qlm2 */
654 if (qlm == 2)
655 {
656 cvmx_gmxx_inf_mode_t inf_mode;
657 inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
658 if (inf_mode.s.speed == 15)
659 return -1;
660 else if(inf_mode.s.mode == 0)
661 return 1;
662 else
663 return 2;
664 }
665 status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm));
666 if (status_reg.s.srio)
667 return 4;
668 else
669 return 3;
670 }
671 else if (OCTEON_IS_MODEL(OCTEON_CN61XX))
672 {
673 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
674 /* QLM is disabled when QLM SPD is 15. */
675 if (qlmx_cfg.s.qlm_spd == 15)
676 return -1;
677
678 switch(qlm)
679 {
680 case 0:
681 switch (qlmx_cfg.s.qlm_cfg)
682 {
683 case 0: /* PCIe 1x4 gen2 / gen1 */
684 return 3;
685 case 2: /* SGMII */
686 return 1;
687 case 3: /* XAUI */
688 return 2;
689 default: return -1;
690 }
691 break;
692 case 1:
693 switch (qlmx_cfg.s.qlm_cfg)
694 {
695 case 0: /* PCIe 1x2 gen2 / gen1 */
696 return 7;
697 case 1: /* PCIe 2x1 gen2 / gen1 */
698 return 8;
699 default: return -1;
700 }
701 break;
702 case 2:
703 switch (qlmx_cfg.s.qlm_cfg)
704 {
705 case 2: /* SGMII */
706 return 1;
707 case 3: /* XAUI */
708 return 2;
709 default: return -1;
710 }
711 break;
712 }
713 }
714 else if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
715 {
716 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
717 /* QLM is disabled when QLM SPD is 15. */
718 if (qlmx_cfg.s.qlm_spd == 15)
719 return -1;
720
721 switch(qlm)
722 {
723 case 0:
724 if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */
725 return 1;
726 break;
727 case 1:
728 switch (qlmx_cfg.s.qlm_cfg)
729 {
730 case 0: /* PCIe 1x2 gen2 / gen1 */
731 return 7;
732 case 1: /* PCIe 2x1 gen2 / gen1 */
733 return 8;
734 default: return -1;
735 }
736 break;
737 }
738 }
739 return -1;
740 }
741