]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/octeon-sdk/cvmx-srio.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / octeon-sdk / cvmx-srio.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  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  * 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  NETWORKS 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  * @file
44  *
45  * Interface to SRIO
46  *
47  * <hr>$Revision: 41586 $<hr>
48  */
49 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
50 #include <asm/octeon/cvmx.h>
51 #include <asm/octeon/cvmx-srio.h>
52 #include <asm/octeon/cvmx-clock.h>
53 #include <asm/octeon/cvmx-atomic.h>
54 #ifdef CONFIG_CAVIUM_DECODE_RSL
55 #include <asm/octeon/cvmx-error.h>
56 #endif
57 #include <asm/octeon/cvmx-sriox-defs.h>
58 #include <asm/octeon/cvmx-sriomaintx-defs.h>
59 #include <asm/octeon/cvmx-sli-defs.h>
60 #include <asm/octeon/cvmx-dpi-defs.h>
61 #include <asm/octeon/cvmx-pexp-defs.h>
62 #include <asm/octeon/cvmx-helper.h>
63 #else
64 #include "cvmx.h"
65 #include "cvmx-srio.h"
66 #include "cvmx-clock.h"
67 #include "cvmx-helper.h"
68 #ifndef CVMX_BUILD_FOR_LINUX_HOST
69 #include "cvmx-atomic.h"
70 #include "cvmx-error.h"
71 #include "cvmx-helper-errata.h"
72 #endif
73 #endif
74
75 #define CVMX_SRIO_USE_FIFO_FOR_MAINT    1
76 #define CVMX_SRIO_CONFIG_TIMEOUT        10000 /* 10ms */
77 #define CVMX_SRIO_DOORBELL_TIMEOUT      10000 /* 10ms */
78 #define CVMX_SRIO_CONFIG_PRIORITY       0
79 #define ULL unsigned long long
80
81 typedef union
82 {
83     uint64_t    u64;
84     struct
85     {
86 #if __BYTE_ORDER == __BIG_ENDIAN
87         uint64_t    upper           : 2;    /* Normally 2 for XKPHYS */
88         uint64_t    reserved_49_61  : 13;   /* Must be zero */
89         uint64_t    io              : 1;    /* 1 for IO space access */
90         uint64_t    did             : 5;    /* DID = 3 */
91         uint64_t    subdid          : 3;    /* SubDID = 3-6 */
92         uint64_t    reserved_36_39  : 4;    /* Must be zero */
93         uint64_t    se              : 2;    /* SubDID extender */
94         uint64_t    reserved_32_33  : 2;    /* Must be zero */
95         uint64_t    hopcount        : 8;    /* Hopcount */
96         uint64_t    address         : 24;   /* Mem address */
97 #else
98         uint64_t    address         : 24;
99         uint64_t    hopcount        : 8;
100         uint64_t    reserved_32_33  : 2;
101         uint64_t    se              : 2;
102         uint64_t    reserved_36_39  : 4;
103         uint64_t    subdid          : 3;
104         uint64_t    did             : 5;
105         uint64_t    io              : 1;
106         uint64_t    reserved_49_61  : 13;
107         uint64_t    upper           : 2;
108 #endif
109     } config;
110     struct
111     {
112 #if __BYTE_ORDER == __BIG_ENDIAN
113         uint64_t    upper           : 2;    /* Normally 2 for XKPHYS */
114         uint64_t    reserved_49_61  : 13;   /* Must be zero */
115         uint64_t    io              : 1;    /* 1 for IO space access */
116         uint64_t    did             : 5;    /* DID = 3 */
117         uint64_t    subdid          : 3;    /* SubDID = 3-6 */
118         uint64_t    reserved_36_39  : 4;    /* Must be zero */
119         uint64_t    se              : 2;    /* SubDID extender */
120         uint64_t    address         : 34;   /* Mem address */
121 #else
122         uint64_t    address         : 34;
123         uint64_t    se              : 2;
124         uint64_t    reserved_36_39  : 4;
125         uint64_t    subdid          : 3;
126         uint64_t    did             : 5;
127         uint64_t    io              : 1;
128         uint64_t    reserved_49_61  : 13;
129         uint64_t    upper           : 2;
130 #endif
131     } mem;
132 } cvmx_sli_address_t;
133
134 typedef struct
135 {
136     cvmx_srio_initialize_flags_t flags;
137     int32_t subidx_ref_count[16];   /* Reference count for SLI_MEM_ACCESS_SUBID[12-27]. Index=X-12 */
138     int32_t s2m_ref_count[16];   /* Reference count for SRIOX_S2M_TYPE[0-15]. */
139 } __cvmx_srio_state_t;
140
141 static CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[2];
142
143
144 #ifndef CVMX_BUILD_FOR_LINUX_HOST
145 /**
146  * @INTERNAL
147  * Allocate a SRIOX_S2M_TYPEX register for mapping a remote SRIO
148  * device's address range into Octeons SLI address space. Reference
149  * counting is used to allow sharing of duplicate setups. The current
150  * implementation treats reads and writes as paired, but this could be
151  * changed if we have trouble running out of indexes.
152  *
153  * @param srio_port SRIO port device is on
154  * @param s2m       SRIOX_S2M_TYPEX setup required
155  *
156  * @return Index of CSR, or negative on failure
157  */
158 static int __cvmx_srio_alloc_s2m(int srio_port, cvmx_sriox_s2m_typex_t s2m)
159 {
160     int s2m_index;
161     /* Search through the S2M_TYPE registers looking for an unsed one or one
162         setup the way we need it */
163     for (s2m_index=0; s2m_index<16; s2m_index++)
164     {
165         /* Increment ref count by 2 since we count read and write
166             independently. We might need a more complicated search in the
167             future */
168         int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], 2);
169         if (ref_count == 0)
170         {
171             /* Unused location. Write our value */
172             cvmx_write_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port), s2m.u64);
173             return s2m_index;
174         }
175         else
176         {
177             /* In use, see if we can use it */
178             if (cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)) == s2m.u64)
179                 return s2m_index;
180             else
181                 cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], -2);
182         }
183     }
184     cvmx_dprintf("SRIO%d: Unable to find free SRIOX_S2M_TYPEX\n", srio_port);
185     return -1;
186 }
187
188
189 /**
190  * @INTERNAL
191  * Free a handle allocated by __cvmx_srio_alloc_s2m
192  *
193  * @param srio_port SRIO port
194  * @param index     Index to free
195  */
196 static void __cvmx_srio_free_s2m(int srio_port, int index)
197 {
198     /* Read to force pending transactions to complete */
199     cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(index, srio_port));
200     cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[index], -2);
201 }
202
203
204 /**
205  * @INTERNAL
206  * Allocate a SLI SubID to map a region of memory. Reference
207  * counting is used to allow sharing of duplicate setups.
208  *
209  * @param subid  SLI_MEM_ACCESS_SUBIDX we need an index for
210  *
211  * @return Index of CSR, or negative on failure
212  */
213 static int __cvmx_srio_alloc_subid(cvmx_sli_mem_access_subidx_t subid)
214 {
215     int mem_index;
216     /* Search through the mem access subid registers looking for an unsed one
217         or one setup the way we need it. PCIe uses the low indexes, so search
218         backwards */
219     for (mem_index=27; mem_index>=12; mem_index--)
220     {
221         int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], 1);
222         if (ref_count == 0)
223         {
224             /* Unused location. Write our value */
225             cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index), subid.u64);
226             return mem_index;
227         }
228         else
229         {
230             /* In use, see if we can use it */
231             if (cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)) == subid.u64)
232                 return mem_index;
233             else
234                 cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], -1);
235         }
236     }
237     cvmx_dprintf("SRIO: Unable to find free SLI_MEM_ACCESS_SUBIDX\n");
238     return -1;
239 }
240
241
242 /**
243  * @INTERNAL
244  * Free a handle allocated by __cvmx_srio_alloc_subid
245  *
246  * @param index  Index to free
247  */
248 static void __cvmx_srio_free_subid(int index)
249 {
250     /* Read to force pending transactions to complete */
251     cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(index));
252     cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[index-12], -1);
253 }
254 #endif
255
256
257 /**
258  * @INTERNAL
259  * Read 32bits from a local port
260  *
261  * @param srio_port SRIO port the device is on
262  * @param offset    Offset in config space. This must be a multiple of 32 bits.
263  * @param result    Result of the read. This will be unmodified on failure.
264  *
265  * @return Zero on success, negative on failure.
266  */
267 static int __cvmx_srio_local_read32(int srio_port, uint32_t offset, uint32_t *result)
268 {
269     cvmx_sriox_maint_op_t maint_op;
270     cvmx_sriox_maint_rd_data_t maint_rd_data;
271     maint_op.u64 = 0;
272     maint_op.s.op = 0; /* Read */
273     maint_op.s.addr = offset;
274
275     /* Make sure SRIO isn't already busy */
276     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
277     {
278         cvmx_dprintf("SRIO%d: Pending bit stuck before config read\n", srio_port);
279         return -1;
280     }
281
282     /* Issue the read to the hardware */
283     cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64);
284
285     /* Wait for the hardware to complete the operation */
286     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
287     {
288         cvmx_dprintf("SRIO%d: Config read timeout\n", srio_port);
289         return -1;
290     }
291
292     /* Display and error and return if the operation failed to issue */
293     maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port));
294     if (maint_op.s.fail)
295     {
296         cvmx_dprintf("SRIO%d: Config read addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset);
297         return -1;
298     }
299
300     /* Wait for the read data to become valid */
301     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_RD_DATA(srio_port), cvmx_sriox_maint_rd_data_t, valid, ==, 1, CVMX_SRIO_CONFIG_TIMEOUT))
302     {
303         cvmx_dprintf("SRIO%d: Config read data timeout\n", srio_port);
304         return -1;
305     }
306
307     /* Get the read data */
308     maint_rd_data.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_RD_DATA(srio_port));
309     *result = maint_rd_data.s.rd_data;
310     return 0;
311 }
312
313
314 /**
315  * @INTERNAL
316  * Write 32bits to a local port
317  * @param srio_port SRIO port the device is on
318  * @param offset    Offset in config space. This must be a multiple of 32 bits.
319  * @param data      Data to write.
320  *
321  * @return Zero on success, negative on failure.
322  */
323 static int __cvmx_srio_local_write32(int srio_port, uint32_t offset, uint32_t data)
324 {
325     cvmx_sriox_maint_op_t maint_op;
326     maint_op.u64 = 0;
327     maint_op.s.wr_data = data;
328     maint_op.s.op = 1; /* Write */
329     maint_op.s.addr = offset;
330
331     /* Make sure SRIO isn't already busy */
332     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
333     {
334         cvmx_dprintf("SRIO%d: Pending bit stuck before config write\n", srio_port);
335         return -1;
336     }
337
338     /* Issue the write to the hardware */
339     cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64);
340
341     /* Wait for the hardware to complete the operation */
342     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
343     {
344         cvmx_dprintf("SRIO%d: Config write timeout\n", srio_port);
345         return -1;
346     }
347
348     /* Display and error and return if the operation failed to issue */
349     maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port));
350     if (maint_op.s.fail)
351     {
352         cvmx_dprintf("SRIO%d: Config write addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset);
353         return -1;
354     }
355     return 0;
356 }
357
358
359 /**
360  * Initialize a SRIO port for use.
361  *
362  * @param srio_port SRIO port to initialize
363  * @param flags     Optional flags
364  *
365  * @return Zero on success
366  */
367 int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags)
368 {
369     cvmx_sriomaintx_port_lt_ctl_t port_lt_ctl;
370     cvmx_sriomaintx_port_rt_ctl_t port_rt_ctl;
371     cvmx_sriomaintx_port_0_ctl_t port_0_ctl;
372     cvmx_sriomaintx_core_enables_t core_enables;
373     cvmx_sriomaintx_port_gen_ctl_t port_gen_ctl;
374     cvmx_sriox_status_reg_t sriox_status_reg;
375     cvmx_mio_rst_ctlx_t mio_rst_ctl;
376     cvmx_sriox_imsg_vport_thr_t sriox_imsg_vport_thr;
377     cvmx_dpi_sli_prtx_cfg_t prt_cfg;
378     cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl;
379
380     sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port));
381     if (!sriox_status_reg.s.srio)
382     {
383         cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port);
384         return -1;
385     }
386
387     __cvmx_srio_state[srio_port].flags = flags;
388
389     /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be
390         programmed */
391     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0))
392     {
393         if (srio_port)
394         {
395             cvmx_ciu_qlm1_t ciu_qlm;
396             ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1);
397             ciu_qlm.s.txbypass = 1;
398             ciu_qlm.s.txdeemph = 5;
399             ciu_qlm.s.txmargin = 0x17;
400             cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64);
401         }
402         else
403         {
404             cvmx_ciu_qlm0_t ciu_qlm;
405             ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0);
406             ciu_qlm.s.txbypass = 1;
407             ciu_qlm.s.txdeemph = 5;
408             ciu_qlm.s.txmargin = 0x17;
409             cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64);
410         }
411     }
412
413     mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port));
414     cvmx_dprintf("SRIO%d: Port in %s mode\n", srio_port,
415         (mio_rst_ctl.s.prtmode) ? "host" : "endpoint");
416
417     /* Bring the port out of reset if necessary */
418     if (srio_port)
419     {
420         cvmx_ciu_soft_prst1_t prst;
421         prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
422         if (prst.s.soft_prst)
423         {
424             prst.s.soft_prst = 0;
425             cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64);
426             cvmx_wait_usec(10000); /* 10ms for new link to stabalize */
427         }
428     }
429     else
430     {
431         cvmx_ciu_soft_prst_t prst;
432         prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
433         if (prst.s.soft_prst)
434         {
435             prst.s.soft_prst = 0;
436             cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64);
437             cvmx_wait_usec(10000); /* 10ms for new link to stabalize */
438         }
439     }
440
441     /* Disable the link while we make changes */
442     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32))
443         return -1;
444     port_0_ctl.s.disable = 1;
445     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32))
446         return -1;
447
448     /* Errata SRIO-14485: Link speed is reported incorrectly in CN63XX
449         pass 1.x */
450     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
451     {
452         cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2;
453         if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32))
454             return -1;
455         if (port_0_ctl2.s.enb_500g)
456         {
457             port_0_ctl2.u32 = 0;
458             port_0_ctl2.s.enb_625g = 1;
459         }
460         else if (port_0_ctl2.s.enb_312g)
461         {
462             port_0_ctl2.u32 = 0;
463             port_0_ctl2.s.enb_500g = 1;
464         }
465         else if (port_0_ctl2.s.enb_250g)
466         {
467             port_0_ctl2.u32 = 0;
468             port_0_ctl2.s.enb_312g = 1;
469         }
470         else if (port_0_ctl2.s.enb_125g)
471         {
472             port_0_ctl2.u32 = 0;
473             port_0_ctl2.s.enb_250g = 1;
474         }
475         else
476         {
477             port_0_ctl2.u32 = 0;
478             port_0_ctl2.s.enb_125g = 1;
479         }
480         if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32))
481             return -1;
482     }
483
484     /* Set the link layer timeout to 10us. The default is too high and causes
485         core bus errors */
486     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), &port_lt_ctl.u32))
487         return -1;
488     port_lt_ctl.s.timeout = 10000 / 200; /* 10us = 10000ns / 200ns */
489     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), port_lt_ctl.u32))
490         return -1;
491
492     /* Set the logical layer timeout to 10ms. The default is too high and causes
493         core bus errors */
494     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), &port_rt_ctl.u32))
495         return -1;
496     port_rt_ctl.s.timeout = 10000000 / 200; /* 10ms = 10000000ns / 200ns */
497     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), port_rt_ctl.u32))
498         return -1;
499
500     /* Allow memory and doorbells. Messaging is enabled later */
501     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &core_enables.u32))
502         return -1;
503     core_enables.s.doorbell = 1;
504     core_enables.s.memory = 1;
505     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), core_enables.u32))
506         return -1;
507
508     /* Allow us to master transactions */
509     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), &port_gen_ctl.u32))
510         return -1;
511     port_gen_ctl.s.menable = 1;
512     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), port_gen_ctl.u32))
513         return -1;
514
515     /* Set the MRRS and MPS for optimal SRIO performance */
516     prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port));
517     prt_cfg.s.mps = 1;
518     prt_cfg.s.mrrs = 1;
519     cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port), prt_cfg.u64);
520
521     sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port));
522     sli_s2m_portx_ctl.s.mrrs = 1;
523     cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port), sli_s2m_portx_ctl.u64);
524
525     /* Setup RX messaging thresholds */
526     sriox_imsg_vport_thr.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port));
527     sriox_imsg_vport_thr.s.max_tot = 48;
528     sriox_imsg_vport_thr.s.max_s1 = 24;
529     sriox_imsg_vport_thr.s.max_s0 = 24;
530     sriox_imsg_vport_thr.s.sp_vport = 1;
531     sriox_imsg_vport_thr.s.buf_thr = 4;
532     sriox_imsg_vport_thr.s.max_p1 = 12;
533     sriox_imsg_vport_thr.s.max_p0 = 12;
534     cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port), sriox_imsg_vport_thr.u64);
535
536     /* Errata SRIO-X: SRIO error behavior may not be optimal in CN63XX pass 1.x */
537     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
538     {
539         cvmx_sriox_tx_ctrl_t sriox_tx_ctrl;
540         sriox_tx_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_TX_CTRL(srio_port));
541         sriox_tx_ctrl.s.tag_th2 = 2;
542         sriox_tx_ctrl.s.tag_th1 = 3;
543         sriox_tx_ctrl.s.tag_th0 = 4;
544         cvmx_write_csr(CVMX_SRIOX_TX_CTRL(srio_port), sriox_tx_ctrl.u64);
545     }
546
547     /* Clear any pending interrupts */
548     cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port)));
549
550     /* Enable error reporting */
551 #if (!defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_LINUX_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL)
552     cvmx_error_enable_group(CVMX_ERROR_GROUP_SRIO, srio_port);
553 #endif
554
555     /* Finally enable the link */
556     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32))
557         return -1;
558     port_0_ctl.s.o_enable = 1;
559     port_0_ctl.s.i_enable = 1;
560     port_0_ctl.s.disable = 0;
561     port_0_ctl.s.prt_lock = 0;
562     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32))
563         return -1;
564
565     return 0;
566 }
567
568
569 /**
570  * Read 32bits from a Device's config space
571  *
572  * @param srio_port SRIO port the device is on
573  * @param srcid_index
574  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
575  * @param destid    RapidIO device ID, or -1 for the local Octeon.
576  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
577  *                  if transactions should use 8bit device IDs.
578  * @param hopcount  Number of hops to the remote device. Use 0 for the local Octeon.
579  * @param offset    Offset in config space. This must be a multiple of 32 bits.
580  * @param result    Result of the read. This will be unmodified on failure.
581  *
582  * @return Zero on success, negative on failure.
583  */
584 int cvmx_srio_config_read32(int srio_port, int srcid_index, int destid,
585                             int is16bit, uint8_t hopcount, uint32_t offset,
586                             uint32_t *result)
587 {
588     if (destid == -1)
589     {
590         int status = __cvmx_srio_local_read32(srio_port, offset, result);
591
592         if ((status == 0) && (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG))
593             cvmx_dprintf("SRIO%d: Local read [0x%06x] <= 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)*result);
594
595         return status;
596     }
597     else
598     {
599 #if CVMX_SRIO_USE_FIFO_FOR_MAINT
600         int return_code;
601         uint32_t pkt = 0;
602         uint32_t sourceid;
603         uint64_t stop_cycle;
604         char rx_buffer[64];
605
606         /* Tell the user */
607         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
608             cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset);
609
610         /* Read the proper source ID */
611         if (srcid_index)
612             __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid);
613         else
614             __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid);
615
616         if (is16bit)
617         {
618             /* Use the 16bit source ID */
619             sourceid &= 0xffff;
620
621             /* MAINT Reads are 11 bytes */
622             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16);
623
624             pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
625             pkt |= 1 << 28;                         /* tt       [29:28] */
626             pkt |= 0x8 << 24;                       /* ftype    [27:24] */
627             pkt |= destid << 8;                     /* destID   [23:8] */
628             pkt |= sourceid >> 8;                   /* sourceID [7:0] */
629             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
630             pkt = 0;
631             pkt |= sourceid << 24;                  /* sourceID [31:24] */
632             pkt |= 0 << 20;                         /* transaction [23:20] */
633             pkt |= 8 << 16;                         /* rdsize [19:16] */
634             pkt |= 0xc0 << 8;                       /* srcTID [15:8] */
635             pkt |= hopcount;                        /* hopcount [7:0] */
636             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
637             pkt = 0;
638             pkt |= offset << 8;                     /* offset [31:11, wdptr[10], reserved[9:8] */
639             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
640         }
641         else
642         {
643             /* Use the 8bit source ID */
644             sourceid = (sourceid >> 16) & 0xff;
645
646             /* MAINT Reads are 9 bytes */
647             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16);
648
649             pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
650             pkt |= 0 << 28;                         /* tt       [29:28] */
651             pkt |= 0x8 << 24;                       /* ftype    [27:24] */
652             pkt |= destid << 16;                    /* destID   [23:16] */
653             pkt |= sourceid << 8;                   /* sourceID [15:8] */
654             pkt |= 0 << 4;                          /* transaction [7:4] */
655             pkt |= 8 << 0;                          /* rdsize [3:0] */
656             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
657             pkt = 0;
658             pkt |= 0xc0 << 24;                      /* srcTID [31:24] */
659             pkt |= hopcount << 16;                  /* hopcount [23:16] */
660             pkt |= offset >> 8;                     /* offset [15:0] */
661             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
662             pkt = 0;
663             pkt |= offset << 24;                    /* offset [31:27, wdptr[26], reserved[25:24] */
664             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
665         }
666
667         stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
668         do
669         {
670             return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer));
671             if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle))
672             {
673                 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
674                     cvmx_dprintf("timeout\n");
675                 return_code = -1;
676             }
677         } while (return_code == 0);
678
679         if (return_code == ((is16bit) ? 23 : 19))
680         {
681             if (is16bit)
682             {
683                 if (offset & 4)
684                     *result = *(uint32_t*)(rx_buffer + 15);
685                 else
686                     *result = *(uint32_t*)(rx_buffer + 11);
687             }
688             else
689             {
690                 if (offset & 4)
691                     *result = *(uint32_t*)(rx_buffer + 13);
692                 else
693                     *result = *(uint32_t*)(rx_buffer + 9);
694             }
695             if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
696                 cvmx_dprintf("0x%08x\n", (unsigned int)*result);
697             return_code = 0;
698         }
699         else
700         {
701             *result = 0xffffffff;
702             return_code = -1;
703         }
704
705         return return_code;
706 #elif !defined(CVMX_BUILD_FOR_LINUX_HOST)
707         uint64_t physical;
708         physical = cvmx_srio_physical_map(srio_port,
709             CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
710             CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
711             srcid_index, destid, is16bit, offset + (hopcount<<24), 4);
712         if (!physical)
713             return -1;
714
715         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
716             cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, offset);
717
718         /* Finally do the maintenance read to complete the config request */
719         *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical));
720         cvmx_srio_physical_unmap(physical, 4);
721
722         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
723             cvmx_dprintf("0x%08x\n", *result);
724
725         return 0;
726 #else
727         return -1;
728 #endif
729     }
730 }
731
732
733 /**
734  * Write 32bits to a Device's config space
735  *
736  * @param srio_port SRIO port the device is on
737  * @param srcid_index
738  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
739  * @param destid    RapidIO device ID, or -1 for the local Octeon.
740  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
741  *                  if transactions should use 8bit device IDs.
742  * @param hopcount  Number of hops to the remote device. Use 0 for the local Octeon.
743  * @param offset    Offset in config space. This must be a multiple of 32 bits.
744  * @param data      Data to write.
745  *
746  * @return Zero on success, negative on failure.
747  */
748 int cvmx_srio_config_write32(int srio_port, int srcid_index, int destid,
749                              int is16bit, uint8_t hopcount, uint32_t offset,
750                              uint32_t data)
751 {
752     if (destid == -1)
753     {
754         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
755             cvmx_dprintf("SRIO%d: Local write[0x%06x] => 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)data);
756
757         return __cvmx_srio_local_write32(srio_port, offset, data);
758     }
759     else
760     {
761 #if CVMX_SRIO_USE_FIFO_FOR_MAINT
762         int return_code;
763         uint32_t pkt = 0;
764         uint32_t sourceid;
765         uint64_t stop_cycle;
766         char rx_buffer[64];
767
768         /* Tell the user */
769         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
770             cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, (unsigned int)offset, (unsigned int)data);
771
772         /* Read the proper source ID */
773         if (srcid_index)
774             __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid);
775         else
776             __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid);
777
778         if (is16bit)
779         {
780             /* Use the 16bit source ID */
781             sourceid &= 0xffff;
782
783             /* MAINT Writes are 19 bytes */
784             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16);
785
786             pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
787             pkt |= 1 << 28;                         /* tt       [29:28] */
788             pkt |= 0x8 << 24;                       /* ftype    [27:24] */
789             pkt |= destid << 8;                     /* destID   [23:8] */
790             pkt |= sourceid >> 8;                   /* sourceID [7:0] */
791             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
792             pkt = 0;
793             pkt |= sourceid << 24;                  /* sourceID [31:24] */
794             pkt |= 1 << 20;                         /* transaction [23:20] */
795             pkt |= 8 << 16;                         /* wrsize [19:16] */
796             pkt |= 0xc0 << 8;                       /* srcTID [15:8] */
797             pkt |= hopcount;                        /* hopcount [7:0] */
798             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
799             pkt = 0;
800             pkt |= offset << 8;                     /* offset [31:11, wdptr[10], reserved[9:8] */
801             if ((offset & 4) == 0)
802                 pkt |= 0xff & (data >> 24);       /* data [7:0] */
803             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
804             if (offset & 4)
805             {
806                 pkt = 0xff & (data >> 24);
807                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
808                 pkt = data << 8;
809                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
810             }
811             else
812             {
813                 pkt = data << 8;
814                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
815                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0);
816             }
817         }
818         else
819         {
820             /* Use the 8bit source ID */
821             sourceid = (sourceid >> 16) & 0xff;
822
823             /* MAINT Writes are 17 bytes */
824             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16);
825
826             pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
827             pkt |= 0 << 28;                         /* tt       [29:28] */
828             pkt |= 0x8 << 24;                       /* ftype    [27:24] */
829             pkt |= destid << 16;                    /* destID   [23:16] */
830             pkt |= sourceid << 8;                   /* sourceID [15:8] */
831             pkt |= 1 << 4;                          /* transaction [7:4] */
832             pkt |= 8 << 0;                          /* wrsize [3:0] */
833             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
834             pkt = 0;
835             pkt |= 0xc0 << 24;                      /* srcTID [31:24] */
836             pkt |= hopcount << 16;                  /* hopcount [23:16] */
837             pkt |= offset >> 8;                     /* offset [15:0] */
838             __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
839             pkt = 0;
840             pkt |= offset << 24;                    /* offset [31:27, wdptr[26], reserved[25:24] */
841             if (offset & 4)
842             {
843                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
844                 pkt = data >> 8;
845                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
846                 pkt = data << 24;
847                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
848             }
849             else
850             {
851                 pkt |= data >> 8;                    /* data [23:0] */
852                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
853                 pkt = data << 24;                    /* data [31:24] */
854                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
855                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0);
856             }
857         }
858
859         stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
860         do
861         {
862             return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer));
863             if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle))
864             {
865                 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
866                     cvmx_dprintf("timeout\n");
867                 return_code = -1;
868             }
869         } while (return_code == 0);
870
871         if (return_code == ((is16bit) ? 15 : 11))
872             return_code = 0;
873         else
874         {
875             cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port);
876             return_code = -1;
877         }
878
879         return return_code;
880 #elif !defined(CVMX_BUILD_FOR_LINUX_HOST)
881         uint64_t physical = cvmx_srio_physical_map(srio_port,
882                 CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
883                 CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
884                 srcid_index, destid, is16bit, offset + (hopcount<<24), 4);
885         if (!physical)
886             return -1;
887
888         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
889             cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, offset, data);
890
891         /* Finally do the maintenance write to complete the config request */
892         cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data);
893         return cvmx_srio_physical_unmap(physical, 4);
894 #else
895         return -1;
896 #endif
897     }
898 }
899
900
901 /**
902  * Send a RapidIO doorbell to a remote device
903  *
904  * @param srio_port SRIO port the device is on
905  * @param srcid_index
906  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
907  * @param destid    RapidIO device ID.
908  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
909  *                  if transactions should use 8bit device IDs.
910  * @param priority  Doorbell priority (0-3)
911  * @param data      Data for doorbell.
912  *
913  * @return Zero on success, negative on failure.
914  */
915 int cvmx_srio_send_doorbell(int srio_port, int srcid_index, int destid, int is16bit, int priority, uint16_t data)
916 {
917     cvmx_sriox_tx_bell_t tx_bell;
918     tx_bell.u64 = 0;
919     tx_bell.s.data = data;
920     tx_bell.s.dest_id = destid;
921     tx_bell.s.src_id = srcid_index;
922     tx_bell.s.id16 = !!is16bit;
923     tx_bell.s.priority = priority;
924
925     /* Make sure the previous doorbell has completed */
926     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_TX_BELL(srio_port), cvmx_sriox_tx_bell_t, pending, ==, 0, CVMX_SRIO_DOORBELL_TIMEOUT))
927     {
928         cvmx_dprintf("SRIO%d: Pending bit stuck before doorbell\n", srio_port);
929         return -1;
930     }
931
932     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
933         cvmx_dprintf("SRIO%d: Send doorbell destid=0x%x, priority=%d, data=0x%x\n", srio_port, destid, priority, 0xffff & data);
934
935     /* Send the doorbell. We don't wait for it to complete. The next doorbell
936         may delay on the pending bit, but this gives the caller the ability to
937         do other stuff while the doorbell processes */
938     cvmx_write_csr(CVMX_SRIOX_TX_BELL(srio_port), tx_bell.u64);
939     return 0;
940 }
941
942
943 /**
944  * Get the status of the last doorbell sent. If the dooorbell
945  * hardware is done, then the status is cleared to get ready for
946  * the next doorbell (or retry).
947  *
948  * @param srio_port SRIO port to check doorbell on
949  *
950  * @return Doorbell status
951  */
952 cvmx_srio_doorbell_status_t cvmx_srio_send_doorbell_status(int srio_port)
953 {
954     cvmx_sriox_tx_bell_t tx_bell;
955     cvmx_sriox_tx_bell_info_t tx_bell_info;
956     cvmx_sriox_int_reg_t int_reg;
957     cvmx_sriox_int_reg_t int_reg_clear;
958
959     /* Return busy if the doorbell is still processing */
960     tx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL(srio_port));
961     if (tx_bell.s.pending)
962         return CVMX_SRIO_DOORBELL_BUSY;
963
964     /* Read and clear the TX doorbell interrupts */
965     int_reg.u64 = cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port));
966     int_reg_clear.u64 = 0;
967     int_reg_clear.s.bell_err = int_reg.s.bell_err;
968     int_reg_clear.s.txbell = int_reg.s.txbell;
969     cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), int_reg_clear.u64);
970
971     /* Check for errors */
972     if (int_reg.s.bell_err)
973     {
974         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
975             cvmx_dprintf("SRIO%d: Send doorbell failed\n", srio_port);
976         tx_bell_info.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL_INFO(srio_port));
977         if (tx_bell_info.s.timeout || tx_bell_info.s.error)
978             return CVMX_SRIO_DOORBELL_ERROR;
979         if (tx_bell_info.s.retry)
980             return CVMX_SRIO_DOORBELL_RETRY;
981     }
982
983     /* Check if we're done */
984     if (int_reg.s.txbell)
985         return CVMX_SRIO_DOORBELL_DONE;
986
987     /* No doorbell found */
988     return CVMX_SRIO_DOORBELL_NONE;
989 }
990
991
992 /**
993  * Read a received doorbell and report data about it.
994  *
995  * @param srio_port SRIO port to check for the received doorbell
996  * @param destid_index
997  *                  Which Octeon destination ID was the doorbell for
998  * @param sequence_num
999  *                  Sequence number of doorbell (32bits)
1000  * @param srcid     RapidIO source ID of the doorbell sender
1001  * @param priority  Priority of the doorbell (0-3)
1002  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
1003  *                  if transactions should use 8bit device IDs.
1004  * @param data      Data in the doorbell (16 bits)
1005  *
1006  * @return Doorbell status. Either DONE, NONE, or ERROR.
1007  */
1008 cvmx_srio_doorbell_status_t cvmx_srio_receive_doorbell(int srio_port,
1009         int *destid_index, uint32_t *sequence_num, int *srcid, int *priority,
1010         int *is16bit, uint16_t *data)
1011 {
1012     cvmx_sriox_rx_bell_seq_t rx_bell_seq;
1013     cvmx_sriox_rx_bell_t rx_bell;
1014
1015     /* Check if there are any pending doorbells */
1016     rx_bell_seq.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL_SEQ(srio_port));
1017     if (!rx_bell_seq.s.count)
1018         return CVMX_SRIO_DOORBELL_NONE;
1019
1020     /* Read the doorbell and write our return parameters */
1021     rx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL(srio_port));
1022     *sequence_num = rx_bell_seq.s.seq;
1023     *srcid = rx_bell.s.src_id;
1024     *priority = rx_bell.s.priority;
1025     *is16bit = rx_bell.s.id16;
1026     *data = rx_bell.s.data;
1027     *destid_index = rx_bell.s.dest_id;
1028
1029     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1030         cvmx_dprintf("SRIO%d: Receive doorbell sequence=0x%x, srcid=0x%x, priority=%d, data=0x%x\n",
1031             srio_port, rx_bell_seq.s.seq, rx_bell.s.src_id, rx_bell.s.priority, rx_bell.s.data);
1032
1033     return CVMX_SRIO_DOORBELL_DONE;
1034 }
1035
1036
1037 /**
1038  * Receive a packet from the Soft Packet FIFO (SPF).
1039  *
1040  * @param srio_port SRIO port to read the packet from.
1041  * @param buffer    Buffer to receive the packet.
1042  * @param buffer_length
1043  *                  Length of the buffer in bytes.
1044  *
1045  * @return Returns the length of the packet read. Negative on failure.
1046  *         Zero if no packets are available.
1047  */
1048 int cvmx_srio_receive_spf(int srio_port, void *buffer, int buffer_length)
1049 {
1050     uint32_t *ptr = (uint32_t *)buffer;
1051     cvmx_sriomaintx_ir_sp_rx_stat_t sriomaintx_ir_sp_rx_stat;
1052
1053     /* Read the SFP status */
1054     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_STAT(srio_port), &sriomaintx_ir_sp_rx_stat.u32))
1055         return -1;
1056
1057     /* Return zero if there isn't a packet available */
1058     if (sriomaintx_ir_sp_rx_stat.s.buffers < 1)
1059         return 0;
1060
1061     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1062         cvmx_dprintf("SRIO%d: Soft packet FIFO received %d bytes", srio_port, sriomaintx_ir_sp_rx_stat.s.octets);
1063
1064     /* Return error if the packet is larger than our buffer */
1065     if (sriomaintx_ir_sp_rx_stat.s.octets > buffer_length)
1066         return -1;
1067
1068     /* Read out the packet four bytes at a time */
1069     buffer_length = sriomaintx_ir_sp_rx_stat.s.octets;
1070     while (buffer_length > 0)
1071     {
1072         __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_DATA(srio_port), ptr);
1073         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1074             cvmx_dprintf(" %08x", (unsigned int)*ptr);
1075         ptr++;
1076         buffer_length-=4;
1077     }
1078
1079     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1080         cvmx_dprintf("\n");
1081
1082     /* Return the number of bytes in the buffer */
1083     return sriomaintx_ir_sp_rx_stat.s.octets;
1084 }
1085
1086 #ifndef CVMX_BUILD_FOR_LINUX_HOST
1087 /**
1088  * Map a remote device's memory region into Octeon's physical
1089  * address area. The caller can then map this into a core using
1090  * the TLB or XKPHYS.
1091  *
1092  * @param srio_port SRIO port to map the device on
1093  * @param write_op  Type of operation to perform on a write to the device.
1094  *                  Normally should be CVMX_SRIO_WRITE_MODE_AUTO.
1095  * @param write_priority
1096  *                  SRIO priority of writes (0-3)
1097  * @param read_op   Type of operation to perform on reads to the device.
1098  *                  Normally should be CVMX_SRIO_READ_MODE_NORMAL.
1099  * @param read_priority
1100  *                  SRIO priority of reads (0-3)
1101  * @param srcid_index
1102  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
1103  * @param destid    RapidIO device ID.
1104  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
1105  *                  if transactions should use 8bit device IDs.
1106  * @param base      Device base address to start the mapping
1107  * @param size      Size of the mapping in bytes
1108  *
1109  * @return Octeon 64bit physical address that accesses the remote device,
1110  *         or zero on failure.
1111  */
1112 uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op,
1113         int write_priority, cvmx_srio_read_mode_t read_op, int read_priority,
1114         int srcid_index, int destid, int is16bit, uint64_t base, uint64_t size)
1115 {
1116     cvmx_sriox_s2m_typex_t needed_s2m_type;
1117     cvmx_sli_mem_access_subidx_t needed_subid;
1118     int s2m_index;
1119     int subdid;
1120     cvmx_sli_address_t sli_address;
1121
1122     /* We currently don't support mapping regions that span a 34 bit boundary.
1123         Keeping track of multiple regions to span 34 bits is hard and not
1124         likely to be needed */
1125     if (((base+size-1)>>34) != (base>>34))
1126     {
1127         cvmx_dprintf("SRIO%d: Failed to map range 0x%llx-0x%llx spanning a 34bit boundary\n",
1128             srio_port, (ULL)base, (ULL)base+size-1);
1129         return 0;
1130     }
1131
1132     /* Build the S2M_TYPE we are going to need */
1133     needed_s2m_type.u64 = 0;
1134     needed_s2m_type.s.wr_op = write_op;
1135     needed_s2m_type.s.rd_op = read_op;
1136     needed_s2m_type.s.wr_prior = write_priority;
1137     needed_s2m_type.s.rd_prior = read_priority;
1138     needed_s2m_type.s.src_id = srcid_index;
1139     needed_s2m_type.s.id16 = !!is16bit;
1140
1141     /* Build the needed SubID config */
1142     needed_subid.u64 = 0;
1143     needed_subid.s.port = srio_port;
1144     needed_subid.s.nmerge = 1;
1145
1146     /* FIXME: We might want to use the device ID swapping modes so the device
1147         ID is part of the lower address bits. This would allow many more
1148         devices to share S2M_TYPE indexes. This would require "base+size-1"
1149         to fit in bits [17:0] or bits[25:0] for 8 bits of device ID */
1150     if (base < (1ull<<34))
1151     {
1152         needed_subid.s.ba = destid;
1153         needed_s2m_type.s.iaow_sel = 0;
1154     }
1155     else if (base < (1ull<<42))
1156     {
1157         needed_subid.s.ba = (base>>34) & 0xff;
1158         needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (42-34);
1159         needed_subid.s.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34);
1160         needed_s2m_type.s.iaow_sel = 1;
1161     }
1162     else
1163     {
1164         if (destid>>8)
1165         {
1166             cvmx_dprintf("SRIO%d: Attempt to map 16bit device ID 0x%x using 66bit addressing\n", srio_port, destid);
1167             return 0;
1168         }
1169         if (base>>50)
1170         {
1171             cvmx_dprintf("SRIO%d: Attempt to map address 0x%llx using 66bit addressing\n", srio_port, (ULL)base);
1172             return 0;
1173         }
1174         needed_subid.s.ba = (base>>34) & 0xffff;
1175         needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (51-34);
1176         needed_s2m_type.s.iaow_sel = 2;
1177     }
1178
1179     /* Find a S2M_TYPE index to use. If this fails return 0 */
1180     s2m_index = __cvmx_srio_alloc_s2m(srio_port, needed_s2m_type);
1181     if (s2m_index == -1)
1182         return 0;
1183
1184     /* Attach the SubID to the S2M_TYPE index */
1185     needed_subid.s.rtype = s2m_index & 3;
1186     needed_subid.s.wtype = s2m_index & 3;
1187     needed_subid.s.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34);
1188     needed_subid.s.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34);
1189
1190     /* Allocate a SubID for use */
1191     subdid = __cvmx_srio_alloc_subid(needed_subid);
1192     if (subdid == -1)
1193     {
1194         /* Free the s2m_index as we aren't using it */
1195         __cvmx_srio_free_s2m(srio_port, s2m_index);
1196         return 0;
1197     }
1198
1199     /* Build the final core physical address */
1200     sli_address.u64 = 0;
1201     sli_address.mem.io = 1;
1202     sli_address.mem.did = 3;
1203     sli_address.mem.subdid = subdid>>2;
1204     sli_address.mem.se = subdid & 3;
1205     sli_address.mem.address = base; /* Bits[33:0] of full address */
1206     return sli_address.u64;
1207 }
1208
1209
1210 /**
1211  * Unmap a physical address window created by cvmx_srio_phys_map().
1212  *
1213  * @param physical_address
1214  *               Physical address returned by cvmx_srio_phys_map().
1215  * @param size   Size used on original call.
1216  *
1217  * @return Zero on success, negative on failure.
1218  */
1219 int cvmx_srio_physical_unmap(uint64_t physical_address, uint64_t size)
1220 {
1221     cvmx_sli_mem_access_subidx_t subid;
1222     int subdid = (physical_address >> 40) & 7;
1223     int extender = (physical_address >> 34) & 3;
1224     int mem_index = subdid * 4 + extender;
1225     int read_s2m_type;
1226
1227     /* Get the subid setup so we can figure out where this mapping was for */
1228     subid.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index));
1229     /* Type[0] is mapped to the Relaxed Ordering
1230        Type[1] is mapped to the No Snoop
1231        Type[2] is mapped directly to bit 50 of the SLI address
1232        Type[3] is mapped directly to bit 59 of the SLI address */
1233     read_s2m_type = ((subid.s.ba>>(50-34))&1<<2) | ((subid.s.ba>>(59-34))&1<<3);
1234     read_s2m_type |= subid.s.rtype;
1235     __cvmx_srio_free_subid(mem_index);
1236     __cvmx_srio_free_s2m(subid.s.port, read_s2m_type);
1237     return 0;
1238 }
1239 #endif