blob: e04a18fc778afd0a963ea5ba8c94b18b8e276f6a [file] [log] [blame]
/*
* arch/arm/plat-ambarella/include/plat/spi.h
*
* Author: Anthony Ginger <hfjiang@ambarella.com>
*
* Copyright (C) 2004-2010, Ambarella, Inc.
*
* 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
*
*/
#ifndef __PLAT_AMBARELLA_SPI_H__
#define __PLAT_AMBARELLA_SPI_H__
#include <linux/spi/spi.h>
/* ==========================================================================*/
#if (CHIP_REV == A5S)
#define SPI_INSTANCES 2
#define SPI_AHB_INSTANCES 0
#define SPI_SLAVE_INSTANCES 1
#define SPI_AHB_SLAVE_INSTANCES 0
#elif (CHIP_REV == S2)
#ifdef CONFIG_PLAT_AMBARELLA_SUPPORT_MMAP_AHB64
#define SPI_INSTANCES 2
#else
#define SPI_INSTANCES 1
#endif
#define SPI_AHB_INSTANCES 0
#define SPI_SLAVE_INSTANCES 1
#define SPI_AHB_SLAVE_INSTANCES 0
#elif (CHIP_REV == S2E)
#define SPI_INSTANCES 1
#define SPI_AHB_INSTANCES 1
#define SPI_SLAVE_INSTANCES 1
#define SPI_AHB_SLAVE_INSTANCES 0
#elif (CHIP_REV == S2L) || (CHIP_REV == S3) || (CHIP_REV == S3L)
#define SPI_INSTANCES 0
#define SPI_AHB_INSTANCES 2
#define SPI_SLAVE_INSTANCES 0
#define SPI_AHB_SLAVE_INSTANCES 1
#elif (CHIP_REV == A7L)
#define SPI_INSTANCES 1
#define SPI_AHB_INSTANCES 0
#define SPI_SLAVE_INSTANCES 1
#define SPI_AHB_SLAVE_INSTANCES 0
#else
#define SPI_INSTANCES 1
#define SPI_AHB_INSTANCES 0
#define SPI_SLAVE_INSTANCES 0
#define SPI_AHB_SLAVE_INSTANCES 0
#endif
#if (CHIP_REV == A5S)
#define SPI_SUPPORT_MASTER_CHANGE_ENA_POLARITY 0
#define SPI_SUPPORT_MASTER_DELAY_START_TIME 0
#define SPI_SUPPORT_NSM_SHAKE_START_BIT_CHSANGE 0
#else
#define SPI_SUPPORT_MASTER_CHANGE_ENA_POLARITY 1
#define SPI_SUPPORT_MASTER_DELAY_START_TIME 1 // S2L only support ssi0, remember to fix it
#define SPI_SUPPORT_NSM_SHAKE_START_BIT_CHSANGE 1 // S2 and S2L is not explain this in PRM
#endif
#if (CHIP_REV == S2L) || (CHIP_REV == S3) || (CHIP_REV == S3L)
#define SPI_TARGET_FRAME 1
#else
#define SPI_TARGET_FRAME 0
#endif
/* ==========================================================================*/
#if (SPI_INSTANCES >= 1)
#define SPI_OFFSET 0x2000
#define SPI_BASE (APB_BASE + SPI_OFFSET)
#define SPI_REG(x) (SPI_BASE + (x))
#endif
#if (SPI_SLAVE_INSTANCES >= 1)
#if (CHIP_REV == A7L)
#define SPI_SLAVE_OFFSET 0x1000
#else
#define SPI_SLAVE_OFFSET 0x1E000
#endif
#define SPI_SLAVE_BASE (APB_BASE + SPI_SLAVE_OFFSET)
#define SPI_SLAVE_REG(x) (SPI_SLAVE_BASE + (x))
#endif
#if (SPI_INSTANCES >= 2)
#define SPI2_OFFSET 0xF000
#define SPI2_BASE (APB_BASE + SPI2_OFFSET)
#define SPI2_REG(x) (SPI2_BASE + (x))
#endif
#if (SPI_INSTANCES >= 3)
#define SPI3_OFFSET 0x15000
#define SPI3_BASE (APB_BASE + SPI3_OFFSET)
#define SPI3_REG(x) (SPI3_BASE + (x))
#endif
#if (SPI_INSTANCES >= 4)
#define SPI4_OFFSET 0x16000
#define SPI4_BASE (APB_BASE + SPI4_OFFSET)
#define SPI4_REG(x) (SPI4_BASE + (x))
#endif
#if (SPI_AHB_INSTANCES == 1)
#define SSI_DMA_OFFSET 0xD000
#define SSI_DMA_BASE (AHB_BASE + SSI_DMA_OFFSET)
#define SSI_DMA_REG(x) (SSI_DMA_BASE + (x))
#if (SPI_INSTANCES == 1)
#define SPI2_OFFSET 0x1F000
#define SPI2_BASE (AHB_BASE + SPI2_OFFSET)
#define SPI2_REG(x) (SPI2_BASE + (x))
#endif
#endif
#if (SPI_AHB_INSTANCES == 2)
#define SPI_OFFSET 0x20000
#define SPI_BASE (AHB_BASE + SPI_OFFSET)
#define SPI_REG(x) (SPI_BASE + (x))
#define SPI2_OFFSET 0x21000
#define SPI2_BASE (AHB_BASE + SPI2_OFFSET)
#define SPI2_REG(x) (SPI2_BASE + (x))
#endif
#if (SPI_AHB_SLAVE_INSTANCES >= 1)
#define SPI_AHB_SLAVE_OFFSET 0x26000
#define SPI_AHB_SLAVE_BASE (AHB_BASE + SPI_AHB_SLAVE_OFFSET)
#define SPI_AHB_SLAVE_REG(x) (SPI_AHB_SLAVE_BASE + (x))
#endif
#define SPI_MASTER_INSTANCES (SPI_INSTANCES + SPI_AHB_INSTANCES)
/* ==========================================================================*/
/* SPI_FIFO_SIZE */
#define SPI_DATA_FIFO_SIZE_16 0x10
#define SPI_DATA_FIFO_SIZE_32 0x20
#define SPI_DATA_FIFO_SIZE_64 0x40
#define SPI_DATA_FIFO_SIZE_128 0x80
/****************************************************/
/* Controller registers definitions */
/****************************************************/
#define SPI_CTRLR0_OFFSET 0x00
#define SPI_CTRLR1_OFFSET 0x04
#define SPI_SSIENR_OFFSET 0x08
#define SPI_MWCR_OFFSET 0x0c // no PRM explain it and no code use it. should be commented after check
#define SPI_SER_OFFSET 0x10
#define SPI_BAUDR_OFFSET 0x14
#define SPI_TXFTLR_OFFSET 0x18
#define SPI_RXFTLR_OFFSET 0x1c
#define SPI_TXFLR_OFFSET 0x20
#define SPI_RXFLR_OFFSET 0x24
#define SPI_SR_OFFSET 0x28
#define SPI_IMR_OFFSET 0x2c
#define SPI_ISR_OFFSET 0x30
#define SPI_RISR_OFFSET 0x34
#define SPI_TXOICR_OFFSET 0x38
#define SPI_RXOICR_OFFSET 0x3c
#define SPI_RXUICR_OFFSET 0x40
#define SPI_MSTICR_OFFSET 0x44
#define SPI_ICR_OFFSET 0x48
#define SPI_DMAC_OFFSET 0x4c
#define SPI_IDR_OFFSET 0x58
#define SPI_VERSION_ID_OFFSET 0x5c
#define SPI_DR_OFFSET 0x60
#if (SPI_SUPPORT_MASTER_CHANGE_ENA_POLARITY == 1)
#define SPI_SSIENPOLR_OFFSET 0x260
#endif
#if (SPI_SUPPORT_MASTER_DELAY_START_TIME == 1)
#define SPI_SCLK_OUT_DLY_OFFSET 0x264
#endif
#if (SPI_SUPPORT_NSM_SHAKE_START_BIT_CHSANGE == 1)
#define SPI_START_BIT_OFFSET 0x268
#endif
#if (SPI_TARGET_FRAME == 1)
#define SPI_TARGET_FRAME_COUNT 0x27c
#define SPI_FRAME_COUNT 0x280
#define SPI_FCRICR 0x284
#define SPI_TX_FRAME_COUNT 0x288
#endif
/* ==========================================================================*/
/* SPI rw mode */
#define SPI_WRITE_READ 0
#define SPI_WRITE_ONLY 1
#define SPI_READ_ONLY 2
/* Tx FIFO empty interrupt mask */
#define SPI_TXEIS_MASK 0x00000001
#define SPI_TXOIS_MASK 0x00000002
#define SPI_RXFIS_MASK 0x00000010
#define SPI_FCRIS_MASK 0x00000100
/* SPI Parameters */
#define SPI_DUMMY_DATA 0xffff
#define MAX_QUERY_TIMES 10
/* Default SPI settings */
#define SPI_MODE SPI_MODE_0
#define SPI_SCPOL 0
#define SPI_SCPH 0
#define SPI_FRF 0
#define SPI_CFS 0x0
#define SPI_DFS 0xf
#define SPI_BAUD_RATE 200000
/* ==========================================================================*/
typedef union {
struct {
u32 dfs : 4; /* [3:0] */
u32 frf : 2; /* [5:4] */
u32 scph : 1; /* [6] */
u32 scpol : 1; /* [7] */
u32 tmod : 2; /* [9:8] */
u32 slv_oe : 1; /* [10] */
u32 srl : 1; /* [11] */
u32 reserv1 : 5; /* [16:12] */
u32 residue : 1; /* [17] */
u32 tx_lsb : 1; /* [18] */
u32 rx_lsb : 1; /* [19] */
u32 reserv2 : 1; /* [20] */
u32 fc_en : 1; /* [21] */
u32 rxd_mg : 4; /* [25:22] */
u32 byte_ws : 1; /* [26] */
u32 hold : 1; /* [27] */
u32 reserv3 : 4; /* [31:28] */
} s;
u32 w;
} spi_ctrl0_reg_t;
typedef union {
struct {
u32 busy : 1; /* [0] */
u32 tfnf : 1; /* [1] */
u32 tfe : 1; /* [2] */
u32 rfne : 1; /* [3] */
u32 rff : 1; /* [4] */
u32 txe : 1; /* [5] */
u32 dcol : 1; /* [6] */
u32 reserve : 25; /* [31:7] */
} s;
u32 w;
} spi_status_reg_t;
/* ==========================================================================*/
#ifndef __ASSEMBLER__
struct ambarella_spi_cfg_info {
u8 spi_mode;
u8 cfs_dfs;
u8 cs_change;
u32 baud_rate;
};
typedef struct ambarella_spi_cfg_info amba_spi_cfg_t;
typedef struct {
u8 bus_id;
u8 cs_id;
u8 *buffer;
u32 n_size; // u16 n_size;
} amba_spi_write_t;
typedef struct {
u8 bus_id;
u8 cs_id;
u8 *buffer;
u16 n_size;
} amba_spi_read_t;
typedef struct {
u8 bus_id;
u8 cs_id;
u8 *w_buffer;
u8 *r_buffer;
u16 w_size;
u16 r_size;
} amba_spi_write_then_read_t;
typedef struct {
u8 bus_id;
u8 cs_id;
u8 *w_buffer;
u8 *r_buffer;
u16 n_size;
} amba_spi_write_and_read_t;
/* ==========================================================================*/
extern int ambarella_spi_write(amba_spi_cfg_t *spi_cfg,
amba_spi_write_t *spi_write);
extern int ambarella_spi_read(amba_spi_cfg_t *spi_cfg,
amba_spi_read_t *spi_read);
extern int ambarella_spi_write_then_read(amba_spi_cfg_t *spi_cfg,
amba_spi_write_then_read_t *spi_write_then_read);
extern int ambarella_spi_write_and_read(amba_spi_cfg_t *spi_cfg,
amba_spi_write_and_read_t *spi_write_and_read);
#endif /* __ASSEMBLER__ */
/* ==========================================================================*/
#endif /* __PLAT_AMBARELLA_SPI_H__ */