📄 pci.c
字号:
PRINTK("\t\t\tPCI-E error: ATUE_PIE_MSK %#08x", __raw_readl(IOP13XX_ATUE_PIE_MSK)); BUG(); } if(clear) __raw_writel(status, IOP13XX_ATUE_PIE_STS); } } return err;}static intiop13xx_pcie_map_irq(struct pci_dev *dev, u8 idsel, u8 pin){ WARN_ON(idsel != 0); switch (pin) { case 1: return ATUE_INTA; case 2: return ATUE_INTB; case 3: return ATUE_INTC; case 4: return ATUE_INTD; default: return -1; }}static u32 iop13xx_atue_read(unsigned long addr){ u32 val; __raw_writel(addr, IOP13XX_ATUE_OCCAR); val = __raw_readl(IOP13XX_ATUE_OCCDR); rmb(); return val;}/* The read routines must check the error status of the last configuration * cycle. If there was an error, the routine returns all hex f's. */static intiop13xx_atue_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value){ u32 val; unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where); /* Hide device numbers > 0 on the local PCI-E bus (Type 0 access) */ if (!PCI_SLOT(devfn) || (addr & 1)) { val = iop13xx_atue_read(addr) >> ((where & 3) * 8); if( iop13xx_atue_pci_status(1) || is_atue_occdr_error() ) { __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR); val = 0xffffffff; } PRINTK("addr=%#0lx, val=%#010x", addr, val); } else val = 0xffffffff; *value = val; return PCIBIOS_SUCCESSFUL;}static intiop13xx_atue_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value){ unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where); u32 val; if (size != 4) { val = iop13xx_atue_read(addr); if (!iop13xx_atue_pci_status(1) == 0) return PCIBIOS_SUCCESSFUL; where = (where & 3) * 8; if (size == 1) val &= ~(0xff << where); else val &= ~(0xffff << where); __raw_writel(val | value << where, IOP13XX_ATUE_OCCDR); } else { __raw_writel(addr, IOP13XX_ATUE_OCCAR); __raw_writel(value, IOP13XX_ATUE_OCCDR); } return PCIBIOS_SUCCESSFUL;}static struct pci_ops iop13xx_atue_ops = { .read = iop13xx_atue_read_config, .write = iop13xx_atue_write_config,};/* When a PCI device does not exist during config cycles, the XScale gets a * bus error instead of returning 0xffffffff. We can't rely on the ATU status * bits to tell us that it was indeed a configuration cycle that caused this * error especially in the case when the ATUE link is down. Instead we rely * on data from the south XSI bridge to validate the abort */intiop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs){ PRINTK("Data abort: address = 0x%08lx " "fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx", addr, fsr, regs->ARM_pc, regs->ARM_lr); PRINTK("IOP13XX_XBG_BECSR: %#10x", __raw_readl(IOP13XX_XBG_BECSR)); PRINTK("IOP13XX_XBG_BERAR: %#10x", __raw_readl(IOP13XX_XBG_BERAR)); PRINTK("IOP13XX_XBG_BERUAR: %#10x", __raw_readl(IOP13XX_XBG_BERUAR)); /* If it was an imprecise abort, then we need to correct the * return address to be _after_ the instruction. */ if (fsr & (1 << 10)) regs->ARM_pc += 4; if (is_atue_occdr_error() || is_atux_occdr_error()) return 0; else return 1;}/* Scan an IOP13XX PCI bus. nr selects which ATU we use. */struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys){ int which_atu; struct pci_bus *bus = NULL; 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) { BUG(); return NULL; } switch (which_atu) { case IOP13XX_INIT_ATU_ATUX: if (time_after_eq(jiffies + msecs_to_jiffies(1000), atux_trhfa_timeout)) /* ensure not wrap */ while(time_before(jiffies, atux_trhfa_timeout)) udelay(100); bus = pci_bus_atux = pci_scan_bus(sys->busnr, &iop13xx_atux_ops, sys); break; case IOP13XX_INIT_ATU_ATUE: bus = pci_bus_atue = pci_scan_bus(sys->busnr, &iop13xx_atue_ops, sys); break; } return bus;}/* This function is called from iop13xx_pci_init() after assigning valid * values to iop13xx_atue_pmmr_offset. This is the location for common * setup of ATUE for all IOP13XX implementations. */void __init iop13xx_atue_setup(void){ int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUE); u32 reg_val;#ifdef CONFIG_PCI_MSI /* BAR 0 (inbound msi window) */ __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_MU_MUBAR); __raw_writel(~(IOP13XX_MU_WINDOW_SIZE - 1), IOP13XX_ATUE_IALR0); __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_ATUE_IATVR0); __raw_writel(IOP13XX_MU_BASE_PCI, IOP13XX_ATUE_IABAR0);#endif /* BAR 1 (1:1 mapping with Physical RAM) */ /* Set limit and enable */ __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1, IOP13XX_ATUE_IALR1); __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1); /* Set base at the top of the reserved address space */ __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUE_IABAR1); /* 1:1 mapping with physical ram * (leave big endian byte swap disabled) */ __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1); __raw_writel(PHYS_OFFSET, IOP13XX_ATUE_IATVR1); /* Outbound window 1 (PCIX/PCIE memory window) */ /* 32 bit Address Space */ __raw_writel(0x0, IOP13XX_ATUE_OUMWTVR1); /* PA[35:32] */ __raw_writel(IOP13XX_ATUE_OUMBAR_ENABLE | (IOP13XX_PCIE_MEM_PHYS_OFFSET >> 32), IOP13XX_ATUE_OUMBAR1); /* Setup the I/O Bar * A[35-16] in 31-12 */ __raw_writel(((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000), IOP13XX_ATUE_OIOBAR); __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR); /* clear startup errors */ iop13xx_atue_pci_status(1); /* OIOBAR function number */ reg_val = __raw_readl(IOP13XX_ATUE_OIOBAR); reg_val &= ~0x7; reg_val |= func; __raw_writel(reg_val, IOP13XX_ATUE_OIOBAR); /* OUMBAR function numbers */ reg_val = __raw_readl(IOP13XX_ATUE_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_ATUE_OUMBAR0); reg_val = __raw_readl(IOP13XX_ATUE_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_ATUE_OUMBAR1); reg_val = __raw_readl(IOP13XX_ATUE_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_ATUE_OUMBAR2); reg_val = __raw_readl(IOP13XX_ATUE_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_ATUE_OUMBAR3); /* Enable inbound and outbound cycles */ reg_val = __raw_readw(IOP13XX_ATUE_ATUCMD); reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; __raw_writew(reg_val, IOP13XX_ATUE_ATUCMD); reg_val = __raw_readl(IOP13XX_ATUE_ATUCR); reg_val |= IOP13XX_ATUE_ATUCR_OUT_EN | IOP13XX_ATUE_ATUCR_IVM; __raw_writel(reg_val, IOP13XX_ATUE_ATUCR);}void __init iop13xx_atue_disable(void){ u32 reg_val; __raw_writew(0x0, IOP13XX_ATUE_ATUCMD); __raw_writel(IOP13XX_ATUE_ATUCR_IVM, IOP13XX_ATUE_ATUCR); /* wait for cycles to quiesce */ while (__raw_readl(IOP13XX_ATUE_PCSR) & (IOP13XX_ATUE_PCSR_OUT_Q_BUSY | IOP13XX_ATUE_PCSR_IN_Q_BUSY | IOP13XX_ATUE_PCSR_LLRB_BUSY)) cpu_relax(); /* BAR 0 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUE_IAUBAR0); __raw_writel(0x0, IOP13XX_ATUE_IABAR0); __raw_writel(0x0, IOP13XX_ATUE_IAUTVR0); __raw_writel(0x0, IOP13XX_ATUE_IATVR0); __raw_writel(0x0, IOP13XX_ATUE_IALR0); reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0); reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0); /* BAR 1 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1); __raw_writel(0x0, IOP13XX_ATUE_IABAR1); __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1); __raw_writel(0x0, IOP13XX_ATUE_IATVR1); __raw_writel(0x0, IOP13XX_ATUE_IALR1); reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1); reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1); /* BAR 2 ( Disabled ) */ __raw_writel(0x0, IOP13XX_ATUE_IAUBAR2); __raw_writel(0x0, IOP13XX_ATUE_IABAR2); __raw_writel(0x0, IOP13XX_ATUE_IAUTVR2); __raw_writel(0x0, IOP13XX_ATUE_IATVR2); __raw_writel(0x0, IOP13XX_ATUE_IALR2); reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2); reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2); /* BAR 3 ( Disabled ) */ reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3); reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3); /* Setup the I/O Bar * A[35-16] in 31-12 */ __raw_writel((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000, IOP13XX_ATUE_OIOBAR); __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR);}/* This function is called from iop13xx_pci_init() after assigning valid * values to iop13xx_atux_pmmr_offset. This is the location for common * setup of ATUX for all IOP13XX implementations. */void __init iop13xx_atux_setup(void){ u32 reg_val; int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX); /* Take PCI-X bus out of reset if bootloader hasn't already. * According to spec, we should wait for 2^25 PCI clocks to meet * the PCI timing parameter Trhfa (RST# high to first access). * This is rarely necessary and often ignored. */ reg_val = __raw_readl(IOP13XX_ATUX_PCSR); if (reg_val & IOP13XX_ATUX_PCSR_P_RSTOUT) { int msec = (reg_val >> IOP13XX_ATUX_PCSR_FREQ_OFFSET) & 0x7; msec = 1000 / (8-msec); /* bits 100=133MHz, 111=>33MHz */ __raw_writel(reg_val & ~IOP13XX_ATUX_PCSR_P_RSTOUT, IOP13XX_ATUX_PCSR); atux_trhfa_timeout = jiffies + msecs_to_jiffies(msec); } else atux_trhfa_timeout = jiffies;#ifdef CONFIG_PCI_MSI /* BAR 0 (inbound msi window) */ __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_MU_MUBAR); __raw_writel(~(IOP13XX_MU_WINDOW_SIZE - 1), IOP13XX_ATUX_IALR0); __raw_writel(IOP13XX_MU_BASE_PHYS, IOP13XX_ATUX_IATVR0); __raw_writel(IOP13XX_MU_BASE_PCI, IOP13XX_ATUX_IABAR0);#endif /* BAR 1 (1:1 mapping with Physical RAM) */ /* Set limit and enable */ __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1, IOP13XX_ATUX_IALR1); __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1); /* Set base at the top of the reserved address space */ __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUX_IABAR1); /* 1:1 mapping with physical ram * (leave big endian byte swap disabled) */ __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1); __raw_writel(PHYS_OFFSET, IOP13XX_ATUX_IATVR1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -