mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
28
arch/sh/drivers/pci/Makefile
Normal file
28
arch/sh/drivers/pci/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Makefile for the PCI specific kernel interface routines under Linux.
|
||||
#
|
||||
obj-y += common.o pci.o
|
||||
|
||||
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_SH7763) += 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_SH7786) += pcie-sh7786.o ops-sh7786.o
|
||||
obj-$(CONFIG_CPU_SH5) += pci-sh5.o ops-sh5.o
|
||||
|
||||
obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \
|
||||
pci-dreamcast.o
|
||||
obj-$(CONFIG_SH_SECUREEDGE5410) += fixups-snapgear.o
|
||||
obj-$(CONFIG_SH_7751_SOLUTION_ENGINE) += fixups-se7751.o
|
||||
obj-$(CONFIG_SH_RTS7751R2D) += fixups-rts7751r2d.o
|
||||
obj-$(CONFIG_SH_SH03) += fixups-sh03.o
|
||||
obj-$(CONFIG_SH_HIGHLANDER) += fixups-r7780rp.o
|
||||
obj-$(CONFIG_SH_SH7785LCR) += fixups-r7780rp.o
|
||||
obj-$(CONFIG_SH_SDK7786) += fixups-sdk7786.o
|
||||
obj-$(CONFIG_SH_SDK7780) += fixups-sdk7780.o
|
||||
obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += fixups-sdk7780.o
|
||||
obj-$(CONFIG_SH_TITAN) += fixups-titan.o
|
||||
obj-$(CONFIG_SH_LANDISK) += fixups-landisk.o
|
||||
obj-$(CONFIG_SH_LBOX_RE2) += fixups-rts7751r2d.o
|
||||
obj-$(CONFIG_SH_CAYMAN) += fixups-cayman.o
|
162
arch/sh/drivers/pci/common.c
Normal file
162
arch/sh/drivers/pci/common.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
/*
|
||||
* These functions are used early on before PCI scanning is done
|
||||
* and all of the pci_dev and pci_bus structures have been created.
|
||||
*/
|
||||
static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
|
||||
int top_bus, int busnr, int devfn)
|
||||
{
|
||||
static struct pci_dev dev;
|
||||
static struct pci_bus bus;
|
||||
|
||||
dev.bus = &bus;
|
||||
dev.sysdata = hose;
|
||||
dev.devfn = devfn;
|
||||
bus.number = busnr;
|
||||
bus.sysdata = hose;
|
||||
bus.ops = hose->pci_ops;
|
||||
|
||||
if(busnr != top_bus)
|
||||
/* Fake a parent bus structure. */
|
||||
bus.parent = &bus;
|
||||
else
|
||||
bus.parent = NULL;
|
||||
|
||||
return &dev;
|
||||
}
|
||||
|
||||
#define EARLY_PCI_OP(rw, size, type) \
|
||||
int __init early_##rw##_config_##size(struct pci_channel *hose, \
|
||||
int top_bus, int bus, int devfn, int offset, type value) \
|
||||
{ \
|
||||
return pci_##rw##_config_##size( \
|
||||
fake_pci_dev(hose, top_bus, bus, devfn), \
|
||||
offset, value); \
|
||||
}
|
||||
|
||||
EARLY_PCI_OP(read, byte, u8 *)
|
||||
EARLY_PCI_OP(read, word, u16 *)
|
||||
EARLY_PCI_OP(read, dword, u32 *)
|
||||
EARLY_PCI_OP(write, byte, u8)
|
||||
EARLY_PCI_OP(write, word, u16)
|
||||
EARLY_PCI_OP(write, dword, u32)
|
||||
|
||||
int __init pci_is_66mhz_capable(struct pci_channel *hose,
|
||||
int top_bus, int current_bus)
|
||||
{
|
||||
u32 pci_devfn;
|
||||
unsigned short vid;
|
||||
int cap66 = -1;
|
||||
u16 stat;
|
||||
|
||||
printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n");
|
||||
|
||||
for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
|
||||
if (PCI_FUNC(pci_devfn))
|
||||
continue;
|
||||
if (early_read_config_word(hose, top_bus, current_bus,
|
||||
pci_devfn, PCI_VENDOR_ID, &vid) !=
|
||||
PCIBIOS_SUCCESSFUL)
|
||||
continue;
|
||||
if (vid == 0xffff)
|
||||
continue;
|
||||
|
||||
/* check 66MHz capability */
|
||||
if (cap66 < 0)
|
||||
cap66 = 1;
|
||||
if (cap66) {
|
||||
early_read_config_word(hose, top_bus, current_bus,
|
||||
pci_devfn, PCI_STATUS, &stat);
|
||||
if (!(stat & PCI_STATUS_66MHZ)) {
|
||||
printk(KERN_DEBUG
|
||||
"PCI: %02x:%02x not 66MHz capable.\n",
|
||||
current_bus, pci_devfn);
|
||||
cap66 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cap66 > 0;
|
||||
}
|
||||
|
||||
static void pcibios_enable_err(unsigned long __data)
|
||||
{
|
||||
struct pci_channel *hose = (struct pci_channel *)__data;
|
||||
|
||||
del_timer(&hose->err_timer);
|
||||
printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
|
||||
enable_irq(hose->err_irq);
|
||||
}
|
||||
|
||||
static void pcibios_enable_serr(unsigned long __data)
|
||||
{
|
||||
struct pci_channel *hose = (struct pci_channel *)__data;
|
||||
|
||||
del_timer(&hose->serr_timer);
|
||||
printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
|
||||
enable_irq(hose->serr_irq);
|
||||
}
|
||||
|
||||
void pcibios_enable_timers(struct pci_channel *hose)
|
||||
{
|
||||
if (hose->err_irq) {
|
||||
init_timer(&hose->err_timer);
|
||||
hose->err_timer.data = (unsigned long)hose;
|
||||
hose->err_timer.function = pcibios_enable_err;
|
||||
}
|
||||
|
||||
if (hose->serr_irq) {
|
||||
init_timer(&hose->serr_timer);
|
||||
hose->serr_timer.data = (unsigned long)hose;
|
||||
hose->serr_timer.function = pcibios_enable_serr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple handler for the regular PCI status errors, called from IRQ
|
||||
* context.
|
||||
*/
|
||||
unsigned int pcibios_handle_status_errors(unsigned long addr,
|
||||
unsigned int status,
|
||||
struct pci_channel *hose)
|
||||
{
|
||||
unsigned int cmd = 0;
|
||||
|
||||
if (status & PCI_STATUS_REC_MASTER_ABORT) {
|
||||
printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
|
||||
cmd |= PCI_STATUS_REC_MASTER_ABORT;
|
||||
}
|
||||
|
||||
if (status & PCI_STATUS_REC_TARGET_ABORT) {
|
||||
printk(KERN_DEBUG "PCI: target abort: ");
|
||||
pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
|
||||
PCI_STATUS_SIG_TARGET_ABORT |
|
||||
PCI_STATUS_REC_MASTER_ABORT, 1);
|
||||
printk("\n");
|
||||
|
||||
cmd |= PCI_STATUS_REC_TARGET_ABORT;
|
||||
}
|
||||
|
||||
if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
|
||||
printk(KERN_DEBUG "PCI: parity error detected: ");
|
||||
pcibios_report_status(PCI_STATUS_PARITY |
|
||||
PCI_STATUS_DETECTED_PARITY, 1);
|
||||
printk("\n");
|
||||
|
||||
cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
|
||||
|
||||
/* Now back off of the IRQ for awhile */
|
||||
if (hose->err_irq) {
|
||||
disable_irq_nosync(hose->err_irq);
|
||||
hose->err_timer.expires = jiffies + HZ;
|
||||
add_timer(&hose->err_timer);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
77
arch/sh/drivers/pci/fixups-cayman.c
Normal file
77
arch/sh/drivers/pci/fixups-cayman.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/types.h>
|
||||
#include <cpu/irq.h>
|
||||
#include "pci-sh5.h"
|
||||
|
||||
int __init pcibios_map_platform_irq(const 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 = pci_swizzle_interrupt_pin(dev, pin);
|
||||
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 + pci_swizzle_interrupt_pin(dev, pin) - 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;
|
||||
}
|
89
arch/sh/drivers/pci/fixups-dreamcast.c
Normal file
89
arch/sh/drivers/pci/fixups-dreamcast.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/fixups-dreamcast.c
|
||||
*
|
||||
* PCI fixups for the Sega Dreamcast
|
||||
*
|
||||
* Copyright (C) 2001, 2002 M. R. Brown
|
||||
* Copyright (C) 2002, 2003, 2006 Paul Mundt
|
||||
*
|
||||
* This file originally bore the message (with enclosed-$):
|
||||
* Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
|
||||
* Dreamcast PCI: Supports SEGA Broadband Adaptor only.
|
||||
*
|
||||
* 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 <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mach/pci.h>
|
||||
|
||||
static void gapspci_fixup_resources(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_channel *p = dev->sysdata;
|
||||
struct resource res;
|
||||
struct pci_bus_region region;
|
||||
|
||||
printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
|
||||
|
||||
switch (dev->device) {
|
||||
case PCI_DEVICE_ID_SEGA_BBA:
|
||||
/*
|
||||
* We also assume that dev->devfn == 0
|
||||
*/
|
||||
dev->resource[1].start = p->resources[0].start + 0x100;
|
||||
dev->resource[1].end = dev->resource[1].start + 0x200 - 1;
|
||||
|
||||
/*
|
||||
* This is not a normal BAR, prevent any attempts to move
|
||||
* the BAR, as this will result in a bus lock.
|
||||
*/
|
||||
dev->resource[1].flags |= IORESOURCE_PCI_FIXED;
|
||||
|
||||
/*
|
||||
* Redirect dma memory allocations to special memory window.
|
||||
*
|
||||
* If this GAPSPCI region were mapped by a BAR, the CPU
|
||||
* phys_addr_t would be pci_resource_start(), and the bus
|
||||
* address would be pci_bus_address(pci_resource_start()).
|
||||
* But apparently there's no BAR mapping it, so we just
|
||||
* "know" its CPU address is GAPSPCI_DMA_BASE.
|
||||
*/
|
||||
res.start = GAPSPCI_DMA_BASE;
|
||||
res.end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1;
|
||||
res.flags = IORESOURCE_MEM;
|
||||
pcibios_resource_to_bus(dev->bus, ®ion, &res);
|
||||
BUG_ON(!dma_declare_coherent_memory(&dev->dev,
|
||||
res.start,
|
||||
region.start,
|
||||
resource_size(&res),
|
||||
DMA_MEMORY_MAP |
|
||||
DMA_MEMORY_EXCLUSIVE));
|
||||
break;
|
||||
default:
|
||||
printk("PCI: Failed resource fixup\n");
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
/*
|
||||
* The interrupt routing semantics here are quite trivial.
|
||||
*
|
||||
* We basically only support one interrupt, so we only bother
|
||||
* updating a device's interrupt line with this single shared
|
||||
* interrupt. Keeps routing quite simple, doesn't it?
|
||||
*/
|
||||
return GAPSPCI_IRQ;
|
||||
}
|
59
arch/sh/drivers/pci/fixups-landisk.c
Normal file
59
arch/sh/drivers/pci/fixups-landisk.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/fixups-landisk.c
|
||||
*
|
||||
* PCI initialization for the I-O DATA Device, Inc. LANDISK board
|
||||
*
|
||||
* Copyright (C) 2006 kogiidena
|
||||
* Copyright (C) 2010 Nobuhiro Iwamatsu
|
||||
*
|
||||
* 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/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
|
||||
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
|
||||
|
||||
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
/*
|
||||
* slot0: pin1-4 = irq5,6,7,8
|
||||
* slot1: pin1-4 = irq6,7,8,5
|
||||
* slot2: pin1-4 = irq7,8,5,6
|
||||
* slot3: pin1-4 = irq8,5,6,7
|
||||
*/
|
||||
int irq = ((slot + pin - 1) & 0x3) + evt2irq(0x2a0);
|
||||
|
||||
if ((slot | (pin - 1)) > 0x3) {
|
||||
printk(KERN_WARNING "PCI: Bad IRQ mapping request for slot %d pin %c\n",
|
||||
slot, pin - 1 + 'A');
|
||||
return -1;
|
||||
}
|
||||
return irq;
|
||||
}
|
||||
|
||||
int pci_fixup_pcic(struct pci_channel *chan)
|
||||
{
|
||||
unsigned long bcr1, mcr;
|
||||
|
||||
bcr1 = __raw_readl(SH7751_BCR1);
|
||||
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
|
||||
pci_write_reg(chan, bcr1, SH4_PCIBCR1);
|
||||
|
||||
mcr = __raw_readl(SH7751_MCR);
|
||||
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
|
||||
pci_write_reg(chan, mcr, SH4_PCIMCR);
|
||||
|
||||
pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
|
||||
pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
|
||||
pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
|
||||
pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
|
||||
|
||||
return 0;
|
||||
}
|
21
arch/sh/drivers/pci/fixups-r7780rp.c
Normal file
21
arch/sh/drivers/pci/fixups-r7780rp.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/fixups-r7780rp.c
|
||||
*
|
||||
* Highlander R7780RP-1 PCI fixups
|
||||
*
|
||||
* Copyright (C) 2003 Lineo uSolutions, Inc.
|
||||
* Copyright (C) 2004 - 2006 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 <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
return evt2irq(0xa20) + slot;
|
||||
}
|
67
arch/sh/drivers/pci/fixups-rts7751r2d.c
Normal file
67
arch/sh/drivers/pci/fixups-rts7751r2d.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/fixups-rts7751r2d.c
|
||||
*
|
||||
* RTS7751R2D / LBOXRE2 PCI fixups
|
||||
*
|
||||
* Copyright (C) 2003 Lineo uSolutions, Inc.
|
||||
* Copyright (C) 2004 Paul Mundt
|
||||
* Copyright (C) 2007 Nobuhiro Iwamatsu
|
||||
*
|
||||
* 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 <linux/pci.h>
|
||||
#include <mach/lboxre2.h>
|
||||
#include <mach/r2d.h>
|
||||
#include "pci-sh4.h"
|
||||
#include <generated/machtypes.h>
|
||||
|
||||
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
|
||||
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
|
||||
|
||||
static u8 rts7751r2d_irq_tab[] __initdata = {
|
||||
IRQ_PCI_INTA,
|
||||
IRQ_PCI_INTB,
|
||||
IRQ_PCI_INTC,
|
||||
IRQ_PCI_INTD,
|
||||
};
|
||||
|
||||
static char lboxre2_irq_tab[] __initdata = {
|
||||
IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
|
||||
};
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
if (mach_is_lboxre2())
|
||||
return lboxre2_irq_tab[slot];
|
||||
else
|
||||
return rts7751r2d_irq_tab[slot];
|
||||
}
|
||||
|
||||
int pci_fixup_pcic(struct pci_channel *chan)
|
||||
{
|
||||
unsigned long bcr1, mcr;
|
||||
|
||||
bcr1 = __raw_readl(SH7751_BCR1);
|
||||
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
|
||||
pci_write_reg(chan, bcr1, SH4_PCIBCR1);
|
||||
|
||||
/* Enable all interrupts, so we known what to fix */
|
||||
pci_write_reg(chan, 0x0000c3ff, SH4_PCIINTM);
|
||||
pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
|
||||
|
||||
pci_write_reg(chan, 0xfb900047, SH7751_PCICONF1);
|
||||
pci_write_reg(chan, 0xab000001, SH7751_PCICONF4);
|
||||
|
||||
mcr = __raw_readl(SH7751_MCR);
|
||||
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
|
||||
pci_write_reg(chan, mcr, SH4_PCIMCR);
|
||||
|
||||
pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
|
||||
pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
|
||||
pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
|
||||
pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
|
||||
|
||||
return 0;
|
||||
}
|
43
arch/sh/drivers/pci/fixups-sdk7780.c
Normal file
43
arch/sh/drivers/pci/fixups-sdk7780.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/fixups-sdk7780.c
|
||||
*
|
||||
* PCI fixups for the SDK7780SE03
|
||||
*
|
||||
* Copyright (C) 2003 Lineo uSolutions, Inc.
|
||||
* Copyright (C) 2004 - 2006 Paul Mundt
|
||||
* Copyright (C) 2006 Nobuhiro Iwamatsu
|
||||
*
|
||||
* 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 <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
#define IRQ_INTA evt2irq(0xa20)
|
||||
#define IRQ_INTB evt2irq(0xa40)
|
||||
#define IRQ_INTC evt2irq(0xa60)
|
||||
#define IRQ_INTD evt2irq(0xa80)
|
||||
|
||||
/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
|
||||
static char sdk7780_irq_tab[4][16] __initdata = {
|
||||
/* INTA */
|
||||
{ IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1 },
|
||||
/* INTB */
|
||||
{ IRQ_INTB, IRQ_INTA, -1, IRQ_INTA, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1 },
|
||||
/* INTC */
|
||||
{ IRQ_INTC, IRQ_INTB, -1, IRQ_INTB, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1 },
|
||||
/* INTD */
|
||||
{ IRQ_INTD, IRQ_INTC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1 },
|
||||
};
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
return sdk7780_irq_tab[pin-1][slot];
|
||||
}
|
67
arch/sh/drivers/pci/fixups-sdk7786.c
Normal file
67
arch/sh/drivers/pci/fixups-sdk7786.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* SDK7786 FPGA PCIe mux handling
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
#define pr_fmt(fmt) "PCI: " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <mach/fpga.h>
|
||||
|
||||
/*
|
||||
* The SDK7786 FPGA supports mangling of most of the slots in some way or
|
||||
* another. Slots 3/4 are special in that only one can be supported at a
|
||||
* time, and both appear on port 3 to the PCI bus scan. Enabling slot 4
|
||||
* (the horizontal edge connector) will disable slot 3 entirely.
|
||||
*
|
||||
* Misconfigurations can be detected through the FPGA via the slot
|
||||
* resistors to determine card presence. Hotplug remains unsupported.
|
||||
*/
|
||||
static unsigned int slot4en __initdata;
|
||||
|
||||
char *__init pcibios_setup(char *str)
|
||||
{
|
||||
if (strcmp(str, "slot4en") == 0) {
|
||||
slot4en = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static int __init sdk7786_pci_init(void)
|
||||
{
|
||||
u16 data = fpga_read_reg(PCIECR);
|
||||
|
||||
/*
|
||||
* Enable slot #4 if it's been specified on the command line.
|
||||
*
|
||||
* Optionally reroute if slot #4 has a card present while slot #3
|
||||
* does not, regardless of command line value.
|
||||
*
|
||||
* Card presence is logically inverted.
|
||||
*/
|
||||
slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3));
|
||||
if (slot4en) {
|
||||
pr_info("Activating PCIe slot#4 (disabling slot#3)\n");
|
||||
|
||||
data &= ~PCIECR_PCIEMUX1;
|
||||
fpga_write_reg(data, PCIECR);
|
||||
|
||||
/* Warn about forced rerouting if slot#3 is occupied */
|
||||
if ((data & PCIECR_PRST3) == 0) {
|
||||
pr_warning("Unreachable card detected in slot#3\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
} else
|
||||
pr_info("PCIe slot#4 disabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(sdk7786_pci_init);
|
112
arch/sh/drivers/pci/fixups-se7751.c
Normal file
112
arch/sh/drivers/pci/fixups-se7751.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
|
||||
{
|
||||
switch (slot) {
|
||||
case 0: return evt2irq(0x3a0);
|
||||
case 1: return evt2irq(0x3a0); /* AMD Ethernet controller */
|
||||
case 2: return -1;
|
||||
case 3: return -1;
|
||||
case 4: return -1;
|
||||
default:
|
||||
printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
|
||||
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
|
||||
|
||||
/*
|
||||
* Only long word accesses of the PCIC's internal local registers and the
|
||||
* configuration registers from the CPU is supported.
|
||||
*/
|
||||
#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
|
||||
#define PCIC_READ(x) readl(PCI_REG(x))
|
||||
|
||||
/*
|
||||
* Description: This function sets up and initializes the pcic, sets
|
||||
* up the BARS, maps the DRAM into the address space etc, etc.
|
||||
*/
|
||||
int pci_fixup_pcic(struct pci_channel *chan)
|
||||
{
|
||||
unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
|
||||
unsigned short bcr2;
|
||||
|
||||
/*
|
||||
* Initialize the slave bus controller on the pcic. The values used
|
||||
* here should not be hardcoded, but they should be taken from the bsc
|
||||
* on the processor, to make this function as generic as possible.
|
||||
* (i.e. Another sbc may usr different SDRAM timing settings -- in order
|
||||
* for the pcic to work, its settings need to be exactly the same.)
|
||||
*/
|
||||
bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
|
||||
bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
|
||||
wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
|
||||
wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
|
||||
wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
|
||||
mcr = (*(volatile unsigned long*)(SH7751_MCR));
|
||||
|
||||
bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */
|
||||
(*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
|
||||
|
||||
bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
|
||||
PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */
|
||||
PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */
|
||||
PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */
|
||||
PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */
|
||||
PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */
|
||||
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
|
||||
PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */
|
||||
|
||||
|
||||
/* Enable all interrupts, so we know what to fix */
|
||||
PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
|
||||
PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
|
||||
|
||||
/* Set up standard PCI config registers */
|
||||
PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */
|
||||
PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */
|
||||
PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */
|
||||
PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */
|
||||
PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */
|
||||
PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
|
||||
PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */
|
||||
PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */
|
||||
PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */
|
||||
PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */
|
||||
|
||||
/* Now turn it on... */
|
||||
PCIC_WRITE(SH7751_PCICR, 0xa5000001);
|
||||
|
||||
/*
|
||||
* Set PCIMBR and PCIIOBR here, assuming a single window
|
||||
* (16M MEM, 256K IO) is enough. If a larger space is
|
||||
* needed, the readx/writex and inx/outx functions will
|
||||
* have to do more (e.g. setting registers for each call).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the MBR so PCI address is one-to-one with window,
|
||||
* meaning all calls go straight through... use BUG_ON to
|
||||
* catch erroneous assumption.
|
||||
*/
|
||||
BUG_ON(chan->resources[1].start != SH7751_PCI_MEMORY_BASE);
|
||||
|
||||
PCIC_WRITE(SH7751_PCIMBR, chan->resources[1].start);
|
||||
|
||||
/* Set IOBR for window containing area specified in pci.h */
|
||||
PCIC_WRITE(SH7751_PCIIOBR, (chan->resources[0].start & SH7751_PCIIOBR_MASK));
|
||||
|
||||
/* All done, may as well say so... */
|
||||
printk("SH7751 PCI: Finished initialization of the PCI controller\n");
|
||||
|
||||
return 1;
|
||||
}
|
32
arch/sh/drivers/pci/fixups-sh03.c
Normal file
32
arch/sh/drivers/pci/fixups-sh03.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sh_intc.h>
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
int irq;
|
||||
|
||||
if (dev->bus->number == 0) {
|
||||
switch (slot) {
|
||||
case 4: return evt2irq(0x2a0); /* eth0 */
|
||||
case 8: return evt2irq(0x2a0); /* eth1 */
|
||||
case 6: return evt2irq(0x240); /* PCI bridge */
|
||||
default:
|
||||
printk(KERN_ERR "PCI: Bad IRQ mapping request "
|
||||
"for slot %d\n", slot);
|
||||
return evt2irq(0x240);
|
||||
}
|
||||
} else {
|
||||
switch (pin) {
|
||||
case 0: irq = evt2irq(0x240); break;
|
||||
case 1: irq = evt2irq(0x240); break;
|
||||
case 2: irq = evt2irq(0x240); break;
|
||||
case 3: irq = evt2irq(0x240); break;
|
||||
case 4: irq = evt2irq(0x240); break;
|
||||
default: irq = -1; break;
|
||||
}
|
||||
}
|
||||
return irq;
|
||||
}
|
39
arch/sh/drivers/pci/fixups-snapgear.c
Normal file
39
arch/sh/drivers/pci/fixups-snapgear.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/ops-snapgear.c
|
||||
*
|
||||
* Author: David McCullough <davidm@snapgear.com>
|
||||
*
|
||||
* Ported to new API by Paul Mundt <lethal@linux-sh.org>
|
||||
*
|
||||
* 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 SnapGear boards
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
int irq = -1;
|
||||
|
||||
switch (slot) {
|
||||
case 8: /* the PCI bridge */ break;
|
||||
case 11: irq = evt2irq(0x300); break; /* USB */
|
||||
case 12: irq = evt2irq(0x360); break; /* PCMCIA */
|
||||
case 13: irq = evt2irq(0x2a0); break; /* eth0 */
|
||||
case 14: irq = evt2irq(0x300); break; /* eth1 */
|
||||
case 15: irq = evt2irq(0x360); break; /* safenet (unused) */
|
||||
}
|
||||
|
||||
printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
|
||||
slot, pin - 1 + 'A', irq);
|
||||
|
||||
return irq;
|
||||
}
|
38
arch/sh/drivers/pci/fixups-titan.c
Normal file
38
arch/sh/drivers/pci/fixups-titan.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* arch/sh/drivers/pci/ops-titan.c
|
||||
*
|
||||
* Ported to new API by Paul Mundt <lethal@linux-sh.org>
|
||||
*
|
||||
* Modified from ops-snapgear.c written by David McCullough
|
||||
* 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 Titan boards
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <mach/titan.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
static char titan_irq_tab[] __initdata = {
|
||||
TITAN_IRQ_WAN,
|
||||
TITAN_IRQ_LAN,
|
||||
TITAN_IRQ_MPCIA,
|
||||
TITAN_IRQ_MPCIB,
|
||||
TITAN_IRQ_USB,
|
||||
};
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
int irq = titan_irq_tab[slot];
|
||||
|
||||
printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
|
||||
slot, pin - 1 + 'A', irq);
|
||||
|
||||
return irq;
|
||||
}
|
82
arch/sh/drivers/pci/ops-dreamcast.c
Normal file
82
arch/sh/drivers/pci/ops-dreamcast.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* PCI operations for the Sega Dreamcast
|
||||
*
|
||||
* Copyright (C) 2001, 2002 M. R. Brown
|
||||
* Copyright (C) 2002, 2003 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 <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <mach/pci.h>
|
||||
|
||||
/*
|
||||
* The !gapspci_config_access case really shouldn't happen, ever, unless
|
||||
* someone implicitly messes around with the last devfn value.. otherwise we
|
||||
* only support a single device anyways, and if we didn't have a BBA, we
|
||||
* wouldn't make it terribly far through the PCI setup anyways.
|
||||
*
|
||||
* Also, we could very easily support both Type 0 and Type 1 configurations
|
||||
* here, but since it doesn't seem that there is any such implementation in
|
||||
* existence, we don't bother.
|
||||
*
|
||||
* I suppose if someone actually gets around to ripping the chip out of
|
||||
* the BBA and hanging some more devices off of it, then this might be
|
||||
* something to take into consideration. However, due to the cost of the BBA,
|
||||
* and the general lack of activity by DC hardware hackers, this doesn't seem
|
||||
* likely to happen anytime soon.
|
||||
*/
|
||||
static int gapspci_config_access(unsigned char bus, unsigned int devfn)
|
||||
{
|
||||
return (bus == 0) && (devfn == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We can also actually read and write in b/w/l sizes! Thankfully this part
|
||||
* was at least done right, and we don't have to do the stupid masking and
|
||||
* shifting that we do on the 7751! Small wonders never cease to amaze.
|
||||
*/
|
||||
static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
|
||||
{
|
||||
*val = 0xffffffff;
|
||||
|
||||
if (!gapspci_config_access(bus->number, devfn))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
switch (size) {
|
||||
case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
|
||||
case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
|
||||
case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
|
||||
{
|
||||
if (!gapspci_config_access(bus->number, devfn))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
switch (size) {
|
||||
case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
|
||||
case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
|
||||
case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct pci_ops gapspci_pci_ops = {
|
||||
.read = gapspci_read,
|
||||
.write = gapspci_write,
|
||||
};
|
108
arch/sh/drivers/pci/ops-sh4.c
Normal file
108
arch/sh/drivers/pci/ops-sh4.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
|
||||
*
|
||||
* Copyright (C) 2002 - 2009 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License v2. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include "pci-sh4.h"
|
||||
|
||||
/*
|
||||
* Direct access to PCI hardware...
|
||||
*/
|
||||
#define CONFIG_CMD(bus, devfn, where) \
|
||||
(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
|
||||
|
||||
/*
|
||||
* Functions for accessing PCI configuration space with type 1 accesses
|
||||
*/
|
||||
static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 *val)
|
||||
{
|
||||
struct pci_channel *chan = bus->sysdata;
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
/*
|
||||
* PCIPDR may only be accessed as 32 bit words,
|
||||
* so we must do byte alignment by hand
|
||||
*/
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
|
||||
data = pci_read_reg(chan, SH4_PCIPDR);
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
*val = (data >> ((where & 3) << 3)) & 0xff;
|
||||
break;
|
||||
case 2:
|
||||
*val = (data >> ((where & 2) << 3)) & 0xffff;
|
||||
break;
|
||||
case 4:
|
||||
*val = data;
|
||||
break;
|
||||
default:
|
||||
return PCIBIOS_FUNC_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since SH4 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.
|
||||
*/
|
||||
static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 val)
|
||||
{
|
||||
struct pci_channel *chan = bus->sysdata;
|
||||
unsigned long flags;
|
||||
int shift;
|
||||
u32 data;
|
||||
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
|
||||
data = pci_read_reg(chan, SH4_PCIPDR);
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
shift = (where & 3) << 3;
|
||||
data &= ~(0xff << shift);
|
||||
data |= ((val & 0xff) << shift);
|
||||
break;
|
||||
case 2:
|
||||
shift = (where & 2) << 3;
|
||||
data &= ~(0xffff << shift);
|
||||
data |= ((val & 0xffff) << shift);
|
||||
break;
|
||||
case 4:
|
||||
data = val;
|
||||
break;
|
||||
default:
|
||||
return PCIBIOS_FUNC_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
pci_write_reg(chan, data, SH4_PCIPDR);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct pci_ops sh4_pci_ops = {
|
||||
.read = sh4_pci_read,
|
||||
.write = sh4_pci_write,
|
||||
};
|
||||
|
||||
int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
return 0;
|
||||
}
|
68
arch/sh/drivers/pci/ops-sh5.c
Normal file
68
arch/sh/drivers/pci/ops-sh5.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 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,
|
||||
};
|
171
arch/sh/drivers/pci/ops-sh7786.c
Normal file
171
arch/sh/drivers/pci/ops-sh7786.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Generic SH7786 PCI-Express operations.
|
||||
*
|
||||
* Copyright (C) 2009 - 2010 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License v2. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "pcie-sh7786.h"
|
||||
|
||||
enum {
|
||||
PCI_ACCESS_READ,
|
||||
PCI_ACCESS_WRITE,
|
||||
};
|
||||
|
||||
static int sh7786_pcie_config_access(unsigned char access_type,
|
||||
struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
|
||||
{
|
||||
struct pci_channel *chan = bus->sysdata;
|
||||
int dev, func, type, reg;
|
||||
|
||||
dev = PCI_SLOT(devfn);
|
||||
func = PCI_FUNC(devfn);
|
||||
type = !!bus->parent;
|
||||
reg = where & ~3;
|
||||
|
||||
if (bus->number > 255 || dev > 31 || func > 7)
|
||||
return PCIBIOS_FUNC_NOT_SUPPORTED;
|
||||
|
||||
/*
|
||||
* While each channel has its own memory-mapped extended config
|
||||
* space, it's generally only accessible when in endpoint mode.
|
||||
* When in root complex mode, the controller is unable to target
|
||||
* itself with either type 0 or type 1 accesses, and indeed, any
|
||||
* controller initiated target transfer to its own config space
|
||||
* result in a completer abort.
|
||||
*
|
||||
* Each channel effectively only supports a single device, but as
|
||||
* the same channel <-> device access works for any PCI_SLOT()
|
||||
* value, we cheat a bit here and bind the controller's config
|
||||
* space to devfn 0 in order to enable self-enumeration. In this
|
||||
* case the regular PAR/PDR path is sidelined and the mangled
|
||||
* config access itself is initiated as a SuperHyway transaction.
|
||||
*/
|
||||
if (pci_is_root_bus(bus)) {
|
||||
if (dev == 0) {
|
||||
if (access_type == PCI_ACCESS_READ)
|
||||
*data = pci_read_reg(chan, PCI_REG(reg));
|
||||
else
|
||||
pci_write_reg(chan, *data, PCI_REG(reg));
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
} else if (dev > 1)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Clear errors */
|
||||
pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR);
|
||||
|
||||
/* Set the PIO address */
|
||||
pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
|
||||
(func << 16) | reg, SH4A_PCIEPAR);
|
||||
|
||||
/* Enable the configuration access */
|
||||
pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR);
|
||||
|
||||
/* Check for errors */
|
||||
if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
/* Check for master and target aborts */
|
||||
if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
if (access_type == PCI_ACCESS_READ)
|
||||
*data = pci_read_reg(chan, SH4A_PCIEPDR);
|
||||
else
|
||||
pci_write_reg(chan, *data, SH4A_PCIEPDR);
|
||||
|
||||
/* Disable the configuration access */
|
||||
pci_write_reg(chan, 0, SH4A_PCIEPCTLR);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 *val)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
u32 data;
|
||||
|
||||
if ((size == 2) && (where & 1))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
else if ((size == 4) && (where & 3))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
|
||||
devfn, where, &data);
|
||||
if (ret != PCIBIOS_SUCCESSFUL) {
|
||||
*val = 0xffffffff;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size == 1)
|
||||
*val = (data >> ((where & 3) << 3)) & 0xff;
|
||||
else if (size == 2)
|
||||
*val = (data >> ((where & 2) << 3)) & 0xffff;
|
||||
else
|
||||
*val = data;
|
||||
|
||||
dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
|
||||
"where=0x%04x size=%d val=0x%08lx\n", bus->number,
|
||||
devfn, where, size, (unsigned long)*val);
|
||||
|
||||
out:
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
int shift, ret;
|
||||
u32 data;
|
||||
|
||||
if ((size == 2) && (where & 1))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
else if ((size == 4) && (where & 3))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
|
||||
devfn, where, &data);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
goto out;
|
||||
|
||||
dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
|
||||
"where=0x%04x size=%d val=%08lx\n", bus->number,
|
||||
devfn, where, size, (unsigned long)val);
|
||||
|
||||
if (size == 1) {
|
||||
shift = (where & 3) << 3;
|
||||
data &= ~(0xff << shift);
|
||||
data |= ((val & 0xff) << shift);
|
||||
} else if (size == 2) {
|
||||
shift = (where & 2) << 3;
|
||||
data &= ~(0xffff << shift);
|
||||
data |= ((val & 0xffff) << shift);
|
||||
} else
|
||||
data = val;
|
||||
|
||||
ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus,
|
||||
devfn, where, &data);
|
||||
out:
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pci_ops sh7786_pci_ops = {
|
||||
.read = sh7786_pcie_read,
|
||||
.write = sh7786_pcie_write,
|
||||
};
|
100
arch/sh/drivers/pci/pci-dreamcast.c
Normal file
100
arch/sh/drivers/pci/pci-dreamcast.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* PCI support for the Sega Dreamcast
|
||||
*
|
||||
* Copyright (C) 2001, 2002 M. R. Brown
|
||||
* Copyright (C) 2002, 2003 Paul Mundt
|
||||
*
|
||||
* This file originally bore the message (with enclosed-$):
|
||||
* Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
|
||||
* Dreamcast PCI: Supports SEGA Broadband Adaptor only.
|
||||
*
|
||||
* 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 <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mach/pci.h>
|
||||
|
||||
static struct resource gapspci_resources[] = {
|
||||
{
|
||||
.name = "GAPSPCI IO",
|
||||
.start = GAPSPCI_BBA_CONFIG,
|
||||
.end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
|
||||
.flags = IORESOURCE_IO,
|
||||
}, {
|
||||
.name = "GAPSPCI mem",
|
||||
.start = GAPSPCI_DMA_BASE,
|
||||
.end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct pci_channel dreamcast_pci_controller = {
|
||||
.pci_ops = &gapspci_pci_ops,
|
||||
.resources = gapspci_resources,
|
||||
.nr_resources = ARRAY_SIZE(gapspci_resources),
|
||||
.io_offset = 0x00000000,
|
||||
.mem_offset = 0x00000000,
|
||||
};
|
||||
|
||||
/*
|
||||
* gapspci init
|
||||
*/
|
||||
|
||||
static int __init gapspci_init(void)
|
||||
{
|
||||
char idbuf[16];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* FIXME: All of this wants documenting to some degree,
|
||||
* even some basic register definitions would be nice.
|
||||
*
|
||||
* I haven't seen anything this ugly since.. maple.
|
||||
*/
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
idbuf[i] = inb(GAPSPCI_REGS+i);
|
||||
|
||||
if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
|
||||
return -ENODEV;
|
||||
|
||||
outl(0x5a14a501, GAPSPCI_REGS+0x18);
|
||||
|
||||
for (i=0; i<1000000; i++)
|
||||
cpu_relax();
|
||||
|
||||
if (inl(GAPSPCI_REGS+0x18) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
outl(0x01000000, GAPSPCI_REGS+0x20);
|
||||
outl(0x01000000, GAPSPCI_REGS+0x24);
|
||||
|
||||
outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
|
||||
outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
|
||||
|
||||
outl(1, GAPSPCI_REGS+0x14);
|
||||
outl(1, GAPSPCI_REGS+0x34);
|
||||
|
||||
/* Setting Broadband Adapter */
|
||||
outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
|
||||
outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
|
||||
outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
|
||||
outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
|
||||
outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
|
||||
outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
|
||||
outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
|
||||
|
||||
return register_pci_controller(&dreamcast_pci_controller);
|
||||
}
|
||||
arch_initcall(gapspci_init);
|
189
arch/sh/drivers/pci/pci-sh4.h
Normal file
189
arch/sh/drivers/pci/pci-sh4.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
#ifndef __PCI_SH4_H
|
||||
#define __PCI_SH4_H
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7785) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7763)
|
||||
#include "pci-sh7780.h"
|
||||
#else
|
||||
#include "pci-sh7751.h"
|
||||
#endif
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
/* startup values */
|
||||
#define PCI_PROBE_BIOS 1
|
||||
#define PCI_PROBE_CONF1 2
|
||||
#define PCI_PROBE_CONF2 4
|
||||
#define PCI_NO_CHECKS 0x400
|
||||
#define PCI_ASSIGN_ROMS 0x1000
|
||||
#define PCI_BIOS_IRQ_SCAN 0x2000
|
||||
|
||||
#define SH4_PCICR 0x100 /* PCI Control Register */
|
||||
#define SH4_PCICR_PREFIX 0xA5000000 /* CR prefix for write */
|
||||
#define SH4_PCICR_FTO 0x00000400 /* TRDY/IRDY Enable */
|
||||
#define SH4_PCICR_TRSB 0x00000200 /* Target Read Single */
|
||||
#define SH4_PCICR_BSWP 0x00000100 /* Target Byte Swap */
|
||||
#define SH4_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */
|
||||
#define SH4_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */
|
||||
#define SH4_PCICR_MD 0x00000030 /* MD9 and MD10 status */
|
||||
#define SH4_PCICR_SERR 0x00000008 /* SERR output assert */
|
||||
#define SH4_PCICR_INTA 0x00000004 /* INTA output assert */
|
||||
#define SH4_PCICR_PRST 0x00000002 /* PCI Reset Assert */
|
||||
#define SH4_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */
|
||||
#define SH4_PCILSR0 0x104 /* PCI Local Space Register0 */
|
||||
#define SH4_PCILSR1 0x108 /* PCI Local Space Register1 */
|
||||
#define SH4_PCILAR0 0x10C /* PCI Local Addr Register1 */
|
||||
#define SH4_PCILAR1 0x110 /* PCI Local Addr Register1 */
|
||||
#define SH4_PCIINT 0x114 /* PCI Interrupt Register */
|
||||
#define SH4_PCIINT_MLCK 0x00008000 /* Master Lock Error */
|
||||
#define SH4_PCIINT_TABT 0x00004000 /* Target Abort Error */
|
||||
#define SH4_PCIINT_TRET 0x00000200 /* Target Retry Error */
|
||||
#define SH4_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */
|
||||
#define SH4_PCIINT_PRTY 0x00000080 /* Address Parity Error */
|
||||
#define SH4_PCIINT_SERR 0x00000040 /* SERR Detection Error */
|
||||
#define SH4_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */
|
||||
#define SH4_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Err Det. */
|
||||
#define SH4_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */
|
||||
#define SH4_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */
|
||||
#define SH4_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */
|
||||
#define SH4_PCIINT_MRPD 0x00000001 /* Master Read PERR Detect */
|
||||
#define SH4_PCIINTM 0x118 /* PCI Interrupt Mask */
|
||||
#define SH4_PCIINTM_TTADIM BIT(14) /* Target-target abort interrupt */
|
||||
#define SH4_PCIINTM_TMTOIM BIT(9) /* Target retry timeout */
|
||||
#define SH4_PCIINTM_MDEIM BIT(8) /* Master function disable error */
|
||||
#define SH4_PCIINTM_APEDIM BIT(7) /* Address parity error detection */
|
||||
#define SH4_PCIINTM_SDIM BIT(6) /* SERR detection */
|
||||
#define SH4_PCIINTM_DPEITWM BIT(5) /* Data parity error for target write */
|
||||
#define SH4_PCIINTM_PEDITRM BIT(4) /* PERR detection for target read */
|
||||
#define SH4_PCIINTM_TADIMM BIT(3) /* Target abort for master */
|
||||
#define SH4_PCIINTM_MADIMM BIT(2) /* Master abort for master */
|
||||
#define SH4_PCIINTM_MWPDIM BIT(1) /* Master write data parity error */
|
||||
#define SH4_PCIINTM_MRDPEIM BIT(0) /* Master read data parity error */
|
||||
#define SH4_PCIALR 0x11C /* Error Address Register */
|
||||
#define SH4_PCICLR 0x120 /* Error Command/Data */
|
||||
#define SH4_PCICLR_MPIO 0x80000000
|
||||
#define SH4_PCICLR_MDMA0 0x40000000 /* DMA0 Transfer Error */
|
||||
#define SH4_PCICLR_MDMA1 0x20000000 /* DMA1 Transfer Error */
|
||||
#define SH4_PCICLR_MDMA2 0x10000000 /* DMA2 Transfer Error */
|
||||
#define SH4_PCICLR_MDMA3 0x08000000 /* DMA3 Transfer Error */
|
||||
#define SH4_PCICLR_TGT 0x04000000 /* Target Transfer Error */
|
||||
#define SH4_PCICLR_CMDL 0x0000000F /* PCI Command at Error */
|
||||
#define SH4_PCIAINT 0x130 /* Arbiter Interrupt Register */
|
||||
#define SH4_PCIAINT_MBKN 0x00002000 /* Master Broken Interrupt */
|
||||
#define SH4_PCIAINT_TBTO 0x00001000 /* Target Bus Time Out */
|
||||
#define SH4_PCIAINT_MBTO 0x00000800 /* Master Bus Time Out */
|
||||
#define SH4_PCIAINT_TABT 0x00000008 /* Target Abort */
|
||||
#define SH4_PCIAINT_MABT 0x00000004 /* Master Abort */
|
||||
#define SH4_PCIAINT_RDPE 0x00000002 /* Read Data Parity Error */
|
||||
#define SH4_PCIAINT_WDPE 0x00000001 /* Write Data Parity Error */
|
||||
#define SH4_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
|
||||
#define SH4_PCIBMLR 0x138 /* Error Bus Master Register */
|
||||
#define SH4_PCIBMLR_REQ4 0x00000010 /* REQ4 bus master at error */
|
||||
#define SH4_PCIBMLR_REQ3 0x00000008 /* REQ3 bus master at error */
|
||||
#define SH4_PCIBMLR_REQ2 0x00000004 /* REQ2 bus master at error */
|
||||
#define SH4_PCIBMLR_REQ1 0x00000002 /* REQ1 bus master at error */
|
||||
#define SH4_PCIBMLR_REQ0 0x00000001 /* REQ0 bus master at error */
|
||||
#define SH4_PCIDMABT 0x140 /* DMA Transfer Arb. Register */
|
||||
#define SH4_PCIDMABT_RRBN 0x00000001 /* DMA Arbitor Round-Robin */
|
||||
#define SH4_PCIDPA0 0x180 /* DMA0 Transfer Addr. */
|
||||
#define SH4_PCIDLA0 0x184 /* DMA0 Local Addr. */
|
||||
#define SH4_PCIDTC0 0x188 /* DMA0 Transfer Cnt. */
|
||||
#define SH4_PCIDCR0 0x18C /* DMA0 Control Register */
|
||||
#define SH4_PCIDCR_ALGN 0x00000600 /* DMA Alignment Mode */
|
||||
#define SH4_PCIDCR_MAST 0x00000100 /* DMA Termination Type */
|
||||
#define SH4_PCIDCR_INTM 0x00000080 /* DMA Interrupt Done Mask*/
|
||||
#define SH4_PCIDCR_INTS 0x00000040 /* DMA Interrupt Done Status */
|
||||
#define SH4_PCIDCR_LHLD 0x00000020 /* Local Address Control */
|
||||
#define SH4_PCIDCR_PHLD 0x00000010 /* PCI Address Control*/
|
||||
#define SH4_PCIDCR_IOSEL 0x00000008 /* PCI Address Space Type */
|
||||
#define SH4_PCIDCR_DIR 0x00000004 /* DMA Transfer Direction */
|
||||
#define SH4_PCIDCR_STOP 0x00000002 /* Force DMA Stop */
|
||||
#define SH4_PCIDCR_STRT 0x00000001 /* DMA Start */
|
||||
#define SH4_PCIDPA1 0x190 /* DMA1 Transfer Addr. */
|
||||
#define SH4_PCIDLA1 0x194 /* DMA1 Local Addr. */
|
||||
#define SH4_PCIDTC1 0x198 /* DMA1 Transfer Cnt. */
|
||||
#define SH4_PCIDCR1 0x19C /* DMA1 Control Register */
|
||||
#define SH4_PCIDPA2 0x1A0 /* DMA2 Transfer Addr. */
|
||||
#define SH4_PCIDLA2 0x1A4 /* DMA2 Local Addr. */
|
||||
#define SH4_PCIDTC2 0x1A8 /* DMA2 Transfer Cnt. */
|
||||
#define SH4_PCIDCR2 0x1AC /* DMA2 Control Register */
|
||||
#define SH4_PCIDPA3 0x1B0 /* DMA3 Transfer Addr. */
|
||||
#define SH4_PCIDLA3 0x1B4 /* DMA3 Local Addr. */
|
||||
#define SH4_PCIDTC3 0x1B8 /* DMA3 Transfer Cnt. */
|
||||
#define SH4_PCIDCR3 0x1BC /* DMA3 Control Register */
|
||||
#define SH4_PCIPAR 0x1C0 /* PIO Address Register */
|
||||
#define SH4_PCIPAR_CFGEN 0x80000000 /* Configuration Enable */
|
||||
#define SH4_PCIPAR_BUSNO 0x00FF0000 /* Config. Bus Number */
|
||||
#define SH4_PCIPAR_DEVNO 0x0000FF00 /* Config. Device Number */
|
||||
#define SH4_PCIPAR_REGAD 0x000000FC /* Register Address Number */
|
||||
#define SH4_PCIMBR 0x1C4 /* Memory Base Address */
|
||||
#define SH4_PCIMBR_MASK 0xFF000000 /* Memory Space Mask */
|
||||
#define SH4_PCIMBR_LOCK 0x00000001 /* Lock Memory Space */
|
||||
#define SH4_PCIIOBR 0x1C8 /* I/O Base Address Register */
|
||||
#define SH4_PCIIOBR_MASK 0xFFFC0000 /* IO Space Mask */
|
||||
#define SH4_PCIIOBR_LOCK 0x00000001 /* Lock IO Space */
|
||||
#define SH4_PCIPINT 0x1CC /* Power Mgmnt Int. Register */
|
||||
#define SH4_PCIPINT_D3 0x00000002 /* D3 Pwr Mgmt. Interrupt */
|
||||
#define SH4_PCIPINT_D0 0x00000001 /* D0 Pwr Mgmt. Interrupt */
|
||||
#define SH4_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */
|
||||
#define SH4_PCICLKR 0x1D4 /* Clock Ctrl. Register */
|
||||
#define SH4_PCICLKR_PCSTP 0x00000002 /* PCI Clock Stop */
|
||||
#define SH4_PCICLKR_BCSTP 0x00000001 /* BCLK Clock Stop */
|
||||
/* For definitions of BCR, MCR see ... */
|
||||
#define SH4_PCIBCR1 0x1E0 /* Memory BCR1 Register */
|
||||
#define SH4_PCIMBR0 SH4_PCIBCR1
|
||||
#define SH4_PCIBCR2 0x1E4 /* Memory BCR2 Register */
|
||||
#define SH4_PCIMBMR0 SH4_PCIBCR2
|
||||
#define SH4_PCIWCR1 0x1E8 /* Wait Control 1 Register */
|
||||
#define SH4_PCIWCR2 0x1EC /* Wait Control 2 Register */
|
||||
#define SH4_PCIWCR3 0x1F0 /* Wait Control 3 Register */
|
||||
#define SH4_PCIMBR2 SH4_PCIWCR3
|
||||
#define SH4_PCIMCR 0x1F4 /* Memory Control Register */
|
||||
#define SH4_PCIBCR3 0x1f8 /* Memory BCR3 Register */
|
||||
#define SH4_PCIPCTR 0x200 /* Port Control Register */
|
||||
#define SH4_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */
|
||||
#define SH4_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */
|
||||
#define SH4_PCIPCTR_P0EN 0x000100000 /* Port 0 Enable */
|
||||
#define SH4_PCIPCTR_P2UP 0x000000020 /* Port2 Pull Up Enable */
|
||||
#define SH4_PCIPCTR_P2IO 0x000000010 /* Port2 Output Enable */
|
||||
#define SH4_PCIPCTR_P1UP 0x000000008 /* Port1 Pull Up Enable */
|
||||
#define SH4_PCIPCTR_P1IO 0x000000004 /* Port1 Output Enable */
|
||||
#define SH4_PCIPCTR_P0UP 0x000000002 /* Port0 Pull Up Enable */
|
||||
#define SH4_PCIPCTR_P0IO 0x000000001 /* Port0 Output Enable */
|
||||
#define SH4_PCIPDTR 0x204 /* Port Data Register */
|
||||
#define SH4_PCIPDTR_PB5 0x000000020 /* Port 5 Enable */
|
||||
#define SH4_PCIPDTR_PB4 0x000000010 /* Port 4 Enable */
|
||||
#define SH4_PCIPDTR_PB3 0x000000008 /* Port 3 Enable */
|
||||
#define SH4_PCIPDTR_PB2 0x000000004 /* Port 2 Enable */
|
||||
#define SH4_PCIPDTR_PB1 0x000000002 /* Port 1 Enable */
|
||||
#define SH4_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */
|
||||
#define SH4_PCIPDR 0x220 /* Port IO Data Register */
|
||||
|
||||
/* arch/sh/kernel/drivers/pci/ops-sh4.c */
|
||||
extern struct pci_ops sh4_pci_ops;
|
||||
int pci_fixup_pcic(struct pci_channel *chan);
|
||||
|
||||
struct sh4_pci_address_space {
|
||||
unsigned long base;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct sh4_pci_address_map {
|
||||
struct sh4_pci_address_space window0;
|
||||
struct sh4_pci_address_space window1;
|
||||
};
|
||||
|
||||
static inline void pci_write_reg(struct pci_channel *chan,
|
||||
unsigned long val, unsigned long reg)
|
||||
{
|
||||
__raw_writel(val, chan->reg_base + reg);
|
||||
}
|
||||
|
||||
static inline unsigned long pci_read_reg(struct pci_channel *chan,
|
||||
unsigned long reg)
|
||||
{
|
||||
return __raw_readl(chan->reg_base + reg);
|
||||
}
|
||||
|
||||
#endif /* __PCI_SH4_H */
|
220
arch/sh/drivers/pci/pci-sh5.c
Normal file
220
arch/sh/drivers/pci/pci-sh5.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Support functions for the SH5 PCI hardware.
|
||||
*/
|
||||
|
||||
#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 <cpu/irq.h>
|
||||
#include <asm/pci.h>
|
||||
#include <asm/io.h>
|
||||
#include "pci-sh5.h"
|
||||
|
||||
unsigned long pcicr_virt;
|
||||
unsigned long PCI_IO_AREA;
|
||||
|
||||
/* Rounds a number UP to the nearest power of two. Used for
|
||||
* sizing the PCI window.
|
||||
*/
|
||||
static u32 __init r2p2(u32 num)
|
||||
{
|
||||
int i = 31;
|
||||
u32 tmp = num;
|
||||
|
||||
if (num == 0)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
if (tmp & (1 << 31))
|
||||
break;
|
||||
i--;
|
||||
tmp <<= 1;
|
||||
} while (i >= 0);
|
||||
|
||||
tmp = 1 << i;
|
||||
/* If the original number isn't a power of 2, round it up */
|
||||
if (tmp != num)
|
||||
tmp <<= 1;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static irqreturn_t pcish5_err_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct pt_regs *regs = get_irq_regs();
|
||||
unsigned pci_int, pci_air, pci_cir, pci_aint;
|
||||
|
||||
pci_int = SH5PCI_READ(INT);
|
||||
pci_cir = SH5PCI_READ(CIR);
|
||||
pci_air = SH5PCI_READ(AIR);
|
||||
|
||||
if (pci_int) {
|
||||
printk("PCI INTERRUPT (at %08llx)!\n", regs->pc);
|
||||
printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
|
||||
printk("PCI AIR -> 0x%x\n", pci_air);
|
||||
printk("PCI CIR -> 0x%x\n", pci_cir);
|
||||
SH5PCI_WRITE(INT, ~0);
|
||||
}
|
||||
|
||||
pci_aint = SH5PCI_READ(AINT);
|
||||
if (pci_aint) {
|
||||
printk("PCI ARB INTERRUPT!\n");
|
||||
printk("PCI AINT -> 0x%x\n", pci_aint);
|
||||
printk("PCI AIR -> 0x%x\n", pci_air);
|
||||
printk("PCI CIR -> 0x%x\n", pci_cir);
|
||||
SH5PCI_WRITE(AINT, ~0);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
|
||||
{
|
||||
printk("SERR IRQ\n");
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static struct resource sh5_pci_resources[2];
|
||||
|
||||
static struct pci_channel sh5pci_controller = {
|
||||
.pci_ops = &sh5_pci_ops,
|
||||
.resources = sh5_pci_resources,
|
||||
.nr_resources = ARRAY_SIZE(sh5_pci_resources),
|
||||
.mem_offset = 0x00000000,
|
||||
.io_offset = 0x00000000,
|
||||
};
|
||||
|
||||
static int __init sh5pci_init(void)
|
||||
{
|
||||
unsigned long memStart = __pa(memory_start);
|
||||
unsigned long memSize = __pa(memory_end) - memStart;
|
||||
u32 lsr0;
|
||||
u32 uval;
|
||||
|
||||
if (request_irq(IRQ_ERR, pcish5_err_irq,
|
||||
0, "PCI Error",NULL) < 0) {
|
||||
printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (request_irq(IRQ_SERR, pcish5_serr_irq,
|
||||
0, "PCI SERR interrupt", NULL) < 0) {
|
||||
printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024);
|
||||
if (!pcicr_virt) {
|
||||
panic("Unable to remap PCICR\n");
|
||||
}
|
||||
|
||||
PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000);
|
||||
if (!PCI_IO_AREA) {
|
||||
panic("Unable to remap PCIIO\n");
|
||||
}
|
||||
|
||||
/* Clear snoop registers */
|
||||
SH5PCI_WRITE(CSCR0, 0);
|
||||
SH5PCI_WRITE(CSCR1, 0);
|
||||
|
||||
/* Switch off interrupts */
|
||||
SH5PCI_WRITE(INTM, 0);
|
||||
SH5PCI_WRITE(AINTM, 0);
|
||||
SH5PCI_WRITE(PINTM, 0);
|
||||
|
||||
/* Set bus active, take it out of reset */
|
||||
uval = SH5PCI_READ(CR);
|
||||
|
||||
/* Set command Register */
|
||||
SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE |
|
||||
CR_PFCS | CR_BMAM);
|
||||
|
||||
uval=SH5PCI_READ(CR);
|
||||
|
||||
/* Allow it to be a master */
|
||||
/* NB - WE DISABLE I/O ACCESS to stop overlap */
|
||||
/* set WAIT bit to enable stepping, an attempt to improve stability */
|
||||
SH5PCI_WRITE_SHORT(CSR_CMD,
|
||||
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_WAIT);
|
||||
|
||||
/*
|
||||
** Set translation mapping memory in order to convert the address
|
||||
** used for the main bus, to the PCI internal address.
|
||||
*/
|
||||
SH5PCI_WRITE(MBR,0x40000000);
|
||||
|
||||
/* Always set the max size 512M */
|
||||
SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024));
|
||||
|
||||
/*
|
||||
** I/O addresses are mapped at internal PCI specific address
|
||||
** as is described into the configuration bridge table.
|
||||
** These are changed to 0, to allow cards that have legacy
|
||||
** io such as vga to function correctly. We set the SH5 IOBAR to
|
||||
** 256K, which is a bit big as we can only have 64K of address space
|
||||
*/
|
||||
|
||||
SH5PCI_WRITE(IOBR,0x0);
|
||||
|
||||
/* Set up a 256K window. Totally pointless waste of address space */
|
||||
SH5PCI_WRITE(IOBMR,0);
|
||||
|
||||
/* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec.
|
||||
* Ideally, we would want to map the I/O region somewhere, but it
|
||||
* is so big this is not that easy!
|
||||
*/
|
||||
SH5PCI_WRITE(CSR_IBAR0,~0);
|
||||
/* Set memory size value */
|
||||
memSize = memory_end - memory_start;
|
||||
|
||||
/* Now we set up the mbars so the PCI bus can see the memory of
|
||||
* the machine */
|
||||
if (memSize < (1024 * 1024)) {
|
||||
printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%lx?\n",
|
||||
memSize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set LSR 0 */
|
||||
lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 :
|
||||
((r2p2(memSize) - 0x100000) | 0x1);
|
||||
SH5PCI_WRITE(LSR0, lsr0);
|
||||
|
||||
/* Set MBAR 0 */
|
||||
SH5PCI_WRITE(CSR_MBAR0, memory_start);
|
||||
SH5PCI_WRITE(LAR0, memory_start);
|
||||
|
||||
SH5PCI_WRITE(CSR_MBAR1,0);
|
||||
SH5PCI_WRITE(LAR1,0);
|
||||
SH5PCI_WRITE(LSR1,0);
|
||||
|
||||
/* Enable the PCI interrupts on the device */
|
||||
SH5PCI_WRITE(INTM, ~0);
|
||||
SH5PCI_WRITE(AINTM, ~0);
|
||||
SH5PCI_WRITE(PINTM, ~0);
|
||||
|
||||
sh5_pci_resources[0].start = PCI_IO_AREA;
|
||||
sh5_pci_resources[0].end = PCI_IO_AREA + 0x10000;
|
||||
|
||||
sh5_pci_resources[1].start = memStart;
|
||||
sh5_pci_resources[1].end = memStart + memSize;
|
||||
|
||||
return register_pci_controller(&sh5pci_controller);
|
||||
}
|
||||
arch_initcall(sh5pci_init);
|
110
arch/sh/drivers/pci/pci-sh5.h
Normal file
110
arch/sh/drivers/pci/pci-sh5.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
* Definitions for the SH5 PCI hardware.
|
||||
*/
|
||||
#ifndef __PCI_SH5_H
|
||||
#define __PCI_SH5_H
|
||||
|
||||
/* Product ID */
|
||||
#define PCISH5_PID 0x350d
|
||||
|
||||
/* vendor ID */
|
||||
#define PCISH5_VID 0x1054
|
||||
|
||||
/* Configuration types */
|
||||
#define ST_TYPE0 0x00 /* Configuration cycle type 0 */
|
||||
#define ST_TYPE1 0x01 /* Configuration cycle type 1 */
|
||||
|
||||
/* VCR data */
|
||||
#define PCISH5_VCR_STATUS 0x00
|
||||
#define PCISH5_VCR_VERSION 0x08
|
||||
|
||||
/*
|
||||
** ICR register offsets and bits
|
||||
*/
|
||||
#define PCISH5_ICR_CR 0x100 /* PCI control register values */
|
||||
#define CR_PBAM (1<<12)
|
||||
#define CR_PFCS (1<<11)
|
||||
#define CR_FTO (1<<10)
|
||||
#define CR_PFE (1<<9)
|
||||
#define CR_TBS (1<<8)
|
||||
#define CR_SPUE (1<<7)
|
||||
#define CR_BMAM (1<<6)
|
||||
#define CR_HOST (1<<5)
|
||||
#define CR_CLKEN (1<<4)
|
||||
#define CR_SOCS (1<<3)
|
||||
#define CR_IOCS (1<<2)
|
||||
#define CR_RSTCTL (1<<1)
|
||||
#define CR_CFINT (1<<0)
|
||||
#define CR_LOCK_MASK 0xa5000000
|
||||
|
||||
#define PCISH5_ICR_INT 0x114 /* Interrupt registert values */
|
||||
#define INT_MADIM (1<<2)
|
||||
|
||||
#define PCISH5_ICR_LSR0 0X104 /* Local space register values */
|
||||
#define PCISH5_ICR_LSR1 0X108 /* Local space register values */
|
||||
#define PCISH5_ICR_LAR0 0x10c /* Local address register values */
|
||||
#define PCISH5_ICR_LAR1 0x110 /* Local address register values */
|
||||
#define PCISH5_ICR_INTM 0x118 /* Interrupt mask register values */
|
||||
#define PCISH5_ICR_AIR 0x11c /* Interrupt error address information register values */
|
||||
#define PCISH5_ICR_CIR 0x120 /* Interrupt error command information register values */
|
||||
#define PCISH5_ICR_AINT 0x130 /* Interrupt error arbiter interrupt register values */
|
||||
#define PCISH5_ICR_AINTM 0x134 /* Interrupt error arbiter interrupt mask register values */
|
||||
#define PCISH5_ICR_BMIR 0x138 /* Interrupt error info register of bus master values */
|
||||
#define PCISH5_ICR_PAR 0x1c0 /* Pio address register values */
|
||||
#define PCISH5_ICR_MBR 0x1c4 /* Memory space bank register values */
|
||||
#define PCISH5_ICR_IOBR 0x1c8 /* I/O space bank register values */
|
||||
#define PCISH5_ICR_PINT 0x1cc /* power management interrupt register values */
|
||||
#define PCISH5_ICR_PINTM 0x1d0 /* power management interrupt mask register values */
|
||||
#define PCISH5_ICR_MBMR 0x1d8 /* memory space bank mask register values */
|
||||
#define PCISH5_ICR_IOBMR 0x1dc /* I/O space bank mask register values */
|
||||
#define PCISH5_ICR_CSCR0 0x210 /* PCI cache snoop control register 0 */
|
||||
#define PCISH5_ICR_CSCR1 0x214 /* PCI cache snoop control register 1 */
|
||||
#define PCISH5_ICR_PDR 0x220 /* Pio data register values */
|
||||
|
||||
/* These are configs space registers */
|
||||
#define PCISH5_ICR_CSR_VID 0x000 /* Vendor id */
|
||||
#define PCISH5_ICR_CSR_DID 0x002 /* Device id */
|
||||
#define PCISH5_ICR_CSR_CMD 0x004 /* Command register */
|
||||
#define PCISH5_ICR_CSR_STATUS 0x006 /* Stautus */
|
||||
#define PCISH5_ICR_CSR_IBAR0 0x010 /* I/O 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 */
|
||||
|
||||
/* Base address of registers */
|
||||
#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000)
|
||||
#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000)
|
||||
/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */
|
||||
|
||||
extern unsigned long pcicr_virt;
|
||||
/* Register selection macro */
|
||||
#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x))
|
||||
/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
|
||||
|
||||
/* Write I/O functions */
|
||||
#define SH5PCI_WRITE(reg,val) __raw_writel((u32)(val),PCISH5_ICR_REG(reg))
|
||||
#define SH5PCI_WRITE_SHORT(reg,val) __raw_writew((u16)(val),PCISH5_ICR_REG(reg))
|
||||
#define SH5PCI_WRITE_BYTE(reg,val) __raw_writeb((u8)(val),PCISH5_ICR_REG(reg))
|
||||
|
||||
/* Read I/O functions */
|
||||
#define SH5PCI_READ(reg) __raw_readl(PCISH5_ICR_REG(reg))
|
||||
#define SH5PCI_READ_SHORT(reg) __raw_readw(PCISH5_ICR_REG(reg))
|
||||
#define SH5PCI_READ_BYTE(reg) __raw_readb(PCISH5_ICR_REG(reg))
|
||||
|
||||
/* Set PCI config bits */
|
||||
#define SET_CONFIG_BITS(bus,devfn,where) ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000)
|
||||
|
||||
/* Set PCI command register */
|
||||
#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where)
|
||||
|
||||
/* Size converters */
|
||||
#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18)
|
||||
#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18)
|
||||
|
||||
extern struct pci_ops sh5_pci_ops;
|
||||
|
||||
#endif /* __PCI_SH5_H */
|
182
arch/sh/drivers/pci/pci-sh7751.c
Normal file
182
arch/sh/drivers/pci/pci-sh7751.c
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Low-Level PCI Support for the SH7751
|
||||
*
|
||||
* Copyright (C) 2003 - 2009 Paul Mundt
|
||||
* Copyright (C) 2001 Dustin McIntire
|
||||
*
|
||||
* With cleanup by Paul van Gool <pvangool@mimotech.com>, 2003.
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include "pci-sh4.h"
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
static int __init __area_sdram_check(struct pci_channel *chan,
|
||||
unsigned int area)
|
||||
{
|
||||
unsigned long word;
|
||||
|
||||
word = __raw_readl(SH7751_BCR1);
|
||||
/* check BCR for SDRAM in area */
|
||||
if (((word >> area) & 1) == 0) {
|
||||
printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%lx\n",
|
||||
area, word);
|
||||
return 0;
|
||||
}
|
||||
pci_write_reg(chan, word, SH4_PCIBCR1);
|
||||
|
||||
word = __raw_readw(SH7751_BCR2);
|
||||
/* check BCR2 for 32bit SDRAM interface*/
|
||||
if (((word >> (area << 1)) & 0x3) != 0x3) {
|
||||
printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%lx\n",
|
||||
area, word);
|
||||
return 0;
|
||||
}
|
||||
pci_write_reg(chan, word, SH4_PCIBCR2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct resource sh7751_pci_resources[] = {
|
||||
{
|
||||
.name = "SH7751_IO",
|
||||
.start = 0x1000,
|
||||
.end = SZ_4M - 1,
|
||||
.flags = IORESOURCE_IO
|
||||
}, {
|
||||
.name = "SH7751_mem",
|
||||
.start = SH7751_PCI_MEMORY_BASE,
|
||||
.end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM
|
||||
},
|
||||
};
|
||||
|
||||
static struct pci_channel sh7751_pci_controller = {
|
||||
.pci_ops = &sh4_pci_ops,
|
||||
.resources = sh7751_pci_resources,
|
||||
.nr_resources = ARRAY_SIZE(sh7751_pci_resources),
|
||||
.mem_offset = 0x00000000,
|
||||
.io_offset = 0x00000000,
|
||||
.io_map_base = SH7751_PCI_IO_BASE,
|
||||
};
|
||||
|
||||
static struct sh4_pci_address_map sh7751_pci_map = {
|
||||
.window0 = {
|
||||
.base = SH7751_CS3_BASE_ADDR,
|
||||
.size = 0x04000000,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sh7751_pci_init(void)
|
||||
{
|
||||
struct pci_channel *chan = &sh7751_pci_controller;
|
||||
unsigned int id;
|
||||
u32 word, reg;
|
||||
|
||||
printk(KERN_NOTICE "PCI: Starting initialization.\n");
|
||||
|
||||
chan->reg_base = 0xfe200000;
|
||||
|
||||
/* check for SH7751/SH7751R hardware */
|
||||
id = pci_read_reg(chan, SH7751_PCICONF0);
|
||||
if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
|
||||
id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
|
||||
pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Set the BCR's to enable PCI access */
|
||||
reg = __raw_readl(SH7751_BCR1);
|
||||
reg |= 0x80000;
|
||||
__raw_writel(reg, SH7751_BCR1);
|
||||
|
||||
/* Turn the clocks back on (not done in reset)*/
|
||||
pci_write_reg(chan, 0, SH4_PCICLKR);
|
||||
/* Clear Powerdown IRQ's (not done in reset) */
|
||||
word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
|
||||
pci_write_reg(chan, word, SH4_PCIPINT);
|
||||
|
||||
/* set the command/status bits to:
|
||||
* Wait Cycle Control + Parity Enable + Bus Master +
|
||||
* Mem space enable
|
||||
*/
|
||||
word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
|
||||
SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
|
||||
pci_write_reg(chan, word, SH7751_PCICONF1);
|
||||
|
||||
/* define this host as the host bridge */
|
||||
word = PCI_BASE_CLASS_BRIDGE << 24;
|
||||
pci_write_reg(chan, word, SH7751_PCICONF2);
|
||||
|
||||
/* Set IO and Mem windows to local address
|
||||
* Make PCI and local address the same for easy 1 to 1 mapping
|
||||
*/
|
||||
word = sh7751_pci_map.window0.size - 1;
|
||||
pci_write_reg(chan, word, SH4_PCILSR0);
|
||||
/* Set the values on window 0 PCI config registers */
|
||||
word = P2SEGADDR(sh7751_pci_map.window0.base);
|
||||
pci_write_reg(chan, word, SH4_PCILAR0);
|
||||
pci_write_reg(chan, word, SH7751_PCICONF5);
|
||||
|
||||
/* Set the local 16MB PCI memory space window to
|
||||
* the lowest PCI mapped address
|
||||
*/
|
||||
word = chan->resources[1].start & SH4_PCIMBR_MASK;
|
||||
pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
|
||||
pci_write_reg(chan, word , SH4_PCIMBR);
|
||||
|
||||
/* Make sure the MSB's of IO window are set to access PCI space
|
||||
* correctly */
|
||||
word = chan->resources[0].start & SH4_PCIIOBR_MASK;
|
||||
pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
|
||||
pci_write_reg(chan, word, SH4_PCIIOBR);
|
||||
|
||||
/* Set PCI WCRx, BCRx's, copy from BSC locations */
|
||||
|
||||
/* check BCR for SDRAM in specified area */
|
||||
switch (sh7751_pci_map.window0.base) {
|
||||
case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(chan, 0); break;
|
||||
case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(chan, 1); break;
|
||||
case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(chan, 2); break;
|
||||
case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(chan, 3); break;
|
||||
case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(chan, 4); break;
|
||||
case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(chan, 5); break;
|
||||
case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(chan, 6); break;
|
||||
}
|
||||
|
||||
if (!word)
|
||||
return -1;
|
||||
|
||||
/* configure the wait control registers */
|
||||
word = __raw_readl(SH7751_WCR1);
|
||||
pci_write_reg(chan, word, SH4_PCIWCR1);
|
||||
word = __raw_readl(SH7751_WCR2);
|
||||
pci_write_reg(chan, word, SH4_PCIWCR2);
|
||||
word = __raw_readl(SH7751_WCR3);
|
||||
pci_write_reg(chan, word, SH4_PCIWCR3);
|
||||
word = __raw_readl(SH7751_MCR);
|
||||
pci_write_reg(chan, word, SH4_PCIMCR);
|
||||
|
||||
/* NOTE: I'm ignoring the PCI error IRQs for now..
|
||||
* TODO: add support for the internal error interrupts and
|
||||
* DMA interrupts...
|
||||
*/
|
||||
|
||||
pci_fixup_pcic(chan);
|
||||
|
||||
/* SH7751 init done, set central function init complete */
|
||||
/* use round robin mode to stop a device starving/overruning */
|
||||
word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
|
||||
pci_write_reg(chan, word, SH4_PCICR);
|
||||
|
||||
return register_pci_controller(chan);
|
||||
}
|
||||
arch_initcall(sh7751_pci_init);
|
129
arch/sh/drivers/pci/pci-sh7751.h
Normal file
129
arch/sh/drivers/pci/pci-sh7751.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Low-Level PCI Support for SH7751 targets
|
||||
*
|
||||
* Dustin McIntire (dustin@sensoria.com) (c) 2001
|
||||
* Paul Mundt (lethal@linux-sh.org) (c) 2003
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PCI_SH7751_H_
|
||||
#define _PCI_SH7751_H_
|
||||
|
||||
/* Platform Specific Values */
|
||||
#define SH7751_VENDOR_ID 0x1054
|
||||
#define SH7751_DEVICE_ID 0x3505
|
||||
#define SH7751R_DEVICE_ID 0x350e
|
||||
|
||||
/* SH7751 Specific Values */
|
||||
#define SH7751_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
|
||||
#define SH7751_PCI_CONFIG_SIZE 0x1000000 /* Config space size */
|
||||
#define SH7751_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */
|
||||
#define SH7751_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */
|
||||
#define SH7751_PCI_IO_BASE 0xFE240000 /* IO space base address */
|
||||
#define SH7751_PCI_IO_SIZE 0x40000 /* Size of IO window */
|
||||
|
||||
#define SH7751_PCIREG_BASE 0xFE200000 /* PCI regs base address */
|
||||
|
||||
#define SH7751_PCICONF0 0x0 /* PCI Config Reg 0 */
|
||||
#define SH7751_PCICONF0_DEVID 0xFFFF0000 /* Device ID */
|
||||
#define SH7751_PCICONF0_VNDID 0x0000FFFF /* Vendor ID */
|
||||
#define SH7751_PCICONF1 0x4 /* PCI Config Reg 1 */
|
||||
#define SH7751_PCICONF1_DPE 0x80000000 /* Data Parity Error */
|
||||
#define SH7751_PCICONF1_SSE 0x40000000 /* System Error Status */
|
||||
#define SH7751_PCICONF1_RMA 0x20000000 /* Master Abort */
|
||||
#define SH7751_PCICONF1_RTA 0x10000000 /* Target Abort Rx Status */
|
||||
#define SH7751_PCICONF1_STA 0x08000000 /* Target Abort Exec Status */
|
||||
#define SH7751_PCICONF1_DEV 0x06000000 /* Timing Status */
|
||||
#define SH7751_PCICONF1_DPD 0x01000000 /* Data Parity Status */
|
||||
#define SH7751_PCICONF1_FBBC 0x00800000 /* Back 2 Back Status */
|
||||
#define SH7751_PCICONF1_UDF 0x00400000 /* User Defined Status */
|
||||
#define SH7751_PCICONF1_66M 0x00200000 /* 66Mhz Operation Status */
|
||||
#define SH7751_PCICONF1_PM 0x00100000 /* Power Management Status */
|
||||
#define SH7751_PCICONF1_PBBE 0x00000200 /* Back 2 Back Control */
|
||||
#define SH7751_PCICONF1_SER 0x00000100 /* SERR Output Control */
|
||||
#define SH7751_PCICONF1_WCC 0x00000080 /* Wait Cycle Control */
|
||||
#define SH7751_PCICONF1_PER 0x00000040 /* Parity Error Response */
|
||||
#define SH7751_PCICONF1_VPS 0x00000020 /* VGA Pallet Snoop */
|
||||
#define SH7751_PCICONF1_MWIE 0x00000010 /* Memory Write+Invalidate */
|
||||
#define SH7751_PCICONF1_SPC 0x00000008 /* Special Cycle Control */
|
||||
#define SH7751_PCICONF1_BUM 0x00000004 /* Bus Master Control */
|
||||
#define SH7751_PCICONF1_MES 0x00000002 /* Memory Space Control */
|
||||
#define SH7751_PCICONF1_IOS 0x00000001 /* I/O Space Control */
|
||||
#define SH7751_PCICONF2 0x8 /* PCI Config Reg 2 */
|
||||
#define SH7751_PCICONF2_BCC 0xFF000000 /* Base Class Code */
|
||||
#define SH7751_PCICONF2_SCC 0x00FF0000 /* Sub-Class Code */
|
||||
#define SH7751_PCICONF2_RLPI 0x0000FF00 /* Programming Interface */
|
||||
#define SH7751_PCICONF2_REV 0x000000FF /* Revision ID */
|
||||
#define SH7751_PCICONF3 0xC /* PCI Config Reg 3 */
|
||||
#define SH7751_PCICONF3_BIST7 0x80000000 /* Bist Supported */
|
||||
#define SH7751_PCICONF3_BIST6 0x40000000 /* Bist Executing */
|
||||
#define SH7751_PCICONF3_BIST3_0 0x0F000000 /* Bist Passed */
|
||||
#define SH7751_PCICONF3_HD7 0x00800000 /* Single Function device */
|
||||
#define SH7751_PCICONF3_HD6_0 0x007F0000 /* Configuration Layout */
|
||||
#define SH7751_PCICONF3_LAT 0x0000FF00 /* Latency Timer */
|
||||
#define SH7751_PCICONF3_CLS 0x000000FF /* Cache Line Size */
|
||||
#define SH7751_PCICONF4 0x10 /* PCI Config Reg 4 */
|
||||
#define SH7751_PCICONF4_BASE 0xFFFFFFFC /* I/O Space Base Addr */
|
||||
#define SH7751_PCICONF4_ASI 0x00000001 /* Address Space Type */
|
||||
#define SH7751_PCICONF5 0x14 /* PCI Config Reg 5 */
|
||||
#define SH7751_PCICONF5_BASE 0xFFFFFFF0 /* Mem Space Base Addr */
|
||||
#define SH7751_PCICONF5_LAP 0x00000008 /* Prefetch Enabled */
|
||||
#define SH7751_PCICONF5_LAT 0x00000006 /* Local Memory type */
|
||||
#define SH7751_PCICONF5_ASI 0x00000001 /* Address Space Type */
|
||||
#define SH7751_PCICONF6 0x18 /* PCI Config Reg 6 */
|
||||
#define SH7751_PCICONF6_BASE 0xFFFFFFF0 /* Mem Space Base Addr */
|
||||
#define SH7751_PCICONF6_LAP 0x00000008 /* Prefetch Enabled */
|
||||
#define SH7751_PCICONF6_LAT 0x00000006 /* Local Memory type */
|
||||
#define SH7751_PCICONF6_ASI 0x00000001 /* Address Space Type */
|
||||
/* PCICONF7 - PCICONF10 are undefined */
|
||||
#define SH7751_PCICONF11 0x2C /* PCI Config Reg 11 */
|
||||
#define SH7751_PCICONF11_SSID 0xFFFF0000 /* Subsystem ID */
|
||||
#define SH7751_PCICONF11_SVID 0x0000FFFF /* Subsystem Vendor ID */
|
||||
/* PCICONF12 is undefined */
|
||||
#define SH7751_PCICONF13 0x34 /* PCI Config Reg 13 */
|
||||
#define SH7751_PCICONF13_CPTR 0x000000FF /* PM function pointer */
|
||||
/* PCICONF14 is undefined */
|
||||
#define SH7751_PCICONF15 0x3C /* PCI Config Reg 15 */
|
||||
#define SH7751_PCICONF15_IPIN 0x000000FF /* Interrupt Pin */
|
||||
#define SH7751_PCICONF16 0x40 /* PCI Config Reg 16 */
|
||||
#define SH7751_PCICONF16_PMES 0xF8000000 /* PME Support */
|
||||
#define SH7751_PCICONF16_D2S 0x04000000 /* D2 Support */
|
||||
#define SH7751_PCICONF16_D1S 0x02000000 /* D1 Support */
|
||||
#define SH7751_PCICONF16_DSI 0x00200000 /* Bit Device Init. */
|
||||
#define SH7751_PCICONF16_PMCK 0x00080000 /* Clock for PME req. */
|
||||
#define SH7751_PCICONF16_VER 0x00070000 /* PM Version */
|
||||
#define SH7751_PCICONF16_NIP 0x0000FF00 /* Next Item Pointer */
|
||||
#define SH7751_PCICONF16_CID 0x000000FF /* Capability Identifier */
|
||||
#define SH7751_PCICONF17 0x44 /* PCI Config Reg 17 */
|
||||
#define SH7751_PCICONF17_DATA 0xFF000000 /* Data field for PM */
|
||||
#define SH7751_PCICONF17_PMES 0x00800000 /* PME Status */
|
||||
#define SH7751_PCICONF17_DSCL 0x00600000 /* Data Scaling Value */
|
||||
#define SH7751_PCICONF17_DSEL 0x001E0000 /* Data Select */
|
||||
#define SH7751_PCICONF17_PMEN 0x00010000 /* PME Enable */
|
||||
#define SH7751_PCICONF17_PWST 0x00000003 /* Power State */
|
||||
/* SH7715 Internal PCI Registers */
|
||||
|
||||
/* Memory Control Registers */
|
||||
#define SH7751_BCR1 0xFF800000 /* Memory BCR1 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_WCR2 0xFF80000C /* Wait Control 2 Register */
|
||||
#define SH7751_WCR3 0xFF800010 /* Wait Control 3 Register */
|
||||
#define SH7751_MCR 0xFF800014 /* Memory Control Register */
|
||||
|
||||
/* General Memory Config Addresses */
|
||||
#define SH7751_CS0_BASE_ADDR 0x0
|
||||
#define SH7751_MEM_REGION_SIZE 0x04000000
|
||||
#define SH7751_CS1_BASE_ADDR (SH7751_CS0_BASE_ADDR + SH7751_MEM_REGION_SIZE)
|
||||
#define SH7751_CS2_BASE_ADDR (SH7751_CS1_BASE_ADDR + SH7751_MEM_REGION_SIZE)
|
||||
#define SH7751_CS3_BASE_ADDR (SH7751_CS2_BASE_ADDR + SH7751_MEM_REGION_SIZE)
|
||||
#define SH7751_CS4_BASE_ADDR (SH7751_CS3_BASE_ADDR + SH7751_MEM_REGION_SIZE)
|
||||
#define SH7751_CS5_BASE_ADDR (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
|
||||
#define SH7751_CS6_BASE_ADDR (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
|
||||
|
||||
#endif /* _PCI_SH7751_H_ */
|
411
arch/sh/drivers/pci/pci-sh7780.c
Normal file
411
arch/sh/drivers/pci/pci-sh7780.c
Normal file
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* Low-Level PCI Support for the SH7780
|
||||
*
|
||||
* Copyright (C) 2005 - 2010 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 <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/log2.h>
|
||||
#include "pci-sh4.h"
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#if defined(CONFIG_CPU_BIG_ENDIAN)
|
||||
# define PCICR_ENDIANNESS SH4_PCICR_BSWP
|
||||
#else
|
||||
# define PCICR_ENDIANNESS 0
|
||||
#endif
|
||||
|
||||
|
||||
static struct resource sh7785_pci_resources[] = {
|
||||
{
|
||||
.name = "PCI IO",
|
||||
.start = 0x1000,
|
||||
.end = SZ_4M - 1,
|
||||
.flags = IORESOURCE_IO,
|
||||
}, {
|
||||
.name = "PCI MEM 0",
|
||||
.start = 0xfd000000,
|
||||
.end = 0xfd000000 + SZ_16M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.name = "PCI MEM 1",
|
||||
.start = 0x10000000,
|
||||
.end = 0x10000000 + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
/*
|
||||
* 32-bit only resources must be last.
|
||||
*/
|
||||
.name = "PCI MEM 2",
|
||||
.start = 0xc0000000,
|
||||
.end = 0xc0000000 + SZ_512M - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct pci_channel sh7780_pci_controller = {
|
||||
.pci_ops = &sh4_pci_ops,
|
||||
.resources = sh7785_pci_resources,
|
||||
.nr_resources = ARRAY_SIZE(sh7785_pci_resources),
|
||||
.io_offset = 0,
|
||||
.mem_offset = 0,
|
||||
.io_map_base = 0xfe200000,
|
||||
.serr_irq = evt2irq(0xa00),
|
||||
.err_irq = evt2irq(0xaa0),
|
||||
};
|
||||
|
||||
struct pci_errors {
|
||||
unsigned int mask;
|
||||
const char *str;
|
||||
} pci_arbiter_errors[] = {
|
||||
{ SH4_PCIAINT_MBKN, "master broken" },
|
||||
{ SH4_PCIAINT_TBTO, "target bus time out" },
|
||||
{ SH4_PCIAINT_MBTO, "master bus time out" },
|
||||
{ SH4_PCIAINT_TABT, "target abort" },
|
||||
{ SH4_PCIAINT_MABT, "master abort" },
|
||||
{ SH4_PCIAINT_RDPE, "read data parity error" },
|
||||
{ SH4_PCIAINT_WDPE, "write data parity error" },
|
||||
}, pci_interrupt_errors[] = {
|
||||
{ SH4_PCIINT_MLCK, "master lock error" },
|
||||
{ SH4_PCIINT_TABT, "target-target abort" },
|
||||
{ SH4_PCIINT_TRET, "target retry time out" },
|
||||
{ SH4_PCIINT_MFDE, "master function disable error" },
|
||||
{ SH4_PCIINT_PRTY, "address parity error" },
|
||||
{ SH4_PCIINT_SERR, "SERR" },
|
||||
{ SH4_PCIINT_TWDP, "data parity error for target write" },
|
||||
{ SH4_PCIINT_TRDP, "PERR detected for target read" },
|
||||
{ SH4_PCIINT_MTABT, "target abort for master" },
|
||||
{ SH4_PCIINT_MMABT, "master abort for master" },
|
||||
{ SH4_PCIINT_MWPD, "master write data parity error" },
|
||||
{ SH4_PCIINT_MRPD, "master read data parity error" },
|
||||
};
|
||||
|
||||
static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct pci_channel *hose = dev_id;
|
||||
unsigned long addr;
|
||||
unsigned int status;
|
||||
unsigned int cmd;
|
||||
int i;
|
||||
|
||||
addr = __raw_readl(hose->reg_base + SH4_PCIALR);
|
||||
|
||||
/*
|
||||
* Handle status errors.
|
||||
*/
|
||||
status = __raw_readw(hose->reg_base + PCI_STATUS);
|
||||
if (status & (PCI_STATUS_PARITY |
|
||||
PCI_STATUS_DETECTED_PARITY |
|
||||
PCI_STATUS_SIG_TARGET_ABORT |
|
||||
PCI_STATUS_REC_TARGET_ABORT |
|
||||
PCI_STATUS_REC_MASTER_ABORT)) {
|
||||
cmd = pcibios_handle_status_errors(addr, status, hose);
|
||||
if (likely(cmd))
|
||||
__raw_writew(cmd, hose->reg_base + PCI_STATUS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle arbiter errors.
|
||||
*/
|
||||
status = __raw_readl(hose->reg_base + SH4_PCIAINT);
|
||||
for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) {
|
||||
if (status & pci_arbiter_errors[i].mask) {
|
||||
printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
|
||||
pci_arbiter_errors[i].str, addr);
|
||||
cmd |= pci_arbiter_errors[i].mask;
|
||||
}
|
||||
}
|
||||
__raw_writel(cmd, hose->reg_base + SH4_PCIAINT);
|
||||
|
||||
/*
|
||||
* Handle the remaining PCI errors.
|
||||
*/
|
||||
status = __raw_readl(hose->reg_base + SH4_PCIINT);
|
||||
for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) {
|
||||
if (status & pci_interrupt_errors[i].mask) {
|
||||
printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
|
||||
pci_interrupt_errors[i].str, addr);
|
||||
cmd |= pci_interrupt_errors[i].mask;
|
||||
}
|
||||
}
|
||||
__raw_writel(cmd, hose->reg_base + SH4_PCIINT);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct pci_channel *hose = dev_id;
|
||||
|
||||
printk(KERN_DEBUG "PCI: system error received: ");
|
||||
pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
|
||||
printk("\n");
|
||||
|
||||
/* Deassert SERR */
|
||||
__raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM);
|
||||
|
||||
/* Back off the IRQ for awhile */
|
||||
disable_irq_nosync(irq);
|
||||
hose->serr_timer.expires = jiffies + HZ;
|
||||
add_timer(&hose->serr_timer);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init sh7780_pci_setup_irqs(struct pci_channel *hose)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Clear out PCI arbiter IRQs */
|
||||
__raw_writel(0, hose->reg_base + SH4_PCIAINT);
|
||||
|
||||
/* Clear all error conditions */
|
||||
__raw_writew(PCI_STATUS_DETECTED_PARITY | \
|
||||
PCI_STATUS_SIG_SYSTEM_ERROR | \
|
||||
PCI_STATUS_REC_MASTER_ABORT | \
|
||||
PCI_STATUS_REC_TARGET_ABORT | \
|
||||
PCI_STATUS_SIG_TARGET_ABORT | \
|
||||
PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
|
||||
|
||||
ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, 0,
|
||||
"PCI SERR interrupt", hose);
|
||||
if (unlikely(ret)) {
|
||||
printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The PCI ERR IRQ needs to be IRQF_SHARED since all of the power
|
||||
* down IRQ vectors are routed through the ERR IRQ vector. We
|
||||
* only request_irq() once as there is only a single masking
|
||||
* source for multiple events.
|
||||
*/
|
||||
ret = request_irq(hose->err_irq, sh7780_pci_err_irq, IRQF_SHARED,
|
||||
"PCI ERR interrupt", hose);
|
||||
if (unlikely(ret)) {
|
||||
free_irq(hose->serr_irq, hose);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Unmask all of the arbiter IRQs. */
|
||||
__raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \
|
||||
SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \
|
||||
SH4_PCIAINT_WDPE, hose->reg_base + SH4_PCIAINTM);
|
||||
|
||||
/* Unmask all of the PCI IRQs */
|
||||
__raw_writel(SH4_PCIINTM_TTADIM | SH4_PCIINTM_TMTOIM | \
|
||||
SH4_PCIINTM_MDEIM | SH4_PCIINTM_APEDIM | \
|
||||
SH4_PCIINTM_SDIM | SH4_PCIINTM_DPEITWM | \
|
||||
SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM | \
|
||||
SH4_PCIINTM_MADIMM | SH4_PCIINTM_MWPDIM | \
|
||||
SH4_PCIINTM_MRDPEIM, hose->reg_base + SH4_PCIINTM);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void __init sh7780_pci_teardown_irqs(struct pci_channel *hose)
|
||||
{
|
||||
free_irq(hose->err_irq, hose);
|
||||
free_irq(hose->serr_irq, hose);
|
||||
}
|
||||
|
||||
static void __init sh7780_pci66_init(struct pci_channel *hose)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
if (!pci_is_66mhz_capable(hose, 0, 0))
|
||||
return;
|
||||
|
||||
/* Enable register access */
|
||||
tmp = __raw_readl(hose->reg_base + SH4_PCICR);
|
||||
tmp |= SH4_PCICR_PREFIX;
|
||||
__raw_writel(tmp, hose->reg_base + SH4_PCICR);
|
||||
|
||||
/* Enable 66MHz operation */
|
||||
tmp = __raw_readw(hose->reg_base + PCI_STATUS);
|
||||
tmp |= PCI_STATUS_66MHZ;
|
||||
__raw_writew(tmp, hose->reg_base + PCI_STATUS);
|
||||
|
||||
/* Done */
|
||||
tmp = __raw_readl(hose->reg_base + SH4_PCICR);
|
||||
tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN;
|
||||
__raw_writel(tmp, hose->reg_base + SH4_PCICR);
|
||||
}
|
||||
|
||||
static int __init sh7780_pci_init(void)
|
||||
{
|
||||
struct pci_channel *chan = &sh7780_pci_controller;
|
||||
phys_addr_t memphys;
|
||||
size_t memsize;
|
||||
unsigned int id;
|
||||
const char *type;
|
||||
int ret, i;
|
||||
|
||||
printk(KERN_NOTICE "PCI: Starting initialization.\n");
|
||||
|
||||
chan->reg_base = 0xfe040000;
|
||||
|
||||
/* Enable CPU access to the PCIC registers. */
|
||||
__raw_writel(PCIECR_ENBL, PCIECR);
|
||||
|
||||
/* Reset */
|
||||
__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST | PCICR_ENDIANNESS,
|
||||
chan->reg_base + SH4_PCICR);
|
||||
|
||||
/*
|
||||
* Wait for it to come back up. The spec says to allow for up to
|
||||
* 1 second after toggling the reset pin, but in practice 100ms
|
||||
* is more than enough.
|
||||
*/
|
||||
mdelay(100);
|
||||
|
||||
id = __raw_readw(chan->reg_base + PCI_VENDOR_ID);
|
||||
if (id != PCI_VENDOR_ID_RENESAS) {
|
||||
printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
id = __raw_readw(chan->reg_base + PCI_DEVICE_ID);
|
||||
type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" :
|
||||
(id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" :
|
||||
(id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" :
|
||||
(id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" :
|
||||
NULL;
|
||||
if (unlikely(!type)) {
|
||||
printk(KERN_ERR "PCI: Found an unsupported Renesas host "
|
||||
"controller, device id 0x%04x.\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printk(KERN_NOTICE "PCI: Found a Renesas %s host "
|
||||
"controller, revision %d.\n", type,
|
||||
__raw_readb(chan->reg_base + PCI_REVISION_ID));
|
||||
|
||||
/*
|
||||
* Now throw it in to register initialization mode and
|
||||
* start the real work.
|
||||
*/
|
||||
__raw_writel(SH4_PCICR_PREFIX | PCICR_ENDIANNESS,
|
||||
chan->reg_base + SH4_PCICR);
|
||||
|
||||
memphys = __pa(memory_start);
|
||||
memsize = roundup_pow_of_two(memory_end - memory_start);
|
||||
|
||||
/*
|
||||
* If there's more than 512MB of memory, we need to roll over to
|
||||
* LAR1/LSR1.
|
||||
*/
|
||||
if (memsize > SZ_512M) {
|
||||
__raw_writel(memphys + SZ_512M, chan->reg_base + SH4_PCILAR1);
|
||||
__raw_writel((((memsize - SZ_512M) - SZ_1M) & 0x1ff00000) | 1,
|
||||
chan->reg_base + SH4_PCILSR1);
|
||||
memsize = SZ_512M;
|
||||
} else {
|
||||
/*
|
||||
* Otherwise just zero it out and disable it.
|
||||
*/
|
||||
__raw_writel(0, chan->reg_base + SH4_PCILAR1);
|
||||
__raw_writel(0, chan->reg_base + SH4_PCILSR1);
|
||||
}
|
||||
|
||||
/*
|
||||
* LAR0/LSR0 covers up to the first 512MB, which is enough to
|
||||
* cover all of lowmem on most platforms.
|
||||
*/
|
||||
__raw_writel(memphys, chan->reg_base + SH4_PCILAR0);
|
||||
__raw_writel(((memsize - SZ_1M) & 0x1ff00000) | 1,
|
||||
chan->reg_base + SH4_PCILSR0);
|
||||
|
||||
/*
|
||||
* Hook up the ERR and SERR IRQs.
|
||||
*/
|
||||
ret = sh7780_pci_setup_irqs(chan);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Disable the cache snoop controller for non-coherent DMA.
|
||||
*/
|
||||
__raw_writel(0, chan->reg_base + SH7780_PCICSCR0);
|
||||
__raw_writel(0, chan->reg_base + SH7780_PCICSAR0);
|
||||
__raw_writel(0, chan->reg_base + SH7780_PCICSCR1);
|
||||
__raw_writel(0, chan->reg_base + SH7780_PCICSAR1);
|
||||
|
||||
/*
|
||||
* Setup the memory BARs
|
||||
*/
|
||||
for (i = 1; i < chan->nr_resources; i++) {
|
||||
struct resource *res = chan->resources + i;
|
||||
resource_size_t size;
|
||||
|
||||
if (unlikely(res->flags & IORESOURCE_IO))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Make sure we're in the right physical addressing mode
|
||||
* for dealing with the resource.
|
||||
*/
|
||||
if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) {
|
||||
chan->nr_resources--;
|
||||
continue;
|
||||
}
|
||||
|
||||
size = resource_size(res);
|
||||
|
||||
/*
|
||||
* The MBMR mask is calculated in units of 256kB, which
|
||||
* keeps things pretty simple.
|
||||
*/
|
||||
__raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
|
||||
chan->reg_base + SH7780_PCIMBMR(i - 1));
|
||||
__raw_writel(res->start, chan->reg_base + SH7780_PCIMBR(i - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* And I/O.
|
||||
*/
|
||||
__raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0);
|
||||
__raw_writel(0, chan->reg_base + SH7780_PCIIOBR);
|
||||
__raw_writel(0, chan->reg_base + SH7780_PCIIOBMR);
|
||||
|
||||
__raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \
|
||||
PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \
|
||||
PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND);
|
||||
|
||||
/*
|
||||
* Initialization mode complete, release the control register and
|
||||
* enable round robin mode to stop device overruns/starvation.
|
||||
*/
|
||||
__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO |
|
||||
PCICR_ENDIANNESS,
|
||||
chan->reg_base + SH4_PCICR);
|
||||
|
||||
ret = register_pci_controller(chan);
|
||||
if (unlikely(ret))
|
||||
goto err;
|
||||
|
||||
sh7780_pci66_init(chan);
|
||||
|
||||
printk(KERN_NOTICE "PCI: Running at %dMHz.\n",
|
||||
(__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ?
|
||||
66 : 33);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
sh7780_pci_teardown_irqs(chan);
|
||||
return ret;
|
||||
}
|
||||
arch_initcall(sh7780_pci_init);
|
46
arch/sh/drivers/pci/pci-sh7780.h
Normal file
46
arch/sh/drivers/pci/pci-sh7780.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Low-Level PCI Support for SH7780 targets
|
||||
*
|
||||
* Dustin McIntire (dustin@sensoria.com) (c) 2001
|
||||
* Paul Mundt (lethal@linux-sh.org) (c) 2003
|
||||
*
|
||||
* May be copied or modified under the terms of the GNU General Public
|
||||
* License. See linux/COPYING for more information.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PCI_SH7780_H_
|
||||
#define _PCI_SH7780_H_
|
||||
|
||||
/* SH7780 Control Registers */
|
||||
#define PCIECR 0xFE000008
|
||||
#define PCIECR_ENBL 0x01
|
||||
|
||||
/* SH7780 Specific Values */
|
||||
#define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */
|
||||
#define SH7780_PCI_CONFIG_SIZE 0x01000000 /* Config space size */
|
||||
|
||||
#define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */
|
||||
|
||||
/* SH7780 PCI Config Registers */
|
||||
#define SH7780_PCIIR 0x114 /* PCI Interrupt Register */
|
||||
#define SH7780_PCIIMR 0x118 /* PCI Interrupt Mask Register */
|
||||
#define SH7780_PCIAIR 0x11C /* Error Address Register */
|
||||
#define SH7780_PCICIR 0x120 /* Error Command/Data Register */
|
||||
#define SH7780_PCIAINT 0x130 /* Arbiter Interrupt Register */
|
||||
#define SH7780_PCIAINTM 0x134 /* Arbiter Int. Mask Register */
|
||||
#define SH7780_PCIBMIR 0x138 /* Error Bus Master Register */
|
||||
#define SH7780_PCIPAR 0x1C0 /* PIO Address Register */
|
||||
#define SH7780_PCIPINT 0x1CC /* Power Mgmnt Int. Register */
|
||||
#define SH7780_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */
|
||||
|
||||
#define SH7780_PCIMBR(x) (0x1E0 + ((x) * 8))
|
||||
#define SH7780_PCIMBMR(x) (0x1E4 + ((x) * 8))
|
||||
#define SH7780_PCIIOBR 0x1F8
|
||||
#define SH7780_PCIIOBMR 0x1FC
|
||||
#define SH7780_PCICSCR0 0x210 /* Cache Snoop1 Cnt. Register */
|
||||
#define SH7780_PCICSCR1 0x214 /* Cache Snoop2 Cnt. Register */
|
||||
#define SH7780_PCICSAR0 0x218 /* Cache Snoop1 Addr. Register */
|
||||
#define SH7780_PCICSAR1 0x21C /* Cache Snoop2 Addr. Register */
|
||||
|
||||
#endif /* _PCI_SH7780_H_ */
|
317
arch/sh/drivers/pci/pci.c
Normal file
317
arch/sh/drivers/pci/pci.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* New-style PCI core.
|
||||
*
|
||||
* Copyright (c) 2004 - 2009 Paul Mundt
|
||||
* Copyright (c) 2002 M. R. Brown
|
||||
*
|
||||
* Modelled after arch/mips/pci/pci.c:
|
||||
* Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org)
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/dma-debug.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
unsigned long PCIBIOS_MIN_IO = 0x0000;
|
||||
unsigned long PCIBIOS_MIN_MEM = 0;
|
||||
|
||||
/*
|
||||
* The PCI controller list.
|
||||
*/
|
||||
static struct pci_channel *hose_head, **hose_tail = &hose_head;
|
||||
|
||||
static int pci_initialized;
|
||||
|
||||
static void pcibios_scanbus(struct pci_channel *hose)
|
||||
{
|
||||
static int next_busno;
|
||||
static int need_domain_info;
|
||||
LIST_HEAD(resources);
|
||||
struct resource *res;
|
||||
resource_size_t offset;
|
||||
int i;
|
||||
struct pci_bus *bus;
|
||||
|
||||
for (i = 0; i < hose->nr_resources; i++) {
|
||||
res = hose->resources + i;
|
||||
offset = 0;
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
offset = hose->io_offset;
|
||||
else if (res->flags & IORESOURCE_MEM)
|
||||
offset = hose->mem_offset;
|
||||
pci_add_resource_offset(&resources, res, offset);
|
||||
}
|
||||
|
||||
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
|
||||
&resources);
|
||||
hose->bus = bus;
|
||||
|
||||
need_domain_info = need_domain_info || hose->index;
|
||||
hose->need_domain_info = need_domain_info;
|
||||
if (bus) {
|
||||
next_busno = bus->busn_res.end + 1;
|
||||
/* Don't allow 8-bit bus number overflow inside the hose -
|
||||
reserve some space for bridges. */
|
||||
if (next_busno > 224) {
|
||||
next_busno = 0;
|
||||
need_domain_info = 1;
|
||||
}
|
||||
|
||||
pci_bus_size_bridges(bus);
|
||||
pci_bus_assign_resources(bus);
|
||||
} else {
|
||||
pci_free_resource_list(&resources);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This interrupt-safe spinlock protects all accesses to PCI
|
||||
* configuration space.
|
||||
*/
|
||||
DEFINE_RAW_SPINLOCK(pci_config_lock);
|
||||
static DEFINE_MUTEX(pci_scan_mutex);
|
||||
|
||||
int register_pci_controller(struct pci_channel *hose)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hose->nr_resources; i++) {
|
||||
struct resource *res = hose->resources + i;
|
||||
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
if (request_resource(&ioport_resource, res) < 0)
|
||||
goto out;
|
||||
} else {
|
||||
if (request_resource(&iomem_resource, res) < 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
*hose_tail = hose;
|
||||
hose_tail = &hose->next;
|
||||
|
||||
/*
|
||||
* Do not panic here but later - this might happen before console init.
|
||||
*/
|
||||
if (!hose->io_map_base) {
|
||||
printk(KERN_WARNING
|
||||
"registering PCI controller with io_map_base unset\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the ERR/PERR and SERR timers, if available.
|
||||
*/
|
||||
pcibios_enable_timers(hose);
|
||||
|
||||
/*
|
||||
* Scan the bus if it is register after the PCI subsystem
|
||||
* initialization.
|
||||
*/
|
||||
if (pci_initialized) {
|
||||
mutex_lock(&pci_scan_mutex);
|
||||
pcibios_scanbus(hose);
|
||||
mutex_unlock(&pci_scan_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
for (--i; i >= 0; i--)
|
||||
release_resource(&hose->resources[i]);
|
||||
|
||||
printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __init pcibios_init(void)
|
||||
{
|
||||
struct pci_channel *hose;
|
||||
|
||||
/* Scan all of the recorded PCI controllers. */
|
||||
for (hose = hose_head; hose; hose = hose->next)
|
||||
pcibios_scanbus(hose);
|
||||
|
||||
pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
|
||||
|
||||
dma_debug_add_bus(&pci_bus_type);
|
||||
|
||||
pci_initialized = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(pcibios_init);
|
||||
|
||||
/*
|
||||
* Called after each bus is probed, but before its children
|
||||
* are examined.
|
||||
*/
|
||||
void pcibios_fixup_bus(struct pci_bus *bus)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to avoid collisions with `mirrored' VGA ports
|
||||
* and other strange ISA hardware, so we always want the
|
||||
* addresses to be allocated in the 0x000-0x0ff region
|
||||
* modulo 0x400.
|
||||
*/
|
||||
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
{
|
||||
struct pci_dev *dev = data;
|
||||
struct pci_channel *hose = dev->sysdata;
|
||||
resource_size_t start = res->start;
|
||||
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
if (start < PCIBIOS_MIN_IO + hose->resources[0].start)
|
||||
start = PCIBIOS_MIN_IO + hose->resources[0].start;
|
||||
|
||||
/*
|
||||
* Put everything into 0x00-0xff region modulo 0x400.
|
||||
*/
|
||||
if (start & 0x300)
|
||||
start = (start + 0x3ff) & ~0x3ff;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
static void __init
|
||||
pcibios_bus_report_status_early(struct pci_channel *hose,
|
||||
int top_bus, int current_bus,
|
||||
unsigned int status_mask, int warn)
|
||||
{
|
||||
unsigned int pci_devfn;
|
||||
u16 status;
|
||||
int ret;
|
||||
|
||||
for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
|
||||
if (PCI_FUNC(pci_devfn))
|
||||
continue;
|
||||
ret = early_read_config_word(hose, top_bus, current_bus,
|
||||
pci_devfn, PCI_STATUS, &status);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
continue;
|
||||
if (status == 0xffff)
|
||||
continue;
|
||||
|
||||
early_write_config_word(hose, top_bus, current_bus,
|
||||
pci_devfn, PCI_STATUS,
|
||||
status & status_mask);
|
||||
if (warn)
|
||||
printk("(%02x:%02x: %04X) ", current_bus,
|
||||
pci_devfn, status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't use pci_find_device() here since we are
|
||||
* called from interrupt context.
|
||||
*/
|
||||
static void __init_refok
|
||||
pcibios_bus_report_status(struct pci_bus *bus, unsigned int status_mask,
|
||||
int warn)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
u16 status;
|
||||
|
||||
/*
|
||||
* ignore host bridge - we handle
|
||||
* that separately
|
||||
*/
|
||||
if (dev->bus->number == 0 && dev->devfn == 0)
|
||||
continue;
|
||||
|
||||
pci_read_config_word(dev, PCI_STATUS, &status);
|
||||
if (status == 0xffff)
|
||||
continue;
|
||||
|
||||
if ((status & status_mask) == 0)
|
||||
continue;
|
||||
|
||||
/* clear the status errors */
|
||||
pci_write_config_word(dev, PCI_STATUS, status & status_mask);
|
||||
|
||||
if (warn)
|
||||
printk("(%s: %04X) ", pci_name(dev), status);
|
||||
}
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
if (dev->subordinate)
|
||||
pcibios_bus_report_status(dev->subordinate, status_mask, warn);
|
||||
}
|
||||
|
||||
void __init_refok pcibios_report_status(unsigned int status_mask, int warn)
|
||||
{
|
||||
struct pci_channel *hose;
|
||||
|
||||
for (hose = hose_head; hose; hose = hose->next) {
|
||||
if (unlikely(!hose->bus))
|
||||
pcibios_bus_report_status_early(hose, hose_head->index,
|
||||
hose->index, status_mask, warn);
|
||||
else
|
||||
pcibios_bus_report_status(hose->bus, status_mask, warn);
|
||||
}
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
/*
|
||||
* I/O space can be accessed via normal processor loads and stores on
|
||||
* this platform but for now we elect not to do this and portable
|
||||
* drivers should not do this anyway.
|
||||
*/
|
||||
if (mmap_state == pci_mmap_io)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Ignore write-combine; for now only return uncached mappings.
|
||||
*/
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
|
||||
return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_GENERIC_IOMAP
|
||||
|
||||
void __iomem *__pci_ioport_map(struct pci_dev *dev,
|
||||
unsigned long port, unsigned int nr)
|
||||
{
|
||||
struct pci_channel *chan = dev->sysdata;
|
||||
|
||||
if (unlikely(!chan->io_map_base)) {
|
||||
chan->io_map_base = sh_io_port_base;
|
||||
|
||||
if (pci_domains_supported)
|
||||
panic("To avoid data corruption io_map_base MUST be "
|
||||
"set with multiple PCI domains.");
|
||||
}
|
||||
|
||||
return (void __iomem *)(chan->io_map_base + port);
|
||||
}
|
||||
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
|
||||
{
|
||||
iounmap(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iounmap);
|
||||
|
||||
#endif /* CONFIG_GENERIC_IOMAP */
|
||||
|
||||
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
|
||||
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
|
579
arch/sh/drivers/pci/pcie-sh7786.c
Normal file
579
arch/sh/drivers/pci/pcie-sh7786.c
Normal file
|
@ -0,0 +1,579 @@
|
|||
/*
|
||||
* Low-Level PCI Express Support for the SH7786
|
||||
*
|
||||
* Copyright (C) 2009 - 2011 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.
|
||||
*/
|
||||
#define pr_fmt(fmt) "PCI: " fmt
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/sh_clk.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include "pcie-sh7786.h"
|
||||
#include <asm/sizes.h>
|
||||
|
||||
struct sh7786_pcie_port {
|
||||
struct pci_channel *hose;
|
||||
struct clk *fclk, phy_clk;
|
||||
unsigned int index;
|
||||
int endpoint;
|
||||
int link;
|
||||
};
|
||||
|
||||
static struct sh7786_pcie_port *sh7786_pcie_ports;
|
||||
static unsigned int nr_ports;
|
||||
|
||||
static struct sh7786_pcie_hwops {
|
||||
int (*core_init)(void);
|
||||
async_func_t port_init_hw;
|
||||
} *sh7786_pcie_hwops;
|
||||
|
||||
static struct resource sh7786_pci0_resources[] = {
|
||||
{
|
||||
.name = "PCIe0 IO",
|
||||
.start = 0xfd000000,
|
||||
.end = 0xfd000000 + SZ_8M - 1,
|
||||
.flags = IORESOURCE_IO,
|
||||
}, {
|
||||
.name = "PCIe0 MEM 0",
|
||||
.start = 0xc0000000,
|
||||
.end = 0xc0000000 + SZ_512M - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
}, {
|
||||
.name = "PCIe0 MEM 1",
|
||||
.start = 0x10000000,
|
||||
.end = 0x10000000 + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.name = "PCIe0 MEM 2",
|
||||
.start = 0xfe100000,
|
||||
.end = 0xfe100000 + SZ_1M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource sh7786_pci1_resources[] = {
|
||||
{
|
||||
.name = "PCIe1 IO",
|
||||
.start = 0xfd800000,
|
||||
.end = 0xfd800000 + SZ_8M - 1,
|
||||
.flags = IORESOURCE_IO,
|
||||
}, {
|
||||
.name = "PCIe1 MEM 0",
|
||||
.start = 0xa0000000,
|
||||
.end = 0xa0000000 + SZ_512M - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
}, {
|
||||
.name = "PCIe1 MEM 1",
|
||||
.start = 0x30000000,
|
||||
.end = 0x30000000 + SZ_256M - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
}, {
|
||||
.name = "PCIe1 MEM 2",
|
||||
.start = 0xfe300000,
|
||||
.end = 0xfe300000 + SZ_1M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource sh7786_pci2_resources[] = {
|
||||
{
|
||||
.name = "PCIe2 IO",
|
||||
.start = 0xfc800000,
|
||||
.end = 0xfc800000 + SZ_4M - 1,
|
||||
.flags = IORESOURCE_IO,
|
||||
}, {
|
||||
.name = "PCIe2 MEM 0",
|
||||
.start = 0x80000000,
|
||||
.end = 0x80000000 + SZ_512M - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
}, {
|
||||
.name = "PCIe2 MEM 1",
|
||||
.start = 0x20000000,
|
||||
.end = 0x20000000 + SZ_256M - 1,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
|
||||
}, {
|
||||
.name = "PCIe2 MEM 2",
|
||||
.start = 0xfcd00000,
|
||||
.end = 0xfcd00000 + SZ_1M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
extern struct pci_ops sh7786_pci_ops;
|
||||
|
||||
#define DEFINE_CONTROLLER(start, idx) \
|
||||
{ \
|
||||
.pci_ops = &sh7786_pci_ops, \
|
||||
.resources = sh7786_pci##idx##_resources, \
|
||||
.nr_resources = ARRAY_SIZE(sh7786_pci##idx##_resources), \
|
||||
.reg_base = start, \
|
||||
.mem_offset = 0, \
|
||||
.io_offset = 0, \
|
||||
}
|
||||
|
||||
static struct pci_channel sh7786_pci_channels[] = {
|
||||
DEFINE_CONTROLLER(0xfe000000, 0),
|
||||
DEFINE_CONTROLLER(0xfe200000, 1),
|
||||
DEFINE_CONTROLLER(0xfcc00000, 2),
|
||||
};
|
||||
|
||||
static struct clk fixed_pciexclkp = {
|
||||
.rate = 100000000, /* 100 MHz reference clock */
|
||||
};
|
||||
|
||||
static void sh7786_pci_fixup(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* Prevent enumeration of root complex resources.
|
||||
*/
|
||||
if (pci_is_root_bus(dev->bus) && dev->devfn == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||
dev->resource[i].start = 0;
|
||||
dev->resource[i].end = 0;
|
||||
dev->resource[i].flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786,
|
||||
sh7786_pci_fixup);
|
||||
|
||||
static int __init phy_wait_for_ack(struct pci_channel *chan)
|
||||
{
|
||||
unsigned int timeout = 100;
|
||||
|
||||
while (timeout--) {
|
||||
if (pci_read_reg(chan, SH4A_PCIEPHYADRR) & (1 << BITS_ACK))
|
||||
return 0;
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int __init pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
|
||||
{
|
||||
unsigned int timeout = 100;
|
||||
|
||||
while (timeout--) {
|
||||
if ((pci_read_reg(chan, SH4A_PCIEINTR) & mask) == mask)
|
||||
return 0;
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void __init phy_write_reg(struct pci_channel *chan, unsigned int addr,
|
||||
unsigned int lane, unsigned int data)
|
||||
{
|
||||
unsigned long phyaddr;
|
||||
|
||||
phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) +
|
||||
((addr & 0xff) << BITS_ADR);
|
||||
|
||||
/* Set write data */
|
||||
pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR);
|
||||
pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR);
|
||||
|
||||
phy_wait_for_ack(chan);
|
||||
|
||||
/* Clear command */
|
||||
pci_write_reg(chan, 0, SH4A_PCIEPHYDOUTR);
|
||||
pci_write_reg(chan, 0, SH4A_PCIEPHYADRR);
|
||||
|
||||
phy_wait_for_ack(chan);
|
||||
}
|
||||
|
||||
static int __init pcie_clk_init(struct sh7786_pcie_port *port)
|
||||
{
|
||||
struct pci_channel *chan = port->hose;
|
||||
struct clk *clk;
|
||||
char fclk_name[16];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* First register the fixed clock
|
||||
*/
|
||||
ret = clk_register(&fixed_pciexclkp);
|
||||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Grab the port's function clock, which the PHY clock depends
|
||||
* on. clock lookups don't help us much at this point, since no
|
||||
* dev_id is available this early. Lame.
|
||||
*/
|
||||
snprintf(fclk_name, sizeof(fclk_name), "pcie%d_fck", port->index);
|
||||
|
||||
port->fclk = clk_get(NULL, fclk_name);
|
||||
if (IS_ERR(port->fclk)) {
|
||||
ret = PTR_ERR(port->fclk);
|
||||
goto err_fclk;
|
||||
}
|
||||
|
||||
clk_enable(port->fclk);
|
||||
|
||||
/*
|
||||
* And now, set up the PHY clock
|
||||
*/
|
||||
clk = &port->phy_clk;
|
||||
|
||||
memset(clk, 0, sizeof(struct clk));
|
||||
|
||||
clk->parent = &fixed_pciexclkp;
|
||||
clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR);
|
||||
clk->enable_bit = BITS_CKE;
|
||||
|
||||
ret = sh_clk_mstp_register(clk, 1);
|
||||
if (unlikely(ret < 0))
|
||||
goto err_phy;
|
||||
|
||||
return 0;
|
||||
|
||||
err_phy:
|
||||
clk_disable(port->fclk);
|
||||
clk_put(port->fclk);
|
||||
err_fclk:
|
||||
clk_unregister(&fixed_pciexclkp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init phy_init(struct sh7786_pcie_port *port)
|
||||
{
|
||||
struct pci_channel *chan = port->hose;
|
||||
unsigned int timeout = 100;
|
||||
|
||||
clk_enable(&port->phy_clk);
|
||||
|
||||
/* Initialize the phy */
|
||||
phy_write_reg(chan, 0x60, 0xf, 0x004b008b);
|
||||
phy_write_reg(chan, 0x61, 0xf, 0x00007b41);
|
||||
phy_write_reg(chan, 0x64, 0xf, 0x00ff4f00);
|
||||
phy_write_reg(chan, 0x65, 0xf, 0x09070907);
|
||||
phy_write_reg(chan, 0x66, 0xf, 0x00000010);
|
||||
phy_write_reg(chan, 0x74, 0xf, 0x0007001c);
|
||||
phy_write_reg(chan, 0x79, 0xf, 0x01fc000d);
|
||||
phy_write_reg(chan, 0xb0, 0xf, 0x00000610);
|
||||
|
||||
/* Deassert Standby */
|
||||
phy_write_reg(chan, 0x67, 0x1, 0x00000400);
|
||||
|
||||
/* Disable clock */
|
||||
clk_disable(&port->phy_clk);
|
||||
|
||||
while (timeout--) {
|
||||
if (pci_read_reg(chan, SH4A_PCIEPHYSR))
|
||||
return 0;
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void __init pcie_reset(struct sh7786_pcie_port *port)
|
||||
{
|
||||
struct pci_channel *chan = port->hose;
|
||||
|
||||
pci_write_reg(chan, 1, SH4A_PCIESRSTR);
|
||||
pci_write_reg(chan, 0, SH4A_PCIETCTLR);
|
||||
pci_write_reg(chan, 0, SH4A_PCIESRSTR);
|
||||
pci_write_reg(chan, 0, SH4A_PCIETXVC0SR);
|
||||
}
|
||||
|
||||
static int __init pcie_init(struct sh7786_pcie_port *port)
|
||||
{
|
||||
struct pci_channel *chan = port->hose;
|
||||
unsigned int data;
|
||||
phys_addr_t memphys;
|
||||
size_t memsize;
|
||||
int ret, i, win;
|
||||
|
||||
/* Begin initialization */
|
||||
pcie_reset(port);
|
||||
|
||||
/*
|
||||
* Initial header for port config space is type 1, set the device
|
||||
* class to match. Hardware takes care of propagating the IDSETR
|
||||
* settings, so there is no need to bother with a quirk.
|
||||
*/
|
||||
pci_write_reg(chan, PCI_CLASS_BRIDGE_PCI << 16, SH4A_PCIEIDSETR1);
|
||||
|
||||
/* Initialize default capabilities. */
|
||||
data = pci_read_reg(chan, SH4A_PCIEEXPCAP0);
|
||||
data &= ~(PCI_EXP_FLAGS_TYPE << 16);
|
||||
|
||||
if (port->endpoint)
|
||||
data |= PCI_EXP_TYPE_ENDPOINT << 20;
|
||||
else
|
||||
data |= PCI_EXP_TYPE_ROOT_PORT << 20;
|
||||
|
||||
data |= PCI_CAP_ID_EXP;
|
||||
pci_write_reg(chan, data, SH4A_PCIEEXPCAP0);
|
||||
|
||||
/* Enable data link layer active state reporting */
|
||||
pci_write_reg(chan, PCI_EXP_LNKCAP_DLLLARC, SH4A_PCIEEXPCAP3);
|
||||
|
||||
/* Enable extended sync and ASPM L0s support */
|
||||
data = pci_read_reg(chan, SH4A_PCIEEXPCAP4);
|
||||
data &= ~PCI_EXP_LNKCTL_ASPMC;
|
||||
data |= PCI_EXP_LNKCTL_ES | 1;
|
||||
pci_write_reg(chan, data, SH4A_PCIEEXPCAP4);
|
||||
|
||||
/* Write out the physical slot number */
|
||||
data = pci_read_reg(chan, SH4A_PCIEEXPCAP5);
|
||||
data &= ~PCI_EXP_SLTCAP_PSN;
|
||||
data |= (port->index + 1) << 19;
|
||||
pci_write_reg(chan, data, SH4A_PCIEEXPCAP5);
|
||||
|
||||
/* Set the completion timer timeout to the maximum 32ms. */
|
||||
data = pci_read_reg(chan, SH4A_PCIETLCTLR);
|
||||
data &= ~0x3f00;
|
||||
data |= 0x32 << 8;
|
||||
pci_write_reg(chan, data, SH4A_PCIETLCTLR);
|
||||
|
||||
/*
|
||||
* Set fast training sequences to the maximum 255,
|
||||
* and enable MAC data scrambling.
|
||||
*/
|
||||
data = pci_read_reg(chan, SH4A_PCIEMACCTLR);
|
||||
data &= ~PCIEMACCTLR_SCR_DIS;
|
||||
data |= (0xff << 16);
|
||||
pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
|
||||
|
||||
memphys = __pa(memory_start);
|
||||
memsize = roundup_pow_of_two(memory_end - memory_start);
|
||||
|
||||
/*
|
||||
* If there's more than 512MB of memory, we need to roll over to
|
||||
* LAR1/LAMR1.
|
||||
*/
|
||||
if (memsize > SZ_512M) {
|
||||
pci_write_reg(chan, memphys + SZ_512M, SH4A_PCIELAR1);
|
||||
pci_write_reg(chan, ((memsize - SZ_512M) - SZ_256) | 1,
|
||||
SH4A_PCIELAMR1);
|
||||
memsize = SZ_512M;
|
||||
} else {
|
||||
/*
|
||||
* Otherwise just zero it out and disable it.
|
||||
*/
|
||||
pci_write_reg(chan, 0, SH4A_PCIELAR1);
|
||||
pci_write_reg(chan, 0, SH4A_PCIELAMR1);
|
||||
}
|
||||
|
||||
/*
|
||||
* LAR0/LAMR0 covers up to the first 512MB, which is enough to
|
||||
* cover all of lowmem on most platforms.
|
||||
*/
|
||||
pci_write_reg(chan, memphys, SH4A_PCIELAR0);
|
||||
pci_write_reg(chan, (memsize - SZ_256) | 1, SH4A_PCIELAMR0);
|
||||
|
||||
/* Finish initialization */
|
||||
data = pci_read_reg(chan, SH4A_PCIETCTLR);
|
||||
data |= 0x1;
|
||||
pci_write_reg(chan, data, SH4A_PCIETCTLR);
|
||||
|
||||
/* Let things settle down a bit.. */
|
||||
mdelay(100);
|
||||
|
||||
/* Enable DL_Active Interrupt generation */
|
||||
data = pci_read_reg(chan, SH4A_PCIEDLINTENR);
|
||||
data |= PCIEDLINTENR_DLL_ACT_ENABLE;
|
||||
pci_write_reg(chan, data, SH4A_PCIEDLINTENR);
|
||||
|
||||
/* Disable MAC data scrambling. */
|
||||
data = pci_read_reg(chan, SH4A_PCIEMACCTLR);
|
||||
data |= PCIEMACCTLR_SCR_DIS | (0xff << 16);
|
||||
pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
|
||||
|
||||
/*
|
||||
* This will timeout if we don't have a link, but we permit the
|
||||
* port to register anyways in order to support hotplug on future
|
||||
* hardware.
|
||||
*/
|
||||
ret = pci_wait_for_irq(chan, MASK_INT_TX_CTRL);
|
||||
|
||||
data = pci_read_reg(chan, SH4A_PCIEPCICONF1);
|
||||
data &= ~(PCI_STATUS_DEVSEL_MASK << 16);
|
||||
data |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
|
||||
(PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST) << 16;
|
||||
pci_write_reg(chan, data, SH4A_PCIEPCICONF1);
|
||||
|
||||
pci_write_reg(chan, 0x80888000, SH4A_PCIETXVC0DCTLR);
|
||||
pci_write_reg(chan, 0x00222000, SH4A_PCIERXVC0DCTLR);
|
||||
|
||||
wmb();
|
||||
|
||||
if (ret == 0) {
|
||||
data = pci_read_reg(chan, SH4A_PCIEMACSR);
|
||||
printk(KERN_NOTICE "PCI: PCIe#%d x%d link detected\n",
|
||||
port->index, (data >> 20) & 0x3f);
|
||||
} else
|
||||
printk(KERN_NOTICE "PCI: PCIe#%d link down\n",
|
||||
port->index);
|
||||
|
||||
for (i = win = 0; i < chan->nr_resources; i++) {
|
||||
struct resource *res = chan->resources + i;
|
||||
resource_size_t size;
|
||||
u32 mask;
|
||||
|
||||
/*
|
||||
* We can't use the 32-bit mode windows in legacy 29-bit
|
||||
* mode, so just skip them entirely.
|
||||
*/
|
||||
if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode())
|
||||
continue;
|
||||
|
||||
pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(win));
|
||||
|
||||
/*
|
||||
* The PAMR mask is calculated in units of 256kB, which
|
||||
* keeps things pretty simple.
|
||||
*/
|
||||
size = resource_size(res);
|
||||
mask = (roundup_pow_of_two(size) / SZ_256K) - 1;
|
||||
pci_write_reg(chan, mask << 18, SH4A_PCIEPAMR(win));
|
||||
|
||||
pci_write_reg(chan, upper_32_bits(res->start),
|
||||
SH4A_PCIEPARH(win));
|
||||
pci_write_reg(chan, lower_32_bits(res->start),
|
||||
SH4A_PCIEPARL(win));
|
||||
|
||||
mask = MASK_PARE;
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
mask |= MASK_SPC;
|
||||
|
||||
pci_write_reg(chan, mask, SH4A_PCIEPTCTLR(win));
|
||||
|
||||
win++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
|
||||
{
|
||||
return evt2irq(0xae0);
|
||||
}
|
||||
|
||||
static int __init sh7786_pcie_core_init(void)
|
||||
{
|
||||
/* Return the number of ports */
|
||||
return test_mode_pin(MODE_PIN12) ? 3 : 2;
|
||||
}
|
||||
|
||||
static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie)
|
||||
{
|
||||
struct sh7786_pcie_port *port = data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Check if we are configured in endpoint or root complex mode,
|
||||
* this is a fixed pin setting that applies to all PCIe ports.
|
||||
*/
|
||||
port->endpoint = test_mode_pin(MODE_PIN11);
|
||||
|
||||
/*
|
||||
* Setup clocks, needed both for PHY and PCIe registers.
|
||||
*/
|
||||
ret = pcie_clk_init(port);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_err("clock initialization failed for port#%d\n",
|
||||
port->index);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = phy_init(port);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_err("phy initialization failed for port#%d\n",
|
||||
port->index);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = pcie_init(port);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_err("core initialization failed for port#%d\n",
|
||||
port->index);
|
||||
return;
|
||||
}
|
||||
|
||||
/* In the interest of preserving device ordering, synchronize */
|
||||
async_synchronize_cookie(cookie);
|
||||
|
||||
register_pci_controller(port->hose);
|
||||
}
|
||||
|
||||
static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
|
||||
.core_init = sh7786_pcie_core_init,
|
||||
.port_init_hw = sh7786_pcie_init_hw,
|
||||
};
|
||||
|
||||
static int __init sh7786_pcie_init(void)
|
||||
{
|
||||
struct clk *platclk;
|
||||
int i;
|
||||
|
||||
printk(KERN_NOTICE "PCI: Starting initialization.\n");
|
||||
|
||||
sh7786_pcie_hwops = &sh7786_65nm_pcie_hwops;
|
||||
|
||||
nr_ports = sh7786_pcie_hwops->core_init();
|
||||
BUG_ON(nr_ports > ARRAY_SIZE(sh7786_pci_channels));
|
||||
|
||||
if (unlikely(nr_ports == 0))
|
||||
return -ENODEV;
|
||||
|
||||
sh7786_pcie_ports = kzalloc(nr_ports * sizeof(struct sh7786_pcie_port),
|
||||
GFP_KERNEL);
|
||||
if (unlikely(!sh7786_pcie_ports))
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Fetch any optional platform clock associated with this block.
|
||||
*
|
||||
* This is a rather nasty hack for boards with spec-mocking FPGAs
|
||||
* that have a secondary set of clocks outside of the on-chip
|
||||
* ones that need to be accounted for before there is any chance
|
||||
* of touching the existing MSTP bits or CPG clocks.
|
||||
*/
|
||||
platclk = clk_get(NULL, "pcie_plat_clk");
|
||||
if (IS_ERR(platclk)) {
|
||||
/* Sane hardware should probably get a WARN_ON.. */
|
||||
platclk = NULL;
|
||||
}
|
||||
|
||||
clk_enable(platclk);
|
||||
|
||||
printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports);
|
||||
|
||||
for (i = 0; i < nr_ports; i++) {
|
||||
struct sh7786_pcie_port *port = sh7786_pcie_ports + i;
|
||||
|
||||
port->index = i;
|
||||
port->hose = sh7786_pci_channels + i;
|
||||
port->hose->io_map_base = port->hose->resources[0].start;
|
||||
|
||||
async_schedule(sh7786_pcie_hwops->port_init_hw, port);
|
||||
}
|
||||
|
||||
async_synchronize_full();
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(sh7786_pcie_init);
|
580
arch/sh/drivers/pci/pcie-sh7786.h
Normal file
580
arch/sh/drivers/pci/pcie-sh7786.h
Normal file
|
@ -0,0 +1,580 @@
|
|||
/*
|
||||
* SH7786 PCI-Express controller definitions.
|
||||
*
|
||||
* Copyright (C) 2008, 2009 Renesas Technology Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __PCI_SH7786_H
|
||||
#define __PCI_SH7786_H
|
||||
|
||||
/* PCIe bus-0(x4) on SH7786 */ // Rev1.171
|
||||
#define SH4A_PCIE_SPW_BASE 0xFE000000 /* spw config address for controller 0 */
|
||||
#define SH4A_PCIE_SPW_BASE1 0xFE200000 /* spw config address for controller 1 (Rev1.14)*/
|
||||
#define SH4A_PCIE_SPW_BASE2 0xFCC00000 /* spw config address for controller 2 (Rev1.171)*/
|
||||
#define SH4A_PCIE_SPW_BASE_LEN 0x00080000
|
||||
|
||||
#define SH4A_PCI_CNFG_BASE 0xFE040000 /* pci config address for controller 0 */
|
||||
#define SH4A_PCI_CNFG_BASE1 0xFE240000 /* pci config address for controller 1 (Rev1.14)*/
|
||||
#define SH4A_PCI_CNFG_BASE2 0xFCC40000 /* pci config address for controller 2 (Rev1.171)*/
|
||||
#define SH4A_PCI_CNFG_BASE_LEN 0x00040000
|
||||
|
||||
#define SH4A_PCIPIO_ADDR_OFFSET 0x000001c0 /* offset to pci config_address */
|
||||
#define SH4A_PCIPIO_DATA_OFFSET 0x00000220 /* offset to pci config_data */
|
||||
|
||||
/*
|
||||
* for PEX8111(Max Payload Size=128B,PCIIO_SIZE=64K),
|
||||
* for other(Max Payload Size=4096B,PCIIO_SIZE=8M)
|
||||
*/
|
||||
|
||||
/* PCI0: PCI memory target transfer 32-bit address translation value(Rev1.11T)*/
|
||||
#define SH4A_PCIBMSTR_TRANSLATION 0x20000000
|
||||
|
||||
/* SPVCR0 */
|
||||
#define SH4A_PCIEVCR0 (0x000000) /* R - 0x0000 0000 32 */
|
||||
#define BITS_TOP_MB (24)
|
||||
#define MASK_TOP_MB (0xff<<BITS_TOP_MB)
|
||||
#define BITS_BOT_MB (16)
|
||||
#define MASK_BOT_MB (0xff<<BITS_BOT_MB)
|
||||
#define BITS_VC_ID (0)
|
||||
#define MASK_VC_ID (0xffff<<BITS_VC_ID)
|
||||
|
||||
/* SPVCR1 */
|
||||
#define SH4A_PCIEVCR1 (0x000004) /* R - 0x0000 0000 32*/
|
||||
#define BITS_BADOPC (5) /* 5 BADOPC 0 R/W */
|
||||
#define MASK_BADOPC (1<<BITS_BADOPC)
|
||||
#define BITS_BADDEST (4) /*4 BADDEST 0 R/W */
|
||||
#define MASK_BADDEST (1<<BITS_BADDEST)
|
||||
#define BITS_UNSOLRESP (3) /* 3 UNSOLRESP 0 R/W */
|
||||
#define MASK_UNSOLRESP (1<<BITS_UNSOLRESP)
|
||||
#define BITS_ERRSNT (1) /* 1 ERRSNT 0 */
|
||||
#define MASK_ERRSNT (1<<BITS_ERRSNT)
|
||||
#define BITS_ERRRCV (0) /* 0 ERRRCV 0 */
|
||||
#define MASK_ERRRCV (1<<BITS_ERRRCV)
|
||||
|
||||
/* PCIEENBLR */
|
||||
#define SH4A_PCIEENBLR (0x000008) /* R/W - 0x0000 0001 32 */
|
||||
|
||||
/* PCIEECR */
|
||||
#define SH4A_PCIEECR (0x00000C) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_ENBL (0) /* 0 ENBL 0 R/W */
|
||||
#define MASK_ENBL (1<<BITS_ENBL)
|
||||
|
||||
/* PCIEPAR */
|
||||
#define SH4A_PCIEPAR (0x000010) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_BN (24)
|
||||
#define MASK_BN (0xff<<BITS_BN)
|
||||
#define BITS_DN (19)
|
||||
#define MASK_DN (0x1f<<BITS_DN)
|
||||
#define BITS_FN (16)
|
||||
#define MASK_FN (0x7<<BITS_FN)
|
||||
#define BITS_EREGNO (8)
|
||||
#define MASK_EREGNO (0xff<<BITS_EREGNO)
|
||||
#define BITS_REGNO (2)
|
||||
#define MASK_REGNO (0x3f<<BITS_REGNO)
|
||||
|
||||
/* PCIEPCTLR */
|
||||
#define SH4A_PCIEPCTLR (0x000018) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_CCIE (31) /* 31 CCIE */
|
||||
#define MASK_CCIE (1<<BITS_CCIE)
|
||||
#define BITS_TYPE (8)
|
||||
#define MASK_TYPE (1<<BITS_TYPE)
|
||||
#define BITS_C_VC (0)
|
||||
#define MASK_C_VC (1<<BITS_C_VC)
|
||||
|
||||
/* PCIEPDR */
|
||||
#define SH4A_PCIEPDR (0x000020) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_PDR (0)
|
||||
#define MASK_PDR (0xffffffff<<BITS_PDR)
|
||||
|
||||
/* PCIEMSGALR */
|
||||
#define SH4A_PCIEMSGALR (0x000030) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_MSGADRL (0)
|
||||
#define MASK_MSGADRL (0xffffffff<<BITS_MSGADRL)
|
||||
|
||||
/* PCIEMSGAHR */
|
||||
#define SH4A_PCIEMSGAHR (0x000034) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_MSGADRH (0)
|
||||
#define MASK_MSGADRH (0xffffffff<<BITS_MSGADRH)
|
||||
|
||||
/* PCIEMSGCTLR */
|
||||
#define SH4A_PCIEMSGCTLR (0x000038) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_MSGIE (31)
|
||||
#define MASK_MSGIE (1<<BITS_MSGIE)
|
||||
#define BITS_MROUTE (16)
|
||||
#define MASK_MROUTE (0x7<<BITS_MROUTE)
|
||||
#define BITS_MCODE (8)
|
||||
#define MASK_MCODE (0xff<<BITS_MCODE)
|
||||
#define BITS_M_VC (0)
|
||||
#define MASK_M_VC (1<<BITS_M_VC)
|
||||
|
||||
/* PCIEMSG */
|
||||
#define SH4A_PCIEMSG (0x000040) /* W - - 32 */
|
||||
#define BITS_MDATA (0)
|
||||
#define MASK_MDATA (0xffffffff<<BITS_MDATA)
|
||||
|
||||
/* PCIEUNLOCKCR */
|
||||
#define SH4A_PCIEUNLOCKCR (0x000048) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEIDR */
|
||||
#define SH4A_PCIEIDR (0x000060) /* R/W - 0x0101 1101 32 */
|
||||
|
||||
/* PCIEDBGCTLR */
|
||||
#define SH4A_PCIEDBGCTLR (0x000100) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEINTXR */
|
||||
#define SH4A_PCIEINTXR (0x004000) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIERMSGR */
|
||||
#define SH4A_PCIERMSGR (0x004010) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIERSTR */
|
||||
#define SH4A_PCIERSTR(x) (0x008000 + ((x) * 0x4)) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIESRSTR */
|
||||
#define SH4A_PCIESRSTR (0x008040) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPHYCTLR */
|
||||
#define SH4A_PCIEPHYCTLR (0x010000) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_CKE (0)
|
||||
#define MASK_CKE (1<<BITS_CKE)
|
||||
|
||||
/* PCIERMSGIER */
|
||||
#define SH4A_PCIERMSGIER (0x004040) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPHYADRR */
|
||||
#define SH4A_PCIEPHYADRR (0x010004) /* R/W - 0x0000 0000 32 */
|
||||
#define BITS_ACK (24) // Rev1.171
|
||||
#define MASK_ACK (1<<BITS_ACK) // Rev1.171
|
||||
#define BITS_CMD (16) // Rev1.171
|
||||
#define MASK_CMD (0x03<<BITS_CMD) // Rev1.171
|
||||
#define BITS_LANE (8)
|
||||
#define MASK_LANE (0x0f<<BITS_LANE)
|
||||
#define BITS_ADR (0)
|
||||
#define MASK_ADR (0xff<<BITS_ADR)
|
||||
|
||||
/* PCIEPHYDINR */ // Rev1.171 start.
|
||||
#define SH4A_PCIEPHYDINR (0x010008) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPHYDOUTR */
|
||||
#define SH4A_PCIEPHYDOUTR (0x01000C) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPHYSR */
|
||||
#define SH4A_PCIEPHYSR (0x010010) /* R/W - 0x0000 0000 32 */ // Rev1.171 end.
|
||||
|
||||
/* PCIEPHYDATAR */
|
||||
#define SH4A_PCIEPHYDATAR (0x00008) /* R/W - 0xxxxx xxxx 32 */
|
||||
#define BITS_DATA (0)
|
||||
#define MASK_DATA (0xffffffff<<BITS_DATA)
|
||||
|
||||
/* PCIETCTLR */
|
||||
#define SH4A_PCIETCTLR (0x020000) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_CFINT (0)
|
||||
#define MASK_CFINT (1<<BITS_CFINT)
|
||||
|
||||
/* PCIETSTR */
|
||||
#define SH4A_PCIETSTR (0x020004) /* R 0x0000 0000 32 */
|
||||
|
||||
/* PCIEINTR */
|
||||
#define SH4A_PCIEINTR (0x020008) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_INT_RX_ERP (31)
|
||||
#define MASK_INT_RX_ERP (1<<BITS_INT_RX_ERP)
|
||||
#define BITS_INT_RX_VCX_Posted (30)
|
||||
#define MASK_INT_RX_VCX_Posted (1<<BITS_INT_RX_VCX_Posted)
|
||||
#define BITS_INT_RX_VCX_NonPosted (29)
|
||||
#define MASK_INT_RX_VCX_NonPosted (1<<BITS_INT_RX_VCX_NonPosted)
|
||||
#define BITS_INT_RX_VCX_CPL (28)
|
||||
#define MASK_INT_RX_VCX_CPL (1<<BITS_INT_RX_VCX_CPL)
|
||||
#define BITS_INT_TX_VCX_Posted (26)
|
||||
#define MASK_INT_TX_VCX_Posted (1<<BITS_INT_TX_VCX_Posted)
|
||||
#define BITS_INT_TX_VCX_NonPosted (25)
|
||||
#define MASK_INT_TX_VCX_NonPosted (1<<BITS_INT_TX_VCX_NonPosted)
|
||||
#define BITS_INT_TX_VCX_CPL (24)
|
||||
#define MASK_INT_TX_VCX_CPL (1<<BITS_INT_TX_VCX_CPL)
|
||||
#define BITS_INT_RX_VC0_Posted (22)
|
||||
#define MASK_INT_RX_VC0_Posted (1<<BITS_INT_RX_VC0_Posted)
|
||||
#define BITS_INT_RX_VC0_NonPosted (21)
|
||||
#define MASK_INT_RX_VC0_NonPosted (1<<BITS_INT_RX_VC0_NonPosted)
|
||||
#define BITS_INT_RX_VC0_CPL (20)
|
||||
#define MASK_INT_RX_VC0_CPL (1<<BITS_INT_RX_VC0_CPL)
|
||||
#define BITS_INT_TX_VC0_Posted (18)
|
||||
#define MASK_INT_TX_VC0_Posted (1<<BITS_INT_TX_VC0_Posted)
|
||||
#define BITS_INT_TX_VC0_NonPosted (17)
|
||||
#define MASK_INT_TX_VC0_NonPosted (1<<BITS_INT_TX_VC0_NonPosted)
|
||||
#define BITS_INT_TX_VC0_CPL (16)
|
||||
#define MASK_INT_TX_VC0_CPL (1<<BITS_INT_TX_VC0_CPL)
|
||||
#define BITS_INT_RX_CTRL (15)
|
||||
#define MASK_INT_RX_CTRL (1<<BITS_INT_RX_CTRL)
|
||||
#define BITS_INT_TX_CTRL (14)
|
||||
#define MASK_INT_TX_CTRL (1<<BITS_INT_TX_CTRL)
|
||||
#define BITS_INTTL (11)
|
||||
#define MASK_INTTL (1<<BITS_INTTL)
|
||||
#define BITS_INTDL (10)
|
||||
#define MASK_INTDL (1<<BITS_INTDL)
|
||||
#define BITS_INTMAC (9)
|
||||
#define MASK_INTMAC (1<<BITS_INTMAC)
|
||||
#define BITS_INTPM (8)
|
||||
#define MASK_INTPM (1<<BITS_INTPM)
|
||||
|
||||
/* PCIEINTER */
|
||||
#define SH4A_PCIEINTER (0x02000C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_INT_RX_ERP (31)
|
||||
#define MASK_INT_RX_ERP (1<<BITS_INT_RX_ERP)
|
||||
#define BITS_INT_RX_VCX_Posted (30)
|
||||
#define MASK_INT_RX_VCX_Posted (1<<BITS_INT_RX_VCX_Posted)
|
||||
#define BITS_INT_RX_VCX_NonPosted (29)
|
||||
#define MASK_INT_RX_VCX_NonPosted (1<<BITS_INT_RX_VCX_NonPosted)
|
||||
#define BITS_INT_RX_VCX_CPL (28)
|
||||
#define MASK_INT_RX_VCX_CPL (1<<BITS_INT_RX_VCX_CPL)
|
||||
#define BITS_INT_TX_VCX_Posted (26)
|
||||
#define MASK_INT_TX_VCX_Posted (1<<BITS_INT_TX_VCX_Posted)
|
||||
#define BITS_INT_TX_VCX_NonPosted (25)
|
||||
#define MASK_INT_TX_VCX_NonPosted (1<<BITS_INT_TX_VCX_NonPosted)
|
||||
#define BITS_INT_TX_VCX_CPL (24)
|
||||
#define MASK_INT_TX_VCX_CPL (1<<BITS_INT_TX_VCX_CPL)
|
||||
#define BITS_INT_RX_VC0_Posted (22)
|
||||
#define MASK_INT_RX_VC0_Posted (1<<BITS_INT_RX_VC0_Posted)
|
||||
#define BITS_INT_RX_VC0_NonPosted (21)
|
||||
#define MASK_INT_RX_VC0_NonPosted (1<<BITS_INT_RX_VC0_NonPosted)
|
||||
#define BITS_INT_RX_VC0_CPL (20)
|
||||
#define MASK_INT_RX_VC0_CPL (1<<BITS_INT_RX_VC0_CPL)
|
||||
#define BITS_INT_TX_VC0_Posted (18)
|
||||
#define MASK_INT_TX_VC0_Posted (1<<BITS_INT_TX_VC0_Posted)
|
||||
#define BITS_INT_TX_VC0_NonPosted (17)
|
||||
#define MASK_INT_TX_VC0_NonPosted (1<<BITS_INT_TX_VC0_NonPosted)
|
||||
#define BITS_INT_TX_VC0_CPL (16)
|
||||
#define MASK_INT_TX_VC0_CPL (1<<BITS_INT_TX_VC0_CPL)
|
||||
#define BITS_INT_RX_CTRL (15)
|
||||
#define MASK_INT_RX_CTRL (1<<BITS_INT_RX_CTRL)
|
||||
#define BITS_INT_TX_CTRL (14)
|
||||
#define MASK_INT_TX_CTRL (1<<BITS_INT_TX_CTRL)
|
||||
#define BITS_INTTL (11)
|
||||
#define MASK_INTTL (1<<BITS_INTTL)
|
||||
#define BITS_INTDL (10)
|
||||
#define MASK_INTDL (1<<BITS_INTDL)
|
||||
#define BITS_INTMAC (9)
|
||||
#define MASK_INTMAC (1<<BITS_INTMAC)
|
||||
#define BITS_INTPM (8)
|
||||
#define MASK_INTPM (1<<BITS_INTPM)
|
||||
|
||||
/* PCIEEH0R */
|
||||
#define SH4A_PCIEEHR(x) (0x020010 + ((x) * 0x4)) /* R - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEAIR */
|
||||
#define SH4A_PCIEAIR (SH4A_PCIE_BASE + 0x020010) /* R/W R/W 0xxxxx xxxx 32 */
|
||||
|
||||
/* PCIECIR */
|
||||
#define SH4A_PCIECIR (SH4A_PCIE_BASE) /* R/W R/W 0xxxxx xxxx 32 */
|
||||
|
||||
/* PCIEERRFR */ // Rev1.18
|
||||
#define SH4A_PCIEERRFR (0x020020) /* R/W R/W 0xxxxx xxxx 32 */ // Rev1.18
|
||||
|
||||
/* PCIEERRFER */
|
||||
#define SH4A_PCIEERRFER (0x020024) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
/* PCIEERRFR2 */
|
||||
#define SH4A_PCIEERRFR2 (0x020028) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
/* PCIEMSIR */
|
||||
#define SH4A_PCIEMSIR (0x020040) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEMSIFR */
|
||||
#define SH4A_PCIEMSIFR (0x020044) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPWRCTLR */
|
||||
#define SH4A_PCIEPWRCTLR (0x020100) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPCCTLR */
|
||||
#define SH4A_PCIEPCCTLR (0x020180) /* R/W - 0x0000 0000 32 */
|
||||
|
||||
// Rev1.18
|
||||
/* PCIELAR0 */
|
||||
#define SH4A_PCIELAR0 (0x020200) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_LARn (20)
|
||||
#define MASK_LARn (0xfff<<BITS_LARn)
|
||||
|
||||
#define SH4A_PCIE_020204 (0x020204) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
/* PCIELAMR0 */
|
||||
#define SH4A_PCIELAMR0 (0x020208) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_LAMRn (20)
|
||||
#define MASK_LAMRn (0x1ff<<BITS_LAMRn)
|
||||
#define BITS_LAREn (0)
|
||||
#define MASK_LAREn (0x1<<BITS_LAREn)
|
||||
|
||||
/* PCIECSCR0 */
|
||||
#define SH4A_PCIECSCR0 (0x020210) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_RANGE (2)
|
||||
#define MASK_RANGE (0x7<<BITS_RANGE)
|
||||
#define BITS_SNPMD (0)
|
||||
#define MASK_SNPMD (0x3<<BITS_SNPMD)
|
||||
|
||||
/* PCIECSAR0 */
|
||||
#define SH4A_PCIECSAR0 (0x020214) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_CSADR (0)
|
||||
#define MASK_CSADR (0xffffffff<<BITS_CSADR)
|
||||
|
||||
/* PCIESTCTLR0 */
|
||||
#define SH4A_PCIESTCTLR0 (0x020218) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_SHPRI (8)
|
||||
#define MASK_SHPRI (0x0f<<BITS_SHPRI)
|
||||
|
||||
#define SH4A_PCIE_020224 (0x020224) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
#define SH4A_PCIELAR1 (0x020220) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIELAMR1 (0x020228) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSCR1 (0x020230) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSAR1 (0x020234) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIESTCTLR1 (0x020238) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
#define SH4A_PCIELAR2 (0x020240) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIE_020244 (0x020244) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIELAMR2 (0x020248) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSCR2 (0x020250) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSAR2 (0x020254) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIESTCTLR2 (0x020258) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
#define SH4A_PCIELAR3 (0x020260) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIE_020264 (0x020264) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIELAMR3 (0x020268) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSCR3 (0x020270) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSAR3 (0x020274) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIESTCTLR3 (0x020278) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
#define SH4A_PCIELAR4 (0x020280) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIE_020284 (0x020284) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIELAMR4 (0x020288) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSCR4 (0x020290) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSAR4 (0x020294) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIESTCTLR4 (0x020298) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
#define SH4A_PCIELAR5 (0x0202A0) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIE_0202A4 (0x0202A4) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIELAMR5 (0x0202A8) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSCR5 (0x0202B0) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIECSAR5 (0x0202B4) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIESTCTLR5 (0x0202B8) /* R/W R/W 0x0000 0000 32 */
|
||||
|
||||
/* PCIEPARL */
|
||||
#define SH4A_PCIEPARL(x) (0x020400 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_PAL (18)
|
||||
#define MASK_PAL (0x3fff<<BITS_PAL)
|
||||
|
||||
/* PCIEPARH */
|
||||
#define SH4A_PCIEPARH(x) (0x020404 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_PAH (0)
|
||||
#define MASK_PAH (0xffffffff<<BITS_PAH)
|
||||
|
||||
/* PCIEPAMR */
|
||||
#define SH4A_PCIEPAMR(x) (0x020408 + ((x) * 0x20)) /* R/W R/W 0x0000 0000 32 */
|
||||
#define BITS_PAM (18)
|
||||
#define MASK_PAM (0x3fff<<BITS_PAM)
|
||||
|
||||
/* PCIEPTCTLR */
|
||||
#define SH4A_PCIEPTCTLR(x) (0x02040C + ((x) * 0x20))
|
||||
#define BITS_PARE (31)
|
||||
#define MASK_PARE (0x1<<BITS_PARE)
|
||||
#define BITS_TC (20)
|
||||
#define MASK_TC (0x7<<BITS_TC)
|
||||
#define BITS_T_VC (16)
|
||||
#define MASK_T_VC (0x1<<BITS_T_VC)
|
||||
#define BITS_LOCK (12)
|
||||
#define MASK_LOCK (0x1<<BITS_LOCK)
|
||||
#define BITS_SPC (8)
|
||||
#define MASK_SPC (0x1<<BITS_SPC)
|
||||
|
||||
#define SH4A_PCIEDMAOR (0x021000) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAR0 (0x021100) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAHR0 (0x021104) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAR0 (0x021108) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAHR0 (0x02110C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMBCNTR0 (0x021110) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSBCNTR0 (0x021114) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSTRR0 (0x021118) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCAR0 (0x02111C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCR0 (0x021120) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCC2R0 (0x021124) /* R/W R/W 0x0000 0000 - */
|
||||
#define SH4A_PCIEDMCCCR0 (0x021128) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCHSR0 (0x02112C) /* R/W - 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAR1 (0x021140) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAHR1 (0x021144) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAR1 (0x021148) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAHR1 (0x02114C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMBCNTR1 (0x021150) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSBCNTR1 (0x021154) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSTRR1 (0x021158) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCAR1 (0x02115C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCR1 (0x021160) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCC2R1 (0x021164) /* R/W R/W 0x0000 0000 - */
|
||||
#define SH4A_PCIEDMCCCR1 (0x021168) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCHSR1 (0x02116C) /* R/W - 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAR2 (0x021180) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAHR2 (0x021184) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAR2 (0x021188) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAHR2 (0x02118C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMBCNTR2 (0x021190) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSBCNTR2 (0x021194) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSTRR2 (0x021198) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCAR2 (0x02119C) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCR2 (0x0211A0) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCC2R2 (0x0211A4) /* R/W R/W 0x0000 0000 - */
|
||||
#define SH4A_PCIEDMCCCR2 (0x0211A8) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAR3 (0x0211C0) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSAHR3 (0x0211C4) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAR3 (0x0211C8) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMDAHR3 (0x0211CC) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMBCNTR3 (0x0211D0) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSBCNTR3 (0x0211D4) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMSTRR3 (0x0211D8) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCAR3 (0x0211DC) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCCR3 (0x0211E0) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCC2R3 (0x0211E4) /* R/W R/W 0x0000 0000 - */
|
||||
#define SH4A_PCIEDMCCCR3 (0x0211E8) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEDMCHSR3 (0x0211EC) /* R/W R/W 0x0000 0000 32 */
|
||||
#define SH4A_PCIEPCICONF0 (0x040000) /* R R - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF1 (0x040004) /* R/W R/W 0x0008 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF2 (0x040008) /* R/W R/W 0xFF00 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF3 (0x04000C) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF4 (0x040010) /* - R/W - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF5 (0x040014) /* - R/W - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF6 (0x040018) /* - R/W - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF7 (0x04001C) /* - R/W - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF8 (0x040020) /* - R/W - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF9 (0x040024) /* - R/W - 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF10 (0x040028) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF11 (0x04002C) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF12 (0x040030) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF13 (0x040034) /* R/W R/W 0x0000 0040 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF14 (0x040038) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEPCICONF15 (0x04003C) /* R/W R/W 0x0000 00FF 8/16/32 */
|
||||
#define SH4A_PCIEPMCAP0 (0x040040) /* R/W R 0x0003 5001 8/16/32 */
|
||||
#define SH4A_PCIEPMCAP1 (0x040044) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEMSICAP0 (0x040050) /* R/W R/W 0x0180 7005 8/16/32 */
|
||||
#define SH4A_PCIEMSICAP1 (0x040054) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEMSICAP2 (0x040058) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEMSICAP3 (0x04005C) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEMSICAP4 (0x040060) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEMSICAP5 (0x040064) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP0 (0x040070) /* R/W R/W 0x0001 0010 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP1 (0x040074) /* R/W R 0x0000 0005 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP2 (0x040078) /* R/W R/W 0x0000 0801 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP3 (0x04007C) /* R/W R 0x0003 F421 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP4 (0x040080) /* R/W R/W 0x0041 0000 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP5 (0x040084) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP6 (0x040088) /* R/W R/W 0x0000 03C0 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP7 (0x04008C) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEEXPCAP8 (0x040090) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP0 (0x040100) /* R/W R 0x1B01 0002 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP1 (0x040104) /* R R 0x0000 0001 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP2 (0x040108) /* R R 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP3 (0x04010C) /* R R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP4 (0x040110) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP5 (0x040114) /* R/W R/W 0x8000 00FF 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP6 (0x040118) /* R/W R 0x0002 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP7 (0x04011C) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP8 (0x040120) /* R/W R/W 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEVCCAP9 (0x040124) /* R/W R 0x0002 0000 8/16/32 */
|
||||
#define SH4A_PCIENUMCAP0 (0x0001B0) /* RW R 0x0001 0003 8/16/32 */
|
||||
#define SH4A_PCIENUMCAP1 (0x0001B4) /* R R 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIENUMCAP2 (0x0001B8) /* R R 0x0000 0000 8/16/32 */
|
||||
#define SH4A_PCIEIDSETR0 (0x041000) /* R/W R 0x0000 FFFF 16/32 */
|
||||
#define SH4A_PCIEIDSETR1 (0x041004) /* R/W R 0xFF00 0000 16/32 */
|
||||
#define SH4A_PCIEBAR0SETR (0x041008) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEBAR1SETR (0x04100C) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEBAR2SETR (0x041010) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEBAR3SETR (0x041014) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEBAR4SETR (0x041018) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEBAR5SETR (0x04101C) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIECISSETR (0x041020) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEIDSETR2 (0x041024) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEEROMSETR (0x041028) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEDSERSETR0 (0x04102C) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEDSERSETR1 (0x041030) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIECTLR (0x041040) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIETLSR (0x041044) /* R/W1C R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIETLCTLR (0x041048) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEDLSR (0x04104C) /* R/W1C R 0x4003 0000 16/32 */
|
||||
#define SH4A_PCIEDLCTLR (0x041050) /* R R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEMACSR (0x041054) /* R/W1C R 0x0041 0000 16/32 */
|
||||
#define SH4A_PCIEMACCTLR (0x041058) /* R/W R 0x0000 0000 16/32 */
|
||||
#define PCIEMACCTLR_SCR_DIS (1 << 27) /* scramble disable */
|
||||
#define SH4A_PCIEPMSTR (0x04105C) /* R/W1C R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEPMCTLR (0x041060) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIETLINTENR (0x041064) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEDLINTENR (0x041068) /* R/W R 0x0000 0000 16/32 */
|
||||
#define PCIEDLINTENR_DLL_ACT_ENABLE (1 << 31) /* DL active irq */
|
||||
#define SH4A_PCIEMACINTENR (0x04106C) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIEPMINTENR (0x041070) /* R/W R 0x0000 0000 16/32 */
|
||||
#define SH4A_PCIETXDCTLR (0x044000) /* R/W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIETXCTLR (0x044020) /* R/W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIETXSR (0x044028) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIETXVC0DCTLR (0x044100) /* R/W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIETXVC0SR (0x044108) /* R/W - H'00888000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0PDTXR (0x044110) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0PHTXR (0x044118) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0NPDTXR (0x044120) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0NPHTXR (0x044128) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0CDTXR (0x044130) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0CHTXR (0x044138) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIETXVCXDCTLR (0x044200) /* R/W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIETXVCXSR (0x044208) /* R/W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXPDTXR (0x044210) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXPHTXR (0x044218) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXNPDTXR (0x044220) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXNPHTXR (0x044228) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXCDTXR (0x044230) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXCHTXR (0x044238) /* W - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIERDCTLR (0x046000) /* RW - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEERPCTLR (0x046008) /* RW - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEERPHR (0x046010) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEERPERR (0x046018) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIERXVC0DCTLR (0x046100) /* RW - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIERXVC0SR (0x046108) /* RW - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0PDRXR (0x046140) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0PHRXR (0x046148) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0PERR (0x046150) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0NPDRXR (0x046158) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0NPHRXR (0x046160) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0NPERR (0x046168) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0CDRXR (0x046170) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0CHRXR (0x046178) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVC0CERR (0x046180) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIERXVCXDCTLR (0x046200) /* RW - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIERXVCXSR (0x046208) /* RW - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXPDRXR (0x046240) /* R - H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXPHRXR (0x046248) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXPERR (0x046250) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXNPDRXR (0x046258) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXNPHRXR (0x046260) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXNPERR (0x046268) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXCDRXR (0x046270) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXCHRXR (0x046278) /* R H'00000000_00000000 32/64 */
|
||||
#define SH4A_PCIEVCXCERR (0x046280) /* R H'00000000_00000000 32/64 */
|
||||
|
||||
/* SSI Register Definition for MSI WORK AROUND --hamada */
|
||||
#define SH4A_PCI_SSI_BASE 0xFFE00000 /* spw config address */
|
||||
#define SH4A_PCI_SSI_BASE_LEN 0x00100000 /* 1MB */
|
||||
|
||||
#define SH4A_SSICR0 (0x000000)
|
||||
#define SH4A_SSICR1 (0x010000)
|
||||
#define SH4A_SSICR2 (0x020000)
|
||||
#define SH4A_SSICR3 (0x030000)
|
||||
|
||||
#define PCI_REG(x) ((x) + 0x40000)
|
||||
|
||||
static inline void
|
||||
pci_write_reg(struct pci_channel *chan, unsigned long val, unsigned long reg)
|
||||
{
|
||||
__raw_writel(val, chan->reg_base + reg);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
pci_read_reg(struct pci_channel *chan, unsigned long reg)
|
||||
{
|
||||
return __raw_readl(chan->reg_base + reg);
|
||||
}
|
||||
|
||||
#endif /* __PCI_SH7786_H */
|
Loading…
Add table
Add a link
Reference in a new issue