|
@@ -238,3 +238,118 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
|
|
|
|
|
|
cpu = smp_processor_id();
|
|
|
|
|
|
+ /* If Type1 access, must set T2 CFG. */
|
|
|
+ if (type1) {
|
|
|
+ t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
|
|
|
+ *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;
|
|
|
+ mb();
|
|
|
+ }
|
|
|
+ mb();
|
|
|
+ draina();
|
|
|
+
|
|
|
+ mcheck_expected(cpu) = 1;
|
|
|
+ mcheck_taken(cpu) = 0;
|
|
|
+ t2_mcheck_any_expected |= (1 << cpu);
|
|
|
+ mb();
|
|
|
+
|
|
|
+ /* Access configuration space. */
|
|
|
+ *(vuip)addr = value;
|
|
|
+ mb();
|
|
|
+ mb(); /* magic */
|
|
|
+
|
|
|
+ /* Wait for possible mcheck. Also, this lets other CPUs clear
|
|
|
+ their mchecks as well, as they can reliably tell when
|
|
|
+ this CPU is in the midst of handling a real mcheck via
|
|
|
+ the "taken" function. */
|
|
|
+ udelay(100);
|
|
|
+
|
|
|
+ if ((taken = mcheck_taken(cpu))) {
|
|
|
+ mcheck_taken(cpu) = 0;
|
|
|
+ t2_mcheck_last_taken |= (1 << cpu);
|
|
|
+ mb();
|
|
|
+ }
|
|
|
+ mcheck_expected(cpu) = 0;
|
|
|
+ t2_mcheck_any_expected = 0;
|
|
|
+ mb();
|
|
|
+
|
|
|
+ /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
|
|
|
+ if (type1) {
|
|
|
+ *(vulp)T2_HAE_3 = t2_cfg;
|
|
|
+ mb();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+t2_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|
|
+ int size, u32 *value)
|
|
|
+{
|
|
|
+ unsigned long addr, pci_addr;
|
|
|
+ unsigned char type1;
|
|
|
+ int shift;
|
|
|
+ long mask;
|
|
|
+
|
|
|
+ if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
|
|
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
|
|
+
|
|
|
+ mask = (size - 1) * 8;
|
|
|
+ shift = (where & 3) * 8;
|
|
|
+ addr = (pci_addr << 5) + mask + T2_CONF;
|
|
|
+ *value = conf_read(addr, type1) >> (shift);
|
|
|
+ return PCIBIOS_SUCCESSFUL;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+t2_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
|
|
|
+ u32 value)
|
|
|
+{
|
|
|
+ unsigned long addr, pci_addr;
|
|
|
+ unsigned char type1;
|
|
|
+ long mask;
|
|
|
+
|
|
|
+ if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
|
|
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
|
|
+
|
|
|
+ mask = (size - 1) * 8;
|
|
|
+ addr = (pci_addr << 5) + mask + T2_CONF;
|
|
|
+ conf_write(addr, value << ((where & 3) * 8), type1);
|
|
|
+ return PCIBIOS_SUCCESSFUL;
|
|
|
+}
|
|
|
+
|
|
|
+struct pci_ops t2_pci_ops =
|
|
|
+{
|
|
|
+ .read = t2_read_config,
|
|
|
+ .write = t2_write_config,
|
|
|
+};
|
|
|
+
|
|
|
+static void __init
|
|
|
+t2_direct_map_window1(unsigned long base, unsigned long length)
|
|
|
+{
|
|
|
+ unsigned long temp;
|
|
|
+
|
|
|
+ __direct_map_base = base;
|
|
|
+ __direct_map_size = length;
|
|
|
+
|
|
|
+ temp = (base & 0xfff00000UL) | ((base + length - 1) >> 20);
|
|
|
+ *(vulp)T2_WBASE1 = temp | 0x80000UL; /* OR in ENABLE bit */
|
|
|
+ temp = (length - 1) & 0xfff00000UL;
|
|
|
+ *(vulp)T2_WMASK1 = temp;
|
|
|
+ *(vulp)T2_TBASE1 = 0;
|
|
|
+
|
|
|
+#if DEBUG_PRINT_FINAL_SETTINGS
|
|
|
+ printk("%s: setting WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
|
|
|
+ __func__, *(vulp)T2_WBASE1, *(vulp)T2_WMASK1, *(vulp)T2_TBASE1);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+static void __init
|
|
|
+t2_sg_map_window2(struct pci_controller *hose,
|
|
|
+ unsigned long base,
|
|
|
+ unsigned long length)
|
|
|
+{
|
|
|
+ unsigned long temp;
|
|
|
+
|
|
|
+ /* Note we can only do 1 SG window, as the other is for direct, so
|
|
|
+ do an ISA SG area, especially for the floppy. */
|
|
|
+ hose->sg_isa = iommu_arena_new(hose, base, length, 0);
|
|
|
+ hose->sg_pci = NULL;
|
|
|
+
|