]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/octeon-sdk/cvmx-srio.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / octeon-sdk / cvmx-srio.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  * @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 #include <asm/octeon/cvmx-qlm.h>
64 #else
65 #include "cvmx.h"
66 #include "cvmx-srio.h"
67 #include "cvmx-clock.h"
68 #include "cvmx-helper.h"
69 #ifndef CVMX_BUILD_FOR_LINUX_HOST
70 #include "cvmx-atomic.h"
71 #if !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)
72 #include "cvmx-error.h"
73 #endif
74 #include "cvmx-helper-errata.h"
75 #endif
76 #include "cvmx-qlm.h"
77 #include "cvmx-helper.h"
78 #endif
79
80 #define CVMX_SRIO_CONFIG_TIMEOUT        10000 /* 10ms */
81 #define CVMX_SRIO_DOORBELL_TIMEOUT      10000 /* 10ms */
82 #define CVMX_SRIO_CONFIG_PRIORITY       0
83 #define ULL unsigned long long
84
85 typedef union
86 {
87     uint64_t    u64;
88     struct
89     {
90 #ifdef __BIG_ENDIAN_BITFIELD
91         uint64_t    upper           : 2;    /* Normally 2 for XKPHYS */
92         uint64_t    reserved_49_61  : 13;   /* Must be zero */
93         uint64_t    io              : 1;    /* 1 for IO space access */
94         uint64_t    did             : 5;    /* DID = 3 */
95         uint64_t    subdid          : 3;    /* SubDID = 3-6 */
96         uint64_t    reserved_36_39  : 4;    /* Must be zero */
97         uint64_t    se              : 2;    /* SubDID extender */
98         uint64_t    reserved_32_33  : 2;    /* Must be zero */
99         uint64_t    hopcount        : 8;    /* Hopcount */
100         uint64_t    address         : 24;   /* Mem address */
101 #else
102         uint64_t    address         : 24;
103         uint64_t    hopcount        : 8;
104         uint64_t    reserved_32_33  : 2;
105         uint64_t    se              : 2;
106         uint64_t    reserved_36_39  : 4;
107         uint64_t    subdid          : 3;
108         uint64_t    did             : 5;
109         uint64_t    io              : 1;
110         uint64_t    reserved_49_61  : 13;
111         uint64_t    upper           : 2;
112 #endif
113     } config;
114     struct
115     {
116 #ifdef __BIG_ENDIAN_BITFIELD
117         uint64_t    upper           : 2;    /* Normally 2 for XKPHYS */
118         uint64_t    reserved_49_61  : 13;   /* Must be zero */
119         uint64_t    io              : 1;    /* 1 for IO space access */
120         uint64_t    did             : 5;    /* DID = 3 */
121         uint64_t    subdid          : 3;    /* SubDID = 3-6 */
122         uint64_t    reserved_36_39  : 4;    /* Must be zero */
123         uint64_t    se              : 2;    /* SubDID extender */
124         uint64_t    address         : 34;   /* Mem address */
125 #else
126         uint64_t    address         : 34;
127         uint64_t    se              : 2;
128         uint64_t    reserved_36_39  : 4;
129         uint64_t    subdid          : 3;
130         uint64_t    did             : 5;
131         uint64_t    io              : 1;
132         uint64_t    reserved_49_61  : 13;
133         uint64_t    upper           : 2;
134 #endif
135     } mem;
136 } cvmx_sli_address_t;
137
138 typedef struct
139 {
140     cvmx_srio_initialize_flags_t flags;
141     int32_t subidx_ref_count[16];   /* Reference count for SLI_MEM_ACCESS_SUBID[12-27]. Index=X-12 */
142     int32_t s2m_ref_count[16];   /* Reference count for SRIOX_S2M_TYPE[0-15]. */
143 } __cvmx_srio_state_t;
144
145 static CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[4];
146
147
148 #ifndef CVMX_BUILD_FOR_LINUX_HOST
149 /**
150  * @INTERNAL
151  * Allocate a SRIOX_S2M_TYPEX register for mapping a remote SRIO
152  * device's address range into Octeons SLI address space. Reference
153  * counting is used to allow sharing of duplicate setups. The current
154  * implementation treats reads and writes as paired, but this could be
155  * changed if we have trouble running out of indexes.
156  *
157  * @param srio_port SRIO port device is on
158  * @param s2m       SRIOX_S2M_TYPEX setup required
159  *
160  * @return Index of CSR, or negative on failure
161  */
162 static int __cvmx_srio_alloc_s2m(int srio_port, cvmx_sriox_s2m_typex_t s2m)
163 {
164     int s2m_index;
165     /* Search through the S2M_TYPE registers looking for an unsed one or one
166         setup the way we need it */
167     for (s2m_index=0; s2m_index<16; s2m_index++)
168     {
169         /* Increment ref count by 2 since we count read and write
170             independently. We might need a more complicated search in the
171             future */
172         int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], 2);
173         if (ref_count == 0)
174         {
175             /* Unused location. Write our value */
176             cvmx_write_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port), s2m.u64);
177             /* Read back to make sure the update is complete */
178             cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port));
179             return s2m_index;
180         }
181         else
182         {
183             /* In use, see if we can use it */
184             if (cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)) == s2m.u64)
185                 return s2m_index;
186             else
187                 cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], -2);
188         }
189     }
190     cvmx_dprintf("SRIO%d: Unable to find free SRIOX_S2M_TYPEX\n", srio_port);
191     return -1;
192 }
193
194
195 /**
196  * @INTERNAL
197  * Free a handle allocated by __cvmx_srio_alloc_s2m
198  *
199  * @param srio_port SRIO port
200  * @param index     Index to free
201  */
202 static void __cvmx_srio_free_s2m(int srio_port, int index)
203 {
204     /* Read to force pending transactions to complete */
205     cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(index, srio_port));
206     cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[index], -2);
207 }
208
209
210 /**
211  * @INTERNAL
212  * Allocate a SLI SubID to map a region of memory. Reference
213  * counting is used to allow sharing of duplicate setups.
214  *
215  * @param subid  SLI_MEM_ACCESS_SUBIDX we need an index for
216  *
217  * @return Index of CSR, or negative on failure
218  */
219 static int __cvmx_srio_alloc_subid(cvmx_sli_mem_access_subidx_t subid)
220 {
221     int mem_index;
222     /* Search through the mem access subid registers looking for an unsed one
223         or one setup the way we need it. PCIe uses the low indexes, so search
224         backwards */
225     for (mem_index=27; mem_index>=12; mem_index--)
226     {
227         int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], 1);
228         if (ref_count == 0)
229         {
230             /* Unused location. Write our value */
231             cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index), subid.u64);
232             /* Read back the value to make sure the update is complete */
233             cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index));
234             return mem_index;
235         }
236         else
237         {
238             /* In use, see if we can use it */
239             if (cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)) == subid.u64)
240                 return mem_index;
241             else
242                 cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], -1);
243         }
244     }
245     cvmx_dprintf("SRIO: Unable to find free SLI_MEM_ACCESS_SUBIDX\n");
246     return -1;
247 }
248
249
250 /**
251  * @INTERNAL
252  * Free a handle allocated by __cvmx_srio_alloc_subid
253  *
254  * @param index  Index to free
255  */
256 static void __cvmx_srio_free_subid(int index)
257 {
258     /* Read to force pending transactions to complete */
259     cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(index));
260     cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[index-12], -1);
261 }
262 #endif
263
264
265 /**
266  * @INTERNAL
267  * Read 32bits from a local port
268  *
269  * @param srio_port SRIO port the device is on
270  * @param offset    Offset in config space. This must be a multiple of 32 bits.
271  * @param result    Result of the read. This will be unmodified on failure.
272  *
273  * @return Zero on success, negative on failure.
274  */
275 static int __cvmx_srio_local_read32(int srio_port, uint32_t offset, uint32_t *result)
276 {
277     cvmx_sriox_maint_op_t maint_op;
278     cvmx_sriox_maint_rd_data_t maint_rd_data;
279     maint_op.u64 = 0;
280     maint_op.s.op = 0; /* Read */
281     maint_op.s.addr = offset;
282
283     /* Make sure SRIO isn't already busy */
284     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
285     {
286         cvmx_dprintf("SRIO%d: Pending bit stuck before config read\n", srio_port);
287         return -1;
288     }
289
290     /* Issue the read to the hardware */
291     cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64);
292
293     /* Wait for the hardware to complete the operation */
294     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
295     {
296         cvmx_dprintf("SRIO%d: Config read timeout\n", srio_port);
297         return -1;
298     }
299
300     /* Display and error and return if the operation failed to issue */
301     maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port));
302     if (maint_op.s.fail)
303     {
304         cvmx_dprintf("SRIO%d: Config read addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset);
305         return -1;
306     }
307
308     /* Wait for the read data to become valid */
309     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_RD_DATA(srio_port), cvmx_sriox_maint_rd_data_t, valid, ==, 1, CVMX_SRIO_CONFIG_TIMEOUT))
310     {
311         cvmx_dprintf("SRIO%d: Config read data timeout\n", srio_port);
312         return -1;
313     }
314
315     /* Get the read data */
316     maint_rd_data.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_RD_DATA(srio_port));
317     *result = maint_rd_data.s.rd_data;
318     return 0;
319 }
320
321
322 /**
323  * @INTERNAL
324  * Write 32bits to a local port
325  * @param srio_port SRIO port the device is on
326  * @param offset    Offset in config space. This must be a multiple of 32 bits.
327  * @param data      Data to write.
328  *
329  * @return Zero on success, negative on failure.
330  */
331 static int __cvmx_srio_local_write32(int srio_port, uint32_t offset, uint32_t data)
332 {
333     cvmx_sriox_maint_op_t maint_op;
334     maint_op.u64 = 0;
335     maint_op.s.wr_data = data;
336     maint_op.s.op = 1; /* Write */
337     maint_op.s.addr = offset;
338
339     /* Make sure SRIO isn't already busy */
340     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
341     {
342         cvmx_dprintf("SRIO%d: Pending bit stuck before config write\n", srio_port);
343         return -1;
344     }
345
346     /* Issue the write to the hardware */
347     cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64);
348
349     /* Wait for the hardware to complete the operation */
350     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
351     {
352         cvmx_dprintf("SRIO%d: Config write timeout\n", srio_port);
353         return -1;
354     }
355
356     /* Display and error and return if the operation failed to issue */
357     maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port));
358     if (maint_op.s.fail)
359     {
360         cvmx_dprintf("SRIO%d: Config write addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset);
361         return -1;
362     }
363     return 0;
364 }
365
366
367 /**
368  * Reset SRIO to link partner
369  *
370  * @param srio_port  SRIO port to initialize
371  *
372  * @return Zero on success
373  */
374 int cvmx_srio_link_rst(int srio_port)
375 {
376     cvmx_sriomaintx_port_0_link_resp_t link_resp;
377
378     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
379         return -1;
380
381     /* Generate a symbol reset to the link partner by writing 0x3. */
382     if (cvmx_srio_config_write32(srio_port, 0, -1, 0, 0,
383         CVMX_SRIOMAINTX_PORT_0_LINK_REQ(srio_port), 3))
384         return -1;
385
386     if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
387         CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32))
388         return -1;
389
390     /* Poll until link partner has received the reset. */
391     while (link_resp.s.valid == 0)
392     {
393         //cvmx_dprintf("Waiting for Link Response\n");
394         if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0,
395             CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32))
396             return -1;
397     }
398
399     /* Valid response, Asserting MAC reset */
400     cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1);
401
402     cvmx_wait(10);
403
404     /* De-asserting MAC Reset */
405     cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0);
406
407     return 0;
408 }
409
410 /**
411  * Initialize a SRIO port for use.
412  *
413  * @param srio_port SRIO port to initialize
414  * @param flags     Optional flags
415  *
416  * @return Zero on success
417  */
418 int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags)
419 {
420     cvmx_sriomaintx_port_lt_ctl_t port_lt_ctl;
421     cvmx_sriomaintx_port_rt_ctl_t port_rt_ctl;
422     cvmx_sriomaintx_port_0_ctl_t port_0_ctl;
423     cvmx_sriomaintx_core_enables_t core_enables;
424     cvmx_sriomaintx_port_gen_ctl_t port_gen_ctl;
425     cvmx_sriox_status_reg_t sriox_status_reg;
426     cvmx_mio_rst_ctlx_t mio_rst_ctl;
427     cvmx_sriox_imsg_vport_thr_t sriox_imsg_vport_thr;
428     cvmx_dpi_sli_prtx_cfg_t prt_cfg;
429     cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl;
430     cvmx_sli_mem_access_ctl_t sli_mem_access_ctl;
431     cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2;
432
433     sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port));
434     if (OCTEON_IS_MODEL(OCTEON_CN66XX))
435     {
436         /* All SRIO ports are connected to QLM0 */ 
437         int status = cvmx_qlm_get_status(0);
438         if (status < 4 || status > 6)
439         {
440             cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port);
441             return -1;
442         }
443     }
444     else if (!sriox_status_reg.s.srio)
445     {
446         cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port);
447         return -1;
448     }
449
450     __cvmx_srio_state[srio_port].flags = flags;
451
452     /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be
453         programmed */
454     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0))
455     {
456         if (srio_port)
457         {
458             cvmx_ciu_qlm1_t ciu_qlm;
459             ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1);
460             ciu_qlm.s.txbypass = 1;
461             ciu_qlm.s.txdeemph = 5;
462             ciu_qlm.s.txmargin = 0x17;
463             cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64);
464         }
465         else
466         {
467             cvmx_ciu_qlm0_t ciu_qlm;
468             ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0);
469             ciu_qlm.s.txbypass = 1;
470             ciu_qlm.s.txdeemph = 5;
471             ciu_qlm.s.txmargin = 0x17;
472             cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64);
473         }
474     }
475
476     /* Don't receive or drive reset signals for the SRIO QLM */
477     if (OCTEON_IS_MODEL(OCTEON_CN66XX))
478     {
479         /* The reset signals are available only for srio_port == 0. */
480         if (srio_port == 0 || (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_2) && srio_port == 1))
481         {
482             cvmx_mio_rst_cntlx_t mio_rst_cntl;
483             mio_rst_cntl.u64 = cvmx_read_csr(CVMX_MIO_RST_CNTLX(srio_port));
484             mio_rst_cntl.s.rst_drv = 0;
485             mio_rst_cntl.s.rst_rcv = 0;
486             mio_rst_cntl.s.rst_chip = 0;
487             cvmx_write_csr(CVMX_MIO_RST_CNTLX(srio_port), mio_rst_cntl.u64);
488         }
489         /* MIO_RST_CNTL2<prtmode> is initialized to 0 on cold reset */
490         mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CNTLX(srio_port));
491     }
492     else
493     {
494         mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port));
495         mio_rst_ctl.s.rst_drv = 0;
496         mio_rst_ctl.s.rst_rcv = 0;
497         mio_rst_ctl.s.rst_chip = 0;
498         cvmx_write_csr(CVMX_MIO_RST_CTLX(srio_port), mio_rst_ctl.u64);
499
500         mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port));
501     }
502
503     cvmx_dprintf("SRIO%d: Port in %s mode\n", srio_port,
504         (mio_rst_ctl.s.prtmode) ? "host" : "endpoint");
505
506     /* Bring the port out of reset if necessary */
507     switch (srio_port)
508     {
509         case 0:
510         {
511             cvmx_ciu_soft_prst_t prst;
512             prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
513             if (prst.s.soft_prst)
514             {
515                 prst.s.soft_prst = 0;
516                 cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64);
517                 /* Wait up to 250ms for the port to come out of reset */
518                 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000))
519                     return -1;
520             }
521             break;
522         }
523         case 1:
524         {
525             cvmx_ciu_soft_prst1_t prst;
526             prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
527             if (prst.s.soft_prst)
528             {
529                 prst.s.soft_prst = 0;
530                 cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64);
531                 /* Wait up to 250ms for the port to come out of reset */
532                 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000))
533                     return -1;
534             }
535             break;
536         }
537         case 2:
538         {
539             cvmx_ciu_soft_prst2_t prst;
540             prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST2);
541             if (prst.s.soft_prst)
542             {
543                 prst.s.soft_prst = 0;
544                 cvmx_write_csr(CVMX_CIU_SOFT_PRST2, prst.u64);
545                 /* Wait up to 250ms for the port to come out of reset */
546                 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000))
547                     return -1;
548             }
549             break;
550         }
551     }
552
553     /* Disable the link while we make changes */
554     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32))
555         return -1;
556     port_0_ctl.s.o_enable = 0;
557     port_0_ctl.s.i_enable = 0;
558     port_0_ctl.s.prt_lock = 1;
559     port_0_ctl.s.disable = 0;
560     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32))
561         return -1;
562
563     /* CN63XX Pass 2.0 and 2.1 errata G-15273 requires the QLM De-emphasis be
564         programmed when using a 156.25Mhz ref clock */
565     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) ||
566         OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1))
567     {
568         cvmx_mio_rst_boot_t mio_rst_boot;
569         cvmx_sriomaintx_lane_x_status_0_t lane_x_status;
570
571         /* Read the QLM config and speed pins */
572         mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
573         if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_LANE_X_STATUS_0(0, srio_port), &lane_x_status.u32))
574             return -1;
575
576         if (srio_port)
577         {
578             cvmx_ciu_qlm1_t ciu_qlm;
579             ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1);
580             switch (mio_rst_boot.cn63xx.qlm1_spd)
581             {
582                 case 0x4: /* 1.25 Gbaud, 156.25MHz */
583                     ciu_qlm.s.txbypass = 1;
584                     ciu_qlm.s.txdeemph = 0x0;
585                     ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0x11 : 0x1c; /* short or med/long */
586                     break;
587                 case 0xb: /* 5.0 Gbaud, 156.25MHz */
588                     ciu_qlm.s.txbypass = 1;
589                     ciu_qlm.s.txdeemph = (lane_x_status.s.rx_type == 0) ? 0xa : 0xf; /* short or med/long */
590                     ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0xf : 0x1a; /* short or med/long */
591                     break;
592             }
593             cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64);
594         }
595         else
596         {
597             cvmx_ciu_qlm0_t ciu_qlm;
598             ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0);
599             switch (mio_rst_boot.cn63xx.qlm0_spd)
600             {
601                 case 0x4: /* 1.25 Gbaud, 156.25MHz */
602                     ciu_qlm.s.txbypass = 1;
603                     ciu_qlm.s.txdeemph = 0x0;
604                     ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0x11 : 0x1c; /* short or med/long */
605                     break;
606                 case 0xb: /* 5.0 Gbaud, 156.25MHz */
607                     ciu_qlm.s.txbypass = 1;
608                     ciu_qlm.s.txdeemph = (lane_x_status.s.rx_type == 0) ? 0xa : 0xf; /* short or med/long */
609                     ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0xf : 0x1a; /* short or med/long */
610                     break;
611             }
612             cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64);
613         }
614     }
615
616     /* Errata SRIO-14485: Link speed is reported incorrectly in CN63XX
617         pass 1.x */
618     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
619     {
620         cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2;
621         if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32))
622             return -1;
623         if (port_0_ctl2.s.enb_500g)
624         {
625             port_0_ctl2.u32 = 0;
626             port_0_ctl2.s.enb_625g = 1;
627         }
628         else if (port_0_ctl2.s.enb_312g)
629         {
630             port_0_ctl2.u32 = 0;
631             port_0_ctl2.s.enb_500g = 1;
632         }
633         else if (port_0_ctl2.s.enb_250g)
634         {
635             port_0_ctl2.u32 = 0;
636             port_0_ctl2.s.enb_312g = 1;
637         }
638         else if (port_0_ctl2.s.enb_125g)
639         {
640             port_0_ctl2.u32 = 0;
641             port_0_ctl2.s.enb_250g = 1;
642         }
643         else
644         {
645             port_0_ctl2.u32 = 0;
646             port_0_ctl2.s.enb_125g = 1;
647         }
648         if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32))
649             return -1;
650     }
651
652     /* Errata SRIO-15351: Turn off SRIOMAINTX_MAC_CTRL[TYPE_MRG] as it may
653         cause packet ACCEPT to be lost */
654     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) || OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1))
655     {
656         cvmx_sriomaintx_mac_ctrl_t mac_ctrl;
657         if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_MAC_CTRL(srio_port), &mac_ctrl.u32))
658             return -1;
659         mac_ctrl.s.type_mrg = 0;
660         if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_MAC_CTRL(srio_port), mac_ctrl.u32))
661             return -1;
662     }
663
664     /* Set the link layer timeout to 1ms. The default is too high and causes
665         core bus errors */
666     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), &port_lt_ctl.u32))
667         return -1;
668     port_lt_ctl.s.timeout = 1000000 / 200; /* 1ms = 1000000ns / 200ns */
669     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), port_lt_ctl.u32))
670         return -1;
671
672     /* Set the logical layer timeout to 100ms. The default is too high and causes
673         core bus errors */
674     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), &port_rt_ctl.u32))
675         return -1;
676     port_rt_ctl.s.timeout = 100000000 / 200; /* 100ms = 100000000ns / 200ns */
677     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), port_rt_ctl.u32))
678         return -1;
679
680     /* Allow memory and doorbells. Messaging is enabled later */
681     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &core_enables.u32))
682         return -1;
683     core_enables.s.doorbell = 1;
684     core_enables.s.memory = 1;
685     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), core_enables.u32))
686         return -1;
687
688     /* Allow us to master transactions */
689     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), &port_gen_ctl.u32))
690         return -1;
691     port_gen_ctl.s.menable = 1;
692     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), port_gen_ctl.u32))
693         return -1;
694
695     /* Set the MRRS and MPS for optimal SRIO performance */
696     prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port));
697     prt_cfg.s.mps = 1;
698     prt_cfg.s.mrrs = 1;
699     prt_cfg.s.molr = 32;
700     if (OCTEON_IS_MODEL(OCTEON_CN66XX))
701         prt_cfg.s.molr = ((prt_cfg.s.qlm_cfg == 1 || prt_cfg.s.qlm_cfg == 3) ? 8
702                           : (prt_cfg.s.qlm_cfg == 4 || prt_cfg.s.qlm_cfg == 6) ? 16
703                           : 32);
704     cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port), prt_cfg.u64);
705
706     sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port));
707     sli_s2m_portx_ctl.s.mrrs = 1;
708     cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port), sli_s2m_portx_ctl.u64);
709
710     /* Setup RX messaging thresholds */
711     sriox_imsg_vport_thr.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port));
712     if (OCTEON_IS_MODEL(OCTEON_CN66XX))
713         sriox_imsg_vport_thr.s.max_tot = ((prt_cfg.s.qlm_cfg == 1 || prt_cfg.s.qlm_cfg == 3) ? 44 : 46);
714     else
715         sriox_imsg_vport_thr.s.max_tot = 48;
716     sriox_imsg_vport_thr.s.max_s1 = 24;
717     sriox_imsg_vport_thr.s.max_s0 = 24;
718     sriox_imsg_vport_thr.s.sp_vport = 1;
719     sriox_imsg_vport_thr.s.buf_thr = 4;
720     sriox_imsg_vport_thr.s.max_p1 = 12;
721     sriox_imsg_vport_thr.s.max_p0 = 12;
722     cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port), sriox_imsg_vport_thr.u64);
723
724     /* Setup RX messaging thresholds for other virtual ports. */
725     if (OCTEON_IS_MODEL(OCTEON_CN66XX))
726     {
727         cvmx_sriox_imsg_vport_thr2_t sriox_imsg_vport_thr2;
728         sriox_imsg_vport_thr2.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR2(srio_port));
729         sriox_imsg_vport_thr2.s.max_s2 = 24;
730         sriox_imsg_vport_thr2.s.max_s3 = 24;
731         cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR2(srio_port), sriox_imsg_vport_thr2.u64);
732     }
733
734     /* Errata SRIO-X: SRIO error behavior may not be optimal in CN63XX pass 1.x */
735     if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
736     {
737         cvmx_sriox_tx_ctrl_t sriox_tx_ctrl;
738         sriox_tx_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_TX_CTRL(srio_port));
739         sriox_tx_ctrl.s.tag_th2 = 2;
740         sriox_tx_ctrl.s.tag_th1 = 3;
741         sriox_tx_ctrl.s.tag_th0 = 4;
742         cvmx_write_csr(CVMX_SRIOX_TX_CTRL(srio_port), sriox_tx_ctrl.u64);
743     }
744
745     /* Errata SLI-15954: SLI relaxed order issues */
746     if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X))
747     {
748         cvmx_sli_ctl_portx_t sli_ctl_portx;
749         sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port));
750         sli_ctl_portx.s.ptlp_ro = 1;    /* Set to same value for all MACs. */
751         sli_ctl_portx.s.ctlp_ro = 1;    /* Set to same value for all MACs. */
752         sli_ctl_portx.s.wait_com = 0;   /* So that no inbound stores wait for a commit */
753         sli_ctl_portx.s.waitl_com = 0;
754         cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port), sli_ctl_portx.u64);
755     }
756
757     if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
758     {
759         /* Clear the ACK state */
760         if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LOCAL_ACKID(srio_port), 0))
761             return -1;
762     }
763
764     /* Bring the link down, then up, by writing to the SRIO port's
765        PORT_0_CTL2 CSR. */
766     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32))
767         return -1;
768     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32))
769         return -1;
770
771     /* Clear any pending interrupts */
772     cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port)));
773
774     /* Enable error reporting */
775 #if (!defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL)
776     cvmx_error_enable_group(CVMX_ERROR_GROUP_SRIO, srio_port);
777 #endif
778
779     /* Finally enable the link */
780     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32))
781         return -1;
782     port_0_ctl.s.o_enable = 1;
783     port_0_ctl.s.i_enable = 1;
784     port_0_ctl.s.disable = 0;
785     port_0_ctl.s.prt_lock = 0;
786     if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32))
787         return -1;
788
789     /* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */
790     sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL);
791     sli_mem_access_ctl.s.max_word = 0;     /* Allow 16 words to combine */
792     sli_mem_access_ctl.s.timer = 127;      /* Wait up to 127 cycles for more data */
793     cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_mem_access_ctl.u64);
794
795     /* FIXME: Disable sending a link request when the SRIO link is
796         brought up. For unknown reasons this code causes issues with some SRIO
797         devices. As we currently don't support hotplug in software, this code
798         should never be needed.  Without link down/up events, the ACKs should
799         start off and stay synchronized */
800 #if 0
801     /* Ask for a link and align our ACK state. CN63XXp1 didn't support this */
802     if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
803     {
804         uint64_t stop_cycle;
805         cvmx_sriomaintx_port_0_err_stat_t sriomaintx_port_0_err_stat;
806
807         /* Clear the SLI_CTL_PORTX[DIS_PORT[ bit to re-enable traffic-flow
808            to the SRIO MACs. */
809         cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port), cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port)));
810
811         /* Wait a little to see if the link comes up */
812         stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/4 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
813         do
814         {
815             /* Read the port link status */
816             if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_ERR_STAT(srio_port), &sriomaintx_port_0_err_stat.u32))
817                 return -1;
818         } while (!sriomaintx_port_0_err_stat.s.pt_ok && (cvmx_clock_get_count(CVMX_CLOCK_CORE) < stop_cycle));
819
820         /* Send link request if link is up */
821         if (sriomaintx_port_0_err_stat.s.pt_ok)
822         {
823             cvmx_sriomaintx_port_0_link_req_t link_req;
824             cvmx_sriomaintx_port_0_link_resp_t link_resp;
825             link_req.u32 = 0;
826             link_req.s.cmd = 4;
827
828             /* Send the request */
829             if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LINK_REQ(srio_port), link_req.u32))
830                 return -1;
831
832             /* Wait for the response */
833             stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/8 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
834             do
835             {
836                 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32))
837                     return -1;
838             } while (!link_resp.s.valid && (cvmx_clock_get_count(CVMX_CLOCK_CORE) < stop_cycle));
839
840             /* Set our ACK state if we got a response */
841             if (link_resp.s.valid)
842             {
843                 cvmx_sriomaintx_port_0_local_ackid_t local_ackid;
844                 local_ackid.u32 = 0;
845                 local_ackid.s.i_ackid = 0;
846                 local_ackid.s.e_ackid = link_resp.s.ackid;
847                 local_ackid.s.o_ackid = link_resp.s.ackid;
848                 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LOCAL_ACKID(srio_port), local_ackid.u32))
849                     return -1;
850             }
851             else 
852                 return -1;
853         }
854     }
855 #endif
856
857     return 0;
858 }
859
860
861 /**
862  * Read 32bits from a Device's config space
863  *
864  * @param srio_port SRIO port the device is on
865  * @param srcid_index
866  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
867  * @param destid    RapidIO device ID, or -1 for the local Octeon.
868  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
869  *                  if transactions should use 8bit device IDs.
870  * @param hopcount  Number of hops to the remote device. Use 0 for the local Octeon.
871  * @param offset    Offset in config space. This must be a multiple of 32 bits.
872  * @param result    Result of the read. This will be unmodified on failure.
873  *
874  * @return Zero on success, negative on failure.
875  */
876 int cvmx_srio_config_read32(int srio_port, int srcid_index, int destid,
877                             int is16bit, uint8_t hopcount, uint32_t offset,
878                             uint32_t *result)
879 {
880     if (destid == -1)
881     {
882         int status = __cvmx_srio_local_read32(srio_port, offset, result);
883
884         if ((status == 0) && (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG))
885             cvmx_dprintf("SRIO%d: Local read [0x%06x] <= 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)*result);
886
887         return status;
888     }
889     else
890     {
891         if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
892         {
893             int return_code;
894             uint32_t pkt = 0;
895             uint32_t sourceid;
896             uint64_t stop_cycle;
897             char rx_buffer[64];
898
899             /* Tell the user */
900             if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
901                 cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset);
902
903             /* Read the proper source ID */
904             if (srcid_index)
905                 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid);
906             else
907                 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid);
908
909             if (is16bit)
910             {
911                 /* Use the 16bit source ID */
912                 sourceid &= 0xffff;
913
914                 /* MAINT Reads are 11 bytes */
915                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16);
916
917                 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
918                 pkt |= 1 << 28;                         /* tt       [29:28] */
919                 pkt |= 0x8 << 24;                       /* ftype    [27:24] */
920                 pkt |= destid << 8;                     /* destID   [23:8] */
921                 pkt |= sourceid >> 8;                   /* sourceID [7:0] */
922                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
923                 pkt = 0;
924                 pkt |= sourceid << 24;                  /* sourceID [31:24] */
925                 pkt |= 0 << 20;                         /* transaction [23:20] */
926                 pkt |= 8 << 16;                         /* rdsize [19:16] */
927                 pkt |= 0xc0 << 8;                       /* srcTID [15:8] */
928                 pkt |= hopcount;                        /* hopcount [7:0] */
929                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
930                 pkt = 0;
931                 pkt |= offset << 8;                     /* offset [31:11, wdptr[10], reserved[9:8] */
932                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
933             }
934             else
935             {
936                 /* Use the 8bit source ID */
937                 sourceid = (sourceid >> 16) & 0xff;
938
939                 /* MAINT Reads are 9 bytes */
940                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16);
941
942                 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
943                 pkt |= 0 << 28;                         /* tt       [29:28] */
944                 pkt |= 0x8 << 24;                       /* ftype    [27:24] */
945                 pkt |= destid << 16;                    /* destID   [23:16] */
946                 pkt |= sourceid << 8;                   /* sourceID [15:8] */
947                 pkt |= 0 << 4;                          /* transaction [7:4] */
948                 pkt |= 8 << 0;                          /* rdsize [3:0] */
949                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
950                 pkt = 0;
951                 pkt |= 0xc0 << 24;                      /* srcTID [31:24] */
952                 pkt |= hopcount << 16;                  /* hopcount [23:16] */
953                 pkt |= offset >> 8;                     /* offset [15:0] */
954                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
955                 pkt = 0;
956                 pkt |= offset << 24;                    /* offset [31:27, wdptr[26], reserved[25:24] */
957                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
958             }
959
960             stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
961             do
962             {
963                 return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer));
964                 if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle))
965                 {
966                     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
967                         cvmx_dprintf("timeout\n");
968                     return_code = -1;
969                 }
970             } while (return_code == 0);
971
972             if (return_code == ((is16bit) ? 23 : 19))
973             {
974                 if (is16bit)
975                 {
976                     if (offset & 4)
977                         *result = *(uint32_t*)(rx_buffer + 15);
978                     else
979                         *result = *(uint32_t*)(rx_buffer + 11);
980                 }
981                 else
982                 {
983                     if (offset & 4)
984                         *result = *(uint32_t*)(rx_buffer + 13);
985                     else
986                         *result = *(uint32_t*)(rx_buffer + 9);
987                 }
988                 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
989                     cvmx_dprintf("0x%08x\n", (unsigned int)*result);
990                 return_code = 0;
991             }
992             else
993             {
994                 *result = 0xffffffff;
995                 return_code = -1;
996             }
997
998             return return_code;
999         }
1000         else
1001         {
1002 #if !defined(CVMX_BUILD_FOR_LINUX_HOST)
1003             uint64_t physical;
1004             physical = cvmx_srio_physical_map(srio_port,
1005                 CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
1006                 CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
1007                 srcid_index, destid, is16bit, offset + (hopcount<<24), 4);
1008             if (!physical)
1009                 return -1;
1010
1011             if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1012                 cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset);
1013
1014             /* Finally do the maintenance read to complete the config request */
1015             *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical));
1016             cvmx_srio_physical_unmap(physical, 4);
1017
1018             if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1019                 cvmx_dprintf("0x%08x\n", (unsigned int)*result);
1020
1021             return 0;
1022 #else
1023             return -1;
1024 #endif
1025         }
1026     }
1027 }
1028 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1029 EXPORT_SYMBOL(cvmx_srio_config_read32);
1030 #endif
1031
1032
1033 /**
1034  * Write 32bits to a Device's config space
1035  *
1036  * @param srio_port SRIO port the device is on
1037  * @param srcid_index
1038  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
1039  * @param destid    RapidIO device ID, or -1 for the local Octeon.
1040  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
1041  *                  if transactions should use 8bit device IDs.
1042  * @param hopcount  Number of hops to the remote device. Use 0 for the local Octeon.
1043  * @param offset    Offset in config space. This must be a multiple of 32 bits.
1044  * @param data      Data to write.
1045  *
1046  * @return Zero on success, negative on failure.
1047  */
1048 int cvmx_srio_config_write32(int srio_port, int srcid_index, int destid,
1049                              int is16bit, uint8_t hopcount, uint32_t offset,
1050                              uint32_t data)
1051 {
1052     if (destid == -1)
1053     {
1054         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1055             cvmx_dprintf("SRIO%d: Local write[0x%06x] => 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)data);
1056
1057         return __cvmx_srio_local_write32(srio_port, offset, data);
1058     }
1059     else
1060     {
1061         if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
1062         {
1063             int return_code;
1064             uint32_t pkt = 0;
1065             uint32_t sourceid;
1066             uint64_t stop_cycle;
1067             char rx_buffer[64];
1068
1069             /* Tell the user */
1070             if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1071                 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);
1072
1073             /* Read the proper source ID */
1074             if (srcid_index)
1075                 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid);
1076             else
1077                 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid);
1078
1079             if (is16bit)
1080             {
1081                 /* Use the 16bit source ID */
1082                 sourceid &= 0xffff;
1083
1084                 /* MAINT Writes are 19 bytes */
1085                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16);
1086
1087                 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
1088                 pkt |= 1 << 28;                         /* tt       [29:28] */
1089                 pkt |= 0x8 << 24;                       /* ftype    [27:24] */
1090                 pkt |= destid << 8;                     /* destID   [23:8] */
1091                 pkt |= sourceid >> 8;                   /* sourceID [7:0] */
1092                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1093                 pkt = 0;
1094                 pkt |= sourceid << 24;                  /* sourceID [31:24] */
1095                 pkt |= 1 << 20;                         /* transaction [23:20] */
1096                 pkt |= 8 << 16;                         /* wrsize [19:16] */
1097                 pkt |= 0xc0 << 8;                       /* srcTID [15:8] */
1098                 pkt |= hopcount;                        /* hopcount [7:0] */
1099                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1100                 pkt = 0;
1101                 pkt |= offset << 8;                     /* offset [31:11, wdptr[10], reserved[9:8] */
1102                 if ((offset & 4) == 0)
1103                     pkt |= 0xff & (data >> 24);       /* data [7:0] */
1104                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1105                 if (offset & 4)
1106                 {
1107                     pkt = 0xff & (data >> 24);
1108                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1109                     pkt = data << 8;
1110                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1111                 }
1112                 else
1113                 {
1114                     pkt = data << 8;
1115                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1116                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0);
1117                 }
1118             }
1119             else
1120             {
1121                 /* Use the 8bit source ID */
1122                 sourceid = (sourceid >> 16) & 0xff;
1123
1124                 /* MAINT Writes are 17 bytes */
1125                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16);
1126
1127                 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
1128                 pkt |= 0 << 28;                         /* tt       [29:28] */
1129                 pkt |= 0x8 << 24;                       /* ftype    [27:24] */
1130                 pkt |= destid << 16;                    /* destID   [23:16] */
1131                 pkt |= sourceid << 8;                   /* sourceID [15:8] */
1132                 pkt |= 1 << 4;                          /* transaction [7:4] */
1133                 pkt |= 8 << 0;                          /* wrsize [3:0] */
1134                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1135                 pkt = 0;
1136                 pkt |= 0xc0 << 24;                      /* srcTID [31:24] */
1137                 pkt |= hopcount << 16;                  /* hopcount [23:16] */
1138                 pkt |= offset >> 8;                     /* offset [15:0] */
1139                 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1140                 pkt = 0;
1141                 pkt |= offset << 24;                    /* offset [31:27, wdptr[26], reserved[25:24] */
1142                 if (offset & 4)
1143                 {
1144                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1145                     pkt = data >> 8;
1146                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1147                     pkt = data << 24;
1148                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1149                 }
1150                 else
1151                 {
1152                     pkt |= data >> 8;                    /* data [23:0] */
1153                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1154                     pkt = data << 24;                    /* data [31:24] */
1155                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
1156                     __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0);
1157                 }
1158             }
1159
1160             stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
1161             do
1162             {
1163                 return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer));
1164                 if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle))
1165                 {
1166                     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1167                         cvmx_dprintf("timeout\n");
1168                     return_code = -1;
1169                 }
1170             } while (return_code == 0);
1171
1172             if (return_code == ((is16bit) ? 15 : 11))
1173                 return_code = 0;
1174             else
1175             {
1176                 cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port);
1177                 return_code = -1;
1178             }
1179
1180             return return_code;
1181         }
1182         else
1183         {
1184 #if !defined(CVMX_BUILD_FOR_LINUX_HOST)
1185             uint64_t physical = cvmx_srio_physical_map(srio_port,
1186                     CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
1187                     CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
1188                     srcid_index, destid, is16bit, offset + (hopcount<<24), 4);
1189             if (!physical)
1190                 return -1;
1191
1192             if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1193                 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);
1194
1195             /* Finally do the maintenance write to complete the config request */
1196             cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data);
1197             return cvmx_srio_physical_unmap(physical, 4);
1198 #else
1199             return -1;
1200 #endif
1201         }
1202     }
1203 }
1204
1205
1206 /**
1207  * Send a RapidIO doorbell to a remote device
1208  *
1209  * @param srio_port SRIO port the device is on
1210  * @param srcid_index
1211  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
1212  * @param destid    RapidIO device ID.
1213  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
1214  *                  if transactions should use 8bit device IDs.
1215  * @param priority  Doorbell priority (0-3)
1216  * @param data      Data for doorbell.
1217  *
1218  * @return Zero on success, negative on failure.
1219  */
1220 int cvmx_srio_send_doorbell(int srio_port, int srcid_index, int destid, int is16bit, int priority, uint16_t data)
1221 {
1222     cvmx_sriox_tx_bell_t tx_bell;
1223     tx_bell.u64 = 0;
1224     tx_bell.s.data = data;
1225     tx_bell.s.dest_id = destid;
1226     tx_bell.s.src_id = srcid_index;
1227     tx_bell.s.id16 = !!is16bit;
1228     tx_bell.s.priority = priority;
1229
1230     /* Make sure the previous doorbell has completed */
1231     if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_TX_BELL(srio_port), cvmx_sriox_tx_bell_t, pending, ==, 0, CVMX_SRIO_DOORBELL_TIMEOUT))
1232     {
1233         cvmx_dprintf("SRIO%d: Pending bit stuck before doorbell\n", srio_port);
1234         return -1;
1235     }
1236
1237     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1238         cvmx_dprintf("SRIO%d: Send doorbell destid=0x%x, priority=%d, data=0x%x\n", srio_port, destid, priority, 0xffff & data);
1239
1240     /* Send the doorbell. We don't wait for it to complete. The next doorbell
1241         may delay on the pending bit, but this gives the caller the ability to
1242         do other stuff while the doorbell processes */
1243     cvmx_write_csr(CVMX_SRIOX_TX_BELL(srio_port), tx_bell.u64);
1244     return 0;
1245 }
1246 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1247 EXPORT_SYMBOL(cvmx_srio_send_doorbell);
1248 #endif
1249
1250 /**
1251  * Get the status of the last doorbell sent. If the dooorbell
1252  * hardware is done, then the status is cleared to get ready for
1253  * the next doorbell (or retry).
1254  *
1255  * @param srio_port SRIO port to check doorbell on
1256  *
1257  * @return Doorbell status
1258  */
1259 cvmx_srio_doorbell_status_t cvmx_srio_send_doorbell_status(int srio_port)
1260 {
1261     cvmx_sriox_tx_bell_t tx_bell;
1262     cvmx_sriox_tx_bell_info_t tx_bell_info;
1263     cvmx_sriox_int_reg_t int_reg;
1264     cvmx_sriox_int_reg_t int_reg_clear;
1265
1266     /* Return busy if the doorbell is still processing */
1267     tx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL(srio_port));
1268     if (tx_bell.s.pending)
1269         return CVMX_SRIO_DOORBELL_BUSY;
1270
1271     /* Read and clear the TX doorbell interrupts */
1272     int_reg.u64 = cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port));
1273     int_reg_clear.u64 = 0;
1274     int_reg_clear.s.bell_err = int_reg.s.bell_err;
1275     int_reg_clear.s.txbell = int_reg.s.txbell;
1276     cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), int_reg_clear.u64);
1277
1278     /* Check for errors */
1279     if (int_reg.s.bell_err)
1280     {
1281         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1282             cvmx_dprintf("SRIO%d: Send doorbell failed\n", srio_port);
1283         tx_bell_info.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL_INFO(srio_port));
1284         if (tx_bell_info.s.timeout)
1285             return CVMX_SRIO_DOORBELL_TMOUT;
1286         if (tx_bell_info.s.error)
1287             return CVMX_SRIO_DOORBELL_ERROR;
1288         if (tx_bell_info.s.retry)
1289             return CVMX_SRIO_DOORBELL_RETRY;
1290     }
1291
1292     /* Check if we're done */
1293     if (int_reg.s.txbell)
1294         return CVMX_SRIO_DOORBELL_DONE;
1295
1296     /* No doorbell found */
1297     return CVMX_SRIO_DOORBELL_NONE;
1298 }
1299
1300
1301 /**
1302  * Read a received doorbell and report data about it.
1303  *
1304  * @param srio_port SRIO port to check for the received doorbell
1305  * @param destid_index
1306  *                  Which Octeon destination ID was the doorbell for
1307  * @param sequence_num
1308  *                  Sequence number of doorbell (32bits)
1309  * @param srcid     RapidIO source ID of the doorbell sender
1310  * @param priority  Priority of the doorbell (0-3)
1311  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
1312  *                  if transactions should use 8bit device IDs.
1313  * @param data      Data in the doorbell (16 bits)
1314  *
1315  * @return Doorbell status. Either DONE, NONE, or ERROR.
1316  */
1317 cvmx_srio_doorbell_status_t cvmx_srio_receive_doorbell(int srio_port,
1318         int *destid_index, uint32_t *sequence_num, int *srcid, int *priority,
1319         int *is16bit, uint16_t *data)
1320 {
1321     cvmx_sriox_rx_bell_seq_t rx_bell_seq;
1322     cvmx_sriox_rx_bell_t rx_bell;
1323
1324     /* Check if there are any pending doorbells */
1325     rx_bell_seq.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL_SEQ(srio_port));
1326     if (!rx_bell_seq.s.count)
1327         return CVMX_SRIO_DOORBELL_NONE;
1328
1329     /* Read the doorbell and write our return parameters */
1330     rx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL(srio_port));
1331     *sequence_num = rx_bell_seq.s.seq;
1332     *srcid = rx_bell.s.src_id;
1333     *priority = rx_bell.s.priority;
1334     *is16bit = rx_bell.s.id16;
1335     *data = rx_bell.s.data;
1336     *destid_index = rx_bell.s.dest_id;
1337
1338     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1339         cvmx_dprintf("SRIO%d: Receive doorbell sequence=0x%x, srcid=0x%x, priority=%d, data=0x%x\n",
1340             srio_port, rx_bell_seq.s.seq, rx_bell.s.src_id, rx_bell.s.priority, rx_bell.s.data);
1341
1342     return CVMX_SRIO_DOORBELL_DONE;
1343 }
1344
1345
1346 /**
1347  * Receive a packet from the Soft Packet FIFO (SPF).
1348  *
1349  * @param srio_port SRIO port to read the packet from.
1350  * @param buffer    Buffer to receive the packet.
1351  * @param buffer_length
1352  *                  Length of the buffer in bytes.
1353  *
1354  * @return Returns the length of the packet read. Negative on failure.
1355  *         Zero if no packets are available.
1356  */
1357 int cvmx_srio_receive_spf(int srio_port, void *buffer, int buffer_length)
1358 {
1359     uint32_t *ptr = (uint32_t *)buffer;
1360     cvmx_sriomaintx_ir_sp_rx_stat_t sriomaintx_ir_sp_rx_stat;
1361
1362     /* Read the SFP status */
1363     if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_STAT(srio_port), &sriomaintx_ir_sp_rx_stat.u32))
1364         return -1;
1365
1366     /* Return zero if there isn't a packet available */
1367     if (sriomaintx_ir_sp_rx_stat.s.buffers < 1)
1368         return 0;
1369
1370     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1371         cvmx_dprintf("SRIO%d: Soft packet FIFO received %d bytes", srio_port, sriomaintx_ir_sp_rx_stat.s.octets);
1372
1373     /* Return error if the packet is larger than our buffer */
1374     if (sriomaintx_ir_sp_rx_stat.s.octets > buffer_length)
1375         return -1;
1376
1377     /* Read out the packet four bytes at a time */
1378     buffer_length = sriomaintx_ir_sp_rx_stat.s.octets;
1379     while (buffer_length > 0)
1380     {
1381         __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_DATA(srio_port), ptr);
1382         if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1383             cvmx_dprintf(" %08x", (unsigned int)*ptr);
1384         ptr++;
1385         buffer_length-=4;
1386     }
1387
1388     if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1389         cvmx_dprintf("\n");
1390
1391     /* Return the number of bytes in the buffer */
1392     return sriomaintx_ir_sp_rx_stat.s.octets;
1393 }
1394
1395 #ifndef CVMX_BUILD_FOR_LINUX_HOST
1396 /**
1397  * Map a remote device's memory region into Octeon's physical
1398  * address area. The caller can then map this into a core using
1399  * the TLB or XKPHYS.
1400  *
1401  * @param srio_port SRIO port to map the device on
1402  * @param write_op  Type of operation to perform on a write to the device.
1403  *                  Normally should be CVMX_SRIO_WRITE_MODE_AUTO.
1404  * @param write_priority
1405  *                  SRIO priority of writes (0-3)
1406  * @param read_op   Type of operation to perform on reads to the device.
1407  *                  Normally should be CVMX_SRIO_READ_MODE_NORMAL.
1408  * @param read_priority
1409  *                  SRIO priority of reads (0-3)
1410  * @param srcid_index
1411  *                  Which SRIO source ID to use. 0 = Primary, 1 = Secondary
1412  * @param destid    RapidIO device ID.
1413  * @param is16bit   Non zero if the transactions should use 16bit device IDs. Zero
1414  *                  if transactions should use 8bit device IDs.
1415  * @param base      Device base address to start the mapping
1416  * @param size      Size of the mapping in bytes
1417  *
1418  * @return Octeon 64bit physical address that accesses the remote device,
1419  *         or zero on failure.
1420  */
1421 uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op,
1422         int write_priority, cvmx_srio_read_mode_t read_op, int read_priority,
1423         int srcid_index, int destid, int is16bit, uint64_t base, uint64_t size)
1424 {
1425     cvmx_sriox_s2m_typex_t needed_s2m_type;
1426     cvmx_sli_mem_access_subidx_t needed_subid;
1427     int s2m_index;
1428     int subdid;
1429     cvmx_sli_address_t sli_address;
1430
1431     /* We currently don't support mapping regions that span a 34 bit boundary.
1432         Keeping track of multiple regions to span 34 bits is hard and not
1433         likely to be needed */
1434     if (((base+size-1)>>34) != (base>>34))
1435     {
1436         cvmx_dprintf("SRIO%d: Failed to map range 0x%llx-0x%llx spanning a 34bit boundary\n",
1437             srio_port, (ULL)base, (ULL)base+size-1);
1438         return 0;
1439     }
1440
1441     /* Build the S2M_TYPE we are going to need */
1442     needed_s2m_type.u64 = 0;
1443     needed_s2m_type.s.wr_op = write_op;
1444     needed_s2m_type.s.rd_op = read_op;
1445     needed_s2m_type.s.wr_prior = write_priority;
1446     needed_s2m_type.s.rd_prior = read_priority;
1447     needed_s2m_type.s.src_id = srcid_index;
1448     needed_s2m_type.s.id16 = !!is16bit;
1449
1450     /* Build the needed SubID config */
1451     needed_subid.u64 = 0;
1452     needed_subid.s.port = srio_port;
1453     needed_subid.s.nmerge = 0;
1454
1455     /* FIXME: We might want to use the device ID swapping modes so the device
1456         ID is part of the lower address bits. This would allow many more
1457         devices to share S2M_TYPE indexes. This would require "base+size-1"
1458         to fit in bits [17:0] or bits[25:0] for 8 bits of device ID */
1459     if (base < (1ull<<34))
1460     {
1461         needed_subid.cn63xx.ba = destid;
1462         needed_s2m_type.s.iaow_sel = 0;
1463     }
1464     else if (base < (1ull<<42))
1465     {
1466         needed_subid.cn63xx.ba = (base>>34) & 0xff;
1467         needed_subid.cn63xx.ba |= ((uint64_t)destid & 0xff) << (42-34);
1468         needed_subid.cn63xx.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34);
1469         needed_s2m_type.s.iaow_sel = 1;
1470     }
1471     else
1472     {
1473         if (destid>>8)
1474         {
1475             cvmx_dprintf("SRIO%d: Attempt to map 16bit device ID 0x%x using 66bit addressing\n", srio_port, destid);
1476             return 0;
1477         }
1478         if (base>>50)
1479         {
1480             cvmx_dprintf("SRIO%d: Attempt to map address 0x%llx using 66bit addressing\n", srio_port, (ULL)base);
1481             return 0;
1482         }
1483         needed_subid.cn63xx.ba = (base>>34) & 0xffff;
1484         needed_subid.cn63xx.ba |= ((uint64_t)destid & 0xff) << (51-34);
1485         needed_s2m_type.s.iaow_sel = 2;
1486     }
1487
1488     /* Find a S2M_TYPE index to use. If this fails return 0 */
1489     s2m_index = __cvmx_srio_alloc_s2m(srio_port, needed_s2m_type);
1490     if (s2m_index == -1)
1491         return 0;
1492
1493     /* Attach the SubID to the S2M_TYPE index */
1494     needed_subid.s.rtype = s2m_index & 3;
1495     needed_subid.s.wtype = s2m_index & 3;
1496     needed_subid.cn63xx.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34);
1497     needed_subid.cn63xx.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34);
1498
1499     /* Allocate a SubID for use */
1500     subdid = __cvmx_srio_alloc_subid(needed_subid);
1501     if (subdid == -1)
1502     {
1503         /* Free the s2m_index as we aren't using it */
1504         __cvmx_srio_free_s2m(srio_port, s2m_index);
1505         return 0;
1506     }
1507
1508     /* Build the final core physical address */
1509     sli_address.u64 = 0;
1510     sli_address.mem.io = 1;
1511     sli_address.mem.did = 3;
1512     sli_address.mem.subdid = subdid>>2;
1513     sli_address.mem.se = subdid & 3;
1514     sli_address.mem.address = base; /* Bits[33:0] of full address */
1515     return sli_address.u64;
1516 }
1517
1518
1519 /**
1520  * Unmap a physical address window created by cvmx_srio_phys_map().
1521  *
1522  * @param physical_address
1523  *               Physical address returned by cvmx_srio_phys_map().
1524  * @param size   Size used on original call.
1525  *
1526  * @return Zero on success, negative on failure.
1527  */
1528 int cvmx_srio_physical_unmap(uint64_t physical_address, uint64_t size)
1529 {
1530     cvmx_sli_mem_access_subidx_t subid;
1531     int subdid = (physical_address >> 40) & 7;
1532     int extender = (physical_address >> 34) & 3;
1533     int mem_index = subdid * 4 + extender;
1534     int read_s2m_type;
1535
1536     /* Get the subid setup so we can figure out where this mapping was for */
1537     subid.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index));
1538     /* Type[0] is mapped to the Relaxed Ordering
1539        Type[1] is mapped to the No Snoop
1540        Type[2] is mapped directly to bit 50 of the SLI address
1541        Type[3] is mapped directly to bit 59 of the SLI address */
1542     read_s2m_type = ((subid.cn63xx.ba>>(50-34))&1<<2) | ((subid.cn63xx.ba>>(59-34))&1<<3);
1543     read_s2m_type |= subid.s.rtype;
1544     __cvmx_srio_free_subid(mem_index);
1545     __cvmx_srio_free_s2m(subid.s.port, read_s2m_type);
1546     return 0;
1547 }
1548
1549 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
1550 /**
1551  * fill out outbound message descriptor
1552  *
1553  * @param port        pip/ipd port number
1554  * @param buf_ptr     pointer to a buffer pointer. the buffer pointer points
1555  *                    to a chain of buffers that hold an outbound srio packet.
1556  *                    the packet can take the format of (1) a pip/ipd inbound
1557  *                    message or (2) an application-generated outbound message
1558  * @param desc_ptr    pointer to an outbound message descriptor. should be null
1559  *                    if *buf_ptr is in the format (1)
1560  *
1561  * @return           0 on success; negative of failure.
1562  */
1563 int cvmx_srio_omsg_desc (uint64_t port, cvmx_buf_ptr_t *buf_ptr,
1564                          cvmx_srio_tx_message_header_t *desc_ptr)
1565 {
1566     int ret_val = -1;
1567     int intf_num;
1568     cvmx_helper_interface_mode_t imode;
1569
1570     uint64_t *desc_addr, *hdr_addr;
1571     cvmx_srio_rx_message_header_t rx_msg_hdr;
1572     cvmx_srio_tx_message_header_t *tx_msg_hdr_ptr;
1573
1574     if (buf_ptr == NULL)
1575         return ret_val;
1576
1577     /* check if port is an srio port */
1578     intf_num = cvmx_helper_get_interface_num (port);
1579     imode = cvmx_helper_interface_get_mode (intf_num);
1580     if (imode !=  CVMX_HELPER_INTERFACE_MODE_SRIO)
1581         return ret_val;
1582
1583     /* app-generated outbound message. descriptor space pre-allocated */
1584     if (desc_ptr != NULL)
1585     {
1586         desc_addr = (uint64_t *) cvmx_phys_to_ptr ((*buf_ptr).s.addr);
1587         *desc_addr = *(uint64_t *) desc_ptr;
1588         ret_val = 0;
1589         return ret_val;
1590     }
1591
1592     /* pip/ipd inbound message. 16-byte srio message header is present */
1593     hdr_addr = (uint64_t *) cvmx_phys_to_ptr ((*buf_ptr).s.addr);
1594     rx_msg_hdr.word0.u64 = *hdr_addr;
1595
1596     /* adjust buffer pointer to get rid of srio message header word 0 */
1597     (*buf_ptr).s.addr += 8;
1598     (*buf_ptr).s.size -= 8; /* last buffer or not */
1599     if ((*buf_ptr).s.addr >> 7 > ((*buf_ptr).s.addr - 8) >> 7)
1600         (*buf_ptr).s.back++;
1601     tx_msg_hdr_ptr = (cvmx_srio_tx_message_header_t *)
1602                          cvmx_phys_to_ptr ((*buf_ptr).s.addr);
1603
1604     /* transfer values from rx to tx */
1605     tx_msg_hdr_ptr->s.prio = rx_msg_hdr.word0.s.prio;
1606     tx_msg_hdr_ptr->s.tt = rx_msg_hdr.word0.s.tt; /* called id in hrm */
1607     tx_msg_hdr_ptr->s.sis = rx_msg_hdr.word0.s.dis;
1608     tx_msg_hdr_ptr->s.ssize = rx_msg_hdr.word0.s.ssize;
1609     tx_msg_hdr_ptr->s.did = rx_msg_hdr.word0.s.sid;
1610     tx_msg_hdr_ptr->s.mbox = rx_msg_hdr.word0.s.mbox;
1611
1612     /* other values we have to decide */
1613     tx_msg_hdr_ptr->s.xmbox = 0;  /* multi-segement in general */
1614     tx_msg_hdr_ptr->s.letter = 0; /* fake like traffic gen */
1615     tx_msg_hdr_ptr->s.lns = 0;    /* not use sriox_omsg_ctrly[] */
1616     tx_msg_hdr_ptr->s.intr = 1;   /* get status */
1617
1618     ret_val = 0;
1619     return ret_val;
1620 }
1621 #endif
1622 #endif