summaryrefslogtreecommitdiff
path: root/src/soc/qualcomm/sc7180
diff options
context:
space:
mode:
authorRavi Kumar Bokka <rbokka@codeaurora.org>2021-07-17 00:01:19 +0530
committerShelley Chen <shchen@google.com>2021-09-21 19:40:39 +0000
commitbd0984d2a11bc8ba0de28d40e53591156a8fc9ac (patch)
tree6ec879d46402f8af81b20ccde0ffce259d411852 /src/soc/qualcomm/sc7180
parent7028c0ec4aadfd436d87faf76540ace0d16a2925 (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.inc3
-rw-r--r--src/soc/qualcomm/sc7180/include/soc/qupv3_spi.h14
-rw-r--r--src/soc/qualcomm/sc7180/qupv3_spi.c220
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(&regs->proto_loopback_cfg, 0);
-
- write32(&regs->spi_demux_sel, slave->cs);
- word_len = ((BITS_PER_WORD - MIN_WORD_LEN) & WORD_LEN_MSK);
- write32(&regs->spi_word_len, word_len);
-
- /* FIFO PACKING CONFIGURATION */
- write32(&regs->geni_tx_packing_cfg0, PACK_VECTOR0
- | (PACK_VECTOR1 << 10));
- write32(&regs->geni_tx_packing_cfg1, PACK_VECTOR2
- | (PACK_VECTOR3 << 10));
- write32(&regs->geni_rx_packing_cfg0, PACK_VECTOR0
- | (PACK_VECTOR1 << 10));
- write32(&regs->geni_rx_packing_cfg1, PACK_VECTOR2
- | (PACK_VECTOR3 << 10));
- write32(&regs->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(&regs->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(&regs->spi_tx_trans_len, size);
- write32(&regs->geni_tx_watermark_reg, TX_WATERMARK);
- }
- if (bytes_in)
- write32(&regs->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(&regs->geni_ser_m_clk_cfg, m_clk_cfg);
- /* Mode:0, cpha=0, cpol=0 */
- write32(&regs->spi_cpha, 0);
- write32(&regs->spi_cpol, 0);
-
- /* Serial engine IO initialization */
- write32(&regs->geni_cgc_ctrl, DEFAULT_CGC_EN);
- write32(&regs->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(&regs->geni_output_ctrl,
- DEFAULT_IO_OUTPUT_CTRL_MSK);
- write32(&regs->geni_force_default_reg, FORCE_DEFAULT);
-
- /* Serial engine IO set mode */
- write32(&regs->se_irq_en, (GENI_M_IRQ_EN |
- GENI_S_IRQ_EN | DMA_TX_IRQ_EN | DMA_RX_IRQ_EN));
- write32(&regs->se_gsi_event_en, 0);
-
- /* Set RX and RFR watermark */
- write32(&regs->geni_rx_watermark_reg, 0);
- write32(&regs->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(&regs->geni_m_irq_clear, 0xFFFFFFFF);
- write32(&regs->geni_s_irq_clear, 0xFFFFFFFF);
- write32(&regs->dma_tx_irq_clr, 0xFFFFFFFF);
- write32(&regs->dma_rx_irq_clr, 0xFFFFFFFF);
- write32(&regs->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(&regs->geni_s_irq_enable, (S_COMMON_GENI_S_IRQ_EN
- | S_CMD_DONE_EN));
- clrbits32(&regs->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);
-}