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
85typedef 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
138typedef 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
145static 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 */
162static 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 */
202static 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 */
219static 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 */
256static 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 */
275static 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 */
331static 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 */
374int 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 */
418int 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 */
876int 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
1029EXPORT_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 */
1048int 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 */
1220int 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
1247EXPORT_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 */
1259cvmx_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 */
1317cvmx_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 */
1357int 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 */
1421uint64_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 */
1528int 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 */
1563int 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
1623