/*******************************************************************************
 *
 *  Copyright(c) 2006 Star Semiconductor Corporation, All rights reserved.
 *
 *  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.
 *
 *  The full GNU General Public License is included in this distribution in the
 *  file called LICENSE.
 *
 *  Contact Information:
 *  Technology Support <tech@starsemi.com>
 *  Star Semiconductor 4F, No.1, Chin-Shan 8th St, Hsin-Chu,300 Taiwan, R.O.C
 *
 ******************************************************************************/

#ifndef _STAR_SPI_H_
#define _STAR_SPI_H_

#include "star_sys_memory_map.h"

#if defined(__UBOOT__)
#define SPI_MEM_MAP_VALUE(reg_offset)		(*((u32 volatile *)(SYSPA_SPI_BASE_ADDR + reg_offset)))
#elif defined(__LINUX__)
#define SPI_MEM_MAP_VALUE(reg_offset)		(*((u32 volatile *)(SYSVA_SPI_BASE_ADDR + reg_offset)))
#else
#error "NO SYSTEM DEFINED"
#endif

/*
 * define access macros
 */
#define SPI_CONFIGURATION_REG			SPI_MEM_MAP_VALUE(0x40)
#define SPI_SERVICE_STATUS_REG			SPI_MEM_MAP_VALUE(0x44)
#define SPI_BIT_RATE_CONTROL_REG		SPI_MEM_MAP_VALUE(0x48)
#define SPI_TRANSMIT_CONTROL_REG		SPI_MEM_MAP_VALUE(0x4C)
#define SPI_TRANSMIT_BUFFER_REG			SPI_MEM_MAP_VALUE(0x50)
#define SPI_RECEIVE_CONTROL_REG			SPI_MEM_MAP_VALUE(0x54)
#define SPI_RECEIVE_BUFFER_REG			SPI_MEM_MAP_VALUE(0x58)
#define SPI_FIFO_TRANSMIT_CONFIG_REG		SPI_MEM_MAP_VALUE(0x5C)
#define SPI_FIFO_TRANSMIT_CONTROL_REG		SPI_MEM_MAP_VALUE(0x60)
#define SPI_FIFO_RECEIVE_CONFIG_REG		SPI_MEM_MAP_VALUE(0x64)
#define SPI_INTERRUPT_STATUS_REG		SPI_MEM_MAP_VALUE(0x68)
#define SPI_INTERRUPT_ENABLE_REG		SPI_MEM_MAP_VALUE(0x6C)

/*
 * define constants macros
 */
#define SPI_TX_RX_FIFO_DEPTH			(8)

#define SPI_CH0					(0)
#define SPI_CH1					(1)
#define SPI_CH2					(2)
#define SPI_CH3					(3)


#define SPI_RXFIFO_OT_FG			(0x01)
#define SPI_TXFIFO_UT_FG			(0x02)
#define SPI_RXBUF_FULL_FG			(0x04)
#define SPI_TXBUF_EMPTY_FG			(0x08)

#define SPI_RXFIFO_OR_FG			(0x10)
#define SPI_TXFIFO_UR_FG			(0x20)
#define SPI_RXBUF_OR_FG				(0x40)
#define SPI_TXBUF_UR_FG				(0x80)

/*
 * IRQ enable
 */
#define SPI_RX_FF_INTEN		(1 << 0)
#define SPI_TX_FF_INTEN		(1 << 1)
#define SPI_RX_BF_INTEN		(1 << 2)
#define SPI_TX_BF_INTEN		(1 << 3)
#define SPI_RX_FFERR_INTEN	(1 << 4)
#define SPI_TX_FFERR_INTEN	(1 << 5)
#define SPI_RX_BFERR_INTEN	(1 << 6)
#define SPI_TX_BFERR_INTEN	(1 << 7)

/*
 * Config
 */
