Exemple #1
0
/**
 * Modify the device tree to remove all unused interface types.
 */
int board_fixup_fdt(void)
{
	const char *fdt_key;
	int is_spi4000 = 0;
	int is_spi = 0;
	union cvmx_gmxx_inf_mode gmx_mode;

	gmx_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));

	if (!gmx_mode.cn58xx.en) {
		fdt_key ="0,none"; /* Disabled */
	} else {
		if (gmx_mode.cn58xx.type) {
			fdt_key = "0,spi";
			is_spi4000 = cvmx_spi4000_is_present(0);
			is_spi = 1;
		} else {
			fdt_key = "0,rgmii";
		}
	}
	octeon_fdt_patch(working_fdt, fdt_key, NULL);

	if (is_spi) {
		if (is_spi4000)
			fdt_key = "9,spi4000";
		else
			fdt_key = "9,not-spi4000";
		octeon_fdt_patch(working_fdt, fdt_key, NULL);
	}
}
Exemple #2
0
/**
 * @INTERNAL
 * Probe RGMII ports and determine the number present
 *
 * @param interface Interface to probe
 *
 * @return Number of RGMII/GMII/MII ports (0-4).
 */
int __cvmx_helper_rgmii_probe(int interface)
{
    int num_ports = 0;
    cvmx_gmxx_inf_mode_t mode;
    mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));

    if (mode.s.type)
    {
        if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
        {
            cvmx_dprintf("ERROR: RGMII initialize called in SPI interface\n");
        }
        else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
        {
            /* On these chips "type" says we're in GMII/MII mode. This
                limits us to 2 ports */
            num_ports = 2;
        }
        else
        {
            cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", __FUNCTION__);
        }
    }
    else
    {
        if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
        {
            num_ports = 4;
        }
        else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
        {
            num_ports = 3;
        }
        else
        {
            cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", __FUNCTION__);
        }
    }
    return num_ports;
}
Exemple #3
0
void board_mdio_init(void)
{
	cvmx_smi_clk_t smi_clk;
	int val;
	/* Force us into RGMII mode */
	cvmx_write_csr(CVMX_GMXX_INF_MODE(0), 0x2);

	/* Set the SMI clock to 7 MHz, which is the fastest that
	 * all the parts on the board can handle.
	 */
	smi_clk.u64 = cvmx_read_csr(CVMX_SMI_CLK);
	smi_clk.cn50xx.phase = (gd->cpu_clk + 7) / 7;
	cvmx_write_csr(CVMX_SMI_CLK, smi_clk.u64);
	cvmx_read_csr(CVMX_SMI_CLK);

	/* Enable SMI to talk with the GMII switch */
	cvmx_write_csr(CVMX_SMI_EN, 0x1);
	cvmx_read_csr(CVMX_SMI_EN);

	/* Broadcom switch setup */

	/* Force IMP speed/mode */
	brcm_miiphy_write(0, 0xe, 0x8b);

	/* Force port 5 speed/mode */
	brcm_miiphy_write(0x0, 0x5d, 0x4b);

	/* Set up port based VLAN - effectively divides
	 * the switch into 2 - one 5 port, and one 2 port
	 * switches
	 */
	/* Octeon port 1 (IMP) is connected to 4 external switch ports
	 * for LAN connection
	 */
	brcm_miiphy_write(0x31, 0x0, 0x10f);	/* Port 0 */
	brcm_miiphy_write(0x31, 0x2, 0x10f);	/* Port 1 */
	brcm_miiphy_write(0x31, 0x4, 0x10f);	/* Port 2 */
	brcm_miiphy_write(0x31, 0x6, 0x10f);	/* Port 3 */
	brcm_miiphy_write(0x31, 0x10, 0x10f);	/* IMP */

	/* Set default VLAN ID to 0x1 */
	brcm_miiphy_write(0x34, 0x10, 0x1);	/* Port 0 */
	brcm_miiphy_write(0x34, 0x12, 0x1);	/* Port 1 */
	brcm_miiphy_write(0x34, 0x14, 0x1);	/* Port 2 */
	brcm_miiphy_write(0x34, 0x16, 0x1);	/* Port 3 */
	brcm_miiphy_write(0x34, 0x20, 0x1);	/* IMP */

	/* Octeon port 0 (port 5) is connected to 1 external switch port
	 * for WAN connection
	 */
	brcm_miiphy_write(0x31, 0x8, 0x30);	/* Port 4 */
	brcm_miiphy_write(0x31, 0xa, 0x30);	/* Port 5 */

	/* Set default VLAN ID to 0x2 */
	brcm_miiphy_write(0x34, 0x18, 0x2);	/* Port 4 */
	brcm_miiphy_write(0x34, 0x1A, 0x2);	/* Port 5 */

	/* Set up two VLANs (1 and 2) that correspone to the port based
	 * VLAN configuration.  This should allow the two 'logical' switches
	 * to have the same MAC address in each one, as would be the case in Octeon
	 * bridging between its two ports.
	 */
	brcm_miiphy_write(0x05, 0x83, (0x10f << 9) | 0x10f);	/* Vlan table entry contents */
	brcm_miiphy_write(0x05, 0x81, 0x1);	/* Vlan entry index */
	brcm_miiphy_write(0x05, 0x80, 0x80);	/* Write VLAN entryx */

	brcm_miiphy_write(0x05, 0x83, (0x30 << 9) | 0x30);	/* Vlan table entry contents */
	brcm_miiphy_write(0x05, 0x81, 0x2);	/* Vlan entry index */
	brcm_miiphy_write(0x05, 0x80, 0x80);	/* Write VLAN entryx */

	/* Enable 802.1Q */
	brcm_miiphy_read(0x34, 0x0, &val);
	val = val | 0x80;
	brcm_miiphy_write(0x34, 0x0, val);

	/* Must disable STP for all ports, as
	 * disabling forwarding via HW_FWDG_EN pin changes
	 * the defaults
	 */
	brcm_miiphy_write(0x0, 0x0, 0);
	brcm_miiphy_write(0x0, 0x1, 0);
	brcm_miiphy_write(0x0, 0x2, 0);
	brcm_miiphy_write(0x0, 0x3, 0);
	brcm_miiphy_write(0x0, 0x4, 0);
	brcm_miiphy_write(0x0, 0x5, 0);
	brcm_miiphy_write(0x0, 0x6, 0);
	brcm_miiphy_write(0x0, 0x7, 0);

	/* Now enable forwarding */
	brcm_miiphy_read(0x0, 0xb, &val);
	val = (val & ~0x3) | 0x2;
	brcm_miiphy_write(0x0, 0xb, val);

	brcm_workaround();

}
Exemple #4
0
static int cvm_oct_driver_probe(struct platform_device *dev)
{
	int num_interfaces;
	int interface;
	int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
	int qos;

	octeon_mdiobus_force_mod_depencency();
	pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);

	if (OCTEON_IS_MODEL(OCTEON_CN52XX))
		cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
	else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
		cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
	else
		cvm_oct_mac_addr_offset = 0;

