/* 2009-08-20: File added and changed by Sony Corporation */
/*
 *  File Name       : linux/drivers/char/mp200_spi.h
 *  Function        : MP200 SPI interface
 *  Release Version : Ver 1.02
 *  Release Date    : 2006/03/06
 *
 *  Copyright (C) NEC Electronics Corporation 2005-2006
 *
 *
 *  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 Free Softwere Foundation; either version 2
 *  of 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 warrnty 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.
 *
 */

#ifndef __DRIVERS_CHAR_MP200_SPI_H
#define __DRIVERS_CHAR_MP200_SPI_H

#include <asm/arch/spi.h>

/*
 * SPI register
 */
#define SP0_ADDR  IO_ADDRESS(MP200_SP0_BASE)
#define SP1_ADDR  IO_ADDRESS(MP200_SP1_BASE)
#define SP2_ADDR  IO_ADDRESS(MP200_SP2_BASE)

#define SPx_TX_DATA_PHYS(ADDR)		((ADDR) + 0x00000010)
#define SPx_RX_DATA_PHYS(ADDR)		((ADDR) + 0x00000014)

#define SPx_POL_VAL_SPI0		SPI_POL_VAL_SPI0
#define SPx_POL_VAL_SPI1		SPI_POL_VAL_SPI1
#define SPx_POL_VAL_SPI2		SPI_POL_VAL_SPI2

#define SPx_CONTROL_TX_EMP		(0x01 << 15)
#define SPx_CONTROL_RX_FULL		(0x01 << 14)
#define SPx_CONTROL_RST			(0x01 << 8)
#define SPx_CONTROL_TX_FULL		(0x01 << 7)
#define SPx_CONTROL_RX_EMP		(0x01 << 6)
#define SPx_CONTROL_WRT			(0x01 << 3)
#define SPx_CONTROL_RD			(0x01 << 2)
#define SPx_CONTROL_STOP		(0x01 << 1)
#define SPx_CONTROL_START		(0x01 << 0)

#define SPx_STATUS_TX_STOP		(0x01 << 6)
#define SPx_STATUS_RX_STOP		(0x01 << 5)
#define SPx_STATUS_TERR			(0x01 << 4)
#define SPx_STATUS_RDV			(0x01 << 3)
#define SPx_STATUS_END			(0x01 << 2)
#define SPx_STATUS_TX_UDR		(0x01 << 1)
#define SPx_STATUS_RX_OVR		(0x01 << 0)
#define SPx_STATUS_ALLERR		(SPx_STATUS_TERR | SPx_STATUS_TX_UDR | SPx_STATUS_RX_OVR)

#define SPx_RAW_STATUS_TX_STOP_RAW	(0x01 << 6)
#define SPx_RAW_STATUS_RX_STOP_RAW	(0x01 << 5)
#define SPx_RAW_STATUS_TERR_RAW		(0x01 << 4)
#define SPx_RAW_STATUS_RDV_RAW		(0x01 << 3)
#define SPx_RAW_STATUS_END_RAW		(0x01 << 2)
#define SPx_RAW_STATUS_TX_UDR_RAW	(0x01 << 1)
#define SPx_RAW_STATUS_RX_OVR_RAW	(0x01 << 0)

#define SPx_ENSET_TX_STOP_EN		(0x01 << 6)
#define SPx_ENSET_RX_STOP_EN		(0x01 << 5)
#define SPx_ENSET_TERR_EN		(0x01 << 4)
#define SPx_ENSET_RDV_EN		(0x01 << 3)
#define SPx_ENSET_END_EN		(0x01 << 2)
#define SPx_ENSET_TX_UDR_EN		(0x01 << 1)
#define SPx_ENSET_RX_OVR_EN		(0x01 << 0)
#define SPx_ENSET_ALLERR_EN		(SPx_ENSET_TERR_EN | SPx_ENSET_TX_UDR_EN | SPx_ENSET_RX_OVR_EN)

#define SPx_ENCLR_TX_STOP_MASK		(0x01 << 6)
#define SPx_ENCLR_RX_STOP_MASK		(0x01 << 5)
#define SPx_ENCLR_TERR_MASK		(0x01 << 4)
#define SPx_ENCLR_RDV_MASK		(0x01 << 3)
#define SPx_ENCLR_END_MASK		(0x01 << 2)
#define SPx_ENCLR_TX_UDR_MASK		(0x01 << 1)
#define SPx_ENCLR_RX_OVR_MASK		(0x01 << 0)
#define SPx_ENCLR_ALLERR_MASK		(SPx_ENCLR_TERR_MASK | SPx_ENCLR_TX_UDR_MASK | SPx_ENCLR_RX_OVR_MASK)
#define SPx_ENCLR_ALL_MASK		(SPx_ENCLR_TX_STOP_MASK   \
					 | SPx_ENCLR_RX_STOP_MASK \
					 | SPx_ENCLR_TERR_MASK    \
					 | SPx_ENCLR_RDV_MASK     \
					 | SPx_ENCLR_END_MASK     \
					 | SPx_ENCLR_TX_UDR_MASK  \
					 | SPx_ENCLR_RX_OVR_MASK)

#define SPx_FFCLR_TX_STOP_CLR		(0x01 << 6)
#define SPx_FFCLR_RX_STOP_CLR		(0x01 << 5)
#define SPx_FFCLR_TERR_CLR		(0x01 << 4)
#define SPx_FFCLR_RDV_CLR		(0x01 << 3)
#define SPx_FFCLR_END_CLR		(0x01 << 2)
#define SPx_FFCLR_TX_UDR_CLR		(0x01 << 1)
#define SPx_FFCLR_RX_OVR_CLR		(0x01 << 0)
#define SPx_FFCLR_ALL_CLR		(SPx_FFCLR_TX_STOP_CLR   \
					 | SPx_FFCLR_RX_STOP_CLR \
					 | SPx_FFCLR_TERR_CLR    \
					 | SPx_FFCLR_RDV_CLR     \
					 | SPx_FFCLR_END_CLR     \
					 | SPx_FFCLR_TX_UDR_CLR  \
					 | SPx_FFCLR_RX_OVR_CLR)

