Commit 88154c96 authored by Heiko Stübner's avatar Heiko Stübner Committed by David S. Miller

arc_emac: add clock handling

This adds ability for the arc_emac to really handle its supplying clock.
To get the needed clock-frequency either a real clock or the previous
clock-frequency property must be provided.
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
Tested-by: default avatarMax Schwarz <max.schwarz@online.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 796bec1e
...@@ -4,11 +4,15 @@ Required properties: ...@@ -4,11 +4,15 @@ Required properties:
- compatible: Should be "snps,arc-emac" - compatible: Should be "snps,arc-emac"
- reg: Address and length of the register set for the device - reg: Address and length of the register set for the device
- interrupts: Should contain the EMAC interrupts - interrupts: Should contain the EMAC interrupts
- clock-frequency: CPU frequency. It is needed to calculate and set polling
period of EMAC.
- max-speed: see ethernet.txt file in the same directory. - max-speed: see ethernet.txt file in the same directory.
- phy: see ethernet.txt file in the same directory. - phy: see ethernet.txt file in the same directory.
Clock handling:
The clock frequency is needed to calculate and set polling period of EMAC.
It must be provided by one of:
- clock-frequency: CPU frequency.
- clocks: reference to the clock supplying the EMAC.
Child nodes of the driver are the individual PHY devices connected to the Child nodes of the driver are the individual PHY devices connected to the
MDIO bus. They must have a "reg" property given the PHY address on the MDIO bus. MDIO bus. They must have a "reg" property given the PHY address on the MDIO bus.
...@@ -19,7 +23,11 @@ Examples: ...@@ -19,7 +23,11 @@ Examples:
reg = <0xc0fc2000 0x3c>; reg = <0xc0fc2000 0x3c>;
interrupts = <6>; interrupts = <6>;
mac-address = [ 00 11 22 33 44 55 ]; mac-address = [ 00 11 22 33 44 55 ];
clock-frequency = <80000000>; clock-frequency = <80000000>;
/* or */
clocks = <&emac_clock>;
max-speed = <100>; max-speed = <100>;
phy = <&phy0>; phy = <&phy0>;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/clk.h>
/* STATUS and ENABLE Register bit masks */ /* STATUS and ENABLE Register bit masks */
#define TXINT_MASK (1<<0) /* Transmit interrupt */ #define TXINT_MASK (1<<0) /* Transmit interrupt */
...@@ -131,6 +132,7 @@ struct arc_emac_priv { ...@@ -131,6 +132,7 @@ struct arc_emac_priv {
struct mii_bus *bus; struct mii_bus *bus;
void __iomem *regs; void __iomem *regs;
struct clk *clk;
struct napi_struct napi; struct napi_struct napi;
struct net_device_stats stats; struct net_device_stats stats;
......
...@@ -649,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -649,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* Get CPU clock frequency from device tree */
if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&clock_frequency)) {
dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n");
return -EINVAL;
}
/* Get IRQ from device tree */ /* Get IRQ from device tree */
irq = irq_of_parse_and_map(pdev->dev.of_node, 0); irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!irq) { if (!irq) {
...@@ -687,13 +680,32 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -687,13 +680,32 @@ static int arc_emac_probe(struct platform_device *pdev)
} }
dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs);
priv->clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(priv->clk)) {
/* Get CPU clock frequency from device tree */
if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&clock_frequency)) {
dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n");
err = -EINVAL;
goto out_netdev;
}
} else {
err = clk_prepare_enable(priv->clk);
if (err) {
dev_err(&pdev->dev, "failed to enable clock\n");
goto out_clkget;
}
clock_frequency = clk_get_rate(priv->clk);
}
id = arc_reg_get(priv, R_ID); id = arc_reg_get(priv, R_ID);
/* Check for EMAC revision 5 or 7, magic number */ /* Check for EMAC revision 5 or 7, magic number */
if (!(id == 0x0005fd02 || id == 0x0007fd02)) { if (!(id == 0x0005fd02 || id == 0x0007fd02)) {
dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id);
err = -ENODEV; err = -ENODEV;
goto out_netdev; goto out_clken;
} }
dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id);
...@@ -708,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -708,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev)
ndev->name, ndev); ndev->name, ndev);
if (err) { if (err) {
dev_err(&pdev->dev, "could not allocate IRQ\n"); dev_err(&pdev->dev, "could not allocate IRQ\n");
goto out_netdev; goto out_clken;
} }
/* Get MAC address from device tree */ /* Get MAC address from device tree */
...@@ -729,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -729,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev)
if (!priv->rxbd) { if (!priv->rxbd) {
dev_err(&pdev->dev, "failed to allocate data buffers\n"); dev_err(&pdev->dev, "failed to allocate data buffers\n");
err = -ENOMEM; err = -ENOMEM;
goto out_netdev; goto out_clken;
} }
priv->txbd = priv->rxbd + RX_BD_NUM; priv->txbd = priv->rxbd + RX_BD_NUM;
...@@ -741,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -741,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev)
err = arc_mdio_probe(pdev, priv); err = arc_mdio_probe(pdev, priv);
if (err) { if (err) {
dev_err(&pdev->dev, "failed to probe MII bus\n"); dev_err(&pdev->dev, "failed to probe MII bus\n");
goto out_netdev; goto out_clken;
} }
priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0,
...@@ -771,6 +783,12 @@ static int arc_emac_probe(struct platform_device *pdev) ...@@ -771,6 +783,12 @@ static int arc_emac_probe(struct platform_device *pdev)
priv->phy_dev = NULL; priv->phy_dev = NULL;
out_mdio: out_mdio:
arc_mdio_remove(priv); arc_mdio_remove(priv);
out_clken:
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
out_clkget:
if (!IS_ERR(priv->clk))
clk_put(priv->clk);
out_netdev: out_netdev:
free_netdev(ndev); free_netdev(ndev);
return err; return err;
...@@ -786,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev) ...@@ -786,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev)
arc_mdio_remove(priv); arc_mdio_remove(priv);
unregister_netdev(ndev); unregister_netdev(ndev);
netif_napi_del(&priv->napi); netif_napi_del(&priv->napi);
if (!IS_ERR(priv->clk)) {
clk_disable_unprepare(priv->clk);
clk_put(priv->clk);
}
free_netdev(ndev); free_netdev(ndev);
return 0; return 0;
......
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