@@ -739,11 +739,15 @@ static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, i
static int ax88172_link_reset(struct usbnet *dev)
{
u16 lpa;
+ u16 adv;
+ u16 res;
u8 mode;
mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
- if (lpa & LPA_DUPLEX)
+ adv = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ res = mii_nway_result(lpa|adv);
+ if (res & LPA_DUPLEX)
mode |= AX_MEDIUM_FULL_DUPLEX;
ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
@@ -816,7 +820,7 @@ static int ax8817x_get_eeprom(struct net_device *net,
eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
return -EINVAL;
}
- return 0;
+ return i * 2;
}
static void ax8817x_get_drvinfo (struct net_device *net,
@@ -960,6 +964,29 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
msleep(5);
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read;
+ dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
+ dbg("Error reading PHY ID: %02x", ret);
+ goto out2;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto out2;
+ }
+ dev->mii.phy_id = *((u8 *)buf + 1);
+
+ if (dev->mii.phy_id == 0x10)
+ {
if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
dbg("Select PHY #1 failed: %d", ret);
goto out2;
@@ -984,6 +1011,21 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
dbg("Failed to set Internal/External PHY reset control: %d", ret);
goto out2;
}
+ }
+ else
+ {
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0000, 0, 0, buf)) < 0) {
+ dbg("Select PHY #1 failed: %d", ret);
+ goto out2;
+ }
+
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+ dbg("Failed to power down internal PHY: %d", ret);
+ goto out2;
+ }
+ }
msleep(150);
if ((ret =
@@ -1006,6 +1048,8 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
}
+ if (dev->mii.phy_id == 0x10)
+ {
if (((ret =
ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
|| (*((u16 *)buf) != 0x003b)) {
@@ -1013,26 +1057,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
}
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
- dev->mii.phy_id_mask = 0xff;
- dev->mii.reg_num_mask = 0xff;
-
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
- dbg("Error reading PHY ID: %02x", ret);
- goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
- ret);
- ret = -EIO;
- goto out2;
- }
- dev->mii.phy_id = *((u8 *)buf + 1);
-
if ((ret =
ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
dbg("Set external PHY reset pin level: %d", ret);
@@ -1045,14 +1069,14 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
}
msleep(150);
-
+ }
dev->net->set_multicast_list = ax8817x_set_multicast;
dev->net->ethtool_ops = &ax88772_ethtool_ops;
ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA);
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
mii_nway_restart(&dev->mii);
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
@@ -1060,7 +1084,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8), AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
goto out2;
}
@@ -1088,6 +1112,663 @@ out1:
return ret;
}
+static int mediacheck(struct usbnet *dev)
+{
+ int ret,fullduplex;
+ u16 phylinkstatus1, phylinkstatus2, data16, tempshort = 0;
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+
+
+ if ((ret =ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG,dev->mii.phy_id,
+ GMII_PHY_ANLPAR, REG_LENGTH, &data16)) < 0) {
+ dbg("error on reading MII register 5 failed: %02x", ret);
+ return ret; //
+ }
+ phylinkstatus1 = le16_to_cpu(data16);
+
+ if ((ret =ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG,dev->mii.phy_id, GMII_PHY_1000BT_STATUS,
+ REG_LENGTH, &data16)) < 0) {
+ dbg("error on reading MII register 0x0a failed: %02x", ret);
+ return ret; //
+ }
+ phylinkstatus2 = le16_to_cpu(data16);
+
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){ //1st generation Marvel PHY
+ if(ax178dataptr->LedMode == 1){
+ if ((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG,dev->mii.phy_id, MARVELL_MANUAL_LED,
+ REG_LENGTH, &data16)) < 0) {
+ dbg("error on reading MII register 0x19 failed: %02x", ret);
+ return ret; //
+ }
+ tempshort = le16_to_cpu(data16);
+ tempshort &=0xfc0f;
+ }
+ }
+
+ fullduplex=1;
+ if(phylinkstatus2 & (GMII_1000_AUX_STATUS_FD_CAPABLE|GMII_1000_AUX_STATUS_HD_CAPABLE)){ /* 1000BT full duplex */
+ ax178dataptr->MediaLink =
+ MEDIUM_GIGA_MODE|MEDIUM_FULL_DUPLEX_MODE|MEDIUM_ENABLE_125MHZ|MEDIUM_ENABLE_RECEIVE;
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode == 1){
+ tempshort|=0x3e0;
+ }
+ }
+ }else if(phylinkstatus1 & GMII_ANLPAR_100TXFD){ /* 100BT full duplex */
+ ax178dataptr->MediaLink=MEDIUM_FULL_DUPLEX_MODE|MEDIUM_ENABLE_RECEIVE|MEDIUM_MII_100M_MODE;
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode == 1){
+ tempshort|=0x3b0;
+ }
+ }
+ }else if(phylinkstatus1 & GMII_ANLPAR_100TX){ /* 100BT half duplex */
+ ax178dataptr->MediaLink=(MEDIUM_ENABLE_RECEIVE|MEDIUM_MII_100M_MODE);
+ fullduplex=0;
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode == 1){
+ tempshort|=0x3b0;
+ }
+ }
+ }else if(phylinkstatus1 & GMII_ANLPAR_10TFD){ /* 10 full duplex */
+ ax178dataptr->MediaLink = (MEDIUM_FULL_DUPLEX_MODE|MEDIUM_ENABLE_RECEIVE);
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode == 1){
+ tempshort|=0x02f0;
+ }
+ }
+ }else{
+ /* 10 half duplex*/
+ ax178dataptr->MediaLink = MEDIUM_ENABLE_RECEIVE;
+ fullduplex=0;
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode == 1){
+ tempshort|=0x02f0;
+ }
+ }
+ }
+
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode == 1){
+ data16 = le16_to_cpu(tempshort);
+ if ( (ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, (u8)dev->mii.phy_id,
+ MARVELL_MANUAL_LED, REG_LENGTH, &data16)) < 0){
+ dbg("error on writing MII register 0x19 failed: %02x", ret);
+ return ret;
+ }
+ }
+ }
+ ax178dataptr->MediaLink |= 0x0004;
+ if(ax178dataptr->UseRgmii != 0)
+ ax178dataptr->MediaLink |= 0x0008;
+ if(fullduplex){
+ ax178dataptr->MediaLink |= 0x0020; //ebable tx flow control as default;
+ ax178dataptr->MediaLink |= 0x0010; //ebable rx flow control as default;
+ }
+
+ return 0;
+}
+
+static int marevell_init(struct usbnet *dev)
+{
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+ u16 tmp,phyreg,PhyPatch,data16;
+ int ret;
+ void *buf;
+ u8 PhyID = (u8)ax178dataptr->PhyID;
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ if(ax178dataptr->UseGpio0)
+ {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,AXGPIOS_GPO0EN |AXGPIOS_RSE,0, 0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(25);
+ tmp = AXGPIOS_GPO2 | AXGPIOS_GPO2EN | AXGPIOS_GPO0EN;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(25);
+ tmp = AXGPIOS_GPO2EN | AXGPIOS_GPO0EN;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(245);
+ tmp = AXGPIOS_GPO2 | AXGPIOS_GPO2EN | AXGPIOS_GPO0EN;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+
+ }
+ else /* !UseGpio0 */
+ {
+ tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_RSE;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ if(ax178dataptr->LedMode != 1) //our new demo board
+ {
+ msleep(25);
+ tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_GPO2EN | AXGPIOS_GPO2;
+ if ((ret =ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(25);
+ tmp = AXGPIOS_GPO2EN | AXGPIOS_GPO1|AXGPIOS_GPO1EN;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(245);
+ tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN|AXGPIOS_GPO2|AXGPIOS_GPO2EN;
+ if ((ret = ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ }
+ else if(ax178dataptr->LedMode == 1) //bufflo old card
+ {
+ msleep(350);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(350);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1|AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ }
+ }
+
+
+ if((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, PhyID, PHY_MARVELL_STATUS, REG_LENGTH, &data16)) < 0){
+ dbg("read register reg 27 failed: %d", ret);
+ return ret;
+ } //read phy register
+
+ phyreg = le16_to_cpu(data16);
+ if(!(phyreg & MARVELL_STATUS_HWCFG)){
+ ax178dataptr->UseRgmii=1;
+ PhyPatch = MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY;
+ data16 = cpu_to_le16(PhyPatch);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, PHY_MARVELL_CTRL, REG_LENGTH, &data16)) < 0)
+ return ret;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ }
+
+ if(ax178dataptr->LedMode == 1){
+ if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+ return ret;
+ phyreg = le16_to_cpu(data16);
+ phyreg &= 0xf8ff;
+ phyreg |= (1+0x100);
+
+ data16 = le16_to_cpu(phyreg);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH,&data16))< 0)
+ return ret;
+ if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+ return ret;
+ phyreg = le16_to_cpu(data16);
+ phyreg &=0xfc0f;
+ } else if(ax178dataptr->LedMode == 2){
+
+ if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+ return ret;
+
+ phyreg = le16_to_cpu(data16);
+ phyreg &= 0xf886;
+ phyreg |= (1+0x10+0x300);
+ data16 = cpu_to_le16(phyreg);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH,&data16))< 0)
+ return ret;
+
+ }else if(ax178dataptr->LedMode == 5){
+ if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+ return ret;
+ phyreg = le16_to_cpu(data16);
+ phyreg &= 0xf8be;
+ phyreg |= (1+0x40+0x300);
+ data16 = cpu_to_le16(phyreg);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH,&data16))< 0)
+ return ret;
+ }
+
+ ax178dataptr->phyreg = phyreg;
+ return 0;
+}
+
+static int cicada_init(struct usbnet *dev)
+{
+
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+ u16 tmp, phyreg, i, data16;
+ int ret;
+ void *buf;
+ u8 PhyID = (u8)ax178dataptr->PhyID;
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ if(ax178dataptr->UseGpio0)
+ {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,AXGPIOS_GPO0 | AXGPIOS_GPO0EN | AXGPIOS_RSE,0, 0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ }
+ else
+ {
+ tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_RSE;
+ if ((ret =ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ if(ax178dataptr->LedMode!= 1) //our new demo board
+ {
+ msleep(25);
+ tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_GPO2EN | AXGPIOS_GPO2;
+ if ((ret =ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(25);
+ tmp = AXGPIOS_GPO2EN | AXGPIOS_GPO1|AXGPIOS_GPO1EN;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(245);
+ tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN|AXGPIOS_GPO2|AXGPIOS_GPO2EN;
+ if ((ret = ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ }
+ else if(ax178dataptr->LedMode==1) //bufflo old card
+ {
+ msleep(350);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(350);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1|AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ }
+ }
+
+ if(ax178dataptr->PhyMode == PHY_MODE_CICADA_FAMILY){ //CICADA 1st version phy
+ ax178dataptr->UseRgmii=1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;// MEDIUM_ENABLE_125MHZ;
+
+ for (i = 0; i < sizeof(CICADA_FAMILY_HWINIT)/sizeof(CICADA_FAMILY_HWINIT[0]); i++) {
+ data16 = cpu_to_le16(CICADA_FAMILY_HWINIT[i].value);
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, CICADA_FAMILY_HWINIT[i].offset, REG_LENGTH, &data16);
+ if(ret < 0) return ret;
+ }
+ }
+ else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V2){
+ ax178dataptr->UseRgmii=1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+
+ for (i = 0; i < ( sizeof(CICADA_V2_HWINIT)/sizeof(CICADA_V2_HWINIT[0]) ); i++) {
+ data16 = cpu_to_le16(CICADA_V2_HWINIT[i].value);
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, CICADA_V2_HWINIT[i].offset, REG_LENGTH, &data16);
+ if(ret < 0) return ret;
+ }
+ }
+ else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX){
+ ax178dataptr->UseRgmii=1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+
+ for (i = 0; i < ( sizeof(CICADA_V2_ASIX_HWINIT)/sizeof(CICADA_V2_ASIX_HWINIT[0]) ); i++) {
+ data16 = cpu_to_le16(CICADA_V2_ASIX_HWINIT[i].value);
+ ret=ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, CICADA_V2_ASIX_HWINIT[i].offset, REG_LENGTH, &data16);
+ if(ret < 0) return ret;
+ }
+ }
+
+ if(ax178dataptr->PhyMode == PHY_MODE_CICADA_FAMILY){
+ if(ax178dataptr->LedMode == 3){
+ if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, 27, 2, &data16))< 0)
+ return ret;
+ phyreg = le16_to_cpu(data16);
+ phyreg &= 0xfcff;
+ phyreg |= 0x0100;
+ data16 = cpu_to_le16(phyreg);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 27,2,&data16))< 0)
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int agere_init(struct usbnet *dev)
+{
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+ u16 tmp, phyreg, i;
+ int ret;
+ void *buf;
+ u8 PhyID = (u8)ax178dataptr->PhyID;
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_RSE,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(25);
+ if ((ret=ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,AXGPIOS_GPO1|AXGPIOS_GPO1EN
+ | AXGPIOS_GPO2EN | AXGPIOS_GPO2,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(25);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO2EN | AXGPIOS_GPO1
+ | AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+ msleep(245);
+ if ((ret=ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,AXGPIOS_GPO1|AXGPIOS_GPO1EN|AXGPIOS_GPO2
+ | AXGPIOS_GPO2EN,0,0,buf)) < 0){
+ dbg("write GPIO failed: %d", ret);
+ return ret;
+ }
+
+ ax178dataptr->UseRgmii=1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+
+ phyreg = cpu_to_le16(BMCR_RESET);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MII_BMCR, REG_LENGTH, &phyreg)) < 0) {
+ dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
+ return ret;
+ } //software reset
+
+ while (1)
+ {
+ phyreg = cpu_to_le16(0x1001);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 21, REG_LENGTH, &phyreg);
+ msleep(10);
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, PhyID, 21, REG_LENGTH, &phyreg);
+ tmp = le16_to_cpu(phyreg);
+ if ((tmp & 0xf00f) == 0x1001)
+ break;
+ msleep(10);
+ }
+
+ if (ax178dataptr->LedMode == 4)
+ {
+ phyreg = cpu_to_le16(0x7417);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 28, 2, &phyreg);
+ }
+ else if (ax178dataptr->LedMode == 9)
+ {
+ phyreg = cpu_to_le16(0x7a10);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 28, 2, &phyreg);
+ }
+ else if (ax178dataptr->LedMode == 10)
+ {
+ phyreg = cpu_to_le16(0x7a13);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 28, 2, &phyreg);
+ }
+
+ for (i = 0; i < ( sizeof(AGERE_FAMILY_HWINIT)/sizeof(AGERE_FAMILY_HWINIT[0]) ); i++) {
+ phyreg = cpu_to_le16(AGERE_FAMILY_HWINIT[i].value);
+ ret=ax8817x_write_cmd(dev,AX_CMD_WRITE_MII_REG,PhyID,AGERE_FAMILY_HWINIT[i].offset,REG_LENGTH,&phyreg);
+ if(ret < 0) return ret;
+ }
+
+ return 0;
+}
+
+static int phy_init(struct usbnet *dev)
+{
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+ int ret;
+ u16 tmp, data16, phyanar, phyauxctrl, phyctrl, phyreg = 0;
+ void *buf;
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
+ if((ret = marevell_init(dev)) < 0) return ret;
+ }else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_FAMILY) {
+ if((ret = cicada_init(dev)) < 0) return ret;
+ }else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) {
+ if((ret = cicada_init(dev)) < 0) return ret;
+ }else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX) {
+ if((ret = cicada_init(dev)) < 0) return ret;
+ }else if(ax178dataptr->PhyMode == PHY_MODE_AGERE_FAMILY) {
+ if((ret = agere_init(dev)) < 0) return ret;
+ }
+
+ if(ax178dataptr->PhyMode != PHY_MODE_AGERE_FAMILY)
+ {
+ /* reset phy */
+ data16 = cpu_to_le16(BMCR_RESET);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, dev->mii.phy_id,
+ MII_BMCR, REG_LENGTH, (void *)(&data16))) < 0) {
+ dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
+ return ret;
+ }
+ }
+
+ if ((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, dev->mii.phy_id , MII_BMCR,
+ REG_LENGTH, &data16)) < 0) {
+ dbg("error on read MII reg - MII_BMCR: %02x", ret);
+ return ret; //could be 0x0000
+ }
+
+ phyctrl = le16_to_cpu(data16);
+ tmp=phyctrl;
+ phyctrl &=~(BMCR_PDOWN|BMCR_ISOLATE);
+ if(phyctrl != tmp){
+ data16 = cpu_to_le16(phyctrl);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, dev->mii.phy_id, MII_BMCR,
+ REG_LENGTH, &data16)) < 0) {
+ dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
+ return ret;
+ }
+
+ }
+
+ phyctrl&= ~BMCR_ISOLATE;
+ phyanar=1+(0x0400|ADVERTISE_100FULL|ADVERTISE_100HALF|ADVERTISE_10FULL|ADVERTISE_10HALF);
+ phyauxctrl=0x0200; //1000M and full duplex
+
+ data16 = cpu_to_le16(phyanar);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+ GMII_PHY_ANAR,REG_LENGTH,&data16))< 0) return ret;
+
+ data16 = cpu_to_le16(phyauxctrl);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+ GMII_PHY_1000BT_CONTROL,REG_LENGTH,&data16))< 0) return ret;
+
+ phyctrl |= (BMCR_ANENABLE|BMCR_ANRESTART);
+ data16 = cpu_to_le16(phyctrl);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+ GMII_PHY_CONTROL,REG_LENGTH,&data16))< 0) return ret;
+
+ if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+ if(ax178dataptr->LedMode==1) {
+ phyreg |= 0x3f0;
+ data16 = cpu_to_le16(phyreg);
+ if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+ 25,REG_LENGTH,&phyreg))< 0) return ret;
+ }
+ }
+
+ msleep(3000);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ (AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8)),
+ 0x000e, 0, buf)) < 0) {
+ dbg("write IPG IPG1 IPG2 reg failed: %d", ret);
+ return ret;
+ }
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, buf)) < 0) {
+ dbg("disable PHY access failed: %d", ret);
+ return ret;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ (AX_RX_CTL_MFB | AX_RX_CTL_START | AX_RX_CTL_AB),
+ 0, 0, buf)) < 0) {
+ dbg("write RX ctrl reg failed: %d", ret);
+ return ret;
+ }
+
+ return 0;
+
+}
+
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ void *buf;
+ u16 EepromData,PhyID, temp16;
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr;
+
+ get_endpoints(dev,intf);
+
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ dbg ("Cannot allocate memory for buffer");
+ return -ENOMEM;
+ }
+
+ /* allocate 178 data */
+ if (!(ax178dataptr = kmalloc (sizeof(struct ax88178_data), GFP_KERNEL))) {
+ dbg ("Cannot allocate memory for AX88178 data");
+ return -ENOMEM;
+ }
+ memset (ax178dataptr, 0, sizeof(struct ax88178_data));
+ ax17xdataptr->ax178dataptr = ax178dataptr;
+ /* end of allocate 178 data */
+
+ if ((ret = ax8817x_write_cmd(dev, 0x22, 0x0000, 0, 0, buf)) < 0) {
+ dbg("write S/W reset failed: %d", ret);
+ return ret;
+ }
+ msleep(150);
+
+ if ((ret = ax8817x_write_cmd(dev, 0x20, 0x0048, 0, 0, buf)) < 0) {
+ dbg("write S/W reset failed: %d", ret);
+ return ret;
+ }
+ msleep(150);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0, buf)) < 0) {
+ dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+ return ret; //stop rcv
+ }
+
+ msleep(150);
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
+ dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
+ return ret;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+ /* End of get MAC address */
+
+
+ /* Get the EEPROM data*/
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_EN, 0, 0, 0, buf)) < 0) {
+ dbg("enable SROM reading failed: %d", ret);
+ return ret; // ???
+ }
+
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+ 0x0017, 0, 2, (void *)(&EepromData))) < 0) {
+ dbg("read SROM address 17h failed: %d", ret);
+ return ret;
+ }
+
+ ax178dataptr->EepromData = le16_to_cpu(EepromData);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_DIS, 0, 0, 0, buf)) < 0) {
+ dbg("disable SROM reading failed: %d", ret);
+ return ret; // ???
+ }
+ /* End of get EEPROM data */
+
+ /* Get PHY id */
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, buf)) < 0) {
+ dbg("enable PHY reg. access capability: %d", ret);
+ return ret; //enable Phy register access capability
+ }
+
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, REG_LENGTH, &temp16)) < 0) {
+ dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
+ return ret;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
+ return -EIO;
+ }
+
+ PhyID = le16_to_cpu(temp16);
+ PhyID = (PhyID >> 8) & PHY_ID_MASK;
+ ax178dataptr->PhyID = PhyID;
+ /* End of get PHY id */
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read;
+ dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.phy_id_mask = 0x3f;
+ dev->mii.reg_num_mask = 0x1f;
+ dev->mii.phy_id = (u8)ax178dataptr->PhyID;
+
+ if (ax178dataptr->EepromData == 0xffff)
+ {
+ ax178dataptr->PhyMode = PHY_MODE_MARVELL;
+ ax178dataptr->LedMode = 0;
+ ax178dataptr->UseGpio0 = 1; //True
+ }
+ else
+ {
+ ax178dataptr->PhyMode = (u8)(ax178dataptr->EepromData & EEPROMMASK);
+ ax178dataptr->LedMode = (u8)(ax178dataptr->EepromData>>8);
+ if(ax178dataptr->EepromData & 0x80) {
+ ax178dataptr->UseGpio0=0; //MARVEL se and other
+ }
+ else {
+ ax178dataptr->UseGpio0=1; //cameo
+ }
+ }
+
+ if ((ret = phy_init(dev)) < 0) return ret;
+
+ return 0;
+}
+
static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
u32 *header;
@@ -1199,6 +1880,70 @@ static int ax88772_link_reset(struct usbnet *dev)
return 0;
}
+static int set_media(struct usbnet *dev)
+{
+ int ret;
+ void *buf;
+ struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, buf)) < 0) {
+ dbg("enable PHY reg. access capability: %d", ret);
+ return ret; //enable Phy register access capability
+ }
+
+ mediacheck(dev);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ ax178dataptr->MediaLink, 0, 0, buf)) < 0) {
+ dbg("write mode medium reg failed: %d", ret);
+ return ret;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, buf)) < 0) {
+ dbg("disable PHY access failed: %d", ret);
+ return ret;
+ }
+
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+ return 0;
+}
+
+static int ax88178_link_reset(struct usbnet *dev)
+{
+ int ret;
+
+ if ((ret = set_media(dev)) < 0) return ret;
+ return 0;
+}
+
+static const struct driver_info ax88178_info = {
+ .description = "ASIX AX88178 USB 2.0 Ethernet",
+ .bind = ax88178_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88178_link_reset,
+ .flags = FLAG_ETHER|FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .data = 0x00130103, //useless here
+};
+
+static const struct driver_info belkin178_info = {
+ .description = "Belkin Gigabit USB 2.0 Network Adapter",
+ .bind = ax88178_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88178_link_reset,
+ .flags = FLAG_ETHER|FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .data = 0x00130103, //useless here
+};
+
static const struct driver_info ax8817x_info = {
.description = "ASIX AX8817x USB 2.0 Ethernet",
.bind = ax8817x_bind,
@@ -1251,6 +1996,18 @@ static const struct driver_info ax88772_info = {
.data = 0x00130103,
};
+static const struct driver_info dlink_dub_e100b_info = {
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
+ .bind = ax88772_bind,
+ .status = ax8817x_status,
+ .link_reset = ax88772_link_reset,
+ .reset = ax88772_link_reset,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .data = 0x00130103,
+};
+
#endif /* CONFIG_USB_AX8817X */