/* * 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; }
/* * 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; }
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; }
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; }
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=>w_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, >_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; }
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, >_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 */ }