#if defined(CONFIG_SG590) || defined(CONFIG_SG770)
{
	union cvmx_gmxx_inf_mode mode;
	mode.u64 = 0;
	mode.s.en = 1;
	cvmx_write_csr(CVMX_GMXX_INF_MODE(0), mode.u64);
}
#endif
#ifdef CONFIG_SG8200
/*
 *	SG8200 directs the 2 internal ports out MII to 2 single 100Mbit
 *	interfaces. (The switch is on the 8139C+).
 */
{
	union cvmx_gmxx_inf_mode mode;
	mode.u64 = 0;
	mode.s.en = 1;
	mode.s.p0mii = 1;
	mode.s.type = 1;
	cvmx_write_csr(CVMX_GMXX_INF_MODE(0), mode.u64);
}
#endif

	cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
	if (cvm_oct_poll_queue == NULL) {
		pr_err("octeon-ethernet: Cannot create workqueue");
		return -ENOMEM;
	}

	cvm_oct_configure_common_hw();

	cvmx_helper_initialize_packet_io_global();

	/* Change the input group for all ports before input is enabled */
	num_interfaces = cvmx_helper_get_number_of_interfaces();
	for (interface = 0; interface < num_interfaces; interface++) {
		int num_ports = cvmx_helper_ports_on_interface(interface);
		int port;

		for (port = cvmx_helper_get_ipd_port(interface, 0);
		     port < cvmx_helper_get_ipd_port(interface, num_ports);
		     port++) {
			union cvmx_pip_prt_tagx pip_prt_tagx;
			pip_prt_tagx.u64 =
			    cvmx_read_csr(CVMX_PIP_PRT_TAGX(port));
			pip_prt_tagx.s.grp = pow_receive_group;
			cvmx_write_csr(CVMX_PIP_PRT_TAGX(port),
				       pip_prt_tagx.u64);
		}
	}

	cvmx_helper_ipd_and_packet_input_enable();

	memset(cvm_oct_device, 0, sizeof(cvm_oct_device));

	/*
	 * Initialize the FAU used for counting packet buffers that
	 * need to be freed.
	 */
	cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0);

	/* Initialize the FAU used for counting tx SKBs that need to be freed */
	cvmx_fau_atomic_write32(FAU_TOTAL_TX_TO_CLEAN, 0);

	if ((pow_send_group != -1)) {
		struct net_device *dev;
		pr_info("\tConfiguring device for POW only access\n");
		dev = alloc_etherdev(sizeof(struct octeon_ethernet));
		if (dev) {
			/* Initialize the device private structure. */
			struct octeon_ethernet *priv = netdev_priv(dev);

			dev->netdev_ops = &cvm_oct_pow_netdev_ops;
			priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
			priv->port = CVMX_PIP_NUM_INPUT_PORTS;
			priv->queue = -1;
			strcpy(dev->name, "pow%d");
			for (qos = 0; qos < 16; qos++)
				skb_queue_head_init(&priv->tx_free_list[qos]);

			if (register_netdev(dev) < 0) {
				pr_err("Failed to register ethernet device for POW\n");
				free_netdev(dev);
			} else {
				cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev;
				pr_info("%s: POW send group %d, receive group %d\n",
					dev->name, pow_send_group,
					pow_receive_group);
			}
		} else {
			pr_err("Failed to allocate ethernet device for POW\n");
		}
	}

	num_interfaces = cvmx_helper_get_number_of_interfaces();
	for (interface = 0; interface < num_interfaces; interface++) {
		cvmx_helper_interface_mode_t imode =
		    cvmx_helper_interface_get_mode(interface);
		int num_ports = cvmx_helper_ports_on_interface(interface);
		int port;

		for (port = cvmx_helper_get_ipd_port(interface, 0);
		     port < cvmx_helper_get_ipd_port(interface, num_ports);
		     port++) {
			struct octeon_ethernet *priv;
			struct net_device *dev =
			    alloc_etherdev(sizeof(struct octeon_ethernet));
			if (!dev) {
				pr_err("Failed to allocate ethernet device for port %d\n", port);
				continue;
			}

			/* Initialize the device private structure. */
			priv = netdev_priv(dev);

			INIT_DELAYED_WORK(&priv->port_periodic_work,
					  cvm_oct_periodic_worker);
			priv->imode = imode;
			priv->port = port;
			priv->queue = cvmx_pko_get_base_queue(priv->port);
			priv->fau = fau - cvmx_pko_get_num_queues(port) * 4;
			for (qos = 0; qos < 16; qos++)
				skb_queue_head_init(&priv->tx_free_list[qos]);
			for (qos = 0; qos < cvmx_pko_get_num_queues(port);
			     qos++)
				cvmx_fau_atomic_write32(priv->fau + qos * 4, 0);

			switch (priv->imode) {

			/* These types don't support ports to IPD/PKO */
			case CVMX_HELPER_INTERFACE_MODE_DISABLED:
			case CVMX_HELPER_INTERFACE_MODE_PCIE:
			case CVMX_HELPER_INTERFACE_MODE_PICMG:
				break;

			case CVMX_HELPER_INTERFACE_MODE_NPI:
				dev->netdev_ops = &cvm_oct_npi_netdev_ops;
				strcpy(dev->name, "npi%d");
				break;

			case CVMX_HELPER_INTERFACE_MODE_XAUI:
				dev->netdev_ops = &cvm_oct_xaui_netdev_ops;
				strcpy(dev->name, "xaui%d");
				break;

			case CVMX_HELPER_INTERFACE_MODE_LOOP:
				dev->netdev_ops = &cvm_oct_npi_netdev_ops;
				strcpy(dev->name, "loop%d");
				break;

			case CVMX_HELPER_INTERFACE_MODE_SGMII:
				dev->netdev_ops = &cvm_oct_sgmii_netdev_ops;
				strcpy(dev->name, "eth%d");
				break;

			case CVMX_HELPER_INTERFACE_MODE_SPI:
				dev->netdev_ops = &cvm_oct_spi_netdev_ops;
				strcpy(dev->name, "spi%d");
				break;

			case CVMX_HELPER_INTERFACE_MODE_RGMII:
			case CVMX_HELPER_INTERFACE_MODE_GMII:
				dev->netdev_ops = &cvm_oct_rgmii_netdev_ops;
				strcpy(dev->name, "eth%d");
				break;
			}

			if (!dev->netdev_ops) {
				free_netdev(dev);
			} else if (register_netdev(dev) < 0) {
				pr_err("Failed to register ethernet device "
					 "for interface %d, port %d\n",
					 interface, priv->port);
				free_netdev(dev);
			} else {
				cvm_oct_device[priv->port] = dev;
				fau -=
				    cvmx_pko_get_num_queues(priv->port) *
				    sizeof(uint32_t);
				queue_delayed_work(cvm_oct_poll_queue,
						   &priv->port_periodic_work, HZ);
			}
		}
	}

	cvm_oct_tx_initialize();
	cvm_oct_rx_initialize();

	/*
	 * 150 uS: about 10 1500-byte packtes at 1GE.
	 */
	cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000);

	queue_delayed_work(cvm_oct_poll_queue, &cvm_oct_rx_refill_work, HZ);

