0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/pci.h>
0010 #include <linux/delay.h>
0011 #include <linux/string.h>
0012 #include <linux/init.h>
0013
0014 #include <asm/io.h>
0015 #include <asm/pci-bridge.h>
0016 #include <asm/machdep.h>
0017
0018 int __indirect_read_config(struct pci_controller *hose,
0019 unsigned char bus_number, unsigned int devfn,
0020 int offset, int len, u32 *val)
0021 {
0022 volatile void __iomem *cfg_data;
0023 u8 cfg_type = 0;
0024 u32 bus_no, reg;
0025
0026 if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) {
0027 if (bus_number != hose->first_busno)
0028 return PCIBIOS_DEVICE_NOT_FOUND;
0029 if (devfn != 0)
0030 return PCIBIOS_DEVICE_NOT_FOUND;
0031 }
0032
0033 if (ppc_md.pci_exclude_device)
0034 if (ppc_md.pci_exclude_device(hose, bus_number, devfn))
0035 return PCIBIOS_DEVICE_NOT_FOUND;
0036
0037 if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
0038 if (bus_number != hose->first_busno)
0039 cfg_type = 1;
0040
0041 bus_no = (bus_number == hose->first_busno) ?
0042 hose->self_busno : bus_number;
0043
0044 if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
0045 reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
0046 else
0047 reg = offset & 0xfc;
0048
0049 if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN)
0050 out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
0051 (devfn << 8) | reg | cfg_type));
0052 else
0053 out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
0054 (devfn << 8) | reg | cfg_type));
0055
0056
0057
0058
0059
0060 cfg_data = hose->cfg_data + (offset & 3);
0061 switch (len) {
0062 case 1:
0063 *val = in_8(cfg_data);
0064 break;
0065 case 2:
0066 *val = in_le16(cfg_data);
0067 break;
0068 default:
0069 *val = in_le32(cfg_data);
0070 break;
0071 }
0072 return PCIBIOS_SUCCESSFUL;
0073 }
0074
0075 int indirect_read_config(struct pci_bus *bus, unsigned int devfn,
0076 int offset, int len, u32 *val)
0077 {
0078 struct pci_controller *hose = pci_bus_to_host(bus);
0079
0080 return __indirect_read_config(hose, bus->number, devfn, offset, len,
0081 val);
0082 }
0083
0084 int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
0085 int offset, int len, u32 val)
0086 {
0087 struct pci_controller *hose = pci_bus_to_host(bus);
0088 volatile void __iomem *cfg_data;
0089 u8 cfg_type = 0;
0090 u32 bus_no, reg;
0091
0092 if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) {
0093 if (bus->number != hose->first_busno)
0094 return PCIBIOS_DEVICE_NOT_FOUND;
0095 if (devfn != 0)
0096 return PCIBIOS_DEVICE_NOT_FOUND;
0097 }
0098
0099 if (ppc_md.pci_exclude_device)
0100 if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
0101 return PCIBIOS_DEVICE_NOT_FOUND;
0102
0103 if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
0104 if (bus->number != hose->first_busno)
0105 cfg_type = 1;
0106
0107 bus_no = (bus->number == hose->first_busno) ?
0108 hose->self_busno : bus->number;
0109
0110 if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
0111 reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
0112 else
0113 reg = offset & 0xfc;
0114
0115 if (hose->indirect_type & PPC_INDIRECT_TYPE_BIG_ENDIAN)
0116 out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
0117 (devfn << 8) | reg | cfg_type));
0118 else
0119 out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
0120 (devfn << 8) | reg | cfg_type));
0121
0122
0123 if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
0124 if ((offset == PCI_PRIMARY_BUS) &&
0125 (bus->number == hose->first_busno))
0126 val &= 0xffffff00;
0127
0128
0129 if ((hose->indirect_type & PPC_INDIRECT_TYPE_BROKEN_MRM) &&
0130 offset == PCI_CACHE_LINE_SIZE) {
0131 val = 0;
0132 }
0133
0134
0135
0136
0137
0138 cfg_data = hose->cfg_data + (offset & 3);
0139 switch (len) {
0140 case 1:
0141 out_8(cfg_data, val);
0142 break;
0143 case 2:
0144 out_le16(cfg_data, val);
0145 break;
0146 default:
0147 out_le32(cfg_data, val);
0148 break;
0149 }
0150 return PCIBIOS_SUCCESSFUL;
0151 }
0152
0153 static struct pci_ops indirect_pci_ops =
0154 {
0155 .read = indirect_read_config,
0156 .write = indirect_write_config,
0157 };
0158
0159 void setup_indirect_pci(struct pci_controller *hose, resource_size_t cfg_addr,
0160 resource_size_t cfg_data, u32 flags)
0161 {
0162 resource_size_t base = cfg_addr & PAGE_MASK;
0163 void __iomem *mbase;
0164
0165 mbase = ioremap(base, PAGE_SIZE);
0166 hose->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK);
0167 if ((cfg_data & PAGE_MASK) != base)
0168 mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
0169 hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK);
0170 hose->ops = &indirect_pci_ops;
0171 hose->indirect_type = flags;
0172 }