diff options
author | Heiko Stübner <heiko@sntech.de> | 2014-04-25 04:06:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-27 19:46:17 -0400 |
commit | 88154c96ee2dab84ae78ad41562b4a3a23d83788 (patch) | |
tree | 8b5892907536e3d31a325ce0587e3e1a6e416535 /drivers/net/ethernet/arc | |
parent | 796bec1efbbd3be98d84cd68279c6ec03a4782f9 (diff) |
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: Heiko Stuebner <heiko@sntech.de>
Tested-by: Max Schwarz <max.schwarz@online.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/arc')
-rw-r--r-- | drivers/net/ethernet/arc/emac.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/arc/emac_main.c | 46 |
2 files changed, 37 insertions, 11 deletions
diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h index 928fac6dd10a..53f85bf71526 100644 --- a/drivers/net/ethernet/arc/emac.h +++ b/drivers/net/ethernet/arc/emac.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/dma-mapping.h> | 11 | #include <linux/dma-mapping.h> |
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <linux/phy.h> | 13 | #include <linux/phy.h> |
14 | #include <linux/clk.h> | ||
14 | 15 | ||
15 | /* STATUS and ENABLE Register bit masks */ | 16 | /* STATUS and ENABLE Register bit masks */ |
16 | #define TXINT_MASK (1<<0) /* Transmit interrupt */ | 17 | #define TXINT_MASK (1<<0) /* Transmit interrupt */ |
@@ -131,6 +132,7 @@ struct arc_emac_priv { | |||
131 | struct mii_bus *bus; | 132 | struct mii_bus *bus; |
132 | 133 | ||
133 | void __iomem *regs; | 134 | void __iomem *regs; |
135 | struct clk *clk; | ||
134 | 136 | ||
135 | struct napi_struct napi; | 137 | struct napi_struct napi; |
136 | struct net_device_stats stats; | 138 | struct net_device_stats stats; |
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index 9747ddaf6ad2..d647a7d115ac 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c | |||
@@ -649,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
649 | return -ENODEV; | 649 | return -ENODEV; |
650 | } | 650 | } |
651 | 651 | ||
652 | /* Get CPU clock frequency from device tree */ | ||
653 | if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", | ||
654 | &clock_frequency)) { | ||
655 | dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); | ||
656 | return -EINVAL; | ||
657 | } | ||
658 | |||
659 | /* Get IRQ from device tree */ | 652 | /* Get IRQ from device tree */ |
660 | irq = irq_of_parse_and_map(pdev->dev.of_node, 0); | 653 | irq = irq_of_parse_and_map(pdev->dev.of_node, 0); |
661 | if (!irq) { | 654 | if (!irq) { |
@@ -687,13 +680,32 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
687 | } | 680 | } |
688 | dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); | 681 | dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); |
689 | 682 | ||
683 | priv->clk = of_clk_get(pdev->dev.of_node, 0); | ||
684 | if (IS_ERR(priv->clk)) { | ||
685 | /* Get CPU clock frequency from device tree */ | ||
686 | if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", | ||
687 | &clock_frequency)) { | ||
688 | dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); | ||
689 | err = -EINVAL; | ||
690 | goto out_netdev; | ||
691 | } | ||
692 | } else { | ||
693 | err = clk_prepare_enable(priv->clk); | ||
694 | if (err) { | ||
695 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
696 | goto out_clkget; | ||
697 | } | ||
698 | |||
699 | clock_frequency = clk_get_rate(priv->clk); | ||
700 | } | ||
701 | |||
690 | id = arc_reg_get(priv, R_ID); | 702 | id = arc_reg_get(priv, R_ID); |
691 | 703 | ||
692 | /* Check for EMAC revision 5 or 7, magic number */ | 704 | /* Check for EMAC revision 5 or 7, magic number */ |
693 | if (!(id == 0x0005fd02 || id == 0x0007fd02)) { | 705 | if (!(id == 0x0005fd02 || id == 0x0007fd02)) { |
694 | dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); | 706 | dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); |
695 | err = -ENODEV; | 707 | err = -ENODEV; |
696 | goto out_netdev; | 708 | goto out_clken; |
697 | } | 709 | } |
698 | dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); | 710 | dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); |
699 | 711 | ||
@@ -708,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
708 | ndev->name, ndev); | 720 | ndev->name, ndev); |
709 | if (err) { | 721 | if (err) { |
710 | dev_err(&pdev->dev, "could not allocate IRQ\n"); | 722 | dev_err(&pdev->dev, "could not allocate IRQ\n"); |
711 | goto out_netdev; | 723 | goto out_clken; |
712 | } | 724 | } |
713 | 725 | ||
714 | /* Get MAC address from device tree */ | 726 | /* Get MAC address from device tree */ |
@@ -729,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
729 | if (!priv->rxbd) { | 741 | if (!priv->rxbd) { |
730 | dev_err(&pdev->dev, "failed to allocate data buffers\n"); | 742 | dev_err(&pdev->dev, "failed to allocate data buffers\n"); |
731 | err = -ENOMEM; | 743 | err = -ENOMEM; |
732 | goto out_netdev; | 744 | goto out_clken; |
733 | } | 745 | } |
734 | 746 | ||
735 | priv->txbd = priv->rxbd + RX_BD_NUM; | 747 | priv->txbd = priv->rxbd + RX_BD_NUM; |
@@ -741,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
741 | err = arc_mdio_probe(pdev, priv); | 753 | err = arc_mdio_probe(pdev, priv); |
742 | if (err) { | 754 | if (err) { |
743 | dev_err(&pdev->dev, "failed to probe MII bus\n"); | 755 | dev_err(&pdev->dev, "failed to probe MII bus\n"); |
744 | goto out_netdev; | 756 | goto out_clken; |
745 | } | 757 | } |
746 | 758 | ||
747 | priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, | 759 | priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, |
@@ -771,6 +783,12 @@ out_netif_api: | |||
771 | priv->phy_dev = NULL; | 783 | priv->phy_dev = NULL; |
772 | out_mdio: | 784 | out_mdio: |
773 | arc_mdio_remove(priv); | 785 | arc_mdio_remove(priv); |
786 | out_clken: | ||
787 | if (!IS_ERR(priv->clk)) | ||
788 | clk_disable_unprepare(priv->clk); | ||
789 | out_clkget: | ||
790 | if (!IS_ERR(priv->clk)) | ||
791 | clk_put(priv->clk); | ||
774 | out_netdev: | 792 | out_netdev: |
775 | free_netdev(ndev); | 793 | free_netdev(ndev); |
776 | return err; | 794 | return err; |
@@ -786,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev) | |||
786 | arc_mdio_remove(priv); | 804 | arc_mdio_remove(priv); |
787 | unregister_netdev(ndev); | 805 | unregister_netdev(ndev); |
788 | netif_napi_del(&priv->napi); | 806 | netif_napi_del(&priv->napi); |
807 | |||
808 | if (!IS_ERR(priv->clk)) { | ||
809 | clk_disable_unprepare(priv->clk); | ||
810 | clk_put(priv->clk); | ||
811 | } | ||
812 | |||
789 | free_netdev(ndev); | 813 | free_netdev(ndev); |
790 | 814 | ||
791 | return 0; | 815 | return 0; |