[TG3]: Add various register methods

This patch adds various dedicated register read/write methods for the
existing workarounds, including PCIX target workaround, write with read
flush, etc. The chips that require these workarounds will use these
dedicated access functions.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Michael Chan 2005-08-09 20:16:46 -07:00 committed by David S. Miller
parent 2009493065
commit 1ee582d8e4

View file

@ -340,16 +340,16 @@ static struct {
static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
{ {
if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { spin_lock_bh(&tp->indirect_lock);
spin_lock_bh(&tp->indirect_lock); pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); spin_unlock_bh(&tp->indirect_lock);
spin_unlock_bh(&tp->indirect_lock); }
} else {
writel(val, tp->regs + off); static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val)
if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0) {
readl(tp->regs + off); writel(val, tp->regs + off);
} readl(tp->regs + off);
} }
static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
@ -366,14 +366,6 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
} }
} }
static void tg3_write32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
{
void __iomem *mbox = tp->regs + off;
writel(val, mbox);
if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
readl(mbox);
}
static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
{ {
void __iomem *mbox = tp->regs + off; void __iomem *mbox = tp->regs + off;
@ -4222,7 +4214,7 @@ static void tg3_stop_fw(struct tg3 *);
static int tg3_chip_reset(struct tg3 *tp) static int tg3_chip_reset(struct tg3 *tp)
{ {
u32 val; u32 val;
u32 flags_save; void (*write_op)(struct tg3 *, u32, u32);
int i; int i;
if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
@ -4234,8 +4226,9 @@ static int tg3_chip_reset(struct tg3 *tp)
* fun things. So, temporarily disable the 5701 * fun things. So, temporarily disable the 5701
* hardware workaround, while we do the reset. * hardware workaround, while we do the reset.
*/ */
flags_save = tp->tg3_flags; write_op = tp->write32;
tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG; if (write_op == tg3_write_flush_reg32)
tp->write32 = tg3_write32;
/* do the reset */ /* do the reset */
val = GRC_MISC_CFG_CORECLK_RESET; val = GRC_MISC_CFG_CORECLK_RESET;
@ -4254,8 +4247,8 @@ static int tg3_chip_reset(struct tg3 *tp)
val |= GRC_MISC_CFG_KEEP_GPHY_POWER; val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
tw32(GRC_MISC_CFG, val); tw32(GRC_MISC_CFG, val);
/* restore 5701 hardware bug workaround flag */ /* restore 5701 hardware bug workaround write method */
tp->tg3_flags = flags_save; tp->write32 = write_op;
/* Unfortunately, we have to delay before the PCI read back. /* Unfortunately, we have to delay before the PCI read back.
* Some 575X chips even will not respond to a PCI cfg access * Some 575X chips even will not respond to a PCI cfg access
@ -4641,7 +4634,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
int cpu_scratch_size, struct fw_info *info) int cpu_scratch_size, struct fw_info *info)
{ {
int err, i; int err, i;
u32 orig_tg3_flags = tp->tg3_flags;
void (*write_op)(struct tg3 *, u32, u32); void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE && if (cpu_base == TX_CPU_BASE &&
@ -4657,11 +4649,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
else else
write_op = tg3_write_indirect_reg32; write_op = tg3_write_indirect_reg32;
/* Force use of PCI config space for indirect register
* write calls.
*/
tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
/* It is possible that bootcode is still loading at this point. /* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu. * Get the nvram lock first before halting the cpu.
*/ */
@ -4697,7 +4684,6 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
err = 0; err = 0;
out: out:
tp->tg3_flags = orig_tg3_flags;
return err; return err;
} }
@ -9331,11 +9317,25 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg); pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
} }
/* Default fast path register access methods */
tp->read32 = tg3_read32; tp->read32 = tg3_read32;
tp->write32 = tg3_write_indirect_reg32; tp->write32 = tg3_write32;
tp->write32_mbox = tg3_write32; tp->write32_mbox = tg3_write32;
tp->write32_tx_mbox = tg3_write32_tx_mbox; tp->write32_tx_mbox = tg3_write32;
tp->write32_rx_mbox = tg3_write32_rx_mbox; tp->write32_rx_mbox = tg3_write32;
/* Various workaround register access methods */
if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
tp->write32 = tg3_write_indirect_reg32;
else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
tp->write32 = tg3_write_flush_reg32;
if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
tp->write32_tx_mbox = tg3_write32_tx_mbox;
if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
tp->write32_rx_mbox = tg3_write_flush_reg32;
}
/* Get eeprom hw config before calling tg3_set_power_state(). /* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be