Author: thompsa
Date: Thu Sep  2 03:47:07 2010
New Revision: 212130
URL: http://svn.freebsd.org/changeset/base/212130

Log:
  Add GPIO programming for more PHY hardware.
  
  Submitted by: yongari

Modified:
  head/sys/dev/usb/net/if_axe.c
  head/sys/dev/usb/net/if_axereg.h

Modified: head/sys/dev/usb/net/if_axe.c
==============================================================================
--- head/sys/dev/usb/net/if_axe.c       Thu Sep  2 03:44:56 2010        
(r212129)
+++ head/sys/dev/usb/net/if_axe.c       Thu Sep  2 03:47:07 2010        
(r212130)
@@ -515,12 +515,19 @@ axe_get_phyno(struct axe_softc *sc, int 
        return (phyno);
 }
 
+#define        AXE_GPIO_WRITE(x, y)    do {                            \
+       axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, (x), NULL);          \
+       uether_pause(ue, (y));                                  \
+} while (0)
+
 static void
 axe_ax88178_init(struct axe_softc *sc)
 {
-       int gpio0 = 0, phymode = 0;
-       uint16_t eeprom;
+       struct usb_ether *ue;
+       int gpio0, phymode;
+       uint16_t eeprom, val;
 
+       ue = &sc->sc_ue;
        axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL);
        /* XXX magic */
        axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom);
@@ -529,46 +536,89 @@ axe_ax88178_init(struct axe_softc *sc)
 
        /* if EEPROM is invalid we have to use to GPIO0 */
        if (eeprom == 0xffff) {
-               phymode = 0;
+               phymode = AXE_PHY_MODE_MARVELL;
                gpio0 = 1;
        } else {
-               phymode = eeprom & 7;
+               phymode = eeprom & 0x7f;
                gpio0 = (eeprom & 0x80) ? 0 : 1;
        }
 
-       axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL);
-       uether_pause(&sc->sc_ue, hz / 16);
-
-       if ((eeprom >> 8) != 0x01) {
-               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
-               uether_pause(&sc->sc_ue, hz / 32);
-
-               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL);
-               uether_pause(&sc->sc_ue, hz / 3);
-
-               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
-               uether_pause(&sc->sc_ue, hz / 32);
-       } else {
-               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL);
-               uether_pause(&sc->sc_ue, hz / 32);
-
-               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL);
-               uether_pause(&sc->sc_ue, hz / 32);
+       if (bootverbose)
+               device_printf(sc->sc_ue.ue_dev, "EEPROM data : 0x%04x\n",
+                   eeprom);
+       /* Program GPIOs depending on PHY hardware. */
+       switch (phymode) {
+       case AXE_PHY_MODE_MARVELL:
+               if (gpio0 == 1) {
+                       AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO0_EN,
+                           hz / 32);
+                       AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2 | AXE_GPIO2_EN,
+                           hz / 32);
+                       AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2_EN, hz / 4);
+                       AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2 | AXE_GPIO2_EN,
+                           hz / 32);
+               } else
+                       AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
+                           AXE_GPIO1_EN, hz / 32);
+               break;
+       case AXE_PHY_MODE_CICADA:
+               if (gpio0 == 1)
+                       AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO0 |
+                           AXE_GPIO0_EN, hz / 32);
+               else
+                       AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
+                           AXE_GPIO1_EN, hz / 32);
+               break;
+       case AXE_PHY_MODE_AGERE:
+               AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
+                   AXE_GPIO1_EN, hz / 32);
+               AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | AXE_GPIO2 |
+                   AXE_GPIO2_EN, hz / 32);
+               AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | AXE_GPIO2_EN, hz / 4);
+               AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | AXE_GPIO2 |
+                   AXE_GPIO2_EN, hz / 32);
+               break;
+       case AXE_PHY_MODE_REALTEK_8211CL:
+       case AXE_PHY_MODE_REALTEK_8211BN:
+       case AXE_PHY_MODE_REALTEK_8251CL:
+               val = gpio0 == 1 ? AXE_GPIO0 | AXE_GPIO0_EN :
+                   AXE_GPIO1 | AXE_GPIO1_EN;
+               AXE_GPIO_WRITE(val, hz / 32);
+               AXE_GPIO_WRITE(val | AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
+               AXE_GPIO_WRITE(val | AXE_GPIO2_EN, hz / 4);
+               AXE_GPIO_WRITE(val | AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
+               if (phymode == AXE_PHY_MODE_REALTEK_8211CL) {
+                       axe_miibus_writereg(ue->ue_dev, sc->sc_phyno,
+                           0x1F, 0x0005);
+                       axe_miibus_writereg(ue->ue_dev, sc->sc_phyno,
+                           0x0C, 0x0000);
+                       val = axe_miibus_readreg(ue->ue_dev, sc->sc_phyno,
+                           0x0001);
+                       axe_miibus_writereg(ue->ue_dev, sc->sc_phyno,
+                           0x01, val | 0x0080);
+                       axe_miibus_writereg(ue->ue_dev, sc->sc_phyno,
+                           0x1F, 0x0000);
+               }
+               break;
+       default:
+               /* Unknown PHY model or no need to program GPIOs. */
+               break;
        }
 
        /* soft reset */
        axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
-       uether_pause(&sc->sc_ue, hz / 4);
+       uether_pause(ue, hz / 4);
 
        axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
            AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
-       uether_pause(&sc->sc_ue, hz / 4);
+       uether_pause(ue, hz / 4);
        /* Enable MII/GMII/RGMII interface to work with external PHY. */
        axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL);
