/*
 *  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>
 *
 *  Revision history:
 *   22nd Aug 2003 Initial version.
 *   20th Dec 2004 Added ssp_config for changing port config without
 *                 closing the port.
 *    4th Aug 2005 Added option to disable irq handler registration and
 *                 cleaned up irq and clock detection.
 */

#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 <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/arch/ssp.h>
#include <asm/arch/pxa-regs.h>

#define PXA_SSP_PORTS 	3

#define TIMEOUT 100000

struct ssp_info_ {
	int irq;
	u32 clock;
};

/*
 * SSP port clock and IRQ settings
 */
static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = {
#if defined (CONFIG_PXA27x)
	{IRQ_SSP,	CKEN23_SSP1},
	{IRQ_SSP2,	CKEN3_SSP2},
	{IRQ_SSP3,	CKEN4_SSP3},
#else
	{IRQ_SSP,	CKEN3_SSP},
	{IRQ_NSSP,	CKEN9_NSSP},
	{IRQ_ASSP,	CKEN10_ASSP},
#endif
};

static DEFINE_MUTEX(mutex);
static int use_count[PXA_SSP_PORTS] = {0, 0, 0};

static irqreturn_t ssp_interrupt(int irq, void *dev_id)
{
	struct ssp_dev *dev = (struct ssp_dev*) dev_id;
	unsigned int status = SSSR_P(dev->port);

	SSSR_P(dev->port) = status; /* clear status bits */

	if (status & SSSR_ROR)
		printk(KERN_WARNING "SSP(%d): receiver overrun\n", dev->port);

	if (status & SSSR_TUR)
		printk(KERN_WARNING "SSP(%d): transmitter underrun\n", dev->port);

	if (status & SSSR_BCE)
		printk(KERN_WARNING "SSP(%d): bit count error\n", dev->port);

	return IRQ_HANDLED;
}

/**
 * ssp_write_word - write a word to the SSP port
 * @data: 32-bit, MSB justified data to write.
 *
 * Wait for a free entry in the SSP transmit FIFO, and write a data
 * word to the SSP port.
 *
 * The caller is expected to perform the necessary locking.
 *
 * Returns:
 *   %-ETIMEDOUT	timeout occurred
 *   0			success
 */
int ssp_write_word(struct ssp_dev *dev, u32 data)
{
	int timeout = TIMEOUT;

	while (!(SSSR_P(dev->port) & SSSR_TNF)) {
	        if (!--timeout)
	        	return -ETIMEDOUT;
		cpu_relax();
	}

	SSDR_P(dev->port) = data;

	return 0;
}

/**
 * ssp_read_word - read a word from the SSP port
 *
 * Wait for a data word in the SSP receive FIFO, and return the
 * received data.  Data is LSB justified.
 *
 * Note: Currently, if data is not expected to be received, this
 * function will wait for ever.
 *
 * The caller is expected to perform the necessary locking.
 *
 * Returns:
 *   %-ETIMEDOUT	timeout occurred
 *   32-bit data	success
 */
int ssp_read_word(struct ssp_dev *dev, u32 *data)
{
	int timeout = TIMEOUT;

	while (!(SSSR_P(dev->port) & SSSR_RNE)) {
	        if (!--timeout)
	        	return -ETIMEDOUT;
		cpu_relax();
	}

	*data = SSDR_P(dev->port);
	return 0;
}

/**
 * ssp_flush - flush the transmit and receive FIFOs
 *
 * Wait for the SSP to idle, and ensure that the receive FIFO
 * is empty.
 *
 * The caller is expected to perform the necessary locking.
 */
int ssp_flush(struct ssp_dev *dev)
{
	int timeout = TIMEOUT * 2;

	do {
		while (SSSR_P(dev->port) & SSSR_RNE) {
		        if (!--timeout)
		        	return -ETIMEDOUT;
			(void) SSDR_P(dev->port);
		}
	        if (!--timeout)
	        	return -ETIMEDOUT;
	} while (SSSR_P(dev->port) & SSSR_BSY);

	return 0;
}

/**
 * ssp_enable - enable the SSP port
 *
 * Turn on the SSP port.
 */
void ssp_enable(struct ssp_dev *dev)
{
	SSCR0_P(dev->port) |= SSCR0_SSE;
}

/**
 * ssp_disable - shut down the SSP port
 *
 * Turn off the SSP port, optionally powering it down.
 */
void ssp_disable(struct ssp_dev *dev)
{
	SSCR0_P(dev->port) &= ~SSCR0_SSE;
}

