Merge branch 'master' of git://git.denx.de/u-boot-spi

This commit is contained in:
Tom Rini 2015-12-11 15:07:44 -05:00
commit 5076c64a08
12 changed files with 465 additions and 419 deletions

View File

@ -13,7 +13,11 @@ Andreas Bießmann <andreas.devel@googlemail.com>
Aneesh V <aneesh@ti.com> Aneesh V <aneesh@ti.com>
Dirk Behme <dirk.behme@googlemail.com> Dirk Behme <dirk.behme@googlemail.com>
Fabio Estevam <fabio.estevam@freescale.com> Fabio Estevam <fabio.estevam@freescale.com>
Jagannadha Sutradharudu Teki <402jagan@gmail.com> Jagan Teki <402jagan@gmail.com>
Jagan Teki <jaganna@gmail.com>
Jagan Teki <jaganna@xilinx.com>
Jagan Teki <jagannadh.teki@gmail.com>
Jagan Teki <jagannadha.sutradharudu-teki@xilinx.com>
Markus Klotzbuecher <mk@denx.de> Markus Klotzbuecher <mk@denx.de>
Prabhakar Kushwaha <prabhakar@freescale.com> Prabhakar Kushwaha <prabhakar@freescale.com>
Rajeshwari Shinde <rajeshwari.s@samsung.com> Rajeshwari Shinde <rajeshwari.s@samsung.com>

View File

@ -44,6 +44,9 @@ DECLARE_GLOBAL_DATA_PTR;
#define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_PU100KOHM | \ #define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_PU100KOHM | \
PAD_CTL_DSE_3P3V_49OHM) PAD_CTL_DSE_3P3V_49OHM)
#define QSPI_PAD_CTRL \
(PAD_CTL_DSE_3P3V_49OHM | PAD_CTL_PUE | PAD_CTL_PUS_PU47KOHM)
#ifdef CONFIG_SYS_I2C_MXC #ifdef CONFIG_SYS_I2C_MXC
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL) #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
/* I2C1 for PMIC */ /* I2C1 for PMIC */
@ -455,6 +458,29 @@ int board_phy_config(struct phy_device *phydev)
} }
#endif #endif
#ifdef CONFIG_FSL_QSPI
static iomux_v3_cfg_t const quadspi_pads[] = {
MX7D_PAD_EPDC_DATA00__QSPI_A_DATA0 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
MX7D_PAD_EPDC_DATA01__QSPI_A_DATA1 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
MX7D_PAD_EPDC_DATA02__QSPI_A_DATA2 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
MX7D_PAD_EPDC_DATA03__QSPI_A_DATA3 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
MX7D_PAD_EPDC_DATA05__QSPI_A_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL),
MX7D_PAD_EPDC_DATA06__QSPI_A_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL),
};
int board_qspi_init(void)
{
/* Set the iomux */
imx_iomux_v3_setup_multiple_pads(quadspi_pads,
ARRAY_SIZE(quadspi_pads));
/* Set the clock */
set_clk_qspi();
return 0;
}
#endif
int board_early_init_f(void) int board_early_init_f(void)
{ {
setup_iomux_uart(); setup_iomux_uart();
@ -481,6 +507,10 @@ int board_init(void)
setup_lcd(); setup_lcd();
#endif #endif
#ifdef CONFIG_FSL_QSPI
board_qspi_init();
#endif
return 0; return 0;
} }

View File

@ -12,11 +12,7 @@ obj-$(CONFIG_SPL_SPI_LOAD) += spi_spl_load.o
obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o
endif endif
#ifndef CONFIG_DM_SPI obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o sf_params.o sf.o
obj-$(CONFIG_SPI_FLASH) += sf_probe.o
#endif
obj-$(CONFIG_CMD_SF) += sf.o
obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o

View File

