aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKim Phillips <kim.phillips@freescale.com>2007-04-13 02:26:03 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-28 11:01:04 -0400
commit728de4c927a3544b6d3da331b634035d4c75ca17 (patch)
tree5f05e0b318de9c1d517bd7bbca5964249c7cc885 /drivers
parenta999589ccaae16472531e0616f23826ad097aa40 (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')
-rw-r--r--drivers/net/Kconfig4
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/ucc_geth.c814
-rw-r--r--drivers/net/ucc_geth.h108
-rw-r--r--drivers/net/ucc_geth_mii.c279
-rw-r--r--drivers/net/ucc_geth_mii.h100
-rw-r--r--drivers/net/ucc_geth_phy.c785
-rw-r--r--drivers/net/ucc_geth_phy.h217
8 files changed, 659 insertions, 1650 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ee920ad1a5f5..87d69752d86a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2296,10 +2296,6 @@ config UGETH_TX_ON_DEMOND
2296 bool "Transmit on Demond support" 2296 bool "Transmit on Demond support"
2297 depends on UCC_GETH 2297 depends on UCC_GETH
2298 2298
2299config UGETH_HAS_GIGA
2300 bool
2301 depends on UCC_GETH && PPC_MPC836x
2302
2303config MV643XX_ETH 2299config MV643XX_ETH
2304 tristate "MV-643XX Ethernet support" 2300 tristate "MV-643XX Ethernet support"
2305 depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32) 2301 depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 58527322a39d..59c0459a037c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -18,7 +18,7 @@ gianfar_driver-objs := gianfar.o \
18 gianfar_sysfs.o 18 gianfar_sysfs.o
19 19
20obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o 20obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
21ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o 21ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o
22 22
23# 23#
24# link order important here 24# link order important here
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
220static 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
284static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd) 212static 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
1428static 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
1449static int init_check_frame_length_mode(int length_check, 1338static 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
1480static 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
1514static int init_rx_parameters(int reject_broadcast, 1369static 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
1679static void adjust_link(struct net_device *dev) 1507static 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 */
1754static int init_phy(struct net_device *dev) 1593static 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
1845static int ugeth_transmit_on_demand(struct ucc_geth_private *ugeth) 1630static 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)
2487static void ucc_geth_stop(struct ucc_geth_private *ugeth) 2272static 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
2532static int ucc_geth_startup(struct ucc_geth_private *ugeth) 2302static 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
2416static 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
3844static 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 */
3864static 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 */
3896static 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 */
3912static 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. */
3968static int ucc_geth_open(struct net_device *dev) 3627static 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
4064const struct ethtool_ops ucc_geth_ethtool_ops = { }; 3721const struct ethtool_ops ucc_geth_ethtool_ops = { };
4065 3722
3723static 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
4066static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) 3743static 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
4243static int __init ucc_geth_init(void) 3960static 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
4255static void __exit ucc_geth_exit(void) 3982static 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
4260module_init(ucc_geth_init); 3988module_init(ucc_geth_init);
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index a66561253593..6e97c20b92aa 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -28,6 +28,8 @@
28#include <asm/ucc.h> 28#include <asm/ucc.h>
29#include <asm/ucc_fast.h> 29#include <asm/ucc_fast.h>
30 30
31#include "ucc_geth_mii.h"
32
31#define NUM_TX_QUEUES 8 33#define NUM_TX_QUEUES 8
32#define NUM_RX_QUEUES 8 34#define NUM_RX_QUEUES 8
33#define NUM_BDS_IN_PREFETCHED_BDS 4 35#define NUM_BDS_IN_PREFETCHED_BDS 4
@@ -36,15 +38,6 @@
36#define ENET_INIT_PARAM_MAX_ENTRIES_RX 9 38#define ENET_INIT_PARAM_MAX_ENTRIES_RX 9
37#define ENET_INIT_PARAM_MAX_ENTRIES_TX 8 39#define ENET_INIT_PARAM_MAX_ENTRIES_TX 8
38 40
39struct ucc_mii_mng {
40 u32 miimcfg; /* MII management configuration reg */
41 u32 miimcom; /* MII management command reg */
42 u32 miimadd; /* MII management address reg */
43 u32 miimcon; /* MII management control reg */
44 u32 miimstat; /* MII management status reg */
45 u32 miimind; /* MII management indication reg */
46} __attribute__ ((packed));
47
48struct ucc_geth { 41struct ucc_geth {
49 struct ucc_fast uccf; 42 struct ucc_fast uccf;
50 43
@@ -53,7 +46,7 @@ struct ucc_geth {
53 u32 ipgifg; /* interframe gap reg. */ 46 u32 ipgifg; /* interframe gap reg. */
54 u32 hafdup; /* half-duplex reg. */ 47 u32 hafdup; /* half-duplex reg. */
55 u8 res1[0x10]; 48 u8 res1[0x10];
56 struct ucc_mii_mng miimng; /* MII management structure */ 49 u8 miimng[0x18]; /* MII management structure moved to _mii.h */
57 u32 ifctl; /* interface control reg */ 50 u32 ifctl; /* interface control reg */
58 u32 ifstat; /* interface statux reg */ 51 u32 ifstat; /* interface statux reg */
59 u32 macstnaddr1; /* mac station address part 1 reg */ 52 u32 macstnaddr1; /* mac station address part 1 reg */
@@ -381,66 +374,6 @@ struct ucc_geth {
381#define UCCS_MPD 0x01 /* Magic Packet 374#define UCCS_MPD 0x01 /* Magic Packet
382 Detected */ 375 Detected */
383 376
384/* UCC GETH MIIMCFG (MII Management Configuration Register) */
385#define MIIMCFG_RESET_MANAGEMENT 0x80000000 /* Reset
386 management */
387#define MIIMCFG_NO_PREAMBLE 0x00000010 /* Preamble
388 suppress */
389#define MIIMCFG_CLOCK_DIVIDE_SHIFT (31 - 31) /* clock divide
390 << shift */
391#define MIIMCFG_CLOCK_DIVIDE_MAX 0xf /* clock divide max val
392 */
393#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2 0x00000000 /* divide by 2 */
394#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4 0x00000001 /* divide by 4 */
395#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6 0x00000002 /* divide by 6 */
396#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8 0x00000003 /* divide by 8 */
397#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10 0x00000004 /* divide by 10
398 */
399#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14 0x00000005 /* divide by 14
400 */
401#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16 0x00000008 /* divide by 16
402 */
403#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20 0x00000006 /* divide by 20
404 */
405#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28 0x00000007 /* divide by 28
406 */
407#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32 0x00000009 /* divide by 32
408 */
409#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48 0x0000000a /* divide by 48
410 */
411#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64 0x0000000b /* divide by 64
412 */
413#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80 0x0000000c /* divide by 80
414 */
415#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112 0x0000000d /* divide by
416 112 */
417#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160 0x0000000e /* divide by
418 160 */
419#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224 0x0000000f /* divide by
420 224 */
421
422/* UCC GETH MIIMCOM (MII Management Command Register) */
423#define MIIMCOM_SCAN_CYCLE 0x00000002 /* Scan cycle */
424#define MIIMCOM_READ_CYCLE 0x00000001 /* Read cycle */
425
426/* UCC GETH MIIMADD (MII Management Address Register) */
427#define MIIMADD_PHY_ADDRESS_SHIFT (31 - 23) /* PHY Address
428 << shift */
429#define MIIMADD_PHY_REGISTER_SHIFT (31 - 31) /* PHY Register
430 << shift */
431
432/* UCC GETH MIIMCON (MII Management Control Register) */
433#define MIIMCON_PHY_CONTROL_SHIFT (31 - 31) /* PHY Control
434 << shift */
435#define MIIMCON_PHY_STATUS_SHIFT (31 - 31) /* PHY Status
436 << shift */
437
438/* UCC GETH MIIMIND (MII Management Indicator Register) */
439#define MIIMIND_NOT_VALID 0x00000004 /* Not valid */
440#define MIIMIND_SCAN 0x00000002 /* Scan in
441 progress */
442#define MIIMIND_BUSY 0x00000001
443
444/* UCC GETH IFSTAT (Interface Status Register) */ 377/* UCC GETH IFSTAT (Interface Status Register) */
445#define IFSTAT_EXCESS_DEFER 0x00000200 /* Excessive 378#define IFSTAT_EXCESS_DEFER 0x00000200 /* Excessive
446 transmission 379 transmission
@@ -1009,15 +942,6 @@ struct ucc_geth_hardware_statistics {
1009 register */ 942 register */
1010#define UCC_GETH_MACCFG1_INIT 0 943#define UCC_GETH_MACCFG1_INIT 0
1011#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1) 944#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1)
1012#define UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT \
1013 (MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112)
1014
1015/* Ethernet speed */
1016enum enet_speed {
1017 ENET_SPEED_10BT, /* 10 Base T */
1018 ENET_SPEED_100BT, /* 100 Base T */
1019 ENET_SPEED_1000BT /* 1000 Base T */
1020};
1021 945
1022/* Ethernet Address Type. */ 946/* Ethernet Address Type. */
1023enum enet_addr_type { 947enum enet_addr_type {
@@ -1026,22 +950,6 @@ enum enet_addr_type {
1026 ENET_ADDR_TYPE_BROADCAST 950 ENET_ADDR_TYPE_BROADCAST
1027}; 951};
1028 952
1029/* TBI / MII Set Register */
1030enum enet_tbi_mii_reg {
1031 ENET_TBI_MII_CR = 0x00, /* Control (CR ) */
1032 ENET_TBI_MII_SR = 0x01, /* Status (SR ) */
1033 ENET_TBI_MII_ANA = 0x04, /* AN advertisement (ANA ) */
1034 ENET_TBI_MII_ANLPBPA = 0x05, /* AN link partner base page ability
1035 (ANLPBPA) */
1036 ENET_TBI_MII_ANEX = 0x06, /* AN expansion (ANEX ) */
1037 ENET_TBI_MII_ANNPT = 0x07, /* AN next page transmit (ANNPT ) */
1038 ENET_TBI_MII_ANLPANP = 0x08, /* AN link partner ability next page
1039 (ANLPANP) */
1040 ENET_TBI_MII_EXST = 0x0F, /* Extended status (EXST ) */
1041 ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics (JD ) */
1042 ENET_TBI_MII_TBICON = 0x11 /* TBI control (TBICON ) */
1043};
1044
1045/* UCC GETH 82xx Ethernet Address Recognition Location */ 953/* UCC GETH 82xx Ethernet Address Recognition Location */
1046enum ucc_geth_enet_address_recognition_location { 954enum ucc_geth_enet_address_recognition_location {
1047 UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station 955 UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station
@@ -1239,8 +1147,7 @@ struct ucc_geth_info {
1239 u16 pausePeriod; 1147 u16 pausePeriod;
1240 u16 extensionField; 1148 u16 extensionField;
1241 u8 phy_address; 1149 u8 phy_address;
1242 u32 board_flags; 1150 u32 mdio_bus;
1243 u32 phy_interrupt;
1244 u8 weightfactor[NUM_TX_QUEUES]; 1151 u8 weightfactor[NUM_TX_QUEUES];
1245 u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; 1152 u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
1246 u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; 1153 u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
@@ -1249,7 +1156,6 @@ struct ucc_geth_info {
1249 u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; 1156 u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
1250 u16 bdRingLenTx[NUM_TX_QUEUES]; 1157 u16 bdRingLenTx[NUM_TX_QUEUES];
1251 u16 bdRingLenRx[NUM_RX_QUEUES]; 1158 u16 bdRingLenRx[NUM_RX_QUEUES];
1252 enum enet_interface enet_interface;
1253 enum ucc_geth_num_of_station_addresses numStationAddresses; 1159 enum ucc_geth_num_of_station_addresses numStationAddresses;
1254 enum qe_fltr_largest_external_tbl_lookup_key_size 1160 enum qe_fltr_largest_external_tbl_lookup_key_size
1255 largestexternallookupkeysize; 1161 largestexternallookupkeysize;
@@ -1326,9 +1232,11 @@ struct ucc_geth_private {
1326 /* index of the first skb which hasn't been transmitted yet. */ 1232 /* index of the first skb which hasn't been transmitted yet. */
1327 u16 skb_dirtytx[NUM_TX_QUEUES]; 1233 u16 skb_dirtytx[NUM_TX_QUEUES];
1328 1234
1329 struct work_struct tq;
1330 struct timer_list phy_info_timer;
1331 struct ugeth_mii_info *mii_info; 1235 struct ugeth_mii_info *mii_info;
1236 struct phy_device *phydev;
1237 phy_interface_t phy_interface;
1238 int max_speed;
1239 uint32_t msg_enable;
1332 int oldspeed; 1240 int oldspeed;
1333 int oldduplex; 1241 int oldduplex;
1334 int oldlink; 1242 int oldlink;
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
new file mode 100644
index 000000000000..73b5a538e8f4
--- /dev/null
+++ b/drivers/net/ucc_geth_mii.c
@@ -0,0 +1,279 @@
1/*
2 * drivers/net/ucc_geth_mii.c
3 *
4 * Gianfar Ethernet Driver -- MIIM bus implementation
5 * Provides Bus interface for MIIM regs
6 *
7 * Author: Li Yang
8 *
9 * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/string.h>
21#include <linux/errno.h>
22#include <linux/unistd.h>
23#include <linux/slab.h>
24#include <linux/interrupt.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/netdevice.h>
28#include <linux/etherdevice.h>
29#include <linux/skbuff.h>
30#include <linux/spinlock.h>
31#include <linux/mm.h>
32#include <linux/module.h>
33#include <linux/platform_device.h>
34#include <asm/ocp.h>
35#include <linux/crc32.h>
36#include <linux/mii.h>
37#include <linux/phy.h>
38#include <linux/fsl_devices.h>
39
40#include <asm/of_platform.h>
41#include <asm/io.h>
42#include <asm/irq.h>
43#include <asm/uaccess.h>
44#include <asm/ucc.h>
45
46#include "ucc_geth_mii.h"
47#include "ucc_geth.h"
48
49#define DEBUG
50#ifdef DEBUG
51#define vdbg(format, arg...) printk(KERN_DEBUG , format "\n" , ## arg)
52#else
53#define vdbg(format, arg...) do {} while(0)
54#endif
55
56#define DRV_DESC "QE UCC Ethernet Controller MII Bus"
57#define DRV_NAME "fsl-uec_mdio"
58
59/* Write value to the PHY for this device to the register at regnum, */
60/* waiting until the write is done before it returns. All PHY */
61/* configuration has to be done through the master UEC MIIM regs */
62int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
63{
64 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
65
66 /* Setting up the MII Mangement Address Register */
67 out_be32(&regs->miimadd,
68 (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum);
69
70 /* Setting up the MII Mangement Control Register with the value */
71 out_be32(&regs->miimcon, value);
72
73 /* Wait till MII management write is complete */
74 while ((in_be32(&regs->miimind)) & MIIMIND_BUSY)
75 cpu_relax();
76
77 return 0;
78}
79
80/* Reads from register regnum in the PHY for device dev, */
81/* returning the value. Clears miimcom first. All PHY */
82/* configuration has to be done through the TSEC1 MIIM regs */
83int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
84{
85 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
86 u16 value;
87
88 /* Setting up the MII Mangement Address Register */
89 out_be32(&regs->miimadd,
90 (mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | regnum);
91
92 /* Clear miimcom, perform an MII management read cycle */
93 out_be32(&regs->miimcom, 0);
94 out_be32(&regs->miimcom, MIIMCOM_READ_CYCLE);
95
96 /* Wait till MII management write is complete */
97 while ((in_be32(&regs->miimind)) & (MIIMIND_BUSY | MIIMIND_NOT_VALID))
98 cpu_relax();
99
100 /* Read MII management status */
101 value = in_be32(&regs->miimstat);
102
103 return value;
104}
105
106/* Reset the MIIM registers, and wait for the bus to free */
107int uec_mdio_reset(struct mii_bus *bus)
108{
109 struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
110 unsigned int timeout = PHY_INIT_TIMEOUT;
111
112 spin_lock_bh(&bus->mdio_lock);
113
114 /* Reset the management interface */
115 out_be32(&regs->miimcfg, MIIMCFG_RESET_MANAGEMENT);
116
117 /* Setup the MII Mgmt clock speed */
118 out_be32(&regs->miimcfg, MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112);
119
120 /* Wait until the bus is free */
121 while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
122 cpu_relax();
123
124 spin_unlock_bh(&bus->mdio_lock);
125
126 if (timeout <= 0) {
127 printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name);
128 return -EBUSY;
129 }
130
131 return 0;
132}
133
134static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *match)
135{
136 struct device *device = &ofdev->dev;
137 struct device_node *np = ofdev->node, *tempnp = NULL;
138 struct device_node *child = NULL;
139 struct ucc_mii_mng __iomem *regs;
140 struct mii_bus *new_bus;
141 struct resource res;
142 int k, err = 0;
143
144 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
145
146 if (NULL == new_bus)
147 return -ENOMEM;
148
149 new_bus->name = "UCC Ethernet Controller MII Bus";
150 new_bus->read = &uec_mdio_read;
151 new_bus->write = &uec_mdio_write;
152 new_bus->reset = &uec_mdio_reset;
153
154 memset(&res, 0, sizeof(res));
155
156 err = of_address_to_resource(np, 0, &res);
157 if (err)
158 goto reg_map_fail;
159
160 new_bus->id = res.start;
161
162 new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL);
163
164 if (NULL == new_bus->irq) {
165 err = -ENOMEM;
166 goto reg_map_fail;
167 }
168
169 for (k = 0; k < 32; k++)
170 new_bus->irq[k] = PHY_POLL;
171
172 while ((child = of_get_next_child(np, child)) != NULL) {
173 int irq = irq_of_parse_and_map(child, 0);
174 if (irq != NO_IRQ) {
175 const u32 *id = get_property(child, "reg", NULL);
176 new_bus->irq[*id] = irq;
177 }
178 }
179
180 /* Set the base address */
181 regs = ioremap(res.start, sizeof(struct ucc_mii_mng));
182
183 if (NULL == regs) {
184 err = -ENOMEM;
185 goto ioremap_fail;
186 }
187
188 new_bus->priv = (void __force *)regs;
189
190 new_bus->dev = device;
191 dev_set_drvdata(device, new_bus);
192
193 /* Read MII management master from device tree */
194 while ((tempnp = of_find_compatible_node(tempnp, "network", "ucc_geth"))
195 != NULL) {
196 struct resource tempres;
197
198 err = of_address_to_resource(tempnp, 0, &tempres);
199 if (err)
200 goto bus_register_fail;
201
202 /* if our mdio regs fall within this UCC regs range */
203 if ((res.start >= tempres.start) &&
204 (res.end <= tempres.end)) {
205 /* set this UCC to be the MII master */
206 const u32 *id = get_property(tempnp, "device-id", NULL);
207 if (id == NULL)
208 goto bus_register_fail;
209
210 ucc_set_qe_mux_mii_mng(*id - 1);
211
212 /* assign the TBI an address which won't
213 * conflict with the PHYs */
214 out_be32(&regs->utbipar, UTBIPAR_INIT_TBIPA);
215 break;
216 }
217 }
218
219 err = mdiobus_register(new_bus);
220 if (0 != err) {
221 printk(KERN_ERR "%s: Cannot register as MDIO bus\n",
222 new_bus->name);
223 goto bus_register_fail;
224 }
225
226 return 0;
227
228bus_register_fail:
229 iounmap(regs);
230ioremap_fail:
231 kfree(new_bus->irq);
232reg_map_fail:
233 kfree(new_bus);
234
235 return err;
236}
237
238int uec_mdio_remove(struct of_device *ofdev)
239{
240 struct device *device = &ofdev->dev;
241 struct mii_bus *bus = dev_get_drvdata(device);
242
243 mdiobus_unregister(bus);
244
245 dev_set_drvdata(device, NULL);
246
247 iounmap((void __iomem *)bus->priv);
248 bus->priv = NULL;
249 kfree(bus);
250
251 return 0;
252}
253
254static struct of_device_id uec_mdio_match[] = {
255 {
256 .type = "mdio",
257 .compatible = "ucc_geth_phy",
258 },
259 {},
260};
261
262MODULE_DEVICE_TABLE(of, uec_mdio_match);
263
264static struct of_platform_driver uec_mdio_driver = {
265 .name = DRV_NAME,
266 .probe = uec_mdio_probe,
267 .remove = uec_mdio_remove,
268 .match_table = uec_mdio_match,
269};
270
271int __init uec_mdio_init(void)
272{
273 return of_register_platform_driver(&uec_mdio_driver);
274}
275
276void __exit uec_mdio_exit(void)
277{
278 of_unregister_platform_driver(&uec_mdio_driver);
279}
diff --git a/drivers/net/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h
new file mode 100644
index 000000000000..98430fe0bfc6
--- /dev/null
+++ b/drivers/net/ucc_geth_mii.h
@@ -0,0 +1,100 @@
1/*
2 * drivers/net/ucc_geth_mii.h
3 *
4 * Gianfar Ethernet Driver -- MII Management Bus Implementation
5 * Driver for the MDIO bus controller in the Gianfar register space
6 *
7 * Author: Andy Fleming
8 * Maintainer: Kumar Gala
9 *
10 * Copyright (c) 2002-2004 Freescale Semiconductor, Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18#ifndef __UEC_MII_H
19#define __UEC_MII_H
20
21/* UCC GETH MIIMCFG (MII Management Configuration Register) */
22#define MIIMCFG_RESET_MANAGEMENT 0x80000000 /* Reset
23 management */
24#define MIIMCFG_NO_PREAMBLE 0x00000010 /* Preamble
25 suppress */
26#define MIIMCFG_CLOCK_DIVIDE_SHIFT (31 - 31) /* clock divide
27 << shift */
28#define MIIMCFG_CLOCK_DIVIDE_MAX 0xf /* max clock divide */
29#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2 0x00000000
30#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4 0x00000001
31#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6 0x00000002
32#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8 0x00000003
33#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10 0x00000004
34#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14 0x00000005
35#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16 0x00000008
36#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20 0x00000006
37#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28 0x00000007
38#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32 0x00000009
39#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48 0x0000000a
40#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64 0x0000000b
41#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80 0x0000000c
42#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112 0x0000000d
43#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160 0x0000000e
44#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224 0x0000000f
45
46/* UCC GETH MIIMCOM (MII Management Command Register) */
47#define MIIMCOM_SCAN_CYCLE 0x00000002 /* Scan cycle */
48#define MIIMCOM_READ_CYCLE 0x00000001 /* Read cycle */
49
50/* UCC GETH MIIMADD (MII Management Address Register) */
51#define MIIMADD_PHY_ADDRESS_SHIFT (31 - 23) /* PHY Address
52 << shift */
53#define MIIMADD_PHY_REGISTER_SHIFT (31 - 31) /* PHY Register
54 << shift */
55
56/* UCC GETH MIIMCON (MII Management Control Register) */
57#define MIIMCON_PHY_CONTROL_SHIFT (31 - 31) /* PHY Control
58 << shift */
59#define MIIMCON_PHY_STATUS_SHIFT (31 - 31) /* PHY Status
60 << shift */
61
62/* UCC GETH MIIMIND (MII Management Indicator Register) */
63#define MIIMIND_NOT_VALID 0x00000004 /* Not valid */
64#define MIIMIND_SCAN 0x00000002 /* Scan in
65 progress */
66#define MIIMIND_BUSY 0x00000001
67
68/* Initial TBI Physical Address */
69#define UTBIPAR_INIT_TBIPA 0x1f
70
71struct ucc_mii_mng {
72 u32 miimcfg; /* MII management configuration reg */
73 u32 miimcom; /* MII management command reg */
74 u32 miimadd; /* MII management address reg */
75 u32 miimcon; /* MII management control reg */
76 u32 miimstat; /* MII management status reg */
77 u32 miimind; /* MII management indication reg */
78 u8 notcare[28]; /* Space holder */
79 u32 utbipar; /* TBI phy address reg */
80} __attribute__ ((packed));
81
82/* TBI / MII Set Register */
83enum enet_tbi_mii_reg {
84 ENET_TBI_MII_CR = 0x00, /* Control */
85 ENET_TBI_MII_SR = 0x01, /* Status */
86 ENET_TBI_MII_ANA = 0x04, /* AN advertisement */
87 ENET_TBI_MII_ANLPBPA = 0x05, /* AN link partner base page ability */
88 ENET_TBI_MII_ANEX = 0x06, /* AN expansion */
89 ENET_TBI_MII_ANNPT = 0x07, /* AN next page transmit */
90 ENET_TBI_MII_ANLPANP = 0x08, /* AN link partner ability next page */
91 ENET_TBI_MII_EXST = 0x0F, /* Extended status */
92 ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics */
93 ENET_TBI_MII_TBICON = 0x11 /* TBI control */
94};
95
96int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
97int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
98int __init uec_mdio_init(void);
99void __exit uec_mdio_exit(void);
100#endif /* __UEC_MII_H */
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
deleted file mode 100644
index 9373d895b9ec..000000000000
--- a/drivers/net/ucc_geth_phy.c
+++ /dev/null
@@ -1,785 +0,0 @@
1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
3 *
4 * Author: Shlomi Gridish <gridish@freescale.com>
5 *
6 * Description:
7 * UCC GETH Driver -- PHY handling
8 *
9 * Changelog:
10 * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
11 * - Rearrange code and style fixes
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/string.h>
22#include <linux/errno.h>
23#include <linux/slab.h>
24#include <linux/interrupt.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/netdevice.h>
28#include <linux/etherdevice.h>
29#include <linux/skbuff.h>
30#include <linux/spinlock.h>
31#include <linux/mm.h>
32#include <linux/module.h>
33#include <linux/version.h>
34#include <linux/crc32.h>
35#include <linux/mii.h>
36#include <linux/ethtool.h>
37
38#include <asm/io.h>
39#include <asm/irq.h>
40#include <asm/uaccess.h>
41
42#include "ucc_geth.h"
43#include "ucc_geth_phy.h"
44
45#define ugphy_printk(level, format, arg...) \
46 printk(level format "\n", ## arg)
47
48#define ugphy_dbg(format, arg...) \
49 ugphy_printk(KERN_DEBUG, format , ## arg)
50#define ugphy_err(format, arg...) \
51 ugphy_printk(KERN_ERR, format , ## arg)
52#define ugphy_info(format, arg...) \
53 ugphy_printk(KERN_INFO, format , ## arg)
54#define ugphy_warn(format, arg...) \
55 ugphy_printk(KERN_WARNING, format , ## arg)
56
57#ifdef UGETH_VERBOSE_DEBUG
58#define ugphy_vdbg ugphy_dbg
59#else
60#define ugphy_vdbg(fmt, args...) do { } while (0)
61#endif /* UGETH_VERBOSE_DEBUG */
62
63static void config_genmii_advert(struct ugeth_mii_info *mii_info);
64static void genmii_setup_forced(struct ugeth_mii_info *mii_info);
65static void genmii_restart_aneg(struct ugeth_mii_info *mii_info);
66static int gbit_config_aneg(struct ugeth_mii_info *mii_info);
67static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
68static int genmii_update_link(struct ugeth_mii_info *mii_info);
69static int genmii_read_status(struct ugeth_mii_info *mii_info);
70
71static u16 ucc_geth_phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
72{
73 u16 retval;
74 unsigned long flags;
75
76 ugphy_vdbg("%s: IN", __FUNCTION__);
77
78 spin_lock_irqsave(&mii_info->mdio_lock, flags);
79 retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
80 spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
81
82 return retval;
83}
84
85static void ucc_geth_phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
86{
87 unsigned long flags;
88
89 ugphy_vdbg("%s: IN", __FUNCTION__);
90
91 spin_lock_irqsave(&mii_info->mdio_lock, flags);
92 mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
93 spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
94}
95
96/* Write value to the PHY for this device to the register at regnum, */
97/* waiting until the write is done before it returns. All PHY */
98/* configuration has to be done through the TSEC1 MIIM regs */
99void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
100{
101 struct ucc_geth_private *ugeth = netdev_priv(dev);
102 struct ucc_mii_mng *mii_regs;
103 enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg) regnum;
104 u32 tmp_reg;
105
106 ugphy_vdbg("%s: IN", __FUNCTION__);
107
108 spin_lock_irq(&ugeth->lock);
109
110 mii_regs = ugeth->mii_info->mii_regs;
111
112 /* Set this UCC to be the master of the MII managment */
113 ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
114
115 /* Stop the MII management read cycle */
116 out_be32(&mii_regs->miimcom, 0);
117 /* Setting up the MII Mangement Address Register */
118 tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
119 out_be32(&mii_regs->miimadd, tmp_reg);
120
121 /* Setting up the MII Mangement Control Register with the value */
122 out_be32(&mii_regs->miimcon, (u32) value);
123
124 /* Wait till MII management write is complete */
125 while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
126 cpu_relax();
127
128 spin_unlock_irq(&ugeth->lock);
129
130 udelay(10000);
131}
132
133/* Reads from register regnum in the PHY for device dev, */
134/* returning the value. Clears miimcom first. All PHY */
135/* configuration has to be done through the TSEC1 MIIM regs */
136int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
137{
138 struct ucc_geth_private *ugeth = netdev_priv(dev);
139 struct ucc_mii_mng *mii_regs;
140 enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg) regnum;
141 u32 tmp_reg;
142 u16 value;
143
144 ugphy_vdbg("%s: IN", __FUNCTION__);
145
146 spin_lock_irq(&ugeth->lock);
147
148 mii_regs = ugeth->mii_info->mii_regs;
149
150 /* Setting up the MII Mangement Address Register */
151 tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
152 out_be32(&mii_regs->miimadd, tmp_reg);
153
154 /* Perform an MII management read cycle */
155 out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE);
156
157 /* Wait till MII management write is complete */
158 while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
159 cpu_relax();
160
161 udelay(10000);
162
163 /* Read MII management status */
164 value = (u16) in_be32(&mii_regs->miimstat);
165 out_be32(&mii_regs->miimcom, 0);
166 if (value == 0xffff)
167 ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x",
168 mii_id, mii_reg, (u32) & (mii_regs->miimcfg));
169
170 spin_unlock_irq(&ugeth->lock);
171
172 return (value);
173}
174
175void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info)
176{
177 ugphy_vdbg("%s: IN", __FUNCTION__);
178
179 if (mii_info->phyinfo->ack_interrupt)
180 mii_info->phyinfo->ack_interrupt(mii_info);
181}
182
183void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
184 u32 interrupts)
185{
186 ugphy_vdbg("%s: IN", __FUNCTION__);
187
188 mii_info->interrupts = interrupts;
189 if (mii_info->phyinfo->config_intr)
190 mii_info->phyinfo->config_intr(mii_info);
191}
192
193/* Writes MII_ADVERTISE with the appropriate values, after
194 * sanitizing advertise to make sure only supported features
195 * are advertised
196 */
197static void config_genmii_advert(struct ugeth_mii_info *mii_info)
198{
199 u32 advertise;
200 u16 adv;
201
202 ugphy_vdbg("%s: IN", __FUNCTION__);
203
204 /* Only allow advertising what this PHY supports */
205 mii_info->advertising &= mii_info->phyinfo->features;
206 advertise = mii_info->advertising;
207
208 /* Setup standard advertisement */
209 adv = ucc_geth_phy_read(mii_info, MII_ADVERTISE);
210 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
211 if (advertise & ADVERTISED_10baseT_Half)
212 adv |= ADVERTISE_10HALF;
213 if (advertise & ADVERTISED_10baseT_Full)
214 adv |= ADVERTISE_10FULL;
215 if (advertise & ADVERTISED_100baseT_Half)
216 adv |= ADVERTISE_100HALF;
217 if (advertise & ADVERTISED_100baseT_Full)
218 adv |= ADVERTISE_100FULL;
219 ucc_geth_phy_write(mii_info, MII_ADVERTISE, adv);
220}
221
222static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
223{
224 u16 ctrl;
225 u32 features = mii_info->phyinfo->features;
226
227 ugphy_vdbg("%s: IN", __FUNCTION__);
228
229 ctrl = ucc_geth_phy_read(mii_info, MII_BMCR);
230
231 ctrl &=
232 ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
233 ctrl |= BMCR_RESET;
234
235 switch (mii_info->speed) {
236 case SPEED_1000:
237 if (features & (SUPPORTED_1000baseT_Half
238 | SUPPORTED_1000baseT_Full)) {
239 ctrl |= BMCR_SPEED1000;
240 break;
241 }
242 mii_info->speed = SPEED_100;
243 case SPEED_100:
244 if (features & (SUPPORTED_100baseT_Half
245 | SUPPORTED_100baseT_Full)) {
246 ctrl |= BMCR_SPEED100;
247 break;
248 }
249 mii_info->speed = SPEED_10;
250 case SPEED_10:
251 if (features & (SUPPORTED_10baseT_Half
252 | SUPPORTED_10baseT_Full))
253 break;
254 default: /* Unsupported speed! */
255 ugphy_err("%s: Bad speed!", mii_info->dev->name);
256 break;
257 }
258
259 ucc_geth_phy_write(mii_info, MII_BMCR, ctrl);
260}
261
262/* Enable and Restart Autonegotiation */
263static void genmii_restart_aneg(struct ugeth_mii_info *mii_info)
264{
265 u16 ctl;
266
267 ugphy_vdbg("%s: IN", __FUNCTION__);
268
269 ctl = ucc_geth_phy_read(mii_info, MII_BMCR);
270 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
271 ucc_geth_phy_write(mii_info, MII_BMCR, ctl);
272}
273
274static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
275{
276 u16 adv;
277 u32 advertise;
278
279 ugphy_vdbg("%s: IN", __FUNCTION__);
280
281 if (mii_info->autoneg) {
282 /* Configure the ADVERTISE register */
283 config_genmii_advert(mii_info);
284 advertise = mii_info->advertising;
285
286 adv = ucc_geth_phy_read(mii_info, MII_1000BASETCONTROL);
287 adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
288 MII_1000BASETCONTROL_HALFDUPLEXCAP);
289 if (advertise & SUPPORTED_1000baseT_Half)
290 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
291 if (advertise & SUPPORTED_1000baseT_Full)
292 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
293 ucc_geth_phy_write(mii_info, MII_1000BASETCONTROL, adv);
294
295 /* Start/Restart aneg */
296 genmii_restart_aneg(mii_info);
297 } else
298 genmii_setup_forced(mii_info);
299
300 return 0;
301}
302
303static int genmii_config_aneg(struct ugeth_mii_info *mii_info)
304{
305 ugphy_vdbg("%s: IN", __FUNCTION__);
306
307 if (mii_info->autoneg) {
308 config_genmii_advert(mii_info);
309 genmii_restart_aneg(mii_info);
310 } else
311 genmii_setup_forced(mii_info);
312
313 return 0;
314}
315
316static int genmii_update_link(struct ugeth_mii_info *mii_info)
317{
318 u16 status;
319
320 ugphy_vdbg("%s: IN", __FUNCTION__);
321
322 /* Do a fake read */
323 ucc_geth_phy_read(mii_info, MII_BMSR);
324
325 /* Read link and autonegotiation status */
326 status = ucc_geth_phy_read(mii_info, MII_BMSR);
327 if ((status & BMSR_LSTATUS) == 0)
328 mii_info->link = 0;
329 else
330 mii_info->link = 1;
331
332 /* If we are autonegotiating, and not done,
333 * return an error */
334 if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
335 return -EAGAIN;
336
337 return 0;
338}
339
340static int genmii_read_status(struct ugeth_mii_info *mii_info)
341{
342 u16 status;
343 int err;
344
345 ugphy_vdbg("%s: IN", __FUNCTION__);
346
347 /* Update the link, but return if there
348 * was an error */
349 err = genmii_update_link(mii_info);
350 if (err)
351 return err;
352
353 if (mii_info->autoneg) {
354 status = ucc_geth_phy_read(mii_info, MII_LPA);
355
356 if (status & (LPA_10FULL | LPA_100FULL))
357 mii_info->duplex = DUPLEX_FULL;
358 else
359 mii_info->duplex = DUPLEX_HALF;
360 if (status & (LPA_100FULL | LPA_100HALF))
361 mii_info->speed = SPEED_100;
362 else
363 mii_info->speed = SPEED_10;
364 mii_info->pause = 0;
365 }
366 /* On non-aneg, we assume what we put in BMCR is the speed,
367 * though magic-aneg shouldn't prevent this case from occurring
368 */
369
370 return 0;
371}
372
373static int marvell_init(struct ugeth_mii_info *mii_info)
374{
375 ugphy_vdbg("%s: IN", __FUNCTION__);
376
377 ucc_geth_phy_write(mii_info, 0x14, 0x0cd2);
378 ucc_geth_phy_write(mii_info, 0x1b,
379 (ucc_geth_phy_read(mii_info, 0x1b) & ~0x000f) | 0x000b);
380 ucc_geth_phy_write(mii_info, MII_BMCR,
381 ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
382 msleep(4000);
383
384 return 0;
385}
386
387static int marvell_config_aneg(struct ugeth_mii_info *mii_info)
388{
389 ugphy_vdbg("%s: IN", __FUNCTION__);
390
391 /* The Marvell PHY has an errata which requires
392 * that certain registers get written in order
393 * to restart autonegotiation */
394 ucc_geth_phy_write(mii_info, MII_BMCR, BMCR_RESET);
395
396 ucc_geth_phy_write(mii_info, 0x1d, 0x1f);
397 ucc_geth_phy_write(mii_info, 0x1e, 0x200c);
398 ucc_geth_phy_write(mii_info, 0x1d, 0x5);
399 ucc_geth_phy_write(mii_info, 0x1e, 0);
400 ucc_geth_phy_write(mii_info, 0x1e, 0x100);
401
402 gbit_config_aneg(mii_info);
403
404 return 0;
405}
406
407static int marvell_read_status(struct ugeth_mii_info *mii_info)
408{
409 u16 status;
410 int err;
411
412 ugphy_vdbg("%s: IN", __FUNCTION__);
413
414 /* Update the link, but return if there
415 * was an error */
416 err = genmii_update_link(mii_info);
417 if (err)
418 return err;
419
420 /* If the link is up, read the speed and duplex */
421 /* If we aren't autonegotiating, assume speeds
422 * are as set */
423 if (mii_info->autoneg && mii_info->link) {
424 int speed;
425 status = ucc_geth_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
426
427 /* Get the duplexity */
428 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
429 mii_info->duplex = DUPLEX_FULL;
430 else
431 mii_info->duplex = DUPLEX_HALF;
432
433 /* Get the speed */
434 speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
435 switch (speed) {
436 case MII_M1011_PHY_SPEC_STATUS_1000:
437 mii_info->speed = SPEED_1000;
438 break;
439 case MII_M1011_PHY_SPEC_STATUS_100:
440 mii_info->speed = SPEED_100;
441 break;
442 default:
443 mii_info->speed = SPEED_10;
444 break;
445 }
446 mii_info->pause = 0;
447 }
448
449 return 0;
450}
451
452static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info)
453{
454 ugphy_vdbg("%s: IN", __FUNCTION__);
455
456 /* Clear the interrupts by reading the reg */
457 ucc_geth_phy_read(mii_info, MII_M1011_IEVENT);
458
459 return 0;
460}
461
462static int marvell_config_intr(struct ugeth_mii_info *mii_info)
463{
464 ugphy_vdbg("%s: IN", __FUNCTION__);
465
466 if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
467 ucc_geth_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
468 else
469 ucc_geth_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
470
471 return 0;
472}
473
474static int cis820x_init(struct ugeth_mii_info *mii_info)
475{
476 ugphy_vdbg("%s: IN", __FUNCTION__);
477
478 ucc_geth_phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
479 MII_CIS8201_AUXCONSTAT_INIT);
480 ucc_geth_phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
481
482 return 0;
483}
484
485static int cis820x_read_status(struct ugeth_mii_info *mii_info)
486{
487 u16 status;
488 int err;
489
490 ugphy_vdbg("%s: IN", __FUNCTION__);
491
492 /* Update the link, but return if there
493 * was an error */
494 err = genmii_update_link(mii_info);
495 if (err)
496 return err;
497
498 /* If the link is up, read the speed and duplex */
499 /* If we aren't autonegotiating, assume speeds
500 * are as set */
501 if (mii_info->autoneg && mii_info->link) {
502 int speed;
503
504 status = ucc_geth_phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
505 if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
506 mii_info->duplex = DUPLEX_FULL;
507 else
508 mii_info->duplex = DUPLEX_HALF;
509
510 speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
511
512 switch (speed) {
513 case MII_CIS8201_AUXCONSTAT_GBIT:
514 mii_info->speed = SPEED_1000;
515 break;
516 case MII_CIS8201_AUXCONSTAT_100:
517 mii_info->speed = SPEED_100;
518 break;
519 default:
520 mii_info->speed = SPEED_10;
521 break;
522 }
523 }
524
525 return 0;
526}
527
528static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info)
529{
530 ugphy_vdbg("%s: IN", __FUNCTION__);
531
532 ucc_geth_phy_read(mii_info, MII_CIS8201_ISTAT);
533
534 return 0;
535}
536
537static int cis820x_config_intr(struct ugeth_mii_info *mii_info)
538{
539 ugphy_vdbg("%s: IN", __FUNCTION__);
540
541 if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
542 ucc_geth_phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
543 else
544 ucc_geth_phy_write(mii_info, MII_CIS8201_IMASK, 0);
545
546 return 0;
547}
548
549#define DM9161_DELAY 10
550
551static int dm9161_read_status(struct ugeth_mii_info *mii_info)
552{
553 u16 status;
554 int err;
555
556 ugphy_vdbg("%s: IN", __FUNCTION__);
557
558 /* Update the link, but return if there
559 * was an error */
560 err = genmii_update_link(mii_info);
561 if (err)
562 return err;
563
564 /* If the link is up, read the speed and duplex */
565 /* If we aren't autonegotiating, assume speeds
566 * are as set */
567 if (mii_info->autoneg && mii_info->link) {
568 status = ucc_geth_phy_read(mii_info, MII_DM9161_SCSR);
569 if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
570 mii_info->speed = SPEED_100;
571 else
572 mii_info->speed = SPEED_10;
573
574 if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
575 mii_info->duplex = DUPLEX_FULL;
576 else
577 mii_info->duplex = DUPLEX_HALF;
578 }
579
580 return 0;
581}
582
583static int dm9161_config_aneg(struct ugeth_mii_info *mii_info)
584{
585 struct dm9161_private *priv = mii_info->priv;
586
587 ugphy_vdbg("%s: IN", __FUNCTION__);
588
589 if (0 == priv->resetdone)
590 return -EAGAIN;
591
592 return 0;
593}
594
595static void dm9161_timer(unsigned long data)
596{
597 struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
598 struct dm9161_private *priv = mii_info->priv;
599 u16 status = ucc_geth_phy_read(mii_info, MII_BMSR);
600
601 ugphy_vdbg("%s: IN", __FUNCTION__);
602
603 if (status & BMSR_ANEGCOMPLETE) {
604 priv->resetdone = 1;
605 } else
606 mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
607}
608
609static int dm9161_init(struct ugeth_mii_info *mii_info)
610{
611 struct dm9161_private *priv;
612
613 ugphy_vdbg("%s: IN", __FUNCTION__);
614
615 /* Allocate the private data structure */
616 priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
617
618 if (NULL == priv)
619 return -ENOMEM;
620
621 mii_info->priv = priv;
622
623 /* Reset is not done yet */
624 priv->resetdone = 0;
625
626 ucc_geth_phy_write(mii_info, MII_BMCR,
627 ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
628
629 ucc_geth_phy_write(mii_info, MII_BMCR,
630 ucc_geth_phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
631
632 config_genmii_advert(mii_info);
633 /* Start/Restart aneg */
634 genmii_config_aneg(mii_info);
635
636 /* Start a timer for DM9161_DELAY seconds to wait
637 * for the PHY to be ready */
638 init_timer(&priv->timer);
639 priv->timer.function = &dm9161_timer;
640 priv->timer.data = (unsigned long)mii_info;
641 mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
642
643 return 0;
644}
645
646static void dm9161_close(struct ugeth_mii_info *mii_info)
647{
648 struct dm9161_private *priv = mii_info->priv;
649
650 ugphy_vdbg("%s: IN", __FUNCTION__);
651
652 del_timer_sync(&priv->timer);
653 kfree(priv);
654}
655
656static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
657{
658 ugphy_vdbg("%s: IN", __FUNCTION__);
659
660 /* Clear the interrupts by reading the reg */
661 ucc_geth_phy_read(mii_info, MII_DM9161_INTR);
662
663
664 return 0;
665}
666
667static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
668{
669 ugphy_vdbg("%s: IN", __FUNCTION__);
670
671 if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
672 ucc_geth_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
673 else
674 ucc_geth_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
675
676 return 0;
677}
678
679/* Cicada 820x */
680static struct phy_info phy_info_cis820x = {
681 .phy_id = 0x000fc440,
682 .name = "Cicada Cis8204",
683 .phy_id_mask = 0x000fffc0,
684 .features = MII_GBIT_FEATURES,
685 .init = &cis820x_init,
686 .config_aneg = &gbit_config_aneg,
687 .read_status = &cis820x_read_status,
688 .ack_interrupt = &cis820x_ack_interrupt,
689 .config_intr = &cis820x_config_intr,
690};
691
692static struct phy_info phy_info_dm9161 = {
693 .phy_id = 0x0181b880,
694 .phy_id_mask = 0x0ffffff0,
695 .name = "Davicom DM9161E",
696 .init = dm9161_init,
697 .config_aneg = dm9161_config_aneg,
698 .read_status = dm9161_read_status,
699 .close = dm9161_close,
700};
701
702static struct phy_info phy_info_dm9161a = {
703 .phy_id = 0x0181b8a0,
704 .phy_id_mask = 0x0ffffff0,
705 .name = "Davicom DM9161A",
706 .features = MII_BASIC_FEATURES,
707 .init = dm9161_init,
708 .config_aneg = dm9161_config_aneg,
709 .read_status = dm9161_read_status,
710 .ack_interrupt = dm9161_ack_interrupt,
711 .config_intr = dm9161_config_intr,
712 .close = dm9161_close,
713};
714
715static struct phy_info phy_info_marvell = {
716 .phy_id = 0x01410c00,
717 .phy_id_mask = 0xffffff00,
718 .name = "Marvell 88E11x1",
719 .features = MII_GBIT_FEATURES,
720 .init = &marvell_init,
721 .config_aneg = &marvell_config_aneg,
722 .read_status = &marvell_read_status,
723 .ack_interrupt = &marvell_ack_interrupt,
724 .config_intr = &marvell_config_intr,
725};
726
727static struct phy_info phy_info_genmii = {
728 .phy_id = 0x00000000,
729 .phy_id_mask = 0x00000000,
730 .name = "Generic MII",
731 .features = MII_BASIC_FEATURES,
732 .config_aneg = genmii_config_aneg,
733 .read_status = genmii_read_status,
734};
735
736static struct phy_info *phy_info[] = {
737 &phy_info_cis820x,
738 &phy_info_marvell,
739 &phy_info_dm9161,
740 &phy_info_dm9161a,
741 &phy_info_genmii,
742 NULL
743};
744
745/* Use the PHY ID registers to determine what type of PHY is attached
746 * to device dev. return a struct phy_info structure describing that PHY
747 */
748struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info)
749{
750 u16 phy_reg;
751 u32 phy_ID;
752 int i;
753 struct phy_info *theInfo = NULL;
754 struct net_device *dev = mii_info->dev;
755
756 ugphy_vdbg("%s: IN", __FUNCTION__);
757
758 /* Grab the bits from PHYIR1, and put them in the upper half */
759 phy_reg = ucc_geth_phy_read(mii_info, MII_PHYSID1);
760 phy_ID = (phy_reg & 0xffff) << 16;
761
762 /* Grab the bits from PHYIR2, and put them in the lower half */
763 phy_reg = ucc_geth_phy_read(mii_info, MII_PHYSID2);
764 phy_ID |= (phy_reg & 0xffff);
765
766 /* loop through all the known PHY types, and find one that */
767 /* matches the ID we read from the PHY. */
768 for (i = 0; phy_info[i]; i++)
769 if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){
770 theInfo = phy_info[i];
771 break;
772 }
773
774 /* This shouldn't happen, as we have generic PHY support */
775 if (theInfo == NULL) {
776 ugphy_info("%s: PHY id %x is not supported!", dev->name,
777 phy_ID);
778 return NULL;
779 } else {
780 ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name,
781 phy_ID);
782 }
783
784 return theInfo;
785}
diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h
deleted file mode 100644
index f5740783670f..000000000000
--- a/drivers/net/ucc_geth_phy.h
+++ /dev/null
@@ -1,217 +0,0 @@
1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
3 *
4 * Author: Shlomi Gridish <gridish@freescale.com>
5 *
6 * Description:
7 * UCC GETH Driver -- PHY handling
8 *
9 * Changelog:
10 * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
11 * - Rearrange code and style fixes
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 */
19#ifndef __UCC_GETH_PHY_H__
20#define __UCC_GETH_PHY_H__
21
22#define MII_end ((u32)-2)
23#define MII_read ((u32)-1)
24
25#define MIIMIND_BUSY 0x00000001
26#define MIIMIND_NOTVALID 0x00000004
27
28#define UGETH_AN_TIMEOUT 2000
29
30/* 1000BT control (Marvell & BCM54xx at least) */
31#define MII_1000BASETCONTROL 0x09
32#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200
33#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100
34
35/* Cicada Extended Control Register 1 */
36#define MII_CIS8201_EXT_CON1 0x17
37#define MII_CIS8201_EXTCON1_INIT 0x0000
38
39/* Cicada Interrupt Mask Register */
40#define MII_CIS8201_IMASK 0x19
41#define MII_CIS8201_IMASK_IEN 0x8000
42#define MII_CIS8201_IMASK_SPEED 0x4000
43#define MII_CIS8201_IMASK_LINK 0x2000
44#define MII_CIS8201_IMASK_DUPLEX 0x1000
45#define MII_CIS8201_IMASK_MASK 0xf000
46
47/* Cicada Interrupt Status Register */
48#define MII_CIS8201_ISTAT 0x1a
49#define MII_CIS8201_ISTAT_STATUS 0x8000
50#define MII_CIS8201_ISTAT_SPEED 0x4000
51#define MII_CIS8201_ISTAT_LINK 0x2000
52#define MII_CIS8201_ISTAT_DUPLEX 0x1000
53
54/* Cicada Auxiliary Control/Status Register */
55#define MII_CIS8201_AUX_CONSTAT 0x1c
56#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
57#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
58#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
59#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
60#define MII_CIS8201_AUXCONSTAT_100 0x0008
61
62/* 88E1011 PHY Status Register */
63#define MII_M1011_PHY_SPEC_STATUS 0x11
64#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000
65#define MII_M1011_PHY_SPEC_STATUS_100 0x4000
66#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
67#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
68#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
69#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400
70
71#define MII_M1011_IEVENT 0x13
72#define MII_M1011_IEVENT_CLEAR 0x0000
73
74#define MII_M1011_IMASK 0x12
75#define MII_M1011_IMASK_INIT 0x6400
76#define MII_M1011_IMASK_CLEAR 0x0000
77
78#define MII_DM9161_SCR 0x10
79#define MII_DM9161_SCR_INIT 0x0610
80
81/* DM9161 Specified Configuration and Status Register */
82#define MII_DM9161_SCSR 0x11
83#define MII_DM9161_SCSR_100F 0x8000
84#define MII_DM9161_SCSR_100H 0x4000
85#define MII_DM9161_SCSR_10F 0x2000
86#define MII_DM9161_SCSR_10H 0x1000
87
88/* DM9161 Interrupt Register */
89#define MII_DM9161_INTR 0x15
90#define MII_DM9161_INTR_PEND 0x8000
91#define MII_DM9161_INTR_DPLX_MASK 0x0800
92#define MII_DM9161_INTR_SPD_MASK 0x0400
93#define MII_DM9161_INTR_LINK_MASK 0x0200
94#define MII_DM9161_INTR_MASK 0x0100
95#define MII_DM9161_INTR_DPLX_CHANGE 0x0010
96#define MII_DM9161_INTR_SPD_CHANGE 0x0008
97#define MII_DM9161_INTR_LINK_CHANGE 0x0004
98#define MII_DM9161_INTR_INIT 0x0000
99#define MII_DM9161_INTR_STOP \
100(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
101 | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
102
103/* DM9161 10BT Configuration/Status */
104#define MII_DM9161_10BTCSR 0x12
105#define MII_DM9161_10BTCSR_INIT 0x7800
106
107#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
108 SUPPORTED_10baseT_Full | \
109 SUPPORTED_100baseT_Half | \
110 SUPPORTED_100baseT_Full | \
111 SUPPORTED_Autoneg | \
112 SUPPORTED_TP | \
113 SUPPORTED_MII)
114
115#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
116 SUPPORTED_1000baseT_Half | \
117 SUPPORTED_1000baseT_Full)
118
119#define MII_READ_COMMAND 0x00000001
120
121#define MII_INTERRUPT_DISABLED 0x0
122#define MII_INTERRUPT_ENABLED 0x1
123/* Taken from mii_if_info and sungem_phy.h */
124struct ugeth_mii_info {
125 /* Information about the PHY type */
126 /* And management functions */
127 struct phy_info *phyinfo;
128
129 struct ucc_mii_mng *mii_regs;
130
131 /* forced speed & duplex (no autoneg)
132 * partner speed & duplex & pause (autoneg)
133 */
134 int speed;
135 int duplex;
136 int pause;
137
138 /* The most recently read link state */
139 int link;
140
141 /* Enabled Interrupts */
142 u32 interrupts;
143
144 u32 advertising;
145 int autoneg;
146 int mii_id;
147
148 /* private data pointer */
149 /* For use by PHYs to maintain extra state */
150 void *priv;
151
152 /* Provided by host chip */
153 struct net_device *dev;
154
155 /* A lock to ensure that only one thing can read/write
156 * the MDIO bus at a time */
157 spinlock_t mdio_lock;
158
159 /* Provided by ethernet driver */
160 int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
161 void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
162 int val);
163};
164
165/* struct phy_info: a structure which defines attributes for a PHY
166 *
167 * id will contain a number which represents the PHY. During
168 * startup, the driver will poll the PHY to find out what its
169 * UID--as defined by registers 2 and 3--is. The 32-bit result
170 * gotten from the PHY will be ANDed with phy_id_mask to
171 * discard any bits which may change based on revision numbers
172 * unimportant to functionality
173 *
174 * There are 6 commands which take a ugeth_mii_info structure.
175 * Each PHY must declare config_aneg, and read_status.
176 */
177struct phy_info {
178 u32 phy_id;
179 char *name;
180 unsigned int phy_id_mask;
181 u32 features;
182
183 /* Called to initialize the PHY */
184 int (*init) (struct ugeth_mii_info * mii_info);
185
186 /* Called to suspend the PHY for power */
187 int (*suspend) (struct ugeth_mii_info * mii_info);
188
189 /* Reconfigures autonegotiation (or disables it) */
190 int (*config_aneg) (struct ugeth_mii_info * mii_info);
191
192 /* Determines the negotiated speed and duplex */
193 int (*read_status) (struct ugeth_mii_info * mii_info);
194
195 /* Clears any pending interrupts */
196 int (*ack_interrupt) (struct ugeth_mii_info * mii_info);
197
198 /* Enables or disables interrupts */
199 int (*config_intr) (struct ugeth_mii_info * mii_info);
200
201 /* Clears up any memory if needed */
202 void (*close) (struct ugeth_mii_info * mii_info);
203};
204
205struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info);
206void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
207int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
208void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info);
209void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
210 u32 interrupts);
211
212struct dm9161_private {
213 struct timer_list timer;
214 int resetdone;
215};
216
217#endif /* __UCC_GETH_PHY_H__ */