diff options
Diffstat (limited to 'drivers/net/fs_enet/fs_enet-main.c')
-rw-r--r-- | drivers/net/fs_enet/fs_enet-main.c | 212 |
1 files changed, 131 insertions, 81 deletions
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 196298f33db..34412bc7c4b 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * kind, whether express or implied. | 15 | * kind, whether express or implied. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/config.h> | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
21 | #include <linux/types.h> | 20 | #include <linux/types.h> |
@@ -38,6 +37,7 @@ | |||
38 | #include <linux/bitops.h> | 37 | #include <linux/bitops.h> |
39 | #include <linux/fs.h> | 38 | #include <linux/fs.h> |
40 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
40 | #include <linux/phy.h> | ||
41 | 41 | ||
42 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
@@ -672,7 +672,7 @@ static int fs_request_irq(struct net_device *dev, int irq, const char *name, | |||
672 | struct fs_enet_private *fep = netdev_priv(dev); | 672 | struct fs_enet_private *fep = netdev_priv(dev); |
673 | 673 | ||
674 | (*fep->ops->pre_request_irq)(dev, irq); | 674 | (*fep->ops->pre_request_irq)(dev, irq); |
675 | return request_irq(irq, irqf, SA_SHIRQ, name, dev); | 675 | return request_irq(irq, irqf, IRQF_SHARED, name, dev); |
676 | } | 676 | } |
677 | 677 | ||
678 | static void fs_free_irq(struct net_device *dev, int irq) | 678 | static void fs_free_irq(struct net_device *dev, int irq) |
@@ -683,35 +683,6 @@ static void fs_free_irq(struct net_device *dev, int irq) | |||
683 | (*fep->ops->post_free_irq)(dev, irq); | 683 | (*fep->ops->post_free_irq)(dev, irq); |
684 | } | 684 | } |
685 | 685 | ||
686 | /**********************************************************************************/ | ||
687 | |||
688 | /* This interrupt occurs when the PHY detects a link change. */ | ||
689 | static irqreturn_t | ||
690 | fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
691 | { | ||
692 | struct net_device *dev = dev_id; | ||
693 | struct fs_enet_private *fep; | ||
694 | const struct fs_platform_info *fpi; | ||
695 | |||
696 | fep = netdev_priv(dev); | ||
697 | fpi = fep->fpi; | ||
698 | |||
699 | /* | ||
700 | * Acknowledge the interrupt if possible. If we have not | ||
701 | * found the PHY yet we can't process or acknowledge the | ||
702 | * interrupt now. Instead we ignore this interrupt for now, | ||
703 | * which we can do since it is edge triggered. It will be | ||
704 | * acknowledged later by fs_enet_open(). | ||
705 | */ | ||
706 | if (!fep->phy) | ||
707 | return IRQ_NONE; | ||
708 | |||
709 | fs_mii_ack_int(dev); | ||
710 | fs_mii_link_status_change_check(dev, 0); | ||
711 | |||
712 | return IRQ_HANDLED; | ||
713 | } | ||
714 | |||
715 | static void fs_timeout(struct net_device *dev) | 686 | static void fs_timeout(struct net_device *dev) |
716 | { | 687 | { |
717 | struct fs_enet_private *fep = netdev_priv(dev); | 688 | struct fs_enet_private *fep = netdev_priv(dev); |
@@ -723,10 +694,13 @@ static void fs_timeout(struct net_device *dev) | |||
723 | spin_lock_irqsave(&fep->lock, flags); | 694 | spin_lock_irqsave(&fep->lock, flags); |
724 | 695 | ||
725 | if (dev->flags & IFF_UP) { | 696 | if (dev->flags & IFF_UP) { |
697 | phy_stop(fep->phydev); | ||
726 | (*fep->ops->stop)(dev); | 698 | (*fep->ops->stop)(dev); |
727 | (*fep->ops->restart)(dev); | 699 | (*fep->ops->restart)(dev); |
700 | phy_start(fep->phydev); | ||
728 | } | 701 | } |
729 | 702 | ||
703 | phy_start(fep->phydev); | ||
730 | wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY); | 704 | wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY); |
731 | spin_unlock_irqrestore(&fep->lock, flags); | 705 | spin_unlock_irqrestore(&fep->lock, flags); |
732 | 706 | ||
@@ -734,35 +708,112 @@ static void fs_timeout(struct net_device *dev) | |||
734 | netif_wake_queue(dev); | 708 | netif_wake_queue(dev); |
735 | } | 709 | } |
736 | 710 | ||
711 | /*----------------------------------------------------------------------------- | ||
712 | * generic link-change handler - should be sufficient for most cases | ||
713 | *-----------------------------------------------------------------------------*/ | ||
714 | static void generic_adjust_link(struct net_device *dev) | ||
715 | { | ||
716 | struct fs_enet_private *fep = netdev_priv(dev); | ||
717 | struct phy_device *phydev = fep->phydev; | ||
718 | int new_state = 0; | ||
719 | |||
720 | if (phydev->link) { | ||
721 | |||
722 | /* adjust to duplex mode */ | ||
723 | if (phydev->duplex != fep->oldduplex){ | ||
724 | new_state = 1; | ||
725 | fep->oldduplex = phydev->duplex; | ||
726 | } | ||
727 | |||
728 | if (phydev->speed != fep->oldspeed) { | ||
729 | new_state = 1; | ||
730 | fep->oldspeed = phydev->speed; | ||
731 | } | ||
732 | |||
733 | if (!fep->oldlink) { | ||
734 | new_state = 1; | ||
735 | fep->oldlink = 1; | ||
736 | netif_schedule(dev); | ||
737 | netif_carrier_on(dev); | ||
738 | netif_start_queue(dev); | ||
739 | } | ||
740 | |||
741 | if (new_state) | ||
742 | fep->ops->restart(dev); | ||
743 | |||
744 | } else if (fep->oldlink) { | ||
745 | new_state = 1; | ||
746 | fep->oldlink = 0; | ||
747 | fep->oldspeed = 0; | ||
748 | fep->oldduplex = -1; | ||
749 | netif_carrier_off(dev); | ||
750 | netif_stop_queue(dev); | ||
751 | } | ||
752 | |||
753 | if (new_state && netif_msg_link(fep)) | ||
754 | phy_print_status(phydev); | ||
755 | } | ||
756 | |||
757 | |||
758 | static void fs_adjust_link(struct net_device *dev) | ||
759 | { | ||
760 | struct fs_enet_private *fep = netdev_priv(dev); | ||
761 | unsigned long flags; | ||
762 | |||
763 | spin_lock_irqsave(&fep->lock, flags); | ||
764 | |||
765 | if(fep->ops->adjust_link) | ||
766 | fep->ops->adjust_link(dev); | ||
767 | else | ||
768 | generic_adjust_link(dev); | ||
769 | |||
770 | spin_unlock_irqrestore(&fep->lock, flags); | ||
771 | } | ||
772 | |||
773 | static int fs_init_phy(struct net_device *dev) | ||
774 | { | ||
775 | struct fs_enet_private *fep = netdev_priv(dev); | ||
776 | struct phy_device *phydev; | ||
777 | |||
778 | fep->oldlink = 0; | ||
779 | fep->oldspeed = 0; | ||
780 | fep->oldduplex = -1; | ||
781 | if(fep->fpi->bus_id) | ||
782 | phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0); | ||
783 | else { | ||
784 | printk("No phy bus ID specified in BSP code\n"); | ||
785 | return -EINVAL; | ||
786 | } | ||
787 | if (IS_ERR(phydev)) { | ||
788 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | ||
789 | return PTR_ERR(phydev); | ||
790 | } | ||
791 | |||
792 | fep->phydev = phydev; | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | |||
737 | static int fs_enet_open(struct net_device *dev) | 798 | static int fs_enet_open(struct net_device *dev) |
738 | { | 799 | { |
739 | struct fs_enet_private *fep = netdev_priv(dev); | 800 | struct fs_enet_private *fep = netdev_priv(dev); |
740 | const struct fs_platform_info *fpi = fep->fpi; | ||
741 | int r; | 801 | int r; |
802 | int err; | ||
742 | 803 | ||
743 | /* Install our interrupt handler. */ | 804 | /* Install our interrupt handler. */ |
744 | r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt); | 805 | r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt); |
745 | if (r != 0) { | 806 | if (r != 0) { |
746 | printk(KERN_ERR DRV_MODULE_NAME | 807 | printk(KERN_ERR DRV_MODULE_NAME |
747 | ": %s Could not allocate FEC IRQ!", dev->name); | 808 | ": %s Could not allocate FS_ENET IRQ!", dev->name); |
748 | return -EINVAL; | 809 | return -EINVAL; |
749 | } | 810 | } |
750 | 811 | ||
751 | /* Install our phy interrupt handler */ | 812 | err = fs_init_phy(dev); |
752 | if (fpi->phy_irq != -1) { | 813 | if(err) |
753 | 814 | return err; | |
754 | r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt); | ||
755 | if (r != 0) { | ||
756 | printk(KERN_ERR DRV_MODULE_NAME | ||
757 | ": %s Could not allocate PHY IRQ!", dev->name); | ||
758 | fs_free_irq(dev, fep->interrupt); | ||
759 | return -EINVAL; | ||
760 | } | ||
761 | } | ||
762 | 815 | ||
763 | fs_mii_startup(dev); | 816 | phy_start(fep->phydev); |
764 | netif_carrier_off(dev); | ||
765 | fs_mii_link_status_change_check(dev, 1); | ||
766 | 817 | ||
767 | return 0; | 818 | return 0; |
768 | } | 819 | } |
@@ -770,20 +821,19 @@ static int fs_enet_open(struct net_device *dev) | |||
770 | static int fs_enet_close(struct net_device *dev) | 821 | static int fs_enet_close(struct net_device *dev) |
771 | { | 822 | { |
772 | struct fs_enet_private *fep = netdev_priv(dev); | 823 | struct fs_enet_private *fep = netdev_priv(dev); |
773 | const struct fs_platform_info *fpi = fep->fpi; | ||
774 | unsigned long flags; | 824 | unsigned long flags; |
775 | 825 | ||
776 | netif_stop_queue(dev); | 826 | netif_stop_queue(dev); |
777 | netif_carrier_off(dev); | 827 | netif_carrier_off(dev); |
778 | fs_mii_shutdown(dev); | 828 | phy_stop(fep->phydev); |
779 | 829 | ||
780 | spin_lock_irqsave(&fep->lock, flags); | 830 | spin_lock_irqsave(&fep->lock, flags); |
781 | (*fep->ops->stop)(dev); | 831 | (*fep->ops->stop)(dev); |
782 | spin_unlock_irqrestore(&fep->lock, flags); | 832 | spin_unlock_irqrestore(&fep->lock, flags); |
783 | 833 | ||
784 | /* release any irqs */ | 834 | /* release any irqs */ |
785 | if (fpi->phy_irq != -1) | 835 | phy_disconnect(fep->phydev); |
786 | fs_free_irq(dev, fpi->phy_irq); | 836 | fep->phydev = NULL; |
787 | fs_free_irq(dev, fep->interrupt); | 837 | fs_free_irq(dev, fep->interrupt); |
788 | 838 | ||
789 | return 0; | 839 | return 0; |
@@ -831,33 +881,19 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
831 | static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 881 | static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
832 | { | 882 | { |
833 | struct fs_enet_private *fep = netdev_priv(dev); | 883 | struct fs_enet_private *fep = netdev_priv(dev); |
834 | unsigned long flags; | 884 | return phy_ethtool_gset(fep->phydev, cmd); |
835 | int rc; | ||
836 | |||
837 | spin_lock_irqsave(&fep->lock, flags); | ||
838 | rc = mii_ethtool_gset(&fep->mii_if, cmd); | ||
839 | spin_unlock_irqrestore(&fep->lock, flags); | ||
840 | |||
841 | return rc; | ||
842 | } | 885 | } |
843 | 886 | ||
844 | static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 887 | static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
845 | { | 888 | { |
846 | struct fs_enet_private *fep = netdev_priv(dev); | 889 | struct fs_enet_private *fep = netdev_priv(dev); |
847 | unsigned long flags; | 890 | phy_ethtool_sset(fep->phydev, cmd); |
848 | int rc; | 891 | return 0; |
849 | |||
850 | spin_lock_irqsave(&fep->lock, flags); | ||
851 | rc = mii_ethtool_sset(&fep->mii_if, cmd); | ||
852 | spin_unlock_irqrestore(&fep->lock, flags); | ||
853 | |||
854 | return rc; | ||
855 | } | 892 | } |
856 | 893 | ||
857 | static int fs_nway_reset(struct net_device *dev) | 894 | static int fs_nway_reset(struct net_device *dev) |
858 | { | 895 | { |
859 | struct fs_enet_private *fep = netdev_priv(dev); | 896 | return 0; |
860 | return mii_nway_restart(&fep->mii_if); | ||
861 | } | 897 | } |
862 | 898 | ||
863 | static u32 fs_get_msglevel(struct net_device *dev) | 899 | static u32 fs_get_msglevel(struct net_device *dev) |
@@ -872,7 +908,7 @@ static void fs_set_msglevel(struct net_device *dev, u32 value) | |||
872 | fep->msg_enable = value; | 908 | fep->msg_enable = value; |
873 | } | 909 | } |
874 | 910 | ||
875 | static struct ethtool_ops fs_ethtool_ops = { | 911 | static const struct ethtool_ops fs_ethtool_ops = { |
876 | .get_drvinfo = fs_get_drvinfo, | 912 | .get_drvinfo = fs_get_drvinfo, |
877 | .get_regs_len = fs_get_regs_len, | 913 | .get_regs_len = fs_get_regs_len, |
878 | .get_settings = fs_get_settings, | 914 | .get_settings = fs_get_settings, |
@@ -899,7 +935,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
899 | return -EINVAL; | 935 | return -EINVAL; |
900 | 936 | ||
901 | spin_lock_irqsave(&fep->lock, flags); | 937 | spin_lock_irqsave(&fep->lock, flags); |
902 | rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL); | 938 | rc = phy_mii_ioctl(fep->phydev, mii, cmd); |
903 | spin_unlock_irqrestore(&fep->lock, flags); | 939 | spin_unlock_irqrestore(&fep->lock, flags); |
904 | return rc; | 940 | return rc; |
905 | } | 941 | } |
@@ -1031,12 +1067,6 @@ static struct net_device *fs_init_instance(struct device *dev, | |||
1031 | } | 1067 | } |
1032 | registered = 1; | 1068 | registered = 1; |
1033 | 1069 | ||
1034 | err = fs_mii_connect(ndev); | ||
1035 | if (err != 0) { | ||
1036 | printk(KERN_ERR DRV_MODULE_NAME | ||
1037 | ": %s fs_mii_connect failed.\n", ndev->name); | ||
1038 | goto err; | ||
1039 | } | ||
1040 | 1070 | ||
1041 | return ndev; | 1071 | return ndev; |
1042 | 1072 | ||
@@ -1074,8 +1104,6 @@ static int fs_cleanup_instance(struct net_device *ndev) | |||
1074 | 1104 | ||
1075 | fpi = fep->fpi; | 1105 | fpi = fep->fpi; |
1076 | 1106 | ||
1077 | fs_mii_disconnect(ndev); | ||
1078 | |||
1079 | unregister_netdev(ndev); | 1107 | unregister_netdev(ndev); |
1080 | 1108 | ||
1081 | dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t), | 1109 | dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t), |
@@ -1197,17 +1225,39 @@ static int __init fs_init(void) | |||
1197 | r = setup_immap(); | 1225 | r = setup_immap(); |
1198 | if (r != 0) | 1226 | if (r != 0) |
1199 | return r; | 1227 | return r; |
1200 | r = driver_register(&fs_enet_fec_driver); | 1228 | |
1229 | #ifdef CONFIG_FS_ENET_HAS_FCC | ||
1230 | /* let's insert mii stuff */ | ||
1231 | r = fs_enet_mdio_bb_init(); | ||
1232 | |||
1233 | if (r != 0) { | ||
1234 | printk(KERN_ERR DRV_MODULE_NAME | ||
1235 | "BB PHY init failed.\n"); | ||
1236 | return r; | ||
1237 | } | ||
1238 | r = driver_register(&fs_enet_fcc_driver); | ||
1201 | if (r != 0) | 1239 | if (r != 0) |
1202 | goto err; | 1240 | goto err; |
1241 | #endif | ||
1203 | 1242 | ||
1204 | r = driver_register(&fs_enet_fcc_driver); | 1243 | #ifdef CONFIG_FS_ENET_HAS_FEC |
1244 | r = fs_enet_mdio_fec_init(); | ||
1245 | if (r != 0) { | ||
1246 | printk(KERN_ERR DRV_MODULE_NAME | ||
1247 | "FEC PHY init failed.\n"); | ||
1248 | return r; | ||
1249 | } | ||
1250 | |||
1251 | r = driver_register(&fs_enet_fec_driver); | ||
1205 | if (r != 0) | 1252 | if (r != 0) |
1206 | goto err; | 1253 | goto err; |
1254 | #endif | ||
1207 | 1255 | ||
1256 | #ifdef CONFIG_FS_ENET_HAS_SCC | ||
1208 | r = driver_register(&fs_enet_scc_driver); | 1257 | r = driver_register(&fs_enet_scc_driver); |
1209 | if (r != 0) | 1258 | if (r != 0) |
1210 | goto err; | 1259 | goto err; |
1260 | #endif | ||
1211 | 1261 | ||
1212 | return 0; | 1262 | return 0; |
1213 | err: | 1263 | err: |