@ -44,13 +44,10 @@ enum {
#endif #endif
SECT_32K = 1 << 1, SECT_32K = 1 << 1,
E_FSR = 1 << 2, E_FSR = 1 << 2,
SST_BP = 1 << 3, SST_WR = 1 << 3,
SST_WP = 1 << 4, WR_QPP = 1 << 4,
WR_QPP = 1 << 5,
}; };
#define SST_WR (SST_BP | SST_WP)
enum spi_nor_option_flags { enum spi_nor_option_flags {
SNOR_F_SST_WR = (1 << 0), SNOR_F_SST_WR = (1 << 0),
SNOR_F_USE_FSR = (1 << 1), SNOR_F_USE_FSR = (1 << 1),
@ -66,6 +63,7 @@ enum spi_nor_option_flags {
#define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 #define SPI_FLASH_CFI_MFR_MACRONIX 0xc2
#define SPI_FLASH_CFI_MFR_SST 0xbf #define SPI_FLASH_CFI_MFR_SST 0xbf
#define SPI_FLASH_CFI_MFR_WINBOND 0xef #define SPI_FLASH_CFI_MFR_WINBOND 0xef
#define SPI_FLASH_CFI_MFR_ATMEL 0x1f
/* Erase commands */ /* Erase commands */
#define CMD_ERASE_4K 0x20 #define CMD_ERASE_4K 0x20
@ -171,12 +169,6 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
/* Flash erase(sectors) operation, support all possible erase commands */ /* Flash erase(sectors) operation, support all possible erase commands */
int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
/* Read the status register */
int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs);
/* Program the status register */
int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws);
/* Lock stmicro spi flash region */ /* Lock stmicro spi flash region */
int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);
@ -186,12 +178,6 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len);
/* Check if a stmicro spi flash region is completely locked */ /* Check if a stmicro spi flash region is completely locked */
int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len);
/* Read the config register */
int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc);
/* Program the config register */
int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc);
/* Enable writing on the SPI flash */ /* Enable writing on the SPI flash */
static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
{ {
@ -204,12 +190,6 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
} }
/*
* Send the read status command to the device and wait for the wip
* (write-in-progress) bit to clear itself.
*/
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
/* /*
* Used for spi_flash write operation * Used for spi_flash write operation
* - SPI claim * - SPI claim
@ -245,4 +225,16 @@ int spi_flash_mtd_register(struct spi_flash *flash);
void spi_flash_mtd_unregister(void); void spi_flash_mtd_unregister(void);
#endif #endif
/**
* spi_flash_scan - scan the SPI FLASH
* @flash: the spi flash structure
*
* The drivers can use this fuction to scan the SPI FLASH.
* In the scanning, it will try to get all the necessary information to
* fill the spi_flash{}.
*
* Return: 0 for success, others for failure.
*/
int spi_flash_scan(struct spi_flash *flash);
#endif /* _SF_INTERNAL_H_ */ #endif /* _SF_INTERNAL_H_ */

View File

