|
@@ -325,3 +325,94 @@ apecs_init_arch(void)
|
|
|
{
|
|
|
struct pci_controller *hose;
|
|
|
|
|
|
+ /*
|
|
|
+ * Create our single hose.
|
|
|
+ */
|
|
|
+
|
|
|
+ pci_isa_hose = hose = alloc_pci_controller();
|
|
|
+ hose->io_space = &ioport_resource;
|
|
|
+ hose->mem_space = &iomem_resource;
|
|
|
+ hose->index = 0;
|
|
|
+
|
|
|
+ hose->sparse_mem_base = APECS_SPARSE_MEM - IDENT_ADDR;
|
|
|
+ hose->dense_mem_base = APECS_DENSE_MEM - IDENT_ADDR;
|
|
|
+ hose->sparse_io_base = APECS_IO - IDENT_ADDR;
|
|
|
+ hose->dense_io_base = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set up the PCI to main memory translation windows.
|
|
|
+ *
|
|
|
+ * Window 1 is direct access 1GB at 1GB
|
|
|
+ * Window 2 is scatter-gather 8MB at 8MB (for isa)
|
|
|
+ */
|
|
|
+ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
|
|
|
+ hose->sg_pci = NULL;
|
|
|
+ __direct_map_base = 0x40000000;
|
|
|
+ __direct_map_size = 0x40000000;
|
|
|
+
|
|
|
+ *(vuip)APECS_IOC_PB1R = __direct_map_base | 0x00080000;
|
|
|
+ *(vuip)APECS_IOC_PM1R = (__direct_map_size - 1) & 0xfff00000U;
|
|
|
+ *(vuip)APECS_IOC_TB1R = 0;
|
|
|
+
|
|
|
+ *(vuip)APECS_IOC_PB2R = hose->sg_isa->dma_base | 0x000c0000;
|
|
|
+ *(vuip)APECS_IOC_PM2R = (hose->sg_isa->size - 1) & 0xfff00000;
|
|
|
+ *(vuip)APECS_IOC_TB2R = virt_to_phys(hose->sg_isa->ptes) >> 1;
|
|
|
+
|
|
|
+ apecs_pci_tbi(hose, 0, -1);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Finally, clear the HAXR2 register, which gets used
|
|
|
+ * for PCI Config Space accesses. That is the way
|
|
|
+ * we want to use it, and we do not want to depend on
|
|
|
+ * what ARC or SRM might have left behind...
|
|
|
+ */
|
|
|
+ *(vuip)APECS_IOC_HAXR2 = 0;
|
|
|
+ mb();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+apecs_pci_clr_err(void)
|
|
|
+{
|
|
|
+ unsigned int jd;
|
|
|
+
|
|
|
+ jd = *(vuip)APECS_IOC_DCSR;
|
|
|
+ if (jd & 0xffe0L) {
|
|
|
+ *(vuip)APECS_IOC_SEAR;
|
|
|
+ *(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
|
|
|
+ mb();
|
|
|
+ *(vuip)APECS_IOC_DCSR;
|
|
|
+ }
|
|
|
+ *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
|
|
|
+ mb();
|
|
|
+ *(vuip)APECS_IOC_TBIA;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+apecs_machine_check(unsigned long vector, unsigned long la_ptr)
|
|
|
+{
|
|
|
+ struct el_common *mchk_header;
|
|
|
+ struct el_apecs_procdata *mchk_procdata;
|
|
|
+ struct el_apecs_sysdata_mcheck *mchk_sysdata;
|
|
|
+
|
|
|
+ mchk_header = (struct el_common *)la_ptr;
|
|
|
+
|
|
|
+ mchk_procdata = (struct el_apecs_procdata *)
|
|
|
+ (la_ptr + mchk_header->proc_offset
|
|
|
+ - sizeof(mchk_procdata->paltemp));
|
|
|
+
|
|
|
+ mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
|
|
|
+ (la_ptr + mchk_header->sys_offset);
|
|
|
+
|
|
|
+
|
|
|
+ /* Clear the error before any reporting. */
|
|
|
+ mb();
|
|
|
+ mb(); /* magic */
|
|
|
+ draina();
|
|
|
+ apecs_pci_clr_err();
|
|
|
+ wrmces(0x7); /* reset machine check pending flag */
|
|
|
+ mb();
|
|
|
+
|
|
|
+ process_mcheck_info(vector, la_ptr, "APECS",
|
|
|
+ (mcheck_expected(0)
|
|
|
+ && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
|
|
|
+}
|