diff options
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 | 82 |
2 files changed, 61 insertions, 23 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 eeecc29cf5b7..d647a7d115ac 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c | |||
@@ -574,6 +574,18 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) | |||
574 | return NETDEV_TX_OK; | 574 | return NETDEV_TX_OK; |
575 | } | 575 | } |
576 | 576 | ||
577 | static void arc_emac_set_address_internal(struct net_device *ndev) | ||
578 | { | ||
579 | struct arc_emac_priv *priv = netdev_priv(ndev); | ||
580 | unsigned int addr_low, addr_hi; | ||
581 | |||
582 | addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); | ||
583 | addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); | ||
584 | |||
585 | arc_reg_set(priv, R_ADDRL, addr_low); | ||
586 | arc_reg_set(priv, R_ADDRH, addr_hi); | ||
587 | } | ||
588 | |||
577 | /** | 589 | /** |
578 | * arc_emac_set_address - Set the MAC address for this device. | 590 | * arc_emac_set_address - Set the MAC address for this device. |
579 | * @ndev: Pointer to net_device structure. | 591 | * @ndev: Pointer to net_device structure. |
@@ -587,9 +599,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) | |||
587 | */ | 599 | */ |
588 | static int arc_emac_set_address(struct net_device *ndev, void *p) | 600 | static int arc_emac_set_address(struct net_device *ndev, void *p) |
589 | { | 601 | { |
590 | struct arc_emac_priv *priv = netdev_priv(ndev); | ||
591 | struct sockaddr *addr = p; | 602 | struct sockaddr *addr = p; |
592 | unsigned int addr_low, addr_hi; | ||
593 | 603 | ||
594 | if (netif_running(ndev)) | 604 | if (netif_running(ndev)) |
595 | return -EBUSY; | 605 | return -EBUSY; |
@@ -599,11 +609,7 @@ static int arc_emac_set_address(struct net_device *ndev, void *p) | |||
599 | 609 | ||
600 | memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); | 610 | memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); |
601 | 611 | ||
602 | addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); | 612 | arc_emac_set_address_internal(ndev); |
603 | addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); | ||
604 | |||
605 | arc_reg_set(priv, R_ADDRL, addr_low); | ||
606 | arc_reg_set(priv, R_ADDRH, addr_hi); | ||
607 | 613 | ||
608 | return 0; | 614 | return 0; |
609 | } | 615 | } |
@@ -643,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
643 | return -ENODEV; | 649 | return -ENODEV; |
644 | } | 650 | } |
645 | 651 | ||
646 | /* Get CPU clock frequency from device tree */ | ||
647 | if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", | ||
648 | &clock_frequency)) { | ||
649 | dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); | ||
650 | return -EINVAL; | ||
651 | } | ||
652 | |||
653 | /* Get IRQ from device tree */ | 652 | /* Get IRQ from device tree */ |
654 | irq = irq_of_parse_and_map(pdev->dev.of_node, 0); | 653 | irq = irq_of_parse_and_map(pdev->dev.of_node, 0); |
655 | if (!irq) { | 654 | if (!irq) { |
@@ -677,17 +676,36 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
677 | priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); | 676 | priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); |
678 | if (IS_ERR(priv->regs)) { | 677 | if (IS_ERR(priv->regs)) { |
679 | err = PTR_ERR(priv->regs); | 678 | err = PTR_ERR(priv->regs); |
680 | goto out; | 679 | goto out_netdev; |
681 | } | 680 | } |
682 | 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); |
683 | 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 | |||
684 | id = arc_reg_get(priv, R_ID); | 702 | id = arc_reg_get(priv, R_ID); |
685 | 703 | ||
686 | /* Check for EMAC revision 5 or 7, magic number */ | 704 | /* Check for EMAC revision 5 or 7, magic number */ |
687 | if (!(id == 0x0005fd02 || id == 0x0007fd02)) { | 705 | if (!(id == 0x0005fd02 || id == 0x0007fd02)) { |
688 | 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); |
689 | err = -ENODEV; | 707 | err = -ENODEV; |
690 | goto out; | 708 | goto out_clken; |
691 | } | 709 | } |
692 | 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); |
693 | 711 | ||
@@ -702,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
702 | ndev->name, ndev); | 720 | ndev->name, ndev); |
703 | if (err) { | 721 | if (err) { |
704 | dev_err(&pdev->dev, "could not allocate IRQ\n"); | 722 | dev_err(&pdev->dev, "could not allocate IRQ\n"); |
705 | goto out; | 723 | goto out_clken; |
706 | } | 724 | } |
707 | 725 | ||
708 | /* Get MAC address from device tree */ | 726 | /* Get MAC address from device tree */ |
@@ -713,6 +731,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
713 | else | 731 | else |
714 | eth_hw_addr_random(ndev); | 732 | eth_hw_addr_random(ndev); |
715 | 733 | ||
734 | arc_emac_set_address_internal(ndev); | ||
716 | dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); | 735 | dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); |
717 | 736 | ||
718 | /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ | 737 | /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ |
@@ -722,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
722 | if (!priv->rxbd) { | 741 | if (!priv->rxbd) { |
723 | dev_err(&pdev->dev, "failed to allocate data buffers\n"); | 742 | dev_err(&pdev->dev, "failed to allocate data buffers\n"); |
724 | err = -ENOMEM; | 743 | err = -ENOMEM; |
725 | goto out; | 744 | goto out_clken; |
726 | } | 745 | } |
727 | 746 | ||
728 | priv->txbd = priv->rxbd + RX_BD_NUM; | 747 | priv->txbd = priv->rxbd + RX_BD_NUM; |
@@ -734,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
734 | err = arc_mdio_probe(pdev, priv); | 753 | err = arc_mdio_probe(pdev, priv); |
735 | if (err) { | 754 | if (err) { |
736 | dev_err(&pdev->dev, "failed to probe MII bus\n"); | 755 | dev_err(&pdev->dev, "failed to probe MII bus\n"); |
737 | goto out; | 756 | goto out_clken; |
738 | } | 757 | } |
739 | 758 | ||
740 | 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, |
@@ -742,7 +761,7 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
742 | if (!priv->phy_dev) { | 761 | if (!priv->phy_dev) { |
743 | dev_err(&pdev->dev, "of_phy_connect() failed\n"); | 762 | dev_err(&pdev->dev, "of_phy_connect() failed\n"); |
744 | err = -ENODEV; | 763 | err = -ENODEV; |
745 | goto out; | 764 | goto out_mdio; |
746 | } | 765 | } |
747 | 766 | ||
748 | dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", | 767 | dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", |
@@ -752,14 +771,25 @@ static int arc_emac_probe(struct platform_device *pdev) | |||
752 | 771 | ||
753 | err = register_netdev(ndev); | 772 | err = register_netdev(ndev); |
754 | if (err) { | 773 | if (err) { |
755 | netif_napi_del(&priv->napi); | ||
756 | dev_err(&pdev->dev, "failed to register network device\n"); | 774 | dev_err(&pdev->dev, "failed to register network device\n"); |
757 | goto out; | 775 | goto out_netif_api; |
758 | } | 776 | } |
759 | 777 | ||
760 | return 0; | 778 | return 0; |
761 | 779 | ||
762 | out: | 780 | out_netif_api: |
781 | netif_napi_del(&priv->napi); | ||
782 | phy_disconnect(priv->phy_dev); | ||
783 | priv->phy_dev = NULL; | ||
784 | out_mdio: | ||
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); | ||
792 | out_netdev: | ||
763 | free_netdev(ndev); | 793 | free_netdev(ndev); |
764 | return err; | 794 | return err; |
765 | } | 795 | } |
@@ -774,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev) | |||
774 | arc_mdio_remove(priv); | 804 | arc_mdio_remove(priv); |
775 | unregister_netdev(ndev); | 805 | unregister_netdev(ndev); |
776 | 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 | |||
777 | free_netdev(ndev); | 813 | free_netdev(ndev); |
778 | 814 | ||
779 | return 0; | 815 | return 0; |