diff options
Diffstat (limited to 'drivers/net/fec.c')
-rw-r--r-- | drivers/net/fec.c | 248 |
1 files changed, 180 insertions, 68 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index cce32d43175f..2a71373719ae 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -17,6 +17,8 @@ | |||
17 | * | 17 | * |
18 | * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) | 18 | * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) |
19 | * Copyright (c) 2004-2006 Macq Electronique SA. | 19 | * Copyright (c) 2004-2006 Macq Electronique SA. |
20 | * | ||
21 | * Copyright (C) 2010 Freescale Semiconductor, Inc. | ||
20 | */ | 22 | */ |
21 | 23 | ||
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -45,29 +47,41 @@ | |||
45 | 47 | ||
46 | #include <asm/cacheflush.h> | 48 | #include <asm/cacheflush.h> |
47 | 49 | ||
48 | #ifndef CONFIG_ARCH_MXC | 50 | #ifndef CONFIG_ARM |
49 | #include <asm/coldfire.h> | 51 | #include <asm/coldfire.h> |
50 | #include <asm/mcfsim.h> | 52 | #include <asm/mcfsim.h> |
51 | #endif | 53 | #endif |
52 | 54 | ||
53 | #include "fec.h" | 55 | #include "fec.h" |
54 | 56 | ||
55 | #ifdef CONFIG_ARCH_MXC | 57 | #if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) |
56 | #include <mach/hardware.h> | ||
57 | #define FEC_ALIGNMENT 0xf | 58 | #define FEC_ALIGNMENT 0xf |
58 | #else | 59 | #else |
59 | #define FEC_ALIGNMENT 0x3 | 60 | #define FEC_ALIGNMENT 0x3 |
60 | #endif | 61 | #endif |
61 | 62 | ||
62 | /* | 63 | #define DRIVER_NAME "fec" |
63 | * Define the fixed address of the FEC hardware. | 64 | |
64 | */ | 65 | /* Controller is ENET-MAC */ |
65 | #if defined(CONFIG_M5272) | 66 | #define FEC_QUIRK_ENET_MAC (1 << 0) |
67 | /* Controller needs driver to swap frame */ | ||
68 | #define FEC_QUIRK_SWAP_FRAME (1 << 1) | ||
66 | 69 | ||
67 | static unsigned char fec_mac_default[] = { | 70 | static struct platform_device_id fec_devtype[] = { |
68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 71 | { |
72 | .name = DRIVER_NAME, | ||
73 | .driver_data = 0, | ||
74 | }, { | ||
75 | .name = "imx28-fec", | ||
76 | .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME, | ||
77 | } | ||
69 | }; | 78 | }; |
70 | 79 | ||
80 | static unsigned char macaddr[ETH_ALEN]; | ||
81 | module_param_array(macaddr, byte, NULL, 0); | ||
82 | MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); | ||
83 | |||
84 | #if defined(CONFIG_M5272) | ||
71 | /* | 85 | /* |
72 | * Some hardware gets it MAC address out of local flash memory. | 86 | * Some hardware gets it MAC address out of local flash memory. |
73 | * if this is non-zero then assume it is the address to get MAC from. | 87 | * if this is non-zero then assume it is the address to get MAC from. |
@@ -133,7 +147,8 @@ static unsigned char fec_mac_default[] = { | |||
133 | * account when setting it. | 147 | * account when setting it. |
134 | */ | 148 | */ |
135 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ | 149 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ |
136 | defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC) | 150 | defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ |
151 | defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) | ||
137 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) | 152 | #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) |
138 | #else | 153 | #else |
139 | #define OPT_FRAME_SIZE 0 | 154 | #define OPT_FRAME_SIZE 0 |
@@ -186,7 +201,6 @@ struct fec_enet_private { | |||
186 | int mii_timeout; | 201 | int mii_timeout; |
187 | uint phy_speed; | 202 | uint phy_speed; |
188 | phy_interface_t phy_interface; | 203 | phy_interface_t phy_interface; |
189 | int index; | ||
190 | int link; | 204 | int link; |
191 | int full_duplex; | 205 | int full_duplex; |
192 | struct completion mdio_done; | 206 | struct completion mdio_done; |
@@ -213,10 +227,23 @@ static void fec_stop(struct net_device *dev); | |||
213 | /* Transmitter timeout */ | 227 | /* Transmitter timeout */ |
214 | #define TX_TIMEOUT (2 * HZ) | 228 | #define TX_TIMEOUT (2 * HZ) |
215 | 229 | ||
230 | static void *swap_buffer(void *bufaddr, int len) | ||
231 | { | ||
232 | int i; | ||
233 | unsigned int *buf = bufaddr; | ||
234 | |||
235 | for (i = 0; i < (len + 3) / 4; i++, buf++) | ||
236 | *buf = cpu_to_be32(*buf); | ||
237 | |||
238 | return bufaddr; | ||
239 | } | ||
240 | |||
216 | static netdev_tx_t | 241 | static netdev_tx_t |
217 | fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | 242 | fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) |
218 | { | 243 | { |
219 | struct fec_enet_private *fep = netdev_priv(dev); | 244 | struct fec_enet_private *fep = netdev_priv(dev); |
245 | const struct platform_device_id *id_entry = | ||
246 | platform_get_device_id(fep->pdev); | ||
220 | struct bufdesc *bdp; | 247 | struct bufdesc *bdp; |
221 | void *bufaddr; | 248 | void *bufaddr; |
222 | unsigned short status; | 249 | unsigned short status; |
@@ -261,6 +288,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
261 | bufaddr = fep->tx_bounce[index]; | 288 | bufaddr = fep->tx_bounce[index]; |
262 | } | 289 | } |
263 | 290 | ||
291 | /* | ||
292 | * Some design made an incorrect assumption on endian mode of | ||
293 | * the system that it's running on. As the result, driver has to | ||
294 | * swap every frame going to and coming from the controller. | ||
295 | */ | ||
296 | if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) | ||
297 | swap_buffer(bufaddr, skb->len); | ||
298 | |||
264 | /* Save skb pointer */ | 299 | /* Save skb pointer */ |
265 | fep->tx_skbuff[fep->skb_cur] = skb; | 300 | fep->tx_skbuff[fep->skb_cur] = skb; |
266 | 301 | ||
@@ -429,6 +464,8 @@ static void | |||
429 | fec_enet_rx(struct net_device *dev) | 464 | fec_enet_rx(struct net_device *dev) |
430 | { | 465 | { |
431 | struct fec_enet_private *fep = netdev_priv(dev); | 466 | struct fec_enet_private *fep = netdev_priv(dev); |
467 | const struct platform_device_id *id_entry = | ||
468 | platform_get_device_id(fep->pdev); | ||
432 | struct bufdesc *bdp; | 469 | struct bufdesc *bdp; |
433 | unsigned short status; | 470 | unsigned short status; |
434 | struct sk_buff *skb; | 471 | struct sk_buff *skb; |
@@ -492,6 +529,9 @@ fec_enet_rx(struct net_device *dev) | |||
492 | dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, | 529 | dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, |
493 | DMA_FROM_DEVICE); | 530 | DMA_FROM_DEVICE); |
494 | 531 | ||
532 | if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) | ||
533 | swap_buffer(data, pkt_len); | ||
534 | |||
495 | /* This does 16 byte alignment, exactly what we need. | 535 | /* This does 16 byte alignment, exactly what we need. |
496 | * The packet length includes FCS, but we don't want to | 536 | * The packet length includes FCS, but we don't want to |
497 | * include that when passing upstream as it messes up | 537 | * include that when passing upstream as it messes up |
@@ -538,37 +578,50 @@ rx_processing_done: | |||
538 | } | 578 | } |
539 | 579 | ||
540 | /* ------------------------------------------------------------------------- */ | 580 | /* ------------------------------------------------------------------------- */ |
541 | #ifdef CONFIG_M5272 | ||
542 | static void __inline__ fec_get_mac(struct net_device *dev) | 581 | static void __inline__ fec_get_mac(struct net_device *dev) |
543 | { | 582 | { |
544 | struct fec_enet_private *fep = netdev_priv(dev); | 583 | struct fec_enet_private *fep = netdev_priv(dev); |
584 | struct fec_platform_data *pdata = fep->pdev->dev.platform_data; | ||
545 | unsigned char *iap, tmpaddr[ETH_ALEN]; | 585 | unsigned char *iap, tmpaddr[ETH_ALEN]; |
546 | 586 | ||
547 | if (FEC_FLASHMAC) { | 587 | /* |
548 | /* | 588 | * try to get mac address in following order: |
549 | * Get MAC address from FLASH. | 589 | * |
550 | * If it is all 1's or 0's, use the default. | 590 | * 1) module parameter via kernel command line in form |
551 | */ | 591 | * fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0 |
552 | iap = (unsigned char *)FEC_FLASHMAC; | 592 | */ |
553 | if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && | 593 | iap = macaddr; |
554 | (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) | 594 | |
555 | iap = fec_mac_default; | 595 | /* |
556 | if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && | 596 | * 2) from flash or fuse (via platform data) |
557 | (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) | 597 | */ |
558 | iap = fec_mac_default; | 598 | if (!is_valid_ether_addr(iap)) { |
559 | } else { | 599 | #ifdef CONFIG_M5272 |
560 | *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW); | 600 | if (FEC_FLASHMAC) |
561 | *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16); | 601 | iap = (unsigned char *)FEC_FLASHMAC; |
602 | #else | ||
603 | if (pdata) | ||
604 | memcpy(iap, pdata->mac, ETH_ALEN); | ||
605 | #endif | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * 3) FEC mac registers set by bootloader | ||
610 | */ | ||
611 | if (!is_valid_ether_addr(iap)) { | ||
612 | *((unsigned long *) &tmpaddr[0]) = | ||
613 | be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW)); | ||
614 | *((unsigned short *) &tmpaddr[4]) = | ||
615 | be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16); | ||
562 | iap = &tmpaddr[0]; | 616 | iap = &tmpaddr[0]; |
563 | } | 617 | } |
564 | 618 | ||
565 | memcpy(dev->dev_addr, iap, ETH_ALEN); | 619 | memcpy(dev->dev_addr, iap, ETH_ALEN); |
566 | 620 | ||
567 | /* Adjust MAC if using default MAC address */ | 621 | /* Adjust MAC if using macaddr */ |
568 | if (iap == fec_mac_default) | 622 | if (iap == macaddr) |
569 | dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; | 623 | dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id; |
570 | } | 624 | } |
571 | #endif | ||
572 | 625 | ||
573 | /* ------------------------------------------------------------------------- */ | 626 | /* ------------------------------------------------------------------------- */ |
574 | 627 | ||
@@ -651,8 +704,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | |||
651 | fep->mii_timeout = 0; | 704 | fep->mii_timeout = 0; |
652 | init_completion(&fep->mdio_done); | 705 | init_completion(&fep->mdio_done); |
653 | 706 | ||
654 | /* start a read op */ | 707 | /* start a write op */ |
655 | writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | | 708 | writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | |
656 | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | | 709 | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | |
657 | FEC_MMFR_TA | FEC_MMFR_DATA(value), | 710 | FEC_MMFR_TA | FEC_MMFR_DATA(value), |
658 | fep->hwp + FEC_MII_DATA); | 711 | fep->hwp + FEC_MII_DATA); |
@@ -681,6 +734,7 @@ static int fec_enet_mii_probe(struct net_device *dev) | |||
681 | char mdio_bus_id[MII_BUS_ID_SIZE]; | 734 | char mdio_bus_id[MII_BUS_ID_SIZE]; |
682 | char phy_name[MII_BUS_ID_SIZE + 3]; | 735 | char phy_name[MII_BUS_ID_SIZE + 3]; |
683 | int phy_id; | 736 | int phy_id; |
737 | int dev_id = fep->pdev->id; | ||
684 | 738 | ||
685 | fep->phy_dev = NULL; | 739 | fep->phy_dev = NULL; |
686 | 740 | ||
@@ -692,6 +746,8 @@ static int fec_enet_mii_probe(struct net_device *dev) | |||
692 | continue; | 746 | continue; |
693 | if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) | 747 | if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) |
694 | continue; | 748 | continue; |
749 | if (dev_id--) | ||
750 | continue; | ||
695 | strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); | 751 | strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); |
696 | break; | 752 | break; |
697 | } | 753 | } |
@@ -729,10 +785,35 @@ static int fec_enet_mii_probe(struct net_device *dev) | |||
729 | 785 | ||
730 | static int fec_enet_mii_init(struct platform_device *pdev) | 786 | static int fec_enet_mii_init(struct platform_device *pdev) |
731 | { | 787 | { |
788 | static struct mii_bus *fec0_mii_bus; | ||
732 | struct net_device *dev = platform_get_drvdata(pdev); | 789 | struct net_device *dev = platform_get_drvdata(pdev); |
733 | struct fec_enet_private *fep = netdev_priv(dev); | 790 | struct fec_enet_private *fep = netdev_priv(dev); |
791 | const struct platform_device_id *id_entry = | ||
792 | platform_get_device_id(fep->pdev); | ||
734 | int err = -ENXIO, i; | 793 | int err = -ENXIO, i; |
735 | 794 | ||
795 | /* | ||
796 | * The dual fec interfaces are not equivalent with enet-mac. | ||
797 | * Here are the differences: | ||
798 | * | ||
799 | * - fec0 supports MII & RMII modes while fec1 only supports RMII | ||
800 | * - fec0 acts as the 1588 time master while fec1 is slave | ||
801 | * - external phys can only be configured by fec0 | ||
802 | * | ||
803 | * That is to say fec1 can not work independently. It only works | ||
804 | * when fec0 is working. The reason behind this design is that the | ||
805 | * second interface is added primarily for Switch mode. | ||
806 | * | ||
807 | * Because of the last point above, both phys are attached on fec0 | ||
808 | * mdio interface in board design, and need to be configured by | ||
809 | * fec0 mii_bus. | ||
810 | */ | ||
811 | if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id) { | ||
812 | /* fec1 uses fec0 mii_bus */ | ||
813 | fep->mii_bus = fec0_mii_bus; | ||
814 | return 0; | ||
815 | } | ||
816 | |||
736 | fep->mii_timeout = 0; | 817 | fep->mii_timeout = 0; |
737 | 818 | ||
738 | /* | 819 | /* |
@@ -769,6 +850,10 @@ static int fec_enet_mii_init(struct platform_device *pdev) | |||
769 | if (mdiobus_register(fep->mii_bus)) | 850 | if (mdiobus_register(fep->mii_bus)) |
770 | goto err_out_free_mdio_irq; | 851 | goto err_out_free_mdio_irq; |
771 | 852 | ||
853 | /* save fec0 mii_bus */ | ||
854 | if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) | ||
855 | fec0_mii_bus = fep->mii_bus; | ||
856 | |||
772 | return 0; | 857 | return 0; |
773 | 858 | ||
774 | err_out_free_mdio_irq: | 859 | err_out_free_mdio_irq: |
@@ -1067,9 +1152,8 @@ static const struct net_device_ops fec_netdev_ops = { | |||
1067 | /* | 1152 | /* |
1068 | * XXX: We need to clean up on failure exits here. | 1153 | * XXX: We need to clean up on failure exits here. |
1069 | * | 1154 | * |
1070 | * index is only used in legacy code | ||
1071 | */ | 1155 | */ |
1072 | static int fec_enet_init(struct net_device *dev, int index) | 1156 | static int fec_enet_init(struct net_device *dev) |
1073 | { | 1157 | { |
1074 | struct fec_enet_private *fep = netdev_priv(dev); | 1158 | struct fec_enet_private *fep = netdev_priv(dev); |
1075 | struct bufdesc *cbd_base; | 1159 | struct bufdesc *cbd_base; |
@@ -1086,26 +1170,11 @@ static int fec_enet_init(struct net_device *dev, int index) | |||
1086 | 1170 | ||
1087 | spin_lock_init(&fep->hw_lock); | 1171 | spin_lock_init(&fep->hw_lock); |
1088 | 1172 | ||
1089 | fep->index = index; | ||
1090 | fep->hwp = (void __iomem *)dev->base_addr; | 1173 | fep->hwp = (void __iomem *)dev->base_addr; |
1091 | fep->netdev = dev; | 1174 | fep->netdev = dev; |
1092 | 1175 | ||
1093 | /* Set the Ethernet address */ | 1176 | /* Get the Ethernet address */ |
1094 | #ifdef CONFIG_M5272 | ||
1095 | fec_get_mac(dev); | 1177 | fec_get_mac(dev); |
1096 | #else | ||
1097 | { | ||
1098 | unsigned long l; | ||
1099 | l = readl(fep->hwp + FEC_ADDR_LOW); | ||
1100 | dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); | ||
1101 | dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); | ||
1102 | dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); | ||
1103 | dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); | ||
1104 | l = readl(fep->hwp + FEC_ADDR_HIGH); | ||
1105 | dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); | ||
1106 | dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); | ||
1107 | } | ||
1108 | #endif | ||
1109 | 1178 | ||
1110 | /* Set receive and transmit descriptor base. */ | 1179 | /* Set receive and transmit descriptor base. */ |
1111 | fep->rx_bd_base = cbd_base; | 1180 | fep->rx_bd_base = cbd_base; |
@@ -1156,12 +1225,25 @@ static void | |||
1156 | fec_restart(struct net_device *dev, int duplex) | 1225 | fec_restart(struct net_device *dev, int duplex) |
1157 | { | 1226 | { |
1158 | struct fec_enet_private *fep = netdev_priv(dev); | 1227 | struct fec_enet_private *fep = netdev_priv(dev); |
1228 | const struct platform_device_id *id_entry = | ||
1229 | platform_get_device_id(fep->pdev); | ||
1159 | int i; | 1230 | int i; |
1231 | u32 val, temp_mac[2]; | ||
1160 | 1232 | ||
1161 | /* Whack a reset. We should wait for this. */ | 1233 | /* Whack a reset. We should wait for this. */ |
1162 | writel(1, fep->hwp + FEC_ECNTRL); | 1234 | writel(1, fep->hwp + FEC_ECNTRL); |
1163 | udelay(10); | 1235 | udelay(10); |
1164 | 1236 | ||
1237 | /* | ||
1238 | * enet-mac reset will reset mac address registers too, | ||
1239 | * so need to reconfigure it. | ||
1240 | */ | ||
1241 | if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { | ||
1242 | memcpy(&temp_mac, dev->dev_addr, ETH_ALEN); | ||
1243 | writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); | ||
1244 | writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); | ||
1245 | } | ||
1246 | |||
1165 | /* Clear any outstanding interrupt. */ | 1247 | /* Clear any outstanding interrupt. */ |
1166 | writel(0xffc00000, fep->hwp + FEC_IEVENT); | 1248 | writel(0xffc00000, fep->hwp + FEC_IEVENT); |
1167 | 1249 | ||
@@ -1208,20 +1290,45 @@ fec_restart(struct net_device *dev, int duplex) | |||
1208 | /* Set MII speed */ | 1290 | /* Set MII speed */ |
1209 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); | 1291 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); |
1210 | 1292 | ||
1211 | #ifdef FEC_MIIGSK_ENR | 1293 | /* |
1212 | if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { | 1294 | * The phy interface and speed need to get configured |
1213 | /* disable the gasket and wait */ | 1295 | * differently on enet-mac. |
1214 | writel(0, fep->hwp + FEC_MIIGSK_ENR); | 1296 | */ |
1215 | while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) | 1297 | if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { |
1216 | udelay(1); | 1298 | val = readl(fep->hwp + FEC_R_CNTRL); |
1217 | 1299 | ||
1218 | /* configure the gasket: RMII, 50 MHz, no loopback, no echo */ | 1300 | /* MII or RMII */ |
1219 | writel(1, fep->hwp + FEC_MIIGSK_CFGR); | 1301 | if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) |
1302 | val |= (1 << 8); | ||
1303 | else | ||
1304 | val &= ~(1 << 8); | ||
1220 | 1305 | ||
1221 | /* re-enable the gasket */ | 1306 | /* 10M or 100M */ |
1222 | writel(2, fep->hwp + FEC_MIIGSK_ENR); | 1307 | if (fep->phy_dev && fep->phy_dev->speed == SPEED_100) |
1223 | } | 1308 | val &= ~(1 << 9); |
1309 | else | ||
1310 | val |= (1 << 9); | ||
1311 | |||
1312 | writel(val, fep->hwp + FEC_R_CNTRL); | ||
1313 | } else { | ||
1314 | #ifdef FEC_MIIGSK_ENR | ||
1315 | if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { | ||
1316 | /* disable the gasket and wait */ | ||
1317 | writel(0, fep->hwp + FEC_MIIGSK_ENR); | ||
1318 | while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) | ||
1319 | udelay(1); | ||
1320 | |||
1321 | /* | ||
1322 | * configure the gasket: | ||
1323 | * RMII, 50 MHz, no loopback, no echo | ||
1324 | */ | ||
1325 | writel(1, fep->hwp + FEC_MIIGSK_CFGR); | ||
1326 | |||
1327 | /* re-enable the gasket */ | ||
1328 | writel(2, fep->hwp + FEC_MIIGSK_ENR); | ||
1329 | } | ||
1224 | #endif | 1330 | #endif |
1331 | } | ||
1225 | 1332 | ||
1226 | /* And last, enable the transmit and receive processing */ | 1333 | /* And last, enable the transmit and receive processing */ |
1227 | writel(2, fep->hwp + FEC_ECNTRL); | 1334 | writel(2, fep->hwp + FEC_ECNTRL); |
@@ -1316,7 +1423,7 @@ fec_probe(struct platform_device *pdev) | |||
1316 | } | 1423 | } |
1317 | clk_enable(fep->clk); | 1424 | clk_enable(fep->clk); |
1318 | 1425 | ||
1319 | ret = fec_enet_init(ndev, 0); | 1426 | ret = fec_enet_init(ndev); |
1320 | if (ret) | 1427 | if (ret) |
1321 | goto failed_init; | 1428 | goto failed_init; |
1322 | 1429 | ||
@@ -1380,8 +1487,10 @@ fec_suspend(struct device *dev) | |||
1380 | 1487 | ||
1381 | if (ndev) { | 1488 | if (ndev) { |
1382 | fep = netdev_priv(ndev); | 1489 | fep = netdev_priv(ndev); |
1383 | if (netif_running(ndev)) | 1490 | if (netif_running(ndev)) { |
1384 | fec_enet_close(ndev); | 1491 | fec_stop(ndev); |
1492 | netif_device_detach(ndev); | ||
1493 | } | ||
1385 | clk_disable(fep->clk); | 1494 | clk_disable(fep->clk); |
1386 | } | 1495 | } |
1387 | return 0; | 1496 | return 0; |
@@ -1396,8 +1505,10 @@ fec_resume(struct device *dev) | |||
1396 | if (ndev) { | 1505 | if (ndev) { |
1397 | fep = netdev_priv(ndev); | 1506 | fep = netdev_priv(ndev); |
1398 | clk_enable(fep->clk); | 1507 | clk_enable(fep->clk); |
1399 | if (netif_running(ndev)) | 1508 | if (netif_running(ndev)) { |
1400 | fec_enet_open(ndev); | 1509 | fec_restart(ndev, fep->full_duplex); |
1510 | netif_device_attach(ndev); | ||
1511 | } | ||
1401 | } | 1512 | } |
1402 | return 0; | 1513 | return 0; |
1403 | } | 1514 | } |
@@ -1414,12 +1525,13 @@ static const struct dev_pm_ops fec_pm_ops = { | |||
1414 | 1525 | ||
1415 | static struct platform_driver fec_driver = { | 1526 | static struct platform_driver fec_driver = { |
1416 | .driver = { | 1527 | .driver = { |
1417 | .name = "fec", | 1528 | .name = DRIVER_NAME, |
1418 | .owner = THIS_MODULE, | 1529 | .owner = THIS_MODULE, |
1419 | #ifdef CONFIG_PM | 1530 | #ifdef CONFIG_PM |
1420 | .pm = &fec_pm_ops, | 1531 | .pm = &fec_pm_ops, |
1421 | #endif | 1532 | #endif |
1422 | }, | 1533 | }, |
1534 | .id_table = fec_devtype, | ||
1423 | .probe = fec_probe, | 1535 | .probe = fec_probe, |
1424 | .remove = __devexit_p(fec_drv_remove), | 1536 | .remove = __devexit_p(fec_drv_remove), |
1425 | }; | 1537 | }; |