diff options
author | Tom Rini <trini@konsulko.com> | 2019-02-07 14:48:56 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2019-02-07 14:48:56 -0500 |
commit | 50e24381c097579ff2a8b171838347c82c2fba04 (patch) | |
tree | 211a78888bf1fa02244bb7dcd5963eaa050b9199 /include | |
parent | 4dfe43849a4c76ac5fc2486d20e37d459f980a00 (diff) | |
parent | 4d40e009c06742df9582f8b54f37f6cea0680ba1 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-spi
- SPI-NOR support
Diffstat (limited to 'include')
-rw-r--r-- | include/configs/T102xQDS.h | 1 | ||||
-rw-r--r-- | include/configs/T102xRDB.h | 1 | ||||
-rw-r--r-- | include/configs/T104xRDB.h | 1 | ||||
-rw-r--r-- | include/configs/T208xQDS.h | 1 | ||||
-rw-r--r-- | include/configs/T208xRDB.h | 1 | ||||
-rw-r--r-- | include/configs/cgtqmx6eval.h | 1 | ||||
-rw-r--r-- | include/configs/gw_ventana.h | 1 | ||||
-rw-r--r-- | include/configs/km/kmp204x-common.h | 1 | ||||
-rw-r--r-- | include/configs/ls1021aiot.h | 1 | ||||
-rw-r--r-- | include/configs/ls2080aqds.h | 2 | ||||
-rw-r--r-- | include/configs/rk3036_common.h | 1 | ||||
-rw-r--r-- | include/configs/rk3128_common.h | 1 | ||||
-rw-r--r-- | include/configs/rk3188_common.h | 1 | ||||
-rw-r--r-- | include/configs/rk3288_common.h | 1 | ||||
-rw-r--r-- | include/configs/rk3328_common.h | 1 | ||||
-rw-r--r-- | include/configs/socfpga_stratix10_socdk.h | 1 | ||||
-rw-r--r-- | include/configs/turris_omnia.h | 1 | ||||
-rw-r--r-- | include/linux/bitops.h | 5 | ||||
-rw-r--r-- | include/linux/mtd/cfi.h | 32 | ||||
-rw-r--r-- | include/linux/mtd/spi-nor.h | 419 | ||||
-rw-r--r-- | include/spi_flash.h | 105 |
21 files changed, 478 insertions, 101 deletions
diff --git a/include/configs/T102xQDS.h b/include/configs/T102xQDS.h index f3b0fe0144f..c63dfd31868 100644 --- a/include/configs/T102xQDS.h +++ b/include/configs/T102xQDS.h @@ -501,7 +501,6 @@ unsigned long get_board_ddr_clk(void); /* * eSPI - Enhanced SPI */ -#define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_SPEED 10000000 #define CONFIG_SF_DEFAULT_MODE 0 diff --git a/include/configs/T102xRDB.h b/include/configs/T102xRDB.h index 673d1112e22..c72be9fb387 100644 --- a/include/configs/T102xRDB.h +++ b/include/configs/T102xRDB.h @@ -498,7 +498,6 @@ unsigned long get_board_ddr_clk(void); /* * eSPI - Enhanced SPI */ -#define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_SPEED 10000000 #define CONFIG_SF_DEFAULT_MODE 0 diff --git a/include/configs/T104xRDB.h b/include/configs/T104xRDB.h index 7375d6ff460..4cecab3401e 100644 --- a/include/configs/T104xRDB.h +++ b/include/configs/T104xRDB.h @@ -521,7 +521,6 @@ $(SRCTREE)/board/freescale/t104xrdb/t1042d4_sd_rcw.cfg /* * eSPI - Enhanced SPI */ -#define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_SPEED 10000000 #define CONFIG_SF_DEFAULT_MODE 0 #define CONFIG_ENV_SPI_BUS 0 diff --git a/include/configs/T208xQDS.h b/include/configs/T208xQDS.h index 1dcf2779d75..69ec109831a 100644 --- a/include/configs/T208xQDS.h +++ b/include/configs/T208xQDS.h @@ -497,7 +497,6 @@ unsigned long get_board_ddr_clk(void); */ #ifdef CONFIG_SPI_FLASH -#define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_SPEED 10000000 #define CONFIG_SF_DEFAULT_MODE 0 #endif diff --git a/include/configs/T208xRDB.h b/include/configs/T208xRDB.h index ddb60b3d6d9..1d6a390b72d 100644 --- a/include/configs/T208xRDB.h +++ b/include/configs/T208xRDB.h @@ -437,7 +437,6 @@ unsigned long get_board_ddr_clk(void); * eSPI - Enhanced SPI */ #ifdef CONFIG_SPI_FLASH -#define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_SPEED 10000000 #define CONFIG_SF_DEFAULT_MODE 0 #endif diff --git a/include/configs/cgtqmx6eval.h b/include/configs/cgtqmx6eval.h index 5d247886aed..e01bf5bf1bb 100644 --- a/include/configs/cgtqmx6eval.h +++ b/include/configs/cgtqmx6eval.h @@ -31,7 +31,6 @@ #define CONFIG_SYS_FSL_ESDHC_ADDR 0 /* SPI NOR */ -#define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_STMICRO #define CONFIG_SPI_FLASH_SST #define CONFIG_SF_DEFAULT_BUS 0 diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h index 6cafdc66859..6e23fa29b33 100644 --- a/include/configs/gw_ventana.h +++ b/include/configs/gw_ventana.h @@ -52,7 +52,6 @@ /* SPI */ #ifdef CONFIG_CMD_SF #define CONFIG_SPI_FLASH_MTD - #define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_BUS 0 #define CONFIG_SF_DEFAULT_CS 0 /* GPIO 3-19 (21248) */ diff --git a/include/configs/km/kmp204x-common.h b/include/configs/km/kmp204x-common.h index a8f7300c1eb..c762c93ac0a 100644 --- a/include/configs/km/kmp204x-common.h +++ b/include/configs/km/kmp204x-common.h @@ -253,7 +253,6 @@ int get_scl(void); /* * eSPI - Enhanced SPI */ -#define CONFIG_SPI_FLASH_BAR /* 4 byte-addressing */ #define CONFIG_SF_DEFAULT_SPEED 20000000 #define CONFIG_SF_DEFAULT_MODE 0 diff --git a/include/configs/ls1021aiot.h b/include/configs/ls1021aiot.h index 10dc0c68435..6be8df109bd 100644 --- a/include/configs/ls1021aiot.h +++ b/include/configs/ls1021aiot.h @@ -135,7 +135,6 @@ #define QSPI0_AMBA_BASE 0x40000000 #define FSL_QSPI_FLASH_SIZE (1 << 24) #define FSL_QSPI_FLASH_NUM 2 -#define CONFIG_SPI_FLASH_BAR #define CONFIG_SPI_FLASH_SPANSION #endif diff --git a/include/configs/ls2080aqds.h b/include/configs/ls2080aqds.h index 2822811da5d..a23a4edaee2 100644 --- a/include/configs/ls2080aqds.h +++ b/include/configs/ls2080aqds.h @@ -294,8 +294,6 @@ unsigned long get_board_ddr_clk(void); /* SPI */ #if defined(CONFIG_FSL_QSPI) || defined(CONFIG_FSL_DSPI) -#define CONFIG_SPI_FLASH - #ifdef CONFIG_FSL_DSPI #define CONFIG_SPI_FLASH_STMICRO #define CONFIG_SPI_FLASH_SST diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h index e307855d041..4fc9226712d 100644 --- a/include/configs/rk3036_common.h +++ b/include/configs/rk3036_common.h @@ -28,7 +28,6 @@ #define SDRAM_BANK_SIZE (512UL << 20UL) #define SDRAM_MAX_SIZE (CONFIG_NR_DRAM_BANKS * SDRAM_BANK_SIZE) -#define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_GIGADEVICE #define CONFIG_SF_DEFAULT_SPEED 20000000 diff --git a/include/configs/rk3128_common.h b/include/configs/rk3128_common.h index f4f64edc4a2..94517158055 100644 --- a/include/configs/rk3128_common.h +++ b/include/configs/rk3128_common.h @@ -30,7 +30,6 @@ #define CONFIG_SYS_SDRAM_BASE 0x60000000 #define SDRAM_MAX_SIZE 0x80000000 -#define CONFIG_SPI_FLASH #define CONFIG_SF_DEFAULT_SPEED 20000000 #define CONFIG_USB_OHCI_NEW #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h index 612d6439d13..36e494ee95a 100644 --- a/include/configs/rk3188_common.h +++ b/include/configs/rk3188_common.h @@ -37,7 +37,6 @@ #define SDRAM_BANK_SIZE (2UL << 30) #define SDRAM_MAX_SIZE 0x80000000 -#define CONFIG_SPI_FLASH #define CONFIG_SF_DEFAULT_SPEED 20000000 #ifndef CONFIG_SPL_BUILD diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h index 01f297b2c16..c59f5eff7a9 100644 --- a/include/configs/rk3288_common.h +++ b/include/configs/rk3288_common.h @@ -40,7 +40,6 @@ #define SDRAM_BANK_SIZE (2UL << 30) #define SDRAM_MAX_SIZE 0xfe000000 -#define CONFIG_SPI_FLASH #define CONFIG_SF_DEFAULT_SPEED 20000000 #ifndef CONFIG_SPL_BUILD diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h index 7913ef72140..02233d6a661 100644 --- a/include/configs/rk3328_common.h +++ b/include/configs/rk3328_common.h @@ -26,7 +26,6 @@ #define CONFIG_SYS_SDRAM_BASE 0 #define SDRAM_MAX_SIZE 0xff000000 -#define CONFIG_SPI_FLASH #define CONFIG_SF_DEFAULT_SPEED 20000000 #ifndef CONFIG_SPL_BUILD diff --git a/include/configs/socfpga_stratix10_socdk.h b/include/configs/socfpga_stratix10_socdk.h index f9319a2234f..0e73239f568 100644 --- a/include/configs/socfpga_stratix10_socdk.h +++ b/include/configs/socfpga_stratix10_socdk.h @@ -57,7 +57,6 @@ */ #ifdef CONFIG_CADENCE_QSPI /* Enable it if you want to use dual-stacked mode */ -#undef CONFIG_SF_DUAL_FLASH /*#define CONFIG_QSPI_RBF_ADDR 0x720000*/ /* Flash device info */ diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h index 710b8991a4c..b90be65a4fb 100644 --- a/include/configs/turris_omnia.h +++ b/include/configs/turris_omnia.h @@ -37,7 +37,6 @@ /* SPI NOR flash default params, used by sf commands */ #define CONFIG_SF_DEFAULT_SPEED 1000000 #define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 -#define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_SPANSION /* diff --git a/include/linux/bitops.h b/include/linux/bitops.h index a47f6d17bb5..259df43fb00 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -21,8 +21,13 @@ * position @h. For example * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. */ +#ifdef CONFIG_SANDBOX +#define GENMASK(h, l) \ + (((~0UL) << (l)) & (~0UL >> (CONFIG_SANDBOX_BITS_PER_LONG - 1 - (h)))) +#else #define GENMASK(h, l) \ (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) +#endif #define GENMASK_ULL(h, l) \ (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h new file mode 100644 index 00000000000..3555518bd3f --- /dev/null +++ b/include/linux/mtd/cfi.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al. + * + */ + +#ifndef __MTD_CFI_H__ +#define __MTD_CFI_H__ + +#define CFI_MFR_ANY 0xFFFF +#define CFI_ID_ANY 0xFFFF +#define CFI_MFR_CONTINUATION 0x007F + +#define CFI_MFR_AMD 0x0001 +#define CFI_MFR_AMIC 0x0037 +#define CFI_MFR_ATMEL 0x001F +#define CFI_MFR_EON 0x001C +#define CFI_MFR_FUJITSU 0x0004 +#define CFI_MFR_HYUNDAI 0x00AD +#define CFI_MFR_INTEL 0x0089 +#define CFI_MFR_MACRONIX 0x00C2 +#define CFI_MFR_NEC 0x0010 +#define CFI_MFR_PMC 0x009D +#define CFI_MFR_SAMSUNG 0x00EC +#define CFI_MFR_SHARP 0x00B0 +#define CFI_MFR_SST 0x00BF +#define CFI_MFR_ST 0x0020 /* STMicroelectronics */ +#define CFI_MFR_MICRON 0x002C /* Micron */ +#define CFI_MFR_TOSHIBA 0x0098 +#define CFI_MFR_WINBOND 0x00DA + +#endif /* __MTD_CFI_H__ */ diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h new file mode 100644 index 00000000000..88e80af5794 --- /dev/null +++ b/include/linux/mtd/spi-nor.h @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Synced from Linux v4.19 + */ + +#ifndef __LINUX_MTD_SPI_NOR_H +#define __LINUX_MTD_SPI_NOR_H + +#include <linux/bitops.h> +#include <linux/mtd/cfi.h> +#include <linux/mtd/mtd.h> + +/* + * Manufacturer IDs + * + * The first byte returned from the flash after sending opcode SPINOR_OP_RDID. + * Sometimes these are the same as CFI IDs, but sometimes they aren't. + */ +#define SNOR_MFR_ATMEL CFI_MFR_ATMEL +#define SNOR_MFR_GIGADEVICE 0xc8 +#define SNOR_MFR_INTEL CFI_MFR_INTEL +#define SNOR_MFR_ST CFI_MFR_ST /* ST Micro <--> Micron */ +#define SNOR_MFR_MICRON CFI_MFR_MICRON /* ST Micro <--> Micron */ +#define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX +#define SNOR_MFR_SPANSION CFI_MFR_AMD +#define SNOR_MFR_SST CFI_MFR_SST +#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */ + +/* + * Note on opcode nomenclature: some opcodes have a format like + * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number + * of I/O lines used for the opcode, address, and data (respectively). The + * FUNCTION has an optional suffix of '4', to represent an opcode which + * requires a 4-byte (32-bit) address. + */ + +/* Flash opcodes. */ +#define SPINOR_OP_WREN 0x06 /* Write enable */ +#define SPINOR_OP_RDSR 0x05 /* Read status register */ +#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */ +#define SPINOR_OP_RDSR2 0x3f /* Read status register 2 */ +#define SPINOR_OP_WRSR2 0x3e /* Write status register 2 */ +#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ +#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ +#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */ +#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */ +#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */ +#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */ +#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ +#define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */ +#define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */ +#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */ +#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ +#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */ +#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ +#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ +#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ +#define SPINOR_OP_RDSFDP 0x5a /* Read SFDP */ +#define SPINOR_OP_RDCR 0x35 /* Read configuration register */ +#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ +#define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */ +#define SPINOR_OP_RDEAR 0xc8 /* Read Extended Address Register */ +#define SPINOR_OP_WREAR 0xc5 /* Write Extended Address Register */ + +/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ +#define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ +#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */ +#define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */ +#define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */ +#define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */ +#define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */ +#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ +#define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */ +#define SPINOR_OP_PP_1_4_4_4B 0x3e /* Quad page program */ +#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */ +#define SPINOR_OP_BE_32K_4B 0x5c /* Erase 32KiB block */ +#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ + +/* Double Transfer Rate opcodes - defined in JEDEC JESD216B. */ +#define SPINOR_OP_READ_1_1_1_DTR 0x0d +#define SPINOR_OP_READ_1_2_2_DTR 0xbd +#define SPINOR_OP_READ_1_4_4_DTR 0xed + +#define SPINOR_OP_READ_1_1_1_DTR_4B 0x0e +#define SPINOR_OP_READ_1_2_2_DTR_4B 0xbe +#define SPINOR_OP_READ_1_4_4_DTR_4B 0xee + +/* Used for SST flashes only. */ +#define SPINOR_OP_BP 0x02 /* Byte program */ +#define SPINOR_OP_WRDI 0x04 /* Write disable */ +#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */ + +/* Used for S3AN flashes only */ +#define SPINOR_OP_XSE 0x50 /* Sector erase */ +#define SPINOR_OP_XPP 0x82 /* Page program */ +#define SPINOR_OP_XRDSR 0xd7 /* Read status register */ + +#define XSR_PAGESIZE BIT(0) /* Page size in Po2 or Linear */ +#define XSR_RDY BIT(7) /* Ready */ + +/* Used for Macronix and Winbond flashes. */ +#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ +#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ + +/* Used for Spansion flashes only. */ +#define SPINOR_OP_BRWR 0x17 /* Bank register write */ +#define SPINOR_OP_BRRD 0x16 /* Bank register read */ +#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ + +/* Used for Micron flashes only. */ +#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ +#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ + +/* Status Register bits. */ +#define SR_WIP BIT(0) /* Write in progress */ +#define SR_WEL BIT(1) /* Write enable latch */ +/* meaning of other SR_* bits may differ between vendors */ +#define SR_BP0 BIT(2) /* Block protect 0 */ +#define SR_BP1 BIT(3) /* Block protect 1 */ +#define SR_BP2 BIT(4) /* Block protect 2 */ +#define SR_TB BIT(5) /* Top/Bottom protect */ +#define SR_SRWD BIT(7) /* SR write protect */ +/* Spansion/Cypress specific status bits */ +#define SR_E_ERR BIT(5) +#define SR_P_ERR BIT(6) + +#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ + +/* Enhanced Volatile Configuration Register bits */ +#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ + +/* Flag Status Register bits */ +#define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */ +#define FSR_E_ERR BIT(5) /* Erase operation status */ +#define FSR_P_ERR BIT(4) /* Program operation status */ +#define FSR_PT_ERR BIT(1) /* Protection error bit */ + +/* Configuration Register bits. */ +#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ + +/* Status Register 2 bits. */ +#define SR2_QUAD_EN_BIT7 BIT(7) + +/* Supported SPI protocols */ +#define SNOR_PROTO_INST_MASK GENMASK(23, 16) +#define SNOR_PROTO_INST_SHIFT 16 +#define SNOR_PROTO_INST(_nbits) \ + ((((unsigned long)(_nbits)) << SNOR_PROTO_INST_SHIFT) & \ + SNOR_PROTO_INST_MASK) + +#define SNOR_PROTO_ADDR_MASK GENMASK(15, 8) +#define SNOR_PROTO_ADDR_SHIFT 8 +#define SNOR_PROTO_ADDR(_nbits) \ + ((((unsigned long)(_nbits)) << SNOR_PROTO_ADDR_SHIFT) & \ + SNOR_PROTO_ADDR_MASK) + +#define SNOR_PROTO_DATA_MASK GENMASK(7, 0) +#define SNOR_PROTO_DATA_SHIFT 0 +#define SNOR_PROTO_DATA(_nbits) \ + ((((unsigned long)(_nbits)) << SNOR_PROTO_DATA_SHIFT) & \ + SNOR_PROTO_DATA_MASK) + +#define SNOR_PROTO_IS_DTR BIT(24) /* Double Transfer Rate */ + +#define SNOR_PROTO_STR(_inst_nbits, _addr_nbits, _data_nbits) \ + (SNOR_PROTO_INST(_inst_nbits) | \ + SNOR_PROTO_ADDR(_addr_nbits) | \ + SNOR_PROTO_DATA(_data_nbits)) +#define SNOR_PROTO_DTR(_inst_nbits, _addr_nbits, _data_nbits) \ + (SNOR_PROTO_IS_DTR | \ + SNOR_PROTO_STR(_inst_nbits, _addr_nbits, _data_nbits)) + +enum spi_nor_protocol { + SNOR_PROTO_1_1_1 = SNOR_PROTO_STR(1, 1, 1), + SNOR_PROTO_1_1_2 = SNOR_PROTO_STR(1, 1, 2), + SNOR_PROTO_1_1_4 = SNOR_PROTO_STR(1, 1, 4), + SNOR_PROTO_1_1_8 = SNOR_PROTO_STR(1, 1, 8), + SNOR_PROTO_1_2_2 = SNOR_PROTO_STR(1, 2, 2), + SNOR_PROTO_1_4_4 = SNOR_PROTO_STR(1, 4, 4), + SNOR_PROTO_1_8_8 = SNOR_PROTO_STR(1, 8, 8), + SNOR_PROTO_2_2_2 = SNOR_PROTO_STR(2, 2, 2), + SNOR_PROTO_4_4_4 = SNOR_PROTO_STR(4, 4, 4), + SNOR_PROTO_8_8_8 = SNOR_PROTO_STR(8, 8, 8), + + SNOR_PROTO_1_1_1_DTR = SNOR_PROTO_DTR(1, 1, 1), + SNOR_PROTO_1_2_2_DTR = SNOR_PROTO_DTR(1, 2, 2), + SNOR_PROTO_1_4_4_DTR = SNOR_PROTO_DTR(1, 4, 4), + SNOR_PROTO_1_8_8_DTR = SNOR_PROTO_DTR(1, 8, 8), +}; + +static inline bool spi_nor_protocol_is_dtr(enum spi_nor_protocol proto) +{ + return !!(proto & SNOR_PROTO_IS_DTR); +} + +static inline u8 spi_nor_get_protocol_inst_nbits(enum spi_nor_protocol proto) +{ + return ((unsigned long)(proto & SNOR_PROTO_INST_MASK)) >> + SNOR_PROTO_INST_SHIFT; +} + +static inline u8 spi_nor_get_protocol_addr_nbits(enum spi_nor_protocol proto) +{ + return ((unsigned long)(proto & SNOR_PROTO_ADDR_MASK)) >> + SNOR_PROTO_ADDR_SHIFT; +} + +static inline u8 spi_nor_get_protocol_data_nbits(enum spi_nor_protocol proto) +{ + return ((unsigned long)(proto & SNOR_PROTO_DATA_MASK)) >> + SNOR_PROTO_DATA_SHIFT; +} + +static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto) +{ + return spi_nor_get_protocol_data_nbits(proto); +} + +#define SPI_NOR_MAX_CMD_SIZE 8 +enum spi_nor_ops { + SPI_NOR_OPS_READ = 0, + SPI_NOR_OPS_WRITE, + SPI_NOR_OPS_ERASE, + SPI_NOR_OPS_LOCK, + SPI_NOR_OPS_UNLOCK, +}; + +enum spi_nor_option_flags { + SNOR_F_USE_FSR = BIT(0), + SNOR_F_HAS_SR_TB = BIT(1), + SNOR_F_NO_OP_CHIP_ERASE = BIT(2), + SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), + SNOR_F_READY_XSR_RDY = BIT(4), + SNOR_F_USE_CLSR = BIT(5), + SNOR_F_BROKEN_RESET = BIT(6), +}; + +/** + * struct flash_info - Forward declaration of a structure used internally by + * spi_nor_scan() + */ +struct flash_info; + +/* TODO: Remove, once all users of spi_flash interface are moved to MTD */ +#define spi_flash spi_nor + +/** + * struct spi_nor - Structure for defining a the SPI NOR layer + * @mtd: point to a mtd_info structure + * @lock: the lock for the read/write/erase/lock/unlock operations + * @dev: point to a spi device, or a spi nor controller device. + * @info: spi-nor part JDEC MFR id and other info + * @page_size: the page size of the SPI NOR + * @addr_width: number of address bytes + * @erase_opcode: the opcode for erasing a sector + * @read_opcode: the read opcode + * @read_dummy: the dummy needed by the read operation + * @program_opcode: the program opcode + * @bank_read_cmd: Bank read cmd + * @bank_write_cmd: Bank write cmd + * @bank_curr: Current flash bank + * @sst_write_second: used by the SST write operation + * @flags: flag options for the current SPI-NOR (SNOR_F_*) + * @read_proto: the SPI protocol for read operations + * @write_proto: the SPI protocol for write operations + * @reg_proto the SPI protocol for read_reg/write_reg/erase operations + * @cmd_buf: used by the write_reg + * @prepare: [OPTIONAL] do some preparations for the + * read/write/erase/lock/unlock operations + * @unprepare: [OPTIONAL] do some post work after the + * read/write/erase/lock/unlock operations + * @read_reg: [DRIVER-SPECIFIC] read out the register + * @write_reg: [DRIVER-SPECIFIC] write data to the register + * @read: [DRIVER-SPECIFIC] read data from the SPI NOR + * @write: [DRIVER-SPECIFIC] write data to the SPI NOR + * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR + * at the offset @offs; if not provided by the driver, + * spi-nor will send the erase opcode via write_reg() + * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR + * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR + * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is + * @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode + * completely locked + * @priv: the private data + */ +struct spi_nor { + struct mtd_info mtd; + struct udevice *dev; + struct spi_slave *spi; + const struct flash_info *info; + u32 page_size; + u8 addr_width; + u8 erase_opcode; + u8 read_opcode; + u8 read_dummy; + u8 program_opcode; +#ifdef CONFIG_SPI_FLASH_BAR + u8 bank_read_cmd; + u8 bank_write_cmd; + u8 bank_curr; +#endif + enum spi_nor_protocol read_proto; + enum spi_nor_protocol write_proto; + enum spi_nor_protocol reg_proto; + bool sst_write_second; + u32 flags; + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; + + int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); + void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); + int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); + int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); + + ssize_t (*read)(struct spi_nor *nor, loff_t from, + size_t len, u_char *read_buf); + ssize_t (*write)(struct spi_nor *nor, loff_t to, + size_t len, const u_char *write_buf); + int (*erase)(struct spi_nor *nor, loff_t offs); + + int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*quad_enable)(struct spi_nor *nor); + + void *priv; +/* Compatibility for spi_flash, remove once sf layer is merged with mtd */ + const char *name; + u32 size; + u32 sector_size; + u32 erase_size; +}; + +static inline void spi_nor_set_flash_node(struct spi_nor *nor, + const struct device_node *np) +{ + mtd_set_of_node(&nor->mtd, np); +} + +static inline const struct +device_node *spi_nor_get_flash_node(struct spi_nor *nor) +{ + return mtd_get_of_node(&nor->mtd); +} + +/** + * struct spi_nor_hwcaps - Structure for describing the hardware capabilies + * supported by the SPI controller (bus master). + * @mask: the bitmask listing all the supported hw capabilies + */ +struct spi_nor_hwcaps { + u32 mask; +}; + +/* + *(Fast) Read capabilities. + * MUST be ordered by priority: the higher bit position, the higher priority. + * As a matter of performances, it is relevant to use Octo SPI protocols first, + * then Quad SPI protocols before Dual SPI protocols, Fast Read and lastly + * (Slow) Read. + */ +#define SNOR_HWCAPS_READ_MASK GENMASK(14, 0) +#define SNOR_HWCAPS_READ BIT(0) +#define SNOR_HWCAPS_READ_FAST BIT(1) +#define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2) + +#define SNOR_HWCAPS_READ_DUAL GENMASK(6, 3) +#define SNOR_HWCAPS_READ_1_1_2 BIT(3) +#define SNOR_HWCAPS_READ_1_2_2 BIT(4) +#define SNOR_HWCAPS_READ_2_2_2 BIT(5) +#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(6) + +#define SNOR_HWCAPS_READ_QUAD GENMASK(10, 7) +#define SNOR_HWCAPS_READ_1_1_4 BIT(7) +#define SNOR_HWCAPS_READ_1_4_4 BIT(8) +#define SNOR_HWCAPS_READ_4_4_4 BIT(9) +#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10) + +#define SNOR_HWCPAS_READ_OCTO GENMASK(14, 11) +#define SNOR_HWCAPS_READ_1_1_8 BIT(11) +#define SNOR_HWCAPS_READ_1_8_8 BIT(12) +#define SNOR_HWCAPS_READ_8_8_8 BIT(13) +#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(14) + +/* + * Page Program capabilities. + * MUST be ordered by priority: the higher bit position, the higher priority. + * Like (Fast) Read capabilities, Octo/Quad SPI protocols are preferred to the + * legacy SPI 1-1-1 protocol. + * Note that Dual Page Programs are not supported because there is no existing + * JEDEC/SFDP standard to define them. Also at this moment no SPI flash memory + * implements such commands. + */ +#define SNOR_HWCAPS_PP_MASK GENMASK(22, 16) +#define SNOR_HWCAPS_PP BIT(16) + +#define SNOR_HWCAPS_PP_QUAD GENMASK(19, 17) +#define SNOR_HWCAPS_PP_1_1_4 BIT(17) +#define SNOR_HWCAPS_PP_1_4_4 BIT(18) +#define SNOR_HWCAPS_PP_4_4_4 BIT(19) + +#define SNOR_HWCAPS_PP_OCTO GENMASK(22, 20) +#define SNOR_HWCAPS_PP_1_1_8 BIT(20) +#define SNOR_HWCAPS_PP_1_8_8 BIT(21) +#define SNOR_HWCAPS_PP_8_8_8 BIT(22) + +/** + * spi_nor_scan() - scan the SPI NOR + * @nor: the spi_nor structure + * + * The drivers can use this function to scan the SPI NOR. + * In the scanning, it will try to get all the necessary information to + * fill the mtd_info{} and the spi_nor{}. + * + * Return: 0 for success, others for failure. + */ +int spi_nor_scan(struct spi_nor *nor); + +#endif diff --git a/include/spi_flash.h b/include/spi_flash.h index e427e960d54..7f691e8559c 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -11,6 +11,7 @@ #include <dm.h> /* Because we dereference struct udevice here */ #include <linux/types.h> +#include <linux/mtd/spi-nor.h> #ifndef CONFIG_SF_DEFAULT_SPEED # define CONFIG_SF_DEFAULT_SPEED 1000000 @@ -27,86 +28,6 @@ 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 - * @erase_size: 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; - - u32 size; - u32 page_size; - u32 sector_size; - u32 erase_size; -#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 -}; - 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, @@ -225,19 +146,37 @@ 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); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; + + return mtd->_read(mtd, offset, len, &retlen, 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); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; + + return mtd->_write(mtd, offset, len, &retlen, buf); } static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, size_t len) { - return flash->erase(flash, offset, len); + struct mtd_info *mtd = &flash->mtd; + struct erase_info instr; + + if (offset % mtd->erasesize || len % mtd->erasesize) { + printf("SF: Erase offset/length not multiple of erase size\n"); + return -EINVAL; + } + + memset(&instr, 0, sizeof(instr)); + instr.addr = offset; + instr.len = len; + + return mtd->_erase(mtd, &instr); } #endif |