Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cvmx-helper.c
Go to the documentation of this file.
1 /***********************license start***************
2  * Author: Cavium Networks
3  *
4  * Contact: [email protected]
5  * This file is part of the OCTEON SDK
6  *
7  * Copyright (c) 2003-2008 Cavium Networks
8  *
9  * This file is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License, Version 2, as
11  * published by the Free Software Foundation.
12  *
13  * This file is distributed in the hope that it will be useful, but
14  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16  * NONINFRINGEMENT. See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this file; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  * or visit http://www.gnu.org/licenses/.
23  *
24  * This file may also be available under a different license from Cavium.
25  * Contact Cavium Networks for more information
26  ***********************license end**************************************/
27 
28 /*
29  *
30  * Helper functions for common, but complicated tasks.
31  *
32  */
33 #include <asm/octeon/octeon.h>
34 
35 #include <asm/octeon/cvmx-config.h>
36 
37 #include <asm/octeon/cvmx-fpa.h>
38 #include <asm/octeon/cvmx-pip.h>
39 #include <asm/octeon/cvmx-pko.h>
40 #include <asm/octeon/cvmx-ipd.h>
41 #include <asm/octeon/cvmx-spi.h>
42 #include <asm/octeon/cvmx-helper.h>
44 
48 
57  uint64_t priorities[16]);
58 
68 
69 /* Port count per interface */
70 static int interface_port_count[4] = { 0, 0, 0, 0 };
71 
72 /* Port last configured link info index by IPD/PKO port */
74  port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
75 
85 {
87  return 4;
88  else
89  return 3;
90 }
91 
102 {
103  return interface_port_count[interface];
104 }
105 
117 {
118  union cvmx_gmxx_inf_mode mode;
119  if (interface == 2)
121 
122  if (interface == 3) {
126  else
128  }
129 
130  if (interface == 0
132  && cvmx_sysinfo_get()->board_rev_major == 1) {
133  /*
134  * Lie about interface type of CN3005 board. This
135  * board has a switch on port 1 like the other
136  * evaluation boards, but it is connected over RGMII
137  * instead of GMII. Report GMII mode so that the
138  * speed is forced to 1 Gbit full duplex. Other than
139  * some initial configuration (which does not use the
140  * output of this function) there is no difference in
141  * setup between GMII and RGMII modes.
142  */
144  }
145 
146  /* Interface 1 is always disabled on CN31XX and CN30XX */
147  if ((interface == 1)
152 
153  mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
154 
156  switch (mode.cn56xx.mode) {
157  case 0:
159  case 1:
161  case 2:
163  case 3:
165  default:
167  }
168  } else {
169  if (!mode.s.en)
171 
172  if (mode.s.type) {
176  else
178  } else
180  }
181 }
182 
194 static int __cvmx_helper_port_setup_ipd(int ipd_port)
195 {
196  union cvmx_pip_prt_cfgx port_config;
197  union cvmx_pip_prt_tagx tag_config;
198 
199  port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
200  tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
201 
202  /* Have each port go to a different POW queue */
203  port_config.s.qos = ipd_port & 0x7;
204 
205  /* Process the headers and place the IP header in the work queue */
206  port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
207 
208  tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
209  tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
210  tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
211  tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
212  tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
213  tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
214  tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
215  tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
216  tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
217  tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
218  tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
219  tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
220  tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
221  tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
222  tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
223  tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
224  /* Put all packets in group 0. Other groups can be used by the app */
225  tag_config.s.grp = 0;
226 
227  cvmx_pip_config_port(ipd_port, port_config, tag_config);
228 
229  /* Give the user a chance to override our setting for each port */
232 
233  return 0;
234 }
235 
246 {
247  switch (cvmx_helper_interface_get_mode(interface)) {
248  /* These types don't support ports to IPD/PKO */
251  interface_port_count[interface] = 0;
252  break;
253  /* XAUI is a single high speed port */
255  interface_port_count[interface] =
256  __cvmx_helper_xaui_enumerate(interface);
257  break;
258  /*
259  * RGMII/GMII/MII are all treated about the same. Most
260  * functions refer to these ports as RGMII.
261  */
264  interface_port_count[interface] =
266  break;
267  /*
268  * SPI4 can have 1-16 ports depending on the device at
269  * the other end.
270  */
272  interface_port_count[interface] =
273  __cvmx_helper_spi_enumerate(interface);
274  break;
275  /*
276  * SGMII can have 1-4 ports depending on how many are
277  * hooked up.
278  */
281  interface_port_count[interface] =
283  break;
284  /* PCI target Network Packet Interface */
286  interface_port_count[interface] =
287  __cvmx_helper_npi_enumerate(interface);
288  break;
289  /*
290  * Special loopback only ports. These are not the same
291  * as other ports in loopback mode.
292  */
294  interface_port_count[interface] =
295  __cvmx_helper_loop_enumerate(interface);
296  break;
297  }
298 
299  interface_port_count[interface] =
301  interface_port_count
302  [interface]);
303 
304  /* Make sure all global variables propagate to other cores */
305  CVMX_SYNCWS;
306 
307  return 0;
308 }
309 
322 {
324  /* At this stage in the game we don't want packets to be moving yet.
325  The following probe calls should perform hardware setup
326  needed to determine port counts. Receive must still be disabled */
327  switch (cvmx_helper_interface_get_mode(interface)) {
328  /* These types don't support ports to IPD/PKO */
331  break;
332  /* XAUI is a single high speed port */
334  __cvmx_helper_xaui_probe(interface);
335  break;
336  /*
337  * RGMII/GMII/MII are all treated about the same. Most
338  * functions refer to these ports as RGMII.
339  */
342  __cvmx_helper_rgmii_probe(interface);
343  break;
344  /*
345  * SPI4 can have 1-16 ports depending on the device at
346  * the other end.
347  */
349  __cvmx_helper_spi_probe(interface);
350  break;
351  /*
352  * SGMII can have 1-4 ports depending on how many are
353  * hooked up.
354  */
357  __cvmx_helper_sgmii_probe(interface);
358  break;
359  /* PCI target Network Packet Interface */
361  __cvmx_helper_npi_probe(interface);
362  break;
363  /*
364  * Special loopback only ports. These are not the same
365  * as other ports in loopback mode.
366  */
368  __cvmx_helper_loop_probe(interface);
369  break;
370  }
371 
372  /* Make sure all global variables propagate to other cores */
373  CVMX_SYNCWS;
374 
375  return 0;
376 }
377 
388 static int __cvmx_helper_interface_setup_ipd(int interface)
389 {
390  int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
391  int num_ports = interface_port_count[interface];
392 
393  while (num_ports--) {
394  __cvmx_helper_port_setup_ipd(ipd_port);
395  ipd_port++;
396  }
397  return 0;
398 }
399 
406 static int __cvmx_helper_global_setup_ipd(void)
407 {
408  /* Setup the global packet input options */
409  cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
412  /* The +8 is to account for the next ptr */
413  (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
414  /* The +8 is to account for the next ptr */
419  return 0;
420 }
421 
431 static int __cvmx_helper_interface_setup_pko(int interface)
432 {
433  /*
434  * Each packet output queue has an associated priority. The
435  * higher the priority, the more often it can send a packet. A
436  * priority of 8 means it can send in all 8 rounds of
437  * contention. We're going to make each queue one less than
438  * the last. The vector of priorities has been extended to
439  * support CN5xxx CPUs, where up to 16 queues can be
440  * associated to a port. To keep backward compatibility we
441  * don't change the initial 8 priorities and replicate them in
442  * the second half. With per-core PKO queues (PKO lockless
443  * operation) all queues have the same priority.
444  */
445  uint64_t priorities[16] =
446  { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
447 
448  /*
449  * Setup the IPD/PIP and PKO for the ports discovered
450  * above. Here packet classification, tagging and output
451  * priorities are set.
452  */
453  int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
454  int num_ports = interface_port_count[interface];
455  while (num_ports--) {
456  /*
457  * Give the user a chance to override the per queue
458  * priorities.
459  */
461  cvmx_override_pko_queue_priority(ipd_port, priorities);
462 
463  cvmx_pko_config_port(ipd_port,
464  cvmx_pko_get_base_queue_per_core(ipd_port,
465  0),
466  cvmx_pko_get_num_queues(ipd_port),
467  priorities);
468  ipd_port++;
469  }
470  return 0;
471 }
472 
479 static int __cvmx_helper_global_setup_pko(void)
480 {
481  /*
482  * Disable tagwait FAU timeout. This needs to be done before
483  * anyone might start packet output using tags.
484  */
485  union cvmx_iob_fau_timeout fau_to;
486  fau_to.u64 = 0;
487  fau_to.s.tout_val = 0xfff;
488  fau_to.s.tout_enb = 0;
489  cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
490  return 0;
491 }
492 
498 static int __cvmx_helper_global_setup_backpressure(void)
499 {
500 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
501  /* Disable backpressure if configured to do so */
502  /* Disable backpressure (pause frame) generation */
503  int num_interfaces = cvmx_helper_get_number_of_interfaces();
504  int interface;
505  for (interface = 0; interface < num_interfaces; interface++) {
506  switch (cvmx_helper_interface_get_mode(interface)) {
512  break;
518  cvmx_gmx_set_backpressure_override(interface, 0xf);
519  break;
520  }
521  }
522 #endif
523 
524  return 0;
525 }
526 
538 static int __cvmx_helper_packet_hardware_enable(int interface)
539 {
540  int result = 0;
541  switch (cvmx_helper_interface_get_mode(interface)) {
542  /* These types don't support ports to IPD/PKO */
545  /* Nothing to do */
546  break;
547  /* XAUI is a single high speed port */
549  result = __cvmx_helper_xaui_enable(interface);
550  break;
551  /*
552  * RGMII/GMII/MII are all treated about the same. Most
553  * functions refer to these ports as RGMII
554  */
557  result = __cvmx_helper_rgmii_enable(interface);
558  break;
559  /*
560  * SPI4 can have 1-16 ports depending on the device at
561  * the other end
562  */
564  result = __cvmx_helper_spi_enable(interface);
565  break;
566  /*
567  * SGMII can have 1-4 ports depending on how many are
568  * hooked up
569  */
572  result = __cvmx_helper_sgmii_enable(interface);
573  break;
574  /* PCI target Network Packet Interface */
576  result = __cvmx_helper_npi_enable(interface);
577  break;
578  /*
579  * Special loopback only ports. These are not the same
580  * as other ports in loopback mode
581  */
583  result = __cvmx_helper_loop_enable(interface);
584  break;
585  }
586  result |= __cvmx_helper_board_hardware_enable(interface);
587  return result;
588 }
589 
597 {
598 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
599  (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
600 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
601  (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
602 #define FIX_IPD_OUTPORT 0
603  /* Ports 0-15 are interface 0, 16-31 are interface 1 */
604 #define INTERFACE(port) (port >> 4)
605 #define INDEX(port) (port & 0xf)
606  uint64_t *p64;
607  cvmx_pko_command_word0_t pko_command;
608  union cvmx_buf_ptr g_buffer, pkt_buffer;
609  cvmx_wqe_t *work;
610  int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
611  union cvmx_gmxx_prtx_cfg gmx_cfg;
612  int retry_cnt;
613  int retry_loop_cnt;
614  int i;
615  cvmx_helper_link_info_t link_info;
616 
617  /* Save values for restore at end */
618  uint64_t prtx_cfg =
619  cvmx_read_csr(CVMX_GMXX_PRTX_CFG
621  uint64_t tx_ptr_en =
623  uint64_t rx_ptr_en =
625  uint64_t rxx_jabber =
626  cvmx_read_csr(CVMX_GMXX_RXX_JABBER
628  uint64_t frame_max =
629  cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
631 
632  /* Configure port to gig FDX as required for loopback mode */
634 
635  /*
636  * Disable reception on all ports so if traffic is present it
637  * will not interfere.
638  */
639  cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
640 
641  cvmx_wait(100000000ull);
642 
643  for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
644  retry_cnt = 100000;
645  wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
646  pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
647  wqe_pcnt &= 0x7f;
648 
649  num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
650 
651  if (num_segs == 0)
652  goto fix_ipd_exit;
653 
654  num_segs += 1;
655 
656  size =
658  ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
660 
662  1 << INDEX(FIX_IPD_OUTPORT));
663  CVMX_SYNC;
664 
665  g_buffer.u64 = 0;
666  g_buffer.s.addr =
667  cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
668  if (g_buffer.s.addr == 0) {
669  cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
670  "buffer allocation failure.\n");
671  goto fix_ipd_exit;
672  }
673 
674  g_buffer.s.pool = CVMX_FPA_WQE_POOL;
675  g_buffer.s.size = num_segs;
676 
677  pkt_buffer.u64 = 0;
678  pkt_buffer.s.addr =
679  cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
680  if (pkt_buffer.s.addr == 0) {
681  cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
682  "buffer allocation failure.\n");
683  goto fix_ipd_exit;
684  }
685  pkt_buffer.s.i = 1;
686  pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
687  pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
688 
689  p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
690  p64[0] = 0xffffffffffff0000ull;
691  p64[1] = 0x08004510ull;
692  p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
693  p64[3] = 0x3a5fc0a81073c0a8ull;
694 
695  for (i = 0; i < num_segs; i++) {
696  if (i > 0)
697  pkt_buffer.s.size =
699 
700  if (i == (num_segs - 1))
701  pkt_buffer.s.i = 0;
702 
703  *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
704  8 * i) = pkt_buffer.u64;
705  }
706 
707  /* Build the PKO command */
708  pko_command.u64 = 0;
709  pko_command.s.segs = num_segs;
710  pko_command.s.total_bytes = size;
711  pko_command.s.dontfree = 0;
712  pko_command.s.gather = 1;
713 
714  gmx_cfg.u64 =
715  cvmx_read_csr(CVMX_GMXX_PRTX_CFG
718  gmx_cfg.s.en = 1;
719  cvmx_write_csr(CVMX_GMXX_PRTX_CFG
721  INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
723  1 << INDEX(FIX_IPD_OUTPORT));
725  1 << INDEX(FIX_IPD_OUTPORT));
726 
727  cvmx_write_csr(CVMX_GMXX_RXX_JABBER
729  INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
730  cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
732  INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
733 
734  cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
735  cvmx_pko_get_base_queue
736  (FIX_IPD_OUTPORT),
738  cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
739  cvmx_pko_get_base_queue
740  (FIX_IPD_OUTPORT), pko_command,
741  g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
742 
743  CVMX_SYNC;
744 
745  do {
746  work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
747  retry_cnt--;
748  } while ((work == NULL) && (retry_cnt > 0));
749 
750  if (!retry_cnt)
751  cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
752  "get_work() timeout occurred.\n");
753 
754  /* Free packet */
755  if (work)
756  cvmx_helper_free_packet_data(work);
757  }
758 
759 fix_ipd_exit:
760 
761  /* Return CSR configs to saved values */
762  cvmx_write_csr(CVMX_GMXX_PRTX_CFG
764  prtx_cfg);
766  tx_ptr_en);
768  rx_ptr_en);
769  cvmx_write_csr(CVMX_GMXX_RXX_JABBER
771  rxx_jabber);
772  cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
774  frame_max);
775  cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
776  /* Set link to down so autonegotiation will set it up again */
777  link_info.u64 = 0;
779 
780  /*
781  * Bring the link back up as autonegotiation is not done in
782  * user applications.
783  */
785 
786  CVMX_SYNC;
787  if (num_segs)
788  cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
789 
790  return !!num_segs;
791 
792 }
793 
801 {
802  int num_interfaces;
803  int interface;
804 
805  /* Enable IPD */
806  cvmx_ipd_enable();
807 
808  /*
809  * Time to enable hardware ports packet input and output. Note
810  * that at this point IPD/PIP must be fully functional and PKO
811  * must be disabled
812  */
813  num_interfaces = cvmx_helper_get_number_of_interfaces();
814  for (interface = 0; interface < num_interfaces; interface++) {
815  if (cvmx_helper_ports_on_interface(interface) > 0)
816  __cvmx_helper_packet_hardware_enable(interface);
817  }
818 
819  /* Finally enable PKO now that the entire path is up and running */
820  cvmx_pko_enable();
821 
826  return 0;
827 }
828 
839 {
840  int result = 0;
841  int interface;
842  union cvmx_l2c_cfg l2c_cfg;
843  union cvmx_smix_en smix_en;
844  const int num_interfaces = cvmx_helper_get_number_of_interfaces();
845 
846  /*
847  * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
848  * be disabled.
849  */
852 
853  /*
854  * Tell L2 to give the IOB statically higher priority compared
855  * to the cores. This avoids conditions where IO blocks might
856  * be starved under very high L2 loads.
857  */
858  l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
859  l2c_cfg.s.lrf_arb_mode = 0;
860  l2c_cfg.s.rfb_arb_mode = 0;
861  cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
862 
863  /* Make sure SMI/MDIO is enabled so we can query PHYs */
864  smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
865  if (!smix_en.s.en) {
866  smix_en.s.en = 1;
867  cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
868  }
869 
870  /* Newer chips actually have two SMI/MDIO interfaces */
874  smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
875  if (!smix_en.s.en) {
876  smix_en.s.en = 1;
877  cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
878  }
879  }
880 
882  for (interface = 0; interface < num_interfaces; interface++) {
883  result |= cvmx_helper_interface_probe(interface);
884  if (cvmx_helper_ports_on_interface(interface) > 0)
885  cvmx_dprintf("Interface %d has %d ports (%s)\n",
886  interface,
890  (interface)));
891  result |= __cvmx_helper_interface_setup_ipd(interface);
892  result |= __cvmx_helper_interface_setup_pko(interface);
893  }
894 
895  result |= __cvmx_helper_global_setup_ipd();
896  result |= __cvmx_helper_global_setup_pko();
897 
898  /* Enable any flow control and backpressure */
899  result |= __cvmx_helper_global_setup_backpressure();
900 
901 #if CVMX_HELPER_ENABLE_IPD
903 #endif
904  return result;
905 }
906 
913 {
914  return cvmx_pko_initialize_local();
915 }
916 
927 {
928  cvmx_helper_link_info_t link_info;
929  int interface = cvmx_helper_get_interface_num(ipd_port);
931 
932  if (index >= cvmx_helper_ports_on_interface(interface)) {
933  link_info.u64 = 0;
934  return link_info;
935  }
936 
937  link_info = cvmx_helper_link_get(ipd_port);
938  if (link_info.u64 == port_link_info[ipd_port].u64)
939  return link_info;
940 
941  /* If we fail to set the link speed, port_link_info will not change */
942  cvmx_helper_link_set(ipd_port, link_info);
943 
944  /*
945  * port_link_info should be the current value, which will be
946  * different than expect if cvmx_helper_link_set() failed.
947  */
948  return port_link_info[ipd_port];
949 }
950 
962 {
964  int interface = cvmx_helper_get_interface_num(ipd_port);
966 
967  /* The default result will be a down link unless the code below
968  changes it */
969  result.u64 = 0;
970 
971  if (index >= cvmx_helper_ports_on_interface(interface))
972  return result;
973 
974  switch (cvmx_helper_interface_get_mode(interface)) {
977  /* Network links are not supported */
978  break;
980  result = __cvmx_helper_xaui_link_get(ipd_port);
981  break;
983  if (index == 0)
984  result = __cvmx_helper_rgmii_link_get(ipd_port);
985  else {
986  result.s.full_duplex = 1;
987  result.s.link_up = 1;
988  result.s.speed = 1000;
989  }
990  break;
992  result = __cvmx_helper_rgmii_link_get(ipd_port);
993  break;
995  result = __cvmx_helper_spi_link_get(ipd_port);
996  break;
999  result = __cvmx_helper_sgmii_link_get(ipd_port);
1000  break;
1003  /* Network links are not supported */
1004  break;
1005  }
1006  return result;
1007 }
1008 
1021 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1022 {
1023  int result = -1;
1024  int interface = cvmx_helper_get_interface_num(ipd_port);
1026 
1027  if (index >= cvmx_helper_ports_on_interface(interface))
1028  return -1;
1029 
1030  switch (cvmx_helper_interface_get_mode(interface)) {
1033  break;
1035  result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1036  break;
1037  /*
1038  * RGMII/GMII/MII are all treated about the same. Most
1039  * functions refer to these ports as RGMII.
1040  */
1043  result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1044  break;
1046  result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1047  break;
1050  result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1051  break;
1054  break;
1055  }
1056  /* Set the port_link_info here so that the link status is updated
1057  no matter how cvmx_helper_link_set is called. We don't change
1058  the value if link_set failed */
1059  if (result == 0)
1060  port_link_info[ipd_port].u64 = link_info.u64;
1061  return result;
1062 }
1063 
1077 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
1078  int enable_external)
1079 {
1080  int result = -1;
1081  int interface = cvmx_helper_get_interface_num(ipd_port);
1083 
1084  if (index >= cvmx_helper_ports_on_interface(interface))
1085  return -1;
1086 
1087  switch (cvmx_helper_interface_get_mode(interface)) {
1093  break;
1095  result =
1097  enable_internal,
1098  enable_external);
1099  break;
1102  result =
1104  enable_internal,
1105  enable_external);
1106  break;
1109  result =
1111  enable_internal,
1112  enable_external);
1113  break;
1114  }
1115  return result;
1116 }