Commit c4c3f3ff authored by Jesse Barnes's avatar Jesse Barnes Committed by David Mosberger

[PATCH] ia64: sn2 pci fixes (among others)

sn2 still doesn't use ACPI to describe PCI busses on the system (I'm
working on it), so we have to do it the old fashioned way.  This patch
also includes a few other fixes.
parent 7dea98b2
......@@ -40,15 +40,12 @@
#include <linux/namei.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/dcache.h>
#include <asm/sn/hwgfs.h>
extern struct vfsmount *hwgfs_vfsmount;
/* TODO: Move this to some .h file or, more likely, use a slightly
different interface from lookup_create. */
extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
static int
walk_parents_mkdir(
const char **path,
......
......@@ -30,17 +30,13 @@
#include <asm/sn/pci/pcibr_private.h>
#include <asm/sn/pci/bridge.h>
#ifdef DEBUG_CONFIG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/*
* These routines are only used during sn_pci_init for probing each bus, and
* can probably be removed with a little more cleanup now that the SAL routines
* work on sn2.
*/
#ifdef CONFIG_PCI
extern vertex_hdl_t pci_bus_to_vertex(unsigned char);
extern vertex_hdl_t devfn_to_vertex(unsigned char bus, unsigned char devfn);
int sn_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
......@@ -49,10 +45,12 @@ int sn_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
vertex_hdl_t device_vertex;
device_vertex = devfn_to_vertex(bus->number, devfn);
if (!device_vertex)
return PCIBIOS_DEVICE_NOT_FOUND;
res = pciio_config_get(device_vertex, (unsigned) where, size);
*val = (unsigned int) res;
res = pciio_config_get(device_vertex, (unsigned)where, size);
*val = (u32)res;
return PCIBIOS_SUCCESSFUL;
}
......@@ -61,79 +59,21 @@ int sn_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size
vertex_hdl_t device_vertex;
device_vertex = devfn_to_vertex(bus->number, devfn);
if (!device_vertex)
return PCIBIOS_DEVICE_NOT_FOUND;
pciio_config_set( device_vertex, (unsigned)where, size, (uint64_t) val);
pciio_config_set(device_vertex, (unsigned)where, size, (uint64_t)val);
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops sn_pci_ops = {
.read = sn_read_config,
.write = sn_write_config
.write = sn_write_config,
};
/*
* sn_pci_find_bios - SNIA64 pci_find_bios() platform specific code.
*/
void __init
sn_pci_find_bios(void)
{
extern struct pci_ops *pci_root_ops;
/*
* Go initialize our IO Infrastructure ..
*/
extern void sgi_master_io_infr_init(void);
sgi_master_io_infr_init();
/* sn_io_infrastructure_init(); */
pci_root_ops = &sn_pci_ops;
}
void
pci_fixup_ioc3(struct pci_dev *d)
{
int i;
unsigned int size;
/* IOC3 only decodes 0x20 bytes of the config space, reading
* beyond that is relatively benign but writing beyond that
* (especially the base address registers) will shut down the
* pci bus...so avoid doing so.
* NOTE: this means we can't program the intr_pin into the device,
* currently we hack this with special code in
* sgi_pci_intr_support()
*/
DBG("pci_fixup_ioc3: Fixing base addresses for ioc3 device %s\n", d->slot_name);
/* I happen to know from the spec that the ioc3 needs only 0xfffff
* The standard pci trick of writing ~0 to the baddr and seeing
* what comes back doesn't work with the ioc3
*/
size = 0xfffff;
d->resource[0].end = (unsigned long) d->resource[0].start + (unsigned long) size;
/*
* Zero out the resource structure .. because we did not go through
* the normal PCI Infrastructure Init, garbbage are left in these
* fileds.
*/
for (i = 1; i <= PCI_ROM_RESOURCE; i++) {
d->resource[i].start = 0UL;
d->resource[i].end = 0UL;
d->resource[i].flags = 0UL;
}
d->subsystem_vendor = 0;
d->subsystem_device = 0;
}
#else
void sn_pci_find_bios(void) {}
void pci_fixup_ioc3(struct pci_dev *d) {}
struct list_head pci_root_buses;
struct list_head pci_root_buses;
struct list_head pci_devices;
#endif /* CONFIG_PCI */
......@@ -411,34 +411,6 @@ sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int
}
}
/*
* Most drivers currently do not properly tell the arch specific pci dma
* interfaces whether they can handle A64. Here is where we privately
* keep track of this.
*/
static void __init
set_sn_pci64(struct pci_dev *dev)
{
unsigned short vendor = dev->vendor;
unsigned short device = dev->device;
if (vendor == PCI_VENDOR_ID_QLOGIC) {
if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) ||
(device == PCI_DEVICE_ID_QLOGIC_ISP2200)) {
SET_PCIA64(dev);
return;
}
}
if (vendor == PCI_VENDOR_ID_SGI) {
if (device == PCI_DEVICE_ID_SGI_IOC3) {
SET_PCIA64(dev);
return;
}
}
}
/*
* sn_pci_fixup() - This routine is called when platform_pci_fixup() is
* invoked at the end of pcibios_init() to link the Linux pci
......@@ -455,10 +427,9 @@ sn_pci_fixup(int arg)
struct sn_widget_sysdata *widget_sysdata;
struct sn_device_sysdata *device_sysdata;
pciio_intr_t intr_handle;
int cpuid, bit;
int cpuid;
vertex_hdl_t device_vertex;
pciio_intr_line_t lines;
extern void sn_pci_find_bios(void);
extern int numnodes;
int cnode;
......@@ -466,8 +437,11 @@ sn_pci_fixup(int arg)
#ifdef CONFIG_PROC_FS
extern void register_sn_procfs(void);
#endif
extern void irix_io_init(void);
init_hcl();
irix_io_init();
sn_pci_find_bios();
for (cnode = 0; cnode < numnodes; cnode++) {
extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int);
intr_init_vecblk(NODEPDA(cnode), cnode, 0);
......@@ -512,32 +486,25 @@ sn_pci_fixup(int arg)
unsigned int irq;
int idx;
u16 cmd;
vertex_hdl_t vhdl;
unsigned long size;
extern int bit_pos_to_irq(int);
if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
device_dev->device == PCI_DEVICE_ID_SGI_IOC3) {
extern void pci_fixup_ioc3(struct pci_dev *d);
pci_fixup_ioc3(device_dev);
}
/* Set the device vertex */
device_sysdata = kmalloc(sizeof(struct sn_device_sysdata),
GFP_KERNEL);
device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn);
device_sysdata->isa64 = 0;
/*
* Set the xbridge Device(X) Write Buffer Flush and Xbow Flush
* register addresses.
*/
(void) set_flush_addresses(device_dev, device_sysdata);
device_vertex = device_sysdata->vhdl;
device_dev->sysdata = (void *) device_sysdata;
set_sn_pci64(device_dev);
set_isPIC(device_sysdata);
/*
* Set the xbridge Device(X) Write Buffer Flush and Xbow Flush
* register addresses.
*/
set_flush_addresses(device_dev, device_sysdata);
pci_read_config_word(device_dev, PCI_COMMAND, &cmd);
/*
......@@ -546,13 +513,12 @@ sn_pci_fixup(int arg)
* read from the card and it was set in the card by our
* Infrastructure ..
*/
vhdl = device_sysdata->vhdl;
for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
size = 0;
size = device_dev->resource[idx].end -
device_dev->resource[idx].start;
if (size) {
device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(device_vertex, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET;
}
else
......@@ -567,28 +533,6 @@ sn_pci_fixup(int arg)
if (device_dev->resource[idx].flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
#if 0
/*
* Software WAR for a Software BUG.
* This is only temporary.
* See PV 872791
*/
/*
* Now handle the ROM resource ..
*/
size = device_dev->resource[PCI_ROM_RESOURCE].end -
device_dev->resource[PCI_ROM_RESOURCE].start;
if (size) {
device_dev->resource[PCI_ROM_RESOURCE].start =
(unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0,
size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET;
device_dev->resource[PCI_ROM_RESOURCE].end =
device_dev->resource[PCI_ROM_RESOURCE].start + size;
}
#endif
/*
* Update the Command Word on the Card.
......@@ -597,14 +541,8 @@ sn_pci_fixup(int arg)
/* bit gets dropped .. no harm */
pci_write_config_word(device_dev, PCI_COMMAND, cmd);
pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines);
if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
lines = 1;
}
device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata;
device_vertex = device_sysdata->vhdl;
pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN,
(unsigned char *)&lines);
irqpdaindr->current = device_dev;
intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex);
......@@ -622,7 +560,8 @@ sn_pci_fixup(int arg)
size = device_dev->resource[idx].end -
device_dev->resource[idx].start;
if (size == 0) continue;
if (size == 0)
continue;
for (i=0; i<8; i++) {
if (ibits & (1 << i) ) {
......@@ -636,22 +575,6 @@ sn_pci_fixup(int arg)
}
}
#ifdef ajmtestintr
{
int slot = PCI_SLOT(device_dev->devfn);
static int timer_set = 0;
pcibr_intr_t pcibr_intr = (pcibr_intr_t)intr_handle;
pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft;
extern void intr_test_handle_intr(int, void*, struct pt_regs *);
if (!timer_set) {
intr_test_set_timer();
timer_set = 1;
}
intr_test_register_irq(irq, pcibr_soft, slot);
request_irq(irq, intr_test_handle_intr,0,NULL, NULL);
}
#endif
}
/*
......@@ -928,3 +851,37 @@ pci_bus_to_hcl_cvlink(void)
return(0);
}
/*
* Ugly hack to get PCI setup until we have a proper ACPI namespace.
*/
extern struct pci_ops sn_pci_ops;
int __init
sn_pci_init (void)
{
# define PCI_BUSES_TO_SCAN 256
int i = 0;
struct pci_controller *controller;
/*
* set pci_raw_ops, etc.
*/
sn_pci_fixup(0);
controller = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
if (controller) {
memset(controller, 0, sizeof(struct pci_controller));
/* just allocate some devices and fill in the pci_dev structs */
for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
pci_scan_bus(i, &sn_pci_ops, controller);
}
/*
* actually find devices and fill in hwgraph structs
*/
sn_pci_fixup(1);
return 0;
}
subsys_initcall(sn_pci_init);
......@@ -9,15 +9,13 @@
#include <linux/types.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/sn_cpuid.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/pda.h>
#include <linux/smp.h>
extern int init_hcl(void);
/*
* per_hub_init
......@@ -80,30 +78,3 @@ per_hub_init(cnodeid_t cnode)
/* Initialize error interrupts for this hub. */
hub_error_init(cnode);
}
/*
* This routine is responsible for the setup of all the IRIX hwgraph style
* stuff that's been pulled into linux. It's called by sn_pci_find_bios which
* is called just before the generic Linux PCI layer does its probing (by
* platform_pci_fixup aka sn_pci_fixup).
*
* It is very IMPORTANT that this call is only made by the Master CPU!
*
*/
void
sgi_master_io_infr_init(void)
{
extern void irix_io_init(void);
init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */
irix_io_init(); /* Do IRIX Compatibility IO Init */
#ifdef CONFIG_KDB
{
extern void kdba_io_init(void);
kdba_io_init();
}
#endif
}
......@@ -26,6 +26,12 @@ void
sn_flush_all_caches(long flush_addr, long bytes)
{
flush_icache_range(flush_addr, flush_addr+bytes);
/*
* The last call may have returned before the caches
* were actually flushed, so we call it again to make
* sure.
*/
flush_icache_range(flush_addr, flush_addr+bytes);
mb();
}
EXPORT_SYMBOL(sn_flush_all_caches);
......@@ -105,5 +105,6 @@ extern int hwgraph_info_remove_LBL(vertex_hdl_t, char *, arbitrary_info_t *);
extern char * vertex_to_name(vertex_hdl_t, char *, uint);
extern graph_error_t hwgraph_vertex_unref(vertex_hdl_t);
extern int init_hcl(void);
#endif /* _ASM_IA64_SN_HCL_H */
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