18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/arch/mips/txx9/pci.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Based on linux/arch/mips/txx9/rbtx4927/setup.c, 58c2ecf20Sopenharmony_ci * linux/arch/mips/txx9/rbtx4938/setup.c, 68c2ecf20Sopenharmony_ci * and RBTX49xx patch from CELF patch archive. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright 2001-2005 MontaVista Software Inc. 98c2ecf20Sopenharmony_ci * Copyright (C) 1996, 97, 2001, 04 Ralf Baechle (ralf@linux-mips.org) 108c2ecf20Sopenharmony_ci * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 138c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 148c2ecf20Sopenharmony_ci * for more details. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 188c2ecf20Sopenharmony_ci#include <linux/io.h> 198c2ecf20Sopenharmony_ci#include <asm/txx9/generic.h> 208c2ecf20Sopenharmony_ci#include <asm/txx9/pci.h> 218c2ecf20Sopenharmony_ci#ifdef CONFIG_TOSHIBA_FPCIB0 228c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 238c2ecf20Sopenharmony_ci#include <linux/slab.h> 248c2ecf20Sopenharmony_ci#include <asm/i8259.h> 258c2ecf20Sopenharmony_ci#include <asm/txx9/smsc_fdc37m81x.h> 268c2ecf20Sopenharmony_ci#endif 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int __init 298c2ecf20Sopenharmony_ciearly_read_config_word(struct pci_controller *hose, 308c2ecf20Sopenharmony_ci int top_bus, int bus, int devfn, int offset, u16 *value) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct pci_bus fake_bus; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci fake_bus.number = bus; 358c2ecf20Sopenharmony_ci fake_bus.sysdata = hose; 368c2ecf20Sopenharmony_ci fake_bus.ops = hose->pci_ops; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (bus != top_bus) 398c2ecf20Sopenharmony_ci /* Fake a parent bus structure. */ 408c2ecf20Sopenharmony_ci fake_bus.parent = &fake_bus; 418c2ecf20Sopenharmony_ci else 428c2ecf20Sopenharmony_ci fake_bus.parent = NULL; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci return pci_bus_read_config_word(&fake_bus, devfn, offset, value); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciint __init txx9_pci66_check(struct pci_controller *hose, int top_bus, 488c2ecf20Sopenharmony_ci int current_bus) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci u32 pci_devfn; 518c2ecf20Sopenharmony_ci unsigned short vid; 528c2ecf20Sopenharmony_ci int cap66 = -1; 538c2ecf20Sopenharmony_ci u16 stat; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* It seems SLC90E66 needs some time after PCI reset... */ 568c2ecf20Sopenharmony_ci mdelay(80); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci pr_info("PCI: Checking 66MHz capabilities...\n"); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) { 618c2ecf20Sopenharmony_ci if (PCI_FUNC(pci_devfn)) 628c2ecf20Sopenharmony_ci continue; 638c2ecf20Sopenharmony_ci if (early_read_config_word(hose, top_bus, current_bus, 648c2ecf20Sopenharmony_ci pci_devfn, PCI_VENDOR_ID, &vid) != 658c2ecf20Sopenharmony_ci PCIBIOS_SUCCESSFUL) 668c2ecf20Sopenharmony_ci continue; 678c2ecf20Sopenharmony_ci if (vid == 0xffff) 688c2ecf20Sopenharmony_ci continue; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* check 66MHz capability */ 718c2ecf20Sopenharmony_ci if (cap66 < 0) 728c2ecf20Sopenharmony_ci cap66 = 1; 738c2ecf20Sopenharmony_ci if (cap66) { 748c2ecf20Sopenharmony_ci early_read_config_word(hose, top_bus, current_bus, 758c2ecf20Sopenharmony_ci pci_devfn, PCI_STATUS, &stat); 768c2ecf20Sopenharmony_ci if (!(stat & PCI_STATUS_66MHZ)) { 778c2ecf20Sopenharmony_ci pr_debug("PCI: %02x:%02x not 66MHz capable.\n", 788c2ecf20Sopenharmony_ci current_bus, pci_devfn); 798c2ecf20Sopenharmony_ci cap66 = 0; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci return cap66 > 0; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic struct resource primary_pci_mem_res[2] = { 888c2ecf20Sopenharmony_ci { .name = "PCI MEM" }, 898c2ecf20Sopenharmony_ci { .name = "PCI MMIO" }, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_cistatic struct resource primary_pci_io_res = { .name = "PCI IO" }; 928c2ecf20Sopenharmony_cistruct pci_controller txx9_primary_pcic = { 938c2ecf20Sopenharmony_ci .mem_resource = &primary_pci_mem_res[0], 948c2ecf20Sopenharmony_ci .io_resource = &primary_pci_io_res, 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 988c2ecf20Sopenharmony_ciint txx9_pci_mem_high __initdata = 1; 998c2ecf20Sopenharmony_ci#else 1008c2ecf20Sopenharmony_ciint txx9_pci_mem_high __initdata; 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* 1048c2ecf20Sopenharmony_ci * allocate pci_controller and resources. 1058c2ecf20Sopenharmony_ci * mem_base, io_base: physical address. 0 for auto assignment. 1068c2ecf20Sopenharmony_ci * mem_size and io_size means max size on auto assignment. 1078c2ecf20Sopenharmony_ci * pcic must be &txx9_primary_pcic or NULL. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_cistruct pci_controller *__init 1108c2ecf20Sopenharmony_citxx9_alloc_pci_controller(struct pci_controller *pcic, 1118c2ecf20Sopenharmony_ci unsigned long mem_base, unsigned long mem_size, 1128c2ecf20Sopenharmony_ci unsigned long io_base, unsigned long io_size) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct pcic { 1158c2ecf20Sopenharmony_ci struct pci_controller c; 1168c2ecf20Sopenharmony_ci struct resource r_mem[2]; 1178c2ecf20Sopenharmony_ci struct resource r_io; 1188c2ecf20Sopenharmony_ci } *new = NULL; 1198c2ecf20Sopenharmony_ci int min_size = 0x10000; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (!pcic) { 1228c2ecf20Sopenharmony_ci new = kzalloc(sizeof(*new), GFP_KERNEL); 1238c2ecf20Sopenharmony_ci if (!new) 1248c2ecf20Sopenharmony_ci return NULL; 1258c2ecf20Sopenharmony_ci new->r_mem[0].name = "PCI mem"; 1268c2ecf20Sopenharmony_ci new->r_mem[1].name = "PCI mmio"; 1278c2ecf20Sopenharmony_ci new->r_io.name = "PCI io"; 1288c2ecf20Sopenharmony_ci new->c.mem_resource = new->r_mem; 1298c2ecf20Sopenharmony_ci new->c.io_resource = &new->r_io; 1308c2ecf20Sopenharmony_ci pcic = &new->c; 1318c2ecf20Sopenharmony_ci } else 1328c2ecf20Sopenharmony_ci BUG_ON(pcic != &txx9_primary_pcic); 1338c2ecf20Sopenharmony_ci pcic->io_resource->flags = IORESOURCE_IO; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* 1368c2ecf20Sopenharmony_ci * for auto assignment, first search a (big) region for PCI 1378c2ecf20Sopenharmony_ci * MEM, then search a region for PCI IO. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci if (mem_base) { 1408c2ecf20Sopenharmony_ci pcic->mem_resource[0].start = mem_base; 1418c2ecf20Sopenharmony_ci pcic->mem_resource[0].end = mem_base + mem_size - 1; 1428c2ecf20Sopenharmony_ci if (request_resource(&iomem_resource, &pcic->mem_resource[0])) 1438c2ecf20Sopenharmony_ci goto free_and_exit; 1448c2ecf20Sopenharmony_ci } else { 1458c2ecf20Sopenharmony_ci unsigned long min = 0, max = 0x20000000; /* low 512MB */ 1468c2ecf20Sopenharmony_ci if (!mem_size) { 1478c2ecf20Sopenharmony_ci /* default size for auto assignment */ 1488c2ecf20Sopenharmony_ci if (txx9_pci_mem_high) 1498c2ecf20Sopenharmony_ci mem_size = 0x20000000; /* mem:512M(max) */ 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci mem_size = 0x08000000; /* mem:128M(max) */ 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci if (txx9_pci_mem_high) { 1548c2ecf20Sopenharmony_ci min = 0x20000000; 1558c2ecf20Sopenharmony_ci max = 0xe0000000; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci /* search free region for PCI MEM */ 1588c2ecf20Sopenharmony_ci for (; mem_size >= min_size; mem_size /= 2) { 1598c2ecf20Sopenharmony_ci if (allocate_resource(&iomem_resource, 1608c2ecf20Sopenharmony_ci &pcic->mem_resource[0], 1618c2ecf20Sopenharmony_ci mem_size, min, max, 1628c2ecf20Sopenharmony_ci mem_size, NULL, NULL) == 0) 1638c2ecf20Sopenharmony_ci break; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci if (mem_size < min_size) 1668c2ecf20Sopenharmony_ci goto free_and_exit; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci pcic->mem_resource[1].flags = IORESOURCE_MEM | IORESOURCE_BUSY; 1708c2ecf20Sopenharmony_ci if (io_base) { 1718c2ecf20Sopenharmony_ci pcic->mem_resource[1].start = io_base; 1728c2ecf20Sopenharmony_ci pcic->mem_resource[1].end = io_base + io_size - 1; 1738c2ecf20Sopenharmony_ci if (request_resource(&iomem_resource, &pcic->mem_resource[1])) 1748c2ecf20Sopenharmony_ci goto release_and_exit; 1758c2ecf20Sopenharmony_ci } else { 1768c2ecf20Sopenharmony_ci if (!io_size) 1778c2ecf20Sopenharmony_ci /* default size for auto assignment */ 1788c2ecf20Sopenharmony_ci io_size = 0x01000000; /* io:16M(max) */ 1798c2ecf20Sopenharmony_ci /* search free region for PCI IO in low 512MB */ 1808c2ecf20Sopenharmony_ci for (; io_size >= min_size; io_size /= 2) { 1818c2ecf20Sopenharmony_ci if (allocate_resource(&iomem_resource, 1828c2ecf20Sopenharmony_ci &pcic->mem_resource[1], 1838c2ecf20Sopenharmony_ci io_size, 0, 0x20000000, 1848c2ecf20Sopenharmony_ci io_size, NULL, NULL) == 0) 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci if (io_size < min_size) 1888c2ecf20Sopenharmony_ci goto release_and_exit; 1898c2ecf20Sopenharmony_ci io_base = pcic->mem_resource[1].start; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci pcic->mem_resource[0].flags = IORESOURCE_MEM; 1938c2ecf20Sopenharmony_ci if (pcic == &txx9_primary_pcic && 1948c2ecf20Sopenharmony_ci mips_io_port_base == (unsigned long)-1) { 1958c2ecf20Sopenharmony_ci /* map ioport 0 to PCI I/O space address 0 */ 1968c2ecf20Sopenharmony_ci set_io_port_base(IO_BASE + pcic->mem_resource[1].start); 1978c2ecf20Sopenharmony_ci pcic->io_resource->start = 0; 1988c2ecf20Sopenharmony_ci pcic->io_offset = 0; /* busaddr == ioaddr */ 1998c2ecf20Sopenharmony_ci pcic->io_map_base = IO_BASE + pcic->mem_resource[1].start; 2008c2ecf20Sopenharmony_ci } else { 2018c2ecf20Sopenharmony_ci /* physaddr to ioaddr */ 2028c2ecf20Sopenharmony_ci pcic->io_resource->start = 2038c2ecf20Sopenharmony_ci io_base - (mips_io_port_base - IO_BASE); 2048c2ecf20Sopenharmony_ci pcic->io_offset = io_base - (mips_io_port_base - IO_BASE); 2058c2ecf20Sopenharmony_ci pcic->io_map_base = mips_io_port_base; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci pcic->io_resource->end = pcic->io_resource->start + io_size - 1; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci pcic->mem_offset = 0; /* busaddr == physaddr */ 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci pr_info("PCI: IO %pR MEM %pR\n", &pcic->mem_resource[1], 2128c2ecf20Sopenharmony_ci &pcic->mem_resource[0]); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* register_pci_controller() will request MEM resource */ 2158c2ecf20Sopenharmony_ci release_resource(&pcic->mem_resource[0]); 2168c2ecf20Sopenharmony_ci return pcic; 2178c2ecf20Sopenharmony_ci release_and_exit: 2188c2ecf20Sopenharmony_ci release_resource(&pcic->mem_resource[0]); 2198c2ecf20Sopenharmony_ci free_and_exit: 2208c2ecf20Sopenharmony_ci kfree(new); 2218c2ecf20Sopenharmony_ci pr_err("PCI: Failed to allocate resources.\n"); 2228c2ecf20Sopenharmony_ci return NULL; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int __init 2268c2ecf20Sopenharmony_citxx9_arch_pci_init(void) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci PCIBIOS_MIN_IO = 0x8000; /* reseve legacy I/O space */ 2298c2ecf20Sopenharmony_ci return 0; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ciarch_initcall(txx9_arch_pci_init); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci/* IRQ/IDSEL mapping */ 2348c2ecf20Sopenharmony_ciint txx9_pci_option = 2358c2ecf20Sopenharmony_ci#ifdef CONFIG_PICMG_PCI_BACKPLANE_DEFAULT 2368c2ecf20Sopenharmony_ci TXX9_PCI_OPT_PICMG | 2378c2ecf20Sopenharmony_ci#endif 2388c2ecf20Sopenharmony_ci TXX9_PCI_OPT_CLK_AUTO; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cienum txx9_pci_err_action txx9_pci_err_action = TXX9_PCI_ERR_REPORT; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci#ifdef CONFIG_TOSHIBA_FPCIB0 2438c2ecf20Sopenharmony_cistatic irqreturn_t i8259_interrupt(int irq, void *dev_id) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci int isairq; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci isairq = i8259_irq(); 2488c2ecf20Sopenharmony_ci if (unlikely(isairq <= I8259A_IRQ_BASE)) 2498c2ecf20Sopenharmony_ci return IRQ_NONE; 2508c2ecf20Sopenharmony_ci generic_handle_irq(isairq); 2518c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int txx9_i8259_irq_setup(int irq) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci int err; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci init_i8259_irqs(); 2598c2ecf20Sopenharmony_ci err = request_irq(irq, &i8259_interrupt, IRQF_SHARED, 2608c2ecf20Sopenharmony_ci "cascade(i8259)", (void *)(long)irq); 2618c2ecf20Sopenharmony_ci if (!err) 2628c2ecf20Sopenharmony_ci pr_info("PCI-ISA bridge PIC (irq %d)\n", irq); 2638c2ecf20Sopenharmony_ci return err; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic void __ref quirk_slc90e66_bridge(struct pci_dev *dev) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci int irq; /* PCI/ISA Bridge interrupt */ 2698c2ecf20Sopenharmony_ci u8 reg_64; 2708c2ecf20Sopenharmony_ci u32 reg_b0; 2718c2ecf20Sopenharmony_ci u8 reg_e1; 2728c2ecf20Sopenharmony_ci irq = pcibios_map_irq(dev, PCI_SLOT(dev->devfn), 1); /* INTA */ 2738c2ecf20Sopenharmony_ci if (!irq) 2748c2ecf20Sopenharmony_ci return; 2758c2ecf20Sopenharmony_ci txx9_i8259_irq_setup(irq); 2768c2ecf20Sopenharmony_ci pci_read_config_byte(dev, 0x64, ®_64); 2778c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0xb0, ®_b0); 2788c2ecf20Sopenharmony_ci pci_read_config_byte(dev, 0xe1, ®_e1); 2798c2ecf20Sopenharmony_ci /* serial irq control */ 2808c2ecf20Sopenharmony_ci reg_64 = 0xd0; 2818c2ecf20Sopenharmony_ci /* serial irq pin */ 2828c2ecf20Sopenharmony_ci reg_b0 |= 0x00010000; 2838c2ecf20Sopenharmony_ci /* ide irq on isa14 */ 2848c2ecf20Sopenharmony_ci reg_e1 &= 0xf0; 2858c2ecf20Sopenharmony_ci reg_e1 |= 0x0d; 2868c2ecf20Sopenharmony_ci pci_write_config_byte(dev, 0x64, reg_64); 2878c2ecf20Sopenharmony_ci pci_write_config_dword(dev, 0xb0, reg_b0); 2888c2ecf20Sopenharmony_ci pci_write_config_byte(dev, 0xe1, reg_e1); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci smsc_fdc37m81x_init(0x3f0); 2918c2ecf20Sopenharmony_ci smsc_fdc37m81x_config_beg(); 2928c2ecf20Sopenharmony_ci smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM, 2938c2ecf20Sopenharmony_ci SMSC_FDC37M81X_KBD); 2948c2ecf20Sopenharmony_ci smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1); 2958c2ecf20Sopenharmony_ci smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12); 2968c2ecf20Sopenharmony_ci smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE, 2978c2ecf20Sopenharmony_ci 1); 2988c2ecf20Sopenharmony_ci smsc_fdc37m81x_config_end(); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic void quirk_slc90e66_ide(struct pci_dev *dev) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci unsigned char dat; 3048c2ecf20Sopenharmony_ci int regs[2] = {0x41, 0x43}; 3058c2ecf20Sopenharmony_ci int i; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ 3088c2ecf20Sopenharmony_ci pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14); 3098c2ecf20Sopenharmony_ci pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &dat); 3108c2ecf20Sopenharmony_ci pr_info("PCI: %s: IRQ %02x", pci_name(dev), dat); 3118c2ecf20Sopenharmony_ci /* enable SMSC SLC90E66 IDE */ 3128c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(regs); i++) { 3138c2ecf20Sopenharmony_ci pci_read_config_byte(dev, regs[i], &dat); 3148c2ecf20Sopenharmony_ci pci_write_config_byte(dev, regs[i], dat | 0x80); 3158c2ecf20Sopenharmony_ci pci_read_config_byte(dev, regs[i], &dat); 3168c2ecf20Sopenharmony_ci pr_cont(" IDETIM%d %02x", i, dat); 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci pci_read_config_byte(dev, 0x5c, &dat); 3198c2ecf20Sopenharmony_ci /* 3208c2ecf20Sopenharmony_ci * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! 3218c2ecf20Sopenharmony_ci * 3228c2ecf20Sopenharmony_ci * This line of code is intended to provide the user with a work 3238c2ecf20Sopenharmony_ci * around solution to the anomalies cited in SMSC's anomaly sheet 3248c2ecf20Sopenharmony_ci * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"". 3258c2ecf20Sopenharmony_ci * 3268c2ecf20Sopenharmony_ci * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ci dat |= 0x01; 3298c2ecf20Sopenharmony_ci pci_write_config_byte(dev, 0x5c, dat); 3308c2ecf20Sopenharmony_ci pci_read_config_byte(dev, 0x5c, &dat); 3318c2ecf20Sopenharmony_ci pr_cont(" REG5C %02x\n", dat); 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci#endif /* CONFIG_TOSHIBA_FPCIB0 */ 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic void tc35815_fixup(struct pci_dev *dev) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci /* This device may have PM registers but not they are not supported. */ 3388c2ecf20Sopenharmony_ci if (dev->pm_cap) { 3398c2ecf20Sopenharmony_ci dev_info(&dev->dev, "PM disabled\n"); 3408c2ecf20Sopenharmony_ci dev->pm_cap = 0; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic void final_fixup(struct pci_dev *dev) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci unsigned char bist; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* Do build-in self test */ 3498c2ecf20Sopenharmony_ci if (pci_read_config_byte(dev, PCI_BIST, &bist) == PCIBIOS_SUCCESSFUL && 3508c2ecf20Sopenharmony_ci (bist & PCI_BIST_CAPABLE)) { 3518c2ecf20Sopenharmony_ci unsigned long timeout; 3528c2ecf20Sopenharmony_ci pci_set_power_state(dev, PCI_D0); 3538c2ecf20Sopenharmony_ci pr_info("PCI: %s BIST...", pci_name(dev)); 3548c2ecf20Sopenharmony_ci pci_write_config_byte(dev, PCI_BIST, PCI_BIST_START); 3558c2ecf20Sopenharmony_ci timeout = jiffies + HZ * 2; /* timeout after 2 sec */ 3568c2ecf20Sopenharmony_ci do { 3578c2ecf20Sopenharmony_ci pci_read_config_byte(dev, PCI_BIST, &bist); 3588c2ecf20Sopenharmony_ci if (time_after(jiffies, timeout)) 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci } while (bist & PCI_BIST_START); 3618c2ecf20Sopenharmony_ci if (bist & (PCI_BIST_CODE_MASK | PCI_BIST_START)) 3628c2ecf20Sopenharmony_ci pr_cont("failed. (0x%x)\n", bist); 3638c2ecf20Sopenharmony_ci else 3648c2ecf20Sopenharmony_ci pr_cont("OK.\n"); 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci#ifdef CONFIG_TOSHIBA_FPCIB0 3698c2ecf20Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460 3708c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_0, 3718c2ecf20Sopenharmony_ci quirk_slc90e66_bridge); 3728c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, 3738c2ecf20Sopenharmony_ci quirk_slc90e66_ide); 3748c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, 3758c2ecf20Sopenharmony_ci quirk_slc90e66_ide); 3768c2ecf20Sopenharmony_ci#endif 3778c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2, 3788c2ecf20Sopenharmony_ci PCI_DEVICE_ID_TOSHIBA_TC35815_NWU, tc35815_fixup); 3798c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2, 3808c2ecf20Sopenharmony_ci PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939, tc35815_fixup); 3818c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, final_fixup); 3828c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, final_fixup); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ciint pcibios_plat_dev_init(struct pci_dev *dev) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci return 0; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic int (*txx9_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); 3908c2ecf20Sopenharmony_ciint pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci return txx9_pci_map_irq(dev, slot, pin); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cichar * (*txx9_board_pcibios_setup)(char *str) __initdata; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cichar *__init txx9_pcibios_setup(char *str) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str)) 4008c2ecf20Sopenharmony_ci return NULL; 4018c2ecf20Sopenharmony_ci if (!strcmp(str, "picmg")) { 4028c2ecf20Sopenharmony_ci /* PICMG compliant backplane (TOSHIBA JMB-PICMG-ATX 4038c2ecf20Sopenharmony_ci (5V or 3.3V), JMB-PICMG-L2 (5V only), etc.) */ 4048c2ecf20Sopenharmony_ci txx9_pci_option |= TXX9_PCI_OPT_PICMG; 4058c2ecf20Sopenharmony_ci return NULL; 4068c2ecf20Sopenharmony_ci } else if (!strcmp(str, "nopicmg")) { 4078c2ecf20Sopenharmony_ci /* non-PICMG compliant backplane (TOSHIBA 4088c2ecf20Sopenharmony_ci RBHBK4100,RBHBK4200, Interface PCM-PCM05, etc.) */ 4098c2ecf20Sopenharmony_ci txx9_pci_option &= ~TXX9_PCI_OPT_PICMG; 4108c2ecf20Sopenharmony_ci return NULL; 4118c2ecf20Sopenharmony_ci } else if (!strncmp(str, "clk=", 4)) { 4128c2ecf20Sopenharmony_ci char *val = str + 4; 4138c2ecf20Sopenharmony_ci txx9_pci_option &= ~TXX9_PCI_OPT_CLK_MASK; 4148c2ecf20Sopenharmony_ci if (strcmp(val, "33") == 0) 4158c2ecf20Sopenharmony_ci txx9_pci_option |= TXX9_PCI_OPT_CLK_33; 4168c2ecf20Sopenharmony_ci else if (strcmp(val, "66") == 0) 4178c2ecf20Sopenharmony_ci txx9_pci_option |= TXX9_PCI_OPT_CLK_66; 4188c2ecf20Sopenharmony_ci else /* "auto" */ 4198c2ecf20Sopenharmony_ci txx9_pci_option |= TXX9_PCI_OPT_CLK_AUTO; 4208c2ecf20Sopenharmony_ci return NULL; 4218c2ecf20Sopenharmony_ci } else if (!strncmp(str, "err=", 4)) { 4228c2ecf20Sopenharmony_ci if (!strcmp(str + 4, "panic")) 4238c2ecf20Sopenharmony_ci txx9_pci_err_action = TXX9_PCI_ERR_PANIC; 4248c2ecf20Sopenharmony_ci else if (!strcmp(str + 4, "ignore")) 4258c2ecf20Sopenharmony_ci txx9_pci_err_action = TXX9_PCI_ERR_IGNORE; 4268c2ecf20Sopenharmony_ci return NULL; 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci txx9_pci_map_irq = txx9_board_vec->pci_map_irq; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return str; 4328c2ecf20Sopenharmony_ci} 433