#ifdef CONFIG_SG590
{
	void cvm_oct_marvel_switch_init(void);
	printk("cavium-ethernet: enabling Marvell 88e6046 switch: intra-switch forwarding disabled\n");
	cvm_oct_marvel_switch_init();
}
#endif

	return 0;
}
Exemple #5
0
/**
 * @INTERNAL
 * Configure an IPD/PKO port for the specified link state. This
 * function does not influence auto negotiation at the PHY level.
 * The passed link state must always match the link state returned
 * by cvmx_helper_link_get(). It is normally best to use
 * cvmx_helper_link_autoconf() instead.
 *
 * @param ipd_port  IPD/PKO port to configure
 * @param link_info The new link state
 *
 * @return Zero on success, negative on failure
 */
int __cvmx_helper_rgmii_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
{
    int result = 0;
    int interface = cvmx_helper_get_interface_num(ipd_port);
    int index = cvmx_helper_get_interface_index_num(ipd_port);
    cvmx_gmxx_prtx_cfg_t original_gmx_cfg;
    cvmx_gmxx_prtx_cfg_t new_gmx_cfg;
    cvmx_pko_mem_queue_qos_t pko_mem_queue_qos;
    cvmx_pko_mem_queue_qos_t pko_mem_queue_qos_save[16];
    cvmx_gmxx_tx_ovr_bp_t gmx_tx_ovr_bp;
    cvmx_gmxx_tx_ovr_bp_t gmx_tx_ovr_bp_save;
    int i;

    /* Ignore speed sets in the simulator */
    if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
        return 0;

    /* Read the current settings so we know the current enable state */
    original_gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
    new_gmx_cfg = original_gmx_cfg;

    /* Disable the lowest level RX */
    cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface),
                   cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) & ~(1<<index));

    memset(pko_mem_queue_qos_save, 0, sizeof(pko_mem_queue_qos_save));
    /* Disable all queues so that TX should become idle */
    for (i=0; i<cvmx_pko_get_num_queues(ipd_port); i++)
    {
        int queue = cvmx_pko_get_base_queue(ipd_port) + i;
        cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue);
        pko_mem_queue_qos.u64 = cvmx_read_csr(CVMX_PKO_MEM_QUEUE_QOS);
        pko_mem_queue_qos.s.pid = ipd_port;
        pko_mem_queue_qos.s.qid = queue;
        pko_mem_queue_qos_save[i] = pko_mem_queue_qos;
        pko_mem_queue_qos.s.qos_mask = 0;
        cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, pko_mem_queue_qos.u64);
    }

    /* Disable backpressure */
    gmx_tx_ovr_bp.u64 = cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface));
    gmx_tx_ovr_bp_save = gmx_tx_ovr_bp;
    gmx_tx_ovr_bp.s.bp &= ~(1<<index);
    gmx_tx_ovr_bp.s.en |= 1<<index;
    cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp.u64);
    cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface));

    /* Poll the GMX state machine waiting for it to become idle. Preferably we
        should only change speed when it is idle. If it doesn't become idle we
        will still do the speed change, but there is a slight chance that GMX
        will lockup */
    cvmx_write_csr(CVMX_NPI_DBG_SELECT, interface*0x800 + index*0x100 + 0x880);
    CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&7, ==, 0, 10000);
    CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&0xf, ==, 0, 10000);

    /* Disable the port before we make any changes */
    new_gmx_cfg.s.en = 0;
    cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64);
    cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));

    /* Set full/half duplex */
    if (!link_info.s.link_up)
        new_gmx_cfg.s.duplex = 1;   /* Force full duplex on down links */
    else
        new_gmx_cfg.s.duplex = link_info.s.full_duplex;

    /* Set the link speed. Anything unknown is set to 1Gbps */
    if (link_info.s.speed == 10)
    {
        new_gmx_cfg.s.slottime = 0;
        new_gmx_cfg.s.speed = 0;
    }
    else if (link_info.s.speed == 100)
    {
        new_gmx_cfg.s.slottime = 0;
        new_gmx_cfg.s.speed = 0;
    }
    else
    {
        new_gmx_cfg.s.slottime = 1;
        new_gmx_cfg.s.speed = 1;
    }

    /* Adjust the clocks */
    if (link_info.s.speed == 10)
    {
        cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 50);
        cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40);
        cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
    }
    else if (link_info.s.speed == 100)
    {
        cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 5);
        cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40);
        cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
    }
    else
    {
        cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1);
        cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200);
        cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000);
    }

    if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
    {
        if ((link_info.s.speed == 10) || (link_info.s.speed == 100))
        {
            cvmx_gmxx_inf_mode_t mode;
            mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));

            /*
            ** Port  .en  .type  .p0mii  Configuration
            ** ----  ---  -----  ------  -----------------------------------------
            **  X      0     X      X    All links are disabled.
            **  0      1     X      0    Port 0 is RGMII
            **  0      1     X      1    Port 0 is MII
            **  1      1     0      X    Ports 1 and 2 are configured as RGMII ports.
            **  1      1     1      X    Port 1: GMII/MII; Port 2: disabled. GMII or
            **                           MII port is selected by GMX_PRT1_CFG[SPEED].
            */

            /* In MII mode, CLK_CNT = 1. */
            if (((index == 0) && (mode.s.p0mii == 1)) || ((index != 0) && (mode.s.type == 1)))
            {
                cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1);
            }
        }
    }

    /* Do a read to make sure all setup stuff is complete */
    cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));

    /* Save the new GMX setting without enabling the port */
    cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64);

    /* Enable the lowest level RX */
    cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface),
                   cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) | (1<<index));

    /* Re-enable the TX path */
    for (i=0; i<cvmx_pko_get_num_queues(ipd_port); i++)
    {
        int queue = cvmx_pko_get_base_queue(ipd_port) + i;
        cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue);
        cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, pko_mem_queue_qos_save[i].u64);
    }

    /* Restore backpressure */
    cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp_save.u64);

    /* Restore the GMX enable state. Port config is complete */
    new_gmx_cfg.s.en = original_gmx_cfg.s.en;
    cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64);

    return result;
}
Exemple #6
0
/**
 * @INTERNAL
 * Configure all of the ASX, GMX, and PKO regsiters required
 * to get RGMII to function on the supplied interface.
 *
 * @param interface PKO Interface to configure (0 or 1)
 *
 * @return Zero on success
 */
