diff options
author | Ravi Kumar Bokka <rbokka@codeaurora.org> | 2021-07-16 16:59:25 +0530 |
---|---|---|
committer | Shelley Chen <shchen@google.com> | 2021-09-03 16:59:06 +0000 |
commit | 423945876dd632598ee842894cac50203c93d4ea (patch) | |
tree | 001b9f300894cee8f2f0cd06a45e2d1c8bef5858 /src/soc/qualcomm/sc7180 | |
parent | 65af8bbe72125eeaf970e5e57102cb802d00fc69 (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.inc | 4 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/bootblock.c | 2 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/include/soc/addressmap.h | 10 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/include/soc/qspi.h | 108 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/qspi.c | 296 | ||||
-rw-r--r-- | src/soc/qualcomm/sc7180/spi.c | 36 |
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); |