/* 10G controller driver for Samsung SoCs
 *
 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/etherdevice.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/sxgbe_platform.h>

#include "sxgbe_common.h"
#include "sxgbe_reg.h"

#ifdef CONFIG_OF
static int sxgbe_probe_config_dt(struct platform_device *pdev,
				 struct sxgbe_plat_data *plat,
				 const char **mac)
{
	struct device_node *np = pdev->dev.of_node;
	struct sxgbe_dma_cfg *dma_cfg;

	if (!np)
		return -ENODEV;

	*mac = of_get_mac_address(np);
	plat->interface = of_get_phy_mode(np);

	plat->bus_id = of_alias_get_id(np, "ethernet");
	if (plat->bus_id < 0)
		plat->bus_id = 0;

	plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
					   sizeof(*plat->mdio_bus_data),
					   GFP_KERNEL);

	dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
	if (!dma_cfg)
		return -ENOMEM;

	plat->dma_cfg = dma_cfg;
	of_property_read_u32(np, "samsung,pbl", &dma_cfg->pbl);
	if (of_property_read_u32(np, "samsung,burst-map", &dma_cfg->burst_map) == 0)
		dma_cfg->fixed_burst = true;

	return 0;
}
#else
static int sxgbe_probe_config_dt(struct platform_device *pdev,
				 struct sxgbe_plat_data *plat,
				 const char **mac)
{
	return -ENOSYS;
}
#endif /* CONFIG_OF */

/**
 * sxgbe_platform_probe
 * @pdev: platform device pointer
 * Description: platform_device probe function. It allocates
 * the necessary resources and invokes the main to init
 * the net device, register the mdio bus etc.
 */
static int sxgbe_platform_probe(struct platform_device *pdev)
{
	int ret;
	int i, chan;
	struct resource *res;
	struct device *dev = &pdev->dev;
	void __iomem *addr;
	struct sxgbe_priv_data *priv = NULL;
	struct sxgbe_plat_data *plat_dat = NULL;
	const char *mac = NULL;
	struct net_device *ndev = platform_get_drvdata(pdev);
	struct device_node *node = dev->of_node;

	/* Get memory resource */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		goto err_out;

	addr = devm_ioremap_resource(dev, res);
	if (IS_ERR(addr))
		return PTR_ERR(addr);

	if (pdev->dev.of_node) {
		plat_dat = devm_kzalloc(&pdev->dev,
					sizeof(struct sxgbe_plat_data),
					GFP_KERNEL);
		if (!plat_dat)
			return  -ENOMEM;

		ret = sxgbe_probe_config_dt(pdev, plat_dat, &mac);
		if (ret) {
			pr_err("%s: main dt probe failed\n", __func__);
			return ret;
		}
	}

	/* Get MAC address if available (DT) */
	if (mac)
		ether_addr_copy(priv->dev->dev_addr, mac);

	priv = sxgbe_drv_probe(&(pdev->dev), plat_dat, addr);
	if (!priv) {
		pr_err("%s: main driver probe failed\n", __func__);
		goto err_out;
	}

	/* Get the SXGBE common INT information */
	priv->irq  = irq_of_parse_and_map(node, 0);
	if (priv->irq <= 0) {
		dev_err(dev, "sxgbe common irq parsing failed\n");
		goto err_drv_remove;
	}

	/* Get the TX/RX IRQ numbers */
	for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) {
		priv->txq[i]->irq_no = irq_of_parse_and_map(node, chan++);
		if (priv->txq[i]->irq_no <= 0) {
			dev_err(dev, "sxgbe tx irq parsing failed\n");
			goto err_tx_irq_unmap;
		}
	}

	for (i = 0; i < SXGBE_RX_QUEUES; i++) {
		priv->rxq[i]->irq_no = irq_of_parse_and_map(node, chan++);
		if (priv->rxq[i]->irq_no <= 0) {
			dev_err(dev, "sxgbe rx irq parsing failed\n");
			goto err_rx_irq_unmap;
		}
	}

	priv->lpi_irq = irq_of_parse_and_map(node, chan);
	if (priv->lpi_irq <= 0) {
		dev_err(dev, "sxgbe lpi irq parsing failed\n");
		goto err_rx_irq_unmap;
	}

	platform_set_drvdata(pdev, priv->dev);

	pr_debug("platform driver registration completed\n");

	return 0;

err_rx_irq_unmap:
	while (--i)
		irq_dispose_mapping(priv->rxq[i]->irq_no);
	i = SXGBE_TX_QUEUES;
err_tx_irq_unmap:
	while (--i)
		irq_dispose_mapping(priv->txq[i]->irq_no);
	irq_dispose_mapping(priv->irq);
err_drv_remove:
	sxgbe_drv_remove(ndev);
err_out:
	return -ENODEV;
}

/**
 * sxgbe_platform_remove
 * @pdev: platform device pointer
 * Description: this function calls the main to free the net resources
 * and calls the platforms hook and release the resources (e.g. mem).
 */
static int sxgbe_platform_remove(struct platform_device *pdev)
{
	struct net_device *ndev = platform_get_drvdata(pdev);
	int ret = sxgbe_drv_remove(ndev);

	return ret;
}

#ifdef CONFIG_PM
static int sxgbe_platform_suspend(struct device *dev)
{
	struct net_device *ndev = dev_get_drvdata(dev);

	return sxgbe_suspend(ndev);
}

static int sxgbe_platform_resume(struct device *dev)
{
	struct net_device *ndev = dev_get_drvdata(dev);

	return sxgbe_resume(ndev);
}

static int sxgbe_platform_freeze(struct device *dev)
{
	struct net_device *ndev = dev_get_drvdata(dev);

	return sxgbe_freeze(ndev);
}

static int sxgbe_platform_restore(struct device *dev)
{
	struct net_device *ndev = dev_get_drvdata(dev);

	return sxgbe_restore(ndev);
}

static const struct dev_pm_ops sxgbe_platform_pm_ops = {
	.suspend	= sxgbe_platform_suspend,
	.resume		= sxgbe_platform_resume,
	.freeze		= sxgbe_platform_freeze,
	.thaw		= sxgbe_platform_restore,
	.restore	= sxgbe_platform_restore,
};
#else
static const struct dev_pm_ops sxgbe_platform_pm_ops;
#endif /* CONFIG_PM */

static const struct of_device_id sxgbe_dt_ids[] = {
	{ .compatible = "samsung,sxgbe-v2.0a"},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sxgbe_dt_ids);

static struct platform_driver sxgbe_platform_driver = {
	.probe	= sxgbe_platform_probe,
	.remove	= sxgbe_platform_remove,
	.driver	= {
		.name		= SXGBE_RESOURCE_NAME,
		.owner		= THIS_MODULE,
		.pm		= &sxgbe_platform_pm_ops,
		.of_match_table	= of_match_ptr(sxgbe_dt_ids),
	},
};

int sxgbe_register_platform(void)
{
	int err;

	err = platform_driver_register(&sxgbe_platform_driver);
	if (err)
		pr_err("failed to register the platform driver\n");

	return err;
}

void sxgbe_unregister_platform(void)
{
	platform_driver_unregister(&sxgbe_platform_driver);
}
