📄 pci_schizo.c
字号:
break; case 1: /* 16-bit IO space, 16MB */ pbm->io_space.start = a; pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); pbm->io_space.flags = IORESOURCE_IO; saw_io = 1; break; case 2: /* 32-bit MEM space, 2GB */ pbm->mem_space.start = a; pbm->mem_space.end = a + (0x80000000UL - 1UL); pbm->mem_space.flags = IORESOURCE_MEM; saw_mem = 1; break; default: break; }; } if (!saw_cfg || !saw_io || !saw_mem) { prom_printf("%s: Fatal error, missing %s PBM range.\n", pbm->name, ((!saw_cfg ? "CFG" : (!saw_io ? "IO" : "MEM")))); prom_halt(); } printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n", pbm->name, pbm->config_space, pbm->io_space.start, pbm->mem_space.start);}static void pbm_register_toplevel_resources(struct pci_controller_info *p, struct pci_pbm_info *pbm){ pbm->io_space.name = pbm->mem_space.name = pbm->name; request_resource(&ioport_resource, &pbm->io_space); request_resource(&iomem_resource, &pbm->mem_space); pci_register_legacy_regions(&pbm->io_space, &pbm->mem_space);}#define SCHIZO_STRBUF_CONTROL (0x02800UL)#define SCHIZO_STRBUF_FLUSH (0x02808UL)#define SCHIZO_STRBUF_FSYNC (0x02810UL)#define SCHIZO_STRBUF_CTXFLUSH (0x02818UL)#define SCHIZO_STRBUF_CTXMATCH (0x10000UL)static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm){ unsigned long base = pbm->pbm_regs; u64 control; if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { /* TOMATILLO lacks streaming cache. */ return; } /* SCHIZO has context flushing. */ pbm->stc.strbuf_control = base + SCHIZO_STRBUF_CONTROL; pbm->stc.strbuf_pflush = base + SCHIZO_STRBUF_FLUSH; pbm->stc.strbuf_fsync = base + SCHIZO_STRBUF_FSYNC; pbm->stc.strbuf_ctxflush = base + SCHIZO_STRBUF_CTXFLUSH; pbm->stc.strbuf_ctxmatch_base = base + SCHIZO_STRBUF_CTXMATCH; pbm->stc.strbuf_flushflag = (volatile unsigned long *) ((((unsigned long)&pbm->stc.__flushflag_buf[0]) + 63UL) & ~63UL); pbm->stc.strbuf_flushflag_pa = (unsigned long) __pa(pbm->stc.strbuf_flushflag); /* Turn off LRU locking and diag mode, enable the * streaming buffer and leave the rerun-disable * setting however OBP set it. */ control = schizo_read(pbm->stc.strbuf_control); control &= ~(SCHIZO_STRBUF_CTRL_LPTR | SCHIZO_STRBUF_CTRL_LENAB | SCHIZO_STRBUF_CTRL_DENAB); control |= SCHIZO_STRBUF_CTRL_ENAB; schizo_write(pbm->stc.strbuf_control, control); pbm->stc.strbuf_enabled = 1;}#define SCHIZO_IOMMU_CONTROL (0x00200UL)#define SCHIZO_IOMMU_TSBBASE (0x00208UL)#define SCHIZO_IOMMU_FLUSH (0x00210UL)#define SCHIZO_IOMMU_CTXFLUSH (0x00218UL)static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm){ struct pci_iommu *iommu = pbm->iommu; unsigned long i, tagbase, database; u32 vdma[2], dma_mask; u64 control; int err, tsbsize; err = prom_getproperty(pbm->prom_node, "virtual-dma", (char *)&vdma[0], sizeof(vdma)); if (err == 0 || err == -1) { /* No property, use default values. */ vdma[0] = 0xc0000000; vdma[1] = 0x40000000; } dma_mask = vdma[0]; switch (vdma[1]) { case 0x20000000: dma_mask |= 0x1fffffff; tsbsize = 64; break; case 0x40000000: dma_mask |= 0x3fffffff; tsbsize = 128; break; case 0x80000000: dma_mask |= 0x7fffffff; tsbsize = 128; break; default: prom_printf("SCHIZO: strange virtual-dma size.\n"); prom_halt(); }; /* Register addresses, SCHIZO has iommu ctx flushing. */ iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE; iommu->iommu_flush = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH; iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH; /* We use the main control/status register of SCHIZO as the write * completion register. */ iommu->write_complete_reg = pbm->controller_regs + 0x10000UL; /* * Invalidate TLB Entries. */ control = schizo_read(iommu->iommu_control); control |= SCHIZO_IOMMU_CTRL_DENAB; schizo_write(iommu->iommu_control, control); tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; for(i = 0; i < 16; i++) { schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); } /* Leave diag mode enabled for full-flushing done * in pci_iommu.c */ pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); control = schizo_read(iommu->iommu_control); control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); switch (tsbsize) { case 64: control |= SCHIZO_IOMMU_TSBSZ_64K; break; case 128: control |= SCHIZO_IOMMU_TSBSZ_128K; break; }; control |= SCHIZO_IOMMU_CTRL_ENAB; schizo_write(iommu->iommu_control, control);}#define SCHIZO_PCI_IRQ_RETRY (0x1a00UL)#define SCHIZO_IRQ_RETRY_INF 0xffUL#define SCHIZO_PCI_DIAG (0x2020UL)#define SCHIZO_PCIDIAG_D_BADECC (1UL << 10UL) /* Disable BAD ECC errors (Schizo) */#define SCHIZO_PCIDIAG_D_BYPASS (1UL << 9UL) /* Disable MMU bypass mode (Schizo/Tomatillo) */#define SCHIZO_PCIDIAG_D_TTO (1UL << 8UL) /* Disable TTO errors (Schizo/Tomatillo) */#define SCHIZO_PCIDIAG_D_RTRYARB (1UL << 7UL) /* Disable retry arbitration (Schizo) */#define SCHIZO_PCIDIAG_D_RETRY (1UL << 6UL) /* Disable retry limit (Schizo/Tomatillo) */#define SCHIZO_PCIDIAG_D_INTSYNC (1UL << 5UL) /* Disable interrupt/DMA synch (Schizo/Tomatillo) */#define SCHIZO_PCIDIAG_I_DMA_PARITY (1UL << 3UL) /* Invert DMA parity (Schizo/Tomatillo) */#define SCHIZO_PCIDIAG_I_PIOD_PARITY (1UL << 2UL) /* Invert PIO data parity (Schizo/Tomatillo) */#define SCHIZO_PCIDIAG_I_PIOA_PARITY (1UL << 1UL) /* Invert PIO address parity (Schizo/Tomatillo) */#define TOMATILLO_PCI_IOC_CSR (0x2248UL)#define TOMATILLO_IOC_PART_WPENAB 0x0000000000080000UL#define TOMATILLO_IOC_RDMULT_PENAB 0x0000000000040000UL#define TOMATILLO_IOC_RDONE_PENAB 0x0000000000020000UL#define TOMATILLO_IOC_RDLINE_PENAB 0x0000000000010000UL#define TOMATILLO_IOC_RDMULT_PLEN 0x000000000000c000UL#define TOMATILLO_IOC_RDMULT_PLEN_SHIFT 14UL#define TOMATILLO_IOC_RDONE_PLEN 0x0000000000003000UL#define TOMATILLO_IOC_RDONE_PLEN_SHIFT 12UL#define TOMATILLO_IOC_RDLINE_PLEN 0x0000000000000c00UL#define TOMATILLO_IOC_RDLINE_PLEN_SHIFT 10UL#define TOMATILLO_IOC_PREF_OFF 0x00000000000003f8UL#define TOMATILLO_IOC_PREF_OFF_SHIFT 3UL#define TOMATILLO_IOC_RDMULT_CPENAB 0x0000000000000004UL#define TOMATILLO_IOC_RDONE_CPENAB 0x0000000000000002UL#define TOMATILLO_IOC_RDLINE_CPENAB 0x0000000000000001UL#define TOMATILLO_PCI_IOC_TDIAG (0x2250UL)#define TOMATILLO_PCI_IOC_DDIAG (0x2290UL)static void schizo_pbm_hw_init(struct pci_pbm_info *pbm){ u64 tmp; schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); /* Enable arbiter for all PCI slots. */ tmp |= 0xff; if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO && pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; if (!prom_getbool(pbm->prom_node, "no-bus-parking")) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO && pbm->chip_version <= 0x1) tmp |= SCHIZO_PCICTRL_DTO_INT; else tmp &= ~SCHIZO_PCICTRL_DTO_INT; if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) tmp |= (SCHIZO_PCICTRL_MRM_PREF | SCHIZO_PCICTRL_RDO_PREF | SCHIZO_PCICTRL_RDL_PREF); schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG); tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | SCHIZO_PCIDIAG_D_RETRY | SCHIZO_PCIDIAG_D_INTSYNC); schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp); if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { /* Clear prefetch lengths to workaround a bug in * Jalapeno... */ tmp = (TOMATILLO_IOC_PART_WPENAB | (1 << TOMATILLO_IOC_PREF_OFF_SHIFT) | TOMATILLO_IOC_RDMULT_CPENAB | TOMATILLO_IOC_RDONE_CPENAB | TOMATILLO_IOC_RDLINE_CPENAB); schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR, tmp); }}static void schizo_pbm_init(struct pci_controller_info *p, int prom_node, u32 portid, int chip_type){ struct linux_prom64_registers pr_regs[4]; unsigned int busrange[2]; struct pci_pbm_info *pbm; const char *chipset_name; u32 ino_bitmap[2]; int is_pbm_a; int err; switch (chip_type) { case PBM_CHIP_TYPE_TOMATILLO: chipset_name = "TOMATILLO"; break; case PBM_CHIP_TYPE_SCHIZO_PLUS: chipset_name = "SCHIZO+"; break; case PBM_CHIP_TYPE_SCHIZO: default: chipset_name = "SCHIZO"; break; }; /* For SCHIZO, three OBP regs: * 1) PBM controller regs * 2) Schizo front-end controller regs (same for both PBMs) * 3) PBM PCI config space * * For TOMATILLO, four OBP regs: * 1) PBM controller regs * 2) Tomatillo front-end controller regs * 3) PBM PCI config space * 4) Ichip regs */ err = prom_getproperty(prom_node, "reg", (char *)&pr_regs[0], sizeof(pr_regs)); if (err == 0 || err == -1) { prom_printf("%s: Fatal error, no reg property.\n", chipset_name); prom_halt(); } is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); if (is_pbm_a) pbm = &p->pbm_A; else pbm = &p->pbm_B; pbm->portid = portid; pbm->parent = p; pbm->prom_node = prom_node; pbm->pci_first_slot = 1; pbm->chip_type = chip_type; pbm->chip_version = prom_getintdefault(prom_node, "version#", 0); pbm->chip_revision = prom_getintdefault(prom_node, "module-revision#", 0); pbm->pbm_regs = pr_regs[0].phys_addr; pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; if (chip_type == PBM_CHIP_TYPE_TOMATILLO) pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; sprintf(pbm->name, (chip_type == PBM_CHIP_TYPE_TOMATILLO ? "TOMATILLO%d PBM%c" : "SCHIZO%d PBM%c"), p->index, (pbm == &p->pbm_A ? 'A' : 'B')); printk("%s: ver[%x:%x], portid %x, " "cregs[%lx] pregs[%lx]\n", pbm->name, pbm->chip_version, pbm->chip_revision, pbm->portid, pbm->controller_regs, pbm->pbm_regs); schizo_pbm_hw_init(pbm); prom_getstring(prom_node, "name", pbm->prom_name, sizeof(pbm->prom_name)); err = prom_getproperty(prom_node, "ranges", (char *) pbm->pbm_ranges, sizeof(pbm->pbm_ranges)); if (err == 0 || err == -1) { prom_printf("%s: Fatal error, no ranges property.\n", pbm->name); prom_halt(); } pbm->num_pbm_ranges = (err / sizeof(struct linux_prom_pci_ranges)); schizo_determine_mem_io_space(pbm); pbm_register_toplevel_resources(p, pbm); err = prom_getproperty(prom_node, "interrupt-map", (char *)pbm->pbm_intmap, sizeof(pbm->pbm_intmap)); if (err != -1) { pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); err = prom_getproperty(prom_node, "interrupt-map-mask", (char *)&pbm->pbm_intmask, sizeof(pbm->pbm_intmask)); if (err == -1) { prom_printf("%s: Fatal error, no " "interrupt-map-mask.\n", pbm->name); prom_halt(); } } else { pbm->num_pbm_intmap = 0; memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } err = prom_getproperty(prom_node, "ino-bitmap", (char *) &ino_bitmap[0], sizeof(ino_bitmap)); if (err == 0 || err == -1) { prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name); prom_halt(); } pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | ((u64)ino_bitmap[0] << 0UL)); err = prom_getproperty(prom_node, "bus-range", (char *)&busrange[0], sizeof(busrange)); if (err == 0 || err == -1) { prom_printf("%s: Fatal error, no bus-range.\n", pbm->name); prom_h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -