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