#define SPx_CONTROL2_TX_STOP_MODE	(0x01 << 9)
#define SPx_CONTROL2_RX_STOP_MODE	(0x01 << 8)
#define SPx_CONTROL2_RX_FIFO_FULL_MASK	((0xFF << 16) | (0xFF << 0))

#define DEVNO_IS_INVALID(dev_no)	( dev_no != SPI_DEV_SPI1 && dev_no != SPI_DEV_SPI2 )

/*
 * device info
 */
#define SPI_NAME			"spi"
#define SPI_DIR				"spi"

#if 0
/* SPI0 is Unsupported */
#define SPI_MINOR_SPI0			0
#endif
#define SPI_MINOR_SPI1			1
#define SPI_MINOR_SPI2			2

/*
 * transfer status
 */
#define SPI_STOP			0
#define SPI_ACTIVE			1

/*
 * buffer status
 */
#define SPI_BUFF_FULL			(0x01 << 0)
#define SPI_BUFF_EMPTY			(0x01 << 1)
#define SPI_BUFF_OVER_ERR		(0x01 << 2)

/*
 * other define
 */
#define SPI_BUFSIZE_MAX			65536	/* buffer size max [byte] */
#define SPI_BLKSIZE_MAX			32768	/* block size max [byte] */
#define SPI_BLKNUM_MAX			16	/* block number max */
#define SPI_BLKSIZE			1024	/* block size default [byte] */

#define SPI_OFF				0	/* clock/reset off */
#define SPI_ON				1	/* clock/reset on */
#define SPI_RESET			2	/* reset on->off */

#define SPI_FIFO_MAX			32	/* fifo count max */
#define SPI_DMA_BLOCK_SIZE_MAX		65534	/* dma block size max [byte] */

/*
 * spi register info
 */
typedef struct {
	volatile unsigned int mode;		/* SPx_MODE       (0x00) */
	volatile unsigned int pol;		/* SPx_POL        (0x04) */
	volatile unsigned int control;		/* SPx_CONTROL    (0x08) */
	unsigned int :32; 			/* reserved       (0x0c) */
	volatile unsigned int tx_data;		/* SPx_TX_DATA    (0x10) */
	volatile unsigned int rx_data;		/* SPx_RX_DATA    (0x14) */
	volatile unsigned int status;		/* SPx_STATUS     (0x18) */
	volatile unsigned int raw_status;	/* SPx_RAW_STATUS (0x1c) */
	volatile unsigned int enset;		/* SPx_ENSET      (0x20) */
	volatile unsigned int enclr;		/* SPx_ENCLR      (0x24) */
	volatile unsigned int ffclr;		/* SPx_FFCLR      (0x28) */
	unsigned int :32; 			/* reserved       (0x2c) */
	unsigned int :32; 			/* reserved       (0x30) */
	volatile unsigned int control2;		/* SPx_CONTROL2   (0x34) */
	volatile unsigned int tiecs;		/* SPx_TIECS      (0x38) */
} spi_regs;

/*
 * buffer info
 */
typedef struct {
	dma_addr_t dma_addr;	/* dma transfer start address (physics) */
	unsigned int top;	/* buffer top address (virtual) */
	unsigned int end;	/* buffer end address (virtual) */
	unsigned int dma_ptr;	/* buffer pointer for dma/cpu transfer */
	unsigned int usr_ptr;	/* buffer pointer for read/write */
	unsigned int blknum;	/* block number */
	unsigned int state;	/* buffer status */
} spi_buf_t;

/*
 * transfer info
 */
typedef struct {
	dma_regs_t *dma_regs;	/* dma_regs_t */
	int const rx_lch;	/* dma rx channel no */
	int const tx_lch;	/* dma tx channel no */
	unsigned int const rx_data;	/* rx data transfer address (physics) */
	unsigned int const tx_data;	/* tx data transfer address (physics) */
	unsigned int int_spi;	/* int spi no */
	unsigned int dma_err;	/* dma error status */
	unsigned int spi_err;	/* spi error status */
	unsigned int state;	/* transfer status */
	wait_queue_head_t wait;	/* wait queue */
	spinlock_t spinlock;	/* spin lock */
	spi_buf_t buf;		/* buffer info */
} spi_trans_t;

/*
 * smu info
 */
typedef struct {
	unsigned int pclk;	/* pclk */
	unsigned int sclk;	/* sclk */
	unsigned int pclk_ctrl;	/* pclk ctrl */
	unsigned int sclk_ctrl;	/* sclk ctrl */
	unsigned int reset;	/* reset */
	unsigned int div_sclk;	/* divsclk */
} spi_smu_t;

/*
 * spi data info
 */
typedef struct {
	spi_regs   *regs;	/* spi register info */
	spi_mode_t *mode;	/* spi mode info */
	unsigned int pol;	/* spi pol info */
	spi_smu_t *smu;		/* smu info */
	spi_trans_t *trans;	/* transfer info */
	mode_t opened;		/* open flag */
	unsigned int k_flag;            /* kernel flag */
	struct semaphore sem_rw;        /* semaphore for open/release */
	struct semaphore sem_open;	/* semaphore for open/release */
} spi_data_t;

#endif				/* __DRIVERS_CHAR_MP200_SPI_H */
