+#define RT2880_PCI_REG_PCICFG_ADDR 0x00
+#define RT2880_PCI_REG_PCIMSK_ADDR 0x0c
+#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10
+#define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18
+#define RT2880_PCI_REG_CONFIG_ADDR 0x20
+#define RT2880_PCI_REG_CONFIG_DATA 0x24
+#define RT2880_PCI_REG_MEMBASE 0x28
+#define RT2880_PCI_REG_IOBASE 0x2c
+#define RT2880_PCI_REG_ID 0x30
+#define RT2880_PCI_REG_CLASS 0x34
+#define RT2880_PCI_REG_SUBID 0x38
+#define RT2880_PCI_REG_ARBCTL 0x80
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+void __iomem *rt2880_pci_base;
+
+static u32 rt2880_pci_reg_read(u32 reg)
+{
+ return readl(rt2880_pci_base + reg);
+}
+
+static void rt2880_pci_reg_write(u32 val, u32 reg)
+{
+ writel(val, rt2880_pci_base + reg);
+}
+
+static void config_access(unsigned char access_type, struct pci_bus *bus,
+ unsigned int devfn, unsigned char where, u32 *data)
+{
+ unsigned int slot = PCI_SLOT(devfn);
+ unsigned int address;
+ u8 func = PCI_FUNC(devfn);
+
+ address = (bus->number << 16) | (slot << 11) | (func << 8) |
+ (where & 0xfc) | 0x80000000;
+
+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
+ if (access_type == PCI_ACCESS_WRITE)
+ rt2880_pci_reg_write(*data, RT2880_PCI_REG_CONFIG_DATA);
+ else
+ *data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
+}
+
+static int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ u32 data = 0;
+
+ config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if (size == 4) {
+ data = val;
+ } else {
+ config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops rt2880_pci_ops = {
+ .read = rt2880_pci_config_read,
+ .write = rt2880_pci_config_write,