diff options
author | Ravi Kumar Bokka <rbokka@codeaurora.org> | 2021-07-17 00:01:19 +0530 |
---|---|---|
committer | Shelley Chen <shchen@google.com> | 2021-09-21 19:40:39 +0000 |
commit | bd0984d2a11bc8ba0de28d40e53591156a8fc9ac (patch) | |
tree | 6ec879d46402f8af81b20ccde0ffce259d411852 /src/soc/qualcomm/sc7180 | |
parent | 7028c0ec4aadfd436d87faf76540ace0d16a2925 (diff) |
soc/qualcomm/common/spi: Add support for SPI common driver
This implements qup spi driver for qualcomm chipsets
Rename header file names for trogdor to prevent breakage.
BUG=b:182963902
TEST=Validated on qualcomm sc7180 and sc7280 development board.
Signed-off-by: Rajesh Patil <rajpat@codeaurora.org>
Change-Id: I2f2b25b6661fcd518f70383da0c7788c5269c97b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55953
Reviewed-by: Shelley Chen <shchen@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/qualcomm/sc7180')
-rw-r--r-- | src/soc/qualcomm/sc7180/Makefile.inc | 3 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/include/soc/qupv3_spi.h | 14 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/qupv3_spi.c | 220 |
3 files changed, 1 insertions, 236 deletions
diff --git a/src/soc/qualcomm/sc7180/Makefile.inc b/src/soc/qualcomm/sc7180/Makefile.inc index 0d7e4d62bd..8fb8b48e10 100644 --- a/src/soc/qualcomm/sc7180/Makefile.inc +++ b/src/soc/qualcomm/sc7180/Makefile.inc @@ -9,7 +9,7 @@ all-y += ../common/gpio.c all-y += ../common/spi.c all-$(CONFIG_SC7180_QSPI) += ../common/qspi.c all-y += ../common/qupv3_i2c.c -all-y += qupv3_spi.c +all-y += ../common/qupv3_spi.c all-y += clock.c all-y += ../common/clock.c all-y += qcom_qup_se.c @@ -20,7 +20,6 @@ all-y += ../common/qup_se_handler.c bootblock-y += bootblock.c bootblock-y += mmu.c bootblock-$(CONFIG_DRIVERS_UART) += ../common/uart_bitbang.c - ################################################################################ verstage-$(CONFIG_DRIVERS_UART) += qupv3_uart.c diff --git a/src/soc/qualcomm/sc7180/include/soc/qupv3_spi.h b/src/soc/qualcomm/sc7180/include/soc/qupv3_spi.h deleted file mode 100644 index 87c81fad62..0000000000 --- a/src/soc/qualcomm/sc7180/include/soc/qupv3_spi.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __SPI_QUP_QCOM_HEADER___ -#define __SPI_QUP_QCOM_HEADER___ - -#include <spi-generic.h> - -int qup_spi_claim_bus(const struct spi_slave *slave); -int qup_spi_xfer(const struct spi_slave *slave, const void *dout, - size_t bytes_out, void *din, size_t bytes_in); -void qup_spi_release_bus(const struct spi_slave *slave); -void qup_spi_init(unsigned int bus, unsigned int speed_hz); - -#endif /*__SPI_QUP_QCOM_HEADER___*/ diff --git a/src/soc/qualcomm/sc7180/qupv3_spi.c b/src/soc/qualcomm/sc7180/qupv3_spi.c deleted file mode 100644 index 9cf05ab7b2..0000000000 --- a/src/soc/qualcomm/sc7180/qupv3_spi.c +++ /dev/null @@ -1,220 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#include <assert.h> -#include <console/console.h> -#include <lib.h> -#include <soc/clock.h> -#include <soc/gpio.h> -#include <soc/qcom_qup_se.h> -#include <soc/qupv3_config_common.h> -#include <soc/qup_se_handlers_common.h> -#include <soc/qupv3_spi.h> -#include <types.h> - -/* SE_SPI_LOOPBACK register fields */ -#define LOOPBACK_ENABLE 0x1 - -/* SE_SPI_WORD_LEN register fields */ -#define WORD_LEN_MSK QC_GENMASK(9, 0) -#define MIN_WORD_LEN 4 - -/* SPI_TX/SPI_RX_TRANS_LEN fields */ -#define TRANS_LEN_MSK QC_GENMASK(23, 0) - -/* M_CMD OP codes for SPI */ -#define SPI_TX_ONLY 1 -#define SPI_RX_ONLY 2 -#define SPI_FULL_DUPLEX 3 -#define SPI_TX_RX 7 -#define SPI_CS_ASSERT 8 -#define SPI_CS_DEASSERT 9 -#define SPI_SCK_ONLY 10 - -/* M_CMD params for SPI */ -/* If fragmentation bit is set then CS will not toggle after each transfer */ -#define M_CMD_FRAGMENTATION BIT(2) - -#define BITS_PER_BYTE 8 -#define BITS_PER_WORD 8 -#define TX_WATERMARK 1 - -#define IRQ_TRIGGER (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN | \ - M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN | \ - M_CMD_CANCEL_EN | M_CMD_ABORT_EN) - -static void setup_fifo_params(const struct spi_slave *slave) -{ - unsigned int se_bus = slave->bus; - struct qup_regs *regs = qup[se_bus].regs; - u32 word_len = 0; - - /* Disable loopback mode */ - write32(®s->proto_loopback_cfg, 0); - - write32(®s->spi_demux_sel, slave->cs); - word_len = ((BITS_PER_WORD - MIN_WORD_LEN) & WORD_LEN_MSK); - write32(®s->spi_word_len, word_len); - - /* FIFO PACKING CONFIGURATION */ - write32(®s->geni_tx_packing_cfg0, PACK_VECTOR0 - | (PACK_VECTOR1 << 10)); - write32(®s->geni_tx_packing_cfg1, PACK_VECTOR2 - | (PACK_VECTOR3 << 10)); - write32(®s->geni_rx_packing_cfg0, PACK_VECTOR0 - | (PACK_VECTOR1 << 10)); - write32(®s->geni_rx_packing_cfg1, PACK_VECTOR2 - | (PACK_VECTOR3 << 10)); - write32(®s->geni_byte_granularity, (log2(BITS_PER_WORD) - 3)); -} - -static void qup_setup_m_cmd(unsigned int se_bus, u32 cmd, u32 params) -{ - struct qup_regs *regs = qup[se_bus].regs; - u32 m_cmd = (cmd << M_OPCODE_SHFT); - - m_cmd |= (params & M_PARAMS_MSK); - write32(®s->geni_m_cmd0, m_cmd); -} - -int qup_spi_xfer(const struct spi_slave *slave, const void *dout, - size_t bytes_out, void *din, size_t bytes_in) -{ - u32 m_cmd = 0; - u32 m_param = M_CMD_FRAGMENTATION; - int size; - unsigned int se_bus = slave->bus; - struct qup_regs *regs = qup[se_bus].regs; - - if ((bytes_in == 0) && (bytes_out == 0)) - return 0; - - setup_fifo_params(slave); - - if (!bytes_out) { - size = bytes_in; - m_cmd = SPI_RX_ONLY; - dout = NULL; - } else if (!bytes_in) { - size = bytes_out; - m_cmd = SPI_TX_ONLY; - din = NULL; - } else { - size = MIN(bytes_in, bytes_out); - m_cmd = SPI_FULL_DUPLEX; - } - - /* Check for maximum permissible transfer length */ - assert(!(size & ~TRANS_LEN_MSK)); - - if (bytes_out) { - write32(®s->spi_tx_trans_len, size); - write32(®s->geni_tx_watermark_reg, TX_WATERMARK); - } - if (bytes_in) - write32(®s->spi_rx_trans_len, size); - - qup_setup_m_cmd(se_bus, m_cmd, m_param); - - if (qup_handle_transfer(se_bus, dout, din, size)) - return -1; - - qup_spi_xfer(slave, dout + size, MAX((int)bytes_out - size, 0), - din + size, MAX((int)bytes_in - size, 0)); - - return 0; -} - -static int spi_qup_set_cs(const struct spi_slave *slave, bool enable) -{ - u32 m_cmd = 0; - u32 m_irq = 0; - unsigned int se_bus = slave->bus; - struct stopwatch sw; - - m_cmd = (enable) ? SPI_CS_ASSERT : SPI_CS_DEASSERT; - qup_setup_m_cmd(se_bus, m_cmd, 0); - - stopwatch_init_usecs_expire(&sw, 100); - do { - m_irq = qup_wait_for_m_irq(se_bus); - if (m_irq & M_CMD_DONE_EN) { - write32(&qup[se_bus].regs->geni_m_irq_clear, m_irq); - break; - } - write32(&qup[se_bus].regs->geni_m_irq_clear, m_irq); - } while (!stopwatch_expired(&sw)); - - if (!(m_irq & M_CMD_DONE_EN)) { - printk(BIOS_INFO, "%s:Failed to %s chip\n", __func__, - (enable) ? "Assert" : "Deassert"); - qup_m_cancel_and_abort(se_bus); - return -1; - } - return 0; -} - -void qup_spi_init(unsigned int bus, unsigned int speed_hz) -{ - u32 m_clk_cfg = 0, div = DEFAULT_SE_CLK / speed_hz; - struct qup_regs *regs = qup[bus].regs; - - /* Make sure div can hit target frequency within +/- 1KHz range */ - assert(((DEFAULT_SE_CLK - speed_hz * div) <= div * KHz) && (div > 0)); - qupv3_se_fw_load_and_init(bus, SE_PROTOCOL_SPI, MIXED); - clock_enable_qup(bus); - m_clk_cfg |= ((div << CLK_DIV_SHFT) | SER_CLK_EN); - write32(®s->geni_ser_m_clk_cfg, m_clk_cfg); - /* Mode:0, cpha=0, cpol=0 */ - write32(®s->spi_cpha, 0); - write32(®s->spi_cpol, 0); - - /* Serial engine IO initialization */ - write32(®s->geni_cgc_ctrl, DEFAULT_CGC_EN); - write32(®s->dma_general_cfg, - (AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON - | DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON)); - write32(®s->geni_output_ctrl, - DEFAULT_IO_OUTPUT_CTRL_MSK); - write32(®s->geni_force_default_reg, FORCE_DEFAULT); - - /* Serial engine IO set mode */ - write32(®s->se_irq_en, (GENI_M_IRQ_EN | - GENI_S_IRQ_EN | DMA_TX_IRQ_EN | DMA_RX_IRQ_EN)); - write32(®s->se_gsi_event_en, 0); - - /* Set RX and RFR watermark */ - write32(®s->geni_rx_watermark_reg, 0); - write32(®s->geni_rx_rfr_watermark_reg, FIFO_DEPTH - 2); - - /* GPIO Configuration */ - gpio_configure(qup[bus].pin[0], qup[bus].func[0], GPIO_NO_PULL, - GPIO_6MA, GPIO_INPUT); /* MISO */ - gpio_configure(qup[bus].pin[1], qup[bus].func[1], GPIO_NO_PULL, - GPIO_6MA, GPIO_OUTPUT); /* MOSI */ - gpio_configure(qup[bus].pin[2], qup[bus].func[2], GPIO_NO_PULL, - GPIO_6MA, GPIO_OUTPUT); /* CLK */ - gpio_configure(qup[bus].pin[3], qup[bus].func[3], GPIO_NO_PULL, - GPIO_6MA, GPIO_OUTPUT); /* CS */ - - /* Select and setup FIFO mode */ - write32(®s->geni_m_irq_clear, 0xFFFFFFFF); - write32(®s->geni_s_irq_clear, 0xFFFFFFFF); - write32(®s->dma_tx_irq_clr, 0xFFFFFFFF); - write32(®s->dma_rx_irq_clr, 0xFFFFFFFF); - write32(®s->geni_m_irq_enable, (M_COMMON_GENI_M_IRQ_EN | - M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN | - M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)); - write32(®s->geni_s_irq_enable, (S_COMMON_GENI_S_IRQ_EN - | S_CMD_DONE_EN)); - clrbits32(®s->geni_dma_mode_en, GENI_DMA_MODE_EN); -} - -int qup_spi_claim_bus(const struct spi_slave *slave) -{ - return spi_qup_set_cs(slave, 1); -} - -void qup_spi_release_bus(const struct spi_slave *slave) -{ - spi_qup_set_cs(slave, 0); -} |