diff options
Diffstat (limited to 'drivers/net/fs_enet')
-rw-r--r-- | drivers/net/fs_enet/Makefile | 6 | ||||
-rw-r--r-- | drivers/net/fs_enet/fec.h | 42 | ||||
-rw-r--r-- | drivers/net/fs_enet/fs_enet-main.c | 212 | ||||
-rw-r--r-- | drivers/net/fs_enet/fs_enet-mii.c | 507 | ||||
-rw-r--r-- | drivers/net/fs_enet/fs_enet.h | 43 | ||||
-rw-r--r-- | drivers/net/fs_enet/mac-fcc.c | 33 | ||||
-rw-r--r-- | drivers/net/fs_enet/mac-fec.c | 143 | ||||
-rw-r--r-- | drivers/net/fs_enet/mac-scc.c | 5 | ||||
-rw-r--r-- | drivers/net/fs_enet/mii-bitbang.c | 449 | ||||
-rw-r--r-- | drivers/net/fs_enet/mii-fec.c | 243 | ||||
-rw-r--r-- | drivers/net/fs_enet/mii-fixed.c | 92 |
11 files changed, 714 insertions, 1061 deletions
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile index d6dd3f2fb43e..02d4dc18ba69 100644 --- a/drivers/net/fs_enet/Makefile +++ b/drivers/net/fs_enet/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_FS_ENET) += fs_enet.o | 5 | obj-$(CONFIG_FS_ENET) += fs_enet.o |
6 | 6 | ||
7 | obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o | 7 | obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o |
8 | obj-$(CONFIG_8260) += mac-fcc.o | 8 | obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o |
9 | 9 | ||
10 | fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o | 10 | fs_enet-objs := fs_enet-main.o |
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h new file mode 100644 index 000000000000..e980527e2b99 --- /dev/null +++ b/drivers/net/fs_enet/fec.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef FS_ENET_FEC_H | ||
2 | #define FS_ENET_FEC_H | ||
3 | |||
4 | /* CRC polynomium used by the FEC for the multicast group filtering */ | ||
5 | #define FEC_CRC_POLY 0x04C11DB7 | ||
6 | |||
7 | #define FEC_MAX_MULTICAST_ADDRS 64 | ||
8 | |||
9 | /* Interrupt events/masks. | ||
10 | */ | ||
11 | #define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */ | ||
12 | #define FEC_ENET_BABR 0x40000000U /* Babbling receiver */ | ||
13 | #define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */ | ||
14 | #define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */ | ||
15 | #define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */ | ||
16 | #define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */ | ||
17 | #define FEC_ENET_RXF 0x02000000U /* Full frame received */ | ||
18 | #define FEC_ENET_RXB 0x01000000U /* A buffer was received */ | ||
19 | #define FEC_ENET_MII 0x00800000U /* MII interrupt */ | ||
20 | #define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */ | ||
21 | |||
22 | #define FEC_ECNTRL_PINMUX 0x00000004 | ||
23 | #define FEC_ECNTRL_ETHER_EN 0x00000002 | ||
24 | #define FEC_ECNTRL_RESET 0x00000001 | ||
25 | |||
26 | #define FEC_RCNTRL_BC_REJ 0x00000010 | ||
27 | #define FEC_RCNTRL_PROM 0x00000008 | ||
28 | #define FEC_RCNTRL_MII_MODE 0x00000004 | ||
29 | #define FEC_RCNTRL_DRT 0x00000002 | ||
30 | #define FEC_RCNTRL_LOOP 0x00000001 | ||
31 | |||
32 | #define FEC_TCNTRL_FDEN 0x00000004 | ||
33 | #define FEC_TCNTRL_HBC 0x00000002 | ||
34 | #define FEC_TCNTRL_GTS 0x00000001 | ||
35 | |||
36 | |||
37 | |||
38 | /* | ||
39 | * Delay to wait for FEC reset command to complete (in us) | ||
40 | */ | ||
41 | #define FEC_RESET_DELAY 50 | ||
42 | #endif | ||
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 196298f33db8..34412bc7c4b6 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: |
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c deleted file mode 100644 index c6770377ef87..000000000000 --- a/drivers/net/fs_enet/fs_enet-mii.c +++ /dev/null | |||
@@ -1,507 +0,0 @@ | |||
1 | /* | ||
2 | * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. | ||
3 | * | ||
4 | * Copyright (c) 2003 Intracom S.A. | ||
5 | * by Pantelis Antoniou <panto@intracom.gr> | ||
6 | * | ||
7 | * 2005 (c) MontaVista Software, Inc. | ||
8 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
9 | * | ||
10 | * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com> | ||
11 | * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se> | ||
12 | * | ||
13 | * This file is licensed under the terms of the GNU General Public License | ||
14 | * version 2. This program is licensed "as is" without any warranty of any | ||
15 | * kind, whether express or implied. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/ptrace.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/netdevice.h> | ||
34 | #include <linux/etherdevice.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/mii.h> | ||
38 | #include <linux/ethtool.h> | ||
39 | #include <linux/bitops.h> | ||
40 | |||
41 | #include <asm/pgtable.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | |||
45 | #include "fs_enet.h" | ||
46 | |||
47 | /*************************************************/ | ||
48 | |||
49 | /* | ||
50 | * Generic PHY support. | ||
51 | * Should work for all PHYs, but link change is detected by polling | ||
52 | */ | ||
53 | |||
54 | static void generic_timer_callback(unsigned long data) | ||
55 | { | ||
56 | struct net_device *dev = (struct net_device *)data; | ||
57 | struct fs_enet_private *fep = netdev_priv(dev); | ||
58 | |||
59 | fep->phy_timer_list.expires = jiffies + HZ / 2; | ||
60 | |||
61 | add_timer(&fep->phy_timer_list); | ||
62 | |||
63 | fs_mii_link_status_change_check(dev, 0); | ||
64 | } | ||
65 | |||
66 | static void generic_startup(struct net_device *dev) | ||
67 | { | ||
68 | struct fs_enet_private *fep = netdev_priv(dev); | ||
69 | |||
70 | fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */ | ||
71 | fep->phy_timer_list.data = (unsigned long)dev; | ||
72 | fep->phy_timer_list.function = generic_timer_callback; | ||
73 | add_timer(&fep->phy_timer_list); | ||
74 | } | ||
75 | |||
76 | static void generic_shutdown(struct net_device *dev) | ||
77 | { | ||
78 | struct fs_enet_private *fep = netdev_priv(dev); | ||
79 | |||
80 | del_timer_sync(&fep->phy_timer_list); | ||
81 | } | ||
82 | |||
83 | /* ------------------------------------------------------------------------- */ | ||
84 | /* The Davicom DM9161 is used on the NETTA board */ | ||
85 | |||
86 | /* register definitions */ | ||
87 | |||
88 | #define MII_DM9161_ANAR 4 /* Aux. Config Register */ | ||
89 | #define MII_DM9161_ACR 16 /* Aux. Config Register */ | ||
90 | #define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */ | ||
91 | #define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */ | ||
92 | #define MII_DM9161_INTR 21 /* Interrupt Register */ | ||
93 | #define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */ | ||
94 | #define MII_DM9161_DISCR 23 /* Disconnect Counter Register */ | ||
95 | |||
96 | static void dm9161_startup(struct net_device *dev) | ||
97 | { | ||
98 | struct fs_enet_private *fep = netdev_priv(dev); | ||
99 | |||
100 | fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000); | ||
101 | /* Start autonegotiation */ | ||
102 | fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200); | ||
103 | |||
104 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
105 | schedule_timeout(HZ*8); | ||
106 | } | ||
107 | |||
108 | static void dm9161_ack_int(struct net_device *dev) | ||
109 | { | ||
110 | struct fs_enet_private *fep = netdev_priv(dev); | ||
111 | |||
112 | fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR); | ||
113 | } | ||
114 | |||
115 | static void dm9161_shutdown(struct net_device *dev) | ||
116 | { | ||
117 | struct fs_enet_private *fep = netdev_priv(dev); | ||
118 | |||
119 | fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00); | ||
120 | } | ||
121 | |||
122 | /**********************************************************************************/ | ||
123 | |||
124 | static const struct phy_info phy_info[] = { | ||
125 | { | ||
126 | .id = 0x00181b88, | ||
127 | .name = "DM9161", | ||
128 | .startup = dm9161_startup, | ||
129 | .ack_int = dm9161_ack_int, | ||
130 | .shutdown = dm9161_shutdown, | ||
131 | }, { | ||
132 | .id = 0, | ||
133 | .name = "GENERIC", | ||
134 | .startup = generic_startup, | ||
135 | .shutdown = generic_shutdown, | ||
136 | }, | ||
137 | }; | ||
138 | |||
139 | /**********************************************************************************/ | ||
140 | |||
141 | static int phy_id_detect(struct net_device *dev) | ||
142 | { | ||
143 | struct fs_enet_private *fep = netdev_priv(dev); | ||
144 | const struct fs_platform_info *fpi = fep->fpi; | ||
145 | struct fs_enet_mii_bus *bus = fep->mii_bus; | ||
146 | int i, r, start, end, phytype, physubtype; | ||
147 | const struct phy_info *phy; | ||
148 | int phy_hwid, phy_id; | ||
149 | |||
150 | phy_hwid = -1; | ||
151 | fep->phy = NULL; | ||
152 | |||
153 | /* auto-detect? */ | ||
154 | if (fpi->phy_addr == -1) { | ||
155 | start = 1; | ||
156 | end = 32; | ||
157 | } else { /* direct */ | ||
158 | start = fpi->phy_addr; | ||
159 | end = start + 1; | ||
160 | } | ||
161 | |||
162 | for (phy_id = start; phy_id < end; phy_id++) { | ||
163 | /* skip already used phy addresses on this bus */ | ||
164 | if (bus->usage_map & (1 << phy_id)) | ||
165 | continue; | ||
166 | r = fs_mii_read(dev, phy_id, MII_PHYSID1); | ||
167 | if (r == -1 || (phytype = (r & 0xffff)) == 0xffff) | ||
168 | continue; | ||
169 | r = fs_mii_read(dev, phy_id, MII_PHYSID2); | ||
170 | if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff) | ||
171 | continue; | ||
172 | phy_hwid = (phytype << 16) | physubtype; | ||
173 | if (phy_hwid != -1) | ||
174 | break; | ||
175 | } | ||
176 | |||
177 | if (phy_hwid == -1) { | ||
178 | printk(KERN_ERR DRV_MODULE_NAME | ||
179 | ": %s No PHY detected! range=0x%02x-0x%02x\n", | ||
180 | dev->name, start, end); | ||
181 | return -1; | ||
182 | } | ||
183 | |||
184 | for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++) | ||
185 | if (phy->id == (phy_hwid >> 4) || phy->id == 0) | ||
186 | break; | ||
187 | |||
188 | if (i >= ARRAY_SIZE(phy_info)) { | ||
189 | printk(KERN_ERR DRV_MODULE_NAME | ||
190 | ": %s PHY id 0x%08x is not supported!\n", | ||
191 | dev->name, phy_hwid); | ||
192 | return -1; | ||
193 | } | ||
194 | |||
195 | fep->phy = phy; | ||
196 | |||
197 | /* mark this address as used */ | ||
198 | bus->usage_map |= (1 << phy_id); | ||
199 | |||
200 | printk(KERN_INFO DRV_MODULE_NAME | ||
201 | ": %s Phy @ 0x%x, type %s (0x%08x)%s\n", | ||
202 | dev->name, phy_id, fep->phy->name, phy_hwid, | ||
203 | fpi->phy_addr == -1 ? " (auto-detected)" : ""); | ||
204 | |||
205 | return phy_id; | ||
206 | } | ||
207 | |||
208 | void fs_mii_startup(struct net_device *dev) | ||
209 | { | ||
210 | struct fs_enet_private *fep = netdev_priv(dev); | ||
211 | |||
212 | if (fep->phy->startup) | ||
213 | (*fep->phy->startup) (dev); | ||
214 | } | ||
215 | |||
216 | void fs_mii_shutdown(struct net_device *dev) | ||
217 | { | ||
218 | struct fs_enet_private *fep = netdev_priv(dev); | ||
219 | |||
220 | if (fep->phy->shutdown) | ||
221 | (*fep->phy->shutdown) (dev); | ||
222 | } | ||
223 | |||
224 | void fs_mii_ack_int(struct net_device *dev) | ||
225 | { | ||
226 | struct fs_enet_private *fep = netdev_priv(dev); | ||
227 | |||
228 | if (fep->phy->ack_int) | ||
229 | (*fep->phy->ack_int) (dev); | ||
230 | } | ||
231 | |||
232 | #define MII_LINK 0x0001 | ||
233 | #define MII_HALF 0x0002 | ||
234 | #define MII_FULL 0x0004 | ||
235 | #define MII_BASE4 0x0008 | ||
236 | #define MII_10M 0x0010 | ||
237 | #define MII_100M 0x0020 | ||
238 | #define MII_1G 0x0040 | ||
239 | #define MII_10G 0x0080 | ||
240 | |||
241 | /* return full mii info at one gulp, with a usable form */ | ||
242 | static unsigned int mii_full_status(struct mii_if_info *mii) | ||
243 | { | ||
244 | unsigned int status; | ||
245 | int bmsr, adv, lpa, neg; | ||
246 | struct fs_enet_private* fep = netdev_priv(mii->dev); | ||
247 | |||
248 | /* first, a dummy read, needed to latch some MII phys */ | ||
249 | (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); | ||
250 | bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); | ||
251 | |||
252 | /* no link */ | ||
253 | if ((bmsr & BMSR_LSTATUS) == 0) | ||
254 | return 0; | ||
255 | |||
256 | status = MII_LINK; | ||
257 | |||
258 | /* Lets look what ANEG says if it's supported - otherwize we shall | ||
259 | take the right values from the platform info*/ | ||
260 | if(!mii->force_media) { | ||
261 | /* autoneg not completed; don't bother */ | ||
262 | if ((bmsr & BMSR_ANEGCOMPLETE) == 0) | ||
263 | return 0; | ||
264 | |||
265 | adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE); | ||
266 | lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA); | ||
267 | |||
268 | neg = lpa & adv; | ||
269 | } else { | ||
270 | neg = fep->fpi->bus_info->lpa; | ||
271 | } | ||
272 | |||
273 | if (neg & LPA_100FULL) | ||
274 | status |= MII_FULL | MII_100M; | ||
275 | else if (neg & LPA_100BASE4) | ||
276 | status |= MII_FULL | MII_BASE4 | MII_100M; | ||
277 | else if (neg & LPA_100HALF) | ||
278 | status |= MII_HALF | MII_100M; | ||
279 | else if (neg & LPA_10FULL) | ||
280 | status |= MII_FULL | MII_10M; | ||
281 | else | ||
282 | status |= MII_HALF | MII_10M; | ||
283 | |||
284 | return status; | ||
285 | } | ||
286 | |||
287 | void fs_mii_link_status_change_check(struct net_device *dev, int init_media) | ||
288 | { | ||
289 | struct fs_enet_private *fep = netdev_priv(dev); | ||
290 | struct mii_if_info *mii = &fep->mii_if; | ||
291 | unsigned int mii_status; | ||
292 | int ok_to_print, link, duplex, speed; | ||
293 | unsigned long flags; | ||
294 | |||
295 | ok_to_print = netif_msg_link(fep); | ||
296 | |||
297 | mii_status = mii_full_status(mii); | ||
298 | |||
299 | if (!init_media && mii_status == fep->last_mii_status) | ||
300 | return; | ||
301 | |||
302 | fep->last_mii_status = mii_status; | ||
303 | |||
304 | link = !!(mii_status & MII_LINK); | ||
305 | duplex = !!(mii_status & MII_FULL); | ||
306 | speed = (mii_status & MII_100M) ? 100 : 10; | ||
307 | |||
308 | if (link == 0) { | ||
309 | netif_carrier_off(mii->dev); | ||
310 | netif_stop_queue(dev); | ||
311 | if (!init_media) { | ||
312 | spin_lock_irqsave(&fep->lock, flags); | ||
313 | (*fep->ops->stop)(dev); | ||
314 | spin_unlock_irqrestore(&fep->lock, flags); | ||
315 | } | ||
316 | |||
317 | if (ok_to_print) | ||
318 | printk(KERN_INFO "%s: link down\n", mii->dev->name); | ||
319 | |||
320 | } else { | ||
321 | |||
322 | mii->full_duplex = duplex; | ||
323 | |||
324 | netif_carrier_on(mii->dev); | ||
325 | |||
326 | spin_lock_irqsave(&fep->lock, flags); | ||
327 | fep->duplex = duplex; | ||
328 | fep->speed = speed; | ||
329 | (*fep->ops->restart)(dev); | ||
330 | spin_unlock_irqrestore(&fep->lock, flags); | ||
331 | |||
332 | netif_start_queue(dev); | ||
333 | |||
334 | if (ok_to_print) | ||
335 | printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n", | ||
336 | dev->name, speed, duplex ? "full" : "half"); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | /**********************************************************************************/ | ||
341 | |||
342 | int fs_mii_read(struct net_device *dev, int phy_id, int location) | ||
343 | { | ||
344 | struct fs_enet_private *fep = netdev_priv(dev); | ||
345 | struct fs_enet_mii_bus *bus = fep->mii_bus; | ||
346 | |||
347 | unsigned long flags; | ||
348 | int ret; | ||
349 | |||
350 | spin_lock_irqsave(&bus->mii_lock, flags); | ||
351 | ret = (*bus->mii_read)(bus, phy_id, location); | ||
352 | spin_unlock_irqrestore(&bus->mii_lock, flags); | ||
353 | |||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | void fs_mii_write(struct net_device *dev, int phy_id, int location, int value) | ||
358 | { | ||
359 | struct fs_enet_private *fep = netdev_priv(dev); | ||
360 | struct fs_enet_mii_bus *bus = fep->mii_bus; | ||
361 | unsigned long flags; | ||
362 | |||
363 | spin_lock_irqsave(&bus->mii_lock, flags); | ||
364 | (*bus->mii_write)(bus, phy_id, location, value); | ||
365 | spin_unlock_irqrestore(&bus->mii_lock, flags); | ||
366 | } | ||
367 | |||
368 | /*****************************************************************************/ | ||
369 | |||
370 | /* list of all registered mii buses */ | ||
371 | static LIST_HEAD(fs_mii_bus_list); | ||
372 | |||
373 | static struct fs_enet_mii_bus *lookup_bus(int method, int id) | ||
374 | { | ||
375 | struct list_head *ptr; | ||
376 | struct fs_enet_mii_bus *bus; | ||
377 | |||
378 | list_for_each(ptr, &fs_mii_bus_list) { | ||
379 | bus = list_entry(ptr, struct fs_enet_mii_bus, list); | ||
380 | if (bus->bus_info->method == method && | ||
381 | bus->bus_info->id == id) | ||
382 | return bus; | ||
383 | } | ||
384 | return NULL; | ||
385 | } | ||
386 | |||
387 | static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi) | ||
388 | { | ||
389 | struct fs_enet_mii_bus *bus; | ||
390 | int ret = 0; | ||
391 | |||
392 | bus = kmalloc(sizeof(*bus), GFP_KERNEL); | ||
393 | if (bus == NULL) { | ||
394 | ret = -ENOMEM; | ||
395 | goto err; | ||
396 | } | ||
397 | memset(bus, 0, sizeof(*bus)); | ||
398 | spin_lock_init(&bus->mii_lock); | ||
399 | bus->bus_info = bi; | ||
400 | bus->refs = 0; | ||
401 | bus->usage_map = 0; | ||
402 | |||
403 | /* perform initialization */ | ||
404 | switch (bi->method) { | ||
405 | |||
406 | case fsmii_fixed: | ||
407 | ret = fs_mii_fixed_init(bus); | ||
408 | if (ret != 0) | ||
409 | goto err; | ||
410 | break; | ||
411 | |||
412 | case fsmii_bitbang: | ||
413 | ret = fs_mii_bitbang_init(bus); | ||
414 | if (ret != 0) | ||
415 | goto err; | ||
416 | break; | ||
417 | #ifdef CONFIG_FS_ENET_HAS_FEC | ||
418 | case fsmii_fec: | ||
419 | ret = fs_mii_fec_init(bus); | ||
420 | if (ret != 0) | ||
421 | goto err; | ||
422 | break; | ||
423 | #endif | ||
424 | default: | ||
425 | ret = -EINVAL; | ||
426 | goto err; | ||
427 | } | ||
428 | |||
429 | list_add(&bus->list, &fs_mii_bus_list); | ||
430 | |||
431 | return bus; | ||
432 | |||
433 | err: | ||
434 | if (bus) | ||
435 | kfree(bus); | ||
436 | return ERR_PTR(ret); | ||
437 | } | ||
438 | |||
439 | static void destroy_bus(struct fs_enet_mii_bus *bus) | ||
440 | { | ||
441 | /* remove from bus list */ | ||
442 | list_del(&bus->list); | ||
443 | |||
444 | /* nothing more needed */ | ||
445 | kfree(bus); | ||
446 | } | ||
447 | |||
448 | int fs_mii_connect(struct net_device *dev) | ||
449 | { | ||
450 | struct fs_enet_private *fep = netdev_priv(dev); | ||
451 | const struct fs_platform_info *fpi = fep->fpi; | ||
452 | struct fs_enet_mii_bus *bus = NULL; | ||
453 | |||
454 | /* check method validity */ | ||
455 | switch (fpi->bus_info->method) { | ||
456 | case fsmii_fixed: | ||
457 | case fsmii_bitbang: | ||
458 | break; | ||
459 | #ifdef CONFIG_FS_ENET_HAS_FEC | ||
460 | case fsmii_fec: | ||
461 | break; | ||
462 | #endif | ||
463 | default: | ||
464 | printk(KERN_ERR DRV_MODULE_NAME | ||
465 | ": %s Unknown MII bus method (%d)!\n", | ||
466 | dev->name, fpi->bus_info->method); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | |||
470 | bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id); | ||
471 | |||
472 | /* if not found create new bus */ | ||
473 | if (bus == NULL) { | ||
474 | bus = create_bus(fpi->bus_info); | ||
475 | if (IS_ERR(bus)) { | ||
476 | printk(KERN_ERR DRV_MODULE_NAME | ||
477 | ": %s MII bus creation failure!\n", dev->name); | ||
478 | return PTR_ERR(bus); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | bus->refs++; | ||
483 | |||
484 | fep->mii_bus = bus; | ||
485 | |||
486 | fep->mii_if.dev = dev; | ||
487 | fep->mii_if.phy_id_mask = 0x1f; | ||
488 | fep->mii_if.reg_num_mask = 0x1f; | ||
489 | fep->mii_if.mdio_read = fs_mii_read; | ||
490 | fep->mii_if.mdio_write = fs_mii_write; | ||
491 | fep->mii_if.force_media = fpi->bus_info->disable_aneg; | ||
492 | fep->mii_if.phy_id = phy_id_detect(dev); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | void fs_mii_disconnect(struct net_device *dev) | ||
498 | { | ||
499 | struct fs_enet_private *fep = netdev_priv(dev); | ||
500 | struct fs_enet_mii_bus *bus = NULL; | ||
501 | |||
502 | bus = fep->mii_bus; | ||
503 | fep->mii_bus = NULL; | ||
504 | |||
505 | if (--bus->refs <= 0) | ||
506 | destroy_bus(bus); | ||
507 | } | ||
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index e7ec96c964a9..92590d8fc24b 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h | |||
@@ -5,19 +5,37 @@ | |||
5 | #include <linux/netdevice.h> | 5 | #include <linux/netdevice.h> |
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | #include <linux/list.h> | 7 | #include <linux/list.h> |
8 | #include <linux/phy.h> | ||
9 | #include <linux/dma-mapping.h> | ||
8 | 10 | ||
9 | #include <linux/fs_enet_pd.h> | 11 | #include <linux/fs_enet_pd.h> |
10 | 12 | ||
11 | #include <asm/dma-mapping.h> | ||
12 | |||
13 | #ifdef CONFIG_CPM1 | 13 | #ifdef CONFIG_CPM1 |
14 | #include <asm/commproc.h> | 14 | #include <asm/commproc.h> |
15 | |||
16 | struct fec_info { | ||
17 | fec_t* fecp; | ||
18 | u32 mii_speed; | ||
19 | }; | ||
15 | #endif | 20 | #endif |
16 | 21 | ||
17 | #ifdef CONFIG_CPM2 | 22 | #ifdef CONFIG_CPM2 |
18 | #include <asm/cpm2.h> | 23 | #include <asm/cpm2.h> |
19 | #endif | 24 | #endif |
20 | 25 | ||
26 | /* This is used to operate with pins. | ||
27 | Note that the actual port size may | ||
28 | be different; cpm(s) handle it OK */ | ||
29 | struct bb_info { | ||
30 | u8 mdio_dat_msk; | ||
31 | u8 mdio_dir_msk; | ||
32 | u8 *mdio_dir; | ||
33 | u8 *mdio_dat; | ||
34 | u8 mdc_msk; | ||
35 | u8 *mdc_dat; | ||
36 | int delay; | ||
37 | }; | ||
38 | |||
21 | /* hw driver ops */ | 39 | /* hw driver ops */ |
22 | struct fs_ops { | 40 | struct fs_ops { |
23 | int (*setup_data)(struct net_device *dev); | 41 | int (*setup_data)(struct net_device *dev); |
@@ -25,6 +43,7 @@ struct fs_ops { | |||
25 | void (*free_bd)(struct net_device *dev); | 43 | void (*free_bd)(struct net_device *dev); |
26 | void (*cleanup_data)(struct net_device *dev); | 44 | void (*cleanup_data)(struct net_device *dev); |
27 | void (*set_multicast_list)(struct net_device *dev); | 45 | void (*set_multicast_list)(struct net_device *dev); |
46 | void (*adjust_link)(struct net_device *dev); | ||
28 | void (*restart)(struct net_device *dev); | 47 | void (*restart)(struct net_device *dev); |
29 | void (*stop)(struct net_device *dev); | 48 | void (*stop)(struct net_device *dev); |
30 | void (*pre_request_irq)(struct net_device *dev, int irq); | 49 | void (*pre_request_irq)(struct net_device *dev, int irq); |
@@ -100,10 +119,6 @@ struct fs_enet_mii_bus { | |||
100 | }; | 119 | }; |
101 | }; | 120 | }; |
102 | 121 | ||
103 | int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus); | ||
104 | int fs_mii_fixed_init(struct fs_enet_mii_bus *bus); | ||
105 | int fs_mii_fec_init(struct fs_enet_mii_bus *bus); | ||
106 | |||
107 | struct fs_enet_private { | 122 | struct fs_enet_private { |
108 | struct device *dev; /* pointer back to the device (must be initialized first) */ | 123 | struct device *dev; /* pointer back to the device (must be initialized first) */ |
109 | spinlock_t lock; /* during all ops except TX pckt processing */ | 124 | spinlock_t lock; /* during all ops except TX pckt processing */ |
@@ -130,7 +145,8 @@ struct fs_enet_private { | |||
130 | struct fs_enet_mii_bus *mii_bus; | 145 | struct fs_enet_mii_bus *mii_bus; |
131 | int interrupt; | 146 | int interrupt; |
132 | 147 | ||
133 | int duplex, speed; /* current settings */ | 148 | struct phy_device *phydev; |
149 | int oldduplex, oldspeed, oldlink; /* current settings */ | ||
134 | 150 | ||
135 | /* event masks */ | 151 | /* event masks */ |
136 | u32 ev_napi_rx; /* mask of NAPI rx events */ | 152 | u32 ev_napi_rx; /* mask of NAPI rx events */ |
@@ -168,15 +184,9 @@ struct fs_enet_private { | |||
168 | }; | 184 | }; |
169 | 185 | ||
170 | /***************************************************************************/ | 186 | /***************************************************************************/ |
171 | 187 | int fs_enet_mdio_bb_init(void); | |
172 | int fs_mii_read(struct net_device *dev, int phy_id, int location); | 188 | int fs_mii_fixed_init(struct fs_enet_mii_bus *bus); |
173 | void fs_mii_write(struct net_device *dev, int phy_id, int location, int value); | 189 | int fs_enet_mdio_fec_init(void); |
174 | |||
175 | void fs_mii_startup(struct net_device *dev); | ||
176 | void fs_mii_shutdown(struct net_device *dev); | ||
177 | void fs_mii_ack_int(struct net_device *dev); | ||
178 | |||
179 | void fs_mii_link_status_change_check(struct net_device *dev, int init_media); | ||
180 | 190 | ||
181 | void fs_init_bds(struct net_device *dev); | 191 | void fs_init_bds(struct net_device *dev); |
182 | void fs_cleanup_bds(struct net_device *dev); | 192 | void fs_cleanup_bds(struct net_device *dev); |
@@ -194,7 +204,6 @@ int fs_enet_platform_init(void); | |||
194 | void fs_enet_platform_cleanup(void); | 204 | void fs_enet_platform_cleanup(void); |
195 | 205 | ||
196 | /***************************************************************************/ | 206 | /***************************************************************************/ |
197 | |||
198 | /* buffer descriptor access macros */ | 207 | /* buffer descriptor access macros */ |
199 | 208 | ||
200 | /* access macros */ | 209 | /* access macros */ |
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 95e2bb8dd7b4..1ff2597b8495 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * kind, whether express or implied. | 12 | * kind, whether express or implied. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
@@ -35,6 +34,7 @@ | |||
35 | #include <linux/bitops.h> | 34 | #include <linux/bitops.h> |
36 | #include <linux/fs.h> | 35 | #include <linux/fs.h> |
37 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/phy.h> | ||
38 | 38 | ||
39 | #include <asm/immap_cpm2.h> | 39 | #include <asm/immap_cpm2.h> |
40 | #include <asm/mpc8260.h> | 40 | #include <asm/mpc8260.h> |
@@ -123,22 +123,32 @@ static int do_pd_setup(struct fs_enet_private *fep) | |||
123 | 123 | ||
124 | /* Attach the memory for the FCC Parameter RAM */ | 124 | /* Attach the memory for the FCC Parameter RAM */ |
125 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram"); | 125 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram"); |
126 | fep->fcc.ep = (void *)r->start; | 126 | fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1); |
127 | |||
128 | if (fep->fcc.ep == NULL) | 127 | if (fep->fcc.ep == NULL) |
129 | return -EINVAL; | 128 | return -EINVAL; |
130 | 129 | ||
131 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs"); | 130 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs"); |
132 | fep->fcc.fccp = (void *)r->start; | 131 | fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1); |
133 | |||
134 | if (fep->fcc.fccp == NULL) | 132 | if (fep->fcc.fccp == NULL) |
135 | return -EINVAL; | 133 | return -EINVAL; |
136 | 134 | ||
137 | fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c; | 135 | if (fep->fpi->fcc_regs_c) { |
136 | |||
137 | fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c; | ||
138 | } else { | ||
139 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
140 | "fcc_regs_c"); | ||
141 | fep->fcc.fcccp = (void *)ioremap(r->start, | ||
142 | r->end - r->start + 1); | ||
143 | } | ||
138 | 144 | ||
139 | if (fep->fcc.fcccp == NULL) | 145 | if (fep->fcc.fcccp == NULL) |
140 | return -EINVAL; | 146 | return -EINVAL; |
141 | 147 | ||
148 | fep->fcc.mem = (void *)fep->fpi->mem_offset; | ||
149 | if (fep->fcc.mem == NULL) | ||
150 | return -EINVAL; | ||
151 | |||
142 | return 0; | 152 | return 0; |
143 | } | 153 | } |
144 | 154 | ||
@@ -156,8 +166,6 @@ static int setup_data(struct net_device *dev) | |||
156 | if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */ | 166 | if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */ |
157 | return -EINVAL; | 167 | return -EINVAL; |
158 | 168 | ||
159 | fep->fcc.mem = (void *)fpi->mem_offset; | ||
160 | |||
161 | if (do_pd_setup(fep) != 0) | 169 | if (do_pd_setup(fep) != 0) |
162 | return -EINVAL; | 170 | return -EINVAL; |
163 | 171 | ||
@@ -395,7 +403,7 @@ static void restart(struct net_device *dev) | |||
395 | 403 | ||
396 | /* adjust to speed (for RMII mode) */ | 404 | /* adjust to speed (for RMII mode) */ |
397 | if (fpi->use_rmii) { | 405 | if (fpi->use_rmii) { |
398 | if (fep->speed == 100) | 406 | if (fep->phydev->speed == 100) |
399 | C8(fcccp, fcc_gfemr, 0x20); | 407 | C8(fcccp, fcc_gfemr, 0x20); |
400 | else | 408 | else |
401 | S8(fcccp, fcc_gfemr, 0x20); | 409 | S8(fcccp, fcc_gfemr, 0x20); |
@@ -421,7 +429,7 @@ static void restart(struct net_device *dev) | |||
421 | S32(fccp, fcc_fpsmr, FCC_PSMR_RMII); | 429 | S32(fccp, fcc_fpsmr, FCC_PSMR_RMII); |
422 | 430 | ||
423 | /* adjust to duplex mode */ | 431 | /* adjust to duplex mode */ |
424 | if (fep->duplex) | 432 | if (fep->phydev->duplex) |
425 | S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); | 433 | S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); |
426 | else | 434 | else |
427 | C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); | 435 | C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); |
@@ -487,7 +495,10 @@ static void rx_bd_done(struct net_device *dev) | |||
487 | 495 | ||
488 | static void tx_kickstart(struct net_device *dev) | 496 | static void tx_kickstart(struct net_device *dev) |
489 | { | 497 | { |
490 | /* nothing */ | 498 | struct fs_enet_private *fep = netdev_priv(dev); |
499 | fcc_t *fccp = fep->fcc.fccp; | ||
500 | |||
501 | S32(fccp, fcc_ftodr, 0x80); | ||
491 | } | 502 | } |
492 | 503 | ||
493 | static u32 get_int_events(struct net_device *dev) | 504 | static u32 get_int_events(struct net_device *dev) |
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 3dad69dfdb2c..c2c5fd419bd0 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * kind, whether express or implied. | 12 | * kind, whether express or implied. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
@@ -47,6 +46,7 @@ | |||
47 | #endif | 46 | #endif |
48 | 47 | ||
49 | #include "fs_enet.h" | 48 | #include "fs_enet.h" |
49 | #include "fec.h" | ||
50 | 50 | ||
51 | /*************************************************/ | 51 | /*************************************************/ |
52 | 52 | ||
@@ -76,50 +76,8 @@ | |||
76 | /* clear bits */ | 76 | /* clear bits */ |
77 | #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v)) | 77 | #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v)) |
78 | 78 | ||
79 | |||
80 | /* CRC polynomium used by the FEC for the multicast group filtering */ | ||
81 | #define FEC_CRC_POLY 0x04C11DB7 | ||
82 | |||
83 | #define FEC_MAX_MULTICAST_ADDRS 64 | ||
84 | |||
85 | /* Interrupt events/masks. | ||
86 | */ | ||
87 | #define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */ | ||
88 | #define FEC_ENET_BABR 0x40000000U /* Babbling receiver */ | ||
89 | #define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */ | ||
90 | #define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */ | ||
91 | #define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */ | ||
92 | #define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */ | ||
93 | #define FEC_ENET_RXF 0x02000000U /* Full frame received */ | ||
94 | #define FEC_ENET_RXB 0x01000000U /* A buffer was received */ | ||
95 | #define FEC_ENET_MII 0x00800000U /* MII interrupt */ | ||
96 | #define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */ | ||
97 | |||
98 | #define FEC_ECNTRL_PINMUX 0x00000004 | ||
99 | #define FEC_ECNTRL_ETHER_EN 0x00000002 | ||
100 | #define FEC_ECNTRL_RESET 0x00000001 | ||
101 | |||
102 | #define FEC_RCNTRL_BC_REJ 0x00000010 | ||
103 | #define FEC_RCNTRL_PROM 0x00000008 | ||
104 | #define FEC_RCNTRL_MII_MODE 0x00000004 | ||
105 | #define FEC_RCNTRL_DRT 0x00000002 | ||
106 | #define FEC_RCNTRL_LOOP 0x00000001 | ||
107 | |||
108 | #define FEC_TCNTRL_FDEN 0x00000004 | ||
109 | #define FEC_TCNTRL_HBC 0x00000002 | ||
110 | #define FEC_TCNTRL_GTS 0x00000001 | ||
111 | |||
112 | |||
113 | /* Make MII read/write commands for the FEC. | ||
114 | */ | ||
115 | #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) | ||
116 | #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) | ||
117 | #define mk_mii_end 0 | ||
118 | |||
119 | #define FEC_MII_LOOPS 10000 | ||
120 | |||
121 | /* | 79 | /* |
122 | * Delay to wait for FEC reset command to complete (in us) | 80 | * Delay to wait for FEC reset command to complete (in us) |
123 | */ | 81 | */ |
124 | #define FEC_RESET_DELAY 50 | 82 | #define FEC_RESET_DELAY 50 |
125 | 83 | ||
@@ -304,13 +262,15 @@ static void restart(struct net_device *dev) | |||
304 | int r; | 262 | int r; |
305 | u32 addrhi, addrlo; | 263 | u32 addrhi, addrlo; |
306 | 264 | ||
265 | struct mii_bus* mii = fep->phydev->bus; | ||
266 | struct fec_info* fec_inf = mii->priv; | ||
267 | |||
307 | r = whack_reset(fep->fec.fecp); | 268 | r = whack_reset(fep->fec.fecp); |
308 | if (r != 0) | 269 | if (r != 0) |
309 | printk(KERN_ERR DRV_MODULE_NAME | 270 | printk(KERN_ERR DRV_MODULE_NAME |
310 | ": %s FEC Reset FAILED!\n", dev->name); | 271 | ": %s FEC Reset FAILED!\n", dev->name); |
311 | |||
312 | /* | 272 | /* |
313 | * Set station address. | 273 | * Set station address. |
314 | */ | 274 | */ |
315 | addrhi = ((u32) dev->dev_addr[0] << 24) | | 275 | addrhi = ((u32) dev->dev_addr[0] << 24) | |
316 | ((u32) dev->dev_addr[1] << 16) | | 276 | ((u32) dev->dev_addr[1] << 16) | |
@@ -351,12 +311,12 @@ static void restart(struct net_device *dev) | |||
351 | FW(fecp, fun_code, 0x78000000); | 311 | FW(fecp, fun_code, 0x78000000); |
352 | 312 | ||
353 | /* | 313 | /* |
354 | * Set MII speed. | 314 | * Set MII speed. |
355 | */ | 315 | */ |
356 | FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed); | 316 | FW(fecp, mii_speed, fec_inf->mii_speed); |
357 | 317 | ||
358 | /* | 318 | /* |
359 | * Clear any outstanding interrupt. | 319 | * Clear any outstanding interrupt. |
360 | */ | 320 | */ |
361 | FW(fecp, ievent, 0xffc0); | 321 | FW(fecp, ievent, 0xffc0); |
362 | FW(fecp, ivec, (fep->interrupt / 2) << 29); | 322 | FW(fecp, ivec, (fep->interrupt / 2) << 29); |
@@ -391,11 +351,12 @@ static void restart(struct net_device *dev) | |||
391 | } | 351 | } |
392 | #endif | 352 | #endif |
393 | 353 | ||
354 | |||
394 | FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ | 355 | FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ |
395 | /* | 356 | /* |
396 | * adjust to duplex mode | 357 | * adjust to duplex mode |
397 | */ | 358 | */ |
398 | if (fep->duplex) { | 359 | if (fep->phydev->duplex) { |
399 | FC(fecp, r_cntrl, FEC_RCNTRL_DRT); | 360 | FC(fecp, r_cntrl, FEC_RCNTRL_DRT); |
400 | FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ | 361 | FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ |
401 | } else { | 362 | } else { |
@@ -419,9 +380,11 @@ static void restart(struct net_device *dev) | |||
419 | static void stop(struct net_device *dev) | 380 | static void stop(struct net_device *dev) |
420 | { | 381 | { |
421 | struct fs_enet_private *fep = netdev_priv(dev); | 382 | struct fs_enet_private *fep = netdev_priv(dev); |
383 | const struct fs_platform_info *fpi = fep->fpi; | ||
422 | fec_t *fecp = fep->fec.fecp; | 384 | fec_t *fecp = fep->fec.fecp; |
423 | struct fs_enet_mii_bus *bus = fep->mii_bus; | 385 | |
424 | const struct fs_mii_bus_info *bi = bus->bus_info; | 386 | struct fec_info* feci= fep->phydev->bus->priv; |
387 | |||
425 | int i; | 388 | int i; |
426 | 389 | ||
427 | if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) | 390 | if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) |
@@ -445,11 +408,11 @@ static void stop(struct net_device *dev) | |||
445 | fs_cleanup_bds(dev); | 408 | fs_cleanup_bds(dev); |
446 | 409 | ||
447 | /* shut down FEC1? that's where the mii bus is */ | 410 | /* shut down FEC1? that's where the mii bus is */ |
448 | if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) { | 411 | if (fpi->has_phy) { |
449 | FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ | 412 | FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ |
450 | FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); | 413 | FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); |
451 | FW(fecp, ievent, FEC_ENET_MII); | 414 | FW(fecp, ievent, FEC_ENET_MII); |
452 | FW(fecp, mii_speed, bus->fec.mii_speed); | 415 | FW(fecp, mii_speed, feci->mii_speed); |
453 | } | 416 | } |
454 | } | 417 | } |
455 | 418 | ||
@@ -584,73 +547,3 @@ const struct fs_ops fs_fec_ops = { | |||
584 | .free_bd = free_bd, | 547 | .free_bd = free_bd, |
585 | }; | 548 | }; |
586 | 549 | ||
587 | /***********************************************************************/ | ||
588 | |||
589 | static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) | ||
590 | { | ||
591 | fec_t *fecp = bus->fec.fecp; | ||
592 | int i, ret = -1; | ||
593 | |||
594 | if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) | ||
595 | BUG(); | ||
596 | |||
597 | /* Add PHY address to register command. */ | ||
598 | FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location)); | ||
599 | |||
600 | for (i = 0; i < FEC_MII_LOOPS; i++) | ||
601 | if ((FR(fecp, ievent) & FEC_ENET_MII) != 0) | ||
602 | break; | ||
603 | |||
604 | if (i < FEC_MII_LOOPS) { | ||
605 | FW(fecp, ievent, FEC_ENET_MII); | ||
606 | ret = FR(fecp, mii_data) & 0xffff; | ||
607 | } | ||
608 | |||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value) | ||
613 | { | ||
614 | fec_t *fecp = bus->fec.fecp; | ||
615 | int i; | ||
616 | |||
617 | /* this must never happen */ | ||
618 | if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) | ||
619 | BUG(); | ||
620 | |||
621 | /* Add PHY address to register command. */ | ||
622 | FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value)); | ||
623 | |||
624 | for (i = 0; i < FEC_MII_LOOPS; i++) | ||
625 | if ((FR(fecp, ievent) & FEC_ENET_MII) != 0) | ||
626 | break; | ||
627 | |||
628 | if (i < FEC_MII_LOOPS) | ||
629 | FW(fecp, ievent, FEC_ENET_MII); | ||
630 | } | ||
631 | |||
632 | int fs_mii_fec_init(struct fs_enet_mii_bus *bus) | ||
633 | { | ||
634 | bd_t *bd = (bd_t *)__res; | ||
635 | const struct fs_mii_bus_info *bi = bus->bus_info; | ||
636 | fec_t *fecp; | ||
637 | |||
638 | if (bi->id != 0) | ||
639 | return -1; | ||
640 | |||
641 | bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec; | ||
642 | bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) | ||
643 | & 0x3F) << 1; | ||
644 | |||
645 | fecp = bus->fec.fecp; | ||
646 | |||
647 | FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ | ||
648 | FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); | ||
649 | FW(fecp, ievent, FEC_ENET_MII); | ||
650 | FW(fecp, mii_speed, bus->fec.mii_speed); | ||
651 | |||
652 | bus->mii_read = mii_read; | ||
653 | bus->mii_write = mii_write; | ||
654 | |||
655 | return 0; | ||
656 | } | ||
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index a772b286f96d..95ec5872c507 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * kind, whether express or implied. | 12 | * kind, whether express or implied. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
@@ -370,7 +369,7 @@ static void restart(struct net_device *dev) | |||
370 | W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22); | 369 | W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22); |
371 | 370 | ||
372 | /* Set full duplex mode if needed */ | 371 | /* Set full duplex mode if needed */ |
373 | if (fep->duplex) | 372 | if (fep->phydev->duplex) |
374 | S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE); | 373 | S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE); |
375 | 374 | ||
376 | S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); | 375 | S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); |
@@ -501,6 +500,8 @@ static void tx_restart(struct net_device *dev) | |||
501 | scc_cr_cmd(fep, CPM_CR_RESTART_TX); | 500 | scc_cr_cmd(fep, CPM_CR_RESTART_TX); |
502 | } | 501 | } |
503 | 502 | ||
503 | |||
504 | |||
504 | /*************************************************************************/ | 505 | /*************************************************************************/ |
505 | 506 | ||
506 | const struct fs_ops fs_scc_ops = { | 507 | const struct fs_ops fs_scc_ops = { |
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 24a5e2e23d18..0b9b8b5c847c 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | 15 | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | 16 | #include <linux/module.h> |
18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -34,6 +33,7 @@ | |||
34 | #include <linux/mii.h> | 33 | #include <linux/mii.h> |
35 | #include <linux/ethtool.h> | 34 | #include <linux/ethtool.h> |
36 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/platform_device.h> | ||
37 | 37 | ||
38 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
39 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
@@ -41,129 +41,25 @@ | |||
41 | 41 | ||
42 | #include "fs_enet.h" | 42 | #include "fs_enet.h" |
43 | 43 | ||
44 | #ifdef CONFIG_8xx | 44 | static int bitbang_prep_bit(u8 **datp, u8 *mskp, |
45 | static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) | 45 | struct fs_mii_bit *mii_bit) |
46 | { | 46 | { |
47 | immap_t *im = (immap_t *)fs_enet_immap; | 47 | void *dat; |
48 | void *dir, *dat, *ppar; | ||
49 | int adv; | 48 | int adv; |
50 | u8 msk; | 49 | u8 msk; |
51 | 50 | ||
52 | switch (port) { | 51 | dat = (void*) mii_bit->offset; |
53 | case fsiop_porta: | ||
54 | dir = &im->im_ioport.iop_padir; | ||
55 | dat = &im->im_ioport.iop_padat; | ||
56 | ppar = &im->im_ioport.iop_papar; | ||
57 | break; | ||
58 | |||
59 | case fsiop_portb: | ||
60 | dir = &im->im_cpm.cp_pbdir; | ||
61 | dat = &im->im_cpm.cp_pbdat; | ||
62 | ppar = &im->im_cpm.cp_pbpar; | ||
63 | break; | ||
64 | |||
65 | case fsiop_portc: | ||
66 | dir = &im->im_ioport.iop_pcdir; | ||
67 | dat = &im->im_ioport.iop_pcdat; | ||
68 | ppar = &im->im_ioport.iop_pcpar; | ||
69 | break; | ||
70 | |||
71 | case fsiop_portd: | ||
72 | dir = &im->im_ioport.iop_pddir; | ||
73 | dat = &im->im_ioport.iop_pddat; | ||
74 | ppar = &im->im_ioport.iop_pdpar; | ||
75 | break; | ||
76 | |||
77 | case fsiop_porte: | ||
78 | dir = &im->im_cpm.cp_pedir; | ||
79 | dat = &im->im_cpm.cp_pedat; | ||
80 | ppar = &im->im_cpm.cp_pepar; | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | printk(KERN_ERR DRV_MODULE_NAME | ||
85 | "Illegal port value %d!\n", port); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | adv = bit >> 3; | ||
90 | dir = (char *)dir + adv; | ||
91 | dat = (char *)dat + adv; | ||
92 | ppar = (char *)ppar + adv; | ||
93 | |||
94 | msk = 1 << (7 - (bit & 7)); | ||
95 | if ((in_8(ppar) & msk) != 0) { | ||
96 | printk(KERN_ERR DRV_MODULE_NAME | ||
97 | "pin %d on port %d is not general purpose!\n", bit, port); | ||
98 | return -EINVAL; | ||
99 | } | ||
100 | |||
101 | *dirp = dir; | ||
102 | *datp = dat; | ||
103 | *mskp = msk; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | #endif | ||
108 | |||
109 | #ifdef CONFIG_8260 | ||
110 | static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) | ||
111 | { | ||
112 | iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport; | ||
113 | void *dir, *dat, *ppar; | ||
114 | int adv; | ||
115 | u8 msk; | ||
116 | |||
117 | switch (port) { | ||
118 | case fsiop_porta: | ||
119 | dir = &io->iop_pdira; | ||
120 | dat = &io->iop_pdata; | ||
121 | ppar = &io->iop_ppara; | ||
122 | break; | ||
123 | |||
124 | case fsiop_portb: | ||
125 | dir = &io->iop_pdirb; | ||
126 | dat = &io->iop_pdatb; | ||
127 | ppar = &io->iop_pparb; | ||
128 | break; | ||
129 | |||
130 | case fsiop_portc: | ||
131 | dir = &io->iop_pdirc; | ||
132 | dat = &io->iop_pdatc; | ||
133 | ppar = &io->iop_pparc; | ||
134 | break; | ||
135 | |||
136 | case fsiop_portd: | ||
137 | dir = &io->iop_pdird; | ||
138 | dat = &io->iop_pdatd; | ||
139 | ppar = &io->iop_ppard; | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | printk(KERN_ERR DRV_MODULE_NAME | ||
144 | "Illegal port value %d!\n", port); | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | 52 | ||
148 | adv = bit >> 3; | 53 | adv = mii_bit->bit >> 3; |
149 | dir = (char *)dir + adv; | ||
150 | dat = (char *)dat + adv; | 54 | dat = (char *)dat + adv; |
151 | ppar = (char *)ppar + adv; | ||
152 | 55 | ||
153 | msk = 1 << (7 - (bit & 7)); | 56 | msk = 1 << (7 - (mii_bit->bit & 7)); |
154 | if ((in_8(ppar) & msk) != 0) { | ||
155 | printk(KERN_ERR DRV_MODULE_NAME | ||
156 | "pin %d on port %d is not general purpose!\n", bit, port); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | 57 | ||
160 | *dirp = dir; | ||
161 | *datp = dat; | 58 | *datp = dat; |
162 | *mskp = msk; | 59 | *mskp = msk; |
163 | 60 | ||
164 | return 0; | 61 | return 0; |
165 | } | 62 | } |
166 | #endif | ||
167 | 63 | ||
168 | static inline void bb_set(u8 *p, u8 m) | 64 | static inline void bb_set(u8 *p, u8 m) |
169 | { | 65 | { |
@@ -180,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m) | |||
180 | return (in_8(p) & m) != 0; | 76 | return (in_8(p) & m) != 0; |
181 | } | 77 | } |
182 | 78 | ||
183 | static inline void mdio_active(struct fs_enet_mii_bus *bus) | 79 | static inline void mdio_active(struct bb_info *bitbang) |
184 | { | 80 | { |
185 | bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); | 81 | bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk); |
186 | } | 82 | } |
187 | 83 | ||
188 | static inline void mdio_tristate(struct fs_enet_mii_bus *bus) | 84 | static inline void mdio_tristate(struct bb_info *bitbang ) |
189 | { | 85 | { |
190 | bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); | 86 | bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk); |
191 | } | 87 | } |
192 | 88 | ||
193 | static inline int mdio_read(struct fs_enet_mii_bus *bus) | 89 | static inline int mdio_read(struct bb_info *bitbang ) |
194 | { | 90 | { |
195 | return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); | 91 | return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk); |
196 | } | 92 | } |
197 | 93 | ||
198 | static inline void mdio(struct fs_enet_mii_bus *bus, int what) | 94 | static inline void mdio(struct bb_info *bitbang , int what) |
199 | { | 95 | { |
200 | if (what) | 96 | if (what) |
201 | bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); | 97 | bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk); |
202 | else | 98 | else |
203 | bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); | 99 | bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk); |
204 | } | 100 | } |
205 | 101 | ||
206 | static inline void mdc(struct fs_enet_mii_bus *bus, int what) | 102 | static inline void mdc(struct bb_info *bitbang , int what) |
207 | { | 103 | { |
208 | if (what) | 104 | if (what) |
209 | bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); | 105 | bb_set(bitbang->mdc_dat, bitbang->mdc_msk); |
210 | else | 106 | else |
211 | bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); | 107 | bb_clr(bitbang->mdc_dat, bitbang->mdc_msk); |
212 | } | 108 | } |
213 | 109 | ||
214 | static inline void mii_delay(struct fs_enet_mii_bus *bus) | 110 | static inline void mii_delay(struct bb_info *bitbang ) |
215 | { | 111 | { |
216 | udelay(bus->bus_info->i.bitbang.delay); | 112 | udelay(bitbang->delay); |
217 | } | 113 | } |
218 | 114 | ||
219 | /* Utility to send the preamble, address, and register (common to read and write). */ | 115 | /* Utility to send the preamble, address, and register (common to read and write). */ |
220 | static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) | 116 | static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg) |
221 | { | 117 | { |
222 | int j; | 118 | int j; |
223 | 119 | ||
@@ -229,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) | |||
229 | * but it is safer and will be much more robust. | 125 | * but it is safer and will be much more robust. |
230 | */ | 126 | */ |
231 | 127 | ||
232 | mdio_active(bus); | 128 | mdio_active(bitbang); |
233 | mdio(bus, 1); | 129 | mdio(bitbang, 1); |
234 | for (j = 0; j < 32; j++) { | 130 | for (j = 0; j < 32; j++) { |
235 | mdc(bus, 0); | 131 | mdc(bitbang, 0); |
236 | mii_delay(bus); | 132 | mii_delay(bitbang); |
237 | mdc(bus, 1); | 133 | mdc(bitbang, 1); |
238 | mii_delay(bus); | 134 | mii_delay(bitbang); |
239 | } | 135 | } |
240 | 136 | ||
241 | /* send the start bit (01) and the read opcode (10) or write (10) */ | 137 | /* send the start bit (01) and the read opcode (10) or write (10) */ |
242 | mdc(bus, 0); | 138 | mdc(bitbang, 0); |
243 | mdio(bus, 0); | 139 | mdio(bitbang, 0); |
244 | mii_delay(bus); | 140 | mii_delay(bitbang); |
245 | mdc(bus, 1); | 141 | mdc(bitbang, 1); |
246 | mii_delay(bus); | 142 | mii_delay(bitbang); |
247 | mdc(bus, 0); | 143 | mdc(bitbang, 0); |
248 | mdio(bus, 1); | 144 | mdio(bitbang, 1); |
249 | mii_delay(bus); | 145 | mii_delay(bitbang); |
250 | mdc(bus, 1); | 146 | mdc(bitbang, 1); |
251 | mii_delay(bus); | 147 | mii_delay(bitbang); |
252 | mdc(bus, 0); | 148 | mdc(bitbang, 0); |
253 | mdio(bus, read); | 149 | mdio(bitbang, read); |
254 | mii_delay(bus); | 150 | mii_delay(bitbang); |
255 | mdc(bus, 1); | 151 | mdc(bitbang, 1); |
256 | mii_delay(bus); | 152 | mii_delay(bitbang); |
257 | mdc(bus, 0); | 153 | mdc(bitbang, 0); |
258 | mdio(bus, !read); | 154 | mdio(bitbang, !read); |
259 | mii_delay(bus); | 155 | mii_delay(bitbang); |
260 | mdc(bus, 1); | 156 | mdc(bitbang, 1); |
261 | mii_delay(bus); | 157 | mii_delay(bitbang); |
262 | 158 | ||
263 | /* send the PHY address */ | 159 | /* send the PHY address */ |
264 | for (j = 0; j < 5; j++) { | 160 | for (j = 0; j < 5; j++) { |
265 | mdc(bus, 0); | 161 | mdc(bitbang, 0); |
266 | mdio(bus, (addr & 0x10) != 0); | 162 | mdio(bitbang, (addr & 0x10) != 0); |
267 | mii_delay(bus); | 163 | mii_delay(bitbang); |
268 | mdc(bus, 1); | 164 | mdc(bitbang, 1); |
269 | mii_delay(bus); | 165 | mii_delay(bitbang); |
270 | addr <<= 1; | 166 | addr <<= 1; |
271 | } | 167 | } |
272 | 168 | ||
273 | /* send the register address */ | 169 | /* send the register address */ |
274 | for (j = 0; j < 5; j++) { | 170 | for (j = 0; j < 5; j++) { |
275 | mdc(bus, 0); | 171 | mdc(bitbang, 0); |
276 | mdio(bus, (reg & 0x10) != 0); | 172 | mdio(bitbang, (reg & 0x10) != 0); |
277 | mii_delay(bus); | 173 | mii_delay(bitbang); |
278 | mdc(bus, 1); | 174 | mdc(bitbang, 1); |
279 | mii_delay(bus); | 175 | mii_delay(bitbang); |
280 | reg <<= 1; | 176 | reg <<= 1; |
281 | } | 177 | } |
282 | } | 178 | } |
283 | 179 | ||
284 | static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) | 180 | static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location) |
285 | { | 181 | { |
286 | u16 rdreg; | 182 | u16 rdreg; |
287 | int ret, j; | 183 | int ret, j; |
288 | u8 addr = phy_id & 0xff; | 184 | u8 addr = phy_id & 0xff; |
289 | u8 reg = location & 0xff; | 185 | u8 reg = location & 0xff; |
186 | struct bb_info* bitbang = bus->priv; | ||
290 | 187 | ||
291 | bitbang_pre(bus, 1, addr, reg); | 188 | bitbang_pre(bitbang, 1, addr, reg); |
292 | 189 | ||
293 | /* tri-state our MDIO I/O pin so we can read */ | 190 | /* tri-state our MDIO I/O pin so we can read */ |
294 | mdc(bus, 0); | 191 | mdc(bitbang, 0); |
295 | mdio_tristate(bus); | 192 | mdio_tristate(bitbang); |
296 | mii_delay(bus); | 193 | mii_delay(bitbang); |
297 | mdc(bus, 1); | 194 | mdc(bitbang, 1); |
298 | mii_delay(bus); | 195 | mii_delay(bitbang); |
299 | 196 | ||
300 | /* check the turnaround bit: the PHY should be driving it to zero */ | 197 | /* check the turnaround bit: the PHY should be driving it to zero */ |
301 | if (mdio_read(bus) != 0) { | 198 | if (mdio_read(bitbang) != 0) { |
302 | /* PHY didn't drive TA low */ | 199 | /* PHY didn't drive TA low */ |
303 | for (j = 0; j < 32; j++) { | 200 | for (j = 0; j < 32; j++) { |
304 | mdc(bus, 0); | 201 | mdc(bitbang, 0); |
305 | mii_delay(bus); | 202 | mii_delay(bitbang); |
306 | mdc(bus, 1); | 203 | mdc(bitbang, 1); |
307 | mii_delay(bus); | 204 | mii_delay(bitbang); |
308 | } | 205 | } |
309 | ret = -1; | 206 | ret = -1; |
310 | goto out; | 207 | goto out; |
311 | } | 208 | } |
312 | 209 | ||
313 | mdc(bus, 0); | 210 | mdc(bitbang, 0); |
314 | mii_delay(bus); | 211 | mii_delay(bitbang); |
315 | 212 | ||
316 | /* read 16 bits of register data, MSB first */ | 213 | /* read 16 bits of register data, MSB first */ |
317 | rdreg = 0; | 214 | rdreg = 0; |
318 | for (j = 0; j < 16; j++) { | 215 | for (j = 0; j < 16; j++) { |
319 | mdc(bus, 1); | 216 | mdc(bitbang, 1); |
320 | mii_delay(bus); | 217 | mii_delay(bitbang); |
321 | rdreg <<= 1; | 218 | rdreg <<= 1; |
322 | rdreg |= mdio_read(bus); | 219 | rdreg |= mdio_read(bitbang); |
323 | mdc(bus, 0); | 220 | mdc(bitbang, 0); |
324 | mii_delay(bus); | 221 | mii_delay(bitbang); |
325 | } | 222 | } |
326 | 223 | ||
327 | mdc(bus, 1); | 224 | mdc(bitbang, 1); |
328 | mii_delay(bus); | 225 | mii_delay(bitbang); |
329 | mdc(bus, 0); | 226 | mdc(bitbang, 0); |
330 | mii_delay(bus); | 227 | mii_delay(bitbang); |
331 | mdc(bus, 1); | 228 | mdc(bitbang, 1); |
332 | mii_delay(bus); | 229 | mii_delay(bitbang); |
333 | 230 | ||
334 | ret = rdreg; | 231 | ret = rdreg; |
335 | out: | 232 | out: |
336 | return ret; | 233 | return ret; |
337 | } | 234 | } |
338 | 235 | ||
339 | static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) | 236 | static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val) |
340 | { | 237 | { |
341 | int j; | 238 | int j; |
239 | struct bb_info* bitbang = bus->priv; | ||
240 | |||
342 | u8 addr = phy_id & 0xff; | 241 | u8 addr = phy_id & 0xff; |
343 | u8 reg = location & 0xff; | 242 | u8 reg = location & 0xff; |
344 | u16 value = val & 0xffff; | 243 | u16 value = val & 0xffff; |
345 | 244 | ||
346 | bitbang_pre(bus, 0, addr, reg); | 245 | bitbang_pre(bitbang, 0, addr, reg); |
347 | 246 | ||
348 | /* send the turnaround (10) */ | 247 | /* send the turnaround (10) */ |
349 | mdc(bus, 0); | 248 | mdc(bitbang, 0); |
350 | mdio(bus, 1); | 249 | mdio(bitbang, 1); |
351 | mii_delay(bus); | 250 | mii_delay(bitbang); |
352 | mdc(bus, 1); | 251 | mdc(bitbang, 1); |
353 | mii_delay(bus); | 252 | mii_delay(bitbang); |
354 | mdc(bus, 0); | 253 | mdc(bitbang, 0); |
355 | mdio(bus, 0); | 254 | mdio(bitbang, 0); |
356 | mii_delay(bus); | 255 | mii_delay(bitbang); |
357 | mdc(bus, 1); | 256 | mdc(bitbang, 1); |
358 | mii_delay(bus); | 257 | mii_delay(bitbang); |
359 | 258 | ||
360 | /* write 16 bits of register data, MSB first */ | 259 | /* write 16 bits of register data, MSB first */ |
361 | for (j = 0; j < 16; j++) { | 260 | for (j = 0; j < 16; j++) { |
362 | mdc(bus, 0); | 261 | mdc(bitbang, 0); |
363 | mdio(bus, (value & 0x8000) != 0); | 262 | mdio(bitbang, (value & 0x8000) != 0); |
364 | mii_delay(bus); | 263 | mii_delay(bitbang); |
365 | mdc(bus, 1); | 264 | mdc(bitbang, 1); |
366 | mii_delay(bus); | 265 | mii_delay(bitbang); |
367 | value <<= 1; | 266 | value <<= 1; |
368 | } | 267 | } |
369 | 268 | ||
370 | /* | 269 | /* |
371 | * Tri-state the MDIO line. | 270 | * Tri-state the MDIO line. |
372 | */ | 271 | */ |
373 | mdio_tristate(bus); | 272 | mdio_tristate(bitbang); |
374 | mdc(bus, 0); | 273 | mdc(bitbang, 0); |
375 | mii_delay(bus); | 274 | mii_delay(bitbang); |
376 | mdc(bus, 1); | 275 | mdc(bitbang, 1); |
377 | mii_delay(bus); | 276 | mii_delay(bitbang); |
277 | return 0; | ||
378 | } | 278 | } |
379 | 279 | ||
380 | int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus) | 280 | static int fs_enet_mii_bb_reset(struct mii_bus *bus) |
281 | { | ||
282 | /*nothing here - dunno how to reset it*/ | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi) | ||
381 | { | 287 | { |
382 | const struct fs_mii_bus_info *bi = bus->bus_info; | ||
383 | int r; | 288 | int r; |
384 | 289 | ||
385 | r = bitbang_prep_bit(&bus->bitbang.mdio_dir, | 290 | bitbang->delay = fmpi->delay; |
386 | &bus->bitbang.mdio_dat, | 291 | |
387 | &bus->bitbang.mdio_msk, | 292 | r = bitbang_prep_bit(&bitbang->mdio_dir, |
388 | bi->i.bitbang.mdio_port, | 293 | &bitbang->mdio_dir_msk, |
389 | bi->i.bitbang.mdio_bit); | 294 | &fmpi->mdio_dir); |
390 | if (r != 0) | 295 | if (r != 0) |
391 | return r; | 296 | return r; |
392 | 297 | ||
393 | r = bitbang_prep_bit(&bus->bitbang.mdc_dir, | 298 | r = bitbang_prep_bit(&bitbang->mdio_dat, |
394 | &bus->bitbang.mdc_dat, | 299 | &bitbang->mdio_dat_msk, |
395 | &bus->bitbang.mdc_msk, | 300 | &fmpi->mdio_dat); |
396 | bi->i.bitbang.mdc_port, | ||
397 | bi->i.bitbang.mdc_bit); | ||
398 | if (r != 0) | 301 | if (r != 0) |
399 | return r; | 302 | return r; |
400 | 303 | ||
401 | bus->mii_read = mii_read; | 304 | r = bitbang_prep_bit(&bitbang->mdc_dat, |
402 | bus->mii_write = mii_write; | 305 | &bitbang->mdc_msk, |
306 | &fmpi->mdc_dat); | ||
307 | if (r != 0) | ||
308 | return r; | ||
403 | 309 | ||
404 | return 0; | 310 | return 0; |
405 | } | 311 | } |
312 | |||
313 | |||
314 | static int __devinit fs_enet_mdio_probe(struct device *dev) | ||
315 | { | ||
316 | struct platform_device *pdev = to_platform_device(dev); | ||
317 | struct fs_mii_bb_platform_info *pdata; | ||
318 | struct mii_bus *new_bus; | ||
319 | struct bb_info *bitbang; | ||
320 | int err = 0; | ||
321 | |||
322 | if (NULL == dev) | ||
323 | return -EINVAL; | ||
324 | |||
325 | new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); | ||
326 | |||
327 | if (NULL == new_bus) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); | ||
331 | |||
332 | if (NULL == bitbang) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | new_bus->name = "BB MII Bus", | ||
336 | new_bus->read = &fs_enet_mii_bb_read, | ||
337 | new_bus->write = &fs_enet_mii_bb_write, | ||
338 | new_bus->reset = &fs_enet_mii_bb_reset, | ||
339 | new_bus->id = pdev->id; | ||
340 | |||
341 | new_bus->phy_mask = ~0x9; | ||
342 | pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data; | ||
343 | |||
344 | if (NULL == pdata) { | ||
345 | printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id); | ||
346 | return -ENODEV; | ||
347 | } | ||
348 | |||
349 | /*set up workspace*/ | ||
350 | fs_mii_bitbang_init(bitbang, pdata); | ||
351 | |||
352 | new_bus->priv = bitbang; | ||
353 | |||
354 | new_bus->irq = pdata->irq; | ||
355 | |||
356 | new_bus->dev = dev; | ||
357 | dev_set_drvdata(dev, new_bus); | ||
358 | |||
359 | err = mdiobus_register(new_bus); | ||
360 | |||
361 | if (0 != err) { | ||
362 | printk (KERN_ERR "%s: Cannot register as MDIO bus\n", | ||
363 | new_bus->name); | ||
364 | goto bus_register_fail; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | bus_register_fail: | ||
370 | kfree(bitbang); | ||
371 | kfree(new_bus); | ||
372 | |||
373 | return err; | ||
374 | } | ||
375 | |||
376 | |||
377 | static int fs_enet_mdio_remove(struct device *dev) | ||
378 | { | ||
379 | struct mii_bus *bus = dev_get_drvdata(dev); | ||
380 | |||
381 | mdiobus_unregister(bus); | ||
382 | |||
383 | dev_set_drvdata(dev, NULL); | ||
384 | |||
385 | iounmap((void *) (&bus->priv)); | ||
386 | bus->priv = NULL; | ||
387 | kfree(bus); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static struct device_driver fs_enet_bb_mdio_driver = { | ||
393 | .name = "fsl-bb-mdio", | ||
394 | .bus = &platform_bus_type, | ||
395 | .probe = fs_enet_mdio_probe, | ||
396 | .remove = fs_enet_mdio_remove, | ||
397 | }; | ||
398 | |||
399 | int fs_enet_mdio_bb_init(void) | ||
400 | { | ||
401 | return driver_register(&fs_enet_bb_mdio_driver); | ||
402 | } | ||
403 | |||
404 | void fs_enet_mdio_bb_exit(void) | ||
405 | { | ||
406 | driver_unregister(&fs_enet_bb_mdio_driver); | ||
407 | } | ||
408 | |||
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c new file mode 100644 index 000000000000..1328e10caa35 --- /dev/null +++ b/drivers/net/fs_enet/mii-fec.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. | ||
3 | * | ||
4 | * Copyright (c) 2003 Intracom S.A. | ||
5 | * by Pantelis Antoniou <panto@intracom.gr> | ||
6 | * | ||
7 | * 2005 (c) MontaVista Software, Inc. | ||
8 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
9 | * | ||
10 | * This file is licensed under the terms of the GNU General Public License | ||
11 | * version 2. This program is licensed "as is" without any warranty of any | ||
12 | * kind, whether express or implied. | ||
13 | */ | ||
14 | |||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/ptrace.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/skbuff.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/mii.h> | ||
35 | #include <linux/ethtool.h> | ||
36 | #include <linux/bitops.h> | ||
37 | #include <linux/platform_device.h> | ||
38 | |||
39 | #include <asm/pgtable.h> | ||
40 | #include <asm/irq.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | |||
43 | #include "fs_enet.h" | ||
44 | #include "fec.h" | ||
45 | |||
46 | /* Make MII read/write commands for the FEC. | ||
47 | */ | ||
48 | #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) | ||
49 | #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) | ||
50 | #define mk_mii_end 0 | ||
51 | |||
52 | #define FEC_MII_LOOPS 10000 | ||
53 | |||
54 | static int match_has_phy (struct device *dev, void* data) | ||
55 | { | ||
56 | struct platform_device* pdev = container_of(dev, struct platform_device, dev); | ||
57 | struct fs_platform_info* fpi; | ||
58 | if(strcmp(pdev->name, (char*)data)) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | fpi = pdev->dev.platform_data; | ||
64 | if((fpi)&&(fpi->has_phy)) | ||
65 | return 1; | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi) | ||
70 | { | ||
71 | struct resource *r; | ||
72 | fec_t *fecp; | ||
73 | char* name = "fsl-cpm-fec"; | ||
74 | |||
75 | /* we need fec in order to be useful */ | ||
76 | struct platform_device *fec_pdev = | ||
77 | container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy), | ||
78 | struct platform_device, dev); | ||
79 | |||
80 | if(fec_pdev == NULL) { | ||
81 | printk(KERN_ERR"Unable to find PHY for %s", name); | ||
82 | return -ENODEV; | ||
83 | } | ||
84 | |||
85 | r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs"); | ||
86 | |||
87 | fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t)); | ||
88 | fec->mii_speed = fmpi->mii_speed; | ||
89 | |||
90 | setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ | ||
91 | setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); | ||
92 | out_be32(&fecp->fec_ievent, FEC_ENET_MII); | ||
93 | out_be32(&fecp->fec_mii_speed, fec->mii_speed); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) | ||
99 | { | ||
100 | struct fec_info* fec = bus->priv; | ||
101 | fec_t *fecp = fec->fecp; | ||
102 | int i, ret = -1; | ||
103 | |||
104 | if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) | ||
105 | BUG(); | ||
106 | |||
107 | /* Add PHY address to register command. */ | ||
108 | out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); | ||
109 | |||
110 | for (i = 0; i < FEC_MII_LOOPS; i++) | ||
111 | if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) | ||
112 | break; | ||
113 | |||
114 | if (i < FEC_MII_LOOPS) { | ||
115 | out_be32(&fecp->fec_ievent, FEC_ENET_MII); | ||
116 | ret = in_be32(&fecp->fec_mii_data) & 0xffff; | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | |||
121 | } | ||
122 | |||
123 | static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) | ||
124 | { | ||
125 | struct fec_info* fec = bus->priv; | ||
126 | fec_t *fecp = fec->fecp; | ||
127 | int i; | ||
128 | |||
129 | /* this must never happen */ | ||
130 | if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) | ||
131 | BUG(); | ||
132 | |||
133 | /* Add PHY address to register command. */ | ||
134 | out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); | ||
135 | |||
136 | for (i = 0; i < FEC_MII_LOOPS; i++) | ||
137 | if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) | ||
138 | break; | ||
139 | |||
140 | if (i < FEC_MII_LOOPS) | ||
141 | out_be32(&fecp->fec_ievent, FEC_ENET_MII); | ||
142 | |||
143 | return 0; | ||
144 | |||
145 | } | ||
146 | |||
147 | static int fs_enet_fec_mii_reset(struct mii_bus *bus) | ||
148 | { | ||
149 | /* nothing here - for now */ | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int __devinit fs_enet_fec_mdio_probe(struct device *dev) | ||
154 | { | ||
155 | struct platform_device *pdev = to_platform_device(dev); | ||
156 | struct fs_mii_fec_platform_info *pdata; | ||
157 | struct mii_bus *new_bus; | ||
158 | struct fec_info *fec; | ||
159 | int err = 0; | ||
160 | if (NULL == dev) | ||
161 | return -EINVAL; | ||
162 | new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); | ||
163 | |||
164 | if (NULL == new_bus) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL); | ||
168 | |||
169 | if (NULL == fec) | ||
170 | return -ENOMEM; | ||
171 | |||
172 | new_bus->name = "FEC MII Bus", | ||
173 | new_bus->read = &fs_enet_fec_mii_read, | ||
174 | new_bus->write = &fs_enet_fec_mii_write, | ||
175 | new_bus->reset = &fs_enet_fec_mii_reset, | ||
176 | new_bus->id = pdev->id; | ||
177 | |||
178 | pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data; | ||
179 | |||
180 | if (NULL == pdata) { | ||
181 | printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id); | ||
182 | return -ENODEV; | ||
183 | } | ||
184 | |||
185 | /*set up workspace*/ | ||
186 | |||
187 | fs_mii_fec_init(fec, pdata); | ||
188 | new_bus->priv = fec; | ||
189 | |||
190 | new_bus->irq = pdata->irq; | ||
191 | |||
192 | new_bus->dev = dev; | ||
193 | dev_set_drvdata(dev, new_bus); | ||
194 | |||
195 | err = mdiobus_register(new_bus); | ||
196 | |||
197 | if (0 != err) { | ||
198 | printk (KERN_ERR "%s: Cannot register as MDIO bus\n", | ||
199 | new_bus->name); | ||
200 | goto bus_register_fail; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | |||
205 | bus_register_fail: | ||
206 | kfree(new_bus); | ||
207 | |||
208 | return err; | ||
209 | } | ||
210 | |||
211 | |||
212 | static int fs_enet_fec_mdio_remove(struct device *dev) | ||
213 | { | ||
214 | struct mii_bus *bus = dev_get_drvdata(dev); | ||
215 | |||
216 | mdiobus_unregister(bus); | ||
217 | |||
218 | dev_set_drvdata(dev, NULL); | ||
219 | kfree(bus->priv); | ||
220 | |||
221 | bus->priv = NULL; | ||
222 | kfree(bus); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static struct device_driver fs_enet_fec_mdio_driver = { | ||
228 | .name = "fsl-cpm-fec-mdio", | ||
229 | .bus = &platform_bus_type, | ||
230 | .probe = fs_enet_fec_mdio_probe, | ||
231 | .remove = fs_enet_fec_mdio_remove, | ||
232 | }; | ||
233 | |||
234 | int fs_enet_mdio_fec_init(void) | ||
235 | { | ||
236 | return driver_register(&fs_enet_fec_mdio_driver); | ||
237 | } | ||
238 | |||
239 | void fs_enet_mdio_fec_exit(void) | ||
240 | { | ||
241 | driver_unregister(&fs_enet_fec_mdio_driver); | ||
242 | } | ||
243 | |||
diff --git a/drivers/net/fs_enet/mii-fixed.c b/drivers/net/fs_enet/mii-fixed.c deleted file mode 100644 index b3e192d612e5..000000000000 --- a/drivers/net/fs_enet/mii-fixed.c +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | /* | ||
2 | * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. | ||
3 | * | ||
4 | * Copyright (c) 2003 Intracom S.A. | ||
5 | * by Pantelis Antoniou <panto@intracom.gr> | ||
6 | * | ||
7 | * 2005 (c) MontaVista Software, Inc. | ||
8 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
9 | * | ||
10 | * This file is licensed under the terms of the GNU General Public License | ||
11 | * version 2. This program is licensed "as is" without any warranty of any | ||
12 | * kind, whether express or implied. | ||
13 | */ | ||
14 | |||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/ptrace.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/skbuff.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/mii.h> | ||
35 | #include <linux/ethtool.h> | ||
36 | #include <linux/bitops.h> | ||
37 | |||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/uaccess.h> | ||
41 | |||
42 | #include "fs_enet.h" | ||
43 | |||
44 | static const u16 mii_regs[7] = { | ||
45 | 0x3100, | ||
46 | 0x786d, | ||
47 | 0x0fff, | ||
48 | 0x0fff, | ||
49 | 0x01e1, | ||
50 | 0x45e1, | ||
51 | 0x0003, | ||
52 | }; | ||
53 | |||
54 | static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) | ||
55 | { | ||
56 | int ret = 0; | ||
57 | |||
58 | if ((unsigned int)location >= ARRAY_SIZE(mii_regs)) | ||
59 | return -1; | ||
60 | |||
61 | if (location != 5) | ||
62 | ret = mii_regs[location]; | ||
63 | else | ||
64 | ret = bus->fixed.lpa; | ||
65 | |||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) | ||
70 | { | ||
71 | /* do nothing */ | ||
72 | } | ||
73 | |||
74 | int fs_mii_fixed_init(struct fs_enet_mii_bus *bus) | ||
75 | { | ||
76 | const struct fs_mii_bus_info *bi = bus->bus_info; | ||
77 | |||
78 | bus->fixed.lpa = 0x45e1; /* default 100Mb, full duplex */ | ||
79 | |||
80 | /* if speed is fixed at 10Mb, remove 100Mb modes */ | ||
81 | if (bi->i.fixed.speed == 10) | ||
82 | bus->fixed.lpa &= ~LPA_100; | ||
83 | |||
84 | /* if duplex is half, remove full duplex modes */ | ||
85 | if (bi->i.fixed.duplex == 0) | ||
86 | bus->fixed.lpa &= ~LPA_DUPLEX; | ||
87 | |||
88 | bus->mii_read = mii_read; | ||
89 | bus->mii_write = mii_write; | ||
90 | |||
91 | return 0; | ||
92 | } | ||