Skip to content

Commit

Permalink
sh: pci: New-style controller registration.
Browse files Browse the repository at this point in the history
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: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
pmundt committed Apr 20, 2009
1 parent 99f95f1 commit e79066a
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 83 deletions.
97 changes: 72 additions & 25 deletions arch/sh/drivers/pci/pci-new.c
Expand Up @@ -13,40 +13,90 @@
#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);

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);
pci_enable_bridges(bus);
}
}

/* 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;
static DEFINE_MUTEX(pci_scan_mutex);

pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
}
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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
87 changes: 40 additions & 47 deletions arch/sh/drivers/pci/pci-sh7780.c
Expand Up @@ -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");

Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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);
29 changes: 18 additions & 11 deletions arch/sh/include/asm/pci.h
Expand Up @@ -17,24 +17,31 @@
* external) PCI controllers.
*/
struct pci_channel {
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;

unsigned long io_map_base;
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;

unsigned long io_map_base;
};

/*
* Each board initializes this array and terminates it with a NULL entry.
*/
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;
Expand Down

0 comments on commit e79066a

Please sign in to comment.