static const struct pin_mux tx48_pads[] = {
{ OFFSET(i2c0_sda), MODE(7) | RXACTIVE | PULLUDEN | PULLUP_EN, },
{ OFFSET(i2c0_scl), MODE(7) | RXACTIVE | PULLUDEN | PULLUP_EN, },
+ { OFFSET(emu1), MODE(7), }, /* ETH PHY Reset */
};
static const struct pin_mux tx48_i2c_pads[] = {
}
#ifdef CONFIG_DRIVER_TI_CPSW
-static void tx48_phy_init(char *name, int addr)
+static void tx48_phy_init(void)
{
debug("%s: Resetting ethernet PHY\n", __func__);
.hw_stats_reg_ofs = 0x900,
.mac_control = (1 << 5) /* MIIEN */,
.control = cpsw_control,
- .phy_init = tx48_phy_init,
.gigabit_en = 0,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,
{
__raw_writel(RMII_MODE_ENABLE, MAC_MII_SEL);
__raw_writel(0x5D, GMII_SEL);
+ tx48_phy_init();
return cpsw_register(&cpsw_data);
}
#endif /* CONFIG_DRIVER_TI_CPSW */
return generic_for_interface(interface);
}
+static int aneg_enabled(struct phy_device *phydev)
+{
+ static const char *aneg = "_aneg";
+ char varname[strlen(phydev->bus->name) + strlen(aneg) + 1];
+
+ snprintf(varname, sizeof(varname), "%s%s", phydev->bus->name, aneg);
+ return getenv_yesno(varname);
+}
+
+static int phy_get_speed(struct phy_device *phydev)
+{
+ int ret;
+ static const char *aneg = "_speed";
+ char varname[strlen(phydev->bus->name) + strlen(aneg) + 1];
+ ulong val;
+
+ snprintf(varname, sizeof(varname), "%s%s", phydev->bus->name, aneg);
+
+ val = getenv_ulong(varname, 10, 100);
+ switch (val) {
+ case 1000:
+ ret = SPEED_1000;
+ break;
+ case 100:
+ ret = SPEED_100;
+ break;
+ case 10:
+ ret = SPEED_10;
+ break;
+ default:
+ printf("Improper setting '%s' for %s; assuming 100\n",
+ getenv(varname), varname);
+ ret = SPEED_100;
+ }
+ return ret;
+}
+
+static int phy_get_duplex(struct phy_device *phydev)
+{
+ int ret = DUPLEX_FULL;
+ static const char *aneg = "_duplex";
+ char varname[strlen(phydev->bus->name) + strlen(aneg) + 4];
+ const char *val;
+
+ snprintf(varname, sizeof(varname), "%s%d%s",
+ phydev->bus->name, phydev->addr, aneg);
+
+ val = getenv(varname);
+ if (val != NULL) {
+ if (strcasecmp(val, "full") != 0) {
+ if (strcasecmp(val, "half") == 0) {
+ ret = DUPLEX_HALF;
+ } else {
+ printf("Improper setting '%s' for %s; assuming 'full'\n",
+ val, varname);
+ printf("Expected one of: 'full', 'half'\n");
+ }
+ }
+ }
+
+ return ret;
+}
+
static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
int phy_id,
phy_interface_t interface)
dev->link = 1;
dev->interface = interface;
- dev->autoneg = AUTONEG_ENABLE;
-
dev->addr = addr;
dev->phy_id = phy_id;
dev->bus = bus;
dev->drv = get_phy_driver(dev, interface);
+ if (aneg_enabled(dev)) {
+ dev->autoneg = AUTONEG_ENABLE;
+ } else {
+ dev->autoneg = AUTONEG_DISABLE;
+ dev->speed = phy_get_speed(dev);
+ dev->duplex = phy_get_duplex(dev);
+
+ switch (dev->speed) {
+ case SPEED_1000:
+ if (dev->duplex == DUPLEX_FULL)
+ dev->supported &= SUPPORTED_1000baseT_Full;
+ else
+ dev->supported &= SUPPORTED_1000baseT_Half;
+ break;
+ case SPEED_100:
+ if (dev->duplex == DUPLEX_FULL)
+ dev->supported &= SUPPORTED_100baseT_Full;
+ else
+ dev->supported &= SUPPORTED_100baseT_Half;
+ break;
+ case SPEED_10:
+ if (dev->duplex == DUPLEX_FULL)
+ dev->supported &= SUPPORTED_10baseT_Full;
+ else
+ dev->supported &= SUPPORTED_10baseT_Half;
+ break;
+ default:
+ printf("Unsupported speed: %d\n", dev->speed);
+ }
+ }
+
phy_probe(dev);
bus->phymap[addr] = dev;
return smsc_parse_status(phydev);
}
+static int smsc_mdix_setup(struct phy_device *phydev)
+{
+ int ret;
+ static const char *mdix = "_mdi";
+ char varname[strlen(phydev->bus->name) + strlen(mdix) + 1];
+ const char *val;
+
+ snprintf(varname, sizeof(varname), "%s%s", phydev->bus->name, mdix);
+
+ val = getenv(varname);
+ if (val) {
+ if (strcasecmp(val, "auto") == 0) {
+ ret = 0;
+ } else if (strcasecmp(val, "mdix") == 0) {
+ ret = 1;
+ } else if (strcasecmp(val, "mdi") == 0) {
+ ret = 2;
+ } else {
+ printf("Improper setting '%s' for %s\n", val, varname);
+ printf("Expected one of: 'auto', 'mdi', 'mdix'\n");
+ return -EINVAL;
+ }
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+static int smsc_config(struct phy_device *phydev)
+{
+ int mdix = smsc_mdix_setup(phydev);
+
+ if (mdix < 0) {
+ return mdix;
+ } else if (mdix) {
+ int ret = phy_write(phydev, MDIO_DEVAD_NONE, 0x1b,
+ (1 << 15) | ((mdix & 1) << 13));
+ if (ret) {
+ printf("Failed to setup MDI/MDIX mode: %d\n", ret);
+ return ret;
+ }
+ }
+ return genphy_config_aneg(phydev);
+}
+
static struct phy_driver lan8700_driver = {
.name = "SMSC LAN8700",
.uid = 0x0007c0c0,
.uid = 0x0007c0f0,
.mask = 0xffff0,
.features = PHY_GBIT_FEATURES,
- .config = &genphy_config_aneg,
+ .config = &smsc_config,
.startup = &smsc_startup,
.shutdown = &genphy_shutdown,
};