summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorZeng Zhaoming <b32542@freescale.com>2011-07-05 09:19:52 +0800
committerJason Liu <r64343@freescale.com>2012-01-09 20:18:31 +0800
commitaed5fca18fe3af2e214e4b0cb5c52677667027c9 (patch)
tree99e57108a97b95f0cd29c55e1810449c6472f10c /drivers/net
parent0362c13c41f2e4c9dacf4925d4c2a366d0eaf744 (diff)
ENGR00152528-2 ENET: add enet support for mx6q.
Enabled all speed mode, 10M/100M/1G. add "fec_mac" kernel parameter to set mac address. Since clock and board rework issue, some hard code stays to make it work. Signed-off-by: Zeng Zhaoming <b32542@freescale.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/fec.c83
1 files changed, 78 insertions, 5 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8baff7d5..eaf9420844e4 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -18,7 +18,7 @@
* Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
* Copyright (c) 2004-2006 Macq Electronique SA.
*
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
*/
#include <linux/module.h>
@@ -68,10 +68,18 @@
#define FEC_QUIRK_SWAP_FRAME (1 << 1)
static struct platform_device_id fec_devtype[] = {
+#ifdef CONFIG_SOC_IMX6Q
+ {
+ .name = DRIVER_NAME,
+ .driver_data = FEC_QUIRK_ENET_MAC,
+ },
+#else
{
.name = DRIVER_NAME,
.driver_data = 0,
- }, {
+ },
+#endif
+ {
.name = "imx28-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
},
@@ -860,6 +868,31 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
return 0;
}
+#ifdef CONFIG_MACH_MX6Q_SABREAUTO
+
+static int mx6_sabreauto_rework(struct mii_bus *bus)
+{
+ unsigned short val;
+
+ /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+ fec_enet_mdio_write(bus, 0, 0xd, 0x7);
+ fec_enet_mdio_write(bus, 0, 0xe, 0x8016);
+ fec_enet_mdio_write(bus, 0, 0xd, 0x4007);
+ val = fec_enet_mdio_read(bus, 0, 0xe);
+
+ val &= 0xffe3;
+ val |= 0x18;
+ fec_enet_mdio_write(bus, 0, 0xe, val);
+
+ /* introduce tx clock delay */
+ fec_enet_mdio_write(bus, 0, 0x1d, 0x5);
+ val = fec_enet_mdio_read(bus, 0, 0x1e);
+ val |= 0x0100;
+ fec_enet_mdio_write(bus, 0, 0x1e, val);
+
+ return 0;
+}
+#endif
static int fec_enet_mdio_reset(struct mii_bus *bus)
{
@@ -899,15 +932,20 @@ static int fec_enet_mii_probe(struct net_device *ndev)
}
snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
- phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0,
+ fep->phy_interface);
+
if (IS_ERR(phy_dev)) {
printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
return PTR_ERR(phy_dev);
}
/* mask with MAC supported features */
- phy_dev->supported &= PHY_BASIC_FEATURES;
+ if (cpu_is_mx6q())
+ phy_dev->supported &= PHY_GBIT_FEATURES;
+ else
+ phy_dev->supported &= PHY_BASIC_FEATURES;
+
phy_dev->advertising = phy_dev->supported;
fep->phy_dev = phy_dev;
@@ -959,6 +997,11 @@ static int fec_enet_mii_init(struct platform_device *pdev)
* Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed)
*/
fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1;
+
+#ifdef CONFIG_MACH_MX6Q_SABREAUTO
+ /* FIXME: hard code to 0x1a for clock issue */
+ fep->phy_speed = 0x11a;
+#endif
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
fep->mii_bus = mdiobus_alloc();
@@ -975,6 +1018,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
fep->mii_bus->priv = fep;
fep->mii_bus->parent = &pdev->dev;
+#ifdef CONFIG_MACH_MX6Q_SABREAUTO
+ mx6_sabreauto_rework(fep->mii_bus);
+#endif
+
fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (!fep->mii_bus->irq) {
err = -ENOMEM;
@@ -1151,6 +1198,7 @@ fec_enet_open(struct net_device *ndev)
fec_enet_free_buffers(ndev);
return ret;
}
+
phy_start(fep->phy_dev);
netif_start_queue(ndev);
fep->opened = 1;
@@ -1537,6 +1585,31 @@ static struct platform_driver fec_driver = {
.remove = __devexit_p(fec_drv_remove),
};
+static int fec_mac_addr_setup(char *mac_addr)
+{
+ char *ptr, *p = mac_addr;
+ unsigned long tmp;
+ int i = 0, ret = 0;
+
+ while (p && (*p) && i < 6) {
+ ptr = strchr(p, ':');
+ if (ptr)
+ *ptr++ = '\0';
+
+ if (strlen(p)) {
+ ret = strict_strtoul(p, 16, &tmp);
+ if (ret < 0 || tmp > 0xff)
+ break;
+ macaddr[i++] = tmp;
+ }
+ p = ptr;
+ }
+
+ return 0;
+}
+
+__setup("fec_mac=", fec_mac_addr_setup);
+
static int __init
fec_enet_module_init(void)
{