* [PATCH] sungem: add support for G5 PowerMac, some PM fixes
@ 2004-01-22 5:50 Benjamin Herrenschmidt
2004-01-22 6:08 ` David S. Miller
0 siblings, 1 reply; 5+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-22 5:50 UTC (permalink / raw)
To: David S. Miller; +Cc: Jeff Garzik, Linux Kernel list
Hi David !
Here's a patch against Linus current tree that update the sungem
driver. It adds support for the PowerMac G5, reduces a few mdelay's,
and try to schedule on some longer delays during the PM process.
There is still a race (from day 1 of the PM code actually) around
the PM semaphore when calling flush_scheduled_work() with the semaphore
held (since the workqueue can try to get it too). It's not fixed by
this patch yet, but I'd like this one to get in ASAP so we have the
G5 support in now.
Thye patch shouldn't affect non-powermac's.
Any comments ? If no, please submit to Andrew/Linus
Regards,
Ben.
diff -urN linux-2.5-merge/drivers/net/sungem.c linuxppc-2.5-benh/drivers/net/sungem.c
--- linux-2.5-merge/drivers/net/sungem.c 2004-01-22 14:25:56.748570272 +1100
+++ linuxppc-2.5-benh/drivers/net/sungem.c 2004-01-22 14:21:48.762269920 +1100
@@ -103,6 +103,8 @@
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMAC2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_GMAC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{0, }
};
@@ -778,6 +780,10 @@
struct gem *gp = dev->priv;
u32 gem_status = readl(gp->regs + GREG_STAT);
+ /* Swallow interrupts when shutting the chip down */
+ if (gp->hw_running == 0)
+ goto out;
+
spin_lock(&gp->lock);
if (gem_status & GREG_STAT_ABNORMAL) {
@@ -1240,6 +1246,12 @@
gp->lstate = link_force_ok;
return 0;
case link_aneg:
+ /* We try forced modes after a failed aneg only on PHYs that don't
+ * have "magic_aneg" bit set, which means they internally do the
+ * while forced-mode thingy. On these, we just restart aneg
+ */
+ if (gp->phy_mii.def->magic_aneg)
+ return 1;
if (netif_msg_link(gp))
printk(KERN_INFO "%s: switching to forced 100bt\n",
gp->dev->name);
@@ -1497,19 +1509,27 @@
* to schedule instead
*/
pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
- mdelay(10);
for (j = 0; j < 3; j++) {
/* Some PHYs used by apple have problem getting back to us,
- * we _know_ it's actually at addr 0, that's a hack, but
+ * we _know_ it's actually at addr 0 or 1, that's a hack, but
* it helps to do that reset now. I suspect some motherboards
* don't wire the PHY reset line properly, thus the PHY doesn't
* come back with the above pmac_call_feature.
*/
gp->mii_phy_addr = 0;
phy_write(gp, MII_BMCR, BMCR_RESET);
+ gp->mii_phy_addr = 1;
+ phy_write(gp, MII_BMCR, BMCR_RESET);
/* We should probably break some locks here and schedule... */
mdelay(10);
- for (i = 0; i < 32; i++) {
+
+ /* On K2, we only probe the internal PHY at address 1, other
+ * addresses tend to return garbage.
+ */
+ if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
+ break;
+
+ for (i = 0; i < 32; i++) {
gp->mii_phy_addr = i;
if (phy_read(gp, MII_BMCR) != 0xffff)
break;
@@ -1770,6 +1790,8 @@
/* Must be invoked under gp->lock. */
static void gem_init_pause_thresholds(struct gem *gp)
{
+ u32 cfg;
+
/* Calculate pause thresholds. Setting the OFF threshold to the
* full RX fifo size effectively disables PAUSE generation which
* is what we do for 10/100 only GEMs which have FIFOs too small
@@ -1786,17 +1808,28 @@
gp->rx_pause_on = on;
}
- {
- u32 cfg;
- cfg = 0;
+ /* Configure the chip "burst" DMA mode & enable some
+ * HW bug fixes on Apple version
+ */
+ cfg = 0;
+ if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
+ cfg |= GREG_CFG_RONPAULBIT | GREG_CFG_ENBUG2FIX;
#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
- cfg |= GREG_CFG_IBURST;
+ cfg |= GREG_CFG_IBURST;
#endif
- cfg |= ((31 << 1) & GREG_CFG_TXDMALIM);
- cfg |= ((31 << 6) & GREG_CFG_RXDMALIM);
+ cfg |= ((31 << 1) & GREG_CFG_TXDMALIM);
+ cfg |= ((31 << 6) & GREG_CFG_RXDMALIM);
+ writel(cfg, gp->regs + GREG_CFG);
+
+ /* If Infinite Burst didn't stick, then use different
+ * thresholds (and Apple bug fixes don't exist)
+ */
+ if (readl(gp->regs + GREG_CFG) & GREG_CFG_IBURST) {
+ cfg = ((2 << 1) & GREG_CFG_TXDMALIM);
+ cfg = ((8 << 6) & GREG_CFG_RXDMALIM);
writel(cfg, gp->regs + GREG_CFG);
- }
+ }
}
static int gem_check_invariants(struct gem *gp)
@@ -1931,18 +1964,10 @@
u16 cmd;
u32 mif_cfg;
+ mb();
pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout((21 * HZ) / 1000);
-
- pci_read_config_word(gp->pdev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
- pci_write_config_word(gp->pdev, PCI_COMMAND, cmd);
- pci_write_config_byte(gp->pdev, PCI_LATENCY_TIMER, 6);
- pci_write_config_byte(gp->pdev, PCI_CACHE_LINE_SIZE, 8);
-
- mdelay(1);
+ udelay(3);
mif_cfg = readl(gp->regs + MIF_CFG);
mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
@@ -1950,8 +1975,6 @@
writel(mif_cfg, gp->regs + MIF_CFG);
writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
-
- mdelay(1);
}
/* Turn off the chip's clock */
@@ -1962,10 +1985,17 @@
#endif /* CONFIG_PPC_PMAC */
-/* Must be invoked under gp->lock. */
+/* Must be invoked with no lock held. */
static void gem_stop_phy(struct gem *gp)
{
u32 mifcfg;
+ unsigned long flags;
+
+ /* Let the chip settle down a bit, it seems that helps
+ * for sleep mode on some models
+ */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/100);
/* Make sure we aren't polling PHY status change. We
* don't currently use that feature though
@@ -1976,17 +2006,28 @@
if (gp->wake_on_lan) {
/* Setup wake-on-lan */
- } else
+ } else {
writel(0, gp->regs + MAC_RXCFG);
+ (void)readl(gp->regs + MAC_RXCFG);
+ /* Machine sleep will die in strange ways if we
+ * dont wait a bit here, looks like the chip takes
+ * some time to really shut down
+ */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/100);
+ }
+
writel(0, gp->regs + MAC_TXCFG);
writel(0, gp->regs + MAC_XIFCFG);
writel(0, gp->regs + TXDMA_CFG);
writel(0, gp->regs + RXDMA_CFG);
if (!gp->wake_on_lan) {
+ spin_lock_irqsave(&gp->lock, flags);
gem_stop(gp);
writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+ spin_unlock_irqrestore(&gp->lock, flags);
}
if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
@@ -2008,31 +2049,33 @@
/* Shut down the chip, must be called with pm_sem held. */
static void gem_shutdown(struct gem *gp)
{
- /* Make us not-running to avoid timers respawning */
+ /* Make us not-running to avoid timers respawning
+ * and swallow irqs
+ */
gp->hw_running = 0;
+ wmb();
/* Stop the link timer */
del_timer_sync(&gp->link_timer);
/* Stop the reset task */
while (gp->reset_task_pending)
- schedule();
+ yield();
/* Actually stop the chip */
- spin_lock_irq(&gp->lock);
if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
gem_stop_phy(gp);
- spin_unlock_irq(&gp->lock);
-
#ifdef CONFIG_PPC_PMAC
/* Power down the chip */
gem_apple_powerdown(gp);
#endif /* CONFIG_PPC_PMAC */
- } else {
- gem_stop(gp);
+ } else{
+ unsigned long flags;
- spin_unlock_irq(&gp->lock);
+ spin_lock_irqsave(&gp->lock, flags);
+ gem_stop(gp);
+ spin_unlock_irqrestore(&gp->lock, flags);
}
}
@@ -2692,6 +2735,7 @@
* not have properly shut down the PHY.
*/
#ifdef CONFIG_PPC_PMAC
+ gp->of_node = pci_device_to_OF_node(pdev);
if (pdev->vendor == PCI_VENDOR_ID_APPLE)
gem_apple_powerup(gp);
#endif
@@ -2725,9 +2769,6 @@
goto err_out_iounmap;
}
-#ifdef CONFIG_PPC_PMAC
- gp->of_node = pci_device_to_OF_node(pdev);
-#endif
if (gem_get_device_address(gp))
goto err_out_free_consistent;
diff -urN linux-2.5-merge/drivers/net/sungem.h linuxppc-2.5-benh/drivers/net/sungem.h
--- linux-2.5-merge/drivers/net/sungem.h 2004-01-22 14:25:56.752569664 +1100
+++ linuxppc-2.5-benh/drivers/net/sungem.h 2004-01-22 14:21:48.780267184 +1100
@@ -28,6 +28,9 @@
#define GREG_CFG_IBURST 0x00000001 /* Infinite Burst */
#define GREG_CFG_TXDMALIM 0x0000003e /* TX DMA grant limit */
#define GREG_CFG_RXDMALIM 0x000007c0 /* RX DMA grant limit */
+#define GREG_CFG_RONPAULBIT 0x00000800 /* Use mem read multiple for PCI read
+ * after infinite burst (Apple) */
+#define GREG_CFG_ENBUG2FIX 0x00001000 /* Fix Rx hang after overflow */
/* Global Interrupt Status Register.
*
diff -urN linux-2.5-merge/drivers/net/sungem_phy.c linuxppc-2.5-benh/drivers/net/sungem_phy.c
--- linux-2.5-merge/drivers/net/sungem_phy.c 2004-01-22 14:25:56.772566624 +1100
+++ linuxppc-2.5-benh/drivers/net/sungem_phy.c 2004-01-22 14:21:48.782266880 +1100
@@ -72,7 +72,7 @@
int limit = 10000;
val = __phy_read(phy, phy_id, MII_BMCR);
- val &= ~BMCR_ISOLATE;
+ val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
val |= BMCR_RESET;
__phy_write(phy, phy_id, MII_BMCR, val);
@@ -157,7 +157,7 @@
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
phy_write(phy, MII_BCM5400_GB_CONTROL, data);
- mdelay(10);
+ udelay(100);
/* Reset and configure cascaded 10/100 PHY */
(void)reset_one_mii_phy(phy, 0x1f);
@@ -217,7 +217,7 @@
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
phy_write(phy, MII_BCM5400_GB_CONTROL, data);
- mdelay(10);
+ udelay(10);
/* Reset and configure cascaded 10/100 PHY */
(void)reset_one_mii_phy(phy, 0x1f);
@@ -258,7 +258,7 @@
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
phy_write(phy, MII_BCM5400_GB_CONTROL, data);
- mdelay(10);
+ udelay(10);
/* Reset and configure cascaded 10/100 PHY */
(void)reset_one_mii_phy(phy, 0x1f);
@@ -302,6 +302,15 @@
return 0;
}
+static int bcm5421k2_init(struct mii_phy* phy)
+{
+ /* Init code borrowed from OF */
+ phy_write(phy, 4, 0x01e1);
+ phy_write(phy, 9, 0x0300);
+
+ return 0;
+}
+
static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
{
u16 ctl, adv;
@@ -647,7 +656,7 @@
.phy_id_mask = 0xfffffff0,
.name = "BCM5201",
.features = MII_BASIC_FEATURES,
- .magic_aneg = 0,
+ .magic_aneg = 1,
.ops = &bcm5201_phy_ops
};
@@ -666,7 +675,7 @@
.phy_id_mask = 0xfffffff0,
.name = "BCM5221",
.features = MII_BASIC_FEATURES,
- .magic_aneg = 0,
+ .magic_aneg = 1,
.ops = &bcm5221_phy_ops
};
@@ -746,6 +755,25 @@
.ops = &bcm5421_phy_ops
};
+/* Broadcom BCM 5421 built-in K2 */
+static struct mii_phy_ops bcm5421k2_phy_ops = {
+ .init = bcm5421k2_init,
+ .suspend = bcm5411_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5421k2_phy_def = {
+ .phy_id = 0x002062e0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5421-K2",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5421k2_phy_ops
+};
+
/* Marvell 88E1101 (Apple seem to deal with 2 different revs,
* I masked out the 8 last bits to get both, but some specs
* would be useful here) --BenH.
@@ -790,6 +818,7 @@
&bcm5401_phy_def,
&bcm5411_phy_def,
&bcm5421_phy_def,
+ &bcm5421k2_phy_def,
&marvell_phy_def,
&genmii_phy_def,
NULL
@@ -813,8 +842,8 @@
goto fail;
/* Read ID and find matching entry */
- id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2))
- & 0xfffffff0;
+ id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+ printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
for (i=0; (def = mii_phy_table[i]) != NULL; i++)
if ((id & def->phy_id_mask) == def->phy_id)
break;
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] sungem: add support for G5 PowerMac, some PM fixes
2004-01-22 5:50 [PATCH] sungem: add support for G5 PowerMac, some PM fixes Benjamin Herrenschmidt
@ 2004-01-22 6:08 ` David S. Miller
2004-01-22 23:13 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 5+ messages in thread
From: David S. Miller @ 2004-01-22 6:08 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: jgarzik, linux-kernel
On Thu, 22 Jan 2004 16:50:43 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> + if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
> + break;
> +
> + for (i = 0; i < 32; i++) {
Please fix this indentation, and I'll happily apply this ;-)
I assume you'll have a 2.4.x variant of this patch too?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] sungem: add support for G5 PowerMac, some PM fixes
2004-01-22 6:08 ` David S. Miller
@ 2004-01-22 23:13 ` Benjamin Herrenschmidt
2004-01-26 7:01 ` David S. Miller
0 siblings, 1 reply; 5+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-22 23:13 UTC (permalink / raw)
To: David S. Miller; +Cc: Jeff Garzik, Linux Kernel list
On Thu, 2004-01-22 at 17:08, David S. Miller wrote:
> On Thu, 22 Jan 2004 16:50:43 +1100
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> > + if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
> > + break;
> > +
> > + for (i = 0; i < 32; i++) {
>
> Please fix this indentation, and I'll happily apply this ;-)
>
> I assume you'll have a 2.4.x variant of this patch too?
Ohh, this was just a tab vs. space issue actually, the resulting indent
was fine ;) Anyway, here's the fixed version. The 2.4 backport will
come next week hopefully when I'll walk through all my pending 2.4
stuffs, I want to dbl check a few things in it first (and I'm not yet
100% certain I will merge the G5 support in 2.4 upstream anyway).
Note: the new PCI ID isn't yet in Linus tree, but it's in the patches
I'm currently sending to Andrew.
Ben.
diff -urN linux-2.5-merge/drivers/net/sungem.c linuxppc-2.5-benh/drivers/net/sungem.c
--- linux-2.5-merge/drivers/net/sungem.c 2004-01-23 10:10:00.836189096 +1100
+++ linuxppc-2.5-benh/drivers/net/sungem.c 2004-01-23 10:10:53.087245728 +1100
@@ -103,6 +103,8 @@
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMAC2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_GMAC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{0, }
};
@@ -778,6 +780,10 @@
struct gem *gp = dev->priv;
u32 gem_status = readl(gp->regs + GREG_STAT);
+ /* Swallow interrupts when shutting the chip down */
+ if (gp->hw_running == 0)
+ goto out;
+
spin_lock(&gp->lock);
if (gem_status & GREG_STAT_ABNORMAL) {
@@ -1240,6 +1246,12 @@
gp->lstate = link_force_ok;
return 0;
case link_aneg:
+ /* We try forced modes after a failed aneg only on PHYs that don't
+ * have "magic_aneg" bit set, which means they internally do the
+ * while forced-mode thingy. On these, we just restart aneg
+ */
+ if (gp->phy_mii.def->magic_aneg)
+ return 1;
if (netif_msg_link(gp))
printk(KERN_INFO "%s: switching to forced 100bt\n",
gp->dev->name);
@@ -1497,18 +1509,26 @@
* to schedule instead
*/
pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
- mdelay(10);
for (j = 0; j < 3; j++) {
/* Some PHYs used by apple have problem getting back to us,
- * we _know_ it's actually at addr 0, that's a hack, but
+ * we _know_ it's actually at addr 0 or 1, that's a hack, but
* it helps to do that reset now. I suspect some motherboards
* don't wire the PHY reset line properly, thus the PHY doesn't
* come back with the above pmac_call_feature.
*/
gp->mii_phy_addr = 0;
phy_write(gp, MII_BMCR, BMCR_RESET);
+ gp->mii_phy_addr = 1;
+ phy_write(gp, MII_BMCR, BMCR_RESET);
/* We should probably break some locks here and schedule... */
mdelay(10);
+
+ /* On K2, we only probe the internal PHY at address 1, other
+ * addresses tend to return garbage.
+ */
+ if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
+ break;
+
for (i = 0; i < 32; i++) {
gp->mii_phy_addr = i;
if (phy_read(gp, MII_BMCR) != 0xffff)
@@ -1770,6 +1790,8 @@
/* Must be invoked under gp->lock. */
static void gem_init_pause_thresholds(struct gem *gp)
{
+ u32 cfg;
+
/* Calculate pause thresholds. Setting the OFF threshold to the
* full RX fifo size effectively disables PAUSE generation which
* is what we do for 10/100 only GEMs which have FIFOs too small
@@ -1786,17 +1808,28 @@
gp->rx_pause_on = on;
}
- {
- u32 cfg;
- cfg = 0;
+ /* Configure the chip "burst" DMA mode & enable some
+ * HW bug fixes on Apple version
+ */
+ cfg = 0;
+ if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
+ cfg |= GREG_CFG_RONPAULBIT | GREG_CFG_ENBUG2FIX;
#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
- cfg |= GREG_CFG_IBURST;
+ cfg |= GREG_CFG_IBURST;
#endif
- cfg |= ((31 << 1) & GREG_CFG_TXDMALIM);
- cfg |= ((31 << 6) & GREG_CFG_RXDMALIM);
+ cfg |= ((31 << 1) & GREG_CFG_TXDMALIM);
+ cfg |= ((31 << 6) & GREG_CFG_RXDMALIM);
+ writel(cfg, gp->regs + GREG_CFG);
+
+ /* If Infinite Burst didn't stick, then use different
+ * thresholds (and Apple bug fixes don't exist)
+ */
+ if (readl(gp->regs + GREG_CFG) & GREG_CFG_IBURST) {
+ cfg = ((2 << 1) & GREG_CFG_TXDMALIM);
+ cfg = ((8 << 6) & GREG_CFG_RXDMALIM);
writel(cfg, gp->regs + GREG_CFG);
- }
+ }
}
static int gem_check_invariants(struct gem *gp)
@@ -1931,18 +1964,10 @@
u16 cmd;
u32 mif_cfg;
+ mb();
pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout((21 * HZ) / 1000);
-
- pci_read_config_word(gp->pdev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
- pci_write_config_word(gp->pdev, PCI_COMMAND, cmd);
- pci_write_config_byte(gp->pdev, PCI_LATENCY_TIMER, 6);
- pci_write_config_byte(gp->pdev, PCI_CACHE_LINE_SIZE, 8);
-
- mdelay(1);
+ udelay(3);
mif_cfg = readl(gp->regs + MIF_CFG);
mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
@@ -1950,8 +1975,6 @@
writel(mif_cfg, gp->regs + MIF_CFG);
writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
-
- mdelay(1);
}
/* Turn off the chip's clock */
@@ -1962,10 +1985,17 @@
#endif /* CONFIG_PPC_PMAC */
-/* Must be invoked under gp->lock. */
+/* Must be invoked with no lock held. */
static void gem_stop_phy(struct gem *gp)
{
u32 mifcfg;
+ unsigned long flags;
+
+ /* Let the chip settle down a bit, it seems that helps
+ * for sleep mode on some models
+ */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/100);
/* Make sure we aren't polling PHY status change. We
* don't currently use that feature though
@@ -1976,17 +2006,28 @@
if (gp->wake_on_lan) {
/* Setup wake-on-lan */
- } else
+ } else {
writel(0, gp->regs + MAC_RXCFG);
+ (void)readl(gp->regs + MAC_RXCFG);
+ /* Machine sleep will die in strange ways if we
+ * dont wait a bit here, looks like the chip takes
+ * some time to really shut down
+ */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/100);
+ }
+
writel(0, gp->regs + MAC_TXCFG);
writel(0, gp->regs + MAC_XIFCFG);
writel(0, gp->regs + TXDMA_CFG);
writel(0, gp->regs + RXDMA_CFG);
if (!gp->wake_on_lan) {
+ spin_lock_irqsave(&gp->lock, flags);
gem_stop(gp);
writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+ spin_unlock_irqrestore(&gp->lock, flags);
}
if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
@@ -2008,31 +2049,33 @@
/* Shut down the chip, must be called with pm_sem held. */
static void gem_shutdown(struct gem *gp)
{
- /* Make us not-running to avoid timers respawning */
+ /* Make us not-running to avoid timers respawning
+ * and swallow irqs
+ */
gp->hw_running = 0;
+ wmb();
/* Stop the link timer */
del_timer_sync(&gp->link_timer);
/* Stop the reset task */
while (gp->reset_task_pending)
- schedule();
+ yield();
/* Actually stop the chip */
- spin_lock_irq(&gp->lock);
if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
gem_stop_phy(gp);
- spin_unlock_irq(&gp->lock);
-
#ifdef CONFIG_PPC_PMAC
/* Power down the chip */
gem_apple_powerdown(gp);
#endif /* CONFIG_PPC_PMAC */
- } else {
- gem_stop(gp);
+ } else{
+ unsigned long flags;
- spin_unlock_irq(&gp->lock);
+ spin_lock_irqsave(&gp->lock, flags);
+ gem_stop(gp);
+ spin_unlock_irqrestore(&gp->lock, flags);
}
}
@@ -2692,6 +2735,7 @@
* not have properly shut down the PHY.
*/
#ifdef CONFIG_PPC_PMAC
+ gp->of_node = pci_device_to_OF_node(pdev);
if (pdev->vendor == PCI_VENDOR_ID_APPLE)
gem_apple_powerup(gp);
#endif
@@ -2725,9 +2769,6 @@
goto err_out_iounmap;
}
-#ifdef CONFIG_PPC_PMAC
- gp->of_node = pci_device_to_OF_node(pdev);
-#endif
if (gem_get_device_address(gp))
goto err_out_free_consistent;
diff -urN linux-2.5-merge/drivers/net/sungem.h linuxppc-2.5-benh/drivers/net/sungem.h
--- linux-2.5-merge/drivers/net/sungem.h 2004-01-23 10:10:00.853186512 +1100
+++ linuxppc-2.5-benh/drivers/net/sungem.h 2004-01-23 10:10:15.303989656 +1100
@@ -28,6 +28,9 @@
#define GREG_CFG_IBURST 0x00000001 /* Infinite Burst */
#define GREG_CFG_TXDMALIM 0x0000003e /* TX DMA grant limit */
#define GREG_CFG_RXDMALIM 0x000007c0 /* RX DMA grant limit */
+#define GREG_CFG_RONPAULBIT 0x00000800 /* Use mem read multiple for PCI read
+ * after infinite burst (Apple) */
+#define GREG_CFG_ENBUG2FIX 0x00001000 /* Fix Rx hang after overflow */
/* Global Interrupt Status Register.
*
diff -urN linux-2.5-merge/drivers/net/sungem_phy.c linuxppc-2.5-benh/drivers/net/sungem_phy.c
--- linux-2.5-merge/drivers/net/sungem_phy.c 2004-01-23 10:10:00.866184536 +1100
+++ linuxppc-2.5-benh/drivers/net/sungem_phy.c 2004-01-23 10:10:15.323986616 +1100
@@ -72,7 +72,7 @@
int limit = 10000;
val = __phy_read(phy, phy_id, MII_BMCR);
- val &= ~BMCR_ISOLATE;
+ val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
val |= BMCR_RESET;
__phy_write(phy, phy_id, MII_BMCR, val);
@@ -157,7 +157,7 @@
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
phy_write(phy, MII_BCM5400_GB_CONTROL, data);
- mdelay(10);
+ udelay(100);
/* Reset and configure cascaded 10/100 PHY */
(void)reset_one_mii_phy(phy, 0x1f);
@@ -217,7 +217,7 @@
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
phy_write(phy, MII_BCM5400_GB_CONTROL, data);
- mdelay(10);
+ udelay(10);
/* Reset and configure cascaded 10/100 PHY */
(void)reset_one_mii_phy(phy, 0x1f);
@@ -258,7 +258,7 @@
data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
phy_write(phy, MII_BCM5400_GB_CONTROL, data);
- mdelay(10);
+ udelay(10);
/* Reset and configure cascaded 10/100 PHY */
(void)reset_one_mii_phy(phy, 0x1f);
@@ -302,6 +302,15 @@
return 0;
}
+static int bcm5421k2_init(struct mii_phy* phy)
+{
+ /* Init code borrowed from OF */
+ phy_write(phy, 4, 0x01e1);
+ phy_write(phy, 9, 0x0300);
+
+ return 0;
+}
+
static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
{
u16 ctl, adv;
@@ -647,7 +656,7 @@
.phy_id_mask = 0xfffffff0,
.name = "BCM5201",
.features = MII_BASIC_FEATURES,
- .magic_aneg = 0,
+ .magic_aneg = 1,
.ops = &bcm5201_phy_ops
};
@@ -666,7 +675,7 @@
.phy_id_mask = 0xfffffff0,
.name = "BCM5221",
.features = MII_BASIC_FEATURES,
- .magic_aneg = 0,
+ .magic_aneg = 1,
.ops = &bcm5221_phy_ops
};
@@ -746,6 +755,25 @@
.ops = &bcm5421_phy_ops
};
+/* Broadcom BCM 5421 built-in K2 */
+static struct mii_phy_ops bcm5421k2_phy_ops = {
+ .init = bcm5421k2_init,
+ .suspend = bcm5411_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5421k2_phy_def = {
+ .phy_id = 0x002062e0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5421-K2",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5421k2_phy_ops
+};
+
/* Marvell 88E1101 (Apple seem to deal with 2 different revs,
* I masked out the 8 last bits to get both, but some specs
* would be useful here) --BenH.
@@ -790,6 +818,7 @@
&bcm5401_phy_def,
&bcm5411_phy_def,
&bcm5421_phy_def,
+ &bcm5421k2_phy_def,
&marvell_phy_def,
&genmii_phy_def,
NULL
@@ -813,8 +842,8 @@
goto fail;
/* Read ID and find matching entry */
- id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2))
- & 0xfffffff0;
+ id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+ printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
for (i=0; (def = mii_phy_table[i]) != NULL; i++)
if ((id & def->phy_id_mask) == def->phy_id)
break;
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] sungem: add support for G5 PowerMac, some PM fixes
2004-01-22 23:13 ` Benjamin Herrenschmidt
@ 2004-01-26 7:01 ` David S. Miller
2004-01-26 7:13 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 5+ messages in thread
From: David S. Miller @ 2004-01-26 7:01 UTC (permalink / raw)
To: benh; +Cc: jgarzik, linux-kernel
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Fri, 23 Jan 2004 10:13:12 +1100
Anyway, here's the fixed version.
Applied, thanks. This one might have to wait for 2.6.3-pre1 though
for merging.
The 2.4 backport will come next week hopefully when I'll walk
through all my pending 2.4 stuffs, I want to dbl check a few things
in it first (and I'm not yet 100% certain I will merge the G5
support in 2.4 upstream anyway).
You should be able to literally copy the 2.6.x driver into the 2.4.x
tree with perhaps only a one liner or two (if that).
the new PCI ID isn't yet in Linus tree, but it's in the patches
I'm currently sending to Andrew.
I'd prefer in the future you not do it this way, just give it
instead within the driver update so that you patch by itself
stands alone.
Thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] sungem: add support for G5 PowerMac, some PM fixes
2004-01-26 7:01 ` David S. Miller
@ 2004-01-26 7:13 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 5+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-26 7:13 UTC (permalink / raw)
To: David S. Miller; +Cc: Jeff Garzik, Linux Kernel list
On Mon, 2004-01-26 at 18:01, David S. Miller wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Date: Fri, 23 Jan 2004 10:13:12 +1100
>
> Anyway, here's the fixed version.
>
> Applied, thanks. This one might have to wait for 2.6.3-pre1 though
> for merging.
That's fine, the rest of the PowerMac updates are waiting for 2.6.3 too.
> The 2.4 backport will come next week hopefully when I'll walk
> through all my pending 2.4 stuffs, I want to dbl check a few things
> in it first (and I'm not yet 100% certain I will merge the G5
> support in 2.4 upstream anyway).
>
> You should be able to literally copy the 2.6.x driver into the 2.4.x
> tree with perhaps only a one liner or two (if that).
Yes. I'll do that along with other things I need to backport.
> the new PCI ID isn't yet in Linus tree, but it's in the patches
> I'm currently sending to Andrew.
>
> I'd prefer in the future you not do it this way, just give it
> instead within the driver update so that you patch by itself
> stands alone.
Ok.
Ben.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2004-01-26 7:14 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-01-22 5:50 [PATCH] sungem: add support for G5 PowerMac, some PM fixes Benjamin Herrenschmidt
2004-01-22 6:08 ` David S. Miller
2004-01-22 23:13 ` Benjamin Herrenschmidt
2004-01-26 7:01 ` David S. Miller
2004-01-26 7:13 ` Benjamin Herrenschmidt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox