aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet
diff options
context:
space:
mode:
authorVitaly Bordug <vbordug@ru.mvista.com>2006-08-15 02:00:30 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-19 17:44:31 -0400
commit5b4b8454344a0391bb0f69fda0f4ec8e1f0d2fed (patch)
treea5e662cdc03d319e56a277281dcde754150276f4 /drivers/net/fs_enet
parent11b0bacd717c285c94dbb56505a28434b34f0639 (diff)
[PATCH] FS_ENET: use PAL for mii management
This patch should update the fs_enet infrastructure to utilize Phy Abstraction Layer subsystem. Along with the above, there are apparent bugfixes, overhaul and improvements. Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/fs_enet')
-rw-r--r--drivers/net/fs_enet/Makefile6
-rw-r--r--drivers/net/fs_enet/fec.h42
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c207
-rw-r--r--drivers/net/fs_enet/fs_enet-mii.c505
-rw-r--r--drivers/net/fs_enet/fs_enet.h40
-rw-r--r--drivers/net/fs_enet/mac-fcc.c32
-rw-r--r--drivers/net/fs_enet/mac-fec.c142
-rw-r--r--drivers/net/fs_enet/mac-scc.c4
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c448
-rw-r--r--drivers/net/fs_enet/mii-fec.c243
-rw-r--r--drivers/net/fs_enet/mii-fixed.c91
11 files changed, 711 insertions, 1049 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
5obj-$(CONFIG_FS_ENET) += fs_enet.o 5obj-$(CONFIG_FS_ENET) += fs_enet.o
6 6
7obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o 7obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
8obj-$(CONFIG_8260) += mac-fcc.o 8obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
9 9
10fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o 10fs_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 f6abff5846b3..df62506a1787 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -37,6 +37,7 @@
37#include <linux/bitops.h> 37#include <linux/bitops.h>
38#include <linux/fs.h> 38#include <linux/fs.h>
39#include <linux/platform_device.h> 39#include <linux/platform_device.h>
40#include <linux/phy.h>
40 41
41#include <linux/vmalloc.h> 42#include <linux/vmalloc.h>
42#include <asm/pgtable.h> 43#include <asm/pgtable.h>
@@ -682,35 +683,6 @@ static void fs_free_irq(struct net_device *dev, int irq)
682 (*fep->ops->post_free_irq)(dev, irq); 683 (*fep->ops->post_free_irq)(dev, irq);
683} 684}
684 685
685/**********************************************************************************/
686
687/* This interrupt occurs when the PHY detects a link change. */
688static irqreturn_t
689fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
690{
691 struct net_device *dev = dev_id;
692 struct fs_enet_private *fep;
693 const struct fs_platform_info *fpi;
694
695 fep = netdev_priv(dev);
696 fpi = fep->fpi;
697
698 /*
699 * Acknowledge the interrupt if possible. If we have not
700 * found the PHY yet we can't process or acknowledge the
701 * interrupt now. Instead we ignore this interrupt for now,
702 * which we can do since it is edge triggered. It will be
703 * acknowledged later by fs_enet_open().
704 */
705 if (!fep->phy)
706 return IRQ_NONE;
707
708 fs_mii_ack_int(dev);
709 fs_mii_link_status_change_check(dev, 0);
710
711 return IRQ_HANDLED;
712}
713
714static void fs_timeout(struct net_device *dev) 686static void fs_timeout(struct net_device *dev)
715{ 687{
716 struct fs_enet_private *fep = netdev_priv(dev); 688 struct fs_enet_private *fep = netdev_priv(dev);
@@ -722,10 +694,13 @@ static void fs_timeout(struct net_device *dev)
722 spin_lock_irqsave(&fep->lock, flags); 694 spin_lock_irqsave(&fep->lock, flags);
723 695
724 if (dev->flags & IFF_UP) { 696 if (dev->flags & IFF_UP) {
697 phy_stop(fep->phydev);
725 (*fep->ops->stop)(dev); 698 (*fep->ops->stop)(dev);
726 (*fep->ops->restart)(dev); 699 (*fep->ops->restart)(dev);
700 phy_start(fep->phydev);
727 } 701 }
728 702
703 phy_start(fep->phydev);
729 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);
730 spin_unlock_irqrestore(&fep->lock, flags); 705 spin_unlock_irqrestore(&fep->lock, flags);
731 706
@@ -733,35 +708,112 @@ static void fs_timeout(struct net_device *dev)
733 netif_wake_queue(dev); 708 netif_wake_queue(dev);
734} 709}
735 710
711/*-----------------------------------------------------------------------------
712 * generic link-change handler - should be sufficient for most cases
713 *-----------------------------------------------------------------------------*/
714static 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
758static 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
773static 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
736static int fs_enet_open(struct net_device *dev) 798static int fs_enet_open(struct net_device *dev)
737{ 799{
738 struct fs_enet_private *fep = netdev_priv(dev); 800 struct fs_enet_private *fep = netdev_priv(dev);
739 const struct fs_platform_info *fpi = fep->fpi;
740 int r; 801 int r;
802 int err;
741 803
742 /* Install our interrupt handler. */ 804 /* Install our interrupt handler. */
743 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);
744 if (r != 0) { 806 if (r != 0) {
745 printk(KERN_ERR DRV_MODULE_NAME 807 printk(KERN_ERR DRV_MODULE_NAME
746 ": %s Could not allocate FEC IRQ!", dev->name); 808 ": %s Could not allocate FS_ENET IRQ!", dev->name);
747 return -EINVAL; 809 return -EINVAL;
748 } 810 }
749 811
750 /* Install our phy interrupt handler */ 812 err = fs_init_phy(dev);
751 if (fpi->phy_irq != -1) { 813 if(err)
752 814 return err;
753 r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
754 if (r != 0) {
755 printk(KERN_ERR DRV_MODULE_NAME
756 ": %s Could not allocate PHY IRQ!", dev->name);
757 fs_free_irq(dev, fep->interrupt);
758 return -EINVAL;
759 }
760 }
761 815
762 fs_mii_startup(dev); 816 phy_start(fep->phydev);
763 netif_carrier_off(dev);
764 fs_mii_link_status_change_check(dev, 1);
765 817
766 return 0; 818 return 0;
767} 819}
@@ -769,20 +821,19 @@ static int fs_enet_open(struct net_device *dev)
769static int fs_enet_close(struct net_device *dev) 821static int fs_enet_close(struct net_device *dev)
770{ 822{
771 struct fs_enet_private *fep = netdev_priv(dev); 823 struct fs_enet_private *fep = netdev_priv(dev);
772 const struct fs_platform_info *fpi = fep->fpi;
773 unsigned long flags; 824 unsigned long flags;
774 825
775 netif_stop_queue(dev); 826 netif_stop_queue(dev);
776 netif_carrier_off(dev); 827 netif_carrier_off(dev);
777 fs_mii_shutdown(dev); 828 phy_stop(fep->phydev);
778 829
779 spin_lock_irqsave(&fep->lock, flags); 830 spin_lock_irqsave(&fep->lock, flags);
780 (*fep->ops->stop)(dev); 831 (*fep->ops->stop)(dev);
781 spin_unlock_irqrestore(&fep->lock, flags); 832 spin_unlock_irqrestore(&fep->lock, flags);
782 833
783 /* release any irqs */ 834 /* release any irqs */
784 if (fpi->phy_irq != -1) 835 phy_disconnect(fep->phydev);
785 fs_free_irq(dev, fpi->phy_irq); 836 fep->phydev = NULL;
786 fs_free_irq(dev, fep->interrupt); 837 fs_free_irq(dev, fep->interrupt);
787 838
788 return 0; 839 return 0;
@@ -830,33 +881,19 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
830static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 881static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
831{ 882{
832 struct fs_enet_private *fep = netdev_priv(dev); 883 struct fs_enet_private *fep = netdev_priv(dev);
833 unsigned long flags; 884 return phy_ethtool_gset(fep->phydev, cmd);
834 int rc;
835
836 spin_lock_irqsave(&fep->lock, flags);
837 rc = mii_ethtool_gset(&fep->mii_if, cmd);
838 spin_unlock_irqrestore(&fep->lock, flags);
839
840 return rc;
841} 885}
842 886
843static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 887static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
844{ 888{
845 struct fs_enet_private *fep = netdev_priv(dev); 889 struct fs_enet_private *fep = netdev_priv(dev);
846 unsigned long flags; 890 phy_ethtool_sset(fep->phydev, cmd);
847 int rc; 891 return 0;
848
849 spin_lock_irqsave(&fep->lock, flags);
850 rc = mii_ethtool_sset(&fep->mii_if, cmd);
851 spin_unlock_irqrestore(&fep->lock, flags);
852
853 return rc;
854} 892}
855 893
856static int fs_nway_reset(struct net_device *dev) 894static int fs_nway_reset(struct net_device *dev)
857{ 895{
858 struct fs_enet_private *fep = netdev_priv(dev); 896 return 0;
859 return mii_nway_restart(&fep->mii_if);
860} 897}
861 898
862static u32 fs_get_msglevel(struct net_device *dev) 899static u32 fs_get_msglevel(struct net_device *dev)
@@ -898,7 +935,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
898 return -EINVAL; 935 return -EINVAL;
899 936
900 spin_lock_irqsave(&fep->lock, flags); 937 spin_lock_irqsave(&fep->lock, flags);
901 rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL); 938 rc = phy_mii_ioctl(fep->phydev, mii, cmd);
902 spin_unlock_irqrestore(&fep->lock, flags); 939 spin_unlock_irqrestore(&fep->lock, flags);
903 return rc; 940 return rc;
904} 941}
@@ -1030,12 +1067,6 @@ static struct net_device *fs_init_instance(struct device *dev,
1030 } 1067 }
1031 registered = 1; 1068 registered = 1;
1032 1069
1033 err = fs_mii_connect(ndev);
1034 if (err != 0) {
1035 printk(KERN_ERR DRV_MODULE_NAME
1036 ": %s fs_mii_connect failed.\n", ndev->name);
1037 goto err;
1038 }
1039 1070
1040 return ndev; 1071 return ndev;
1041 1072
@@ -1073,8 +1104,6 @@ static int fs_cleanup_instance(struct net_device *ndev)
1073 1104
1074 fpi = fep->fpi; 1105 fpi = fep->fpi;
1075 1106
1076 fs_mii_disconnect(ndev);
1077
1078 unregister_netdev(ndev); 1107 unregister_netdev(ndev);
1079 1108
1080 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),
@@ -1196,17 +1225,39 @@ static int __init fs_init(void)
1196 r = setup_immap(); 1225 r = setup_immap();
1197 if (r != 0) 1226 if (r != 0)
1198 return r; 1227 return r;
1199 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);
1200 if (r != 0) 1239 if (r != 0)
1201 goto err; 1240 goto err;
1241#endif
1202 1242
1203 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);
1204 if (r != 0) 1252 if (r != 0)
1205 goto err; 1253 goto err;
1254#endif
1206 1255
1256#ifdef CONFIG_FS_ENET_HAS_SCC
1207 r = driver_register(&fs_enet_scc_driver); 1257 r = driver_register(&fs_enet_scc_driver);
1208 if (r != 0) 1258 if (r != 0)
1209 goto err; 1259 goto err;
1260#endif
1210 1261
1211 return 0; 1262 return 0;
1212err: 1263err:
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 b7e6e21725cb..000000000000
--- a/drivers/net/fs_enet/fs_enet-mii.c
+++ /dev/null
@@ -1,505 +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/module.h>
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/string.h>
24#include <linux/ptrace.h>
25#include <linux/errno.h>
26#include <linux/ioport.h>
27#include <linux/slab.h>
28#include <linux/interrupt.h>
29#include <linux/pci.h>
30#include <linux/init.h>
31#include <linux/delay.h>
32#include <linux/netdevice.h>
33#include <linux/etherdevice.h>
34#include <linux/skbuff.h>
35#include <linux/spinlock.h>
36#include <linux/mii.h>
37#include <linux/ethtool.h>
38#include <linux/bitops.h>
39
40#include <asm/pgtable.h>
41#include <asm/irq.h>
42#include <asm/uaccess.h>
43
44#include "fs_enet.h"
45
46/*************************************************/
47
48/*
49 * Generic PHY support.
50 * Should work for all PHYs, but link change is detected by polling
51 */
52
53static void generic_timer_callback(unsigned long data)
54{
55 struct net_device *dev = (struct net_device *)data;
56 struct fs_enet_private *fep = netdev_priv(dev);
57
58 fep->phy_timer_list.expires = jiffies + HZ / 2;
59
60 add_timer(&fep->phy_timer_list);
61
62 fs_mii_link_status_change_check(dev, 0);
63}
64
65static void generic_startup(struct net_device *dev)
66{
67 struct fs_enet_private *fep = netdev_priv(dev);
68
69 fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
70 fep->phy_timer_list.data = (unsigned long)dev;
71 fep->phy_timer_list.function = generic_timer_callback;
72 add_timer(&fep->phy_timer_list);
73}
74
75static void generic_shutdown(struct net_device *dev)
76{
77 struct fs_enet_private *fep = netdev_priv(dev);
78
79 del_timer_sync(&fep->phy_timer_list);
80}
81
82/* ------------------------------------------------------------------------- */
83/* The Davicom DM9161 is used on the NETTA board */
84
85/* register definitions */
86
87#define MII_DM9161_ANAR 4 /* Aux. Config Register */
88#define MII_DM9161_ACR 16 /* Aux. Config Register */
89#define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */
90#define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */
91#define MII_DM9161_INTR 21 /* Interrupt Register */
92#define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */
93#define MII_DM9161_DISCR 23 /* Disconnect Counter Register */
94
95static void dm9161_startup(struct net_device *dev)
96{
97 struct fs_enet_private *fep = netdev_priv(dev);
98
99 fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
100 /* Start autonegotiation */
101 fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
102
103 set_current_state(TASK_UNINTERRUPTIBLE);
104 schedule_timeout(HZ*8);
105}
106
107static void dm9161_ack_int(struct net_device *dev)
108{
109 struct fs_enet_private *fep = netdev_priv(dev);
110
111 fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
112}
113
114static void dm9161_shutdown(struct net_device *dev)
115{
116 struct fs_enet_private *fep = netdev_priv(dev);
117
118 fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
119}
120
121/**********************************************************************************/
122
123static const struct phy_info phy_info[] = {
124 {
125 .id = 0x00181b88,
126 .name = "DM9161",
127 .startup = dm9161_startup,
128 .ack_int = dm9161_ack_int,
129 .shutdown = dm9161_shutdown,
130 }, {
131 .id = 0,
132 .name = "GENERIC",
133 .startup = generic_startup,
134 .shutdown = generic_shutdown,
135 },
136};
137
138/**********************************************************************************/
139
140static int phy_id_detect(struct net_device *dev)
141{
142 struct fs_enet_private *fep = netdev_priv(dev);
143 const struct fs_platform_info *fpi = fep->fpi;
144 struct fs_enet_mii_bus *bus = fep->mii_bus;
145 int i, r, start, end, phytype, physubtype;
146 const struct phy_info *phy;
147 int phy_hwid, phy_id;
148
149 phy_hwid = -1;
150 fep->phy = NULL;
151
152 /* auto-detect? */
153 if (fpi->phy_addr == -1) {
154 start = 1;
155 end = 32;
156 } else { /* direct */
157 start = fpi->phy_addr;
158 end = start + 1;
159 }
160
161 for (phy_id = start; phy_id < end; phy_id++) {
162 /* skip already used phy addresses on this bus */
163 if (bus->usage_map & (1 << phy_id))
164 continue;
165 r = fs_mii_read(dev, phy_id, MII_PHYSID1);
166 if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
167 continue;
168 r = fs_mii_read(dev, phy_id, MII_PHYSID2);
169 if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
170 continue;
171 phy_hwid = (phytype << 16) | physubtype;
172 if (phy_hwid != -1)
173 break;
174 }
175
176 if (phy_hwid == -1) {
177 printk(KERN_ERR DRV_MODULE_NAME
178 ": %s No PHY detected! range=0x%02x-0x%02x\n",
179 dev->name, start, end);
180 return -1;
181 }
182
183 for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
184 if (phy->id == (phy_hwid >> 4) || phy->id == 0)
185 break;
186
187 if (i >= ARRAY_SIZE(phy_info)) {
188 printk(KERN_ERR DRV_MODULE_NAME
189 ": %s PHY id 0x%08x is not supported!\n",
190 dev->name, phy_hwid);
191 return -1;
192 }
193
194 fep->phy = phy;
195
196 /* mark this address as used */
197 bus->usage_map |= (1 << phy_id);
198
199 printk(KERN_INFO DRV_MODULE_NAME
200 ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
201 dev->name, phy_id, fep->phy->name, phy_hwid,
202 fpi->phy_addr == -1 ? " (auto-detected)" : "");
203
204 return phy_id;
205}
206
207void fs_mii_startup(struct net_device *dev)
208{
209 struct fs_enet_private *fep = netdev_priv(dev);
210
211 if (fep->phy->startup)
212 (*fep->phy->startup) (dev);
213}
214
215void fs_mii_shutdown(struct net_device *dev)
216{
217 struct fs_enet_private *fep = netdev_priv(dev);
218
219 if (fep->phy->shutdown)
220 (*fep->phy->shutdown) (dev);
221}
222
223void fs_mii_ack_int(struct net_device *dev)
224{
225 struct fs_enet_private *fep = netdev_priv(dev);
226
227 if (fep->phy->ack_int)
228 (*fep->phy->ack_int) (dev);
229}
230
231#define MII_LINK 0x0001
232#define MII_HALF 0x0002
233#define MII_FULL 0x0004
234#define MII_BASE4 0x0008
235#define MII_10M 0x0010
236#define MII_100M 0x0020
237#define MII_1G 0x0040
238#define MII_10G 0x0080
239
240/* return full mii info at one gulp, with a usable form */
241static unsigned int mii_full_status(struct mii_if_info *mii)
242{
243 unsigned int status;
244 int bmsr, adv, lpa, neg;
245 struct fs_enet_private* fep = netdev_priv(mii->dev);
246
247 /* first, a dummy read, needed to latch some MII phys */
248 (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
249 bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
250
251 /* no link */
252 if ((bmsr & BMSR_LSTATUS) == 0)
253 return 0;
254
255 status = MII_LINK;
256
257 /* Lets look what ANEG says if it's supported - otherwize we shall
258 take the right values from the platform info*/
259 if(!mii->force_media) {
260 /* autoneg not completed; don't bother */
261 if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
262 return 0;
263
264 adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
265 lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
266
267 neg = lpa & adv;
268 } else {
269 neg = fep->fpi->bus_info->lpa;
270 }
271
272 if (neg & LPA_100FULL)
273 status |= MII_FULL | MII_100M;
274 else if (neg & LPA_100BASE4)
275 status |= MII_FULL | MII_BASE4 | MII_100M;
276 else if (neg & LPA_100HALF)
277 status |= MII_HALF | MII_100M;
278 else if (neg & LPA_10FULL)
279 status |= MII_FULL | MII_10M;
280 else
281 status |= MII_HALF | MII_10M;
282
283 return status;
284}
285
286void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
287{
288 struct fs_enet_private *fep = netdev_priv(dev);
289 struct mii_if_info *mii = &fep->mii_if;
290 unsigned int mii_status;
291 int ok_to_print, link, duplex, speed;
292 unsigned long flags;
293
294 ok_to_print = netif_msg_link(fep);
295
296 mii_status = mii_full_status(mii);
297
298 if (!init_media && mii_status == fep->last_mii_status)
299 return;
300
301 fep->last_mii_status = mii_status;
302
303 link = !!(mii_status & MII_LINK);
304 duplex = !!(mii_status & MII_FULL);
305 speed = (mii_status & MII_100M) ? 100 : 10;
306
307 if (link == 0) {
308 netif_carrier_off(mii->dev);
309 netif_stop_queue(dev);
310 if (!init_media) {
311 spin_lock_irqsave(&fep->lock, flags);
312 (*fep->ops->stop)(dev);
313 spin_unlock_irqrestore(&fep->lock, flags);
314 }
315
316 if (ok_to_print)
317 printk(KERN_INFO "%s: link down\n", mii->dev->name);
318
319 } else {
320
321 mii->full_duplex = duplex;
322
323 netif_carrier_on(mii->dev);
324
325 spin_lock_irqsave(&fep->lock, flags);
326 fep->duplex = duplex;
327 fep->speed = speed;
328 (*fep->ops->restart)(dev);
329 spin_unlock_irqrestore(&fep->lock, flags);
330
331 netif_start_queue(dev);
332
333 if (ok_to_print)
334 printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
335 dev->name, speed, duplex ? "full" : "half");
336 }
337}
338
339/**********************************************************************************/
340
341int fs_mii_read(struct net_device *dev, int phy_id, int location)
342{
343 struct fs_enet_private *fep = netdev_priv(dev);
344 struct fs_enet_mii_bus *bus = fep->mii_bus;
345
346 unsigned long flags;
347 int ret;
348
349 spin_lock_irqsave(&bus->mii_lock, flags);
350 ret = (*bus->mii_read)(bus, phy_id, location);
351 spin_unlock_irqrestore(&bus->mii_lock, flags);
352
353 return ret;
354}
355
356void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
357{
358 struct fs_enet_private *fep = netdev_priv(dev);
359 struct fs_enet_mii_bus *bus = fep->mii_bus;
360 unsigned long flags;
361
362 spin_lock_irqsave(&bus->mii_lock, flags);
363 (*bus->mii_write)(bus, phy_id, location, value);
364 spin_unlock_irqrestore(&bus->mii_lock, flags);
365}
366
367/*****************************************************************************/
368
369/* list of all registered mii buses */
370static LIST_HEAD(fs_mii_bus_list);
371
372static struct fs_enet_mii_bus *lookup_bus(int method, int id)
373{
374 struct list_head *ptr;
375 struct fs_enet_mii_bus *bus;
376
377 list_for_each(ptr, &fs_mii_bus_list) {
378 bus = list_entry(ptr, struct fs_enet_mii_bus, list);
379 if (bus->bus_info->method == method &&
380 bus->bus_info->id == id)
381 return bus;
382 }
383 return NULL;
384}
385
386static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
387{
388 struct fs_enet_mii_bus *bus;
389 int ret = 0;
390
391 bus = kmalloc(sizeof(*bus), GFP_KERNEL);
392 if (bus == NULL) {
393 ret = -ENOMEM;
394 goto err;
395 }
396 memset(bus, 0, sizeof(*bus));
397 spin_lock_init(&bus->mii_lock);
398 bus->bus_info = bi;
399 bus->refs = 0;
400 bus->usage_map = 0;
401
402 /* perform initialization */
403 switch (bi->method) {
404
405 case fsmii_fixed:
406 ret = fs_mii_fixed_init(bus);
407 if (ret != 0)
408 goto err;
409 break;
410
411 case fsmii_bitbang:
412 ret = fs_mii_bitbang_init(bus);
413 if (ret != 0)
414 goto err;
415 break;
416#ifdef CONFIG_FS_ENET_HAS_FEC
417 case fsmii_fec:
418 ret = fs_mii_fec_init(bus);
419 if (ret != 0)
420 goto err;
421 break;
422#endif
423 default:
424 ret = -EINVAL;
425 goto err;
426 }
427
428 list_add(&bus->list, &fs_mii_bus_list);
429
430 return bus;
431
432err:
433 kfree(bus);
434 return ERR_PTR(ret);
435}
436
437static void destroy_bus(struct fs_enet_mii_bus *bus)
438{
439 /* remove from bus list */
440 list_del(&bus->list);
441
442 /* nothing more needed */
443 kfree(bus);
444}
445
446int fs_mii_connect(struct net_device *dev)
447{
448 struct fs_enet_private *fep = netdev_priv(dev);
449 const struct fs_platform_info *fpi = fep->fpi;
450 struct fs_enet_mii_bus *bus = NULL;
451
452 /* check method validity */
453 switch (fpi->bus_info->method) {
454 case fsmii_fixed:
455 case fsmii_bitbang:
456 break;
457#ifdef CONFIG_FS_ENET_HAS_FEC
458 case fsmii_fec:
459 break;
460#endif
461 default:
462 printk(KERN_ERR DRV_MODULE_NAME
463 ": %s Unknown MII bus method (%d)!\n",
464 dev->name, fpi->bus_info->method);
465 return -EINVAL;
466 }
467
468 bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
469
470 /* if not found create new bus */
471 if (bus == NULL) {
472 bus = create_bus(fpi->bus_info);
473 if (IS_ERR(bus)) {
474 printk(KERN_ERR DRV_MODULE_NAME
475 ": %s MII bus creation failure!\n", dev->name);
476 return PTR_ERR(bus);
477 }
478 }
479
480 bus->refs++;
481
482 fep->mii_bus = bus;
483
484 fep->mii_if.dev = dev;
485 fep->mii_if.phy_id_mask = 0x1f;
486 fep->mii_if.reg_num_mask = 0x1f;
487 fep->mii_if.mdio_read = fs_mii_read;
488 fep->mii_if.mdio_write = fs_mii_write;
489 fep->mii_if.force_media = fpi->bus_info->disable_aneg;
490 fep->mii_if.phy_id = phy_id_detect(dev);
491
492 return 0;
493}
494
495void fs_mii_disconnect(struct net_device *dev)
496{
497 struct fs_enet_private *fep = netdev_priv(dev);
498 struct fs_enet_mii_bus *bus = NULL;
499
500 bus = fep->mii_bus;
501 fep->mii_bus = NULL;
502
503 if (--bus->refs <= 0)
504 destroy_bus(bus);
505}
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e7ec96c964a9..95022c005f75 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -5,6 +5,7 @@
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>
8 9
9#include <linux/fs_enet_pd.h> 10#include <linux/fs_enet_pd.h>
10 11
@@ -12,12 +13,30 @@
12 13
13#ifdef CONFIG_CPM1 14#ifdef CONFIG_CPM1
14#include <asm/commproc.h> 15#include <asm/commproc.h>
16
17struct fec_info {
18 fec_t* fecp;
19 u32 mii_speed;
20};
15#endif 21#endif
16 22
17#ifdef CONFIG_CPM2 23#ifdef CONFIG_CPM2
18#include <asm/cpm2.h> 24#include <asm/cpm2.h>
19#endif 25#endif
20 26
27/* This is used to operate with pins.
28 Note that the actual port size may
29 be different; cpm(s) handle it OK */
30struct bb_info {
31 u8 mdio_dat_msk;
32 u8 mdio_dir_msk;
33 u8 *mdio_dir;
34 u8 *mdio_dat;
35 u8 mdc_msk;
36 u8 *mdc_dat;
37 int delay;
38};
39
21/* hw driver ops */ 40/* hw driver ops */
22struct fs_ops { 41struct fs_ops {
23 int (*setup_data)(struct net_device *dev); 42 int (*setup_data)(struct net_device *dev);
@@ -25,6 +44,7 @@ struct fs_ops {
25 void (*free_bd)(struct net_device *dev); 44 void (*free_bd)(struct net_device *dev);
26 void (*cleanup_data)(struct net_device *dev); 45 void (*cleanup_data)(struct net_device *dev);
27 void (*set_multicast_list)(struct net_device *dev); 46 void (*set_multicast_list)(struct net_device *dev);
47 void (*adjust_link)(struct net_device *dev);
28 void (*restart)(struct net_device *dev); 48 void (*restart)(struct net_device *dev);
29 void (*stop)(struct net_device *dev); 49 void (*stop)(struct net_device *dev);
30 void (*pre_request_irq)(struct net_device *dev, int irq); 50 void (*pre_request_irq)(struct net_device *dev, int irq);
@@ -100,10 +120,6 @@ struct fs_enet_mii_bus {
100 }; 120 };
101}; 121};
102 122
103int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
104int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
105int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
106
107struct fs_enet_private { 123struct fs_enet_private {
108 struct device *dev; /* pointer back to the device (must be initialized first) */ 124 struct device *dev; /* pointer back to the device (must be initialized first) */
109 spinlock_t lock; /* during all ops except TX pckt processing */ 125 spinlock_t lock; /* during all ops except TX pckt processing */
@@ -130,7 +146,8 @@ struct fs_enet_private {
130 struct fs_enet_mii_bus *mii_bus; 146 struct fs_enet_mii_bus *mii_bus;
131 int interrupt; 147 int interrupt;
132 148
133 int duplex, speed; /* current settings */ 149 struct phy_device *phydev;
150 int oldduplex, oldspeed, oldlink; /* current settings */
134 151
135 /* event masks */ 152 /* event masks */
136 u32 ev_napi_rx; /* mask of NAPI rx events */ 153 u32 ev_napi_rx; /* mask of NAPI rx events */
@@ -168,15 +185,9 @@ struct fs_enet_private {
168}; 185};
169 186
170/***************************************************************************/ 187/***************************************************************************/
171 188int fs_enet_mdio_bb_init(void);
172int fs_mii_read(struct net_device *dev, int phy_id, int location); 189int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
173void fs_mii_write(struct net_device *dev, int phy_id, int location, int value); 190int fs_enet_mdio_fec_init(void);
174
175void fs_mii_startup(struct net_device *dev);
176void fs_mii_shutdown(struct net_device *dev);
177void fs_mii_ack_int(struct net_device *dev);
178
179void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
180 191
181void fs_init_bds(struct net_device *dev); 192void fs_init_bds(struct net_device *dev);
182void fs_cleanup_bds(struct net_device *dev); 193void fs_cleanup_bds(struct net_device *dev);
@@ -194,7 +205,6 @@ int fs_enet_platform_init(void);
194void fs_enet_platform_cleanup(void); 205void fs_enet_platform_cleanup(void);
195 206
196/***************************************************************************/ 207/***************************************************************************/
197
198/* buffer descriptor access macros */ 208/* buffer descriptor access macros */
199 209
200/* access macros */ 210/* access macros */
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 64e20982c1fe..1ff2597b8495 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -34,6 +34,7 @@
34#include <linux/bitops.h> 34#include <linux/bitops.h>
35#include <linux/fs.h> 35#include <linux/fs.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/phy.h>
37 38
38#include <asm/immap_cpm2.h> 39#include <asm/immap_cpm2.h>
39#include <asm/mpc8260.h> 40#include <asm/mpc8260.h>
@@ -122,22 +123,32 @@ static int do_pd_setup(struct fs_enet_private *fep)
122 123
123 /* Attach the memory for the FCC Parameter RAM */ 124 /* Attach the memory for the FCC Parameter RAM */
124 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram"); 125 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
125 fep->fcc.ep = (void *)r->start; 126 fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1);
126
127 if (fep->fcc.ep == NULL) 127 if (fep->fcc.ep == NULL)
128 return -EINVAL; 128 return -EINVAL;
129 129
130 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs"); 130 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
131 fep->fcc.fccp = (void *)r->start; 131 fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1);
132
133 if (fep->fcc.fccp == NULL) 132 if (fep->fcc.fccp == NULL)
134 return -EINVAL; 133 return -EINVAL;
135 134
136 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 }
137 144
138 if (fep->fcc.fcccp == NULL) 145 if (fep->fcc.fcccp == NULL)
139 return -EINVAL; 146 return -EINVAL;
140 147
148 fep->fcc.mem = (void *)fep->fpi->mem_offset;
149 if (fep->fcc.mem == NULL)
150 return -EINVAL;
151
141 return 0; 152 return 0;
142} 153}
143 154
@@ -155,8 +166,6 @@ static int setup_data(struct net_device *dev)
155 if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */ 166 if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
156 return -EINVAL; 167 return -EINVAL;
157 168
158 fep->fcc.mem = (void *)fpi->mem_offset;
159
160 if (do_pd_setup(fep) != 0) 169 if (do_pd_setup(fep) != 0)
161 return -EINVAL; 170 return -EINVAL;
162 171
@@ -394,7 +403,7 @@ static void restart(struct net_device *dev)
394 403
395 /* adjust to speed (for RMII mode) */ 404 /* adjust to speed (for RMII mode) */
396 if (fpi->use_rmii) { 405 if (fpi->use_rmii) {
397 if (fep->speed == 100) 406 if (fep->phydev->speed == 100)
398 C8(fcccp, fcc_gfemr, 0x20); 407 C8(fcccp, fcc_gfemr, 0x20);
399 else 408 else
400 S8(fcccp, fcc_gfemr, 0x20); 409 S8(fcccp, fcc_gfemr, 0x20);
@@ -420,7 +429,7 @@ static void restart(struct net_device *dev)
420 S32(fccp, fcc_fpsmr, FCC_PSMR_RMII); 429 S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
421 430
422 /* adjust to duplex mode */ 431 /* adjust to duplex mode */
423 if (fep->duplex) 432 if (fep->phydev->duplex)
424 S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); 433 S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
425 else 434 else
426 C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); 435 C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
@@ -486,7 +495,10 @@ static void rx_bd_done(struct net_device *dev)
486 495
487static void tx_kickstart(struct net_device *dev) 496static void tx_kickstart(struct net_device *dev)
488{ 497{
489 /* nothing */ 498 struct fs_enet_private *fep = netdev_priv(dev);
499 fcc_t *fccp = fep->fcc.fccp;
500
501 S32(fccp, fcc_ftodr, 0x80);
490} 502}
491 503
492static u32 get_int_events(struct net_device *dev) 504static 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 e09547077529..c2c5fd419bd0 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -46,6 +46,7 @@
46#endif 46#endif
47 47
48#include "fs_enet.h" 48#include "fs_enet.h"
49#include "fec.h"
49 50
50/*************************************************/ 51/*************************************************/
51 52
@@ -75,50 +76,8 @@
75/* clear bits */ 76/* clear bits */
76#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))
77 78
78
79/* CRC polynomium used by the FEC for the multicast group filtering */
80#define FEC_CRC_POLY 0x04C11DB7
81
82#define FEC_MAX_MULTICAST_ADDRS 64
83
84/* Interrupt events/masks.
85*/
86#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */
87#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */
88#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */
89#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */
90#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */
91#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */
92#define FEC_ENET_RXF 0x02000000U /* Full frame received */
93#define FEC_ENET_RXB 0x01000000U /* A buffer was received */
94#define FEC_ENET_MII 0x00800000U /* MII interrupt */
95#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */
96
97#define FEC_ECNTRL_PINMUX 0x00000004
98#define FEC_ECNTRL_ETHER_EN 0x00000002
99#define FEC_ECNTRL_RESET 0x00000001
100
101#define FEC_RCNTRL_BC_REJ 0x00000010
102#define FEC_RCNTRL_PROM 0x00000008
103#define FEC_RCNTRL_MII_MODE 0x00000004
104#define FEC_RCNTRL_DRT 0x00000002
105#define FEC_RCNTRL_LOOP 0x00000001
106
107#define FEC_TCNTRL_FDEN 0x00000004
108#define FEC_TCNTRL_HBC 0x00000002
109#define FEC_TCNTRL_GTS 0x00000001
110
111
112/* Make MII read/write commands for the FEC.
113*/
114#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
115#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
116#define mk_mii_end 0
117
118#define FEC_MII_LOOPS 10000
119
120/* 79/*
121 * Delay to wait for FEC reset command to complete (in us) 80 * Delay to wait for FEC reset command to complete (in us)
122 */ 81 */
123#define FEC_RESET_DELAY 50 82#define FEC_RESET_DELAY 50
124 83
@@ -303,13 +262,15 @@ static void restart(struct net_device *dev)
303 int r; 262 int r;
304 u32 addrhi, addrlo; 263 u32 addrhi, addrlo;
305 264
265 struct mii_bus* mii = fep->phydev->bus;
266 struct fec_info* fec_inf = mii->priv;
267
306 r = whack_reset(fep->fec.fecp); 268 r = whack_reset(fep->fec.fecp);
307 if (r != 0) 269 if (r != 0)
308 printk(KERN_ERR DRV_MODULE_NAME 270 printk(KERN_ERR DRV_MODULE_NAME
309 ": %s FEC Reset FAILED!\n", dev->name); 271 ": %s FEC Reset FAILED!\n", dev->name);
310
311 /* 272 /*
312 * Set station address. 273 * Set station address.
313 */ 274 */
314 addrhi = ((u32) dev->dev_addr[0] << 24) | 275 addrhi = ((u32) dev->dev_addr[0] << 24) |
315 ((u32) dev->dev_addr[1] << 16) | 276 ((u32) dev->dev_addr[1] << 16) |
@@ -350,12 +311,12 @@ static void restart(struct net_device *dev)
350 FW(fecp, fun_code, 0x78000000); 311 FW(fecp, fun_code, 0x78000000);
351 312
352 /* 313 /*
353 * Set MII speed. 314 * Set MII speed.
354 */ 315 */
355 FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed); 316 FW(fecp, mii_speed, fec_inf->mii_speed);
356 317
357 /* 318 /*
358 * Clear any outstanding interrupt. 319 * Clear any outstanding interrupt.
359 */ 320 */
360 FW(fecp, ievent, 0xffc0); 321 FW(fecp, ievent, 0xffc0);
361 FW(fecp, ivec, (fep->interrupt / 2) << 29); 322 FW(fecp, ivec, (fep->interrupt / 2) << 29);
@@ -390,11 +351,12 @@ static void restart(struct net_device *dev)
390 } 351 }
391#endif 352#endif
392 353
354
393 FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ 355 FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
394 /* 356 /*
395 * adjust to duplex mode 357 * adjust to duplex mode
396 */ 358 */
397 if (fep->duplex) { 359 if (fep->phydev->duplex) {
398 FC(fecp, r_cntrl, FEC_RCNTRL_DRT); 360 FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
399 FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ 361 FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
400 } else { 362 } else {
@@ -418,9 +380,11 @@ static void restart(struct net_device *dev)
418static void stop(struct net_device *dev) 380static void stop(struct net_device *dev)
419{ 381{
420 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;
421 fec_t *fecp = fep->fec.fecp; 384 fec_t *fecp = fep->fec.fecp;
422 struct fs_enet_mii_bus *bus = fep->mii_bus; 385
423 const struct fs_mii_bus_info *bi = bus->bus_info; 386 struct fec_info* feci= fep->phydev->bus->priv;
387
424 int i; 388 int i;
425 389
426 if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) 390 if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
@@ -444,11 +408,11 @@ static void stop(struct net_device *dev)
444 fs_cleanup_bds(dev); 408 fs_cleanup_bds(dev);
445 409
446 /* shut down FEC1? that's where the mii bus is */ 410 /* shut down FEC1? that's where the mii bus is */
447 if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) { 411 if (fpi->has_phy) {
448 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ 412 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
449 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); 413 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
450 FW(fecp, ievent, FEC_ENET_MII); 414 FW(fecp, ievent, FEC_ENET_MII);
451 FW(fecp, mii_speed, bus->fec.mii_speed); 415 FW(fecp, mii_speed, feci->mii_speed);
452 } 416 }
453} 417}
454 418
@@ -583,73 +547,3 @@ const struct fs_ops fs_fec_ops = {
583 .free_bd = free_bd, 547 .free_bd = free_bd,
584}; 548};
585 549
586/***********************************************************************/
587
588static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
589{
590 fec_t *fecp = bus->fec.fecp;
591 int i, ret = -1;
592
593 if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
594 BUG();
595
596 /* Add PHY address to register command. */
597 FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
598
599 for (i = 0; i < FEC_MII_LOOPS; i++)
600 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
601 break;
602
603 if (i < FEC_MII_LOOPS) {
604 FW(fecp, ievent, FEC_ENET_MII);
605 ret = FR(fecp, mii_data) & 0xffff;
606 }
607
608 return ret;
609}
610
611static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
612{
613 fec_t *fecp = bus->fec.fecp;
614 int i;
615
616 /* this must never happen */
617 if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
618 BUG();
619
620 /* Add PHY address to register command. */
621 FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
622
623 for (i = 0; i < FEC_MII_LOOPS; i++)
624 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
625 break;
626
627 if (i < FEC_MII_LOOPS)
628 FW(fecp, ievent, FEC_ENET_MII);
629}
630
631int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
632{
633 bd_t *bd = (bd_t *)__res;
634 const struct fs_mii_bus_info *bi = bus->bus_info;
635 fec_t *fecp;
636
637 if (bi->id != 0)
638 return -1;
639
640 bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
641 bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
642 & 0x3F) << 1;
643
644 fecp = bus->fec.fecp;
645
646 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
647 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
648 FW(fecp, ievent, FEC_ENET_MII);
649 FW(fecp, mii_speed, bus->fec.mii_speed);
650
651 bus->mii_read = mii_read;
652 bus->mii_write = mii_write;
653
654 return 0;
655}
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index eaa24fab645f..95ec5872c507 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -369,7 +369,7 @@ static void restart(struct net_device *dev)
369 W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22); 369 W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
370 370
371 /* Set full duplex mode if needed */ 371 /* Set full duplex mode if needed */
372 if (fep->duplex) 372 if (fep->phydev->duplex)
373 S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE); 373 S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
374 374
375 S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); 375 S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
@@ -500,6 +500,8 @@ static void tx_restart(struct net_device *dev)
500 scc_cr_cmd(fep, CPM_CR_RESTART_TX); 500 scc_cr_cmd(fep, CPM_CR_RESTART_TX);
501} 501}
502 502
503
504
503/*************************************************************************/ 505/*************************************************************************/
504 506
505const struct fs_ops fs_scc_ops = { 507const 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 48f9cf83ab6f..0b9b8b5c847c 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -33,6 +33,7 @@
33#include <linux/mii.h> 33#include <linux/mii.h>
34#include <linux/ethtool.h> 34#include <linux/ethtool.h>
35#include <linux/bitops.h> 35#include <linux/bitops.h>
36#include <linux/platform_device.h>
36 37
37#include <asm/pgtable.h> 38#include <asm/pgtable.h>
38#include <asm/irq.h> 39#include <asm/irq.h>
@@ -40,129 +41,25 @@
40 41
41#include "fs_enet.h" 42#include "fs_enet.h"
42 43
43#ifdef CONFIG_8xx 44static int bitbang_prep_bit(u8 **datp, u8 *mskp,
44static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) 45 struct fs_mii_bit *mii_bit)
45{ 46{
46 immap_t *im = (immap_t *)fs_enet_immap; 47 void *dat;
47 void *dir, *dat, *ppar;
48 int adv; 48 int adv;
49 u8 msk; 49 u8 msk;
50 50
51 switch (port) { 51 dat = (void*) mii_bit->offset;
52 case fsiop_porta:
53 dir = &im->im_ioport.iop_padir;
54 dat = &im->im_ioport.iop_padat;
55 ppar = &im->im_ioport.iop_papar;
56 break;
57
58 case fsiop_portb:
59 dir = &im->im_cpm.cp_pbdir;
60 dat = &im->im_cpm.cp_pbdat;
61 ppar = &im->im_cpm.cp_pbpar;
62 break;
63
64 case fsiop_portc:
65 dir = &im->im_ioport.iop_pcdir;
66 dat = &im->im_ioport.iop_pcdat;
67 ppar = &im->im_ioport.iop_pcpar;
68 break;
69
70 case fsiop_portd:
71 dir = &im->im_ioport.iop_pddir;
72 dat = &im->im_ioport.iop_pddat;
73 ppar = &im->im_ioport.iop_pdpar;
74 break;
75
76 case fsiop_porte:
77 dir = &im->im_cpm.cp_pedir;
78 dat = &im->im_cpm.cp_pedat;
79 ppar = &im->im_cpm.cp_pepar;
80 break;
81
82 default:
83 printk(KERN_ERR DRV_MODULE_NAME
84 "Illegal port value %d!\n", port);
85 return -EINVAL;
86 }
87
88 adv = bit >> 3;
89 dir = (char *)dir + adv;
90 dat = (char *)dat + adv;
91 ppar = (char *)ppar + adv;
92
93 msk = 1 << (7 - (bit & 7));
94 if ((in_8(ppar) & msk) != 0) {
95 printk(KERN_ERR DRV_MODULE_NAME
96 "pin %d on port %d is not general purpose!\n", bit, port);
97 return -EINVAL;
98 }
99
100 *dirp = dir;
101 *datp = dat;
102 *mskp = msk;
103
104 return 0;
105}
106#endif
107
108#ifdef CONFIG_8260
109static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
110{
111 iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
112 void *dir, *dat, *ppar;
113 int adv;
114 u8 msk;
115
116 switch (port) {
117 case fsiop_porta:
118 dir = &io->iop_pdira;
119 dat = &io->iop_pdata;
120 ppar = &io->iop_ppara;
121 break;
122
123 case fsiop_portb:
124 dir = &io->iop_pdirb;
125 dat = &io->iop_pdatb;
126 ppar = &io->iop_pparb;
127 break;
128
129 case fsiop_portc:
130 dir = &io->iop_pdirc;
131 dat = &io->iop_pdatc;
132 ppar = &io->iop_pparc;
133 break;
134
135 case fsiop_portd:
136 dir = &io->iop_pdird;
137 dat = &io->iop_pdatd;
138 ppar = &io->iop_ppard;
139 break;
140
141 default:
142 printk(KERN_ERR DRV_MODULE_NAME
143 "Illegal port value %d!\n", port);
144 return -EINVAL;
145 }
146 52
147 adv = bit >> 3; 53 adv = mii_bit->bit >> 3;
148 dir = (char *)dir + adv;
149 dat = (char *)dat + adv; 54 dat = (char *)dat + adv;
150 ppar = (char *)ppar + adv;
151 55
152 msk = 1 << (7 - (bit & 7)); 56 msk = 1 << (7 - (mii_bit->bit & 7));
153 if ((in_8(ppar) & msk) != 0) {
154 printk(KERN_ERR DRV_MODULE_NAME
155 "pin %d on port %d is not general purpose!\n", bit, port);
156 return -EINVAL;
157 }
158 57
159 *dirp = dir;
160 *datp = dat; 58 *datp = dat;
161 *mskp = msk; 59 *mskp = msk;
162 60
163 return 0; 61 return 0;
164} 62}
165#endif
166 63
167static inline void bb_set(u8 *p, u8 m) 64static inline void bb_set(u8 *p, u8 m)
168{ 65{
@@ -179,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m)
179 return (in_8(p) & m) != 0; 76 return (in_8(p) & m) != 0;
180} 77}
181 78
182static inline void mdio_active(struct fs_enet_mii_bus *bus) 79static inline void mdio_active(struct bb_info *bitbang)
183{ 80{
184 bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); 81 bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
185} 82}
186 83
187static inline void mdio_tristate(struct fs_enet_mii_bus *bus) 84static inline void mdio_tristate(struct bb_info *bitbang )
188{ 85{
189 bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); 86 bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
190} 87}
191 88
192static inline int mdio_read(struct fs_enet_mii_bus *bus) 89static inline int mdio_read(struct bb_info *bitbang )
193{ 90{
194 return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); 91 return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
195} 92}
196 93
197static inline void mdio(struct fs_enet_mii_bus *bus, int what) 94static inline void mdio(struct bb_info *bitbang , int what)
198{ 95{
199 if (what) 96 if (what)
200 bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); 97 bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
201 else 98 else
202 bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); 99 bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
203} 100}
204 101
205static inline void mdc(struct fs_enet_mii_bus *bus, int what) 102static inline void mdc(struct bb_info *bitbang , int what)
206{ 103{
207 if (what) 104 if (what)
208 bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); 105 bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
209 else 106 else
210 bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); 107 bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
211} 108}
212 109
213static inline void mii_delay(struct fs_enet_mii_bus *bus) 110static inline void mii_delay(struct bb_info *bitbang )
214{ 111{
215 udelay(bus->bus_info->i.bitbang.delay); 112 udelay(bitbang->delay);
216} 113}
217 114
218/* 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). */
219static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) 116static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
220{ 117{
221 int j; 118 int j;
222 119
@@ -228,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
228 * but it is safer and will be much more robust. 125 * but it is safer and will be much more robust.
229 */ 126 */
230 127
231 mdio_active(bus); 128 mdio_active(bitbang);
232 mdio(bus, 1); 129 mdio(bitbang, 1);
233 for (j = 0; j < 32; j++) { 130 for (j = 0; j < 32; j++) {
234 mdc(bus, 0); 131 mdc(bitbang, 0);
235 mii_delay(bus); 132 mii_delay(bitbang);
236 mdc(bus, 1); 133 mdc(bitbang, 1);
237 mii_delay(bus); 134 mii_delay(bitbang);
238 } 135 }
239 136
240 /* 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) */
241 mdc(bus, 0); 138 mdc(bitbang, 0);
242 mdio(bus, 0); 139 mdio(bitbang, 0);
243 mii_delay(bus); 140 mii_delay(bitbang);
244 mdc(bus, 1); 141 mdc(bitbang, 1);
245 mii_delay(bus); 142 mii_delay(bitbang);
246 mdc(bus, 0); 143 mdc(bitbang, 0);
247 mdio(bus, 1); 144 mdio(bitbang, 1);
248 mii_delay(bus); 145 mii_delay(bitbang);
249 mdc(bus, 1); 146 mdc(bitbang, 1);
250 mii_delay(bus); 147 mii_delay(bitbang);
251 mdc(bus, 0); 148 mdc(bitbang, 0);
252 mdio(bus, read); 149 mdio(bitbang, read);
253 mii_delay(bus); 150 mii_delay(bitbang);
254 mdc(bus, 1); 151 mdc(bitbang, 1);
255 mii_delay(bus); 152 mii_delay(bitbang);
256 mdc(bus, 0); 153 mdc(bitbang, 0);
257 mdio(bus, !read); 154 mdio(bitbang, !read);
258 mii_delay(bus); 155 mii_delay(bitbang);
259 mdc(bus, 1); 156 mdc(bitbang, 1);
260 mii_delay(bus); 157 mii_delay(bitbang);
261 158
262 /* send the PHY address */ 159 /* send the PHY address */
263 for (j = 0; j < 5; j++) { 160 for (j = 0; j < 5; j++) {
264 mdc(bus, 0); 161 mdc(bitbang, 0);
265 mdio(bus, (addr & 0x10) != 0); 162 mdio(bitbang, (addr & 0x10) != 0);
266 mii_delay(bus); 163 mii_delay(bitbang);
267 mdc(bus, 1); 164 mdc(bitbang, 1);
268 mii_delay(bus); 165 mii_delay(bitbang);
269 addr <<= 1; 166 addr <<= 1;
270 } 167 }
271 168
272 /* send the register address */ 169 /* send the register address */
273 for (j = 0; j < 5; j++) { 170 for (j = 0; j < 5; j++) {
274 mdc(bus, 0); 171 mdc(bitbang, 0);
275 mdio(bus, (reg & 0x10) != 0); 172 mdio(bitbang, (reg & 0x10) != 0);
276 mii_delay(bus); 173 mii_delay(bitbang);
277 mdc(bus, 1); 174 mdc(bitbang, 1);
278 mii_delay(bus); 175 mii_delay(bitbang);
279 reg <<= 1; 176 reg <<= 1;
280 } 177 }
281} 178}
282 179
283static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) 180static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
284{ 181{
285 u16 rdreg; 182 u16 rdreg;
286 int ret, j; 183 int ret, j;
287 u8 addr = phy_id & 0xff; 184 u8 addr = phy_id & 0xff;
288 u8 reg = location & 0xff; 185 u8 reg = location & 0xff;
186 struct bb_info* bitbang = bus->priv;
289 187
290 bitbang_pre(bus, 1, addr, reg); 188 bitbang_pre(bitbang, 1, addr, reg);
291 189
292 /* tri-state our MDIO I/O pin so we can read */ 190 /* tri-state our MDIO I/O pin so we can read */
293 mdc(bus, 0); 191 mdc(bitbang, 0);
294 mdio_tristate(bus); 192 mdio_tristate(bitbang);
295 mii_delay(bus); 193 mii_delay(bitbang);
296 mdc(bus, 1); 194 mdc(bitbang, 1);
297 mii_delay(bus); 195 mii_delay(bitbang);
298 196
299 /* 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 */
300 if (mdio_read(bus) != 0) { 198 if (mdio_read(bitbang) != 0) {
301 /* PHY didn't drive TA low */ 199 /* PHY didn't drive TA low */
302 for (j = 0; j < 32; j++) { 200 for (j = 0; j < 32; j++) {
303 mdc(bus, 0); 201 mdc(bitbang, 0);
304 mii_delay(bus); 202 mii_delay(bitbang);
305 mdc(bus, 1); 203 mdc(bitbang, 1);
306 mii_delay(bus); 204 mii_delay(bitbang);
307 } 205 }
308 ret = -1; 206 ret = -1;
309 goto out; 207 goto out;
310 } 208 }
311 209
312 mdc(bus, 0); 210 mdc(bitbang, 0);
313 mii_delay(bus); 211 mii_delay(bitbang);
314 212
315 /* read 16 bits of register data, MSB first */ 213 /* read 16 bits of register data, MSB first */
316 rdreg = 0; 214 rdreg = 0;
317 for (j = 0; j < 16; j++) { 215 for (j = 0; j < 16; j++) {
318 mdc(bus, 1); 216 mdc(bitbang, 1);
319 mii_delay(bus); 217 mii_delay(bitbang);
320 rdreg <<= 1; 218 rdreg <<= 1;
321 rdreg |= mdio_read(bus); 219 rdreg |= mdio_read(bitbang);
322 mdc(bus, 0); 220 mdc(bitbang, 0);
323 mii_delay(bus); 221 mii_delay(bitbang);
324 } 222 }
325 223
326 mdc(bus, 1); 224 mdc(bitbang, 1);
327 mii_delay(bus); 225 mii_delay(bitbang);
328 mdc(bus, 0); 226 mdc(bitbang, 0);
329 mii_delay(bus); 227 mii_delay(bitbang);
330 mdc(bus, 1); 228 mdc(bitbang, 1);
331 mii_delay(bus); 229 mii_delay(bitbang);
332 230
333 ret = rdreg; 231 ret = rdreg;
334out: 232out:
335 return ret; 233 return ret;
336} 234}
337 235
338static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) 236static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
339{ 237{
340 int j; 238 int j;
239 struct bb_info* bitbang = bus->priv;
240
341 u8 addr = phy_id & 0xff; 241 u8 addr = phy_id & 0xff;
342 u8 reg = location & 0xff; 242 u8 reg = location & 0xff;
343 u16 value = val & 0xffff; 243 u16 value = val & 0xffff;
344 244
345 bitbang_pre(bus, 0, addr, reg); 245 bitbang_pre(bitbang, 0, addr, reg);
346 246
347 /* send the turnaround (10) */ 247 /* send the turnaround (10) */
348 mdc(bus, 0); 248 mdc(bitbang, 0);
349 mdio(bus, 1); 249 mdio(bitbang, 1);
350 mii_delay(bus); 250 mii_delay(bitbang);
351 mdc(bus, 1); 251 mdc(bitbang, 1);
352 mii_delay(bus); 252 mii_delay(bitbang);
353 mdc(bus, 0); 253 mdc(bitbang, 0);
354 mdio(bus, 0); 254 mdio(bitbang, 0);
355 mii_delay(bus); 255 mii_delay(bitbang);
356 mdc(bus, 1); 256 mdc(bitbang, 1);
357 mii_delay(bus); 257 mii_delay(bitbang);
358 258
359 /* write 16 bits of register data, MSB first */ 259 /* write 16 bits of register data, MSB first */
360 for (j = 0; j < 16; j++) { 260 for (j = 0; j < 16; j++) {
361 mdc(bus, 0); 261 mdc(bitbang, 0);
362 mdio(bus, (value & 0x8000) != 0); 262 mdio(bitbang, (value & 0x8000) != 0);
363 mii_delay(bus); 263 mii_delay(bitbang);
364 mdc(bus, 1); 264 mdc(bitbang, 1);
365 mii_delay(bus); 265 mii_delay(bitbang);
366 value <<= 1; 266 value <<= 1;
367 } 267 }
368 268
369 /* 269 /*
370 * Tri-state the MDIO line. 270 * Tri-state the MDIO line.
371 */ 271 */
372 mdio_tristate(bus); 272 mdio_tristate(bitbang);
373 mdc(bus, 0); 273 mdc(bitbang, 0);
374 mii_delay(bus); 274 mii_delay(bitbang);
375 mdc(bus, 1); 275 mdc(bitbang, 1);
376 mii_delay(bus); 276 mii_delay(bitbang);
277 return 0;
377} 278}
378 279
379int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus) 280static int fs_enet_mii_bb_reset(struct mii_bus *bus)
281{
282 /*nothing here - dunno how to reset it*/
283 return 0;
284}
285
286static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
380{ 287{
381 const struct fs_mii_bus_info *bi = bus->bus_info;
382 int r; 288 int r;
383 289
384 r = bitbang_prep_bit(&bus->bitbang.mdio_dir, 290 bitbang->delay = fmpi->delay;
385 &bus->bitbang.mdio_dat, 291
386 &bus->bitbang.mdio_msk, 292 r = bitbang_prep_bit(&bitbang->mdio_dir,
387 bi->i.bitbang.mdio_port, 293 &bitbang->mdio_dir_msk,
388 bi->i.bitbang.mdio_bit); 294 &fmpi->mdio_dir);
389 if (r != 0) 295 if (r != 0)
390 return r; 296 return r;
391 297
392 r = bitbang_prep_bit(&bus->bitbang.mdc_dir, 298 r = bitbang_prep_bit(&bitbang->mdio_dat,
393 &bus->bitbang.mdc_dat, 299 &bitbang->mdio_dat_msk,
394 &bus->bitbang.mdc_msk, 300 &fmpi->mdio_dat);
395 bi->i.bitbang.mdc_port,
396 bi->i.bitbang.mdc_bit);
397 if (r != 0) 301 if (r != 0)
398 return r; 302 return r;
399 303
400 bus->mii_read = mii_read; 304 r = bitbang_prep_bit(&bitbang->mdc_dat,
401 bus->mii_write = mii_write; 305 &bitbang->mdc_msk,
306 &fmpi->mdc_dat);
307 if (r != 0)
308 return r;
402 309
403 return 0; 310 return 0;
404} 311}
312
313
314static 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
369bus_register_fail:
370 kfree(bitbang);
371 kfree(new_bus);
372
373 return err;
374}
375
376
377static 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
392static 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
399int fs_enet_mdio_bb_init(void)
400{
401 return driver_register(&fs_enet_bb_mdio_driver);
402}
403
404void 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
54static 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
69static 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
98static 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
123static 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
147static int fs_enet_fec_mii_reset(struct mii_bus *bus)
148{
149 /* nothing here - for now */
150 return 0;
151}
152
153static 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
205bus_register_fail:
206 kfree(new_bus);
207
208 return err;
209}
210
211
212static 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
227static 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
234int fs_enet_mdio_fec_init(void)
235{
236 return driver_register(&fs_enet_fec_mdio_driver);
237}
238
239void 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 ae4a9c3bb393..000000000000
--- a/drivers/net/fs_enet/mii-fixed.c
+++ /dev/null
@@ -1,91 +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/module.h>
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/string.h>
21#include <linux/ptrace.h>
22#include <linux/errno.h>
23#include <linux/ioport.h>
24#include <linux/slab.h>
25#include <linux/interrupt.h>
26#include <linux/pci.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/netdevice.h>
30#include <linux/etherdevice.h>
31#include <linux/skbuff.h>
32#include <linux/spinlock.h>
33#include <linux/mii.h>
34#include <linux/ethtool.h>
35#include <linux/bitops.h>
36
37#include <asm/pgtable.h>
38#include <asm/irq.h>
39#include <asm/uaccess.h>
40
41#include "fs_enet.h"
42
43static const u16 mii_regs[7] = {
44 0x3100,
45 0x786d,
46 0x0fff,
47 0x0fff,
48 0x01e1,
49 0x45e1,
50 0x0003,
51};
52
53static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
54{
55 int ret = 0;
56
57 if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
58 return -1;
59
60 if (location != 5)
61 ret = mii_regs[location];
62 else
63 ret = bus->fixed.lpa;
64
65 return ret;
66}
67
68static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
69{
70 /* do nothing */
71}
72
73int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
74{
75 const struct fs_mii_bus_info *bi = bus->bus_info;
76
77 bus->fixed.lpa = 0x45e1; /* default 100Mb, full duplex */
78
79 /* if speed is fixed at 10Mb, remove 100Mb modes */
80 if (bi->i.fixed.speed == 10)
81 bus->fixed.lpa &= ~LPA_100;
82
83 /* if duplex is half, remove full duplex modes */
84 if (bi->i.fixed.duplex == 0)
85 bus->fixed.lpa &= ~LPA_DUPLEX;
86
87 bus->mii_read = mii_read;
88 bus->mii_write = mii_write;
89
90 return 0;
91}