|
@@ -146,3 +146,98 @@ tsunami_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|
|
if (mk_conf_addr(bus, devfn, where, &addr, &type1))
|
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
|
|
|
|
|
+ switch (size) {
|
|
|
+ case 1:
|
|
|
+ __kernel_stb(value, *(vucp)addr);
|
|
|
+ mb();
|
|
|
+ __kernel_ldbu(*(vucp)addr);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ __kernel_stw(value, *(vusp)addr);
|
|
|
+ mb();
|
|
|
+ __kernel_ldwu(*(vusp)addr);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ *(vuip)addr = value;
|
|
|
+ mb();
|
|
|
+ *(vuip)addr;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return PCIBIOS_SUCCESSFUL;
|
|
|
+}
|
|
|
+
|
|
|
+struct pci_ops tsunami_pci_ops =
|
|
|
+{
|
|
|
+ .read = tsunami_read_config,
|
|
|
+ .write = tsunami_write_config,
|
|
|
+};
|
|
|
+
|
|
|
+void
|
|
|
+tsunami_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
|
|
|
+{
|
|
|
+ tsunami_pchip *pchip = hose->index ? TSUNAMI_pchip1 : TSUNAMI_pchip0;
|
|
|
+ volatile unsigned long *csr;
|
|
|
+ unsigned long value;
|
|
|
+
|
|
|
+ /* We can invalidate up to 8 tlb entries in a go. The flush
|
|
|
+ matches against <31:16> in the pci address. */
|
|
|
+ csr = &pchip->tlbia.csr;
|
|
|
+ if (((start ^ end) & 0xffff0000) == 0)
|
|
|
+ csr = &pchip->tlbiv.csr;
|
|
|
+
|
|
|
+ /* For TBIA, it doesn't matter what value we write. For TBI,
|
|
|
+ it's the shifted tag bits. */
|
|
|
+ value = (start & 0xffff0000) >> 12;
|
|
|
+
|
|
|
+ *csr = value;
|
|
|
+ mb();
|
|
|
+ *csr;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
|
|
|
+static long __init
|
|
|
+tsunami_probe_read(volatile unsigned long *vaddr)
|
|
|
+{
|
|
|
+ long dont_care, probe_result;
|
|
|
+ int cpu = smp_processor_id();
|
|
|
+ int s = swpipl(IPL_MCHECK - 1);
|
|
|
+
|
|
|
+ mcheck_taken(cpu) = 0;
|
|
|
+ mcheck_expected(cpu) = 1;
|
|
|
+ mb();
|
|
|
+ dont_care = *vaddr;
|
|
|
+ draina();
|
|
|
+ mcheck_expected(cpu) = 0;
|
|
|
+ probe_result = !mcheck_taken(cpu);
|
|
|
+ mcheck_taken(cpu) = 0;
|
|
|
+ setipl(s);
|
|
|
+
|
|
|
+ printk("dont_care == 0x%lx\n", dont_care);
|
|
|
+
|
|
|
+ return probe_result;
|
|
|
+}
|
|
|
+
|
|
|
+static long __init
|
|
|
+tsunami_probe_write(volatile unsigned long *vaddr)
|
|
|
+{
|
|
|
+ long true_contents, probe_result = 1;
|
|
|
+
|
|
|
+ TSUNAMI_cchip->misc.csr |= (1L << 28); /* clear NXM... */
|
|
|
+ true_contents = *vaddr;
|
|
|
+ *vaddr = 0;
|
|
|
+ draina();
|
|
|
+ if (TSUNAMI_cchip->misc.csr & (1L << 28)) {
|
|
|
+ int source = (TSUNAMI_cchip->misc.csr >> 29) & 7;
|
|
|
+ TSUNAMI_cchip->misc.csr |= (1L << 28); /* ...and unlock NXS. */
|
|
|
+ probe_result = 0;
|
|
|
+ printk("tsunami_probe_write: unit %d at 0x%016lx\n", source,
|
|
|
+ (unsigned long)vaddr);
|
|
|
+ }
|
|
|
+ if (probe_result)
|
|
|
+ *vaddr = true_contents;
|
|
|
+ return probe_result;
|
|
|
+}
|
|
|
+#else
|
|
|
+#define tsunami_probe_read(ADDR) 1
|
|
|
+#endif /* NXM_MACHINE_CHECKS_ON_TSUNAMI */
|