Commit 4e6d698f authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 32bc7a2c b11bfb9a
...@@ -42,11 +42,23 @@ Optional properties: ...@@ -42,11 +42,23 @@ Optional properties:
support both 1000BaseX and SGMII modes. If set, the phy-mode support both 1000BaseX and SGMII modes. If set, the phy-mode
should be set to match the mode selected on core reset (i.e. should be set to match the mode selected on core reset (i.e.
by the basex_or_sgmii core input line). by the basex_or_sgmii core input line).
- clocks : AXI bus clock for the device. Refer to common clock bindings. - clock-names: Tuple listing input clock names. Possible clocks:
Used to calculate MDIO clock divisor. If not specified, it is s_axi_lite_clk: Clock for AXI register slave interface
auto-detected from the CPU clock (but only on platforms where axis_clk: AXI4-Stream clock for TXD RXD TXC and RXS interfaces
this is possible). New device trees should specify this - the ref_clk: Ethernet reference clock, used by signal delay
auto detection is only for backward compatibility. 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 - axistream-connected: Reference to another node which contains the resources
for the AXI DMA controller used by this device. for the AXI DMA controller used by this device.
If this is specified, the DMA-related resources from that If this is specified, the DMA-related resources from that
...@@ -62,7 +74,8 @@ Example: ...@@ -62,7 +74,8 @@ Example:
device_type = "network"; device_type = "network";
interrupt-parent = <&microblaze_0_axi_intc>; interrupt-parent = <&microblaze_0_axi_intc>;
interrupts = <2 0 1>; 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"; phy-mode = "mii";
reg = <0x40c00000 0x40000 0x50c00000 0x40000>; reg = <0x40c00000 0x40000 0x50c00000 0x40000>;
xlnx,rxcsum = <0x2>; xlnx,rxcsum = <0x2>;
......
...@@ -376,6 +376,8 @@ struct axidma_bd { ...@@ -376,6 +376,8 @@ struct axidma_bd {
struct sk_buff *skb; struct sk_buff *skb;
} __aligned(XAXIDMA_BD_MINIMUM_ALIGNMENT); } __aligned(XAXIDMA_BD_MINIMUM_ALIGNMENT);
#define XAE_NUM_MISC_CLOCKS 3
/** /**
* struct axienet_local - axienet private per device data * struct axienet_local - axienet private per device data
* @ndev: Pointer for net_device to which it will be attached. * @ndev: Pointer for net_device to which it will be attached.
...@@ -385,7 +387,8 @@ struct axidma_bd { ...@@ -385,7 +387,8 @@ struct axidma_bd {
* @phylink_config: phylink configuration settings * @phylink_config: phylink configuration settings
* @pcs_phy: Reference to PCS/PMA PHY if used * @pcs_phy: Reference to PCS/PMA PHY if used
* @switch_x_sgmii: Whether switchable 1000BaseX/SGMII mode is enabled in the core * @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_bus: Pointer to MII bus structure
* @mii_clk_div: MII bus clock divider value * @mii_clk_div: MII bus clock divider value
* @regs_start: Resource start for axienet device addresses * @regs_start: Resource start for axienet device addresses
...@@ -434,7 +437,8 @@ struct axienet_local { ...@@ -434,7 +437,8 @@ struct axienet_local {
bool switch_x_sgmii; 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; struct mii_bus *mii_bus;
u8 mii_clk_div; u8 mii_clk_div;
......
...@@ -1863,17 +1863,35 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -1863,17 +1863,35 @@ static int axienet_probe(struct platform_device *pdev)
lp->rx_bd_num = RX_BD_NUM_DEFAULT; lp->rx_bd_num = RX_BD_NUM_DEFAULT;
lp->tx_bd_num = TX_BD_NUM_DEFAULT; lp->tx_bd_num = TX_BD_NUM_DEFAULT;
lp->clk = devm_clk_get_optional(&pdev->dev, NULL); lp->axi_clk = devm_clk_get_optional(&pdev->dev, "s_axi_lite_clk");
if (IS_ERR(lp->clk)) { if (!lp->axi_clk) {
ret = PTR_ERR(lp->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; goto free_netdev;
} }
ret = clk_prepare_enable(lp->clk); ret = clk_prepare_enable(lp->axi_clk);
if (ret) { 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; 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 */ /* Map device registers */
ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0); ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
lp->regs = devm_ioremap_resource(&pdev->dev, ethres); lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
...@@ -2109,7 +2127,8 @@ static int axienet_probe(struct platform_device *pdev) ...@@ -2109,7 +2127,8 @@ static int axienet_probe(struct platform_device *pdev)
of_node_put(lp->phy_node); of_node_put(lp->phy_node);
cleanup_clk: 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:
free_netdev(ndev); free_netdev(ndev);
...@@ -2132,7 +2151,8 @@ static int axienet_remove(struct platform_device *pdev) ...@@ -2132,7 +2151,8 @@ static int axienet_remove(struct platform_device *pdev)
axienet_mdio_teardown(lp); 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); of_node_put(lp->phy_node);
lp->phy_node = NULL; lp->phy_node = NULL;
......
...@@ -159,8 +159,8 @@ int axienet_mdio_enable(struct axienet_local *lp) ...@@ -159,8 +159,8 @@ int axienet_mdio_enable(struct axienet_local *lp)
lp->mii_clk_div = 0; lp->mii_clk_div = 0;
if (lp->clk) { if (lp->axi_clk) {
host_clock = clk_get_rate(lp->clk); host_clock = clk_get_rate(lp->axi_clk);
} else { } else {
struct device_node *np1; struct device_node *np1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment