Commit 65c7b2d6 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by David S. Miller

[SUNGEM]: Add support for G5 PowerMAC plus PM fixes.

parent c1f8218a
......@@ -103,6 +103,8 @@ static struct pci_device_id gem_pci_tbl[] = {
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 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
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 @@ static int gem_mdio_link_not_up(struct gem *gp)
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 @@ static void gem_init_phy(struct gem *gp)
* 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 @@ static void gem_init_mac(struct gem *gp)
/* 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 @@ static void gem_init_pause_thresholds(struct gem *gp)
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 @@ static void gem_apple_powerup(struct gem *gp)
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 @@ static void gem_apple_powerup(struct gem *gp)
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 @@ static void gem_apple_powerdown(struct gem *gp)
#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 @@ static void gem_stop_phy(struct gem *gp)
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 @@ static void gem_stop_phy(struct gem *gp)
/* 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 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
* 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 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
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;
......
......@@ -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.
*
......
......@@ -72,7 +72,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
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 @@ static int bcm5400_init(struct mii_phy* phy)
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 @@ static int bcm5401_init(struct mii_phy* phy)
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 @@ static int bcm5411_init(struct mii_phy* phy)
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 @@ static int bcm5421_init(struct mii_phy* phy)
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 @@ static struct mii_phy_def bcm5201_phy_def = {
.phy_id_mask = 0xfffffff0,
.name = "BCM5201",
.features = MII_BASIC_FEATURES,
.magic_aneg = 0,
.magic_aneg = 1,
.ops = &bcm5201_phy_ops
};
......@@ -666,7 +675,7 @@ static struct mii_phy_def bcm5221_phy_def = {
.phy_id_mask = 0xfffffff0,
.name = "BCM5221",
.features = MII_BASIC_FEATURES,
.magic_aneg = 0,
.magic_aneg = 1,
.ops = &bcm5221_phy_ops
};
......@@ -746,6 +755,25 @@ static struct mii_phy_def bcm5421_phy_def = {
.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 @@ static struct mii_phy_def* mii_phy_table[] = {
&bcm5401_phy_def,
&bcm5411_phy_def,
&bcm5421_phy_def,
&bcm5421k2_phy_def,
&marvell_phy_def,
&genmii_phy_def,
NULL
......@@ -813,8 +842,8 @@ int mii_phy_probe(struct mii_phy *phy, int mii_id)
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment