0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/kernel.h>
0015 #include <linux/of_address.h>
0016 #include <linux/pci.h>
0017
0018 #include <asm/pci-bridge.h>
0019 #include <asm/isa-bridge.h>
0020 #include <asm/machdep.h>
0021
0022 #include <asm/ppc-pci.h>
0023
0024 #include "pasemi.h"
0025
0026 #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
0027
0028 static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset)
0029 {
0030
0031
0032
0033
0034 if (bus == 0 && devfn == 0)
0035 return offset < 8192;
0036 else
0037 return offset < 4096;
0038 }
0039
0040 static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
0041 u8 bus, u8 devfn, int offset)
0042 {
0043 return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset);
0044 }
0045
0046 static inline int is_root_port(int busno, int devfn)
0047 {
0048 return ((busno == 0) && (PCI_FUNC(devfn) < 4) &&
0049 ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17)));
0050 }
0051
0052 static inline int is_5945_reg(int reg)
0053 {
0054 return (((reg >= 0x18) && (reg < 0x34)) ||
0055 ((reg >= 0x158) && (reg < 0x178)));
0056 }
0057
0058 static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
0059 int offset, int len, u32 *val)
0060 {
0061 struct pci_controller *hose;
0062 void volatile __iomem *addr, *dummy;
0063 int byte;
0064 u32 tmp;
0065
0066 if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset))
0067 return 0;
0068
0069 hose = pci_bus_to_host(bus);
0070
0071 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3);
0072 byte = offset & 0x3;
0073
0074
0075
0076
0077
0078 dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10);
0079 out_le32(dummy, 0);
0080 tmp = in_le32(addr);
0081 out_le32(addr, tmp);
0082
0083 switch (len) {
0084 case 1:
0085 *val = (tmp >> (8*byte)) & 0xff;
0086 break;
0087 case 2:
0088 if (byte == 0)
0089 *val = tmp & 0xffff;
0090 else
0091 *val = (tmp >> 16) & 0xffff;
0092 break;
0093 default:
0094 *val = tmp;
0095 break;
0096 }
0097
0098 return 1;
0099 }
0100
0101 #ifdef CONFIG_PPC_PASEMI_NEMO
0102 #define PXP_ERR_CFG_REG 0x4
0103 #define PXP_IGNORE_PCIE_ERRORS 0x800
0104 #define SB600_BUS 5
0105
0106 static void sb600_set_flag(int bus)
0107 {
0108 static void __iomem *iob_mapbase = NULL;
0109 struct resource res;
0110 struct device_node *dn;
0111 int err;
0112
0113 if (iob_mapbase == NULL) {
0114 dn = of_find_compatible_node(NULL, "isa", "pasemi,1682m-iob");
0115 if (!dn) {
0116 pr_crit("NEMO SB600 missing iob node\n");
0117 return;
0118 }
0119
0120 err = of_address_to_resource(dn, 0, &res);
0121 of_node_put(dn);
0122
0123 if (err) {
0124 pr_crit("NEMO SB600 missing resource\n");
0125 return;
0126 }
0127
0128 pr_info("NEMO SB600 IOB base %08llx\n",res.start);
0129
0130 iob_mapbase = ioremap(res.start + 0x100, 0x94);
0131 }
0132
0133 if (iob_mapbase != NULL) {
0134 if (bus == SB600_BUS) {
0135
0136
0137
0138
0139 out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) | PXP_IGNORE_PCIE_ERRORS);
0140 } else {
0141
0142
0143
0144 out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) & ~PXP_IGNORE_PCIE_ERRORS);
0145 }
0146 }
0147 }
0148
0149 #else
0150
0151 static void sb600_set_flag(int bus)
0152 {
0153 }
0154 #endif
0155
0156 static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
0157 int offset, int len, u32 *val)
0158 {
0159 struct pci_controller *hose;
0160 void volatile __iomem *addr;
0161
0162 hose = pci_bus_to_host(bus);
0163 if (!hose)
0164 return PCIBIOS_DEVICE_NOT_FOUND;
0165
0166 if (!pa_pxp_offset_valid(bus->number, devfn, offset))
0167 return PCIBIOS_BAD_REGISTER_NUMBER;
0168
0169 if (workaround_5945(bus, devfn, offset, len, val))
0170 return PCIBIOS_SUCCESSFUL;
0171
0172 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
0173
0174 sb600_set_flag(bus->number);
0175
0176
0177
0178
0179
0180 switch (len) {
0181 case 1:
0182 *val = in_8(addr);
0183 break;
0184 case 2:
0185 *val = in_le16(addr);
0186 break;
0187 default:
0188 *val = in_le32(addr);
0189 break;
0190 }
0191
0192 return PCIBIOS_SUCCESSFUL;
0193 }
0194
0195 static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn,
0196 int offset, int len, u32 val)
0197 {
0198 struct pci_controller *hose;
0199 void volatile __iomem *addr;
0200
0201 hose = pci_bus_to_host(bus);
0202 if (!hose)
0203 return PCIBIOS_DEVICE_NOT_FOUND;
0204
0205 if (!pa_pxp_offset_valid(bus->number, devfn, offset))
0206 return PCIBIOS_BAD_REGISTER_NUMBER;
0207
0208 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
0209
0210 sb600_set_flag(bus->number);
0211
0212
0213
0214
0215
0216 switch (len) {
0217 case 1:
0218 out_8(addr, val);
0219 break;
0220 case 2:
0221 out_le16(addr, val);
0222 break;
0223 default:
0224 out_le32(addr, val);
0225 break;
0226 }
0227 return PCIBIOS_SUCCESSFUL;
0228 }
0229
0230 static struct pci_ops pa_pxp_ops = {
0231 .read = pa_pxp_read_config,
0232 .write = pa_pxp_write_config,
0233 };
0234
0235 static void __init setup_pa_pxp(struct pci_controller *hose)
0236 {
0237 hose->ops = &pa_pxp_ops;
0238 hose->cfg_data = ioremap(0xe0000000, 0x10000000);
0239 }
0240
0241 static int __init pas_add_bridge(struct device_node *dev)
0242 {
0243 struct pci_controller *hose;
0244
0245 pr_debug("Adding PCI host bridge %pOF\n", dev);
0246
0247 hose = pcibios_alloc_controller(dev);
0248 if (!hose)
0249 return -ENOMEM;
0250
0251 hose->first_busno = 0;
0252 hose->last_busno = 0xff;
0253 hose->controller_ops = pasemi_pci_controller_ops;
0254
0255 setup_pa_pxp(hose);
0256
0257 pr_info("Found PA-PXP PCI host bridge.\n");
0258
0259
0260 pci_process_bridge_OF_ranges(hose, dev, 1);
0261
0262
0263
0264
0265
0266 isa_bridge_find_early(hose);
0267
0268 return 0;
0269 }
0270
0271 void __init pas_pci_init(void)
0272 {
0273 struct device_node *np, *root;
0274 int res;
0275
0276 root = of_find_node_by_path("/");
0277 if (!root) {
0278 pr_crit("pas_pci_init: can't find root of device tree\n");
0279 return;
0280 }
0281
0282 pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
0283
0284 np = of_find_compatible_node(root, NULL, "pasemi,rootbus");
0285 if (np) {
0286 res = pas_add_bridge(np);
0287 of_node_put(np);
0288 }
0289 }
0290
0291 void __iomem *__init pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
0292 {
0293 struct pci_controller *hose;
0294
0295 hose = pci_bus_to_host(dev->bus);
0296
0297 return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset);
0298 }
0299
0300 struct pci_controller_ops pasemi_pci_controller_ops;