Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266167
b: refs/heads/master
c: 230dec6
h: refs/heads/master
i:
  266165: 84b3196
  266163: b9b6bd1
  266159: b1e02f9
v: v3
  • Loading branch information
Shawn Guo authored and David S. Miller committed Sep 23, 2011
1 parent d354930 commit 77fcd01
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c828827f8426f2cd8e37315c59ae406534a16d48
refs/heads/master: 230dec61313dc5f5720311d0b492f69f5466b0a4
9 changes: 4 additions & 5 deletions trunk/drivers/net/ethernet/freescale/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ config NET_VENDOR_FREESCALE
default y
depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
M523x || M527x || M5272 || M528x || M520x || M532x || \
IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC || \
ARCH_MXC || ARCH_MXS || \
(PPC_MPC52xx && PPC_BESTCOMM)
---help---
If you have a network (Ethernet) card belonging to this class, say Y
Expand All @@ -16,16 +16,15 @@ config NET_VENDOR_FREESCALE

Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about IBM devices. If you say Y, you will be asked for
your specific card in the following questions.
the questions about Freescale devices. If you say Y, you will be
asked for your specific card in the following questions.

if NET_VENDOR_FREESCALE

config FEC
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \
IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC)
default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
ARCH_MXC || ARCH_MXS)
select PHYLIB
---help---
Say Y here if you want to use the built-in 10/100 Fast ethernet
Expand Down
66 changes: 53 additions & 13 deletions trunk/drivers/net/ethernet/freescale/fec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -72,6 +72,8 @@
#define FEC_QUIRK_SWAP_FRAME (1 << 1)
/* Controller uses gasket */
#define FEC_QUIRK_USE_GASKET (1 << 2)
/* Controller has GBIT support */
#define FEC_QUIRK_HAS_GBIT (1 << 3)

static struct platform_device_id fec_devtype[] = {
{
Expand All @@ -87,6 +89,9 @@ static struct platform_device_id fec_devtype[] = {
}, {
.name = "imx28-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
}, {
.name = "imx6q-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT,
}, {
/* sentinel */
}
Expand All @@ -97,12 +102,14 @@ enum imx_fec_type {
IMX25_FEC = 1, /* runs on i.mx25/50/53 */
IMX27_FEC, /* runs on i.mx27/35/51 */
IMX28_FEC,
IMX6Q_FEC,
};

static const struct of_device_id fec_dt_ids[] = {
{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
{ .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fec_dt_ids);
Expand Down Expand Up @@ -373,6 +380,7 @@ fec_restart(struct net_device *ndev, int duplex)
int i;
u32 temp_mac[2];
u32 rcntl = OPT_FRAME_SIZE | 0x04;
u32 ecntl = 0x2; /* ETHEREN */

/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
Expand Down Expand Up @@ -442,18 +450,23 @@ fec_restart(struct net_device *ndev, int duplex)
/* Enable flow control and length check */
rcntl |= 0x40000000 | 0x00000020;

/* MII or RMII */
if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
/* RGMII, RMII or MII */
if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
rcntl |= (1 << 6);
else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
rcntl |= (1 << 8);
else
rcntl &= ~(1 << 8);

/* 10M or 100M */
if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
rcntl &= ~(1 << 9);
else
rcntl |= (1 << 9);

/* 1G, 100M or 10M */
if (fep->phy_dev) {
if (fep->phy_dev->speed == SPEED_1000)
ecntl |= (1 << 5);
else if (fep->phy_dev->speed == SPEED_100)
rcntl &= ~(1 << 9);
else
rcntl |= (1 << 9);
}
} else {
#ifdef FEC_MIIGSK_ENR
if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
Expand All @@ -478,8 +491,15 @@ fec_restart(struct net_device *ndev, int duplex)
}
writel(rcntl, fep->hwp + FEC_R_CNTRL);

if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
/* enable ENET endian swap */
ecntl |= (1 << 8);
/* enable ENET store and forward mode */
writel(1 << 8, fep->hwp + FEC_X_WMRK);
}

/* And last, enable the transmit and receive processing */
writel(2, fep->hwp + FEC_ECNTRL);
writel(ecntl, fep->hwp + FEC_ECNTRL);
writel(0, fep->hwp + FEC_R_DES_ACTIVE);

/* Enable interrupts we wish to service */
Expand All @@ -490,6 +510,8 @@ static void
fec_stop(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);

/* We cannot expect a graceful transmit stop without link !!! */
if (fep->link) {
Expand All @@ -504,6 +526,10 @@ fec_stop(struct net_device *ndev)
udelay(10);
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);

/* We have to keep ENET enabled to have MII interrupt stay working */
if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
writel(2, fep->hwp + FEC_ECNTRL);
}


Expand Down Expand Up @@ -918,6 +944,8 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
static int fec_enet_mii_probe(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);
struct phy_device *phy_dev = NULL;
char mdio_bus_id[MII_BUS_ID_SIZE];
char phy_name[MII_BUS_ID_SIZE + 3];
Expand Down Expand Up @@ -949,14 +977,18 @@ 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);
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 (id_entry->driver_data & FEC_QUIRK_HAS_GBIT)
phy_dev->supported &= PHY_GBIT_FEATURES;
else
phy_dev->supported &= PHY_BASIC_FEATURES;

phy_dev->advertising = phy_dev->supported;

fep->phy_dev = phy_dev;
Expand Down Expand Up @@ -1006,8 +1038,16 @@ static int fec_enet_mii_init(struct platform_device *pdev)

/*
* Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed)
*
* The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while
* for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. The i.MX28
* Reference Manual has an error on this, and gets fixed on i.MX6Q
* document.
*/
fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1;
fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000);
if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
fep->phy_speed--;
fep->phy_speed <<= 1;
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);

fep->mii_bus = mdiobus_alloc();
Expand Down

0 comments on commit 77fcd01

Please sign in to comment.