1d27ba308SAdrian Chadd /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3d27ba308SAdrian Chadd * 4d27ba308SAdrian Chadd * Copyright (c) 2021 Adrian Chadd <adrian@FreeBSD.org> 5d27ba308SAdrian Chadd * 6d27ba308SAdrian Chadd * Redistribution and use in source and binary forms, with or without 7d27ba308SAdrian Chadd * modification, are permitted provided that the following conditions 8d27ba308SAdrian Chadd * are met: 9d27ba308SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 10d27ba308SAdrian Chadd * notice, this list of conditions and the following disclaimer. 11d27ba308SAdrian Chadd * 2. Redistributions in binary form must reproduce the above copyright 12d27ba308SAdrian Chadd * notice, this list of conditions and the following disclaimer in the 13d27ba308SAdrian Chadd * documentation and/or other materials provided with the distribution. 14d27ba308SAdrian Chadd * 15d27ba308SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d27ba308SAdrian Chadd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d27ba308SAdrian Chadd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d27ba308SAdrian Chadd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d27ba308SAdrian Chadd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d27ba308SAdrian Chadd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d27ba308SAdrian Chadd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d27ba308SAdrian Chadd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23d27ba308SAdrian Chadd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d27ba308SAdrian Chadd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d27ba308SAdrian Chadd * SUCH DAMAGE. 26d27ba308SAdrian Chadd */ 27d27ba308SAdrian Chadd 28d27ba308SAdrian Chadd #ifndef __QCOM_SPI_VAR_H__ 29d27ba308SAdrian Chadd #define __QCOM_SPI_VAR_H__ 30d27ba308SAdrian Chadd 31d27ba308SAdrian Chadd typedef enum { 32d27ba308SAdrian Chadd QCOM_SPI_HW_QPI_V1_1 = 1, 33d27ba308SAdrian Chadd QCOM_SPI_HW_QPI_V2_1 = 2, 34d27ba308SAdrian Chadd QCOM_SPI_HW_QPI_V2_2 = 3, 35d27ba308SAdrian Chadd } qcom_spi_hw_version_t; 36d27ba308SAdrian Chadd 37d27ba308SAdrian Chadd #define CS_MAX 4 38d27ba308SAdrian Chadd 39d27ba308SAdrian Chadd struct qcom_spi_softc { 40d27ba308SAdrian Chadd device_t sc_dev; 41d27ba308SAdrian Chadd device_t spibus; 42d27ba308SAdrian Chadd 43d27ba308SAdrian Chadd uint32_t sc_debug; 44d27ba308SAdrian Chadd 45d27ba308SAdrian Chadd struct resource *sc_mem_res; 46d27ba308SAdrian Chadd struct resource *sc_irq_res; 47d27ba308SAdrian Chadd void *sc_irq_h; 48d27ba308SAdrian Chadd 49d27ba308SAdrian Chadd struct mtx sc_mtx; 50d27ba308SAdrian Chadd bool sc_busy; /* an SPI transfer (cmd+data) 51d27ba308SAdrian Chadd * is active */ 52d27ba308SAdrian Chadd 53d27ba308SAdrian Chadd qcom_spi_hw_version_t hw_version; 54d27ba308SAdrian Chadd 55d27ba308SAdrian Chadd clk_t clk_core; /* QUP/SPI core */ 56d27ba308SAdrian Chadd clk_t clk_iface; /* SPI interface */ 57d27ba308SAdrian Chadd 58d27ba308SAdrian Chadd /* For GPIO chip selects .. */ 59d27ba308SAdrian Chadd gpio_pin_t cs_pins[CS_MAX]; 60d27ba308SAdrian Chadd 61d27ba308SAdrian Chadd struct { 62d27ba308SAdrian Chadd /* 63d27ba308SAdrian Chadd * FIFO size / block size in bytes. 64d27ba308SAdrian Chadd * 65d27ba308SAdrian Chadd * The FIFO slots are DWORD sized, not byte sized. 66d27ba308SAdrian Chadd * So if the transfer size is set to 8 bits per 67d27ba308SAdrian Chadd * word (which is what we'll support initially) 68d27ba308SAdrian Chadd * the effective available FIFO is 69d27ba308SAdrian Chadd * fifo_size / sizeof(uint32_t). 70d27ba308SAdrian Chadd */ 71d27ba308SAdrian Chadd uint32_t input_block_size; 72d27ba308SAdrian Chadd uint32_t output_block_size; 73d27ba308SAdrian Chadd uint32_t input_fifo_size; 74d27ba308SAdrian Chadd uint32_t output_fifo_size; 75d27ba308SAdrian Chadd 76d27ba308SAdrian Chadd uint32_t cs_select; 77d27ba308SAdrian Chadd uint32_t num_cs; 78d27ba308SAdrian Chadd uint32_t max_frequency; 79d27ba308SAdrian Chadd } config; 80d27ba308SAdrian Chadd 81d27ba308SAdrian Chadd struct { 82d27ba308SAdrian Chadd uint32_t transfer_mode; /* QUP_IO_M_MODE_* */ 83d27ba308SAdrian Chadd uint32_t transfer_word_size; /* how many bytes in a transfer word */ 84d27ba308SAdrian Chadd uint32_t frequency; 85d27ba308SAdrian Chadd bool cs_high; /* true if CS is high for active */ 86d27ba308SAdrian Chadd } state; 87d27ba308SAdrian Chadd 88d27ba308SAdrian Chadd struct { 89d27ba308SAdrian Chadd bool tx_dma_done; 90d27ba308SAdrian Chadd bool rx_dma_done; 91d27ba308SAdrian Chadd bool done; 92d27ba308SAdrian Chadd bool do_tx; 93d27ba308SAdrian Chadd bool do_rx; 94d27ba308SAdrian Chadd bool error; 95d27ba308SAdrian Chadd } intr; 96d27ba308SAdrian Chadd 97d27ba308SAdrian Chadd struct { 98d27ba308SAdrian Chadd bool active; /* a (sub) transfer is active */ 99d27ba308SAdrian Chadd uint32_t num_words; /* number of word_size words to transfer */ 100d27ba308SAdrian Chadd const char *tx_buf; 101d27ba308SAdrian Chadd int tx_len; 102d27ba308SAdrian Chadd int tx_offset; 103d27ba308SAdrian Chadd char *rx_buf; 104d27ba308SAdrian Chadd int rx_len; 105d27ba308SAdrian Chadd int rx_offset; 106d27ba308SAdrian Chadd bool done; 107d27ba308SAdrian Chadd } transfer; 108d27ba308SAdrian Chadd }; 109d27ba308SAdrian Chadd 110d27ba308SAdrian Chadd #define QCOM_SPI_QUP_VERSION_V1(sc) \ 111d27ba308SAdrian Chadd ((sc)->hw_version == QCOM_SPI_HW_QPI_V1_1) 112d27ba308SAdrian Chadd 113d27ba308SAdrian Chadd #define QCOM_SPI_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 114d27ba308SAdrian Chadd #define QCOM_SPI_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 115d27ba308SAdrian Chadd #define QCOM_SPI_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) 116d27ba308SAdrian Chadd #define QCOM_SPI_READ_4(sc, reg) bus_read_4((sc)->sc_mem_res, (reg)) 117d27ba308SAdrian Chadd #define QCOM_SPI_WRITE_4(sc, reg, val) bus_write_4((sc)->sc_mem_res, \ 118d27ba308SAdrian Chadd (reg), (val)) 119d27ba308SAdrian Chadd 120d27ba308SAdrian Chadd /* XXX TODO: the region size should be in the tag or softc */ 121d27ba308SAdrian Chadd #define QCOM_SPI_BARRIER_WRITE(sc) bus_barrier((sc)->sc_mem_res, \ 122d27ba308SAdrian Chadd 0, 0x600, BUS_SPACE_BARRIER_WRITE) 123d27ba308SAdrian Chadd #define QCOM_SPI_BARRIER_READ(sc) bus_barrier((sc)->sc_mem_res, \ 124d27ba308SAdrian Chadd 0, 0x600, BUS_SPACE_BARRIER_READ) 125d27ba308SAdrian Chadd #define QCOM_SPI_BARRIER_RW(sc) bus_barrier((sc)->sc_mem_res, \ 126d27ba308SAdrian Chadd 0, 0x600, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) 127d27ba308SAdrian Chadd 128d27ba308SAdrian Chadd extern int qcom_spi_hw_read_controller_transfer_sizes( 129d27ba308SAdrian Chadd struct qcom_spi_softc *sc); 130d27ba308SAdrian Chadd extern int qcom_spi_hw_qup_set_state_locked(struct qcom_spi_softc *sc, 131d27ba308SAdrian Chadd uint32_t state); 132d27ba308SAdrian Chadd extern int qcom_spi_hw_qup_init_locked(struct qcom_spi_softc *sc); 133d27ba308SAdrian Chadd extern int qcom_spi_hw_spi_init_locked(struct qcom_spi_softc *sc); 134d27ba308SAdrian Chadd extern int qcom_spi_hw_spi_cs_force(struct qcom_spi_softc *sc, int cs, 135d27ba308SAdrian Chadd bool enable); 136d27ba308SAdrian Chadd extern int qcom_spi_hw_interrupt_handle(struct qcom_spi_softc *sc); 137d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_transfer_selection(struct qcom_spi_softc *sc, 138d27ba308SAdrian Chadd uint32_t len); 139d27ba308SAdrian Chadd extern int qcom_spi_hw_complete_transfer(struct qcom_spi_softc *sc); 140d27ba308SAdrian Chadd 141d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_current_transfer(struct qcom_spi_softc *sc); 142d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_pio_transfer_cnt(struct qcom_spi_softc *sc); 143d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_block_transfer_cnt(struct qcom_spi_softc *sc); 144d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_io_modes(struct qcom_spi_softc *sc); 145d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_spi_io_clock_polarity( 146d27ba308SAdrian Chadd struct qcom_spi_softc *sc, bool cpol); 147d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_spi_config(struct qcom_spi_softc *sc, 148d27ba308SAdrian Chadd uint32_t clock_val, bool cpha); 149d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_qup_config(struct qcom_spi_softc *sc, 150d27ba308SAdrian Chadd bool is_tx, bool is_rx); 151d27ba308SAdrian Chadd extern int qcom_spi_hw_setup_operational_mask(struct qcom_spi_softc *sc); 152d27ba308SAdrian Chadd extern int qcom_spi_hw_ack_write_pio_fifo(struct qcom_spi_softc *sc); 153d27ba308SAdrian Chadd extern int qcom_spi_hw_ack_opmode(struct qcom_spi_softc *sc); 154d27ba308SAdrian Chadd extern int qcom_spi_hw_write_pio_fifo(struct qcom_spi_softc *sc); 155d27ba308SAdrian Chadd extern int qcom_spi_hw_write_pio_block(struct qcom_spi_softc *sc); 156d27ba308SAdrian Chadd extern int qcom_spi_hw_read_pio_fifo(struct qcom_spi_softc *sc); 157d27ba308SAdrian Chadd extern int qcom_spi_hw_read_pio_block(struct qcom_spi_softc *sc); 158d27ba308SAdrian Chadd extern int qcom_spi_hw_do_full_reset(struct qcom_spi_softc *sc); 159d27ba308SAdrian Chadd 160d27ba308SAdrian Chadd #endif /* __QCOM_SPI_VAR_H__ */ 161