/* Copyright (c) 2008-2014, The Linux Foundation. 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 version 2 and * only version 2 as published by the Free Software Foundation. * * 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. * */ #ifndef _SPI_QSD_H #define _SPI_QSD_H #include #include #define SPI_DRV_NAME "spi_qsd" #if defined(CONFIG_SPI_QSD) || defined(CONFIG_SPI_QSD_MODULE) #define QSD_REG(x) (x) #define QUP_REG(x) #define SPI_FIFO_WORD_CNT 0x0048 #else #define QSD_REG(x) #define QUP_REG(x) (x) #define QUP_CONFIG 0x0000 /* N & NO_INPUT/NO_OUPUT bits */ #define QUP_ERROR_FLAGS_EN 0x030C #define QUP_ERR_MASK 0x3 #define SPI_OUTPUT_FIFO_WORD_CNT 0x010C #define SPI_INPUT_FIFO_WORD_CNT 0x0214 #define QUP_MX_WRITE_COUNT 0x0150 #define QUP_MX_WRITE_CNT_CURRENT 0x0154 #define QUP_CONFIG_SPI_MODE 0x0100 #endif #define GSBI_CTRL_REG 0x0 #define GSBI_SPI_CONFIG 0x30 /* B-family only registers */ #define QUP_HARDWARE_VER 0x0030 #define QUP_HARDWARE_VER_2_1_1 0X20010001 #define QUP_OPERATIONAL_MASK 0x0028 #define QUP_OP_MASK_OUTPUT_SERVICE_FLAG 0x100 #define QUP_OP_MASK_INPUT_SERVICE_FLAG 0x200 #define QUP_ERROR_FLAGS 0x0308 #define SPI_CONFIG QSD_REG(0x0000) QUP_REG(0x0300) #define SPI_IO_CONTROL QSD_REG(0x0004) QUP_REG(0x0304) #define SPI_IO_MODES QSD_REG(0x0008) QUP_REG(0x0008) #define SPI_SW_RESET QSD_REG(0x000C) QUP_REG(0x000C) #define SPI_TIME_OUT_CURRENT QSD_REG(0x0014) QUP_REG(0x0014) #define SPI_MX_OUTPUT_COUNT QSD_REG(0x0018) QUP_REG(0x0100) #define SPI_MX_OUTPUT_CNT_CURRENT QSD_REG(0x001C) QUP_REG(0x0104) #define SPI_MX_INPUT_COUNT QSD_REG(0x0020) QUP_REG(0x0200) #define SPI_MX_INPUT_CNT_CURRENT QSD_REG(0x0024) QUP_REG(0x0204) #define SPI_MX_READ_COUNT QSD_REG(0x0028) QUP_REG(0x0208) #define SPI_MX_READ_CNT_CURRENT QSD_REG(0x002C) QUP_REG(0x020C) #define SPI_OPERATIONAL QSD_REG(0x0030) QUP_REG(0x0018) #define SPI_ERROR_FLAGS QSD_REG(0x0034) QUP_REG(0x001C) #define SPI_ERROR_FLAGS_EN QSD_REG(0x0038) QUP_REG(0x0020) #define SPI_DEASSERT_WAIT QSD_REG(0x003C) QUP_REG(0x0310) #define SPI_OUTPUT_DEBUG QSD_REG(0x0040) QUP_REG(0x0108) #define SPI_INPUT_DEBUG QSD_REG(0x0044) QUP_REG(0x0210) #define SPI_TEST_CTRL QSD_REG(0x004C) QUP_REG(0x0024) #define SPI_OUTPUT_FIFO QSD_REG(0x0100) QUP_REG(0x0110) #define SPI_INPUT_FIFO QSD_REG(0x0200) QUP_REG(0x0218) #define SPI_STATE QSD_REG(SPI_OPERATIONAL) QUP_REG(0x0004) /* QUP_CONFIG fields */ #define SPI_CFG_N 0x0000001F #define SPI_NO_INPUT 0x00000080 #define SPI_NO_OUTPUT 0x00000040 #define SPI_EN_EXT_OUT_FLAG 0x00010000 /* SPI_CONFIG fields */ #define SPI_CFG_LOOPBACK 0x00000100 #define SPI_CFG_INPUT_FIRST 0x00000200 #define SPI_CFG_HS_MODE 0x00000400 /* SPI_IO_CONTROL fields */ #define SPI_IO_C_FORCE_CS 0x00000800 #define SPI_IO_C_CLK_IDLE_HIGH 0x00000400 #define SPI_IO_C_MX_CS_MODE 0x00000100 #define SPI_IO_C_CS_N_POLARITY 0x000000F0 #define SPI_IO_C_CS_N_POLARITY_0 0x00000010 #define SPI_IO_C_CS_SELECT 0x0000000C #define SPI_IO_C_TRISTATE_CS 0x00000002 #define SPI_IO_C_NO_TRI_STATE 0x00000001 /* SPI_IO_MODES fields */ #define SPI_IO_M_OUTPUT_BIT_SHIFT_EN QSD_REG(0x00004000) QUP_REG(0x00010000) #define SPI_IO_M_PACK_EN QSD_REG(0x00002000) QUP_REG(0x00008000) #define SPI_IO_M_UNPACK_EN QSD_REG(0x00001000) QUP_REG(0x00004000) #define SPI_IO_M_INPUT_MODE QSD_REG(0x00000C00) QUP_REG(0x00003000) #define SPI_IO_M_OUTPUT_MODE QSD_REG(0x00000300) QUP_REG(0x00000C00) #define SPI_IO_M_INPUT_FIFO_SIZE QSD_REG(0x000000C0) QUP_REG(0x00000380) #define SPI_IO_M_INPUT_BLOCK_SIZE QSD_REG(0x00000030) QUP_REG(0x00000060) #define SPI_IO_M_OUTPUT_FIFO_SIZE QSD_REG(0x0000000C) QUP_REG(0x0000001C) #define SPI_IO_M_OUTPUT_BLOCK_SIZE QSD_REG(0x00000003) QUP_REG(0x00000003) #define INPUT_BLOCK_SZ_SHIFT QSD_REG(4) QUP_REG(5) #define INPUT_FIFO_SZ_SHIFT QSD_REG(6) QUP_REG(7) #define OUTPUT_BLOCK_SZ_SHIFT QSD_REG(0) QUP_REG(0) #define OUTPUT_FIFO_SZ_SHIFT QSD_REG(2) QUP_REG(2) #define OUTPUT_MODE_SHIFT QSD_REG(8) QUP_REG(10) #define INPUT_MODE_SHIFT QSD_REG(10) QUP_REG(12) /* SPI_OPERATIONAL fields */ #define SPI_OP_MAX_INPUT_DONE_FLAG 0x00000800 #define SPI_OP_MAX_OUTPUT_DONE_FLAG 0x00000400 #define SPI_OP_INPUT_SERVICE_FLAG 0x00000200 #define SPI_OP_OUTPUT_SERVICE_FLAG 0x00000100 #define SPI_OP_INPUT_FIFO_FULL 0x00000080 #define SPI_OP_OUTPUT_FIFO_FULL 0x00000040 #define SPI_OP_IP_FIFO_NOT_EMPTY 0x00000020 #define SPI_OP_OP_FIFO_NOT_EMPTY 0x00000010 #define SPI_OP_STATE_VALID 0x00000004 #define SPI_OP_STATE 0x00000003 #define SPI_OP_STATE_CLEAR_BITS 0x2 enum spi_qup_state { SPI_OP_STATE_RESET = 0x00000000, SPI_OP_STATE_RUN = 0x00000001, SPI_OP_STATE_PAUSE = 0x00000003, }; /* SPI_ERROR_FLAGS fields */ #define SPI_ERR_OUTPUT_OVER_RUN_ERR 0x00000020 #define SPI_ERR_INPUT_UNDER_RUN_ERR 0x00000010 #define SPI_ERR_OUTPUT_UNDER_RUN_ERR 0x00000008 #define SPI_ERR_INPUT_OVER_RUN_ERR 0x00000004 #define SPI_ERR_CLK_OVER_RUN_ERR 0x00000002 #define SPI_ERR_CLK_UNDER_RUN_ERR 0x00000001 /* We don't allow transactions larger than 4K-64 or 64K-64 due to mx_input/output_cnt register size */ #define SPI_MAX_TRANSFERS QSD_REG(0xFC0) QUP_REG(0xFC0) #define SPI_MAX_LEN (SPI_MAX_TRANSFERS * dd->bytes_per_word) #define SPI_NUM_CHIPSELECTS 4 #define SPI_SUPPORTED_MODES (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP) /* high speed mode is when bus rate is greater then 26MHz */ #define SPI_HS_MIN_RATE (26000000) #define SPI_DELAY_THRESHOLD 1 /* Default timeout is 10 milliseconds */ #define SPI_DEFAULT_TIMEOUT 10 /* 250 microseconds */ #define SPI_TRYLOCK_DELAY 250 /* Data Mover burst size */ #define DM_BURST_SIZE 16 /* Data Mover commands should be aligned to 64 bit(8 bytes) */ #define DM_BYTE_ALIGN 8 enum spi_qup_qup_version { SPI_QUP_VERSION_NONE = 0x0, SPI_QUP_VERSION_BFAM = 0x2, }; enum spi_qup_pipe_direction { SPI_BAM_CONSUMER_PIPE = 0x0, SPI_BAM_PRODUCER_PIPE = 0x1, }; #define SPI_BAM_MAX_DESC_NUM 32 #define SPI_MAX_TRFR_BTWN_RESETS ((64 * 1024) - 16) /* 64KB - 16byte */ enum spi_qup_clk_path_vec_idx { spi_qup_CLK_PATH_SUSPEND_VEC = 0, spi_qup_CLK_PATH_RESUME_VEC = 1, }; #define spi_qup_CLK_PATH_AVRG_BW(dd) (76800000) #define spi_qup_CLK_PATH_BRST_BW(dd) (76800000) static char const * const spi_rsrcs[] = { "spi_clk", "spi_miso", "spi_mosi" }; static char const * const spi_cs_rsrcs[] = { "spi_cs", "spi_cs1", "spi_cs2", "spi_cs3", }; enum spi_qup_mode { SPI_FIFO_MODE = 0x0, /* 00 */ SPI_BLOCK_MODE = 0x1, /* 01 */ SPI_BAM_MODE = 0x3, /* 11 */ SPI_MODE_NONE = 0xFF, /* invalid value */ }; /* Structure for SPI CS GPIOs */ struct spi_cs_gpio { int gpio_num; bool valid; }; /** * qup_i2c_clk_path_vote: data to use bus scaling driver for clock path vote * * @client_hdl when zero, client is not registered with the bus scaling driver, * and bus scaling functionality should not be used. When non zero, it * is a bus scaling client id and may be used to vote for clock path. * @reg_err when true, registration error was detected and an error message was * logged. i2c will attempt to re-register but will log error only once. * once registration succeed, the flag is set to false. */ struct qup_i2c_clk_path_vote { u32 client_hdl; struct msm_bus_scale_pdata *pdata; bool reg_err; }; struct spi_qup_bam_pipe { const char *name; struct sps_pipe *handle; struct sps_connect config; bool teardown_required; }; struct spi_qup_bam { void __iomem *base; phys_addr_t phys_addr; uintptr_t handle; u32 irq; struct spi_qup_bam_pipe prod; struct spi_qup_bam_pipe cons; bool deregister_required; u32 curr_rx_bytes_recvd; u32 curr_tx_bytes_sent; u32 bam_rx_len; u32 bam_tx_len; }; struct spi_qup { void __iomem *base; struct device *dev; struct clk *cclk; /* core clock */ struct clk *iclk; /* interface clock */ int irq; spinlock_t lock; int in_fifo_sz; int out_fifo_sz; int in_blk_sz; int out_blk_sz; struct spi_transfer *xfer; struct completion done; struct completion dma_tx_done; int error; int w_size; /* bytes per SPI word */ int n_words; int tx_bytes; int rx_bytes; const u8 *tx_buf; u8 *rx_buf; int qup_v1; int mode; struct dma_slave_config rx_conf; struct dma_slave_config tx_conf; }; /* Forward declaration */ static inline int spi_qup_set_state(struct spi_qup *dd, enum spi_qup_state state); #if defined(CONFIG_SPI_QSD) || defined(CONFIG_SPI_QSD_MODULE) static inline void spi_qup_disable_irqs(struct spi_qup *dd) { disable_irq(dd->irq); } #else static inline void spi_qup_disable_irqs(struct spi_qup *dd) { disable_irq(dd->irq); } static inline void spi_qup_enable_irqs(struct spi_qup *dd) { enable_irq(dd->irq); } static inline int spi_qup_prepare_for_write(struct spi_qup *dd) { if (spi_qup_set_state(dd, SPI_OP_STATE_RUN)) return -EINVAL; if (spi_qup_set_state(dd, SPI_OP_STATE_PAUSE)) return -EINVAL; return 0; } #endif #endif