diff options
Diffstat (limited to 'cvmx-srio.c')
-rw-r--r-- | cvmx-srio.c | 907 |
1 files changed, 644 insertions, 263 deletions
diff --git a/cvmx-srio.c b/cvmx-srio.c index f8511c6b08d8..ed9ba3e6c876 100644 --- a/cvmx-srio.c +++ b/cvmx-srio.c @@ -1,5 +1,5 @@ /***********************license start*************** - * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights + * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights * reserved. * * @@ -15,7 +15,7 @@ * disclaimer in the documentation and/or other materials provided * with the distribution. - * * Neither the name of Cavium Networks nor the names of + * * Neither the name of Cavium Inc. nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. @@ -26,7 +26,7 @@ * countries. * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR + * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM @@ -60,6 +60,7 @@ #include <asm/octeon/cvmx-dpi-defs.h> #include <asm/octeon/cvmx-pexp-defs.h> #include <asm/octeon/cvmx-helper.h> +#include <asm/octeon/cvmx-qlm.h> #else #include "cvmx.h" #include "cvmx-srio.h" @@ -70,9 +71,10 @@ #include "cvmx-error.h" #include "cvmx-helper-errata.h" #endif +#include "cvmx-qlm.h" +#include "cvmx-helper.h" #endif -#define CVMX_SRIO_USE_FIFO_FOR_MAINT 1 #define CVMX_SRIO_CONFIG_TIMEOUT 10000 /* 10ms */ #define CVMX_SRIO_DOORBELL_TIMEOUT 10000 /* 10ms */ #define CVMX_SRIO_CONFIG_PRIORITY 0 @@ -83,7 +85,7 @@ typedef union uint64_t u64; struct { -#if __BYTE_ORDER == __BIG_ENDIAN +#ifdef __BIG_ENDIAN_BITFIELD uint64_t upper : 2; /* Normally 2 for XKPHYS */ uint64_t reserved_49_61 : 13; /* Must be zero */ uint64_t io : 1; /* 1 for IO space access */ @@ -109,7 +111,7 @@ typedef union } config; struct { -#if __BYTE_ORDER == __BIG_ENDIAN +#ifdef __BIG_ENDIAN_BITFIELD uint64_t upper : 2; /* Normally 2 for XKPHYS */ uint64_t reserved_49_61 : 13; /* Must be zero */ uint64_t io : 1; /* 1 for IO space access */ @@ -138,7 +140,7 @@ typedef struct int32_t s2m_ref_count[16]; /* Reference count for SRIOX_S2M_TYPE[0-15]. */ } __cvmx_srio_state_t; -static CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[2]; +static CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[4]; #ifndef CVMX_BUILD_FOR_LINUX_HOST @@ -170,6 +172,8 @@ static int __cvmx_srio_alloc_s2m(int srio_port, cvmx_sriox_s2m_typex_t s2m) { /* Unused location. Write our value */ cvmx_write_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port), s2m.u64); + /* Read back to make sure the update is complete */ + cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)); return s2m_index; } else @@ -223,6 +227,8 @@ static int __cvmx_srio_alloc_subid(cvmx_sli_mem_access_subidx_t subid) { /* Unused location. Write our value */ cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index), subid.u64); + /* Read back the value to make sure the update is complete */ + cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)); return mem_index; } else @@ -357,6 +363,49 @@ static int __cvmx_srio_local_write32(int srio_port, uint32_t offset, uint32_t da /** + * Reset SRIO to link partner + * + * @param srio_port SRIO port to initialize + * + * @return Zero on success + */ +int cvmx_srio_link_rst(int srio_port) +{ + cvmx_sriomaintx_port_0_link_resp_t link_resp; + + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + return -1; + + /* Generate a symbol reset to the link partner by writing 0x3. */ + if (cvmx_srio_config_write32(srio_port, 0, -1, 0, 0, + CVMX_SRIOMAINTX_PORT_0_LINK_REQ(srio_port), 3)) + return -1; + + if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, + CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32)) + return -1; + + /* Poll until link partner has received the reset. */ + while (link_resp.s.valid == 0) + { + //cvmx_dprintf("Waiting for Link Response\n"); + if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, + CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32)) + return -1; + } + + /* Valid response, Asserting MAC reset */ + cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1); + + cvmx_wait(10); + + /* De-asserting MAC Reset */ + cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0); + + return 0; +} + +/** * Initialize a SRIO port for use. * * @param srio_port SRIO port to initialize @@ -376,9 +425,21 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) cvmx_sriox_imsg_vport_thr_t sriox_imsg_vport_thr; cvmx_dpi_sli_prtx_cfg_t prt_cfg; cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; + cvmx_sli_mem_access_ctl_t sli_mem_access_ctl; + cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2; sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port)); - if (!sriox_status_reg.s.srio) + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) + { + /* All SRIO ports are connected to QLM0 */ + int status = cvmx_qlm_get_status(0); + if (status < 4 || status > 6) + { + cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port); + return -1; + } + } + else if (!sriox_status_reg.s.srio) { cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port); return -1; @@ -410,41 +471,146 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) } } - mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port)); + /* Don't receive or drive reset signals for the SRIO QLM */ + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) + { + /* The reset signals are available only for srio_port == 0. */ + if (srio_port == 0 || (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_2) && srio_port == 1)) + { + cvmx_mio_rst_cntlx_t mio_rst_cntl; + mio_rst_cntl.u64 = cvmx_read_csr(CVMX_MIO_RST_CNTLX(srio_port)); + mio_rst_cntl.s.rst_drv = 0; + mio_rst_cntl.s.rst_rcv = 0; + mio_rst_cntl.s.rst_chip = 0; + cvmx_write_csr(CVMX_MIO_RST_CNTLX(srio_port), mio_rst_cntl.u64); + } + /* MIO_RST_CNTL2<prtmode> is initialized to 0 on cold reset */ + mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CNTLX(srio_port)); + } + else + { + mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port)); + mio_rst_ctl.s.rst_drv = 0; + mio_rst_ctl.s.rst_rcv = 0; + mio_rst_ctl.s.rst_chip = 0; + cvmx_write_csr(CVMX_MIO_RST_CTLX(srio_port), mio_rst_ctl.u64); + + mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port)); + } + cvmx_dprintf("SRIO%d: Port in %s mode\n", srio_port, (mio_rst_ctl.s.prtmode) ? "host" : "endpoint"); /* Bring the port out of reset if necessary */ - if (srio_port) + switch (srio_port) { - cvmx_ciu_soft_prst1_t prst; - prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); - if (prst.s.soft_prst) + case 0: { - prst.s.soft_prst = 0; - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64); - cvmx_wait_usec(10000); /* 10ms for new link to stabalize */ + cvmx_ciu_soft_prst_t prst; + prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + if (prst.s.soft_prst) + { + prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64); + /* Wait up to 250ms for the port to come out of reset */ + if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000)) + return -1; + } + break; } - } - else - { - cvmx_ciu_soft_prst_t prst; - prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); - if (prst.s.soft_prst) + case 1: { - prst.s.soft_prst = 0; - cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64); - cvmx_wait_usec(10000); /* 10ms for new link to stabalize */ + cvmx_ciu_soft_prst1_t prst; + prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + if (prst.s.soft_prst) + { + prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64); + /* Wait up to 250ms for the port to come out of reset */ + if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000)) + return -1; + } + break; + } + case 2: + { + cvmx_ciu_soft_prst2_t prst; + prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST2); + if (prst.s.soft_prst) + { + prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST2, prst.u64); + /* Wait up to 250ms for the port to come out of reset */ + if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000)) + return -1; + } + break; } } /* Disable the link while we make changes */ if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32)) return -1; - port_0_ctl.s.disable = 1; + port_0_ctl.s.o_enable = 0; + port_0_ctl.s.i_enable = 0; + port_0_ctl.s.prt_lock = 1; + port_0_ctl.s.disable = 0; if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32)) return -1; + /* CN63XX Pass 2.0 and 2.1 errata G-15273 requires the QLM De-emphasis be + programmed when using a 156.25Mhz ref clock */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) || + OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1)) + { + cvmx_mio_rst_boot_t mio_rst_boot; + cvmx_sriomaintx_lane_x_status_0_t lane_x_status; + + /* Read the QLM config and speed pins */ + mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); + if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_LANE_X_STATUS_0(0, srio_port), &lane_x_status.u32)) + return -1; + + if (srio_port) + { + cvmx_ciu_qlm1_t ciu_qlm; + ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); + switch (mio_rst_boot.cn63xx.qlm1_spd) + { + case 0x4: /* 1.25 Gbaud, 156.25MHz */ + ciu_qlm.s.txbypass = 1; + ciu_qlm.s.txdeemph = 0x0; + ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0x11 : 0x1c; /* short or med/long */ + break; + case 0xb: /* 5.0 Gbaud, 156.25MHz */ + ciu_qlm.s.txbypass = 1; + ciu_qlm.s.txdeemph = (lane_x_status.s.rx_type == 0) ? 0xa : 0xf; /* short or med/long */ + ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0xf : 0x1a; /* short or med/long */ + break; + } + cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); + } + else + { + cvmx_ciu_qlm0_t ciu_qlm; + ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); + switch (mio_rst_boot.cn63xx.qlm0_spd) + { + case 0x4: /* 1.25 Gbaud, 156.25MHz */ + ciu_qlm.s.txbypass = 1; + ciu_qlm.s.txdeemph = 0x0; + ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0x11 : 0x1c; /* short or med/long */ + break; + case 0xb: /* 5.0 Gbaud, 156.25MHz */ + ciu_qlm.s.txbypass = 1; + ciu_qlm.s.txdeemph = (lane_x_status.s.rx_type == 0) ? 0xa : 0xf; /* short or med/long */ + ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0xf : 0x1a; /* short or med/long */ + break; + } + cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); + } + } + /* Errata SRIO-14485: Link speed is reported incorrectly in CN63XX pass 1.x */ if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) @@ -481,19 +647,31 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) return -1; } - /* Set the link layer timeout to 10us. The default is too high and causes + /* Errata SRIO-15351: Turn off SRIOMAINTX_MAC_CTRL[TYPE_MRG] as it may + cause packet ACCEPT to be lost */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) || OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1)) + { + cvmx_sriomaintx_mac_ctrl_t mac_ctrl; + if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_MAC_CTRL(srio_port), &mac_ctrl.u32)) + return -1; + mac_ctrl.s.type_mrg = 0; + if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_MAC_CTRL(srio_port), mac_ctrl.u32)) + return -1; + } + + /* Set the link layer timeout to 1ms. The default is too high and causes core bus errors */ if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), &port_lt_ctl.u32)) return -1; - port_lt_ctl.s.timeout = 10000 / 200; /* 10us = 10000ns / 200ns */ + port_lt_ctl.s.timeout = 1000000 / 200; /* 1ms = 1000000ns / 200ns */ if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), port_lt_ctl.u32)) return -1; - /* Set the logical layer timeout to 10ms. The default is too high and causes + /* Set the logical layer timeout to 100ms. The default is too high and causes core bus errors */ if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), &port_rt_ctl.u32)) return -1; - port_rt_ctl.s.timeout = 10000000 / 200; /* 10ms = 10000000ns / 200ns */ + port_rt_ctl.s.timeout = 100000000 / 200; /* 100ms = 100000000ns / 200ns */ if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), port_rt_ctl.u32)) return -1; @@ -516,6 +694,11 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port)); prt_cfg.s.mps = 1; prt_cfg.s.mrrs = 1; + prt_cfg.s.molr = 32; + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) + prt_cfg.s.molr = ((prt_cfg.s.qlm_cfg == 1 || prt_cfg.s.qlm_cfg == 3) ? 8 + : (prt_cfg.s.qlm_cfg == 4 || prt_cfg.s.qlm_cfg == 6) ? 16 + : 32); cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port), prt_cfg.u64); sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port)); @@ -524,7 +707,10 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) /* Setup RX messaging thresholds */ sriox_imsg_vport_thr.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port)); - sriox_imsg_vport_thr.s.max_tot = 48; + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) + sriox_imsg_vport_thr.s.max_tot = ((prt_cfg.s.qlm_cfg == 1 || prt_cfg.s.qlm_cfg == 3) ? 44 : 46); + else + sriox_imsg_vport_thr.s.max_tot = 48; sriox_imsg_vport_thr.s.max_s1 = 24; sriox_imsg_vport_thr.s.max_s0 = 24; sriox_imsg_vport_thr.s.sp_vport = 1; @@ -533,6 +719,16 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) sriox_imsg_vport_thr.s.max_p0 = 12; cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port), sriox_imsg_vport_thr.u64); + /* Setup RX messaging thresholds for other virtual ports. */ + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) + { + cvmx_sriox_imsg_vport_thr2_t sriox_imsg_vport_thr2; + sriox_imsg_vport_thr2.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR2(srio_port)); + sriox_imsg_vport_thr2.s.max_s2 = 24; + sriox_imsg_vport_thr2.s.max_s3 = 24; + cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR2(srio_port), sriox_imsg_vport_thr2.u64); + } + /* Errata SRIO-X: SRIO error behavior may not be optimal in CN63XX pass 1.x */ if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) { @@ -544,6 +740,32 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) cvmx_write_csr(CVMX_SRIOX_TX_CTRL(srio_port), sriox_tx_ctrl.u64); } + /* Errata SLI-15954: SLI relaxed order issues */ + if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) + { + cvmx_sli_ctl_portx_t sli_ctl_portx; + sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port)); + sli_ctl_portx.s.ptlp_ro = 1; /* Set to same value for all MACs. */ + sli_ctl_portx.s.ctlp_ro = 1; /* Set to same value for all MACs. */ + sli_ctl_portx.s.wait_com = 0; /* So that no inbound stores wait for a commit */ + sli_ctl_portx.s.waitl_com = 0; + cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port), sli_ctl_portx.u64); + } + + if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + { + /* Clear the ACK state */ + if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LOCAL_ACKID(srio_port), 0)) + return -1; + } + + /* Bring the link down, then up, by writing to the SRIO port's + PORT_0_CTL2 CSR. */ + if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32)) + return -1; + if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32)) + return -1; + /* Clear any pending interrupts */ cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port))); @@ -562,6 +784,74 @@ int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32)) return -1; + /* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ + sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL); + sli_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ + sli_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ + cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_mem_access_ctl.u64); + + /* FIXME: Disable sending a link request when the SRIO link is + brought up. For unknown reasons this code causes issues with some SRIO + devices. As we currently don't support hotplug in software, this code + should never be needed. Without link down/up events, the ACKs should + start off and stay synchronized */ +#if 0 + /* Ask for a link and align our ACK state. CN63XXp1 didn't support this */ + if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + { + uint64_t stop_cycle; + cvmx_sriomaintx_port_0_err_stat_t sriomaintx_port_0_err_stat; + + /* Clear the SLI_CTL_PORTX[DIS_PORT[ bit to re-enable traffic-flow + to the SRIO MACs. */ + cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port), cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port))); + + /* Wait a little to see if the link comes up */ + stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/4 + cvmx_clock_get_count(CVMX_CLOCK_CORE); + do + { + /* Read the port link status */ + if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_ERR_STAT(srio_port), &sriomaintx_port_0_err_stat.u32)) + return -1; + } while (!sriomaintx_port_0_err_stat.s.pt_ok && (cvmx_clock_get_count(CVMX_CLOCK_CORE) < stop_cycle)); + + /* Send link request if link is up */ + if (sriomaintx_port_0_err_stat.s.pt_ok) + { + cvmx_sriomaintx_port_0_link_req_t link_req; + cvmx_sriomaintx_port_0_link_resp_t link_resp; + link_req.u32 = 0; + link_req.s.cmd = 4; + + /* Send the request */ + if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LINK_REQ(srio_port), link_req.u32)) + return -1; + + /* Wait for the response */ + stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/8 + cvmx_clock_get_count(CVMX_CLOCK_CORE); + do + { + if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32)) + return -1; + } while (!link_resp.s.valid && (cvmx_clock_get_count(CVMX_CLOCK_CORE) < stop_cycle)); + + /* Set our ACK state if we got a response */ + if (link_resp.s.valid) + { + cvmx_sriomaintx_port_0_local_ackid_t local_ackid; + local_ackid.u32 = 0; + local_ackid.s.i_ackid = 0; + local_ackid.s.e_ackid = link_resp.s.ackid; + local_ackid.s.o_ackid = link_resp.s.ackid; + if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LOCAL_ACKID(srio_port), local_ackid.u32)) + return -1; + } + else + return -1; + } + } +#endif + return 0; } @@ -596,138 +886,146 @@ int cvmx_srio_config_read32(int srio_port, int srcid_index, int destid, } else { -#if CVMX_SRIO_USE_FIFO_FOR_MAINT - int return_code; - uint32_t pkt = 0; - uint32_t sourceid; - uint64_t stop_cycle; - char rx_buffer[64]; + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + { + int return_code; + uint32_t pkt = 0; + uint32_t sourceid; + uint64_t stop_cycle; + char rx_buffer[64]; - /* Tell the user */ - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset); + /* Tell the user */ + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset); - /* Read the proper source ID */ - if (srcid_index) - __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); - else - __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); + /* Read the proper source ID */ + if (srcid_index) + __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); + else + __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); - if (is16bit) - { - /* Use the 16bit source ID */ - sourceid &= 0xffff; - - /* MAINT Reads are 11 bytes */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16); - - pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ - pkt |= 1 << 28; /* tt [29:28] */ - pkt |= 0x8 << 24; /* ftype [27:24] */ - pkt |= destid << 8; /* destID [23:8] */ - pkt |= sourceid >> 8; /* sourceID [7:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= sourceid << 24; /* sourceID [31:24] */ - pkt |= 0 << 20; /* transaction [23:20] */ - pkt |= 8 << 16; /* rdsize [19:16] */ - pkt |= 0xc0 << 8; /* srcTID [15:8] */ - pkt |= hopcount; /* hopcount [7:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - } - else - { - /* Use the 8bit source ID */ - sourceid = (sourceid >> 16) & 0xff; - - /* MAINT Reads are 9 bytes */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16); - - pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ - pkt |= 0 << 28; /* tt [29:28] */ - pkt |= 0x8 << 24; /* ftype [27:24] */ - pkt |= destid << 16; /* destID [23:16] */ - pkt |= sourceid << 8; /* sourceID [15:8] */ - pkt |= 0 << 4; /* transaction [7:4] */ - pkt |= 8 << 0; /* rdsize [3:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= 0xc0 << 24; /* srcTID [31:24] */ - pkt |= hopcount << 16; /* hopcount [23:16] */ - pkt |= offset >> 8; /* offset [15:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - } + if (is16bit) + { + /* Use the 16bit source ID */ + sourceid &= 0xffff; - stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); - do - { - return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); - if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) + /* MAINT Reads are 11 bytes */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16); + + pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ + pkt |= 1 << 28; /* tt [29:28] */ + pkt |= 0x8 << 24; /* ftype [27:24] */ + pkt |= destid << 8; /* destID [23:8] */ + pkt |= sourceid >> 8; /* sourceID [7:0] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = 0; + pkt |= sourceid << 24; /* sourceID [31:24] */ + pkt |= 0 << 20; /* transaction [23:20] */ + pkt |= 8 << 16; /* rdsize [19:16] */ + pkt |= 0xc0 << 8; /* srcTID [15:8] */ + pkt |= hopcount; /* hopcount [7:0] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = 0; + pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + } + else { - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("timeout\n"); - return_code = -1; + /* Use the 8bit source ID */ + sourceid = (sourceid >> 16) & 0xff; + + /* MAINT Reads are 9 bytes */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16); + + pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ + pkt |= 0 << 28; /* tt [29:28] */ + pkt |= 0x8 << 24; /* ftype [27:24] */ + pkt |= destid << 16; /* destID [23:16] */ + pkt |= sourceid << 8; /* sourceID [15:8] */ + pkt |= 0 << 4; /* transaction [7:4] */ + pkt |= 8 << 0; /* rdsize [3:0] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = 0; + pkt |= 0xc0 << 24; /* srcTID [31:24] */ + pkt |= hopcount << 16; /* hopcount [23:16] */ + pkt |= offset >> 8; /* offset [15:0] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = 0; + pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); } - } while (return_code == 0); - if (return_code == ((is16bit) ? 23 : 19)) - { - if (is16bit) + stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); + do { - if (offset & 4) - *result = *(uint32_t*)(rx_buffer + 15); + return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); + if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) + { + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + cvmx_dprintf("timeout\n"); + return_code = -1; + } + } while (return_code == 0); + + if (return_code == ((is16bit) ? 23 : 19)) + { + if (is16bit) + { + if (offset & 4) + *result = *(uint32_t*)(rx_buffer + 15); + else + *result = *(uint32_t*)(rx_buffer + 11); + } else - *result = *(uint32_t*)(rx_buffer + 11); + { + if (offset & 4) + *result = *(uint32_t*)(rx_buffer + 13); + else + *result = *(uint32_t*)(rx_buffer + 9); + } + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + cvmx_dprintf("0x%08x\n", (unsigned int)*result); + return_code = 0; } else { - if (offset & 4) - *result = *(uint32_t*)(rx_buffer + 13); - else - *result = *(uint32_t*)(rx_buffer + 9); + *result = 0xffffffff; + return_code = -1; } - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("0x%08x\n", (unsigned int)*result); - return_code = 0; + + return return_code; } else { - *result = 0xffffffff; - return_code = -1; - } - - return return_code; -#elif !defined(CVMX_BUILD_FOR_LINUX_HOST) - uint64_t physical; - physical = cvmx_srio_physical_map(srio_port, - CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, - CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, - srcid_index, destid, is16bit, offset + (hopcount<<24), 4); - if (!physical) - return -1; +#if !defined(CVMX_BUILD_FOR_LINUX_HOST) + uint64_t physical; + physical = cvmx_srio_physical_map(srio_port, + CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, + CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, + srcid_index, destid, is16bit, offset + (hopcount<<24), 4); + if (!physical) + return -1; - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, offset); + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset); - /* Finally do the maintenance read to complete the config request */ - *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical)); - cvmx_srio_physical_unmap(physical, 4); + /* Finally do the maintenance read to complete the config request */ + *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical)); + cvmx_srio_physical_unmap(physical, 4); - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("0x%08x\n", *result); + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + cvmx_dprintf("0x%08x\n", (unsigned int)*result); - return 0; + return 0; #else - return -1; + return -1; #endif + } } } +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_srio_config_read32); +#endif /** @@ -758,142 +1056,147 @@ int cvmx_srio_config_write32(int srio_port, int srcid_index, int destid, } else { -#if CVMX_SRIO_USE_FIFO_FOR_MAINT - int return_code; - uint32_t pkt = 0; - uint32_t sourceid; - uint64_t stop_cycle; - char rx_buffer[64]; - - /* Tell the user */ - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - 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); + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + { + int return_code; + uint32_t pkt = 0; + uint32_t sourceid; + uint64_t stop_cycle; + char rx_buffer[64]; - /* Read the proper source ID */ - if (srcid_index) - __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); - else - __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); + /* Tell the user */ + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + 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); - if (is16bit) - { - /* Use the 16bit source ID */ - sourceid &= 0xffff; - - /* MAINT Writes are 19 bytes */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16); - - pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ - pkt |= 1 << 28; /* tt [29:28] */ - pkt |= 0x8 << 24; /* ftype [27:24] */ - pkt |= destid << 8; /* destID [23:8] */ - pkt |= sourceid >> 8; /* sourceID [7:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= sourceid << 24; /* sourceID [31:24] */ - pkt |= 1 << 20; /* transaction [23:20] */ - pkt |= 8 << 16; /* wrsize [19:16] */ - pkt |= 0xc0 << 8; /* srcTID [15:8] */ - pkt |= hopcount; /* hopcount [7:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ - if ((offset & 4) == 0) - pkt |= 0xff & (data >> 24); /* data [7:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - if (offset & 4) - { - pkt = 0xff & (data >> 24); - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = data << 8; - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - } + /* Read the proper source ID */ + if (srcid_index) + __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); else + __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); + + if (is16bit) { - pkt = data << 8; - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); - } - } - else - { - /* Use the 8bit source ID */ - sourceid = (sourceid >> 16) & 0xff; - - /* MAINT Writes are 17 bytes */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16); - - pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ - pkt |= 0 << 28; /* tt [29:28] */ - pkt |= 0x8 << 24; /* ftype [27:24] */ - pkt |= destid << 16; /* destID [23:16] */ - pkt |= sourceid << 8; /* sourceID [15:8] */ - pkt |= 1 << 4; /* transaction [7:4] */ - pkt |= 8 << 0; /* wrsize [3:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= 0xc0 << 24; /* srcTID [31:24] */ - pkt |= hopcount << 16; /* hopcount [23:16] */ - pkt |= offset >> 8; /* offset [15:0] */ - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = 0; - pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ - if (offset & 4) - { + /* Use the 16bit source ID */ + sourceid &= 0xffff; + + /* MAINT Writes are 19 bytes */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16); + + pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ + pkt |= 1 << 28; /* tt [29:28] */ + pkt |= 0x8 << 24; /* ftype [27:24] */ + pkt |= destid << 8; /* destID [23:8] */ + pkt |= sourceid >> 8; /* sourceID [7:0] */ __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = data >> 8; + pkt = 0; + pkt |= sourceid << 24; /* sourceID [31:24] */ + pkt |= 1 << 20; /* transaction [23:20] */ + pkt |= 8 << 16; /* wrsize [19:16] */ + pkt |= 0xc0 << 8; /* srcTID [15:8] */ + pkt |= hopcount; /* hopcount [7:0] */ __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = data << 24; + pkt = 0; + pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ + if ((offset & 4) == 0) + pkt |= 0xff & (data >> 24); /* data [7:0] */ __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + if (offset & 4) + { + pkt = 0xff & (data >> 24); + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = data << 8; + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + } + else + { + pkt = data << 8; + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); + } } else { - pkt |= data >> 8; /* data [23:0] */ + /* Use the 8bit source ID */ + sourceid = (sourceid >> 16) & 0xff; + + /* MAINT Writes are 17 bytes */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16); + + pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ + pkt |= 0 << 28; /* tt [29:28] */ + pkt |= 0x8 << 24; /* ftype [27:24] */ + pkt |= destid << 16; /* destID [23:16] */ + pkt |= sourceid << 8; /* sourceID [15:8] */ + pkt |= 1 << 4; /* transaction [7:4] */ + pkt |= 8 << 0; /* wrsize [3:0] */ __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - pkt = data << 24; /* data [31:24] */ + pkt = 0; + pkt |= 0xc0 << 24; /* srcTID [31:24] */ + pkt |= hopcount << 16; /* hopcount [23:16] */ + pkt |= offset >> 8; /* offset [15:0] */ __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); - __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); + pkt = 0; + pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ + if (offset & 4) + { + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = data >> 8; + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = data << 24; + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + } + else + { + pkt |= data >> 8; /* data [23:0] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + pkt = data << 24; /* data [31:24] */ + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); + __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); + } } - } - stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); - do - { - return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); - if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) + stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); + do { - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("timeout\n"); + return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); + if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) + { + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + cvmx_dprintf("timeout\n"); + return_code = -1; + } + } while (return_code == 0); + + if (return_code == ((is16bit) ? 15 : 11)) + return_code = 0; + else + { + cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port); return_code = -1; } - } while (return_code == 0); - if (return_code == ((is16bit) ? 15 : 11)) - return_code = 0; + return return_code; + } else { - cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port); - return_code = -1; - } +#if !defined(CVMX_BUILD_FOR_LINUX_HOST) + uint64_t physical = cvmx_srio_physical_map(srio_port, + CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, + CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, + srcid_index, destid, is16bit, offset + (hopcount<<24), 4); + if (!physical) + return -1; - return return_code; -#elif !defined(CVMX_BUILD_FOR_LINUX_HOST) - uint64_t physical = cvmx_srio_physical_map(srio_port, - CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, - CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, - srcid_index, destid, is16bit, offset + (hopcount<<24), 4); - if (!physical) - return -1; - - if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) - cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, offset, data); + if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) + 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); - /* Finally do the maintenance write to complete the config request */ - cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data); - return cvmx_srio_physical_unmap(physical, 4); + /* Finally do the maintenance write to complete the config request */ + cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data); + return cvmx_srio_physical_unmap(physical, 4); #else - return -1; + return -1; #endif + } } } @@ -938,7 +1241,9 @@ int cvmx_srio_send_doorbell(int srio_port, int srcid_index, int destid, int is16 cvmx_write_csr(CVMX_SRIOX_TX_BELL(srio_port), tx_bell.u64); return 0; } - +#ifdef CVMX_BUILD_FOR_LINUX_KERNEL +EXPORT_SYMBOL(cvmx_srio_send_doorbell); +#endif /** * Get the status of the last doorbell sent. If the dooorbell @@ -974,7 +1279,9 @@ cvmx_srio_doorbell_status_t cvmx_srio_send_doorbell_status(int srio_port) if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) cvmx_dprintf("SRIO%d: Send doorbell failed\n", srio_port); tx_bell_info.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL_INFO(srio_port)); - if (tx_bell_info.s.timeout || tx_bell_info.s.error) + if (tx_bell_info.s.timeout) + return CVMX_SRIO_DOORBELL_TMOUT; + if (tx_bell_info.s.error) return CVMX_SRIO_DOORBELL_ERROR; if (tx_bell_info.s.retry) return CVMX_SRIO_DOORBELL_RETRY; @@ -1141,7 +1448,7 @@ uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op, /* Build the needed SubID config */ needed_subid.u64 = 0; needed_subid.s.port = srio_port; - needed_subid.s.nmerge = 1; + needed_subid.s.nmerge = 0; /* FIXME: We might want to use the device ID swapping modes so the device ID is part of the lower address bits. This would allow many more @@ -1149,14 +1456,14 @@ uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op, to fit in bits [17:0] or bits[25:0] for 8 bits of device ID */ if (base < (1ull<<34)) { - needed_subid.s.ba = destid; + needed_subid.cn63xx.ba = destid; needed_s2m_type.s.iaow_sel = 0; } else if (base < (1ull<<42)) { - needed_subid.s.ba = (base>>34) & 0xff; - needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (42-34); - needed_subid.s.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34); + needed_subid.cn63xx.ba = (base>>34) & 0xff; + needed_subid.cn63xx.ba |= ((uint64_t)destid & 0xff) << (42-34); + needed_subid.cn63xx.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34); needed_s2m_type.s.iaow_sel = 1; } else @@ -1171,8 +1478,8 @@ uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op, cvmx_dprintf("SRIO%d: Attempt to map address 0x%llx using 66bit addressing\n", srio_port, (ULL)base); return 0; } - needed_subid.s.ba = (base>>34) & 0xffff; - needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (51-34); + needed_subid.cn63xx.ba = (base>>34) & 0xffff; + needed_subid.cn63xx.ba |= ((uint64_t)destid & 0xff) << (51-34); needed_s2m_type.s.iaow_sel = 2; } @@ -1184,8 +1491,8 @@ uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op, /* Attach the SubID to the S2M_TYPE index */ needed_subid.s.rtype = s2m_index & 3; needed_subid.s.wtype = s2m_index & 3; - needed_subid.s.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34); - needed_subid.s.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34); + needed_subid.cn63xx.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34); + needed_subid.cn63xx.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34); /* Allocate a SubID for use */ subdid = __cvmx_srio_alloc_subid(needed_subid); @@ -1230,10 +1537,84 @@ int cvmx_srio_physical_unmap(uint64_t physical_address, uint64_t size) Type[1] is mapped to the No Snoop Type[2] is mapped directly to bit 50 of the SLI address Type[3] is mapped directly to bit 59 of the SLI address */ - read_s2m_type = ((subid.s.ba>>(50-34))&1<<2) | ((subid.s.ba>>(59-34))&1<<3); + read_s2m_type = ((subid.cn63xx.ba>>(50-34))&1<<2) | ((subid.cn63xx.ba>>(59-34))&1<<3); read_s2m_type |= subid.s.rtype; __cvmx_srio_free_subid(mem_index); __cvmx_srio_free_s2m(subid.s.port, read_s2m_type); return 0; } + +#ifdef CVMX_ENABLE_PKO_FUNCTIONS +/** + * fill out outbound message descriptor + * + * @param port pip/ipd port number + * @param buf_ptr pointer to a buffer pointer. the buffer pointer points + * to a chain of buffers that hold an outbound srio packet. + * the packet can take the format of (1) a pip/ipd inbound + * message or (2) an application-generated outbound message + * @param desc_ptr pointer to an outbound message descriptor. should be null + * if *buf_ptr is in the format (1) + * + * @return 0 on success; negative of failure. + */ +int cvmx_srio_omsg_desc (uint64_t port, cvmx_buf_ptr_t *buf_ptr, + cvmx_srio_tx_message_header_t *desc_ptr) +{ + int ret_val = -1; + int intf_num; + cvmx_helper_interface_mode_t imode; + + uint64_t *desc_addr, *hdr_addr; + cvmx_srio_rx_message_header_t rx_msg_hdr; + cvmx_srio_tx_message_header_t *tx_msg_hdr_ptr; + + if (buf_ptr == NULL) + return ret_val; + + /* check if port is an srio port */ + intf_num = cvmx_helper_get_interface_num (port); + imode = cvmx_helper_interface_get_mode (intf_num); + if (imode != CVMX_HELPER_INTERFACE_MODE_SRIO) + return ret_val; + + /* app-generated outbound message. descriptor space pre-allocated */ + if (desc_ptr != NULL) + { + desc_addr = (uint64_t *) cvmx_phys_to_ptr ((*buf_ptr).s.addr); + *desc_addr = *(uint64_t *) desc_ptr; + ret_val = 0; + return ret_val; + } + + /* pip/ipd inbound message. 16-byte srio message header is present */ + hdr_addr = (uint64_t *) cvmx_phys_to_ptr ((*buf_ptr).s.addr); + rx_msg_hdr.word0.u64 = *hdr_addr; + + /* adjust buffer pointer to get rid of srio message header word 0 */ + (*buf_ptr).s.addr += 8; + (*buf_ptr).s.size -= 8; /* last buffer or not */ + if ((*buf_ptr).s.addr >> 7 > ((*buf_ptr).s.addr - 8) >> 7) + (*buf_ptr).s.back++; + tx_msg_hdr_ptr = (cvmx_srio_tx_message_header_t *) + cvmx_phys_to_ptr ((*buf_ptr).s.addr); + + /* transfer values from rx to tx */ + tx_msg_hdr_ptr->s.prio = rx_msg_hdr.word0.s.prio; + tx_msg_hdr_ptr->s.tt = rx_msg_hdr.word0.s.tt; /* called id in hrm */ + tx_msg_hdr_ptr->s.sis = rx_msg_hdr.word0.s.dis; + tx_msg_hdr_ptr->s.ssize = rx_msg_hdr.word0.s.ssize; + tx_msg_hdr_ptr->s.did = rx_msg_hdr.word0.s.sid; + tx_msg_hdr_ptr->s.mbox = rx_msg_hdr.word0.s.mbox; + + /* other values we have to decide */ + tx_msg_hdr_ptr->s.xmbox = 0; /* multi-segement in general */ + tx_msg_hdr_ptr->s.letter = 0; /* fake like traffic gen */ + tx_msg_hdr_ptr->s.lns = 0; /* not use sriox_omsg_ctrly[] */ + tx_msg_hdr_ptr->s.intr = 1; /* get status */ + + ret_val = 0; + return ret_val; +} +#endif #endif |