-       uether_pause(&sc->sc_ue, hz / 4);
+       uether_pause(ue, hz / 4);
 
        axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
 }
+#undef AXE_GPIO_WRITE
 
 static void
 axe_ax88772_init(struct axe_softc *sc)
@@ -637,10 +687,9 @@ axe_attach_post(struct usb_ether *ue)
         * Load PHY indexes first. Needed by axe_xxx_init().
         */
        axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, sc->sc_phyaddrs);
-#if 1
-       device_printf(sc->sc_ue.ue_dev, "PHYADDR 0x%02x:0x%02x\n",
-           sc->sc_phyaddrs[0], sc->sc_phyaddrs[1]);
-#endif
+       if (bootverbose)
+               device_printf(sc->sc_ue.ue_dev, "PHYADDR 0x%02x:0x%02x\n",
+                   sc->sc_phyaddrs[0], sc->sc_phyaddrs[1]);
        sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI);
        if (sc->sc_phyno == -1)
                sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC);

Modified: head/sys/dev/usb/net/if_axereg.h
==============================================================================
--- head/sys/dev/usb/net/if_axereg.h    Thu Sep  2 03:44:56 2010        
(r212129)
+++ head/sys/dev/usb/net/if_axereg.h    Thu Sep  2 03:47:07 2010        
(r212130)
@@ -153,6 +153,25 @@
 
 #define        AXE_772_PHY_NO_EPHY     0x10    /* Embedded 10/100 PHY of 
AX88772 */
 
+#define        AXE_GPIO0_EN            0x01
+#define        AXE_GPIO0               0x02
+#define        AXE_GPIO1_EN            0x04
+#define        AXE_GPIO1               0x08
+#define        AXE_GPIO2_EN            0x10
+#define        AXE_GPIO2               0x20
+#define        AXE_GPIO_RELOAD_EEPROM  0x80
+
+#define        AXE_PHY_MODE_MARVELL            0x00
+#define        AXE_PHY_MODE_CICADA             0x01
+#define        AXE_PHY_MODE_AGERE              0x02
+#define        AXE_PHY_MODE_CICADA_V2          0x05
+#define        AXE_PHY_MODE_AGERE_GMII         0x06
+#define        AXE_PHY_MODE_CICADA_V2_ASIX     0x09
+#define        AXE_PHY_MODE_REALTEK_8211CL     0x0C
+#define        AXE_PHY_MODE_REALTEK_8211BN     0x0D
+#define        AXE_PHY_MODE_REALTEK_8251CL     0x0E
+#define        AXE_PHY_MODE_ATTANSIC           0x40
+
 #define        AXE_BULK_BUF_SIZE       16384   /* bytes */
 
 #define        AXE_CTL_READ            0x01
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to