42
42
#include <linux/of_address.h>
43
43
#include <linux/of_irq.h>
44
44
#include <linux/of_net.h>
45
+ #include <linux/of_mdio.h>
45
46
#include <linux/slab.h>
46
47
47
48
#include <asm/processor.h>
@@ -2420,6 +2421,219 @@ static int emac_read_uint_prop(struct device_node *np, const char *name,
2420
2421
return 0 ;
2421
2422
}
2422
2423
2424
+ static 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
+
2437
+ static 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
+
2449
+ static 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
+
2456
+ static 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
+
2463
+ static 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
+
2479
+ static 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
+
2493
+ static 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
+
2508
+ static 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
+
2525
+ static 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
+
2541
+ static 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
+
2549
+ static 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
+
2589
+ static 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
+
2616
+ static 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
+
2423
2637
static int emac_init_phy (struct emac_instance * dev )
2424
2638
{
2425
2639
struct device_node * np = dev -> ofdev -> dev .of_node ;
@@ -2430,15 +2644,12 @@ static int emac_init_phy(struct emac_instance *dev)
2430
2644
dev -> phy .dev = ndev ;
2431
2645
dev -> phy .mode = dev -> phy_mode ;
2432
2646
2433
- /* PHY-less configuration.
2434
- * XXX I probably should move these settings to the dev tree
2435
- */
2436
- if (dev -> phy_address == 0xffffffff && dev -> phy_map == 0xffffffff ) {
2647
+ /* PHY-less configuration. */
2648
+ if ((dev -> phy_address == 0xffffffff && dev -> phy_map == 0xffffffff ) ||
2649
+ of_phy_is_fixed_link (np )) {
2437
2650
emac_reset (dev );
2438
2651
2439
- /* PHY-less configuration.
2440
- * XXX I probably should move these settings to the dev tree
2441
- */
2652
+ /* PHY-less configuration. */
2442
2653
dev -> phy .address = -1 ;
2443
2654
dev -> phy .features = SUPPORTED_MII ;
2444
2655
if (emac_phy_supports_gige (dev -> phy_mode ))
@@ -2447,6 +2658,16 @@ static int emac_init_phy(struct emac_instance *dev)
2447
2658
dev -> phy .features |= SUPPORTED_100baseT_Full ;
2448
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
2671
return 0 ;
2451
2672
}
2452
2673
@@ -2490,6 +2711,18 @@ static int emac_init_phy(struct emac_instance *dev)
2490
2711
2491
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
2726
if (dev -> phy_address != 0xffffffff )
2494
2727
phy_map = ~(1 << dev -> phy_address );
2495
2728
@@ -2517,6 +2750,7 @@ static int emac_init_phy(struct emac_instance *dev)
2517
2750
return - ENXIO ;
2518
2751
}
2519
2752
2753
+ init_phy :
2520
2754
/* Init PHY */
2521
2755
if (dev -> phy .def -> ops -> init )
2522
2756
dev -> phy .def -> ops -> init (& dev -> phy );
@@ -2988,6 +3222,12 @@ static int emac_remove(struct platform_device *ofdev)
2988
3222
if (emac_has_feature (dev , EMAC_FTR_HAS_ZMII ))
2989
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
3231
busy_phy_map &= ~(1 << dev -> phy .address );
2992
3232
DBG (dev , "busy_phy_map now %#x" NL , busy_phy_map );
2993
3233
0 commit comments