[U-Boot] [PATCH v7 74/76] sf: Drop entire spi-flash framework

All set ready for SPI-NOR.
Cc: Simon Glass sjg@chromium.org Cc: Bin Meng bmeng.cn@gmail.com Cc: Mugunthan V N mugunthanvnm@ti.com Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com Signed-off-by: Jagan Teki jteki@openedev.com --- Changes for v7: - Rebase to previous v7 patch set
MAINTAINERS | 1 - Makefile | 1 - cmd/sf.c | 4 +- common/env_sf.c | 4 +- drivers/Makefile | 1 - drivers/mtd/Kconfig | 2 - drivers/mtd/spi/Kconfig | 131 ----- drivers/mtd/spi/Makefile | 18 - drivers/mtd/spi/fsl_espi_spl.c | 90 --- drivers/mtd/spi/sandbox.c | 697 ----------------------- drivers/mtd/spi/sf-uclass.c | 103 ---- drivers/mtd/spi/sf.c | 58 -- drivers/mtd/spi/sf_dataflash.c | 701 ------------------------ drivers/mtd/spi/sf_internal.h | 243 --------- drivers/mtd/spi/sf_mtd.c | 104 ---- drivers/mtd/spi/sf_params.c | 146 ----- drivers/mtd/spi/sf_probe.c | 181 ------ drivers/mtd/spi/spi_flash.c | 1182 ---------------------------------------- drivers/mtd/spi/spi_spl_load.c | 90 --- include/spi_flash.h | 225 +------- 20 files changed, 6 insertions(+), 3976 deletions(-) delete mode 100644 drivers/mtd/spi/Kconfig delete mode 100644 drivers/mtd/spi/Makefile delete mode 100644 drivers/mtd/spi/fsl_espi_spl.c delete mode 100644 drivers/mtd/spi/sandbox.c delete mode 100644 drivers/mtd/spi/sf-uclass.c delete mode 100644 drivers/mtd/spi/sf.c delete mode 100644 drivers/mtd/spi/sf_dataflash.c delete mode 100644 drivers/mtd/spi/sf_internal.h delete mode 100644 drivers/mtd/spi/sf_mtd.c delete mode 100644 drivers/mtd/spi/sf_params.c delete mode 100644 drivers/mtd/spi/sf_probe.c delete mode 100644 drivers/mtd/spi/spi_flash.c delete mode 100644 drivers/mtd/spi/spi_spl_load.c
diff --git a/MAINTAINERS b/MAINTAINERS index b387207..4b23d18 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -385,7 +385,6 @@ SPI M: Jagan Teki jteki@openedev.com S: Maintained T: git git://git.denx.de/u-boot-spi.git -F: drivers/mtd/spi/ F: drivers/spi/ F: include/spi*
diff --git a/Makefile b/Makefile index 4e67433..e9579b8 100644 --- a/Makefile +++ b/Makefile @@ -636,7 +636,6 @@ libs-y += drivers/mtd/ libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/ libs-y += drivers/mtd/onenand/ libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/ -libs-y += drivers/mtd/spi/ libs-y += drivers/mtd/spi-nor/ libs-y += drivers/net/ libs-y += drivers/net/phy/ diff --git a/cmd/sf.c b/cmd/sf.c index bbdbe52..bf5a3ce 100644 --- a/cmd/sf.c +++ b/cmd/sf.c @@ -85,7 +85,7 @@ static int do_spi_flash_probe(int argc, char * const argv[]) unsigned int speed = CONFIG_SF_DEFAULT_SPEED; unsigned int mode = CONFIG_SF_DEFAULT_MODE; char *endp; -#if defined(CONFIG_DM_SPI_FLASH) || defined (CONFIG_DM_MTD_SPI_NOR) +#ifdef CONFIG_DM_MTD_SPI_NOR struct udevice *new, *bus_dev; int ret; #else @@ -118,7 +118,7 @@ static int do_spi_flash_probe(int argc, char * const argv[]) return -1; }
-#if defined(CONFIG_DM_SPI_FLASH) || defined (CONFIG_DM_MTD_SPI_NOR) +#ifdef CONFIG_DM_MTD_SPI_NOR /* Remove the old device, otherwise probe will just be a nop */ ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); if (!ret) { diff --git a/common/env_sf.c b/common/env_sf.c index 962cac4..a3decbe 100644 --- a/common/env_sf.c +++ b/common/env_sf.c @@ -52,7 +52,7 @@ int saveenv(void) char *saved_buffer = NULL, flag = OBSOLETE_FLAG; u32 saved_size, saved_offset, sector = 1; int ret; -#if defined(CONFIG_DM_SPI_FLASH) || defined (CONFIG_DM_MTD_SPI_NOR) +#ifdef CONFIG_DM_MTD_SPI_NOR struct udevice *new;
ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, @@ -242,7 +242,7 @@ int saveenv(void) char *saved_buffer = NULL; int ret = 1; env_t env_new; -#if defined(CONFIG_DM_SPI_FLASH) || defined (CONFIG_DM_MTD_SPI_NOR) +#ifdef CONFIG_DM_MTD_SPI_NOR struct udevice *new;
ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, diff --git a/drivers/Makefile b/drivers/Makefile index 1d179b9..c3bc3c5 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/ obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/ obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/ obj-$(CONFIG_SPL_SPI_NOR_SUPPORT) += mtd/spi-nor/ -obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/ obj-$(CONFIG_SPL_SPI_SUPPORT) += spi/ obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/ obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/ diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 2c8846b..99b821a 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -32,6 +32,4 @@ endmenu
source "drivers/mtd/nand/Kconfig"
-source "drivers/mtd/spi/Kconfig" - source "drivers/mtd/spi-nor/Kconfig" diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig deleted file mode 100644 index 3f7433c..0000000 --- a/drivers/mtd/spi/Kconfig +++ /dev/null @@ -1,131 +0,0 @@ -menu "SPI Flash Support" - -config DM_SPI_FLASH - bool "Enable Driver Model for SPI flash" - depends on DM && DM_SPI - help - Enable driver model for SPI flash. This SPI flash interface - (spi_flash_probe(), spi_flash_write(), etc.) is then - implemented by the SPI flash uclass. There is one standard - SPI flash driver which knows how to probe most chips - supported by U-Boot. The uclass interface is defined in - include/spi_flash.h, but is currently fully compatible - with the old interface to avoid confusion and duplication - during the transition parent. SPI and SPI flash must be - enabled together (it is not possible to use driver model - for one and not the other). - -config SPI_FLASH_SANDBOX - bool "Support sandbox SPI flash device" - depends on SANDBOX && DM_SPI_FLASH - help - Since sandbox cannot access real devices, an emulation mechanism is - provided instead. Drivers can be connected up to the sandbox SPI - bus (see CONFIG_SANDBOX_SPI) and SPI traffic will be routed to this - device. Typically the contents of the emulated SPI flash device is - stored in a file on the host filesystem. - -config SPI_FLASH - bool "Legacy SPI Flash Interface support" - help - Enable the legacy SPI flash support. This will include basic - standard support for things like probing, read / write, and - erasing through cmd_sf interface. - - If unsure, say N - -config SPI_FLASH_BAR - bool "SPI flash Bank/Extended address register support" - depends on SPI_FLASH - help - Enable the SPI flash Bank/Extended address register support. - Bank/Extended address registers are used to access the flash - which has size > 16MiB in 3-byte addressing. - -if SPI_FLASH - -config SPI_FLASH_ATMEL - bool "Atmel SPI flash support" - help - Add support for various Atmel SPI flash chips (AT45xxx and AT25xxx) - -config SPI_FLASH_EON - bool "EON SPI flash support" - help - Add support for various EON SPI flash chips (EN25xxx) - -config SPI_FLASH_GIGADEVICE - bool "GigaDevice SPI flash support" - help - Add support for various GigaDevice SPI flash chips (GD25xxx) - -config SPI_FLASH_MACRONIX - bool "Macronix SPI flash support" - help - Add support for various Macronix SPI flash chips (MX25Lxxx) - -config SPI_FLASH_SPANSION - bool "Spansion SPI flash support" - help - Add support for various Spansion SPI flash chips (S25FLxxx) - -config SPI_FLASH_STMICRO - bool "STMicro SPI flash support" - help - Add support for various STMicro SPI flash chips (M25Pxxx and N25Qxxx) - -config SPI_FLASH_SST - bool "SST SPI flash support" - help - Add support for various SST SPI flash chips (SST25xxx) - -config SPI_FLASH_WINBOND - bool "Winbond SPI flash support" - help - Add support for various Winbond SPI flash chips (W25xxx) - -endif - -config SPI_FLASH_USE_4K_SECTORS - bool "Use small 4096 B erase sectors" - depends on SPI_FLASH - default y - help - Many flash memories support erasing small (4096 B) sectors. Depending - on the usage this feature may provide performance gain in comparison - to erasing whole blocks (32/64 KiB). - Changing a small part of the flash's contents is usually faster with - small sectors. On the other hand erasing should be faster when using - 64 KiB block instead of 16 × 4 KiB sectors. - - Please note that some tools/drivers/filesystems may not work with - 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). - -config SPI_FLASH_DATAFLASH - bool "AT45xxx DataFlash support" - depends on SPI_FLASH && DM_SPI_FLASH - help - Enable the access for SPI-flash-based AT45xxx DataFlash chips. - DataFlash is a kind of SPI flash. Most AT45 chips have two buffers - in each chip, which may be used for double buffered I/O; but this - driver doesn't (yet) use these for any kind of i/o overlap or prefetching. - - Sometimes DataFlash is packaged in MMC-format cards, although the - MMC stack can't (yet?) distinguish between MMC and DataFlash - protocols during enumeration. - - If unsure, say N - -config SPI_FLASH_MTD - bool "SPI Flash MTD support" - depends on SPI_FLASH - help - Enable the MTD support for spi flash layer, this adapter is for - translating mtd_read/mtd_write commands into spi_flash_read/write - commands. It is not intended to use it within sf_cmd or the SPI - flash subsystem. Such an adapter is needed for subsystems like - UBI which can only operate on top of the MTD layer. - - If unsure, say N - -endmenu # menu "SPI Flash Support" diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile deleted file mode 100644 index c665836..0000000 --- a/drivers/mtd/spi/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# (C) Copyright 2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o - -ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_SPL_SPI_LOAD) += spi_spl_load.o -obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o -endif - -obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o sf_params.o sf.o -obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o -obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o -obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/fsl_espi_spl.c b/drivers/mtd/spi/fsl_espi_spl.c deleted file mode 100644 index b915469..0000000 --- a/drivers/mtd/spi/fsl_espi_spl.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2013 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <spi_flash.h> -#include <malloc.h> - -#define ESPI_BOOT_IMAGE_SIZE 0x48 -#define ESPI_BOOT_IMAGE_ADDR 0x50 -#define CONFIG_CFG_DATA_SECTOR 0 - -void spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst) -{ - struct spi_flash *flash; - - flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, - CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); - if (flash == NULL) { - puts("\nspi_flash_probe failed"); - hang(); - } - - spi_flash_read(flash, offs, size, vdst); -} - -/* - * The main entry for SPI booting. It's necessary that SDRAM is already - * configured and available since this code loads the main U-Boot image - * from SPI into SDRAM and starts it from there. - */ -void spi_boot(void) -{ - void (*uboot)(void) __noreturn; - u32 offset, code_len, copy_len = 0; -#ifndef CONFIG_FSL_CORENET - unsigned char *buf = NULL; -#endif - struct spi_flash *flash; - - flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, - CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); - if (flash == NULL) { - puts("\nspi_flash_probe failed"); - hang(); - } - -#ifdef CONFIG_FSL_CORENET - offset = CONFIG_SYS_SPI_FLASH_U_BOOT_OFFS; - code_len = CONFIG_SYS_SPI_FLASH_U_BOOT_SIZE; -#else - /* - * Load U-Boot image from SPI flash into RAM - */ - buf = malloc(flash->page_size); - if (buf == NULL) { - puts("\nmalloc failed"); - hang(); - } - memset(buf, 0, flash->page_size); - - spi_flash_read(flash, CONFIG_CFG_DATA_SECTOR, - flash->page_size, (void *)buf); - offset = *(u32 *)(buf + ESPI_BOOT_IMAGE_ADDR); - /* Skip spl code */ - offset += CONFIG_SYS_SPI_FLASH_U_BOOT_OFFS; - /* Get the code size from offset 0x48 */ - code_len = *(u32 *)(buf + ESPI_BOOT_IMAGE_SIZE); - /* Skip spl code */ - code_len = code_len - CONFIG_SPL_MAX_SIZE; -#endif - /* copy code to DDR */ - printf("Loading second stage boot loader "); - while (copy_len <= code_len) { - spi_flash_read(flash, offset + copy_len, 0x2000, - (void *)(CONFIG_SYS_SPI_FLASH_U_BOOT_DST - + copy_len)); - copy_len = copy_len + 0x2000; - putc('.'); - } - - /* - * Jump to U-Boot image - */ - flush_cache(CONFIG_SYS_SPI_FLASH_U_BOOT_DST, code_len); - uboot = (void *)CONFIG_SYS_SPI_FLASH_U_BOOT_START; - (*uboot)(); -} diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c deleted file mode 100644 index 895604d..0000000 --- a/drivers/mtd/spi/sandbox.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Simulate a SPI flash - * - * Copyright (c) 2011-2013 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <dm.h> -#include <malloc.h> -#include <spi.h> -#include <os.h> - -#include <spi_flash.h> -#include "sf_internal.h" - -#include <asm/getopt.h> -#include <asm/spi.h> -#include <asm/state.h> -#include <dm/device-internal.h> -#include <dm/lists.h> -#include <dm/uclass-internal.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* - * The different states that our SPI flash transitions between. - * We need to keep track of this across multiple xfer calls since - * the SPI bus could possibly call down into us multiple times. - */ -enum sandbox_sf_state { - SF_CMD, /* default state -- we're awaiting a command */ - SF_ID, /* read the flash's (jedec) ID code */ - SF_ADDR, /* processing the offset in the flash to read/etc... */ - SF_READ, /* reading data from the flash */ - SF_WRITE, /* writing data to the flash, i.e. page programming */ - SF_ERASE, /* erase the flash */ - SF_READ_STATUS, /* read the flash's status register */ - SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/ - SF_WRITE_STATUS, /* write the flash's status register */ -}; - -static const char *sandbox_sf_state_name(enum sandbox_sf_state state) -{ - static const char * const states[] = { - "CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS", - "READ_STATUS1", "WRITE_STATUS", - }; - return states[state]; -} - -/* Bits for the status register */ -#define STAT_WIP (1 << 0) -#define STAT_WEL (1 << 1) - -/* Assume all SPI flashes have 3 byte addresses since they do atm */ -#define SF_ADDR_LEN 3 - -#define IDCODE_LEN 3 - -/* Used to quickly bulk erase backing store */ -static u8 sandbox_sf_0xff[0x1000]; - -/* Internal state data for each SPI flash */ -struct sandbox_spi_flash { - unsigned int cs; /* Chip select we are attached to */ - /* - * As we receive data over the SPI bus, our flash transitions - * between states. For example, we start off in the SF_CMD - * state where the first byte tells us what operation to perform - * (such as read or write the flash). But the operation itself - * can go through a few states such as first reading in the - * offset in the flash to perform the requested operation. - * Thus "state" stores the exact state that our machine is in - * while "cmd" stores the overall command we're processing. - */ - enum sandbox_sf_state state; - uint cmd; - /* Erase size of current erase command */ - uint erase_size; - /* Current position in the flash; used when reading/writing/etc... */ - uint off; - /* How many address bytes we've consumed */ - uint addr_bytes, pad_addr_bytes; - /* The current flash status (see STAT_XXX defines above) */ - u16 status; - /* Data describing the flash we're emulating */ - const struct spi_flash_params *data; - /* The file on disk to serv up data from */ - int fd; -}; - -struct sandbox_spi_flash_plat_data { - const char *filename; - const char *device_name; - int bus; - int cs; -}; - -/** - * This is a very strange probe function. If it has platform data (which may - * have come from the device tree) then this function gets the filename and - * device type from there. Failing that it looks at the command line - * parameter. - */ -static int sandbox_sf_probe(struct udevice *dev) -{ - /* spec = idcode:file */ - struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - const char *file; - size_t len, idname_len; - const struct spi_flash_params *data; - struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); - struct sandbox_state *state = state_get_current(); - struct udevice *bus = dev->parent; - const char *spec = NULL; - int ret = 0; - int cs = -1; - int i; - - debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); - if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) { - for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) { - if (state->spi[bus->seq][i].emul == dev) - cs = i; - } - } - if (cs == -1) { - printf("Error: Unknown chip select for device '%s'\n", - dev->name); - return -EINVAL; - } - debug("found at cs %d\n", cs); - - if (!pdata->filename) { - struct sandbox_state *state = state_get_current(); - - assert(bus->seq != -1); - if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) - spec = state->spi[bus->seq][cs].spec; - if (!spec) { - ret = -ENOENT; - goto error; - } - - file = strchr(spec, ':'); - if (!file) { - printf("sandbox_sf: unable to parse file\n"); - ret = -EINVAL; - goto error; - } - idname_len = file - spec; - pdata->filename = file + 1; - pdata->device_name = spec; - ++file; - } else { - spec = strchr(pdata->device_name, ','); - if (spec) - spec++; - else - spec = pdata->device_name; - idname_len = strlen(spec); - } - debug("%s: device='%s'\n", __func__, spec); - - for (data = spi_flash_params_table; data->name; data++) { - len = strlen(data->name); - if (idname_len != len) - continue; - if (!strncasecmp(spec, data->name, len)) - break; - } - if (!data->name) { - printf("sandbox_sf: unknown flash '%*s'\n", (int)idname_len, - spec); - ret = -EINVAL; - goto error; - } - - if (sandbox_sf_0xff[0] == 0x00) - memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); - - sbsf->fd = os_open(pdata->filename, 02); - if (sbsf->fd == -1) { - free(sbsf); - printf("sandbox_sf: unable to open file '%s'\n", - pdata->filename); - ret = -EIO; - goto error; - } - - sbsf->data = data; - sbsf->cs = cs; - - return 0; - - error: - debug("%s: Got error %d\n", __func__, ret); - return ret; -} - -static int sandbox_sf_remove(struct udevice *dev) -{ - struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - - os_close(sbsf->fd); - - return 0; -} - -static void sandbox_sf_cs_activate(struct udevice *dev) -{ - struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - - debug("sandbox_sf: CS activated; state is fresh!\n"); - - /* CS is asserted, so reset state */ - sbsf->off = 0; - sbsf->addr_bytes = 0; - sbsf->pad_addr_bytes = 0; - sbsf->state = SF_CMD; - sbsf->cmd = SF_CMD; -} - -static void sandbox_sf_cs_deactivate(struct udevice *dev) -{ - debug("sandbox_sf: CS deactivated; cmd done processing!\n"); -} - -/* - * There are times when the data lines are allowed to tristate. What - * is actually sensed on the line depends on the hardware. It could - * always be 0xFF/0x00 (if there are pull ups/downs), or things could - * float and so we'd get garbage back. This func encapsulates that - * scenario so we can worry about the details here. - */ -static void sandbox_spi_tristate(u8 *buf, uint len) -{ - /* XXX: make this into a user config option ? */ - memset(buf, 0xff, len); -} - -/* Figure out what command this stream is telling us to do */ -static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, - u8 *tx) -{ - enum sandbox_sf_state oldstate = sbsf->state; - - /* We need to output a byte for the cmd byte we just ate */ - if (tx) - sandbox_spi_tristate(tx, 1); - - sbsf->cmd = rx[0]; - switch (sbsf->cmd) { - case CMD_READ_ID: - sbsf->state = SF_ID; - sbsf->cmd = SF_ID; - break; - case CMD_READ_ARRAY_FAST: - sbsf->pad_addr_bytes = 1; - case CMD_READ_ARRAY_SLOW: - case CMD_PAGE_PROGRAM: - sbsf->state = SF_ADDR; - break; - case CMD_WRITE_DISABLE: - debug(" write disabled\n"); - sbsf->status &= ~STAT_WEL; - break; - case CMD_READ_STATUS: - sbsf->state = SF_READ_STATUS; - break; - case CMD_READ_STATUS1: - sbsf->state = SF_READ_STATUS1; - break; - case CMD_WRITE_ENABLE: - debug(" write enabled\n"); - sbsf->status |= STAT_WEL; - break; - case CMD_WRITE_STATUS: - sbsf->state = SF_WRITE_STATUS; - break; - default: { - int flags = sbsf->data->flags; - - /* we only support erase here */ - if (sbsf->cmd == CMD_ERASE_CHIP) { - sbsf->erase_size = sbsf->data->sector_size * - sbsf->data->nr_sectors; - } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { - sbsf->erase_size = 4 << 10; - } else if (sbsf->cmd == CMD_ERASE_32K && (flags & SECT_32K)) { - sbsf->erase_size = 32 << 10; - } else if (sbsf->cmd == CMD_ERASE_64K && - !(flags & (SECT_4K | SECT_32K))) { - sbsf->erase_size = 64 << 10; - } else { - debug(" cmd unknown: %#x\n", sbsf->cmd); - return -EIO; - } - sbsf->state = SF_ADDR; - break; - } - } - - if (oldstate != sbsf->state) - debug(" cmd: transition to %s state\n", - sandbox_sf_state_name(sbsf->state)); - - return 0; -} - -int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size) -{ - int todo; - int ret; - - while (size > 0) { - todo = min(size, (int)sizeof(sandbox_sf_0xff)); - ret = os_write(sbsf->fd, sandbox_sf_0xff, todo); - if (ret != todo) - return ret; - size -= todo; - } - - return 0; -} - -static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, - const void *rxp, void *txp, unsigned long flags) -{ - struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - const uint8_t *rx = rxp; - uint8_t *tx = txp; - uint cnt, pos = 0; - int bytes = bitlen / 8; - int ret; - - debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, - sandbox_sf_state_name(sbsf->state), bytes); - - if ((flags & SPI_XFER_BEGIN)) - sandbox_sf_cs_activate(dev); - - if (sbsf->state == SF_CMD) { - /* Figure out the initial state */ - ret = sandbox_sf_process_cmd(sbsf, rx, tx); - if (ret) - return ret; - ++pos; - } - - /* Process the remaining data */ - while (pos < bytes) { - switch (sbsf->state) { - case SF_ID: { - u8 id; - - debug(" id: off:%u tx:", sbsf->off); - if (sbsf->off < IDCODE_LEN) { - /* Extract correct byte from ID 0x00aabbcc */ - id = sbsf->data->jedec >> - (8 * (IDCODE_LEN - 1 - sbsf->off)); - } else { - id = 0; - } - debug("%d %02x\n", sbsf->off, id); - tx[pos++] = id; - ++sbsf->off; - break; - } - case SF_ADDR: - debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, - rx[pos]); - - if (sbsf->addr_bytes++ < SF_ADDR_LEN) - sbsf->off = (sbsf->off << 8) | rx[pos]; - debug("addr:%06x\n", sbsf->off); - - if (tx) - sandbox_spi_tristate(&tx[pos], 1); - pos++; - - /* See if we're done processing */ - if (sbsf->addr_bytes < - SF_ADDR_LEN + sbsf->pad_addr_bytes) - break; - - /* Next state! */ - if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { - puts("sandbox_sf: os_lseek() failed"); - return -EIO; - } - switch (sbsf->cmd) { - case CMD_READ_ARRAY_FAST: - case CMD_READ_ARRAY_SLOW: - sbsf->state = SF_READ; - break; - case CMD_PAGE_PROGRAM: - sbsf->state = SF_WRITE; - break; - default: - /* assume erase state ... */ - sbsf->state = SF_ERASE; - goto case_sf_erase; - } - debug(" cmd: transition to %s state\n", - sandbox_sf_state_name(sbsf->state)); - break; - case SF_READ: - /* - * XXX: need to handle exotic behavior: - * - reading past end of device - */ - - cnt = bytes - pos; - debug(" tx: read(%u)\n", cnt); - assert(tx); - ret = os_read(sbsf->fd, tx + pos, cnt); - if (ret < 0) { - puts("sandbox_sf: os_read() failed\n"); - return -EIO; - } - pos += ret; - break; - case SF_READ_STATUS: - debug(" read status: %#x\n", sbsf->status); - cnt = bytes - pos; - memset(tx + pos, sbsf->status, cnt); - pos += cnt; - break; - case SF_READ_STATUS1: - debug(" read status: %#x\n", sbsf->status); - cnt = bytes - pos; - memset(tx + pos, sbsf->status >> 8, cnt); - pos += cnt; - break; - case SF_WRITE_STATUS: - debug(" write status: %#x (ignored)\n", rx[pos]); - pos = bytes; - break; - case SF_WRITE: - /* - * XXX: need to handle exotic behavior: - * - unaligned addresses - * - more than a page (256) worth of data - * - reading past end of device - */ - if (!(sbsf->status & STAT_WEL)) { - puts("sandbox_sf: write enable not set before write\n"); - goto done; - } - - cnt = bytes - pos; - debug(" rx: write(%u)\n", cnt); - if (tx) - sandbox_spi_tristate(&tx[pos], cnt); - ret = os_write(sbsf->fd, rx + pos, cnt); - if (ret < 0) { - puts("sandbox_spi: os_write() failed\n"); - return -EIO; - } - pos += ret; - sbsf->status &= ~STAT_WEL; - break; - case SF_ERASE: - case_sf_erase: { - if (!(sbsf->status & STAT_WEL)) { - puts("sandbox_sf: write enable not set before erase\n"); - goto done; - } - - /* verify address is aligned */ - if (sbsf->off & (sbsf->erase_size - 1)) { - debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", - sbsf->cmd, sbsf->erase_size, - sbsf->off); - sbsf->status &= ~STAT_WEL; - goto done; - } - - debug(" sector erase addr: %u, size: %u\n", sbsf->off, - sbsf->erase_size); - - cnt = bytes - pos; - if (tx) - sandbox_spi_tristate(&tx[pos], cnt); - pos += cnt; - - /* - * TODO(vapier@gentoo.org): latch WIP in status, and - * delay before clearing it ? - */ - ret = sandbox_erase_part(sbsf, sbsf->erase_size); - sbsf->status &= ~STAT_WEL; - if (ret) { - debug("sandbox_sf: Erase failed\n"); - goto done; - } - goto done; - } - default: - debug(" ??? no idea what to do ???\n"); - goto done; - } - } - - done: - if (flags & SPI_XFER_END) - sandbox_sf_cs_deactivate(dev); - return pos == bytes ? 0 : -EIO; -} - -int sandbox_sf_ofdata_to_platdata(struct udevice *dev) -{ - struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); - const void *blob = gd->fdt_blob; - int node = dev->of_offset; - - pdata->filename = fdt_getprop(blob, node, "sandbox,filename", NULL); - pdata->device_name = fdt_getprop(blob, node, "compatible", NULL); - if (!pdata->filename || !pdata->device_name) { - debug("%s: Missing properties, filename=%s, device_name=%s\n", - __func__, pdata->filename, pdata->device_name); - return -EINVAL; - } - - return 0; -} - -static const struct dm_spi_emul_ops sandbox_sf_emul_ops = { - .xfer = sandbox_sf_xfer, -}; - -#ifdef CONFIG_SPI_FLASH -static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state, - const char *arg) -{ - unsigned long bus, cs; - const char *spec = sandbox_spi_parse_spec(arg, &bus, &cs); - - if (!spec) - return 1; - - /* - * It is safe to not make a copy of 'spec' because it comes from the - * command line. - * - * TODO(sjg@chromium.org): It would be nice if we could parse the - * spec here, but the problem is that no U-Boot init has been done - * yet. Perhaps we can figure something out. - */ - state->spi[bus][cs].spec = spec; - return 0; -} -SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: <bus>:<cs>:<id>:<file>"); - -int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, - struct udevice *bus, int of_offset, const char *spec) -{ - struct udevice *emul; - char name[20], *str; - struct driver *drv; - int ret; - - /* now the emulator */ - strncpy(name, spec, sizeof(name) - 6); - name[sizeof(name) - 6] = '\0'; - strcat(name, "-emul"); - str = strdup(name); - if (!str) - return -ENOMEM; - drv = lists_driver_lookup_name("sandbox_sf_emul"); - if (!drv) { - puts("Cannot find sandbox_sf_emul driver\n"); - return -ENOENT; - } - ret = device_bind(bus, drv, str, NULL, of_offset, &emul); - if (ret) { - printf("Cannot create emul device for spec '%s' (err=%d)\n", - spec, ret); - return ret; - } - state->spi[busnum][cs].emul = emul; - - return 0; -} - -void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs) -{ - struct udevice *dev; - - dev = state->spi[busnum][cs].emul; - device_remove(dev); - device_unbind(dev); - state->spi[busnum][cs].emul = NULL; -} - -static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum, - int cs, const char *spec) -{ - struct udevice *bus, *slave; - int ret; - - ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus); - if (ret) { - printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum, - spec, ret); - return ret; - } - ret = spi_find_chip_select(bus, cs, &slave); - if (!ret) { - printf("Chip select %d already exists for spec '%s'\n", cs, - spec); - return -EEXIST; - } - - ret = device_bind_driver(bus, "spi_flash_std", spec, &slave); - if (ret) - return ret; - - return sandbox_sf_bind_emul(state, busnum, cs, bus, -1, spec); -} - -int sandbox_spi_get_emul(struct sandbox_state *state, - struct udevice *bus, struct udevice *slave, - struct udevice **emulp) -{ - struct sandbox_spi_info *info; - int busnum = bus->seq; - int cs = spi_chip_select(slave); - int ret; - - info = &state->spi[busnum][cs]; - if (!info->emul) { - /* Use the same device tree node as the SPI flash device */ - debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ", - __func__, busnum, cs); - ret = sandbox_sf_bind_emul(state, busnum, cs, bus, - slave->of_offset, slave->name); - if (ret) { - debug("failed (err=%d)\n", ret); - return ret; - } - debug("OK\n"); - } - *emulp = info->emul; - - return 0; -} - -int dm_scan_other(bool pre_reloc_only) -{ - struct sandbox_state *state = state_get_current(); - int busnum, cs; - - if (pre_reloc_only) - return 0; - for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) { - for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) { - const char *spec = state->spi[busnum][cs].spec; - int ret; - - if (spec) { - ret = sandbox_sf_bind_bus_cs(state, busnum, - cs, spec); - if (ret) { - debug("%s: Bind failed for bus %d, cs %d\n", - __func__, busnum, cs); - return ret; - } - } - } - } - - return 0; -} -#endif - -static const struct udevice_id sandbox_sf_ids[] = { - { .compatible = "sandbox,spi-flash" }, - { } -}; - -U_BOOT_DRIVER(sandbox_sf_emul) = { - .name = "sandbox_sf_emul", - .id = UCLASS_SPI_EMUL, - .of_match = sandbox_sf_ids, - .ofdata_to_platdata = sandbox_sf_ofdata_to_platdata, - .probe = sandbox_sf_probe, - .remove = sandbox_sf_remove, - .priv_auto_alloc_size = sizeof(struct sandbox_spi_flash), - .platdata_auto_alloc_size = sizeof(struct sandbox_spi_flash_plat_data), - .ops = &sandbox_sf_emul_ops, -}; diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c deleted file mode 100644 index 19de964..0000000 --- a/drivers/mtd/spi/sf-uclass.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2014 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <dm.h> -#include <spi.h> -#include <spi_flash.h> -#include <dm/device-internal.h> -#include "sf_internal.h" - -DECLARE_GLOBAL_DATA_PTR; - -int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf) -{ - return sf_get_ops(dev)->read(dev, offset, len, buf); -} - -int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, - const void *buf) -{ - return sf_get_ops(dev)->write(dev, offset, len, buf); -} - -int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) -{ - return sf_get_ops(dev)->erase(dev, offset, len); -} - -/* - * TODO(sjg@chromium.org): This is an old-style function. We should remove - * it when all SPI flash drivers use dm - */ -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode) -{ - struct udevice *dev; - - if (spi_flash_probe_bus_cs(bus, cs, max_hz, spi_mode, &dev)) - return NULL; - - return dev_get_uclass_priv(dev); -} - -void spi_flash_free(struct spi_flash *flash) -{ - device_remove(flash->spi->dev); -} - -int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode, - struct udevice **devp) -{ - struct spi_slave *slave; - struct udevice *bus; - char *str; - int ret; - -#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_USE_TINY_PRINTF) - str = "spi_flash"; -#else - char name[30]; - - snprintf(name, sizeof(name), "spi_flash@%d:%d", busnum, cs); - str = strdup(name); -#endif - ret = spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode, - "spi_flash_std", str, &bus, &slave); - if (ret) - return ret; - - *devp = slave->dev; - return 0; -} - -static int spi_flash_post_bind(struct udevice *dev) -{ -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - struct dm_spi_flash_ops *ops = sf_get_ops(dev); - static int reloc_done; - - if (!reloc_done) { - if (ops->read) - ops->read += gd->reloc_off; - if (ops->write) - ops->write += gd->reloc_off; - if (ops->erase) - ops->erase += gd->reloc_off; - - reloc_done++; - } -#endif - return 0; -} - -UCLASS_DRIVER(spi_flash) = { - .id = UCLASS_SPI_FLASH, - .name = "spi_flash", - .post_bind = spi_flash_post_bind, - .per_device_auto_alloc_size = sizeof(struct spi_flash), -}; diff --git a/drivers/mtd/spi/sf.c b/drivers/mtd/spi/sf.c deleted file mode 100644 index 664e860..0000000 --- a/drivers/mtd/spi/sf.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPI flash interface - * - * Copyright (C) 2008 Atmel Corporation - * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <spi.h> - -static int spi_flash_read_write(struct spi_slave *spi, - const u8 *cmd, size_t cmd_len, - const u8 *data_out, u8 *data_in, - size_t data_len) -{ - unsigned long flags = SPI_XFER_BEGIN; - int ret; - -#ifdef CONFIG_SF_DUAL_FLASH - if (spi->flags & SPI_XFER_U_PAGE) - flags |= SPI_XFER_U_PAGE; -#endif - if (data_len == 0) - flags |= SPI_XFER_END; - - ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); - if (ret) { - debug("SF: Failed to send command (%zu bytes): %d\n", - cmd_len, ret); - } else if (data_len != 0) { - ret = spi_xfer(spi, data_len * 8, data_out, data_in, - SPI_XFER_END); - if (ret) - debug("SF: Failed to transfer %zu bytes of data: %d\n", - data_len, ret); - } - - return ret; -} - -int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len) -{ - return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len); -} - -int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len) -{ - return spi_flash_cmd_read(spi, &cmd, 1, response, len); -} - -int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, - const void *data, size_t data_len) -{ - return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len); -} diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c deleted file mode 100644 index 0f66b99..0000000 --- a/drivers/mtd/spi/sf_dataflash.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * - * Atmel DataFlash probing - * - * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc. - * Haikun Wang (haikun.wang@freescale.com) - * - * SPDX-License-Identifier: GPL-2.0+ -*/ -#include <common.h> -#include <dm.h> -#include <errno.h> -#include <fdtdec.h> -#include <spi.h> -#include <spi_flash.h> -#include <div64.h> -#include <linux/err.h> -#include <linux/math64.h> - -#include "sf_internal.h" - -/* reads can bypass the buffers */ -#define OP_READ_CONTINUOUS 0xE8 -#define OP_READ_PAGE 0xD2 - -/* group B requests can run even while status reports "busy" */ -#define OP_READ_STATUS 0xD7 /* group B */ - -/* move data between host and buffer */ -#define OP_READ_BUFFER1 0xD4 /* group B */ -#define OP_READ_BUFFER2 0xD6 /* group B */ -#define OP_WRITE_BUFFER1 0x84 /* group B */ -#define OP_WRITE_BUFFER2 0x87 /* group B */ - -/* erasing flash */ -#define OP_ERASE_PAGE 0x81 -#define OP_ERASE_BLOCK 0x50 - -/* move data between buffer and flash */ -#define OP_TRANSFER_BUF1 0x53 -#define OP_TRANSFER_BUF2 0x55 -#define OP_MREAD_BUFFER1 0xD4 -#define OP_MREAD_BUFFER2 0xD6 -#define OP_MWERASE_BUFFER1 0x83 -#define OP_MWERASE_BUFFER2 0x86 -#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ -#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ - -/* write to buffer, then write-erase to flash */ -#define OP_PROGRAM_VIA_BUF1 0x82 -#define OP_PROGRAM_VIA_BUF2 0x85 - -/* compare buffer to flash */ -#define OP_COMPARE_BUF1 0x60 -#define OP_COMPARE_BUF2 0x61 - -/* read flash to buffer, then write-erase to flash */ -#define OP_REWRITE_VIA_BUF1 0x58 -#define OP_REWRITE_VIA_BUF2 0x59 - -/* - * newer chips report JEDEC manufacturer and device IDs; chip - * serial number and OTP bits; and per-sector writeprotect. - */ -#define OP_READ_ID 0x9F -#define OP_READ_SECURITY 0x77 -#define OP_WRITE_SECURITY_REVC 0x9A -#define OP_WRITE_SECURITY 0x9B /* revision D */ - - -struct dataflash { - uint8_t command[16]; - unsigned short page_offset; /* offset in flash address */ -}; - -/* - * Return the status of the DataFlash device. - */ -static inline int dataflash_status(struct spi_slave *spi) -{ - int ret; - u8 status; - /* - * NOTE: at45db321c over 25 MHz wants to write - * a dummy byte after the opcode... - */ - ret = spi_flash_cmd(spi, OP_READ_STATUS, &status, 1); - return ret ? -EIO : status; -} - -/* - * Poll the DataFlash device until it is READY. - * This usually takes 5-20 msec or so; more for sector erase. - * ready: return > 0 - */ -static int dataflash_waitready(struct spi_slave *spi) -{ - int status; - int timeout = 2 * CONFIG_SYS_HZ; - int timebase; - - timebase = get_timer(0); - do { - status = dataflash_status(spi); - if (status < 0) - status = 0; - - if (status & (1 << 7)) /* RDY/nBSY */ - return status; - - mdelay(3); - } while (get_timer(timebase) < timeout); - - return -ETIME; -} - -/* - * Erase pages of flash. - */ -static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) -{ - struct dataflash *dataflash; - struct spi_flash *spi_flash; - struct spi_slave *spi; - unsigned blocksize; - uint8_t *command; - uint32_t rem; - int status; - - dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - spi = spi_flash->spi; - - blocksize = spi_flash->page_size << 3; - - memset(dataflash->command, 0 , sizeof(dataflash->command)); - command = dataflash->command; - - debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); - - div_u64_rem(len, spi_flash->page_size, &rem); - if (rem) - return -EINVAL; - div_u64_rem(offset, spi_flash->page_size, &rem); - if (rem) - return -EINVAL; - - status = spi_claim_bus(spi); - if (status) { - debug("SPI DATAFLASH: unable to claim SPI bus\n"); - return status; - } - - while (len > 0) { - unsigned int pageaddr; - int do_block; - /* - * Calculate flash page address; use block erase (for speed) if - * we're at a block boundary and need to erase the whole block. - */ - pageaddr = div_u64(offset, spi_flash->page_size); - do_block = (pageaddr & 0x7) == 0 && len >= blocksize; - pageaddr = pageaddr << dataflash->page_offset; - - command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; - command[1] = (uint8_t)(pageaddr >> 16); - command[2] = (uint8_t)(pageaddr >> 8); - command[3] = 0; - - debug("%s ERASE %s: (%x) %x %x %x [%d]\n", - dev->name, do_block ? "block" : "page", - command[0], command[1], command[2], command[3], - pageaddr); - - status = spi_flash_cmd_write(spi, command, 4, NULL, 0); - if (status < 0) { - debug("%s: erase send command error!\n", dev->name); - return -EIO; - } - - status = dataflash_waitready(spi); - if (status < 0) { - debug("%s: erase waitready error!\n", dev->name); - return status; - } - - if (do_block) { - offset += blocksize; - len -= blocksize; - } else { - offset += spi_flash->page_size; - len -= spi_flash->page_size; - } - } - - spi_release_bus(spi); - - return 0; -} - -/* - * Read from the DataFlash device. - * offset : Start offset in flash device - * len : Amount to read - * buf : Buffer containing the data - */ -static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, - void *buf) -{ - struct dataflash *dataflash; - struct spi_flash *spi_flash; - struct spi_slave *spi; - unsigned int addr; - uint8_t *command; - int status; - - dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - spi = spi_flash->spi; - - memset(dataflash->command, 0 , sizeof(dataflash->command)); - command = dataflash->command; - - debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); - debug("READ: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - - /* Calculate flash page/byte address */ - addr = (((unsigned)offset / spi_flash->page_size) - << dataflash->page_offset) - + ((unsigned)offset % spi_flash->page_size); - - status = spi_claim_bus(spi); - if (status) { - debug("SPI DATAFLASH: unable to claim SPI bus\n"); - return status; - } - - /* - * Continuous read, max clock = f(car) which may be less than - * the peak rate available. Some chips support commands with - * fewer "don't care" bytes. Both buffers stay unchanged. - */ - command[0] = OP_READ_CONTINUOUS; - command[1] = (uint8_t)(addr >> 16); - command[2] = (uint8_t)(addr >> 8); - command[3] = (uint8_t)(addr >> 0); - - /* plus 4 "don't care" bytes, command len: 4 + 4 "don't care" bytes */ - status = spi_flash_cmd_read(spi, command, 8, buf, len); - - spi_release_bus(spi); - - return status; -} - -/* - * Write to the DataFlash device. - * offset : Start offset in flash device - * len : Amount to write - * buf : Buffer containing the data - */ -int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) -{ - struct dataflash *dataflash; - struct spi_flash *spi_flash; - struct spi_slave *spi; - uint8_t *command; - unsigned int pageaddr, addr, to, writelen; - size_t remaining = len; - u_char *writebuf = (u_char *)buf; - int status = -EINVAL; - - dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - spi = spi_flash->spi; - - memset(dataflash->command, 0 , sizeof(dataflash->command)); - command = dataflash->command; - - debug("%s: write 0x%x..0x%x\n", dev->name, offset, (offset + len)); - - pageaddr = ((unsigned)offset / spi_flash->page_size); - to = ((unsigned)offset % spi_flash->page_size); - if (to + len > spi_flash->page_size) - writelen = spi_flash->page_size - to; - else - writelen = len; - - status = spi_claim_bus(spi); - if (status) { - debug("SPI DATAFLASH: unable to claim SPI bus\n"); - return status; - } - - while (remaining > 0) { - debug("write @ %d:%d len=%d\n", pageaddr, to, writelen); - - /* - * REVISIT: - * (a) each page in a sector must be rewritten at least - * once every 10K sibling erase/program operations. - * (b) for pages that are already erased, we could - * use WRITE+MWRITE not PROGRAM for ~30% speedup. - * (c) WRITE to buffer could be done while waiting for - * a previous MWRITE/MWERASE to complete ... - * (d) error handling here seems to be mostly missing. - * - * Two persistent bits per page, plus a per-sector counter, - * could support (a) and (b) ... we might consider using - * the second half of sector zero, which is just one block, - * to track that state. (On AT91, that sector should also - * support boot-from-DataFlash.) - */ - - addr = pageaddr << dataflash->page_offset; - - /* (1) Maybe transfer partial page to Buffer1 */ - if (writelen != spi_flash->page_size) { - command[0] = OP_TRANSFER_BUF1; - command[1] = (addr & 0x00FF0000) >> 16; - command[2] = (addr & 0x0000FF00) >> 8; - command[3] = 0; - - debug("TRANSFER: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - - status = spi_flash_cmd_write(spi, command, 4, NULL, 0); - if (status < 0) { - debug("%s: write(<pagesize) command error!\n", - dev->name); - return -EIO; - } - - status = dataflash_waitready(spi); - if (status < 0) { - debug("%s: write(<pagesize) waitready error!\n", - dev->name); - return status; - } - } - - /* (2) Program full page via Buffer1 */ - addr += to; - command[0] = OP_PROGRAM_VIA_BUF1; - command[1] = (addr & 0x00FF0000) >> 16; - command[2] = (addr & 0x0000FF00) >> 8; - command[3] = (addr & 0x000000FF); - - debug("PROGRAM: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - - status = spi_flash_cmd_write(spi, command, - 4, writebuf, writelen); - if (status < 0) { - debug("%s: write send command error!\n", dev->name); - return -EIO; - } - - status = dataflash_waitready(spi); - if (status < 0) { - debug("%s: write waitready error!\n", dev->name); - return status; - } - -#ifdef CONFIG_SPI_DATAFLASH_WRITE_VERIFY - /* (3) Compare to Buffer1 */ - addr = pageaddr << dataflash->page_offset; - command[0] = OP_COMPARE_BUF1; - command[1] = (addr & 0x00FF0000) >> 16; - command[2] = (addr & 0x0000FF00) >> 8; - command[3] = 0; - - debug("COMPARE: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - - status = spi_flash_cmd_write(spi, command, - 4, writebuf, writelen); - if (status < 0) { - debug("%s: write(compare) send command error!\n", - dev->name); - return -EIO; - } - - status = dataflash_waitready(spi); - - /* Check result of the compare operation */ - if (status & (1 << 6)) { - printf("SPI DataFlash: write compare page %u, err %d\n", - pageaddr, status); - remaining = 0; - status = -EIO; - break; - } else { - status = 0; - } - -#endif /* CONFIG_SPI_DATAFLASH_WRITE_VERIFY */ - remaining = remaining - writelen; - pageaddr++; - to = 0; - writebuf += writelen; - - if (remaining > spi_flash->page_size) - writelen = spi_flash->page_size; - else - writelen = remaining; - } - - spi_release_bus(spi); - - return 0; -} - -static int add_dataflash(struct udevice *dev, char *name, int nr_pages, - int pagesize, int pageoffset, char revision) -{ - struct spi_flash *spi_flash; - struct dataflash *dataflash; - - dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - - dataflash->page_offset = pageoffset; - - spi_flash->name = name; - spi_flash->page_size = pagesize; - spi_flash->size = nr_pages * pagesize; - spi_flash->erasesize = pagesize; - -#ifndef CONFIG_SPL_BUILD - printf("SPI DataFlash: Detected %s with page size ", spi_flash->name); - print_size(spi_flash->page_size, ", erase size "); - print_size(spi_flash->erasesize, ", total "); - print_size(spi_flash->size, ""); - printf(", revision %c", revision); - puts("\n"); -#endif - - return 0; -} - -struct flash_info { - char *name; - - /* - * JEDEC id has a high byte of zero plus three data bytes: - * the manufacturer id, then a two byte device id. - */ - uint32_t jedec_id; - - /* The size listed here is what works with OP_ERASE_PAGE. */ - unsigned nr_pages; - uint16_t pagesize; - uint16_t pageoffset; - - uint16_t flags; -#define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ -#define IS_POW2PS 0x0001 /* uses 2^N byte pages */ -}; - -static struct flash_info dataflash_data[] = { - /* - * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, - * one with IS_POW2PS and the other without. The entry with the - * non-2^N byte page size can't name exact chip revisions without - * losing backwards compatibility for cmdlinepart. - * - * Those two entries have different name spelling format in order to - * show their difference obviously. - * The upper case refer to the chip isn't in normal 2^N bytes page-size - * mode. - * The lower case refer to the chip is in normal 2^N bytes page-size - * mode. - * - * These newer chips also support 128-byte security registers (with - * 64 bytes one-time-programmable) and software write-protection. - */ - { "AT45DB011B", 0x1f2200, 512, 264, 9, SUP_POW2PS}, - { "at45db011d", 0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, - { "at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, - { "at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, - { "at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, - { "at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */ - - { "AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, - { "at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS}, - - { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, - { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, -}; - -static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id) -{ - int tmp; - uint32_t jedec; - struct flash_info *info; - int status; - - /* - * JEDEC also defines an optional "extended device information" - * string for after vendor-specific data, after the three bytes - * we use here. Supporting some chips might require using it. - * - * If the vendor ID isn't Atmel's (0x1f), assume this call failed. - * That's not an error; only rev C and newer chips handle it, and - * only Atmel sells these chips. - */ - if (id[0] != 0x1f) - return NULL; - - jedec = id[0]; - jedec = jedec << 8; - jedec |= id[1]; - jedec = jedec << 8; - jedec |= id[2]; - - for (tmp = 0, info = dataflash_data; - tmp < ARRAY_SIZE(dataflash_data); - tmp++, info++) { - if (info->jedec_id == jedec) { - if (info->flags & SUP_POW2PS) { - status = dataflash_status(spi); - if (status < 0) { - debug("SPI DataFlash: status error %d\n", - status); - return NULL; - } - if (status & 0x1) { - if (info->flags & IS_POW2PS) - return info; - } else { - if (!(info->flags & IS_POW2PS)) - return info; - } - } else { - return info; - } - } - } - - /* - * Treat other chips as errors ... we won't know the right page - * size (it might be binary) even when we can tell which density - * class is involved (legacy chip id scheme). - */ - printf("SPI DataFlash: Unsupported flash IDs: "); - printf("manuf %02x, jedec %04x, ext_jedec %04x\n", - id[0], jedec, id[3] << 8 | id[4]); - return NULL; -} - -/* - * Detect and initialize DataFlash device, using JEDEC IDs on newer chips - * or else the ID code embedded in the status bits: - * - * Device Density ID code #Pages PageSize Offset - * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 - * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1024 264 9 - * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 - * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 - * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 - * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 - * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 - * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 - */ -static int spi_dataflash_probe(struct udevice *dev) -{ - struct spi_slave *spi = dev_get_parent_priv(dev); - struct spi_flash *spi_flash; - struct flash_info *info; - u8 idcode[5]; - int ret, status = 0; - - spi_flash = dev_get_uclass_priv(dev); - spi_flash->dev = dev; - - ret = spi_claim_bus(spi); - if (ret) - return ret; - - ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); - if (ret) { - printf("SPI DataFlash: Failed to get idcodes\n"); - goto err_read_cmd; - } - - /* - * Try to detect dataflash by JEDEC ID. - * If it succeeds we know we have either a C or D part. - * D will support power of 2 pagesize option. - * Both support the security register, though with different - * write procedures. - */ - info = jedec_probe(spi, idcode); - if (info != NULL) - add_dataflash(dev, info->name, info->nr_pages, - info->pagesize, info->pageoffset, - (info->flags & SUP_POW2PS) ? 'd' : 'c'); - else { - /* - * Older chips support only legacy commands, identifing - * capacity using bits in the status byte. - */ - status = dataflash_status(spi); - if (status <= 0 || status == 0xff) { - printf("SPI DataFlash: read status error %d\n", status); - if (status == 0 || status == 0xff) - status = -ENODEV; - goto err_read_cmd; - } - /* - * if there's a device there, assume it's dataflash. - * board setup should have set spi->max_speed_max to - * match f(car) for continuous reads, mode 0 or 3. - */ - switch (status & 0x3c) { - case 0x0c: /* 0 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB011B", - 512, 264, 9, 0); - break; - case 0x14: /* 0 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB021B", - 1024, 264, 9, 0); - break; - case 0x1c: /* 0 1 1 1 x x */ - status = add_dataflash(dev, "AT45DB041x", - 2048, 264, 9, 0); - break; - case 0x24: /* 1 0 0 1 x x */ - status = add_dataflash(dev, "AT45DB081B", - 4096, 264, 9, 0); - break; - case 0x2c: /* 1 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB161x", - 4096, 528, 10, 0); - break; - case 0x34: /* 1 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB321x", - 8192, 528, 10, 0); - break; - case 0x38: /* 1 1 1 x x x */ - case 0x3c: - status = add_dataflash(dev, "AT45DB642x", - 8192, 1056, 11, 0); - break; - /* obsolete AT45DB1282 not (yet?) supported */ - default: - dev_info(&spi->dev, "unsupported device (%x)\n", - status & 0x3c); - status = -ENODEV; - goto err_read_cmd; - } - } - - /* Assign spi data */ - spi_flash->spi = spi; - spi_flash->memory_map = spi->memory_map; - spi_flash->dual_flash = spi->option; - - spi_release_bus(spi); - - return 0; - -err_read_cmd: - spi_release_bus(spi); - - return status; -} - -static const struct dm_spi_flash_ops spi_dataflash_ops = { - .read = spi_dataflash_read, - .write = spi_dataflash_write, - .erase = spi_dataflash_erase, -}; - -static const struct udevice_id spi_dataflash_ids[] = { - { .compatible = "atmel,at45", }, - { .compatible = "atmel,dataflash", }, - { } -}; - -U_BOOT_DRIVER(spi_dataflash) = { - .name = "spi_dataflash", - .id = UCLASS_SPI_FLASH, - .of_match = spi_dataflash_ids, - .probe = spi_dataflash_probe, - .priv_auto_alloc_size = sizeof(struct dataflash), - .ops = &spi_dataflash_ops, -}; diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h deleted file mode 100644 index 007a5a0..0000000 --- a/drivers/mtd/spi/sf_internal.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * SPI flash internal definitions - * - * Copyright (C) 2008 Atmel Corporation - * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _SF_INTERNAL_H_ -#define _SF_INTERNAL_H_ - -#include <linux/types.h> -#include <linux/compiler.h> - -/* Dual SPI flash memories - see SPI_COMM_DUAL_... */ -enum spi_dual_flash { - SF_SINGLE_FLASH = 0, - SF_DUAL_STACKED_FLASH = BIT(0), - SF_DUAL_PARALLEL_FLASH = BIT(1), -}; - -/* Enum list - Full read commands */ -enum spi_read_cmds { - ARRAY_SLOW = BIT(0), - ARRAY_FAST = BIT(1), - DUAL_OUTPUT_FAST = BIT(2), - QUAD_OUTPUT_FAST = BIT(3), - DUAL_IO_FAST = BIT(4), - QUAD_IO_FAST = BIT(5), -}; - -/* Normal - Extended - Full command set */ -#define RD_NORM (ARRAY_SLOW | ARRAY_FAST) -#define RD_EXTN (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST) -#define RD_FULL (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST) - -/* sf param flags */ -enum { -#ifndef CONFIG_SPI_FLASH_USE_4K_SECTORS - SECT_4K = 0, -#else - SECT_4K = BIT(0), -#endif - SECT_32K = BIT(1), - E_FSR = BIT(2), - SST_WR = BIT(3), - WR_QPP = BIT(4), -}; - -enum spi_nor_option_flags { - SNOR_F_SST_WR = BIT(0), - SNOR_F_USE_FSR = BIT(1), -}; - -#define SPI_FLASH_3B_ADDR_LEN 3 -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) -#define SPI_FLASH_16MB_BOUN 0x1000000 - -/* CFI Manufacture ID's */ -#define SPI_FLASH_CFI_MFR_SPANSION 0x01 -#define SPI_FLASH_CFI_MFR_STMICRO 0x20 -#define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 -#define SPI_FLASH_CFI_MFR_SST 0xbf -#define SPI_FLASH_CFI_MFR_WINBOND 0xef -#define SPI_FLASH_CFI_MFR_ATMEL 0x1f - -/* Erase commands */ -#define CMD_ERASE_4K 0x20 -#define CMD_ERASE_32K 0x52 -#define CMD_ERASE_CHIP 0xc7 -#define CMD_ERASE_64K 0xd8 - -/* Write commands */ -#define CMD_WRITE_STATUS 0x01 -#define CMD_PAGE_PROGRAM 0x02 -#define CMD_WRITE_DISABLE 0x04 -#define CMD_WRITE_ENABLE 0x06 -#define CMD_QUAD_PAGE_PROGRAM 0x32 -#define CMD_WRITE_EVCR 0x61 - -/* Read commands */ -#define CMD_READ_ARRAY_SLOW 0x03 -#define CMD_READ_ARRAY_FAST 0x0b -#define CMD_READ_DUAL_OUTPUT_FAST 0x3b -#define CMD_READ_DUAL_IO_FAST 0xbb -#define CMD_READ_QUAD_OUTPUT_FAST 0x6b -#define CMD_READ_QUAD_IO_FAST 0xeb -#define CMD_READ_ID 0x9f -#define CMD_READ_STATUS 0x05 -#define CMD_READ_STATUS1 0x35 -#define CMD_READ_CONFIG 0x35 -#define CMD_FLAG_STATUS 0x70 -#define CMD_READ_EVCR 0x65 - -/* Bank addr access commands */ -#ifdef CONFIG_SPI_FLASH_BAR -# define CMD_BANKADDR_BRWR 0x17 -# define CMD_BANKADDR_BRRD 0x16 -# define CMD_EXTNADDR_WREAR 0xC5 -# define CMD_EXTNADDR_RDEAR 0xC8 -#endif - -/* Common status */ -#define STATUS_WIP BIT(0) -#define STATUS_QEB_WINSPAN BIT(1) -#define STATUS_QEB_MXIC BIT(6) -#define STATUS_PEC BIT(7) -#define STATUS_QEB_MICRON BIT(7) -#define SR_BP0 BIT(2) /* Block protect 0 */ -#define SR_BP1 BIT(3) /* Block protect 1 */ -#define SR_BP2 BIT(4) /* Block protect 2 */ - -/* Flash timeout values */ -#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) -#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) -#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) - -/* SST specific */ -#ifdef CONFIG_SPI_FLASH_SST -# define CMD_SST_BP 0x02 /* Byte Program */ -# define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ - -int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); -int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); -#endif - -/** - * struct spi_flash_params - SPI/QSPI flash device params structure - * - * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) - * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) - * @ext_jedec: Device ext_jedec ID - * @sector_size: Isn't necessarily a sector size from vendor, - * the size listed here is what works with CMD_ERASE_64K - * @nr_sectors: No.of sectors on this device - * @e_rd_cmd: Enum list for read commands - * @flags: Important param, for flash specific behaviour - */ -struct spi_flash_params { - const char *name; - u32 jedec; - u16 ext_jedec; - u32 sector_size; - u32 nr_sectors; - u8 e_rd_cmd; - u16 flags; -}; - -extern const struct spi_flash_params spi_flash_params_table[]; - -/* Send a single-byte command to the device and read the response */ -int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); - -/* - * Send a multi-byte command to the device and read the response. Used - * for flash array reads, etc. - */ -int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len); - -/* - * Send a multi-byte command to the device followed by (optional) - * data. Used for programming the flash array, etc. - */ -int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, - const void *data, size_t data_len); - - -/* Flash erase(sectors) operation, support all possible erase commands */ -int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); - -/* Lock stmicro spi flash region */ -int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); - -/* Unlock stmicro spi flash region */ -int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); - -/* Check if a stmicro spi flash region is completely locked */ -int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); - -/* Enable writing on the SPI flash */ -static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) -{ - return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); -} - -/* Disable writing on the SPI flash */ -static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) -{ - return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); -} - -/* - * Used for spi_flash write operation - * - SPI claim - * - spi_flash_cmd_write_enable - * - spi_flash_cmd_write - * - spi_flash_cmd_wait_ready - * - SPI release - */ -int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, const void *buf, size_t buf_len); - -/* - * Flash write operation, support all possible write commands. - * Write the requested data out breaking it up into multiple write - * commands as needed per the write size. - */ -int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, - size_t len, const void *buf); - -/* - * Same as spi_flash_cmd_read() except it also claims/releases the SPI - * bus. Used as common part of the ->read() operation. - */ -int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len); - -/* Flash read operation, support all possible read commands */ -int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, - size_t len, void *data); - -#ifdef CONFIG_SPI_FLASH_MTD -int spi_flash_mtd_register(struct spi_flash *flash); -void spi_flash_mtd_unregister(void); -#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_ */ diff --git a/drivers/mtd/spi/sf_mtd.c b/drivers/mtd/spi/sf_mtd.c deleted file mode 100644 index 9a8302d..0000000 --- a/drivers/mtd/spi/sf_mtd.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2012-2014 Daniel Schwierzeck, daniel.schwierzeck@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <malloc.h> -#include <asm/errno.h> -#include <linux/mtd/mtd.h> -#include <spi_flash.h> - -static struct mtd_info sf_mtd_info; -static char sf_mtd_name[8]; - -static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct spi_flash *flash = mtd->priv; - int err; - - instr->state = MTD_ERASING; - - err = spi_flash_erase(flash, instr->addr, instr->len); - if (err) { - instr->state = MTD_ERASE_FAILED; - instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; - return -EIO; - } - - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - - return 0; -} - -static int spi_flash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct spi_flash *flash = mtd->priv; - int err; - - err = spi_flash_read(flash, from, len, buf); - if (!err) - *retlen = len; - - return err; -} - -static int spi_flash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct spi_flash *flash = mtd->priv; - int err; - - err = spi_flash_write(flash, to, len, buf); - if (!err) - *retlen = len; - - return err; -} - -static void spi_flash_mtd_sync(struct mtd_info *mtd) -{ -} - -static int spi_flash_mtd_number(void) -{ -#ifdef CONFIG_SYS_MAX_FLASH_BANKS - return CONFIG_SYS_MAX_FLASH_BANKS; -#else - return 0; -#endif -} - -int spi_flash_mtd_register(struct spi_flash *flash) -{ - memset(&sf_mtd_info, 0, sizeof(sf_mtd_info)); - sprintf(sf_mtd_name, "nor%d", spi_flash_mtd_number()); - - sf_mtd_info.name = sf_mtd_name; - sf_mtd_info.type = MTD_NORFLASH; - sf_mtd_info.flags = MTD_CAP_NORFLASH; - sf_mtd_info.writesize = 1; - sf_mtd_info.writebufsize = flash->page_size; - - sf_mtd_info._erase = spi_flash_mtd_erase; - sf_mtd_info._read = spi_flash_mtd_read; - sf_mtd_info._write = spi_flash_mtd_write; - sf_mtd_info._sync = spi_flash_mtd_sync; - - sf_mtd_info.size = flash->size; - sf_mtd_info.priv = flash; - - /* Only uniform flash devices for now */ - sf_mtd_info.numeraseregions = 0; - sf_mtd_info.erasesize = flash->erasesize; - - return add_mtd_device(&sf_mtd_info); -} - -void spi_flash_mtd_unregister(void) -{ - del_mtd_device(&sf_mtd_info); -} diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c deleted file mode 100644 index 4f37e33..0000000 --- a/drivers/mtd/spi/sf_params.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPI flash Params table - * - * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <spi.h> -#include <spi_flash.h> - -#include "sf_internal.h" - -/* SPI/QSPI flash device params structure */ -const struct spi_flash_params spi_flash_params_table[] = { -#ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ - {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K}, - {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, - {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, - {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K}, - {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K}, - {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, - {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, - {"AT26DF081A", 0x1f4501, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K}, -#endif -#ifdef CONFIG_SPI_FLASH_EON /* EON */ - {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, RD_NORM, 0}, - {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, RD_NORM, 0}, - {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, RD_NORM, 0}, -#endif -#ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ - {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, -#endif -#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ - {"IS25LP032", 0x9d6016, 0x0, 64 * 1024, 64, RD_NORM, 0}, - {"IS25LP064", 0x9d6017, 0x0, 64 * 1024, 128, RD_NORM, 0}, - {"IS25LP128", 0x9d6018, 0x0, 64 * 1024, 256, RD_NORM, 0}, -#endif -#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ - {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, RD_NORM, 0}, - {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, RD_NORM, 0}, - {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, RD_NORM, 0}, - {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, RD_NORM, 0}, - {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, RD_NORM, 0}, - {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, RD_NORM, 0}, - {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP}, - {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP}, - {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, -#endif -#ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ - {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, RD_NORM, 0}, - {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, RD_NORM, 0}, - {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, RD_NORM, 0}, - {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, RD_NORM, 0}, - {"S25FL116K", 0x014015, 0x0, 64 * 1024, 128, RD_NORM, 0}, - {"S25FL164K", 0x014017, 0x0140, 64 * 1024, 128, RD_NORM, 0}, - {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, RD_FULL, WR_QPP}, - {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, RD_FULL, WR_QPP}, - {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, RD_FULL, WR_QPP}, - {"S25FL128S_256K", 0x012018, 0x4d00, 256 * 1024, 64, RD_FULL, WR_QPP}, - {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"S25FL256S_256K", 0x010219, 0x4d00, 256 * 1024, 128, RD_FULL, WR_QPP}, - {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_FULL, WR_QPP}, - {"S25FL512S_256K", 0x010220, 0x4d00, 256 * 1024, 256, RD_FULL, WR_QPP}, - {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL, WR_QPP}, - {"S25FL512S_512K", 0x010220, 0x4f00, 256 * 1024, 256, RD_FULL, WR_QPP}, -#endif -#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ - {"M25P10", 0x202011, 0x0, 32 * 1024, 4, RD_NORM, 0}, - {"M25P20", 0x202012, 0x0, 64 * 1024, 4, RD_NORM, 0}, - {"M25P40", 0x202013, 0x0, 64 * 1024, 8, RD_NORM, 0}, - {"M25P80", 0x202014, 0x0, 64 * 1024, 16, RD_NORM, 0}, - {"M25P16", 0x202015, 0x0, 64 * 1024, 32, RD_NORM, 0}, - {"M25PE16", 0x208015, 0x1000, 64 * 1024, 32, RD_NORM, 0}, - {"M25PX16", 0x207115, 0x1000, 64 * 1024, 32, RD_EXTN, 0}, - {"M25P32", 0x202016, 0x0, 64 * 1024, 64, RD_NORM, 0}, - {"M25P64", 0x202017, 0x0, 64 * 1024, 128, RD_NORM, 0}, - {"M25P128", 0x202018, 0x0, 256 * 1024, 64, RD_NORM, 0}, - {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP | E_FSR | SECT_4K}, - {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP | E_FSR | SECT_4K}, - {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, - {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, -#endif -#ifdef CONFIG_SPI_FLASH_SST /* SST */ - {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, - {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WR}, - {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K | SST_WR}, - {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K | SST_WR}, - {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, RD_NORM, SECT_4K | SST_WR}, - {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, RD_NORM, SECT_4K | SST_WR}, - {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K | SST_WR}, - {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, - {"SST25WF040B", 0x621613, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, - {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WR}, -#endif -#ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ - {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, RD_NORM, 0}, - {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, RD_NORM, 0}, - {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, RD_NORM, 0}, - {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, - {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K}, - {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, - {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, - {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K}, -#endif - {}, /* Empty entry to terminate the list */ - /* - * Note: - * Below paired flash devices has similar spi_flash params. - * (S25FL129P_64K, S25FL128S_64K) - * (W25Q80BL, W25Q80BV) - * (W25Q16CL, W25Q16DV) - * (W25Q32BV, W25Q32FV_SPI) - * (W25Q64CV, W25Q64FV_SPI) - * (W25Q128BV, W25Q128FV_SPI) - * (W25Q32DW, W25Q32FV_QPI) - * (W25Q64DW, W25Q64FV_QPI) - * (W25Q128FW, W25Q128FV_QPI) - */ -}; diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c deleted file mode 100644 index daa1d5b..0000000 --- a/drivers/mtd/spi/sf_probe.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * SPI flash probing - * - * Copyright (C) 2008 Atmel Corporation - * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik - * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <dm.h> -#include <errno.h> -#include <malloc.h> -#include <spi.h> -#include <spi_flash.h> - -#include "sf_internal.h" - -/** - * spi_flash_probe_slave() - Probe for a SPI flash device on a bus - * - * @flashp: Pointer to place to put flash info, which may be NULL if the - * space should be allocated - */ -static int spi_flash_probe_slave(struct spi_flash *flash) -{ - struct spi_slave *spi = flash->spi; - int ret; - - /* Setup spi_slave */ - if (!spi) { - printf("SF: Failed to set up slave\n"); - return -ENODEV; - } - - /* Claim spi bus */ - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: Failed to claim SPI bus: %d\n", ret); - return ret; - } - - ret = spi_flash_scan(flash); - if (ret) { - ret = -EINVAL; - goto err_read_id; - } - -#ifdef CONFIG_SPI_FLASH_MTD - ret = spi_flash_mtd_register(flash); -#endif - -err_read_id: - spi_release_bus(spi); - return ret; -} - -#ifndef CONFIG_DM_SPI_FLASH -static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) -{ - struct spi_flash *flash; - - /* Allocate space if needed (not used by sf-uclass */ - flash = calloc(1, sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate spi_flash\n"); - return NULL; - } - - flash->spi = bus; - if (spi_flash_probe_slave(flash)) { - spi_free_slave(bus); - free(flash); - return NULL; - } - - return flash; -} - -struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode) -{ - struct spi_slave *bus; - - bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); - if (!bus) - return NULL; - return spi_flash_probe_tail(bus); -} - -#ifdef CONFIG_OF_SPI_FLASH -struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, - int spi_node) -{ - struct spi_slave *bus; - - bus = spi_setup_slave_fdt(blob, slave_node, spi_node); - if (!bus) - return NULL; - return spi_flash_probe_tail(bus); -} -#endif - -void spi_flash_free(struct spi_flash *flash) -{ -#ifdef CONFIG_SPI_FLASH_MTD - spi_flash_mtd_unregister(); -#endif - spi_free_slave(flash->spi); - free(flash); -} - -#else /* defined CONFIG_DM_SPI_FLASH */ - -static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, - void *buf) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); - - return spi_flash_cmd_read_ops(flash, offset, len, buf); -} - -static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); - -#if defined(CONFIG_SPI_FLASH_SST) - if (flash->flags & SNOR_F_SST_WR) { - if (flash->spi->mode & SPI_TX_BYTE) - return sst_write_bp(flash, offset, len, buf); - else - return sst_write_wp(flash, offset, len, buf); - } -#endif - - return spi_flash_cmd_write_ops(flash, offset, len, buf); -} - -static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); - - return spi_flash_cmd_erase_ops(flash, offset, len); -} - -static int spi_flash_std_probe(struct udevice *dev) -{ - struct spi_slave *slave = dev_get_parent_priv(dev); - struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); - struct spi_flash *flash; - - flash = dev_get_uclass_priv(dev); - flash->dev = dev; - flash->spi = slave; - debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); - return spi_flash_probe_slave(flash); -} - -static const struct dm_spi_flash_ops spi_flash_std_ops = { - .read = spi_flash_std_read, - .write = spi_flash_std_write, - .erase = spi_flash_std_erase, -}; - -static const struct udevice_id spi_flash_std_ids[] = { - { .compatible = "spi-flash" }, - { } -}; - -U_BOOT_DRIVER(spi_flash_std) = { - .name = "spi_flash_std", - .id = UCLASS_SPI_FLASH, - .of_match = spi_flash_std_ids, - .probe = spi_flash_std_probe, - .priv_auto_alloc_size = sizeof(struct spi_flash), - .ops = &spi_flash_std_ops, -}; - -#endif /* CONFIG_DM_SPI_FLASH */ diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c deleted file mode 100644 index 891e1ec..0000000 --- a/drivers/mtd/spi/spi_flash.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * SPI Flash Core - * - * Copyright (C) 2015 Jagan Teki jteki@openedev.com - * 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+ - */ - -#include <common.h> -#include <errno.h> -#include <malloc.h> -#include <mapmem.h> -#include <spi.h> -#include <spi_flash.h> -#include <linux/log2.h> - -#include "sf_internal.h" - -DECLARE_GLOBAL_DATA_PTR; - -static void spi_flash_addr(u32 addr, u8 *cmd) -{ - /* cmd[0] is actual command */ - cmd[1] = addr >> 16; - cmd[2] = addr >> 8; - cmd[3] = addr >> 0; -} - -static int read_sr(struct spi_flash *flash, u8 *rs) -{ - int ret; - u8 cmd; - - cmd = CMD_READ_STATUS; - ret = spi_flash_read_common(flash, &cmd, 1, rs, 1); - if (ret < 0) { - debug("SF: fail to read status register\n"); - return ret; - } - - return 0; -} - -static int read_fsr(struct spi_flash *flash, u8 *fsr) -{ - int ret; - const u8 cmd = CMD_FLAG_STATUS; - - ret = spi_flash_read_common(flash, &cmd, 1, fsr, 1); - if (ret < 0) { - debug("SF: fail to read flag status register\n"); - return ret; - } - - return 0; -} - -static int write_sr(struct spi_flash *flash, u8 ws) -{ - u8 cmd; - int ret; - - cmd = CMD_WRITE_STATUS; - ret = spi_flash_write_common(flash, &cmd, 1, &ws, 1); - if (ret < 0) { - debug("SF: fail to write status register\n"); - return ret; - } - - return 0; -} - -#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) -static int read_cr(struct spi_flash *flash, u8 *rc) -{ - int ret; - u8 cmd; - - cmd = CMD_READ_CONFIG; - ret = spi_flash_read_common(flash, &cmd, 1, rc, 1); - if (ret < 0) { - debug("SF: fail to read config register\n"); - return ret; - } - - return 0; -} - -static int write_cr(struct spi_flash *flash, u8 wc) -{ - u8 data[2]; - u8 cmd; - int ret; - - ret = read_sr(flash, &data[0]); - if (ret < 0) - return ret; - - cmd = CMD_WRITE_STATUS; - data[1] = wc; - ret = spi_flash_write_common(flash, &cmd, 1, &data, 2); - if (ret) { - debug("SF: fail to write config register\n"); - return ret; - } - - return 0; -} -#endif - -#ifdef CONFIG_SPI_FLASH_STMICRO -static int read_evcr(struct spi_flash *flash, u8 *evcr) -{ - int ret; - const u8 cmd = CMD_READ_EVCR; - - ret = spi_flash_read_common(flash, &cmd, 1, evcr, 1); - if (ret < 0) { - debug("SF: error reading EVCR\n"); - return ret; - } - - return 0; -} - -static int write_evcr(struct spi_flash *flash, u8 evcr) -{ - u8 cmd; - int ret; - - cmd = CMD_WRITE_EVCR; - ret = spi_flash_write_common(flash, &cmd, 1, &evcr, 1); - if (ret < 0) { - debug("SF: error while writing EVCR register\n"); - return ret; - } - - return 0; -} -#endif - -#ifdef CONFIG_SPI_FLASH_BAR -static int spi_flash_write_bar(struct spi_flash *flash, u32 offset) -{ - u8 cmd, bank_sel; - int ret; - - bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift); - if (bank_sel == flash->bank_curr) - goto bar_end; - - cmd = flash->bank_write_cmd; - ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); - if (ret < 0) { - debug("SF: fail to write bank register\n"); - return ret; - } - -bar_end: - flash->bank_curr = bank_sel; - 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 bar_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; - } - -bar_end: - flash->bank_curr = curr_bank; - return 0; -} -#endif - -#ifdef CONFIG_SF_DUAL_FLASH -static void spi_flash_dual(struct spi_flash *flash, u32 *addr) -{ - struct spi_slave *spi = flash->spi; - - switch (flash->dual_flash) { - case SF_DUAL_STACKED_FLASH: - if (*addr >= (flash->size >> 1)) { - *addr -= flash->size >> 1; - spi->flags |= SPI_XFER_U_PAGE; - } else { - spi->flags &= ~SPI_XFER_U_PAGE; - } - break; - case SF_DUAL_PARALLEL_FLASH: - *addr >>= flash->shift; - break; - default: - debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash); - break; - } -} -#endif - -static int spi_flash_sr_ready(struct spi_flash *flash) -{ - u8 sr; - int ret; - - ret = read_sr(flash, &sr); - if (ret < 0) - return ret; - - return !(sr & STATUS_WIP); -} - -static int spi_flash_fsr_ready(struct spi_flash *flash) -{ - u8 fsr; - int ret; - - ret = read_fsr(flash, &fsr); - if (ret < 0) - return ret; - - return fsr & STATUS_PEC; -} - -static int spi_flash_ready(struct spi_flash *flash) -{ - int sr, fsr; - - sr = spi_flash_sr_ready(flash); - if (sr < 0) - return sr; - - fsr = 1; - if (flash->flags & SNOR_F_USE_FSR) { - fsr = spi_flash_fsr_ready(flash); - if (fsr < 0) - return fsr; - } - - return sr && fsr; -} - -static int spi_flash_cmd_wait_ready(struct spi_flash *flash, - unsigned long timeout) -{ - int timebase, ret; - - timebase = get_timer(0); - - while (get_timer(timebase) < timeout) { - ret = spi_flash_ready(flash); - if (ret < 0) - return ret; - if (ret) - return 0; - } - - printf("SF: Timeout!\n"); - - return -ETIMEDOUT; -} - -int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, const void *buf, size_t buf_len) -{ - struct spi_slave *spi = flash->spi; - unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; - int ret; - - if (buf == NULL) - timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; - - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: unable to claim SPI bus\n"); - return ret; - } - - ret = spi_flash_cmd_write_enable(flash); - if (ret < 0) { - debug("SF: enabling write failed\n"); - return ret; - } - - ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); - if (ret < 0) { - debug("SF: write cmd failed\n"); - return ret; - } - - ret = spi_flash_cmd_wait_ready(flash, timeout); - if (ret < 0) { - debug("SF: write %s timed out\n", - timeout == SPI_FLASH_PROG_TIMEOUT ? - "program" : "page erase"); - return ret; - } - - spi_release_bus(spi); - - return ret; -} - -int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) -{ - u32 erase_size, erase_addr; - u8 cmd[SPI_FLASH_CMD_LEN]; - int ret = -1; - - erase_size = flash->erasesize; - if (offset % erase_size || len % erase_size) { - debug("SF: Erase offset/length not multiple of erase size\n"); - return -1; - } - - if (flash->flash_is_locked) { - if (flash->flash_is_locked(flash, offset, len) > 0) { - printf("offset 0x%x is protected and cannot be erased\n", - offset); - return -EINVAL; - } - } - - cmd[0] = flash->erase_cmd; - while (len) { - erase_addr = offset; - -#ifdef CONFIG_SF_DUAL_FLASH - if (flash->dual_flash > SF_SINGLE_FLASH) - spi_flash_dual(flash, &erase_addr); -#endif -#ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bar(flash, erase_addr); - if (ret < 0) - return ret; -#endif - spi_flash_addr(erase_addr, cmd); - - debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], - cmd[2], cmd[3], erase_addr); - - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); - if (ret < 0) { - debug("SF: erase failed\n"); - break; - } - - offset += erase_size; - len -= erase_size; - } - - return ret; -} - -int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, - size_t len, const void *buf) -{ - struct spi_slave *spi = flash->spi; - unsigned long byte_addr, page_size; - u32 write_addr; - size_t chunk_len, actual; - u8 cmd[SPI_FLASH_CMD_LEN]; - int ret = -1; - - page_size = flash->page_size; - - if (flash->flash_is_locked) { - if (flash->flash_is_locked(flash, offset, len) > 0) { - printf("offset 0x%x is protected and cannot be written\n", - offset); - return -EINVAL; - } - } - - cmd[0] = flash->write_cmd; - for (actual = 0; actual < len; actual += chunk_len) { - write_addr = offset; - -#ifdef CONFIG_SF_DUAL_FLASH - if (flash->dual_flash > SF_SINGLE_FLASH) - spi_flash_dual(flash, &write_addr); -#endif -#ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bar(flash, write_addr); - if (ret < 0) - return ret; -#endif - byte_addr = offset % page_size; - chunk_len = min(len - actual, (size_t)(page_size - byte_addr)); - - if (spi->max_write_size) - chunk_len = min(chunk_len, - (size_t)spi->max_write_size); - - spi_flash_addr(write_addr, cmd); - - debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", - buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); - - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), - buf + actual, chunk_len); - if (ret < 0) { - debug("SF: write failed\n"); - break; - } - - offset += chunk_len; - } - - return ret; -} - -int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len) -{ - struct spi_slave *spi = flash->spi; - int ret; - - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: unable to claim SPI bus\n"); - return ret; - } - - ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); - if (ret < 0) { - debug("SF: read cmd failed\n"); - return ret; - } - - spi_release_bus(spi); - - return ret; -} - -void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len) -{ - memcpy(data, offset, len); -} - -int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, - size_t len, void *data) -{ - struct spi_slave *spi = flash->spi; - u8 *cmd, cmdsz; - u32 remain_len, read_len, read_addr; - int bank_sel = 0; - int ret = -1; - - /* Handle memory-mapped SPI */ - if (flash->memory_map) { - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: unable to claim SPI bus\n"); - return ret; - } - spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP); - spi_flash_copy_mmap(data, flash->memory_map + offset, len); - spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP_END); - spi_release_bus(spi); - return 0; - } - - cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; - cmd = calloc(1, cmdsz); - if (!cmd) { - debug("SF: Failed to allocate cmd\n"); - return -ENOMEM; - } - - cmd[0] = flash->read_cmd; - while (len) { - read_addr = offset; - -#ifdef CONFIG_SF_DUAL_FLASH - if (flash->dual_flash > SF_SINGLE_FLASH) - spi_flash_dual(flash, &read_addr); -#endif -#ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bar(flash, read_addr); - if (ret < 0) - return ret; - bank_sel = flash->bank_curr; -#endif - remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * - (bank_sel + 1)) - offset; - if (len < remain_len) - read_len = len; - else - read_len = remain_len; - - spi_flash_addr(read_addr, cmd); - - ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); - if (ret < 0) { - debug("SF: read failed\n"); - break; - } - - offset += read_len; - len -= read_len; - data += read_len; - } - - free(cmd); - return ret; -} - -#ifdef CONFIG_SPI_FLASH_SST -static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) -{ - struct spi_slave *spi = flash->spi; - int ret; - u8 cmd[4] = { - CMD_SST_BP, - offset >> 16, - offset >> 8, - offset, - }; - - debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", - spi_w8r8(spi, CMD_READ_STATUS), buf, cmd[0], offset); - - ret = spi_flash_cmd_write_enable(flash); - if (ret) - return ret; - - ret = spi_flash_cmd_write(spi, cmd, sizeof(cmd), buf, 1); - if (ret) - return ret; - - return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); -} - -int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf) -{ - struct spi_slave *spi = flash->spi; - size_t actual, cmd_len; - int ret; - u8 cmd[4]; - - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: Unable to claim SPI bus\n"); - return ret; - } - - /* If the data is not word aligned, write out leading single byte */ - actual = offset % 2; - if (actual) { - ret = sst_byte_write(flash, offset, buf); - if (ret) - goto done; - } - offset += actual; - - ret = spi_flash_cmd_write_enable(flash); - if (ret) - goto done; - - cmd_len = 4; - cmd[0] = CMD_SST_AAI_WP; - cmd[1] = offset >> 16; - cmd[2] = offset >> 8; - cmd[3] = offset; - - for (; actual < len - 1; actual += 2) { - debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", - spi_w8r8(spi, CMD_READ_STATUS), buf + actual, - cmd[0], offset); - - ret = spi_flash_cmd_write(spi, cmd, cmd_len, - buf + actual, 2); - if (ret) { - debug("SF: sst word program failed\n"); - break; - } - - ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); - if (ret) - break; - - cmd_len = 1; - offset += 2; - } - - if (!ret) - ret = spi_flash_cmd_write_disable(flash); - - /* If there is a single trailing byte, write it out */ - if (!ret && actual != len) - ret = sst_byte_write(flash, offset, buf + actual); - - done: - debug("SF: sst: program %s %zu bytes @ 0x%zx\n", - ret ? "failure" : "success", len, offset - actual); - - spi_release_bus(spi); - return ret; -} - -int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf) -{ - struct spi_slave *spi = flash->spi; - size_t actual; - int ret; - - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: Unable to claim SPI bus\n"); - return ret; - } - - for (actual = 0; actual < len; actual++) { - ret = sst_byte_write(flash, offset, buf + actual); - if (ret) { - debug("SF: sst byte program failed\n"); - break; - } - offset++; - } - - if (!ret) - ret = spi_flash_cmd_write_disable(flash); - - debug("SF: sst: program %s %zu bytes @ 0x%zx\n", - ret ? "failure" : "success", len, offset - actual); - - spi_release_bus(spi); - return ret; -} -#endif - -#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) -static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, - u32 *len) -{ - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - int shift = ffs(mask) - 1; - int pow; - - if (!(sr & mask)) { - /* No protection */ - *ofs = 0; - *len = 0; - } else { - pow = ((sr & mask) ^ mask) >> shift; - *len = flash->size >> pow; - *ofs = flash->size - *len; - } -} - -/* - * Return 1 if the entire region is locked, 0 otherwise - */ -static int stm_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len, - u8 sr) -{ - loff_t lock_offs; - u32 lock_len; - - stm_get_locked_range(flash, sr, &lock_offs, &lock_len); - - return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); -} - -/* - * Check if a region of the flash is (completely) locked. See stm_lock() for - * more info. - * - * Returns 1 if entire region is locked, 0 if any portion is unlocked, and - * negative on errors. - */ -int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) -{ - int status; - u8 sr; - - status = read_sr(flash, &sr); - if (status < 0) - return status; - - return stm_is_locked_sr(flash, ofs, len, sr); -} - -/* - * Lock a region of the flash. Compatible with ST Micro and similar flash. - * Supports only the block protection bits BP{0,1,2} in the status register - * (SR). Does not support these features found in newer SR bitfields: - * - TB: top/bottom protect - only handle TB=0 (top protect) - * - SEC: sector/block protect - only handle SEC=0 (block protect) - * - CMP: complement protect - only support CMP=0 (range is not complemented) - * - * Sample table portion for 8MB flash (Winbond w25q64fw): - * - * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion - * -------------------------------------------------------------------------- - * X | X | 0 | 0 | 0 | NONE | NONE - * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 - * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 - * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 - * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 - * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 - * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 - * X | X | 1 | 1 | 1 | 8 MB | ALL - * - * Returns negative on errors, 0 on success. - */ -int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) -{ - u8 status_old, status_new; - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - u8 shift = ffs(mask) - 1, pow, val; - int ret; - - ret = read_sr(flash, &status_old); - if (ret < 0) - return ret; - - /* SPI NOR always locks to the end */ - if (ofs + len != flash->size) { - /* Does combined region extend to end? */ - if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len, - status_old)) - return -EINVAL; - len = flash->size - ofs; - } - - /* - * Need smallest pow such that: - * - * 1 / (2^pow) <= (len / size) - * - * so (assuming power-of-2 size) we do: - * - * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) - */ - pow = ilog2(flash->size) - ilog2(len); - val = mask - (pow << shift); - if (val & ~mask) - return -EINVAL; - - /* Don't "lock" with no region! */ - if (!(val & mask)) - return -EINVAL; - - status_new = (status_old & ~mask) | val; - - /* Only modify protection if it will not unlock other areas */ - if ((status_new & mask) <= (status_old & mask)) - return -EINVAL; - - write_sr(flash, status_new); - - return 0; -} - -/* - * Unlock a region of the flash. See stm_lock() for more info - * - * Returns negative on errors, 0 on success. - */ -int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) -{ - uint8_t status_old, status_new; - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - u8 shift = ffs(mask) - 1, pow, val; - int ret; - - ret = read_sr(flash, &status_old); - if (ret < 0) - return ret; - - /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(flash, ofs - flash->erasesize, flash->erasesize, - status_old)) - return -EINVAL; - /* - * Need largest pow such that: - * - * 1 / (2^pow) >= (len / size) - * - * so (assuming power-of-2 size) we do: - * - * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) - */ - pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len)); - if (ofs + len == flash->size) { - val = 0; /* fully unlocked */ - } else { - val = mask - (pow << shift); - /* Some power-of-two sizes are not supported */ - if (val & ~mask) - return -EINVAL; - } - - status_new = (status_old & ~mask) | val; - - /* Only modify protection if it will not lock other areas */ - if ((status_new & mask) >= (status_old & mask)) - return -EINVAL; - - write_sr(flash, status_new); - - return 0; -} -#endif - - -#ifdef CONFIG_SPI_FLASH_MACRONIX -static int macronix_quad_enable(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) - return 0; - - ret = write_sr(flash, qeb_status | STATUS_QEB_MXIC); - if (ret < 0) - return ret; - - /* read SR and check it */ - ret = read_sr(flash, &qeb_status); - if (!(ret >= 0 && (qeb_status & STATUS_QEB_MXIC))) { - printf("SF: Macronix SR Quad bit not clear\n"); - return -EINVAL; - } - - return ret; -} -#endif - -#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) -static int spansion_quad_enable(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) - return 0; - - ret = write_cr(flash, qeb_status | STATUS_QEB_WINSPAN); - if (ret < 0) - return ret; - - /* read CR and check it */ - ret = read_cr(flash, &qeb_status); - if (!(ret >= 0 && (qeb_status & STATUS_QEB_WINSPAN))) { - printf("SF: Spansion CR Quad bit not clear\n"); - return -EINVAL; - } - - return ret; -} -#endif - -#ifdef CONFIG_SPI_FLASH_STMICRO -static int micron_quad_enable(struct spi_flash *flash) -{ - u8 qeb_status; - int ret; - - ret = read_evcr(flash, &qeb_status); - if (ret < 0) - return ret; - - if (!(qeb_status & STATUS_QEB_MICRON)) - return 0; - - ret = write_evcr(flash, qeb_status & ~STATUS_QEB_MICRON); - if (ret < 0) - return ret; - - /* read EVCR and check it */ - ret = read_evcr(flash, &qeb_status); - if (!(ret >= 0 && !(qeb_status & STATUS_QEB_MICRON))) { - printf("SF: Micron EVCR Quad bit not clear\n"); - return -EINVAL; - } - - return ret; -} -#endif - -static int set_quad_mode(struct spi_flash *flash, u8 idcode0) -{ - switch (idcode0) { -#ifdef CONFIG_SPI_FLASH_MACRONIX - case SPI_FLASH_CFI_MFR_MACRONIX: - return macronix_quad_enable(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 spansion_quad_enable(flash); -#endif -#ifdef CONFIG_SPI_FLASH_STMICRO - case SPI_FLASH_CFI_MFR_STMICRO: - return micron_quad_enable(flash); -#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) -{ -#ifdef CONFIG_DM_SPI_FLASH - fdt_addr_t addr; - fdt_size_t size; - int node = flash->dev->of_offset; - - 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); -#endif - - 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 cmd, idcode[5]; - int ret; - static u8 spi_read_cmds_array[] = { - CMD_READ_ARRAY_SLOW, - CMD_READ_ARRAY_FAST, - CMD_READ_DUAL_OUTPUT_FAST, - CMD_READ_QUAD_OUTPUT_FAST, - CMD_READ_DUAL_IO_FAST, - CMD_READ_QUAD_IO_FAST }; - - /* 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 = 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 (spi->mode & SPI_TX_BYTE) - 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->erasesize = 4096 << flash->shift; - } else if (params->flags & SECT_32K) { - flash->erase_cmd = CMD_ERASE_32K; - flash->erasesize = 32768 << flash->shift; - } else { - flash->erase_cmd = CMD_ERASE_64K; - flash->erasesize = flash->sector_size; - } - - /* Look for the fastest read cmd */ - cmd = fls(params->e_rd_cmd & spi->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 && spi->mode & SPI_TX_QUAD) - 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 = set_quad_mode(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->erasesize, ", 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; -} diff --git a/drivers/mtd/spi/spi_spl_load.c b/drivers/mtd/spi/spi_spl_load.c deleted file mode 100644 index ca56fe9..0000000 --- a/drivers/mtd/spi/spi_spl_load.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2011 OMICRON electronics GmbH - * - * based on drivers/mtd/nand/nand_spl_load.c - * - * Copyright (C) 2011 - * Heiko Schocher, DENX Software Engineering, hs@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <spi.h> -#include <spi_flash.h> -#include <errno.h> -#include <spl.h> - -#ifdef CONFIG_SPL_OS_BOOT -/* - * Load the kernel, check for a valid header we can parse, and if found load - * the kernel and then device tree. - */ -static int spi_load_image_os(struct spi_flash *flash, - struct image_header *header) -{ - /* Read for a header, parse or error out. */ - spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, 0x40, - (void *)header); - - if (image_get_magic(header) != IH_MAGIC) - return -1; - - spl_parse_image_header(header); - - spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, - spl_image.size, (void *)spl_image.load_addr); - - /* Read device tree. */ - spi_flash_read(flash, CONFIG_SYS_SPI_ARGS_OFFS, - CONFIG_SYS_SPI_ARGS_SIZE, - (void *)CONFIG_SYS_SPL_ARGS_ADDR); - - return 0; -} -#endif - -/* - * The main entry for SPI booting. It's necessary that SDRAM is already - * configured and available since this code loads the main U-Boot image - * from SPI into SDRAM and starts it from there. - */ -int spl_spi_load_image(void) -{ - int err = 0; - struct spi_flash *flash; - struct image_header *header; - - /* - * Load U-Boot image from SPI flash into RAM - */ - - flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, - CONFIG_SF_DEFAULT_CS, - CONFIG_SF_DEFAULT_SPEED, - CONFIG_SF_DEFAULT_MODE); - if (!flash) { - puts("SPI probe failed.\n"); - return -ENODEV; - } - - /* use CONFIG_SYS_TEXT_BASE as temporary storage area */ - header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); - -#ifdef CONFIG_SPL_OS_BOOT - if (spl_start_uboot() || spi_load_image_os(flash, header)) -#endif - { - /* Load u-boot, mkimage header is 64 bytes. */ - err = spi_flash_read(flash, CONFIG_SYS_SPI_U_BOOT_OFFS, 0x40, - (void *)header); - if (err) - return err; - - spl_parse_image_header(header); - err = spi_flash_read(flash, CONFIG_SYS_SPI_U_BOOT_OFFS, - spl_image.size, (void *)spl_image.load_addr); - } - - return err; -} diff --git a/include/spi_flash.h b/include/spi_flash.h index 962fab3..c9ea9e2 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -1,8 +1,9 @@ /* * Common SPI flash Interface * - * Copyright (C) 2008 Atmel Corporation + * Copyright (C) 2016 Jagan Teki jteki@openedev.com * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. + * Copyright (C) 2008 Atmel Corporation * * SPDX-License-Identifier: GPL-2.0 */ @@ -27,90 +28,6 @@ # define CONFIG_SF_DEFAULT_BUS 0 #endif
-struct spi_slave; - -/** - * struct spi_flash - SPI flash structure - * - * @spi: SPI slave - * @dev: SPI flash device - * @name: Name of SPI flash - * @dual_flash: Indicates dual flash memories - dual stacked, parallel - * @shift: Flash shift useful in dual parallel - * @flags: Indication of spi flash flags - * @size: Total flash size - * @page_size: Write (page) size - * @sector_size: Sector size - * @erasesize: Erase size - * @bank_read_cmd: Bank read cmd - * @bank_write_cmd: Bank write cmd - * @bank_curr: Current flash bank - * @erase_cmd: Erase cmd 4K, 32K, 64K - * @read_cmd: Read cmd - Array Fast, Extn read and quad read. - * @write_cmd: Write cmd - page and quad program. - * @dummy_byte: Dummy cycles for read operation. - * @memory_map: Address of read-only SPI flash access - * @flash_lock: lock a region of the SPI Flash - * @flash_unlock: unlock a region of the SPI Flash - * @flash_is_locked: check if a region of the SPI Flash is completely locked - * @read: Flash read ops: Read len bytes at offset into buf - * Supported cmds: Fast Array Read - * @write: Flash write ops: Write len bytes from buf into offset - * Supported cmds: Page Program - * @erase: Flash erase ops: Erase len bytes from offset - * Supported cmds: Sector erase 4K, 32K, 64K - * return 0 - Success, 1 - Failure - */ -struct spi_flash { - struct spi_slave *spi; -#ifdef CONFIG_DM_SPI_FLASH - struct udevice *dev; -#endif - const char *name; - u8 dual_flash; - u8 shift; - u16 flags; - - uint64_t size; - u32 page_size; - u32 sector_size; - u32 erasesize; -#ifdef CONFIG_SPI_FLASH_BAR - u8 bank_read_cmd; - u8 bank_write_cmd; - u8 bank_curr; -#endif - u8 erase_cmd; - u8 read_cmd; - u8 write_cmd; - u8 dummy_byte; - - void *memory_map; - - int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); - int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); - int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); -#ifndef CONFIG_DM_SPI_FLASH - /* - * These are not strictly needed for driver model, but keep them here - * while the transition is in progress. - * - * Normally each driver would provide its own operations, but for - * SPI flash most chips use the same algorithms. One approach is - * to create a 'common' SPI flash device which knows how to talk - * to most devices, and then allow other drivers to be used instead - * if required, perhaps with a way of scanning through the list to - * find the driver that matches the device. - */ - int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); - int (*write)(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); - int (*erase)(struct spi_flash *flash, u32 offset, size_t len); -#endif -}; - -#ifdef CONFIG_MTD_SPI_NOR - typedef struct mtd_info spi_flash_t;
static inline int spi_flash_read(spi_flash_t *info, u32 offset, @@ -171,144 +88,6 @@ void spi_flash_free(spi_flash_t *flash);
#endif /* CONFIG_DM_MTD_SPI_NOR */
-#else - -typedef struct spi_flash spi_flash_t; - -static inline int spi_flash_protect(struct spi_flash *flash, u32 ofs, u32 len, - bool prot) -{ - if (!flash->flash_lock || !flash->flash_unlock) - return -EOPNOTSUPP; - - if (prot) - return flash->flash_lock(flash, ofs, len); - else - return flash->flash_unlock(flash, ofs, len); -} - -#endif /* CONFIG_MTD_SPI_NOR */ - -struct dm_spi_flash_ops { - int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); - int (*write)(struct udevice *dev, u32 offset, size_t len, - const void *buf); - int (*erase)(struct udevice *dev, u32 offset, size_t len); -}; - -/* Access the serial operations for a device */ -#define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops) - -#ifdef CONFIG_DM_SPI_FLASH -/** - * spi_flash_read_dm() - Read data from SPI flash - * - * @dev: SPI flash device - * @offset: Offset into device in bytes to read from - * @len: Number of bytes to read - * @buf: Buffer to put the data that is read - * @return 0 if OK, -ve on error - */ -int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf); - -/** - * spi_flash_write_dm() - Write data to SPI flash - * - * @dev: SPI flash device - * @offset: Offset into device in bytes to write to - * @len: Number of bytes to write - * @buf: Buffer containing bytes to write - * @return 0 if OK, -ve on error - */ -int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, - const void *buf); - -/** - * spi_flash_erase_dm() - Erase blocks of the SPI flash - * - * Note that @len must be a muiltiple of the flash sector size. - * - * @dev: SPI flash device - * @offset: Offset into device in bytes to start erasing - * @len: Number of bytes to erase - * @return 0 if OK, -ve on error - */ -int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); - -int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode, - struct udevice **devp); - -/* Compatibility function - this is the old U-Boot API */ -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode); - -/* Compatibility function - this is the old U-Boot API */ -void spi_flash_free(struct spi_flash *flash); - -static inline int spi_flash_read(struct spi_flash *flash, u32 offset, - size_t len, void *buf) -{ - return spi_flash_read_dm(flash->dev, offset, len, buf); -} - -static inline int spi_flash_write(struct spi_flash *flash, u32 offset, - size_t len, const void *buf) -{ - return spi_flash_write_dm(flash->dev, offset, len, buf); -} - -static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, - size_t len) -{ - return spi_flash_erase_dm(flash->dev, offset, len); -} - -struct sandbox_state; - -int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, - struct udevice *bus, int of_offset, const char *spec); - -void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs); - -#elif !defined(CONFIG_MTD_SPI_NOR) - -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode); - -/** - * Set up a new SPI flash from an fdt node - * - * @param blob Device tree blob - * @param slave_node Pointer to this SPI slave node in the device tree - * @param spi_node Cached pointer to the SPI interface this node belongs - * to - * @return 0 if ok, -1 on error - */ -struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, - int spi_node); - -void spi_flash_free(struct spi_flash *flash); - -static inline int spi_flash_read(struct spi_flash *flash, u32 offset, - size_t len, void *buf) -{ - return flash->read(flash, offset, len, buf); -} - -static inline int spi_flash_write(struct spi_flash *flash, u32 offset, - size_t len, const void *buf) -{ - return flash->write(flash, offset, len, buf); -} - -static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, - size_t len) -{ - return flash->erase(flash, offset, len); -} -#endif - void spi_boot(void) __noreturn; void spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst);
participants (1)
-
Jagan Teki