diff options
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r-- | drivers/net/ucc_geth.c | 946 |
1 files changed, 346 insertions, 600 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 639e1e6913bf..16b9acdabbe8 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/fsl_devices.h> | 29 | #include <linux/fsl_devices.h> |
30 | #include <linux/ethtool.h> | 30 | #include <linux/ethtool.h> |
31 | #include <linux/mii.h> | 31 | #include <linux/mii.h> |
32 | #include <linux/phy.h> | ||
32 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
33 | 34 | ||
34 | #include <asm/of_platform.h> | 35 | #include <asm/of_platform.h> |
@@ -41,12 +42,13 @@ | |||
41 | #include <asm/ucc_fast.h> | 42 | #include <asm/ucc_fast.h> |
42 | 43 | ||
43 | #include "ucc_geth.h" | 44 | #include "ucc_geth.h" |
44 | #include "ucc_geth_phy.h" | 45 | #include "ucc_geth_mii.h" |
45 | 46 | ||
46 | #undef DEBUG | 47 | #undef DEBUG |
47 | 48 | ||
48 | #define DRV_DESC "QE UCC Gigabit Ethernet Controller version:Sept 11, 2006" | 49 | #define DRV_DESC "QE UCC Gigabit Ethernet Controller" |
49 | #define DRV_NAME "ucc_geth" | 50 | #define DRV_NAME "ucc_geth" |
51 | #define DRV_VERSION "1.1" | ||
50 | 52 | ||
51 | #define ugeth_printk(level, format, arg...) \ | 53 | #define ugeth_printk(level, format, arg...) \ |
52 | printk(level format "\n", ## arg) | 54 | printk(level format "\n", ## arg) |
@@ -73,22 +75,13 @@ static struct ucc_geth_info ugeth_primary_info = { | |||
73 | .bd_mem_part = MEM_PART_SYSTEM, | 75 | .bd_mem_part = MEM_PART_SYSTEM, |
74 | .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, | 76 | .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, |
75 | .max_rx_buf_length = 1536, | 77 | .max_rx_buf_length = 1536, |
76 | /* FIXME: should be changed in run time for 1G and 100M */ | 78 | /* adjusted at startup if max-speed 1000 */ |
77 | #ifdef CONFIG_UGETH_HAS_GIGA | ||
78 | .urfs = UCC_GETH_URFS_GIGA_INIT, | ||
79 | .urfet = UCC_GETH_URFET_GIGA_INIT, | ||
80 | .urfset = UCC_GETH_URFSET_GIGA_INIT, | ||
81 | .utfs = UCC_GETH_UTFS_GIGA_INIT, | ||
82 | .utfet = UCC_GETH_UTFET_GIGA_INIT, | ||
83 | .utftt = UCC_GETH_UTFTT_GIGA_INIT, | ||
84 | #else | ||
85 | .urfs = UCC_GETH_URFS_INIT, | 79 | .urfs = UCC_GETH_URFS_INIT, |
86 | .urfet = UCC_GETH_URFET_INIT, | 80 | .urfet = UCC_GETH_URFET_INIT, |
87 | .urfset = UCC_GETH_URFSET_INIT, | 81 | .urfset = UCC_GETH_URFSET_INIT, |
88 | .utfs = UCC_GETH_UTFS_INIT, | 82 | .utfs = UCC_GETH_UTFS_INIT, |
89 | .utfet = UCC_GETH_UTFET_INIT, | 83 | .utfet = UCC_GETH_UTFET_INIT, |
90 | .utftt = UCC_GETH_UTFTT_INIT, | 84 | .utftt = UCC_GETH_UTFTT_INIT, |
91 | #endif | ||
92 | .ufpt = 256, | 85 | .ufpt = 256, |
93 | .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, | 86 | .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, |
94 | .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, | 87 | .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, |
@@ -217,70 +210,6 @@ static struct list_head *dequeue(struct list_head *lh) | |||
217 | } | 210 | } |
218 | } | 211 | } |
219 | 212 | ||
220 | static int get_interface_details(enum enet_interface enet_interface, | ||
221 | enum enet_speed *speed, | ||
222 | int *r10m, | ||
223 | int *rmm, | ||
224 | int *rpm, | ||
225 | int *tbi, int *limited_to_full_duplex) | ||
226 | { | ||
227 | /* Analyze enet_interface according to Interface Mode | ||
228 | Configuration table */ | ||
229 | switch (enet_interface) { | ||
230 | case ENET_10_MII: | ||
231 | *speed = ENET_SPEED_10BT; | ||
232 | break; | ||
233 | case ENET_10_RMII: | ||
234 | *speed = ENET_SPEED_10BT; | ||
235 | *r10m = 1; | ||
236 | *rmm = 1; | ||
237 | break; | ||
238 | case ENET_10_RGMII: | ||
239 | *speed = ENET_SPEED_10BT; | ||
240 | *rpm = 1; | ||
241 | *r10m = 1; | ||
242 | *limited_to_full_duplex = 1; | ||
243 | break; | ||
244 | case ENET_100_MII: | ||
245 | *speed = ENET_SPEED_100BT; | ||
246 | break; | ||
247 | case ENET_100_RMII: | ||
248 | *speed = ENET_SPEED_100BT; | ||
249 | *rmm = 1; | ||
250 | break; | ||
251 | case ENET_100_RGMII: | ||
252 | *speed = ENET_SPEED_100BT; | ||
253 | *rpm = 1; | ||
254 | *limited_to_full_duplex = 1; | ||
255 | break; | ||
256 | case ENET_1000_GMII: | ||
257 | *speed = ENET_SPEED_1000BT; | ||
258 | *limited_to_full_duplex = 1; | ||
259 | break; | ||
260 | case ENET_1000_RGMII: | ||
261 | *speed = ENET_SPEED_1000BT; | ||
262 | *rpm = 1; | ||
263 | *limited_to_full_duplex = 1; | ||
264 | break; | ||
265 | case ENET_1000_TBI: | ||
266 | *speed = ENET_SPEED_1000BT; | ||
267 | *tbi = 1; | ||
268 | *limited_to_full_duplex = 1; | ||
269 | break; | ||
270 | case ENET_1000_RTBI: | ||
271 | *speed = ENET_SPEED_1000BT; | ||
272 | *rpm = 1; | ||
273 | *tbi = 1; | ||
274 | *limited_to_full_duplex = 1; | ||
275 | break; | ||
276 | default: | ||
277 | return -EINVAL; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd) | 213 | static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd) |
285 | { | 214 | { |
286 | struct sk_buff *skb = NULL; | 215 | struct sk_buff *skb = NULL; |
@@ -758,24 +687,6 @@ static void dump_regs(struct ucc_geth_private *ugeth) | |||
758 | ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", | 687 | ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", |
759 | (u32) & ugeth->ug_regs->hafdup, | 688 | (u32) & ugeth->ug_regs->hafdup, |
760 | in_be32(&ugeth->ug_regs->hafdup)); | 689 | in_be32(&ugeth->ug_regs->hafdup)); |
761 | ugeth_info("miimcfg : addr - 0x%08x, val - 0x%08x", | ||
762 | (u32) & ugeth->ug_regs->miimng.miimcfg, | ||
763 | in_be32(&ugeth->ug_regs->miimng.miimcfg)); | ||
764 | ugeth_info("miimcom : addr - 0x%08x, val - 0x%08x", | ||
765 | (u32) & ugeth->ug_regs->miimng.miimcom, | ||
766 | in_be32(&ugeth->ug_regs->miimng.miimcom)); | ||
767 | ugeth_info("miimadd : addr - 0x%08x, val - 0x%08x", | ||
768 | (u32) & ugeth->ug_regs->miimng.miimadd, | ||
769 | in_be32(&ugeth->ug_regs->miimng.miimadd)); | ||
770 | ugeth_info("miimcon : addr - 0x%08x, val - 0x%08x", | ||
771 | (u32) & ugeth->ug_regs->miimng.miimcon, | ||
772 | in_be32(&ugeth->ug_regs->miimng.miimcon)); | ||
773 | ugeth_info("miimstat : addr - 0x%08x, val - 0x%08x", | ||
774 | (u32) & ugeth->ug_regs->miimng.miimstat, | ||
775 | in_be32(&ugeth->ug_regs->miimng.miimstat)); | ||
776 | ugeth_info("miimmind : addr - 0x%08x, val - 0x%08x", | ||
777 | (u32) & ugeth->ug_regs->miimng.miimind, | ||
778 | in_be32(&ugeth->ug_regs->miimng.miimind)); | ||
779 | ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x", | 690 | ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x", |
780 | (u32) & ugeth->ug_regs->ifctl, | 691 | (u32) & ugeth->ug_regs->ifctl, |
781 | in_be32(&ugeth->ug_regs->ifctl)); | 692 | in_be32(&ugeth->ug_regs->ifctl)); |
@@ -1425,27 +1336,6 @@ static int init_mac_station_addr_regs(u8 address_byte_0, | |||
1425 | return 0; | 1336 | return 0; |
1426 | } | 1337 | } |
1427 | 1338 | ||
1428 | static int init_mac_duplex_mode(int full_duplex, | ||
1429 | int limited_to_full_duplex, | ||
1430 | volatile u32 *maccfg2_register) | ||
1431 | { | ||
1432 | u32 value = 0; | ||
1433 | |||
1434 | /* some interfaces must work in full duplex mode */ | ||
1435 | if ((full_duplex == 0) && (limited_to_full_duplex == 1)) | ||
1436 | return -EINVAL; | ||
1437 | |||
1438 | value = in_be32(maccfg2_register); | ||
1439 | |||
1440 | if (full_duplex) | ||
1441 | value |= MACCFG2_FDX; | ||
1442 | else | ||
1443 | value &= ~MACCFG2_FDX; | ||
1444 | |||
1445 | out_be32(maccfg2_register, value); | ||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1449 | static int init_check_frame_length_mode(int length_check, | 1339 | static int init_check_frame_length_mode(int length_check, |
1450 | volatile u32 *maccfg2_register) | 1340 | volatile u32 *maccfg2_register) |
1451 | { | 1341 | { |
@@ -1477,40 +1367,6 @@ static int init_preamble_length(u8 preamble_length, | |||
1477 | return 0; | 1367 | return 0; |
1478 | } | 1368 | } |
1479 | 1369 | ||
1480 | static int init_mii_management_configuration(int reset_mgmt, | ||
1481 | int preamble_supress, | ||
1482 | volatile u32 *miimcfg_register, | ||
1483 | volatile u32 *miimind_register) | ||
1484 | { | ||
1485 | unsigned int timeout = PHY_INIT_TIMEOUT; | ||
1486 | u32 value = 0; | ||
1487 | |||
1488 | value = in_be32(miimcfg_register); | ||
1489 | if (reset_mgmt) { | ||
1490 | value |= MIIMCFG_RESET_MANAGEMENT; | ||
1491 | out_be32(miimcfg_register, value); | ||
1492 | } | ||
1493 | |||
1494 | value = 0; | ||
1495 | |||
1496 | if (preamble_supress) | ||
1497 | value |= MIIMCFG_NO_PREAMBLE; | ||
1498 | |||
1499 | value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT; | ||
1500 | out_be32(miimcfg_register, value); | ||
1501 | |||
1502 | /* Wait until the bus is free */ | ||
1503 | while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--) | ||
1504 | cpu_relax(); | ||
1505 | |||
1506 | if (timeout <= 0) { | ||
1507 | ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__); | ||
1508 | return -ETIMEDOUT; | ||
1509 | } | ||
1510 | |||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | static int init_rx_parameters(int reject_broadcast, | 1370 | static int init_rx_parameters(int reject_broadcast, |
1515 | int receive_short_frames, | 1371 | int receive_short_frames, |
1516 | int promiscuous, volatile u32 *upsmr_register) | 1372 | int promiscuous, volatile u32 *upsmr_register) |
@@ -1570,10 +1426,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1570 | struct ucc_geth_info *ug_info; | 1426 | struct ucc_geth_info *ug_info; |
1571 | struct ucc_geth *ug_regs; | 1427 | struct ucc_geth *ug_regs; |
1572 | struct ucc_fast *uf_regs; | 1428 | struct ucc_fast *uf_regs; |
1573 | enum enet_speed speed; | 1429 | int ret_val; |
1574 | int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm = | 1430 | u32 upsmr, maccfg2, tbiBaseAddress; |
1575 | 0, limited_to_full_duplex = 0; | ||
1576 | u32 upsmr, maccfg2, utbipar, tbiBaseAddress; | ||
1577 | u16 value; | 1431 | u16 value; |
1578 | 1432 | ||
1579 | ugeth_vdbg("%s: IN", __FUNCTION__); | 1433 | ugeth_vdbg("%s: IN", __FUNCTION__); |
@@ -1582,24 +1436,13 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1582 | ug_regs = ugeth->ug_regs; | 1436 | ug_regs = ugeth->ug_regs; |
1583 | uf_regs = ugeth->uccf->uf_regs; | 1437 | uf_regs = ugeth->uccf->uf_regs; |
1584 | 1438 | ||
1585 | /* Analyze enet_interface according to Interface Mode Configuration | ||
1586 | table */ | ||
1587 | ret_val = | ||
1588 | get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm, | ||
1589 | &rpm, &tbi, &limited_to_full_duplex); | ||
1590 | if (ret_val != 0) { | ||
1591 | ugeth_err | ||
1592 | ("%s: half duplex not supported in requested configuration.", | ||
1593 | __FUNCTION__); | ||
1594 | return ret_val; | ||
1595 | } | ||
1596 | |||
1597 | /* Set MACCFG2 */ | 1439 | /* Set MACCFG2 */ |
1598 | maccfg2 = in_be32(&ug_regs->maccfg2); | 1440 | maccfg2 = in_be32(&ug_regs->maccfg2); |
1599 | maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; | 1441 | maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; |
1600 | if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT)) | 1442 | if ((ugeth->max_speed == SPEED_10) || |
1443 | (ugeth->max_speed == SPEED_100)) | ||
1601 | maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; | 1444 | maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; |
1602 | else if (speed == ENET_SPEED_1000BT) | 1445 | else if (ugeth->max_speed == SPEED_1000) |
1603 | maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; | 1446 | maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; |
1604 | maccfg2 |= ug_info->padAndCrc; | 1447 | maccfg2 |= ug_info->padAndCrc; |
1605 | out_be32(&ug_regs->maccfg2, maccfg2); | 1448 | out_be32(&ug_regs->maccfg2, maccfg2); |
@@ -1607,54 +1450,39 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1607 | /* Set UPSMR */ | 1450 | /* Set UPSMR */ |
1608 | upsmr = in_be32(&uf_regs->upsmr); | 1451 | upsmr = in_be32(&uf_regs->upsmr); |
1609 | upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); | 1452 | upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); |
1610 | if (rpm) | 1453 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || |
1454 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || | ||
1455 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || | ||
1456 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1611 | upsmr |= UPSMR_RPM; | 1457 | upsmr |= UPSMR_RPM; |
1612 | if (r10m) | 1458 | switch (ugeth->max_speed) { |
1613 | upsmr |= UPSMR_R10M; | 1459 | case SPEED_10: |
1614 | if (tbi) | 1460 | upsmr |= UPSMR_R10M; |
1461 | /* FALLTHROUGH */ | ||
1462 | case SPEED_100: | ||
1463 | if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) | ||
1464 | upsmr |= UPSMR_RMM; | ||
1465 | } | ||
1466 | } | ||
1467 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || | ||
1468 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1615 | upsmr |= UPSMR_TBIM; | 1469 | upsmr |= UPSMR_TBIM; |
1616 | if (rmm) | 1470 | } |
1617 | upsmr |= UPSMR_RMM; | ||
1618 | out_be32(&uf_regs->upsmr, upsmr); | 1471 | out_be32(&uf_regs->upsmr, upsmr); |
1619 | 1472 | ||
1620 | /* Set UTBIPAR */ | ||
1621 | utbipar = in_be32(&ug_regs->utbipar); | ||
1622 | utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK; | ||
1623 | if (tbi) | ||
1624 | utbipar |= | ||
1625 | (ug_info->phy_address + | ||
1626 | ugeth->ug_info->uf_info. | ||
1627 | ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; | ||
1628 | else | ||
1629 | utbipar |= | ||
1630 | (0x10 + | ||
1631 | ugeth->ug_info->uf_info. | ||
1632 | ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; | ||
1633 | out_be32(&ug_regs->utbipar, utbipar); | ||
1634 | |||
1635 | /* Disable autonegotiation in tbi mode, because by default it | 1473 | /* Disable autonegotiation in tbi mode, because by default it |
1636 | comes up in autonegotiation mode. */ | 1474 | comes up in autonegotiation mode. */ |
1637 | /* Note that this depends on proper setting in utbipar register. */ | 1475 | /* Note that this depends on proper setting in utbipar register. */ |
1638 | if (tbi) { | 1476 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || |
1477 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1639 | tbiBaseAddress = in_be32(&ug_regs->utbipar); | 1478 | tbiBaseAddress = in_be32(&ug_regs->utbipar); |
1640 | tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; | 1479 | tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; |
1641 | tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; | 1480 | tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; |
1642 | value = | 1481 | value = ugeth->phydev->bus->read(ugeth->phydev->bus, |
1643 | ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress, | 1482 | (u8) tbiBaseAddress, ENET_TBI_MII_CR); |
1644 | ENET_TBI_MII_CR); | ||
1645 | value &= ~0x1000; /* Turn off autonegotiation */ | 1483 | value &= ~0x1000; /* Turn off autonegotiation */ |
1646 | ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress, | 1484 | ugeth->phydev->bus->write(ugeth->phydev->bus, |
1647 | ENET_TBI_MII_CR, value); | 1485 | (u8) tbiBaseAddress, ENET_TBI_MII_CR, value); |
1648 | } | ||
1649 | |||
1650 | ret_val = init_mac_duplex_mode(1, | ||
1651 | limited_to_full_duplex, | ||
1652 | &ug_regs->maccfg2); | ||
1653 | if (ret_val != 0) { | ||
1654 | ugeth_err | ||
1655 | ("%s: half duplex not supported in requested configuration.", | ||
1656 | __FUNCTION__); | ||
1657 | return ret_val; | ||
1658 | } | 1486 | } |
1659 | 1487 | ||
1660 | init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); | 1488 | init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); |
@@ -1676,76 +1504,88 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1676 | * function converts those variables into the appropriate | 1504 | * function converts those variables into the appropriate |
1677 | * register values, and can bring down the device if needed. | 1505 | * register values, and can bring down the device if needed. |
1678 | */ | 1506 | */ |
1507 | |||
1679 | static void adjust_link(struct net_device *dev) | 1508 | static void adjust_link(struct net_device *dev) |
1680 | { | 1509 | { |
1681 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 1510 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
1682 | struct ucc_geth *ug_regs; | 1511 | struct ucc_geth *ug_regs; |
1683 | u32 tempval; | 1512 | struct ucc_fast *uf_regs; |
1684 | struct ugeth_mii_info *mii_info = ugeth->mii_info; | 1513 | struct phy_device *phydev = ugeth->phydev; |
1514 | unsigned long flags; | ||
1515 | int new_state = 0; | ||
1685 | 1516 | ||
1686 | ug_regs = ugeth->ug_regs; | 1517 | ug_regs = ugeth->ug_regs; |
1518 | uf_regs = ugeth->uccf->uf_regs; | ||
1687 | 1519 | ||
1688 | if (mii_info->link) { | 1520 | spin_lock_irqsave(&ugeth->lock, flags); |
1521 | |||
1522 | if (phydev->link) { | ||
1523 | u32 tempval = in_be32(&ug_regs->maccfg2); | ||
1524 | u32 upsmr = in_be32(&uf_regs->upsmr); | ||
1689 | /* Now we make sure that we can be in full duplex mode. | 1525 | /* Now we make sure that we can be in full duplex mode. |
1690 | * If not, we operate in half-duplex mode. */ | 1526 | * If not, we operate in half-duplex mode. */ |
1691 | if (mii_info->duplex != ugeth->oldduplex) { | 1527 | if (phydev->duplex != ugeth->oldduplex) { |
1692 | if (!(mii_info->duplex)) { | 1528 | new_state = 1; |
1693 | tempval = in_be32(&ug_regs->maccfg2); | 1529 | if (!(phydev->duplex)) |
1694 | tempval &= ~(MACCFG2_FDX); | 1530 | tempval &= ~(MACCFG2_FDX); |
1695 | out_be32(&ug_regs->maccfg2, tempval); | 1531 | else |
1696 | |||
1697 | ugeth_info("%s: Half Duplex", dev->name); | ||
1698 | } else { | ||
1699 | tempval = in_be32(&ug_regs->maccfg2); | ||
1700 | tempval |= MACCFG2_FDX; | 1532 | tempval |= MACCFG2_FDX; |
1701 | out_be32(&ug_regs->maccfg2, tempval); | 1533 | ugeth->oldduplex = phydev->duplex; |
1702 | |||
1703 | ugeth_info("%s: Full Duplex", dev->name); | ||
1704 | } | ||
1705 | |||
1706 | ugeth->oldduplex = mii_info->duplex; | ||
1707 | } | 1534 | } |
1708 | 1535 | ||
1709 | if (mii_info->speed != ugeth->oldspeed) { | 1536 | if (phydev->speed != ugeth->oldspeed) { |
1710 | switch (mii_info->speed) { | 1537 | new_state = 1; |
1711 | case 1000: | 1538 | switch (phydev->speed) { |
1712 | ugeth->ug_info->enet_interface = ENET_1000_RGMII; | 1539 | case SPEED_1000: |
1540 | tempval = ((tempval & | ||
1541 | ~(MACCFG2_INTERFACE_MODE_MASK)) | | ||
1542 | MACCFG2_INTERFACE_MODE_BYTE); | ||
1713 | break; | 1543 | break; |
1714 | case 100: | 1544 | case SPEED_100: |
1715 | ugeth->ug_info->enet_interface = ENET_100_RGMII; | 1545 | case SPEED_10: |
1716 | break; | 1546 | tempval = ((tempval & |
1717 | case 10: | 1547 | ~(MACCFG2_INTERFACE_MODE_MASK)) | |
1718 | ugeth->ug_info->enet_interface = ENET_10_RGMII; | 1548 | MACCFG2_INTERFACE_MODE_NIBBLE); |
1549 | /* if reduced mode, re-set UPSMR.R10M */ | ||
1550 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || | ||
1551 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || | ||
1552 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || | ||
1553 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1554 | if (phydev->speed == SPEED_10) | ||
1555 | upsmr |= UPSMR_R10M; | ||
1556 | else | ||
1557 | upsmr &= ~(UPSMR_R10M); | ||
1558 | } | ||
1719 | break; | 1559 | break; |
1720 | default: | 1560 | default: |
1721 | ugeth_warn | 1561 | if (netif_msg_link(ugeth)) |
1722 | ("%s: Ack! Speed (%d) is not 10/100/1000!", | 1562 | ugeth_warn( |
1723 | dev->name, mii_info->speed); | 1563 | "%s: Ack! Speed (%d) is not 10/100/1000!", |
1564 | dev->name, phydev->speed); | ||
1724 | break; | 1565 | break; |
1725 | } | 1566 | } |
1726 | adjust_enet_interface(ugeth); | 1567 | ugeth->oldspeed = phydev->speed; |
1727 | |||
1728 | ugeth_info("%s: Speed %dBT", dev->name, | ||
1729 | mii_info->speed); | ||
1730 | |||
1731 | ugeth->oldspeed = mii_info->speed; | ||
1732 | } | 1568 | } |
1733 | 1569 | ||
1570 | out_be32(&ug_regs->maccfg2, tempval); | ||
1571 | out_be32(&uf_regs->upsmr, upsmr); | ||
1572 | |||
1734 | if (!ugeth->oldlink) { | 1573 | if (!ugeth->oldlink) { |
1735 | ugeth_info("%s: Link is up", dev->name); | 1574 | new_state = 1; |
1736 | ugeth->oldlink = 1; | 1575 | ugeth->oldlink = 1; |
1737 | netif_carrier_on(dev); | ||
1738 | netif_schedule(dev); | 1576 | netif_schedule(dev); |
1739 | } | 1577 | } |
1740 | } else { | 1578 | } else if (ugeth->oldlink) { |
1741 | if (ugeth->oldlink) { | 1579 | new_state = 1; |
1742 | ugeth_info("%s: Link is down", dev->name); | ||
1743 | ugeth->oldlink = 0; | 1580 | ugeth->oldlink = 0; |
1744 | ugeth->oldspeed = 0; | 1581 | ugeth->oldspeed = 0; |
1745 | ugeth->oldduplex = -1; | 1582 | ugeth->oldduplex = -1; |
1746 | netif_carrier_off(dev); | ||
1747 | } | ||
1748 | } | 1583 | } |
1584 | |||
1585 | if (new_state && netif_msg_link(ugeth)) | ||
1586 | phy_print_status(phydev); | ||
1587 | |||
1588 | spin_unlock_irqrestore(&ugeth->lock, flags); | ||
1749 | } | 1589 | } |
1750 | 1590 | ||
1751 | /* Configure the PHY for dev. | 1591 | /* Configure the PHY for dev. |
@@ -1753,102 +1593,40 @@ static void adjust_link(struct net_device *dev) | |||
1753 | */ | 1593 | */ |
1754 | static int init_phy(struct net_device *dev) | 1594 | static int init_phy(struct net_device *dev) |
1755 | { | 1595 | { |
1756 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 1596 | struct ucc_geth_private *priv = netdev_priv(dev); |
1757 | struct phy_info *curphy; | 1597 | struct phy_device *phydev; |
1758 | struct ucc_mii_mng *mii_regs; | 1598 | char phy_id[BUS_ID_SIZE]; |
1759 | struct ugeth_mii_info *mii_info; | ||
1760 | int err; | ||
1761 | 1599 | ||
1762 | mii_regs = &ugeth->ug_regs->miimng; | 1600 | priv->oldlink = 0; |
1601 | priv->oldspeed = 0; | ||
1602 | priv->oldduplex = -1; | ||
1763 | 1603 | ||
1764 | ugeth->oldlink = 0; | 1604 | snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus, |
1765 | ugeth->oldspeed = 0; | 1605 | priv->ug_info->phy_address); |
1766 | ugeth->oldduplex = -1; | ||
1767 | 1606 | ||
1768 | mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL); | 1607 | phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); |
1769 | 1608 | ||
1770 | if (NULL == mii_info) { | 1609 | if (IS_ERR(phydev)) { |
1771 | ugeth_err("%s: Could not allocate mii_info", dev->name); | 1610 | printk("%s: Could not attach to PHY\n", dev->name); |
1772 | return -ENOMEM; | 1611 | return PTR_ERR(phydev); |
1773 | } | 1612 | } |
1774 | 1613 | ||
1775 | mii_info->mii_regs = mii_regs; | 1614 | phydev->supported &= (ADVERTISED_10baseT_Half | |
1776 | mii_info->speed = SPEED_1000; | ||
1777 | mii_info->duplex = DUPLEX_FULL; | ||
1778 | mii_info->pause = 0; | ||
1779 | mii_info->link = 0; | ||
1780 | |||
1781 | mii_info->advertising = (ADVERTISED_10baseT_Half | | ||
1782 | ADVERTISED_10baseT_Full | | 1615 | ADVERTISED_10baseT_Full | |
1783 | ADVERTISED_100baseT_Half | | 1616 | ADVERTISED_100baseT_Half | |
1784 | ADVERTISED_100baseT_Full | | 1617 | ADVERTISED_100baseT_Full); |
1785 | ADVERTISED_1000baseT_Full); | ||
1786 | mii_info->autoneg = 1; | ||
1787 | 1618 | ||
1788 | mii_info->mii_id = ugeth->ug_info->phy_address; | 1619 | if (priv->max_speed == SPEED_1000) |
1620 | phydev->supported |= ADVERTISED_1000baseT_Full; | ||
1789 | 1621 | ||
1790 | mii_info->dev = dev; | 1622 | phydev->advertising = phydev->supported; |
1791 | 1623 | ||
1792 | mii_info->mdio_read = &read_phy_reg; | 1624 | priv->phydev = phydev; |
1793 | mii_info->mdio_write = &write_phy_reg; | ||
1794 | |||
1795 | spin_lock_init(&mii_info->mdio_lock); | ||
1796 | |||
1797 | ugeth->mii_info = mii_info; | ||
1798 | |||
1799 | spin_lock_irq(&ugeth->lock); | ||
1800 | |||
1801 | /* Set this UCC to be the master of the MII managment */ | ||
1802 | ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num); | ||
1803 | |||
1804 | if (init_mii_management_configuration(1, | ||
1805 | ugeth->ug_info-> | ||
1806 | miiPreambleSupress, | ||
1807 | &mii_regs->miimcfg, | ||
1808 | &mii_regs->miimind)) { | ||
1809 | ugeth_err("%s: The MII Bus is stuck!", dev->name); | ||
1810 | err = -1; | ||
1811 | goto bus_fail; | ||
1812 | } | ||
1813 | |||
1814 | spin_unlock_irq(&ugeth->lock); | ||
1815 | |||
1816 | /* get info for this PHY */ | ||
1817 | curphy = get_phy_info(ugeth->mii_info); | ||
1818 | |||
1819 | if (curphy == NULL) { | ||
1820 | ugeth_err("%s: No PHY found", dev->name); | ||
1821 | err = -1; | ||
1822 | goto no_phy; | ||
1823 | } | ||
1824 | |||
1825 | mii_info->phyinfo = curphy; | ||
1826 | |||
1827 | /* Run the commands which initialize the PHY */ | ||
1828 | if (curphy->init) { | ||
1829 | err = curphy->init(ugeth->mii_info); | ||
1830 | if (err) | ||
1831 | goto phy_init_fail; | ||
1832 | } | ||
1833 | 1625 | ||
1834 | return 0; | 1626 | return 0; |
1835 | |||
1836 | phy_init_fail: | ||
1837 | no_phy: | ||
1838 | bus_fail: | ||
1839 | kfree(mii_info); | ||
1840 | |||
1841 | return err; | ||
1842 | } | 1627 | } |
1843 | 1628 | ||
1844 | #ifdef CONFIG_UGETH_TX_ON_DEMOND | ||
1845 | static int ugeth_transmit_on_demand(struct ucc_geth_private *ugeth) | ||
1846 | { | ||
1847 | struct ucc_fastransmit_on_demand(ugeth->uccf); | ||
1848 | 1629 | ||
1849 | return 0; | ||
1850 | } | ||
1851 | #endif | ||
1852 | 1630 | ||
1853 | static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) | 1631 | static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) |
1854 | { | 1632 | { |
@@ -2356,6 +2134,8 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) | |||
2356 | } | 2134 | } |
2357 | for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { | 2135 | for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { |
2358 | bd = ugeth->p_tx_bd_ring[i]; | 2136 | bd = ugeth->p_tx_bd_ring[i]; |
2137 | if (!bd) | ||
2138 | continue; | ||
2359 | for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { | 2139 | for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { |
2360 | if (ugeth->tx_skbuff[i][j]) { | 2140 | if (ugeth->tx_skbuff[i][j]) { |
2361 | dma_unmap_single(NULL, | 2141 | dma_unmap_single(NULL, |
@@ -2487,6 +2267,7 @@ static void ucc_geth_set_multi(struct net_device *dev) | |||
2487 | static void ucc_geth_stop(struct ucc_geth_private *ugeth) | 2267 | static void ucc_geth_stop(struct ucc_geth_private *ugeth) |
2488 | { | 2268 | { |
2489 | struct ucc_geth *ug_regs = ugeth->ug_regs; | 2269 | struct ucc_geth *ug_regs = ugeth->ug_regs; |
2270 | struct phy_device *phydev = ugeth->phydev; | ||
2490 | u32 tempval; | 2271 | u32 tempval; |
2491 | 2272 | ||
2492 | ugeth_vdbg("%s: IN", __FUNCTION__); | 2273 | ugeth_vdbg("%s: IN", __FUNCTION__); |
@@ -2495,8 +2276,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) | |||
2495 | ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); | 2276 | ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); |
2496 | 2277 | ||
2497 | /* Tell the kernel the link is down */ | 2278 | /* Tell the kernel the link is down */ |
2498 | ugeth->mii_info->link = 0; | 2279 | phy_stop(phydev); |
2499 | adjust_link(ugeth->dev); | ||
2500 | 2280 | ||
2501 | /* Mask all interrupts */ | 2281 | /* Mask all interrupts */ |
2502 | out_be32(ugeth->uccf->p_ucce, 0x00000000); | 2282 | out_be32(ugeth->uccf->p_ucce, 0x00000000); |
@@ -2509,50 +2289,24 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) | |||
2509 | tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); | 2289 | tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); |
2510 | out_be32(&ug_regs->maccfg1, tempval); | 2290 | out_be32(&ug_regs->maccfg1, tempval); |
2511 | 2291 | ||
2512 | if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { | ||
2513 | /* Clear any pending interrupts */ | ||
2514 | mii_clear_phy_interrupt(ugeth->mii_info); | ||
2515 | |||
2516 | /* Disable PHY Interrupts */ | ||
2517 | mii_configure_phy_interrupt(ugeth->mii_info, | ||
2518 | MII_INTERRUPT_DISABLED); | ||
2519 | } | ||
2520 | |||
2521 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); | 2292 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); |
2522 | 2293 | ||
2523 | if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { | ||
2524 | free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev); | ||
2525 | } else { | ||
2526 | del_timer_sync(&ugeth->phy_info_timer); | ||
2527 | } | ||
2528 | |||
2529 | ucc_geth_memclean(ugeth); | 2294 | ucc_geth_memclean(ugeth); |
2530 | } | 2295 | } |
2531 | 2296 | ||
2532 | static int ucc_geth_startup(struct ucc_geth_private *ugeth) | 2297 | static int ucc_struct_init(struct ucc_geth_private *ugeth) |
2533 | { | 2298 | { |
2534 | struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; | ||
2535 | struct ucc_geth_init_pram *p_init_enet_pram; | ||
2536 | struct ucc_fast_private *uccf; | ||
2537 | struct ucc_geth_info *ug_info; | 2299 | struct ucc_geth_info *ug_info; |
2538 | struct ucc_fast_info *uf_info; | 2300 | struct ucc_fast_info *uf_info; |
2539 | struct ucc_fast *uf_regs; | 2301 | int i; |
2540 | struct ucc_geth *ug_regs; | ||
2541 | int ret_val = -EINVAL; | ||
2542 | u32 remoder = UCC_GETH_REMODER_INIT; | ||
2543 | u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; | ||
2544 | u32 ifstat, i, j, size, l2qt, l3qt, length; | ||
2545 | u16 temoder = UCC_GETH_TEMODER_INIT; | ||
2546 | u16 test; | ||
2547 | u8 function_code = 0; | ||
2548 | u8 *bd, *endOfRing; | ||
2549 | u8 numThreadsRxNumerical, numThreadsTxNumerical; | ||
2550 | |||
2551 | ugeth_vdbg("%s: IN", __FUNCTION__); | ||
2552 | 2302 | ||
2553 | ug_info = ugeth->ug_info; | 2303 | ug_info = ugeth->ug_info; |
2554 | uf_info = &ug_info->uf_info; | 2304 | uf_info = &ug_info->uf_info; |
2555 | 2305 | ||
2306 | /* Create CQs for hash tables */ | ||
2307 | INIT_LIST_HEAD(&ugeth->group_hash_q); | ||
2308 | INIT_LIST_HEAD(&ugeth->ind_hash_q); | ||
2309 | |||
2556 | if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || | 2310 | if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || |
2557 | (uf_info->bd_mem_part == MEM_PART_MURAM))) { | 2311 | (uf_info->bd_mem_part == MEM_PART_MURAM))) { |
2558 | ugeth_err("%s: Bad memory partition value.", __FUNCTION__); | 2312 | ugeth_err("%s: Bad memory partition value.", __FUNCTION__); |
@@ -2647,12 +2401,42 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2647 | for (i = 0; i < ug_info->numQueuesTx; i++) | 2401 | for (i = 0; i < ug_info->numQueuesTx; i++) |
2648 | uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); | 2402 | uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); |
2649 | /* Initialize the general fast UCC block. */ | 2403 | /* Initialize the general fast UCC block. */ |
2650 | if (ucc_fast_init(uf_info, &uccf)) { | 2404 | if (ucc_fast_init(uf_info, &ugeth->uccf)) { |
2651 | ugeth_err("%s: Failed to init uccf.", __FUNCTION__); | 2405 | ugeth_err("%s: Failed to init uccf.", __FUNCTION__); |
2652 | ucc_geth_memclean(ugeth); | 2406 | ucc_geth_memclean(ugeth); |
2653 | return -ENOMEM; | 2407 | return -ENOMEM; |
2654 | } | 2408 | } |
2655 | ugeth->uccf = uccf; | 2409 | |
2410 | ugeth->ug_regs = (struct ucc_geth *) ioremap(uf_info->regs, sizeof(struct ucc_geth)); | ||
2411 | |||
2412 | return 0; | ||
2413 | } | ||
2414 | |||
2415 | static int ucc_geth_startup(struct ucc_geth_private *ugeth) | ||
2416 | { | ||
2417 | struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; | ||
2418 | struct ucc_geth_init_pram *p_init_enet_pram; | ||
2419 | struct ucc_fast_private *uccf; | ||
2420 | struct ucc_geth_info *ug_info; | ||
2421 | struct ucc_fast_info *uf_info; | ||
2422 | struct ucc_fast *uf_regs; | ||
2423 | struct ucc_geth *ug_regs; | ||
2424 | int ret_val = -EINVAL; | ||
2425 | u32 remoder = UCC_GETH_REMODER_INIT; | ||
2426 | u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; | ||
2427 | u32 ifstat, i, j, size, l2qt, l3qt, length; | ||
2428 | u16 temoder = UCC_GETH_TEMODER_INIT; | ||
2429 | u16 test; | ||
2430 | u8 function_code = 0; | ||
2431 | u8 *bd, *endOfRing; | ||
2432 | u8 numThreadsRxNumerical, numThreadsTxNumerical; | ||
2433 | |||
2434 | ugeth_vdbg("%s: IN", __FUNCTION__); | ||
2435 | uccf = ugeth->uccf; | ||
2436 | ug_info = ugeth->ug_info; | ||
2437 | uf_info = &ug_info->uf_info; | ||
2438 | uf_regs = uccf->uf_regs; | ||
2439 | ug_regs = ugeth->ug_regs; | ||
2656 | 2440 | ||
2657 | switch (ug_info->numThreadsRx) { | 2441 | switch (ug_info->numThreadsRx) { |
2658 | case UCC_GETH_NUM_OF_THREADS_1: | 2442 | case UCC_GETH_NUM_OF_THREADS_1: |
@@ -2711,10 +2495,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2711 | || (ug_info->vlanOperationNonTagged != | 2495 | || (ug_info->vlanOperationNonTagged != |
2712 | UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); | 2496 | UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); |
2713 | 2497 | ||
2714 | uf_regs = uccf->uf_regs; | ||
2715 | ug_regs = (struct ucc_geth *) (uccf->uf_regs); | ||
2716 | ugeth->ug_regs = ug_regs; | ||
2717 | |||
2718 | init_default_reg_vals(&uf_regs->upsmr, | 2498 | init_default_reg_vals(&uf_regs->upsmr, |
2719 | &ug_regs->maccfg1, &ug_regs->maccfg2); | 2499 | &ug_regs->maccfg1, &ug_regs->maccfg2); |
2720 | 2500 | ||
@@ -3177,8 +2957,8 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3177 | /* Size varies with number of Rx queues */ | 2957 | /* Size varies with number of Rx queues */ |
3178 | ugeth->rx_irq_coalescing_tbl_offset = | 2958 | ugeth->rx_irq_coalescing_tbl_offset = |
3179 | qe_muram_alloc(ug_info->numQueuesRx * | 2959 | qe_muram_alloc(ug_info->numQueuesRx * |
3180 | sizeof(struct ucc_geth_rx_interrupt_coalescing_entry), | 2960 | sizeof(struct ucc_geth_rx_interrupt_coalescing_entry) |
3181 | UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); | 2961 | + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); |
3182 | if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) { | 2962 | if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) { |
3183 | ugeth_err | 2963 | ugeth_err |
3184 | ("%s: Can not allocate DPRAM memory for" | 2964 | ("%s: Can not allocate DPRAM memory for" |
@@ -3359,13 +3139,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
3359 | for (j = 0; j < NUM_OF_PADDRS; j++) | 3139 | for (j = 0; j < NUM_OF_PADDRS; j++) |
3360 | ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j); | 3140 | ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j); |
3361 | 3141 | ||
3362 | /* Create CQs for hash tables */ | ||
3363 | if (ug_info->maxGroupAddrInHash > 0) { | ||
3364 | INIT_LIST_HEAD(&ugeth->group_hash_q); | ||
3365 | } | ||
3366 | if (ug_info->maxIndAddrInHash > 0) { | ||
3367 | INIT_LIST_HEAD(&ugeth->ind_hash_q); | ||
3368 | } | ||
3369 | p_82xx_addr_filt = | 3142 | p_82xx_addr_filt = |
3370 | (struct ucc_geth_82xx_address_filtering_pram *) ugeth-> | 3143 | (struct ucc_geth_82xx_address_filtering_pram *) ugeth-> |
3371 | p_rx_glbl_pram->addressfiltering; | 3144 | p_rx_glbl_pram->addressfiltering; |
@@ -3562,6 +3335,9 @@ static void ucc_geth_timeout(struct net_device *dev) | |||
3562 | static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) | 3335 | static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) |
3563 | { | 3336 | { |
3564 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 3337 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
3338 | #ifdef CONFIG_UGETH_TX_ON_DEMAND | ||
3339 | struct ucc_fast_private *uccf; | ||
3340 | #endif | ||
3565 | u8 *bd; /* BD pointer */ | 3341 | u8 *bd; /* BD pointer */ |
3566 | u32 bd_status; | 3342 | u32 bd_status; |
3567 | u8 txQ = 0; | 3343 | u8 txQ = 0; |
@@ -3620,6 +3396,10 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3620 | out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]); | 3396 | out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]); |
3621 | } | 3397 | } |
3622 | 3398 | ||
3399 | #ifdef CONFIG_UGETH_TX_ON_DEMAND | ||
3400 | uccf = ugeth->uccf; | ||
3401 | out_be16(uccf->p_utodr, UCC_FAST_TOD); | ||
3402 | #endif | ||
3623 | spin_unlock_irq(&ugeth->lock); | 3403 | spin_unlock_irq(&ugeth->lock); |
3624 | 3404 | ||
3625 | return 0; | 3405 | return 0; |
@@ -3635,7 +3415,6 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit | |||
3635 | 3415 | ||
3636 | ugeth_vdbg("%s: IN", __FUNCTION__); | 3416 | ugeth_vdbg("%s: IN", __FUNCTION__); |
3637 | 3417 | ||
3638 | spin_lock(&ugeth->lock); | ||
3639 | /* collect received buffers */ | 3418 | /* collect received buffers */ |
3640 | bd = ugeth->rxBd[rxQ]; | 3419 | bd = ugeth->rxBd[rxQ]; |
3641 | 3420 | ||
@@ -3683,7 +3462,6 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit | |||
3683 | skb = get_new_skb(ugeth, bd); | 3462 | skb = get_new_skb(ugeth, bd); |
3684 | if (!skb) { | 3463 | if (!skb) { |
3685 | ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); | 3464 | ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); |
3686 | spin_unlock(&ugeth->lock); | ||
3687 | ugeth->stats.rx_dropped++; | 3465 | ugeth->stats.rx_dropped++; |
3688 | break; | 3466 | break; |
3689 | } | 3467 | } |
@@ -3704,7 +3482,6 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit | |||
3704 | } | 3482 | } |
3705 | 3483 | ||
3706 | ugeth->rxBd[rxQ] = bd; | 3484 | ugeth->rxBd[rxQ] = bd; |
3707 | spin_unlock(&ugeth->lock); | ||
3708 | return howmany; | 3485 | return howmany; |
3709 | } | 3486 | } |
3710 | 3487 | ||
@@ -3756,23 +3533,38 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) | |||
3756 | static int ucc_geth_poll(struct net_device *dev, int *budget) | 3533 | static int ucc_geth_poll(struct net_device *dev, int *budget) |
3757 | { | 3534 | { |
3758 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 3535 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
3536 | struct ucc_geth_info *ug_info; | ||
3537 | struct ucc_fast_private *uccf; | ||
3759 | int howmany; | 3538 | int howmany; |
3760 | int rx_work_limit = *budget; | 3539 | u8 i; |
3761 | u8 rxQ = 0; | 3540 | int rx_work_limit; |
3541 | register u32 uccm; | ||
3542 | |||
3543 | ug_info = ugeth->ug_info; | ||
3762 | 3544 | ||
3545 | rx_work_limit = *budget; | ||
3763 | if (rx_work_limit > dev->quota) | 3546 | if (rx_work_limit > dev->quota) |
3764 | rx_work_limit = dev->quota; | 3547 | rx_work_limit = dev->quota; |
3765 | 3548 | ||
3766 | howmany = ucc_geth_rx(ugeth, rxQ, rx_work_limit); | 3549 | howmany = 0; |
3550 | |||
3551 | for (i = 0; i < ug_info->numQueuesRx; i++) { | ||
3552 | howmany += ucc_geth_rx(ugeth, i, rx_work_limit); | ||
3553 | } | ||
3767 | 3554 | ||
3768 | dev->quota -= howmany; | 3555 | dev->quota -= howmany; |
3769 | rx_work_limit -= howmany; | 3556 | rx_work_limit -= howmany; |
3770 | *budget -= howmany; | 3557 | *budget -= howmany; |
3771 | 3558 | ||
3772 | if (rx_work_limit >= 0) | 3559 | if (rx_work_limit > 0) { |
3773 | netif_rx_complete(dev); | 3560 | netif_rx_complete(dev); |
3561 | uccf = ugeth->uccf; | ||
3562 | uccm = in_be32(uccf->p_uccm); | ||
3563 | uccm |= UCCE_RX_EVENTS; | ||
3564 | out_be32(uccf->p_uccm, uccm); | ||
3565 | } | ||
3774 | 3566 | ||
3775 | return (rx_work_limit < 0) ? 1 : 0; | 3567 | return (rx_work_limit > 0) ? 0 : 1; |
3776 | } | 3568 | } |
3777 | #endif /* CONFIG_UGETH_NAPI */ | 3569 | #endif /* CONFIG_UGETH_NAPI */ |
3778 | 3570 | ||
@@ -3782,10 +3574,13 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) | |||
3782 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 3574 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
3783 | struct ucc_fast_private *uccf; | 3575 | struct ucc_fast_private *uccf; |
3784 | struct ucc_geth_info *ug_info; | 3576 | struct ucc_geth_info *ug_info; |
3785 | register u32 ucce = 0; | 3577 | register u32 ucce; |
3786 | register u32 bit_mask = UCCE_RXBF_SINGLE_MASK; | 3578 | register u32 uccm; |
3787 | register u32 tx_mask = UCCE_TXBF_SINGLE_MASK; | 3579 | #ifndef CONFIG_UGETH_NAPI |
3788 | register u8 i; | 3580 | register u32 rx_mask; |
3581 | #endif | ||
3582 | register u32 tx_mask; | ||
3583 | u8 i; | ||
3789 | 3584 | ||
3790 | ugeth_vdbg("%s: IN", __FUNCTION__); | 3585 | ugeth_vdbg("%s: IN", __FUNCTION__); |
3791 | 3586 | ||
@@ -3795,174 +3590,57 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) | |||
3795 | uccf = ugeth->uccf; | 3590 | uccf = ugeth->uccf; |
3796 | ug_info = ugeth->ug_info; | 3591 | ug_info = ugeth->ug_info; |
3797 | 3592 | ||
3798 | do { | 3593 | /* read and clear events */ |
3799 | ucce |= (u32) (in_be32(uccf->p_ucce) & in_be32(uccf->p_uccm)); | 3594 | ucce = (u32) in_be32(uccf->p_ucce); |
3800 | 3595 | uccm = (u32) in_be32(uccf->p_uccm); | |
3801 | /* clear event bits for next time */ | 3596 | ucce &= uccm; |
3802 | /* Side effect here is to mask ucce variable | 3597 | out_be32(uccf->p_ucce, ucce); |
3803 | for future processing below. */ | ||
3804 | out_be32(uccf->p_ucce, ucce); /* Clear with ones, | ||
3805 | but only bits in UCCM */ | ||
3806 | |||
3807 | /* We ignore Tx interrupts because Tx confirmation is | ||
3808 | done inside Tx routine */ | ||
3809 | 3598 | ||
3599 | /* check for receive events that require processing */ | ||
3600 | if (ucce & UCCE_RX_EVENTS) { | ||
3601 | #ifdef CONFIG_UGETH_NAPI | ||
3602 | if (netif_rx_schedule_prep(dev)) { | ||
3603 | uccm &= ~UCCE_RX_EVENTS; | ||
3604 | out_be32(uccf->p_uccm, uccm); | ||
3605 | __netif_rx_schedule(dev); | ||
3606 | } | ||
3607 | #else | ||
3608 | rx_mask = UCCE_RXBF_SINGLE_MASK; | ||
3810 | for (i = 0; i < ug_info->numQueuesRx; i++) { | 3609 | for (i = 0; i < ug_info->numQueuesRx; i++) { |
3811 | if (ucce & bit_mask) | 3610 | if (ucce & rx_mask) |
3812 | ucc_geth_rx(ugeth, i, | 3611 | ucc_geth_rx(ugeth, i, (int)ugeth->ug_info->bdRingLenRx[i]); |
3813 | (int)ugeth->ug_info-> | 3612 | ucce &= ~rx_mask; |
3814 | bdRingLenRx[i]); | 3613 | rx_mask <<= 1; |
3815 | ucce &= ~bit_mask; | ||
3816 | bit_mask <<= 1; | ||
3817 | } | 3614 | } |
3615 | #endif /* CONFIG_UGETH_NAPI */ | ||
3616 | } | ||
3818 | 3617 | ||
3618 | /* Tx event processing */ | ||
3619 | if (ucce & UCCE_TX_EVENTS) { | ||
3620 | spin_lock(&ugeth->lock); | ||
3621 | tx_mask = UCCE_TXBF_SINGLE_MASK; | ||
3819 | for (i = 0; i < ug_info->numQueuesTx; i++) { | 3622 | for (i = 0; i < ug_info->numQueuesTx; i++) { |
3820 | if (ucce & tx_mask) | 3623 | if (ucce & tx_mask) |
3821 | ucc_geth_tx(dev, i); | 3624 | ucc_geth_tx(dev, i); |
3822 | ucce &= ~tx_mask; | 3625 | ucce &= ~tx_mask; |
3823 | tx_mask <<= 1; | 3626 | tx_mask <<= 1; |
3824 | } | 3627 | } |
3628 | spin_unlock(&ugeth->lock); | ||
3629 | } | ||
3825 | 3630 | ||
3826 | /* Exceptions */ | 3631 | /* Errors and other events */ |
3632 | if (ucce & UCCE_OTHER) { | ||
3827 | if (ucce & UCCE_BSY) { | 3633 | if (ucce & UCCE_BSY) { |
3828 | ugeth_vdbg("Got BUSY irq!!!!"); | ||
3829 | ugeth->stats.rx_errors++; | 3634 | ugeth->stats.rx_errors++; |
3830 | ucce &= ~UCCE_BSY; | ||
3831 | } | 3635 | } |
3832 | if (ucce & UCCE_OTHER) { | 3636 | if (ucce & UCCE_TXE) { |
3833 | ugeth_vdbg("Got frame with error (ucce - 0x%08x)!!!!", | 3637 | ugeth->stats.tx_errors++; |
3834 | ucce); | ||
3835 | ugeth->stats.rx_errors++; | ||
3836 | ucce &= ~ucce; | ||
3837 | } | 3638 | } |
3838 | } | 3639 | } |
3839 | while (ucce); | ||
3840 | |||
3841 | return IRQ_HANDLED; | ||
3842 | } | ||
3843 | |||
3844 | static irqreturn_t phy_interrupt(int irq, void *dev_id) | ||
3845 | { | ||
3846 | struct net_device *dev = (struct net_device *)dev_id; | ||
3847 | struct ucc_geth_private *ugeth = netdev_priv(dev); | ||
3848 | |||
3849 | ugeth_vdbg("%s: IN", __FUNCTION__); | ||
3850 | |||
3851 | /* Clear the interrupt */ | ||
3852 | mii_clear_phy_interrupt(ugeth->mii_info); | ||
3853 | |||
3854 | /* Disable PHY interrupts */ | ||
3855 | mii_configure_phy_interrupt(ugeth->mii_info, MII_INTERRUPT_DISABLED); | ||
3856 | |||
3857 | /* Schedule the phy change */ | ||
3858 | schedule_work(&ugeth->tq); | ||
3859 | 3640 | ||
3860 | return IRQ_HANDLED; | 3641 | return IRQ_HANDLED; |
3861 | } | 3642 | } |
3862 | 3643 | ||
3863 | /* Scheduled by the phy_interrupt/timer to handle PHY changes */ | ||
3864 | static void ugeth_phy_change(struct work_struct *work) | ||
3865 | { | ||
3866 | struct ucc_geth_private *ugeth = | ||
3867 | container_of(work, struct ucc_geth_private, tq); | ||
3868 | struct net_device *dev = ugeth->dev; | ||
3869 | struct ucc_geth *ug_regs; | ||
3870 | int result = 0; | ||
3871 | |||
3872 | ugeth_vdbg("%s: IN", __FUNCTION__); | ||
3873 | |||
3874 | ug_regs = ugeth->ug_regs; | ||
3875 | |||
3876 | /* Delay to give the PHY a chance to change the | ||
3877 | * register state */ | ||
3878 | msleep(1); | ||
3879 | |||
3880 | /* Update the link, speed, duplex */ | ||
3881 | result = ugeth->mii_info->phyinfo->read_status(ugeth->mii_info); | ||
3882 | |||
3883 | /* Adjust the known status as long as the link | ||
3884 | * isn't still coming up */ | ||
3885 | if ((0 == result) || (ugeth->mii_info->link == 0)) | ||
3886 | adjust_link(dev); | ||
3887 | |||
3888 | /* Reenable interrupts, if needed */ | ||
3889 | if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) | ||
3890 | mii_configure_phy_interrupt(ugeth->mii_info, | ||
3891 | MII_INTERRUPT_ENABLED); | ||
3892 | } | ||
3893 | |||
3894 | /* Called every so often on systems that don't interrupt | ||
3895 | * the core for PHY changes */ | ||
3896 | static void ugeth_phy_timer(unsigned long data) | ||
3897 | { | ||
3898 | struct net_device *dev = (struct net_device *)data; | ||
3899 | struct ucc_geth_private *ugeth = netdev_priv(dev); | ||
3900 | |||
3901 | schedule_work(&ugeth->tq); | ||
3902 | |||
3903 | mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ); | ||
3904 | } | ||
3905 | |||
3906 | /* Keep trying aneg for some time | ||
3907 | * If, after GFAR_AN_TIMEOUT seconds, it has not | ||
3908 | * finished, we switch to forced. | ||
3909 | * Either way, once the process has completed, we either | ||
3910 | * request the interrupt, or switch the timer over to | ||
3911 | * using ugeth_phy_timer to check status */ | ||
3912 | static void ugeth_phy_startup_timer(unsigned long data) | ||
3913 | { | ||
3914 | struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data; | ||
3915 | struct ucc_geth_private *ugeth = netdev_priv(mii_info->dev); | ||
3916 | static int secondary = UGETH_AN_TIMEOUT; | ||
3917 | int result; | ||
3918 | |||
3919 | /* Configure the Auto-negotiation */ | ||
3920 | result = mii_info->phyinfo->config_aneg(mii_info); | ||
3921 | |||
3922 | /* If autonegotiation failed to start, and | ||
3923 | * we haven't timed out, reset the timer, and return */ | ||
3924 | if (result && secondary--) { | ||
3925 | mod_timer(&ugeth->phy_info_timer, jiffies + HZ); | ||
3926 | return; | ||
3927 | } else if (result) { | ||
3928 | /* Couldn't start autonegotiation. | ||
3929 | * Try switching to forced */ | ||
3930 | mii_info->autoneg = 0; | ||
3931 | result = mii_info->phyinfo->config_aneg(mii_info); | ||
3932 | |||
3933 | /* Forcing failed! Give up */ | ||
3934 | if (result) { | ||
3935 | ugeth_err("%s: Forcing failed!", mii_info->dev->name); | ||
3936 | return; | ||
3937 | } | ||
3938 | } | ||
3939 | |||
3940 | /* Kill the timer so it can be restarted */ | ||
3941 | del_timer_sync(&ugeth->phy_info_timer); | ||
3942 | |||
3943 | /* Grab the PHY interrupt, if necessary/possible */ | ||
3944 | if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { | ||
3945 | if (request_irq(ugeth->ug_info->phy_interrupt, | ||
3946 | phy_interrupt, IRQF_SHARED, | ||
3947 | "phy_interrupt", mii_info->dev) < 0) { | ||
3948 | ugeth_err("%s: Can't get IRQ %d (PHY)", | ||
3949 | mii_info->dev->name, | ||
3950 | ugeth->ug_info->phy_interrupt); | ||
3951 | } else { | ||
3952 | mii_configure_phy_interrupt(ugeth->mii_info, | ||
3953 | MII_INTERRUPT_ENABLED); | ||
3954 | return; | ||
3955 | } | ||
3956 | } | ||
3957 | |||
3958 | /* Start the timer again, this time in order to | ||
3959 | * handle a change in status */ | ||
3960 | init_timer(&ugeth->phy_info_timer); | ||
3961 | ugeth->phy_info_timer.function = &ugeth_phy_timer; | ||
3962 | ugeth->phy_info_timer.data = (unsigned long)mii_info->dev; | ||
3963 | mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ); | ||
3964 | } | ||
3965 | |||
3966 | /* Called when something needs to use the ethernet device */ | 3644 | /* Called when something needs to use the ethernet device */ |
3967 | /* Returns 0 for success. */ | 3645 | /* Returns 0 for success. */ |
3968 | static int ucc_geth_open(struct net_device *dev) | 3646 | static int ucc_geth_open(struct net_device *dev) |
@@ -3979,6 +3657,12 @@ static int ucc_geth_open(struct net_device *dev) | |||
3979 | return -EINVAL; | 3657 | return -EINVAL; |
3980 | } | 3658 | } |
3981 | 3659 | ||
3660 | err = ucc_struct_init(ugeth); | ||
3661 | if (err) { | ||
3662 | ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); | ||
3663 | return err; | ||
3664 | } | ||
3665 | |||
3982 | err = ucc_geth_startup(ugeth); | 3666 | err = ucc_geth_startup(ugeth); |
3983 | if (err) { | 3667 | if (err) { |
3984 | ugeth_err("%s: Cannot configure net device, aborting.", | 3668 | ugeth_err("%s: Cannot configure net device, aborting.", |
@@ -4006,10 +3690,12 @@ static int ucc_geth_open(struct net_device *dev) | |||
4006 | 3690 | ||
4007 | err = init_phy(dev); | 3691 | err = init_phy(dev); |
4008 | if (err) { | 3692 | if (err) { |
4009 | ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name); | 3693 | ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); |
4010 | return err; | 3694 | return err; |
4011 | } | 3695 | } |
4012 | #ifndef CONFIG_UGETH_NAPI | 3696 | |
3697 | phy_start(ugeth->phydev); | ||
3698 | |||
4013 | err = | 3699 | err = |
4014 | request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, | 3700 | request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, |
4015 | "UCC Geth", dev); | 3701 | "UCC Geth", dev); |
@@ -4019,15 +3705,6 @@ static int ucc_geth_open(struct net_device *dev) | |||
4019 | ucc_geth_stop(ugeth); | 3705 | ucc_geth_stop(ugeth); |
4020 | return err; | 3706 | return err; |
4021 | } | 3707 | } |
4022 | #endif /* CONFIG_UGETH_NAPI */ | ||
4023 | |||
4024 | /* Set up the PHY change work queue */ | ||
4025 | INIT_WORK(&ugeth->tq, ugeth_phy_change); | ||
4026 | |||
4027 | init_timer(&ugeth->phy_info_timer); | ||
4028 | ugeth->phy_info_timer.function = &ugeth_phy_startup_timer; | ||
4029 | ugeth->phy_info_timer.data = (unsigned long)ugeth->mii_info; | ||
4030 | mod_timer(&ugeth->phy_info_timer, jiffies + HZ); | ||
4031 | 3708 | ||
4032 | err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); | 3709 | err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); |
4033 | if (err) { | 3710 | if (err) { |
@@ -4050,11 +3727,8 @@ static int ucc_geth_close(struct net_device *dev) | |||
4050 | 3727 | ||
4051 | ucc_geth_stop(ugeth); | 3728 | ucc_geth_stop(ugeth); |
4052 | 3729 | ||
4053 | /* Shutdown the PHY */ | 3730 | phy_disconnect(ugeth->phydev); |
4054 | if (ugeth->mii_info->phyinfo->close) | 3731 | ugeth->phydev = NULL; |
4055 | ugeth->mii_info->phyinfo->close(ugeth->mii_info); | ||
4056 | |||
4057 | kfree(ugeth->mii_info); | ||
4058 | 3732 | ||
4059 | netif_stop_queue(dev); | 3733 | netif_stop_queue(dev); |
4060 | 3734 | ||
@@ -4063,20 +3737,53 @@ static int ucc_geth_close(struct net_device *dev) | |||
4063 | 3737 | ||
4064 | const struct ethtool_ops ucc_geth_ethtool_ops = { }; | 3738 | const struct ethtool_ops ucc_geth_ethtool_ops = { }; |
4065 | 3739 | ||
3740 | static phy_interface_t to_phy_interface(const char *interface_type) | ||
3741 | { | ||
3742 | if (strcasecmp(interface_type, "mii") == 0) | ||
3743 | return PHY_INTERFACE_MODE_MII; | ||
3744 | if (strcasecmp(interface_type, "gmii") == 0) | ||
3745 | return PHY_INTERFACE_MODE_GMII; | ||
3746 | if (strcasecmp(interface_type, "tbi") == 0) | ||
3747 | return PHY_INTERFACE_MODE_TBI; | ||
3748 | if (strcasecmp(interface_type, "rmii") == 0) | ||
3749 | return PHY_INTERFACE_MODE_RMII; | ||
3750 | if (strcasecmp(interface_type, "rgmii") == 0) | ||
3751 | return PHY_INTERFACE_MODE_RGMII; | ||
3752 | if (strcasecmp(interface_type, "rgmii-id") == 0) | ||
3753 | return PHY_INTERFACE_MODE_RGMII_ID; | ||
3754 | if (strcasecmp(interface_type, "rtbi") == 0) | ||
3755 | return PHY_INTERFACE_MODE_RTBI; | ||
3756 | |||
3757 | return PHY_INTERFACE_MODE_MII; | ||
3758 | } | ||
3759 | |||
4066 | static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) | 3760 | static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) |
4067 | { | 3761 | { |
4068 | struct device *device = &ofdev->dev; | 3762 | struct device *device = &ofdev->dev; |
4069 | struct device_node *np = ofdev->node; | 3763 | struct device_node *np = ofdev->node; |
3764 | struct device_node *mdio; | ||
4070 | struct net_device *dev = NULL; | 3765 | struct net_device *dev = NULL; |
4071 | struct ucc_geth_private *ugeth = NULL; | 3766 | struct ucc_geth_private *ugeth = NULL; |
4072 | struct ucc_geth_info *ug_info; | 3767 | struct ucc_geth_info *ug_info; |
4073 | struct resource res; | 3768 | struct resource res; |
4074 | struct device_node *phy; | 3769 | struct device_node *phy; |
4075 | int err, ucc_num, phy_interface; | 3770 | int err, ucc_num, max_speed = 0; |
4076 | static int mii_mng_configured = 0; | ||
4077 | const phandle *ph; | 3771 | const phandle *ph; |
4078 | const unsigned int *prop; | 3772 | const unsigned int *prop; |
4079 | const void *mac_addr; | 3773 | const void *mac_addr; |
3774 | phy_interface_t phy_interface; | ||
3775 | static const int enet_to_speed[] = { | ||
3776 | SPEED_10, SPEED_10, SPEED_10, | ||
3777 | SPEED_100, SPEED_100, SPEED_100, | ||
3778 | SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000, | ||
3779 | }; | ||
3780 | static const phy_interface_t enet_to_phy_interface[] = { | ||
3781 | PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII, | ||
3782 | PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII, | ||
3783 | PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, | ||
3784 | PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, | ||
3785 | PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, | ||
3786 | }; | ||
4080 | 3787 | ||
4081 | ugeth_vdbg("%s: IN", __FUNCTION__); | 3788 | ugeth_vdbg("%s: IN", __FUNCTION__); |
4082 | 3789 | ||
@@ -4087,6 +3794,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4087 | 3794 | ||
4088 | ug_info = &ugeth_info[ucc_num]; | 3795 | ug_info = &ugeth_info[ucc_num]; |
4089 | ug_info->uf_info.ucc_num = ucc_num; | 3796 | ug_info->uf_info.ucc_num = ucc_num; |
3797 | |||
4090 | prop = get_property(np, "rx-clock", NULL); | 3798 | prop = get_property(np, "rx-clock", NULL); |
4091 | ug_info->uf_info.rx_clock = *prop; | 3799 | ug_info->uf_info.rx_clock = *prop; |
4092 | prop = get_property(np, "tx-clock", NULL); | 3800 | prop = get_property(np, "tx-clock", NULL); |
@@ -4104,13 +3812,72 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4104 | if (phy == NULL) | 3812 | if (phy == NULL) |
4105 | return -ENODEV; | 3813 | return -ENODEV; |
4106 | 3814 | ||
3815 | /* set the PHY address */ | ||
4107 | prop = get_property(phy, "reg", NULL); | 3816 | prop = get_property(phy, "reg", NULL); |
3817 | if (prop == NULL) | ||
3818 | return -1; | ||
4108 | ug_info->phy_address = *prop; | 3819 | ug_info->phy_address = *prop; |
4109 | prop = get_property(phy, "interface", NULL); | 3820 | |
4110 | ug_info->enet_interface = *prop; | 3821 | /* get the phy interface type, or default to MII */ |
4111 | ug_info->phy_interrupt = irq_of_parse_and_map(phy, 0); | 3822 | prop = get_property(np, "interface-type", NULL); |
4112 | ug_info->board_flags = (ug_info->phy_interrupt == NO_IRQ)? | 3823 | if (!prop) { |
4113 | 0:FSL_UGETH_BRD_HAS_PHY_INTR; | 3824 | /* handle interface property present in old trees */ |
3825 | prop = get_property(phy, "interface", NULL); | ||
3826 | if (prop != NULL) | ||
3827 | phy_interface = enet_to_phy_interface[*prop]; | ||
3828 | else | ||
3829 | phy_interface = PHY_INTERFACE_MODE_MII; | ||
3830 | } else { | ||
3831 | phy_interface = to_phy_interface((const char *)prop); | ||
3832 | } | ||
3833 | |||
3834 | /* get speed, or derive from interface */ | ||
3835 | prop = get_property(np, "max-speed", NULL); | ||
3836 | if (!prop) { | ||
3837 | /* handle interface property present in old trees */ | ||
3838 | prop = get_property(phy, "interface", NULL); | ||
3839 | if (prop != NULL) | ||
3840 | max_speed = enet_to_speed[*prop]; | ||
3841 | } else { | ||
3842 | max_speed = *prop; | ||
3843 | } | ||
3844 | if (!max_speed) { | ||
3845 | switch (phy_interface) { | ||
3846 | case PHY_INTERFACE_MODE_GMII: | ||
3847 | case PHY_INTERFACE_MODE_RGMII: | ||
3848 | case PHY_INTERFACE_MODE_RGMII_ID: | ||
3849 | case PHY_INTERFACE_MODE_TBI: | ||
3850 | case PHY_INTERFACE_MODE_RTBI: | ||
3851 | max_speed = SPEED_1000; | ||
3852 | break; | ||
3853 | default: | ||
3854 | max_speed = SPEED_100; | ||
3855 | break; | ||
3856 | } | ||
3857 | } | ||
3858 | |||
3859 | if (max_speed == SPEED_1000) { | ||
3860 | ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT; | ||
3861 | ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT; | ||
3862 | ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT; | ||
3863 | ug_info->uf_info.utfs = UCC_GETH_UTFS_GIGA_INIT; | ||
3864 | ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT; | ||
3865 | ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT; | ||
3866 | } | ||
3867 | |||
3868 | /* Set the bus id */ | ||
3869 | mdio = of_get_parent(phy); | ||
3870 | |||
3871 | if (mdio == NULL) | ||
3872 | return -1; | ||
3873 | |||
3874 | err = of_address_to_resource(mdio, 0, &res); | ||
3875 | of_node_put(mdio); | ||
3876 | |||
3877 | if (err) | ||
3878 | return -1; | ||
3879 | |||
3880 | ug_info->mdio_bus = res.start; | ||
4114 | 3881 | ||
4115 | printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", | 3882 | printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", |
4116 | ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, | 3883 | ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, |
@@ -4122,43 +3889,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4122 | return -ENODEV; | 3889 | return -ENODEV; |
4123 | } | 3890 | } |
4124 | 3891 | ||
4125 | /* FIXME: Work around for early chip rev. */ | ||
4126 | /* There's a bug in initial chip rev(s) in the RGMII ac */ | ||
4127 | /* timing. */ | ||
4128 | /* The following compensates by writing to the reserved */ | ||
4129 | /* QE Port Output Hold Registers (CPOH1?). */ | ||
4130 | prop = get_property(phy, "interface", NULL); | ||
4131 | phy_interface = *prop; | ||
4132 | if ((phy_interface == ENET_1000_RGMII) || | ||
4133 | (phy_interface == ENET_100_RGMII) || | ||
4134 | (phy_interface == ENET_10_RGMII)) { | ||
4135 | struct device_node *soc; | ||
4136 | phys_addr_t immrbase = -1; | ||
4137 | u32 *tmp_reg; | ||
4138 | u32 tmp_val; | ||
4139 | |||
4140 | soc = of_find_node_by_type(NULL, "soc"); | ||
4141 | if (soc) { | ||
4142 | unsigned int size; | ||
4143 | const void *prop = get_property(soc, "reg", &size); | ||
4144 | immrbase = of_translate_address(soc, prop); | ||
4145 | of_node_put(soc); | ||
4146 | }; | ||
4147 | |||
4148 | tmp_reg = (u32 *) ioremap(immrbase + 0x14A8, 0x4); | ||
4149 | tmp_val = in_be32(tmp_reg); | ||
4150 | if (ucc_num == 1) | ||
4151 | out_be32(tmp_reg, tmp_val | 0x00003000); | ||
4152 | else if (ucc_num == 2) | ||
4153 | out_be32(tmp_reg, tmp_val | 0x0c000000); | ||
4154 | iounmap(tmp_reg); | ||
4155 | } | ||
4156 | |||
4157 | if (!mii_mng_configured) { | ||
4158 | ucc_set_qe_mux_mii_mng(ucc_num); | ||
4159 | mii_mng_configured = 1; | ||
4160 | } | ||
4161 | |||
4162 | /* Create an ethernet device instance */ | 3892 | /* Create an ethernet device instance */ |
4163 | dev = alloc_etherdev(sizeof(*ugeth)); | 3893 | dev = alloc_etherdev(sizeof(*ugeth)); |
4164 | 3894 | ||
@@ -4192,6 +3922,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4192 | dev->set_multicast_list = ucc_geth_set_multi; | 3922 | dev->set_multicast_list = ucc_geth_set_multi; |
4193 | dev->ethtool_ops = &ucc_geth_ethtool_ops; | 3923 | dev->ethtool_ops = &ucc_geth_ethtool_ops; |
4194 | 3924 | ||
3925 | ugeth->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; | ||
3926 | ugeth->phy_interface = phy_interface; | ||
3927 | ugeth->max_speed = max_speed; | ||
3928 | |||
4195 | err = register_netdev(dev); | 3929 | err = register_netdev(dev); |
4196 | if (err) { | 3930 | if (err) { |
4197 | ugeth_err("%s: Cannot register net device, aborting.", | 3931 | ugeth_err("%s: Cannot register net device, aborting.", |
@@ -4200,13 +3934,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4200 | return err; | 3934 | return err; |
4201 | } | 3935 | } |
4202 | 3936 | ||
4203 | ugeth->ug_info = ug_info; | ||
4204 | ugeth->dev = dev; | ||
4205 | |||
4206 | mac_addr = of_get_mac_address(np); | 3937 | mac_addr = of_get_mac_address(np); |
4207 | if (mac_addr) | 3938 | if (mac_addr) |
4208 | memcpy(dev->dev_addr, mac_addr, 6); | 3939 | memcpy(dev->dev_addr, mac_addr, 6); |
4209 | 3940 | ||
3941 | ugeth->ug_info = ug_info; | ||
3942 | ugeth->dev = dev; | ||
3943 | |||
4210 | return 0; | 3944 | return 0; |
4211 | } | 3945 | } |
4212 | 3946 | ||
@@ -4242,19 +3976,30 @@ static struct of_platform_driver ucc_geth_driver = { | |||
4242 | 3976 | ||
4243 | static int __init ucc_geth_init(void) | 3977 | static int __init ucc_geth_init(void) |
4244 | { | 3978 | { |
4245 | int i; | 3979 | int i, ret; |
3980 | |||
3981 | ret = uec_mdio_init(); | ||
3982 | |||
3983 | if (ret) | ||
3984 | return ret; | ||
4246 | 3985 | ||
4247 | printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); | 3986 | printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); |
4248 | for (i = 0; i < 8; i++) | 3987 | for (i = 0; i < 8; i++) |
4249 | memcpy(&(ugeth_info[i]), &ugeth_primary_info, | 3988 | memcpy(&(ugeth_info[i]), &ugeth_primary_info, |
4250 | sizeof(ugeth_primary_info)); | 3989 | sizeof(ugeth_primary_info)); |
4251 | 3990 | ||
4252 | return of_register_platform_driver(&ucc_geth_driver); | 3991 | ret = of_register_platform_driver(&ucc_geth_driver); |
3992 | |||
3993 | if (ret) | ||
3994 | uec_mdio_exit(); | ||
3995 | |||
3996 | return ret; | ||
4253 | } | 3997 | } |
4254 | 3998 | ||
4255 | static void __exit ucc_geth_exit(void) | 3999 | static void __exit ucc_geth_exit(void) |
4256 | { | 4000 | { |
4257 | of_unregister_platform_driver(&ucc_geth_driver); | 4001 | of_unregister_platform_driver(&ucc_geth_driver); |
4002 | uec_mdio_exit(); | ||
4258 | } | 4003 | } |
4259 | 4004 | ||
4260 | module_init(ucc_geth_init); | 4005 | module_init(ucc_geth_init); |
@@ -4262,4 +4007,5 @@ module_exit(ucc_geth_exit); | |||
4262 | 4007 | ||
4263 | MODULE_AUTHOR("Freescale Semiconductor, Inc"); | 4008 | MODULE_AUTHOR("Freescale Semiconductor, Inc"); |
4264 | MODULE_DESCRIPTION(DRV_DESC); | 4009 | MODULE_DESCRIPTION(DRV_DESC); |
4010 | MODULE_VERSION(DRV_VERSION); | ||
4265 | MODULE_LICENSE("GPL"); | 4011 | MODULE_LICENSE("GPL"); |