@ -11,327 +11,21 @@
#include <common.h> #include <common.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <fdtdec.h>
#include <malloc.h> #include <malloc.h>
#include <mapmem.h>
#include <spi.h> #include <spi.h>
#include <spi_flash.h> #include <spi_flash.h>
#include <asm/io.h>
#include "sf_internal.h" #include "sf_internal.h"
DECLARE_GLOBAL_DATA_PTR;
/* Read commands array */
static u8 spi_read_cmds_array[] = {
CMD_READ_ARRAY_SLOW,
CMD_READ_ARRAY_FAST,
CMD_READ_DUAL_OUTPUT_FAST,
CMD_READ_DUAL_IO_FAST,
CMD_READ_QUAD_OUTPUT_FAST,
CMD_READ_QUAD_IO_FAST,
};
#ifdef CONFIG_SPI_FLASH_MACRONIX
static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
{
u8 qeb_status;
int ret;
ret = spi_flash_cmd_read_status(flash, &qeb_status);
if (ret < 0)
return ret;
if (qeb_status & STATUS_QEB_MXIC) {
debug("SF: mxic: QEB is already set\n");
} else {
ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
}
return ret;
}
#endif
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
static int spi_flash_set_qeb_winspan(struct spi_flash *flash)
{
u8 qeb_status;
int ret;
ret = spi_flash_cmd_read_config(flash, &qeb_status);
if (ret < 0)
return ret;
if (qeb_status & STATUS_QEB_WINSPAN) {
debug("SF: winspan: QEB is already set\n");
} else {
ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN);
if (ret < 0)
return ret;
}
return ret;
}
#endif
static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
{
switch (idcode0) {
#ifdef CONFIG_SPI_FLASH_MACRONIX
case SPI_FLASH_CFI_MFR_MACRONIX:
return spi_flash_set_qeb_mxic(flash);
#endif
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
case SPI_FLASH_CFI_MFR_SPANSION:
case SPI_FLASH_CFI_MFR_WINBOND:
return spi_flash_set_qeb_winspan(flash);
#endif
#ifdef CONFIG_SPI_FLASH_STMICRO
case SPI_FLASH_CFI_MFR_STMICRO:
debug("SF: QEB is volatile for %02x flash\n", idcode0);
return 0;
#endif
default:
printf("SF: Need set QEB func for %02x flash\n", idcode0);
return -1;
}
}
#ifdef CONFIG_SPI_FLASH_BAR
static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0)
{
u8 curr_bank = 0;
int ret;
if (flash->size <= SPI_FLASH_16MB_BOUN)
goto bank_end;
switch (idcode0) {
case SPI_FLASH_CFI_MFR_SPANSION:
flash->bank_read_cmd = CMD_BANKADDR_BRRD;
flash->bank_write_cmd = CMD_BANKADDR_BRWR;
default:
flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
}
ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
&curr_bank, 1);
if (ret) {
debug("SF: fail to read bank addr register\n");
return ret;
}
bank_end:
flash->bank_curr = curr_bank;
return 0;
}
#endif
static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
struct spi_flash *flash)
{
const struct spi_flash_params *params;
u8 cmd;
u16 jedec = idcode[1] << 8 | idcode[2];
u16 ext_jedec = idcode[3] << 8 | idcode[4];
/* Validate params from spi_flash_params table */
params = spi_flash_params_table;
for (; params->name != NULL; params++) {
if ((params->jedec >> 16) == idcode[0]) {
if ((params->jedec & 0xFFFF) == jedec) {
if (params->ext_jedec == 0)
break;
else if (params->ext_jedec == ext_jedec)
break;
}
}
}
if (!params->name) {
printf("SF: Unsupported flash IDs: ");
printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
idcode[0], jedec, ext_jedec);
return -EPROTONOSUPPORT;
}
/* Assign spi data */
flash->spi = spi;
flash->name = params->name;
flash->memory_map = spi->memory_map;
flash->dual_flash = flash->spi->option;
/* Assign spi flash flags */
if (params->flags & SST_WR)
flash->flags |= SNOR_F_SST_WR;
/* Assign spi_flash ops */
#ifndef CONFIG_DM_SPI_FLASH
flash->write = spi_flash_cmd_write_ops;
#if defined(CONFIG_SPI_FLASH_SST)
if (flash->flags & SNOR_F_SST_WR) {
if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
flash->write = sst_write_bp;
else
flash->write = sst_write_wp;
}
#endif
flash->erase = spi_flash_cmd_erase_ops;
flash->read = spi_flash_cmd_read_ops;
#endif
/* lock hooks are flash specific - assign them based on idcode0 */
switch (idcode[0]) {
#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
case SPI_FLASH_CFI_MFR_STMICRO:
case SPI_FLASH_CFI_MFR_SST:
flash->flash_lock = stm_lock;
flash->flash_unlock = stm_unlock;
flash->flash_is_locked = stm_is_locked;
#endif
break;
default:
debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
}
/* Compute the flash size */
flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
/*
* The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
* 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
* the 0x4d00 Extended JEDEC code have 512b pages. All of the others
* have 256b pages.
*/
if (ext_jedec == 0x4d00) {
if ((jedec == 0x0215) || (jedec == 0x216))
flash->page_size = 256;
else
flash->page_size = 512;
} else {
flash->page_size = 256;
}
flash->page_size <<= flash->shift;
flash->sector_size = params->sector_size << flash->shift;
flash->size = flash->sector_size * params->nr_sectors << flash->shift;
#ifdef CONFIG_SF_DUAL_FLASH
if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
flash->size <<= 1;
#endif
/* Compute erase sector and command */
if (params->flags & SECT_4K) {
flash->erase_cmd = CMD_ERASE_4K;
flash->erase_size = 4096 << flash->shift;
} else if (params->flags & SECT_32K) {
flash->erase_cmd = CMD_ERASE_32K;
flash->erase_size = 32768 << flash->shift;
} else {
flash->erase_cmd = CMD_ERASE_64K;
flash->erase_size = flash->sector_size;
}
/* Now erase size becomes valid sector size */
flash->sector_size = flash->erase_size;
/* Look for the fastest read cmd */
cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
if (cmd) {
cmd = spi_read_cmds_array[cmd - 1];
flash->read_cmd = cmd;
} else {
/* Go for default supported read cmd */
flash->read_cmd = CMD_READ_ARRAY_FAST;
}
/* Not require to look for fastest only two write cmds yet */
if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP)
flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
else
/* Go for default supported write cmd */
flash->write_cmd = CMD_PAGE_PROGRAM;
/* Read dummy_byte: dummy byte is determined based on the
* dummy cycles of a particular command.
* Fast commands - dummy_byte = dummy_cycles/8
* I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8
* For I/O commands except cmd[0] everything goes on no.of lines
* based on particular command but incase of fast commands except
* data all go on single line irrespective of command.
*/
switch (flash->read_cmd) {
case CMD_READ_QUAD_IO_FAST:
flash->dummy_byte = 2;
break;
case CMD_READ_ARRAY_SLOW:
flash->dummy_byte = 0;
break;
default:
flash->dummy_byte = 1;
}
#ifdef CONFIG_SPI_FLASH_STMICRO
if (params->flags & E_FSR)
flash->flags |= SNOR_F_USE_FSR;
#endif
/* Configure the BAR - discover bank cmds and read current bank */
#ifdef CONFIG_SPI_FLASH_BAR
int ret = spi_flash_read_bank(flash, idcode[0]);
if (ret < 0)
return ret;
#endif
/* Flash powers up read-only, so clear BP# bits */
#if defined(CONFIG_SPI_FLASH_ATMEL) || \
defined(CONFIG_SPI_FLASH_MACRONIX) || \
defined(CONFIG_SPI_FLASH_SST)
spi_flash_cmd_write_status(flash, 0);
#endif
return 0;
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
{
fdt_addr_t addr;
fdt_size_t size;
int node;
/* If there is no node, do nothing */
node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
if (node < 0)
return 0;
addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
if (addr == FDT_ADDR_T_NONE) {
debug("%s: Cannot decode address\n", __func__);
return 0;
}
if (flash->size != size) {
debug("%s: Memory map must cover entire device\n", __func__);
return -1;
}
flash->memory_map = map_sysmem(addr, size);
return 0;
}
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
/** /**
* spi_flash_probe_slave() - Probe for a SPI flash device on a bus * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
* *
* @spi: Bus to probe
* @flashp: Pointer to place to put flash info, which may be NULL if the * @flashp: Pointer to place to put flash info, which may be NULL if the
* space should be allocated * space should be allocated
*/ */
int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) static int spi_flash_probe_slave(struct spi_flash *flash)
{ {
u8 idcode[5]; struct spi_slave *spi = flash->spi;
int ret; int ret;
/* Setup spi_slave */ /* Setup spi_slave */
@ -347,59 +41,12 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
return ret; return ret;
} }
/* Read the ID codes */ ret = spi_flash_scan(flash);
ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
if (ret) { if (ret) {
printf("SF: Failed to get idcodes\n");
goto err_read_id;
}
#ifdef DEBUG
printf("SF: Got idcodes\n");
print_buffer(0, idcode, 1, sizeof(idcode), 0);
#endif
if (spi_flash_validate_params(spi, idcode, flash)) {
ret = -EINVAL; ret = -EINVAL;
goto err_read_id; goto err_read_id;
} }
/* Set the quad enable bit - only for quad commands */
if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
(flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
(flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
if (spi_flash_set_qeb(flash, idcode[0])) {
debug("SF: Fail to set QEB for %02x\n", idcode[0]);
ret = -EINVAL;
goto err_read_id;
}
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
debug("SF: FDT decode error\n");
ret = -EINVAL;
goto err_read_id;
}
#endif
#ifndef CONFIG_SPL_BUILD
printf("SF: Detected %s with page size ", flash->name);
print_size(flash->page_size, ", erase size ");
print_size(flash->erase_size, ", total ");
print_size(flash->size, "");
if (flash->memory_map)
printf(", mapped at %p", flash->memory_map);
puts("\n");
#endif
#ifndef CONFIG_SPI_FLASH_BAR
if (((flash->dual_flash == SF_SINGLE_FLASH) &&
(flash->size > SPI_FLASH_16MB_BOUN)) ||
((flash->dual_flash > SF_SINGLE_FLASH) &&
(flash->size > SPI_FLASH_16MB_BOUN << 1))) {
puts("SF: Warning - Only lower 16MiB accessible,");
puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
}
#endif
#ifdef CONFIG_SPI_FLASH_MTD #ifdef CONFIG_SPI_FLASH_MTD
ret = spi_flash_mtd_register(flash); ret = spi_flash_mtd_register(flash);
#endif #endif
@ -410,7 +57,7 @@ err_read_id:
} }
#ifndef CONFIG_DM_SPI_FLASH #ifndef CONFIG_DM_SPI_FLASH
struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
{ {
struct spi_flash *flash; struct spi_flash *flash;
@ -421,7 +68,8 @@ struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
return NULL; return NULL;
} }
if (spi_flash_probe_slave(bus, flash)) { flash->spi = bus;
if (spi_flash_probe_slave(flash)) {
spi_free_slave(bus); spi_free_slave(bus);
free(flash); free(flash);
return NULL; return NULL;
@ -473,7 +121,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
return spi_flash_cmd_read_ops(flash, offset, len, buf); return spi_flash_cmd_read_ops(flash, offset, len, buf);
} }
int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
const void *buf) const void *buf)
{ {
struct spi_flash *flash = dev_get_uclass_priv(dev); struct spi_flash *flash = dev_get_uclass_priv(dev);
@ -490,14 +138,14 @@ int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
return spi_flash_cmd_write_ops(flash, offset, len, buf); return spi_flash_cmd_write_ops(flash, offset, len, buf);
} }
int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
{ {
struct spi_flash *flash = dev_get_uclass_priv(dev); struct spi_flash *flash = dev_get_uclass_priv(dev);
return spi_flash_cmd_erase_ops(flash, offset, len); return spi_flash_cmd_erase_ops(flash, offset, len);
} }
int spi_flash_std_probe(struct udevice *dev) static int spi_flash_std_probe(struct udevice *dev)
{ {
struct spi_slave *slave = dev_get_parent_priv(dev); struct spi_slave *slave = dev_get_parent_priv(dev);
struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
@ -505,8 +153,9 @@ int spi_flash_std_probe(struct udevice *dev)
flash = dev_get_uclass_priv(dev); flash = dev_get_uclass_priv(dev);
flash->dev = dev; flash->dev = dev;
flash->spi = slave;
debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
return spi_flash_probe_slave(slave, flash); return spi_flash_probe_slave(flash);
} }
static const struct dm_spi_flash_ops spi_flash_std_ops = { static const struct dm_spi_flash_ops spi_flash_std_ops = {

View File

@ -1,9 +1,10 @@
/* /*
* SPI flash operations * SPI Flash Core
* *
* Copyright (C) 2008 Atmel Corporation * Copyright (C) 2015 Jagan Teki <jteki@openedev.com>
* Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
* Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
* Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
* Copyright (C) 2008 Atmel Corporation
* *
* SPDX-License-Identifier: GPL-2.0+ * SPDX-License-Identifier: GPL-2.0+
*/ */
@ -11,14 +12,15 @@
#include <common.h> #include <common.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <mapmem.h>
#include <spi.h> #include <spi.h>
#include <spi_flash.h> #include <spi_flash.h>
#include <watchdog.h>
#include <linux/compiler.h>
#include <linux/log2.h> #include <linux/log2.h>
#include "sf_internal.h" #include "sf_internal.h"
DECLARE_GLOBAL_DATA_PTR;
static void spi_flash_addr(u32 addr, u8 *cmd) static void spi_flash_addr(u32 addr, u8 *cmd)
{ {
/* cmd[0] is actual command */ /* cmd[0] is actual command */
@ -27,7 +29,17 @@ static void spi_flash_addr(u32 addr, u8 *cmd)
cmd[3] = addr >> 0; cmd[3] = addr >> 0;
} }
int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) /* Read commands array */
static u8 spi_read_cmds_array[] = {
CMD_READ_ARRAY_SLOW,
CMD_READ_ARRAY_FAST,
CMD_READ_DUAL_OUTPUT_FAST,
CMD_READ_DUAL_IO_FAST,
CMD_READ_QUAD_OUTPUT_FAST,
CMD_READ_QUAD_IO_FAST,
};
static int read_sr(struct spi_flash *flash, u8 *rs)
{ {
int ret; int ret;
u8 cmd; u8 cmd;
@ -56,7 +68,7 @@ static int read_fsr(struct spi_flash *flash, u8 *fsr)
return 0; return 0;
} }
int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) static int write_sr(struct spi_flash *flash, u8 ws)
{ {
u8 cmd; u8 cmd;
int ret; int ret;
@ -72,7 +84,7 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws)
} }
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) static int read_cr(struct spi_flash *flash, u8 *rc)
{ {
int ret; int ret;
u8 cmd; u8 cmd;
@ -87,13 +99,13 @@ int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc)
return 0; return 0;
} }
int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) static int write_cr(struct spi_flash *flash, u8 wc)
{ {
u8 data[2]; u8 data[2];
u8 cmd; u8 cmd;
int ret; int ret;
ret = spi_flash_cmd_read_status(flash, &data[0]); ret = read_sr(flash, &data[0]);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -110,7 +122,7 @@ int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc)
#endif #endif
#ifdef CONFIG_SPI_FLASH_BAR #ifdef CONFIG_SPI_FLASH_BAR
static int spi_flash_write_bank(struct spi_flash *flash, u32 offset) static int spi_flash_write_bar(struct spi_flash *flash, u32 offset)
{ {
u8 cmd, bank_sel; u8 cmd, bank_sel;
int ret; int ret;
@ -130,10 +142,40 @@ bar_end:
flash->bank_curr = bank_sel; flash->bank_curr = bank_sel;
return flash->bank_curr; return flash->bank_curr;
} }
static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
{
u8 curr_bank = 0;
int ret;
if (flash->size <= SPI_FLASH_16MB_BOUN)
goto bank_end;
switch (idcode0) {
case SPI_FLASH_CFI_MFR_SPANSION:
flash->bank_read_cmd = CMD_BANKADDR_BRRD;
flash->bank_write_cmd = CMD_BANKADDR_BRWR;
break;
default:
flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
}
ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
&curr_bank, 1);
if (ret) {
debug("SF: fail to read bank addr register\n");
return ret;
}
bank_end:
flash->bank_curr = curr_bank;
return 0;
}
#endif #endif
#ifdef CONFIG_SF_DUAL_FLASH #ifdef CONFIG_SF_DUAL_FLASH
static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr) static void spi_flash_dual(struct spi_flash *flash, u32 *addr)
{ {
switch (flash->dual_flash) { switch (flash->dual_flash) {
case SF_DUAL_STACKED_FLASH: case SF_DUAL_STACKED_FLASH:
@ -159,7 +201,7 @@ static int spi_flash_sr_ready(struct spi_flash *flash)
u8 sr; u8 sr;
int ret; int ret;
ret = spi_flash_cmd_read_status(flash, &sr); ret = read_sr(flash, &sr);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -196,7 +238,8 @@ static int spi_flash_ready(struct spi_flash *flash)
return sr && fsr; return sr && fsr;
} }
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) static int spi_flash_cmd_wait_ready(struct spi_flash *flash,
unsigned long timeout)
{ {
int timebase, ret; int timebase, ret;
@ -282,10 +325,10 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
#ifdef CONFIG_SF_DUAL_FLASH #ifdef CONFIG_SF_DUAL_FLASH
if (flash->dual_flash > SF_SINGLE_FLASH) if (flash->dual_flash > SF_SINGLE_FLASH)
spi_flash_dual_flash(flash, &erase_addr); spi_flash_dual(flash, &erase_addr);
#endif #endif
#ifdef CONFIG_SPI_FLASH_BAR #ifdef CONFIG_SPI_FLASH_BAR
ret = spi_flash_write_bank(flash, erase_addr); ret = spi_flash_write_bar(flash, erase_addr);
if (ret < 0) if (ret < 0)
return ret; return ret;
#endif #endif
@ -332,10 +375,10 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
#ifdef CONFIG_SF_DUAL_FLASH #ifdef CONFIG_SF_DUAL_FLASH
if (flash->dual_flash > SF_SINGLE_FLASH) if (flash->dual_flash > SF_SINGLE_FLASH)
spi_flash_dual_flash(flash, &write_addr); spi_flash_dual(flash, &write_addr);
#endif #endif
#ifdef CONFIG_SPI_FLASH_BAR #ifdef CONFIG_SPI_FLASH_BAR
ret = spi_flash_write_bank(flash, write_addr); ret = spi_flash_write_bar(flash, write_addr);
if (ret < 0) if (ret < 0)
return ret; return ret;
#endif #endif
@ -427,10 +470,10 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
#ifdef CONFIG_SF_DUAL_FLASH #ifdef CONFIG_SF_DUAL_FLASH
if (flash->dual_flash > SF_SINGLE_FLASH) if (flash->dual_flash > SF_SINGLE_FLASH)
spi_flash_dual_flash(flash, &read_addr); spi_flash_dual(flash, &read_addr);
#endif #endif
#ifdef CONFIG_SPI_FLASH_BAR #ifdef CONFIG_SPI_FLASH_BAR
ret = spi_flash_write_bank(flash, read_addr); ret = spi_flash_write_bar(flash, read_addr);
if (ret < 0) if (ret < 0)
return ret; return ret;
bank_sel = flash->bank_curr; bank_sel = flash->bank_curr;
@ -628,7 +671,7 @@ int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len)
int status; int status;
u8 sr; u8 sr;
status = spi_flash_cmd_read_status(flash, &sr); status = read_sr(flash, &sr);
if (status < 0) if (status < 0)
return status; return status;
@ -665,7 +708,7 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len)
u8 shift = ffs(mask) - 1, pow, val; u8 shift = ffs(mask) - 1, pow, val;
int ret; int ret;
ret = spi_flash_cmd_read_status(flash, &status_old); ret = read_sr(flash, &status_old);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -702,7 +745,7 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len)
if ((status_new & mask) <= (status_old & mask)) if ((status_new & mask) <= (status_old & mask))
return -EINVAL; return -EINVAL;
spi_flash_cmd_write_status(flash, status_new); write_sr(flash, status_new);
return 0; return 0;
} }
@ -719,7 +762,7 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
u8 shift = ffs(mask) - 1, pow, val; u8 shift = ffs(mask) - 1, pow, val;
int ret; int ret;
ret = spi_flash_cmd_read_status(flash, &status_old); ret = read_sr(flash, &status_old);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -752,8 +795,321 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
if ((status_new & mask) >= (status_old & mask)) if ((status_new & mask) >= (status_old & mask))
return -EINVAL; return -EINVAL;
spi_flash_cmd_write_status(flash, status_new); write_sr(flash, status_new);
return 0; return 0;
} }
#endif #endif
#ifdef CONFIG_SPI_FLASH_MACRONIX
static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
{
u8 qeb_status;
int ret;
ret = read_sr(flash, &qeb_status);
if (ret < 0)
return ret;
if (qeb_status & STATUS_QEB_MXIC) {
debug("SF: mxic: QEB is already set\n");
} else {
ret = write_sr(flash, STATUS_QEB_MXIC);
if (ret < 0)
return ret;
}
return ret;
}
#endif
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
static int spi_flash_set_qeb_winspan(struct spi_flash *flash)
{
u8 qeb_status;
int ret;
ret = read_cr(flash, &qeb_status);
if (ret < 0)
return ret;
if (qeb_status & STATUS_QEB_WINSPAN) {
debug("SF: winspan: QEB is already set\n");
} else {
ret = write_cr(flash, STATUS_QEB_WINSPAN);
if (ret < 0)
return ret;
}
return ret;
}
#endif
static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
{
switch (idcode0) {
#ifdef CONFIG_SPI_FLASH_MACRONIX
case SPI_FLASH_CFI_MFR_MACRONIX:
return spi_flash_set_qeb_mxic(flash);
#endif
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
case SPI_FLASH_CFI_MFR_SPANSION:
case SPI_FLASH_CFI_MFR_WINBOND:
return spi_flash_set_qeb_winspan(flash);
#endif
#ifdef CONFIG_SPI_FLASH_STMICRO
case SPI_FLASH_CFI_MFR_STMICRO:
debug("SF: QEB is volatile for %02x flash\n", idcode0);
return 0;
#endif
default:
printf("SF: Need set QEB func for %02x flash\n", idcode0);
return -1;
}
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
{
fdt_addr_t addr;
fdt_size_t size;
int node;
/* If there is no node, do nothing */
node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
if (node < 0)
return 0;
addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
if (addr == FDT_ADDR_T_NONE) {
debug("%s: Cannot decode address\n", __func__);
return 0;
}
if (flash->size != size) {
debug("%s: Memory map must cover entire device\n", __func__);
return -1;
}
flash->memory_map = map_sysmem(addr, size);
return 0;
}
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
int spi_flash_scan(struct spi_flash *flash)
{
struct spi_slave *spi = flash->spi;
const struct spi_flash_params *params;
u16 jedec, ext_jedec;
u8 idcode[5];
u8 cmd;
int ret;
/* Read the ID codes */
ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
if (ret) {
printf("SF: Failed to get idcodes\n");
return -EINVAL;
}
#ifdef DEBUG
printf("SF: Got idcodes\n");
print_buffer(0, idcode, 1, sizeof(idcode), 0);
#endif
jedec = idcode[1] << 8 | idcode[2];
ext_jedec = idcode[3] << 8 | idcode[4];
/* Validate params from spi_flash_params table */
params = spi_flash_params_table;
for (; params->name != NULL; params++) {
if ((params->jedec >> 16) == idcode[0]) {
if ((params->jedec & 0xFFFF) == jedec) {
if (params->ext_jedec == 0)
break;
else if (params->ext_jedec == ext_jedec)
break;
}
}
}
if (!params->name) {
printf("SF: Unsupported flash IDs: ");
printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
idcode[0], jedec, ext_jedec);
return -EPROTONOSUPPORT;
}
/* Flash powers up read-only, so clear BP# bits */
if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL ||
idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX ||
idcode[0] == SPI_FLASH_CFI_MFR_SST)
write_sr(flash, 0);
/* Assign spi data */
flash->name = params->name;
flash->memory_map = spi->memory_map;
flash->dual_flash = flash->spi->option;
/* Assign spi flash flags */
if (params->flags & SST_WR)
flash->flags |= SNOR_F_SST_WR;
/* Assign spi_flash ops */
#ifndef CONFIG_DM_SPI_FLASH
flash->write = spi_flash_cmd_write_ops;
#if defined(CONFIG_SPI_FLASH_SST)
if (flash->flags & SNOR_F_SST_WR) {
if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
flash->write = sst_write_bp;
else
flash->write = sst_write_wp;
}
#endif
flash->erase = spi_flash_cmd_erase_ops;
flash->read = spi_flash_cmd_read_ops;
#endif
/* lock hooks are flash specific - assign them based on idcode0 */
switch (idcode[0]) {
#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
case SPI_FLASH_CFI_MFR_STMICRO:
case SPI_FLASH_CFI_MFR_SST:
flash->flash_lock = stm_lock;
flash->flash_unlock = stm_unlock;
flash->flash_is_locked = stm_is_locked;
#endif
break;
default:
debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
}
/* Compute the flash size */
flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
/*
* The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
* 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
* the 0x4d00 Extended JEDEC code have 512b pages. All of the others
* have 256b pages.
*/
if (ext_jedec == 0x4d00) {
if ((jedec == 0x0215) || (jedec == 0x216))
flash->page_size = 256;
else
flash->page_size = 512;
} else {
flash->page_size = 256;
}
flash->page_size <<= flash->shift;
flash->sector_size = params->sector_size << flash->shift;
flash->size = flash->sector_size * params->nr_sectors << flash->shift;
#ifdef CONFIG_SF_DUAL_FLASH
if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
flash->size <<= 1;
#endif
/* Compute erase sector and command */
if (params->flags & SECT_4K) {
flash->erase_cmd = CMD_ERASE_4K;
flash->erase_size = 4096 << flash->shift;
} else if (params->flags & SECT_32K) {
flash->erase_cmd = CMD_ERASE_32K;
flash->erase_size = 32768 << flash->shift;
} else {
flash->erase_cmd = CMD_ERASE_64K;
flash->erase_size = flash->sector_size;
}
/* Now erase size becomes valid sector size */
flash->sector_size = flash->erase_size;
/* Look for the fastest read cmd */
cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
if (cmd) {
cmd = spi_read_cmds_array[cmd - 1];
flash->read_cmd = cmd;
} else {
/* Go for default supported read cmd */
flash->read_cmd = CMD_READ_ARRAY_FAST;
}
/* Not require to look for fastest only two write cmds yet */
if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP)
flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
else
/* Go for default supported write cmd */
flash->write_cmd = CMD_PAGE_PROGRAM;
/* Set the quad enable bit - only for quad commands */
if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
(flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
(flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
ret = spi_flash_set_qeb(flash, idcode[0]);
if (ret) {
debug("SF: Fail to set QEB for %02x\n", idcode[0]);
return -EINVAL;
}
}
/* Read dummy_byte: dummy byte is determined based on the
* dummy cycles of a particular command.
* Fast commands - dummy_byte = dummy_cycles/8
* I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8
* For I/O commands except cmd[0] everything goes on no.of lines
* based on particular command but incase of fast commands except
* data all go on single line irrespective of command.
*/
switch (flash->read_cmd) {
case CMD_READ_QUAD_IO_FAST:
flash->dummy_byte = 2;
break;
case CMD_READ_ARRAY_SLOW:
flash->dummy_byte = 0;
break;
default:
flash->dummy_byte = 1;
}
#ifdef CONFIG_SPI_FLASH_STMICRO
if (params->flags & E_FSR)
flash->flags |= SNOR_F_USE_FSR;
#endif
/* Configure the BAR - discover bank cmds and read current bank */
#ifdef CONFIG_SPI_FLASH_BAR
ret = spi_flash_read_bar(flash, idcode[0]);
if (ret < 0)
return ret;
#endif
#if CONFIG_IS_ENABLED(OF_CONTROL)
ret = spi_flash_decode_fdt(gd->fdt_blob, flash);
if (ret) {
debug("SF: FDT decode error\n");
return -EINVAL;
}
#endif
#ifndef CONFIG_SPL_BUILD
printf("SF: Detected %s with page size ", flash->name);
print_size(flash->page_size, ", erase size ");
print_size(flash->erase_size, ", total ");
print_size(flash->size, "");
if (flash->memory_map)
printf(", mapped at %p", flash->memory_map);
puts("\n");
#endif
#ifndef CONFIG_SPI_FLASH_BAR
if (((flash->dual_flash == SF_SINGLE_FLASH) &&
(flash->size > SPI_FLASH_16MB_BOUN)) ||
((flash->dual_flash > SF_SINGLE_FLASH) &&
(flash->size > SPI_FLASH_16MB_BOUN << 1))) {
puts("SF: Warning - Only lower 16MiB accessible,");
puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
}
#endif
return ret;
}

