diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-03 13:01:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-03 13:01:33 -0400 |
| commit | c36c804559d3a891a2e655ba8185b4fa7eaee156 (patch) | |
| tree | 0a4092432229616b2fdc53d87ea32e944212c626 /drivers/net/fec_mpc52xx.c | |
| parent | be2e88011bd800222bfd7b477c727966f93186a9 (diff) | |
| parent | 3b5750644b2ffa2a76fdfe7b4e00e4af2ecf3539 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
[POWERPC] Bolt in SLB entry for kernel stack on secondary cpus
[POWERPC] PS3: Update ps3_defconfig
[POWERPC] PS3: Remove unsupported wakeup sources
[POWERPC] PS3: Make ps3_virq_setup and ps3_virq_destroy static
[POWERPC] PS3: Add time include to lpm
[POWERPC] Fix slb.c compile warnings
[POWERPC] Xilinx: Fix compile warnings
[POWERPC] Squash build warning for print of resource_size_t in fsl_soc.c
[RAPIDIO] fix current kernel-doc notation
[POWERPC] 86xx: mpc8610_hpcd: add support for PCI Express x8 slot
Fix a potential issue in mpc52xx uart driver
[POWERPC] mpc5200: Allow for fixed speed MII configurations
[POWERPC] 86xx: Fix the wrong serial1 interrupt for 8610 board
Diffstat (limited to 'drivers/net/fec_mpc52xx.c')
| -rw-r--r-- | drivers/net/fec_mpc52xx.c | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index d21b7ab64bd1..5f9c42e7a7f1 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c | |||
| @@ -43,6 +43,29 @@ | |||
| 43 | 43 | ||
| 44 | #define DRIVER_NAME "mpc52xx-fec" | 44 | #define DRIVER_NAME "mpc52xx-fec" |
| 45 | 45 | ||
| 46 | #define FEC5200_PHYADDR_NONE (-1) | ||
| 47 | #define FEC5200_PHYADDR_7WIRE (-2) | ||
| 48 | |||
| 49 | /* Private driver data structure */ | ||
| 50 | struct mpc52xx_fec_priv { | ||
| 51 | int duplex; | ||
| 52 | int speed; | ||
| 53 | int r_irq; | ||
| 54 | int t_irq; | ||
| 55 | struct mpc52xx_fec __iomem *fec; | ||
| 56 | struct bcom_task *rx_dmatsk; | ||
| 57 | struct bcom_task *tx_dmatsk; | ||
| 58 | spinlock_t lock; | ||
| 59 | int msg_enable; | ||
| 60 | |||
| 61 | /* MDIO link details */ | ||
| 62 | int phy_addr; | ||
| 63 | unsigned int phy_speed; | ||
| 64 | struct phy_device *phydev; | ||
| 65 | enum phy_state link; | ||
| 66 | }; | ||
| 67 | |||
| 68 | |||
| 46 | static irqreturn_t mpc52xx_fec_interrupt(int, void *); | 69 | static irqreturn_t mpc52xx_fec_interrupt(int, void *); |
| 47 | static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); | 70 | static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); |
| 48 | static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); | 71 | static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); |
| @@ -223,7 +246,7 @@ static int mpc52xx_fec_phy_start(struct net_device *dev) | |||
| 223 | struct mpc52xx_fec_priv *priv = netdev_priv(dev); | 246 | struct mpc52xx_fec_priv *priv = netdev_priv(dev); |
| 224 | int err; | 247 | int err; |
| 225 | 248 | ||
| 226 | if (!priv->has_phy) | 249 | if (priv->phy_addr < 0) |
| 227 | return 0; | 250 | return 0; |
| 228 | 251 | ||
| 229 | err = mpc52xx_fec_init_phy(dev); | 252 | err = mpc52xx_fec_init_phy(dev); |
| @@ -243,7 +266,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev) | |||
| 243 | { | 266 | { |
| 244 | struct mpc52xx_fec_priv *priv = netdev_priv(dev); | 267 | struct mpc52xx_fec_priv *priv = netdev_priv(dev); |
| 245 | 268 | ||
| 246 | if (!priv->has_phy) | 269 | if (!priv->phydev) |
| 247 | return; | 270 | return; |
| 248 | 271 | ||
| 249 | phy_disconnect(priv->phydev); | 272 | phy_disconnect(priv->phydev); |
| @@ -255,7 +278,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev) | |||
| 255 | static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv, | 278 | static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv, |
| 256 | struct mii_ioctl_data *mii_data, int cmd) | 279 | struct mii_ioctl_data *mii_data, int cmd) |
| 257 | { | 280 | { |
| 258 | if (!priv->has_phy) | 281 | if (!priv->phydev) |
| 259 | return -ENOTSUPP; | 282 | return -ENOTSUPP; |
| 260 | 283 | ||
| 261 | return phy_mii_ioctl(priv->phydev, mii_data, cmd); | 284 | return phy_mii_ioctl(priv->phydev, mii_data, cmd); |
| @@ -265,7 +288,7 @@ static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv) | |||
| 265 | { | 288 | { |
| 266 | struct mpc52xx_fec __iomem *fec = priv->fec; | 289 | struct mpc52xx_fec __iomem *fec = priv->fec; |
| 267 | 290 | ||
| 268 | if (!priv->has_phy) | 291 | if (priv->phydev) |
| 269 | return; | 292 | return; |
| 270 | 293 | ||
| 271 | out_be32(&fec->mii_speed, priv->phy_speed); | 294 | out_be32(&fec->mii_speed, priv->phy_speed); |
| @@ -704,7 +727,7 @@ static void mpc52xx_fec_start(struct net_device *dev) | |||
| 704 | rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ | 727 | rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ |
| 705 | rcntrl |= FEC_RCNTRL_FCE; | 728 | rcntrl |= FEC_RCNTRL_FCE; |
| 706 | 729 | ||
| 707 | if (priv->has_phy) | 730 | if (priv->phy_addr != FEC5200_PHYADDR_7WIRE) |
| 708 | rcntrl |= FEC_RCNTRL_MII_MODE; | 731 | rcntrl |= FEC_RCNTRL_MII_MODE; |
| 709 | 732 | ||
| 710 | if (priv->duplex == DUPLEX_FULL) | 733 | if (priv->duplex == DUPLEX_FULL) |
| @@ -864,7 +887,10 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) | |||
| 864 | struct net_device *ndev; | 887 | struct net_device *ndev; |
| 865 | struct mpc52xx_fec_priv *priv = NULL; | 888 | struct mpc52xx_fec_priv *priv = NULL; |
| 866 | struct resource mem; | 889 | struct resource mem; |
| 867 | const phandle *ph; | 890 | struct device_node *phy_node; |
| 891 | const phandle *phy_handle; | ||
| 892 | const u32 *prop; | ||
| 893 | int prop_size; | ||
| 868 | 894 | ||
| 869 | phys_addr_t rx_fifo; | 895 | phys_addr_t rx_fifo; |
| 870 | phys_addr_t tx_fifo; | 896 | phys_addr_t tx_fifo; |
| @@ -948,26 +974,37 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) | |||
| 948 | mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); | 974 | mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); |
| 949 | 975 | ||
| 950 | priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); | 976 | priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); |
| 951 | priv->duplex = DUPLEX_FULL; | ||
| 952 | |||
| 953 | /* is the phy present in device tree? */ | ||
| 954 | ph = of_get_property(op->node, "phy-handle", NULL); | ||
| 955 | if (ph) { | ||
| 956 | const unsigned int *prop; | ||
| 957 | struct device_node *phy_dn; | ||
| 958 | priv->has_phy = 1; | ||
| 959 | 977 | ||
| 960 | phy_dn = of_find_node_by_phandle(*ph); | 978 | /* |
| 961 | prop = of_get_property(phy_dn, "reg", NULL); | 979 | * Link mode configuration |
| 962 | priv->phy_addr = *prop; | 980 | */ |
| 963 | 981 | ||
| 964 | of_node_put(phy_dn); | 982 | /* Start with safe defaults for link connection */ |
| 983 | priv->phy_addr = FEC5200_PHYADDR_NONE; | ||
| 984 | priv->speed = 100; | ||
| 985 | priv->duplex = DUPLEX_HALF; | ||
| 986 | priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; | ||
| 987 | |||
| 988 | /* the 7-wire property means don't use MII mode */ | ||
| 989 | if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) | ||
| 990 | priv->phy_addr = FEC5200_PHYADDR_7WIRE; | ||
| 991 | |||
| 992 | /* The current speed preconfigures the speed of the MII link */ | ||
| 993 | prop = of_get_property(op->node, "current-speed", &prop_size); | ||
| 994 | if (prop && (prop_size >= sizeof(u32) * 2)) { | ||
| 995 | priv->speed = prop[0]; | ||
| 996 | priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; | ||
| 997 | } | ||
| 965 | 998 | ||
| 966 | /* Phy speed */ | 999 | /* If there is a phy handle, setup link to that phy */ |
| 967 | priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; | 1000 | phy_handle = of_get_property(op->node, "phy-handle", &prop_size); |
| 968 | } else { | 1001 | if (phy_handle && (prop_size >= sizeof(phandle))) { |
| 969 | dev_info(&ndev->dev, "can't find \"phy-handle\" in device" | 1002 | phy_node = of_find_node_by_phandle(*phy_handle); |
| 970 | " tree, using 7-wire mode\n"); | 1003 | prop = of_get_property(phy_node, "reg", &prop_size); |
| 1004 | if (prop && (prop_size >= sizeof(u32))) | ||
| 1005 | if ((*prop >= 0) && (*prop < PHY_MAX_ADDR)) | ||
| 1006 | priv->phy_addr = *prop; | ||
| 1007 | of_node_put(phy_node); | ||
| 971 | } | 1008 | } |
| 972 | 1009 | ||
| 973 | /* Hardware init */ | 1010 | /* Hardware init */ |
| @@ -982,6 +1019,20 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) | |||
| 982 | if (rv < 0) | 1019 | if (rv < 0) |
| 983 | goto probe_error; | 1020 | goto probe_error; |
| 984 | 1021 | ||
| 1022 | /* Now report the link setup */ | ||
| 1023 | switch (priv->phy_addr) { | ||
| 1024 | case FEC5200_PHYADDR_NONE: | ||
| 1025 | dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n", | ||
| 1026 | priv->speed, priv->duplex ? 'F' : 'H'); | ||
| 1027 | break; | ||
| 1028 | case FEC5200_PHYADDR_7WIRE: | ||
| 1029 | dev_info(&ndev->dev, "using 7-wire PHY mode\n"); | ||
| 1030 | break; | ||
| 1031 | default: | ||
| 1032 | dev_info(&ndev->dev, "Using PHY at MDIO address %i\n", | ||
| 1033 | priv->phy_addr); | ||
| 1034 | } | ||
| 1035 | |||
| 985 | /* We're done ! */ | 1036 | /* We're done ! */ |
| 986 | dev_set_drvdata(&op->dev, ndev); | 1037 | dev_set_drvdata(&op->dev, ndev); |
| 987 | 1038 | ||
