static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { struct tegra_pcie_port *pp = bus_to_port(bus->number); void __iomem *addr; if (pp) { if (devfn != 0) { *val = 0xffffffff; return PCIBIOS_DEVICE_NOT_FOUND; } addr = pp->base + (where & ~0x3); } else { addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) + PCIE_CONF_DEV(PCI_SLOT(devfn)) + PCIE_CONF_FUNC(PCI_FUNC(devfn)) + PCIE_CONF_REG(where)); } *val = readl(addr); if (size == 1) *val = (*val >> (8 * (where & 3))) & 0xff; else if (size == 2)
static int basic_pcie_rd_conf(void __iomem *base, struct pci_bus *bus, u32 devfn, int where, int size, u32 *val) { writel(PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(PCI_SLOT(devfn)) | PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN, base + PCIE_CONF_ADDR_OFF); *val = readl(base + PCIE_CONF_DATA_OFF); if (size == 1) *val = (*val >> (8 * (where & 3))) & 0xff; else if (size == 2)
/* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ static int rcar_pcie_config_access(struct rcar_pcie *pcie, unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 *data) { int dev, func, reg, index; dev = PCI_SLOT(devfn); func = PCI_FUNC(devfn); reg = where & ~3; index = reg / 4; /* * While each channel has its own memory-mapped extended config * space, it's generally only accessible when in endpoint mode. * When in root complex mode, the controller is unable to target * itself with either type 0 or type 1 accesses, and indeed, any * controller initiated target transfer to its own config space * result in a completer abort. * * Each channel effectively only supports a single device, but as * the same channel <-> device access works for any PCI_SLOT() * value, we cheat a bit here and bind the controller's config * space to devfn 0 in order to enable self-enumeration. In this * case the regular ECAR/ECDR path is sidelined and the mangled * config access itself is initiated as an internal bus transaction. */ if (pci_is_root_bus(bus)) { if (dev != 0) return PCIBIOS_DEVICE_NOT_FOUND; if (access_type == PCI_ACCESS_READ) { *data = pci_read_reg(pcie, PCICONF(index)); } else { /* Keep an eye out for changes to the root bus number */ if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS)) pcie->root_bus_nr = *data & 0xff; pci_write_reg(pcie, *data, PCICONF(index)); } return PCIBIOS_SUCCESSFUL; } if (pcie->root_bus_nr < 0) return PCIBIOS_DEVICE_NOT_FOUND; /* Clear errors */ pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR); /* Set the PIO address */ pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR); /* Enable the configuration access */ if (bus->parent->number == pcie->root_bus_nr) pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR); else pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR); /* Check for errors */ if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST) return PCIBIOS_DEVICE_NOT_FOUND; /* Check for master and target aborts */ if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) & (PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT)) return PCIBIOS_DEVICE_NOT_FOUND; if (access_type == PCI_ACCESS_READ) *data = pci_read_reg(pcie, PCIECDR); else pci_write_reg(pcie, *data, PCIECDR); /* Disable the configuration access */ pci_write_reg(pcie, 0, PCIECCTLR); return PCIBIOS_SUCCESSFUL; }