/*
 * PCI bus setup for Marvell mv64360/mv64460 host bridges (Discovery)
 *
 * Author: Dale Farnsworth <dale@farnsworth.org>
 *
 * 2007 (c) MontaVista, Software, Inc.  This file is licensed under
 * the terms of the GNU General Public License version 2.  This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 */

#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>

#include <asm/prom.h>
#include <asm/pci-bridge.h>

#define PCI_HEADER_TYPE_INVALID		0x7f	/* Invalid PCI header type */

#ifdef CONFIG_SYSFS
/* 32-bit hex or dec stringified number + '\n' */
#define MV64X60_VAL_LEN_MAX		11
#define MV64X60_PCICFG_CPCI_HOTSWAP	0x68

static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, char *buf, loff_t off,
				   size_t count)
{
	struct pci_dev *phb;
	u32 v;

	if (off > 0)
		return 0;
	if (count < MV64X60_VAL_LEN_MAX)
		return -EINVAL;

	phb = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
	if (!phb)
		return -ENODEV;
	pci_read_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, &v);
	pci_dev_put(phb);

	return sprintf(buf, "0x%08x\n", v);
}

static ssize_t mv64x60_hs_reg_write(struct kobject *kobj, char *buf, loff_t off,
				    size_t count)
{
	struct pci_dev *phb;
	u32 v;

	if (off > 0)
		return 0;
	if (count <= 0)
		return -EINVAL;

	if (sscanf(buf, "%i", &v) != 1)
		return -EINVAL;

	phb = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
	if (!phb)
		return -ENODEV;
	pci_write_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, v);
	pci_dev_put(phb);

	return count;
}

static struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */
	.attr = {
		.name = "hs_reg",
		.mode = S_IRUGO | S_IWUSR,
		.owner = THIS_MODULE,
	},
	.size  = MV64X60_VAL_LEN_MAX,
	.read  = mv64x60_hs_reg_read,
	.write = mv64x60_hs_reg_write,
};

static int __init mv64x60_sysfs_init(void)
{
	struct device_node *np;
	struct platform_device *pdev;
	const unsigned int *prop;

	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60");
	if (!np)
		return 0;

	prop = of_get_property(np, "hs_reg_valid", NULL);
	of_node_put(np);

	pdev = platform_device_register_simple("marvell,mv64x60", 0, NULL, 0);
	if (IS_ERR(pdev))
		return PTR_ERR(pdev);

	return sysfs_create_bin_file(&pdev->dev.kobj, &mv64x60_hs_reg_attr);
}

subsys_initcall(mv64x60_sysfs_init);

#endif /* CONFIG_SYSFS */

static void __init mv64x60_pci_fixup_early(struct pci_dev *dev)
{
	/*
	 * Set the host bridge hdr_type to an invalid value so that
	 * pci_setup_device() will ignore the host bridge.
	 */
	dev->hdr_type = PCI_HEADER_TYPE_INVALID;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360,
			mv64x60_pci_fixup_early);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64460,
			mv64x60_pci_fixup_early);

static int __init mv64x60_add_bridge(struct device_node *dev)
{
	int len;
	struct pci_controller *hose;
	struct resource rsrc;
	const int *bus_range;
	int primary;

	memset(&rsrc, 0, sizeof(rsrc));

	/* Fetch host bridge registers address */
	if (of_address_to_resource(dev, 0, &rsrc)) {
		printk(KERN_ERR "No PCI reg property in device tree\n");
		return -ENODEV;
	}

	/* Get bus range if any */
	bus_range = of_get_property(dev, "bus-range", &len);
	if (bus_range == NULL || len < 2 * sizeof(int))
		printk(KERN_WARNING "Can't get bus-range for %s, assume"
		       " bus 0\n", dev->full_name);

	hose = pcibios_alloc_controller();
	if (!hose)
		return -ENOMEM;

	hose->arch_data = dev;
	hose->set_cfg_type = 1;

	hose->first_busno = bus_range ? bus_range[0] : 0;
	hose->last_busno = bus_range ? bus_range[1] : 0xff;

	setup_indirect_pci(hose, rsrc.start, rsrc.start + 4);
	hose->bus_offset = hose->first_busno;

	printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. "
	       "Firmware bus number: %d->%d\n",
	       (unsigned long long)rsrc.start, hose->first_busno,
	       hose->last_busno);

	/* Interpret the "ranges" property */
	/* This also maps the I/O region and sets isa_io/mem_base */
	primary = (hose->first_busno == 0);
	pci_process_bridge_OF_ranges(hose, dev, primary);

	return 0;
}

void __init mv64x60_pci_init(void)
{
	struct device_node *np = NULL;

	while ((np = of_find_compatible_node(np, "pci", "marvell,mv64x60-pci")))
		mv64x60_add_bridge(np);
}
