Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e79066a6 authored by Paul Mundt's avatar Paul Mundt
Browse files

sh: pci: New-style controller registration.



This moves off of the board_pci_channels[] approach for bus registration
and over to a cleaner register_pci_controller(), all derived from the
MIPS code.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 99f95f11
Loading
Loading
Loading
Loading
+72 −25
Original line number Diff line number Diff line
@@ -13,29 +13,30 @@
#include <linux/init.h>
#include <linux/dma-debug.h>
#include <linux/io.h>
#include <linux/mutex.h>

static int __init pcibios_init(void)
/*
 * The PCI controller list.
 */
static struct pci_channel *hose_head, **hose_tail = &hose_head;

static int pci_initialized;

static void __devinit pcibios_scanbus(struct pci_channel *hose)
{
	struct pci_channel *p;
	static int next_busno;
	struct pci_bus *bus;
	int busno;

	/* init channels */
	busno = 0;
	for (p = board_pci_channels; p->init; p++) {
		if (p->init(p) == 0)
			p->enabled = 1;
		else
			pr_err("Unable to init pci channel %d\n", busno);
		busno++;
	}
	/* Catch botched conversion attempts */
	BUG_ON(hose->init);

	/* scan the buses */
	busno = 0;
	for (p = board_pci_channels; p->init; p++) {
		if (p->enabled) {
			bus = pci_scan_bus(busno, p->pci_ops, p);
			busno = bus->subordinate + 1;
	bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
	if (bus) {
		next_busno = bus->subordinate + 1;
		/* Don't allow 8-bit bus number overflow inside the hose -
		   reserve some space for bridges. */
		if (next_busno > 224)
			next_busno = 0;

		pci_bus_size_bridges(bus);
		pci_bus_assign_resources(bus);
@@ -43,10 +44,59 @@ static int __init pcibios_init(void)
	}
}

static DEFINE_MUTEX(pci_scan_mutex);

void __devinit register_pci_controller(struct pci_channel *hose)
{
	if (request_resource(&iomem_resource, hose->mem_resource) < 0)
		goto out;
	if (request_resource(&ioport_resource, hose->io_resource) < 0) {
		release_resource(hose->mem_resource);
		goto out;
	}

	*hose_tail = hose;
	hose_tail = &hose->next;

	/*
	 * Do not panic here but later - this might hapen before console init.
	 */
	if (!hose->io_map_base) {
		printk(KERN_WARNING
		       "registering PCI controller with io_map_base unset\n");
	}

	/*
	 * Scan the bus if it is register after the PCI subsystem
	 * initialization.
	 */
	if (pci_initialized) {
		mutex_lock(&pci_scan_mutex);
		pcibios_scanbus(hose);
		mutex_unlock(&pci_scan_mutex);
	}

	return;

out:
	printk(KERN_WARNING
	       "Skipping PCI bus scan due to resource conflict\n");
}

static int __init pcibios_init(void)
{
	struct pci_channel *hose;

	/* Scan all of the recorded PCI controllers.  */
	for (hose = hose_head; hose; hose = hose->next)
		pcibios_scanbus(hose);

	pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);

	dma_debug_add_bus(&pci_bus_type);

	pci_initialized = 1;

	return 0;
}
subsys_initcall(pcibios_init);
@@ -74,7 +124,6 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev,
	}
}


/*
 *  Called after each bus is probed, but before its children
 *  are examined.
@@ -186,5 +235,3 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
{
	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}

EXPORT_SYMBOL(board_pci_channels);
+40 −47
Original line number Diff line number Diff line
@@ -15,11 +15,47 @@
#include <linux/delay.h>
#include "pci-sh4.h"

static int __init sh7780_pci_init(struct pci_channel *chan)
extern u8 pci_cache_line_size;

static struct resource sh7785_io_resource = {
	.name	= "SH7785_IO",
	.start	= SH7780_PCI_IO_BASE,
	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
	.flags	= IORESOURCE_IO
};

static struct resource sh7785_mem_resource = {
	.name	= "SH7785_mem",
	.start	= SH7780_PCI_MEMORY_BASE,
	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
	.flags	= IORESOURCE_MEM
};

static struct pci_channel sh7780_pci_controller = {
	.pci_ops	= &sh4_pci_ops,
	.mem_resource	= &sh7785_mem_resource,
	.io_resource	= &sh7785_io_resource,
};

static struct sh4_pci_address_map sh7780_pci_map = {
	.window0	= {
#if defined(CONFIG_32BIT)
		.base	= SH7780_32BIT_DDR_BASE_ADDR,
		.size	= 0x40000000,
#else
		.base	= SH7780_CS0_BASE_ADDR,
		.size	= 0x20000000,
#endif
	},
};

static int __init sh7780_pci_init(void)
{
	struct pci_channel *chan = &sh7780_pci_controller;
	unsigned int id;
	const char *type = NULL;
	int ret;
	u32 word;

	printk(KERN_NOTICE "PCI: Starting intialization.\n");

@@ -54,52 +90,6 @@ static int __init sh7780_pci_init(struct pci_channel *chan)
	if ((ret = sh4_pci_check_direct(chan)) != 0)
		return ret;

	/*
	 * Platform specific initialization (BSC registers, and memory space
	 * mapping) will be called via the platform defined function
	 * pcibios_init_platform().
	 */
	return pcibios_init_platform();
}

extern u8 pci_cache_line_size;

static struct resource sh7785_io_resource = {
	.name	= "SH7785_IO",
	.start	= SH7780_PCI_IO_BASE,
	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
	.flags	= IORESOURCE_IO
};

static struct resource sh7785_mem_resource = {
	.name	= "SH7785_mem",
	.start	= SH7780_PCI_MEMORY_BASE,
	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
	.flags	= IORESOURCE_MEM
};

struct pci_channel board_pci_channels[] = {
	{ sh7780_pci_init, &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff },
	{ NULL, NULL, NULL, 0, 0 },
};

static struct sh4_pci_address_map sh7780_pci_map = {
	.window0	= {
#if defined(CONFIG_32BIT)
		.base	= SH7780_32BIT_DDR_BASE_ADDR,
		.size	= 0x40000000,
#else
		.base	= SH7780_CS0_BASE_ADDR,
		.size	= 0x20000000,
#endif
	},
};

int __init pcibios_init_platform(void)
{
	struct pci_channel *chan = &board_pci_channels[0];
	u32 word;

	/*
	 * Set the class and sub-class codes.
	 */
@@ -153,5 +143,8 @@ int __init pcibios_init_platform(void)

	__set_io_port_base(SH7780_PCI_IO_BASE);

	register_pci_controller(chan);

	return 0;
}
arch_initcall(sh7780_pci_init);
+18 −11
Original line number Diff line number Diff line
@@ -17,13 +17,18 @@
 * external) PCI controllers.
 */
struct pci_channel {
	struct pci_channel	*next;

	int			(*init)(struct pci_channel *chan);

	struct pci_ops		*pci_ops;
	struct resource		*io_resource;
	struct resource		*mem_resource;

	int			first_devfn;
	int			last_devfn;
	int			enabled;

	unsigned long		reg_base;
	unsigned long		io_base;

@@ -35,6 +40,8 @@ struct pci_channel {
 */
extern struct pci_channel board_pci_channels[];

extern void register_pci_controller(struct pci_channel *hose);

extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;

struct pci_dev;