arch/mips/pci/pci-ar2315.c

Source file repositories/reference/linux-study-clean/arch/mips/pci/pci-ar2315.c

File Facts

System
Linux kernel
Corpus path
arch/mips/pci/pci-ar2315.c
Extension
.c
Size
15075 bytes
Lines
522
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ar2315_pci_ctrl {
	void __iomem *cfg_mem;
	void __iomem *mmr_mem;
	unsigned irq;
	unsigned irq_ext;
	struct irq_domain *domain;
	struct pci_controller pci_ctrl;
	struct resource mem_res;
	struct resource io_res;
};

static inline dma_addr_t ar2315_dev_offset(struct device *dev)
{
	if (dev && dev_is_pci(dev))
		return AR2315_PCI_HOST_SDRAM_BASEADDR;
	return 0;
}

dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
	return paddr + ar2315_dev_offset(dev);
}

phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dma_addr)
{
	return dma_addr - ar2315_dev_offset(dev);
}

static inline struct ar2315_pci_ctrl *ar2315_pci_bus_to_apc(struct pci_bus *bus)
{
	struct pci_controller *hose = bus->sysdata;

	return container_of(hose, struct ar2315_pci_ctrl, pci_ctrl);
}

static inline u32 ar2315_pci_reg_read(struct ar2315_pci_ctrl *apc, u32 reg)
{
	return __raw_readl(apc->mmr_mem + reg);
}

static inline void ar2315_pci_reg_write(struct ar2315_pci_ctrl *apc, u32 reg,
					u32 val)
{
	__raw_writel(val, apc->mmr_mem + reg);
}

static inline void ar2315_pci_reg_mask(struct ar2315_pci_ctrl *apc, u32 reg,
				       u32 mask, u32 val)
{
	u32 ret = ar2315_pci_reg_read(apc, reg);

	ret &= ~mask;
	ret |= val;
	ar2315_pci_reg_write(apc, reg, ret);
}

static int ar2315_pci_cfg_access(struct ar2315_pci_ctrl *apc, unsigned devfn,
				 int where, int size, u32 *ptr, bool write)
{
	int func = PCI_FUNC(devfn);
	int dev = PCI_SLOT(devfn);
	u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3);
	u32 mask = 0xffffffff >> 8 * (4 - size);
	u32 sh = (where & 3) * 8;
	u32 value, isr;

	/* Prevent access past the remapped area */
	if (addr >= AR2315_PCI_CFG_SIZE || dev > 18)
		return PCIBIOS_DEVICE_NOT_FOUND;

	/* Clear pending errors */
	ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
	/* Select Configuration access */
	ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, 0,
			    AR2315_PCIMISC_CFG_SEL);

	mb();	/* PCI must see space change before we begin */

	value = __raw_readl(apc->cfg_mem + addr);

	isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR);

	if (isr & AR2315_PCI_INT_ABORT)
		goto exit_err;

	if (write) {
		value = (value & ~(mask << sh)) | *ptr << sh;
		__raw_writel(value, apc->cfg_mem + addr);
		isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR);
		if (isr & AR2315_PCI_INT_ABORT)

Annotation

Implementation Notes