123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- /*
- * 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
- static int __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;
- fake_bus.number = bus;
- fake_bus.sysdata = hose;
- fake_bus.ops = hose->pci_ops;
- if (bus != top_bus)
- /* Fake a parent bus structure. */
- fake_bus.parent = &fake_bus;
- else
- fake_bus.parent = NULL;
- return pci_bus_read_config_word(&fake_bus, devfn, offset, value);
- }
- int __init txx9_pci66_check(struct pci_controller *hose, int top_bus,
- int current_bus)
- {
- u32 pci_devfn;
- unsigned short vid;
- int cap66 = -1;
- u16 stat;
- /* It seems SLC90E66 needs some time after PCI reset... */
- mdelay(80);
- 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 struct resource primary_pci_mem_res[2] = {
- { .name = "PCI MEM" },
- { .name = "PCI MMIO" },
- };
- static struct resource primary_pci_io_res = { .name = "PCI IO" };
- struct pci_controller txx9_primary_pcic = {
- .mem_resource = &primary_pci_mem_res[0],
- .io_resource = &primary_pci_io_res,
- };
- #ifdef CONFIG_64BIT
- int txx9_pci_mem_high __initdata = 1;
- #else
- int txx9_pci_mem_high __initdata;
- #endif
- /*
- * allocate pci_controller and resources.
- * mem_base, io_base: physical address. 0 for auto assignment.
- * mem_size and io_size means max size on auto assignment.
- * pcic must be &txx9_primary_pcic or NULL.
- */
- struct pci_controller *__init
- txx9_alloc_pci_controller(struct pci_controller *pcic,
- unsigned long mem_base, unsigned long mem_size,
- unsigned long io_base, unsigned long io_size)
- {
- struct pcic {
- struct pci_controller c;
- struct resource r_mem[2];
- struct resource r_io;
- } *new = NULL;
- int min_size = 0x10000;
- if (!pcic) {
- new = kzalloc(sizeof(*new), GFP_KERNEL);
- if (!new)
- return NULL;
- new->r_mem[0].name = "PCI mem";
- new->r_mem[1].name = "PCI mmio";
- new->r_io.name = "PCI io";
- new->c.mem_resource = new->r_mem;
- new->c.io_resource = &new->r_io;
- pcic = &new->c;
- } else
- BUG_ON(pcic != &txx9_primary_pcic);
- pcic->io_resource->flags = IORESOURCE_IO;
- /*
- * 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 {
- unsigned long 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;
- }
- pcic->mem_resource[0].flags = IORESOURCE_MEM;
- if (pcic == &txx9_primary_pcic &&
- mips_io_port_base == (unsigned long)-1) {
- /* map ioport 0 to PCI I/O space address 0 */
- set_io_port_base(IO_BASE + pcic->mem_resource[1].start);
- pcic->io_resource->start = 0;
- pcic->io_offset = 0; /* busaddr == ioaddr */
- pcic->io_map_base = IO_BASE + pcic->mem_resource[1].start;
- } else {
- /* physaddr to ioaddr */
- pcic->io_resource->start =
- io_base - (mips_io_port_base - IO_BASE);
- pcic->io_offset = io_base - (mips_io_port_base - IO_BASE);
- pcic->io_map_base = mips_io_port_base;
- }
- pcic->io_resource->end = pcic->io_resource->start + io_size - 1;
- pcic->mem_offset = 0; /* busaddr == physaddr */
- printk(KERN_INFO "PCI: IO %pR MEM %pR\n",
- &pcic->mem_resource[1], &pcic->mem_resource[0]);
- /* register_pci_controller() will request MEM resource */
- release_resource(&pcic->mem_resource[0]);
- return pcic;
- release_and_exit:
- release_resource(&pcic->mem_resource[0]);
- free_and_exit:
- kfree(new);
- printk(KERN_ERR "PCI: Failed to allocate resources.\n");
- return NULL;
- }
- static int __init
- txx9_arch_pci_init(void)
- {
- PCIBIOS_MIN_IO = 0x8000; /* reseve legacy I/O space */
- return 0;
- }
- arch_initcall(txx9_arch_pci_init);
- /* IRQ/IDSEL mapping */
- int txx9_pci_option =
- #ifdef CONFIG_PICMG_PCI_BACKPLANE_DEFAULT
- TXX9_PCI_OPT_PICMG |
- #endif
- TXX9_PCI_OPT_CLK_AUTO;
- enum txx9_pci_err_action txx9_pci_err_action = TXX9_PCI_ERR_REPORT;
- #ifdef CONFIG_TOSHIBA_FPCIB0
- static irqreturn_t i8259_interrupt(int irq, void *dev_id)
- {
- int isairq;
- isairq = i8259_irq();
- if (unlikely(isairq <= I8259A_IRQ_BASE))
- return IRQ_NONE;
- generic_handle_irq(isairq);
- return IRQ_HANDLED;
- }
- static int txx9_i8259_irq_setup(int irq)
- {
- int err;
- init_i8259_irqs();
- err = request_irq(irq, &i8259_interrupt, IRQF_SHARED,
- "cascade(i8259)", (void *)(long)irq);
- if (!err)
- printk(KERN_INFO "PCI-ISA bridge PIC (irq %d)\n", irq);
- return err;
- }
- static void __ref quirk_slc90e66_bridge(struct pci_dev *dev)
- {
- int irq; /* PCI/ISA Bridge interrupt */
- u8 reg_64;
- u32 reg_b0;
- u8 reg_e1;
- irq = pcibios_map_irq(dev, PCI_SLOT(dev->devfn), 1); /* INTA */
- if (!irq)
- return;
- txx9_i8259_irq_setup(irq);
- pci_read_config_byte(dev, 0x64, ®_64);
- pci_read_config_dword(dev, 0xb0, ®_b0);
- pci_read_config_byte(dev, 0xe1, ®_e1);
- /* serial irq control */
- reg_64 = 0xd0;
- /* serial irq pin */
- reg_b0 |= 0x00010000;
- /* ide irq on isa14 */
- reg_e1 &= 0xf0;
- reg_e1 |= 0x0d;
- pci_write_config_byte(dev, 0x64, reg_64);
- pci_write_config_dword(dev, 0xb0, reg_b0);
- pci_write_config_byte(dev, 0xe1, reg_e1);
- smsc_fdc37m81x_init(0x3f0);
- smsc_fdc37m81x_config_beg();
- smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM,
- SMSC_FDC37M81X_KBD);
- smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1);
- smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12);
- smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE,
- 1);
- smsc_fdc37m81x_config_end();
- }
- static void quirk_slc90e66_ide(struct pci_dev *dev)
- {
- unsigned char 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);
- printk(KERN_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);
- printk(KERN_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);
- printk(KERN_CONT " REG5C %02x", dat);
- printk(KERN_CONT "\n");
- }
- #endif /* CONFIG_TOSHIBA_FPCIB0 */
- static void 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;
- }
- }
- static void final_fixup(struct pci_dev *dev)
- {
- unsigned char bist;
- /* Do build-in self test */
- if (pci_read_config_byte(dev, PCI_BIST, &bist) == PCIBIOS_SUCCESSFUL &&
- (bist & PCI_BIST_CAPABLE)) {
- unsigned long timeout;
- pci_set_power_state(dev, PCI_D0);
- printk(KERN_INFO "PCI: %s BIST...", pci_name(dev));
- pci_write_config_byte(dev, PCI_BIST, PCI_BIST_START);
- timeout = jiffies + HZ * 2; /* timeout after 2 sec */
- do {
- pci_read_config_byte(dev, PCI_BIST, &bist);
- if (time_after(jiffies, timeout))
- break;
- } while (bist & PCI_BIST_START);
- if (bist & (PCI_BIST_CODE_MASK | PCI_BIST_START))
- printk(KERN_CONT "failed. (0x%x)\n", bist);
- else
- printk(KERN_CONT "OK.\n");
- }
- }
- #ifdef CONFIG_TOSHIBA_FPCIB0
- #define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_0,
- quirk_slc90e66_bridge);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1,
- quirk_slc90e66_ide);
- DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1,
- quirk_slc90e66_ide);
- #endif
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2,
- PCI_DEVICE_ID_TOSHIBA_TC35815_NWU, tc35815_fixup);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2,
- PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939, tc35815_fixup);
- DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, final_fixup);
- DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, final_fixup);
- int pcibios_plat_dev_init(struct pci_dev *dev)
- {
- return 0;
- }
- int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
- {
- return txx9_board_vec->pci_map_irq(dev, slot, pin);
- }
- char * (*txx9_board_pcibios_setup)(char *str) __initdata;
- char *__init txx9_pcibios_setup(char *str)
- {
- if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str))
- return NULL;
- if (!strcmp(str, "picmg")) {
- /* PICMG compliant backplane (TOSHIBA JMB-PICMG-ATX
- (5V or 3.3V), JMB-PICMG-L2 (5V only), etc.) */
- txx9_pci_option |= TXX9_PCI_OPT_PICMG;
- return NULL;
- } else if (!strcmp(str, "nopicmg")) {
- /* non-PICMG compliant backplane (TOSHIBA
- RBHBK4100,RBHBK4200, Interface PCM-PCM05, etc.) */
- txx9_pci_option &= ~TXX9_PCI_OPT_PICMG;
- return NULL;
- } else if (!strncmp(str, "clk=", 4)) {
- char *val = str + 4;
- txx9_pci_option &= ~TXX9_PCI_OPT_CLK_MASK;
- if (strcmp(val, "33") == 0)
- txx9_pci_option |= TXX9_PCI_OPT_CLK_33;
- else if (strcmp(val, "66") == 0)
- txx9_pci_option |= TXX9_PCI_OPT_CLK_66;
- else /* "auto" */
- txx9_pci_option |= TXX9_PCI_OPT_CLK_AUTO;
- return NULL;
- } else if (!strncmp(str, "err=", 4)) {
- if (!strcmp(str + 4, "panic"))
- txx9_pci_err_action = TXX9_PCI_ERR_PANIC;
- else if (!strcmp(str + 4, "ignore"))
- txx9_pci_err_action = TXX9_PCI_ERR_IGNORE;
- return NULL;
- }
- return str;
- }
|