diff options
author | Kim Phillips <kim.phillips@freescale.com> | 2007-04-13 02:26:03 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 11:01:04 -0400 |
commit | 728de4c927a3544b6d3da331b634035d4c75ca17 (patch) | |
tree | 5f05e0b318de9c1d517bd7bbca5964249c7cc885 /drivers/net/ucc_geth.c | |
parent | a999589ccaae16472531e0616f23826ad097aa40 (diff) |
ucc_geth: migrate ucc_geth to phylib
migrate ucc_geth to use the common phylib code.
There are several side effects from doing this:
o deprecate 'interface' property specification present
in some old device tree source files in
favour of a split 'max-speed' and 'interface-type'
description to appropriately match definitions
in include/linux/phy.h. Note that 'interface' property
is still honoured if max-speed or interface-type
are not present (backward compatible).
o compile-time CONFIG_UGETH_HAS_GIGA is eliminated
in favour of probe time speed derivation logic.
o adjust_link streamlined to only operate on maccfg2
and upsmr.r10m, instead of reapplying static initial
values related to the interface-type.
o Addition of UEC MDIO of_platform driver requires
platform code add 'mdio' type to id list
prior to calling of_platform_bus_probe (separate patch).
o ucc_struct_init introduced to reduce ucc_geth_startup
complexity.
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r-- | drivers/net/ucc_geth.c | 814 |
1 files changed, 271 insertions, 543 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 639e1e6913bf..d93cfde663e9 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,7 +42,7 @@ | |||
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 | ||
@@ -73,22 +74,13 @@ static struct ucc_geth_info ugeth_primary_info = { | |||
73 | .bd_mem_part = MEM_PART_SYSTEM, | 74 | .bd_mem_part = MEM_PART_SYSTEM, |
74 | .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, | 75 | .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, |
75 | .max_rx_buf_length = 1536, | 76 | .max_rx_buf_length = 1536, |
76 | /* FIXME: should be changed in run time for 1G and 100M */ | 77 | /* 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, | 78 | .urfs = UCC_GETH_URFS_INIT, |
86 | .urfet = UCC_GETH_URFET_INIT, | 79 | .urfet = UCC_GETH_URFET_INIT, |
87 | .urfset = UCC_GETH_URFSET_INIT, | 80 | .urfset = UCC_GETH_URFSET_INIT, |
88 | .utfs = UCC_GETH_UTFS_INIT, | 81 | .utfs = UCC_GETH_UTFS_INIT, |
89 | .utfet = UCC_GETH_UTFET_INIT, | 82 | .utfet = UCC_GETH_UTFET_INIT, |
90 | .utftt = UCC_GETH_UTFTT_INIT, | 83 | .utftt = UCC_GETH_UTFTT_INIT, |
91 | #endif | ||
92 | .ufpt = 256, | 84 | .ufpt = 256, |
93 | .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, | 85 | .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, |
94 | .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, | 86 | .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, |
@@ -217,70 +209,6 @@ static struct list_head *dequeue(struct list_head *lh) | |||
217 | } | 209 | } |
218 | } | 210 | } |
219 | 211 | ||
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) | 212 | static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd) |
285 | { | 213 | { |
286 | struct sk_buff *skb = NULL; | 214 | struct sk_buff *skb = NULL; |
@@ -758,24 +686,6 @@ static void dump_regs(struct ucc_geth_private *ugeth) | |||
758 | ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", | 686 | ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", |
759 | (u32) & ugeth->ug_regs->hafdup, | 687 | (u32) & ugeth->ug_regs->hafdup, |
760 | in_be32(&ugeth->ug_regs->hafdup)); | 688 | 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", | 689 | ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x", |
780 | (u32) & ugeth->ug_regs->ifctl, | 690 | (u32) & ugeth->ug_regs->ifctl, |
781 | in_be32(&ugeth->ug_regs->ifctl)); | 691 | in_be32(&ugeth->ug_regs->ifctl)); |
@@ -1425,27 +1335,6 @@ static int init_mac_station_addr_regs(u8 address_byte_0, | |||
1425 | return 0; | 1335 | return 0; |
1426 | } | 1336 | } |
1427 | 1337 | ||
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, | 1338 | static int init_check_frame_length_mode(int length_check, |
1450 | volatile u32 *maccfg2_register) | 1339 | volatile u32 *maccfg2_register) |
1451 | { | 1340 | { |
@@ -1477,40 +1366,6 @@ static int init_preamble_length(u8 preamble_length, | |||
1477 | return 0; | 1366 | return 0; |
1478 | } | 1367 | } |
1479 | 1368 | ||
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, | 1369 | static int init_rx_parameters(int reject_broadcast, |
1515 | int receive_short_frames, | 1370 | int receive_short_frames, |
1516 | int promiscuous, volatile u32 *upsmr_register) | 1371 | int promiscuous, volatile u32 *upsmr_register) |
@@ -1570,10 +1425,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1570 | struct ucc_geth_info *ug_info; | 1425 | struct ucc_geth_info *ug_info; |
1571 | struct ucc_geth *ug_regs; | 1426 | struct ucc_geth *ug_regs; |
1572 | struct ucc_fast *uf_regs; | 1427 | struct ucc_fast *uf_regs; |
1573 | enum enet_speed speed; | 1428 | int ret_val; |
1574 | int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm = | 1429 | u32 upsmr, maccfg2, tbiBaseAddress; |
1575 | 0, limited_to_full_duplex = 0; | ||
1576 | u32 upsmr, maccfg2, utbipar, tbiBaseAddress; | ||
1577 | u16 value; | 1430 | u16 value; |
1578 | 1431 | ||
1579 | ugeth_vdbg("%s: IN", __FUNCTION__); | 1432 | ugeth_vdbg("%s: IN", __FUNCTION__); |
@@ -1582,24 +1435,13 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1582 | ug_regs = ugeth->ug_regs; | 1435 | ug_regs = ugeth->ug_regs; |
1583 | uf_regs = ugeth->uccf->uf_regs; | 1436 | uf_regs = ugeth->uccf->uf_regs; |
1584 | 1437 | ||
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 */ | 1438 | /* Set MACCFG2 */ |
1598 | maccfg2 = in_be32(&ug_regs->maccfg2); | 1439 | maccfg2 = in_be32(&ug_regs->maccfg2); |
1599 | maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; | 1440 | maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; |
1600 | if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT)) | 1441 | if ((ugeth->max_speed == SPEED_10) || |
1442 | (ugeth->max_speed == SPEED_100)) | ||
1601 | maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; | 1443 | maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; |
1602 | else if (speed == ENET_SPEED_1000BT) | 1444 | else if (ugeth->max_speed == SPEED_1000) |
1603 | maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; | 1445 | maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; |
1604 | maccfg2 |= ug_info->padAndCrc; | 1446 | maccfg2 |= ug_info->padAndCrc; |
1605 | out_be32(&ug_regs->maccfg2, maccfg2); | 1447 | out_be32(&ug_regs->maccfg2, maccfg2); |
@@ -1607,54 +1449,39 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1607 | /* Set UPSMR */ | 1449 | /* Set UPSMR */ |
1608 | upsmr = in_be32(&uf_regs->upsmr); | 1450 | upsmr = in_be32(&uf_regs->upsmr); |
1609 | upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); | 1451 | upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); |
1610 | if (rpm) | 1452 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || |
1453 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || | ||
1454 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || | ||
1455 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1611 | upsmr |= UPSMR_RPM; | 1456 | upsmr |= UPSMR_RPM; |
1612 | if (r10m) | 1457 | switch (ugeth->max_speed) { |
1613 | upsmr |= UPSMR_R10M; | 1458 | case SPEED_10: |
1614 | if (tbi) | 1459 | upsmr |= UPSMR_R10M; |
1460 | /* FALLTHROUGH */ | ||
1461 | case SPEED_100: | ||
1462 | if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) | ||
1463 | upsmr |= UPSMR_RMM; | ||
1464 | } | ||
1465 | } | ||
1466 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || | ||
1467 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1615 | upsmr |= UPSMR_TBIM; | 1468 | upsmr |= UPSMR_TBIM; |
1616 | if (rmm) | 1469 | } |
1617 | upsmr |= UPSMR_RMM; | ||
1618 | out_be32(&uf_regs->upsmr, upsmr); | 1470 | out_be32(&uf_regs->upsmr, upsmr); |
1619 | 1471 | ||
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 | 1472 | /* Disable autonegotiation in tbi mode, because by default it |
1636 | comes up in autonegotiation mode. */ | 1473 | comes up in autonegotiation mode. */ |
1637 | /* Note that this depends on proper setting in utbipar register. */ | 1474 | /* Note that this depends on proper setting in utbipar register. */ |
1638 | if (tbi) { | 1475 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || |
1476 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1639 | tbiBaseAddress = in_be32(&ug_regs->utbipar); | 1477 | tbiBaseAddress = in_be32(&ug_regs->utbipar); |
1640 | tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; | 1478 | tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; |
1641 | tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; | 1479 | tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; |
1642 | value = | 1480 | value = ugeth->phydev->bus->read(ugeth->phydev->bus, |
1643 | ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress, | 1481 | (u8) tbiBaseAddress, ENET_TBI_MII_CR); |
1644 | ENET_TBI_MII_CR); | ||
1645 | value &= ~0x1000; /* Turn off autonegotiation */ | 1482 | value &= ~0x1000; /* Turn off autonegotiation */ |
1646 | ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress, | 1483 | ugeth->phydev->bus->write(ugeth->phydev->bus, |
1647 | ENET_TBI_MII_CR, value); | 1484 | (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 | } | 1485 | } |
1659 | 1486 | ||
1660 | init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); | 1487 | init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); |
@@ -1676,76 +1503,88 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
1676 | * function converts those variables into the appropriate | 1503 | * function converts those variables into the appropriate |
1677 | * register values, and can bring down the device if needed. | 1504 | * register values, and can bring down the device if needed. |
1678 | */ | 1505 | */ |
1506 | |||
1679 | static void adjust_link(struct net_device *dev) | 1507 | static void adjust_link(struct net_device *dev) |
1680 | { | 1508 | { |
1681 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 1509 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
1682 | struct ucc_geth *ug_regs; | 1510 | struct ucc_geth *ug_regs; |
1683 | u32 tempval; | 1511 | struct ucc_fast *uf_regs; |
1684 | struct ugeth_mii_info *mii_info = ugeth->mii_info; | 1512 | struct phy_device *phydev = ugeth->phydev; |
1513 | unsigned long flags; | ||
1514 | int new_state = 0; | ||
1685 | 1515 | ||
1686 | ug_regs = ugeth->ug_regs; | 1516 | ug_regs = ugeth->ug_regs; |
1517 | uf_regs = ugeth->uccf->uf_regs; | ||
1687 | 1518 | ||
1688 | if (mii_info->link) { | 1519 | spin_lock_irqsave(&ugeth->lock, flags); |
1520 | |||
1521 | if (phydev->link) { | ||
1522 | u32 tempval = in_be32(&ug_regs->maccfg2); | ||
1523 | u32 upsmr = in_be32(&uf_regs->upsmr); | ||
1689 | /* Now we make sure that we can be in full duplex mode. | 1524 | /* Now we make sure that we can be in full duplex mode. |
1690 | * If not, we operate in half-duplex mode. */ | 1525 | * If not, we operate in half-duplex mode. */ |
1691 | if (mii_info->duplex != ugeth->oldduplex) { | 1526 | if (phydev->duplex != ugeth->oldduplex) { |
1692 | if (!(mii_info->duplex)) { | 1527 | new_state = 1; |
1693 | tempval = in_be32(&ug_regs->maccfg2); | 1528 | if (!(phydev->duplex)) |
1694 | tempval &= ~(MACCFG2_FDX); | 1529 | tempval &= ~(MACCFG2_FDX); |
1695 | out_be32(&ug_regs->maccfg2, tempval); | 1530 | else |
1696 | |||
1697 | ugeth_info("%s: Half Duplex", dev->name); | ||
1698 | } else { | ||
1699 | tempval = in_be32(&ug_regs->maccfg2); | ||
1700 | tempval |= MACCFG2_FDX; | 1531 | tempval |= MACCFG2_FDX; |
1701 | out_be32(&ug_regs->maccfg2, tempval); | 1532 | ugeth->oldduplex = phydev->duplex; |
1702 | |||
1703 | ugeth_info("%s: Full Duplex", dev->name); | ||
1704 | } | ||
1705 | |||
1706 | ugeth->oldduplex = mii_info->duplex; | ||
1707 | } | 1533 | } |
1708 | 1534 | ||
1709 | if (mii_info->speed != ugeth->oldspeed) { | 1535 | if (phydev->speed != ugeth->oldspeed) { |
1710 | switch (mii_info->speed) { | 1536 | new_state = 1; |
1711 | case 1000: | 1537 | switch (phydev->speed) { |
1712 | ugeth->ug_info->enet_interface = ENET_1000_RGMII; | 1538 | case SPEED_1000: |
1713 | break; | 1539 | tempval = ((tempval & |
1714 | case 100: | 1540 | ~(MACCFG2_INTERFACE_MODE_MASK)) | |
1715 | ugeth->ug_info->enet_interface = ENET_100_RGMII; | 1541 | MACCFG2_INTERFACE_MODE_BYTE); |
1716 | break; | 1542 | break; |
1717 | case 10: | 1543 | case SPEED_100: |
1718 | ugeth->ug_info->enet_interface = ENET_10_RGMII; | 1544 | case SPEED_10: |
1545 | tempval = ((tempval & | ||
1546 | ~(MACCFG2_INTERFACE_MODE_MASK)) | | ||
1547 | MACCFG2_INTERFACE_MODE_NIBBLE); | ||
1548 | /* if reduced mode, re-set UPSMR.R10M */ | ||
1549 | if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || | ||
1550 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || | ||
1551 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || | ||
1552 | (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { | ||
1553 | if (phydev->speed == SPEED_10) | ||
1554 | upsmr |= UPSMR_R10M; | ||
1555 | else | ||
1556 | upsmr &= ~(UPSMR_R10M); | ||
1557 | } | ||
1719 | break; | 1558 | break; |
1720 | default: | 1559 | default: |
1721 | ugeth_warn | 1560 | if (netif_msg_link(ugeth)) |
1722 | ("%s: Ack! Speed (%d) is not 10/100/1000!", | 1561 | ugeth_warn( |
1723 | dev->name, mii_info->speed); | 1562 | "%s: Ack! Speed (%d) is not 10/100/1000!", |
1563 | dev->name, phydev->speed); | ||
1724 | break; | 1564 | break; |
1725 | } | 1565 | } |
1726 | adjust_enet_interface(ugeth); | 1566 | 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 | } | 1567 | } |
1733 | 1568 | ||
1569 | out_be32(&ug_regs->maccfg2, tempval); | ||
1570 | out_be32(&uf_regs->upsmr, upsmr); | ||
1571 | |||
1734 | if (!ugeth->oldlink) { | 1572 | if (!ugeth->oldlink) { |
1735 | ugeth_info("%s: Link is up", dev->name); | 1573 | new_state = 1; |
1736 | ugeth->oldlink = 1; | 1574 | ugeth->oldlink = 1; |
1737 | netif_carrier_on(dev); | ||
1738 | netif_schedule(dev); | 1575 | netif_schedule(dev); |
1739 | } | 1576 | } |
1740 | } else { | 1577 | } else if (ugeth->oldlink) { |
1741 | if (ugeth->oldlink) { | 1578 | new_state = 1; |
1742 | ugeth_info("%s: Link is down", dev->name); | ||
1743 | ugeth->oldlink = 0; | 1579 | ugeth->oldlink = 0; |
1744 | ugeth->oldspeed = 0; | 1580 | ugeth->oldspeed = 0; |
1745 | ugeth->oldduplex = -1; | 1581 | ugeth->oldduplex = -1; |
1746 | netif_carrier_off(dev); | ||
1747 | } | ||
1748 | } | 1582 | } |
1583 | |||
1584 | if (new_state && netif_msg_link(ugeth)) | ||
1585 | phy_print_status(phydev); | ||
1586 | |||
1587 | spin_unlock_irqrestore(&ugeth->lock, flags); | ||
1749 | } | 1588 | } |
1750 | 1589 | ||
1751 | /* Configure the PHY for dev. | 1590 | /* Configure the PHY for dev. |
@@ -1753,94 +1592,40 @@ static void adjust_link(struct net_device *dev) | |||
1753 | */ | 1592 | */ |
1754 | static int init_phy(struct net_device *dev) | 1593 | static int init_phy(struct net_device *dev) |
1755 | { | 1594 | { |
1756 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 1595 | struct ucc_geth_private *priv = netdev_priv(dev); |
1757 | struct phy_info *curphy; | 1596 | struct phy_device *phydev; |
1758 | struct ucc_mii_mng *mii_regs; | 1597 | char phy_id[BUS_ID_SIZE]; |
1759 | struct ugeth_mii_info *mii_info; | ||
1760 | int err; | ||
1761 | 1598 | ||
1762 | mii_regs = &ugeth->ug_regs->miimng; | 1599 | priv->oldlink = 0; |
1600 | priv->oldspeed = 0; | ||
1601 | priv->oldduplex = -1; | ||
1763 | 1602 | ||
1764 | ugeth->oldlink = 0; | 1603 | snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus, |
1765 | ugeth->oldspeed = 0; | 1604 | priv->ug_info->phy_address); |
1766 | ugeth->oldduplex = -1; | ||
1767 | 1605 | ||
1768 | mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL); | 1606 | phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); |
1769 | 1607 | ||
1770 | if (NULL == mii_info) { | 1608 | if (IS_ERR(phydev)) { |
1771 | ugeth_err("%s: Could not allocate mii_info", dev->name); | 1609 | printk("%s: Could not attach to PHY\n", dev->name); |
1772 | return -ENOMEM; | 1610 | return PTR_ERR(phydev); |
1773 | } | 1611 | } |
1774 | 1612 | ||
1775 | mii_info->mii_regs = mii_regs; | 1613 | 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 | | 1614 | ADVERTISED_10baseT_Full | |
1783 | ADVERTISED_100baseT_Half | | 1615 | ADVERTISED_100baseT_Half | |
1784 | ADVERTISED_100baseT_Full | | 1616 | ADVERTISED_100baseT_Full); |
1785 | ADVERTISED_1000baseT_Full); | ||
1786 | mii_info->autoneg = 1; | ||
1787 | |||
1788 | mii_info->mii_id = ugeth->ug_info->phy_address; | ||
1789 | |||
1790 | mii_info->dev = dev; | ||
1791 | 1617 | ||
1792 | mii_info->mdio_read = &read_phy_reg; | 1618 | if (priv->max_speed == SPEED_1000) |
1793 | mii_info->mdio_write = &write_phy_reg; | 1619 | phydev->supported |= ADVERTISED_1000baseT_Full; |
1794 | 1620 | ||
1795 | spin_lock_init(&mii_info->mdio_lock); | 1621 | phydev->advertising = phydev->supported; |
1796 | 1622 | ||
1797 | ugeth->mii_info = mii_info; | 1623 | priv->phydev = phydev; |
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 | 1624 | ||
1834 | return 0; | 1625 | return 0; |
1835 | |||
1836 | phy_init_fail: | ||
1837 | no_phy: | ||
1838 | bus_fail: | ||
1839 | kfree(mii_info); | ||
1840 | |||
1841 | return err; | ||
1842 | } | 1626 | } |
1843 | 1627 | ||
1628 | |||
1844 | #ifdef CONFIG_UGETH_TX_ON_DEMOND | 1629 | #ifdef CONFIG_UGETH_TX_ON_DEMOND |
1845 | static int ugeth_transmit_on_demand(struct ucc_geth_private *ugeth) | 1630 | static int ugeth_transmit_on_demand(struct ucc_geth_private *ugeth) |
1846 | { | 1631 | { |
@@ -2487,6 +2272,7 @@ static void ucc_geth_set_multi(struct net_device *dev) | |||
2487 | static void ucc_geth_stop(struct ucc_geth_private *ugeth) | 2272 | static void ucc_geth_stop(struct ucc_geth_private *ugeth) |
2488 | { | 2273 | { |
2489 | struct ucc_geth *ug_regs = ugeth->ug_regs; | 2274 | struct ucc_geth *ug_regs = ugeth->ug_regs; |
2275 | struct phy_device *phydev = ugeth->phydev; | ||
2490 | u32 tempval; | 2276 | u32 tempval; |
2491 | 2277 | ||
2492 | ugeth_vdbg("%s: IN", __FUNCTION__); | 2278 | ugeth_vdbg("%s: IN", __FUNCTION__); |
@@ -2495,8 +2281,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) | |||
2495 | ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); | 2281 | ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); |
2496 | 2282 | ||
2497 | /* Tell the kernel the link is down */ | 2283 | /* Tell the kernel the link is down */ |
2498 | ugeth->mii_info->link = 0; | 2284 | phy_stop(phydev); |
2499 | adjust_link(ugeth->dev); | ||
2500 | 2285 | ||
2501 | /* Mask all interrupts */ | 2286 | /* Mask all interrupts */ |
2502 | out_be32(ugeth->uccf->p_ucce, 0x00000000); | 2287 | out_be32(ugeth->uccf->p_ucce, 0x00000000); |
@@ -2509,46 +2294,16 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) | |||
2509 | tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); | 2294 | tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); |
2510 | out_be32(&ug_regs->maccfg1, tempval); | 2295 | out_be32(&ug_regs->maccfg1, tempval); |
2511 | 2296 | ||
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); | 2297 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); |
2522 | 2298 | ||
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); | 2299 | ucc_geth_memclean(ugeth); |
2530 | } | 2300 | } |
2531 | 2301 | ||
2532 | static int ucc_geth_startup(struct ucc_geth_private *ugeth) | 2302 | static int ucc_struct_init(struct ucc_geth_private *ugeth) |
2533 | { | 2303 | { |
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; | 2304 | struct ucc_geth_info *ug_info; |
2538 | struct ucc_fast_info *uf_info; | 2305 | struct ucc_fast_info *uf_info; |
2539 | struct ucc_fast *uf_regs; | 2306 | 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 | 2307 | ||
2553 | ug_info = ugeth->ug_info; | 2308 | ug_info = ugeth->ug_info; |
2554 | uf_info = &ug_info->uf_info; | 2309 | uf_info = &ug_info->uf_info; |
@@ -2647,12 +2402,42 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2647 | for (i = 0; i < ug_info->numQueuesTx; i++) | 2402 | for (i = 0; i < ug_info->numQueuesTx; i++) |
2648 | uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); | 2403 | uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); |
2649 | /* Initialize the general fast UCC block. */ | 2404 | /* Initialize the general fast UCC block. */ |
2650 | if (ucc_fast_init(uf_info, &uccf)) { | 2405 | if (ucc_fast_init(uf_info, &ugeth->uccf)) { |
2651 | ugeth_err("%s: Failed to init uccf.", __FUNCTION__); | 2406 | ugeth_err("%s: Failed to init uccf.", __FUNCTION__); |
2652 | ucc_geth_memclean(ugeth); | 2407 | ucc_geth_memclean(ugeth); |
2653 | return -ENOMEM; | 2408 | return -ENOMEM; |
2654 | } | 2409 | } |
2655 | ugeth->uccf = uccf; | 2410 | |
2411 | ugeth->ug_regs = (struct ucc_geth *) ioremap(uf_info->regs, sizeof(struct ucc_geth)); | ||
2412 | |||
2413 | return 0; | ||
2414 | } | ||
2415 | |||
2416 | static int ucc_geth_startup(struct ucc_geth_private *ugeth) | ||
2417 | { | ||
2418 | struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; | ||
2419 | struct ucc_geth_init_pram *p_init_enet_pram; | ||
2420 | struct ucc_fast_private *uccf; | ||
2421 | struct ucc_geth_info *ug_info; | ||
2422 | struct ucc_fast_info *uf_info; | ||
2423 | struct ucc_fast *uf_regs; | ||
2424 | struct ucc_geth *ug_regs; | ||
2425 | int ret_val = -EINVAL; | ||
2426 | u32 remoder = UCC_GETH_REMODER_INIT; | ||
2427 | u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; | ||
2428 | u32 ifstat, i, j, size, l2qt, l3qt, length; | ||
2429 | u16 temoder = UCC_GETH_TEMODER_INIT; | ||
2430 | u16 test; | ||
2431 | u8 function_code = 0; | ||
2432 | u8 *bd, *endOfRing; | ||
2433 | u8 numThreadsRxNumerical, numThreadsTxNumerical; | ||
2434 | |||
2435 | ugeth_vdbg("%s: IN", __FUNCTION__); | ||
2436 | uccf = ugeth->uccf; | ||
2437 | ug_info = ugeth->ug_info; | ||
2438 | uf_info = &ug_info->uf_info; | ||
2439 | uf_regs = uccf->uf_regs; | ||
2440 | ug_regs = ugeth->ug_regs; | ||
2656 | 2441 | ||
2657 | switch (ug_info->numThreadsRx) { | 2442 | switch (ug_info->numThreadsRx) { |
2658 | case UCC_GETH_NUM_OF_THREADS_1: | 2443 | case UCC_GETH_NUM_OF_THREADS_1: |
@@ -2711,10 +2496,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) | |||
2711 | || (ug_info->vlanOperationNonTagged != | 2496 | || (ug_info->vlanOperationNonTagged != |
2712 | UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); | 2497 | UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); |
2713 | 2498 | ||
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, | 2499 | init_default_reg_vals(&uf_regs->upsmr, |
2719 | &ug_regs->maccfg1, &ug_regs->maccfg2); | 2500 | &ug_regs->maccfg1, &ug_regs->maccfg2); |
2720 | 2501 | ||
@@ -3841,128 +3622,6 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) | |||
3841 | return IRQ_HANDLED; | 3622 | return IRQ_HANDLED; |
3842 | } | 3623 | } |
3843 | 3624 | ||
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 | |||
3860 | return IRQ_HANDLED; | ||
3861 | } | ||
3862 | |||
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 */ | 3625 | /* Called when something needs to use the ethernet device */ |
3967 | /* Returns 0 for success. */ | 3626 | /* Returns 0 for success. */ |
3968 | static int ucc_geth_open(struct net_device *dev) | 3627 | static int ucc_geth_open(struct net_device *dev) |
@@ -3979,6 +3638,12 @@ static int ucc_geth_open(struct net_device *dev) | |||
3979 | return -EINVAL; | 3638 | return -EINVAL; |
3980 | } | 3639 | } |
3981 | 3640 | ||
3641 | err = ucc_struct_init(ugeth); | ||
3642 | if (err) { | ||
3643 | ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); | ||
3644 | return err; | ||
3645 | } | ||
3646 | |||
3982 | err = ucc_geth_startup(ugeth); | 3647 | err = ucc_geth_startup(ugeth); |
3983 | if (err) { | 3648 | if (err) { |
3984 | ugeth_err("%s: Cannot configure net device, aborting.", | 3649 | ugeth_err("%s: Cannot configure net device, aborting.", |
@@ -4006,9 +3671,12 @@ static int ucc_geth_open(struct net_device *dev) | |||
4006 | 3671 | ||
4007 | err = init_phy(dev); | 3672 | err = init_phy(dev); |
4008 | if (err) { | 3673 | if (err) { |
4009 | ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name); | 3674 | ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); |
4010 | return err; | 3675 | return err; |
4011 | } | 3676 | } |
3677 | |||
3678 | phy_start(ugeth->phydev); | ||
3679 | |||
4012 | #ifndef CONFIG_UGETH_NAPI | 3680 | #ifndef CONFIG_UGETH_NAPI |
4013 | err = | 3681 | err = |
4014 | request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, | 3682 | request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, |
@@ -4021,14 +3689,6 @@ static int ucc_geth_open(struct net_device *dev) | |||
4021 | } | 3689 | } |
4022 | #endif /* CONFIG_UGETH_NAPI */ | 3690 | #endif /* CONFIG_UGETH_NAPI */ |
4023 | 3691 | ||
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 | |||
4032 | err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); | 3692 | err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); |
4033 | if (err) { | 3693 | if (err) { |
4034 | ugeth_err("%s: Cannot enable net device, aborting.", dev->name); | 3694 | ugeth_err("%s: Cannot enable net device, aborting.", dev->name); |
@@ -4050,11 +3710,8 @@ static int ucc_geth_close(struct net_device *dev) | |||
4050 | 3710 | ||
4051 | ucc_geth_stop(ugeth); | 3711 | ucc_geth_stop(ugeth); |
4052 | 3712 | ||
4053 | /* Shutdown the PHY */ | 3713 | phy_disconnect(ugeth->phydev); |
4054 | if (ugeth->mii_info->phyinfo->close) | 3714 | ugeth->phydev = NULL; |
4055 | ugeth->mii_info->phyinfo->close(ugeth->mii_info); | ||
4056 | |||
4057 | kfree(ugeth->mii_info); | ||
4058 | 3715 | ||
4059 | netif_stop_queue(dev); | 3716 | netif_stop_queue(dev); |
4060 | 3717 | ||
@@ -4063,20 +3720,53 @@ static int ucc_geth_close(struct net_device *dev) | |||
4063 | 3720 | ||
4064 | const struct ethtool_ops ucc_geth_ethtool_ops = { }; | 3721 | const struct ethtool_ops ucc_geth_ethtool_ops = { }; |
4065 | 3722 | ||
3723 | static phy_interface_t to_phy_interface(const char *interface_type) | ||
3724 | { | ||
3725 | if (strcasecmp(interface_type, "mii") == 0) | ||
3726 | return PHY_INTERFACE_MODE_MII; | ||
3727 | if (strcasecmp(interface_type, "gmii") == 0) | ||
3728 | return PHY_INTERFACE_MODE_GMII; | ||
3729 | if (strcasecmp(interface_type, "tbi") == 0) | ||
3730 | return PHY_INTERFACE_MODE_TBI; | ||
3731 | if (strcasecmp(interface_type, "rmii") == 0) | ||
3732 | return PHY_INTERFACE_MODE_RMII; | ||
3733 | if (strcasecmp(interface_type, "rgmii") == 0) | ||
3734 | return PHY_INTERFACE_MODE_RGMII; | ||
3735 | if (strcasecmp(interface_type, "rgmii-id") == 0) | ||
3736 | return PHY_INTERFACE_MODE_RGMII_ID; | ||
3737 | if (strcasecmp(interface_type, "rtbi") == 0) | ||
3738 | return PHY_INTERFACE_MODE_RTBI; | ||
3739 | |||
3740 | return PHY_INTERFACE_MODE_MII; | ||
3741 | } | ||
3742 | |||
4066 | static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) | 3743 | static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) |
4067 | { | 3744 | { |
4068 | struct device *device = &ofdev->dev; | 3745 | struct device *device = &ofdev->dev; |
4069 | struct device_node *np = ofdev->node; | 3746 | struct device_node *np = ofdev->node; |
3747 | struct device_node *mdio; | ||
4070 | struct net_device *dev = NULL; | 3748 | struct net_device *dev = NULL; |
4071 | struct ucc_geth_private *ugeth = NULL; | 3749 | struct ucc_geth_private *ugeth = NULL; |
4072 | struct ucc_geth_info *ug_info; | 3750 | struct ucc_geth_info *ug_info; |
4073 | struct resource res; | 3751 | struct resource res; |
4074 | struct device_node *phy; | 3752 | struct device_node *phy; |
4075 | int err, ucc_num, phy_interface; | 3753 | int err, ucc_num, max_speed = 0; |
4076 | static int mii_mng_configured = 0; | ||
4077 | const phandle *ph; | 3754 | const phandle *ph; |
4078 | const unsigned int *prop; | 3755 | const unsigned int *prop; |
4079 | const void *mac_addr; | 3756 | const void *mac_addr; |
3757 | phy_interface_t phy_interface; | ||
3758 | static const int enet_to_speed[] = { | ||
3759 | SPEED_10, SPEED_10, SPEED_10, | ||
3760 | SPEED_100, SPEED_100, SPEED_100, | ||
3761 | SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000, | ||
3762 | }; | ||
3763 | static const phy_interface_t enet_to_phy_interface[] = { | ||
3764 | PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII, | ||
3765 | PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII, | ||
3766 | PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, | ||
3767 | PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, | ||
3768 | PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, | ||
3769 | }; | ||
4080 | 3770 | ||
4081 | ugeth_vdbg("%s: IN", __FUNCTION__); | 3771 | ugeth_vdbg("%s: IN", __FUNCTION__); |
4082 | 3772 | ||
@@ -4087,6 +3777,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4087 | 3777 | ||
4088 | ug_info = &ugeth_info[ucc_num]; | 3778 | ug_info = &ugeth_info[ucc_num]; |
4089 | ug_info->uf_info.ucc_num = ucc_num; | 3779 | ug_info->uf_info.ucc_num = ucc_num; |
3780 | |||
4090 | prop = get_property(np, "rx-clock", NULL); | 3781 | prop = get_property(np, "rx-clock", NULL); |
4091 | ug_info->uf_info.rx_clock = *prop; | 3782 | ug_info->uf_info.rx_clock = *prop; |
4092 | prop = get_property(np, "tx-clock", NULL); | 3783 | prop = get_property(np, "tx-clock", NULL); |
@@ -4104,13 +3795,72 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4104 | if (phy == NULL) | 3795 | if (phy == NULL) |
4105 | return -ENODEV; | 3796 | return -ENODEV; |
4106 | 3797 | ||
3798 | /* set the PHY address */ | ||
4107 | prop = get_property(phy, "reg", NULL); | 3799 | prop = get_property(phy, "reg", NULL); |
3800 | if (prop == NULL) | ||
3801 | return -1; | ||
4108 | ug_info->phy_address = *prop; | 3802 | ug_info->phy_address = *prop; |
4109 | prop = get_property(phy, "interface", NULL); | 3803 | |
4110 | ug_info->enet_interface = *prop; | 3804 | /* get the phy interface type, or default to MII */ |
4111 | ug_info->phy_interrupt = irq_of_parse_and_map(phy, 0); | 3805 | prop = get_property(np, "interface-type", NULL); |
4112 | ug_info->board_flags = (ug_info->phy_interrupt == NO_IRQ)? | 3806 | if (!prop) { |
4113 | 0:FSL_UGETH_BRD_HAS_PHY_INTR; | 3807 | /* handle interface property present in old trees */ |
3808 | prop = get_property(phy, "interface", NULL); | ||
3809 | if (prop != NULL) | ||
3810 | phy_interface = enet_to_phy_interface[*prop]; | ||
3811 | else | ||
3812 | phy_interface = PHY_INTERFACE_MODE_MII; | ||
3813 | } else { | ||
3814 | phy_interface = to_phy_interface((const char *)prop); | ||
3815 | } | ||
3816 | |||
3817 | /* get speed, or derive from interface */ | ||
3818 | prop = get_property(np, "max-speed", NULL); | ||
3819 | if (!prop) { | ||
3820 | /* handle interface property present in old trees */ | ||
3821 | prop = get_property(phy, "interface", NULL); | ||
3822 | if (prop != NULL) | ||
3823 | max_speed = enet_to_speed[*prop]; | ||
3824 | } else { | ||
3825 | max_speed = *prop; | ||
3826 | } | ||
3827 | if (!max_speed) { | ||
3828 | switch (phy_interface) { | ||
3829 | case PHY_INTERFACE_MODE_GMII: | ||
3830 | case PHY_INTERFACE_MODE_RGMII: | ||
3831 | case PHY_INTERFACE_MODE_RGMII_ID: | ||
3832 | case PHY_INTERFACE_MODE_TBI: | ||
3833 | case PHY_INTERFACE_MODE_RTBI: | ||
3834 | max_speed = SPEED_1000; | ||
3835 | break; | ||
3836 | default: | ||
3837 | max_speed = SPEED_100; | ||
3838 | break; | ||
3839 | } | ||
3840 | } | ||
3841 | |||
3842 | if (max_speed == SPEED_1000) { | ||
3843 | ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT; | ||
3844 | ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT; | ||
3845 | ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT; | ||
3846 | ug_info->uf_info.utfs = UCC_GETH_UTFS_GIGA_INIT; | ||
3847 | ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT; | ||
3848 | ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT; | ||
3849 | } | ||
3850 | |||
3851 | /* Set the bus id */ | ||
3852 | mdio = of_get_parent(phy); | ||
3853 | |||
3854 | if (mdio == NULL) | ||
3855 | return -1; | ||
3856 | |||
3857 | err = of_address_to_resource(mdio, 0, &res); | ||
3858 | of_node_put(mdio); | ||
3859 | |||
3860 | if (err) | ||
3861 | return -1; | ||
3862 | |||
3863 | ug_info->mdio_bus = res.start; | ||
4114 | 3864 | ||
4115 | printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", | 3865 | 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, | 3866 | ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, |
@@ -4122,43 +3872,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4122 | return -ENODEV; | 3872 | return -ENODEV; |
4123 | } | 3873 | } |
4124 | 3874 | ||
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 */ | 3875 | /* Create an ethernet device instance */ |
4163 | dev = alloc_etherdev(sizeof(*ugeth)); | 3876 | dev = alloc_etherdev(sizeof(*ugeth)); |
4164 | 3877 | ||
@@ -4192,6 +3905,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; | 3905 | dev->set_multicast_list = ucc_geth_set_multi; |
4193 | dev->ethtool_ops = &ucc_geth_ethtool_ops; | 3906 | dev->ethtool_ops = &ucc_geth_ethtool_ops; |
4194 | 3907 | ||
3908 | ugeth->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; | ||
3909 | ugeth->phy_interface = phy_interface; | ||
3910 | ugeth->max_speed = max_speed; | ||
3911 | |||
4195 | err = register_netdev(dev); | 3912 | err = register_netdev(dev); |
4196 | if (err) { | 3913 | if (err) { |
4197 | ugeth_err("%s: Cannot register net device, aborting.", | 3914 | ugeth_err("%s: Cannot register net device, aborting.", |
@@ -4200,13 +3917,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
4200 | return err; | 3917 | return err; |
4201 | } | 3918 | } |
4202 | 3919 | ||
4203 | ugeth->ug_info = ug_info; | ||
4204 | ugeth->dev = dev; | ||
4205 | |||
4206 | mac_addr = of_get_mac_address(np); | 3920 | mac_addr = of_get_mac_address(np); |
4207 | if (mac_addr) | 3921 | if (mac_addr) |
4208 | memcpy(dev->dev_addr, mac_addr, 6); | 3922 | memcpy(dev->dev_addr, mac_addr, 6); |
4209 | 3923 | ||
3924 | ugeth->ug_info = ug_info; | ||
3925 | ugeth->dev = dev; | ||
3926 | |||
4210 | return 0; | 3927 | return 0; |
4211 | } | 3928 | } |
4212 | 3929 | ||
@@ -4242,19 +3959,30 @@ static struct of_platform_driver ucc_geth_driver = { | |||
4242 | 3959 | ||
4243 | static int __init ucc_geth_init(void) | 3960 | static int __init ucc_geth_init(void) |
4244 | { | 3961 | { |
4245 | int i; | 3962 | int i, ret; |
3963 | |||
3964 | ret = uec_mdio_init(); | ||
3965 | |||
3966 | if (ret) | ||
3967 | return ret; | ||
4246 | 3968 | ||
4247 | printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); | 3969 | printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); |
4248 | for (i = 0; i < 8; i++) | 3970 | for (i = 0; i < 8; i++) |
4249 | memcpy(&(ugeth_info[i]), &ugeth_primary_info, | 3971 | memcpy(&(ugeth_info[i]), &ugeth_primary_info, |
4250 | sizeof(ugeth_primary_info)); | 3972 | sizeof(ugeth_primary_info)); |
4251 | 3973 | ||
4252 | return of_register_platform_driver(&ucc_geth_driver); | 3974 | ret = of_register_platform_driver(&ucc_geth_driver); |
3975 | |||
3976 | if (ret) | ||
3977 | uec_mdio_exit(); | ||
3978 | |||
3979 | return ret; | ||
4253 | } | 3980 | } |
4254 | 3981 | ||
4255 | static void __exit ucc_geth_exit(void) | 3982 | static void __exit ucc_geth_exit(void) |
4256 | { | 3983 | { |
4257 | of_unregister_platform_driver(&ucc_geth_driver); | 3984 | of_unregister_platform_driver(&ucc_geth_driver); |
3985 | uec_mdio_exit(); | ||
4258 | } | 3986 | } |
4259 | 3987 | ||
4260 | module_init(ucc_geth_init); | 3988 | module_init(ucc_geth_init); |