/*
 *
 *  Copyright (C) 2007 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/clk.h>

#include <mach/hardware.h>
#include <mach/comcerto-2000/clk-rst.h>

#include "pfe_mod.h"

/**
 * pfe_platform_probe -
 *
 *
 */
static int pfe_platform_probe(struct platform_device *pdev)
{
	struct resource *r;
	int rc;
	struct clk *clk_axi;

	printk(KERN_INFO "%s\n", __func__);

	pfe = kzalloc(sizeof(struct pfe), GFP_KERNEL);
	if (!pfe) {
		rc = -ENOMEM;
		goto err_alloc;
	}

	platform_set_drvdata(pdev, pfe);

	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ddr");
	if (!r) {
		printk(KERN_INFO "platform_get_resource_byname(ddr) failed\n");
		rc = -ENXIO;
		goto err_ddr;
	}
	
	pfe->ddr_phys_baseaddr = r->start;
	pfe->ddr_size = resource_size(r);

	pfe->ddr_baseaddr = ioremap(r->start, resource_size(r));
	pr_err("pfe->ddr_baseaddr = %p size %u\n", pfe->ddr_baseaddr, resource_size(r));
	if (!pfe->ddr_baseaddr) {
		printk(KERN_INFO "ioremap(%p %08x) ddr failed\n", (void*) r->start, resource_size(r));
		rc = -ENOMEM;
		goto err_ddr;
	}
	
	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "axi");
	if (!r) {
		printk(KERN_INFO "platform_get_resource_byname(axi) failed\n");
		rc = -ENXIO;
		goto err_axi;
	}

	pfe->cbus_baseaddr = ioremap(r->start, resource_size(r));
	pr_err("cbus start %08x size %08x\n", r->start, resource_size(r));
	if (!pfe->cbus_baseaddr) {
		printk(KERN_INFO "ioremap() axi failed\n");
		rc = -ENOMEM;
		goto err_axi;
	}

	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb");
	if (!r) {
		printk(KERN_INFO "platform_get_resource_byname(apb) failed\n");
		rc = -ENXIO;
		goto err_apb;
	}

	pfe->apb_baseaddr = ioremap(r->start, resource_size(r));
	if (!pfe->apb_baseaddr) {
		printk(KERN_INFO "ioremap() apb failed\n");
		rc = -ENOMEM;
		goto err_apb;
	}

	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iram");
	if (!r) {
		printk(KERN_INFO "platform_get_resource_byname(iram) failed\n");
		rc = -ENXIO;
		goto err_iram;
	}

	pfe->iram_phys_baseaddr = r->start;
	pfe->iram_baseaddr = ioremap(r->start, resource_size(r));
	if (!pfe->iram_baseaddr) {
		printk(KERN_INFO "ioremap() iram failed\n");
		rc = -ENOMEM;
		goto err_iram;
	}

        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipsec");
        if (!r) {
                printk(KERN_INFO "platform_get_resource_byname(ipsec) failed\n");
                rc = -ENXIO;
                goto err_ipsec;
        }

        pfe->ipsec_phys_baseaddr = r->start;
	/* Just map only initial 1MB , as its enough to access espah engine
	*/
        //pfe->ipsec_baseaddr = ioremap(r->start, resource_size(r));
        pfe->ipsec_baseaddr = ioremap(r->start, 1*1024*1024);
        if (!pfe->ipsec_baseaddr) {
                printk(KERN_INFO "ioremap() ipsec failed\n");
                rc = -ENOMEM;
                goto err_ipsec;
        }

        printk(KERN_INFO "ipsec: baseaddr :%x --- %x\n",  (u32)pfe->ipsec_phys_baseaddr,  (u32)pfe->ipsec_baseaddr);

	pfe->dev = &pdev->dev;

	/* FIXME this needs to be done at the BSP level with proper locking */
	writel(readl(APB_VADDR(AXI_RESET_1)) | (1 << 3), APB_VADDR(AXI_RESET_1));
	mdelay(1);
	writel(readl(APB_VADDR(AXI_RESET_1)) & ~(1 << 3), APB_VADDR(AXI_RESET_1));

	/* Get the system clock */
	clk_axi = clk_get(NULL,"axi");
	if (IS_ERR(clk_axi)) {
		printk(KERN_INFO "clk_get call failed\n");
		rc = -ENXIO;
		goto err_clk;
	}

	pfe->ctrl.clk_axi = clk_axi;
	pfe->ctrl.sys_clk = clk_get_rate(clk_axi) / 1000;  // save sys_clk value as KHz

	rc = pfe_probe(pfe);
	if (rc < 0)
		goto err_probe;

	return 0;

err_probe:
	clk_put(clk_axi);
err_clk:
        iounmap(pfe->ipsec_baseaddr);
err_ipsec:
	iounmap(pfe->iram_baseaddr);
err_iram:
	iounmap(pfe->apb_baseaddr);

err_apb:
	iounmap(pfe->cbus_baseaddr);

err_axi:
	iounmap(pfe->ddr_baseaddr);

err_ddr:
	platform_set_drvdata(pdev, NULL);

	kfree(pfe);

err_alloc:
	return rc;
}


/**
 * pfe_platform_remove -
 *
 *
 */
static int pfe_platform_remove(struct platform_device *pdev)
{
	struct pfe *pfe = platform_get_drvdata(pdev);
	int rc;
	
	printk(KERN_INFO "%s\n", __func__);

	rc = pfe_remove(pfe);

	/* FIXME this needs to be done at the BSP level with proper locking */
	writel(readl(APB_VADDR(AXI_RESET_1)) | (1 << 3), APB_VADDR(AXI_RESET_1));

	clk_put(pfe->ctrl.clk_axi);
	iounmap(pfe->ipsec_baseaddr);
	iounmap(pfe->iram_baseaddr);
	iounmap(pfe->apb_baseaddr);
	iounmap(pfe->cbus_baseaddr);
	iounmap(pfe->ddr_baseaddr);

	platform_set_drvdata(pdev, NULL);

	kfree(pfe);

	return rc;
}

#ifdef CONFIG_PM

#ifdef CONFIG_PM_SLEEP
static int pfe_platform_suspend(struct device *dev)
{
	struct pfe *pfe = platform_get_drvdata(to_platform_device(dev));
	struct net_device *netdev;
	int i;

	printk(KERN_INFO "%s\n", __func__);

	pfe->wake = 0;

	for (i = 0; i < (NUM_GEMAC_SUPPORT - 1); i++ ) {
		netdev = pfe->eth.eth_priv[i]->dev;

		netif_device_detach(netdev);

		if (netif_running(netdev))
			if(pfe_eth_suspend(netdev))
				pfe->wake =1;
	}

	/* Shutdown PFE only if we're not waking up the system */
	if (!pfe->wake) {
		pfe_ctrl_suspend(&pfe->ctrl);
		pfe_hif_exit(pfe);
		pfe_hif_lib_exit(pfe);

		class_disable();
		tmu_disable(0xf);
#if !defined(CONFIG_UTIL_DISABLED)
		util_disable();
#endif
		pfe_hw_exit(pfe);
		c2000_block_reset(COMPONENT_PFE_SYS, 1);
		clk_disable(pfe->hfe_clock);
	}

	return 0;
}

static int pfe_platform_resume(struct device *dev)
{
	struct pfe *pfe = platform_get_drvdata(to_platform_device(dev));
	struct net_device *netdev;
	int i;

	printk(KERN_INFO "%s\n", __func__);

	if (!pfe->wake) {
		/* Sequence follows VLSI recommendation (bug 71927) */
		c2000_block_reset(COMPONENT_PFE_SYS, 1);
		mdelay(1);
		c2000_block_reset(COMPONENT_PFE_SYS, 0);
		clk_enable(pfe->hfe_clock);

		pfe_hw_init(pfe, 1);
		pfe_hif_lib_init(pfe);
		pfe_hif_init(pfe);
#if !defined(CONFIG_UTIL_DISABLED)
		util_enable();
#endif
		tmu_enable(0xf);
		class_enable();
		pfe_ctrl_resume(&pfe->ctrl);
	}

	for(i = 0; i < (NUM_GEMAC_SUPPORT - 1); i++) {
		netdev = pfe->eth.eth_priv[i]->dev;

		if (pfe->eth.eth_priv[i]->mii_bus)
			pfe_eth_mdio_reset(pfe->eth.eth_priv[i]->mii_bus);

		if (netif_running(netdev))
			pfe_eth_resume(netdev);

		netif_device_attach(netdev);
	}
	return 0;
}
#else
#define pfe_platform_suspend NULL
#define pfe_platform_resume NULL
#endif

static const struct dev_pm_ops pfe_platform_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(pfe_platform_suspend, pfe_platform_resume)
};

#endif

static struct platform_driver pfe_platform_driver = {
	.probe = pfe_platform_probe,
	.remove = pfe_platform_remove,
	.driver = {
		.name = "pfe",
#ifdef CONFIG_PM
		.pm = &pfe_platform_pm_ops,
#endif
	},
};


static int __init pfe_module_init(void)
{
	printk(KERN_INFO "%s\n", __func__);

	return platform_driver_register(&pfe_platform_driver);
}


static void __exit pfe_module_exit(void)
{
	platform_driver_unregister(&pfe_platform_driver);

	printk(KERN_INFO "%s\n", __func__);
}

MODULE_LICENSE("GPL");
module_init(pfe_module_init);
module_exit(pfe_module_exit);
