summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2021-03-27 01:17:17 +0300
committerDavid S. Miller <davem@davemloft.net>2021-03-27 01:17:17 +0300
commit4e6d698f86a49681fd5e8e3639da3dbe451333bb (patch)
treecba9ceadaf439408c6d5e10fe8e4636ddb004d9e
parent32bc7a2cca4d748e434702378ec1c728a2387e04 (diff)
parentb11bfb9a19f9d790eea10cbd338b6b7f086c6dca (diff)
downloadlinux-4e6d698f86a49681fd5e8e3639da3dbe451333bb.tar.xz
Merge branch 'axienet-clock-additions'
Robert Hancock says: ==================== axienet clock additions Add support to the axienet driver for controlling all of the clocks that the logic core may utilize. Changed since v3: -Added Acked-by to patch 1 -Now applies to net-next tree after earlier patches merged in - code unchanged from v3 Changed since v2: -Additional clock description clarification Changed since v1: -Clarified clock usages in documentation and code comments ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/xilinx_axienet.txt25
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet.h8
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c34
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c4
4 files changed, 54 insertions, 17 deletions
diff --git a/Documentation/devicetree/bindings/net/xilinx_axienet.txt b/Documentation/devicetree/bindings/net/xilinx_axienet.txt
index 2cd452419ed0..b8e4894bc634 100644
--- a/Documentation/devicetree/bindings/net/xilinx_axienet.txt
+++ b/Documentation/devicetree/bindings/net/xilinx_axienet.txt
@@ -42,11 +42,23 @@ Optional properties:
support both 1000BaseX and SGMII modes. If set, the phy-mode
should be set to match the mode selected on core reset (i.e.
by the basex_or_sgmii core input line).
-- clocks : AXI bus clock for the device. Refer to common clock bindings.
- Used to calculate MDIO clock divisor. If not specified, it is
- auto-detected from the CPU clock (but only on platforms where
- this is possible). New device trees should specify this - the
- auto detection is only for backward compatibility.
+- clock-names: Tuple listing input clock names. Possible clocks:
+ s_axi_lite_clk: Clock for AXI register slave interface
+ axis_clk: AXI4-Stream clock for TXD RXD TXC and RXS interfaces
+ ref_clk: Ethernet reference clock, used by signal delay
+ primitives and transceivers
+ mgt_clk: MGT reference clock (used by optional internal
+ PCS/PMA PHY)
+
+ Note that if s_axi_lite_clk is not specified by name, the
+ first clock of any name is used for this. If that is also not
+ specified, the clock rate is auto-detected from the CPU clock
+ (but only on platforms where this is possible). New device
+ trees should specify all applicable clocks by name - the
+ fallbacks to an unnamed clock or to CPU clock are only for
+ backward compatibility.
+- clocks: Phandles to input clocks matching clock-names. Refer to common
+ clock bindings.
- axistream-connected: Reference to another node which contains the resources
for the AXI DMA controller used by this device.
If this is specified, the DMA-related resources from that
@@ -62,7 +74,8 @@ Example:
device_type = "network";
interrupt-parent = <&microblaze_0_axi_intc>;
interrupts = <2 0 1>;
- clocks = <&axi_clk>;
+ clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk";
+ clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>;
phy-mode = "mii";
reg = <0x40c00000 0x40000 0x50c00000 0x40000>;
xlnx,rxcsum = <0x2>;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 1e966a39967e..708769349f76 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -376,6 +376,8 @@ struct axidma_bd {
struct sk_buff *skb;
} __aligned(XAXIDMA_BD_MINIMUM_ALIGNMENT);
+#define XAE_NUM_MISC_CLOCKS 3
+
/**
* struct axienet_local - axienet private per device data
* @ndev: Pointer for net_device to which it will be attached.
@@ -385,7 +387,8 @@ struct axidma_bd {
* @phylink_config: phylink configuration settings
* @pcs_phy: Reference to PCS/PMA PHY if used
* @switch_x_sgmii: Whether switchable 1000BaseX/SGMII mode is enabled in the core
- * @clk: Clock for AXI bus
+ * @axi_clk: AXI4-Lite bus clock
+ * @misc_clks: Misc ethernet clocks (AXI4-Stream, Ref, MGT clocks)
* @mii_bus: Pointer to MII bus structure
* @mii_clk_div: MII bus clock divider value
* @regs_start: Resource start for axienet device addresses
@@ -434,7 +437,8 @@ struct axienet_local {
bool switch_x_sgmii;
- struct clk *clk;
+ struct clk *axi_clk;
+ struct clk_bulk_data misc_clks[XAE_NUM_MISC_CLOCKS];
struct mii_bus *mii_bus;
u8 mii_clk_div;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 5d677db0aee5..9635101fbb88 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1863,17 +1863,35 @@ static int axienet_probe(struct platform_device *pdev)
lp->rx_bd_num = RX_BD_NUM_DEFAULT;
lp->tx_bd_num = TX_BD_NUM_DEFAULT;
- lp->clk = devm_clk_get_optional(&pdev->dev, NULL);
- if (IS_ERR(lp->clk)) {
- ret = PTR_ERR(lp->clk);
+ lp->axi_clk = devm_clk_get_optional(&pdev->dev, "s_axi_lite_clk");
+ if (!lp->axi_clk) {
+ /* For backward compatibility, if named AXI clock is not present,
+ * treat the first clock specified as the AXI clock.
+ */
+ lp->axi_clk = devm_clk_get_optional(&pdev->dev, NULL);
+ }
+ if (IS_ERR(lp->axi_clk)) {
+ ret = PTR_ERR(lp->axi_clk);
goto free_netdev;
}
- ret = clk_prepare_enable(lp->clk);
+ ret = clk_prepare_enable(lp->axi_clk);
if (ret) {
- dev_err(&pdev->dev, "Unable to enable clock: %d\n", ret);
+ dev_err(&pdev->dev, "Unable to enable AXI clock: %d\n", ret);
goto free_netdev;
}
+ lp->misc_clks[0].id = "axis_clk";
+ lp->misc_clks[1].id = "ref_clk";
+ lp->misc_clks[2].id = "mgt_clk";
+
+ ret = devm_clk_bulk_get_optional(&pdev->dev, XAE_NUM_MISC_CLOCKS, lp->misc_clks);
+ if (ret)
+ goto cleanup_clk;
+
+ ret = clk_bulk_prepare_enable(XAE_NUM_MISC_CLOCKS, lp->misc_clks);
+ if (ret)
+ goto cleanup_clk;
+
/* Map device registers */
ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
@@ -2109,7 +2127,8 @@ cleanup_mdio:
of_node_put(lp->phy_node);
cleanup_clk:
- clk_disable_unprepare(lp->clk);
+ clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, lp->misc_clks);
+ clk_disable_unprepare(lp->axi_clk);
free_netdev:
free_netdev(ndev);
@@ -2132,7 +2151,8 @@ static int axienet_remove(struct platform_device *pdev)
axienet_mdio_teardown(lp);
- clk_disable_unprepare(lp->clk);
+ clk_bulk_disable_unprepare(XAE_NUM_MISC_CLOCKS, lp->misc_clks);
+ clk_disable_unprepare(lp->axi_clk);
of_node_put(lp->phy_node);
lp->phy_node = NULL;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index 9c014cee34b2..48f544f6c999 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -159,8 +159,8 @@ int axienet_mdio_enable(struct axienet_local *lp)
lp->mii_clk_div = 0;
- if (lp->clk) {
- host_clock = clk_get_rate(lp->clk);
+ if (lp->axi_clk) {
+ host_clock = clk_get_rate(lp->axi_clk);
} else {
struct device_node *np1;