View File

@ -140,7 +140,7 @@ config XILINX_SPI
config ZYNQ_SPI config ZYNQ_SPI
bool "Zynq SPI driver" bool "Zynq SPI driver"
depends on ARCH_ZYNQ || TARGET_XILINX_ZYNQMP depends on ARCH_ZYNQ || ARCH_ZYNQMP
help help
Enable the Zynq SPI driver. This driver can be used to Enable the Zynq SPI driver. This driver can be used to
access the SPI NOR flash on platforms embedding this Zynq access the SPI NOR flash on platforms embedding this Zynq

View File

@ -378,6 +378,8 @@ int spi_slave_ofdata_to_platdata(const void *blob, int node,
mode |= SPI_CPHA; mode |= SPI_CPHA;
if (fdtdec_get_bool(blob, node, "spi-cs-high")) if (fdtdec_get_bool(blob, node, "spi-cs-high"))
mode |= SPI_CS_HIGH; mode |= SPI_CS_HIGH;
if (fdtdec_get_bool(blob, node, "spi-3wire"))
mode |= SPI_3WIRE;
if (fdtdec_get_bool(blob, node, "spi-half-duplex")) if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
mode |= SPI_PREAMBLE; mode |= SPI_PREAMBLE;
plat->mode = mode; plat->mode = mode;

View File

@ -293,7 +293,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
qslave->cmd = 0; qslave->cmd = 0;
qslave->cmd |= QSPI_WLEN(8); qslave->cmd |= QSPI_WLEN(8);
qslave->cmd |= QSPI_EN_CS(slave->cs); qslave->cmd |= QSPI_EN_CS(slave->cs);
if (flags & SPI_3WIRE) if (qslave->mode & SPI_3WIRE)
qslave->cmd |= QSPI_3_PIN; qslave->cmd |= QSPI_3_PIN;
qslave->cmd |= 0xfff; qslave->cmd |= 0xfff;

View File

@ -287,7 +287,8 @@ static const struct dm_spi_ops xilinx_spi_ops = {
}; };
static const struct udevice_id xilinx_spi_ids[] = { static const struct udevice_id xilinx_spi_ids[] = {
{ .compatible = "xlnx,xilinx-spi" }, { .compatible = "xlnx,xps-spi-2.00.a" },
{ .compatible = "xlnx,xps-spi-2.00.b" },
{ } { }
}; };

