This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

The 6678 questions about Linux network drive

HI,

I am an developer of embedded Linux driver , I'm in the development of Linux drivers about 6678 platform, some problems encountered in the development of the network driver, I put the sgmii1 directly connected to the  network switch chip BCM5396 port, I am using Ti drive of the original development board ,but the network does not work, requests for advice,thank you。

  • Welcome to the TI E2E forum. I hope you will find many good answers here and in the TI.com documents and in the TI Wiki Pages (for processor issues). Be sure to search those for helpful information and to browse for the questions others may have asked on similar topics (e2e.ti.com). Please read all the links below my signature.

    We will get back to you on the above query shortly. Thank you for your patience.

    Thank you.

    PS: We strongly recommend you to create new e2e thread for your queries instead of following up on an old/closed e2e thread, new threads gets more attention than old threads and can provide link of old threads or information on the new post for clarity and faster response.

  • I presume that you are working c6x linux and custom board.
    I request you to elaborate your problem.
    Like what problem you are getting after you have modified the code.
    Link got up ?
    Please investigate the network registers to findout what exact problem you are getting.
  • Thank you for your reply,The phenomenon is shown in Figure:

    The first picture is normal start, but the network is not working properly,The second picture is in the process of starting the following code error:

    //keystone_netcp.c
    
    /* Request PA firmware */
    ret = request_firmware(&fw, data->pa_pdsp.firmware, &pdev->dev);
    if (ret != 0) {
    printk(KERN_ERR "PA: Cannot find %s firmware\n", data->pa_pdsp.firmware);
    return ret;
    }
    
    /* Configure the PA */
    ret = keystone_pa_config(data->pa_pdsp.pdsp, (const unsigned int*) fw->data,
    fw->size, ndev->dev_addr);
    if (ret != 0) {
    printk(KERN_ERR "%s: PA init failed\n", __FUNCTION__);
    return ret;
    }
    
    release_firmware(fw);

    The third picture is a stop here during startup

    The following is the modified code

    /*
     * Copyright (C) 2011 Texas Instruments Incorporated
     * Authors: Sandeep Paulraj <s-paulraj@ti.com>
     *          Aurelien Jacquiot <a-jacquiot@ti.com>
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License as
     * published by the Free Software Foundation version 2.
     *
     * This program is distributed "as is" WITHOUT ANY WARRANTY of any
     * kind, whether express or implied; without even the implied warranty
     * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     */
    
    #include <linux/kernel.h>
    #include <linux/delay.h>
    #include <linux/types.h>
    
    #include <asm/setup.h>
    #include <asm/machdep.h>
    #include <asm/io.h>
    #include <asm/sgmii.h>
    #include <asm/dscr.h>
    
    #include <mach/keystone_netcp.h>
    #include <mach/keystone_pa.h>
    #include <mach/keystone_qmss.h>
    #include <mach/keystone_cpsw.h>
    
    static int serdes_init(void)
    {
    #ifdef CONFIG_ARCH_BOARD_EVM6670
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGPLL, 0x00000051);
    #else
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGPLL, 0x00000041);
    #endif
    	_c6x_delay(2000);
    
    #ifdef CONFIG_ARCH_BOARD_EVMTCI6616
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGRX0, 0x00460411);
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGRX1, 0x00460411);
    
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGTX0, 0x00011F91);
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGTX1, 0x00011F91);
    #else
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGRX0, 0x00700621);
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGRX1, 0x00700621);
    
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGTX0, 0x000108A1);
    	dscr_set_reg(DSCR_SGMII_SERDES_CFGTX1, 0x000108A1);
    #endif
    	_c6x_delay(2000);
    
    	return 0;
    }	
    
    static int sgmii_init(void)
    {
    	struct sgmii_config_s sgmiic0, sgmiic1;
    
    	sgmiic0.master    = 1;
    	sgmiic0.loopback  = 0;
    	sgmiic0.autoneg   = 1;
    #ifdef CONFIG_ARCH_BOARD_EVMTCI6616
    	sgmiic0.txconfig  = 0x00011f91;
    	sgmiic0.rxconfig  = 0x00460411;
    #else
    	sgmiic0.txconfig  = 0x000108a1;
    	sgmiic0.rxconfig  = 0x00700621;
    #endif
    #ifdef CONFIG_ARCH_BOARD_EVM6670
    	sgmiic0.auxconfig = 0x00000051; /* PLL multiplier */
    #else
    	sgmiic0.auxconfig = 0x00000041; /* PLL multiplier */
    #endif
    	sgmii_config(0, &sgmiic0);
    
    	sgmiic1.master    = 1;
    	sgmiic1.loopback  = 0;
    	sgmiic1.autoneg   = 1;
    #ifdef CONFIG_ARCH_BOARD_EVMTCI6616
    	sgmiic0.txconfig  = 0x00011f91;
    	sgmiic0.rxconfig  = 0x00460411;
    #else
    	sgmiic1.txconfig  = 0x000108a1;
    	sgmiic1.rxconfig  = 0x00700621;
    #endif
    #ifdef CONFIG_ARCH_BOARD_EVM6670
    	sgmiic0.auxconfig = 0x00000051; /* PLL multiplier */
    #else
    	sgmiic1.auxconfig = 0x00000041; /* PLL multiplier */
    #endif
    	sgmii_config(1, &sgmiic1);
    
    	printk("SGMII init complete\n");
    
    	return 0;
    }
    
    static int hw_cpsw_config(u32 ctl, u32 max_pkt_size)
    {
    	u32 i;
    
    	/* Max length register */
    	__raw_writel(max_pkt_size, (DEVICE_CPSW_BASE + CPSW_REG_MAXLEN));
    	
    	/* Control register */
    	__raw_writel(ctl, (DEVICE_CPSW_BASE + CPSW_REG_CTL));
    	
    	/* All statistics enabled by default */
    	__raw_writel(CPSW_REG_VAL_STAT_ENABLE_ALL, (DEVICE_CPSW_BASE +
    						    CPSW_REG_STAT_PORT_EN));
    	
    	/* Reset and enable the ALE */
    	__raw_writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE, (DEVICE_CPSW_BASE
    							     + CPSW_REG_ALE_CONTROL));
        
    	/* All ports put into forward mode */
    	for (i = 0; i < CPSW_NUM_PORTS; i++)
    		__raw_writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE,
    			     (DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)));
    	
    	return 0;
    }
    
    int evm_pa_ss_init(void)
    {	
    	/* Reset SGMII */
    	sgmii_reset(0);
    	sgmii_reset(1);
    
    	/* SERDES init */
    	serdes_init();
    	/* Configure the SGMII */
    	sgmii_init();
    	/* Enable port 0 with max pkt size to 9000 */
    	hw_cpsw_config(CPSW_CTL_P0_ENABLE, 9000);
    	
    	return 0;
    }
    
    arch_initcall(evm_pa_ss_init);
    

    //keystone_netcp.c

    static int __devinit netcp_probe(struct platform_device *pdev)
    {
    	struct netcp_platform_data *data = pdev->dev.platform_data;
    	struct net_device	   *ndev;
    	struct netcp_priv          *priv;
    	int                         i, ret = 0;
    #ifdef EMAC_ARCH_HAS_MAC_ADDR
    	u8			    hw_emac_addr[6];
    #endif
    	u32                         acc_ram;
    	struct pktdma_rx_cfg	    c_rx_cfg;
    	struct pktdma_tx_cfg	    c_tx_cfg;
    	struct qm_config	    c_q_cfg;
    	struct pktdma_rx_cfg	   *rx_cfg = &c_rx_cfg;
    	struct pktdma_tx_cfg	   *tx_cfg = &c_tx_cfg;
    	struct qm_config	   *q_cfg  = &c_q_cfg; 
    	const struct firmware      *fw;
    
    	if (!data) {
    		pr_err("KeyStone NetCP: platform data missing\n");
    		return -ENODEV;
    	}
    
    	ndev = alloc_etherdev(sizeof(struct netcp_priv));
    	if (!ndev) {
    		pr_err("KeyStone NetCP: error allocating net_device\n");
    		return -ENOMEM;
    	}
    
    	platform_set_drvdata(pdev, ndev);
    	priv = netdev_priv(ndev);
    	spin_lock_init(&priv->lock);
    	priv->data = *data;
    	priv->pdev = pdev;
    	priv->ndev = ndev;
    	priv->dev  = &ndev->dev;
    	priv->msg_enable = netif_msg_init(debug_level, NETCP_DEBUG);
    	priv->rx_packet_max = max(rx_packet_max, 128);
    
    	/* MII/MDIO init */
    	priv->msg_enable        = NETIF_MSG_LINK;
    	priv->mii.advertising   = ADVERTISED_1000baseT_Full;
    	priv->mii.phy_id        = data->phy_id;
    	priv->mii.phy_id_mask   = 0x1f;
    	priv->mii.reg_num_mask  = 0x1f;
    	priv->mii.force_media   = 1;
    	priv->mii.full_duplex   = 1;
    	priv->mii.supports_gmii = 1;
    	priv->mii.dev	        = ndev;
    	priv->mii.mdio_read     = netcp_mdio_read;
    	priv->mii.mdio_write    = netcp_mdio_write;
    
    	netcp_mdio_init();
    
    #ifdef EMAC_ARCH_HAS_MAC_ADDR
    	/* SoC or board hw has MAC address */
    	if (config.enetaddr[0] == 0 && config.enetaddr[1] == 0 &&
    	    config.enetaddr[2] == 0 && config.enetaddr[3] == 0 &&
    	    config.enetaddr[4] == 0 && config.enetaddr[5] == 0) {
    		if (!emac_arch_get_mac_addr(hw_emac_addr))
    			for (i = 0; i <= 5; i++)
    				config.enetaddr[i] = hw_emac_addr[i] & 0xff;
    	}
    #endif
    
    	if (is_valid_ether_addr(config.enetaddr))
    		memcpy(ndev->dev_addr, config.enetaddr, ETH_ALEN);
    	else
    		random_ether_addr(ndev->dev_addr);
    
    	/* Use internal link RAM according to SPRUGR9B section 4.1.1.3 */
    	q_cfg->link_ram_base		= 0x00080000;
    	q_cfg->link_ram_size		= 0x3FFF;
    
    	/* Allocate memory for descriptors */
    	acc_ram = qm_mem_alloc(DEVICE_QM_ACC_RAM_SIZE, (u32*)&q_cfg->mem_region_base);
    	if (!acc_ram) {
    		printk(KERN_ERR "%s: descriptor memory allocation failed\n", 
    		       __FUNCTION__);
    		return -ENOMEM;
    	}
    	    
    	q_cfg->mem_regnum_descriptors	= DEVICE_NUM_DESCS;
    	q_cfg->dest_q			= DEVICE_QM_ETH_FREE_Q;
    
    	memset((void *) acc_ram, 0, DEVICE_QM_ACC_RAM_SIZE);
    
    #ifdef EMAC_ARCH_HAS_INTERRUPT
    	/* Request QM accumulator firmware */
    	ret = request_firmware(&fw, data->qm_pdsp.firmware, &pdev->dev);
    	if (ret != 0) {
    		printk(KERN_ERR "QM: Cannot find  %s firmware\n", data->qm_pdsp.firmware);
    		return ret;
    	}
    
    	/* load QM PDSP firmwares for accumulators */
    	q_cfg->pdsp_firmware[0].id       = data->qm_pdsp.pdsp; 
    	q_cfg->pdsp_firmware[0].firmware = (unsigned int *) fw->data;
    	q_cfg->pdsp_firmware[0].size     = fw->size;;
    #else
    	q_cfg->pdsp_firmware[0].firmware = NULL;
    #endif
    	q_cfg->pdsp_firmware[1].firmware = NULL;
    
    	/* Initialize QM */
    	hw_qm_setup(q_cfg);
    	release_firmware(fw);
    
    	/* Configure Rx and Tx PKTDMA */
    	rx_cfg->rx_base          = DEVICE_PA_CDMA_RX_CHAN_CFG_BASE;
    	rx_cfg->n_rx_chans       = DEVICE_PA_CDMA_RX_NUM_CHANNELS;
    	rx_cfg->flow_base        = DEVICE_PA_CDMA_RX_FLOW_CFG_BASE;
    	rx_cfg->nrx_flows        = DEVICE_PA_CDMA_RX_NUM_FLOWS;
    	rx_cfg->qmnum_free_buf   = 0;
    	rx_cfg->queue_free_buf   = DEVICE_QM_ETH_RX_FREE_Q;
    	rx_cfg->qmnum_rx         = 0;
    	rx_cfg->queue_rx         = DEVICE_QM_ETH_RX_Q;
    	rx_cfg->tdown_poll_count = DEVICE_RX_CDMA_TIMEOUT_COUNT;
    #ifndef EMAC_ARCH_HAS_INTERRUPT
    	rx_cfg->use_acc          = 0;
    #else
    	rx_cfg->use_acc          = 1;
    	rx_cfg->acc_threshold    = DEVICE_RX_INT_THRESHOLD;
    	rx_cfg->acc_channel      = DEVICE_QM_ETH_ACC_RX_CHANNEL;
    	
    	/* Set the accumulator list memory in the descriptor memory */
    	acc_list_addr_rx = (u32*) qm_mem_alloc(((rx_cfg->acc_threshold + 1) * 2) << 2,
    					       (u32*)&acc_list_phys_addr_rx);
    	if (acc_list_addr_rx == NULL) {
    		printk(KERN_ERR "%s: accumulator memory allocation failed\n",
    		       __FUNCTION__);
    		return -ENOMEM;
    	}
    	memset((void *) acc_list_addr_rx, 0, ((rx_cfg->acc_threshold + 1) * 2) << 2);
    	
    	rx_cfg->acc_list_addr      = (u32) acc_list_addr_rx;
    	rx_cfg->acc_list_phys_addr = (u32) acc_list_phys_addr_rx;
    #endif
    
    	pktdma_rx_config(rx_cfg);
    
    	tx_cfg->gbl_ctl_base     = DEVICE_PA_CDMA_GLOBAL_CFG_BASE;
    	tx_cfg->tx_base          = DEVICE_PA_CDMA_TX_CHAN_CFG_BASE;
    	tx_cfg->n_tx_chans       = DEVICE_PA_CDMA_TX_NUM_CHANNELS;
    	tx_cfg->queue_tx         = DEVICE_QM_ETH_TX_CP_Q;
    #ifndef EMAC_ARCH_HAS_INTERRUPT
    	tx_cfg->use_acc          = 0;
    #else
    	tx_cfg->use_acc          = 1;
    	tx_cfg->acc_threshold    = DEVICE_TX_INT_THRESHOLD;
    	tx_cfg->acc_channel      = DEVICE_QM_ETH_ACC_TX_CHANNEL;
    	
    	/* Set the accumulator list memory in the descriptor memory */
    	acc_list_addr_tx = (u32*) qm_mem_alloc(((tx_cfg->acc_threshold + 1) * 2) << 2,
    					       (u32*)&acc_list_phys_addr_tx);
    	if (acc_list_addr_tx == NULL) {
    		printk(KERN_ERR "%s: accumulator memory allocation failed\n",
    		       __FUNCTION__);
    		return -ENOMEM;
    	}
    	memset((void *) acc_list_addr_tx, 0, ((tx_cfg->acc_threshold + 1) * 2) << 2);
    	
    	tx_cfg->acc_list_addr      = (u32) acc_list_addr_tx;
    	tx_cfg->acc_list_phys_addr = (u32) acc_list_phys_addr_tx;
    #endif
    
    	pktdma_tx_config(tx_cfg);
    
    	/* Initialize QMSS/PKTDMA queues */
    	netcp_cleanup_qs(ndev);
    	netcp_init_qs(ndev);
    
    	/* Stop EMAC */
    	cpmac_drv_stop();
    
    	/* Streaming switch configuration */
    	streaming_switch_setup();
    
    	/* Reset the PA */
    	ret = keystone_pa_reset();
    	if (ret != 0) {
    		printk(KERN_ERR "%s: PA reset failed d\n", __FUNCTION__);
    		return ret;
    	}
    
    	/* Request PA firmware */
    	ret = request_firmware(&fw, data->pa_pdsp.firmware, &pdev->dev);
    	if (ret != 0) {
    		printk(KERN_ERR "PA: Cannot find  %s firmware\n", data->pa_pdsp.firmware);
    		return ret;
    	}
    
    	/* Configure the PA */
    	ret = keystone_pa_config(data->pa_pdsp.pdsp, (const unsigned int*) fw->data,
    				 fw->size, ndev->dev_addr);
    	if (ret != 0) {
    		printk(KERN_ERR "%s: PA init failed\n", __FUNCTION__);
    		return ret;
    	}
    
    	release_firmware(fw);
    
    	/* Setup Ethernet driver function */
    	ether_setup(ndev);
    
    	/* NAPI register */
    	netif_napi_add(ndev, &priv->napi, netcp_poll, DEVICE_NAPI_WEIGHT);
    
    #ifdef EMAC_ARCH_HAS_INTERRUPT
    	/* Register interrupts */
    	ret = request_irq(data->rx_irq, netcp_rx_interrupt, 0, ndev->name, ndev);
    	if (ret == 0) {
    		ret = request_irq(data->tx_irq, netcp_tx_interrupt, 0, ndev->name, ndev);
    		if (ret != 0) {
    			printk(KERN_ERR "%s: irq %d register failed (%d)\n",
    			       __FUNCTION__, data->tx_irq, ret);
    			return -EINVAL;
    		}
    		ndev->irq = data->rx_irq;
    	} else {
    		printk(KERN_WARNING "%s: irq mode failed (%d), use polling\n", 
    		       __FUNCTION__, ret);
    		ndev->irq = -1;
    	}
    
    #else
    	ndev->irq = -1;
    #endif
    
    	/* Register the network device */
    	ndev->dev_id         = 0;
    	ndev->watchdog_timeo = DEVICE_TX_TIMEOUT;
    	ndev->netdev_ops     = &keystone_netdev_ops;
    
    	SET_ETHTOOL_OPS(ndev, &netcp_ethtool_ops);
    	SET_NETDEV_DEV(ndev, &pdev->dev);
    
    	ret = register_netdev(ndev);
    	if (ret) {
    		printk(KERN_ERR "%s: error registering net device\n",__FUNCTION__);
    		ret = -ENODEV;
    		goto clean_ndev_ret;
    	}
    
    	return 0;
    
    clean_ndev_ret:
    	free_netdev(ndev);
    	return ret;
    }