arch/mips/txx9/generic/pci.c

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

File Facts

System
Linux kernel
Corpus path
arch/mips/txx9/generic/pci.c
Extension
.c
Size
12252 bytes
Lines
436
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 pcic {
		struct pci_controller c;
		struct resource r_mem[2];
		struct resource r_io;
	} *new = NULL;
	int min_size = 0x10000;

	if (!pcic) {
		new = kzalloc_obj(*new);
		if (!new)
			return NULL;
		new->r_mem[0].name = "PCI mem";
		new->r_mem[1].name = "PCI mmio";
		new->r_io.name = "PCI io";
		new->c.mem_resource = new->r_mem;
		new->c.io_resource = &new->r_io;
		pcic = &new->c;
	} else
		BUG_ON(pcic != &txx9_primary_pcic);
	pcic->io_resource->flags = IORESOURCE_IO;

	/*
	 * for auto assignment, first search a (big) region for PCI
	 * MEM, then search a region for PCI IO.
	 */
	if (mem_base) {
		pcic->mem_resource[0].start = mem_base;
		pcic->mem_resource[0].end = mem_base + mem_size - 1;
		if (request_resource(&iomem_resource, &pcic->mem_resource[0]))
			goto free_and_exit;
	} else {
		unsigned long min = 0, max = 0x20000000; /* low 512MB */
		if (!mem_size) {
			/* default size for auto assignment */
			if (txx9_pci_mem_high)
				mem_size = 0x20000000;	/* mem:512M(max) */
			else
				mem_size = 0x08000000;	/* mem:128M(max) */
		}
		if (txx9_pci_mem_high) {
			min = 0x20000000;
			max = 0xe0000000;
		}
		/* search free region for PCI MEM */
		for (; mem_size >= min_size; mem_size /= 2) {
			if (allocate_resource(&iomem_resource,
					      &pcic->mem_resource[0],
					      mem_size, min, max,
					      mem_size, NULL, NULL) == 0)
				break;
		}
		if (mem_size < min_size)
			goto free_and_exit;
	}

	pcic->mem_resource[1].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
	if (io_base) {
		pcic->mem_resource[1].start = io_base;
		pcic->mem_resource[1].end = io_base + io_size - 1;
		if (request_resource(&iomem_resource, &pcic->mem_resource[1]))
			goto release_and_exit;
	} else {
		if (!io_size)
			/* default size for auto assignment */
			io_size = 0x01000000;	/* io:16M(max) */
		/* search free region for PCI IO in low 512MB */
		for (; io_size >= min_size; io_size /= 2) {
			if (allocate_resource(&iomem_resource,
					      &pcic->mem_resource[1],
					      io_size, 0, 0x20000000,
					      io_size, NULL, NULL) == 0)
				break;
		}
		if (io_size < min_size)
			goto release_and_exit;
		io_base = pcic->mem_resource[1].start;
	}

	pcic->mem_resource[0].flags = IORESOURCE_MEM;
	if (pcic == &txx9_primary_pcic &&
	    mips_io_port_base == (unsigned long)-1) {
		/* map ioport 0 to PCI I/O space address 0 */
		set_io_port_base(IO_BASE + pcic->mem_resource[1].start);
		pcic->io_resource->start = 0;
		pcic->io_offset = 0;	/* busaddr == ioaddr */
		pcic->io_map_base = IO_BASE + pcic->mem_resource[1].start;
	} else {
		/* physaddr to ioaddr */
		pcic->io_resource->start =
			io_base - (mips_io_port_base - IO_BASE);

Annotation

Implementation Notes