On Thu, Oct 21, 2010 at 08:57:08PM +0530, Pratyush Anand wrote: > You can see the patch for arch specific code at: > > http://permalink.gmane.org/gmane.linux.ports.arm.kernel/88754 > > Yes , there are different methods to generate cfg0 and cfg1 in my controller. > I had already tried that , but it is not helping. My bet is that willy is right. Can you get a PCI-E bus analyzer attached to see what transactions the PCI-E Bridge is generating on the secondary bus? > This modification is not in posted patch. So I am pesting the pcie_ops > basic cfg rd/wr routine here: > > ---------------------------------------------------------------------------------------------------------------------- > static int spear13xx_pcie_rd_conf(struct pcie_port *pp, struct pci_bus *bus, > u32 devfn, int where, int size, u32 *val) > { > struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base; > u32 address = (u32)pp->va_cfg0_base | (PCI_FUNC(devfn) << 16) > | (where & 0xFFFC); > > writel((bus->number << 24) | (PCI_SLOT(devfn) << 19), > &app_reg->pom_cfg0_addr_start); > writel(readl(&app_reg->slv_armisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_armisc); > if (bus->parent->number == pp->root_bus_nr) > writel(readl(&app_reg->slv_armisc) | > AXI_OP_TYPE_CONFIG_RDRW_TYPE0, > &app_reg->slv_armisc); Does reading app_reg->slv_armisc register have any side effects? Is there any reason you can't cache this value and use the cached value with the '|' expression? > else > writel(readl(&app_reg->slv_armisc) | > AXI_OP_TYPE_CONFIG_RDRW_TYPE1, > &app_reg->slv_armisc); > udelay(1); > *val = readl(address); Why the udelay()? Is the writel() a posted or non-posted write? (ie does the CPU stall until the write completes or not?) If the CPU does not stall (writes are "posted"), then the udelay() is pointless and misleading. > if (size == 1) > *val = (*val >> (8 * (where & 3))) & 0xff; > else if (size == 2) > *val = (*val >> (8 * (where & 3))) & 0xffff; > > writel(readl(&app_reg->slv_armisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_armisc); Why clear those bits in the slv_armisc register? Borrow a PCIe protocol analyzer for a week or two and this would be easy to resolve. > return PCIBIOS_SUCCESSFUL; > } > > static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, > int size, u32 *val) > { > struct pcie_port *pp = bus_to_port(bus->number); > unsigned long flags; > int ret; > > if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { > *val = 0xffffffff; > return PCIBIOS_DEVICE_NOT_FOUND; > } > > spin_lock_irqsave(&pp->conf_lock, flags); > if (bus->number != pp->root_bus_nr) > ret = spear13xx_pcie_rd_conf(pp, bus, devfn, where, size, val); > else { > spear_dbi_read_reg(pp, where, size, val); > ret = 0; > } Why do both pcie_rd_conf() and spear13xx_pcie_rd_conf() have to check the bus->number? AFAIK, only the root control should need special handling to setup up type0 or type1 config transactions on the PCIe bridge. Or does this PCIe-PCIe bridge need SW support to correctly handle CFG space? hth, grant > spin_unlock_irqrestore(&pp->conf_lock, flags); > > return ret; > } > > static int spear13xx_pcie_wr_conf(struct pcie_port *pp, struct pci_bus *bus, > u32 devfn, int where, int size, u32 val) > { > int ret = PCIBIOS_SUCCESSFUL; > struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base; > u32 address = (u32)pp->va_cfg0_base | (PCI_FUNC(devfn) << 16) > | (where & 0xFFFC); > > writel((bus->number << 24) | (PCI_SLOT(devfn) << 19), > &app_reg->pom_cfg0_addr_start); > writel(readl(&app_reg->slv_awmisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_awmisc); > if (bus->parent->number == pp->root_bus_nr) > writel(readl(&app_reg->slv_awmisc) > | AXI_OP_TYPE_CONFIG_RDRW_TYPE0, > &app_reg->slv_awmisc); > else > writel(readl(&app_reg->slv_awmisc) > | AXI_OP_TYPE_CONFIG_RDRW_TYPE1, > &app_reg->slv_awmisc); > if (size == 4) > writel(val, address); > else if (size == 2) > writew(val, address + (where & 2)); > else if (size == 1) > writeb(val, address + (where & 3)); > else > ret = PCIBIOS_BAD_REGISTER_NUMBER; > writel(readl(&app_reg->slv_awmisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_awmisc); > return ret; > } > > static int pcie_wr_conf(struct pci_bus *bus, u32 devfn, > int where, int size, u32 val) > { > struct pcie_port *pp = bus_to_port(bus->number); > unsigned long flags; > int ret; > > if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) > return PCIBIOS_DEVICE_NOT_FOUND; > > spin_lock_irqsave(&pp->conf_lock, flags); > if (bus->number != pp->root_bus_nr) > ret = spear13xx_pcie_wr_conf(pp, bus, devfn, where, size, val); > else { > spear_dbi_write_reg(pp, where, size, val); > ret = 0; > } > spin_unlock_irqrestore(&pp->conf_lock, flags); > > return ret; > } > > > > static int spear13xx_pcie_rd_conf(struct pcie_port *pp, struct pci_bus *bus, > u32 devfn, int where, int size, u32 *val) > { > struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base; > u32 address = (u32)pp->va_cfg0_base | (PCI_FUNC(devfn) << 16) > | (where & 0xFFFC); > > writel((bus->number << 24) | (PCI_SLOT(devfn) << 19), > &app_reg->pom_cfg0_addr_start); > writel(readl(&app_reg->slv_armisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_armisc); > if (bus->parent->number == pp->root_bus_nr) > writel(readl(&app_reg->slv_armisc) | > AXI_OP_TYPE_CONFIG_RDRW_TYPE0, > &app_reg->slv_armisc); > else > writel(readl(&app_reg->slv_armisc) | > AXI_OP_TYPE_CONFIG_RDRW_TYPE1, > &app_reg->slv_armisc); > udelay(1); > *val = readl(address); > if (size == 1) > *val = (*val >> (8 * (where & 3))) & 0xff; > else if (size == 2) > *val = (*val >> (8 * (where & 3))) & 0xffff; > > writel(readl(&app_reg->slv_armisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_armisc); > > return PCIBIOS_SUCCESSFUL; > } > > static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, > int size, u32 *val) > { > struct pcie_port *pp = bus_to_port(bus->number); > unsigned long flags; > int ret; > > if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { > *val = 0xffffffff; > return PCIBIOS_DEVICE_NOT_FOUND; > } > > spin_lock_irqsave(&pp->conf_lock, flags); > if (bus->number != pp->root_bus_nr) > ret = spear13xx_pcie_rd_conf(pp, bus, devfn, where, size, val); > else { > spear_dbi_read_reg(pp, where, size, val); > ret = 0; > } > spin_unlock_irqrestore(&pp->conf_lock, flags); > > return ret; > } > > static int spear13xx_pcie_wr_conf(struct pcie_port *pp, struct pci_bus *bus, > u32 devfn, int where, int size, u32 val) > { > int ret = PCIBIOS_SUCCESSFUL; > struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base; > u32 address = (u32)pp->va_cfg0_base | (PCI_FUNC(devfn) << 16) > | (where & 0xFFFC); > > writel((bus->number << 24) | (PCI_SLOT(devfn) << 19), > &app_reg->pom_cfg0_addr_start); > writel(readl(&app_reg->slv_awmisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_awmisc); > if (bus->parent->number == pp->root_bus_nr) > writel(readl(&app_reg->slv_awmisc) > | AXI_OP_TYPE_CONFIG_RDRW_TYPE0, > &app_reg->slv_awmisc); > else > writel(readl(&app_reg->slv_awmisc) > | AXI_OP_TYPE_CONFIG_RDRW_TYPE1, > &app_reg->slv_awmisc); > if (size == 4) > writel(val, address); > else if (size == 2) > writew(val, address + (where & 2)); > else if (size == 1) > writeb(val, address + (where & 3)); > else > ret = PCIBIOS_BAD_REGISTER_NUMBER; > writel(readl(&app_reg->slv_awmisc) & ~(AXI_OP_TYPE_MASK), > &app_reg->slv_awmisc); > return ret; > } > > static int pcie_wr_conf(struct pci_bus *bus, u32 devfn, > int where, int size, u32 val) > { > struct pcie_port *pp = bus_to_port(bus->number); > unsigned long flags; > int ret; > > if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) > return PCIBIOS_DEVICE_NOT_FOUND; > > spin_lock_irqsave(&pp->conf_lock, flags); > if (bus->number != pp->root_bus_nr) > ret = spear13xx_pcie_wr_conf(pp, bus, devfn, where, size, val); > else { > spear_dbi_write_reg(pp, where, size, val); > ret = 0; > } > spin_unlock_irqrestore(&pp->conf_lock, flags); > > return ret; > } > > > > > > > On Thu, Oct 21, 2010 at 5:55 PM, Matthew Wilcox <matthew@xxxxxx> wrote: > > On Thu, Oct 21, 2010 at 05:16:22PM +0530, Pratyush Anand wrote: > >> Hi All, > >> > >> I have developed support for a PCIE host controller on linux platform > >> for an SOC. > >> > >> It works well with PCIE devices (e.g.usb3.0 card, ethernet card, pcie > >> to sata )from various vendors. > >> > >> However, I am having problem in using any card where device is > >> connected below a bridge (class 0x0604). > >> > >> What ever bus number is programmed , cfg register value are from > >> bridge only not of downstream device. > > > > It would be helpful if you could post your code. I suspect the problem is > > that you're telling the host bridge to generate CfgRd0 instead of CfgRd1. > > > > -- > > Matthew Wilcox Intel Open Source Technology Centre > > "Bill, look, we understand that you're interested in selling us this > > operating system, but compare it to ours. We can't possibly take such > > a retrograde step." > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-pci" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html