]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/octeon-sdk/cvmx-qlm.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / octeon-sdk / cvmx-qlm.c
1 /***********************license start***************
2  * Copyright (c) 2011  Cavium Inc. (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 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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 }