|
@@ -193,3 +193,177 @@ wildfire_hardware_probe(void)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
hard_qbb = (temp >> 8) & 7;
|
|
hard_qbb = (temp >> 8) & 7;
|
|
|
|
+ soft_qbb = (temp >> 4) & 7;
|
|
|
|
+
|
|
|
|
+ /* Init the HW configuration variables. */
|
|
|
|
+ wildfire_hard_qbb_mask = (1 << hard_qbb);
|
|
|
|
+ wildfire_soft_qbb_mask = (1 << soft_qbb);
|
|
|
|
+
|
|
|
|
+ wildfire_gp_mask = 0;
|
|
|
|
+ wildfire_hs_mask = 0;
|
|
|
|
+ wildfire_iop_mask = 0;
|
|
|
|
+ wildfire_ior_mask = 0;
|
|
|
|
+ wildfire_pca_mask = 0;
|
|
|
|
+
|
|
|
|
+ wildfire_cpu_mask = 0;
|
|
|
|
+ wildfire_mem_mask = 0;
|
|
|
|
+
|
|
|
|
+ memset(wildfire_hard_qbb_map, QBB_MAP_EMPTY, WILDFIRE_MAX_QBB);
|
|
|
|
+ memset(wildfire_soft_qbb_map, QBB_MAP_EMPTY, WILDFIRE_MAX_QBB);
|
|
|
|
+
|
|
|
|
+ /* First, determine which QBBs are present. */
|
|
|
|
+ qsa = WILDFIRE_qsa(soft_qbb);
|
|
|
|
+
|
|
|
|
+ temp = qsa->qsa_qbb_id.csr;
|
|
|
|
+#if 0
|
|
|
|
+ printk(KERN_ERR "QSA_QBB_ID at base %p is 0x%lx\n", qsa, temp);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ if (temp & 0x40) /* Is there an HS? */
|
|
|
|
+ wildfire_hs_mask = 1;
|
|
|
|
+
|
|
|
|
+ if (temp & 0x20) { /* Is there a GP? */
|
|
|
|
+ gp = WILDFIRE_gp(soft_qbb);
|
|
|
|
+ temp = 0;
|
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
|
+ temp |= gp->gpa_qbb_map[i].csr << (i * 8);
|
|
|
|
+#if 0
|
|
|
|
+ printk(KERN_ERR "GPA_QBB_MAP[%d] at base %p is 0x%lx\n",
|
|
|
|
+ i, gp, temp);
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (hard_qbb = 0; hard_qbb < WILDFIRE_MAX_QBB; hard_qbb++) {
|
|
|
|
+ if (temp & 8) { /* Is there a QBB? */
|
|
|
|
+ soft_qbb = temp & 7;
|
|
|
|
+ wildfire_hard_qbb_mask |= (1 << hard_qbb);
|
|
|
|
+ wildfire_soft_qbb_mask |= (1 << soft_qbb);
|
|
|
|
+ }
|
|
|
|
+ temp >>= 4;
|
|
|
|
+ }
|
|
|
|
+ wildfire_gp_mask = wildfire_soft_qbb_mask;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Next determine each QBBs resources. */
|
|
|
|
+ for (soft_qbb = 0; soft_qbb < WILDFIRE_MAX_QBB; soft_qbb++) {
|
|
|
|
+ if (WILDFIRE_QBB_EXISTS(soft_qbb)) {
|
|
|
|
+ qsd = WILDFIRE_qsd(soft_qbb);
|
|
|
|
+ temp = qsd->qsd_whami.csr;
|
|
|
|
+#if 0
|
|
|
|
+ printk(KERN_ERR "QSD_WHAMI at base %p is 0x%lx\n", qsd, temp);
|
|
|
|
+#endif
|
|
|
|
+ hard_qbb = (temp >> 8) & 7;
|
|
|
|
+ wildfire_hard_qbb_map[hard_qbb] = soft_qbb;
|
|
|
|
+ wildfire_soft_qbb_map[soft_qbb] = hard_qbb;
|
|
|
|
+
|
|
|
|
+ qsa = WILDFIRE_qsa(soft_qbb);
|
|
|
|
+ temp = qsa->qsa_qbb_pop[0].csr;
|
|
|
|
+#if 0
|
|
|
|
+ printk(KERN_ERR "QSA_QBB_POP_0 at base %p is 0x%lx\n", qsa, temp);
|
|
|
|
+#endif
|
|
|
|
+ wildfire_cpu_mask |= ((temp >> 0) & 0xf) << (soft_qbb << 2);
|
|
|
|
+ wildfire_mem_mask |= ((temp >> 4) & 0xf) << (soft_qbb << 2);
|
|
|
|
+
|
|
|
|
+ temp = qsa->qsa_qbb_pop[1].csr;
|
|
|
|
+#if 0
|
|
|
|
+ printk(KERN_ERR "QSA_QBB_POP_1 at base %p is 0x%lx\n", qsa, temp);
|
|
|
|
+#endif
|
|
|
|
+ wildfire_iop_mask |= (1 << soft_qbb);
|
|
|
|
+ wildfire_ior_mask |= ((temp >> 4) & 0xf) << (soft_qbb << 2);
|
|
|
|
+
|
|
|
|
+ temp = qsa->qsa_qbb_id.csr;
|
|
|
|
+#if 0
|
|
|
|
+ printk(KERN_ERR "QSA_QBB_ID at %p is 0x%lx\n", qsa, temp);
|
|
|
|
+#endif
|
|
|
|
+ if (temp & 0x20)
|
|
|
|
+ wildfire_gp_mask |= (1 << soft_qbb);
|
|
|
|
+
|
|
|
|
+ /* Probe for PCA existence here. */
|
|
|
|
+ for (i = 0; i < WILDFIRE_PCA_PER_QBB; i++) {
|
|
|
|
+ iop = WILDFIRE_iop(soft_qbb);
|
|
|
|
+ ne = WILDFIRE_ne(soft_qbb, i);
|
|
|
|
+ fe = WILDFIRE_fe(soft_qbb, i);
|
|
|
|
+
|
|
|
|
+ if ((iop->iop_hose[i].init.csr & 1) == 1 &&
|
|
|
|
+ ((ne->ne_what_am_i.csr & 0xf00000300UL) == 0x100000300UL) &&
|
|
|
|
+ ((fe->fe_what_am_i.csr & 0xf00000300UL) == 0x100000200UL))
|
|
|
|
+ {
|
|
|
|
+ wildfire_pca_mask |= 1 << ((soft_qbb << 2) + i);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#if DEBUG_DUMP_CONFIG
|
|
|
|
+ wildfire_dump_hardware_config();
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void __init
|
|
|
|
+wildfire_init_arch(void)
|
|
|
|
+{
|
|
|
|
+ int qbbno;
|
|
|
|
+
|
|
|
|
+ /* With multiple PCI buses, we play with I/O as physical addrs. */
|
|
|
|
+ ioport_resource.end = ~0UL;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* Probe the hardware for info about configuration. */
|
|
|
|
+ wildfire_hardware_probe();
|
|
|
|
+
|
|
|
|
+ /* Now init all the found QBBs. */
|
|
|
|
+ for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
|
|
|
|
+ wildfire_init_qbb(qbbno);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Normal direct PCI DMA mapping. */
|
|
|
|
+ __direct_map_base = 0x40000000UL;
|
|
|
|
+ __direct_map_size = 0x80000000UL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+wildfire_machine_check(unsigned long vector, unsigned long la_ptr)
|
|
|
|
+{
|
|
|
|
+ mb();
|
|
|
|
+ mb(); /* magic */
|
|
|
|
+ draina();
|
|
|
|
+ /* FIXME: clear pci errors */
|
|
|
|
+ wrmces(0x7);
|
|
|
|
+ mb();
|
|
|
|
+
|
|
|
|
+ process_mcheck_info(vector, la_ptr, "WILDFIRE",
|
|
|
|
+ mcheck_expected(smp_processor_id()));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+wildfire_kill_arch(int mode)
|
|
|
|
+{
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+wildfire_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
|
|
|
|
+{
|
|
|
|
+ int qbbno = hose->index >> 3;
|
|
|
|
+ int hoseno = hose->index & 7;
|
|
|
|
+ wildfire_pci *pci = WILDFIRE_pci(qbbno, hoseno);
|
|
|
|
+
|
|
|
|
+ mb();
|
|
|
|
+ pci->pci_flush_tlb.csr; /* reading does the trick */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
|
|
|
|
+ unsigned long *pci_addr, unsigned char *type1)
|
|
|
|
+{
|
|
|
|
+ struct pci_controller *hose = pbus->sysdata;
|
|
|
|
+ unsigned long addr;
|
|
|
|
+ u8 bus = pbus->number;
|
|
|
|
+
|
|
|
|
+ DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
|
|
|
|
+ "pci_addr=0x%p, type1=0x%p)\n",
|
|
|
|
+ bus, device_fn, where, pci_addr, type1));
|
|
|
|
+
|
|
|
|
+ if (!pbus->parent) /* No parent means peer PCI bus. */
|
|
|
|
+ bus = 0;
|
|
|
|
+ *type1 = (bus != 0);
|
|
|
|
+
|