aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2017-02-20 14:10:58 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-22 15:36:47 -0500
commita577ca6badb5261d3fa1bcbb3332ae7874f1a3a2 (patch)
tree5b5843c6b0a47ccd092e37c2b3bcd21884678bf5
parentca78d3173cff3503bcd15723b049757f75762d15 (diff)
net: emac: add support for device-tree based PHY discovery and setup
This patch adds glue-code that allows the EMAC driver to interface with the existing dt-supported PHYs in drivers/net/phy. Because currently, the emac driver maintains a small library of supported phys for in a private phy.c file located in the drivers directory. The support is limited to mostly single ethernet transceiver like the: CIS8201, BCM5248, ET1011C, Marvell 88E1111 and 88E1112, AR8035. However, routers like the Netgear WNDR4700 and Cisco Meraki MX60(W) have a 5-port switch (AR8327N) attached to the EMAC. The switch chip is supported by the qca8k mdio driver, which uses the generic phy library. Another reason is that PHYLIB also supports the BCM54610, which was used for the Western Digital My Book Live. This will now also make EMAC select PHYLIB. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ibm/emac/Kconfig1
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c254
-rw-r--r--drivers/net/ethernet/ibm/emac/core.h4
3 files changed, 252 insertions, 7 deletions
diff --git a/drivers/net/ethernet/ibm/emac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig
index 3f44a30e0615..90d49191beb3 100644
--- a/drivers/net/ethernet/ibm/emac/Kconfig
+++ b/drivers/net/ethernet/ibm/emac/Kconfig
@@ -2,6 +2,7 @@ config IBM_EMAC
2 tristate "IBM EMAC Ethernet support" 2 tristate "IBM EMAC Ethernet support"
3 depends on PPC_DCR 3 depends on PPC_DCR
4 select CRC32 4 select CRC32
5 select PHYLIB
5 help 6 help
6 This driver supports the IBM EMAC family of Ethernet controllers 7 This driver supports the IBM EMAC family of Ethernet controllers
7 typically found on 4xx embedded PowerPC chips, but also on the 8 typically found on 4xx embedded PowerPC chips, but also on the
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 6ead2335a169..275c2e2349ad 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -42,6 +42,7 @@
42#include <linux/of_address.h> 42#include <linux/of_address.h>
43#include <linux/of_irq.h> 43#include <linux/of_irq.h>
44#include <linux/of_net.h> 44#include <linux/of_net.h>
45#include <linux/of_mdio.h>
45#include <linux/slab.h> 46#include <linux/slab.h>
46 47
47#include <asm/processor.h> 48#include <asm/processor.h>
@@ -2420,6 +2421,219 @@ static int emac_read_uint_prop(struct device_node *np, const char *name,
2420 return 0; 2421 return 0;
2421} 2422}
2422 2423
2424static void emac_adjust_link(struct net_device *ndev)
2425{
2426 struct emac_instance *dev = netdev_priv(ndev);
2427 struct phy_device *phy = dev->phy_dev;
2428
2429 dev->phy.autoneg = phy->autoneg;
2430 dev->phy.speed = phy->speed;
2431 dev->phy.duplex = phy->duplex;
2432 dev->phy.pause = phy->pause;
2433 dev->phy.asym_pause = phy->asym_pause;
2434 dev->phy.advertising = phy->advertising;
2435}
2436
2437static int emac_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
2438{
2439 int ret = emac_mdio_read(bus->priv, addr, regnum);
2440 /* This is a workaround for powered down ports/phys.
2441 * In the wild, this was seen on the Cisco Meraki MX60(W).
2442 * This hardware disables ports as part of the handoff
2443 * procedure. Accessing the ports will lead to errors
2444 * (-ETIMEDOUT, -EREMOTEIO) that do more harm than good.
2445 */
2446 return ret < 0 ? 0xffff : ret;
2447}
2448
2449static int emac_mii_bus_write(struct mii_bus *bus, int addr,
2450 int regnum, u16 val)
2451{
2452 emac_mdio_write(bus->priv, addr, regnum, val);
2453 return 0;
2454}
2455
2456static int emac_mii_bus_reset(struct mii_bus *bus)
2457{
2458 struct emac_instance *dev = netdev_priv(bus->priv);
2459
2460 return emac_reset(dev);
2461}
2462
2463static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise)
2464{
2465 struct net_device *ndev = phy->dev;
2466 struct emac_instance *dev = netdev_priv(ndev);
2467
2468 dev->phy.autoneg = AUTONEG_ENABLE;
2469 dev->phy.speed = SPEED_1000;
2470 dev->phy.duplex = DUPLEX_FULL;
2471 dev->phy.advertising = advertise;
2472 phy->autoneg = AUTONEG_ENABLE;
2473 phy->speed = dev->phy.speed;
2474 phy->duplex = dev->phy.duplex;
2475 phy->advertising = advertise;
2476 return phy_start_aneg(dev->phy_dev);
2477}
2478
2479static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)
2480{
2481 struct net_device *ndev = phy->dev;
2482 struct emac_instance *dev = netdev_priv(ndev);
2483
2484 dev->phy.autoneg = AUTONEG_DISABLE;
2485 dev->phy.speed = speed;
2486 dev->phy.duplex = fd;
2487 phy->autoneg = AUTONEG_DISABLE;
2488 phy->speed = speed;
2489 phy->duplex = fd;
2490 return phy_start_aneg(dev->phy_dev);
2491}
2492
2493static int emac_mdio_poll_link(struct mii_phy *phy)
2494{
2495 struct net_device *ndev = phy->dev;
2496 struct emac_instance *dev = netdev_priv(ndev);
2497 int res;
2498
2499 res = phy_read_status(dev->phy_dev);
2500 if (res) {
2501 dev_err(&dev->ofdev->dev, "link update failed (%d).", res);
2502 return ethtool_op_get_link(ndev);
2503 }
2504
2505 return dev->phy_dev->link;
2506}
2507
2508static int emac_mdio_read_link(struct mii_phy *phy)
2509{
2510 struct net_device *ndev = phy->dev;
2511 struct emac_instance *dev = netdev_priv(ndev);
2512 int res;
2513
2514 res = phy_read_status(dev->phy_dev);
2515 if (res)
2516 return res;
2517
2518 dev->phy.speed = phy->speed;
2519 dev->phy.duplex = phy->duplex;
2520 dev->phy.pause = phy->pause;
2521 dev->phy.asym_pause = phy->asym_pause;
2522 return 0;
2523}
2524
2525static int emac_mdio_init_phy(struct mii_phy *phy)
2526{
2527 struct net_device *ndev = phy->dev;
2528 struct emac_instance *dev = netdev_priv(ndev);
2529
2530 phy_start(dev->phy_dev);
2531 dev->phy.autoneg = phy->autoneg;
2532 dev->phy.speed = phy->speed;
2533 dev->phy.duplex = phy->duplex;
2534 dev->phy.advertising = phy->advertising;
2535 dev->phy.pause = phy->pause;
2536 dev->phy.asym_pause = phy->asym_pause;
2537
2538 return phy_init_hw(dev->phy_dev);
2539}
2540
2541static const struct mii_phy_ops emac_dt_mdio_phy_ops = {
2542 .init = emac_mdio_init_phy,
2543 .setup_aneg = emac_mdio_setup_aneg,
2544 .setup_forced = emac_mdio_setup_forced,
2545 .poll_link = emac_mdio_poll_link,
2546 .read_link = emac_mdio_read_link,
2547};
2548
2549static int emac_dt_mdio_probe(struct emac_instance *dev)
2550{
2551 struct device_node *mii_np;
2552 int res;
2553
2554 mii_np = of_get_child_by_name(dev->ofdev->dev.of_node, "mdio");
2555 if (!mii_np) {
2556 dev_err(&dev->ofdev->dev, "no mdio definition found.");
2557 return -ENODEV;
2558 }
2559
2560 if (!of_device_is_available(mii_np)) {
2561 res = -ENODEV;
2562 goto put_node;
2563 }
2564
2565 dev->mii_bus = devm_mdiobus_alloc(&dev->ofdev->dev);
2566 if (!dev->mii_bus) {
2567 res = -ENOMEM;
2568 goto put_node;
2569 }
2570
2571 dev->mii_bus->priv = dev->ndev;
2572 dev->mii_bus->parent = dev->ndev->dev.parent;
2573 dev->mii_bus->name = "emac_mdio";
2574 dev->mii_bus->read = &emac_mii_bus_read;
2575 dev->mii_bus->write = &emac_mii_bus_write;
2576 dev->mii_bus->reset = &emac_mii_bus_reset;
2577 snprintf(dev->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev->ofdev->name);
2578 res = of_mdiobus_register(dev->mii_bus, mii_np);
2579 if (res) {
2580 dev_err(&dev->ofdev->dev, "cannot register MDIO bus %s (%d)",
2581 dev->mii_bus->name, res);
2582 }
2583
2584 put_node:
2585 of_node_put(mii_np);
2586 return res;
2587}
2588
2589static int emac_dt_phy_connect(struct emac_instance *dev,
2590 struct device_node *phy_handle)
2591{
2592 int res;
2593
2594 dev->phy.def = devm_kzalloc(&dev->ofdev->dev, sizeof(*dev->phy.def),
2595 GFP_KERNEL);
2596 if (!dev->phy.def)
2597 return -ENOMEM;
2598
2599 dev->phy_dev = of_phy_connect(dev->ndev, phy_handle, &emac_adjust_link,
2600 0, dev->phy_mode);
2601 if (!dev->phy_dev) {
2602 dev_err(&dev->ofdev->dev, "failed to connect to PHY.\n");
2603 return -ENODEV;
2604 }
2605
2606 dev->phy.def->phy_id = dev->phy_dev->drv->phy_id;
2607 dev->phy.def->phy_id_mask = dev->phy_dev->drv->phy_id_mask;
2608 dev->phy.def->name = dev->phy_dev->drv->name;
2609 dev->phy.def->ops = &emac_dt_mdio_phy_ops;
2610 dev->phy.features = dev->phy_dev->supported;
2611 dev->phy.address = dev->phy_dev->mdio.addr;
2612 dev->phy.mode = dev->phy_dev->interface;
2613 return 0;
2614}
2615
2616static int emac_dt_phy_probe(struct emac_instance *dev)
2617{
2618 struct device_node *np = dev->ofdev->dev.of_node;
2619 struct device_node *phy_handle;
2620 int res = 0;
2621
2622 phy_handle = of_parse_phandle(np, "phy-handle", 0);
2623
2624 if (phy_handle) {
2625 res = emac_dt_mdio_probe(dev);
2626 if (!res) {
2627 res = emac_dt_phy_connect(dev, phy_handle);
2628 if (res)
2629 mdiobus_unregister(dev->mii_bus);
2630 }
2631 }
2632
2633 of_node_put(phy_handle);
2634 return res;
2635}
2636
2423static int emac_init_phy(struct emac_instance *dev) 2637static int emac_init_phy(struct emac_instance *dev)
2424{ 2638{
2425 struct device_node *np = dev->ofdev->dev.of_node; 2639 struct device_node *np = dev->ofdev->dev.of_node;
@@ -2430,15 +2644,12 @@ static int emac_init_phy(struct emac_instance *dev)
2430 dev->phy.dev = ndev; 2644 dev->phy.dev = ndev;
2431 dev->phy.mode = dev->phy_mode; 2645 dev->phy.mode = dev->phy_mode;
2432 2646
2433 /* PHY-less configuration. 2647 /* PHY-less configuration. */
2434 * XXX I probably should move these settings to the dev tree 2648 if ((dev->phy_address == 0xffffffff && dev->phy_map == 0xffffffff) ||
2435 */ 2649 of_phy_is_fixed_link(np)) {
2436 if (dev->phy_address == 0xffffffff && dev->phy_map == 0xffffffff) {
2437 emac_reset(dev); 2650 emac_reset(dev);
2438 2651
2439 /* PHY-less configuration. 2652 /* PHY-less configuration. */
2440 * XXX I probably should move these settings to the dev tree
2441 */
2442 dev->phy.address = -1; 2653 dev->phy.address = -1;
2443 dev->phy.features = SUPPORTED_MII; 2654 dev->phy.features = SUPPORTED_MII;
2444 if (emac_phy_supports_gige(dev->phy_mode)) 2655 if (emac_phy_supports_gige(dev->phy_mode))
@@ -2447,6 +2658,16 @@ static int emac_init_phy(struct emac_instance *dev)
2447 dev->phy.features |= SUPPORTED_100baseT_Full; 2658 dev->phy.features |= SUPPORTED_100baseT_Full;
2448 dev->phy.pause = 1; 2659 dev->phy.pause = 1;
2449 2660
2661 if (of_phy_is_fixed_link(np)) {
2662 int res = emac_dt_mdio_probe(dev);
2663
2664 if (!res) {
2665 res = of_phy_register_fixed_link(np);
2666 if (res)
2667 mdiobus_unregister(dev->mii_bus);
2668 }
2669 return res;
2670 }
2450 return 0; 2671 return 0;
2451 } 2672 }
2452 2673
@@ -2490,6 +2711,18 @@ static int emac_init_phy(struct emac_instance *dev)
2490 2711
2491 emac_configure(dev); 2712 emac_configure(dev);
2492 2713
2714 if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII)) {
2715 int res = emac_dt_phy_probe(dev);
2716
2717 mutex_unlock(&emac_phy_map_lock);
2718 if (!res)
2719 goto init_phy;
2720
2721 dev_err(&dev->ofdev->dev, "failed to attach dt phy (%d).\n",
2722 res);
2723 return res;
2724 }
2725
2493 if (dev->phy_address != 0xffffffff) 2726 if (dev->phy_address != 0xffffffff)
2494 phy_map = ~(1 << dev->phy_address); 2727 phy_map = ~(1 << dev->phy_address);
2495 2728
@@ -2517,6 +2750,7 @@ static int emac_init_phy(struct emac_instance *dev)
2517 return -ENXIO; 2750 return -ENXIO;
2518 } 2751 }
2519 2752
2753 init_phy:
2520 /* Init PHY */ 2754 /* Init PHY */
2521 if (dev->phy.def->ops->init) 2755 if (dev->phy.def->ops->init)
2522 dev->phy.def->ops->init(&dev->phy); 2756 dev->phy.def->ops->init(&dev->phy);
@@ -2988,6 +3222,12 @@ static int emac_remove(struct platform_device *ofdev)
2988 if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII)) 3222 if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
2989 zmii_detach(dev->zmii_dev, dev->zmii_port); 3223 zmii_detach(dev->zmii_dev, dev->zmii_port);
2990 3224
3225 if (dev->phy_dev)
3226 phy_disconnect(dev->phy_dev);
3227
3228 if (dev->mii_bus)
3229 mdiobus_unregister(dev->mii_bus);
3230
2991 busy_phy_map &= ~(1 << dev->phy.address); 3231 busy_phy_map &= ~(1 << dev->phy.address);
2992 DBG(dev, "busy_phy_map now %#x" NL, busy_phy_map); 3232 DBG(dev, "busy_phy_map now %#x" NL, busy_phy_map);
2993 3233
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index 93ae11494810..0710a6685489 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -199,6 +199,10 @@ struct emac_instance {
199 struct emac_instance *mdio_instance; 199 struct emac_instance *mdio_instance;
200 struct mutex mdio_lock; 200 struct mutex mdio_lock;
201 201
202 /* Device-tree based phy configuration */
203 struct mii_bus *mii_bus;
204 struct phy_device *phy_dev;
205
202 /* ZMII infos if any */ 206 /* ZMII infos if any */
203 u32 zmii_ph; 207 u32 zmii_ph;
204 u32 zmii_port; 208 u32 zmii_port;