Commit dada8441 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/sfr
parents d0c451f8 bb0fd83e
......@@ -12,12 +12,11 @@
#include "ppc32-types.h"
#include "zlib.h"
#include <linux/elf.h>
#include <linux/string.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/bootinfo.h>
void memmove(void *dst, void *im, int len);
extern void *finddevice(const char *);
extern int getprop(void *, const char *, void *, int);
extern void printk(char *fmt, ...);
......
......@@ -72,6 +72,7 @@ extern void init_ras_IRQ(void);
extern void find_and_init_phbs(void);
extern void pSeries_pcibios_fixup(void);
extern void pSeries_pcibios_fixup_bus(struct pci_bus *bus);
extern void iSeries_pcibios_fixup(void);
extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
......@@ -245,6 +246,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifndef CONFIG_PPC_ISERIES
ppc_md.pcibios_fixup = pSeries_pcibios_fixup;
ppc_md.pcibios_fixup_bus = pSeries_pcibios_fixup_bus;
#else
ppc_md.pcibios_fixup = NULL;
// ppc_md.pcibios_fixup = iSeries_pcibios_fixup;
......
......@@ -26,6 +26,7 @@
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <asm/paca.h>
#include <asm/processor.h>
#include <asm/naca.h>
......
......@@ -344,8 +344,8 @@ irq_recheck:
recheck:
mfmsr r10 /* Get current interrupt state */
li r4,0
ori r4,r4,MSR_EE|MSR_RI
andc r10,r10,r4 /* clear MSR_EE and MSR_RI */
ori r4,r4,MSR_EE
andc r10,r10,r4 /* clear MSR_EE */
mtmsrd r10,1 /* Update machine state */
#ifdef CONFIG_PPC_ISERIES
......@@ -396,7 +396,7 @@ restore:
mfmsr r0
li r2, MSR_RI
andc r0,r0,r2
mtmsrd r0
mtmsrd r0,1
ld r0,_MSR(r1)
mtspr SRR1,r0
......@@ -422,7 +422,7 @@ restore:
/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */
do_work:
/* Enable interrupts */
ori r10,r10,MSR_EE|MSR_RI
ori r10,r10,MSR_EE
mtmsrd r10,1
andi. r0,r3,_TIF_NEED_RESCHED
......
......@@ -562,7 +562,7 @@ fast_exception_return:
mfmsr r20
li r21, MSR_RI
andc r20,r20,r21
mtmsrd r20
mtmsrd r20,1
mtspr SRR1,r23
mtspr SRR0,r22
......@@ -989,7 +989,7 @@ _GLOBAL(do_stab_bolted)
mfmsr r22
li r23, MSR_RI
andc r22,r22,r23
mtmsrd r22
mtmsrd r22,1
ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */
ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */
......@@ -1094,7 +1094,7 @@ SLB_NUM_ENTRIES = 64
mfmsr r22
li r23, MSR_RI
andc r22,r22,r23
mtmsrd r22
mtmsrd r22,1
ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */
ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */
......
......@@ -394,81 +394,6 @@ handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
local_irq_disable();
}
#ifdef CONFIG_SMP
extern unsigned long irq_affinity [NR_IRQS];
typedef struct {
unsigned long cpu;
unsigned long timestamp;
} ____cacheline_aligned irq_balance_t;
static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
= { [ 0 ... NR_IRQS-1 ] = { 0, 0 } };
#define IDLE_ENOUGH(cpu,now) \
(idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
#define IRQ_ALLOWED(cpu,allowed_mask) \
((1UL << cpu) & (allowed_mask))
#define IRQ_BALANCE_INTERVAL (HZ/50)
static unsigned long move(unsigned long curr_cpu, unsigned long allowed_mask,
unsigned long now, int direction)
{
int search_idle = 1;
int cpu = curr_cpu;
goto inside;
do {
if (unlikely(cpu == curr_cpu))
search_idle = 0;
inside:
if (direction == 1) {
cpu++;
if (cpu >= NR_CPUS)
cpu = 0;
} else {
cpu--;
if (cpu == -1)
cpu = NR_CPUS-1;
}
} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
(search_idle && !IDLE_ENOUGH(cpu,now)));
return cpu;
}
static inline void balance_irq(int irq)
{
irq_balance_t *entry = irq_balance + irq;
unsigned long now = jiffies;
if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) {
unsigned long allowed_mask;
unsigned int new_cpu;
unsigned long random_number;
if (!irq_desc[irq].handler->set_affinity)
return;
random_number = mftb();
random_number &= 1;
allowed_mask = cpu_online_map & irq_affinity[irq];
entry->timestamp = now;
new_cpu = move(entry->cpu, allowed_mask, now, random_number);
if (entry->cpu != new_cpu) {
entry->cpu = new_cpu;
irq_desc[irq].handler->set_affinity(irq, 1UL << new_cpu);
}
}
}
#else
#define balance_irq(irq) do { } while (0)
#endif
/*
* Eventually, this should take an array of interrupts and an array size
* so it can dispatch multiple interrupts.
......@@ -480,10 +405,6 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq;
/* XXX This causes bad performance and lockups on XICS - Anton */
if (naca->interrupt_controller == IC_OPEN_PIC)
balance_irq(irq);
kstat_cpu(cpu).irqs[irq]++;
spin_lock(&desc->lock);
ack_irq(irq);
......
......@@ -43,12 +43,6 @@
#include "open_pic.h"
#include "pci.h"
/*******************************************************************
* Forward declares of prototypes.
*******************************************************************/
struct pci_controller *alloc_phb(struct device_node *dev, char *model,
unsigned int addr_size_words) ;
/* RTAS tokens */
static int read_pci_config;
static int write_pci_config;
......@@ -144,242 +138,173 @@ struct pci_ops rtas_pci_ops = {
* openfirmware and sets it in the pci_dev and pci_config line.
*
******************************************************************/
int
pci_read_irq_line(struct pci_dev *Pci_Dev)
int pci_read_irq_line(struct pci_dev *pci_dev)
{
u8 InterruptPin;
struct device_node *Node;
u8 intpin;
struct device_node *node;
pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
pci_read_config_byte(Pci_Dev, PCI_INTERRUPT_PIN, &InterruptPin);
if (InterruptPin == 0) {
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",Pci_Dev->slot_name);
if (intpin == 0) {
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_dev->slot_name);
return 0;
}
Node = pci_device_to_OF_node(Pci_Dev);
if ( Node == NULL) {
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",Pci_Dev->slot_name);
node = pci_device_to_OF_node(pci_dev);
if (node == NULL) {
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
pci_dev->slot_name);
return -1;
}
if (Node->n_intrs == 0) {
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",Pci_Dev->slot_name);
if (node->n_intrs == 0) {
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_dev->slot_name);
return -1;
}
Pci_Dev->irq = Node->intrs[0].line;
pci_dev->irq = node->intrs[0].line;
if (s7a_workaround) {
if (Pci_Dev->irq > 16)
Pci_Dev->irq -= 3;
if (pci_dev->irq > 16)
pci_dev->irq -= 3;
}
pci_write_config_byte(Pci_Dev, PCI_INTERRUPT_LINE, Pci_Dev->irq);
pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",Pci_Dev->slot_name,Pci_Dev->irq);
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
pci_dev->slot_name, pci_dev->irq);
return 0;
}
/******************************************************************
* Find all PHBs in the system and initialize a set of data
* structures to represent them.
******************************************************************/
unsigned long __init
find_and_init_phbs(void)
static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev,
int primary)
{
struct device_node *Pci_Node;
struct pci_controller *phb;
unsigned int root_addr_size_words = 0, this_addr_size_words = 0;
unsigned int this_addr_count = 0, range_stride;
unsigned int *ui_ptr = NULL, *ranges;
char *model;
struct pci_range64 range;
unsigned int *ranges;
unsigned long size;
int rlen = 0;
int memno = 0;
struct resource *res;
unsigned int memno, rlen, i, index;
unsigned int *opprop;
int has_isa = 0;
PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n");
read_pci_config = rtas_token("read-pci-config");
write_pci_config = rtas_token("write-pci-config");
ibm_read_pci_config = rtas_token("ibm,read-pci-config");
ibm_write_pci_config = rtas_token("ibm,write-pci-config");
int np, na = prom_n_addr_cells(dev);
unsigned long pci_addr, cpu_phys_addr;
np = na + 5;
/*
* The ranges property is laid out as an array of elements,
* each of which comprises:
* cells 0 - 2: a PCI address
* cells 3 or 3+4: a CPU physical address
* (size depending on dev->n_addr_cells)
* cells 4+5 or 5+6: the size of the range
*/
rlen = 0;
hose->io_base_phys = 0;
ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
while ((rlen -= np * sizeof(unsigned int)) >= 0) {
res = NULL;
pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
cpu_phys_addr = ranges[3];
if (na == 2)
cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
switch (ranges[0] >> 24) {
case 1: /* I/O space */
hose->io_base_phys = cpu_phys_addr;
hose->io_base_virt = __ioremap(hose->io_base_phys,
size, _PAGE_NO_CACHE);
if (primary) {
pci_io_base = (unsigned long)hose->io_base_virt;
if (find_type_devices("isa"))
isa_io_base = pci_io_base;
}
if (naca->interrupt_controller == IC_OPEN_PIC) {
opprop = (unsigned int *)get_property(find_path_device("/"),
"platform-open-pic", NULL);
res = &hose->io_resource;
res->flags = IORESOURCE_IO;
res->start = pci_addr;
res->start += (unsigned long)hose->io_base_virt -
pci_io_base;
break;
case 2: /* memory space */
memno = 0;
while (memno < 3 && hose->mem_resources[memno].flags)
++memno;
if (memno == 0)
hose->pci_mem_offset = cpu_phys_addr - pci_addr;
if (memno < 3) {
res = &hose->mem_resources[memno];
res->flags = IORESOURCE_MEM;
res->start = cpu_phys_addr;
}
break;
}
if (res != NULL) {
res->name = dev->full_name;
res->end = res->start + size - 1;
res->parent = NULL;
res->sibling = NULL;
res->child = NULL;
}
ranges += np;
}
}
/* Get the root address word size. */
ui_ptr = (unsigned int *) get_property(find_path_device("/"),
"#size-cells", NULL);
if (ui_ptr) {
root_addr_size_words = *ui_ptr;
} else {
PPCDBG(PPCDBG_PHBINIT, "\tget #size-cells failed.\n");
return(-1);
}
static void python_countermeasures(unsigned long addr)
{
void *chip_regs;
volatile u32 *tmp, i;
if (find_type_devices("isa")) {
has_isa = 1;
PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n");
}
/* Python's register file is 1 MB in size. */
chip_regs = ioremap(addr & ~(0xfffffUL), 0x100000);
index = 0;
/*
* Firmware doesn't always clear this bit which is critical
* for good performance - Anton
*/
/******************************************************************
* Find all PHB devices and create an object for them.
******************************************************************/
for (Pci_Node = find_devices("pci"); Pci_Node != NULL; Pci_Node = Pci_Node->next) {
model = (char *) get_property(Pci_Node, "model", NULL);
if (model != NULL) {
phb = alloc_phb(Pci_Node, model, root_addr_size_words);
if (phb == NULL) return(-1);
}
else {
continue;
}
/* Get this node's address word size. */
ui_ptr = (unsigned int *) get_property(Pci_Node, "#size-cells", NULL);
if (ui_ptr)
this_addr_size_words = *ui_ptr;
else
this_addr_size_words = 1;
/* Get this node's address word count. */
ui_ptr = (unsigned int *) get_property(Pci_Node, "#address-cells", NULL);
if (ui_ptr)
this_addr_count = *ui_ptr;
else
this_addr_count = 3;
range_stride = this_addr_count + root_addr_size_words + this_addr_size_words;
memno = 0;
phb->io_base_phys = 0;
ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen);
PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen);
for (i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) {
/* Put the PCI addr part of the current element into a
* '64' struct.
*/
range = *((struct pci_range64 *)(ranges + i));
/* If this is a '32' element, map into a 64 struct. */
if ((range_stride * sizeof(int)) ==
sizeof(struct pci_range32)) {
range.parent_addr =
(unsigned long)(*(ranges + i + 3));
range.size =
(((unsigned long)(*(ranges + i + 4)))<<32) |
(*(ranges + i + 5));
} else {
range.parent_addr =
(((unsigned long)(*(ranges + i + 3)))<<32) |
(*(ranges + i + 4));
range.size =
(((unsigned long)(*(ranges + i + 5)))<<32) |
(*(ranges + i + 6));
}
PPCDBG(PPCDBG_PHBINIT, "\trange.parent_addr = 0x%lx\n",
range.parent_addr);
PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.hi = 0x%lx\n",
range.child_addr.a_hi);
PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.mid = 0x%lx\n",
range.child_addr.a_mid);
PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.lo = 0x%lx\n",
range.child_addr.a_lo);
PPCDBG(PPCDBG_PHBINIT, "\trange.size = 0x%lx\n",
range.size);
res = NULL;
switch ((range.child_addr.a_hi >> 24) & 0x3) {
case 1: /* I/O space */
PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n");
phb->io_base_phys = range.parent_addr;
res = &phb->io_resource;
res->name = Pci_Node->full_name;
res->flags = IORESOURCE_IO;
phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE);
if (!pci_io_base) {
pci_io_base = (unsigned long)phb->io_base_virt;
if (has_isa)
isa_io_base = pci_io_base;
}
res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
res->start += (unsigned long)phb->io_base_virt - pci_io_base;
res->end = res->start + range.size - 1;
res->parent = NULL;
res->sibling = NULL;
res->child = NULL;
phb->pci_io_offset = range.parent_addr -
((((unsigned long)
range.child_addr.a_mid) << 32) |
(range.child_addr.a_lo));
PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset = 0x%lx\n",
phb->pci_io_offset);
break;
case 2: /* mem space */
PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n");
phb->pci_mem_offset = range.parent_addr -
((((unsigned long)
range.child_addr.a_mid) << 32) |
(range.child_addr.a_lo));
PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n",
phb->pci_mem_offset);
if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) {
res = &(phb->mem_resources[memno]);
++memno;
res->name = Pci_Node->full_name;
res->flags = IORESOURCE_MEM;
res->start = range.parent_addr;
res->end = range.parent_addr + range.size - 1;
res->parent = NULL;
res->sibling = NULL;
res->child = NULL;
}
break;
}
}
PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys = 0x%lx\n",
phb->io_base_phys);
PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n",
phb->pci_mem_offset);
#define PRG_CL_RESET_VALID 0x00010000
if (naca->interrupt_controller == IC_OPEN_PIC) {
int addr = root_addr_size_words * (index + 2) - 1;
openpic_setup_ISU(index, opprop[addr]);
}
index++;
tmp = (u32 *)((unsigned long)chip_regs + 0xf6030);
if (*tmp & PRG_CL_RESET_VALID) {
printk(KERN_INFO "Python workaround: ");
*tmp &= ~PRG_CL_RESET_VALID;
/*
* We must read it back for changes to
* take effect
*/
i = *tmp;
printk("reg0: %x\n", i);
}
pci_devs_phb_init();
return 0; /*Success */
iounmap(chip_regs);
}
/******************************************************************
*
* Allocate and partially initialize a structure to represent a PHB.
*
******************************************************************/
struct pci_controller *
alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
struct pci_controller *alloc_phb(struct device_node *dev,
unsigned int addr_size_words)
{
struct pci_controller *phb;
unsigned int *ui_ptr = NULL, len;
struct reg_property64 reg_struct;
int *bus_range;
int *buid_vals;
char *model;
enum phb_types phb_type;
model = (char *)get_property(dev, "model", NULL);
if (!model) {
printk(KERN_ERR "alloc_phb: phb has no model property\n");
model = "<empty>";
}
PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name);
PPCDBG(PPCDBG_PHBINIT, "\tdev = 0x%lx\n", dev);
PPCDBG(PPCDBG_PHBINIT, "\tmodel = 0x%lx\n", model);
PPCDBG(PPCDBG_PHBINIT, "\taddr_size_words = 0x%lx\n", addr_size_words);
/* Found a PHB, now figure out where his registers are mapped. */
ui_ptr = (unsigned int *) get_property(dev, "reg", &len);
if (ui_ptr == NULL) {
PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n");
return(NULL);
return NULL;
}
if (addr_size_words == 1) {
......@@ -389,83 +314,30 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
reg_struct = *((struct reg_property64 *)ui_ptr);
}
PPCDBG(PPCDBG_PHBINIT, "\treg_struct.address = 0x%lx\n", reg_struct.address);
PPCDBG(PPCDBG_PHBINIT, "\treg_struct.size = 0x%lx\n", reg_struct.size);
/***************************************************************
* Set chip specific data in the phb, including types &
* register pointers.
***************************************************************/
/****************************************************************
* Python
***************************************************************/
if (strstr(model, "Python")) {
void *chip_regs;
volatile u32 *tmp, i;
PPCDBG(PPCDBG_PHBINIT, "\tCreate python\n");
phb = pci_alloc_pci_controller("PHB PY", phb_type_python);
if (phb == NULL)
return NULL;
/* Python's register file is 1 MB in size. */
chip_regs = ioremap(reg_struct.address & ~(0xfffffUL),
0x100000);
/*
* Firmware doesn't always clear this bit which is critical
* for good performance - Anton
*/
#define PRG_CL_RESET_VALID 0x00010000
tmp = (u32 *)((unsigned long)chip_regs + 0xf6030);
if (*tmp & PRG_CL_RESET_VALID) {
printk("Python workaround: ");
*tmp &= ~PRG_CL_RESET_VALID;
/*
* We must read it back for changes to
* take effect
*/
i = *tmp;
printk("reg0: %x\n", i);
}
phb_type = phb_type_python;
} else if (strstr(model, "Speedwagon")) {
phb_type = phb_type_speedwagon;
} else if (strstr(model, "Winnipeg")) {
phb_type = phb_type_winnipeg;
} else {
printk(KERN_ERR "alloc_phb: unknown PHB %s\n", model);
phb_type = phb_type_unknown;
}
/***************************************************************
* Speedwagon
* include Winnipeg as well for the time being.
***************************************************************/
} else if ((strstr(model, "Speedwagon")) ||
(strstr(model, "Winnipeg"))) {
PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n");
phb = pci_alloc_pci_controller("PHB SW", phb_type_speedwagon);
if (phb == NULL)
return NULL;
phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8;
/***************************************************************
* Trying to build a known just gets the code in trouble.
***************************************************************/
} else {
PPCDBG(PPCDBG_PHBINIT, "\tUnknown PHB Type!\n");
printk("PCI: Unknown Phb Type!\n");
phb = pci_alloc_pci_controller(phb_type);
if (phb == NULL)
return NULL;
}
if (phb_type == phb_type_python)
python_countermeasures(reg_struct.address);
bus_range = (int *) get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
PPCDBG(PPCDBG_PHBINIT, "Can't get bus-range for %s\n", dev->full_name);
kfree(phb);
return(NULL);
return NULL;
}
/***************************************************************
* Finished with the initialization
***************************************************************/
phb->first_busno = bus_range[0];
phb->last_busno = bus_range[1];
......@@ -473,7 +345,7 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
phb->ops = &rtas_pci_ops;
buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len);
if (buid_vals == NULL) {
phb->buid = 0;
} else {
......@@ -486,24 +358,71 @@ alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words)
panic("pSeries_pci: this system has large bus numbers and the kernel was not\n"
"built with the patch that fixes include/linux/pci.h struct pci_bus so\n"
"number, primary, secondary and subordinate are ints.\n");
}
if (len < 2 * sizeof(int))
phb->buid = (unsigned long)buid_vals[0]; // Support for new OF that only has 1 integer for buid.
else
phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |
(((unsigned long)buid_vals[1]) & 0xffffffff);
}
if (len < 2 * sizeof(int))
// Support for new OF that only has 1 integer for buid.
phb->buid = (unsigned long)buid_vals[0];
else
phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |
(((unsigned long)buid_vals[1]) & 0xffffffff);
phb->first_busno += (phb->global_number << 8);
phb->last_busno += (phb->global_number << 8);
}
/* Dump PHB information for Debug */
PPCDBGCALL(PPCDBG_PHBINIT,dumpPci_Controller(phb) );
PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Controller(phb));
return phb;
}
unsigned long __init find_and_init_phbs(void)
{
struct device_node *node;
struct pci_controller *phb;
unsigned int root_size_cells = 0;
unsigned int index;
unsigned int *opprop;
struct device_node *root = find_path_device("/");
read_pci_config = rtas_token("read-pci-config");
write_pci_config = rtas_token("write-pci-config");
ibm_read_pci_config = rtas_token("ibm,read-pci-config");
ibm_write_pci_config = rtas_token("ibm,write-pci-config");
if (naca->interrupt_controller == IC_OPEN_PIC) {
opprop = (unsigned int *)get_property(root,
"platform-open-pic", NULL);
}
root_size_cells = prom_n_size_cells(root);
index = 0;
for (node = root->child; node != NULL; node = node->sibling) {
if (node->type == NULL || strcmp(node->type, "pci") != 0)
continue;
phb = alloc_phb(node, root_size_cells);
if (!phb)
continue;
pci_process_bridge_OF_ranges(phb, node, index == 0);
if (naca->interrupt_controller == IC_OPEN_PIC) {
int addr = root_size_cells * (index + 2) - 1;
openpic_setup_ISU(index, opprop[addr]);
}
index++;
}
pci_devs_phb_init();
return 0;
}
void
fixup_resources(struct pci_dev *dev)
{
......@@ -581,6 +500,55 @@ fixup_resources(struct pci_dev *dev)
}
}
void __init pSeries_pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_controller *phb = PCI_GET_PHB_PTR(bus);
struct resource *res;
int i;
if (bus->parent == NULL) {
/* This is a host bridge - fill in its resources */
phb->bus = bus;
bus->resource[0] = res = &phb->io_resource;
if (!res->flags)
BUG(); /* No I/O resource for this PHB? */
for (i = 0; i < 3; ++i) {
res = &phb->mem_resources[i];
if (!res->flags) {
if (i == 0)
BUG(); /* No memory resource for this PHB? */
}
bus->resource[i+1] = res;
}
} else {
/* This is a subordinate bridge */
pci_read_bridge_bases(bus);
for (i = 0; i < 4; ++i) {
if ((res = bus->resource[i]) == NULL)
continue;
if (!res->flags)
continue;
if (res == pci_find_parent_resource(bus->self, res)) {
/* Transparent resource -- don't try to "fix" it. */
continue;
}
if (res->flags & IORESOURCE_IO) {
unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base;
res->start += offset;
res->end += offset;
} else if (phb->pci_mem_offset
&& (res->flags & IORESOURCE_MEM)) {
if (res->start < phb->pci_mem_offset) {
res->start += phb->pci_mem_offset;
res->end += phb->pci_mem_offset;
}
}
}
}
}
static void check_s7a(void)
{
struct device_node *root;
......@@ -629,17 +597,6 @@ pci_find_hose_for_OF_device(struct device_node *node)
return NULL;
}
/***********************************************************************
* ppc64_pcibios_init
*
* Chance to initialize and structures or variable before PCI Bus walk.
*
***********************************************************************/
void
pSeries_pcibios_init(void)
{
}
/*
* This is called very early before the page table is setup.
*/
......
......@@ -49,7 +49,6 @@ static void fixup_windbond_82c105(struct pci_dev* dev);
void fixup_resources(struct pci_dev* dev);
void iSeries_pcibios_init(void);
void pSeries_pcibios_init(void);
struct pci_controller* hose_head;
struct pci_controller** hose_tail = &hose_head;
......@@ -363,16 +362,33 @@ pcibios_assign_resources(void)
* Allocate pci_controller(phb) initialized common variables.
*/
struct pci_controller * __init
pci_alloc_pci_controller(char *model, enum phb_types controller_type)
pci_alloc_pci_controller(enum phb_types controller_type)
{
struct pci_controller *hose;
PPCDBG(PPCDBG_PHBINIT, "PCI: Allocate pci_controller for %s\n",model);
char *model;
hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller));
if(hose == NULL) {
printk(KERN_ERR "PCI: Allocate pci_controller failed.\n");
return NULL;
}
memset(hose, 0, sizeof(struct pci_controller));
switch(controller_type) {
case phb_type_python:
model = "PHB PY";
break;
case phb_type_speedwagon:
model = "PHB SW";
break;
case phb_type_winnipeg:
model = "PHB WP";
break;
default:
model = "PHB UK";
break;
}
if(strlen(model) < 8)
strcpy(hose->what,model);
else
......@@ -393,9 +409,7 @@ pcibios_init(void)
struct pci_bus *bus;
int next_busno;
#ifndef CONFIG_PPC_ISERIES
pSeries_pcibios_init();
#else
#ifdef CONFIG_PPC_ISERIES
iSeries_pcibios_init();
#endif
......@@ -450,54 +464,7 @@ subsys_initcall(pcibios_init);
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
#ifndef CONFIG_PPC_ISERIES
struct pci_controller *phb = PCI_GET_PHB_PTR(bus);
struct resource *res;
int i;
if (bus->parent == NULL) {
/* This is a host bridge - fill in its resources */
phb->bus = bus;
bus->resource[0] = res = &phb->io_resource;
if (!res->flags)
BUG(); /* No I/O resource for this PHB? */
for (i = 0; i < 3; ++i) {
res = &phb->mem_resources[i];
if (!res->flags) {
if (i == 0)
BUG(); /* No memory resource for this PHB? */
}
bus->resource[i+1] = res;
}
} else {
/* This is a subordinate bridge */
pci_read_bridge_bases(bus);
for (i = 0; i < 4; ++i) {
if ((res = bus->resource[i]) == NULL)
continue;
if (!res->flags)
continue;
if (res == pci_find_parent_resource(bus->self, res)) {
/* Transparent resource -- don't try to "fix" it. */
continue;
}
if (res->flags & IORESOURCE_IO) {
unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base;
res->start += offset;
res->end += offset;
} else if (phb->pci_mem_offset
&& (res->flags & IORESOURCE_MEM)) {
if (res->start < phb->pci_mem_offset) {
res->start += phb->pci_mem_offset;
res->end += phb->pci_mem_offset;
}
}
}
}
#endif
if ( ppc_md.pcibios_fixup_bus )
if (ppc_md.pcibios_fixup_bus)
ppc_md.pcibios_fixup_bus(bus);
}
......
......@@ -14,7 +14,7 @@
extern unsigned long isa_io_base;
extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type);
extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type);
extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
extern struct pci_controller* hose_head;
......
......@@ -2040,11 +2040,11 @@ prom_bi_rec_verify(struct bi_record *bi_recs)
if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
return NULL;
last = (struct bi_record *)bi_recs->data[0];
last = (struct bi_record *)(long)bi_recs->data[0];
if ( last == NULL || last->tag != BI_LAST )
return NULL;
first = (struct bi_record *)last->data[0];
first = (struct bi_record *)(long)last->data[0];
if ( first == NULL || first != bi_recs )
return NULL;
......
......@@ -20,7 +20,8 @@ enum phb_types {
phb_type_unknown = 0x0,
phb_type_hypervisor = 0x1,
phb_type_python = 0x10,
phb_type_speedwagon = 0x11
phb_type_speedwagon = 0x11,
phb_type_winnipeg = 0x12
};
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment