summaryrefslogtreecommitdiff
path: root/src/soc/qualcomm/sc7180
diff options
context:
space:
mode:
authorRavi Kumar Bokka <rbokka@codeaurora.org>2021-07-16 16:59:25 +0530
committerShelley Chen <shchen@google.com>2021-09-03 16:59:06 +0000
commit423945876dd632598ee842894cac50203c93d4ea (patch)
tree001b9f300894cee8f2f0cd06a45e2d1c8bef5858 /src/soc/qualcomm/sc7180
parent65af8bbe72125eeaf970e5e57102cb802d00fc69 (diff)
soc/qualcomm/common/qspi: Add support for common QSPI driver
copy existing QSPI driver from /soc/qualcomm/sc7180 to common folder. This common QSPI driver works in master mode and provides read/write operation for the slave devices like flash. BUG=b:182963902 TEST=Validated on qualcomm sc7180 and sc7280 development board Signed-off-by: Rajesh Patil <rajpat@codeaurora.org> Change-Id: I5b3816b823e14db1dd13f1eb4a6761c7a61604b9 Reviewed-on: https://review.coreboot.org/c/coreboot/+/55323 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Shelley Chen <shchen@google.com>
Diffstat (limited to 'src/soc/qualcomm/sc7180')
-rw-r--r--src/soc/qualcomm/sc7180/Makefile.inc4
-rw-r--r--src/soc/qualcomm/sc7180/bootblock.c2
-rw-r--r--src/soc/qualcomm/sc7180/include/soc/addressmap.h10
-rw-r--r--src/soc/qualcomm/sc7180/include/soc/qspi.h108
-rw-r--r--src/soc/qualcomm/sc7180/qspi.c296
-rw-r--r--src/soc/qualcomm/sc7180/spi.c36
6 files changed, 13 insertions, 443 deletions
diff --git a/src/soc/qualcomm/sc7180/Makefile.inc b/src/soc/qualcomm/sc7180/Makefile.inc
index 83f9eb5127..048faf59da 100644
--- a/src/soc/qualcomm/sc7180/Makefile.inc
+++ b/src/soc/qualcomm/sc7180/Makefile.inc
@@ -5,12 +5,12 @@ decompressor-y += decompressor.c
decompressor-y += mmu.c
decompressor-y += ../common/timer.c
all-y += ../common/timer.c
-all-y += spi.c
all-y += ../common/gpio.c
+all-y += ../common/spi.c
+all-$(CONFIG_SC7180_QSPI) += ../common/qspi.c
all-y += qupv3_i2c.c
all-y += qupv3_spi.c
all-y += clock.c
-all-$(CONFIG_SC7180_QSPI) += qspi.c
all-y += ../common/clock.c
all-y += qcom_qup_se.c
all-y += qupv3_config.c
diff --git a/src/soc/qualcomm/sc7180/bootblock.c b/src/soc/qualcomm/sc7180/bootblock.c
index cfeb6f94f2..be79ba6124 100644
--- a/src/soc/qualcomm/sc7180/bootblock.c
+++ b/src/soc/qualcomm/sc7180/bootblock.c
@@ -2,7 +2,7 @@
#include <bootblock_common.h>
#include <soc/clock.h>
-#include <soc/qspi.h>
+#include <soc/qspi_common.h>
#include <soc/qupv3_config.h>
void bootblock_soc_init(void)
diff --git a/src/soc/qualcomm/sc7180/include/soc/addressmap.h b/src/soc/qualcomm/sc7180/include/soc/addressmap.h
index 832ef42968..e360e8a30e 100644
--- a/src/soc/qualcomm/sc7180/include/soc/addressmap.h
+++ b/src/soc/qualcomm/sc7180/include/soc/addressmap.h
@@ -46,4 +46,14 @@
#define QMP_PHY_PCS_REG_BASE 0x088e9c00
#define USB_HOST_DWC3_BASE 0x0a60c100
+/* SC7180 QSPI GPIO PINS */
+#define QSPI_CLK GPIO(63)
+#define QSPI_DATA_0 GPIO(64)
+#define QSPI_DATA_1 GPIO(65)
+#define QSPI_CS GPIO(68)
+
+#define GPIO_FUNC_QSPI_DATA_0 GPIO64_FUNC_QSPI_DATA_0
+#define GPIO_FUNC_QSPI_DATA_1 GPIO65_FUNC_QSPI_DATA_1
+#define GPIO_FUNC_QSPI_CLK GPIO63_FUNC_QSPI_CLK
+
#endif /* __SOC_QUALCOMM_SC7180_ADDRESS_MAP_H__ */
diff --git a/src/soc/qualcomm/sc7180/include/soc/qspi.h b/src/soc/qualcomm/sc7180/include/soc/qspi.h
deleted file mode 100644
index bad3071b61..0000000000
--- a/src/soc/qualcomm/sc7180/include/soc/qspi.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#include <types.h>
-#include <soc/addressmap.h>
-#include <spi-generic.h>
-
-#ifndef __SOC_QUALCOMM_SC7180_QSPI_H__
-#define __SOC_QUALCOMM_SC7180_QSPI_H__
-
-struct sc7180_qspi_regs {
- u32 mstr_cfg;
- u32 ahb_mstr_cfg;
- u32 reserve_0;
- u32 mstr_int_en;
- u32 mstr_int_sts;
- u32 pio_xfer_ctrl;
- u32 pio_xfer_cfg;
- u32 pio_xfer_sts;
- u32 pio_dataout_1byte;
- u32 pio_dataout_4byte;
- u32 rd_fifo_cfg;
- u32 rd_fifo_sts;
- u32 rd_fifo_rst;
- u32 reserve_1[3];
- u32 next_dma_desc_addr;
- u32 current_dma_desc_addr;
- u32 current_mem_addr;
- u32 hw_version;
- u32 rd_fifo[16];
-};
-
-check_member(sc7180_qspi_regs, rd_fifo, 0x50);
-static struct sc7180_qspi_regs * const sc7180_qspi = (void *) QSPI_BASE;
-
-// MSTR_CONFIG register
-
-#define TX_DATA_OE_DELAY_SHIFT 24
-#define TX_DATA_OE_DELAY_MASK (0x3 << TX_DATA_OE_DELAY_SHIFT)
-#define TX_CS_N_DELAY_SHIFT 22
-#define TX_CS_N_DELAY_MASK (0x3 << TX_CS_N_DELAY_SHIFT)
-#define TX_CLK_DELAY_SHIFT 20
-#define TX_CLK_DELAY_MASK (0x3 << TX_CLK_DELAY_SHIFT)
-#define TX_DATA_DELAY_SHIFT 18
-#define TX_DATA_DELAY_MASK (0x3 << TX_DATA_DELAY_SHIFT)
-#define LPA_BASE_SHIFT 14
-#define LPA_BASE_MASK (0xF << LPA_BASE_SHIFT)
-#define SBL_EN BIT(13)
-#define CHIP_SELECT_NUM BIT(12)
-#define SPI_MODE_SHIFT 10
-#define SPI_MODE_MASK (0x3 << SPI_MODE_SHIFT)
-#define BIG_ENDIAN_MODE BIT(9)
-#define DMA_ENABLE BIT(8)
-#define PIN_WPN BIT(7)
-#define PIN_HOLDN BIT(6)
-#define FB_CLK_EN BIT(4)
-#define FULL_CYCLE_MODE BIT(3)
-
-// MSTR_INT_ENABLE and MSTR_INT_STATUS register
-
-#define DMA_CHAIN_DONE BIT(31)
-#define TRANSACTION_DONE BIT(16)
-#define WRITE_FIFO_OVERRUN BIT(11)
-#define WRITE_FIFO_FULL BIT(10)
-#define HRESP_FROM_NOC_ERR BIT(3)
-#define RESP_FIFO_RDY BIT(2)
-#define RESP_FIFO_NOT_EMPTY BIT(1)
-#define RESP_FIFO_UNDERRUN BIT(0)
-
-// PIO_TRANSFER_CONFIG register
-
-#define TRANSFER_FRAGMENT BIT(8)
-#define MULTI_IO_MODE_SHIFT 1
-#define MULTI_IO_MODE_MASK (0x7 << MULTI_IO_MODE_SHIFT)
-#define TRANSFER_DIRECTION BIT(0)
-
-// PIO_TRANSFER_STATUS register
-
-#define WR_FIFO_BYTES_SHIFT 16
-#define WR_FIFO_BYTES_MASK (0xFFFF << WR_FIFO_BYTES_SHIFT)
-
-// RD_FIFO_CONFIG register
-
-#define CONTINUOUS_MODE BIT(0)
-
-// RD_FIFO_STATUS register
-
-#define FIFO_EMPTY BIT(11)
-#define WR_CNTS_SHIFT 4
-#define WR_CNTS_MASK (0x7F << WR_CNTS_SHIFT)
-#define RDY_64BYTE BIT(3)
-#define RDY_32BYTE BIT(2)
-#define RDY_16BYTE BIT(1)
-#define FIFO_RDY BIT(0)
-
-// RD_FIFO_RESET register
-
-#define RESET_FIFO BIT(0)
-
-#define QSPI_MAX_PACKET_COUNT 0xFFC0
-
-void quadspi_init(uint32_t hz);
-int sc7180_claim_bus(const struct spi_slave *slave);
-int sc7180_setup_bus(const struct spi_slave *slave);
-void sc7180_release_bus(const struct spi_slave *slave);
-int sc7180_xfer(const struct spi_slave *slave, const void *dout,
- size_t out_bytes, void *din, size_t in_bytes);
-int sc7180_xfer_dual(const struct spi_slave *slave, const void *dout,
- size_t out_bytes, void *din, size_t in_bytes);
-#endif /* __SOC_QUALCOMM_SC7180_QSPI_H__ */
diff --git a/src/soc/qualcomm/sc7180/qspi.c b/src/soc/qualcomm/sc7180/qspi.c
deleted file mode 100644
index 825e298a73..0000000000
--- a/src/soc/qualcomm/sc7180/qspi.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#include <spi-generic.h>
-#include <spi_flash.h>
-#include <arch/cache.h>
-#include <device/mmio.h>
-#include <soc/addressmap.h>
-#include <soc/qspi.h>
-#include <soc/gpio.h>
-#include <soc/clock.h>
-#include <symbols.h>
-#include <assert.h>
-#include <gpio.h>
-#include <string.h>
-
-#define CACHE_LINE_SIZE 64
-
-static int curr_desc_idx = -1;
-
-struct cmd_desc {
- uint32_t data_address;
- uint32_t next_descriptor;
- uint32_t direction:1;
- uint32_t multi_io_mode:3;
- uint32_t reserved1:4;
- uint32_t fragment:1;
- uint32_t reserved2:7;
- uint32_t length:16;
- //------------------------//
- uint32_t bounce_src;
- uint32_t bounce_dst;
- uint32_t bounce_length;
- uint64_t padding[5];
-};
-
-enum qspi_mode {
- SDR_1BIT = 1,
- SDR_2BIT = 2,
- SDR_4BIT = 3,
- DDR_1BIT = 5,
- DDR_2BIT = 6,
- DDR_4BIT = 7,
-};
-
-enum cs_state {
- CS_DEASSERT,
- CS_ASSERT
-};
-
-struct xfer_cfg {
- enum qspi_mode mode;
-};
-
-enum bus_xfer_direction {
- MASTER_READ = 0,
- MASTER_WRITE = 1,
-};
-
-struct {
- struct cmd_desc descriptors[3];
- uint8_t buffers[3][CACHE_LINE_SIZE];
-} *dma = (void *)_dma_coherent;
-
-static void dma_transfer_chain(struct cmd_desc *chain)
-{
- uint32_t mstr_int_status;
-
- write32(&sc7180_qspi->mstr_int_sts, 0xFFFFFFFF);
- write32(&sc7180_qspi->next_dma_desc_addr, (uint32_t)(uintptr_t) chain);
-
- while (1) {
- mstr_int_status = read32(&sc7180_qspi->mstr_int_sts);
- if (mstr_int_status & DMA_CHAIN_DONE)
- break;
- }
-}
-
-static void flush_chain(void)
-{
- struct cmd_desc *desc = &dma->descriptors[0];
- uint8_t *src;
- uint8_t *dst;
-
- dma_transfer_chain(desc);
-
- while (desc) {
- if (desc->direction == MASTER_READ) {
- if (desc->bounce_length == 0)
- dcache_invalidate_by_mva(
- (void *)(uintptr_t) desc->data_address,
- desc->length);
- else {
- src = (void *)(uintptr_t) desc->bounce_src;
- dst = (void *)(uintptr_t) desc->bounce_dst;
- memcpy(dst, src, desc->bounce_length);
- }
- }
- desc = (void *)(uintptr_t) desc->next_descriptor;
- }
- curr_desc_idx = -1;
-}
-
-static struct cmd_desc *allocate_descriptor(void)
-{
- struct cmd_desc *current;
- struct cmd_desc *next;
- uint8_t index;
-
- current = (curr_desc_idx == -1) ?
- NULL : &dma->descriptors[curr_desc_idx];
-
- index = ++curr_desc_idx;
- next = &dma->descriptors[index];
-
- next->data_address = (uint32_t) (uintptr_t) dma->buffers[index];
-
- next->next_descriptor = 0;
- next->direction = MASTER_READ;
- next->multi_io_mode = 0;
- next->reserved1 = 0;
- /*
- * QSPI controller doesn't support transfer starts with read segment.
- * So to support read transfers that are not preceded by write, set
- * transfer fragment bit = 1
- */
- next->fragment = 1;
- next->reserved2 = 0;
- next->length = 0;
- next->bounce_src = 0;
- next->bounce_dst = 0;
- next->bounce_length = 0;
-
- if (current)
- current->next_descriptor = (uint32_t)(uintptr_t) next;
-
- return next;
-}
-
-static void cs_change(enum cs_state state)
-{
- gpio_set(GPIO(68), state == CS_DEASSERT);
-}
-
-static void configure_gpios(void)
-{
- gpio_output(GPIO(68), 1);
-
- gpio_configure(GPIO(64), GPIO64_FUNC_QSPI_DATA_0,
- GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT);
-
- gpio_configure(GPIO(65), GPIO65_FUNC_QSPI_DATA_1,
- GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT);
-
- gpio_configure(GPIO(63), GPIO63_FUNC_QSPI_CLK,
- GPIO_NO_PULL, GPIO_8MA, GPIO_OUTPUT);
-}
-
-static void queue_bounce_data(uint8_t *data, uint32_t data_bytes,
- enum qspi_mode data_mode, bool write)
-{
- struct cmd_desc *desc;
- uint8_t *ptr;
-
- desc = allocate_descriptor();
- desc->direction = write;
- desc->multi_io_mode = data_mode;
- ptr = (void *)(uintptr_t) desc->data_address;
-
- if (write) {
- memcpy(ptr, data, data_bytes);
- } else {
- desc->bounce_src = (uint32_t)(uintptr_t) ptr;
- desc->bounce_dst = (uint32_t)(uintptr_t) data;
- desc->bounce_length = data_bytes;
- }
-
- desc->length = data_bytes;
-}
-
-static void queue_direct_data(uint8_t *data, uint32_t data_bytes,
- enum qspi_mode data_mode, bool write)
-{
- struct cmd_desc *desc;
-
- desc = allocate_descriptor();
- desc->direction = write;
- desc->multi_io_mode = data_mode;
- desc->data_address = (uint32_t)(uintptr_t) data;
- desc->length = data_bytes;
-
- if (write)
- dcache_clean_by_mva(data, data_bytes);
- else
- dcache_invalidate_by_mva(data, data_bytes);
-}
-
-static void queue_data(uint8_t *data, uint32_t data_bytes,
- enum qspi_mode data_mode, bool write)
-{
- uint8_t *aligned_ptr;
- uint8_t *epilog_ptr;
- uint32_t prolog_bytes, aligned_bytes, epilog_bytes;
-
- if (data_bytes == 0)
- return;
-
- aligned_ptr =
- (uint8_t *)ALIGN_UP((uintptr_t)data, CACHE_LINE_SIZE);
-
- prolog_bytes = MIN(data_bytes, aligned_ptr - data);
- aligned_bytes = ALIGN_DOWN(data_bytes - prolog_bytes, CACHE_LINE_SIZE);
- epilog_bytes = data_bytes - prolog_bytes - aligned_bytes;
-
- epilog_ptr = data + prolog_bytes + aligned_bytes;
-
- if (prolog_bytes)
- queue_bounce_data(data, prolog_bytes, data_mode, write);
- if (aligned_bytes)
- queue_direct_data(aligned_ptr, aligned_bytes, data_mode, write);
- if (epilog_bytes)
- queue_bounce_data(epilog_ptr, epilog_bytes, data_mode, write);
-}
-
-static void reg_init(void)
-{
- uint32_t spi_mode;
- uint32_t tx_data_oe_delay, tx_data_delay;
- uint32_t mstr_config;
-
- spi_mode = 0;
-
- tx_data_oe_delay = 0;
- tx_data_delay = 0;
-
- mstr_config = (tx_data_oe_delay << TX_DATA_OE_DELAY_SHIFT) |
- (tx_data_delay << TX_DATA_DELAY_SHIFT) | (SBL_EN) |
- (spi_mode << SPI_MODE_SHIFT) |
- (PIN_HOLDN) |
- (FB_CLK_EN) |
- (DMA_ENABLE) |
- (FULL_CYCLE_MODE);
-
- write32(&sc7180_qspi->mstr_cfg, mstr_config);
- write32(&sc7180_qspi->ahb_mstr_cfg, 0xA42);
- write32(&sc7180_qspi->mstr_int_en, 0x0);
- write32(&sc7180_qspi->mstr_int_sts, 0xFFFFFFFF);
- write32(&sc7180_qspi->rd_fifo_cfg, 0x0);
- write32(&sc7180_qspi->rd_fifo_rst, RESET_FIFO);
-}
-
-void quadspi_init(uint32_t hz)
-{
- assert(dcache_line_bytes() == CACHE_LINE_SIZE);
- clock_configure_qspi(hz * 4);
- configure_gpios();
- reg_init();
-}
-
-int sc7180_claim_bus(const struct spi_slave *slave)
-{
- cs_change(CS_ASSERT);
- return 0;
-}
-
-void sc7180_release_bus(const struct spi_slave *slave)
-{
- cs_change(CS_DEASSERT);
-}
-
-static int xfer(enum qspi_mode mode, const void *dout, size_t out_bytes,
- void *din, size_t in_bytes)
-{
- if ((out_bytes && !dout) || (in_bytes && !din) ||
- (in_bytes && out_bytes)) {
- return -1;
- }
-
- queue_data((uint8_t *) (out_bytes ? dout : din),
- in_bytes | out_bytes, mode, !!out_bytes);
-
- flush_chain();
-
- return 0;
-}
-
-int sc7180_xfer(const struct spi_slave *slave, const void *dout,
- size_t out_bytes, void *din, size_t in_bytes)
-{
- return xfer(SDR_1BIT, dout, out_bytes, din, in_bytes);
-}
-
-int sc7180_xfer_dual(const struct spi_slave *slave, const void *dout,
- size_t out_bytes, void *din, size_t in_bytes)
-{
- return xfer(SDR_2BIT, dout, out_bytes, din, in_bytes);
-}
diff --git a/src/soc/qualcomm/sc7180/spi.c b/src/soc/qualcomm/sc7180/spi.c
deleted file mode 100644
index 45abe90e8c..0000000000
--- a/src/soc/qualcomm/sc7180/spi.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#include <spi-generic.h>
-#include <spi_flash.h>
-#include <soc/qspi.h>
-#include <soc/qupv3_spi.h>
-
-static const struct spi_ctrlr qspi_ctrlr = {
- .claim_bus = sc7180_claim_bus,
- .release_bus = sc7180_release_bus,
- .xfer = sc7180_xfer,
- .xfer_dual = sc7180_xfer_dual,
- .max_xfer_size = QSPI_MAX_PACKET_COUNT,
-};
-
-const struct spi_ctrlr spi_qup_ctrlr = {
- .claim_bus = qup_spi_claim_bus,
- .release_bus = qup_spi_release_bus,
- .xfer = qup_spi_xfer,
- .max_xfer_size = 65535,
-};
-
-const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
- {
- .ctrlr = &qspi_ctrlr,
- .bus_start = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS,
- .bus_end = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS,
- },
- {
- .ctrlr = &spi_qup_ctrlr,
- .bus_start = 0,
- .bus_end = 11,
- },
-};
-
-const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);