[PATCH] [2/2] PM support for emac driver
Geoff Levand
geoffrey.levand at am.sony.com
Sat Jun 4 09:22:47 EST 2005
This is a first attempt to add PM support to the PPC 440 emac
driver. Still needed are code to take care of the PHY chip,
and to support wake-on-lan. Any comments on how to do
those would be most welcome.
The 'PM support for Ebony' patch I posted can be used to test
on that platform.
-Geoff
* emac-pm.patch
Signed-off-by: Geoff Levand <geoffrey.levand at am.sony.com> for CELF
--
Index: linux-2.6.12-bhpm/drivers/net/ibm_emac/ibm_emac_core.c
===================================================================
--- linux-2.6.12-bhpm.orig/drivers/net/ibm_emac/ibm_emac_core.c 2005-06-02 15:09:23.000000000 -0700
+++ linux-2.6.12-bhpm/drivers/net/ibm_emac/ibm_emac_core.c 2005-06-02 17:11:02.000000000 -0700
@@ -1306,7 +1306,7 @@
ep->ack_slot = 0;
}
-static void emac_reset_configure(struct ocp_enet_private *fep)
+static void emac_reset(struct ocp_enet_private *fep)
{
emac_t *emacp = fep->emacp;
int i;
@@ -1338,6 +1338,14 @@
/* Switch IRQs off for now */
out_be32(&emacp->em0iser, 0);
+}
+
+static void emac_reset_configure(struct ocp_enet_private *fep)
+{
+ emac_t *emacp = fep->emacp;
+
+ /* Reset EMAC */
+ emac_reset(fep);
/* Configure MAL rx channel */
mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG);
@@ -1615,20 +1623,10 @@
}
}
-static int emac_open(struct net_device *dev)
+static int emac_up(struct net_device *dev)
{
- struct ocp_enet_private *fep = dev->priv;
int rc;
-
- spin_lock_irq(&fep->lock);
-
- fep->opened = 1;
- netif_carrier_off(dev);
-
- /* Reset & configure the chip */
- emac_reset_configure(fep);
-
- spin_unlock_irq(&fep->lock);
+ struct ocp_enet_private *fep = dev->priv;
/* Request our interrupt lines */
rc = request_irq(dev->irq, emac_mac_irq, 0, "IBM EMAC MAC", dev);
@@ -1646,6 +1644,24 @@
return rc;
}
+static int emac_open(struct net_device *dev)
+{
+ struct ocp_enet_private *fep = dev->priv;
+
+ spin_lock_irq(&fep->lock);
+
+ fep->opened = 1;
+ netif_carrier_off(dev);
+
+ /* Reset & configure the chip */
+ emac_reset_configure(fep);
+
+ spin_unlock_irq(&fep->lock);
+
+ return emac_up(dev);
+
+}
+
static int emac_close(struct net_device *dev)
{
struct ocp_enet_private *fep = dev->priv;
@@ -1975,6 +1991,71 @@
return 0;
}
+#ifdef CONFIG_PM
+static int emac_suspend(struct ocp_device *pdev, u32 state)
+{
+ struct net_device *netdev = ocp_get_drvdata(pdev);
+ struct ocp_enet_private *fep = netdev->priv;
+
+ pr_debug("PM:emac_suspend:%d\n", state);
+
+ if(netif_running(netdev))
+ emac_close(netdev);
+
+ /* Stop timer and Reset the chip */
+ spin_lock_irq(&fep->lock);
+ del_timer(&fep->link_timer);
+ fep->opened = 0;
+ emac_reset(fep);
+ spin_unlock_irq(&fep->lock);
+
+ /* detach */
+ netif_device_detach(netdev);
+
+ /*
+ * Save current states then turn off EMAC and PHY
+ * according to specified state.
+ * make WOL(WakeupOnLan) enable, if needed
+ */
+ // XXX:TBD
+ pdev->current_state = state;
+
+ return 0;
+}
+
+static int emac_resume(struct ocp_device *pdev)
+{
+ struct net_device *netdev = ocp_get_drvdata(pdev);
+ struct ocp_enet_private *fep = netdev->priv;
+
+ pr_debug("emac_resume:\n");
+
+ /* Turn on EMAC and PHY and restore state */
+ // XXX:TBD
+ pdev->current_state = 0;
+
+ /* Reset & configure the chip then Restart Timer */
+ spin_lock_irq(&fep->lock);
+
+ fep->opened = 1;
+ netif_carrier_off(netdev);
+ emac_reset_configure(fep);
+
+ (fep->link_timer).expires = jiffies+1;
+ add_timer(&fep->link_timer);
+
+ spin_unlock_irq(&fep->lock);
+
+ /* attach */
+ netif_device_attach(netdev);
+
+ if(netif_running(netdev))
+ emac_up(netdev);
+
+ return 0;
+}
+#endif
+
/* Structure for a device driver */
static struct ocp_device_id emac_ids[] = {
{.vendor = OCP_ANY_ID,.function = OCP_FUNC_EMAC},
@@ -1987,6 +2068,10 @@
.probe = emac_probe,
.remove = emac_remove,
+#ifdef CONFIG_PM
+ .suspend = emac_suspend,
+ .resume = emac_resume,
+#endif
};
static int __init emac_init(void)
-EOF
More information about the Linuxppc-embedded
mailing list