int __cvmx_helper_rgmii_enable(int interface)
{
    int num_ports = cvmx_helper_ports_on_interface(interface);
    int port;
    cvmx_gmxx_inf_mode_t mode;
    cvmx_asxx_tx_prt_en_t asx_tx;
    cvmx_asxx_rx_prt_en_t asx_rx;

    mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));

    if (mode.s.en == 0)
        return -1;
    if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) && mode.s.type == 1)   /* Ignore SPI interfaces */
        return -1;

    /* Configure the ASX registers needed to use the RGMII ports */
    asx_tx.u64 = 0;
    asx_tx.s.prt_en = cvmx_build_mask(num_ports);
    cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), asx_tx.u64);

    asx_rx.u64 = 0;
    asx_rx.s.prt_en = cvmx_build_mask(num_ports);
    cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), asx_rx.u64);

    /* Configure the GMX registers needed to use the RGMII ports */
    for (port=0; port<num_ports; port++)
    {
        /* Setting of CVMX_GMXX_TXX_THRESH has been moved to
            __cvmx_helper_setup_gmx() */

        /* Configure more flexible RGMII preamble checking. Pass 1 doesn't
           support this feature. */
        cvmx_gmxx_rxx_frm_ctl_t frm_ctl;
        frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface));
        frm_ctl.s.pre_free = 1;  /* New field, so must be compile time */
        cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface), frm_ctl.u64);

        /* Each pause frame transmitted will ask for about 10M bit times
            before resume.  If buffer space comes available before that time
            has expired, an XON pause frame (0 time) will be transmitted to
            restart the flow. */
        cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_TIME(port, interface), 20000);
        cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL(port, interface), 19000);

        /*
         * Board types we have to know at compile-time.
         */
#if defined(OCTEON_BOARD_CAPK_0100ND)
        cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 26);
        cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 26);
#else
	/*
	 * Vendor-defined board types.
	 */
#if defined(OCTEON_VENDOR_LANNER)
	switch (cvmx_sysinfo_get()->board_type) {
	case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
	case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
            if (port == 0) {
                cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 4);
	    } else {
                cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 7);
            }
            cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 0);
	    break;
	}
#else
        /*
         * For board types we can determine at runtime.
         */
        if (OCTEON_IS_MODEL(OCTEON_CN50XX))
        {
            cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 16);
            cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 16);
        }
        else
        {
            cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 24);
            cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 24);
        }
#endif
#endif
    }

    __cvmx_helper_setup_gmx(interface, num_ports);

    /* enable the ports now */
    for (port=0; port<num_ports; port++)
    {
        cvmx_gmxx_prtx_cfg_t gmx_cfg;
        cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, port));
        gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(port, interface));
        gmx_cfg.s.en = 1;
        cvmx_write_csr(CVMX_GMXX_PRTX_CFG(port, interface), gmx_cfg.u64);
    }
    return 0;
}
Exemple #7
0
/*
 * Read QLM and return status based on CN66XX.
 * @return  Return 1 if QLM is SGMII
 *                 2 if QLM is XAUI
 *                 3 if QLM is PCIe gen2 / gen1
 *                 4 if QLM is SRIO 1x4 short / long
 *                 5 if QLM is SRIO 2x2 short / long
 *                 6 if QLM is SRIO 4x1 short / long
 *                 7 if QLM is PCIe 1x2 gen2 / gen1
 *                 8 if QLM is PCIe 2x1 gen2 / gen1
 *                 9 if QLM is ILK
 *                 10 if QLM is RXAUI
 *                 -1 otherwise
 */
