/*
 *  linux/arch/arm/mach-pxa/ssp.c
 *
 *  based on linux/arch/arm/mach-sa1100/ssp.c by Russell King
 *
 *  Copyright (C) 2003 Russell King.
 *  Copyright (C) 2003 Wolfson Microelectronics PLC
 *
 * 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.
 *
 *  PXA2xx SSP driver.  This provides the generic core for simple
 *  IO-based SSP applications and allows easy port setup for DMA access.
 *
 *  Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>

#include <asm/irq.h>
#include <mach/hardware.h>

static DEFINE_MUTEX(ssp_lock);
static LIST_HEAD(ssp_list);

struct ssp_device *pxa_ssp_request(int port, const char *label)
{
	struct ssp_device *ssp = NULL;

	mutex_lock(&ssp_lock);

	list_for_each_entry(ssp, &ssp_list, node) {
		if (ssp->port_id == port && ssp->use_count == 0) {
			ssp->use_count++;
			ssp->label = label;
			break;
		}
	}

	mutex_unlock(&ssp_lock);

	if (&ssp->node == &ssp_list)
		return NULL;

	return ssp;
}
EXPORT_SYMBOL(pxa_ssp_request);

struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node,
				      const char *label)
{
	struct ssp_device *ssp = NULL;

	mutex_lock(&ssp_lock);

	list_for_each_entry(ssp, &ssp_list, node) {
		if (ssp->of_node == of_node && ssp->use_count == 0) {
			ssp->use_count++;
			ssp->label = label;
			break;
		}
	}

	mutex_unlock(&ssp_lock);

	if (&ssp->node == &ssp_list)
		return NULL;

	return ssp;
}
EXPORT_SYMBOL(pxa_ssp_request_of);

void pxa_ssp_free(struct ssp_device *ssp)
{
	mutex_lock(&ssp_lock);
	if (ssp->use_count) {
		ssp->use_count--;
		ssp->label = NULL;
	} else
		dev_err(&ssp->pdev->dev, "device already free\n");
	mutex_unlock(&ssp_lock);
}
EXPORT_SYMBOL(pxa_ssp_free);

#ifdef CONFIG_OF
static const struct of_device_id pxa_ssp_of_ids[] = {
	{ .compatible = "mrvl,pxa25x-ssp",	.data = (void *) PXA25x_SSP },
	{ .compatible = "mvrl,pxa25x-nssp",	.data = (void *) PXA25x_NSSP },
	{ .compatible = "mrvl,pxa27x-ssp",	.data = (void *) PXA27x_SSP },
	{ .compatible = "mrvl,pxa3xx-ssp",	.data = (void *) PXA3xx_SSP },
	{ .compatible = "mvrl,pxa168-ssp",	.data = (void *) PXA168_SSP },
	{ .compatible = "mrvl,pxa910-ssp",	.data = (void *) PXA910_SSP },
	{ .compatible = "mrvl,ce4100-ssp",	.data = (void *) CE4100_SSP },
	{ .compatible = "mrvl,lpss-ssp",	.data = (void *) LPSS_SSP },
	{ },
};
MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
#endif

static int pxa_ssp_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct ssp_device *ssp;
	struct device *dev = &pdev->dev;

	ssp = devm_kzalloc(dev, sizeof(struct ssp_device), GFP_KERNEL);
	if (ssp == NULL)
		return -ENOMEM;

	ssp->pdev = pdev;

	ssp->clk = devm_clk_get(dev, NULL);
	if (IS_ERR(ssp->clk))
		return PTR_ERR(ssp->clk);

	if (dev->of_node) {
		struct of_phandle_args dma_spec;
		struct device_node *np = dev->of_node;

		/*
		 * FIXME: we should allocate the DMA channel from this
		 * context and pass the channel down to the ssp users.
		 * For now, we lookup the rx and tx indices manually
		 */

		/* rx */
		of_parse_phandle_with_args(np, "dmas", "#dma-cells",
					   0, &dma_spec);
		ssp->drcmr_rx = dma_spec.args[0];
		of_node_put(dma_spec.np);

		/* tx */
		of_parse_phandle_with_args(np, "dmas", "#dma-cells",
					   1, &dma_spec);
		ssp->drcmr_tx = dma_spec.args[0];
		of_node_put(dma_spec.np);
	} else {
		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
		if (res == NULL) {
			dev_err(dev, "no SSP RX DRCMR defined\n");
			return -ENODEV;
		}
		ssp->drcmr_rx = res->start;

		res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
		if (res == NULL) {
			dev_err(dev, "no SSP TX DRCMR defined\n");
			return -ENODEV;
		}
		ssp->drcmr_tx = res->start;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(dev, "no memory resource defined\n");
		return -ENODEV;
	}

	res = devm_request_mem_region(dev, res->start, resource_size(res),
				      pdev->name);
	if (res == NULL) {
		dev_err(dev, "failed to request memory resource\n");
		return -EBUSY;
	}

	ssp->phys_base = res->start;

	ssp->mmio_base = devm_ioremap(dev, res->start, resource_size(res));
	if (ssp->mmio_base == NULL) {
		dev_err(dev, "failed to ioremap() registers\n");
		return -ENODEV;
	}

	ssp->irq = platform_get_irq(pdev, 0);
	if (ssp->irq < 0) {
		dev_err(dev, "no IRQ resource defined\n");
		return -ENODEV;
	}

	if (dev->of_node) {
		const struct of_device_id *id =
			of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
		ssp->type = (int) id->data;
	} else {
		const struct platform_device_id *id =
			platform_get_device_id(pdev);
		ssp->type = (int) id->driver_data;

		/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
		 * starts from 0, do a translation here
		 */
		ssp->port_id = pdev->id + 1;
	}

	ssp->use_count = 0;
	ssp->of_node = dev->of_node;

	mutex_lock(&ssp_lock);
	list_add(&ssp->node, &ssp_list);
	mutex_unlock(&ssp_lock);

	platform_set_drvdata(pdev, ssp);

	return 0;
}

static int pxa_ssp_remove(struct platform_device *pdev)
{
	struct resource *res;
	struct ssp_device *ssp;

	ssp = platform_get_drvdata(pdev);
	if (ssp == NULL)
		return -ENODEV;

	iounmap(ssp->mmio_base);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	release_mem_region(res->start, resource_size(res));

	clk_put(ssp->clk);

	mutex_lock(&ssp_lock);
	list_del(&ssp->node);
	mutex_unlock(&ssp_lock);

	kfree(ssp);
	return 0;
}

static const struct platform_device_id ssp_id_table[] = {
	{ "pxa25x-ssp",		PXA25x_SSP },
	{ "pxa25x-nssp",	PXA25x_NSSP },
	{ "pxa27x-ssp",		PXA27x_SSP },
	{ "pxa168-ssp",		PXA168_SSP },
	{ "pxa910-ssp",		PXA910_SSP },
	{ },
};

static struct platform_driver pxa_ssp_driver = {
	.probe		= pxa_ssp_probe,
	.remove		= pxa_ssp_remove,
	.driver		= {
		.owner		= THIS_MODULE,
		.name		= "pxa2xx-ssp",
		.of_match_table	= of_match_ptr(pxa_ssp_of_ids),
	},
	.id_table	= ssp_id_table,
};

static int __init pxa_ssp_init(void)
{
	return platform_driver_register(&pxa_ssp_driver);
}

static void __exit pxa_ssp_exit(void)
{
	platform_driver_unregister(&pxa_ssp_driver);
}

arch_initcall(pxa_ssp_init);
module_exit(pxa_ssp_exit);

MODULE_DESCRIPTION("PXA SSP driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
