None of the boards we support are using it nor have it wired out of the SoC, just remove it. Signed-off-by: Florian Fainelli <florian@openwrt.org> SVN-Revision: 36061master
parent
a9ef927cce
commit
8bc84bac31
@ -1,453 +0,0 @@ |
||||
/*
|
||||
* Moschip MCS8140 PCI support |
||||
* |
||||
* Copyright (C) 2003 Moschip Semiconductors Ltd. |
||||
* Copyright (C) 2003 Artec Design Ltd. |
||||
* Copyright (C) 2012 Florian Fainelli <florian@openwrt.org> |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
*/ |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/init.h> |
||||
#include <linux/pci.h> |
||||
#include <linux/ptrace.h> |
||||
#include <linux/slab.h> |
||||
#include <linux/ioport.h> |
||||
#include <linux/interrupt.h> |
||||
#include <linux/spinlock.h> |
||||
#include <linux/init.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/of.h> |
||||
#include <linux/io.h> |
||||
|
||||
#include <asm/irq.h> |
||||
#include <asm/system.h> |
||||
#include <asm/mach/pci.h> |
||||
#include <asm/mach/map.h> |
||||
#include <mach/mcs814x.h> |
||||
#include <mach/irqs.h> |
||||
|
||||
#define MCS8140_PCI_CONFIG_SIZE SZ_64M |
||||
#define MCS8140_PCI_IOMISC_SIZE SZ_64M |
||||
|
||||
#define MCS8140_PCI_HOST_BASE 0x80000000 |
||||
#define MCS8140_PCI_IOMISC_BASE 0x00000000 |
||||
#define MCS8140_PCI_PRE_BASE 0x10000000 |
||||
#define MCS8140_PCI_NONPRE_BASE 0x30000000 |
||||
|
||||
#define MCS8140_PCI_CFG_BASE (MCS8140_PCI_HOST_BASE + 0x04000000) |
||||
#define MCS8140_PCI_IO_BASE (MCS8140_PCI_HOST_BASE) |
||||
|
||||
#define MCS8140_PCI_IO_VIRT_BASE (MCS814X_IO_BASE - MCS8140_PCI_CONFIG_SIZE - \ |
||||
MCS8140_PCI_IOMISC_SIZE) |
||||
#define MCS8140_PCI_CFG_VIRT_BASE (MCS814X_IO_BASE - MCS8140_PCI_CONFIG_SIZE) |
||||
|
||||
#define PCI_FATAL_ERROR 1 |
||||
#define EXTERNAL_ABORT_NON_LINE_FETCH 8 |
||||
#define EPRM_DONE 0x80 |
||||
#define EPRM_SDRAM_FUNC0 0xAC |
||||
#define PCI_INTD 4 |
||||
#define MCS8140_PCI_DEVICE_ID 0xA0009710 |
||||
#define MCS8140_PCI_CLASS_ID 0x02000011 /* Host-Class id :0x0600 */ |
||||
#define PCI_IF_CONFIG 0x200 |
||||
|
||||
static void __iomem *mcs8140_pci_master_base; |
||||
static void __iomem *mcs8140_eeprom_emu_base; |
||||
|
||||
static unsigned long __pci_addr(struct pci_bus *bus, |
||||
unsigned int devfn, int offset) |
||||
{ |
||||
unsigned int busnr = bus->number; |
||||
unsigned int slot; |
||||
|
||||
/* we only support bus 0 */ |
||||
if (busnr != 0) |
||||
return 0; |
||||
|
||||
/*
|
||||
* Trap out illegal values |
||||
*/ |
||||
BUG_ON(devfn > 255 || busnr > 255 || devfn > 255); |
||||
|
||||
/* Scan 3 slots */ |
||||
slot = PCI_SLOT(devfn); |
||||
switch (slot) { |
||||
case 1: |
||||
case 2: |
||||
case 3: |
||||
if (PCI_FUNC(devfn) >= 4) |
||||
return 0; |
||||
|
||||
return MCS8140_PCI_CFG_VIRT_BASE | (PCI_SLOT(devfn) << 11) | |
||||
(PCI_FUNC(devfn) << 8) | offset; |
||||
default: |
||||
pr_warn("Ignoring: PCI Slot is %x\n", PCI_SLOT(devfn)); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
static int mcs8140_pci_host_status(void) |
||||
{ |
||||
u32 host_status; |
||||
|
||||
host_status = readl_relaxed(mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
if (host_status & PCI_FATAL_ERROR) { |
||||
writel_relaxed(host_status & 0xfffffff0, |
||||
mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
/* flush write */ |
||||
host_status = |
||||
readl_relaxed(mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
return 1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int mcs8140_pci_read_config(struct pci_bus *bus, |
||||
unsigned int devfn, int where, |
||||
int size, u32 *val) |
||||
{ |
||||
unsigned long v = 0xFFFFFFFF; |
||||
unsigned long addr = __pci_addr(bus, devfn, where); |
||||
|
||||
if (addr != 0) { |
||||
switch (size) { |
||||
case 1: |
||||
v = readb_relaxed(addr); |
||||
break; |
||||
case 2: |
||||
addr &= ~1; |
||||
v = readw_relaxed(addr); |
||||
break; |
||||
default: |
||||
addr &= ~3; |
||||
v = readl_relaxed(addr); |
||||
break; |
||||
} |
||||
} else |
||||
v = 0xffffffff; |
||||
|
||||
if (mcs8140_pci_host_status()) |
||||
v = 0xffffffff; |
||||
|
||||
*val = v; |
||||
|
||||
return PCIBIOS_SUCCESSFUL; |
||||
} |
||||
|
||||
static void mcs8140_eeprom_emu_init(void) |
||||
{ |
||||
writel_relaxed(0x0000000F, mcs8140_eeprom_emu_base + EPRM_SDRAM_FUNC0); |
||||
writel_relaxed(0x08000000, MCS8140_PCI_CFG_VIRT_BASE + 0x10); |
||||
/* Set the DONE bit of the EEPROM emulator */ |
||||
writel_relaxed(0x01, mcs8140_eeprom_emu_base + EPRM_DONE); |
||||
} |
||||
|
||||
static int mcs8140_pci_write_config(struct pci_bus *bus, |
||||
unsigned int devfn, int where, |
||||
int size, u32 val) |
||||
{ |
||||
unsigned long addr = __pci_addr(bus, devfn, where); |
||||
|
||||
if (addr != 0) { |
||||
switch (size) { |
||||
case 1: |
||||
writeb_relaxed((u8)val, addr); |
||||
break; |
||||
case 2: |
||||
writew_relaxed((u16)val, addr); |
||||
break; |
||||
case 4: |
||||
writel_relaxed(val, addr); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return PCIBIOS_SUCCESSFUL; |
||||
} |
||||
|
||||
static struct pci_ops pci_mcs8140_ops = { |
||||
.read = mcs8140_pci_read_config, |
||||
.write = mcs8140_pci_write_config, |
||||
}; |
||||
|
||||
|
||||
static struct resource io_mem = { |
||||
.name = "PCI I/O space", |
||||
.start = MCS8140_PCI_HOST_BASE + MCS8140_PCI_IOMISC_BASE, |
||||
.end = MCS8140_PCI_HOST_BASE + MCS8140_PCI_IOMISC_BASE + SZ_64M, |
||||
.flags = IORESOURCE_IO, |
||||
}; |
||||
|
||||
static struct resource pre_mem = { |
||||
.name = "PCI prefetchable", |
||||
.start = MCS8140_PCI_HOST_BASE + MCS8140_PCI_PRE_BASE, |
||||
.end = MCS8140_PCI_HOST_BASE + MCS8140_PCI_PRE_BASE + SZ_512M, |
||||
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, |
||||
}; |
||||
|
||||
static struct resource non_mem = { |
||||
.name = "PCI non-prefetchable", |
||||
.start = MCS8140_PCI_HOST_BASE + MCS8140_PCI_NONPRE_BASE, |
||||
.end = MCS8140_PCI_HOST_BASE + MCS8140_PCI_NONPRE_BASE + SZ_256M, |
||||
.flags = IORESOURCE_MEM, |
||||
}; |
||||
|
||||
int __init pci_mcs8140_setup_resources(struct pci_sys_data *sys) |
||||
{ |
||||
int ret = 0; |
||||
|
||||
ret = request_resource(&iomem_resource, &io_mem); |
||||
if (ret) { |
||||
pr_err("PCI: unable to allocate I/O " |
||||
"memory region (%d)\n", ret); |
||||
goto out; |
||||
} |
||||
|
||||
ret = request_resource(&iomem_resource, &non_mem); |
||||
if (ret) { |
||||
pr_err("PCI: unable to allocate non-prefetchable " |
||||
"memory region (%d)\n", ret); |
||||
goto release_io_mem; |
||||
} |
||||
|
||||
ret = request_resource(&iomem_resource, &pre_mem); |
||||
if (ret) { |
||||
pr_err("PCI: unable to allocate prefetchable " |
||||
"memory region (%d)\n", ret); |
||||
goto release_non_mem; |
||||
} |
||||
|
||||
mcs8140_eeprom_emu_init(); |
||||
|
||||
pci_add_resource(&sys->resources, &io_mem); |
||||
pci_add_resource(&sys->resources, &non_mem); |
||||
pci_add_resource(&sys->resources, &pre_mem); |
||||
|
||||
return ret; |
||||
|
||||
release_non_mem: |
||||
release_resource(&non_mem); |
||||
release_io_mem: |
||||
release_resource(&io_mem); |
||||
out: |
||||
return ret; |
||||
} |
||||
|
||||
struct pci_bus *pci_mcs8140_scan_bus(int nr, struct pci_sys_data *sys) |
||||
{ |
||||
return pci_scan_bus(sys->busnr, &pci_mcs8140_ops, sys); |
||||
} |
||||
|
||||
|
||||
int __init pci_mcs8140_setup(int nr, struct pci_sys_data *sys) |
||||
{ |
||||
int ret = 0; |
||||
u32 val; |
||||
|
||||
if (nr > 0) |
||||
return 0; |
||||
|
||||
sys->mem_offset = MCS8140_PCI_IO_VIRT_BASE - MCS8140_PCI_IO_BASE; |
||||
sys->io_offset = 0; |
||||
|
||||
ret = pci_mcs8140_setup_resources(sys); |
||||
if (ret < 0) { |
||||
pr_err("unable to setup mcs8140 resources\n"); |
||||
goto out; |
||||
} |
||||
|
||||
val = readl_relaxed(MCS8140_PCI_CFG_VIRT_BASE); |
||||
if (val != MCS8140_PCI_DEVICE_ID) { |
||||
pr_err("cannot find MCS8140 PCI Core: %08x\n", val); |
||||
ret = -EIO; |
||||
goto out; |
||||
} |
||||
|
||||
pr_info("MCS8140 PCI core found\n"); |
||||
|
||||
val = readl_relaxed(MCS8140_PCI_CFG_VIRT_BASE + PCI_COMMAND); |
||||
/* Added to support wireless cards */ |
||||
writel_relaxed(0, MCS8140_PCI_CFG_VIRT_BASE + 0x40); |
||||
writel_relaxed(val | 0x147, MCS8140_PCI_CFG_VIRT_BASE + PCI_COMMAND); |
||||
val = readl_relaxed(MCS8140_PCI_CFG_VIRT_BASE + PCI_COMMAND); |
||||
ret = 1; |
||||
out: |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
static int __init mcs8140_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
||||
{ |
||||
int line = IRQ_PCI_INTA; |
||||
|
||||
if (pin != 0) { |
||||
/* IRQ_PCIA - 22 */ |
||||
if (pin == PCI_INTD) |
||||
line = IRQ_PCI_INTA + pin; /* IRQ_PCIA - 22 */ |
||||
else |
||||
line = IRQ_PCI_INTA + pin - 1; /* IRQ_PCIA - 22 */ |
||||
} |
||||
|
||||
pr_info("PCI: Map interrupt slot 0x%02x pin 0x%02x line 0x%02x\n", |
||||
slot, pin, line); |
||||
|
||||
return line; |
||||
} |
||||
|
||||
static irqreturn_t mcs8140_pci_abort_interrupt(int irq, void *dummy) |
||||
{ |
||||
u32 word; |
||||
|
||||
word = readl_relaxed(mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
if (!(word & (1 << 24))) |
||||
return IRQ_NONE; |
||||
|
||||
writel_relaxed(word & 0xfffffff0, |
||||
mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
/* flush write */ |
||||
word = readl_relaxed(mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
|
||||
return IRQ_HANDLED; |
||||
} |
||||
|
||||
static int mcs8140_pci_abort_irq_init(int irq) |
||||
{ |
||||
u32 word; |
||||
|
||||
/* Enable Interrupt in PCI Master Core */ |
||||
word = readl_relaxed(mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
word |= (1 << 24); |
||||
writel_relaxed(word, mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
|
||||
/* flush write */ |
||||
word = readl_relaxed(mcs8140_pci_master_base + PCI_IF_CONFIG); |
||||
|
||||
return request_irq(irq, mcs8140_pci_abort_interrupt, 0, |
||||
"PCI abort", NULL); |
||||
} |
||||
|
||||
static int mcs8140_pci_host_abort(unsigned long addr, |
||||
unsigned int fsr, struct pt_regs *regs) |
||||
{ |
||||
pr_warn("PCI Data abort: address = 0x%08lx fsr = 0x%03x" |
||||
"PC = 0x%08lx LR = 0x%08lx\n", |
||||
addr, fsr, regs->ARM_pc, regs->ARM_lr); |
||||
|
||||
/*
|
||||
* If it was an imprecise abort, then we need to correct the |
||||
* return address to be _after_ the instruction. |
||||
*/ |
||||
if (fsr & (1 << 10) || mcs8140_pci_host_status()) |
||||
regs->ARM_pc += 4; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static void mcs8140_data_abort_init(void) |
||||
{ |
||||
hook_fault_code(EXTERNAL_ABORT_NON_LINE_FETCH, |
||||
mcs8140_pci_host_abort, SIGBUS, |
||||
0, "external abort on non-line fetch"); |
||||
} |
||||
|
||||
static struct hw_pci mcs8140_pci __initdata = { |
||||
.map_irq = mcs8140_map_irq, |
||||
.nr_controllers = 1, |
||||
.setup = pci_mcs8140_setup, |
||||
.scan = pci_mcs8140_scan_bus, |
||||
}; |
||||
|
||||
static struct map_desc mcs8140_pci_io_desc[] __initdata = { |
||||
{ |
||||
.virtual = MCS8140_PCI_CFG_VIRT_BASE, |
||||
.pfn = __phys_to_pfn(MCS8140_PCI_CFG_BASE), |
||||
.length = MCS8140_PCI_CONFIG_SIZE, |
||||
.type = MT_DEVICE |
||||
}, |
||||
{ |
||||
.virtual = MCS8140_PCI_IO_VIRT_BASE, |
||||
.pfn = __phys_to_pfn(MCS8140_PCI_IO_BASE), |
||||
.length = MCS8140_PCI_IOMISC_SIZE, |
||||
.type = MT_DEVICE |
||||
}, |
||||
}; |
||||
|
||||
static int __devinit mcs8140_pci_probe(struct platform_device *pdev) |
||||
{ |
||||
struct resource *res; |
||||
int ret, irq; |
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
||||
if (!res) { |
||||
dev_err(&pdev->dev, "failed to get mem resource 0\n"); |
||||
return -ENODEV; |
||||
} |
||||
|
||||
mcs8140_pci_master_base = devm_ioremap(&pdev->dev, res->start, |
||||
resource_size(res)); |
||||
if (!mcs8140_pci_master_base) { |
||||
dev_err(&pdev->dev, "failed to remap PCI master regs\n"); |
||||
return -ENODEV; |
||||
} |
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
||||
if (!res) { |
||||
dev_err(&pdev->dev, "failed to get mem resource 1\n"); |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
mcs8140_eeprom_emu_base = devm_ioremap(&pdev->dev, res->start, |
||||
resource_size(res)); |
||||
if (!mcs8140_eeprom_emu_base) { |
||||
dev_err(&pdev->dev, "failed to remap EEPROM regs\n"); |
||||
return -ENOMEM; |
||||
} |
||||
|
||||
irq = platform_get_irq(pdev, 0); |
||||
if (irq < 0) { |
||||
dev_err(&pdev->dev, "failed to get pci abort irq\n"); |
||||
return -ENODEV; |
||||
} |
||||
|
||||
/* Setup static mappins for PCI CFG space */ |
||||
iotable_init(mcs8140_pci_io_desc, ARRAY_SIZE(mcs8140_pci_io_desc)); |
||||
|
||||
pcibios_min_io = MCS8140_PCI_HOST_BASE; |
||||
pcibios_min_mem = MCS8140_PCI_HOST_BASE + MCS8140_PCI_PRE_BASE; |
||||
|
||||
mcs8140_data_abort_init(); |
||||
ret = mcs8140_pci_abort_irq_init(irq); |
||||
if (ret) { |
||||
dev_err(&pdev->dev, "failed to setup abort irq\n"); |
||||
return ret; |
||||
} |
||||
|
||||
pci_common_init(&mcs8140_pci); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static struct of_device_id mcs8140_of_ids[] __devinitdata = { |
||||
{ .compatible = "moschip,mcs8140-pci" }, |
||||
{ .compatible = "moschip,mcs814x-pci" }, |
||||
{ /* sentinel */ }, |
||||
}; |
||||
|
||||
static struct platform_driver mcs8140_pci_driver = { |
||||
.driver = { |
||||
.name = "mcs8140-pci", |
||||
.of_match_table = mcs8140_of_ids, |
||||
}, |
||||
.probe = mcs8140_pci_probe, |
||||
}; |
||||
|
||||
static int __init mcs8140_pci_init(void) |
||||
{ |
||||
return platform_driver_register(&mcs8140_pci_driver); |
||||
} |
||||
subsys_initcall(mcs8140_pci_init); |
||||
|
Loading…
Reference in new issue