#define SPI_CONFIG_SERIAL_MODE	(1 << 9)
#define SPI_CONFIG_FIFO_EN	(1 << 10)
#define SPI_CONFIG_MASTER_EN	(1 << 11)
#define SPI_CONFIG_LBK		(1 << 12)
#define SPI_CONFIG_CLKPHA	(1 << 13)
#define SPI_CONFIG_CLKPOL	(1 << 14)
#define SPI_CONFIG_SWAP_EN	(1 << 24)
#define SPI_CONFIG_HIGH_SPEED	(1 << 30)
#define SPI_CONFIG_SPI_EN	(1 << 31)

/*
 * TX Config
 */
#define SPI_TXCFG_EOF_SHIFT	(2)
#define SPI_TXCFG_EOF		(1 << SPI_TXCFG_EOF_SHIFT)


/*
 * define Character Length Control
 */
#define SPI_LEN_BIT_8				(0)
#define SPI_LEN_BIT_16				(1)
#define SPI_LEN_BIT_24				(2)
#define SPI_LEN_BIT_32				(3)
#define SPI_LEN_MASK				(3)

/*
 * macro declarations
 */
#define HAL_SPI_ENABLE_SPI() \
{ \
    (SPI_CONFIGURATION_REG) |= ((u32)0x1 << 31); \
}

#define HAL_SPI_DISABLE_SPI() \
{ \
    (SPI_CONFIGURATION_REG) &= ~((u32)0x1 << 31); \
}

#define HAL_SPI_ENABLE_DATA_SWAP() \
{ \
    (SPI_CONFIGURATION_REG) |= (0x1 << 24); \
}

#define HAL_SPI_DISABLE_DATA_SWAP() \
{ \
    (SPI_CONFIGURATION_REG) &= ~(0x1 << 24); \
}

#define HAL_SPI_TRANSMIT_DATA(tx_data) \
{ \
    (SPI_TRANSMIT_BUFFER_REG) = tx_data; \
}

#define HAL_SPI_RECEIVE_DATA(rx_data) \
{ \
    (rx_data) = SPI_RECEIVE_BUFFER_REG; \
}

#define HAL_SPI_GET_TRANSMIT_FIFO_WORDS_NUMBER(tx_fifo_words_num) \
{ \
    (tx_fifo_words_num) = SPI_FIFO_TRANSMIT_CONFIG_REG & 0xF; \
}

#define HAL_SPI_GET_RECEIVE_FIFO_WORDS_NUMBER(rx_fifo_words_num) \
{ \
    (rx_fifo_words_num) = SPI_FIFO_RECEIVE_CONFIG_REG & 0xF; \
}

#define HAL_SPI_DISABLE_ALL_INTERRUPT_SOURCES() \
{ \
    (SPI_INTERRUPT_ENABLE_REG) = 0; \
}

#define HAL_SPI_DISABLE_TX_FIFO_THRESHOLD_INTERRUPT() \
{ \
    (SPI_INTERRUPT_ENABLE_REG) &= ~(0x1 << 1); \
}

#define HAL_SPI_DISABLE_RX_FIFO_THRESHOLD_INTERRUPT() \
{ \
    (SPI_INTERRUPT_ENABLE_REG) &= ~(0x1 << 0); \
}

#define HAL_SPI_READ_INTERRUPT_STATUS(status) \
{ \
    (status) = SPI_INTERRUPT_STATUS_REG; \
}

#define HAL_SPI_CLEAR_INTERRUPT_STATUS(status) \
{ \
    (SPI_INTERRUPT_STATUS_REG) = (status & 0xF0); \
}

#define HAL_SPI_SET_FIFO_TRANSMIT_DELAY(delay) \
{ \
    (SPI_FIFO_TRANSMIT_CONTROL_REG) = (delay & 0x1F); \
}

#define GROCX_SPI_SERIAL_MODE_GENERAL		0x0
#define GROCX_SPI_SERIAL_MODE_MICROPROCESSOR	0x1
 
struct grocx_spi_dev_attr
{ 
    u8 spi_serial_mode;
    u8 cs_change_per_word;
};

#endif  // end of #ifndef _STAR_SPI_H_
