From 971fcf99431efb2d5cc5117d9bcdd13a13c2dd41 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 27 Nov 2009 21:21:21 +0000 Subject: ar71xx: add PCI fixup for the WNDR3700 board SVN-Revision: 18565 --- .../ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c index 9c5dd41a4c..472d603ba4 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,82 @@ static struct ar71xx_pci_irq wndr3700_pci_irqs[] __initdata = { static struct ath9k_platform_data wndr3700_wmac0_data; static struct ath9k_platform_data wndr3700_wmac1_data; +static void wndr3700_pci_fixup(struct pci_dev *dev) +{ + void __iomem *mem; + u16 *cal_data; + u16 cmd; + u32 bar0; + u32 val; + + if (ar71xx_mach != AR71XX_MACH_WNDR3700) + return; + + switch (PCI_SLOT(dev->devfn)) { + case 17: + cal_data = wndr3700_wmac0_data.eeprom_data; + break; + case 18: + cal_data = wndr3700_wmac1_data.eeprom_data; + break; + default: + return; + } + + if (*cal_data != 0xa55a) { + printk(KERN_ERR "PCI: no calibration data found for %s\n", + pci_name(dev)); + return; + } + + mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); + if (!mem) { + printk(KERN_ERR "PCI: ioremap error for device %s\n", + pci_name(dev)); + return; + } + + printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); + + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); + + /* Setup the PCI device to allow access to the internal registers */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, AR71XX_PCI_MEM_BASE); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* set pointer to first reg address */ + cal_data += 3; + while (*cal_data != 0xffff) { + u32 reg; + reg = *cal_data++; + val = *cal_data++; + val |= (*cal_data++) << 16; + + __raw_writel(val, mem + reg); + udelay(100); + } + + pci_read_config_dword(dev, PCI_VENDOR_ID, &val); + dev->vendor = val & 0xffff; + dev->device = (val >> 16) & 0xffff; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); + dev->revision = val & 0xff; + dev->class = val >> 8; /* upper 3 bytes */ + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); + + iounmap(mem); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, + wndr3700_pci_fixup); + static int wndr3700_pci_plat_dev_init(struct pci_dev *dev) { switch (PCI_SLOT(dev->devfn)) { -- cgit v1.2.3