/*
 * Generic platform device PATA driver
 *
 * Copyright (C) 2006  Paul Mundt
 *
 * Based on pata_pcmcia:
 *
 *   Copyright 2005-2006 Red Hat Inc <alan@redhat.com>, all rights reserved.
 *
 * 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.
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <scsi/scsi_host.h>
#include <linux/ata.h>
#include <linux/libata.h>
#include <linux/platform_device.h>
#include <linux/pata_platform.h>

#define DRV_NAME "pata_platform"
#define DRV_VERSION "0.1.2"

static int pio_mask = 1;

/*
 * Provide our own set_mode() as we don't want to change anything that has
 * already been configured..
 */
static void pata_platform_set_mode(struct ata_port *ap)
{
	int i;

	for (i = 0; i < ATA_MAX_DEVICES; i++) {
		struct ata_device *dev = &ap->device[i];

		if (ata_dev_enabled(dev)) {
			/* We don't really care */
			dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
			dev->xfer_shift = ATA_SHIFT_PIO;
			dev->flags |= ATA_DFLAG_PIO;
		}
	}
}

static void pata_platform_host_stop(struct ata_host *host)
{
	int i;

	/*
	 * Unmap the bases for MMIO
	 */
	for (i = 0; i < host->n_ports; i++) {
		struct ata_port *ap = host->ports[i];

		if (ap->flags & ATA_FLAG_MMIO) {
			iounmap((void __iomem *)ap->ioaddr.ctl_addr);
			iounmap((void __iomem *)ap->ioaddr.cmd_addr);
		}
	}
}

static struct scsi_host_template pata_platform_sht = {
	.module			= THIS_MODULE,
	.name			= DRV_NAME,
	.ioctl			= ata_scsi_ioctl,
	.queuecommand		= ata_scsi_queuecmd,
	.can_queue		= ATA_DEF_QUEUE,
	.this_id		= ATA_SHT_THIS_ID,
	.sg_tablesize		= LIBATA_MAX_PRD,
	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
	.emulated		= ATA_SHT_EMULATED,
	.use_clustering		= ATA_SHT_USE_CLUSTERING,
	.proc_name		= DRV_NAME,
	.dma_boundary		= ATA_DMA_BOUNDARY,
	.slave_configure	= ata_scsi_slave_config,
	.slave_destroy		= ata_scsi_slave_destroy,
	.bios_param		= ata_std_bios_param,
};

static struct ata_port_operations pata_platform_port_ops = {
	.set_mode		= pata_platform_set_mode,

	.port_disable		= ata_port_disable,
	.tf_load		= ata_tf_load,
	.tf_read		= ata_tf_read,
	.check_status		= ata_check_status,
	.exec_command		= ata_exec_command,
	.dev_select		= ata_std_dev_select,

	.freeze			= ata_bmdma_freeze,
	.thaw			= ata_bmdma_thaw,
	.error_handler		= ata_bmdma_error_handler,
	.post_internal_cmd	= ata_bmdma_post_internal_cmd,

	.qc_prep		= ata_qc_prep,
	.qc_issue		= ata_qc_issue_prot,

	.data_xfer		= ata_pio_data_xfer_noirq,

	.irq_handler		= ata_interrupt,
	.irq_clear		= ata_bmdma_irq_clear,

	.port_start		= ata_port_start,
	.port_stop		= ata_port_stop,
	.host_stop		= pata_platform_host_stop
};

static void pata_platform_setup_port(struct ata_ioports *ioaddr,
				     struct pata_platform_info *info)
{
	unsigned int shift = 0;

	/* Fixup the port shift for platforms that need it */
	if (info && info->ioport_shift)
		shift = info->ioport_shift;

	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << shift);
	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << shift);
	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
	ioaddr->nsect_addr	= ioaddr->cmd_addr + (ATA_REG_NSECT   << shift);
	ioaddr->lbal_addr	= ioaddr->cmd_addr + (ATA_REG_LBAL    << shift);
	ioaddr->lbam_addr	= ioaddr->cmd_addr + (ATA_REG_LBAM    << shift);
	ioaddr->lbah_addr	= ioaddr->cmd_addr + (ATA_REG_LBAH    << shift);
	ioaddr->device_addr	= ioaddr->cmd_addr + (ATA_REG_DEVICE  << shift);
	ioaddr->status_addr	= ioaddr->cmd_addr + (ATA_REG_STATUS  << shift);
	ioaddr->command_addr	= ioaddr->cmd_addr + (ATA_REG_CMD     << shift);
}

