1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
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
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
47 * <hr>$Revision: 41586 $<hr>
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>
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>
65 #include "cvmx-srio.h"
66 #include "cvmx-clock.h"
67 #include "cvmx-helper.h"
68 #ifndef CVMX_BUILD_FOR_LINUX_HOST
69 #include "cvmx-atomic.h"
70 #include "cvmx-error.h"
71 #include "cvmx-helper-errata.h"
75 #define CVMX_SRIO_USE_FIFO_FOR_MAINT 1
76 #define CVMX_SRIO_CONFIG_TIMEOUT 10000 /* 10ms */
77 #define CVMX_SRIO_DOORBELL_TIMEOUT 10000 /* 10ms */
78 #define CVMX_SRIO_CONFIG_PRIORITY 0
79 #define ULL unsigned long long
86 #if __BYTE_ORDER == __BIG_ENDIAN
87 uint64_t upper : 2; /* Normally 2 for XKPHYS */
88 uint64_t reserved_49_61 : 13; /* Must be zero */
89 uint64_t io : 1; /* 1 for IO space access */
90 uint64_t did : 5; /* DID = 3 */
91 uint64_t subdid : 3; /* SubDID = 3-6 */
92 uint64_t reserved_36_39 : 4; /* Must be zero */
93 uint64_t se : 2; /* SubDID extender */
94 uint64_t reserved_32_33 : 2; /* Must be zero */
95 uint64_t hopcount : 8; /* Hopcount */
96 uint64_t address : 24; /* Mem address */
98 uint64_t address : 24;
99 uint64_t hopcount : 8;
100 uint64_t reserved_32_33 : 2;
102 uint64_t reserved_36_39 : 4;
106 uint64_t reserved_49_61 : 13;
112 #if __BYTE_ORDER == __BIG_ENDIAN
113 uint64_t upper : 2; /* Normally 2 for XKPHYS */
114 uint64_t reserved_49_61 : 13; /* Must be zero */
115 uint64_t io : 1; /* 1 for IO space access */
116 uint64_t did : 5; /* DID = 3 */
117 uint64_t subdid : 3; /* SubDID = 3-6 */
118 uint64_t reserved_36_39 : 4; /* Must be zero */
119 uint64_t se : 2; /* SubDID extender */
120 uint64_t address : 34; /* Mem address */
122 uint64_t address : 34;
124 uint64_t reserved_36_39 : 4;
128 uint64_t reserved_49_61 : 13;
132 } cvmx_sli_address_t;
136 cvmx_srio_initialize_flags_t flags;
137 int32_t subidx_ref_count[16]; /* Reference count for SLI_MEM_ACCESS_SUBID[12-27]. Index=X-12 */
138 int32_t s2m_ref_count[16]; /* Reference count for SRIOX_S2M_TYPE[0-15]. */
139 } __cvmx_srio_state_t;
141 static CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[2];
144 #ifndef CVMX_BUILD_FOR_LINUX_HOST
147 * Allocate a SRIOX_S2M_TYPEX register for mapping a remote SRIO
148 * device's address range into Octeons SLI address space. Reference
149 * counting is used to allow sharing of duplicate setups. The current
150 * implementation treats reads and writes as paired, but this could be
151 * changed if we have trouble running out of indexes.
153 * @param srio_port SRIO port device is on
154 * @param s2m SRIOX_S2M_TYPEX setup required
156 * @return Index of CSR, or negative on failure
158 static int __cvmx_srio_alloc_s2m(int srio_port, cvmx_sriox_s2m_typex_t s2m)
161 /* Search through the S2M_TYPE registers looking for an unsed one or one
162 setup the way we need it */
163 for (s2m_index=0; s2m_index<16; s2m_index++)
165 /* Increment ref count by 2 since we count read and write
166 independently. We might need a more complicated search in the
168 int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], 2);
171 /* Unused location. Write our value */
172 cvmx_write_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port), s2m.u64);
177 /* In use, see if we can use it */
178 if (cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)) == s2m.u64)
181 cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], -2);
184 cvmx_dprintf("SRIO%d: Unable to find free SRIOX_S2M_TYPEX\n", srio_port);
191 * Free a handle allocated by __cvmx_srio_alloc_s2m
193 * @param srio_port SRIO port
194 * @param index Index to free
196 static void __cvmx_srio_free_s2m(int srio_port, int index)
198 /* Read to force pending transactions to complete */
199 cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(index, srio_port));
200 cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[index], -2);
206 * Allocate a SLI SubID to map a region of memory. Reference
207 * counting is used to allow sharing of duplicate setups.
209 * @param subid SLI_MEM_ACCESS_SUBIDX we need an index for
211 * @return Index of CSR, or negative on failure
213 static int __cvmx_srio_alloc_subid(cvmx_sli_mem_access_subidx_t subid)
216 /* Search through the mem access subid registers looking for an unsed one
217 or one setup the way we need it. PCIe uses the low indexes, so search
219 for (mem_index=27; mem_index>=12; mem_index--)
221 int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], 1);
224 /* Unused location. Write our value */
225 cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index), subid.u64);
230 /* In use, see if we can use it */
231 if (cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)) == subid.u64)
234 cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], -1);
237 cvmx_dprintf("SRIO: Unable to find free SLI_MEM_ACCESS_SUBIDX\n");
244 * Free a handle allocated by __cvmx_srio_alloc_subid
246 * @param index Index to free
248 static void __cvmx_srio_free_subid(int index)
250 /* Read to force pending transactions to complete */
251 cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(index));
252 cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[index-12], -1);
259 * Read 32bits from a local port
261 * @param srio_port SRIO port the device is on
262 * @param offset Offset in config space. This must be a multiple of 32 bits.
263 * @param result Result of the read. This will be unmodified on failure.
265 * @return Zero on success, negative on failure.
267 static int __cvmx_srio_local_read32(int srio_port, uint32_t offset, uint32_t *result)
269 cvmx_sriox_maint_op_t maint_op;
270 cvmx_sriox_maint_rd_data_t maint_rd_data;
272 maint_op.s.op = 0; /* Read */
273 maint_op.s.addr = offset;
275 /* Make sure SRIO isn't already busy */
276 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
278 cvmx_dprintf("SRIO%d: Pending bit stuck before config read\n", srio_port);
282 /* Issue the read to the hardware */
283 cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64);
285 /* Wait for the hardware to complete the operation */
286 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
288 cvmx_dprintf("SRIO%d: Config read timeout\n", srio_port);
292 /* Display and error and return if the operation failed to issue */
293 maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port));
296 cvmx_dprintf("SRIO%d: Config read addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset);
300 /* Wait for the read data to become valid */
301 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_RD_DATA(srio_port), cvmx_sriox_maint_rd_data_t, valid, ==, 1, CVMX_SRIO_CONFIG_TIMEOUT))
303 cvmx_dprintf("SRIO%d: Config read data timeout\n", srio_port);
307 /* Get the read data */
308 maint_rd_data.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_RD_DATA(srio_port));
309 *result = maint_rd_data.s.rd_data;
316 * Write 32bits to a local port
317 * @param srio_port SRIO port the device is on
318 * @param offset Offset in config space. This must be a multiple of 32 bits.
319 * @param data Data to write.
321 * @return Zero on success, negative on failure.
323 static int __cvmx_srio_local_write32(int srio_port, uint32_t offset, uint32_t data)
325 cvmx_sriox_maint_op_t maint_op;
327 maint_op.s.wr_data = data;
328 maint_op.s.op = 1; /* Write */
329 maint_op.s.addr = offset;
331 /* Make sure SRIO isn't already busy */
332 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
334 cvmx_dprintf("SRIO%d: Pending bit stuck before config write\n", srio_port);
338 /* Issue the write to the hardware */
339 cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64);
341 /* Wait for the hardware to complete the operation */
342 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT))
344 cvmx_dprintf("SRIO%d: Config write timeout\n", srio_port);
348 /* Display and error and return if the operation failed to issue */
349 maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port));
352 cvmx_dprintf("SRIO%d: Config write addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset);
360 * Initialize a SRIO port for use.
362 * @param srio_port SRIO port to initialize
363 * @param flags Optional flags
365 * @return Zero on success
367 int cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags)
369 cvmx_sriomaintx_port_lt_ctl_t port_lt_ctl;
370 cvmx_sriomaintx_port_rt_ctl_t port_rt_ctl;
371 cvmx_sriomaintx_port_0_ctl_t port_0_ctl;
372 cvmx_sriomaintx_core_enables_t core_enables;
373 cvmx_sriomaintx_port_gen_ctl_t port_gen_ctl;
374 cvmx_sriox_status_reg_t sriox_status_reg;
375 cvmx_mio_rst_ctlx_t mio_rst_ctl;
376 cvmx_sriox_imsg_vport_thr_t sriox_imsg_vport_thr;
377 cvmx_dpi_sli_prtx_cfg_t prt_cfg;
378 cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl;
380 sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port));
381 if (!sriox_status_reg.s.srio)
383 cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port);
387 __cvmx_srio_state[srio_port].flags = flags;
389 /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be
391 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0))
395 cvmx_ciu_qlm1_t ciu_qlm;
396 ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1);
397 ciu_qlm.s.txbypass = 1;
398 ciu_qlm.s.txdeemph = 5;
399 ciu_qlm.s.txmargin = 0x17;
400 cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64);
404 cvmx_ciu_qlm0_t ciu_qlm;
405 ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0);
406 ciu_qlm.s.txbypass = 1;
407 ciu_qlm.s.txdeemph = 5;
408 ciu_qlm.s.txmargin = 0x17;
409 cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64);
413 mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port));
414 cvmx_dprintf("SRIO%d: Port in %s mode\n", srio_port,
415 (mio_rst_ctl.s.prtmode) ? "host" : "endpoint");
417 /* Bring the port out of reset if necessary */
420 cvmx_ciu_soft_prst1_t prst;
421 prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
422 if (prst.s.soft_prst)
424 prst.s.soft_prst = 0;
425 cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64);
426 cvmx_wait_usec(10000); /* 10ms for new link to stabalize */
431 cvmx_ciu_soft_prst_t prst;
432 prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
433 if (prst.s.soft_prst)
435 prst.s.soft_prst = 0;
436 cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64);
437 cvmx_wait_usec(10000); /* 10ms for new link to stabalize */
441 /* Disable the link while we make changes */
442 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32))
444 port_0_ctl.s.disable = 1;
445 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32))
448 /* Errata SRIO-14485: Link speed is reported incorrectly in CN63XX
450 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
452 cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2;
453 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32))
455 if (port_0_ctl2.s.enb_500g)
458 port_0_ctl2.s.enb_625g = 1;
460 else if (port_0_ctl2.s.enb_312g)
463 port_0_ctl2.s.enb_500g = 1;
465 else if (port_0_ctl2.s.enb_250g)
468 port_0_ctl2.s.enb_312g = 1;
470 else if (port_0_ctl2.s.enb_125g)
473 port_0_ctl2.s.enb_250g = 1;
478 port_0_ctl2.s.enb_125g = 1;
480 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32))
484 /* Set the link layer timeout to 10us. The default is too high and causes
486 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), &port_lt_ctl.u32))
488 port_lt_ctl.s.timeout = 10000 / 200; /* 10us = 10000ns / 200ns */
489 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), port_lt_ctl.u32))
492 /* Set the logical layer timeout to 10ms. The default is too high and causes
494 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), &port_rt_ctl.u32))
496 port_rt_ctl.s.timeout = 10000000 / 200; /* 10ms = 10000000ns / 200ns */
497 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), port_rt_ctl.u32))
500 /* Allow memory and doorbells. Messaging is enabled later */
501 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &core_enables.u32))
503 core_enables.s.doorbell = 1;
504 core_enables.s.memory = 1;
505 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), core_enables.u32))
508 /* Allow us to master transactions */
509 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), &port_gen_ctl.u32))
511 port_gen_ctl.s.menable = 1;
512 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), port_gen_ctl.u32))
515 /* Set the MRRS and MPS for optimal SRIO performance */
516 prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port));
519 cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port), prt_cfg.u64);
521 sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port));
522 sli_s2m_portx_ctl.s.mrrs = 1;
523 cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port), sli_s2m_portx_ctl.u64);
525 /* Setup RX messaging thresholds */
526 sriox_imsg_vport_thr.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port));
527 sriox_imsg_vport_thr.s.max_tot = 48;
528 sriox_imsg_vport_thr.s.max_s1 = 24;
529 sriox_imsg_vport_thr.s.max_s0 = 24;
530 sriox_imsg_vport_thr.s.sp_vport = 1;
531 sriox_imsg_vport_thr.s.buf_thr = 4;
532 sriox_imsg_vport_thr.s.max_p1 = 12;
533 sriox_imsg_vport_thr.s.max_p0 = 12;
534 cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port), sriox_imsg_vport_thr.u64);
536 /* Errata SRIO-X: SRIO error behavior may not be optimal in CN63XX pass 1.x */
537 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
539 cvmx_sriox_tx_ctrl_t sriox_tx_ctrl;
540 sriox_tx_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_TX_CTRL(srio_port));
541 sriox_tx_ctrl.s.tag_th2 = 2;
542 sriox_tx_ctrl.s.tag_th1 = 3;
543 sriox_tx_ctrl.s.tag_th0 = 4;
544 cvmx_write_csr(CVMX_SRIOX_TX_CTRL(srio_port), sriox_tx_ctrl.u64);
547 /* Clear any pending interrupts */
548 cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port)));
550 /* Enable error reporting */
551 #if (!defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_LINUX_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL)
552 cvmx_error_enable_group(CVMX_ERROR_GROUP_SRIO, srio_port);
555 /* Finally enable the link */
556 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32))
558 port_0_ctl.s.o_enable = 1;
559 port_0_ctl.s.i_enable = 1;
560 port_0_ctl.s.disable = 0;
561 port_0_ctl.s.prt_lock = 0;
562 if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32))
570 * Read 32bits from a Device's config space
572 * @param srio_port SRIO port the device is on
574 * Which SRIO source ID to use. 0 = Primary, 1 = Secondary
575 * @param destid RapidIO device ID, or -1 for the local Octeon.
576 * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero
577 * if transactions should use 8bit device IDs.
578 * @param hopcount Number of hops to the remote device. Use 0 for the local Octeon.
579 * @param offset Offset in config space. This must be a multiple of 32 bits.
580 * @param result Result of the read. This will be unmodified on failure.
582 * @return Zero on success, negative on failure.
584 int cvmx_srio_config_read32(int srio_port, int srcid_index, int destid,
585 int is16bit, uint8_t hopcount, uint32_t offset,
590 int status = __cvmx_srio_local_read32(srio_port, offset, result);
592 if ((status == 0) && (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG))
593 cvmx_dprintf("SRIO%d: Local read [0x%06x] <= 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)*result);
599 #if CVMX_SRIO_USE_FIFO_FOR_MAINT
607 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
608 cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset);
610 /* Read the proper source ID */
612 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid);
614 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid);
618 /* Use the 16bit source ID */
621 /* MAINT Reads are 11 bytes */
622 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16);
624 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
625 pkt |= 1 << 28; /* tt [29:28] */
626 pkt |= 0x8 << 24; /* ftype [27:24] */
627 pkt |= destid << 8; /* destID [23:8] */
628 pkt |= sourceid >> 8; /* sourceID [7:0] */
629 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
631 pkt |= sourceid << 24; /* sourceID [31:24] */
632 pkt |= 0 << 20; /* transaction [23:20] */
633 pkt |= 8 << 16; /* rdsize [19:16] */
634 pkt |= 0xc0 << 8; /* srcTID [15:8] */
635 pkt |= hopcount; /* hopcount [7:0] */
636 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
638 pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */
639 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
643 /* Use the 8bit source ID */
644 sourceid = (sourceid >> 16) & 0xff;
646 /* MAINT Reads are 9 bytes */
647 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16);
649 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
650 pkt |= 0 << 28; /* tt [29:28] */
651 pkt |= 0x8 << 24; /* ftype [27:24] */
652 pkt |= destid << 16; /* destID [23:16] */
653 pkt |= sourceid << 8; /* sourceID [15:8] */
654 pkt |= 0 << 4; /* transaction [7:4] */
655 pkt |= 8 << 0; /* rdsize [3:0] */
656 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
658 pkt |= 0xc0 << 24; /* srcTID [31:24] */
659 pkt |= hopcount << 16; /* hopcount [23:16] */
660 pkt |= offset >> 8; /* offset [15:0] */
661 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
663 pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */
664 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
667 stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
670 return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer));
671 if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle))
673 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
674 cvmx_dprintf("timeout\n");
677 } while (return_code == 0);
679 if (return_code == ((is16bit) ? 23 : 19))
684 *result = *(uint32_t*)(rx_buffer + 15);
686 *result = *(uint32_t*)(rx_buffer + 11);
691 *result = *(uint32_t*)(rx_buffer + 13);
693 *result = *(uint32_t*)(rx_buffer + 9);
695 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
696 cvmx_dprintf("0x%08x\n", (unsigned int)*result);
701 *result = 0xffffffff;
706 #elif !defined(CVMX_BUILD_FOR_LINUX_HOST)
708 physical = cvmx_srio_physical_map(srio_port,
709 CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
710 CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
711 srcid_index, destid, is16bit, offset + (hopcount<<24), 4);
715 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
716 cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, offset);
718 /* Finally do the maintenance read to complete the config request */
719 *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical));
720 cvmx_srio_physical_unmap(physical, 4);
722 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
723 cvmx_dprintf("0x%08x\n", *result);
734 * Write 32bits to a Device's config space
736 * @param srio_port SRIO port the device is on
738 * Which SRIO source ID to use. 0 = Primary, 1 = Secondary
739 * @param destid RapidIO device ID, or -1 for the local Octeon.
740 * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero
741 * if transactions should use 8bit device IDs.
742 * @param hopcount Number of hops to the remote device. Use 0 for the local Octeon.
743 * @param offset Offset in config space. This must be a multiple of 32 bits.
744 * @param data Data to write.
746 * @return Zero on success, negative on failure.
748 int cvmx_srio_config_write32(int srio_port, int srcid_index, int destid,
749 int is16bit, uint8_t hopcount, uint32_t offset,
754 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
755 cvmx_dprintf("SRIO%d: Local write[0x%06x] => 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)data);
757 return __cvmx_srio_local_write32(srio_port, offset, data);
761 #if CVMX_SRIO_USE_FIFO_FOR_MAINT
769 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
770 cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, (unsigned int)offset, (unsigned int)data);
772 /* Read the proper source ID */
774 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid);
776 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid);
780 /* Use the 16bit source ID */
783 /* MAINT Writes are 19 bytes */
784 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16);
786 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
787 pkt |= 1 << 28; /* tt [29:28] */
788 pkt |= 0x8 << 24; /* ftype [27:24] */
789 pkt |= destid << 8; /* destID [23:8] */
790 pkt |= sourceid >> 8; /* sourceID [7:0] */
791 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
793 pkt |= sourceid << 24; /* sourceID [31:24] */
794 pkt |= 1 << 20; /* transaction [23:20] */
795 pkt |= 8 << 16; /* wrsize [19:16] */
796 pkt |= 0xc0 << 8; /* srcTID [15:8] */
797 pkt |= hopcount; /* hopcount [7:0] */
798 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
800 pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */
801 if ((offset & 4) == 0)
802 pkt |= 0xff & (data >> 24); /* data [7:0] */
803 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
806 pkt = 0xff & (data >> 24);
807 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
809 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
814 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
815 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0);
820 /* Use the 8bit source ID */
821 sourceid = (sourceid >> 16) & 0xff;
823 /* MAINT Writes are 17 bytes */
824 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16);
826 pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */
827 pkt |= 0 << 28; /* tt [29:28] */
828 pkt |= 0x8 << 24; /* ftype [27:24] */
829 pkt |= destid << 16; /* destID [23:16] */
830 pkt |= sourceid << 8; /* sourceID [15:8] */
831 pkt |= 1 << 4; /* transaction [7:4] */
832 pkt |= 8 << 0; /* wrsize [3:0] */
833 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
835 pkt |= 0xc0 << 24; /* srcTID [31:24] */
836 pkt |= hopcount << 16; /* hopcount [23:16] */
837 pkt |= offset >> 8; /* offset [15:0] */
838 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
840 pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */
843 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
845 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
847 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
851 pkt |= data >> 8; /* data [23:0] */
852 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
853 pkt = data << 24; /* data [31:24] */
854 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt);
855 __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0);
859 stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE);
862 return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer));
863 if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle))
865 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
866 cvmx_dprintf("timeout\n");
869 } while (return_code == 0);
871 if (return_code == ((is16bit) ? 15 : 11))
875 cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port);
880 #elif !defined(CVMX_BUILD_FOR_LINUX_HOST)
881 uint64_t physical = cvmx_srio_physical_map(srio_port,
882 CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
883 CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY,
884 srcid_index, destid, is16bit, offset + (hopcount<<24), 4);
888 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
889 cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, offset, data);
891 /* Finally do the maintenance write to complete the config request */
892 cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data);
893 return cvmx_srio_physical_unmap(physical, 4);
902 * Send a RapidIO doorbell to a remote device
904 * @param srio_port SRIO port the device is on
906 * Which SRIO source ID to use. 0 = Primary, 1 = Secondary
907 * @param destid RapidIO device ID.
908 * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero
909 * if transactions should use 8bit device IDs.
910 * @param priority Doorbell priority (0-3)
911 * @param data Data for doorbell.
913 * @return Zero on success, negative on failure.
915 int cvmx_srio_send_doorbell(int srio_port, int srcid_index, int destid, int is16bit, int priority, uint16_t data)
917 cvmx_sriox_tx_bell_t tx_bell;
919 tx_bell.s.data = data;
920 tx_bell.s.dest_id = destid;
921 tx_bell.s.src_id = srcid_index;
922 tx_bell.s.id16 = !!is16bit;
923 tx_bell.s.priority = priority;
925 /* Make sure the previous doorbell has completed */
926 if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_TX_BELL(srio_port), cvmx_sriox_tx_bell_t, pending, ==, 0, CVMX_SRIO_DOORBELL_TIMEOUT))
928 cvmx_dprintf("SRIO%d: Pending bit stuck before doorbell\n", srio_port);
932 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
933 cvmx_dprintf("SRIO%d: Send doorbell destid=0x%x, priority=%d, data=0x%x\n", srio_port, destid, priority, 0xffff & data);
935 /* Send the doorbell. We don't wait for it to complete. The next doorbell
936 may delay on the pending bit, but this gives the caller the ability to
937 do other stuff while the doorbell processes */
938 cvmx_write_csr(CVMX_SRIOX_TX_BELL(srio_port), tx_bell.u64);
944 * Get the status of the last doorbell sent. If the dooorbell
945 * hardware is done, then the status is cleared to get ready for
946 * the next doorbell (or retry).
948 * @param srio_port SRIO port to check doorbell on
950 * @return Doorbell status
952 cvmx_srio_doorbell_status_t cvmx_srio_send_doorbell_status(int srio_port)
954 cvmx_sriox_tx_bell_t tx_bell;
955 cvmx_sriox_tx_bell_info_t tx_bell_info;
956 cvmx_sriox_int_reg_t int_reg;
957 cvmx_sriox_int_reg_t int_reg_clear;
959 /* Return busy if the doorbell is still processing */
960 tx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL(srio_port));
961 if (tx_bell.s.pending)
962 return CVMX_SRIO_DOORBELL_BUSY;
964 /* Read and clear the TX doorbell interrupts */
965 int_reg.u64 = cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port));
966 int_reg_clear.u64 = 0;
967 int_reg_clear.s.bell_err = int_reg.s.bell_err;
968 int_reg_clear.s.txbell = int_reg.s.txbell;
969 cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), int_reg_clear.u64);
971 /* Check for errors */
972 if (int_reg.s.bell_err)
974 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
975 cvmx_dprintf("SRIO%d: Send doorbell failed\n", srio_port);
976 tx_bell_info.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL_INFO(srio_port));
977 if (tx_bell_info.s.timeout || tx_bell_info.s.error)
978 return CVMX_SRIO_DOORBELL_ERROR;
979 if (tx_bell_info.s.retry)
980 return CVMX_SRIO_DOORBELL_RETRY;
983 /* Check if we're done */
984 if (int_reg.s.txbell)
985 return CVMX_SRIO_DOORBELL_DONE;
987 /* No doorbell found */
988 return CVMX_SRIO_DOORBELL_NONE;
993 * Read a received doorbell and report data about it.
995 * @param srio_port SRIO port to check for the received doorbell
996 * @param destid_index
997 * Which Octeon destination ID was the doorbell for
998 * @param sequence_num
999 * Sequence number of doorbell (32bits)
1000 * @param srcid RapidIO source ID of the doorbell sender
1001 * @param priority Priority of the doorbell (0-3)
1002 * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero
1003 * if transactions should use 8bit device IDs.
1004 * @param data Data in the doorbell (16 bits)
1006 * @return Doorbell status. Either DONE, NONE, or ERROR.
1008 cvmx_srio_doorbell_status_t cvmx_srio_receive_doorbell(int srio_port,
1009 int *destid_index, uint32_t *sequence_num, int *srcid, int *priority,
1010 int *is16bit, uint16_t *data)
1012 cvmx_sriox_rx_bell_seq_t rx_bell_seq;
1013 cvmx_sriox_rx_bell_t rx_bell;
1015 /* Check if there are any pending doorbells */
1016 rx_bell_seq.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL_SEQ(srio_port));
1017 if (!rx_bell_seq.s.count)
1018 return CVMX_SRIO_DOORBELL_NONE;
1020 /* Read the doorbell and write our return parameters */
1021 rx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL(srio_port));
1022 *sequence_num = rx_bell_seq.s.seq;
1023 *srcid = rx_bell.s.src_id;
1024 *priority = rx_bell.s.priority;
1025 *is16bit = rx_bell.s.id16;
1026 *data = rx_bell.s.data;
1027 *destid_index = rx_bell.s.dest_id;
1029 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1030 cvmx_dprintf("SRIO%d: Receive doorbell sequence=0x%x, srcid=0x%x, priority=%d, data=0x%x\n",
1031 srio_port, rx_bell_seq.s.seq, rx_bell.s.src_id, rx_bell.s.priority, rx_bell.s.data);
1033 return CVMX_SRIO_DOORBELL_DONE;
1038 * Receive a packet from the Soft Packet FIFO (SPF).
1040 * @param srio_port SRIO port to read the packet from.
1041 * @param buffer Buffer to receive the packet.
1042 * @param buffer_length
1043 * Length of the buffer in bytes.
1045 * @return Returns the length of the packet read. Negative on failure.
1046 * Zero if no packets are available.
1048 int cvmx_srio_receive_spf(int srio_port, void *buffer, int buffer_length)
1050 uint32_t *ptr = (uint32_t *)buffer;
1051 cvmx_sriomaintx_ir_sp_rx_stat_t sriomaintx_ir_sp_rx_stat;
1053 /* Read the SFP status */
1054 if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_STAT(srio_port), &sriomaintx_ir_sp_rx_stat.u32))
1057 /* Return zero if there isn't a packet available */
1058 if (sriomaintx_ir_sp_rx_stat.s.buffers < 1)
1061 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1062 cvmx_dprintf("SRIO%d: Soft packet FIFO received %d bytes", srio_port, sriomaintx_ir_sp_rx_stat.s.octets);
1064 /* Return error if the packet is larger than our buffer */
1065 if (sriomaintx_ir_sp_rx_stat.s.octets > buffer_length)
1068 /* Read out the packet four bytes at a time */
1069 buffer_length = sriomaintx_ir_sp_rx_stat.s.octets;
1070 while (buffer_length > 0)
1072 __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_DATA(srio_port), ptr);
1073 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1074 cvmx_dprintf(" %08x", (unsigned int)*ptr);
1079 if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)
1082 /* Return the number of bytes in the buffer */
1083 return sriomaintx_ir_sp_rx_stat.s.octets;
1086 #ifndef CVMX_BUILD_FOR_LINUX_HOST
1088 * Map a remote device's memory region into Octeon's physical
1089 * address area. The caller can then map this into a core using
1090 * the TLB or XKPHYS.
1092 * @param srio_port SRIO port to map the device on
1093 * @param write_op Type of operation to perform on a write to the device.
1094 * Normally should be CVMX_SRIO_WRITE_MODE_AUTO.
1095 * @param write_priority
1096 * SRIO priority of writes (0-3)
1097 * @param read_op Type of operation to perform on reads to the device.
1098 * Normally should be CVMX_SRIO_READ_MODE_NORMAL.
1099 * @param read_priority
1100 * SRIO priority of reads (0-3)
1101 * @param srcid_index
1102 * Which SRIO source ID to use. 0 = Primary, 1 = Secondary
1103 * @param destid RapidIO device ID.
1104 * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero
1105 * if transactions should use 8bit device IDs.
1106 * @param base Device base address to start the mapping
1107 * @param size Size of the mapping in bytes
1109 * @return Octeon 64bit physical address that accesses the remote device,
1110 * or zero on failure.
1112 uint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op,
1113 int write_priority, cvmx_srio_read_mode_t read_op, int read_priority,
1114 int srcid_index, int destid, int is16bit, uint64_t base, uint64_t size)
1116 cvmx_sriox_s2m_typex_t needed_s2m_type;
1117 cvmx_sli_mem_access_subidx_t needed_subid;
1120 cvmx_sli_address_t sli_address;
1122 /* We currently don't support mapping regions that span a 34 bit boundary.
1123 Keeping track of multiple regions to span 34 bits is hard and not
1124 likely to be needed */
1125 if (((base+size-1)>>34) != (base>>34))
1127 cvmx_dprintf("SRIO%d: Failed to map range 0x%llx-0x%llx spanning a 34bit boundary\n",
1128 srio_port, (ULL)base, (ULL)base+size-1);
1132 /* Build the S2M_TYPE we are going to need */
1133 needed_s2m_type.u64 = 0;
1134 needed_s2m_type.s.wr_op = write_op;
1135 needed_s2m_type.s.rd_op = read_op;
1136 needed_s2m_type.s.wr_prior = write_priority;
1137 needed_s2m_type.s.rd_prior = read_priority;
1138 needed_s2m_type.s.src_id = srcid_index;
1139 needed_s2m_type.s.id16 = !!is16bit;
1141 /* Build the needed SubID config */
1142 needed_subid.u64 = 0;
1143 needed_subid.s.port = srio_port;
1144 needed_subid.s.nmerge = 1;
1146 /* FIXME: We might want to use the device ID swapping modes so the device
1147 ID is part of the lower address bits. This would allow many more
1148 devices to share S2M_TYPE indexes. This would require "base+size-1"
1149 to fit in bits [17:0] or bits[25:0] for 8 bits of device ID */
1150 if (base < (1ull<<34))
1152 needed_subid.s.ba = destid;
1153 needed_s2m_type.s.iaow_sel = 0;
1155 else if (base < (1ull<<42))
1157 needed_subid.s.ba = (base>>34) & 0xff;
1158 needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (42-34);
1159 needed_subid.s.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34);
1160 needed_s2m_type.s.iaow_sel = 1;
1166 cvmx_dprintf("SRIO%d: Attempt to map 16bit device ID 0x%x using 66bit addressing\n", srio_port, destid);
1171 cvmx_dprintf("SRIO%d: Attempt to map address 0x%llx using 66bit addressing\n", srio_port, (ULL)base);
1174 needed_subid.s.ba = (base>>34) & 0xffff;
1175 needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (51-34);
1176 needed_s2m_type.s.iaow_sel = 2;
1179 /* Find a S2M_TYPE index to use. If this fails return 0 */
1180 s2m_index = __cvmx_srio_alloc_s2m(srio_port, needed_s2m_type);
1181 if (s2m_index == -1)
1184 /* Attach the SubID to the S2M_TYPE index */
1185 needed_subid.s.rtype = s2m_index & 3;
1186 needed_subid.s.wtype = s2m_index & 3;
1187 needed_subid.s.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34);
1188 needed_subid.s.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34);
1190 /* Allocate a SubID for use */
1191 subdid = __cvmx_srio_alloc_subid(needed_subid);
1194 /* Free the s2m_index as we aren't using it */
1195 __cvmx_srio_free_s2m(srio_port, s2m_index);
1199 /* Build the final core physical address */
1200 sli_address.u64 = 0;
1201 sli_address.mem.io = 1;
1202 sli_address.mem.did = 3;
1203 sli_address.mem.subdid = subdid>>2;
1204 sli_address.mem.se = subdid & 3;
1205 sli_address.mem.address = base; /* Bits[33:0] of full address */
1206 return sli_address.u64;
1211 * Unmap a physical address window created by cvmx_srio_phys_map().
1213 * @param physical_address
1214 * Physical address returned by cvmx_srio_phys_map().
1215 * @param size Size used on original call.
1217 * @return Zero on success, negative on failure.
1219 int cvmx_srio_physical_unmap(uint64_t physical_address, uint64_t size)
1221 cvmx_sli_mem_access_subidx_t subid;
1222 int subdid = (physical_address >> 40) & 7;
1223 int extender = (physical_address >> 34) & 3;
1224 int mem_index = subdid * 4 + extender;
1227 /* Get the subid setup so we can figure out where this mapping was for */
1228 subid.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index));
1229 /* Type[0] is mapped to the Relaxed Ordering
1230 Type[1] is mapped to the No Snoop
1231 Type[2] is mapped directly to bit 50 of the SLI address
1232 Type[3] is mapped directly to bit 59 of the SLI address */
1233 read_s2m_type = ((subid.s.ba>>(50-34))&1<<2) | ((subid.s.ba>>(59-34))&1<<3);
1234 read_s2m_type |= subid.s.rtype;
1235 __cvmx_srio_free_subid(mem_index);
1236 __cvmx_srio_free_s2m(subid.s.port, read_s2m_type);