int cvmx_qlm_get_status(int qlm)
{
    cvmx_mio_qlmx_cfg_t qlmx_cfg;

    if (OCTEON_IS_MODEL(OCTEON_CN68XX))
    {
        qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
        /* QLM is disabled when QLM SPD is 15. */
        if (qlmx_cfg.s.qlm_spd == 15)
            return  -1;

        switch (qlmx_cfg.s.qlm_cfg)
        {
            case 0: /* PCIE */
                return 3;
            case 1: /* ILK */
                return 9;
            case 2: /* SGMII */
                return 1;
            case 3: /* XAUI */
                return 2;
            case 7: /* RXAUI */
                return 10;
            default: return -1;
        }
    }
    else if (OCTEON_IS_MODEL(OCTEON_CN66XX))
    {
        qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
        /* QLM is disabled when QLM SPD is 15. */
        if (qlmx_cfg.s.qlm_spd == 15)
            return  -1;

        switch (qlmx_cfg.s.qlm_cfg)
        {
            case 0x9: /* SGMII */
                return 1;
            case 0xb: /* XAUI */
                return 2;
            case 0x0: /* PCIE gen2 */
            case 0x8: /* PCIE gen2 (alias) */
            case 0x2: /* PCIE gen1 */
            case 0xa: /* PCIE gen1 (alias) */
                return 3;
            case 0x1: /* SRIO 1x4 short */
            case 0x3: /* SRIO 1x4 long */
                return 4;
            case 0x4: /* SRIO 2x2 short */
            case 0x6: /* SRIO 2x2 long */
                return 5;
            case 0x5: /* SRIO 4x1 short */
            case 0x7: /* SRIO 4x1 long */
                if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
                    return 6;
            default:
                return -1;
        }
    }
    else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
    {
        cvmx_sriox_status_reg_t status_reg;
        /* For now skip qlm2 */
        if (qlm == 2)
        {
            cvmx_gmxx_inf_mode_t inf_mode;
            inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
            if (inf_mode.s.speed == 15) 
                return -1;
            else if(inf_mode.s.mode == 0)
                return 1;
            else
                return 2;
        }
        status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm));
        if (status_reg.s.srio)
            return 4;
        else
            return 3;
    }
    else if (OCTEON_IS_MODEL(OCTEON_CN61XX))
    {
        qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
        /* QLM is disabled when QLM SPD is 15. */
        if (qlmx_cfg.s.qlm_spd == 15)
            return  -1;

        switch(qlm)
        {
            case 0:
                switch (qlmx_cfg.s.qlm_cfg)
                {
                    case 0: /* PCIe 1x4 gen2 / gen1 */
                        return 3;
                    case 2: /* SGMII */
                        return 1;
                    case 3: /* XAUI */
                        return 2;
                    default: return -1;
                }
                break;
            case 1:
                switch (qlmx_cfg.s.qlm_cfg)
                {
                    case 0: /* PCIe 1x2 gen2 / gen1 */
                        return 7;
                    case 1: /* PCIe 2x1 gen2 / gen1 */
                        return 8;
                    default: return -1;
                }
                break;
            case 2:
                switch (qlmx_cfg.s.qlm_cfg)
                {
                    case 2: /* SGMII */
                        return 1;
                    case 3: /* XAUI */
                        return 2;
                    default: return -1;
                }
                break;
        }
    }
    else if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
    {
        qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
        /* QLM is disabled when QLM SPD is 15. */
        if (qlmx_cfg.s.qlm_spd == 15)
            return  -1;

        switch(qlm)
        {
            case 0:
                if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */
                    return 1;
                break;
            case 1:
                switch (qlmx_cfg.s.qlm_cfg)
                {
                    case 0: /* PCIe 1x2 gen2 / gen1 */
                        return 7;
                    case 1: /* PCIe 2x1 gen2 / gen1 */
                        return 8;
                    default: return -1;
                }
                break;
        }
    }
    return -1;
}
Exemple #8
0
/**
 * Get the speed (Gbaud) of the QLM in Mhz.
 *
 * @param qlm    QLM to examine
 *
 * @return Speed in Mhz
 */
int cvmx_qlm_get_gbaud_mhz(int qlm)
{
    if (OCTEON_IS_MODEL(OCTEON_CN63XX))
    {
        if (qlm == 2)
        {
            cvmx_gmxx_inf_mode_t inf_mode;
            inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
            switch (inf_mode.s.speed)
            {
                case 0: return 5000;    /* 5     Gbaud */
                case 1: return 2500;    /* 2.5   Gbaud */
                case 2: return 2500;    /* 2.5   Gbaud */
                case 3: return 1250;    /* 1.25  Gbaud */
                case 4: return 1250;    /* 1.25  Gbaud */
                case 5: return 6250;    /* 6.25  Gbaud */
                case 6: return 5000;    /* 5     Gbaud */
                case 7: return 2500;    /* 2.5   Gbaud */
                case 8: return 3125;    /* 3.125 Gbaud */
                case 9: return 2500;    /* 2.5   Gbaud */
                case 10: return 1250;   /* 1.25  Gbaud */
                case 11: return 5000;   /* 5     Gbaud */
                case 12: return 6250;   /* 6.25  Gbaud */
                case 13: return 3750;   /* 3.75  Gbaud */
                case 14: return 3125;   /* 3.125 Gbaud */
                default: return 0;      /* Disabled */
            }
        }
        else
        {
            cvmx_sriox_status_reg_t status_reg;
            status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm));
            if (status_reg.s.srio)
            {
                cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;
                sriomaintx_port_0_ctl2.u32 = cvmx_read_csr(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm));
                switch (sriomaintx_port_0_ctl2.s.sel_baud)
                {
                    case 1: return 1250;    /* 1.25  Gbaud */
                    case 2: return 2500;    /* 2.5   Gbaud */
                    case 3: return 3125;    /* 3.125 Gbaud */
                    case 4: return 5000;    /* 5     Gbaud */
                    case 5: return 6250;    /* 6.250 Gbaud */
                    default: return 0;      /* Disabled */
                }
            }
            else
            {
                cvmx_pciercx_cfg032_t pciercx_cfg032;
                pciercx_cfg032.u32 = cvmx_read_csr(CVMX_PCIERCX_CFG032(qlm));
                switch (pciercx_cfg032.s.ls)
                {
                    case 1:
                        return 2500;
                    case 2:
                        return 5000;
                    case 4:
                        return 8000;
                    default:
                    {
                        cvmx_mio_rst_boot_t mio_rst_boot;
                        mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
                        if ((qlm == 0) && mio_rst_boot.s.qlm0_spd == 0xf)
                            return 0;
                        if ((qlm == 1) && mio_rst_boot.s.qlm1_spd == 0xf)
                            return 0;
                        return 5000; /* Best guess I can make */
                    }
                }
            }
        }
    }
    else if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
    {
        cvmx_mio_qlmx_cfg_t qlm_cfg;

        qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
        switch (qlm_cfg.s.qlm_spd)
        {
            case 0: return 5000;    /* 5     Gbaud */
            case 1: return 2500;    /* 2.5   Gbaud */
            case 2: return 2500;    /* 2.5   Gbaud */
            case 3: return 1250;    /* 1.25  Gbaud */
            case 4: return 1250;    /* 1.25  Gbaud */
            case 5: return 6250;    /* 6.25  Gbaud */
            case 6: return 5000;    /* 5     Gbaud */
            case 7: return 2500;    /* 2.5   Gbaud */
            case 8: return 3125;    /* 3.125 Gbaud */
            case 9: return 2500;    /* 2.5   Gbaud */
            case 10: return 1250;   /* 1.25  Gbaud */
            case 11: return 5000;   /* 5     Gbaud */
            case 12: return 6250;   /* 6.25  Gbaud */
            case 13: return 3750;   /* 3.75  Gbaud */
            case 14: return 3125;   /* 3.125 Gbaud */
            default: return 0;      /* Disabled */
        }
    }
    return 0;
}
/**
 * Configure all of the ASX, GMX, and PKO regsiters required
 * to get RGMII to function on the supplied interface.
 *
 * @interface: PKO Interface to configure (0 or 1)
 *
 * Returns Zero on success
 */
