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**************************************/
49 * Helper functions to abstract board specific data about
50 * network ports from the rest of the cvmx-helper files.
52 * <hr>$Revision: 49627 $<hr>
54 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
55 #include <linux/module.h>
56 #include <asm/octeon/cvmx.h>
57 #include <asm/octeon/cvmx-bootinfo.h>
58 #include <asm/octeon/cvmx-smix-defs.h>
59 #include <asm/octeon/cvmx-gmxx-defs.h>
60 #include <asm/octeon/cvmx-asxx-defs.h>
61 #include <asm/octeon/cvmx-mdio.h>
62 #include <asm/octeon/cvmx-helper.h>
63 #include <asm/octeon/cvmx-helper-util.h>
64 #include <asm/octeon/cvmx-helper-board.h>
65 #include <asm/octeon/cvmx-twsi.h>
68 #include "cvmx-app-init.h"
69 #include "cvmx-sysinfo.h"
70 #include "cvmx-twsi.h"
71 #include "cvmx-mdio.h"
72 #include "cvmx-helper.h"
73 #include "cvmx-helper-util.h"
74 #include "cvmx-helper-board.h"
78 * cvmx_override_board_link_get(int ipd_port) is a function
79 * pointer. It is meant to allow customization of the process of
80 * talking to a PHY to determine link speed. It is called every
81 * time a PHY must be polled for link status. Users should set
82 * this pointer to a function before calling any cvmx-helper
85 CVMX_SHARED cvmx_helper_link_info_t (*cvmx_override_board_link_get)(int ipd_port) = NULL;
88 * Return the MII PHY address associated with the given IPD
89 * port. A result of -1 means there isn't a MII capable PHY
90 * connected to this port. On chips supporting multiple MII
91 * busses the bus number is encoded in bits <15:8>.
93 * This function must be modified for every new Octeon board.
94 * Internally it uses switch statements based on the cvmx_sysinfo
95 * data to determine board types and revisions. It replies on the
96 * fact that every Octeon board receives a unique board type
97 * enumeration from the bootloader.
99 * @param ipd_port Octeon IPD port to get the MII address for.
101 * @return MII PHY address and bus number or -1.
103 int cvmx_helper_board_get_mii_address(int ipd_port)
106 * Board types we have to know at compile-time.
108 #ifdef OCTEON_BOARD_CAPK_0100ND
115 /* XXX Switch PHY? */
123 * For board types we can determine at runtime.
125 switch (cvmx_sysinfo_get()->board_type)
127 case CVMX_BOARD_TYPE_SIM:
128 /* Simulator doesn't have MII */
130 case CVMX_BOARD_TYPE_EBT3000:
131 case CVMX_BOARD_TYPE_EBT5800:
132 case CVMX_BOARD_TYPE_THUNDER:
133 case CVMX_BOARD_TYPE_NICPRO2:
134 /* Interface 0 is SPI4, interface 1 is RGMII */
135 if ((ipd_port >= 16) && (ipd_port < 20))
136 return ipd_port - 16;
139 case CVMX_BOARD_TYPE_LANAI2_A:
144 case CVMX_BOARD_TYPE_LANAI2_U:
145 case CVMX_BOARD_TYPE_LANAI2_G:
150 case CVMX_BOARD_TYPE_KODAMA:
151 case CVMX_BOARD_TYPE_EBH3100:
152 case CVMX_BOARD_TYPE_HIKARI:
153 case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
154 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
155 case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
156 /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a
160 else if (ipd_port == 1)
164 case CVMX_BOARD_TYPE_NAC38:
165 /* Board has 8 RGMII ports PHYs are 0-7 */
166 if ((ipd_port >= 0) && (ipd_port < 4))
168 else if ((ipd_port >= 16) && (ipd_port < 20))
169 return ipd_port - 16 + 4;
172 case CVMX_BOARD_TYPE_EBH3000:
173 /* Board has dual SPI4 and no PHYs */
175 case CVMX_BOARD_TYPE_EBT5810:
176 /* Board has 10g PHYs hooked up to the MII controller on the
177 ** IXF18201 MAC. The 10G PHYS use clause 45 MDIO which the CN58XX
178 ** does not support. All MII accesses go through the IXF part. */
180 case CVMX_BOARD_TYPE_EBH5200:
181 case CVMX_BOARD_TYPE_EBH5201:
182 case CVMX_BOARD_TYPE_EBT5200:
183 /* Board has 2 management ports */
184 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)))
185 return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT;
186 /* Board has 4 SGMII ports. The PHYs start right after the MII
187 ports MII0 = 0, MII1 = 1, SGMII = 2-5 */
188 if ((ipd_port >= 0) && (ipd_port < 4))
192 case CVMX_BOARD_TYPE_EBH5600:
193 case CVMX_BOARD_TYPE_EBH5601:
194 case CVMX_BOARD_TYPE_EBH5610:
195 /* Board has 1 management port */
196 if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
198 /* Board has 8 SGMII ports. 4 connect out, two connect to a switch,
199 and 2 loop to each other */
200 if ((ipd_port >= 0) && (ipd_port < 4))
204 case CVMX_BOARD_TYPE_EBB5600:
206 static unsigned char qlm_switch_addr = 0;
208 /* Board has 1 management port */
209 if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
212 /* Board has 8 SGMII ports. 4 connected QLM1, 4 connected QLM3 */
213 if ((ipd_port >= 0) && (ipd_port < 4))
215 if (qlm_switch_addr != 0x3)
217 qlm_switch_addr = 0x3; /* QLM1 */
218 cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr);
219 cvmx_wait_usec(11000); /* Let the write complete */
221 return ipd_port+1 + (1<<8);
223 else if ((ipd_port >= 16) && (ipd_port < 20))
225 if (qlm_switch_addr != 0xC)
227 qlm_switch_addr = 0xC; /* QLM3 */
228 cvmx_twsix_write_ia(0, 0x71, 0, 1, 1, qlm_switch_addr);
229 cvmx_wait_usec(11000); /* Let the write complete */
231 return ipd_port-16+1 + (1<<8);
236 case CVMX_BOARD_TYPE_EBB6300:
237 /* Board has 2 management ports */
238 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)))
239 return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT + 4;
240 if ((ipd_port >= 0) && (ipd_port < 4))
241 return ipd_port + 1 + (1<<8);
244 case CVMX_BOARD_TYPE_CUST_NB5:
249 case CVMX_BOARD_TYPE_NIC_XLE_4G:
250 /* Board has 4 SGMII ports. connected QLM3(interface 1) */
251 if ((ipd_port >= 16) && (ipd_port < 20))
252 return ipd_port - 16 + 1;
255 case CVMX_BOARD_TYPE_NIC_XLE_10G:
256 return -1; /* We don't use clause 45 MDIO for anything */
257 case CVMX_BOARD_TYPE_BBGW_REF:
258 return -1; /* No PHYs are connected to Octeon, everything is through switch */
259 case CVMX_BOARD_TYPE_CUST_WSX16:
260 if (ipd_port >= 0 && ipd_port <= 3)
262 else if (ipd_port >= 16 && ipd_port <= 19)
263 return ipd_port - 16 + 4;
267 /* Private vendor-defined boards. */
268 #if defined(OCTEON_VENDOR_LANNER)
269 case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
270 /* Interface 1 is 12 BCM5482S PHYs. */
271 if ((ipd_port >= 16) && (ipd_port < 28))
272 return ipd_port - 16;
274 case CVMX_BOARD_TYPE_CUST_LANNER_MR730:
275 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)))
276 return (ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT) + 0x81;
277 if ((ipd_port >= 0) && (ipd_port < 4))
280 case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
281 case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
282 /* Port 0 is a Marvell 88E6161 switch, ports 1 and 2 are Marvell
283 88E1111 interfaces. */
297 /* Some unknown board. Somebody forgot to update this function... */
298 cvmx_dprintf("%s: Unknown board type %d\n",
299 __FUNCTION__, cvmx_sysinfo_get()->board_type);
302 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
303 EXPORT_SYMBOL(cvmx_helper_board_get_mii_address);
309 * This function is the board specific method of determining an
310 * ethernet ports link speed. Most Octeon boards have Marvell PHYs
311 * and are handled by the fall through case. This function must be
312 * updated for boards that don't have the normal Marvell PHYs.
314 * This function must be modified for every new Octeon board.
315 * Internally it uses switch statements based on the cvmx_sysinfo
316 * data to determine board types and revisions. It relies on the
317 * fact that every Octeon board receives a unique board type
318 * enumeration from the bootloader.
320 * @param ipd_port IPD input port associated with the port we want to get link
323 * @return The ports link status. If the link isn't fully resolved, this must
326 cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
328 cvmx_helper_link_info_t result;
330 int is_broadcom_phy = 0;
332 /* Give the user a chance to override the processing of this function */
333 if (cvmx_override_board_link_get)
334 return cvmx_override_board_link_get(ipd_port);
336 /* Unless we fix it later, all links are defaulted to down */
339 #if !defined(OCTEON_BOARD_CAPK_0100ND)
340 /* This switch statement should handle all ports that either don't use
341 Marvell PHYS, or don't support in-band status */
342 switch (cvmx_sysinfo_get()->board_type)
344 case CVMX_BOARD_TYPE_SIM:
345 /* The simulator gives you a simulated 1Gbps full duplex link */
346 result.s.link_up = 1;
347 result.s.full_duplex = 1;
348 result.s.speed = 1000;
350 case CVMX_BOARD_TYPE_LANAI2_A:
351 case CVMX_BOARD_TYPE_LANAI2_U:
352 case CVMX_BOARD_TYPE_LANAI2_G:
354 case CVMX_BOARD_TYPE_EBH3100:
355 case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
356 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
357 case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
358 /* Port 1 on these boards is always Gigabit */
361 result.s.link_up = 1;
362 result.s.full_duplex = 1;
363 result.s.speed = 1000;
366 /* Fall through to the generic code below */
368 case CVMX_BOARD_TYPE_EBH5600:
369 case CVMX_BOARD_TYPE_EBH5601:
370 case CVMX_BOARD_TYPE_EBH5610:
371 /* Board has 1 management ports */
372 if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
375 case CVMX_BOARD_TYPE_EBH5200:
376 case CVMX_BOARD_TYPE_EBH5201:
377 case CVMX_BOARD_TYPE_EBT5200:
378 /* Board has 2 management ports */
379 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)))
382 case CVMX_BOARD_TYPE_EBB6300: /* Only for MII mode, with PHY addresses 0/1. Default is RGMII*/
383 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))
384 && cvmx_helper_board_get_mii_address(ipd_port) >= 0 && cvmx_helper_board_get_mii_address(ipd_port) <= 1)
387 case CVMX_BOARD_TYPE_CUST_NB5:
388 /* Port 1 on these boards is always Gigabit */
391 result.s.link_up = 1;
392 result.s.full_duplex = 1;
393 result.s.speed = 1000;
396 else /* The other port uses a broadcom PHY */
399 case CVMX_BOARD_TYPE_BBGW_REF:
400 /* Port 1 on these boards is always Gigabit */
403 /* Port 2 is not hooked up */
409 /* Ports 0 and 1 connect to the switch */
410 result.s.link_up = 1;
411 result.s.full_duplex = 1;
412 result.s.speed = 1000;
416 /* Private vendor-defined boards. */
417 #if defined(OCTEON_VENDOR_LANNER)
418 case CVMX_BOARD_TYPE_CUST_LANNER_MR730:
419 /* Ports are BCM5482S */
422 case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
423 case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
424 /* Port 0 connects to the switch */
427 result.s.link_up = 1;
428 result.s.full_duplex = 1;
429 result.s.speed = 1000;
437 phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
442 /* Below we are going to read SMI/MDIO register 0x19 which works
444 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19);
445 switch ((phy_status>>8) & 0x7)
451 result.s.link_up = 1;
452 result.s.full_duplex = 0;
456 result.s.link_up = 1;
457 result.s.full_duplex = 1;
461 result.s.link_up = 1;
462 result.s.full_duplex = 0;
463 result.s.speed = 100;
466 result.s.link_up = 1;
467 result.s.full_duplex = 1;
468 result.s.speed = 100;
471 result.s.link_up = 1;
472 result.s.full_duplex = 1;
473 result.s.speed = 100;
476 result.s.link_up = 1;
477 result.s.full_duplex = 0;
478 result.s.speed = 1000;
481 result.s.link_up = 1;
482 result.s.full_duplex = 1;
483 result.s.speed = 1000;
489 /* This code assumes we are using a Marvell Gigabit PHY. All the
490 speed information can be read from register 17 in one go. Somebody
491 using a different PHY will need to handle it above in the board
493 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17);
495 /* If the resolve bit 11 isn't set, see if autoneg is turned off
496 (bit 12, reg 0). The resolve bit doesn't get set properly when
497 autoneg is off, so force it */
498 if ((phy_status & (1<<11)) == 0)
500 int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0);
501 if ((auto_status & (1<<12)) == 0)
505 /* Only return a link if the PHY has finished auto negotiation
506 and set the resolved bit (bit 11) */
507 if (phy_status & (1<<11))
509 #if defined(OCTEON_BOARD_CAPK_0100ND)
510 result.s.link_up = (phy_status>>10)&1;
512 result.s.link_up = 1;
514 result.s.full_duplex = ((phy_status>>13)&1);
515 switch ((phy_status>>14)&3)
517 case 0: /* 10 Mbps */
520 case 1: /* 100 Mbps */
521 result.s.speed = 100;
524 result.s.speed = 1000;
526 case 3: /* Illegal */
533 else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
535 /* We don't have a PHY address, so attempt to use in-band status. It is
536 really important that boards not supporting in-band status never get
537 here. Reading broken in-band status tends to do bad things */
538 cvmx_gmxx_rxx_rx_inbnd_t inband_status;
539 int interface = cvmx_helper_get_interface_num(ipd_port);
540 int index = cvmx_helper_get_interface_index_num(ipd_port);
541 inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface));
543 result.s.link_up = inband_status.s.status;
544 result.s.full_duplex = inband_status.s.duplex;
545 switch (inband_status.s.speed)
547 case 0: /* 10 Mbps */
550 case 1: /* 100 Mbps */
551 result.s.speed = 100;
554 result.s.speed = 1000;
556 case 3: /* Illegal */
563 /* We don't have a PHY address and we don't have in-band status. There
564 is no way to determine the link speed. Return down assuming this
569 /* If link is down, return all fields as zero. */
570 if (!result.s.link_up)
578 * This function as a board specific method of changing the PHY
579 * speed, duplex, and autonegotiation. This programs the PHY and
580 * not Octeon. This can be used to force Octeon's links to
583 * @param phy_addr The address of the PHY to program
585 * Flags to control autonegotiation. Bit 0 is autonegotiation
586 * enable/disable to maintain backward compatibility.
587 * @param link_info Link speed to program. If the speed is zero and autonegotiation
588 * is enabled, all possible negotiation speeds are advertised.
590 * @return Zero on success, negative on failure
592 int cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags,
593 cvmx_helper_link_info_t link_info)
596 /* Set the flow control settings based on link_flags */
597 if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch)
599 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
600 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
601 reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable;
602 reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable;
603 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16);
606 /* If speed isn't set and autoneg is on advertise all supported modes */
607 if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0))
609 cvmx_mdio_phy_reg_control_t reg_control;
610 cvmx_mdio_phy_reg_status_t reg_status;
611 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
612 cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
613 cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
615 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS);
616 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
617 reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4;
618 reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full;
619 reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half;
620 reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full;
621 reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half;
622 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16);
623 if (reg_status.s.capable_extended_status)
625 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
626 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000);
627 reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full;
628 reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half;
629 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16);
631 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL);
632 reg_control.s.autoneg_enable = 1;
633 reg_control.s.restart_autoneg = 1;
634 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
636 else if ((link_flags & set_phy_link_flags_autoneg))
638 cvmx_mdio_phy_reg_control_t reg_control;
639 cvmx_mdio_phy_reg_status_t reg_status;
640 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
641 cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
642 cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
644 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS);
645 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
646 reg_autoneg_adver.s.advert_100base_t4 = 0;
647 reg_autoneg_adver.s.advert_10base_tx_full = 0;
648 reg_autoneg_adver.s.advert_10base_tx_half = 0;
649 reg_autoneg_adver.s.advert_100base_tx_full = 0;
650 reg_autoneg_adver.s.advert_100base_tx_half = 0;
651 if (reg_status.s.capable_extended_status)
653 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
654 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000);
655 reg_control_1000.s.advert_1000base_t_full = 0;
656 reg_control_1000.s.advert_1000base_t_half = 0;
658 switch (link_info.s.speed)
661 reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex;
662 reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex;
665 reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex;
666 reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex;
669 reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex;
670 reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex;
673 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16);
674 if (reg_status.s.capable_extended_status)
675 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16);
676 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL);
677 reg_control.s.autoneg_enable = 1;
678 reg_control.s.restart_autoneg = 1;
679 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
683 cvmx_mdio_phy_reg_control_t reg_control;
684 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL);
685 reg_control.s.autoneg_enable = 0;
686 reg_control.s.restart_autoneg = 1;
687 reg_control.s.duplex = link_info.s.full_duplex;
688 if (link_info.s.speed == 1000)
690 reg_control.s.speed_msb = 1;
691 reg_control.s.speed_lsb = 0;
693 else if (link_info.s.speed == 100)
695 reg_control.s.speed_msb = 0;
696 reg_control.s.speed_lsb = 1;
698 else if (link_info.s.speed == 10)
700 reg_control.s.speed_msb = 0;
701 reg_control.s.speed_lsb = 0;
703 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
711 * This function is called by cvmx_helper_interface_probe() after it
712 * determines the number of ports Octeon can support on a specific
713 * interface. This function is the per board location to override
714 * this value. It is called with the number of ports Octeon might
715 * support and should return the number of actual ports on the
718 * This function must be modified for every new Octeon board.
719 * Internally it uses switch statements based on the cvmx_sysinfo
720 * data to determine board types and revisions. It relies on the
721 * fact that every Octeon board receives a unique board type
722 * enumeration from the bootloader.
724 * @param interface Interface to probe
725 * @param supported_ports
726 * Number of ports Octeon supports.
728 * @return Number of ports the actual board supports. Many times this will
729 * simple be "support_ports".
731 int __cvmx_helper_board_interface_probe(int interface, int supported_ports)
733 switch (cvmx_sysinfo_get()->board_type)
735 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
736 case CVMX_BOARD_TYPE_LANAI2_A:
737 case CVMX_BOARD_TYPE_LANAI2_U:
738 case CVMX_BOARD_TYPE_LANAI2_G:
742 case CVMX_BOARD_TYPE_BBGW_REF:
746 case CVMX_BOARD_TYPE_NIC_XLE_4G:
750 /* The 2nd interface on the EBH5600 is connected to the Marvel switch,
751 which we don't support. Disable ports connected to it */
752 case CVMX_BOARD_TYPE_EBH5600:
756 case CVMX_BOARD_TYPE_EBB5600:
757 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
758 if (cvmx_helper_interface_get_mode(interface) == CVMX_HELPER_INTERFACE_MODE_PICMG)
762 case CVMX_BOARD_TYPE_EBT5810:
763 return 1; /* Two ports on each SPI: 1 hooked to MAC, 1 loopback
764 ** Loopback disabled by default. */
765 #if defined(OCTEON_VENDOR_LANNER)
766 case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
772 #ifdef CVMX_BUILD_FOR_UBOOT
773 if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi"))
776 return supported_ports;
782 * Enable packet input/output from the hardware. This function is
783 * called after by cvmx_helper_packet_hardware_enable() to
784 * perform board specific initialization. For most boards
787 * @param interface Interface to enable
789 * @return Zero on success, negative on failure
791 int __cvmx_helper_board_hardware_enable(int interface)
793 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5)
797 /* Different config for switch port */
798 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0);
799 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0);
800 /* Boards with gigabit WAN ports need a different setting that is
801 compatible with 100 Mbit settings */
802 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc);
803 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc);
806 else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_LANAI2_U)
810 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 16);
811 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 16);
814 else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5)
816 /* Broadcom PHYs require different ASX clocks. Unfortunately
817 many customer don't define a new board Id and simply
818 mangle the CN3010_EVB_HS5 */
821 /* Some customers boards use a hacked up bootloader that identifies them as
822 ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration
823 ** problems. Detect one case, and print warning, while trying to do the right thing.
825 int phy_addr = cvmx_helper_board_get_mii_address(0);
828 int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2);
829 /* Is it a Broadcom PHY? */
830 if (phy_identifier == 0x0143)
833 cvmx_dprintf("ERROR:\n");
834 cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n");
835 cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n");
836 cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n");
837 cvmx_dprintf("ERROR:\n");
839 cvmx_wait(1000000000);
840 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5);
841 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5);
852 * Gets the clock type used for the USB block based on board type.
853 * Used by the USB code for auto configuration of clock type.
855 * @return USB clock type enumeration
857 cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void)
859 switch (cvmx_sysinfo_get()->board_type)
861 case CVMX_BOARD_TYPE_BBGW_REF:
862 case CVMX_BOARD_TYPE_LANAI2_A:
863 case CVMX_BOARD_TYPE_LANAI2_U:
864 case CVMX_BOARD_TYPE_LANAI2_G:
865 #if defined(OCTEON_VENDOR_LANNER)
866 case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
867 case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
869 return USB_CLOCK_TYPE_CRYSTAL_12;
871 return USB_CLOCK_TYPE_REF_48;
877 * Adjusts the number of available USB ports on Octeon based on board
880 * @param supported_ports expected number of ports based on chip type;
883 * @return number of available usb ports, based on board specifics.
884 * Return value is supported_ports if function does not
887 int __cvmx_helper_board_usb_get_num_ports(int supported_ports)
889 switch (cvmx_sysinfo_get()->board_type)
891 case CVMX_BOARD_TYPE_NIC_XLE_4G:
895 return supported_ports;