-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sh: Get the SH-5 PCI support building.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
- Loading branch information
Paul Mundt
committed
Jan 28, 2008
1 parent
d5f68c6
commit b6d7b66
Showing
8 changed files
with
275 additions
and
384 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#include <linux/kernel.h> | ||
#include <linux/init.h> | ||
#include <linux/pci.h> | ||
#include <linux/types.h> | ||
#include <asm/cpu/irq.h> | ||
#include "pci-sh5.h" | ||
|
||
static inline u8 bridge_swizzle(u8 pin, u8 slot) | ||
{ | ||
return (((pin - 1) + slot) % 4) + 1; | ||
} | ||
|
||
int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
{ | ||
int result = -1; | ||
|
||
/* The complication here is that the PCI IRQ lines from the Cayman's 2 | ||
5V slots get into the CPU via a different path from the IRQ lines | ||
from the 3 3.3V slots. Thus, we have to detect whether the card's | ||
interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling' | ||
at the point where we cross from 5V to 3.3V is not the normal case. | ||
The added complication is that we don't know that the 5V slots are | ||
always bus 2, because a card containing a PCI-PCI bridge may be | ||
plugged into a 3.3V slot, and this changes the bus numbering. | ||
Also, the Cayman has an intermediate PCI bus that goes a custom | ||
expansion board header (and to the secondary bridge). This bus has | ||
never been used in practice. | ||
The 1ary onboard PCI-PCI bridge is device 3 on bus 0 | ||
The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of | ||
the 1ary bridge. | ||
*/ | ||
|
||
struct slot_pin { | ||
int slot; | ||
int pin; | ||
} path[4]; | ||
int i=0; | ||
|
||
while (dev->bus->number > 0) { | ||
|
||
slot = path[i].slot = PCI_SLOT(dev->devfn); | ||
pin = path[i].pin = bridge_swizzle(pin, slot); | ||
dev = dev->bus->self; | ||
i++; | ||
if (i > 3) panic("PCI path to root bus too long!\n"); | ||
} | ||
|
||
slot = PCI_SLOT(dev->devfn); | ||
/* This is the slot on bus 0 through which the device is eventually | ||
reachable. */ | ||
|
||
/* Now work back up. */ | ||
if ((slot < 3) || (i == 0)) { | ||
/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final | ||
swizzle now. */ | ||
result = IRQ_INTA + bridge_swizzle(pin, slot) - 1; | ||
} else { | ||
i--; | ||
slot = path[i].slot; | ||
pin = path[i].pin; | ||
if (slot > 0) { | ||
panic("PCI expansion bus device found - not handled!\n"); | ||
} else { | ||
if (i > 0) { | ||
/* 5V slots */ | ||
i--; | ||
slot = path[i].slot; | ||
pin = path[i].pin; | ||
/* 'pin' was swizzled earlier wrt slot, don't do it again. */ | ||
result = IRQ_P2INTA + (pin - 1); | ||
} else { | ||
/* IRQ for 2ary PCI-PCI bridge : unused */ | ||
result = -1; | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
struct pci_channel board_pci_channels[] = { | ||
{ &sh5_pci_ops, NULL, NULL, 0, 0xff }, | ||
{ NULL, NULL, NULL, 0, 0 }, | ||
}; | ||
EXPORT_SYMBOL(board_pci_channels); | ||
|
||
int __init pcibios_init_platform(void) | ||
{ | ||
return sh5pci_init(__pa(memory_start), | ||
__pa(memory_end) - __pa(memory_start)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Support functions for the SH5 PCI hardware. | ||
* | ||
* Copyright (C) 2001 David J. Mckay (david.mckay@st.com) | ||
* Copyright (C) 2003, 2004 Paul Mundt | ||
* Copyright (C) 2004 Richard Curnow | ||
* | ||
* May be copied or modified under the terms of the GNU General Public | ||
* License. See linux/COPYING for more information. | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/rwsem.h> | ||
#include <linux/smp.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/init.h> | ||
#include <linux/errno.h> | ||
#include <linux/pci.h> | ||
#include <linux/delay.h> | ||
#include <linux/types.h> | ||
#include <linux/irq.h> | ||
#include <asm/pci.h> | ||
#include <asm/io.h> | ||
#include "pci-sh5.h" | ||
|
||
static void __init pci_fixup_ide_bases(struct pci_dev *d) | ||
{ | ||
int i; | ||
|
||
/* | ||
* PCI IDE controllers use non-standard I/O port decoding, respect it. | ||
*/ | ||
if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) | ||
return; | ||
printk("PCI: IDE base address fixup for %s\n", pci_name(d)); | ||
for(i=0; i<4; i++) { | ||
struct resource *r = &d->resource[i]; | ||
if ((r->start & ~0x80) == 0x374) { | ||
r->start |= 2; | ||
r->end = r->start; | ||
} | ||
} | ||
} | ||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); | ||
|
||
char * __devinit pcibios_setup(char *str) | ||
{ | ||
return str; | ||
} | ||
|
||
static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where, | ||
int size, u32 *val) | ||
{ | ||
SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); | ||
|
||
switch (size) { | ||
case 1: | ||
*val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3)); | ||
break; | ||
case 2: | ||
*val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2)); | ||
break; | ||
case 4: | ||
*val = SH5PCI_READ(PDR); | ||
break; | ||
} | ||
|
||
return PCIBIOS_SUCCESSFUL; | ||
} | ||
|
||
static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where, | ||
int size, u32 val) | ||
{ | ||
SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); | ||
|
||
switch (size) { | ||
case 1: | ||
SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); | ||
break; | ||
case 2: | ||
SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); | ||
break; | ||
case 4: | ||
SH5PCI_WRITE(PDR, val); | ||
break; | ||
} | ||
|
||
return PCIBIOS_SUCCESSFUL; | ||
} | ||
|
||
struct pci_ops sh5_pci_ops = { | ||
.read = sh5pci_read, | ||
.write = sh5pci_write, | ||
}; |
Oops, something went wrong.