/**
 * ssp_save_state - save the SSP configuration
 * @ssp: pointer to structure to save SSP configuration
 *
 * Save the configured SSP state for suspend.
 */
void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp)
{
	ssp->cr0 = SSCR0_P(dev->port);
	ssp->cr1 = SSCR1_P(dev->port);
	ssp->to = SSTO_P(dev->port);
	ssp->psp = SSPSP_P(dev->port);

	SSCR0_P(dev->port) &= ~SSCR0_SSE;
}

/**
 * ssp_restore_state - restore a previously saved SSP configuration
 * @ssp: pointer to configuration saved by ssp_save_state
 *
 * Restore the SSP configuration saved previously by ssp_save_state.
 */
void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp)
{
	SSSR_P(dev->port) = SSSR_ROR | SSSR_TUR | SSSR_BCE;

	SSCR0_P(dev->port) = ssp->cr0 & ~SSCR0_SSE;
	SSCR1_P(dev->port) = ssp->cr1;
	SSTO_P(dev->port) = ssp->to;
	SSPSP_P(dev->port) = ssp->psp;

	SSCR0_P(dev->port) = ssp->cr0;
}

/**
 * ssp_config - configure SSP port settings
 * @mode: port operating mode
 * @flags: port config flags
 * @psp_flags: port PSP config flags
 * @speed: port speed
 *
 * Port MUST be disabled by ssp_disable before making any config changes.
 */
int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed)
{
	dev->mode = mode;
	dev->flags = flags;
	dev->psp_flags = psp_flags;
	dev->speed = speed;

	/* set up port type, speed, port settings */
	SSCR0_P(dev->port) = (dev->speed | dev->mode);
	SSCR1_P(dev->port) = dev->flags;
	SSPSP_P(dev->port) = dev->psp_flags;

	return 0;
}

/**
 * ssp_init - setup the SSP port
 *
 * initialise and claim resources for the SSP port.
 *
 * Returns:
 *   %-ENODEV	if the SSP port is unavailable
 *   %-EBUSY	if the resources are already in use
 *   %0		on success
 */
int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
{
	int ret;

	if (port > PXA_SSP_PORTS || port == 0)
		return -ENODEV;

	mutex_lock(&mutex);
	if (use_count[port - 1]) {
		mutex_unlock(&mutex);
		return -EBUSY;
	}
	use_count[port - 1]++;

	if (!request_mem_region(__PREG(SSCR0_P(port)), 0x2c, "SSP")) {
		use_count[port - 1]--;
		mutex_unlock(&mutex);
		return -EBUSY;
	}
	dev->port = port;

	/* do we need to get irq */
	if (!(init_flags & SSP_NO_IRQ)) {
		ret = request_irq(ssp_info[port-1].irq, ssp_interrupt,
				0, "SSP", dev);
	    	if (ret)
			goto out_region;
	    	dev->irq = ssp_info[port-1].irq;
	} else
		dev->irq = 0;

	/* turn on SSP port clock */
	pxa_set_cken(ssp_info[port-1].clock, 1);
	mutex_unlock(&mutex);
	return 0;

out_region:
	release_mem_region(__PREG(SSCR0_P(port)), 0x2c);
	use_count[port - 1]--;
	mutex_unlock(&mutex);
	return ret;
}

/**
 * ssp_exit - undo the effects of ssp_init
 *
 * release and free resources for the SSP port.
 */
void ssp_exit(struct ssp_dev *dev)
{
	mutex_lock(&mutex);
	SSCR0_P(dev->port) &= ~SSCR0_SSE;

    	if (dev->port > PXA_SSP_PORTS || dev->port == 0) {
		printk(KERN_WARNING "SSP: tried to close invalid port\n");
		return;
	}

	pxa_set_cken(ssp_info[dev->port-1].clock, 0);
	if (dev->irq)
		free_irq(dev->irq, dev);
	release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c);
	use_count[dev->port - 1]--;
	mutex_unlock(&mutex);
}

EXPORT_SYMBOL(ssp_write_word);
EXPORT_SYMBOL(ssp_read_word);
EXPORT_SYMBOL(ssp_flush);
EXPORT_SYMBOL(ssp_enable);
EXPORT_SYMBOL(ssp_disable);
EXPORT_SYMBOL(ssp_save_state);
EXPORT_SYMBOL(ssp_restore_state);
EXPORT_SYMBOL(ssp_init);
EXPORT_SYMBOL(ssp_exit);
EXPORT_SYMBOL(ssp_config);

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

