/*
 * 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.
 *
 * Copyright (C) 1997, 1998 Ralf Baechle
 * Copyright (C) 1999 SuSE GmbH
 * Copyright (C) 1999-2001 Hewlett-Packard Company
 * Copyright (C) 1999-2001 Grant Grundler
 */
#include <linux/eisa.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/types.h>

#include <asm/io.h>
#include <asm/superio.h>

#define DEBUG_RESOURCES 0
#define DEBUG_CONFIG 0

#if DEBUG_CONFIG
# define DBGC(x...)	printk(KERN_DEBUG x)
#else
# define DBGC(x...)
#endif


#if DEBUG_RESOURCES
#define DBG_RES(x...)	printk(KERN_DEBUG x)
#else
#define DBG_RES(x...)
#endif

struct pci_port_ops *pci_port __ro_after_init;
struct pci_bios_ops *pci_bios __ro_after_init;

static int pci_hba_count __ro_after_init;

/* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data.  */
#define PCI_HBA_MAX 32
static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __ro_after_init;


/********************************************************************
**
** I/O port space support
**
*********************************************************************/

/* EISA port numbers and PCI port numbers share the same interface.  Some
 * machines have both EISA and PCI adapters installed.  Rather than turn
 * pci_port into an array, we reserve bus 0 for EISA and call the EISA
 * routines if the access is to a port on bus 0.  We don't want to fix
 * EISA and ISA drivers which assume port space is <= 0xffff.
 */

#ifdef CONFIG_EISA
#define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr)
#define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr)
#else
#define EISA_IN(size)
#define EISA_OUT(size)
#endif

#define PCI_PORT_IN(type, size) \
u##size in##type (int addr) \
{ \
	int b = PCI_PORT_HBA(addr); \
	EISA_IN(size); \
	if (!parisc_pci_hba[b]) return (u##size) -1; \
	return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
} \
EXPORT_SYMBOL(in##type);

PCI_PORT_IN(b,  8)
PCI_PORT_IN(w, 16)
PCI_PORT_IN(l, 32)


#define PCI_PORT_OUT(type, size) \
void out##type (u##size d, int addr) \
{ \
	int b = PCI_PORT_HBA(addr); \
	EISA_OUT(size); \
	if (!parisc_pci_hba[b]) return; \
	pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
} \
EXPORT_SYMBOL(out##type);

PCI_PORT_OUT(b,  8)
PCI_PORT_OUT(w, 16)
PCI_PORT_OUT(l, 32)



/*
 * BIOS32 replacement.
 */
static int __init pcibios_init(void)
{
	if (!pci_bios)
		return -1;

	if (pci_bios->init) {
		pci_bios->init();
	} else {
		printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
	}

	/* Set the CLS for PCI as early as possible. */
	pci_cache_line_size = pci_dfl_cache_line_size;

	return 0;
}


/* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */
void pcibios_fixup_bus(struct pci_bus *bus)
{
	if (pci_bios->fixup_bus) {
		pci_bios->fixup_bus(bus);
	} else {
		printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
	}
}


/*
 * Called by pci_set_master() - a driver interface.
 *
 * Legacy PDC guarantees to set:
 *	Map Memory BAR's into PA IO space.
 *	Map Expansion ROM BAR into one common PA IO space per bus.
 *	Map IO BAR's into PCI IO space.
 *	Command (see below)
 *	Cache Line Size
 *	Latency Timer
 *	Interrupt Line
 *	PPB: secondary latency timer, io/mmio base/limit,
 *		bus numbers, bridge control
 *
 */
void pcibios_set_master(struct pci_dev *dev)
{
	u8 lat;

	/* If someone already mucked with this, don't touch it. */
	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
	if (lat >= 16) return;

	/*
	** HP generally has fewer devices on the bus than other architectures.
	** upper byte is PCI_LATENCY_TIMER.
	*/
	pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
			      (0x80 << 8) | pci_cache_line_size);
}

/*
 * pcibios_init_bridge() initializes cache line and default latency
 * for pci controllers and pci-pci bridges
 */
void __ref pcibios_init_bridge(struct pci_dev *dev)
{
	unsigned short bridge_ctl, bridge_ctl_new;

	/* We deal only with pci controllers and pci-pci bridges. */
	if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
		return;

	/* PCI-PCI bridge - set the cache line and default latency
	 * (32) for primary and secondary buses.
	 */
	pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);

	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl);

	bridge_ctl_new = bridge_ctl | PCI_BRIDGE_CTL_PARITY |
		PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_MASTER_ABORT;
	dev_info(&dev->dev, "Changing bridge control from 0x%08x to 0x%08x\n",
		bridge_ctl, bridge_ctl_new);

	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl_new);
}

/*
 * pcibios align resources() is called every time generic PCI code
 * wants to generate a new address. The process of looking for
 * an available address, each candidate is first "aligned" and
 * then checked if the resource is available until a match is found.
 *
 * Since we are just checking candidates, don't use any fields other
 * than res->start.
 */
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
				resource_size_t size, resource_size_t alignment)
{
	resource_size_t mask, align, start = res->start;

	DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n",
		pci_name(((struct pci_dev *) data)),
		res->parent, res->start, res->end,
		(int) res->flags, size, alignment);

	/* If it's not IO, then it's gotta be MEM */
	align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;

	/* Align to largest of MIN or input size */
	mask = max(alignment, align) - 1;
	start += mask;
	start &= ~mask;

	return start;
}

/*
 * A driver is enabling the device.  We make sure that all the appropriate
 * bits are set to allow the device to operate as the driver is expecting.
 * We enable the port IO and memory IO bits if the device has any BARs of
 * that type, and we enable the PERR and SERR bits unconditionally.
 * Drivers that do not need parity (eg graphics and possibly networking)
 * can clear these bits if they want.
 */
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
	int err;
	u16 cmd, old_cmd;

	err = pci_enable_resources(dev, mask);
	if (err < 0)
		return err;

	pci_read_config_word(dev, PCI_COMMAND, &cmd);
	old_cmd = cmd;

	cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);

#if 0
	/* If bridge/bus controller has FBB enabled, child must too. */
	if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
		cmd |= PCI_COMMAND_FAST_BACK;
#endif

	if (cmd != old_cmd) {
		dev_info(&dev->dev, "enabling SERR and PARITY (%04x -> %04x)\n",
			old_cmd, cmd);
		pci_write_config_word(dev, PCI_COMMAND, cmd);
	}
	return 0;
}


/* PA-RISC specific */
void pcibios_register_hba(struct pci_hba_data *hba)
{
	if (pci_hba_count >= PCI_HBA_MAX) {
		printk(KERN_ERR "PCI: Too many Host Bus Adapters\n");
		return;
	}

	parisc_pci_hba[pci_hba_count] = hba;
	hba->hba_num = pci_hba_count++;
}

subsys_initcall(pcibios_init);
