Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 77791
b: refs/heads/master
c: b6d7b66
h: refs/heads/master
i:
  77789: 60b598e
  77787: 9705f16
  77783: 79f0927
  77775: 9baed2d
  77759: 08a0047
v: v3
  • Loading branch information
Paul Mundt committed Jan 28, 2008
1 parent b8d1288 commit ce2cd14
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 385 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d5f68c6dbda8e63df258a0c639f03d7565cf1d50
refs/heads/master: b6d7b666097e79a8908e3c43fd55fd291a95e133
1 change: 1 addition & 0 deletions trunk/arch/sh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ config SH_SIMULATOR
config SH_CAYMAN
bool "Hitachi Cayman"
depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103
select SYS_SUPPORTS_PCI

config SH_HARP
bool "ST50 Harp"
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/sh/drivers/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7785) += pci-sh7780.o ops-sh4.o
obj-$(CONFIG_CPU_SH5) += pci-sh5.o ops-sh5.o

obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
dma-dreamcast.o
Expand All @@ -20,3 +21,4 @@ obj-$(CONFIG_SH_TITAN) += ops-titan.o
obj-$(CONFIG_SH_LANDISK) += ops-landisk.o
obj-$(CONFIG_SH_LBOX_RE2) += ops-lboxre2.o fixups-lboxre2.o
obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += ops-se7780.o fixups-se7780.o
obj-$(CONFIG_SH_CAYMAN) += ops-cayman.o
94 changes: 94 additions & 0 deletions trunk/arch/sh/drivers/pci/ops-cayman.c
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));
}
93 changes: 93 additions & 0 deletions trunk/arch/sh/drivers/pci/ops-sh5.c
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,
};
Loading

0 comments on commit ce2cd14

Please sign in to comment.