int __cvmx_helper_rgmii_enable(int interface)
{
	int num_ports = cvmx_helper_ports_on_interface(interface);
	int port;
	struct cvmx_sysinfo *sys_info_ptr = cvmx_sysinfo_get();
	union cvmx_gmxx_inf_mode mode;
	union cvmx_asxx_tx_prt_en asx_tx;
	union cvmx_asxx_rx_prt_en asx_rx;

	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));

	if (mode.s.en == 0)
		return -1;
	if ((OCTEON_IS_MODEL(OCTEON_CN38XX) ||
	     OCTEON_IS_MODEL(OCTEON_CN58XX)) && mode.s.type == 1)
		/* Ignore SPI interfaces */
		return -1;

	/* Configure the ASX registers needed to use the RGMII ports */
	asx_tx.u64 = 0;
	asx_tx.s.prt_en = cvmx_build_mask(num_ports);
	cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), asx_tx.u64);

	asx_rx.u64 = 0;
	asx_rx.s.prt_en = cvmx_build_mask(num_ports);
	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), asx_rx.u64);

	/* Configure the GMX registers needed to use the RGMII ports */
	for (port = 0; port < num_ports; port++) {
		/* Setting of CVMX_GMXX_TXX_THRESH has been moved to
		   __cvmx_helper_setup_gmx() */

		if (cvmx_octeon_is_pass1())
			__cvmx_helper_errata_asx_pass1(interface, port,
						       sys_info_ptr->
						       cpu_clock_hz);
		else {
			/*
			 * Configure more flexible RGMII preamble
			 * checking. Pass 1 doesn't support this
			 * feature.
			 */
			union cvmx_gmxx_rxx_frm_ctl frm_ctl;
			frm_ctl.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
					  (port, interface));
			/* New field, so must be compile time */
			frm_ctl.s.pre_free = 1;
			cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface),
				       frm_ctl.u64);
		}

		/*
		 * Each pause frame transmitted will ask for about 10M
		 * bit times before resume.  If buffer space comes
		 * available before that time has expired, an XON
		 * pause frame (0 time) will be transmitted to restart
		 * the flow.
		 */
		cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_TIME(port, interface),
			       20000);
		cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL
			       (port, interface), 19000);

		if (OCTEON_IS_MODEL(OCTEON_CN50XX)) {
			cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface),
				       16);
			cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface),
				       16);
		} else {
			cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface),
				       24);
			cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface),
				       24);
		}
	}

	__cvmx_helper_setup_gmx(interface, num_ports);

	/* enable the ports now */
	for (port = 0; port < num_ports; port++) {
		union cvmx_gmxx_prtx_cfg gmx_cfg;
		cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port
					  (interface, port));
		gmx_cfg.u64 =
		    cvmx_read_csr(CVMX_GMXX_PRTX_CFG(port, interface));
		gmx_cfg.s.en = 1;
		cvmx_write_csr(CVMX_GMXX_PRTX_CFG(port, interface),
			       gmx_cfg.u64);
	}
	__cvmx_interrupt_asxx_enable(interface);
	__cvmx_interrupt_gmxx_enable(interface);

	return 0;
}
Exemple #10
0
static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn6xxx(int qlm)
{
	cvmx_mio_qlmx_cfg_t qlmx_cfg;

	if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
		qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
		/* QLM is disabled when QLM SPD is 15. */
		if (qlmx_cfg.s.qlm_spd == 15)
			return CVMX_QLM_MODE_DISABLED;

		switch (qlmx_cfg.s.qlm_cfg) {
		case 0:	/* PCIE */
			return CVMX_QLM_MODE_PCIE;
		case 1:	/* ILK */
			return CVMX_QLM_MODE_ILK;
		case 2:	/* SGMII */
			return CVMX_QLM_MODE_SGMII;
		case 3:	/* XAUI */
			return CVMX_QLM_MODE_XAUI;
		case 7:	/* RXAUI */
			return CVMX_QLM_MODE_RXAUI;
		default:
			return CVMX_QLM_MODE_DISABLED;
		}
	} else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
		qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
		/* QLM is disabled when QLM SPD is 15. */
		if (qlmx_cfg.s.qlm_spd == 15)
			return CVMX_QLM_MODE_DISABLED;

		switch (qlmx_cfg.s.qlm_cfg) {
		case 0x9:	/* SGMII */
			return CVMX_QLM_MODE_SGMII;
		case 0xb:	/* XAUI */
			return CVMX_QLM_MODE_XAUI;
		case 0x0:	/* PCIE gen2 */
		case 0x8:	/* PCIE gen2 (alias) */
		case 0x2:	/* PCIE gen1 */
		case 0xa:	/* PCIE gen1 (alias) */
			return CVMX_QLM_MODE_PCIE;
		case 0x1:	/* SRIO 1x4 short */
		case 0x3:	/* SRIO 1x4 long */
			return CVMX_QLM_MODE_SRIO_1X4;
		case 0x4:	/* SRIO 2x2 short */
		case 0x6:	/* SRIO 2x2 long */
			return CVMX_QLM_MODE_SRIO_2X2;
		case 0x5:	/* SRIO 4x1 short */
		case 0x7:	/* SRIO 4x1 long */
			if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
				return CVMX_QLM_MODE_SRIO_4X1;
		/* fallthrough */
		default:
			return CVMX_QLM_MODE_DISABLED;
		}
	} else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
		cvmx_sriox_status_reg_t status_reg;
		/* For now skip qlm2 */
		if (qlm == 2) {
			cvmx_gmxx_inf_mode_t inf_mode;
			inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
			if (inf_mode.s.speed == 15)
				return CVMX_QLM_MODE_DISABLED;
			else if (inf_mode.s.mode == 0)
				return CVMX_QLM_MODE_SGMII;
			else
				return CVMX_QLM_MODE_XAUI;
		}
		status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm));
		if (status_reg.s.srio)
			return CVMX_QLM_MODE_SRIO_1X4;
		else
			return CVMX_QLM_MODE_PCIE;
	} else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
		qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
		/* QLM is disabled when QLM SPD is 15. */
		if (qlmx_cfg.s.qlm_spd == 15)
			return CVMX_QLM_MODE_DISABLED;

		switch (qlm) {
		case 0:
			switch (qlmx_cfg.s.qlm_cfg) {
			case 0:	/* PCIe 1x4 gen2 / gen1 */
				return CVMX_QLM_MODE_PCIE;
			case 2:	/* SGMII */
				return CVMX_QLM_MODE_SGMII;
			case 3:	/* XAUI */
				return CVMX_QLM_MODE_XAUI;
			default:
				return CVMX_QLM_MODE_DISABLED;
			}
			break;
		case 1:
			switch (qlmx_cfg.s.qlm_cfg) {
			case 0:	/* PCIe 1x2 gen2 / gen1 */
				return CVMX_QLM_MODE_PCIE_1X2;
			case 1:	/* PCIe 2x1 gen2 / gen1 */
				return CVMX_QLM_MODE_PCIE_2X1;
			default:
				return CVMX_QLM_MODE_DISABLED;
			}
			break;
		case 2:
			switch (qlmx_cfg.s.qlm_cfg) {
			case 2:	/* SGMII */
				return CVMX_QLM_MODE_SGMII;
			case 3:	/* XAUI */
				return CVMX_QLM_MODE_XAUI;
			default:
				return CVMX_QLM_MODE_DISABLED;
			}
			break;
		}
	} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
		qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
		/* QLM is disabled when QLM SPD is 15. */
		if (qlmx_cfg.s.qlm_spd == 15)
			return CVMX_QLM_MODE_DISABLED;

		switch (qlm) {
		case 0:
			if (qlmx_cfg.s.qlm_cfg == 2)	/* SGMII */
				return CVMX_QLM_MODE_SGMII;
			break;
		case 1:
			switch (qlmx_cfg.s.qlm_cfg) {
			case 0:	/* PCIe 1x2 gen2 / gen1 */
				return CVMX_QLM_MODE_PCIE_1X2;
			case 1:	/* PCIe 2x1 gen2 / gen1 */
				return CVMX_QLM_MODE_PCIE_2X1;
			default:
				return CVMX_QLM_MODE_DISABLED;
			}
			break;
		}
	}
	return CVMX_QLM_MODE_DISABLED;
}
Exemple #11
0
static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn70xx(int qlm)
{
#ifndef CVMX_BUILD_FOR_LINUX_HOST
	if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {
		union cvmx_gserx_dlmx_phy_reset phy_reset;

		phy_reset.u64 = cvmx_read_csr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
		if (phy_reset.s.phy_reset)
			return CVMX_QLM_MODE_DISABLED;

	}
#endif

	switch(qlm) {
	case 0: /* DLM0/DLM1 - SGMII/QSGMII/RXAUI */
		{
			union cvmx_gmxx_inf_mode inf_mode0, inf_mode1;

			inf_mode0.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
			inf_mode1.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(1));

			/* SGMII0 SGMII1 */
			switch (inf_mode0.s.mode) {
			case CVMX_GMX_INF_MODE_SGMII:
				switch (inf_mode1.s.mode) {
				case CVMX_GMX_INF_MODE_SGMII:
					return CVMX_QLM_MODE_SGMII_SGMII;
				case CVMX_GMX_INF_MODE_QSGMII:
					return CVMX_QLM_MODE_SGMII_QSGMII;
				default:
					return CVMX_QLM_MODE_SGMII_DISABLED;
				}
			case CVMX_GMX_INF_MODE_QSGMII:
				switch (inf_mode1.s.mode) {
				case CVMX_GMX_INF_MODE_SGMII:
					return CVMX_QLM_MODE_QSGMII_SGMII;
				case CVMX_GMX_INF_MODE_QSGMII:
					return CVMX_QLM_MODE_QSGMII_QSGMII;
				default:
					return CVMX_QLM_MODE_QSGMII_DISABLED;
				}
			case CVMX_GMX_INF_MODE_RXAUI:
				return CVMX_QLM_MODE_RXAUI_1X2;
			default:
				switch (inf_mode1.s.mode) {
				case CVMX_GMX_INF_MODE_SGMII:
					return CVMX_QLM_MODE_DISABLED_SGMII;
				case CVMX_GMX_INF_MODE_QSGMII:
					return CVMX_QLM_MODE_DISABLED_QSGMII;
				default:
				return CVMX_QLM_MODE_DISABLED;
			}
		}
		}
	case 1:  /* Sata / pem0 */
		{
			union cvmx_gserx_sata_cfg sata_cfg;
			union cvmx_pemx_cfg pem0_cfg;

			sata_cfg.u64 = cvmx_read_csr(CVMX_GSERX_SATA_CFG(0));
			pem0_cfg.u64 = cvmx_read_csr(CVMX_PEMX_CFG(0));

			switch(pem0_cfg.cn70xx.md) {
			case CVMX_PEM_MD_GEN2_2LANE:
			case CVMX_PEM_MD_GEN1_2LANE:
				return CVMX_QLM_MODE_PCIE_1X2;
			case CVMX_PEM_MD_GEN2_1LANE:
			case CVMX_PEM_MD_GEN1_1LANE:
				if (sata_cfg.s.sata_en)
					/* Both PEM0 and PEM1 */
					return CVMX_QLM_MODE_PCIE_2X1;
				else
					/* Only PEM0 */
					return CVMX_QLM_MODE_PCIE_1X1;
			case CVMX_PEM_MD_GEN2_4LANE:
			case CVMX_PEM_MD_GEN1_4LANE:
				return CVMX_QLM_MODE_PCIE;
			default:
				return CVMX_QLM_MODE_DISABLED;
			}
		}
	case 2:
		{
			union cvmx_gserx_sata_cfg sata_cfg;
			union cvmx_pemx_cfg pem0_cfg, pem1_cfg, pem2_cfg;

			sata_cfg.u64 = cvmx_read_csr(CVMX_GSERX_SATA_CFG(0));
			pem0_cfg.u64 = cvmx_read_csr(CVMX_PEMX_CFG(0));
			pem1_cfg.u64 = cvmx_read_csr(CVMX_PEMX_CFG(1));
			pem2_cfg.u64 = cvmx_read_csr(CVMX_PEMX_CFG(2));

			if (sata_cfg.s.sata_en)
				return CVMX_QLM_MODE_SATA_2X1;
			if (pem0_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_4LANE
			    || pem0_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_4LANE)
				return CVMX_QLM_MODE_PCIE;
			if (pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_2LANE
			    || pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_2LANE) {
				return CVMX_QLM_MODE_PCIE_1X2;
			}
			if (pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE
			    || pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE) {
				if (pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE
				    || pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE) {
					return CVMX_QLM_MODE_PCIE_2X1;
				} else
					return CVMX_QLM_MODE_PCIE_1X1;
			}
			if (pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE
			    || pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE)
				return CVMX_QLM_MODE_PCIE_2X1;
			return CVMX_QLM_MODE_DISABLED;
		}
	default:
		return CVMX_QLM_MODE_DISABLED;
	}

	return CVMX_QLM_MODE_DISABLED;
}
Exemple #12
0
/**
 * Get the speed (Gbaud) of the QLM in Mhz.
 *
 * @param qlm    QLM to examine
 *
 * @return Speed in Mhz
 */
int cvmx_qlm_get_gbaud_mhz(int qlm)
{
	if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
		if (qlm == 2) {
			cvmx_gmxx_inf_mode_t inf_mode;
			inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0));
			switch (inf_mode.s.speed) {
			case 0:
				return 5000;	/* 5     Gbaud */
			case 1:
				return 2500;	/* 2.5   Gbaud */
			case 2:
				return 2500;	/* 2.5   Gbaud */
			case 3:
				return 1250;	/* 1.25  Gbaud */
			case 4:
				return 1250;	/* 1.25  Gbaud */
			case 5:
				return 6250;	/* 6.25  Gbaud */
			case 6:
				return 5000;	/* 5     Gbaud */
			case 7:
				return 2500;	/* 2.5   Gbaud */
			case 8:
				return 3125;	/* 3.125 Gbaud */
			case 9:
				return 2500;	/* 2.5   Gbaud */
			case 10:
				return 1250;	/* 1.25  Gbaud */
			case 11:
				return 5000;	/* 5     Gbaud */
			case 12:
				return 6250;	/* 6.25  Gbaud */
			case 13:
				return 3750;	/* 3.75  Gbaud */
			case 14:
				return 3125;	/* 3.125 Gbaud */
			default:
				return 0;	/* Disabled */
			}
		} else {
			cvmx_sriox_status_reg_t status_reg;
			status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm));
			if (status_reg.s.srio) {
				cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;
				sriomaintx_port_0_ctl2.u32 = cvmx_read_csr(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm));
				switch (sriomaintx_port_0_ctl2.s.sel_baud) {
				case 1:
					return 1250;	/* 1.25  Gbaud */
				case 2:
					return 2500;	/* 2.5   Gbaud */
				case 3:
					return 3125;	/* 3.125 Gbaud */
				case 4:
					return 5000;	/* 5     Gbaud */
				case 5:
					return 6250;	/* 6.250 Gbaud */
				default:
					return 0;	/* Disabled */
				}
			} else {
				cvmx_pciercx_cfg032_t pciercx_cfg032;
				pciercx_cfg032.u32 = cvmx_read_csr(CVMX_PCIERCX_CFG032(qlm));
				switch (pciercx_cfg032.s.ls) {
				case 1:
					return 2500;
				case 2:
					return 5000;
				case 4:
					return 8000;
				default:
					{
						cvmx_mio_rst_boot_t mio_rst_boot;
						mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
						if ((qlm == 0) && mio_rst_boot.s.qlm0_spd == 0xf)
							return 0;
						if ((qlm == 1) && mio_rst_boot.s.qlm1_spd == 0xf)
							return 0;
						return 5000;	/* Best guess I can make */
					}
				}
			}
		}
	} else if (OCTEON_IS_OCTEON2()) {
		cvmx_mio_qlmx_cfg_t qlm_cfg;

		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm));
		switch (qlm_cfg.s.qlm_spd) {
		case 0:
			return 5000;	/* 5     Gbaud */
		case 1:
			return 2500;	/* 2.5   Gbaud */
		case 2:
			return 2500;	/* 2.5   Gbaud */
		case 3:
			return 1250;	/* 1.25  Gbaud */
		case 4:
			return 1250;	/* 1.25  Gbaud */
		case 5:
			return 6250;	/* 6.25  Gbaud */
		case 6:
			return 5000;	/* 5     Gbaud */
		case 7:
			return 2500;	/* 2.5   Gbaud */
		case 8:
			return 3125;	/* 3.125 Gbaud */
		case 9:
			return 2500;	/* 2.5   Gbaud */
		case 10:
			return 1250;	/* 1.25  Gbaud */
		case 11:
			return 5000;	/* 5     Gbaud */
		case 12:
			return 6250;	/* 6.25  Gbaud */
		case 13:
			return 3750;	/* 3.75  Gbaud */
		case 14:
			return 3125;	/* 3.125 Gbaud */
		default:
			return 0;	/* Disabled */
		}
	} else if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
		cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;
		uint64_t meas_refclock;
		uint64_t freq;

		/* Measure the reference clock */
		meas_refclock = cvmx_qlm_measure_clock(qlm);
		/* Multiply to get the final frequency */
		mpll_multiplier.u64 = cvmx_read_csr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
		freq = meas_refclock * mpll_multiplier.s.mpll_multiplier;
		freq = (freq + 500000) / 1000000;
		return freq;
	}
	return 0;
}
/**
 * Enable GMX error reporting for the supplied interface
 *
 * @interface: Interface to enable
 */
void __cvmx_interrupt_gmxx_enable(int interface)
{
	union cvmx_gmxx_inf_mode mode;
	union cvmx_gmxx_tx_int_en gmx_tx_int_en;
	int num_ports;
	int index;

	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));

	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
		if (mode.s.en) {
			switch (mode.cn56xx.mode) {
			case 1:	/* XAUI */
				num_ports = 1;
				break;
			case 2:	/* SGMII */
			case 3:	/* PICMG */
				num_ports = 4;
				break;
			default:	/* Disabled */
				num_ports = 0;
				break;
			}
		} else
			num_ports = 0;
	} else {
		if (mode.s.en) {
			if (OCTEON_IS_MODEL(OCTEON_CN38XX)
			    || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
				/*
				 * SPI on CN38XX and CN58XX report all
				 * errors through port 0.  RGMII needs
				 * to check all 4 ports
				 */
				if (mode.s.type)
					num_ports = 1;
				else
					num_ports = 4;
			} else {
				/*
				 * CN30XX, CN31XX, and CN50XX have two
				 * or three ports. GMII and MII has 2,
				 * RGMII has three
				 */
				if (mode.s.type)
					num_ports = 2;
				else
					num_ports = 3;
			}
		} else
			num_ports = 0;
	}

	gmx_tx_int_en.u64 = 0;
	if (num_ports) {
		if (OCTEON_IS_MODEL(OCTEON_CN38XX)
		    || OCTEON_IS_MODEL(OCTEON_CN58XX))
			gmx_tx_int_en.s.ncb_nxa = 1;
		gmx_tx_int_en.s.pko_nxa = 1;
	}
	gmx_tx_int_en.s.undflw = (1 << num_ports) - 1;
	cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64);
	for (index = 0; index < num_ports; index++)
		__cvmx_interrupt_gmxx_rxx_int_en_enable(index, interface);
}