View File

@ -313,6 +313,7 @@ static const struct dm_spi_ops zynq_spi_ops = {
static const struct udevice_id zynq_spi_ids[] = { static const struct udevice_id zynq_spi_ids[] = {
{ .compatible = "xlnx,zynq-spi-r1p6" }, { .compatible = "xlnx,zynq-spi-r1p6" },
{ .compatible = "cdns,spi-r1p6" },
{ } { }
}; };

View File

@ -236,4 +236,19 @@
#define CONFIG_VIDEO_BMP_LOGO #define CONFIG_VIDEO_BMP_LOGO
#endif #endif
#ifdef CONFIG_FSL_QSPI
#define CONFIG_CMD_SF
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_MACRONIX
#define CONFIG_SPI_FLASH_BAR
#define CONFIG_SF_DEFAULT_BUS 0
#define CONFIG_SF_DEFAULT_CS 0
#define CONFIG_SF_DEFAULT_SPEED 40000000
#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
#define FSL_QSPI_FLASH_NUM 1
#define FSL_QSPI_FLASH_SIZE SZ_64M
#define QSPI0_BASE_ADDR QSPI1_IPS_BASE_ADDR
#define QSPI0_AMBA_BASE QSPI0_ARB_BASE_ADDR
#endif
#endif /* __CONFIG_H */ #endif /* __CONFIG_H */