Пример #1
0
/*
 *    Disable QuarterDeck Interrupt.
*/
GT_STATUS sampleQDIntDisable(GT_QD_DEV *dev)
{
    GT_STATUS status;
    GT_LPORT port;

    /*
     *    Writing 0 into eventSetActive(), all port interrupt will be disabled.
    */
    if((status = eventSetActive(dev,0)) != GT_OK)
    {
        MSG_PRINT(("eventSetActive returned fail.\n"));
        return status;
    }

    /*
     *    Writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
    */
    for(port=0; port<3; port++)
    {
        if((status = gprtPhyIntEnable(dev,port,0)) != GT_OK)
        {
            MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
            return status;
        }
    }
    return GT_OK;
}
Пример #2
0
/*
 *    To enable quarterDeck interrupt, you need to call eventSetActive() and
 *    gprtPhyIntEnable(), as following sample routine.
 *    sampleQDIntEnable will enable all interrupt causes.
 *    For Port, GT_ATU_FULL, GT_ATU_DONE, GT_PHY_INTERRUPT, and GT_EE_INTERRUPT
 *    are enabled.
 *
 *    In this sample, GT_SPEED_CHANGED, GT_DUPLEX_CHANGED, and
 *  GT_LINK_STATUS_CHANGED are enabled for ports 0 ~ 2.
*/
GT_STATUS sampleQDIntEnable(GT_QD_DEV *dev)
{
    GT_STATUS status;
    GT_LPORT port;
    GT_U16 data;

    /*
     *    Enable QuarterDeck interrupt for ATUFull, ATUDone, PHYInt, and EEInt.
     *    If writing 0 into eventSetActive(), all port interrupt will be disabled.
    */
    data = GT_STATS_DONE|GT_VTU_PROB|GT_VTU_DONE|
           GT_ATU_FULL|GT_ATU_DONE|GT_EE_INTERRUPT;
/*           GT_ATU_FULL|GT_ATU_DONE|GT_PHY_INTERRUPT|GT_EE_INTERRUPT; */
    if((status = eventSetActive(dev,data)) != GT_OK)
    {
        MSG_PRINT(("eventSetActive returned fail.\n"));
        return status;
    }

    /*
     *    Enable Phy interrupt for every possible interrupt cause.
     *    If writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
    */
    data =     GT_SPEED_CHANGED|GT_DUPLEX_CHANGED|GT_LINK_STATUS_CHANGED;

    for(port=0; port<3; port++)
    {
        if((status = gprtPhyIntEnable(dev,port,data)) != GT_OK)
        {
            MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
            return status;
        }
    }

    return GT_OK;
}
Пример #3
0
GT_STATUS samplePTPInit(GT_QD_DEV *dev)
{
    GT_PTP_CONFIG ptpCfg;
    GT_LPORT port;
    GT_STATUS status;


    /*
     *    1) Setup each port to forward PTP frame to CPU port
    */

    /* setup EtypeType and Policy */
    for(port=0; port<dev->numOfPorts; port++)
    {
        if ((status = gprtSetPortEType(dev, port, (GT_ETYPE)0x88F7)) != GT_OK)
        {
            MSG_PRINT(("gprtSetPortEType returned not OK\n"));
            return status;
        }

        if (port == dev->cpuPortNum)
            continue;

        if ((status = gprtSetPolicy(dev, port, POLICY_TYPE_ETYPE, FRAME_POLICY_TRAP)) != GT_OK)
        {
            MSG_PRINT(("gprtSetPolicy returned not OK\n"));
            return status;
        }
    }

    /* setup Frame Mode for CPU port */
    if ((status = gprtSetFrameMode(dev, dev->cpuPortNum, GT_FRAME_MODE_ETHER_TYPE_DSA)) != GT_OK)
    {
        MSG_PRINT(("gprtSetFrameMode return failed\n"));
        return status;
    }

    /*
     *    2) Enable PTP Interrupt
    */
    eventSetActive(dev, GT_AVB_INT);


    /*
     *    3) Configure PTP
    */
    ptpCfg.ptpEType = 0x88F7;
    ptpCfg.msgIdTSEn = 0xd;        /* id 0, 2, and 3 */
    ptpCfg.tsArrPtr = 0x8;        /* id 0 and 2 for ARR0, id 3 for ARR1 */

    /* Transport specific bits present in PTP Common Header */
    ptpCfg.transSpec = 1;

    /* starting bit location for the Message ID field in the PTP Common Header */
    ptpCfg.msgIdStartBit = 4;

    ptpCfg.ptpArrIntEn = 0x3F;
    ptpCfg.ptpDepIntEn = 0x3F;
    ptpCfg.disTSOverwrite = 0;


    if ((status = gptpSetConfig(dev, &ptpCfg)) != GT_OK)
    {
        MSG_PRINT(("gptpSetConfig return failed\n"));
        return status;
    }
    if ((status = gptpSetPTPEn(dev, GT_TRUE)) != GT_OK)
    {
        MSG_PRINT(("gptpSetPTPEn return failed\n"));
        return status;
    }

    return GT_OK;
}
Пример #4
0
GT_STATUS samplePTPIntHandler(GT_QD_DEV *dev)
{
    GT_U32 int_ports, i, int_status;
    GT_STATUS status;
    GT_PTP_TS_STATUS    ptpStatus;

    /* disable AVB Interrupt */
    eventSetActive(dev, 0);

    /* read interrupt cause */
    if((status=eventGetIntStatus(dev,(GT_U16*)&int_status))!=GT_OK)
    {
        return GT_FAIL;
    }


    if ((int_status & GT_AVB_INT) == 0)
    {
        MSG_PRINT(("eventGetIntStatus return No AVB Interrupt\n"));
        /* it's not PTP interrupt */
        goto ret_int;
    }

    /* read AVB Int status */
    if((status = gptpGetPTPInt(dev, &int_ports)) != GT_OK)
    {
        MSG_PRINT(("gptpGetPTPInt return failed\n"));
        goto ret_int;
    }

    /* for each port, get the timestamp information if necessary */
    i = 0;
    while(int_ports)
    {
        if(!(int_ports & 0x1))
        {
            i++;
            int_ports >>= 1;
            continue;
        }

        /* check Arrival0 Time Stamp */
        if((status = gptpGetTimeStamped(dev, i, PTP_ARR0_TIME, &ptpStatus)) != GT_OK)
        {
            MSG_PRINT(("gptpGetTimeStamped return failed\n"));
            goto ret_int;
        }

        if (ptpStatus.isValid == GT_TRUE)
        {
            switch(ptpStatus.status)
            {
            case PTP_INT_NORMAL:
                /* To Do: No error condition occurred. So store the time stamp and seqId */
                break;

            case PTP_INT_OVERWRITE:
                /* To Do: PTP Logic received several PTP frames and only the last one is valid */
                break;

            case PTP_INT_DROP:
                /* To Do: PTP Logic received several PTP frames and only the first one is valid */
                break;

            default:
                MSG_PRINT(("unknown ptp status %i\n", ptpStatus.status));
                status = GT_FAIL;
                goto ret_int;

            }

            if((status = gptpResetTimeStamp(dev, i, PTP_ARR0_TIME)) != GT_OK)
            {
                MSG_PRINT(("gptpResetTimeStamp return failed\n"));
                goto ret_int;
            }
        }

        /* check Arrival1 Time Stamp */
        if((status = gptpGetTimeStamped(dev, i, PTP_ARR1_TIME, &ptpStatus)) != GT_OK)
        {
            MSG_PRINT(("gptpGetTimeStamped return failed\n"));
            goto ret_int;
        }

        if (ptpStatus.isValid == GT_TRUE)
        {
            switch(ptpStatus.status)
            {
            case PTP_INT_NORMAL:
                /* To Do: No error condition occurred. So store the time stamp and seqId */
                break;

            case PTP_INT_OVERWRITE:
                /* To Do: PTP Logic received several PTP frames and only the last one is valid */
                break;

            case PTP_INT_DROP:
                /* To Do: PTP Logic received several PTP frames and only the first one is valid */
                break;

            default:
                MSG_PRINT(("unknown ptp status %i\n", ptpStatus.status));
                status = GT_FAIL;
                goto ret_int;
            }

            if((status = gptpResetTimeStamp(dev, i, PTP_ARR1_TIME)) != GT_OK)
            {
                MSG_PRINT(("gptpResetTimeStamp return failed\n"));
                goto ret_int;
            }

        }

        /* check Departure Time Stamp */
        if((status = gptpGetTimeStamped(dev, i, PTP_DEP_TIME, &ptpStatus)) != GT_OK)
        {
            MSG_PRINT(("gptpGetTimeStamped return failed\n"));
            goto ret_int;
        }

        if (ptpStatus.isValid == GT_TRUE)
        {
            switch(ptpStatus.status)
            {
            case PTP_INT_NORMAL:
                /* To Do: No error condition occurred. So store the time stamp and seqId */
                break;

            case PTP_INT_OVERWRITE:
                /* To Do: PTP Logic received several PTP frames and only the last one is valid */
                break;

            case PTP_INT_DROP:
                /* To Do: PTP Logic received several PTP frames and only the first one is valid */
                break;

            default:
                MSG_PRINT(("unknown ptp status %i\n", ptpStatus.status));
                status = GT_FAIL;
                goto ret_int;
            }

            if((status = gptpResetTimeStamp(dev, i, PTP_DEP_TIME)) != GT_OK)
            {
                MSG_PRINT(("gptpResetTimeStamp return failed\n"));
                goto ret_int;
            }

        }

        int_ports >>= 1;

    }
Пример #5
0
static int mv_gw_switch_init(int port)
{
    unsigned int        i, p;
    unsigned char       cnt;
    GT_LPORT            port_list[MAX_SWITCH_PORTS];
    struct mv_vlan_cfg  *nc;
    GT_JUMBO_MODE       jumbo_mode;
    GT_DEV_EVENT        gt_event;
    printk("init switch layer... "); 	
	if (!qd_dev) {
		printk("qd_dev is NULL in %s\n",__func__);
		return -1;
	}
		
    ETH_DBG( ETH_DBG_LOAD, ("Device ID     : 0x%x\n",qd_dev->deviceId));
    ETH_DBG( ETH_DBG_LOAD, ("Base Reg Addr : 0x%x\n",qd_dev->baseRegAddr));
    ETH_DBG( ETH_DBG_LOAD, ("No. of Ports  : %d\n",qd_dev->numOfPorts));
    ETH_DBG( ETH_DBG_LOAD, ("CPU Ports     : %ld\n",qd_dev->cpuPortNum));

    /* disable all ports */
    for(p=0; p<qd_dev->numOfPorts; p++) {
	    gstpSetPortState(qd_dev, p, GT_PORT_DISABLE);
    }

    /* set all ports to not modify the vlan tag on egress */
    for(i=0; i<qd_dev->numOfPorts; i++) 
    {
        if(gprtSetEgressMode(qd_dev, i, GT_UNMODIFY_EGRESS) != GT_OK) {
            printk("gprtSetEgressMode GT_UNMODIFY_EGRESS failed\n");
	            return -1;
	        }
    }
	
    /* initialize Switch according to Switch ID */
    switch (qd_dev->deviceId) 
    {
	    case GT_88E6065:
	        /* set CPU port number */
            if(gsysSetCPUPort(qd_dev, SWITCH_PORT_CPU) != GT_OK) {
	            printk("gsysSetCPUPort failed\n");
	            return -1;
	        }
            /* flush all counters for all ports */
	        if(gstatsFlushAll(qd_dev) != GT_OK)
    	        printk("gstatsFlushAll failed\n");
            /* use Marvell Header mode */
	        if(gprtSetHeaderMode(qd_dev, SWITCH_PORT_CPU, GT_TRUE) != GT_OK) {
		        printk("gprtSetHeaderMode GT_TRUE failed\n");
		        return -1;
	        }
	        /* init counters */
	        if(gprtClearAllCtr(qd_dev) != GT_OK)
	            printk("gprtClearAllCtr failed\n");
	        if(gprtSetCtrMode(qd_dev, GT_CTR_ALL) != GT_OK)
	            printk("gprtSetCtrMode failed\n");

	        break;

	    case GT_88E6061: 
	        /* set CPU port number */
            if(gsysSetCPUPort(qd_dev, SWITCH_PORT_CPU) != GT_OK) {
	            printk("gsysSetCPUPort failed\n");
	            return -1;
	        }
            /* use Marvell Header mode */
            if(gprtSetHeaderMode(qd_dev,SWITCH_PORT_CPU,GT_TRUE) != GT_OK) {
		        printk("gprtSetHeaderMode GT_TRUE failed\n");
		        return -1;
	        }   
	        /* init counters */
	        if(gprtClearAllCtr(qd_dev) != GT_OK)
	            printk("gprtClearAllCtr failed\n");
	        if(gprtSetCtrMode(qd_dev, GT_CTR_ALL) != GT_OK)
	            printk("gprtSetCtrMode failed\n");

	        break;

	    case GT_88E6161:
	    case GT_88E6165:
        case GT_88E6171:
            /* flush all counters for all ports */
            if(gstatsFlushAll(qd_dev) != GT_OK) {
                printk("gstatsFlushAll failed\n");
            }
            /* use Marvell Header mode */
	        if(gprtSetHeaderMode(qd_dev,SWITCH_PORT_CPU,GT_TRUE) != GT_OK) {
		        printk("gprtSetHeaderMode GT_TRUE failed\n");
		        return -1;
	        }
            /* set all ports to work in Normal mode (non-DSA tag) */
            for(i=0; i<qd_dev->numOfPorts; i++) 
            {
                if (gprtSetFrameMode(qd_dev, i, GT_FRAME_MODE_NORMAL) != GT_OK) {
                    printk("gprtSetFrameMode to GT_FRAME_MODE_NORMAL on port %d failed\n", i);
                    return -1;
                }
            }

            /* Setup jumbo frames mode */
	        if( MV_RX_BUF_SIZE(gtw_config.mtu) <= 1522)
                	jumbo_mode = GT_JUMBO_MODE_1522;
            	else if( MV_RX_BUF_SIZE(gtw_config.mtu) <= 2048)
                	jumbo_mode = GT_JUMBO_MODE_2048;
            	else
                	jumbo_mode = GT_JUMBO_MODE_10240;

            	for(i=0; i<qd_dev->numOfPorts; i++) {
                	if(gsysSetJumboMode(qd_dev, i, jumbo_mode) != GT_OK) {
                    		printk("gsysSetJumboMode %d failed\n",jumbo_mode);
                    		return -1;
                	}
            	}

	        break;	

	    default:
            printk("Unsupported Switch. Switch ID is 0x%X.\n", qd_dev->deviceId);
	        return -1;
    }

    /* set priorities rules */
    for(i=0; i<qd_dev->numOfPorts; i++) {
        /* default port priority to queue zero */
	    if(gcosSetPortDefaultTc(qd_dev, i, 0) != GT_OK)
	        printk("gcosSetPortDefaultTc failed (port %d)\n", i);
        
        /* enable IP TOS Prio */
	    if(gqosIpPrioMapEn(qd_dev, i, GT_TRUE) != GT_OK)
	        printk("gqosIpPrioMapEn failed (port %d)\n",i);
	
        /* set IP QoS */
	    if(gqosSetPrioMapRule(qd_dev, i, GT_FALSE) != GT_OK)
	        printk("gqosSetPrioMapRule failed (port %d)\n",i);
        
        /* disable Vlan QoS Prio */
	    if(gqosUserPrioMapEn(qd_dev, i, GT_FALSE) != GT_OK)
	        printk("gqosUserPrioMapEn failed (port %d)\n",i);
        
        /* Set force flow control to FALSE for all ports */
	    if(gprtSetForceFc(qd_dev, i, GT_FALSE) != GT_OK)
	        printk("gprtSetForceFc failed (port %d)\n",i);
    }

    /* The switch CPU port is not part of the VLAN, but rather connected by tunneling to each */
    /* of the VLAN's ports. Our MAC addr will be added during start operation to the VLAN DB  */
    /* at switch level to forward packets with this DA to CPU port.                           */
    ETH_DBG( ETH_DBG_LOAD, ("Enabling Tunneling on ports: "));
    for(i=0; i<qd_dev->numOfPorts; i++) {
	    if(i != SWITCH_PORT_CPU) {
	        if(gprtSetVlanTunnel(qd_dev, i, GT_TRUE) != GT_OK) {
		        printk("gprtSetVlanTunnel failed (port %d)\n",i);
		        return -1;
	        }
	        else {
		        ETH_DBG( ETH_DBG_LOAD, ("%d ",i));
	        }
	    }
    }
    ETH_DBG( ETH_DBG_LOAD, ("\n"));

    /* configure ports (excluding CPU port) for each network interface (VLAN): */
    for(i=0, nc=&gtw_config.vlan_cfg[i]; i<gtw_config.vlans_num; i++,nc++) {
        ETH_DBG( ETH_DBG_LOAD, ("vlan%d configuration (nc->ports_mask = 0x%08x) \n",
                                i, nc->ports_mask));
	    /* set port's defaul private vlan id and database number (DB per group): */
	    for(p=0; p<qd_dev->numOfPorts; p++) {
	        if( MV_BIT_CHECK(nc->ports_mask, p) && (p != SWITCH_PORT_CPU) ) {
		        ETH_DBG(ETH_DBG_LOAD,("port %d default private vlan id: 0x%x\n", p, MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p)));
		        if( gvlnSetPortVid(qd_dev, p, MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p)) != GT_OK ) {
			        printk("gvlnSetPortVid failed");
			        return -1;
		        }
		        if( gvlnSetPortVlanDBNum(qd_dev, p, MV_GTW_VLAN_TO_GROUP(nc->vlan_grp_id)) != GT_OK) {
		            printk("gvlnSetPortVlanDBNum failed\n");
		            return -1;
		        }
	        }
	    }

	    /* set port's port-based vlan (CPU port is not part of VLAN) */
        if(mv_gtw_set_port_based_vlan(nc->ports_mask & ~(1<<SWITCH_PORT_CPU)) != 0) {
	        printk("mv_gtw_set_port_based_vlan failed\n");
	    }

        /* set vtu with group vlan id (used in tx) */
        if(mv_gtw_set_vlan_in_vtu(nc->vlan_grp_id, nc->ports_mask | (1<<SWITCH_PORT_CPU)) != 0) {
	        printk("mv_gtw_set_vlan_in_vtu failed\n");
	    }

        /* set vtu with each port private vlan id (used in rx) */
 	    for(p=0; p<qd_dev->numOfPorts; p++) {
	        if(MV_BIT_CHECK(nc->ports_mask, p) && (p!=SWITCH_PORT_CPU)) {
                if(mv_gtw_set_vlan_in_vtu(MV_GTW_PORT_VLAN_ID(nc->vlan_grp_id,p),
                                          nc->ports_mask & ~(1<<SWITCH_PORT_CPU)) != 0) {
		            printk("mv_gtw_set_vlan_in_vtu failed\n");
		        }
	        }
	    }
    }

    /* set cpu-port with port-based vlan to all other ports */
    ETH_DBG( ETH_DBG_LOAD, ("cpu port-based vlan:"));
    for(p=0,cnt=0; p<qd_dev->numOfPorts; p++) {
        if(p != SWITCH_PORT_CPU) {
	        ETH_DBG( ETH_DBG_LOAD, ("%d ",p));
            port_list[cnt] = p;
            cnt++;
        }
    }
    ETH_DBG( ETH_DBG_LOAD, ("\n"));
    if(gvlnSetPortVlanPorts(qd_dev, SWITCH_PORT_CPU, port_list, cnt) != GT_OK) {
        printk("gvlnSetPortVlanPorts failed\n");
        return -1;
    }

    if(gfdbFlush(qd_dev,GT_FLUSH_ALL) != GT_OK) {
	    printk("gfdbFlush failed\n");
    }

    /* done! enable all Switch ports according to the net config table */
    ETH_DBG( ETH_DBG_LOAD, ("enabling: ports "));
    for(p=0; p<qd_dev->numOfPorts; p++) {
	    if (MV_BIT_CHECK(switch_enabled_ports, p)) {
	        ETH_DBG( ETH_DBG_LOAD, ("%d ",p));
	        if(gstpSetPortState(qd_dev, p, GT_PORT_FORWARDING) != GT_OK) {
	            printk("gstpSetPortState failed\n");
	        }
	    }
    }
    ETH_DBG( ETH_DBG_LOAD, ("\n"));

#ifdef CONFIG_MV_GTW_LINK_STATUS
    /* Enable Phy Link Status Changed interrupt at Phy level for the all enabled ports */
    for(p=0; p<qd_dev->numOfPorts; p++) {
	    if(MV_BIT_CHECK(switch_enabled_ports, p) && (p != SWITCH_PORT_CPU)) {
	        if(gprtPhyIntEnable(qd_dev, p, (GT_LINK_STATUS_CHANGED)) != GT_OK) {
		        printk("gprtPhyIntEnable failed port %d\n", p);
	        }
	    }
    }

    if ((qd_dev->deviceId != GT_88E6161) && 
        (qd_dev->deviceId != GT_88E6165) && 
        (qd_dev->deviceId != GT_88E6171)) {
    	if (switch_irq != -1) {
            if(eventSetActive(qd_dev, GT_PHY_INTERRUPT) != GT_OK) {
	    	    printk("eventSetActive failed\n");
            }
    	}
    }
    else {
	    gt_event.event = GT_DEV_INT_PHY;
        gt_event.portList = 0;
        gt_event.phyList = 0x1F;            /* 0x1F is a bit mask for ports 0-4 */
	    if (switch_irq != -1) {
	        if(eventSetDevInt(qd_dev, &gt_event) != GT_OK) {
		        printk("eventSetDevInt failed\n");
	        }
	        if(eventSetActive(qd_dev, GT_DEVICE_INT) != GT_OK) {
    	    	printk("eventSetActive failed\n");
            }
	    }
    }
