sdm845: Add SPI-NOR flash driver
TEST=build & run Change-Id: Ie404faf37617d2ad792310709ca2063f9a372076 Signed-off-by: Mukesh Savaliya <msavaliy@codeaurora.org> Reviewed-on: https://review.coreboot.org/c/25392 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
03f05cff2f
commit
b02452b490
|
@ -6,10 +6,11 @@ if BOARD_GOOGLE_CHEZA_COMMON
|
||||||
|
|
||||||
config BOARD_SPECIFIC_OPTIONS
|
config BOARD_SPECIFIC_OPTIONS
|
||||||
def_bool y
|
def_bool y
|
||||||
select BOARD_ROMSIZE_KB_8192
|
select BOARD_ROMSIZE_KB_16384
|
||||||
select COMMON_CBFS_SPI_WRAPPER
|
select COMMON_CBFS_SPI_WRAPPER
|
||||||
select SOC_QUALCOMM_SDM845
|
select SOC_QUALCOMM_SDM845
|
||||||
select SPI_FLASH
|
select SPI_FLASH
|
||||||
|
select SPI_FLASH_WINBOND
|
||||||
select MAINBOARD_HAS_CHROMEOS
|
select MAINBOARD_HAS_CHROMEOS
|
||||||
select MISSING_BOARD_RESET
|
select MISSING_BOARD_RESET
|
||||||
|
|
||||||
|
|
|
@ -19,4 +19,14 @@ config VBOOT
|
||||||
select VBOOT_RETURN_FROM_VERSTAGE
|
select VBOOT_RETURN_FROM_VERSTAGE
|
||||||
select VBOOT_OPROM_MATTERS
|
select VBOOT_OPROM_MATTERS
|
||||||
select VBOOT_STARTS_IN_BOOTBLOCK
|
select VBOOT_STARTS_IN_BOOTBLOCK
|
||||||
|
|
||||||
|
config SDM845_QSPI
|
||||||
|
bool
|
||||||
|
default y if COMMON_CBFS_SPI_WRAPPER
|
||||||
|
prompt "Build Flash Using SPI-NOR"
|
||||||
|
|
||||||
|
config BOOT_DEVICE_SPI_FLASH_BUS
|
||||||
|
int
|
||||||
|
default 16
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -7,14 +7,15 @@ bootblock-y += spi.c
|
||||||
bootblock-y += mmu.c
|
bootblock-y += mmu.c
|
||||||
bootblock-y += timer.c
|
bootblock-y += timer.c
|
||||||
bootblock-y += gpio.c
|
bootblock-y += gpio.c
|
||||||
bootblock-$(CONFIG_DRIVERS_UART) += uart_bitbang.c
|
|
||||||
bootblock-y += clock.c
|
bootblock-y += clock.c
|
||||||
|
bootblock-$(CONFIG_SDM845_QSPI) += qspi.c
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
verstage-y += spi.c
|
verstage-y += spi.c
|
||||||
verstage-y += timer.c
|
verstage-y += timer.c
|
||||||
verstage-y += gpio.c
|
verstage-y += gpio.c
|
||||||
verstage-y += clock.c
|
verstage-y += clock.c
|
||||||
|
verstage-$(CONFIG_SDM845_QSPI) += qspi.c
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
romstage-y += spi.c
|
romstage-y += spi.c
|
||||||
|
@ -22,6 +23,7 @@ romstage-y += cbmem.c
|
||||||
romstage-y += timer.c
|
romstage-y += timer.c
|
||||||
romstage-y += gpio.c
|
romstage-y += gpio.c
|
||||||
romstage-y += clock.c
|
romstage-y += clock.c
|
||||||
|
romstage-$(CONFIG_SDM845_QSPI) += qspi.c
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
ramstage-y += soc.c
|
ramstage-y += soc.c
|
||||||
|
@ -30,6 +32,7 @@ ramstage-y += cbmem.c
|
||||||
ramstage-y += timer.c
|
ramstage-y += timer.c
|
||||||
ramstage-y += gpio.c
|
ramstage-y += gpio.c
|
||||||
ramstage-y += clock.c
|
ramstage-y += clock.c
|
||||||
|
ramstage-$(CONFIG_SDM845_QSPI) += qspi.c
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
#include <bootblock_common.h>
|
#include <bootblock_common.h>
|
||||||
#include <soc/mmu.h>
|
#include <soc/mmu.h>
|
||||||
#include <soc/clock.h>
|
#include <soc/clock.h>
|
||||||
|
#include <soc/qspi.h>
|
||||||
|
|
||||||
void bootblock_soc_init(void)
|
void bootblock_soc_init(void)
|
||||||
{
|
{
|
||||||
clock_init();
|
clock_init();
|
||||||
sdm845_mmu_init();
|
sdm845_mmu_init();
|
||||||
|
quadspi_init(25 * MHz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
SSRAM_START(0x14680000)
|
SSRAM_START(0x14680000)
|
||||||
OVERLAP_VERSTAGE_ROMSTAGE(0x14680000, 128K)
|
OVERLAP_VERSTAGE_ROMSTAGE(0x14680000, 100K)
|
||||||
REGION(fw_reserved1, 0x146A0000, 0x20000, 4096)
|
DMA_COHERENT(0x14699000, 0x2000)
|
||||||
SSRAM_END(0x146C0000)
|
SSRAM_END(0x146C0000)
|
||||||
|
|
||||||
BSRAM_START(0x14800000)
|
BSRAM_START(0x14800000)
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright 2018 Qualcomm Technologies.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include <types.h>
|
||||||
|
#include <soc/addressmap.h>
|
||||||
|
#include <spi-generic.h>
|
||||||
|
|
||||||
|
#ifndef __SOC_QUALCOMM_SDM845_QSPI_H__
|
||||||
|
#define __SOC_QUALCOMM_SDM845_QSPI_H__
|
||||||
|
|
||||||
|
struct sdm845_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(sdm845_qspi_regs, rd_fifo, 0x50);
|
||||||
|
static struct sdm845_qspi_regs * const sdm845_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 sdm845_claim_bus(const struct spi_slave *slave);
|
||||||
|
int sdm845_setup_bus(const struct spi_slave *slave);
|
||||||
|
void sdm845_release_bus(const struct spi_slave *slave);
|
||||||
|
int sdm845_xfer(const struct spi_slave *slave, const void *dout,
|
||||||
|
size_t out_bytes, void *din, size_t in_bytes);
|
||||||
|
#endif /* __SOC_QUALCOMM_SDM845_QSPI_H__ */
|
|
@ -19,14 +19,19 @@
|
||||||
#include <soc/mmu.h>
|
#include <soc/mmu.h>
|
||||||
#include <soc/symbols.h>
|
#include <soc/symbols.h>
|
||||||
|
|
||||||
void sdm845_mmu_init()
|
#define CACHED_RAM (MA_MEM | MA_S | MA_RW)
|
||||||
|
#define UNCACHED_RAM (MA_MEM | MA_S | MA_RW | MA_MEM_NC)
|
||||||
|
#define DEV_MEM (MA_DEV | MA_S | MA_RW)
|
||||||
|
|
||||||
|
void sdm845_mmu_init(void)
|
||||||
{
|
{
|
||||||
mmu_init();
|
mmu_init();
|
||||||
|
|
||||||
mmu_config_range((void *)(4 * KiB), ((4UL * GiB) - (4 * KiB)),
|
mmu_config_range((void *)(4 * KiB), ((4UL * GiB) - (4 * KiB)), DEV_MEM);
|
||||||
MA_DEV | MA_S | MA_RW);
|
mmu_config_range((void *)_ssram, _ssram_size, CACHED_RAM);
|
||||||
mmu_config_range((void *)_ssram, _ssram_size, MA_MEM | MA_S | MA_RW);
|
mmu_config_range((void *)_bsram, _bsram_size, CACHED_RAM);
|
||||||
mmu_config_range((void *)_bsram, _bsram_size, MA_MEM | MA_S | MA_RW);
|
mmu_config_range((void *)_dma_coherent, _dma_coherent_size,
|
||||||
|
UNCACHED_RAM);
|
||||||
|
|
||||||
mmu_enable();
|
mmu_enable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <spi-generic.h>
|
||||||
|
#include <spi_flash.h>
|
||||||
|
#include <arch/cache.h>
|
||||||
|
#include <arch/io.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(&sdm845_qspi->mstr_int_sts, 0xFFFFFFFF);
|
||||||
|
write32(&sdm845_qspi->next_dma_desc_addr, (uint32_t)(uintptr_t) chain);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
mstr_int_status = read32(&sdm845_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;
|
||||||
|
next->fragment = 0;
|
||||||
|
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;
|
||||||
|
current->fragment = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cs_change(enum cs_state state)
|
||||||
|
{
|
||||||
|
gpio_set(GPIO(90), state == CS_DEASSERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void configure_gpios(void)
|
||||||
|
{
|
||||||
|
gpio_output(GPIO(90), 1);
|
||||||
|
|
||||||
|
gpio_configure(GPIO(91), GPIO91_FUNC_QSPI_DATA,
|
||||||
|
GPIO_NO_PULL, GPIO_2MA, GPIO_ENABLE);
|
||||||
|
|
||||||
|
gpio_configure(GPIO(92), GPIO92_FUNC_QSPI_DATA,
|
||||||
|
GPIO_NO_PULL, GPIO_2MA, GPIO_ENABLE);
|
||||||
|
|
||||||
|
gpio_configure(GPIO(95), GPIO95_FUNC_QSPI_CLK,
|
||||||
|
GPIO_NO_PULL, GPIO_2MA, GPIO_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(&sdm845_qspi->mstr_cfg, mstr_config);
|
||||||
|
write32(&sdm845_qspi->ahb_mstr_cfg, 0xA42);
|
||||||
|
write32(&sdm845_qspi->mstr_int_en, 0x0);
|
||||||
|
write32(&sdm845_qspi->mstr_int_sts, 0xFFFFFFFF);
|
||||||
|
write32(&sdm845_qspi->rd_fifo_cfg, 0x0);
|
||||||
|
write32(&sdm845_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 sdm845_claim_bus(const struct spi_slave *slave)
|
||||||
|
{
|
||||||
|
cs_change(CS_ASSERT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdm845_release_bus(const struct spi_slave *slave)
|
||||||
|
{
|
||||||
|
cs_change(CS_DEASSERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sdm845_xfer(const struct spi_slave *slave, const void *dout,
|
||||||
|
size_t out_bytes, void *din, size_t in_bytes)
|
||||||
|
{
|
||||||
|
enum qspi_mode mode = SDR_1BIT;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -15,35 +15,20 @@
|
||||||
|
|
||||||
#include <spi-generic.h>
|
#include <spi-generic.h>
|
||||||
#include <spi_flash.h>
|
#include <spi_flash.h>
|
||||||
|
#include <soc/qspi.h>
|
||||||
static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spi_ctrlr_release_bus(const struct spi_slave *slave)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
|
|
||||||
size_t bytes_out, void *din, size_t bytes_in)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct spi_ctrlr spi_ctrlr = {
|
static const struct spi_ctrlr spi_ctrlr = {
|
||||||
.claim_bus = spi_ctrlr_claim_bus,
|
.claim_bus = sdm845_claim_bus,
|
||||||
.release_bus = spi_ctrlr_release_bus,
|
.release_bus = sdm845_release_bus,
|
||||||
.xfer = spi_ctrlr_xfer,
|
.xfer = sdm845_xfer,
|
||||||
.max_xfer_size = 65535,
|
.max_xfer_size = QSPI_MAX_PACKET_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
|
const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
|
||||||
{
|
{
|
||||||
.ctrlr = &spi_ctrlr,
|
.ctrlr = &spi_ctrlr,
|
||||||
.bus_start = 0,
|
.bus_start = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS,
|
||||||
.bus_end = 0,
|
.bus_end = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue