📄 pci.c
字号:
/* Outbound window 1 (PCIX/PCIE memory window) */ /* 32 bit Address Space */ __raw_writel(0x0, IOP13XX_ATUX_OUMWTVR1); /* PA[35:32] */ __raw_writel(IOP13XX_ATUX_OUMBAR_ENABLE | IOP13XX_PCIX_MEM_PHYS_OFFSET >> 32, IOP13XX_ATUX_OUMBAR1); /* Setup the I/O Bar * A[35-16] in 31-12 */ __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000, IOP13XX_ATUX_OIOBAR); __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR); /* clear startup errors */ iop13xx_atux_pci_status(1); /* OIOBAR function number */ reg_val = __raw_readl(IOP13XX_ATUX_OIOBAR); reg_val &= ~0x7; reg_val |= func; __raw_writel(reg_val, IOP13XX_ATUX_OIOBAR); /* OUMBAR function numbers */ reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0); reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << IOP13XX_ATU_OUMBAR_FUNC_NUM); reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1); reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << IOP13XX_ATU_OUMBAR_FUNC_NUM); reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2); reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << IOP13XX_ATU_OUMBAR_FUNC_NUM); reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3); reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << IOP13XX_ATU_OUMBAR_FUNC_NUM); reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3); /* Enable inbound and outbound cycles */ reg_val = __raw_readw(IOP13XX_ATUX_ATUCMD); reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; __raw_writew(reg_val, IOP13XX_ATUX_ATUCMD); reg_val = __raw_readl(IOP13XX_ATUX_ATUCR); reg_val |= IOP13XX_ATUX_ATUCR_OUT_EN; __raw_writel(reg_val, IOP13XX_ATUX_ATUCR);}void __init iop13xx_atux_disable(void){ u32 reg_val; __raw_writew(0x0, IOP13XX_ATUX_ATUCMD); __raw_writel(0x0, IOP13XX_ATUX_ATUCR); /* wait for cycles to quiesce */ while (__raw_readl(IOP13XX_ATUX_PCSR) & (IOP13XX_ATUX_PCSR_OUT_Q_BUSY | IOP13XX_ATUX_PCSR_IN_Q_BUSY)) cpu_relax(); /* BAR 0 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUX_IAUBAR0); __raw_writel(0x0, IOP13XX_ATUX_IABAR0); __raw_writel(0x0, IOP13XX_ATUX_IAUTVR0); __raw_writel(0x0, IOP13XX_ATUX_IATVR0); __raw_writel(0x0, IOP13XX_ATUX_IALR0); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0); reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0); /* BAR 1 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1); __raw_writel(0x0, IOP13XX_ATUX_IABAR1); __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1); __raw_writel(0x0, IOP13XX_ATUX_IATVR1); __raw_writel(0x0, IOP13XX_ATUX_IALR1); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1); reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1); /* BAR 2 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUX_IAUBAR2); __raw_writel(0x0, IOP13XX_ATUX_IABAR2); __raw_writel(0x0, IOP13XX_ATUX_IAUTVR2); __raw_writel(0x0, IOP13XX_ATUX_IATVR2); __raw_writel(0x0, IOP13XX_ATUX_IALR2); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2); reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2); /* BAR 3 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUX_IAUBAR3); __raw_writel(0x0, IOP13XX_ATUX_IABAR3); __raw_writel(0x0, IOP13XX_ATUX_IAUTVR3); __raw_writel(0x0, IOP13XX_ATUX_IATVR3); __raw_writel(0x0, IOP13XX_ATUX_IALR3); reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3); reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3); /* Setup the I/O Bar * A[35-16] in 31-12 */ __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000, IOP13XX_ATUX_OIOBAR); __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR);}void __init iop13xx_set_atu_mmr_bases(void){ /* Based on ESSR0, determine the ATU X/E offsets */ switch(__raw_readl(IOP13XX_ESSR0) & (IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX)) { /* both asserted */ case 0: iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET; iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; break; /* IOP13XX_CONTROLLER_ONLY = deasserted * IOP13XX_INTERFACE_SEL_PCIX = asserted */ case IOP13XX_CONTROLLER_ONLY: iop13xx_atux_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET; iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; break; /* IOP13XX_CONTROLLER_ONLY = asserted * IOP13XX_INTERFACE_SEL_PCIX = deasserted */ case IOP13XX_INTERFACE_SEL_PCIX: iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET; iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; break; /* both deasserted */ case IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX: iop13xx_atux_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; iop13xx_atue_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET; break; default: BUG(); }}void __init iop13xx_atu_select(struct hw_pci *plat_pci){ int i; /* set system defaults * note: if "iop13xx_init_atu=" is specified this autodetect * sequence will be bypassed */ if (init_atu == IOP13XX_INIT_ATU_DEFAULT) { /* check for single/dual interface */ if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) { /* ATUE must be present check the device id * to see if ATUX is present. */ init_atu |= IOP13XX_INIT_ATU_ATUE; switch (__raw_readw(IOP13XX_ATUE_DID) & 0xf0) { case 0x70: case 0x80: case 0xc0: init_atu |= IOP13XX_INIT_ATU_ATUX; break; } } else { /* ATUX must be present check the device id * to see if ATUE is present. */ init_atu |= IOP13XX_INIT_ATU_ATUX; switch (__raw_readw(IOP13XX_ATUX_DID) & 0xf0) { case 0x70: case 0x80: case 0xc0: init_atu |= IOP13XX_INIT_ATU_ATUE; break; } } /* check central resource and root complex capability */ if (init_atu & IOP13XX_INIT_ATU_ATUX) if (!(__raw_readl(IOP13XX_ATUX_PCSR) & IOP13XX_ATUX_PCSR_CENTRAL_RES)) init_atu &= ~IOP13XX_INIT_ATU_ATUX; if (init_atu & IOP13XX_INIT_ATU_ATUE) if (__raw_readl(IOP13XX_ATUE_PCSR) & IOP13XX_ATUE_PCSR_END_POINT) init_atu &= ~IOP13XX_INIT_ATU_ATUE; } for (i = 0; i < 2; i++) { if((init_atu & (1 << i)) == (1 << i)) plat_pci->nr_controllers++; }}void __init iop13xx_pci_init(void){ /* clear pre-existing south bridge errors */ __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR); /* Setup the Min Address for PCI memory... */ iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA; /* if Linux is given control of an ATU * clear out its prior configuration, * otherwise do not touch the registers */ if (init_atu & IOP13XX_INIT_ATU_ATUE) { iop13xx_atue_disable(); iop13xx_atue_setup(); } if (init_atu & IOP13XX_INIT_ATU_ATUX) { iop13xx_atux_disable(); iop13xx_atux_setup(); } hook_fault_code(16+6, iop13xx_pci_abort, SIGBUS, "imprecise external abort");}/* initialize the pci memory space. handle any combination of * atue and atux enabled/disabled */int iop13xx_pci_setup(int nr, struct pci_sys_data *sys){ struct resource *res; int which_atu; u32 pcixsr, pcsr; if (nr > 1) return 0; res = kcalloc(2, sizeof(struct resource), GFP_KERNEL); if (!res) panic("PCI: unable to alloc resources"); /* 'nr' assumptions: * ATUX is always 0 * ATUE is 1 when ATUX is also enabled * ATUE is 0 when ATUX is disabled */ switch(init_atu) { case IOP13XX_INIT_ATU_ATUX: which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX; break; case IOP13XX_INIT_ATU_ATUE: which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE; break; case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE): which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX; break; default: which_atu = 0; } if (!which_atu) return 0; switch(which_atu) { case IOP13XX_INIT_ATU_ATUX: pcixsr = __raw_readl(IOP13XX_ATUX_PCIXSR); pcixsr &= ~0xffff; pcixsr |= sys->busnr << IOP13XX_ATUX_PCIXSR_BUS_NUM | 0 << IOP13XX_ATUX_PCIXSR_DEV_NUM | iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX) << IOP13XX_ATUX_PCIXSR_FUNC_NUM; __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR); res[0].start = IOP13XX_PCIX_LOWER_IO_PA + IOP13XX_PCIX_IO_BUS_OFFSET; res[0].end = IOP13XX_PCIX_UPPER_IO_PA; res[0].name = "IQ81340 ATUX PCI I/O Space"; res[0].flags = IORESOURCE_IO; res[1].start = IOP13XX_PCIX_LOWER_MEM_RA; res[1].end = IOP13XX_PCIX_UPPER_MEM_RA; res[1].name = "IQ81340 ATUX PCI Memory Space"; res[1].flags = IORESOURCE_MEM; sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET; sys->io_offset = IOP13XX_PCIX_LOWER_IO_PA; break; case IOP13XX_INIT_ATU_ATUE: /* Note: the function number field in the PCSR is ro */ pcsr = __raw_readl(IOP13XX_ATUE_PCSR); pcsr &= ~(0xfff8 << 16); pcsr |= sys->busnr << IOP13XX_ATUE_PCSR_BUS_NUM | 0 << IOP13XX_ATUE_PCSR_DEV_NUM; __raw_writel(pcsr, IOP13XX_ATUE_PCSR); res[0].start = IOP13XX_PCIE_LOWER_IO_PA + IOP13XX_PCIE_IO_BUS_OFFSET; res[0].end = IOP13XX_PCIE_UPPER_IO_PA; res[0].name = "IQ81340 ATUE PCI I/O Space"; res[0].flags = IORESOURCE_IO; res[1].start = IOP13XX_PCIE_LOWER_MEM_RA; res[1].end = IOP13XX_PCIE_UPPER_MEM_RA; res[1].name = "IQ81340 ATUE PCI Memory Space"; res[1].flags = IORESOURCE_MEM; sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET; sys->io_offset = IOP13XX_PCIE_LOWER_IO_PA; sys->map_irq = iop13xx_pcie_map_irq; break; default: return 0; } request_resource(&ioport_resource, &res[0]); request_resource(&iomem_resource, &res[1]); sys->resource[0] = &res[0]; sys->resource[1] = &res[1]; sys->resource[2] = NULL; return 1;}u16 iop13xx_dev_id(void){ if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) return __raw_readw(IOP13XX_ATUE_DID); else return __raw_readw(IOP13XX_ATUX_DID);}static int __init iop13xx_init_atu_setup(char *str){ init_atu = IOP13XX_INIT_ATU_NONE; if (str) { while (*str != '\0') { switch (*str) { case 'x': case 'X': init_atu |= IOP13XX_INIT_ATU_ATUX; init_atu &= ~IOP13XX_INIT_ATU_NONE; break; case 'e': case 'E': init_atu |= IOP13XX_INIT_ATU_ATUE; init_atu &= ~IOP13XX_INIT_ATU_NONE; break; case ',': case '=': break; default: PRINTK("\"iop13xx_init_atu\" malformed at " "character: \'%c\'", *str); *(str + 1) = '\0'; init_atu = IOP13XX_INIT_ATU_DEFAULT; } str++; } } return 1;}__setup("iop13xx_init_atu", iop13xx_init_atu_setup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -