* [U-Boot] [PATCH v3 2/5] net: fec_mxc: add PHYLIB support
2012-02-02 1:14 [U-Boot] [PATCH v3 1/5] net: fec_mxc: add 1000 Mbps selection Troy Kisky
@ 2012-02-02 1:14 ` Troy Kisky
2012-02-02 1:14 ` [U-Boot] [PATCH v3 3/5] net: phy: add support for Micrel's KSZ9021 Troy Kisky
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Troy Kisky @ 2012-02-02 1:14 UTC (permalink / raw)
To: u-boot
Also, surround non PHYLIB routines miiphy_restart_aneg
and miiphy_wait_aneg with ifndef CONFIG_PHYLIB.
Make fec_miiphy_read, and fec_miiphy_write call a routine
common with PHYLIB version so that when later PHYLIB is required
it is easy to delete the non-PHYLIB code. This separation idea
came from Andy Fleming.
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
Acked-by: Dirk Behme <dirk.behme@de.bosch.com>
---
drivers/net/fec_mxc.c | 122 +++++++++++++++++++++++++++++++++++++++++-------
drivers/net/fec_mxc.h | 5 ++
2 files changed, 109 insertions(+), 18 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 7c42b87..e935426 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -88,16 +88,13 @@ static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
/*
* MII-interface related functions
*/
-static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
- uint16_t *retVal)
+static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr,
+ uint8_t regAddr)
{
- struct eth_device *edev = eth_get_dev_by_name(dev);
- struct fec_priv *fec = (struct fec_priv *)edev->priv;
- struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
-
uint32_t reg; /* convenient holder for the PHY register */
uint32_t phy; /* convenient holder for the PHY */
uint32_t start;
+ int val;
/*
* reading from any PHY's register is done by properly
@@ -129,10 +126,10 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
/*
* it's now safe to read the PHY's register
*/
- *retVal = readl(ð->mii_data);
+ val = (unsigned short)readl(ð->mii_data);
debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
- regAddr, *retVal);
- return 0;
+ regAddr, val);
+ return val;
}
static void fec_mii_setspeed(struct fec_priv *fec)
@@ -146,13 +143,10 @@ static void fec_mii_setspeed(struct fec_priv *fec)
debug("fec_init: mii_speed %08x\n",
readl(&fec->eth->mii_speed));
}
-static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
- uint16_t data)
-{
- struct eth_device *edev = eth_get_dev_by_name(dev);
- struct fec_priv *fec = (struct fec_priv *)edev->priv;
- struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
+static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr,
+ uint8_t regAddr, uint16_t data)
+{
uint32_t reg; /* convenient holder for the PHY register */
uint32_t phy; /* convenient holder for the PHY */
uint32_t start;
@@ -184,6 +178,43 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
return 0;
}
+#ifdef CONFIG_PHYLIB
+int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
+{
+ return fec_mdio_read(bus->priv, phyAddr, regAddr);
+}
+
+int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
+ u16 data)
+{
+ return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
+}
+#else
+
+static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
+ uint16_t *retVal)
+{
+ struct eth_device *edev = eth_get_dev_by_name(dev);
+ struct fec_priv *fec = (struct fec_priv *)edev->priv;
+ struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
+ int val = fec_mdio_read(eth, phyAddr, regAddr);
+ if (val < 0)
+ return val;
+ *retVal = (uint16_t)val;
+ return 0;
+}
+
+static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
+ uint16_t data)
+{
+ struct eth_device *edev = eth_get_dev_by_name(dev);
+ struct fec_priv *fec = (struct fec_priv *)edev->priv;
+ struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
+ return fec_mdio_write(eth, phyAddr, regAddr, data);
+}
+#endif
+
+#ifndef CONFIG_PHYLIB
static int miiphy_restart_aneg(struct eth_device *dev)
{
struct fec_priv *fec = (struct fec_priv *)dev->priv;
@@ -241,6 +272,8 @@ static int miiphy_wait_aneg(struct eth_device *dev)
return 0;
}
+#endif
+
static int fec_rx_task_enable(struct fec_priv *fec)
{
writel(1 << 24, &fec->eth->r_des_active);
@@ -372,6 +405,21 @@ static int fec_set_hwaddr(struct eth_device *dev)
return 0;
}
+static void fec_eth_phy_config(struct eth_device *dev)
+{
+#ifdef CONFIG_PHYLIB
+ struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct phy_device *phydev;
+
+ phydev = phy_connect(fec->bus, fec->phy_id, dev,
+ PHY_INTERFACE_MODE_RGMII);
+ if (phydev) {
+ fec->phydev = phydev;
+ phy_config(phydev);
+ }
+#endif
+}
+
/**
* Start the FEC engine
* @param[in] dev Our device to handle
@@ -428,9 +476,21 @@ static int fec_open(struct eth_device *edev)
}
#endif
+#ifdef CONFIG_PHYLIB
+ if (!fec->phydev)
+ fec_eth_phy_config(edev);
+ if (fec->phydev) {
+ /* Start up the PHY */
+ phy_startup(fec->phydev);
+ speed = fec->phydev->speed;
+ } else {
+ speed = _100BASET;
+ }
+#else
miiphy_wait_aneg(edev);
speed = miiphy_speed(edev->name, fec->phy_id);
miiphy_duplex(edev->name, fec->phy_id);
+#endif
#ifdef CONFIG_FEC_QUIRK_ENET_MAC
{
@@ -558,9 +618,10 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
fec_tbd_init(fec);
+#ifndef CONFIG_PHYLIB
if (fec->xcv_type != SEVENWIRE)
miiphy_restart_aneg(dev);
-
+#endif
fec_open(dev);
return 0;
}
@@ -836,15 +897,38 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
}
fec->phy_id = phy_id;
+#ifdef CONFIG_PHYLIB
+ {
+ struct mii_dev *bus = mdio_alloc();
+ if (!bus) {
+ printf("mdio_alloc failed\n");
+ ret = -ENOMEM;
+ goto err3;
+ }
+ bus->read = fec_phy_read;
+ bus->write = fec_phy_write;
+ sprintf(bus->name, edev->name);
+ bus->priv = fec->eth;
+ ret = mdio_register(bus);
+ if (ret) {
+ printf("mdio_register failed\n");
+ free(bus);
+ ret = -ENOMEM;
+ goto err3;
+ }
+ fec->bus = bus;
+ }
+#else
miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
-
+#endif
eth_register(edev);
if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
memcpy(edev->enetaddr, ethaddr, 6);
}
-
+ /* Configure phy */
+ fec_eth_phy_config(edev);
return ret;
err3:
@@ -877,9 +961,11 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
return lout;
}
+#ifndef CONFIG_PHYLIB
int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
{
struct fec_priv *fec = (struct fec_priv *)dev->priv;
fec->mii_postcall = cb;
return 0;
}
+#endif
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index af33d21..5fd99b7 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -286,7 +286,12 @@ struct fec_priv {
void *base_ptr;
int dev_id;
int phy_id;
+#ifdef CONFIG_PHYLIB
+ struct mii_dev *bus;
+ struct phy_device *phydev;
+#else
int (*mii_postcall)(int);
+#endif
};
/**
--
1.7.5.4
^ permalink raw reply related [flat|nested] 8+ messages in thread* [U-Boot] [PATCH v3 3/5] net: phy: add support for Micrel's KSZ9021
2012-02-02 1:14 [U-Boot] [PATCH v3 1/5] net: fec_mxc: add 1000 Mbps selection Troy Kisky
2012-02-02 1:14 ` [U-Boot] [PATCH v3 2/5] net: fec_mxc: add PHYLIB support Troy Kisky
@ 2012-02-02 1:14 ` Troy Kisky
2012-02-02 1:14 ` [U-Boot] [PATCH v3 4/5] net: phy: make board_phy_config responsible for calling drv->config Troy Kisky
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Troy Kisky @ 2012-02-02 1:14 UTC (permalink / raw)
To: u-boot
Add the gigabit phy KSZ9021.
Also, add function ksz9021_phy_write for
access to the phys extended registers.
The environment variable "disable_giga"
can be used to disable 1000baseTx.
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
Acked-by: Dirk Behme <dirk.behme@de.bosch.com>
---
drivers/net/phy/micrel.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
include/phy.h | 1 +
2 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index d4e64f2..d57896f 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -20,6 +20,8 @@
* author Andy Fleming
*
*/
+#include <config.h>
+#include <common.h>
#include <phy.h>
static struct phy_driver KSZ804_driver = {
@@ -42,10 +44,90 @@ static struct phy_driver KS8721_driver = {
.shutdown = &genphy_shutdown,
};
+/* ksz9021 PHY Registers */
+#define MII_KSZ9021_EXTENDED_CTRL 0x0b
+#define MII_KSZ9021_EXTENDED_DATAW 0x0c
+#define MII_KSZ9021_PHY_CTL 0x1f
+#define MIIM_KSZ9021_PHYCTL_1000 (1 << 6)
+#define MIIM_KSZ9021_PHYCTL_100 (1 << 5)
+#define MIIM_KSZ9021_PHYCTL_10 (1 << 4)
+#define MIIM_KSZ9021_PHYCTL_DUPLEX (1 << 3)
+
+#define CTRL1000_PREFER_MASTER (1 << 10)
+#define CTRL1000_CONFIG_MASTER (1 << 11)
+#define CTRL1000_MANUAL_CONFIG (1 << 12)
+
+int ksz9021_phy_write(struct phy_device *phydev, int devad, int regnum, u16 val)
+{
+ if (devad == MDIO_DEVAD_NONE) {
+ return phy_write(phydev, devad, regnum, val);
+ } else {
+ /* extended registers */
+ phy_write(phydev, MDIO_DEVAD_NONE,
+ MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
+ return phy_write(phydev, MDIO_DEVAD_NONE,
+ MII_KSZ9021_EXTENDED_DATAW, val);
+ }
+}
+
+/* Micrel ksz9021 */
+static int ksz9021_config(struct phy_device *phydev)
+{
+ unsigned ctrl1000 = 0;
+ const unsigned master = CTRL1000_PREFER_MASTER |
+ CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
+ unsigned features = phydev->drv->features;
+
+ if (getenv("disable_giga"))
+ features &= ~(SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full);
+ /* force master mode for 1000BaseT due to chip errata */
+ if (features & SUPPORTED_1000baseT_Half)
+ ctrl1000 |= ADVERTISE_1000HALF | master;
+ if (features & SUPPORTED_1000baseT_Full)
+ ctrl1000 |= ADVERTISE_1000FULL | master;
+ phydev->advertising = phydev->supported = features;
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
+ genphy_config_aneg(phydev);
+ genphy_restart_aneg(phydev);
+ return 0;
+}
+
+static int ksz9021_startup(struct phy_device *phydev)
+{
+ unsigned phy_ctl;
+ genphy_update_link(phydev);
+ phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_PHY_CTL);
+
+ if (phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
+ if (phy_ctl & MIIM_KSZ9021_PHYCTL_1000)
+ phydev->speed = SPEED_1000;
+ else if (phy_ctl & MIIM_KSZ9021_PHYCTL_100)
+ phydev->speed = SPEED_100;
+ else if (phy_ctl & MIIM_KSZ9021_PHYCTL_10)
+ phydev->speed = SPEED_10;
+ return 0;
+}
+
+static struct phy_driver ksz9021_driver = {
+ .name = "Micrel ksz9021",
+ .uid = 0x221610,
+ .mask = 0xfffff0,
+ .features = PHY_GBIT_FEATURES,
+ .config = &ksz9021_config,
+ .startup = &ksz9021_startup,
+ .shutdown = &genphy_shutdown,
+};
+
int phy_micrel_init(void)
{
phy_register(&KSZ804_driver);
phy_register(&KS8721_driver);
+ phy_register(&ksz9021_driver);
return 0;
}
diff --git a/include/phy.h b/include/phy.h
index bc522d5..3c30f11 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -207,6 +207,7 @@ int phy_config(struct phy_device *phydev);
int phy_shutdown(struct phy_device *phydev);
int phy_register(struct phy_driver *drv);
int genphy_config_aneg(struct phy_device *phydev);
+int genphy_restart_aneg(struct phy_device *phydev);
int genphy_update_link(struct phy_device *phydev);
int genphy_config(struct phy_device *phydev);
int genphy_startup(struct phy_device *phydev);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 8+ messages in thread* [U-Boot] [PATCH v3 5/5] i.mx6q: mx6qsabrelite: Update the network configuration
2012-02-02 1:14 [U-Boot] [PATCH v3 1/5] net: fec_mxc: add 1000 Mbps selection Troy Kisky
` (2 preceding siblings ...)
2012-02-02 1:14 ` [U-Boot] [PATCH v3 4/5] net: phy: make board_phy_config responsible for calling drv->config Troy Kisky
@ 2012-02-02 1:14 ` Troy Kisky
2012-02-02 1:37 ` Troy Kisky
2012-02-02 1:25 ` [U-Boot] [PATCH v3 1/5] net: fec_mxc: add 1000 Mbps selection Troy Kisky
4 siblings, 1 reply; 8+ messages in thread
From: Troy Kisky @ 2012-02-02 1:14 UTC (permalink / raw)
To: u-boot
Define CONFIG_PHY_MICREL, and
minimize the tx clock delay.
There is an issue with 1000 baseTx mode on early revs
of the SabreLite boards. The center tap pin 9 of the mag RJ45
USB combo was connected to the 3.3 filtered supply. Letting
this pin float solved the problem. Symptoms of the problem
were packets with many extra zeroes tacked on the end, and random
bit flips causing a high rate of CRC errors. 10/100 baseTx worked
fine on all revs. To disable 1000 baseTx for these boards, simply
define the environment variable disable_giga. ie.
setenv disable_giga 1
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
Acked-by: Dirk Behme <dirk.behme@de.bosch.com>
---
board/freescale/mx6qsabrelite/mx6qsabrelite.c | 46 +++++--------------------
include/configs/mx6qsabrelite.h | 2 +
2 files changed, 11 insertions(+), 37 deletions(-)
diff --git a/board/freescale/mx6qsabrelite/mx6qsabrelite.c b/board/freescale/mx6qsabrelite/mx6qsabrelite.c
index a53b01f..6c11660 100644
--- a/board/freescale/mx6qsabrelite/mx6qsabrelite.c
+++ b/board/freescale/mx6qsabrelite/mx6qsabrelite.c
@@ -193,53 +193,25 @@ int board_mmc_init(bd_t *bis)
}
#endif
-#define MII_1000BASET_CTRL 0x9
-#define MII_EXTENDED_CTRL 0xb
-#define MII_EXTENDED_DATAW 0xc
-
-int fecmxc_mii_postcall(int phy)
+int board_phy_config(struct phy_device *phydev)
{
- /* prefer master mode */
- miiphy_write("FEC", phy, MII_1000BASET_CTRL, 0x0f00);
-
- /* min rx data delay */
- miiphy_write("FEC", phy, MII_EXTENDED_CTRL, 0x8105);
- miiphy_write("FEC", phy, MII_EXTENDED_DATAW, 0x0000);
-
- /* max rx/tx clock delay, min rx/tx control delay */
- miiphy_write("FEC", phy, MII_EXTENDED_CTRL, 0x8104);
- miiphy_write("FEC", phy, MII_EXTENDED_DATAW, 0xf0f0);
- miiphy_write("FEC", phy, MII_EXTENDED_CTRL, 0x104);
-
+ ksz9021_phy_write(phydev, 0, 0x105, 0x0); /* min rx data delay */
+ ksz9021_phy_write(phydev, 0, 0x106, 0x0); /* min tx data delay */
+ /* max rx/tx clock delay, min rx/tx control */
+ ksz9021_phy_write(phydev, 0, 0x104, 0xf0f0);
+ if (phydev->drv->config)
+ phydev->drv->config(phydev);
return 0;
}
int board_eth_init(bd_t *bis)
{
- struct eth_device *dev;
int ret;
-
setup_iomux_enet();
-
ret = cpu_eth_init(bis);
- if (ret) {
+ if (ret)
printf("FEC MXC: %s:failed\n", __func__);
- return ret;
- }
-
- dev = eth_get_dev_by_name("FEC");
- if (!dev) {
- printf("FEC MXC: Unable to get FEC device entry\n");
- return -EINVAL;
- }
-
- ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
- if (ret) {
- printf("FEC MXC: Unable to register FEC mii postcall\n");
- return ret;
- }
-
- return 0;
+ return ret;
}
int board_early_init_f(void)
diff --git a/include/configs/mx6qsabrelite.h b/include/configs/mx6qsabrelite.h
index 2e9775a..47a1832 100644
--- a/include/configs/mx6qsabrelite.h
+++ b/include/configs/mx6qsabrelite.h
@@ -67,6 +67,8 @@
#define CONFIG_FEC_XCV_TYPE RGMII
#define CONFIG_ETHPRIME "FEC"
#define CONFIG_FEC_MXC_PHYADDR 6
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
--
1.7.5.4
^ permalink raw reply related [flat|nested] 8+ messages in thread