Commit cc93d69c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sh: PCI updates

From: Paul Mundt <lethal@Linux-SH.ORG>

This updates the pci-auto code, as well as adding ops and fixups for the
RTS7751R2D board.
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 125190ef
...@@ -12,4 +12,5 @@ obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ ...@@ -12,4 +12,5 @@ obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
dma-dreamcast.o dma-dreamcast.o
obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o
obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
/*
* arch/sh/drivers/pci/fixups-rts7751r2d.c
*
* RTS7751R2D PCI fixups
*
* Copyright (C) 2003 Lineo uSolutions, Inc.
* Copyright (C) 2004 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include "pci-sh7751.h"
#include <asm/io.h>
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
int pci_fixup_pcic(void)
{
unsigned long mcr;
outl(0xfb900047, SH7751_PCICONF1);
outl(0xab000001, SH7751_PCICONF4);
mcr = inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
outl(mcr, SH7751_PCIMCR);
return 0;
}
/*
* linux/arch/sh/kernel/pci-rts7751r2d.c
*
* Author: Ian DaSilva (idasilva@mvista.com)
*
* Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* PCI initialization for the Renesas SH7751R RTS7751R2D board
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <asm/io.h>
#include "pci-sh7751.h"
#include <asm/rts7751r2d/rts7751r2d.h>
int __init pcibios_map_platform_irq(u8 slot, u8 pin)
{
switch (slot) {
case 0: return IRQ_PCISLOT1; /* PCI Extend slot #1 */
case 1: return IRQ_PCISLOT2; /* PCI Extend slot #2 */
case 2: return IRQ_PCMCIA; /* PCI Cardbus Bridge */
case 3: return IRQ_PCIETH; /* Realtek Ethernet controller */
default:
printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
return -1;
}
}
static struct resource sh7751_io_resource = {
.name = "SH7751_IO",
.start = 0x4000,
.end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
.flags = IORESOURCE_IO
};
static struct resource sh7751_mem_resource = {
.name = "SH7751_mem",
.start = SH7751_PCI_MEMORY_BASE,
.end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
.flags = IORESOURCE_MEM
};
extern struct pci_ops sh7751_pci_ops;
struct pci_channel board_pci_channels[] = {
{ &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ NULL, NULL, NULL, 0, 0 },
};
EXPORT_SYMBOL(board_pci_channels);
static struct sh7751_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS3_BASE_ADDR,
.size = 0x03f00000,
},
.flags = SH7751_PCIC_NO_RESET,
};
int __init pcibios_init_platform(void)
{
return sh7751_pcic_init(&sh7751_pci_map);
}
...@@ -61,6 +61,8 @@ static struct sh7751_pci_address_map sh7751_pci_map = { ...@@ -61,6 +61,8 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
.base = SH7751_CS2_BASE_ADDR, .base = SH7751_CS2_BASE_ADDR,
.size = SNAPGEAR_LSR1_SIZE, .size = SNAPGEAR_LSR1_SIZE,
}, },
.flags = SH7751_PCIC_NO_RESET,
}; };
/* /*
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#define DEBUG #undef DEBUG
#ifdef DEBUG #ifdef DEBUG
#define DBG(x...) printk(x) #define DBG(x...) printk(x)
#else #else
...@@ -106,7 +106,8 @@ static void __init ...@@ -106,7 +106,8 @@ static void __init
pciauto_setup_bars(struct pci_channel *hose, pciauto_setup_bars(struct pci_channel *hose,
int top_bus, int top_bus,
int current_bus, int current_bus,
int pci_devfn) int pci_devfn,
int bar_limit)
{ {
u32 bar_response, bar_size, bar_value; u32 bar_response, bar_size, bar_value;
u32 bar, addr_mask, bar_nr = 0; u32 bar, addr_mask, bar_nr = 0;
...@@ -114,7 +115,8 @@ pciauto_setup_bars(struct pci_channel *hose, ...@@ -114,7 +115,8 @@ pciauto_setup_bars(struct pci_channel *hose,
u32 * lower_limit; u32 * lower_limit;
int found_mem64 = 0; int found_mem64 = 0;
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) { for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
u32 bar_addr; u32 bar_addr;
/* Read the old BAR value */ /* Read the old BAR value */
...@@ -123,6 +125,7 @@ pciauto_setup_bars(struct pci_channel *hose, ...@@ -123,6 +125,7 @@ pciauto_setup_bars(struct pci_channel *hose,
pci_devfn, pci_devfn,
bar, bar,
&bar_addr); &bar_addr);
#endif
/* Tickle the BAR and get the response */ /* Tickle the BAR and get the response */
early_write_config_dword(hose, top_bus, early_write_config_dword(hose, top_bus,
...@@ -137,6 +140,7 @@ pciauto_setup_bars(struct pci_channel *hose, ...@@ -137,6 +140,7 @@ pciauto_setup_bars(struct pci_channel *hose,
bar, bar,
&bar_response); &bar_response);
#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
/* /*
* Write the old BAR value back out, only update the BAR * Write the old BAR value back out, only update the BAR
* if we implicitly want resources to be updated, which * if we implicitly want resources to be updated, which
...@@ -147,6 +151,7 @@ pciauto_setup_bars(struct pci_channel *hose, ...@@ -147,6 +151,7 @@ pciauto_setup_bars(struct pci_channel *hose,
pci_devfn, pci_devfn,
bar, bar,
bar_addr); bar_addr);
#endif
/* If BAR is not implemented go to the next BAR */ /* If BAR is not implemented go to the next BAR */
if (!bar_response) if (!bar_response)
...@@ -287,6 +292,11 @@ pciauto_postscan_setup_bridge(struct pci_channel *hose, ...@@ -287,6 +292,11 @@ pciauto_postscan_setup_bridge(struct pci_channel *hose,
{ {
u32 temp; u32 temp;
/*
* [jsun] we always bump up baselines a little, so that if there
* nothing behind P2P bridge, we don't wind up overlapping IO/MEM
* spaces.
*/
pciauto_lower_memspc += 1; pciauto_lower_memspc += 1;
pciauto_lower_iospc += 1; pciauto_lower_iospc += 1;
...@@ -352,6 +362,7 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, ...@@ -352,6 +362,7 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
{ {
u32 temp; u32 temp;
#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
/* /*
* [jsun] we always bump up baselines a little, so that if there * [jsun] we always bump up baselines a little, so that if there
* nothing behind P2P bridge, we don't wind up overlapping IO/MEM * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
...@@ -359,6 +370,7 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, ...@@ -359,6 +370,7 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
*/ */
pciauto_lower_memspc += 1; pciauto_lower_memspc += 1;
pciauto_lower_iospc += 1; pciauto_lower_iospc += 1;
#endif
/* /*
* Configure subordinate bus number. The PCI subsystem * Configure subordinate bus number. The PCI subsystem
...@@ -384,6 +396,10 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, ...@@ -384,6 +396,10 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
* configured by this routine to happily live behind a * configured by this routine to happily live behind a
* P2P bridge in a system. * P2P bridge in a system.
*/ */
#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
pciauto_lower_memspc += 0x00400000;
pciauto_lower_iospc += 0x00004000;
#endif
/* Align memory and I/O to 4KB and 4 byte boundaries. */ /* Align memory and I/O to 4KB and 4 byte boundaries. */
pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
...@@ -400,8 +416,8 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, ...@@ -400,8 +416,8 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
early_read_config_dword(hose, top_bus, current_bus, pci_devfn, early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
PCI_COMMAND, &temp); PCI_COMMAND, &temp);
early_write_config_dword(hose, top_bus, current_bus, pci_devfn, early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
| PCI_COMMAND_MASTER); PCI_COMMAND_MASTER);
} }
#define PCIAUTO_IDE_MODE_MASK 0x05 #define PCIAUTO_IDE_MODE_MASK 0x05
...@@ -455,6 +471,9 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) ...@@ -455,6 +471,9 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
DBG(" Bridge: primary=%.2x, secondary=%.2x\n", DBG(" Bridge: primary=%.2x, secondary=%.2x\n",
current_bus, sub_bus + 1); current_bus, sub_bus + 1);
#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
#endif
pciauto_prescan_setup_bridge(hose, top_bus, current_bus, pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
pci_devfn, sub_bus); pci_devfn, sub_bus);
DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
...@@ -470,7 +489,7 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) ...@@ -470,7 +489,7 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
current_bus, sub_bus + 1); current_bus, sub_bus + 1);
DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
/* Place CardBus Socket/ExCA registers */ /* Place CardBus Socket/ExCA registers */
pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn); pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
pciauto_prescan_setup_cardbus_bridge(hose, top_bus, pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
current_bus, pci_devfn, sub_bus); current_bus, pci_devfn, sub_bus);
...@@ -509,7 +528,7 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) ...@@ -509,7 +528,7 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
PCI_LATENCY_TIMER, 0x80); PCI_LATENCY_TIMER, 0x80);
/* Allocate PCI I/O and/or memory space */ /* Allocate PCI I/O and/or memory space */
pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn); pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5);
} }
return sub_bus; return sub_bus;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "pci-sh7751.h" #include "pci-sh7751.h"
static unsigned int pci_probe = PCI_PROBE_CONF1; static unsigned int pci_probe = PCI_PROBE_CONF1;
extern int pci_fixup_pcic(void);
/* /*
* Direct access to PCI hardware... * Direct access to PCI hardware...
...@@ -74,7 +75,8 @@ static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn, ...@@ -74,7 +75,8 @@ static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn,
} }
/* /*
* Since SH7751 only does 32bit access we'll have to do a read,mask,write operation. * Since SH7751 only does 32bit access we'll have to do a read,
* mask,write operation.
* We'll allow an odd byte offset, though it should be illegal. * We'll allow an odd byte offset, though it should be illegal.
*/ */
static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn, static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn,
...@@ -156,6 +158,7 @@ static int __init pci_check_direct(void) ...@@ -156,6 +158,7 @@ static int __init pci_check_direct(void)
* Handle bus scanning and fixups .... * Handle bus scanning and fixups ....
*/ */
#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
static void __init pci_fixup_ide_bases(struct pci_dev *d) static void __init pci_fixup_ide_bases(struct pci_dev *d)
{ {
int i; int i;
...@@ -174,11 +177,13 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) ...@@ -174,11 +177,13 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
} }
} }
} }
#endif
/* Add future fixups here... */ /* Add future fixups here... */
struct pci_fixup pcibios_fixups[] = { struct pci_fixup pcibios_fixups[] = {
#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
#endif
{ 0 } { 0 }
}; };
...@@ -261,11 +266,11 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) ...@@ -261,11 +266,11 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
outl(word, PCI_REG(SH7751_PCICLKR)); outl(word, PCI_REG(SH7751_PCICLKR));
/* /*
* XXX: This code is unused for the SnapGear boards as it is done in * This code is unused for some boards as it is done in the
* the bootloader and doing it here means the MAC addresses loaded by * bootloader and doing it here means the MAC addresses loaded
* the bootloader get lost. * by the bootloader get lost.
*/ */
#ifndef CONFIG_SH_SECUREEDGE5410 if (!(map->flags & SH7751_PCIC_NO_RESET)) {
/* toggle PCI reset pin */ /* toggle PCI reset pin */
word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
outl(word,PCI_REG(SH7751_PCICR)); outl(word,PCI_REG(SH7751_PCICR));
...@@ -273,7 +278,7 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) ...@@ -273,7 +278,7 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
mdelay(100); mdelay(100);
word = SH7751_PCICR_PREFIX; word = SH7751_PCICR_PREFIX;
outl(word,PCI_REG(SH7751_PCICR)); outl(word,PCI_REG(SH7751_PCICR));
#endif }
/* set the command/status bits to: /* set the command/status bits to:
* Wait Cycle Control + Parity Enable + Bus Master + * Wait Cycle Control + Parity Enable + Bus Master +
...@@ -364,6 +369,10 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) ...@@ -364,6 +369,10 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
* DMA interrupts... * DMA interrupts...
*/ */
#ifdef CONFIG_SH_RTS7751R2D
pci_fixup_pcic();
#endif
/* SH7751 init done, set central function init complete */ /* SH7751 init done, set central function init complete */
/* use round robin mode to stop a device starving/overruning */ /* use round robin mode to stop a device starving/overruning */
word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM; word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM;
......
...@@ -234,6 +234,7 @@ ...@@ -234,6 +234,7 @@
#define SH7751_PCIWCR2 0x1EC /* Wait Control 2 Register */ #define SH7751_PCIWCR2 0x1EC /* Wait Control 2 Register */
#define SH7751_PCIWCR3 0x1F0 /* Wait Control 3 Register */ #define SH7751_PCIWCR3 0x1F0 /* Wait Control 3 Register */
#define SH7751_PCIMCR 0x1F4 /* Memory Control Register */ #define SH7751_PCIMCR 0x1F4 /* Memory Control Register */
#define SH7751_PCIBCR3 0x1f8 /* Memory BCR3 Register */
#define SH7751_PCIPCTR 0x200 /* Port Control Register */ #define SH7751_PCIPCTR 0x200 /* Port Control Register */
#define SH7751_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */ #define SH7751_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */
#define SH7751_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */ #define SH7751_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */
...@@ -256,6 +257,8 @@ ...@@ -256,6 +257,8 @@
/* Memory Control Registers */ /* Memory Control Registers */
#define SH7751_BCR1 0xFF800000 /* Memory BCR1 Register */ #define SH7751_BCR1 0xFF800000 /* Memory BCR1 Register */
#define SH7751_BCR2 0xFF800004 /* Memory BCR2 Register */ #define SH7751_BCR2 0xFF800004 /* Memory BCR2 Register */
#define SH7751_BCR3 0xFF800050 /* Memory BCR3 Register */
#define SH7751_BCR4 0xFE0A00F0 /* Memory BCR4 Register */
#define SH7751_WCR1 0xFF800008 /* Wait Control 1 Register */ #define SH7751_WCR1 0xFF800008 /* Wait Control 1 Register */
#define SH7751_WCR2 0xFF80000C /* Wait Control 2 Register */ #define SH7751_WCR2 0xFF80000C /* Wait Control 2 Register */
#define SH7751_WCR3 0xFF800010 /* Wait Control 3 Register */ #define SH7751_WCR3 0xFF800010 /* Wait Control 3 Register */
...@@ -274,6 +277,9 @@ ...@@ -274,6 +277,9 @@
/* General PCI values */ /* General PCI values */
#define SH7751_PCI_HOST_BRIDGE 0x6 #define SH7751_PCI_HOST_BRIDGE 0x6
/* Flags */
#define SH7751_PCIC_NO_RESET 0x0001
/* External functions defined per platform i.e. Big Sur, SE... (these could be routed /* External functions defined per platform i.e. Big Sur, SE... (these could be routed
* through the machine vectors... */ * through the machine vectors... */
extern int pcibios_init_platform(void); extern int pcibios_init_platform(void);
...@@ -287,6 +293,7 @@ struct sh7751_pci_address_space { ...@@ -287,6 +293,7 @@ struct sh7751_pci_address_space {
struct sh7751_pci_address_map { struct sh7751_pci_address_map {
struct sh7751_pci_address_space window0; struct sh7751_pci_address_space window0;
struct sh7751_pci_address_space window1; struct sh7751_pci_address_space window1;
unsigned long flags;
}; };
/* arch/sh/drivers/pci/pci-sh7751.c */ /* arch/sh/drivers/pci/pci-sh7751.c */
......
...@@ -25,7 +25,7 @@ static int __init pcibios_init(void) ...@@ -25,7 +25,7 @@ static int __init pcibios_init(void)
#ifdef CONFIG_PCI_AUTO #ifdef CONFIG_PCI_AUTO
/* assign resources */ /* assign resources */
busno=0; busno = 0;
for (p = board_pci_channels; p->pci_ops != NULL; p++) { for (p = board_pci_channels; p->pci_ops != NULL; p++) {
busno = pciauto_assign_resources(busno, p) + 1; busno = pciauto_assign_resources(busno, p) + 1;
} }
......
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