#endif /* CONFIG_MV_GTW_LINK_STATUS */

    /* Configure Ethernet related LEDs, currently according to Switch ID */
    switch (qd_dev->deviceId) {

	    case GT_88E6161:
	    case GT_88E6165:
        case GT_88E6171:
		    break; /* do nothing */

	    default:
	        for(p=0; p<qd_dev->numOfPorts; p++) {
	            if( (p != SWITCH_PORT_CPU) && (SWITCH_IS_PORT_CONNECTED(p)) ) {
	                if(gprtSetPhyReg(qd_dev,p,22,0x1FFA)) { 
                        /* Configure Register 22 LED0 to 0xA for Link/Act */
	    	            printk("gprtSetPhyReg failed (port=%d)\n", p);
		            }
	            }
	        }
	        break;
    }

    /* printk("done\n"); */

    return 0;
}
Пример #6
0
unsigned int mv_switch_link_detection_init(void)
{
#ifdef CONFIG_MV_ETH_SWITCH_LINK

	unsigned int p;
	static int link_init_done = 0;
	unsigned int connected_phys_mask = 0;

	if (qd_dev == NULL) {
		printk(KERN_ERR "%s: qd_dev not initialized, call mv_switch_load() first\n", __func__);
		return 0;
	}

	switch_irq = mvBoardSwitchIrqGet();

	if (!qsgmii_module) {
		/* liron, TODO: find a nicer solution or use BoardEnv */
#ifdef MV_INCLUDE_ETH_COMPLEX
		/* QSGMII module is not connected, Switch is working in 3xFE mode */
		connected_phys_mask = 0x0E;	/* KW2: Switch PHYs 1, 2, 3 */
#else
		connected_phys_mask = 0x1F;	/* KW40: Switch PHYs 0, 1, 2, 3, 4 */
#endif

		if (!link_init_done) {
			/* Enable Phy Link Status Changed interrupt at Phy level for the all enabled ports */
			for (p = 0; p < qd_dev->numOfPorts; p++) {
				if (MV_BIT_CHECK(connected_phys_mask, p) && (p != qd_cpu_port)) {
					if (gprtPhyIntEnable(qd_dev, p, (GT_LINK_STATUS_CHANGED)) != GT_OK)
						printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", p);
				}
			}

			if (switch_irq != -1) {
				/* Interrupt supported */

				if ((qd_dev->deviceId == GT_88E6161) || (qd_dev->deviceId == GT_88E6165) ||
				    (qd_dev->deviceId == GT_88E6351) || (qd_dev->deviceId == GT_88E6171) ||
				    (qd_dev->deviceId == GT_88E6172) || (qd_dev->deviceId == GT_88E6176)) {

					GT_DEV_EVENT gt_event = { GT_DEV_INT_PHY, 0, connected_phys_mask };

					if (eventSetDevInt(qd_dev, &gt_event) != GT_OK)
						printk(KERN_ERR "eventSetDevInt failed\n");

					if (eventSetActive(qd_dev, GT_DEVICE_INT) != GT_OK)
						printk(KERN_ERR "eventSetActive failed\n");
				} else {
					if (eventSetActive(qd_dev, GT_PHY_INTERRUPT) != GT_OK)
						printk(KERN_ERR "eventSetActive failed\n");
				}
			}
		}
	}

	if (!link_init_done) {
		if (gephy_on_port >= 0) {
			if (gprtPhyIntEnable(qd_dev, gephy_on_port, (GT_LINK_STATUS_CHANGED)) != GT_OK)
				printk(KERN_ERR "gprtPhyIntEnable failed port %d\n", gephy_on_port);
		}
	}

	if (qsgmii_module)
		connected_phys_mask = 0x0F;	/* Switch ports 0, 1, 2, 3 connected to QSGMII */

	if (gephy_on_port >= 0)
		connected_phys_mask |= (1 << gephy_on_port);

	if (rgmiia_on_port >= 0)
		connected_phys_mask |= (1 << rgmiia_on_port);

	if (!link_init_done) {
		/* we want to use a timer for polling link status if no interrupt is available for all or some of the PHYs */
		if ((switch_irq == -1)) { /* liron, TODO: || (rgmiia_on_port >= 0) */
			/* Use timer for polling */
			switch_link_poll = 1;
			init_timer(&switch_link_timer);
			switch_link_timer.function = mv_switch_link_timer_function;

			if (switch_irq == -1)
				switch_link_timer.data = connected_phys_mask;
			else		/* timer only for RGMII-A connected port */
				switch_link_timer.data = (1 << rgmiia_on_port);

			switch_link_timer.expires = jiffies + (HZ);	/* 1 second */
			add_timer(&switch_link_timer);
		}
	}

	if (!link_init_done) {
		if (switch_irq != -1) {
			/* Interrupt supported */
			mv_eth_switch_interrupt_unmask(qsgmii_module, gephy_on_port);

			if (request_irq(switch_irq, mv_switch_isr, (IRQF_DISABLED | IRQF_SAMPLE_RANDOM), "switch", NULL))
				printk(KERN_ERR "failed to assign irq%d\n", switch_irq);
		}
	}

	link_init_done = 1;

	return connected_phys_mask;
#endif /* CONFIG_MV_ETH_SWITCH_LINK */
}