cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Bycor
Visitor
Visitor
286 Views
Registered: ‎02-18-2021

Unable to modify PHY registers after ifdown called

Jump to solution
I am using Zynq with Petalinux 2020.2 and a standard Ethernet (eth0) on the processor system. The MDIO bus is shared with other external PHYs that are only used by the FPGA.
 
Since I need to do more than just change addresses when talking to the other PHYs, I wanted to disable eth0, communicate to other PHYs, then bring up eth0 again. This would only happen on startup.

I am using this guide:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/145031176/Reading+PHY+registers+over+MDIO+via+the+PHY+Management+GEM+Register

I can read/write while eth0 is up, but if I do "ifdown eth0" I can no longer read/write to the network_control register (nor the eth0 PHY registers). See trace below:

--- Interface up (reads fine):

root@test:~# devmem 0xe000b000 32
0x0000001C
root@test:~# devmem 0xe000b034 32
0x60280000

--- Interface down (cannot read)

root@test:~# ifdown eth0
macb e000b000.ethernet eth0: link down

root@test:~# devmem 0xe000b000 32
0x00000000
root@test:~# devmem 0xe000b034 32
0x00000000
root@test:~# devmem 0xe000b000 32 0x0000001C
root@test:~# devmem 0xe000b000 32

0x00000000

The guide suggests that I should be able to perform ifdown first, then communicate with the PHYs.

Here is the device tree:

gem0: ethernet@e000b000 {
289 compatible = "cdns,zynq-gem", "cdns,gem";
290 reg = <0xe000b000 0x1000>;
291 status = "disabled";
292 interrupts = <0 22 4>;
293 clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
294 clock-names = "pclk", "hclk", "tx_clk";
295 #address-cells = <1>;
296 #size-cells = <0>;
297 };

I thought maybe ifdown was disabling clocks, so I tried clk_ignore_unused in the bootargs, but it did not help.

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
Bycor
Visitor
Visitor
171 Views
Registered: ‎02-18-2021

 I found a way to do this. When the Ethernet interface goes down, many of the clocks get disabled. There may be a way to disable this with the PM, but my quick adjustments to the PM configuration didn't change anything.

So instead, removed the code that disables the clocks. I am not running on a power constrained system, so I don't mind if the clocks run all the time (there is likely a better way to do this from the PM configuration). When I get back to playing with this I might post a way.

In drivers/net/ethernet/cadence/macb_main.c, near line 4667, I comment out the following:

static int __maybe_unused macb_runtime_suspend(struct device *dev)
{
//    struct net_device *netdev = dev_get_drvdata(dev);
//    struct macb *bp = netdev_priv(netdev);

//    if (!(device_may_wakeup(&bp->dev->dev))) {
//        clk_disable_unprepare(bp->tx_clk);
//        clk_disable_unprepare(bp->hclk);
//        clk_disable_unprepare(bp->pclk);
//        clk_disable_unprepare(bp->rx_clk);
//    }

//    if (!(device_may_wakeup(&bp->dev->dev) &&
//        (bp->caps & MACB_CAPS_NEED_TSUCLK)))
//             clk_disable_unprepare(bp->tsu_clk);


    return 0;
}

 

View solution in original post

1 Reply
Bycor
Visitor
Visitor
172 Views
Registered: ‎02-18-2021

 I found a way to do this. When the Ethernet interface goes down, many of the clocks get disabled. There may be a way to disable this with the PM, but my quick adjustments to the PM configuration didn't change anything.

So instead, removed the code that disables the clocks. I am not running on a power constrained system, so I don't mind if the clocks run all the time (there is likely a better way to do this from the PM configuration). When I get back to playing with this I might post a way.

In drivers/net/ethernet/cadence/macb_main.c, near line 4667, I comment out the following:

static int __maybe_unused macb_runtime_suspend(struct device *dev)
{
//    struct net_device *netdev = dev_get_drvdata(dev);
//    struct macb *bp = netdev_priv(netdev);

//    if (!(device_may_wakeup(&bp->dev->dev))) {
//        clk_disable_unprepare(bp->tx_clk);
//        clk_disable_unprepare(bp->hclk);
//        clk_disable_unprepare(bp->pclk);
//        clk_disable_unprepare(bp->rx_clk);
//    }

//    if (!(device_may_wakeup(&bp->dev->dev) &&
//        (bp->caps & MACB_CAPS_NEED_TSUCLK)))
//             clk_disable_unprepare(bp->tsu_clk);


    return 0;
}

 

View solution in original post