diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2008-08-26 07:34:19 -0400 |
---|---|---|
committer | Lennert Buytenhek <buytenh@marvell.com> | 2008-09-19 13:34:00 -0400 |
commit | ed94493fb38a665cebcf750dfabe8a6dd13e136f (patch) | |
tree | c02a9e722bb32232ef975548cbb1291d9ccc92c6 /drivers/net | |
parent | 4fd5f812c23c7deee6425f4a318e85c317cd1d6c (diff) |
mv643xx_eth: convert to phylib
Switch mv643xx_eth from using drivers/net/mii.c to using phylib.
Since the mv643xx_eth hardware does all the link state handling and
PHY polling, the driver will use phylib in the "Doing it all yourself"
mode described in the phylib documentation.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Acked-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/mv643xx_eth.c | 248 |
2 files changed, 105 insertions, 145 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4a11296a951..d85d76019af 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2262,7 +2262,7 @@ config UGETH_TX_ON_DEMAND | |||
2262 | config MV643XX_ETH | 2262 | config MV643XX_ETH |
2263 | tristate "Marvell Discovery (643XX) and Orion ethernet support" | 2263 | tristate "Marvell Discovery (643XX) and Orion ethernet support" |
2264 | depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION | 2264 | depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION |
2265 | select MII | 2265 | select PHYLIB |
2266 | help | 2266 | help |
2267 | This driver supports the gigabit ethernet MACs in the | 2267 | This driver supports the gigabit ethernet MACs in the |
2268 | Marvell Discovery PPC/MIPS chipset family (MV643XX) and | 2268 | Marvell Discovery PPC/MIPS chipset family (MV643XX) and |
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index d0ecc440aac..1f944a23f53 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -48,7 +48,7 @@ | |||
48 | #include <linux/kernel.h> | 48 | #include <linux/kernel.h> |
49 | #include <linux/spinlock.h> | 49 | #include <linux/spinlock.h> |
50 | #include <linux/workqueue.h> | 50 | #include <linux/workqueue.h> |
51 | #include <linux/mii.h> | 51 | #include <linux/phy.h> |
52 | #include <linux/mv643xx_eth.h> | 52 | #include <linux/mv643xx_eth.h> |
53 | #include <asm/io.h> | 53 | #include <asm/io.h> |
54 | #include <asm/types.h> | 54 | #include <asm/types.h> |
@@ -248,9 +248,9 @@ struct mv643xx_eth_shared_private { | |||
248 | struct mv643xx_eth_shared_private *smi; | 248 | struct mv643xx_eth_shared_private *smi; |
249 | 249 | ||
250 | /* | 250 | /* |
251 | * Protects access to SMI_REG, which is shared between ports. | 251 | * Provides access to local SMI interface. |
252 | */ | 252 | */ |
253 | struct mutex phy_lock; | 253 | struct mii_bus smi_bus; |
254 | 254 | ||
255 | /* | 255 | /* |
256 | * If we have access to the error interrupt pin (which is | 256 | * If we have access to the error interrupt pin (which is |
@@ -354,14 +354,13 @@ struct mv643xx_eth_private { | |||
354 | 354 | ||
355 | struct net_device *dev; | 355 | struct net_device *dev; |
356 | 356 | ||
357 | int phy_addr; | 357 | struct phy_device *phy; |
358 | 358 | ||
359 | struct timer_list mib_counters_timer; | 359 | struct timer_list mib_counters_timer; |
360 | spinlock_t mib_counters_lock; | 360 | spinlock_t mib_counters_lock; |
361 | struct mib_counters mib_counters; | 361 | struct mib_counters mib_counters; |
362 | 362 | ||
363 | struct work_struct tx_timeout_task; | 363 | struct work_struct tx_timeout_task; |
364 | struct mii_if_info mii; | ||
365 | 364 | ||
366 | struct napi_struct napi; | 365 | struct napi_struct napi; |
367 | u8 work_link; | 366 | u8 work_link; |
@@ -1076,62 +1075,50 @@ static int smi_wait_ready(struct mv643xx_eth_shared_private *msp) | |||
1076 | return 0; | 1075 | return 0; |
1077 | } | 1076 | } |
1078 | 1077 | ||
1079 | static int smi_reg_read(struct mv643xx_eth_private *mp, | 1078 | static int smi_bus_read(struct mii_bus *bus, int addr, int reg) |
1080 | unsigned int addr, unsigned int reg) | ||
1081 | { | 1079 | { |
1082 | struct mv643xx_eth_shared_private *msp = mp->shared->smi; | 1080 | struct mv643xx_eth_shared_private *msp = bus->priv; |
1083 | void __iomem *smi_reg = msp->base + SMI_REG; | 1081 | void __iomem *smi_reg = msp->base + SMI_REG; |
1084 | int ret; | 1082 | int ret; |
1085 | 1083 | ||
1086 | mutex_lock(&msp->phy_lock); | ||
1087 | |||
1088 | if (smi_wait_ready(msp)) { | 1084 | if (smi_wait_ready(msp)) { |
1089 | printk("%s: SMI bus busy timeout\n", mp->dev->name); | 1085 | printk("mv643xx_eth: SMI bus busy timeout\n"); |
1090 | ret = -ETIMEDOUT; | 1086 | return -ETIMEDOUT; |
1091 | goto out; | ||
1092 | } | 1087 | } |
1093 | 1088 | ||
1094 | writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg); | 1089 | writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg); |
1095 | 1090 | ||
1096 | if (smi_wait_ready(msp)) { | 1091 | if (smi_wait_ready(msp)) { |
1097 | printk("%s: SMI bus busy timeout\n", mp->dev->name); | 1092 | printk("mv643xx_eth: SMI bus busy timeout\n"); |
1098 | ret = -ETIMEDOUT; | 1093 | return -ETIMEDOUT; |
1099 | goto out; | ||
1100 | } | 1094 | } |
1101 | 1095 | ||
1102 | ret = readl(smi_reg); | 1096 | ret = readl(smi_reg); |
1103 | if (!(ret & SMI_READ_VALID)) { | 1097 | if (!(ret & SMI_READ_VALID)) { |
1104 | printk("%s: SMI bus read not valid\n", mp->dev->name); | 1098 | printk("mv643xx_eth: SMI bus read not valid\n"); |
1105 | ret = -ENODEV; | 1099 | return -ENODEV; |
1106 | goto out; | ||
1107 | } | 1100 | } |
1108 | 1101 | ||
1109 | ret &= 0xffff; | 1102 | return ret & 0xffff; |
1110 | |||
1111 | out: | ||
1112 | mutex_unlock(&msp->phy_lock); | ||
1113 | |||
1114 | return ret; | ||
1115 | } | 1103 | } |
1116 | 1104 | ||
1117 | static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, | 1105 | static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val) |
1118 | unsigned int reg, unsigned int value) | ||
1119 | { | 1106 | { |
1120 | struct mv643xx_eth_shared_private *msp = mp->shared->smi; | 1107 | struct mv643xx_eth_shared_private *msp = bus->priv; |
1121 | void __iomem *smi_reg = msp->base + SMI_REG; | 1108 | void __iomem *smi_reg = msp->base + SMI_REG; |
1122 | 1109 | ||
1123 | mutex_lock(&msp->phy_lock); | ||
1124 | |||
1125 | if (smi_wait_ready(msp)) { | 1110 | if (smi_wait_ready(msp)) { |
1126 | printk("%s: SMI bus busy timeout\n", mp->dev->name); | 1111 | printk("mv643xx_eth: SMI bus busy timeout\n"); |
1127 | mutex_unlock(&msp->phy_lock); | ||
1128 | return -ETIMEDOUT; | 1112 | return -ETIMEDOUT; |
1129 | } | 1113 | } |
1130 | 1114 | ||
1131 | writel(SMI_OPCODE_WRITE | (reg << 21) | | 1115 | writel(SMI_OPCODE_WRITE | (reg << 21) | |
1132 | (addr << 16) | (value & 0xffff), smi_reg); | 1116 | (addr << 16) | (val & 0xffff), smi_reg); |
1133 | 1117 | ||
1134 | mutex_unlock(&msp->phy_lock); | 1118 | if (smi_wait_ready(msp)) { |
1119 | printk("mv643xx_eth: SMI bus busy timeout\n"); | ||
1120 | return -ETIMEDOUT; | ||
1121 | } | ||
1135 | 1122 | ||
1136 | return 0; | 1123 | return 0; |
1137 | } | 1124 | } |
@@ -1287,7 +1274,9 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd * | |||
1287 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1274 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1288 | int err; | 1275 | int err; |
1289 | 1276 | ||
1290 | err = mii_ethtool_gset(&mp->mii, cmd); | 1277 | err = phy_read_status(mp->phy); |
1278 | if (err == 0) | ||
1279 | err = phy_ethtool_gset(mp->phy, cmd); | ||
1291 | 1280 | ||
1292 | /* | 1281 | /* |
1293 | * The MAC does not support 1000baseT_Half. | 1282 | * The MAC does not support 1000baseT_Half. |
@@ -1341,7 +1330,7 @@ static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd * | |||
1341 | */ | 1330 | */ |
1342 | cmd->advertising &= ~ADVERTISED_1000baseT_Half; | 1331 | cmd->advertising &= ~ADVERTISED_1000baseT_Half; |
1343 | 1332 | ||
1344 | return mii_ethtool_sset(&mp->mii, cmd); | 1333 | return phy_ethtool_sset(mp->phy, cmd); |
1345 | } | 1334 | } |
1346 | 1335 | ||
1347 | static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd) | 1336 | static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd) |
@@ -1363,7 +1352,7 @@ static int mv643xx_eth_nway_reset(struct net_device *dev) | |||
1363 | { | 1352 | { |
1364 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1353 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1365 | 1354 | ||
1366 | return mii_nway_restart(&mp->mii); | 1355 | return genphy_restart_aneg(mp->phy); |
1367 | } | 1356 | } |
1368 | 1357 | ||
1369 | static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) | 1358 | static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) |
@@ -1373,14 +1362,7 @@ static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) | |||
1373 | 1362 | ||
1374 | static u32 mv643xx_eth_get_link(struct net_device *dev) | 1363 | static u32 mv643xx_eth_get_link(struct net_device *dev) |
1375 | { | 1364 | { |
1376 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1365 | return !!netif_carrier_ok(dev); |
1377 | |||
1378 | return mii_link_ok(&mp->mii); | ||
1379 | } | ||
1380 | |||
1381 | static u32 mv643xx_eth_get_link_phyless(struct net_device *dev) | ||
1382 | { | ||
1383 | return 1; | ||
1384 | } | 1366 | } |
1385 | 1367 | ||
1386 | static void mv643xx_eth_get_strings(struct net_device *dev, | 1368 | static void mv643xx_eth_get_strings(struct net_device *dev, |
@@ -1448,7 +1430,7 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = { | |||
1448 | .set_settings = mv643xx_eth_set_settings_phyless, | 1430 | .set_settings = mv643xx_eth_set_settings_phyless, |
1449 | .get_drvinfo = mv643xx_eth_get_drvinfo, | 1431 | .get_drvinfo = mv643xx_eth_get_drvinfo, |
1450 | .nway_reset = mv643xx_eth_nway_reset_phyless, | 1432 | .nway_reset = mv643xx_eth_nway_reset_phyless, |
1451 | .get_link = mv643xx_eth_get_link_phyless, | 1433 | .get_link = mv643xx_eth_get_link, |
1452 | .set_sg = ethtool_op_set_sg, | 1434 | .set_sg = ethtool_op_set_sg, |
1453 | .get_strings = mv643xx_eth_get_strings, | 1435 | .get_strings = mv643xx_eth_get_strings, |
1454 | .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, | 1436 | .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, |
@@ -1941,16 +1923,16 @@ static void phy_reset(struct mv643xx_eth_private *mp) | |||
1941 | { | 1923 | { |
1942 | int data; | 1924 | int data; |
1943 | 1925 | ||
1944 | data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); | 1926 | data = phy_read(mp->phy, MII_BMCR); |
1945 | if (data < 0) | 1927 | if (data < 0) |
1946 | return; | 1928 | return; |
1947 | 1929 | ||
1948 | data |= BMCR_RESET; | 1930 | data |= BMCR_RESET; |
1949 | if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data) < 0) | 1931 | if (phy_write(mp->phy, MII_BMCR, data) < 0) |
1950 | return; | 1932 | return; |
1951 | 1933 | ||
1952 | do { | 1934 | do { |
1953 | data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); | 1935 | data = phy_read(mp->phy, MII_BMCR); |
1954 | } while (data >= 0 && data & BMCR_RESET); | 1936 | } while (data >= 0 && data & BMCR_RESET); |
1955 | } | 1937 | } |
1956 | 1938 | ||
@@ -1962,7 +1944,7 @@ static void port_start(struct mv643xx_eth_private *mp) | |||
1962 | /* | 1944 | /* |
1963 | * Perform PHY reset, if there is a PHY. | 1945 | * Perform PHY reset, if there is a PHY. |
1964 | */ | 1946 | */ |
1965 | if (mp->phy_addr != -1) { | 1947 | if (mp->phy != NULL) { |
1966 | struct ethtool_cmd cmd; | 1948 | struct ethtool_cmd cmd; |
1967 | 1949 | ||
1968 | mv643xx_eth_get_settings(mp->dev, &cmd); | 1950 | mv643xx_eth_get_settings(mp->dev, &cmd); |
@@ -1979,7 +1961,7 @@ static void port_start(struct mv643xx_eth_private *mp) | |||
1979 | wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); | 1961 | wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); |
1980 | 1962 | ||
1981 | pscr |= DO_NOT_FORCE_LINK_FAIL; | 1963 | pscr |= DO_NOT_FORCE_LINK_FAIL; |
1982 | if (mp->phy_addr == -1) | 1964 | if (mp->phy == NULL) |
1983 | pscr |= FORCE_LINK_PASS; | 1965 | pscr |= FORCE_LINK_PASS; |
1984 | wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); | 1966 | wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); |
1985 | 1967 | ||
@@ -2188,8 +2170,8 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
2188 | { | 2170 | { |
2189 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 2171 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
2190 | 2172 | ||
2191 | if (mp->phy_addr != -1) | 2173 | if (mp->phy != NULL) |
2192 | return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); | 2174 | return phy_mii_ioctl(mp->phy, if_mii(ifr), cmd); |
2193 | 2175 | ||
2194 | return -EOPNOTSUPP; | 2176 | return -EOPNOTSUPP; |
2195 | } | 2177 | } |
@@ -2259,18 +2241,6 @@ static void mv643xx_eth_netpoll(struct net_device *dev) | |||
2259 | } | 2241 | } |
2260 | #endif | 2242 | #endif |
2261 | 2243 | ||
2262 | static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg) | ||
2263 | { | ||
2264 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
2265 | return smi_reg_read(mp, addr, reg); | ||
2266 | } | ||
2267 | |||
2268 | static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val) | ||
2269 | { | ||
2270 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
2271 | smi_reg_write(mp, addr, reg, val); | ||
2272 | } | ||
2273 | |||
2274 | 2244 | ||
2275 | /* platform glue ************************************************************/ | 2245 | /* platform glue ************************************************************/ |
2276 | static void | 2246 | static void |
@@ -2365,11 +2335,23 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) | |||
2365 | if (msp->base == NULL) | 2335 | if (msp->base == NULL) |
2366 | goto out_free; | 2336 | goto out_free; |
2367 | 2337 | ||
2368 | msp->smi = msp; | 2338 | /* |
2369 | if (pd != NULL && pd->shared_smi != NULL) | 2339 | * Set up and register SMI bus. |
2340 | */ | ||
2341 | if (pd == NULL || pd->shared_smi == NULL) { | ||
2342 | msp->smi_bus.priv = msp; | ||
2343 | msp->smi_bus.name = "mv643xx_eth smi"; | ||
2344 | msp->smi_bus.read = smi_bus_read; | ||
2345 | msp->smi_bus.write = smi_bus_write, | ||
2346 | snprintf(msp->smi_bus.id, MII_BUS_ID_SIZE, "%d", pdev->id); | ||
2347 | msp->smi_bus.dev = &pdev->dev; | ||
2348 | msp->smi_bus.phy_mask = 0xffffffff; | ||
2349 | if (mdiobus_register(&msp->smi_bus) < 0) | ||
2350 | goto out_unmap; | ||
2351 | msp->smi = msp; | ||
2352 | } else { | ||
2370 | msp->smi = platform_get_drvdata(pd->shared_smi); | 2353 | msp->smi = platform_get_drvdata(pd->shared_smi); |
2371 | 2354 | } | |
2372 | mutex_init(&msp->phy_lock); | ||
2373 | 2355 | ||
2374 | msp->err_interrupt = NO_IRQ; | 2356 | msp->err_interrupt = NO_IRQ; |
2375 | init_waitqueue_head(&msp->smi_busy_wait); | 2357 | init_waitqueue_head(&msp->smi_busy_wait); |
@@ -2405,6 +2387,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) | |||
2405 | 2387 | ||
2406 | return 0; | 2388 | return 0; |
2407 | 2389 | ||
2390 | out_unmap: | ||
2391 | iounmap(msp->base); | ||
2408 | out_free: | 2392 | out_free: |
2409 | kfree(msp); | 2393 | kfree(msp); |
2410 | out: | 2394 | out: |
@@ -2414,7 +2398,10 @@ out: | |||
2414 | static int mv643xx_eth_shared_remove(struct platform_device *pdev) | 2398 | static int mv643xx_eth_shared_remove(struct platform_device *pdev) |
2415 | { | 2399 | { |
2416 | struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); | 2400 | struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); |
2401 | struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; | ||
2417 | 2402 | ||
2403 | if (pd == NULL || pd->shared_smi == NULL) | ||
2404 | mdiobus_unregister(&msp->smi_bus); | ||
2418 | if (msp->err_interrupt != NO_IRQ) | 2405 | if (msp->err_interrupt != NO_IRQ) |
2419 | free_irq(msp->err_interrupt, msp); | 2406 | free_irq(msp->err_interrupt, msp); |
2420 | iounmap(msp->base); | 2407 | iounmap(msp->base); |
@@ -2462,17 +2449,6 @@ static void set_params(struct mv643xx_eth_private *mp, | |||
2462 | else | 2449 | else |
2463 | uc_addr_get(mp, dev->dev_addr); | 2450 | uc_addr_get(mp, dev->dev_addr); |
2464 | 2451 | ||
2465 | if (pd->phy_addr == MV643XX_ETH_PHY_NONE) { | ||
2466 | mp->phy_addr = -1; | ||
2467 | } else { | ||
2468 | if (pd->phy_addr != MV643XX_ETH_PHY_ADDR_DEFAULT) { | ||
2469 | mp->phy_addr = pd->phy_addr & 0x3f; | ||
2470 | phy_addr_set(mp, mp->phy_addr); | ||
2471 | } else { | ||
2472 | mp->phy_addr = phy_addr_get(mp); | ||
2473 | } | ||
2474 | } | ||
2475 | |||
2476 | mp->default_rx_ring_size = DEFAULT_RX_QUEUE_SIZE; | 2452 | mp->default_rx_ring_size = DEFAULT_RX_QUEUE_SIZE; |
2477 | if (pd->rx_queue_size) | 2453 | if (pd->rx_queue_size) |
2478 | mp->default_rx_ring_size = pd->rx_queue_size; | 2454 | mp->default_rx_ring_size = pd->rx_queue_size; |
@@ -2490,76 +2466,60 @@ static void set_params(struct mv643xx_eth_private *mp, | |||
2490 | mp->txq_count = pd->tx_queue_count ? : 1; | 2466 | mp->txq_count = pd->tx_queue_count ? : 1; |
2491 | } | 2467 | } |
2492 | 2468 | ||
2493 | static int phy_detect(struct mv643xx_eth_private *mp) | 2469 | static struct phy_device *phy_scan(struct mv643xx_eth_private *mp, |
2470 | int phy_addr) | ||
2494 | { | 2471 | { |
2495 | int data; | 2472 | struct mii_bus *bus = &mp->shared->smi->smi_bus; |
2496 | int data2; | 2473 | struct phy_device *phydev; |
2474 | int start; | ||
2475 | int num; | ||
2476 | int i; | ||
2497 | 2477 | ||
2498 | data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); | 2478 | if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) { |
2499 | if (data < 0) | 2479 | start = phy_addr_get(mp) & 0x1f; |
2500 | return -ENODEV; | 2480 | num = 32; |
2481 | } else { | ||
2482 | start = phy_addr & 0x1f; | ||
2483 | num = 1; | ||
2484 | } | ||
2501 | 2485 | ||
2502 | if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE) < 0) | 2486 | phydev = NULL; |
2503 | return -ENODEV; | 2487 | for (i = 0; i < num; i++) { |
2488 | int addr = (start + i) & 0x1f; | ||
2504 | 2489 | ||
2505 | data2 = smi_reg_read(mp, mp->phy_addr, MII_BMCR); | 2490 | if (bus->phy_map[addr] == NULL) |
2506 | if (data2 < 0) | 2491 | mdiobus_scan(bus, addr); |
2507 | return -ENODEV; | ||
2508 | 2492 | ||
2509 | if (((data ^ data2) & BMCR_ANENABLE) == 0) | 2493 | if (phydev == NULL) { |
2510 | return -ENODEV; | 2494 | phydev = bus->phy_map[addr]; |
2511 | 2495 | if (phydev != NULL) | |
2512 | smi_reg_write(mp, mp->phy_addr, MII_BMCR, data); | 2496 | phy_addr_set(mp, addr); |
2497 | } | ||
2498 | } | ||
2513 | 2499 | ||
2514 | return 0; | 2500 | return phydev; |
2515 | } | 2501 | } |
2516 | 2502 | ||
2517 | static int phy_init(struct mv643xx_eth_private *mp, | 2503 | static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) |
2518 | struct mv643xx_eth_platform_data *pd) | ||
2519 | { | 2504 | { |
2520 | struct ethtool_cmd cmd; | 2505 | struct phy_device *phy = mp->phy; |
2521 | int err; | ||
2522 | 2506 | ||
2523 | err = phy_detect(mp); | ||
2524 | if (err) { | ||
2525 | dev_printk(KERN_INFO, &mp->dev->dev, | ||
2526 | "no PHY detected at addr %d\n", mp->phy_addr); | ||
2527 | return err; | ||
2528 | } | ||
2529 | phy_reset(mp); | 2507 | phy_reset(mp); |
2530 | 2508 | ||
2531 | mp->mii.phy_id = mp->phy_addr; | 2509 | phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); |
2532 | mp->mii.phy_id_mask = 0x3f; | 2510 | |
2533 | mp->mii.reg_num_mask = 0x1f; | 2511 | if (speed == 0) { |
2534 | mp->mii.dev = mp->dev; | 2512 | phy->autoneg = AUTONEG_ENABLE; |
2535 | mp->mii.mdio_read = mv643xx_eth_mdio_read; | 2513 | phy->speed = 0; |
2536 | mp->mii.mdio_write = mv643xx_eth_mdio_write; | 2514 | phy->duplex = 0; |
2537 | 2515 | phy->advertising = phy->supported | ADVERTISED_Autoneg; | |
2538 | mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); | ||
2539 | |||
2540 | memset(&cmd, 0, sizeof(cmd)); | ||
2541 | |||
2542 | cmd.port = PORT_MII; | ||
2543 | cmd.transceiver = XCVR_INTERNAL; | ||
2544 | cmd.phy_address = mp->phy_addr; | ||
2545 | if (pd->speed == 0) { | ||
2546 | cmd.autoneg = AUTONEG_ENABLE; | ||
2547 | cmd.speed = SPEED_100; | ||
2548 | cmd.advertising = ADVERTISED_10baseT_Half | | ||
2549 | ADVERTISED_10baseT_Full | | ||
2550 | ADVERTISED_100baseT_Half | | ||
2551 | ADVERTISED_100baseT_Full; | ||
2552 | if (mp->mii.supports_gmii) | ||
2553 | cmd.advertising |= ADVERTISED_1000baseT_Full; | ||
2554 | } else { | 2516 | } else { |
2555 | cmd.autoneg = AUTONEG_DISABLE; | 2517 | phy->autoneg = AUTONEG_DISABLE; |
2556 | cmd.speed = pd->speed; | 2518 | phy->advertising = 0; |
2557 | cmd.duplex = pd->duplex; | 2519 | phy->speed = speed; |
2520 | phy->duplex = duplex; | ||
2558 | } | 2521 | } |
2559 | 2522 | phy_start_aneg(phy); | |
2560 | mv643xx_eth_set_settings(mp->dev, &cmd); | ||
2561 | |||
2562 | return 0; | ||
2563 | } | 2523 | } |
2564 | 2524 | ||
2565 | static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) | 2525 | static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) |
@@ -2573,7 +2533,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) | |||
2573 | } | 2533 | } |
2574 | 2534 | ||
2575 | pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED; | 2535 | pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED; |
2576 | if (mp->phy_addr == -1) { | 2536 | if (mp->phy == NULL) { |
2577 | pscr |= DISABLE_AUTO_NEG_SPEED_GMII; | 2537 | pscr |= DISABLE_AUTO_NEG_SPEED_GMII; |
2578 | if (speed == SPEED_1000) | 2538 | if (speed == SPEED_1000) |
2579 | pscr |= SET_GMII_SPEED_TO_1000; | 2539 | pscr |= SET_GMII_SPEED_TO_1000; |
@@ -2627,18 +2587,16 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2627 | set_params(mp, pd); | 2587 | set_params(mp, pd); |
2628 | dev->real_num_tx_queues = mp->txq_count; | 2588 | dev->real_num_tx_queues = mp->txq_count; |
2629 | 2589 | ||
2630 | mib_counters_clear(mp); | 2590 | if (pd->phy_addr != MV643XX_ETH_PHY_NONE) |
2631 | INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); | 2591 | mp->phy = phy_scan(mp, pd->phy_addr); |
2632 | |||
2633 | if (mp->phy_addr != -1) { | ||
2634 | err = phy_init(mp, pd); | ||
2635 | if (err) | ||
2636 | goto out; | ||
2637 | 2592 | ||
2593 | if (mp->phy != NULL) { | ||
2594 | phy_init(mp, pd->speed, pd->duplex); | ||
2638 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); | 2595 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); |
2639 | } else { | 2596 | } else { |
2640 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless); | 2597 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless); |
2641 | } | 2598 | } |
2599 | |||
2642 | init_pscr(mp, pd->speed, pd->duplex); | 2600 | init_pscr(mp, pd->speed, pd->duplex); |
2643 | 2601 | ||
2644 | 2602 | ||
@@ -2711,6 +2669,8 @@ static int mv643xx_eth_remove(struct platform_device *pdev) | |||
2711 | struct mv643xx_eth_private *mp = platform_get_drvdata(pdev); | 2669 | struct mv643xx_eth_private *mp = platform_get_drvdata(pdev); |
2712 | 2670 | ||
2713 | unregister_netdev(mp->dev); | 2671 | unregister_netdev(mp->dev); |
2672 | if (mp->phy != NULL) | ||
2673 | phy_detach(mp->phy); | ||
2714 | flush_scheduled_work(); | 2674 | flush_scheduled_work(); |
2715 | free_netdev(mp->dev); | 2675 | free_netdev(mp->dev); |
2716 | 2676 | ||