/*
 * 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,
				   struct bin_attribute *attr, 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,
				    struct bin_attribute *attr, 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(dev);
	if (!hose)
		return -ENOMEM;

	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, 0);
	hose->self_busno = 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);
}
