Commit b6d7b666 authored by Paul Mundt's avatar Paul Mundt

sh: Get the SH-5 PCI support building.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent d5f68c6d
...@@ -512,6 +512,7 @@ config SH_SIMULATOR ...@@ -512,6 +512,7 @@ config SH_SIMULATOR
config SH_CAYMAN config SH_CAYMAN
bool "Hitachi Cayman" bool "Hitachi Cayman"
depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103 depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103
select SYS_SUPPORTS_PCI
config SH_HARP config SH_HARP
bool "ST50 Harp" bool "ST50 Harp"
......
...@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o ...@@ -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_SH7751R) += pci-sh7751.o ops-sh4.o
obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.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_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 \ obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
dma-dreamcast.o dma-dreamcast.o
...@@ -20,3 +21,4 @@ obj-$(CONFIG_SH_TITAN) += ops-titan.o ...@@ -20,3 +21,4 @@ obj-$(CONFIG_SH_TITAN) += ops-titan.o
obj-$(CONFIG_SH_LANDISK) += ops-landisk.o obj-$(CONFIG_SH_LANDISK) += ops-landisk.o
obj-$(CONFIG_SH_LBOX_RE2) += ops-lboxre2.o fixups-lboxre2.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_7780_SOLUTION_ENGINE) += ops-se7780.o fixups-se7780.o
obj-$(CONFIG_SH_CAYMAN) += ops-cayman.o
#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));
}
/*
* 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,
};
This diff is collapsed.
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
* *
* Definitions for the SH5 PCI hardware. * Definitions for the SH5 PCI hardware.
*/ */
#ifndef __PCI_SH5_H
#define __PCI_SH5_H
/* Product ID */ /* Product ID */
#define PCISH5_PID 0x350d #define PCISH5_PID 0x350d
...@@ -73,13 +75,12 @@ ...@@ -73,13 +75,12 @@
#define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */ #define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */
#define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */ #define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */
/* Base address of registers */ /* Base address of registers */
#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000) #define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000)
#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000) #define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000)
/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */ /* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */
extern unsigned long pcicr_virt;
/* Register selection macro */ /* Register selection macro */
#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x)) #define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x))
/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */ /* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
...@@ -104,4 +105,9 @@ ...@@ -104,4 +105,9 @@
#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18) #define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18)
#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18) #define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18)
extern struct pci_ops sh5_pci_ops;
/* arch/sh/drivers/pci/pci-sh5.c */
int sh5pci_init(unsigned long memStart, unsigned long memSize);
#endif /* __PCI_SH5_H */
...@@ -71,7 +71,7 @@ subsys_initcall(pcibios_init); ...@@ -71,7 +71,7 @@ subsys_initcall(pcibios_init);
* Called after each bus is probed, but before its children * Called after each bus is probed, but before its children
* are examined. * are examined.
*/ */
void __devinit pcibios_fixup_bus(struct pci_bus *bus) void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus)
{ {
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
} }
......
...@@ -38,9 +38,12 @@ extern struct pci_channel board_pci_channels[]; ...@@ -38,9 +38,12 @@ extern struct pci_channel board_pci_channels[];
#if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785) #if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
#define PCI_IO_AREA 0xFE400000 #define PCI_IO_AREA 0xFE400000
#define PCI_IO_SIZE 0x00400000 #define PCI_IO_SIZE 0x00400000
#elif defined(CONFIG_CPU_SH5)
extern unsigned long PCI_IO_AREA;
#define PCI_IO_SIZE 0x00010000
#else #else
#define PCI_IO_AREA 0xFE240000 #define PCI_IO_AREA 0xFE240000
#define PCI_IO_SIZE 0X00040000 #define PCI_IO_SIZE 0x00040000
#endif #endif
#define PCI_MEM_SIZE 0x01000000 #define PCI_MEM_SIZE 0x01000000
......
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