/* * linux/arch/mips/txx9/pci.c * * Based on linux/arch/mips/txx9/rbtx4927/setup.c, * linux/arch/mips/txx9/rbtx4938/setup.c, * and RBTX49xx patch from CELF patch archive. * * Copyright 2001-2005 MontaVista Software Inc. * Copyright (C) 1996, 97, 2001, 04 Ralf Baechle (ralf@linux-mips.org) * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 * * 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/delay.h> #include <linux/jiffies.h> #include <linux/io.h> #include <asm/txx9/generic.h> #include <asm/txx9/pci.h> #ifdef CONFIG_TOSHIBA_FPCIB0 #include <linux/interrupt.h> #include <linux/slab.h> #include <asm/i8259.h> #include <asm/txx9/smsc_fdc37m81x.h> #endif
staticint __init
early_read_config_word(struct pci_controller *hose, int top_bus, int bus, int devfn, int offset, u16 *value)
{ struct pci_bus fake_bus;
int __init txx9_pci66_check(struct pci_controller *hose, int top_bus, int current_bus)
{
u32 pci_devfn; unsignedshort vid; int cap66 = -1;
u16 stat; int ret;
/* It seems SLC90E66 needs some time after PCI reset... */
mdelay(80);
pr_info("PCI: Checking 66MHz capabilities...\n");
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_VENDOR_ID, &vid); if (ret != PCIBIOS_SUCCESSFUL) continue; if (vid == 0xffff) continue;
/* * for auto assignment, first search a (big) region for PCI * MEM, then search a region for PCI IO.
*/ if (mem_base) {
pcic->mem_resource[0].start = mem_base;
pcic->mem_resource[0].end = mem_base + mem_size - 1; if (request_resource(&iomem_resource, &pcic->mem_resource[0])) goto free_and_exit;
} else { unsignedlong min = 0, max = 0x20000000; /* low 512MB */ if (!mem_size) { /* default size for auto assignment */ if (txx9_pci_mem_high)
mem_size = 0x20000000; /* mem:512M(max) */ else
mem_size = 0x08000000; /* mem:128M(max) */
} if (txx9_pci_mem_high) {
min = 0x20000000;
max = 0xe0000000;
} /* search free region for PCI MEM */ for (; mem_size >= min_size; mem_size /= 2) { if (allocate_resource(&iomem_resource,
&pcic->mem_resource[0],
mem_size, min, max,
mem_size, NULL, NULL) == 0) break;
} if (mem_size < min_size) goto free_and_exit;
}
pcic->mem_resource[1].flags = IORESOURCE_MEM | IORESOURCE_BUSY; if (io_base) {
pcic->mem_resource[1].start = io_base;
pcic->mem_resource[1].end = io_base + io_size - 1; if (request_resource(&iomem_resource, &pcic->mem_resource[1])) goto release_and_exit;
} else { if (!io_size) /* default size for auto assignment */
io_size = 0x01000000; /* io:16M(max) */ /* search free region for PCI IO in low 512MB */ for (; io_size >= min_size; io_size /= 2) { if (allocate_resource(&iomem_resource,
&pcic->mem_resource[1],
io_size, 0, 0x20000000,
io_size, NULL, NULL) == 0) break;
} if (io_size < min_size) goto release_and_exit;
io_base = pcic->mem_resource[1].start;
}
staticvoid quirk_slc90e66_ide(struct pci_dev *dev)
{ unsignedchar dat; int regs[2] = {0x41, 0x43}; int i;
/* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14);
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &dat);
pr_info("PCI: %s: IRQ %02x", pci_name(dev), dat); /* enable SMSC SLC90E66 IDE */ for (i = 0; i < ARRAY_SIZE(regs); i++) {
pci_read_config_byte(dev, regs[i], &dat);
pci_write_config_byte(dev, regs[i], dat | 0x80);
pci_read_config_byte(dev, regs[i], &dat);
pr_cont(" IDETIM%d %02x", i, dat);
}
pci_read_config_byte(dev, 0x5c, &dat); /* * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! * * This line of code is intended to provide the user with a work * around solution to the anomalies cited in SMSC's anomaly sheet * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"". * * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
*/
dat |= 0x01;
pci_write_config_byte(dev, 0x5c, dat);
pci_read_config_byte(dev, 0x5c, &dat);
pr_cont(" REG5C %02x\n", dat);
} #endif/* CONFIG_TOSHIBA_FPCIB0 */
staticvoid tc35815_fixup(struct pci_dev *dev)
{ /* This device may have PM registers but not they are not supported. */ if (dev->pm_cap) {
dev_info(&dev->dev, "PM disabled\n");
dev->pm_cap = 0;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.