summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/net/if_axe.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2010-09-02 03:47:07 +0000
committerthompsa <thompsa@FreeBSD.org>2010-09-02 03:47:07 +0000
commit19070e6cf77ebf360e3b2c3704ccf11c5585c8d4 (patch)
treee6846ffb95fb6d55aeb931874e26f55e20cb79dc /sys/dev/usb/net/if_axe.c
parent052a1466647cc9ebcfc2d465467b0e6838de2e2e (diff)
downloadFreeBSD-src-19070e6cf77ebf360e3b2c3704ccf11c5585c8d4.zip
FreeBSD-src-19070e6cf77ebf360e3b2c3704ccf11c5585c8d4.tar.gz
Add GPIO programming for more PHY hardware.
Submitted by: yongari
Diffstat (limited to 'sys/dev/usb/net/if_axe.c')
-rw-r--r--sys/dev/usb/net/if_axe.c107
1 files changed, 78 insertions, 29 deletions
diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c
index 09f6561..eae72ce 100644
--- a/sys/dev/usb/net/if_axe.c
+++ b/sys/dev/usb/net/if_axe.c
@@ -515,12 +515,19 @@ axe_get_phyno(struct axe_softc *sc, int sel)
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);
OpenPOWER on IntegriCloud