aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.27/boc01/010-090112-mii.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.27/boc01/010-090112-mii.patch')
-rw-r--r--recipes/linux/linux-2.6.27/boc01/010-090112-mii.patch503
1 files changed, 503 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.27/boc01/010-090112-mii.patch b/recipes/linux/linux-2.6.27/boc01/010-090112-mii.patch
new file mode 100644
index 0000000000..33c6cb7498
--- /dev/null
+++ b/recipes/linux/linux-2.6.27/boc01/010-090112-mii.patch
@@ -0,0 +1,503 @@
+Index: linux-2.6.27/drivers/net/gianfar_ethtool.c
+===================================================================
+--- linux-2.6.27.orig/drivers/net/gianfar_ethtool.c
++++ linux-2.6.27/drivers/net/gianfar_ethtool.c
+@@ -182,13 +182,7 @@ static void gfar_gdrvinfo(struct net_dev
+
+ static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+- struct gfar_private *priv = netdev_priv(dev);
+- struct phy_device *phydev = priv->phydev;
+-
+- if (NULL == phydev)
+- return -ENODEV;
+-
+- return phy_ethtool_sset(phydev, cmd);
++ return 0;
+ }
+
+
+@@ -196,15 +190,11 @@ static int gfar_ssettings(struct net_dev
+ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct gfar_private *priv = netdev_priv(dev);
+- struct phy_device *phydev = priv->phydev;
+-
+- if (NULL == phydev)
+- return -ENODEV;
+
+ cmd->maxtxpkt = priv->txcount;
+ cmd->maxrxpkt = priv->rxcount;
+
+- return phy_ethtool_gset(phydev, cmd);
++ return 0;
+ }
+
+ /* Return the length of the register structure */
+@@ -232,18 +222,7 @@ static unsigned int gfar_usecs2ticks(str
+ unsigned int count;
+
+ /* The timer is different, depending on the interface speed */
+- switch (priv->phydev->speed) {
+- case SPEED_1000:
+- count = GFAR_GBIT_TIME;
+- break;
+- case SPEED_100:
+- count = GFAR_100_TIME;
+- break;
+- case SPEED_10:
+- default:
+- count = GFAR_10_TIME;
+- break;
+- }
++ count = GFAR_100_TIME;
+
+ /* Make sure we return a number greater than 0
+ * if usecs > 0 */
+@@ -256,18 +235,7 @@ static unsigned int gfar_ticks2usecs(str
+ unsigned int count;
+
+ /* The timer is different, depending on the interface speed */
+- switch (priv->phydev->speed) {
+- case SPEED_1000:
+- count = GFAR_GBIT_TIME;
+- break;
+- case SPEED_100:
+- count = GFAR_100_TIME;
+- break;
+- case SPEED_10:
+- default:
+- count = GFAR_10_TIME;
+- break;
+- }
++ count = GFAR_100_TIME;
+
+ /* Make sure we return a number greater than 0 */
+ /* if ticks is > 0 */
+@@ -283,9 +251,6 @@ static int gfar_gcoalesce(struct net_dev
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
+ return -EOPNOTSUPP;
+
+- if (NULL == priv->phydev)
+- return -ENODEV;
+-
+ cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
+ cvals->rx_max_coalesced_frames = priv->rxcount;
+
+@@ -342,9 +307,6 @@ static int gfar_scoalesce(struct net_dev
+ else
+ priv->rxcoalescing = 1;
+
+- if (NULL == priv->phydev)
+- return -ENODEV;
+-
+ /* Check the bounds of the values */
+ if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ pr_info("Coalescing is limited to %d microseconds\n",
+Index: linux-2.6.27/drivers/net/gianfar.c
+===================================================================
+--- linux-2.6.27.orig/drivers/net/gianfar.c
++++ linux-2.6.27/drivers/net/gianfar.c
+@@ -116,7 +116,6 @@ static int gfar_change_mtu(struct net_de
+ static irqreturn_t gfar_error(int irq, void *dev_id);
+ static irqreturn_t gfar_transmit(int irq, void *dev_id);
+ static irqreturn_t gfar_interrupt(int irq, void *dev_id);
+-static void adjust_link(struct net_device *dev);
+ static void init_registers(struct net_device *dev);
+ static int init_phy(struct net_device *dev);
+ static int gfar_probe(struct platform_device *pdev);
+@@ -124,7 +123,6 @@ static int gfar_remove(struct platform_d
+ static void free_skb_resources(struct gfar_private *priv);
+ static void gfar_set_multi(struct net_device *dev);
+ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+-static void gfar_configure_serdes(struct net_device *dev);
+ static int gfar_poll(struct napi_struct *napi, int budget);
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void gfar_netpoll(struct net_device *dev);
+@@ -424,8 +422,6 @@ static int gfar_suspend(struct platform_
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval |= MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+- } else {
+- phy_stop(priv->phydev);
+ }
+ }
+
+@@ -438,17 +434,12 @@ static int gfar_resume(struct platform_d
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+- int magic_packet = priv->wol_en &&
+- (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ return 0;
+ }
+
+- if (!magic_packet && priv->phydev)
+- phy_start(priv->phydev);
+-
+ /* Disable Magic Packet mode, in case something
+ * else woke us up.
+ */
+@@ -476,47 +467,6 @@ static int gfar_resume(struct platform_d
+ #define gfar_resume NULL
+ #endif
+
+-/* Reads the controller's registers to determine what interface
+- * connects it to the PHY.
+- */
+-static phy_interface_t gfar_get_interface(struct net_device *dev)
+-{
+- struct gfar_private *priv = netdev_priv(dev);
+- u32 ecntrl = gfar_read(&priv->regs->ecntrl);
+-
+- if (ecntrl & ECNTRL_SGMII_MODE)
+- return PHY_INTERFACE_MODE_SGMII;
+-
+- if (ecntrl & ECNTRL_TBI_MODE) {
+- if (ecntrl & ECNTRL_REDUCED_MODE)
+- return PHY_INTERFACE_MODE_RTBI;
+- else
+- return PHY_INTERFACE_MODE_TBI;
+- }
+-
+- if (ecntrl & ECNTRL_REDUCED_MODE) {
+- if (ecntrl & ECNTRL_REDUCED_MII_MODE)
+- return PHY_INTERFACE_MODE_RMII;
+- else {
+- phy_interface_t interface = priv->einfo->interface;
+-
+- /*
+- * This isn't autodetected right now, so it must
+- * be set by the device tree or platform code.
+- */
+- if (interface == PHY_INTERFACE_MODE_RGMII_ID)
+- return PHY_INTERFACE_MODE_RGMII_ID;
+-
+- return PHY_INTERFACE_MODE_RGMII;
+- }
+- }
+-
+- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT)
+- return PHY_INTERFACE_MODE_GMII;
+-
+- return PHY_INTERFACE_MODE_MII;
+-}
+-
+
+ /* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
+@@ -524,10 +474,6 @@ static phy_interface_t gfar_get_interfac
+ static int init_phy(struct net_device *dev)
+ {
+ struct gfar_private *priv = netdev_priv(dev);
+- uint gigabit_support =
+- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+- SUPPORTED_1000baseT_Full : 0;
+- struct phy_device *phydev;
+ char phy_id[BUS_ID_SIZE];
+ phy_interface_t interface;
+
+@@ -537,54 +483,11 @@ static int init_phy(struct net_device *d
+
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
+
+- interface = gfar_get_interface(dev);
+-
+- phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
+-
+- if (interface == PHY_INTERFACE_MODE_SGMII)
+- gfar_configure_serdes(dev);
+-
+- if (IS_ERR(phydev)) {
+- printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+- return PTR_ERR(phydev);
+- }
+-
+- /* Remove any features not supported by the controller */
+- phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+- phydev->advertising = phydev->supported;
+-
+- priv->phydev = phydev;
++ interface = PHY_INTERFACE_MODE_MII;
+
+ return 0;
+ }
+
+-/*
+- * Initialize TBI PHY interface for communicating with the
+- * SERDES lynx PHY on the chip. We communicate with this PHY
+- * through the MDIO bus on each controller, treating it as a
+- * "normal" PHY at the address found in the TBIPA register. We assume
+- * that the TBIPA register is valid. Either the MDIO bus code will set
+- * it to a value that doesn't conflict with other PHYs on the bus, or the
+- * value doesn't matter, as there are no other PHYs on the bus.
+- */
+-static void gfar_configure_serdes(struct net_device *dev)
+-{
+- struct gfar_private *priv = netdev_priv(dev);
+- struct gfar_mii __iomem *regs =
+- (void __iomem *)&priv->regs->gfar_mii_regs;
+- int tbipa = gfar_read(&priv->regs->tbipa);
+-
+- /* Single clk mode, mii mode off(for serdes communication) */
+- gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT);
+-
+- gfar_local_mdio_write(regs, tbipa, MII_ADVERTISE,
+- ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+- ADVERTISE_1000XPSE_ASYM);
+-
+- gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE |
+- BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+-}
+-
+ static void init_registers(struct net_device *dev)
+ {
+ struct gfar_private *priv = netdev_priv(dev);
+@@ -678,8 +581,6 @@ void stop_gfar(struct net_device *dev)
+ struct gfar __iomem *regs = priv->regs;
+ unsigned long flags;
+
+- phy_stop(priv->phydev);
+-
+ /* Lock it down */
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+@@ -949,7 +850,6 @@ int startup_gfar(struct net_device *dev)
+ }
+ }
+
+- phy_start(priv->phydev);
+
+ /* Configure the coalescing support */
+ if (priv->txcoalescing)
+@@ -1217,9 +1117,6 @@ static int gfar_close(struct net_device
+ cancel_work_sync(&priv->reset_task);
+ stop_gfar(dev);
+
+- /* Disconnect from the PHY */
+- phy_disconnect(priv->phydev);
+- priv->phydev = NULL;
+
+ netif_stop_queue(dev);
+
+@@ -1777,86 +1674,6 @@ static irqreturn_t gfar_interrupt(int ir
+ return IRQ_HANDLED;
+ }
+
+-/* Called every time the controller might need to be made
+- * aware of new link state. The PHY code conveys this
+- * information through variables in the phydev structure, and this
+- * function converts those variables into the appropriate
+- * register values, and can bring down the device if needed.
+- */
+-static void adjust_link(struct net_device *dev)
+-{
+- struct gfar_private *priv = netdev_priv(dev);
+- struct gfar __iomem *regs = priv->regs;
+- unsigned long flags;
+- struct phy_device *phydev = priv->phydev;
+- int new_state = 0;
+-
+- spin_lock_irqsave(&priv->txlock, flags);
+- if (phydev->link) {
+- u32 tempval = gfar_read(&regs->maccfg2);
+- u32 ecntrl = gfar_read(&regs->ecntrl);
+-
+- /* Now we make sure that we can be in full duplex mode.
+- * If not, we operate in half-duplex mode. */
+- if (phydev->duplex != priv->oldduplex) {
+- new_state = 1;
+- if (!(phydev->duplex))
+- tempval &= ~(MACCFG2_FULL_DUPLEX);
+- else
+- tempval |= MACCFG2_FULL_DUPLEX;
+-
+- priv->oldduplex = phydev->duplex;
+- }
+-
+- if (phydev->speed != priv->oldspeed) {
+- new_state = 1;
+- switch (phydev->speed) {
+- case 1000:
+- tempval =
+- ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
+- break;
+- case 100:
+- case 10:
+- tempval =
+- ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+-
+- /* Reduced mode distinguishes
+- * between 10 and 100 */
+- if (phydev->speed == SPEED_100)
+- ecntrl |= ECNTRL_R100;
+- else
+- ecntrl &= ~(ECNTRL_R100);
+- break;
+- default:
+- if (netif_msg_link(priv))
+- printk(KERN_WARNING
+- "%s: Ack! Speed (%d) is not 10/100/1000!\n",
+- dev->name, phydev->speed);
+- break;
+- }
+-
+- priv->oldspeed = phydev->speed;
+- }
+-
+- gfar_write(&regs->maccfg2, tempval);
+- gfar_write(&regs->ecntrl, ecntrl);
+-
+- if (!priv->oldlink) {
+- new_state = 1;
+- priv->oldlink = 1;
+- }
+- } else if (priv->oldlink) {
+- new_state = 1;
+- priv->oldlink = 0;
+- priv->oldspeed = 0;
+- priv->oldduplex = -1;
+- }
+-
+- if (new_state && netif_msg_link(priv))
+- phy_print_status(phydev);
+-
+- spin_unlock_irqrestore(&priv->txlock, flags);
+-}
+
+ /* Update the hash table based on the current list of multicast
+ * addresses we subscribe to. Also, change the promiscuity of
+Index: linux-2.6.27/drivers/net/gianfar.h
+===================================================================
+--- linux-2.6.27.orig/drivers/net/gianfar.h
++++ linux-2.6.27/drivers/net/gianfar.h
+@@ -150,7 +150,7 @@ extern const char gfar_driver_version[];
+ #define MACCFG1_SYNCD_TX_EN 0x00000002
+ #define MACCFG1_TX_EN 0x00000001
+
+-#define MACCFG2_INIT_SETTINGS 0x00007205
++#define MACCFG2_INIT_SETTINGS 0x00007105
+ #define MACCFG2_FULL_DUPLEX 0x00000001
+ #define MACCFG2_IF 0x00000300
+ #define MACCFG2_MII 0x00000100
+@@ -748,7 +748,6 @@ struct gfar_private {
+ struct gianfar_platform_data *einfo;
+
+ /* PHY stuff */
+- struct phy_device *phydev;
+ struct mii_bus *mii_bus;
+ int oldspeed;
+ int oldduplex;
+Index: linux-2.6.27/drivers/net/gianfar_mii.c
+===================================================================
+--- linux-2.6.27.orig/drivers/net/gianfar_mii.c
++++ linux-2.6.27/drivers/net/gianfar_mii.c
+@@ -217,28 +217,10 @@ static int gfar_mdio_probe(struct device
+ if (r)
+ return r;
+
+- if (phy_id == 0xffffffff)
+- break;
+- }
+-
+- /* The bus is full. We don't support using 31 PHYs, sorry */
+- if (i == 0)
+- return -EBUSY;
+-
+- gfar_write(&enet_regs->tbipa, i);
+-
+- err = mdiobus_register(new_bus);
+-
+- if (0 != err) {
+- printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+- new_bus->name);
+- goto bus_register_fail;
+ }
+
+ return 0;
+
+-bus_register_fail:
+- iounmap(regs);
+ reg_map_fail:
+ kfree(new_bus);
+
+Index: linux-2.6.27/drivers/net/gianfar_mii.h
+===================================================================
+--- linux-2.6.27.orig/drivers/net/gianfar_mii.h
++++ linux-2.6.27/drivers/net/gianfar_mii.h
+@@ -27,7 +27,6 @@
+ | SUPPORTED_10baseT_Full \
+ | SUPPORTED_100baseT_Half \
+ | SUPPORTED_100baseT_Full \
+- | SUPPORTED_Autoneg \
+ | SUPPORTED_MII)
+
+ struct gfar_mii {
+Index: linux-2.6.27/drivers/net/phy/phy_device.c
+===================================================================
+--- linux-2.6.27.orig/drivers/net/phy/phy_device.c
++++ linux-2.6.27/drivers/net/phy/phy_device.c
+@@ -281,7 +281,7 @@ struct phy_device * phy_connect(struct n
+ if (IS_ERR(phydev))
+ return phydev;
+
+- phy_prepare_link(phydev, handler);
++ phydev->link = 1;
+
+ phy_start_machine(phydev, NULL);
+
+@@ -302,7 +302,7 @@ void phy_disconnect(struct phy_device *p
+ phy_stop_interrupts(phydev);
+
+ phy_stop_machine(phydev);
+-
++
+ phydev->adjust_link = NULL;
+
+ phy_detach(phydev);
+@@ -438,7 +438,7 @@ int genphy_config_advert(struct phy_devi
+ if (adv < 0)
+ return adv;
+
+- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
++ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+@@ -503,7 +503,7 @@ int genphy_setup_forced(struct phy_devic
+
+ if (DUPLEX_FULL == phydev->duplex)
+ ctl |= BMCR_FULLDPLX;
+-
++
+ err = phy_write(phydev, MII_BMCR, ctl);
+
+ if (err < 0)
+@@ -671,7 +671,7 @@ int genphy_read_status(struct phy_device
+ phydev->duplex = DUPLEX_FULL;
+ } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phydev->speed = SPEED_100;
+-
++
+ if (lpa & LPA_100FULL)
+ phydev->duplex = DUPLEX_FULL;
+ } else
+Index: linux-2.6.27/include/linux/phy.h
+===================================================================
+--- linux-2.6.27.orig/include/linux/phy.h
++++ linux-2.6.27/include/linux/phy.h
+@@ -339,6 +339,11 @@ struct phy_driver {
+ u32 features;
+ u32 flags;
+
++ /* Called during discovery to test if the
++ * device can attach to the bus, even if
++ phy id and mask do not match */
++ bool (*detect)(struct mii_bus *bus, int addr);
++
+ /*
+ * Called to initialize the PHY,
+ * including after a reset