drivers/pci/controller/pci-ixp4xx.c
Source file repositories/reference/linux-study-clean/drivers/pci/controller/pci-ixp4xx.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pci/controller/pci-ixp4xx.c- Extension
.c- Size
- 18135 bytes
- Lines
- 679
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: implementation source
- Status
- source implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/init.hlinux/io.hlinux/kernel.hlinux/of.hlinux/of_pci.hlinux/pci.hlinux/platform_device.hlinux/slab.hlinux/bits.h../pci.h
Detected Declarations
struct ixp4xx_pcifunction readlfunction ixp4xx_writelfunction ixp4xx_pci_check_master_abortfunction ixp4xx_pci_read_indirectfunction ixp4xx_pci_write_indirectfunction ixp4xx_config_addrfunction ixp4xx_crp_byte_lane_enable_bitsfunction ixp4xx_crp_read_configfunction ixp4xx_crp_write_configfunction ixp4xx_byte_lane_enable_bitsfunction ixp4xx_pci_read_configfunction ixp4xx_pci_write_configfunction ixp4xx_pci_addr_to_64mconffunction ixp4xx_pci_parse_map_rangesfunction ixp4xx_pci_parse_map_dma_rangesfunction ixp4xx_pci_abort_handlerfunction ixp4xx_pci_probe
Annotated Snippet
struct ixp4xx_pci {
struct device *dev;
void __iomem *base;
bool errata_hammer;
bool host_mode;
};
/*
* The IXP4xx has a peculiar address bus that will change the
* byte order on SoC peripherals depending on whether the device
* operates in big-endian or little-endian mode. That means that
* readl() and writel() that always use little-endian access
* will not work for SoC peripherals such as the PCI controller
* when used in big-endian mode. The accesses to the individual
* PCI devices on the other hand, are always little-endian and
* can use readl() and writel().
*
* For local AHB bus access we need to use __raw_[readl|writel]()
* to make sure that we access the SoC devices in the CPU native
* endianness.
*/
static inline u32 ixp4xx_readl(struct ixp4xx_pci *p, u32 reg)
{
return __raw_readl(p->base + reg);
}
static inline void ixp4xx_writel(struct ixp4xx_pci *p, u32 reg, u32 val)
{
__raw_writel(val, p->base + reg);
}
static int ixp4xx_pci_check_master_abort(struct ixp4xx_pci *p)
{
u32 isr = ixp4xx_readl(p, IXP4XX_PCI_ISR);
if (isr & IXP4XX_PCI_ISR_PFE) {
/* Make sure the master abort bit is reset */
ixp4xx_writel(p, IXP4XX_PCI_ISR, IXP4XX_PCI_ISR_PFE);
dev_dbg(p->dev, "master abort detected\n");
return -EINVAL;
}
return 0;
}
static int ixp4xx_pci_read_indirect(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
{
ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
if (p->errata_hammer) {
int i;
/*
* PCI workaround - only works if NP PCI space reads have
* no side effects. Hammer the register and read twice 8
* times. last one will be good.
*/
for (i = 0; i < 8; i++) {
ixp4xx_writel(p, IXP4XX_PCI_NP_CBE, cmd);
*data = ixp4xx_readl(p, IXP4XX_PCI_NP_RDATA);
*data = ixp4xx_readl(p, IXP4XX_PCI_NP_RDATA);
}
} else {
ixp4xx_writel(p, IXP4XX_PCI_NP_CBE, cmd);
*data = ixp4xx_readl(p, IXP4XX_PCI_NP_RDATA);
}
return ixp4xx_pci_check_master_abort(p);
}
static int ixp4xx_pci_write_indirect(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 data)
{
ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
/* Set up the write */
ixp4xx_writel(p, IXP4XX_PCI_NP_CBE, cmd);
/* Execute the write by writing to NP_WDATA */
ixp4xx_writel(p, IXP4XX_PCI_NP_WDATA, data);
return ixp4xx_pci_check_master_abort(p);
}
static u32 ixp4xx_config_addr(u8 bus_num, u16 devfn, int where)
{
/* Root bus is always 0 in this hardware */
if (bus_num == 0) {
/* type 0 */
return (PCI_CONF1_ADDRESS(0, 0, PCI_FUNC(devfn), where) &
~PCI_CONF1_ENABLE) | BIT(32-PCI_SLOT(devfn));
Annotation
- Immediate include surface: `linux/init.h`, `linux/io.h`, `linux/kernel.h`, `linux/of.h`, `linux/of_pci.h`, `linux/pci.h`, `linux/platform_device.h`, `linux/slab.h`.
- Detected declarations: `struct ixp4xx_pci`, `function readl`, `function ixp4xx_writel`, `function ixp4xx_pci_check_master_abort`, `function ixp4xx_pci_read_indirect`, `function ixp4xx_pci_write_indirect`, `function ixp4xx_config_addr`, `function ixp4xx_crp_byte_lane_enable_bits`, `function ixp4xx_crp_read_config`, `function ixp4xx_crp_write_config`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.