xref: /kernel/linux/linux-6.6/arch/mips/txx9/generic/pci.c (revision 62306a36)
162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * linux/arch/mips/txx9/pci.c
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Based on linux/arch/mips/txx9/rbtx4927/setup.c,
562306a36Sopenharmony_ci *	    linux/arch/mips/txx9/rbtx4938/setup.c,
662306a36Sopenharmony_ci *	    and RBTX49xx patch from CELF patch archive.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright 2001-2005 MontaVista Software Inc.
962306a36Sopenharmony_ci * Copyright (C) 1996, 97, 2001, 04  Ralf Baechle (ralf@linux-mips.org)
1062306a36Sopenharmony_ci * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
1362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
1462306a36Sopenharmony_ci * for more details.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci#include <linux/delay.h>
1762306a36Sopenharmony_ci#include <linux/jiffies.h>
1862306a36Sopenharmony_ci#include <linux/io.h>
1962306a36Sopenharmony_ci#include <asm/txx9/generic.h>
2062306a36Sopenharmony_ci#include <asm/txx9/pci.h>
2162306a36Sopenharmony_ci#ifdef CONFIG_TOSHIBA_FPCIB0
2262306a36Sopenharmony_ci#include <linux/interrupt.h>
2362306a36Sopenharmony_ci#include <linux/slab.h>
2462306a36Sopenharmony_ci#include <asm/i8259.h>
2562306a36Sopenharmony_ci#include <asm/txx9/smsc_fdc37m81x.h>
2662306a36Sopenharmony_ci#endif
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int __init
2962306a36Sopenharmony_ciearly_read_config_word(struct pci_controller *hose,
3062306a36Sopenharmony_ci		       int top_bus, int bus, int devfn, int offset, u16 *value)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct pci_bus fake_bus;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	fake_bus.number = bus;
3562306a36Sopenharmony_ci	fake_bus.sysdata = hose;
3662306a36Sopenharmony_ci	fake_bus.ops = hose->pci_ops;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (bus != top_bus)
3962306a36Sopenharmony_ci		/* Fake a parent bus structure. */
4062306a36Sopenharmony_ci		fake_bus.parent = &fake_bus;
4162306a36Sopenharmony_ci	else
4262306a36Sopenharmony_ci		fake_bus.parent = NULL;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	return pci_bus_read_config_word(&fake_bus, devfn, offset, value);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciint __init txx9_pci66_check(struct pci_controller *hose, int top_bus,
4862306a36Sopenharmony_ci			    int current_bus)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	u32 pci_devfn;
5162306a36Sopenharmony_ci	unsigned short vid;
5262306a36Sopenharmony_ci	int cap66 = -1;
5362306a36Sopenharmony_ci	u16 stat;
5462306a36Sopenharmony_ci	int ret;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	/* It seems SLC90E66 needs some time after PCI reset... */
5762306a36Sopenharmony_ci	mdelay(80);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	pr_info("PCI: Checking 66MHz capabilities...\n");
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
6262306a36Sopenharmony_ci		if (PCI_FUNC(pci_devfn))
6362306a36Sopenharmony_ci			continue;
6462306a36Sopenharmony_ci		ret = early_read_config_word(hose, top_bus, current_bus,
6562306a36Sopenharmony_ci					     pci_devfn, PCI_VENDOR_ID, &vid);
6662306a36Sopenharmony_ci		if (ret != PCIBIOS_SUCCESSFUL)
6762306a36Sopenharmony_ci			continue;
6862306a36Sopenharmony_ci		if (vid == 0xffff)
6962306a36Sopenharmony_ci			continue;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		/* check 66MHz capability */
7262306a36Sopenharmony_ci		if (cap66 < 0)
7362306a36Sopenharmony_ci			cap66 = 1;
7462306a36Sopenharmony_ci		if (cap66) {
7562306a36Sopenharmony_ci			early_read_config_word(hose, top_bus, current_bus,
7662306a36Sopenharmony_ci					       pci_devfn, PCI_STATUS, &stat);
7762306a36Sopenharmony_ci			if (!(stat & PCI_STATUS_66MHZ)) {
7862306a36Sopenharmony_ci				pr_debug("PCI: %02x:%02x not 66MHz capable.\n",
7962306a36Sopenharmony_ci					 current_bus, pci_devfn);
8062306a36Sopenharmony_ci				cap66 = 0;
8162306a36Sopenharmony_ci				break;
8262306a36Sopenharmony_ci			}
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci	return cap66 > 0;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic struct resource primary_pci_mem_res[2] = {
8962306a36Sopenharmony_ci	{ .name = "PCI MEM" },
9062306a36Sopenharmony_ci	{ .name = "PCI MMIO" },
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_cistatic struct resource primary_pci_io_res = { .name = "PCI IO" };
9362306a36Sopenharmony_cistruct pci_controller txx9_primary_pcic = {
9462306a36Sopenharmony_ci	.mem_resource = &primary_pci_mem_res[0],
9562306a36Sopenharmony_ci	.io_resource = &primary_pci_io_res,
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#ifdef CONFIG_64BIT
9962306a36Sopenharmony_ciint txx9_pci_mem_high __initdata = 1;
10062306a36Sopenharmony_ci#else
10162306a36Sopenharmony_ciint txx9_pci_mem_high __initdata;
10262306a36Sopenharmony_ci#endif
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/*
10562306a36Sopenharmony_ci * allocate pci_controller and resources.
10662306a36Sopenharmony_ci * mem_base, io_base: physical address.	 0 for auto assignment.
10762306a36Sopenharmony_ci * mem_size and io_size means max size on auto assignment.
10862306a36Sopenharmony_ci * pcic must be &txx9_primary_pcic or NULL.
10962306a36Sopenharmony_ci */
11062306a36Sopenharmony_cistruct pci_controller *__init
11162306a36Sopenharmony_citxx9_alloc_pci_controller(struct pci_controller *pcic,
11262306a36Sopenharmony_ci			  unsigned long mem_base, unsigned long mem_size,
11362306a36Sopenharmony_ci			  unsigned long io_base, unsigned long io_size)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	struct pcic {
11662306a36Sopenharmony_ci		struct pci_controller c;
11762306a36Sopenharmony_ci		struct resource r_mem[2];
11862306a36Sopenharmony_ci		struct resource r_io;
11962306a36Sopenharmony_ci	} *new = NULL;
12062306a36Sopenharmony_ci	int min_size = 0x10000;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (!pcic) {
12362306a36Sopenharmony_ci		new = kzalloc(sizeof(*new), GFP_KERNEL);
12462306a36Sopenharmony_ci		if (!new)
12562306a36Sopenharmony_ci			return NULL;
12662306a36Sopenharmony_ci		new->r_mem[0].name = "PCI mem";
12762306a36Sopenharmony_ci		new->r_mem[1].name = "PCI mmio";
12862306a36Sopenharmony_ci		new->r_io.name = "PCI io";
12962306a36Sopenharmony_ci		new->c.mem_resource = new->r_mem;
13062306a36Sopenharmony_ci		new->c.io_resource = &new->r_io;
13162306a36Sopenharmony_ci		pcic = &new->c;
13262306a36Sopenharmony_ci	} else
13362306a36Sopenharmony_ci		BUG_ON(pcic != &txx9_primary_pcic);
13462306a36Sopenharmony_ci	pcic->io_resource->flags = IORESOURCE_IO;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/*
13762306a36Sopenharmony_ci	 * for auto assignment, first search a (big) region for PCI
13862306a36Sopenharmony_ci	 * MEM, then search a region for PCI IO.
13962306a36Sopenharmony_ci	 */
14062306a36Sopenharmony_ci	if (mem_base) {
14162306a36Sopenharmony_ci		pcic->mem_resource[0].start = mem_base;
14262306a36Sopenharmony_ci		pcic->mem_resource[0].end = mem_base + mem_size - 1;
14362306a36Sopenharmony_ci		if (request_resource(&iomem_resource, &pcic->mem_resource[0]))
14462306a36Sopenharmony_ci			goto free_and_exit;
14562306a36Sopenharmony_ci	} else {
14662306a36Sopenharmony_ci		unsigned long min = 0, max = 0x20000000; /* low 512MB */
14762306a36Sopenharmony_ci		if (!mem_size) {
14862306a36Sopenharmony_ci			/* default size for auto assignment */
14962306a36Sopenharmony_ci			if (txx9_pci_mem_high)
15062306a36Sopenharmony_ci				mem_size = 0x20000000;	/* mem:512M(max) */
15162306a36Sopenharmony_ci			else
15262306a36Sopenharmony_ci				mem_size = 0x08000000;	/* mem:128M(max) */
15362306a36Sopenharmony_ci		}
15462306a36Sopenharmony_ci		if (txx9_pci_mem_high) {
15562306a36Sopenharmony_ci			min = 0x20000000;
15662306a36Sopenharmony_ci			max = 0xe0000000;
15762306a36Sopenharmony_ci		}
15862306a36Sopenharmony_ci		/* search free region for PCI MEM */
15962306a36Sopenharmony_ci		for (; mem_size >= min_size; mem_size /= 2) {
16062306a36Sopenharmony_ci			if (allocate_resource(&iomem_resource,
16162306a36Sopenharmony_ci					      &pcic->mem_resource[0],
16262306a36Sopenharmony_ci					      mem_size, min, max,
16362306a36Sopenharmony_ci					      mem_size, NULL, NULL) == 0)
16462306a36Sopenharmony_ci				break;
16562306a36Sopenharmony_ci		}
16662306a36Sopenharmony_ci		if (mem_size < min_size)
16762306a36Sopenharmony_ci			goto free_and_exit;
16862306a36Sopenharmony_ci	}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	pcic->mem_resource[1].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
17162306a36Sopenharmony_ci	if (io_base) {
17262306a36Sopenharmony_ci		pcic->mem_resource[1].start = io_base;
17362306a36Sopenharmony_ci		pcic->mem_resource[1].end = io_base + io_size - 1;
17462306a36Sopenharmony_ci		if (request_resource(&iomem_resource, &pcic->mem_resource[1]))
17562306a36Sopenharmony_ci			goto release_and_exit;
17662306a36Sopenharmony_ci	} else {
17762306a36Sopenharmony_ci		if (!io_size)
17862306a36Sopenharmony_ci			/* default size for auto assignment */
17962306a36Sopenharmony_ci			io_size = 0x01000000;	/* io:16M(max) */
18062306a36Sopenharmony_ci		/* search free region for PCI IO in low 512MB */
18162306a36Sopenharmony_ci		for (; io_size >= min_size; io_size /= 2) {
18262306a36Sopenharmony_ci			if (allocate_resource(&iomem_resource,
18362306a36Sopenharmony_ci					      &pcic->mem_resource[1],
18462306a36Sopenharmony_ci					      io_size, 0, 0x20000000,
18562306a36Sopenharmony_ci					      io_size, NULL, NULL) == 0)
18662306a36Sopenharmony_ci				break;
18762306a36Sopenharmony_ci		}
18862306a36Sopenharmony_ci		if (io_size < min_size)
18962306a36Sopenharmony_ci			goto release_and_exit;
19062306a36Sopenharmony_ci		io_base = pcic->mem_resource[1].start;
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	pcic->mem_resource[0].flags = IORESOURCE_MEM;
19462306a36Sopenharmony_ci	if (pcic == &txx9_primary_pcic &&
19562306a36Sopenharmony_ci	    mips_io_port_base == (unsigned long)-1) {
19662306a36Sopenharmony_ci		/* map ioport 0 to PCI I/O space address 0 */
19762306a36Sopenharmony_ci		set_io_port_base(IO_BASE + pcic->mem_resource[1].start);
19862306a36Sopenharmony_ci		pcic->io_resource->start = 0;
19962306a36Sopenharmony_ci		pcic->io_offset = 0;	/* busaddr == ioaddr */
20062306a36Sopenharmony_ci		pcic->io_map_base = IO_BASE + pcic->mem_resource[1].start;
20162306a36Sopenharmony_ci	} else {
20262306a36Sopenharmony_ci		/* physaddr to ioaddr */
20362306a36Sopenharmony_ci		pcic->io_resource->start =
20462306a36Sopenharmony_ci			io_base - (mips_io_port_base - IO_BASE);
20562306a36Sopenharmony_ci		pcic->io_offset = io_base - (mips_io_port_base - IO_BASE);
20662306a36Sopenharmony_ci		pcic->io_map_base = mips_io_port_base;
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci	pcic->io_resource->end = pcic->io_resource->start + io_size - 1;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	pcic->mem_offset = 0;	/* busaddr == physaddr */
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	pr_info("PCI: IO %pR MEM %pR\n", &pcic->mem_resource[1],
21362306a36Sopenharmony_ci		&pcic->mem_resource[0]);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	/* register_pci_controller() will request MEM resource */
21662306a36Sopenharmony_ci	release_resource(&pcic->mem_resource[0]);
21762306a36Sopenharmony_ci	return pcic;
21862306a36Sopenharmony_ci release_and_exit:
21962306a36Sopenharmony_ci	release_resource(&pcic->mem_resource[0]);
22062306a36Sopenharmony_ci free_and_exit:
22162306a36Sopenharmony_ci	kfree(new);
22262306a36Sopenharmony_ci	pr_err("PCI: Failed to allocate resources.\n");
22362306a36Sopenharmony_ci	return NULL;
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic int __init
22762306a36Sopenharmony_citxx9_arch_pci_init(void)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	PCIBIOS_MIN_IO = 0x8000;	/* reserve legacy I/O space */
23062306a36Sopenharmony_ci	return 0;
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ciarch_initcall(txx9_arch_pci_init);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci/* IRQ/IDSEL mapping */
23562306a36Sopenharmony_ciint txx9_pci_option =
23662306a36Sopenharmony_ci#ifdef CONFIG_PICMG_PCI_BACKPLANE_DEFAULT
23762306a36Sopenharmony_ci	TXX9_PCI_OPT_PICMG |
23862306a36Sopenharmony_ci#endif
23962306a36Sopenharmony_ci	TXX9_PCI_OPT_CLK_AUTO;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cienum txx9_pci_err_action txx9_pci_err_action = TXX9_PCI_ERR_REPORT;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci#ifdef CONFIG_TOSHIBA_FPCIB0
24462306a36Sopenharmony_cistatic irqreturn_t i8259_interrupt(int irq, void *dev_id)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	int isairq;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	isairq = i8259_irq();
24962306a36Sopenharmony_ci	if (unlikely(isairq <= I8259A_IRQ_BASE))
25062306a36Sopenharmony_ci		return IRQ_NONE;
25162306a36Sopenharmony_ci	generic_handle_irq(isairq);
25262306a36Sopenharmony_ci	return IRQ_HANDLED;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic int txx9_i8259_irq_setup(int irq)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	int err;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	init_i8259_irqs();
26062306a36Sopenharmony_ci	err = request_irq(irq, &i8259_interrupt, IRQF_SHARED,
26162306a36Sopenharmony_ci			  "cascade(i8259)", (void *)(long)irq);
26262306a36Sopenharmony_ci	if (!err)
26362306a36Sopenharmony_ci		pr_info("PCI-ISA bridge PIC (irq %d)\n", irq);
26462306a36Sopenharmony_ci	return err;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic void __ref quirk_slc90e66_bridge(struct pci_dev *dev)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	int irq;	/* PCI/ISA Bridge interrupt */
27062306a36Sopenharmony_ci	u8 reg_64;
27162306a36Sopenharmony_ci	u32 reg_b0;
27262306a36Sopenharmony_ci	u8 reg_e1;
27362306a36Sopenharmony_ci	irq = pcibios_map_irq(dev, PCI_SLOT(dev->devfn), 1); /* INTA */
27462306a36Sopenharmony_ci	if (!irq)
27562306a36Sopenharmony_ci		return;
27662306a36Sopenharmony_ci	txx9_i8259_irq_setup(irq);
27762306a36Sopenharmony_ci	pci_read_config_byte(dev, 0x64, &reg_64);
27862306a36Sopenharmony_ci	pci_read_config_dword(dev, 0xb0, &reg_b0);
27962306a36Sopenharmony_ci	pci_read_config_byte(dev, 0xe1, &reg_e1);
28062306a36Sopenharmony_ci	/* serial irq control */
28162306a36Sopenharmony_ci	reg_64 = 0xd0;
28262306a36Sopenharmony_ci	/* serial irq pin */
28362306a36Sopenharmony_ci	reg_b0 |= 0x00010000;
28462306a36Sopenharmony_ci	/* ide irq on isa14 */
28562306a36Sopenharmony_ci	reg_e1 &= 0xf0;
28662306a36Sopenharmony_ci	reg_e1 |= 0x0d;
28762306a36Sopenharmony_ci	pci_write_config_byte(dev, 0x64, reg_64);
28862306a36Sopenharmony_ci	pci_write_config_dword(dev, 0xb0, reg_b0);
28962306a36Sopenharmony_ci	pci_write_config_byte(dev, 0xe1, reg_e1);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	smsc_fdc37m81x_init(0x3f0);
29262306a36Sopenharmony_ci	smsc_fdc37m81x_config_beg();
29362306a36Sopenharmony_ci	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM,
29462306a36Sopenharmony_ci				  SMSC_FDC37M81X_KBD);
29562306a36Sopenharmony_ci	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1);
29662306a36Sopenharmony_ci	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12);
29762306a36Sopenharmony_ci	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE,
29862306a36Sopenharmony_ci				  1);
29962306a36Sopenharmony_ci	smsc_fdc37m81x_config_end();
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic void quirk_slc90e66_ide(struct pci_dev *dev)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	unsigned char dat;
30562306a36Sopenharmony_ci	int regs[2] = {0x41, 0x43};
30662306a36Sopenharmony_ci	int i;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	/* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
30962306a36Sopenharmony_ci	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14);
31062306a36Sopenharmony_ci	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &dat);
31162306a36Sopenharmony_ci	pr_info("PCI: %s: IRQ %02x", pci_name(dev), dat);
31262306a36Sopenharmony_ci	/* enable SMSC SLC90E66 IDE */
31362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(regs); i++) {
31462306a36Sopenharmony_ci		pci_read_config_byte(dev, regs[i], &dat);
31562306a36Sopenharmony_ci		pci_write_config_byte(dev, regs[i], dat | 0x80);
31662306a36Sopenharmony_ci		pci_read_config_byte(dev, regs[i], &dat);
31762306a36Sopenharmony_ci		pr_cont(" IDETIM%d %02x", i, dat);
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci	pci_read_config_byte(dev, 0x5c, &dat);
32062306a36Sopenharmony_ci	/*
32162306a36Sopenharmony_ci	 * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
32262306a36Sopenharmony_ci	 *
32362306a36Sopenharmony_ci	 * This line of code is intended to provide the user with a work
32462306a36Sopenharmony_ci	 * around solution to the anomalies cited in SMSC's anomaly sheet
32562306a36Sopenharmony_ci	 * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"".
32662306a36Sopenharmony_ci	 *
32762306a36Sopenharmony_ci	 * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
32862306a36Sopenharmony_ci	 */
32962306a36Sopenharmony_ci	dat |= 0x01;
33062306a36Sopenharmony_ci	pci_write_config_byte(dev, 0x5c, dat);
33162306a36Sopenharmony_ci	pci_read_config_byte(dev, 0x5c, &dat);
33262306a36Sopenharmony_ci	pr_cont(" REG5C %02x\n", dat);
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci#endif /* CONFIG_TOSHIBA_FPCIB0 */
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic void tc35815_fixup(struct pci_dev *dev)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	/* This device may have PM registers but not they are not supported. */
33962306a36Sopenharmony_ci	if (dev->pm_cap) {
34062306a36Sopenharmony_ci		dev_info(&dev->dev, "PM disabled\n");
34162306a36Sopenharmony_ci		dev->pm_cap = 0;
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic void final_fixup(struct pci_dev *dev)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	unsigned long timeout;
34862306a36Sopenharmony_ci	unsigned char bist;
34962306a36Sopenharmony_ci	int ret;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/* Do build-in self test */
35262306a36Sopenharmony_ci	ret = pci_read_config_byte(dev, PCI_BIST, &bist);
35362306a36Sopenharmony_ci	if ((ret != PCIBIOS_SUCCESSFUL) || !(bist & PCI_BIST_CAPABLE))
35462306a36Sopenharmony_ci		return;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	pci_set_power_state(dev, PCI_D0);
35762306a36Sopenharmony_ci	pr_info("PCI: %s BIST...", pci_name(dev));
35862306a36Sopenharmony_ci	pci_write_config_byte(dev, PCI_BIST, PCI_BIST_START);
35962306a36Sopenharmony_ci	timeout = jiffies + HZ * 2;	/* timeout after 2 sec */
36062306a36Sopenharmony_ci	do {
36162306a36Sopenharmony_ci		pci_read_config_byte(dev, PCI_BIST, &bist);
36262306a36Sopenharmony_ci		if (time_after(jiffies, timeout))
36362306a36Sopenharmony_ci			break;
36462306a36Sopenharmony_ci	} while (bist & PCI_BIST_START);
36562306a36Sopenharmony_ci	if (bist & (PCI_BIST_CODE_MASK | PCI_BIST_START))
36662306a36Sopenharmony_ci		pr_cont("failed. (0x%x)\n", bist);
36762306a36Sopenharmony_ci	else
36862306a36Sopenharmony_ci		pr_cont("OK.\n");
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci#ifdef CONFIG_TOSHIBA_FPCIB0
37262306a36Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460
37362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_0,
37462306a36Sopenharmony_ci	quirk_slc90e66_bridge);
37562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1,
37662306a36Sopenharmony_ci	quirk_slc90e66_ide);
37762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1,
37862306a36Sopenharmony_ci	quirk_slc90e66_ide);
37962306a36Sopenharmony_ci#endif
38062306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2,
38162306a36Sopenharmony_ci			PCI_DEVICE_ID_TOSHIBA_TC35815_NWU, tc35815_fixup);
38262306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2,
38362306a36Sopenharmony_ci			PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939, tc35815_fixup);
38462306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, final_fixup);
38562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, final_fixup);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ciint pcibios_plat_dev_init(struct pci_dev *dev)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	return 0;
39062306a36Sopenharmony_ci}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic int (*txx9_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
39362306a36Sopenharmony_ciint pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	return txx9_pci_map_irq(dev, slot, pin);
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cichar * (*txx9_board_pcibios_setup)(char *str) __initdata;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cichar *__init txx9_pcibios_setup(char *str)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str))
40362306a36Sopenharmony_ci		return NULL;
40462306a36Sopenharmony_ci	if (!strcmp(str, "picmg")) {
40562306a36Sopenharmony_ci		/* PICMG compliant backplane (TOSHIBA JMB-PICMG-ATX
40662306a36Sopenharmony_ci		   (5V or 3.3V), JMB-PICMG-L2 (5V only), etc.) */
40762306a36Sopenharmony_ci		txx9_pci_option |= TXX9_PCI_OPT_PICMG;
40862306a36Sopenharmony_ci		return NULL;
40962306a36Sopenharmony_ci	} else if (!strcmp(str, "nopicmg")) {
41062306a36Sopenharmony_ci		/* non-PICMG compliant backplane (TOSHIBA
41162306a36Sopenharmony_ci		   RBHBK4100,RBHBK4200, Interface PCM-PCM05, etc.) */
41262306a36Sopenharmony_ci		txx9_pci_option &= ~TXX9_PCI_OPT_PICMG;
41362306a36Sopenharmony_ci		return NULL;
41462306a36Sopenharmony_ci	} else if (!strncmp(str, "clk=", 4)) {
41562306a36Sopenharmony_ci		char *val = str + 4;
41662306a36Sopenharmony_ci		txx9_pci_option &= ~TXX9_PCI_OPT_CLK_MASK;
41762306a36Sopenharmony_ci		if (strcmp(val, "33") == 0)
41862306a36Sopenharmony_ci			txx9_pci_option |= TXX9_PCI_OPT_CLK_33;
41962306a36Sopenharmony_ci		else if (strcmp(val, "66") == 0)
42062306a36Sopenharmony_ci			txx9_pci_option |= TXX9_PCI_OPT_CLK_66;
42162306a36Sopenharmony_ci		else /* "auto" */
42262306a36Sopenharmony_ci			txx9_pci_option |= TXX9_PCI_OPT_CLK_AUTO;
42362306a36Sopenharmony_ci		return NULL;
42462306a36Sopenharmony_ci	} else if (!strncmp(str, "err=", 4)) {
42562306a36Sopenharmony_ci		if (!strcmp(str + 4, "panic"))
42662306a36Sopenharmony_ci			txx9_pci_err_action = TXX9_PCI_ERR_PANIC;
42762306a36Sopenharmony_ci		else if (!strcmp(str + 4, "ignore"))
42862306a36Sopenharmony_ci			txx9_pci_err_action = TXX9_PCI_ERR_IGNORE;
42962306a36Sopenharmony_ci		return NULL;
43062306a36Sopenharmony_ci	}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	txx9_pci_map_irq = txx9_board_vec->pci_map_irq;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return str;
43562306a36Sopenharmony_ci}
436