]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/octeon-sdk/cvmx-tra.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / octeon-sdk / cvmx-tra.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  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
43
44
45 /**
46  * @file
47  *
48  * Interface to the Trace buffer hardware.
49  *
50  * <hr>$Revision: 30644 $<hr>
51  */
52 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
53 #include <linux/module.h>
54 #include <asm/octeon/cvmx.h>
55 #include <asm/octeon/cvmx-tra.h>
56 #include <asm/octeon/cvmx-l2c.h>
57 #else
58 #include "cvmx.h"
59 #include "cvmx-tra.h"
60 #include "cvmx-l2c.h"
61 #endif
62
63 static const char *TYPE_ARRAY[] = {
64     "DWB - Don't write back",
65     "PL2 - Prefetch into L2",
66     "PSL1 - Dcache fill, skip L2",
67     "LDD - Dcache fill",
68     "LDI - Icache/IO fill",
69     "LDT - Icache/IO fill, skip L2",
70     "STF - Store full",
71     "STC - Store conditional",
72     "STP - Store partial",
73     "STT - Store full, skip L2",
74     "IOBLD8 - IOB 8bit load",
75     "IOBLD16 - IOB 16bit load",
76     "IOBLD32 - IOB 32bit load",
77     "IOBLD64 - IOB 64bit load",
78     "IOBST - IOB store",
79     "IOBDMA - Async IOB",
80     "SAA - Store atomic add",
81     "RSVD17",
82     "RSVD18",
83     "RSVD19",
84     "RSVD20",
85     "RSVD21",
86     "RSVD22",
87     "RSVD23",
88     "RSVD24",
89     "RSVD25",
90     "RSVD26",
91     "RSVD27",
92     "RSVD28",
93     "RSVD29",
94     "RSVD30",
95     "RSVD31"
96 };
97
98 static const char *TYPE_ARRAY2[] = {
99     "NOP - None",
100     "LDT - Icache/IO fill, skip L2",
101     "LDI - Icache/IO fill",
102     "PL2 - Prefetch into L2",
103     "RPL2 - Mark for replacement in L2",
104     "DWB - Don't write back",
105     "RSVD6",
106     "RSVD7",
107     "LDD - Dcache fill",
108     "PSL1 - Prefetch L1, skip L2",
109     "RSVD10",
110     "RSVD11",
111     "RSVD12",
112     "RSVD13",
113     "RSVD14",
114     "IOBDMA - Async IOB",
115     "STF - Store full",
116     "STT - Store full, skip L2",
117     "STP - Store partial",
118     "STC - Store conditional",
119     "STFIL1 - Store full, invalidate L1",
120     "STTIL1 - Store full, skip L2, invalidate L1",
121     "FAS32 - Atomic 32bit swap",
122     "FAS64 - Atomic 64bit swap",
123     "WBIL2i - Writeback, invalidate, by index/way",
124     "LTGL2i - Read tag@index/way",
125     "STGL2i - Write tag@index/way",
126     "RSVD27",
127     "INVL2 - Invalidate, by address",
128     "WBIL2 - Writeback, invalidate, by address",
129     "WBL2 - Writeback, by address",
130     "LCKL2 - Allocate, lock, by address",
131     "IOBLD8 - IOB 8bit load",
132     "IOBLD16 - IOB 16bit load",
133     "IOBLD32 - IOB 32bit load",
134     "IOBLD64 - IOB 64bit load",
135     "IOBST8 - IOB 8bit store",
136     "IOBST16 - IOB 16bit store",
137     "IOBST32 - IOB 32bit store",
138     "IOBST64 - IOB 64bit store",
139     "SET8 - 8bit Atomic swap with 1's",
140     "SET16 - 16bit Atomic swap with 1's",
141     "SET32 - 32bit Atomic swap with 1's",
142     "SET64 - 64bit Atomic swap with 1's",
143     "CLR8 - 8bit Atomic swap with 0's",
144     "CLR16 - 16bit Atomic swap with 0's",
145     "CLR32 - 32bit Atomic swap with 0's",
146     "CLR64 - 64bit Atomic swap with 0's",
147     "INCR8 - 8bit Atomic fetch & add by 1",
148     "INCR16 - 16bit Atomic fetch & add by 1",
149     "INCR32 - 32bit Atomic fetch & add by 1",
150     "INCR64 - 64bit Atomic fetch & add by 1",
151     "DECR8 - 8bit Atomic fetch & add by -1",
152     "DECR16 - 16bit Atomic fetch & add by -1",
153     "DECR32 - 32bit Atomic fetch & add by -1",
154     "DECR64 - 64bit Atomic fetch & add by -1",
155     "RSVD56",
156     "RSVD57",
157     "FAA32 - 32bit Atomic fetch and add",
158     "FAA64 - 64bit Atomic fetch and add",
159     "RSVD60",
160     "RSVD61",
161     "SAA32 - 32bit Atomic add",
162     "SAA64 - 64bit Atomic add"
163 };
164
165 static const char *SOURCE_ARRAY[] = {
166     "PP0",
167     "PP1",
168     "PP2",
169     "PP3",
170     "PP4",
171     "PP5",
172     "PP6",
173     "PP7",
174     "PP8",
175     "PP9",
176     "PP10",
177     "PP11",
178     "PP12",
179     "PP13",
180     "PP14",
181     "PP15",
182     "PIP/IPD",
183     "PKO-R",
184     "FPA/TIM/DFA/PCI/ZIP/POW/PKO-W",
185     "DWB",
186     "RSVD20",
187     "RSVD21",
188     "RSVD22",
189     "RSVD23",
190     "RSVD24",
191     "RSVD25",
192     "RSVD26",
193     "RSVD27",
194     "RSVD28",
195     "RSVD29",
196     "RSVD30",
197     "RSVD31",
198     "PP16",
199     "PP17",
200     "PP18",
201     "PP19",
202     "PP20",
203     "PP21",
204     "PP22",
205     "PP23",
206     "PP24",
207     "PP25",
208     "PP26",
209     "PP27",
210     "PP28",
211     "PP29",
212     "PP30",
213     "PP31"
214 };
215
216 static const char *DEST_ARRAY[] = {
217     "CIU/GPIO",
218     "RSVD1",
219     "RSVD2",
220     "PCI/PCIe/SLI",
221     "KEY",
222     "FPA",
223     "DFA",
224     "ZIP",
225     "RNG",
226     "IPD",
227     "PKO",
228     "RSVD11",
229     "POW",
230     "USB0",
231     "RAD",
232     "RSVD15",
233     "RSVD16",
234     "RSVD17",
235     "RSVD18",
236     "RSVD19",
237     "RSVD20",
238     "RSVD21",
239     "RSVD22",
240     "RSVD23",
241     "RSVD24",
242     "RSVD25",
243     "RSVD26",
244     "DPI",
245     "RSVD28",
246     "RSVD29",
247     "FAU",
248     "RSVD31"
249 };
250
251 int _cvmx_tra_unit = 0;
252
253 #define CVMX_TRA_SOURCE_MASK       (OCTEON_IS_MODEL(OCTEON_CN63XX) ? 0xf00ff : 0xfffff)
254 #define CVMX_TRA_DESTINATION_MASK  0xfffffffful
255
256 /**
257  * @INTERNAL
258  * Setup the trace buffer filter command mask. The bit position of filter commands
259  * are different for each Octeon model.
260  *
261  * @param filter    Which event to log
262  * @return          Bitmask of filter command based on the event.
263  */
264 static uint64_t __cvmx_tra_set_filter_cmd_mask(cvmx_tra_filt_t filter)
265 {
266     cvmx_tra_filt_cmd_t filter_command;
267
268     if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
269     {
270         /* Bit positions of filter commands are different, map it accordingly */
271         uint64_t cmd = 0;
272         if ((filter & CVMX_TRA_FILT_ALL) == -1ull)
273         {
274             if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
275                 cmd = 0x1ffff;
276             else
277                 cmd = 0xffff;
278         }
279         if (filter & CVMX_TRA_FILT_DWB)
280             cmd |= 1ull<<0;
281         if (filter & CVMX_TRA_FILT_PL2)
282             cmd |= 1ull<<1;
283         if (filter & CVMX_TRA_FILT_PSL1)
284             cmd |= 1ull<<2;
285         if (filter & CVMX_TRA_FILT_LDD)
286             cmd |= 1ull<<3;
287         if (filter & CVMX_TRA_FILT_LDI)
288             cmd |= 1ull<<4;
289         if (filter & CVMX_TRA_FILT_LDT)
290             cmd |= 1ull<<5;
291         if (filter & CVMX_TRA_FILT_STF)
292             cmd |= 1ull<<6;
293         if (filter & CVMX_TRA_FILT_STC)
294             cmd |= 1ull<<7;
295         if (filter & CVMX_TRA_FILT_STP)
296             cmd |= 1ull<<8;
297         if (filter & CVMX_TRA_FILT_STT)
298             cmd |= 1ull<<9;
299         if (filter & CVMX_TRA_FILT_IOBLD8)
300             cmd |= 1ull<<10;
301         if (filter & CVMX_TRA_FILT_IOBLD16)
302             cmd |= 1ull<<11;
303         if (filter & CVMX_TRA_FILT_IOBLD32)
304             cmd |= 1ull<<12;
305         if (filter & CVMX_TRA_FILT_IOBLD64)
306             cmd |= 1ull<<13;
307         if (filter & CVMX_TRA_FILT_IOBST)
308             cmd |= 1ull<<14;
309         if (filter & CVMX_TRA_FILT_IOBDMA)
310             cmd |= 1ull<<15;
311         if (OCTEON_IS_MODEL(OCTEON_CN5XXX) && (filter & CVMX_TRA_FILT_SAA))
312             cmd |= 1ull<<16;
313
314         filter_command.u64 = cmd;
315     }
316     else
317     {
318         if ((filter & CVMX_TRA_FILT_ALL) == -1ull)
319             filter_command.u64 = CVMX_TRA_FILT_ALL;
320         else
321             filter_command.u64 = filter;
322
323         filter_command.cn63xx.reserved_60_61 = 0;
324         filter_command.cn63xx.reserved_56_57 = 0;
325         filter_command.cn63xx.reserved_27_27 = 0;
326         filter_command.cn63xx.reserved_10_14 = 0;
327         filter_command.cn63xx.reserved_6_7 = 0;
328     }
329     return filter_command.u64;
330 }
331
332
333 /**
334  * Setup the TRA buffer for use
335  *
336  * @param control TRA control setup
337  * @param filter  Which events to log
338  * @param source_filter
339  *                Source match
340  * @param dest_filter
341  *                Destination match
342  * @param address Address compare
343  * @param address_mask
344  *                Address mask
345  */
346 void cvmx_tra_setup(cvmx_tra_ctl_t control, cvmx_tra_filt_t filter,
347                     cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter,
348                     uint64_t address, uint64_t address_mask)
349 {
350     cvmx_tra_filt_cmd_t filt_cmd;
351     cvmx_tra_filt_sid_t filt_sid;
352     cvmx_tra_filt_did_t filt_did;
353     int tad;
354
355     filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter);
356     filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK;
357     filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK;
358
359     /* Address filtering does not work when IOBDMA filter command is enabled
360        because of some caveats.  Disable the IOBDMA filter command. */
361     if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 
362         && ((filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA)
363         && address_mask != 0)
364     {
365         cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n");
366         filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA);
367     } 
368
369     /* In OcteonII pass2, the mode bit is added to enable reading the trace 
370        buffer data from different registers for lower and upper 64-bit value.
371        This bit is reserved in other Octeon models. */
372     control.s.rdat_md = 1;
373
374     for (tad = 0; tad < CVMX_L2C_TADS; tad++)
375     {
376         cvmx_write_csr(CVMX_TRAX_CTL(tad),            control.u64);
377         cvmx_write_csr(CVMX_TRAX_FILT_CMD(tad),       filt_cmd.u64);
378         cvmx_write_csr(CVMX_TRAX_FILT_SID(tad),       filt_sid.u64);
379         cvmx_write_csr(CVMX_TRAX_FILT_DID(tad),       filt_did.u64);
380         cvmx_write_csr(CVMX_TRAX_FILT_ADR_ADR(tad),   address);
381         cvmx_write_csr(CVMX_TRAX_FILT_ADR_MSK(tad),   address_mask);
382     }
383 }
384 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
385 EXPORT_SYMBOL(cvmx_tra_setup);
386 #endif
387
388 /**
389  * Setup each TRA buffer for use
390  *
391  * @param tra     Which TRA buffer to use (0-3)
392  * @param control TRA control setup
393  * @param filter  Which events to log
394  * @param source_filter
395  *                Source match
396  * @param dest_filter
397  *                Destination match
398  * @param address Address compare
399  * @param address_mask
400  *                Address mask
401  */
402 void cvmx_tra_setup_v2(int tra, cvmx_tra_ctl_t control, cvmx_tra_filt_t filter,
403                     cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter,
404                     uint64_t address, uint64_t address_mask)
405 {
406     cvmx_tra_filt_cmd_t filt_cmd;
407     cvmx_tra_filt_sid_t filt_sid;
408     cvmx_tra_filt_did_t filt_did;
409
410     if ((tra + 1) > CVMX_L2C_TADS)
411     {
412         cvmx_dprintf("cvmx_tra_setup_per_tra: Invalid tra(%d), max allowed (%d)\n", tra, CVMX_L2C_TADS - 1);
413         tra = 0;
414     }
415
416     filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter);
417     filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK;
418     filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK;
419
420     /* Address filtering does not work when IOBDMA filter command is enabled
421        because of some caveats.  Disable the IOBDMA filter command. */
422     if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 
423         && ((filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA)
424         && address_mask != 0)
425     {
426         cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n");
427         filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA);
428     } 
429
430     /* In OcteonII pass2, the mode bit is added to enable reading the trace 
431        buffer data from different registers for lower and upper 64-bit value.
432        This bit is reserved in other Octeon models. */
433     control.s.rdat_md = 1;
434
435     cvmx_write_csr(CVMX_TRAX_CTL(tra),            control.u64);
436     cvmx_write_csr(CVMX_TRAX_FILT_CMD(tra),       filt_cmd.u64);
437     cvmx_write_csr(CVMX_TRAX_FILT_SID(tra),       filt_sid.u64);
438     cvmx_write_csr(CVMX_TRAX_FILT_DID(tra),       filt_did.u64);
439     cvmx_write_csr(CVMX_TRAX_FILT_ADR_ADR(tra),   address);
440     cvmx_write_csr(CVMX_TRAX_FILT_ADR_MSK(tra),   address_mask);
441 }
442 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
443 EXPORT_SYMBOL(cvmx_tra_setup_v2);
444 #endif
445
446 /**
447  * Setup a TRA trigger. How the triggers are used should be
448  * setup using cvmx_tra_setup.
449  *
450  * @param trigger Trigger to setup (0 or 1)
451  * @param filter  Which types of events to trigger on
452  * @param source_filter
453  *                Source trigger match
454  * @param dest_filter
455  *                Destination trigger match
456  * @param address Trigger address compare
457  * @param address_mask
458  *                Trigger address mask
459  */
460 void cvmx_tra_trig_setup(uint64_t trigger, cvmx_tra_filt_t filter,
461                          cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter,
462                          uint64_t address, uint64_t address_mask)
463 {
464     cvmx_tra_filt_cmd_t tra_filt_cmd;
465     cvmx_tra_filt_sid_t tra_filt_sid;
466     cvmx_tra_filt_did_t tra_filt_did;
467     int tad;
468
469     tra_filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter);
470     tra_filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK;
471     tra_filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK;
472
473     /* Address filtering does not work when IOBDMA filter command is enabled
474        because of some caveats.  Disable the IOBDMA filter command. */
475     if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 
476         && ((tra_filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA)
477         && address_mask != 0)
478     {
479         cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n");
480         tra_filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA);
481     }
482
483     for (tad = 0; tad < CVMX_L2C_TADS; tad++)
484     {
485         cvmx_write_csr(CVMX_TRAX_TRIG0_CMD(tad) + trigger * 64,       tra_filt_cmd.u64);
486         cvmx_write_csr(CVMX_TRAX_TRIG0_SID(tad) + trigger * 64,       tra_filt_sid.u64);
487         cvmx_write_csr(CVMX_TRAX_TRIG0_DID(tad) + trigger * 64,       tra_filt_did.u64);
488         cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_ADR(tad) + trigger * 64,   address);
489         cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_MSK(tad) + trigger * 64,   address_mask);
490     }
491 }
492 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
493 EXPORT_SYMBOL(cvmx_tra_trig_setup);
494 #endif
495
496 /**
497  * Setup each TRA trigger. How the triggers are used should be
498  * setup using cvmx_tra_setup.
499  *
500  * @param tra     Which TRA buffer to use (0-3)
501  * @param trigger Trigger to setup (0 or 1)
502  * @param filter  Which types of events to trigger on
503  * @param source_filter
504  *                Source trigger match
505  * @param dest_filter
506  *                Destination trigger match
507  * @param address Trigger address compare
508  * @param address_mask
509  *                Trigger address mask
510  */
511 void cvmx_tra_trig_setup_v2(int tra, uint64_t trigger, cvmx_tra_filt_t filter,
512                          cvmx_tra_sid_t source_filter, cvmx_tra_did_t dest_filter,
513                          uint64_t address, uint64_t address_mask)
514 {
515     cvmx_tra_filt_cmd_t tra_filt_cmd;
516     cvmx_tra_filt_sid_t tra_filt_sid;
517     cvmx_tra_filt_did_t tra_filt_did;
518
519     tra_filt_cmd.u64 = __cvmx_tra_set_filter_cmd_mask(filter);
520     tra_filt_sid.u64 = source_filter & CVMX_TRA_SOURCE_MASK;
521     tra_filt_did.u64 = dest_filter & CVMX_TRA_DESTINATION_MASK;
522
523     /* Address filtering does not work when IOBDMA filter command is enabled
524        because of some caveats.  Disable the IOBDMA filter command. */
525     if ((OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 
526         && ((tra_filt_cmd.u64 & CVMX_TRA_FILT_IOBDMA) == CVMX_TRA_FILT_IOBDMA)
527         && address_mask != 0)
528     {
529         cvmx_dprintf("The address-based filtering does not work with IOBDMAs, disabling the filter command.\n");
530         tra_filt_cmd.u64 &= ~(CVMX_TRA_FILT_IOBDMA);
531     }
532
533     cvmx_write_csr(CVMX_TRAX_TRIG0_CMD(tra) + trigger * 64,       tra_filt_cmd.u64);
534     cvmx_write_csr(CVMX_TRAX_TRIG0_SID(tra) + trigger * 64,       tra_filt_sid.u64);
535     cvmx_write_csr(CVMX_TRAX_TRIG0_DID(tra) + trigger * 64,       tra_filt_did.u64);
536     cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_ADR(tra) + trigger * 64,   address);
537     cvmx_write_csr(CVMX_TRAX_TRIG0_ADR_MSK(tra) + trigger * 64,   address_mask);
538 }
539 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
540 EXPORT_SYMBOL(cvmx_tra_trig_setup_v2);
541 #endif
542
543 /**
544  * Read an entry from the TRA buffer
545  *
546  * @return Value return. High bit will be zero if there wasn't any data
547  */
548 cvmx_tra_data_t cvmx_tra_read(void)
549 {
550     uint64_t address = CVMX_TRA_READ_DAT;
551     cvmx_tra_data_t result;
552
553     /* The trace buffer format is wider than 64-bits in OcteonII model,
554        read the register again to get the second part of the data. */
555     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
556     {
557         /* These reads need to be as close as possible to each other */
558         result.u128.data = cvmx_read_csr(address);
559         result.u128.datahi = cvmx_read_csr(address);
560     }
561     else if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && !OCTEON_IS_MODEL(OCTEON_CN5XXX))
562     {
563         /* OcteonII pass2 uses different trace buffer data register for reading
564            lower and upper 64-bit values */
565         result.u128.data = cvmx_read_csr(address);
566         result.u128.datahi = cvmx_read_csr(CVMX_TRA_READ_DAT_HI);
567     }
568     else
569     {
570         result.u128.data = cvmx_read_csr(address);
571         result.u128.datahi = 0;
572     }
573
574     return result;
575 }
576
577 /**
578  * Read an entry from the TRA buffer from a given TRA unit.
579  *
580  * @param tra_unit  Trace buffer unit to read
581  *
582  * @return Value return. High bit will be zero if there wasn't any data
583  */
584 cvmx_tra_data_t cvmx_tra_read_v2(int tra_unit)
585 {
586     cvmx_tra_data_t result;
587
588     result.u128.data = cvmx_read_csr(CVMX_TRAX_READ_DAT(tra_unit));
589     result.u128.datahi = cvmx_read_csr(CVMX_TRAX_READ_DAT_HI(tra_unit));
590
591     return result;
592
593
594 /**
595  * Decode a TRA entry into human readable output
596  *
597  * @param tra_ctl Trace control setup
598  * @param data    Data to decode
599  */
600 void cvmx_tra_decode_text(cvmx_tra_ctl_t tra_ctl, cvmx_tra_data_t data)
601 {
602     if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
603     {
604         /* The type is a five bit field for some entries and 4 for other. The four
605            bit entries can be mis-typed if the top is set */
606         int type = data.cmn.type;
607
608         if (type >= 0x1a)
609             type &= 0xf;
610
611         switch (type)
612         {
613             case 0:  /* DWB */
614             case 1:  /* PL2 */
615             case 2:  /* PSL1 */
616             case 3:  /* LDD */
617             case 4:  /* LDI */
618             case 5:  /* LDT */
619                 cvmx_dprintf("0x%016llx %c%+10d %s %s 0x%016llx\n",
620                     (unsigned long long)data.u128.data,
621                     (data.cmn.discontinuity) ? 'D' : ' ',
622                     data.cmn.timestamp << (tra_ctl.s.time_grn*3),
623                     TYPE_ARRAY[type],
624                     SOURCE_ARRAY[data.cmn.source],
625                     (unsigned long long)data.cmn.address);
626                 break;
627             case 6:  /* STF */
628             case 7:  /* STC */
629             case 8:  /* STP */
630             case 9:  /* STT */
631             case 16: /* SAA */
632                 cvmx_dprintf("0x%016llx %c%+10d %s %s mask=0x%02x 0x%016llx\n",
633                    (unsigned long long)data.u128.data,
634                    (data.cmn.discontinuity) ? 'D' : ' ',
635                    data.cmn.timestamp << (tra_ctl.s.time_grn*3),
636                    TYPE_ARRAY[type],
637                    SOURCE_ARRAY[data.store.source],
638                    (unsigned int)data.store.mask,
639                    (unsigned long long)data.store.address << 3);
640                 break;
641             case 10:  /* IOBLD8 */
642             case 11:  /* IOBLD16 */
643             case 12:  /* IOBLD32 */
644             case 13:  /* IOBLD64 */
645             case 14:  /* IOBST */
646                 cvmx_dprintf("0x%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx\n",
647                    (unsigned long long)data.u128.data,
648                    (data.cmn.discontinuity) ? 'D' : ' ',
649                    data.cmn.timestamp << (tra_ctl.s.time_grn*3),
650                    TYPE_ARRAY[type],
651                    SOURCE_ARRAY[data.iobld.source],
652                    DEST_ARRAY[data.iobld.dest],
653                    (unsigned int)data.iobld.subid,
654                    (unsigned long long)data.iobld.address);
655                 break;
656             case 15:  /* IOBDMA */
657                 cvmx_dprintf("0x%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx\n",
658                    (unsigned long long)data.u128.data,
659                    (data.cmn.discontinuity) ? 'D' : ' ',
660                    data.cmn.timestamp << (tra_ctl.s.time_grn*3),
661                    TYPE_ARRAY[type],
662                    SOURCE_ARRAY[data.iob.source],
663                    DEST_ARRAY[data.iob.dest],
664                    (unsigned int)data.iob.mask,
665                    (unsigned long long)data.iob.address << 3);
666                 break;
667             default:
668                 cvmx_dprintf("0x%016llx %c%+10d Unknown format\n",
669                    (unsigned long long)data.u128.data,
670                    (data.cmn.discontinuity) ? 'D' : ' ',
671                    data.cmn.timestamp << (tra_ctl.s.time_grn*3));
672                 break;
673         }
674     }
675     else
676     {
677         int type;
678         int srcId;
679
680         type = data.cmn2.type;
681
682         switch (1ull<<type)
683         {
684             case CVMX_TRA_FILT_DECR64:
685             case CVMX_TRA_FILT_DECR32:
686             case CVMX_TRA_FILT_DECR16:
687             case CVMX_TRA_FILT_DECR8:
688             case CVMX_TRA_FILT_INCR64:
689             case CVMX_TRA_FILT_INCR32:
690             case CVMX_TRA_FILT_INCR16:
691             case CVMX_TRA_FILT_INCR8:
692             case CVMX_TRA_FILT_CLR64:
693             case CVMX_TRA_FILT_CLR32:
694             case CVMX_TRA_FILT_CLR16:
695             case CVMX_TRA_FILT_CLR8:
696             case CVMX_TRA_FILT_SET64:
697             case CVMX_TRA_FILT_SET32:
698             case CVMX_TRA_FILT_SET16:
699             case CVMX_TRA_FILT_SET8:
700             case CVMX_TRA_FILT_LCKL2:
701             case CVMX_TRA_FILT_WBIL2:
702             case CVMX_TRA_FILT_INVL2:
703             case CVMX_TRA_FILT_STGL2I:
704             case CVMX_TRA_FILT_LTGL2I:
705             case CVMX_TRA_FILT_WBIL2I:
706             case CVMX_TRA_FILT_WBL2:
707             case CVMX_TRA_FILT_DWB:
708             case CVMX_TRA_FILT_RPL2:
709             case CVMX_TRA_FILT_PL2:
710             case CVMX_TRA_FILT_LDI:
711             case CVMX_TRA_FILT_LDT:
712                 /* CN68XX has 32 cores which are distributed to use different
713                    trace buffers, decode the core that has data */
714                 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
715                 {
716                     if (data.cmn2.source <= 7)
717                     {
718                         srcId = _cvmx_tra_unit + (data.cmn2.source * 4);
719                         if (srcId >= 16)
720                             srcId += 16;
721                     }
722                     else
723                         srcId = (data.cmn2.source);
724                 }
725                 else
726                         srcId = (data.cmn2.source);
727                 
728                 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s 0x%016llx%llx\n",
729                    (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
730                    (data.cmn2.discontinuity) ? 'D' : ' ',
731                    data.cmn2.timestamp << (tra_ctl.s.time_grn*3),
732                    TYPE_ARRAY2[type],
733                    SOURCE_ARRAY[srcId],
734                    (unsigned long long)data.cmn2.addresshi,
735                    (unsigned long long)data.cmn2.addresslo);
736                 break;
737             case CVMX_TRA_FILT_PSL1:
738             case CVMX_TRA_FILT_LDD:
739             case CVMX_TRA_FILT_FAS64:
740             case CVMX_TRA_FILT_FAS32:
741             case CVMX_TRA_FILT_FAA64:
742             case CVMX_TRA_FILT_FAA32:
743             case CVMX_TRA_FILT_SAA64:
744             case CVMX_TRA_FILT_SAA32:
745             case CVMX_TRA_FILT_STC:
746             case CVMX_TRA_FILT_STF:
747             case CVMX_TRA_FILT_STP:
748             case CVMX_TRA_FILT_STT:
749             case CVMX_TRA_FILT_STTIL1:
750             case CVMX_TRA_FILT_STFIL1:
751                 /* CN68XX has 32 cores which are distributed to use different
752                    trace buffers, decode the core that has data */
753                 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
754                 {
755                     if (data.store2.source <= 7)
756                     {
757                         srcId = _cvmx_tra_unit + (data.store2.source * 4);
758                         if (srcId >= 16)
759                             srcId += 16;
760                     }
761                     else
762                         srcId = data.store2.source;
763                 }
764                 else
765                         srcId = data.store2.source;
766
767                 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s mask=0x%02x 0x%016llx%llx\n",
768                    (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
769                    (data.cmn2.discontinuity) ? 'D' : ' ',
770                    data.cmn2.timestamp << (tra_ctl.s.time_grn*3),
771                    TYPE_ARRAY2[type],
772                    SOURCE_ARRAY[srcId],
773                    (unsigned int)data.store2.mask,
774                    (unsigned long long)data.store2.addresshi,
775                    (unsigned long long)data.store2.addresslo);
776                 break;
777             case CVMX_TRA_FILT_IOBST64:
778             case CVMX_TRA_FILT_IOBST32:
779             case CVMX_TRA_FILT_IOBST16:
780             case CVMX_TRA_FILT_IOBST8:
781             case CVMX_TRA_FILT_IOBLD64:
782             case CVMX_TRA_FILT_IOBLD32:
783             case CVMX_TRA_FILT_IOBLD16:
784             case CVMX_TRA_FILT_IOBLD8:
785                 /* CN68XX has 32 cores which are distributed to use different
786                    trace buffers, decode the core that has data */
787                 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
788                 {
789                     if (data.iobld2.source <= 7)
790                     {
791                         srcId = _cvmx_tra_unit + (data.iobld2.source * 4);
792                         if (srcId >= 16)
793                             srcId += 16;
794                     }
795                     else
796                         srcId = data.iobld2.source;
797                 }
798                 else
799                         srcId = data.iobld2.source;
800
801                 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s->%s subdid=0x%x 0x%016llx%llx\n",
802                    (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
803                    (data.cmn2.discontinuity) ? 'D' : ' ',
804                    data.cmn2.timestamp << (tra_ctl.s.time_grn*3),
805                    TYPE_ARRAY2[type],
806                    SOURCE_ARRAY[srcId],
807                    DEST_ARRAY[data.iobld2.dest],
808                    (unsigned int)data.iobld2.subid,
809                    (unsigned long long)data.iobld2.addresshi,
810                    (unsigned long long)data.iobld2.addresslo);
811                 break;
812             case CVMX_TRA_FILT_IOBDMA:
813                 /* CN68XX has 32 cores which are distributed to use different
814                    trace buffers, decode the core that has data */
815                 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
816                 {
817                     if (data.iob2.source <= 7)
818                     {
819                         srcId = _cvmx_tra_unit + (data.iob2.source * 4);
820                         if (srcId >= 16)
821                             srcId += 16;
822                     }
823                     else
824                         srcId = data.iob2.source;
825                 }
826                 else
827                         srcId = data.iob2.source;
828
829                 cvmx_dprintf("0x%016llx%016llx %c%+10d %s %s->%s len=0x%x 0x%016llx%llx\n",
830                    (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
831                    (data.iob2.discontinuity) ? 'D' : ' ',
832                    data.iob2.timestamp << (tra_ctl.s.time_grn*3),
833                    TYPE_ARRAY2[type],
834                    SOURCE_ARRAY[srcId],
835                    DEST_ARRAY[data.iob2.dest],
836                    (unsigned int)data.iob2.mask,
837                    (unsigned long long)data.iob2.addresshi << 3,
838                    (unsigned long long)data.iob2.addresslo << 3);
839                 break;
840             default:
841                 cvmx_dprintf("0x%016llx%016llx %c%+10d Unknown format\n",
842                    (unsigned long long)data.u128.datahi, (unsigned long long)data.u128.data,
843                    (data.cmn2.discontinuity) ? 'D' : ' ',
844                    data.cmn2.timestamp << (tra_ctl.s.time_grn*3));
845                 break;
846         }
847     }
848 }
849
850 /**
851  * Display the entire trace buffer. It is advised that you
852  * disable the trace buffer before calling this routine
853  * otherwise it could infinitely loop displaying trace data
854  * that it created.
855  */
856 void cvmx_tra_display(void)
857 {
858     int valid = 0;
859
860     /* Collect data from each TRA unit for decoding */
861     if (CVMX_L2C_TADS > 1)
862     {
863         cvmx_trax_ctl_t tra_ctl;
864         cvmx_tra_data_t data[4];
865         int tad;
866         do 
867         {
868             valid = 0;
869             for (tad = 0; tad < CVMX_L2C_TADS; tad++)
870                 data[tad] = cvmx_tra_read_v2(tad);
871
872             for (tad = 0; tad < CVMX_L2C_TADS; tad++)
873             {
874                 tra_ctl.u64 = cvmx_read_csr(CVMX_TRAX_CTL(tad));
875
876                 if (data[tad].cmn2.valid)
877                 {
878                     _cvmx_tra_unit = tad;
879                     cvmx_tra_decode_text(tra_ctl, data[tad]);
880                     valid = 1;
881                 }
882             }
883         } while (valid);
884     }
885     else
886     {
887         cvmx_tra_ctl_t tra_ctl;
888         cvmx_tra_data_t data;
889
890         tra_ctl.u64 = cvmx_read_csr(CVMX_TRA_CTL);
891
892         do
893         {
894             data = cvmx_tra_read();
895             if ((OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) && data.cmn.valid)
896                 valid = 1;
897             else if (data.cmn2.valid)
898                 valid = 1;
899             else
900                 valid = 0;
901     
902             if (valid)
903                 cvmx_tra_decode_text(tra_ctl, data);
904
905         } while (valid);
906     }
907 }
908 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
909 EXPORT_SYMBOL(cvmx_tra_display);
910 #endif
911
912 /**
913  * Display the entire trace buffer. It is advised that you
914  * disable the trace buffer before calling this routine
915  * otherwise it could infinitely loop displaying trace data
916  * that it created.
917  *
918  * @param tra_unit   Which TRA buffer to use.
919  */
920 void cvmx_tra_display_v2(int tra_unit)
921 {
922     int valid = 0;
923
924     cvmx_trax_ctl_t tra_ctl;
925     cvmx_tra_data_t data;
926
927     valid = 0;
928     tra_ctl.u64 = cvmx_read_csr(CVMX_TRAX_CTL(tra_unit));
929
930     do 
931     {
932         data = cvmx_tra_read_v2(tra_unit);
933         if (data.cmn2.valid)
934         {
935             _cvmx_tra_unit = tra_unit; 
936             cvmx_tra_decode_text(tra_ctl, data);
937             valid = 1;
938         }
939     } while (valid);
940 }
941 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
942 EXPORT_SYMBOL(cvmx_tra_display_v2);
943 #endif