/**
 *	pata_platform_probe		-	attach a platform interface
 *	@pdev: platform device
 *
 *	Register a platform bus IDE interface. Such interfaces are PIO and we
 *	assume do not support IRQ sharing.
 *
 *	Platform devices are expected to contain 3 resources per port:
 *
 *		- I/O Base (IORESOURCE_IO or IORESOURCE_MEM)
 *		- CTL Base (IORESOURCE_IO or IORESOURCE_MEM)
 *		- IRQ	   (IORESOURCE_IRQ)
 *
 *	If the base resources are both mem types, the ioremap() is handled
 *	here. For IORESOURCE_IO, it's assumed that there's no remapping
 *	necessary.
 */
static int __devinit pata_platform_probe(struct platform_device *pdev)
{
	struct resource *io_res, *ctl_res;
	struct ata_probe_ent ae;
	unsigned int mmio;
	int ret;

	/*
	 * Simple resource validation ..
	 */
	if (unlikely(pdev->num_resources != 3)) {
		dev_err(&pdev->dev, "invalid number of resources\n");
		return -EINVAL;
	}

	/*
	 * Get the I/O base first
	 */
	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
	if (io_res == NULL) {
		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		if (unlikely(io_res == NULL))
			return -EINVAL;
	}

	/*
	 * Then the CTL base
	 */
	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
	if (ctl_res == NULL) {
		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
		if (unlikely(ctl_res == NULL))
			return -EINVAL;
	}

	/*
	 * Check for MMIO
	 */
	mmio = (( io_res->flags == IORESOURCE_MEM) &&
		(ctl_res->flags == IORESOURCE_MEM));

	/*
	 * Now that that's out of the way, wire up the port..
	 */
	memset(&ae, 0, sizeof(struct ata_probe_ent));
	INIT_LIST_HEAD(&ae.node);
	ae.dev = &pdev->dev;
	ae.port_ops = &pata_platform_port_ops;
	ae.sht = &pata_platform_sht;
	ae.n_ports = 1;
	ae.pio_mask = pio_mask;
	ae.irq = platform_get_irq(pdev, 0);
	ae.irq_flags = 0;
	ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;

	/*
	 * Handle the MMIO case
	 */
	if (mmio) {
		ae.port_flags |= ATA_FLAG_MMIO;

		ae.port[0].cmd_addr = (unsigned long)ioremap(io_res->start,
				io_res->end - io_res->start + 1);
		if (unlikely(!ae.port[0].cmd_addr)) {
			dev_err(&pdev->dev, "failed to remap IO base\n");
			return -ENXIO;
		}

		ae.port[0].ctl_addr = (unsigned long)ioremap(ctl_res->start,
				ctl_res->end - ctl_res->start + 1);
		if (unlikely(!ae.port[0].ctl_addr)) {
			dev_err(&pdev->dev, "failed to remap CTL base\n");
			ret = -ENXIO;
			goto bad_remap;
		}
	} else {
		ae.port[0].cmd_addr = io_res->start;
		ae.port[0].ctl_addr = ctl_res->start;
	}

	ae.port[0].altstatus_addr = ae.port[0].ctl_addr;

	pata_platform_setup_port(&ae.port[0], pdev->dev.platform_data);

	if (unlikely(ata_device_add(&ae) == 0)) {
		ret = -ENODEV;
		goto add_failed;
	}

	return 0;

add_failed:
	if (ae.port[0].ctl_addr && mmio)
		iounmap((void __iomem *)ae.port[0].ctl_addr);
bad_remap:
	if (ae.port[0].cmd_addr && mmio)
		iounmap((void __iomem *)ae.port[0].cmd_addr);

	return ret;
}

/**
 *	pata_platform_remove	-	unplug a platform interface
 *	@pdev: platform device
 *
 *	A platform bus ATA device has been unplugged. Perform the needed
 *	cleanup. Also called on module unload for any active devices.
 */
static int __devexit pata_platform_remove(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct ata_host *host = dev_get_drvdata(dev);

	ata_host_remove(host);
	dev_set_drvdata(dev, NULL);

	return 0;
}

static struct platform_driver pata_platform_driver = {
	.probe		= pata_platform_probe,
	.remove		= __devexit_p(pata_platform_remove),
	.driver = {
		.name		= DRV_NAME,
		.owner		= THIS_MODULE,
	},
};

static int __init pata_platform_init(void)
{
	return platform_driver_register(&pata_platform_driver);
}

static void __exit pata_platform_exit(void)
{
	platform_driver_unregister(&pata_platform_driver);
}
module_init(pata_platform_init);
module_exit(pata_platform_exit);

module_param(pio_mask, int, 0);

MODULE_AUTHOR("Paul Mundt");
MODULE_DESCRIPTION("low-level driver for platform device ATA");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
