diff --git a/MAINTAINERS b/MAINTAINERS index 23de529298f9b20d3cb7dda9500adbf4f14384fc..69131e4ffae4a03fcb013a0d9109626f194a54e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -687,10 +687,18 @@ SPI M: Jagan Teki S: Maintained T: git git://git.denx.de/u-boot-spi.git -F: drivers/mtd/spi/ F: drivers/spi/ F: include/spi* +SPI-NOR +M: Jagan Teki +M: Vignesh R +S: Maintained +F: drivers/mtd/spi/ +F: include/spi_flash.h +F: include/linux/mtd/cfi.h +F: include/linux/mtd/spi-nor.h + SPMI M: Mateusz Kulikowski S: Maintained diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig index 4d47d09637ad0189f71e851ff4288d84637d1759..85ea8946b0fd1a2f1808222d8c44a285c9f8f02e 100644 --- a/arch/arm/mach-omap2/am33xx/Kconfig +++ b/arch/arm/mach-omap2/am33xx/Kconfig @@ -230,7 +230,6 @@ config TARGET_AM43XX_EVM imply DM_I2C imply DM_SPI imply DM_SPI_FLASH - imply SPI_FLASH_BAR imply SPL_ENV_SUPPORT imply SPL_FS_EXT4 imply SPL_FS_FAT diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h index 8cb8385d76db5e7514f19c75f0d9bbfe6d479016..765f28f116bcdb1363ff9d00688219e8d35d6f52 100644 --- a/arch/sh/include/asm/bitops.h +++ b/arch/sh/include/asm/bitops.h @@ -153,6 +153,10 @@ static inline int ffs (int x) } #define PLATFORM_FFS +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + #endif /* __KERNEL__ */ #endif /* __ASM_SH_BITOPS_H */ diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 59028529c92ee6144459821418ca003526266484..935066d66487f820b9b2f1ef54bda4f10d576d3f 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -737,13 +737,34 @@ config SPL_SPI_FLASH_SUPPORT lines). This enables the drivers in drivers/mtd/spi as part of an SPL build. This normally requires SPL_SPI_SUPPORT. +if SPL_SPI_FLASH_SUPPORT + +config SPL_SPI_FLASH_TINY + bool "Enable low footprint SPL SPI Flash support" + depends on !SPI_FLASH_BAR + default y if SPI_FLASH + help + Enable lightweight SPL SPI Flash support that supports just reading + data/images from flash. No support to write/erase flash. Enable + this if you have SPL size limitations and don't need full + fledged SPI flash support. + +config SPL_SPI_FLASH_SFDP_SUPPORT + bool "SFDP table parsing support for SPI NOR flashes" + depends on !SPI_FLASH_BAR && !SPL_SPI_FLASH_TINY + help + Enable support for parsing and auto discovery of parameters for + SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) + tables as per JESD216 standard in SPL. + config SPL_SPI_LOAD bool "Support loading from SPI flash" - depends on SPL_SPI_FLASH_SUPPORT help Enable support for loading next stage, U-Boot or otherwise, from SPI NOR in U-Boot SPL. +endif # SPL_SPI_FLASH_SUPPORT + config SPL_SPI_SUPPORT bool "Support SPI drivers" help diff --git a/configs/alt_defconfig b/configs/alt_defconfig index 396ed5eaf2871d18673aafef191a5c09f8aa5ebb..44f1e1c51a4ca6da4a0c853a634e20ab5e6921b4 100644 --- a/configs/alt_defconfig +++ b/configs/alt_defconfig @@ -65,7 +65,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 51dedc6111ce4dd34430305648600528acdf54ea..8404d71d86e942fc54ed86128e273fa2096fdd03 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -57,7 +57,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig index 6924b0bd06ed010700f91b9826654172a4a26dc8..f9805d24f370b486d67b8ce97558bac0cd34397e 100644 --- a/configs/am57xx_hs_evm_defconfig +++ b/configs/am57xx_hs_evm_defconfig @@ -59,7 +59,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/ap121_defconfig b/configs/ap121_defconfig index 5d54267cd34570a47297e7b9d68089e94048383d..c9dbe4d72174f31873710aa99ca21a917bc595c2 100644 --- a/configs/ap121_defconfig +++ b/configs/ap121_defconfig @@ -35,7 +35,6 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ATMEL=y CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_GIGADEVICE=y diff --git a/configs/ap143_defconfig b/configs/ap143_defconfig index 83eb583b563e8bd2120023aa022eacddf3d272b3..7c1a296e2775e652ec682567610618287e5254cc 100644 --- a/configs/ap143_defconfig +++ b/configs/ap143_defconfig @@ -34,7 +34,6 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y # CONFIG_NET is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ATMEL=y CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_GIGADEVICE=y diff --git a/configs/avnet_ultra96_rev1_defconfig b/configs/avnet_ultra96_rev1_defconfig index 896de78b34e44ab0942a3df67521f7e0af939ca5..3c0f2a54afe8baa9d56ded1ad6763785e40a9847 100644 --- a/configs/avnet_ultra96_rev1_defconfig +++ b/configs/avnet_ultra96_rev1_defconfig @@ -57,7 +57,6 @@ CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig index b4621c359fc635962270f0f38f0985fd67393615..b77ecc178151a4b1e9ac39f8c9ef2d5e2e32454f 100644 --- a/configs/axs101_defconfig +++ b/configs/axs101_defconfig @@ -38,7 +38,6 @@ CONFIG_MMC=y CONFIG_MMC_DW=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig index e7894d297cda246e193269bba00025a41fdc55be..f42b694ca78b203af9896b4af5c4cfdeab7b62cd 100644 --- a/configs/axs103_defconfig +++ b/configs/axs103_defconfig @@ -38,7 +38,6 @@ CONFIG_MMC=y CONFIG_MMC_DW=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y diff --git a/configs/bg0900_defconfig b/configs/bg0900_defconfig index 6de81621cd454a8ed902be2c832a68a20a44aebc..2bafc793bc809960a929f01386cb8db0e37a1efb 100644 --- a/configs/bg0900_defconfig +++ b/configs/bg0900_defconfig @@ -32,7 +32,6 @@ CONFIG_DOS_PARTITION=y CONFIG_NAND=y CONFIG_NAND_MXS=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_MII=y CONFIG_CONS_INDEX=0 diff --git a/configs/blanche_defconfig b/configs/blanche_defconfig index 244ab22f6fc16b10914dc53f9e9bae4d63cb8d86..c5042d885f4ef5ac732c0f28cc8f0fa6110e5f60 100644 --- a/configs/blanche_defconfig +++ b/configs/blanche_defconfig @@ -49,7 +49,6 @@ CONFIG_MTD_NOR_FLASH=y CONFIG_FLASH_CFI_DRIVER=y CONFIG_SYS_FLASH_CFI=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SMC911X=y CONFIG_SMC911X_BASE=0x18000000 diff --git a/configs/cgtqmx6eval_defconfig b/configs/cgtqmx6eval_defconfig index 80bff7dc2092fbb2282cbe0a398cf92f15b111bf..99c581b2de95a2dcca739342b5d01466ed2b76e9 100644 --- a/configs/cgtqmx6eval_defconfig +++ b/configs/cgtqmx6eval_defconfig @@ -55,6 +55,7 @@ CONFIG_DFU_SF=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0x12000000 CONFIG_FSL_ESDHC=y +CONFIG_SPI_FLASH=y CONFIG_PHYLIB=y CONFIG_MII=y CONFIG_SPI=y diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig index fd4cd806e6bd3935b387e22ed0d672f3f1405df5..3ad4d7da0749acde363f342f87cbed98afa64c2e 100644 --- a/configs/chromebit_mickey_defconfig +++ b/configs/chromebit_mickey_defconfig @@ -59,6 +59,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_PWRSEQ=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_DM_PMIC=y diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig index 88a37c5d82c0aa66af7b8be311161cd1a25b4d2d..0ce5ac54dc2f1973ac6478c38d18e09091b36286 100644 --- a/configs/chromebook_jerry_defconfig +++ b/configs/chromebook_jerry_defconfig @@ -64,6 +64,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_PWRSEQ=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_DM_PMIC=y diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig index 2e17e73ded6d0ef8838775dbac718396457065b7..4e7feffefd3436074766ea608f0fd6b7301a3cf2 100644 --- a/configs/chromebook_minnie_defconfig +++ b/configs/chromebook_minnie_defconfig @@ -60,6 +60,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_PWRSEQ=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_DM_PMIC=y diff --git a/configs/cl-som-am57x_defconfig b/configs/cl-som-am57x_defconfig index c409d34d0882b05915f668f672b9b98bb060e777..cd780cdb98cfb419b005f6a89ac4ef57588a0a3d 100644 --- a/configs/cl-som-am57x_defconfig +++ b/configs/cl-som-am57x_defconfig @@ -37,7 +37,6 @@ CONFIG_LED_STATUS_BIT=37 CONFIG_LED_STATUS_STATE=2 CONFIG_MMC_OMAP_HS=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ATMEL=y CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_GIGADEVICE=y diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig index 0f69ff606dba4aa6865491e98f3b7cb060362a24..c90600eaf9d6a08a6e08d9f62b6439c12c750e2c 100644 --- a/configs/clearfog_defconfig +++ b/configs/clearfog_defconfig @@ -48,7 +48,6 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_MV=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MARVELL=y diff --git a/configs/cm_t43_defconfig b/configs/cm_t43_defconfig index fe548f2abaecbcfac21feb10cb555781f6b973cc..ea0cafa6f0ebadf7bb472c023b42cb74257f87e8 100644 --- a/configs/cm_t43_defconfig +++ b/configs/cm_t43_defconfig @@ -49,7 +49,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_OMAP_HS=y CONFIG_NAND=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ATMEL=y CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_GIGADEVICE=y diff --git a/configs/db-88f6820-amc_defconfig b/configs/db-88f6820-amc_defconfig index 03bf2bcafcb80aab47395b3f0549ce4faf2148eb..3e1b404408a2406058dc3022ada372359b7c6799 100644 --- a/configs/db-88f6820-amc_defconfig +++ b/configs/db-88f6820-amc_defconfig @@ -52,7 +52,6 @@ CONFIG_SYS_I2C_MVTWSI=y CONFIG_NAND=y CONFIG_NAND_PXA3XX=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHY_MARVELL=y diff --git a/configs/display5_defconfig b/configs/display5_defconfig index 86ddc26a159bda3937f192647971e7718e72fb07..cdf3642dd210ef336c90286729f42fca8cf92381 100644 --- a/configs/display5_defconfig +++ b/configs/display5_defconfig @@ -65,7 +65,6 @@ CONFIG_SYS_BOOTCOUNT_ADDR=0x020CC068 CONFIG_FSL_ESDHC=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y diff --git a/configs/display5_factory_defconfig b/configs/display5_factory_defconfig index 2d25bd83ba54208c071206b3f7b12e33e0e698be..6b9febf62fb61a43819517234b8459f43f138154 100644 --- a/configs/display5_factory_defconfig +++ b/configs/display5_factory_defconfig @@ -66,7 +66,6 @@ CONFIG_DFU_SF=y CONFIG_FSL_ESDHC=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index fe253a6552e71ef32be948084df9661b42d3839f..ef061501ef35ec34449d05e8ad9612a2380b5bb5 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -67,7 +67,6 @@ CONFIG_SPL_MMC_HS200_SUPPORT=y CONFIG_MMC_OMAP_HS=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index 735be5506a1857594f154a7e6b9cf34aa81b54a3..f98ee470a90965377c11c8e4b0307b81df5bcdd3 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -65,7 +65,6 @@ CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_OMAP_HS=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y diff --git a/configs/ds109_defconfig b/configs/ds109_defconfig index 352403e57385812b20491e5cc2a2458da6a14f64..3e4e71bcbf4e3e2c174ea4b1ec0fab2e3feebf0d 100644 --- a/configs/ds109_defconfig +++ b/configs/ds109_defconfig @@ -25,7 +25,6 @@ CONFIG_SYS_I2C_MVTWSI=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_MVGBE=y CONFIG_MII=y diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 32f37440c31d3eb66581ea7ced220c093e935d9d..ce42f23867c374a663faf748a6a22b9008f9a014 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -44,7 +44,6 @@ CONFIG_SPL_OF_TRANSLATE=y # CONFIG_MMC is not set CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHY_ADDR_ENABLE=y CONFIG_PHY_MARVELL=y diff --git a/configs/evb-rk3036_defconfig b/configs/evb-rk3036_defconfig index 439e69138636013f7ff025aed1d7b45aa34de073..33eaa062f5b8eabd8e8fb20c0c4ae00a72c98f75 100644 --- a/configs/evb-rk3036_defconfig +++ b/configs/evb-rk3036_defconfig @@ -42,6 +42,7 @@ CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_LED=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PINCTRL=y CONFIG_PINCTRL_ROCKCHIP_RK3036=y # CONFIG_SPL_DM_SERIAL is not set diff --git a/configs/evb-rk3128_defconfig b/configs/evb-rk3128_defconfig index 78c5ac6f530b3f53559a08d64bf1ab07da9e20e2..d2c0fb0aae37d181b34800d3eb3bf4b3002b8944 100644 --- a/configs/evb-rk3128_defconfig +++ b/configs/evb-rk3128_defconfig @@ -29,6 +29,7 @@ CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PHY=y CONFIG_PINCTRL=y CONFIG_REGULATOR_PWM=y diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig index 671bb8ca3c30c9c8d8c0226ea198574eee773648..d0eba8a1a077bba1f4ebc432974885d9f34cc079 100644 --- a/configs/evb-rk3288_defconfig +++ b/configs/evb-rk3288_defconfig @@ -52,6 +52,7 @@ CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 10a5f09b313a2c8d0fcde7371fbd4385a7a46830..ad675173b61ab491ab7e320727932071234fa24b 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -32,6 +32,7 @@ CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/evb-rv1108_defconfig b/configs/evb-rv1108_defconfig index 3db453f5f662ea74075ce708d84221f6760058e9..0b586cc10af77c77254ac424af61df9b55c53b37 100644 --- a/configs/evb-rv1108_defconfig +++ b/configs/evb-rv1108_defconfig @@ -29,7 +29,6 @@ CONFIG_FASTBOOT_FLASH_MMC_DEV=1 CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_SPI_FLASH_MTD=y diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig index 25baf4cbbd1a1a7a381a8d875dc7001fddd677c1..4e0898d818647742afa25c95244d9f6671becaad 100644 --- a/configs/fennec-rk3288_defconfig +++ b/configs/fennec-rk3288_defconfig @@ -51,6 +51,7 @@ CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig index 8c1f7639fd7b8c697abf8b0a0c5b40a9c80dfa54..b8eae0f2adb77f5cd1e534b5cb416ff999814d60 100644 --- a/configs/firefly-rk3288_defconfig +++ b/configs/firefly-rk3288_defconfig @@ -54,6 +54,7 @@ CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/gose_defconfig b/configs/gose_defconfig index 0368c659633e65e70fe5fc2196fc3d157d30de56..a5afb3c5699b23519e322f2aa39e649a673fd7df 100644 --- a/configs/gose_defconfig +++ b/configs/gose_defconfig @@ -64,7 +64,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/helios4_defconfig b/configs/helios4_defconfig index 514b40c356f166005f576661914fd75a0f44855f..6ef40b036625a8adeb577b47fa85f97a658fb8be 100644 --- a/configs/helios4_defconfig +++ b/configs/helios4_defconfig @@ -47,7 +47,6 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_MV=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_GIGE=y CONFIG_MVNETA=y diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index ab9e695b0295a11c9fa75e32850ed524a4ef6ef0..c518b707a512c00564bb879544db0e6334559b1b 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -44,7 +44,6 @@ CONFIG_NAND=y CONFIG_NAND_DAVINCI=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y diff --git a/configs/k2g_hs_evm_defconfig b/configs/k2g_hs_evm_defconfig index a6757cc0b4632a4943d049c7a879f1d3b1e283ef..93fa2360ad114af9e01cf2b138abd85c2253ed1f 100644 --- a/configs/k2g_hs_evm_defconfig +++ b/configs/k2g_hs_evm_defconfig @@ -37,7 +37,6 @@ CONFIG_NAND=y CONFIG_NAND_DAVINCI=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y diff --git a/configs/koelsch_defconfig b/configs/koelsch_defconfig index dbacfd87ba5d46118d9819c63f465e4105bbcfd6..1ff14ac4abd02d764308ec0586802c0caa32b4f6 100644 --- a/configs/koelsch_defconfig +++ b/configs/koelsch_defconfig @@ -64,7 +64,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/kylin-rk3036_defconfig b/configs/kylin-rk3036_defconfig index 57558c6323c430924ca253090f134fcd4a785495..d6d5abb2b62577ba9b6986f7ecae9fb2d7cb39d9 100644 --- a/configs/kylin-rk3036_defconfig +++ b/configs/kylin-rk3036_defconfig @@ -40,6 +40,7 @@ CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_LED=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PINCTRL=y CONFIG_DM_REGULATOR_FIXED=y # CONFIG_SPL_DM_SERIAL is not set diff --git a/configs/lager_defconfig b/configs/lager_defconfig index 242e104b6bd31bc2c6de7df07380e2869bb29b68..d924d76911dedaca186fed873ed2fb4cf5c15131 100644 --- a/configs/lager_defconfig +++ b/configs/lager_defconfig @@ -66,7 +66,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/ls2080aqds_SECURE_BOOT_defconfig b/configs/ls2080aqds_SECURE_BOOT_defconfig index d7c0db6343a9616333a83fa95a2dac78f4651575..446c2e776eb87d41d939577189ace31f7f694cbc 100644 --- a/configs/ls2080aqds_SECURE_BOOT_defconfig +++ b/configs/ls2080aqds_SECURE_BOOT_defconfig @@ -38,6 +38,7 @@ CONFIG_FLASH_CFI_DRIVER=y CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y CONFIG_SYS_FLASH_CFI=y CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y CONFIG_E1000=y diff --git a/configs/ls2080aqds_defconfig b/configs/ls2080aqds_defconfig index 51cf327da3e8dc3f96ca0aeda5541d4dc9f3c79c..9e0e66c1240a22e1c062f11355b96331a3c86312 100644 --- a/configs/ls2080aqds_defconfig +++ b/configs/ls2080aqds_defconfig @@ -41,6 +41,7 @@ CONFIG_FLASH_CFI_DRIVER=y CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y CONFIG_SYS_FLASH_CFI=y CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y CONFIG_E1000=y diff --git a/configs/ls2080aqds_nand_defconfig b/configs/ls2080aqds_nand_defconfig index 30b506fafc2a474c2f5d16ebede3dda5f2271c55..9ab38055d050f6918f441fc08e39fbc3c84a930e 100644 --- a/configs/ls2080aqds_nand_defconfig +++ b/configs/ls2080aqds_nand_defconfig @@ -45,6 +45,7 @@ CONFIG_FSL_CAAM=y CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y CONFIG_E1000=y diff --git a/configs/ls2080aqds_qspi_defconfig b/configs/ls2080aqds_qspi_defconfig index 44a718e855b6aff37cdccce568508d51fc264a78..edbf2e91f0896ec852d5ff122bf8a965e558ea9c 100644 --- a/configs/ls2080aqds_qspi_defconfig +++ b/configs/ls2080aqds_qspi_defconfig @@ -36,6 +36,7 @@ CONFIG_FSL_CAAM=y CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y CONFIG_E1000=y diff --git a/configs/ls2080aqds_sdcard_defconfig b/configs/ls2080aqds_sdcard_defconfig index d6ca28979fc92342376c7b210d558a5ea08b830b..fff54b1e790480d31a4a1d2f1d806403ab682b86 100644 --- a/configs/ls2080aqds_sdcard_defconfig +++ b/configs/ls2080aqds_sdcard_defconfig @@ -43,6 +43,7 @@ CONFIG_DM=y CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y CONFIG_PHYLIB=y CONFIG_PHY_GIGE=y CONFIG_E1000=y diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig index a4d2fcd2596aa8c09922ace756f6639cee1af13f..5c716cdec8b8fdb81a905afb98ca0505b9d28ce8 100644 --- a/configs/maxbcm_defconfig +++ b/configs/maxbcm_defconfig @@ -33,7 +33,6 @@ CONFIG_DEFAULT_DEVICE_TREE="armada-xp-maxbcm" CONFIG_SPL_OF_TRANSLATE=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig index 0d9f6c36b66ebb5eb6005c3cd4ec5f452718435c..b26bd1e7c115b490e733a81135a8858581b4e38c 100644 --- a/configs/miqi-rk3288_defconfig +++ b/configs/miqi-rk3288_defconfig @@ -51,6 +51,7 @@ CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig index cfb44ad176d820f9fc34c789766516aabab8c5cf..459c67827dbd50682f216fcf5e14ae42458b4303 100644 --- a/configs/mt7629_rfb_defconfig +++ b/configs/mt7629_rfb_defconfig @@ -42,7 +42,6 @@ CONFIG_SPL_CLK=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_SPI_FLASH_ISSI=y diff --git a/configs/mx6sxsabreauto_defconfig b/configs/mx6sxsabreauto_defconfig index f0954e721301dcbb06ba40349eac21590c656aa4..b60e9b672277e6d103e63c2fc83ff34b05c97551 100644 --- a/configs/mx6sxsabreauto_defconfig +++ b/configs/mx6sxsabreauto_defconfig @@ -39,7 +39,6 @@ CONFIG_NAND=y CONFIG_NAND_MXS=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y CONFIG_MII=y diff --git a/configs/mx6sxsabresd_defconfig b/configs/mx6sxsabresd_defconfig index 8ee2a006d2417f33d8044532d0c1823c848e42c1..5c0aa635c86116816a11b0b3fb58b245632871a5 100644 --- a/configs/mx6sxsabresd_defconfig +++ b/configs/mx6sxsabresd_defconfig @@ -41,7 +41,6 @@ CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y diff --git a/configs/mx6ul_14x14_evk_defconfig b/configs/mx6ul_14x14_evk_defconfig index 2134f6ed6bcc158b41659eb9875b5fb1ebce743c..4a3c56faa619b009b0c21caff3074b1e9a2b2de2 100644 --- a/configs/mx6ul_14x14_evk_defconfig +++ b/configs/mx6ul_14x14_evk_defconfig @@ -46,7 +46,6 @@ CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y CONFIG_PHY_MICREL=y diff --git a/configs/mx6ul_9x9_evk_defconfig b/configs/mx6ul_9x9_evk_defconfig index c941dd2dfd6dc0166d19637bce0a4c39913f34b4..185f543df6e1f2ec9ca11710d726de3606eb7e84 100644 --- a/configs/mx6ul_9x9_evk_defconfig +++ b/configs/mx6ul_9x9_evk_defconfig @@ -46,7 +46,6 @@ CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y CONFIG_PHY_MICREL=y diff --git a/configs/mx6ull_14x14_evk_defconfig b/configs/mx6ull_14x14_evk_defconfig index 59d5d1283cfe75e284c0d72046ee5dccc7ffae6b..a5a1cb504df94947a4f98311903a89e834be90fa 100644 --- a/configs/mx6ull_14x14_evk_defconfig +++ b/configs/mx6ull_14x14_evk_defconfig @@ -33,7 +33,6 @@ CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PINCTRL=y CONFIG_PINCTRL_IMX6=y diff --git a/configs/mx6ull_14x14_evk_plugin_defconfig b/configs/mx6ull_14x14_evk_plugin_defconfig index 331f12d6f033a6254d70f6cfb32bf25c639c28c0..831b8ccd79ff335d74c6020d3393aecde9d69dea 100644 --- a/configs/mx6ull_14x14_evk_plugin_defconfig +++ b/configs/mx6ull_14x14_evk_plugin_defconfig @@ -34,7 +34,6 @@ CONFIG_DM_MMC=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PINCTRL=y CONFIG_PINCTRL_IMX6=y diff --git a/configs/mx7dsabresd_qspi_defconfig b/configs/mx7dsabresd_qspi_defconfig index fb176d79b39d9fd9c3526d2bec8c1f04b07c493c..81f4538fe25d52c19647b8e058e28ca4fe0200c0 100644 --- a/configs/mx7dsabresd_qspi_defconfig +++ b/configs/mx7dsabresd_qspi_defconfig @@ -50,7 +50,6 @@ CONFIG_MMC_HS200_SUPPORT=y CONFIG_FSL_ESDHC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_PHYLIB=y diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig index 92aa802ade92294ed7968419a0041ca145a0ddef..1e54035c0364f88e2090ca567ac46c7d0abf8bcb 100644 --- a/configs/phycore-rk3288_defconfig +++ b/configs/phycore-rk3288_defconfig @@ -55,6 +55,7 @@ CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig index 5cbcb897224d9bfd6fa256f2d178a36217bda5f8..ca194fd62b3270f14e5ef31060cd858206e787d6 100644 --- a/configs/popmetal-rk3288_defconfig +++ b/configs/popmetal-rk3288_defconfig @@ -51,6 +51,7 @@ CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/porter_defconfig b/configs/porter_defconfig index d51db3d5cb28814c00c5f6bf6fb17bb57452e344..7c54a54638693868872391e4206a0c8a09fb4b4d 100644 --- a/configs/porter_defconfig +++ b/configs/porter_defconfig @@ -64,7 +64,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/r8a77970_eagle_defconfig b/configs/r8a77970_eagle_defconfig index 5af1bdb221f6b24c5aef37cab8ef155c62506dc3..d269c62101e32c1931d6ffe2d64f309189d78e31 100644 --- a/configs/r8a77970_eagle_defconfig +++ b/configs/r8a77970_eagle_defconfig @@ -43,7 +43,6 @@ CONFIG_SYS_I2C_RCAR_IIC=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_PHY_MICREL=y diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig index a5faa8fb958ae387de4291d2d6cd7a5acb16deeb..746c0bfb353c40aedc1e4b6a824359c10c3f2f86 100644 --- a/configs/rock2_defconfig +++ b/configs/rock2_defconfig @@ -51,6 +51,7 @@ CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/rock_defconfig b/configs/rock_defconfig index 36e35eb65d5d5cd677643d54a0d2438e61e2a1aa..2de51e8c53169f3d9eafad9abee065b87bb1a6bb 100644 --- a/configs/rock_defconfig +++ b/configs/rock_defconfig @@ -40,6 +40,7 @@ CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_LED=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_PINCTRL=y CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set diff --git a/configs/silk_defconfig b/configs/silk_defconfig index 3350e6903960778efe97f976817d33d11507d641..3cb4f6e005aee659c87f2e0de3a80d0ea285e5bc 100644 --- a/configs/silk_defconfig +++ b/configs/silk_defconfig @@ -66,7 +66,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/socfpga_arria5_defconfig b/configs/socfpga_arria5_defconfig index 0e5e74a6217578548c5b308976e62c7009717030..2f040926490a1a005fa03c5868584c1954571066 100644 --- a/configs/socfpga_arria5_defconfig +++ b/configs/socfpga_arria5_defconfig @@ -51,7 +51,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set diff --git a/configs/socfpga_cyclone5_defconfig b/configs/socfpga_cyclone5_defconfig index e8de0f5709dd546a85556428954b5628d5349269..2625aadf402452cd6325d5920da19b4367c2ef1d 100644 --- a/configs/socfpga_cyclone5_defconfig +++ b/configs/socfpga_cyclone5_defconfig @@ -51,7 +51,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y diff --git a/configs/socfpga_is1_defconfig b/configs/socfpga_is1_defconfig index 682e58fdb8b829dc6d14bd1954a1cb59f107d198..cd7211d202ba6c3dac9ac534dd35752e4d29a8b1 100644 --- a/configs/socfpga_is1_defconfig +++ b/configs/socfpga_is1_defconfig @@ -48,7 +48,6 @@ CONFIG_SYS_I2C_DW=y # CONFIG_MMC is not set CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/socfpga_sockit_defconfig b/configs/socfpga_sockit_defconfig index abbbcb94d34ebe3de0dae502bf17f362391372ed..4c17d1a9e4a5f7ece9d30202b59c200b6c60d7fb 100644 --- a/configs/socfpga_sockit_defconfig +++ b/configs/socfpga_sockit_defconfig @@ -51,7 +51,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y diff --git a/configs/socfpga_socrates_defconfig b/configs/socfpga_socrates_defconfig index 53f8d3c348db96191a4ce3847fb2b9e601f491a5..45fd78a15cd4416f84871fd34161b128562827e3 100644 --- a/configs/socfpga_socrates_defconfig +++ b/configs/socfpga_socrates_defconfig @@ -52,7 +52,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y diff --git a/configs/socfpga_sr1500_defconfig b/configs/socfpga_sr1500_defconfig index 97366cdfff0cdd649ad4a5d2dd0e891d52485006..d984047bfe63508c11aa0163c7c4de9d67b045fb 100644 --- a/configs/socfpga_sr1500_defconfig +++ b/configs/socfpga_sr1500_defconfig @@ -53,7 +53,6 @@ CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_PHY_MARVELL=y diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig index bc3a3a3e227442047ad863db1bc09728ec2e9980..9e6d582ee3af411324086f081262e818de575afe 100644 --- a/configs/socfpga_stratix10_defconfig +++ b/configs/socfpga_stratix10_defconfig @@ -39,7 +39,6 @@ CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set diff --git a/configs/stout_defconfig b/configs/stout_defconfig index acd05564f3273de0a191d49dc009d8fe30844dcb..1b1ed8d3acc4939bc1cdff7c2e0ca12622440cae 100644 --- a/configs/stout_defconfig +++ b/configs/stout_defconfig @@ -64,7 +64,6 @@ CONFIG_RENESAS_SDHI=y CONFIG_MTD=y CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_MICREL=y diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig index 24222e5395dcb8543eb7a5ab2371a6161f2cbff0..68adf7635bff842b554fee6b591b338e0ca75e5f 100644 --- a/configs/tinker-rk3288_defconfig +++ b/configs/tinker-rk3288_defconfig @@ -54,6 +54,7 @@ CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/topic_miami_defconfig b/configs/topic_miami_defconfig index 927ce9ad2848cd34548bd6d357cbc97c4db9e3c3..73dc9531cd92fc4b1ba8a63c08920eb572d13c19 100644 --- a/configs/topic_miami_defconfig +++ b/configs/topic_miami_defconfig @@ -39,7 +39,6 @@ CONFIG_SYS_I2C_CADENCE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_DEBUG_UART_ZYNQ=y diff --git a/configs/topic_miamilite_defconfig b/configs/topic_miamilite_defconfig index e4d52f6a915e7b0f0bd187f0951bd8c8b24d64b5..e379a8e3d4cb8b210eaa1c96e5c66c5e29dbbd6f 100644 --- a/configs/topic_miamilite_defconfig +++ b/configs/topic_miamilite_defconfig @@ -39,8 +39,6 @@ CONFIG_SYS_I2C_CADENCE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_DEBUG_UART_ZYNQ=y diff --git a/configs/topic_miamiplus_defconfig b/configs/topic_miamiplus_defconfig index f742838d7c1f1432628cef72fcb9e3cacbdff654..a7bc257c97b9d0500c4909d63c9ae2d330c03ff2 100644 --- a/configs/topic_miamiplus_defconfig +++ b/configs/topic_miamiplus_defconfig @@ -38,8 +38,6 @@ CONFIG_SYS_I2C_CADENCE=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set # CONFIG_NETDEVICES is not set diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 5cafe2ee340a3060e4924df81d882daa18fad813..7e5943b108519df298a9ddbdf1039068e48ef9e2 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -40,6 +40,7 @@ CONFIG_SCSI_AHCI=y CONFIG_ATSHA204A=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y +CONFIG_SPI_FLASH=y CONFIG_PHY_MARVELL=y CONFIG_PHY_GIGE=y CONFIG_MVNETA=y diff --git a/configs/vyasa-rk3288_defconfig b/configs/vyasa-rk3288_defconfig index 03c8a76cbeaa36c036d5f5cef3b7304b693b7a2a..c4779c0fa15b414e6afe4297b181c4fc4a9a7940 100644 --- a/configs/vyasa-rk3288_defconfig +++ b/configs/vyasa-rk3288_defconfig @@ -49,6 +49,7 @@ CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 57e497c922f83aa4e343e080d07b6cbfb675e9b6..2b226c400421359670aeab65d30d933082ff0049 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -50,7 +50,6 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y diff --git a/configs/xilinx_zynqmp_mini_qspi_defconfig b/configs/xilinx_zynqmp_mini_qspi_defconfig index 3ec435e7ffe783702e5ad02f7ca3df68bda588f3..ba521876b75f7eca076f1ddd7716ac27ca1b1d72 100644 --- a/configs/xilinx_zynqmp_mini_qspi_defconfig +++ b/configs/xilinx_zynqmp_mini_qspi_defconfig @@ -53,8 +53,6 @@ CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zc1232_revA_defconfig b/configs/xilinx_zynqmp_zc1232_revA_defconfig index 9026f00649bbe536d678b221f9bc9f852a2ab931..80a310fb1cee4a9eda8a48c9f0899ecf01e12c28 100644 --- a/configs/xilinx_zynqmp_zc1232_revA_defconfig +++ b/configs/xilinx_zynqmp_zc1232_revA_defconfig @@ -37,8 +37,6 @@ CONFIG_FPGA_ZYNQMPPL=y CONFIG_MISC=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zc1254_revA_defconfig b/configs/xilinx_zynqmp_zc1254_revA_defconfig index 3eed06976053c912a9cbb8afb1c3ff4b4267c855..75ec572827bfb56076f82d5fcc7d486c3bee5b2f 100644 --- a/configs/xilinx_zynqmp_zc1254_revA_defconfig +++ b/configs/xilinx_zynqmp_zc1254_revA_defconfig @@ -37,8 +37,6 @@ CONFIG_FPGA_ZYNQMPPL=y CONFIG_MISC=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zc1275_revA_defconfig b/configs/xilinx_zynqmp_zc1275_revA_defconfig index 8bd7c9c57842e56e22da1ae43b251db9c3ddbade..731bd06d26f4061bd10f91c98acad6aaba6e937c 100644 --- a/configs/xilinx_zynqmp_zc1275_revA_defconfig +++ b/configs/xilinx_zynqmp_zc1275_revA_defconfig @@ -37,8 +37,6 @@ CONFIG_FPGA_ZYNQMPPL=y CONFIG_MISC=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zc1275_revB_defconfig b/configs/xilinx_zynqmp_zc1275_revB_defconfig index 9f023c2bd2bdf27dbc9e64c4f6cba267fe7b73da..1e8e14c952c6a92e8e16c963796275fdda4e00af 100644 --- a/configs/xilinx_zynqmp_zc1275_revB_defconfig +++ b/configs/xilinx_zynqmp_zc1275_revB_defconfig @@ -41,8 +41,6 @@ CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig index f2caac790a1a3d0731cc009902be6287e5d04809..59db2131c0c47d47dc89d405db1f7d1113575ff6 100644 --- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig @@ -61,8 +61,6 @@ CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig index fb369b1ff823af202c2a917f687d8c00a6a2baf3..01c29c0e70a32a87395b2989ad091bf9fe783a8f 100644 --- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig @@ -59,7 +59,6 @@ CONFIG_NAND=y CONFIG_NAND_ARASAN=y CONFIG_SYS_NAND_MAX_CHIPS=2 CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SST=y CONFIG_PHY_MARVELL=y CONFIG_PHY_NATSEMI=y diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig index 10e0fca65578419863ccddbdb18319f0c1c76a2e..6f14234a590e7ce455f05ca6b89ba85dd63e58e8 100644 --- a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig @@ -47,8 +47,6 @@ CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu100_revC_defconfig b/configs/xilinx_zynqmp_zcu100_revC_defconfig index ca96b9ee2aa3a144d165e3f5654ea01ed6e58307..a3c81eb7e97fda53bfedac4941b480a20d819e34 100644 --- a/configs/xilinx_zynqmp_zcu100_revC_defconfig +++ b/configs/xilinx_zynqmp_zcu100_revC_defconfig @@ -57,7 +57,6 @@ CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig b/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig index 30d3147a7a8bc909071eff08c9409e8e7bb40c96..ac1710195a2b4f5b567d0aeb1b384966b4474ab0 100644 --- a/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig +++ b/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig @@ -74,8 +74,6 @@ CONFIG_MMC_UHS_SUPPORT=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu102_revA_defconfig b/configs/xilinx_zynqmp_zcu102_revA_defconfig index bada5e117317941e0c59384a7344f44fcf28c219..604e8c9f71e352f106fa8d20d623fd32a618fe5f 100644 --- a/configs/xilinx_zynqmp_zcu102_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revA_defconfig @@ -72,8 +72,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index 3c4ac01b220c4f53b2e9d83fa47ad3b4404bc892..d0155b1d4feef5224832cffd5a4b15e1dddafdf3 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -72,8 +72,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu104_revA_defconfig b/configs/xilinx_zynqmp_zcu104_revA_defconfig index 90fd431df3dd5e5bb1ce08d7fe44d16ed8d7043e..06c3ca3db69619ec2dd9a53fbdebdd570de58e8e 100644 --- a/configs/xilinx_zynqmp_zcu104_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu104_revA_defconfig @@ -57,8 +57,6 @@ CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu104_revC_defconfig b/configs/xilinx_zynqmp_zcu104_revC_defconfig index eb30e2398f2cb73d4b4f3f7c99205a5c1513732d..d615cb04f40deab0b82928638819500128994db3 100644 --- a/configs/xilinx_zynqmp_zcu104_revC_defconfig +++ b/configs/xilinx_zynqmp_zcu104_revC_defconfig @@ -58,8 +58,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu106_revA_defconfig b/configs/xilinx_zynqmp_zcu106_revA_defconfig index 9e8eb5f483a2db0e94fc29570a9435c7832a1c3f..9f5f97500844a4d6831c0e015a525fa335302a25 100644 --- a/configs/xilinx_zynqmp_zcu106_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu106_revA_defconfig @@ -68,8 +68,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SF_DUAL_FLASH=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/xilinx_zynqmp_zcu111_revA_defconfig b/configs/xilinx_zynqmp_zcu111_revA_defconfig index b8e96042da0a08b9ae159841e3f5fbe4eeb557f0..40586771a035fc226a0c16ef48bb78db1dc1b186 100644 --- a/configs/xilinx_zynqmp_zcu111_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu111_revA_defconfig @@ -60,7 +60,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0x20 CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_cc108_defconfig b/configs/zynq_cc108_defconfig index 5a930d6a3856e88317e7979766d281db7ebae302..1fd18ac364905a83bda311df7d63903cdfc8e91a 100644 --- a/configs/zynq_cc108_defconfig +++ b/configs/zynq_cc108_defconfig @@ -34,7 +34,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_cse_qspi_defconfig b/configs/zynq_cse_qspi_defconfig index 1fc8a597ce9fbf204db34b2cabc7941bf7940854..1f8aa6e4ba90e4e49dea8e1df367841853397cef 100644 --- a/configs/zynq_cse_qspi_defconfig +++ b/configs/zynq_cse_qspi_defconfig @@ -56,7 +56,6 @@ CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-qspi-single" CONFIG_SPL_DM_SEQ_ALIAS=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_dlc20_rev1_0_defconfig b/configs/zynq_dlc20_rev1_0_defconfig index 7ead19208f4f17d1f652ae19da511df8bc0c6ad5..42b565ce46a5371bf5e5e4d341c78b13dac6d072 100644 --- a/configs/zynq_dlc20_rev1_0_defconfig +++ b/configs/zynq_dlc20_rev1_0_defconfig @@ -49,7 +49,6 @@ CONFIG_ZYNQ_I2C0=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_REALTEK=y diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig index 206938584bc0e6e43509a58243c4bc12438f5b4c..83996bb7734a567c1e02d402201cf296e90974f1 100644 --- a/configs/zynq_microzed_defconfig +++ b/configs/zynq_microzed_defconfig @@ -40,7 +40,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y diff --git a/configs/zynq_minized_defconfig b/configs/zynq_minized_defconfig index 1b86040760310a3cb3aa842b65f9a6e3dcb9d9b1..21f807a2d082a46ccb7af88f3d3d876a5f56038b 100644 --- a/configs/zynq_minized_defconfig +++ b/configs/zynq_minized_defconfig @@ -41,7 +41,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y diff --git a/configs/zynq_z_turn_defconfig b/configs/zynq_z_turn_defconfig index ff3322cf85b788c37fcd4e34f4d919879b1463cb..f5cbaae0b190a90d7ffea9b75568a219998fee8e 100644 --- a/configs/zynq_z_turn_defconfig +++ b/configs/zynq_z_turn_defconfig @@ -40,7 +40,6 @@ CONFIG_LED_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig index 9734f24fdfed55c53e3766118d83f9956e90dcea..101568de8e1b33a21c08c3fa90499323dcc3f87b 100644 --- a/configs/zynq_zc702_defconfig +++ b/configs/zynq_zc702_defconfig @@ -52,7 +52,6 @@ CONFIG_LED_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig index 4a03351d1ee250fc314731365fe8c883839cd0b2..313a02a0914160c690ec38d7b15072a58f5e4371 100644 --- a/configs/zynq_zc706_defconfig +++ b/configs/zynq_zc706_defconfig @@ -52,7 +52,6 @@ CONFIG_ZYNQ_I2C0=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig index fed1502d1b6bc2ecb0ec664fe4236b927bcfed8a..22d5b847668c73dc33123098c00ff2626889a8b4 100644 --- a/configs/zynq_zc770_xm010_defconfig +++ b/configs/zynq_zc770_xm010_defconfig @@ -41,7 +41,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig index 630e392e4e0d83a052b0fceb073bb3481b79f1a3..4f11ddedf87a974395e362e2ad1af0127d95b4c9 100644 --- a/configs/zynq_zc770_xm013_defconfig +++ b/configs/zynq_zc770_xm013_defconfig @@ -35,7 +35,6 @@ CONFIG_FPGA_ZYNQPL=y CONFIG_DM_GPIO=y # CONFIG_MMC is not set CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig index dbf5c41739728c164b389cc5b79eb535a99cc0a8..166c03469634ab414f73bb6e64178ffb9b61afa1 100644 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@ -43,7 +43,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig index 9e44e82549f7a26ce04b78ad0592d0b64e29e770..6754ff529a97ad37d00be73c0261aea65fd61f40 100644 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@ -44,7 +44,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET=0xFA CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_PHY_MARVELL=y CONFIG_PHY_REALTEK=y diff --git a/configs/zynq_zybo_z7_defconfig b/configs/zynq_zybo_z7_defconfig index d729ca340c3667be8721a9e62df7b8eefc5c4034..6323645aeb02bcd87dab55d7438cbad75e107440 100644 --- a/configs/zynq_zybo_z7_defconfig +++ b/configs/zynq_zybo_z7_defconfig @@ -43,7 +43,6 @@ CONFIG_DM_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_PHY_REALTEK=y CONFIG_MII=y diff --git a/doc/SPI/README.dual-flash b/doc/SPI/README.dual-flash deleted file mode 100644 index 6c88d65dd49f86a8e1edcf30d4b5b4ccdc53d0d7..0000000000000000000000000000000000000000 --- a/doc/SPI/README.dual-flash +++ /dev/null @@ -1,92 +0,0 @@ -SPI/QSPI Dual flash connection modes: -===================================== - -This describes how SPI/QSPI flash memories are connected to a given -controller in a single chip select line. - -Current spi_flash framework supports, single flash memory connected -to a given controller with single chip select line, but there are some -hw logics(ex: xilinx zynq qspi) that describes two/dual memories are -connected with a single chip select line from a controller. - -"dual_flash" from include/spi.h describes these types of connection mode - -Possible connections: --------------------- -SF_SINGLE_FLASH: - - single spi flash memory connected with single chip select line. - - +------------+ CS +---------------+ - | |----------------------->| | - | Controller | I0[3:0] | Flash memory | - | SPI/QSPI |<======================>| (SPI/QSPI) | - | | CLK | | - | |----------------------->| | - +------------+ +---------------+ - -SF_DUAL_STACKED_FLASH: - - dual spi/qspi flash memories are connected with a single chipselect - line and these two memories are operating stacked fasion with shared buses. - - xilinx zynq qspi controller has implemented this feature [1] - - +------------+ CS +---------------+ - | |---------------------->| | - | | I0[3:0] | Upper Flash | - | | +=========>| memory | - | | | CLK | (SPI/QSPI) | - | | | +---->| | - | Controller | CS | | +---------------+ - | SPI/QSPI |------------|----|---->| | - | | I0[3:0] | | | Lower Flash | - | |<===========+====|====>| memory | - | | CLK | | (SPI/QSPI) | - | |-----------------+---->| | - +------------+ +---------------+ - - - two memory flash devices should has same hw part attributes (like size, - vendor..etc) - - Configurations: - on LQSPI_CFG register, Enable TWO_MEM[BIT:30] on LQSPI_CFG - Enable U_PAGE[BIT:28] if U_PAGE flag set - upper memory - Disable U_PAGE[BIT:28] if U_PAGE flag unset - lower memory - - Operation: - accessing memories serially like one after another. - by default, if U_PAGE is unset lower memory should accessible, - once user wants to access upper memory need to set U_PAGE. - -SPI_FLASH_CONN_DUALPARALLEL: - - dual spi/qspi flash memories are connected with a single chipselect - line and these two memories are operating parallel with separate buses. - - xilinx zynq qspi controller has implemented this feature [1] - - +-------------+ CS +---------------+ - | |---------------------->| | - | | I0[3:0] | Upper Flash | - | |<=====================>| memory | - | | CLK | (SPI/QSPI) | - | |---------------------->| | - | Controller | CS +---------------+ - | SPI/QSPI |---------------------->| | - | | I0[3:0] | Lower Flash | - | |<=====================>| memory | - | | CLK | (SPI/QSPI) | - | |---------------------->| | - +-------------+ +---------------+ - - - two memory flash devices should has same hw part attributes (like size, - vendor..etc) - - Configurations: - Need to enable SEP_BUS[BIT:29],TWO_MEM[BIT:30] on LQSPI_CFG register. - - Operation: - Even bits, i.e. bit 0, 2, 4 ., of a data word is located in the lower memory - and odd bits, i.e. bit 1, 3, 5, ., of a data word is located in the upper memory. - -Note: Technically there is only one CS line from the controller, but -zynq qspi controller has an internal hw logic to enable additional CS -when controller is configured for dual memories. - -[1] http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf - --- -Jagannadha Sutradharudu Teki -05-01-2014. diff --git a/doc/SPI/README.ti_qspi_dra_test b/doc/SPI/README.ti_qspi_dra_test index fe378572369baefc4d1f622b322455375add9917..e89f53587fa7991f46b8f50674e9aaa786a73386 100644 --- a/doc/SPI/README.ti_qspi_dra_test +++ b/doc/SPI/README.ti_qspi_dra_test @@ -22,7 +22,6 @@ Commands to erase/write u-boot/mlo to flash device -------------------------------------------------- U-Boot# sf probe 0 SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB, mapped at 5c000000 -SF: Warning - Only lower 16MiB accessible, Full access #define CONFIG_SPI_FLASH_BAR U-Boot# sf erase 0 0x10000 SF: 65536 bytes @ 0x0 Erased: OK U-Boot# sf erase 0x20000 0x10000 diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 76d5a1d115276d421383df3604f00bfb384e9fcc..e3b40fc157d6287d8d901381bba403408560c85c 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -27,6 +27,8 @@ config SPI_FLASH_SANDBOX config SPI_FLASH bool "Legacy SPI Flash Interface support" + depends on SPI + select SPI_MEM help Enable the legacy SPI flash support. This will include basic standard support for things like probing, read / write, and @@ -34,9 +36,18 @@ config SPI_FLASH If unsure, say N +if SPI_FLASH + +config SPI_FLASH_SFDP_SUPPORT + bool "SFDP table parsing support for SPI NOR flashes" + depends on !SPI_FLASH_BAR + help + Enable support for parsing and auto discovery of parameters for + SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) + tables as per JESD216 standard. + 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 @@ -44,13 +55,10 @@ config SPI_FLASH_BAR config SF_DUAL_FLASH bool "SPI DUAL flash memory support" - depends on SPI_FLASH help Enable this option to support two flash memories connected to a single controller. Currently Xilinx Zynq qspi supports this. -if SPI_FLASH - config SPI_FLASH_ATMEL bool "Atmel SPI flash support" help diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index b4c7e1c98bd5877aae3eb30d99b9aea5ba45633b..f99f6cb16e2969f91c693b7eef92382f87d71596 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -4,12 +4,20 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o +spi-nor-y := sf_probe.o spi-nor-ids.o ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o +ifeq ($(CONFIG_SPL_SPI_FLASH_TINY),y) +spi-nor-y += spi-nor-tiny.o +else +spi-nor-y += spi-nor-core.o +endif +else +spi-nor-y += spi-nor-core.o endif -obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o -obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o +obj-$(CONFIG_SPI_FLASH) += spi-nor.o +obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o sf.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 7b9891cb981c224b3c061f9b0649129059a95a96..084c66e9840b43c06b8b8b2a14182d0011a577b6 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -92,7 +92,7 @@ struct sandbox_spi_flash { /* The current flash status (see STAT_XXX defines above) */ u16 status; /* Data describing the flash we're emulating */ - const struct spi_flash_info *data; + const struct flash_info *data; /* The file on disk to serv up data from */ int fd; }; @@ -122,7 +122,7 @@ static int sandbox_sf_probe(struct udevice *dev) /* spec = idcode:file */ struct sandbox_spi_flash *sbsf = dev_get_priv(dev); size_t len, idname_len; - const struct spi_flash_info *data; + const struct flash_info *data; struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); struct sandbox_state *state = state_get_current(); struct dm_spi_slave_platdata *slave_plat; @@ -155,7 +155,7 @@ static int sandbox_sf_probe(struct udevice *dev) idname_len = strlen(spec); debug("%s: device='%s'\n", __func__, spec); - for (data = spi_flash_ids; data->name; data++) { + for (data = spi_nor_ids; data->name; data++) { len = strlen(data->name); if (idname_len != len) continue; @@ -243,43 +243,43 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, sbsf->cmd = rx[0]; switch (sbsf->cmd) { - case CMD_READ_ID: + case SPINOR_OP_RDID: sbsf->state = SF_ID; sbsf->cmd = SF_ID; break; - case CMD_READ_ARRAY_FAST: + case SPINOR_OP_READ_FAST: sbsf->pad_addr_bytes = 1; - case CMD_READ_ARRAY_SLOW: - case CMD_PAGE_PROGRAM: + case SPINOR_OP_READ: + case SPINOR_OP_PP: sbsf->state = SF_ADDR; break; - case CMD_WRITE_DISABLE: + case SPINOR_OP_WRDI: debug(" write disabled\n"); sbsf->status &= ~STAT_WEL; break; - case CMD_READ_STATUS: + case SPINOR_OP_RDSR: sbsf->state = SF_READ_STATUS; break; - case CMD_READ_STATUS1: + case SPINOR_OP_RDSR2: sbsf->state = SF_READ_STATUS1; break; - case CMD_WRITE_ENABLE: + case SPINOR_OP_WREN: debug(" write enabled\n"); sbsf->status |= STAT_WEL; break; - case CMD_WRITE_STATUS: + case SPINOR_OP_WRSR: sbsf->state = SF_WRITE_STATUS; break; default: { int flags = sbsf->data->flags; /* we only support erase here */ - if (sbsf->cmd == CMD_ERASE_CHIP) { + if (sbsf->cmd == SPINOR_OP_CHIP_ERASE) { sbsf->erase_size = sbsf->data->sector_size * sbsf->data->n_sectors; - } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { + } else if (sbsf->cmd == SPINOR_OP_BE_4K && (flags & SECT_4K)) { sbsf->erase_size = 4 << 10; - } else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) { + } else if (sbsf->cmd == SPINOR_OP_SE && !(flags & SECT_4K)) { sbsf->erase_size = 64 << 10; } else { debug(" cmd unknown: %#x\n", sbsf->cmd); @@ -380,11 +380,11 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, return -EIO; } switch (sbsf->cmd) { - case CMD_READ_ARRAY_FAST: - case CMD_READ_ARRAY_SLOW: + case SPINOR_OP_READ_FAST: + case SPINOR_OP_READ: sbsf->state = SF_READ; break; - case CMD_PAGE_PROGRAM: + case SPINOR_OP_PP: sbsf->state = SF_WRITE; break; default: diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 4a60c1b2b43aaf756151c46c72c3051b194e3f4e..b6a2631747a9d89aea718b5f20eb2b62ec1e4e2c 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -18,6 +18,7 @@ #include "sf_internal.h" +#define CMD_READ_ID 0x9f /* reads can bypass the buffers */ #define OP_READ_CONTINUOUS 0xE8 #define OP_READ_PAGE 0xD2 @@ -441,7 +442,7 @@ static int add_dataflash(struct udevice *dev, char *name, int nr_pages, return 0; } -struct flash_info { +struct data_flash_info { char *name; /* @@ -460,7 +461,7 @@ struct flash_info { #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ }; -static struct flash_info dataflash_data[] = { +static struct data_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 @@ -501,12 +502,12 @@ static struct flash_info dataflash_data[] = { { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, }; -static struct flash_info *jedec_probe(struct spi_slave *spi) +static struct data_flash_info *jedec_probe(struct spi_slave *spi) { int tmp; uint8_t id[5]; uint32_t jedec; - struct flash_info *info; + struct data_flash_info *info; int status; /* @@ -583,7 +584,7 @@ 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; + struct data_flash_info *info; int status; spi_flash = dev_get_uclass_priv(dev); diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 46a504441751124131bb83ede8bdc4a5bd86ec62..a6bf734830a71956b8fdb292774cf6567a326672 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -12,142 +12,65 @@ #include #include -/* 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 spi_nor_option_flags { - SNOR_F_SST_WR = BIT(0), - SNOR_F_USE_FSR = BIT(1), - SNOR_F_USE_UPAGE = BIT(3), -}; +#define SPI_NOR_MAX_ID_LEN 6 +#define SPI_NOR_MAX_ADDR_WIDTH 4 -#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_MICRON 0x2C -#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_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 - -/* 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 - -/* 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 +struct flash_info { +#if !CONFIG_IS_ENABLED(SPI_FLASH_TINY) + char *name; #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 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 SST26_CMD_READ_BPR 0x72 -#define SST26_CMD_WRITE_BPR 0x42 - -#define SST26_BPR_8K_NUM 4 -#define SST26_MAX_BPR_REG_LEN (18 + 1) -#define SST26_BOUND_REG_SIZE ((32 + SST26_BPR_8K_NUM * 8) * SZ_1K) - -enum lock_ctl { - SST26_CTL_LOCK, - SST26_CTL_UNLOCK, - SST26_CTL_CHECK -}; - -# 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 - -#define JEDEC_MFR(info) ((info)->id[0]) -#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) -#define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4])) -#define SPI_FLASH_MAX_ID_LEN 6 - -struct spi_flash_info { - /* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */ - const char *name; - /* * This array stores the ID bytes. * The first three bytes are the JEDIC ID. * JEDEC ID zero means "no ID" (mostly older chips). */ - u8 id[SPI_FLASH_MAX_ID_LEN]; + u8 id[SPI_NOR_MAX_ID_LEN]; u8 id_len; - /* - * The size listed here is what works with SPINOR_OP_SE, which isn't + /* The size listed here is what works with SPINOR_OP_SE, which isn't * necessarily called a "sector" by the vendor. */ - u32 sector_size; - u32 n_sectors; + unsigned int sector_size; + u16 n_sectors; u16 page_size; + u16 addr_width; u16 flags; -#define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly */ -#define E_FSR BIT(1) /* use flag status register for */ -#define SST_WR BIT(2) /* use SST byte/word programming */ -#define WR_QPP BIT(3) /* use Quad Page Program */ -#define RD_QUAD BIT(4) /* use Quad Read */ -#define RD_DUAL BIT(5) /* use Dual Read */ -#define RD_QUADIO BIT(6) /* use Quad IO Read */ -#define RD_DUALIO BIT(7) /* use Dual IO Read */ -#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) +#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */ +#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */ +#define SST_WRITE BIT(2) /* use SST byte programming */ +#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */ +#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ +#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ +#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ +#define USE_FSR BIT(7) /* use flag status register */ +#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ +#define SPI_NOR_HAS_TB BIT(9) /* + * Flash SR has Top/Bottom (TB) protect + * bit. Must be used with + * SPI_NOR_HAS_LOCK. + */ +#define SPI_S3AN BIT(10) /* + * Xilinx Spartan 3AN In-System Flash + * (MFR cannot be used for probing + * because it has the same value as + * ATMEL flashes) + */ +#define SPI_NOR_4B_OPCODES BIT(11) /* + * Use dedicated 4byte address op codes + * to support memory size above 128Mib. + */ +#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ +#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ +#define USE_CLSR BIT(14) /* use CLSR command */ }; -extern const struct spi_flash_info spi_flash_ids[]; +extern const struct flash_info spi_nor_ids[]; + +#define JEDEC_MFR(info) ((info)->id[0]) +#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) /* 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); @@ -167,78 +90,12 @@ 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); - /* Get software write-protect value (BP bits) */ int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); -/* 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_wait_till_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_probe.c b/drivers/mtd/spi/sf_probe.c index 00f8558e7019e9f7b6f2cf0a6d4c2b4a2916c497..7f1378f4946d256e92e4eea8f9bbf9a30818febc 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -40,7 +40,7 @@ static int spi_flash_probe_slave(struct spi_flash *flash) return ret; } - ret = spi_flash_scan(flash); + ret = spi_nor_scan(flash); if (ret) goto err_read_id; @@ -96,32 +96,38 @@ 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); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; - return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); + return log_ret(mtd->_read(mtd, offset, len, &retlen, 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); + struct mtd_info *mtd = &flash->mtd; + size_t retlen; -#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); + return mtd->_write(mtd, offset, len, &retlen, buf); } static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) { struct spi_flash *flash = dev_get_uclass_priv(dev); + 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 spi_flash_cmd_erase_ops(flash, offset, len); + return mtd->_erase(mtd, &instr); } static int spi_flash_std_get_sw_write_prot(struct udevice *dev) @@ -161,6 +167,7 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = { static const struct udevice_id spi_flash_std_ids[] = { { .compatible = "spi-flash" }, + { .compatible = "jedec,spi-nor" }, { } }; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c new file mode 100644 index 0000000000000000000000000000000000000000..b7f073387796a10e795e7c8b27f16c3a920ee583 --- /dev/null +++ b/drivers/mtd/spi/spi-nor-core.c @@ -0,0 +1,2414 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with + * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c + * + * Copyright (C) 2005, Intec Automation Inc. + * Copyright (C) 2014, Freescale Semiconductor, Inc. + * + * Synced from Linux v4.19 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sf_internal.h" + +/* Define max times to check status register before we give up. */ + +/* + * For everything but full-chip erase; probably could be much smaller, but kept + * around for safety for now + */ + +#define HZ CONFIG_SYS_HZ + +#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) + +static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op + *op, void *buf) +{ + if (op->data.dir == SPI_MEM_DATA_IN) + op->data.buf.in = buf; + else + op->data.buf.out = buf; + return spi_mem_exec_op(nor->spi, op); +} + +static int spi_nor_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(len, NULL, 1)); + int ret; + + ret = spi_nor_read_write_reg(nor, &op, val); + if (ret < 0) + dev_dbg(&flash->spimem->spi->dev, "error %d reading %x\n", ret, + code); + + return ret; +} + +static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(len, NULL, 1)); + + return spi_nor_read_write_reg(nor, &op, buf); +} + +static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, + u_char *buf) +{ + struct spi_mem_op op = + SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, from, 1), + SPI_MEM_OP_DUMMY(nor->read_dummy, 1), + SPI_MEM_OP_DATA_IN(len, buf, 1)); + size_t remaining = len; + int ret; + + /* get transfer protocols. */ + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); + op.dummy.buswidth = op.addr.buswidth; + op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); + + /* convert the dummy cycles to the number of bytes */ + op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + + while (remaining) { + op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; + ret = spi_mem_adjust_op_size(nor->spi, &op); + if (ret) + return ret; + + ret = spi_mem_exec_op(nor->spi, &op); + if (ret) + return ret; + + op.addr.val += op.data.nbytes; + remaining -= op.data.nbytes; + op.data.buf.in += op.data.nbytes; + } + + return len; +} + +static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len, + const u_char *buf) +{ + struct spi_mem_op op = + SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, to, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(len, buf, 1)); + size_t remaining = len; + int ret; + + /* get transfer protocols. */ + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); + op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); + + if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) + op.addr.nbytes = 0; + + while (remaining) { + op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; + ret = spi_mem_adjust_op_size(nor->spi, &op); + if (ret) + return ret; + + ret = spi_mem_exec_op(nor->spi, &op); + if (ret) + return ret; + + op.addr.val += op.data.nbytes; + remaining -= op.data.nbytes; + op.data.buf.out += op.data.nbytes; + } + + return len; +} + +/* + * Read the status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. + */ +static int read_sr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); + if (ret < 0) { + pr_debug("error %d reading SR\n", (int)ret); + return ret; + } + + return val; +} + +/* + * Read the flag status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. + */ +static int read_fsr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); + if (ret < 0) { + pr_debug("error %d reading FSR\n", ret); + return ret; + } + + return val; +} + +/* + * Read configuration register, returning its value in the + * location. Return the configuration register value. + * Returns negative if error occurred. + */ +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) +static int read_cr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); + if (ret < 0) { + dev_dbg(nor->dev, "error %d reading CR\n", ret); + return ret; + } + + return val; +} +#endif + +/* + * Write status register 1 byte + * Returns negative if error occurred. + */ +static int write_sr(struct spi_nor *nor, u8 val) +{ + nor->cmd_buf[0] = val; + return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); +} + +/* + * Set write enable latch with Write Enable command. + * Returns negative if error occurred. + */ +static int write_enable(struct spi_nor *nor) +{ + return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); +} + +/* + * Send write disable instruction to the chip. + */ +static int write_disable(struct spi_nor *nor) +{ + return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); +} + +static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) +{ + return mtd->priv; +} + +#ifndef CONFIG_SPI_FLASH_BAR +static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + if (table[i][0] == opcode) + return table[i][1]; + + /* No conversion found, keep input op code. */ + return opcode; +} + +static u8 spi_nor_convert_3to4_read(u8 opcode) +{ + static const u8 spi_nor_3to4_read[][2] = { + { SPINOR_OP_READ, SPINOR_OP_READ_4B }, + { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B }, + { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B }, + { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, + { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, + { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, + + { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B }, + { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B }, + { SPINOR_OP_READ_1_4_4_DTR, SPINOR_OP_READ_1_4_4_DTR_4B }, + }; + + return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, + ARRAY_SIZE(spi_nor_3to4_read)); +} + +static u8 spi_nor_convert_3to4_program(u8 opcode) +{ + static const u8 spi_nor_3to4_program[][2] = { + { SPINOR_OP_PP, SPINOR_OP_PP_4B }, + { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B }, + { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B }, + }; + + return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, + ARRAY_SIZE(spi_nor_3to4_program)); +} + +static u8 spi_nor_convert_3to4_erase(u8 opcode) +{ + static const u8 spi_nor_3to4_erase[][2] = { + { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B }, + { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B }, + { SPINOR_OP_SE, SPINOR_OP_SE_4B }, + }; + + return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase, + ARRAY_SIZE(spi_nor_3to4_erase)); +} + +static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, + const struct flash_info *info) +{ + /* Do some manufacturer fixups first */ + switch (JEDEC_MFR(info)) { + case SNOR_MFR_SPANSION: + /* No small sector erase for 4-byte command set */ + nor->erase_opcode = SPINOR_OP_SE; + nor->mtd.erasesize = info->sector_size; + break; + + default: + break; + } + + nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); + nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode); + nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); +} +#endif /* !CONFIG_SPI_FLASH_BAR */ + +/* Enable/disable 4-byte addressing mode. */ +static int set_4byte(struct spi_nor *nor, const struct flash_info *info, + int enable) +{ + int status; + bool need_wren = false; + u8 cmd; + + switch (JEDEC_MFR(info)) { + case SNOR_MFR_ST: + case SNOR_MFR_MICRON: + /* Some Micron need WREN command; all will accept it */ + need_wren = true; + case SNOR_MFR_MACRONIX: + case SNOR_MFR_WINBOND: + if (need_wren) + write_enable(nor); + + cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; + status = nor->write_reg(nor, cmd, NULL, 0); + if (need_wren) + write_disable(nor); + + if (!status && !enable && + JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + /* + * On Winbond W25Q256FV, leaving 4byte mode causes + * the Extended Address Register to be set to 1, so all + * 3-byte-address reads come from the second 16M. + * We must clear the register to enable normal behavior. + */ + write_enable(nor); + nor->cmd_buf[0] = 0; + nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); + write_disable(nor); + } + + return status; + default: + /* Spansion style */ + nor->cmd_buf[0] = enable << 7; + return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); + } +} + +static int spi_nor_sr_ready(struct spi_nor *nor) +{ + int sr = read_sr(nor); + + if (sr < 0) + return sr; + + if (nor->flags & SNOR_F_USE_CLSR && sr & (SR_E_ERR | SR_P_ERR)) { + if (sr & SR_E_ERR) + dev_dbg(nor->dev, "Erase Error occurred\n"); + else + dev_dbg(nor->dev, "Programming Error occurred\n"); + + nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); + return -EIO; + } + + return !(sr & SR_WIP); +} + +static int spi_nor_fsr_ready(struct spi_nor *nor) +{ + int fsr = read_fsr(nor); + + if (fsr < 0) + return fsr; + + if (fsr & (FSR_E_ERR | FSR_P_ERR)) { + if (fsr & FSR_E_ERR) + dev_dbg(nor->dev, "Erase operation failed.\n"); + else + dev_dbg(nor->dev, "Program operation failed.\n"); + + if (fsr & FSR_PT_ERR) + dev_dbg(nor->dev, + "Attempted to modify a protected sector.\n"); + + nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); + return -EIO; + } + + return fsr & FSR_READY; +} + +static int spi_nor_ready(struct spi_nor *nor) +{ + int sr, fsr; + + sr = spi_nor_sr_ready(nor); + if (sr < 0) + return sr; + fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; + if (fsr < 0) + return fsr; + return sr && fsr; +} + +/* + * Service routine to read status register until ready, or timeout occurs. + * Returns non-zero if error. + */ +static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, + unsigned long timeout) +{ + unsigned long timebase; + int ret; + + timebase = get_timer(0); + + while (get_timer(timebase) < timeout) { + ret = spi_nor_ready(nor); + if (ret < 0) + return ret; + if (ret) + return 0; + } + + dev_err(nor->dev, "flash operation timed out\n"); + + return -ETIMEDOUT; +} + +static int spi_nor_wait_till_ready(struct spi_nor *nor) +{ + return spi_nor_wait_till_ready_with_timeout(nor, + DEFAULT_READY_WAIT_JIFFIES); +} + +#ifdef CONFIG_SPI_FLASH_BAR +/* + * This "clean_bar" is necessary in a situation when one was accessing + * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit. + * + * After it the BA24 bit shall be cleared to allow access to correct + * memory region after SW reset (by calling "reset" command). + * + * Otherwise, the BA24 bit may be left set and then after reset, the + * ROM would read/write/erase SPL from 16 MiB * bank_sel address. + */ +static int clean_bar(struct spi_nor *nor) +{ + u8 cmd, bank_sel = 0; + + if (nor->bank_curr == 0) + return 0; + cmd = nor->bank_write_cmd; + nor->bank_curr = 0; + write_enable(nor); + + return nor->write_reg(nor, cmd, &bank_sel, 1); +} + +static int write_bar(struct spi_nor *nor, u32 offset) +{ + u8 cmd, bank_sel; + int ret; + + bank_sel = offset / SZ_16M; + if (bank_sel == nor->bank_curr) + goto bar_end; + + cmd = nor->bank_write_cmd; + write_enable(nor); + ret = nor->write_reg(nor, cmd, &bank_sel, 1); + if (ret < 0) { + debug("SF: fail to write bank register\n"); + return ret; + } + +bar_end: + nor->bank_curr = bank_sel; + return nor->bank_curr; +} + +static int read_bar(struct spi_nor *nor, const struct flash_info *info) +{ + u8 curr_bank = 0; + int ret; + + switch (JEDEC_MFR(info)) { + case SNOR_MFR_SPANSION: + nor->bank_read_cmd = SPINOR_OP_BRRD; + nor->bank_write_cmd = SPINOR_OP_BRWR; + break; + default: + nor->bank_read_cmd = SPINOR_OP_RDEAR; + nor->bank_write_cmd = SPINOR_OP_WREAR; + } + + ret = nor->read_reg(nor, nor->bank_read_cmd, + &curr_bank, 1); + if (ret) { + debug("SF: fail to read bank addr register\n"); + return ret; + } + nor->bank_curr = curr_bank; + + return 0; +} +#endif + +/* + * Initiate the erasure of a single sector + */ +static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) +{ + u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; + int i; + + if (nor->erase) + return nor->erase(nor, addr); + + /* + * Default implementation, if driver doesn't have a specialized HW + * control + */ + for (i = nor->addr_width - 1; i >= 0; i--) { + buf[i] = addr & 0xff; + addr >>= 8; + } + + return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); +} + +/* + * Erase an address range on the nor chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + u32 addr, len, rem; + int ret; + + dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, + (long long)instr->len); + + div_u64_rem(instr->len, mtd->erasesize, &rem); + if (rem) + return -EINVAL; + + addr = instr->addr; + len = instr->len; + + while (len) { +#ifdef CONFIG_SPI_FLASH_BAR + ret = write_bar(nor, addr); + if (ret < 0) + return ret; +#endif + write_enable(nor); + + ret = spi_nor_erase_sector(nor, addr); + if (ret) + goto erase_err; + + addr += mtd->erasesize; + len -= mtd->erasesize; + + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto erase_err; + } + +erase_err: +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(nor); +#endif + write_disable(nor); + + return ret; +} + +#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) +/* Write status register and ensure bits in mask match written values */ +static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) +{ + int ret; + + write_enable(nor); + ret = write_sr(nor, status_new); + if (ret) + return ret; + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + ret = read_sr(nor); + if (ret < 0) + return ret; + + return ((ret & mask) != (status_new & mask)) ? -EIO : 0; +} + +static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, + uint64_t *len) +{ + struct mtd_info *mtd = &nor->mtd; + 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 = mtd->size >> pow; + if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) + *ofs = 0; + else + *ofs = mtd->size - *len; + } +} + +/* + * Return 1 if the entire region is locked (if @locked is true) or unlocked (if + * @locked is false); 0 otherwise + */ +static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, u64 len, + u8 sr, bool locked) +{ + loff_t lock_offs; + uint64_t lock_len; + + if (!len) + return 1; + + stm_get_locked_range(nor, sr, &lock_offs, &lock_len); + + if (locked) + /* Requested range is a sub-range of locked range */ + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); + else + /* Requested range does not overlap with locked range */ + return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs); +} + +static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr) +{ + return stm_check_lock_status_sr(nor, ofs, len, sr, true); +} + +static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr) +{ + return stm_check_lock_status_sr(nor, ofs, len, sr, false); +} + +/* + * Lock a region of the flash. Compatible with ST Micro and similar flash. + * Supports the block protection bits BP{0,1,2} in the status register + * (SR). Does not support these features found in newer SR bitfields: + * - SEC: sector/block protect - only handle SEC=0 (block protect) + * - CMP: complement protect - only support CMP=0 (range is not complemented) + * + * Support for the following is provided conditionally for some flash: + * - TB: top/bottom protect + * + * 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 + * ------|-------|-------|-------|-------|---------------|------------------- + * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 + * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 + * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 + * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 + * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 + * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 + * + * Returns negative on errors, 0 on success. + */ +static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + struct mtd_info *mtd = &nor->mtd; + int status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + loff_t lock_len; + bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; + bool use_top; + + status_old = read_sr(nor); + if (status_old < 0) + return status_old; + + /* If nothing in our range is unlocked, we don't need to do anything */ + if (stm_is_locked_sr(nor, ofs, len, status_old)) + return 0; + + /* If anything below us is unlocked, we can't use 'bottom' protection */ + if (!stm_is_locked_sr(nor, 0, ofs, status_old)) + can_be_bottom = false; + + /* If anything above us is unlocked, we can't use 'top' protection */ + if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), + status_old)) + can_be_top = false; + + if (!can_be_bottom && !can_be_top) + return -EINVAL; + + /* Prefer top, if both are valid */ + use_top = can_be_top; + + /* lock_len: length of region that should end up locked */ + if (use_top) + lock_len = mtd->size - ofs; + else + lock_len = ofs + len; + + /* + * 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(mtd->size) - ilog2(lock_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 & ~SR_TB) | val; + + /* Disallow further writes if WP pin is asserted */ + status_new |= SR_SRWD; + + if (!use_top) + status_new |= SR_TB; + + /* Don't bother if they're the same */ + if (status_new == status_old) + return 0; + + /* Only modify protection if it will not unlock other areas */ + if ((status_new & mask) < (status_old & mask)) + return -EINVAL; + + return write_sr_and_check(nor, status_new, mask); +} + +/* + * Unlock a region of the flash. See stm_lock() for more info + * + * Returns negative on errors, 0 on success. + */ +static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + struct mtd_info *mtd = &nor->mtd; + int status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + loff_t lock_len; + bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; + bool use_top; + + status_old = read_sr(nor); + if (status_old < 0) + return status_old; + + /* If nothing in our range is locked, we don't need to do anything */ + if (stm_is_unlocked_sr(nor, ofs, len, status_old)) + return 0; + + /* If anything below us is locked, we can't use 'top' protection */ + if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) + can_be_top = false; + + /* If anything above us is locked, we can't use 'bottom' protection */ + if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), + status_old)) + can_be_bottom = false; + + if (!can_be_bottom && !can_be_top) + return -EINVAL; + + /* Prefer top, if both are valid */ + use_top = can_be_top; + + /* lock_len: length of region that should remain locked */ + if (use_top) + lock_len = mtd->size - (ofs + len); + else + lock_len = ofs; + + /* + * 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(mtd->size) - order_base_2(lock_len); + if (lock_len == 0) { + 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 & ~SR_TB) | val; + + /* Don't protect status register if we're fully unlocked */ + if (lock_len == 0) + status_new &= ~SR_SRWD; + + if (!use_top) + status_new |= SR_TB; + + /* Don't bother if they're the same */ + if (status_new == status_old) + return 0; + + /* Only modify protection if it will not lock other areas */ + if ((status_new & mask) > (status_old & mask)) + return -EINVAL; + + return write_sr_and_check(nor, status_new, mask); +} + +/* + * 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. + */ +static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + int status; + + status = read_sr(nor); + if (status < 0) + return status; + + return stm_is_locked_sr(nor, ofs, len, status); +} +#endif /* CONFIG_SPI_FLASH_STMICRO */ + +static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) +{ + int tmp; + u8 id[SPI_NOR_MAX_ID_LEN]; + const struct flash_info *info; + + tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + if (tmp < 0) { + dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); + return ERR_PTR(tmp); + } + + info = spi_nor_ids; + for (; info->name; info++) { + if (info->id_len) { + if (!memcmp(info->id, id, info->id_len)) + return info; + } + } + + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); +} + +static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + int ret; + + dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); + + while (len) { + loff_t addr = from; + size_t read_len = len; + +#ifdef CONFIG_SPI_FLASH_BAR + u32 remain_len; + + ret = write_bar(nor, addr); + if (ret < 0) + return log_ret(ret); + remain_len = (SZ_16M * (nor->bank_curr + 1)) - addr; + + if (len < remain_len) + read_len = len; + else + read_len = remain_len; +#endif + + ret = nor->read(nor, addr, read_len, buf); + if (ret == 0) { + /* We shouldn't see 0-length reads */ + ret = -EIO; + goto read_err; + } + if (ret < 0) + goto read_err; + + *retlen += ret; + buf += ret; + from += ret; + len -= ret; + } + ret = 0; + +read_err: +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(nor); +#endif + return ret; +} + +#ifdef CONFIG_SPI_FLASH_SST +static int sst_write_byteprogram(struct spi_nor *nor, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + size_t actual; + int ret = 0; + + for (actual = 0; actual < len; actual++) { + nor->program_opcode = SPINOR_OP_BP; + + write_enable(nor); + /* write one byte. */ + ret = nor->write(nor, to, 1, buf + actual); + if (ret < 0) + goto sst_write_err; + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto sst_write_err; + to++; + } + +sst_write_err: + write_disable(nor); + return ret; +} + +static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + struct spi_slave *spi = nor->spi; + size_t actual; + int ret; + + dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); + if (spi->mode & SPI_TX_BYTE) + return sst_write_byteprogram(nor, to, len, retlen, buf); + + write_enable(nor); + + nor->sst_write_second = false; + + actual = to % 2; + /* Start write from odd address. */ + if (actual) { + nor->program_opcode = SPINOR_OP_BP; + + /* write one byte. */ + ret = nor->write(nor, to, 1, buf); + if (ret < 0) + goto sst_write_err; + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto sst_write_err; + } + to += actual; + + /* Write out most of the data here. */ + for (; actual < len - 1; actual += 2) { + nor->program_opcode = SPINOR_OP_AAI_WP; + + /* write two bytes. */ + ret = nor->write(nor, to, 2, buf + actual); + if (ret < 0) + goto sst_write_err; + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto sst_write_err; + to += 2; + nor->sst_write_second = true; + } + nor->sst_write_second = false; + + write_disable(nor); + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto sst_write_err; + + /* Write out trailing byte if it exists. */ + if (actual != len) { + write_enable(nor); + + nor->program_opcode = SPINOR_OP_BP; + ret = nor->write(nor, to, 1, buf + actual); + if (ret < 0) + goto sst_write_err; + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto sst_write_err; + write_disable(nor); + actual += 1; + } +sst_write_err: + *retlen += actual; + return ret; +} +#endif +/* + * Write an address range to the nor chip. Data must be written in + * FLASH_PAGESIZE chunks. The address range may be any size provided + * it is within the physical boundaries. + */ +static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + size_t page_offset, page_remain, i; + ssize_t ret; + + dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); + + for (i = 0; i < len; ) { + ssize_t written; + loff_t addr = to + i; + + /* + * If page_size is a power of two, the offset can be quickly + * calculated with an AND operation. On the other cases we + * need to do a modulus operation (more expensive). + * Power of two numbers have only one bit set and we can use + * the instruction hweight32 to detect if we need to do a + * modulus (do_div()) or not. + */ + if (hweight32(nor->page_size) == 1) { + page_offset = addr & (nor->page_size - 1); + } else { + u64 aux = addr; + + page_offset = do_div(aux, nor->page_size); + } + /* the size of data remaining on the first page */ + page_remain = min_t(size_t, + nor->page_size - page_offset, len - i); + +#ifdef CONFIG_SPI_FLASH_BAR + ret = write_bar(nor, addr); + if (ret < 0) + return ret; +#endif + write_enable(nor); + ret = nor->write(nor, addr, page_remain, buf + i); + if (ret < 0) + goto write_err; + written = ret; + + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto write_err; + *retlen += written; + i += written; + if (written != page_remain) { + ret = -EIO; + goto write_err; + } + } + +write_err: +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(nor); +#endif + return ret; +} + +#ifdef CONFIG_SPI_FLASH_MACRONIX +/** + * macronix_quad_enable() - set QE bit in Status Register. + * @nor: pointer to a 'struct spi_nor' + * + * Set the Quad Enable (QE) bit in the Status Register. + * + * bit 6 of the Status Register is the QE bit for Macronix like QSPI memories. + * + * Return: 0 on success, -errno otherwise. + */ +static int macronix_quad_enable(struct spi_nor *nor) +{ + int ret, val; + + val = read_sr(nor); + if (val < 0) + return val; + if (val & SR_QUAD_EN_MX) + return 0; + + write_enable(nor); + + write_sr(nor, val | SR_QUAD_EN_MX); + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + ret = read_sr(nor); + if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { + dev_err(nor->dev, "Macronix Quad bit not set\n"); + return -EINVAL; + } + + return 0; +} +#endif + +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) +/* + * Write status Register and configuration register with 2 bytes + * The first byte will be written to the status register, while the + * second byte will be written to the configuration register. + * Return negative if error occurred. + */ +static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr) +{ + int ret; + + write_enable(nor); + + ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); + if (ret < 0) { + dev_dbg(nor->dev, + "error while writing configuration register\n"); + return -EINVAL; + } + + ret = spi_nor_wait_till_ready(nor); + if (ret) { + dev_dbg(nor->dev, + "timeout while writing configuration register\n"); + return ret; + } + + return 0; +} + +/** + * spansion_read_cr_quad_enable() - set QE bit in Configuration Register. + * @nor: pointer to a 'struct spi_nor' + * + * Set the Quad Enable (QE) bit in the Configuration Register. + * This function should be used with QSPI memories supporting the Read + * Configuration Register (35h) instruction. + * + * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI + * memories. + * + * Return: 0 on success, -errno otherwise. + */ +static int spansion_read_cr_quad_enable(struct spi_nor *nor) +{ + u8 sr_cr[2]; + int ret; + + /* Check current Quad Enable bit value. */ + ret = read_cr(nor); + if (ret < 0) { + dev_dbg(dev, "error while reading configuration register\n"); + return -EINVAL; + } + + if (ret & CR_QUAD_EN_SPAN) + return 0; + + sr_cr[1] = ret | CR_QUAD_EN_SPAN; + + /* Keep the current value of the Status Register. */ + ret = read_sr(nor); + if (ret < 0) { + dev_dbg(dev, "error while reading status register\n"); + return -EINVAL; + } + sr_cr[0] = ret; + + ret = write_sr_cr(nor, sr_cr); + if (ret) + return ret; + + /* Read back and check it. */ + ret = read_cr(nor); + if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { + dev_dbg(nor->dev, "Spansion Quad bit not set\n"); + return -EINVAL; + } + + return 0; +} + +#if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) +/** + * spansion_no_read_cr_quad_enable() - set QE bit in Configuration Register. + * @nor: pointer to a 'struct spi_nor' + * + * Set the Quad Enable (QE) bit in the Configuration Register. + * This function should be used with QSPI memories not supporting the Read + * Configuration Register (35h) instruction. + * + * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI + * memories. + * + * Return: 0 on success, -errno otherwise. + */ +static int spansion_no_read_cr_quad_enable(struct spi_nor *nor) +{ + u8 sr_cr[2]; + int ret; + + /* Keep the current value of the Status Register. */ + ret = read_sr(nor); + if (ret < 0) { + dev_dbg(nor->dev, "error while reading status register\n"); + return -EINVAL; + } + sr_cr[0] = ret; + sr_cr[1] = CR_QUAD_EN_SPAN; + + return write_sr_cr(nor, sr_cr); +} + +#endif /* CONFIG_SPI_FLASH_SFDP_SUPPORT */ +#endif /* CONFIG_SPI_FLASH_SPANSION */ + +struct spi_nor_read_command { + u8 num_mode_clocks; + u8 num_wait_states; + u8 opcode; + enum spi_nor_protocol proto; +}; + +struct spi_nor_pp_command { + u8 opcode; + enum spi_nor_protocol proto; +}; + +enum spi_nor_read_command_index { + SNOR_CMD_READ, + SNOR_CMD_READ_FAST, + SNOR_CMD_READ_1_1_1_DTR, + + /* Dual SPI */ + SNOR_CMD_READ_1_1_2, + SNOR_CMD_READ_1_2_2, + SNOR_CMD_READ_2_2_2, + SNOR_CMD_READ_1_2_2_DTR, + + /* Quad SPI */ + SNOR_CMD_READ_1_1_4, + SNOR_CMD_READ_1_4_4, + SNOR_CMD_READ_4_4_4, + SNOR_CMD_READ_1_4_4_DTR, + + /* Octo SPI */ + SNOR_CMD_READ_1_1_8, + SNOR_CMD_READ_1_8_8, + SNOR_CMD_READ_8_8_8, + SNOR_CMD_READ_1_8_8_DTR, + + SNOR_CMD_READ_MAX +}; + +enum spi_nor_pp_command_index { + SNOR_CMD_PP, + + /* Quad SPI */ + SNOR_CMD_PP_1_1_4, + SNOR_CMD_PP_1_4_4, + SNOR_CMD_PP_4_4_4, + + /* Octo SPI */ + SNOR_CMD_PP_1_1_8, + SNOR_CMD_PP_1_8_8, + SNOR_CMD_PP_8_8_8, + + SNOR_CMD_PP_MAX +}; + +struct spi_nor_flash_parameter { + u64 size; + u32 page_size; + + struct spi_nor_hwcaps hwcaps; + struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; + struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; + + int (*quad_enable)(struct spi_nor *nor); +}; + +static void +spi_nor_set_read_settings(struct spi_nor_read_command *read, + u8 num_mode_clocks, + u8 num_wait_states, + u8 opcode, + enum spi_nor_protocol proto) +{ + read->num_mode_clocks = num_mode_clocks; + read->num_wait_states = num_wait_states; + read->opcode = opcode; + read->proto = proto; +} + +static void +spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, + u8 opcode, + enum spi_nor_protocol proto) +{ + pp->opcode = opcode; + pp->proto = proto; +} + +#if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) +/* + * Serial Flash Discoverable Parameters (SFDP) parsing. + */ + +/** + * spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters. + * @nor: pointer to a 'struct spi_nor' + * @addr: offset in the SFDP area to start reading data from + * @len: number of bytes to read + * @buf: buffer where the SFDP data are copied into (dma-safe memory) + * + * Whatever the actual numbers of bytes for address and dummy cycles are + * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always + * followed by a 3-byte address and 8 dummy clock cycles. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr, + size_t len, void *buf) +{ + u8 addr_width, read_opcode, read_dummy; + int ret; + + read_opcode = nor->read_opcode; + addr_width = nor->addr_width; + read_dummy = nor->read_dummy; + + nor->read_opcode = SPINOR_OP_RDSFDP; + nor->addr_width = 3; + nor->read_dummy = 8; + + while (len) { + ret = nor->read(nor, addr, len, (u8 *)buf); + if (!ret || ret > len) { + ret = -EIO; + goto read_err; + } + if (ret < 0) + goto read_err; + + buf += ret; + addr += ret; + len -= ret; + } + ret = 0; + +read_err: + nor->read_opcode = read_opcode; + nor->addr_width = addr_width; + nor->read_dummy = read_dummy; + + return ret; +} + +struct sfdp_parameter_header { + u8 id_lsb; + u8 minor; + u8 major; + u8 length; /* in double words */ + u8 parameter_table_pointer[3]; /* byte address */ + u8 id_msb; +}; + +#define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb) +#define SFDP_PARAM_HEADER_PTP(p) \ + (((p)->parameter_table_pointer[2] << 16) | \ + ((p)->parameter_table_pointer[1] << 8) | \ + ((p)->parameter_table_pointer[0] << 0)) + +#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ +#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ + +#define SFDP_SIGNATURE 0x50444653U +#define SFDP_JESD216_MAJOR 1 +#define SFDP_JESD216_MINOR 0 +#define SFDP_JESD216A_MINOR 5 +#define SFDP_JESD216B_MINOR 6 + +struct sfdp_header { + u32 signature; /* Ox50444653U <=> "SFDP" */ + u8 minor; + u8 major; + u8 nph; /* 0-base number of parameter headers */ + u8 unused; + + /* Basic Flash Parameter Table. */ + struct sfdp_parameter_header bfpt_header; +}; + +/* Basic Flash Parameter Table */ + +/* + * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs. + * They are indexed from 1 but C arrays are indexed from 0. + */ +#define BFPT_DWORD(i) ((i) - 1) +#define BFPT_DWORD_MAX 16 + +/* The first version of JESB216 defined only 9 DWORDs. */ +#define BFPT_DWORD_MAX_JESD216 9 + +/* 1st DWORD. */ +#define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16) +#define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17) +#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17) +#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17) +#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17) +#define BFPT_DWORD1_DTR BIT(19) +#define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20) +#define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21) +#define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22) + +/* 5th DWORD. */ +#define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0) +#define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4) + +/* 11th DWORD. */ +#define BFPT_DWORD11_PAGE_SIZE_SHIFT 4 +#define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4) + +/* 15th DWORD. */ + +/* + * (from JESD216 rev B) + * Quad Enable Requirements (QER): + * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4 + * reads based on instruction. DQ3/HOLD# functions are hold during + * instruction phase. + * - 001b: QE is bit 1 of status register 2. It is set via Write Status with + * two data bytes where bit 1 of the second byte is one. + * [...] + * Writing only one byte to the status register has the side-effect of + * clearing status register 2, including the QE bit. The 100b code is + * used if writing one byte to the status register does not modify + * status register 2. + * - 010b: QE is bit 6 of status register 1. It is set via Write Status with + * one data byte where bit 6 is one. + * [...] + * - 011b: QE is bit 7 of status register 2. It is set via Write status + * register 2 instruction 3Eh with one data byte where bit 7 is one. + * [...] + * The status register 2 is read using instruction 3Fh. + * - 100b: QE is bit 1 of status register 2. It is set via Write Status with + * two data bytes where bit 1 of the second byte is one. + * [...] + * In contrast to the 001b code, writing one byte to the status + * register does not modify status register 2. + * - 101b: QE is bit 1 of status register 2. Status register 1 is read using + * Read Status instruction 05h. Status register2 is read using + * instruction 35h. QE is set via Writ Status instruction 01h with + * two data bytes where bit 1 of the second byte is one. + * [...] + */ +#define BFPT_DWORD15_QER_MASK GENMASK(22, 20) +#define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */ +#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20) +#define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */ +#define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20) +#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) +#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */ + +struct sfdp_bfpt { + u32 dwords[BFPT_DWORD_MAX]; +}; + +/* Fast Read settings. */ + +static void +spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read, + u16 half, + enum spi_nor_protocol proto) +{ + read->num_mode_clocks = (half >> 5) & 0x07; + read->num_wait_states = (half >> 0) & 0x1f; + read->opcode = (half >> 8) & 0xff; + read->proto = proto; +} + +struct sfdp_bfpt_read { + /* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */ + u32 hwcaps; + + /* + * The bit in BFPT DWORD tells us + * whether the Fast Read x-y-z command is supported. + */ + u32 supported_dword; + u32 supported_bit; + + /* + * The half-word at offset in BFPT DWORD + * encodes the op code, the number of mode clocks and the number of wait + * states to be used by Fast Read x-y-z command. + */ + u32 settings_dword; + u32 settings_shift; + + /* The SPI protocol for this Fast Read x-y-z command. */ + enum spi_nor_protocol proto; +}; + +static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = { + /* Fast Read 1-1-2 */ + { + SNOR_HWCAPS_READ_1_1_2, + BFPT_DWORD(1), BIT(16), /* Supported bit */ + BFPT_DWORD(4), 0, /* Settings */ + SNOR_PROTO_1_1_2, + }, + + /* Fast Read 1-2-2 */ + { + SNOR_HWCAPS_READ_1_2_2, + BFPT_DWORD(1), BIT(20), /* Supported bit */ + BFPT_DWORD(4), 16, /* Settings */ + SNOR_PROTO_1_2_2, + }, + + /* Fast Read 2-2-2 */ + { + SNOR_HWCAPS_READ_2_2_2, + BFPT_DWORD(5), BIT(0), /* Supported bit */ + BFPT_DWORD(6), 16, /* Settings */ + SNOR_PROTO_2_2_2, + }, + + /* Fast Read 1-1-4 */ + { + SNOR_HWCAPS_READ_1_1_4, + BFPT_DWORD(1), BIT(22), /* Supported bit */ + BFPT_DWORD(3), 16, /* Settings */ + SNOR_PROTO_1_1_4, + }, + + /* Fast Read 1-4-4 */ + { + SNOR_HWCAPS_READ_1_4_4, + BFPT_DWORD(1), BIT(21), /* Supported bit */ + BFPT_DWORD(3), 0, /* Settings */ + SNOR_PROTO_1_4_4, + }, + + /* Fast Read 4-4-4 */ + { + SNOR_HWCAPS_READ_4_4_4, + BFPT_DWORD(5), BIT(4), /* Supported bit */ + BFPT_DWORD(7), 16, /* Settings */ + SNOR_PROTO_4_4_4, + }, +}; + +struct sfdp_bfpt_erase { + /* + * The half-word at offset in DWORD encodes the + * op code and erase sector size to be used by Sector Erase commands. + */ + u32 dword; + u32 shift; +}; + +static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = { + /* Erase Type 1 in DWORD8 bits[15:0] */ + {BFPT_DWORD(8), 0}, + + /* Erase Type 2 in DWORD8 bits[31:16] */ + {BFPT_DWORD(8), 16}, + + /* Erase Type 3 in DWORD9 bits[15:0] */ + {BFPT_DWORD(9), 0}, + + /* Erase Type 4 in DWORD9 bits[31:16] */ + {BFPT_DWORD(9), 16}, +}; + +static int spi_nor_hwcaps_read2cmd(u32 hwcaps); + +/** + * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table. + * @nor: pointer to a 'struct spi_nor' + * @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing + * the Basic Flash Parameter Table length and version + * @params: pointer to the 'struct spi_nor_flash_parameter' to be + * filled + * + * The Basic Flash Parameter Table is the main and only mandatory table as + * defined by the SFDP (JESD216) specification. + * It provides us with the total size (memory density) of the data array and + * the number of address bytes for Fast Read, Page Program and Sector Erase + * commands. + * For Fast READ commands, it also gives the number of mode clock cycles and + * wait states (regrouped in the number of dummy clock cycles) for each + * supported instruction op code. + * For Page Program, the page size is now available since JESD216 rev A, however + * the supported instruction op codes are still not provided. + * For Sector Erase commands, this table stores the supported instruction op + * codes and the associated sector sizes. + * Finally, the Quad Enable Requirements (QER) are also available since JESD216 + * rev A. The QER bits encode the manufacturer dependent procedure to be + * executed to set the Quad Enable (QE) bit in some internal register of the + * Quad SPI memory. Indeed the QE bit, when it exists, must be set before + * sending any Quad SPI command to the memory. Actually, setting the QE bit + * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2 + * and IO3 hence enabling 4 (Quad) I/O lines. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_bfpt(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + struct spi_nor_flash_parameter *params) +{ + struct mtd_info *mtd = &nor->mtd; + struct sfdp_bfpt bfpt; + size_t len; + int i, cmd, err; + u32 addr; + u16 half; + + /* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */ + if (bfpt_header->length < BFPT_DWORD_MAX_JESD216) + return -EINVAL; + + /* Read the Basic Flash Parameter Table. */ + len = min_t(size_t, sizeof(bfpt), + bfpt_header->length * sizeof(u32)); + addr = SFDP_PARAM_HEADER_PTP(bfpt_header); + memset(&bfpt, 0, sizeof(bfpt)); + err = spi_nor_read_sfdp(nor, addr, len, &bfpt); + if (err < 0) + return err; + + /* Fix endianness of the BFPT DWORDs. */ + for (i = 0; i < BFPT_DWORD_MAX; i++) + bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]); + + /* Number of address bytes. */ + switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { + case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: + nor->addr_width = 3; + break; + + case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: + nor->addr_width = 4; + break; + + default: + break; + } + + /* Flash Memory Density (in bits). */ + params->size = bfpt.dwords[BFPT_DWORD(2)]; + if (params->size & BIT(31)) { + params->size &= ~BIT(31); + + /* + * Prevent overflows on params->size. Anyway, a NOR of 2^64 + * bits is unlikely to exist so this error probably means + * the BFPT we are reading is corrupted/wrong. + */ + if (params->size > 63) + return -EINVAL; + + params->size = 1ULL << params->size; + } else { + params->size++; + } + params->size >>= 3; /* Convert to bytes. */ + + /* Fast Read settings. */ + for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) { + const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i]; + struct spi_nor_read_command *read; + + if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) { + params->hwcaps.mask &= ~rd->hwcaps; + continue; + } + + params->hwcaps.mask |= rd->hwcaps; + cmd = spi_nor_hwcaps_read2cmd(rd->hwcaps); + read = ¶ms->reads[cmd]; + half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift; + spi_nor_set_read_settings_from_bfpt(read, half, rd->proto); + } + + /* Sector Erase settings. */ + for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) { + const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i]; + u32 erasesize; + u8 opcode; + + half = bfpt.dwords[er->dword] >> er->shift; + erasesize = half & 0xff; + + /* erasesize == 0 means this Erase Type is not supported. */ + if (!erasesize) + continue; + + erasesize = 1U << erasesize; + opcode = (half >> 8) & 0xff; +#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + if (erasesize == SZ_4K) { + nor->erase_opcode = opcode; + mtd->erasesize = erasesize; + break; + } +#endif + if (!mtd->erasesize || mtd->erasesize < erasesize) { + nor->erase_opcode = opcode; + mtd->erasesize = erasesize; + } + } + + /* Stop here if not JESD216 rev A or later. */ + if (bfpt_header->length < BFPT_DWORD_MAX) + return 0; + + /* Page size: this field specifies 'N' so the page size = 2^N bytes. */ + params->page_size = bfpt.dwords[BFPT_DWORD(11)]; + params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK; + params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT; + params->page_size = 1U << params->page_size; + + /* Quad Enable Requirements. */ + switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) { + case BFPT_DWORD15_QER_NONE: + params->quad_enable = NULL; + break; +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + case BFPT_DWORD15_QER_SR2_BIT1_BUGGY: + case BFPT_DWORD15_QER_SR2_BIT1_NO_RD: + params->quad_enable = spansion_no_read_cr_quad_enable; + break; +#endif +#ifdef CONFIG_SPI_FLASH_MACRONIX + case BFPT_DWORD15_QER_SR1_BIT6: + params->quad_enable = macronix_quad_enable; + break; +#endif +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + case BFPT_DWORD15_QER_SR2_BIT1: + params->quad_enable = spansion_read_cr_quad_enable; + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +/** + * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. + * @nor: pointer to a 'struct spi_nor' + * @params: pointer to the 'struct spi_nor_flash_parameter' to be + * filled + * + * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216 + * specification. This is a standard which tends to supported by almost all + * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at + * runtime the main parameters needed to perform basic SPI flash operations such + * as Fast Read, Page Program or Sector Erase commands. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_sfdp(struct spi_nor *nor, + struct spi_nor_flash_parameter *params) +{ + const struct sfdp_parameter_header *param_header, *bfpt_header; + struct sfdp_parameter_header *param_headers = NULL; + struct sfdp_header header; + size_t psize; + int i, err; + + /* Get the SFDP header. */ + err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header); + if (err < 0) + return err; + + /* Check the SFDP header version. */ + if (le32_to_cpu(header.signature) != SFDP_SIGNATURE || + header.major != SFDP_JESD216_MAJOR) + return -EINVAL; + + /* + * Verify that the first and only mandatory parameter header is a + * Basic Flash Parameter Table header as specified in JESD216. + */ + bfpt_header = &header.bfpt_header; + if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID || + bfpt_header->major != SFDP_JESD216_MAJOR) + return -EINVAL; + + /* + * Allocate memory then read all parameter headers with a single + * Read SFDP command. These parameter headers will actually be parsed + * twice: a first time to get the latest revision of the basic flash + * parameter table, then a second time to handle the supported optional + * tables. + * Hence we read the parameter headers once for all to reduce the + * processing time. Also we use kmalloc() instead of devm_kmalloc() + * because we don't need to keep these parameter headers: the allocated + * memory is always released with kfree() before exiting this function. + */ + if (header.nph) { + psize = header.nph * sizeof(*param_headers); + + param_headers = kmalloc(psize, GFP_KERNEL); + if (!param_headers) + return -ENOMEM; + + err = spi_nor_read_sfdp(nor, sizeof(header), + psize, param_headers); + if (err < 0) { + dev_err(dev, "failed to read SFDP parameter headers\n"); + goto exit; + } + } + + /* + * Check other parameter headers to get the latest revision of + * the basic flash parameter table. + */ + for (i = 0; i < header.nph; i++) { + param_header = ¶m_headers[i]; + + if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID && + param_header->major == SFDP_JESD216_MAJOR && + (param_header->minor > bfpt_header->minor || + (param_header->minor == bfpt_header->minor && + param_header->length > bfpt_header->length))) + bfpt_header = param_header; + } + + err = spi_nor_parse_bfpt(nor, bfpt_header, params); + if (err) + goto exit; + + /* Parse other parameter headers. */ + for (i = 0; i < header.nph; i++) { + param_header = ¶m_headers[i]; + + switch (SFDP_PARAM_HEADER_ID(param_header)) { + case SFDP_SECTOR_MAP_ID: + dev_info(dev, "non-uniform erase sector maps are not supported yet.\n"); + break; + + default: + break; + } + + if (err) + goto exit; + } + +exit: + kfree(param_headers); + return err; +} +#else +static int spi_nor_parse_sfdp(struct spi_nor *nor, + struct spi_nor_flash_parameter *params) +{ + return -EINVAL; +} +#endif /* SPI_FLASH_SFDP_SUPPORT */ + +static int spi_nor_init_params(struct spi_nor *nor, + const struct flash_info *info, + struct spi_nor_flash_parameter *params) +{ + /* Set legacy flash parameters as default. */ + memset(params, 0, sizeof(*params)); + + /* Set SPI NOR sizes. */ + params->size = info->sector_size * info->n_sectors; + params->page_size = info->page_size; + + /* (Fast) Read settings. */ + params->hwcaps.mask |= SNOR_HWCAPS_READ; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ], + 0, 0, SPINOR_OP_READ, + SNOR_PROTO_1_1_1); + + if (!(info->flags & SPI_NOR_NO_FR)) { + params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_FAST], + 0, 8, SPINOR_OP_READ_FAST, + SNOR_PROTO_1_1_1); + } + + if (info->flags & SPI_NOR_DUAL_READ) { + params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_2], + 0, 8, SPINOR_OP_READ_1_1_2, + SNOR_PROTO_1_1_2); + } + + if (info->flags & SPI_NOR_QUAD_READ) { + params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4], + 0, 8, SPINOR_OP_READ_1_1_4, + SNOR_PROTO_1_1_4); + } + + /* Page Program settings. */ + params->hwcaps.mask |= SNOR_HWCAPS_PP; + spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], + SPINOR_OP_PP, SNOR_PROTO_1_1_1); + + if (info->flags & SPI_NOR_QUAD_READ) { + params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4; + spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4], + SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4); + } + + /* Select the procedure to set the Quad Enable bit. */ + if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD | + SNOR_HWCAPS_PP_QUAD)) { + switch (JEDEC_MFR(info)) { +#ifdef CONFIG_SPI_FLASH_MACRONIX + case SNOR_MFR_MACRONIX: + params->quad_enable = macronix_quad_enable; + break; +#endif + case SNOR_MFR_ST: + case SNOR_MFR_MICRON: + break; + + default: +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + /* Kept only for backward compatibility purpose. */ + params->quad_enable = spansion_read_cr_quad_enable; +#endif + break; + } + } + + /* Override the parameters with data read from SFDP tables. */ + nor->addr_width = 0; + nor->mtd.erasesize = 0; + if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && + !(info->flags & SPI_NOR_SKIP_SFDP)) { + struct spi_nor_flash_parameter sfdp_params; + + memcpy(&sfdp_params, params, sizeof(sfdp_params)); + if (spi_nor_parse_sfdp(nor, &sfdp_params)) { + nor->addr_width = 0; + nor->mtd.erasesize = 0; + } else { + memcpy(params, &sfdp_params, sizeof(*params)); + } + } + + return 0; +} + +static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + if (table[i][0] == (int)hwcaps) + return table[i][1]; + + return -EINVAL; +} + +static int spi_nor_hwcaps_read2cmd(u32 hwcaps) +{ + static const int hwcaps_read2cmd[][2] = { + { SNOR_HWCAPS_READ, SNOR_CMD_READ }, + { SNOR_HWCAPS_READ_FAST, SNOR_CMD_READ_FAST }, + { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR }, + { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 }, + { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 }, + { SNOR_HWCAPS_READ_2_2_2, SNOR_CMD_READ_2_2_2 }, + { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR }, + { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 }, + { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 }, + { SNOR_HWCAPS_READ_4_4_4, SNOR_CMD_READ_4_4_4 }, + { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR }, + { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 }, + { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, + { SNOR_HWCAPS_READ_8_8_8, SNOR_CMD_READ_8_8_8 }, + { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, + }; + + return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, + ARRAY_SIZE(hwcaps_read2cmd)); +} + +static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) +{ + static const int hwcaps_pp2cmd[][2] = { + { SNOR_HWCAPS_PP, SNOR_CMD_PP }, + { SNOR_HWCAPS_PP_1_1_4, SNOR_CMD_PP_1_1_4 }, + { SNOR_HWCAPS_PP_1_4_4, SNOR_CMD_PP_1_4_4 }, + { SNOR_HWCAPS_PP_4_4_4, SNOR_CMD_PP_4_4_4 }, + { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 }, + { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 }, + { SNOR_HWCAPS_PP_8_8_8, SNOR_CMD_PP_8_8_8 }, + }; + + return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, + ARRAY_SIZE(hwcaps_pp2cmd)); +} + +static int spi_nor_select_read(struct spi_nor *nor, + const struct spi_nor_flash_parameter *params, + u32 shared_hwcaps) +{ + int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1; + const struct spi_nor_read_command *read; + + if (best_match < 0) + return -EINVAL; + + cmd = spi_nor_hwcaps_read2cmd(BIT(best_match)); + if (cmd < 0) + return -EINVAL; + + read = ¶ms->reads[cmd]; + nor->read_opcode = read->opcode; + nor->read_proto = read->proto; + + /* + * In the spi-nor framework, we don't need to make the difference + * between mode clock cycles and wait state clock cycles. + * Indeed, the value of the mode clock cycles is used by a QSPI + * flash memory to know whether it should enter or leave its 0-4-4 + * (Continuous Read / XIP) mode. + * eXecution In Place is out of the scope of the mtd sub-system. + * Hence we choose to merge both mode and wait state clock cycles + * into the so called dummy clock cycles. + */ + nor->read_dummy = read->num_mode_clocks + read->num_wait_states; + return 0; +} + +static int spi_nor_select_pp(struct spi_nor *nor, + const struct spi_nor_flash_parameter *params, + u32 shared_hwcaps) +{ + int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1; + const struct spi_nor_pp_command *pp; + + if (best_match < 0) + return -EINVAL; + + cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match)); + if (cmd < 0) + return -EINVAL; + + pp = ¶ms->page_programs[cmd]; + nor->program_opcode = pp->opcode; + nor->write_proto = pp->proto; + return 0; +} + +static int spi_nor_select_erase(struct spi_nor *nor, + const struct flash_info *info) +{ + struct mtd_info *mtd = &nor->mtd; + + /* Do nothing if already configured from SFDP. */ + if (mtd->erasesize) + return 0; + +#ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS + /* prefer "small sector" erase if possible */ + if (info->flags & SECT_4K) { + nor->erase_opcode = SPINOR_OP_BE_4K; + mtd->erasesize = 4096; + } else if (info->flags & SECT_4K_PMC) { + nor->erase_opcode = SPINOR_OP_BE_4K_PMC; + mtd->erasesize = 4096; + } else +#endif + { + nor->erase_opcode = SPINOR_OP_SE; + mtd->erasesize = info->sector_size; + } + return 0; +} + +static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, + const struct spi_nor_flash_parameter *params, + const struct spi_nor_hwcaps *hwcaps) +{ + u32 ignored_mask, shared_mask; + bool enable_quad_io; + int err; + + /* + * Keep only the hardware capabilities supported by both the SPI + * controller and the SPI flash memory. + */ + shared_mask = hwcaps->mask & params->hwcaps.mask; + + /* SPI n-n-n protocols are not supported yet. */ + ignored_mask = (SNOR_HWCAPS_READ_2_2_2 | + SNOR_HWCAPS_READ_4_4_4 | + SNOR_HWCAPS_READ_8_8_8 | + SNOR_HWCAPS_PP_4_4_4 | + SNOR_HWCAPS_PP_8_8_8); + if (shared_mask & ignored_mask) { + dev_dbg(nor->dev, + "SPI n-n-n protocols are not supported yet.\n"); + shared_mask &= ~ignored_mask; + } + + /* Select the (Fast) Read command. */ + err = spi_nor_select_read(nor, params, shared_mask); + if (err) { + dev_dbg(nor->dev, + "can't select read settings supported by both the SPI controller and memory.\n"); + return err; + } + + /* Select the Page Program command. */ + err = spi_nor_select_pp(nor, params, shared_mask); + if (err) { + dev_dbg(nor->dev, + "can't select write settings supported by both the SPI controller and memory.\n"); + return err; + } + + /* Select the Sector Erase command. */ + err = spi_nor_select_erase(nor, info); + if (err) { + dev_dbg(nor->dev, + "can't select erase settings supported by both the SPI controller and memory.\n"); + return err; + } + + /* Enable Quad I/O if needed. */ + enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 || + spi_nor_get_protocol_width(nor->write_proto) == 4); + if (enable_quad_io && params->quad_enable) + nor->quad_enable = params->quad_enable; + else + nor->quad_enable = NULL; + + return 0; +} + +static int spi_nor_init(struct spi_nor *nor) +{ + int err; + + /* + * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up + * with the software protection bits set + */ + if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || + JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || + JEDEC_MFR(nor->info) == SNOR_MFR_SST || + nor->info->flags & SPI_NOR_HAS_LOCK) { + write_enable(nor); + write_sr(nor, 0); + spi_nor_wait_till_ready(nor); + } + + if (nor->quad_enable) { + err = nor->quad_enable(nor); + if (err) { + dev_dbg(nor->dev, "quad mode not supported\n"); + return err; + } + } + + if (nor->addr_width == 4 && + (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && + !(nor->info->flags & SPI_NOR_4B_OPCODES)) { + /* + * If the RESET# pin isn't hooked up properly, or the system + * otherwise doesn't perform a reset command in the boot + * sequence, it's impossible to 100% protect against unexpected + * reboots (e.g., crashes). Warn the user (or hopefully, system + * designer) that this is bad. + */ + if (nor->flags & SNOR_F_BROKEN_RESET) + printf("enabling reset hack; may not recover from unexpected reboots\n"); + set_4byte(nor, nor->info, 1); + } + + return 0; +} + +int spi_nor_scan(struct spi_nor *nor) +{ + struct spi_nor_flash_parameter params; + const struct flash_info *info = NULL; + struct mtd_info *mtd = &nor->mtd; + struct spi_nor_hwcaps hwcaps = { + .mask = SNOR_HWCAPS_READ | + SNOR_HWCAPS_READ_FAST | + SNOR_HWCAPS_PP, + }; + struct spi_slave *spi = nor->spi; + int ret; + + /* Reset SPI protocol for all commands. */ + nor->reg_proto = SNOR_PROTO_1_1_1; + nor->read_proto = SNOR_PROTO_1_1_1; + nor->write_proto = SNOR_PROTO_1_1_1; + nor->read = spi_nor_read_data; + nor->write = spi_nor_write_data; + nor->read_reg = spi_nor_read_reg; + nor->write_reg = spi_nor_write_reg; + + if (spi->mode & SPI_RX_QUAD) { + hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; + + if (spi->mode & SPI_TX_QUAD) + hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 | + SNOR_HWCAPS_PP_1_1_4 | + SNOR_HWCAPS_PP_1_4_4); + } else if (spi->mode & SPI_RX_DUAL) { + hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; + + if (spi->mode & SPI_TX_DUAL) + hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2; + } + + info = spi_nor_read_id(nor); + if (IS_ERR_OR_NULL(info)) + return -ENOENT; + /* Parse the Serial Flash Discoverable Parameters table. */ + ret = spi_nor_init_params(nor, info, ¶ms); + if (ret) + return ret; + + if (!mtd->name) + mtd->name = info->name; + mtd->priv = nor; + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; + mtd->size = params.size; + mtd->_erase = spi_nor_erase; + mtd->_read = spi_nor_read; + +#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) + /* NOR protection support for STmicro/Micron chips and similar */ + if (JEDEC_MFR(info) == SNOR_MFR_ST || + JEDEC_MFR(info) == SNOR_MFR_MICRON || + JEDEC_MFR(info) == SNOR_MFR_SST || + info->flags & SPI_NOR_HAS_LOCK) { + nor->flash_lock = stm_lock; + nor->flash_unlock = stm_unlock; + nor->flash_is_locked = stm_is_locked; + } +#endif + +#ifdef CONFIG_SPI_FLASH_SST + /* sst nor chips use AAI word program */ + if (info->flags & SST_WRITE) + mtd->_write = sst_write; + else +#endif + mtd->_write = spi_nor_write; + + if (info->flags & USE_FSR) + nor->flags |= SNOR_F_USE_FSR; + if (info->flags & SPI_NOR_HAS_TB) + nor->flags |= SNOR_F_HAS_SR_TB; + if (info->flags & NO_CHIP_ERASE) + nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; + if (info->flags & USE_CLSR) + nor->flags |= SNOR_F_USE_CLSR; + + if (info->flags & SPI_NOR_NO_ERASE) + mtd->flags |= MTD_NO_ERASE; + + nor->page_size = params.page_size; + mtd->writebufsize = nor->page_size; + + /* Some devices cannot do fast-read, no matter what DT tells us */ + if ((info->flags & SPI_NOR_NO_FR) || (spi->mode & SPI_RX_SLOW)) + params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST; + + /* + * Configure the SPI memory: + * - select op codes for (Fast) Read, Page Program and Sector Erase. + * - set the number of dummy cycles (mode cycles + wait states). + * - set the SPI protocols for register and memory accesses. + * - set the Quad Enable bit if needed (required by SPI x-y-4 protos). + */ + ret = spi_nor_setup(nor, info, ¶ms, &hwcaps); + if (ret) + return ret; + + if (nor->addr_width) { + /* already configured from SFDP */ + } else if (info->addr_width) { + nor->addr_width = info->addr_width; + } else if (mtd->size > SZ_16M) { +#ifndef CONFIG_SPI_FLASH_BAR + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; + if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || + info->flags & SPI_NOR_4B_OPCODES) + spi_nor_set_4byte_opcodes(nor, info); +#else + /* Configure the BAR - discover bank cmds and read current bank */ + nor->addr_width = 3; + ret = read_bar(nor, info); + if (ret < 0) + return ret; +#endif + } else { + nor->addr_width = 3; + } + + if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { + dev_dbg(dev, "address width is too large: %u\n", + nor->addr_width); + return -EINVAL; + } + + /* Send all the required SPI flash commands to initialize device */ + nor->info = info; + ret = spi_nor_init(nor); + if (ret) + return ret; + + nor->name = mtd->name; + nor->size = mtd->size; + nor->erase_size = mtd->erasesize; + nor->sector_size = mtd->erasesize; + +#ifndef CONFIG_SPL_BUILD + printf("SF: Detected %s with page size ", nor->name); + print_size(nor->page_size, ", erase size "); + print_size(nor->erase_size, ", total "); + print_size(nor->size, ""); + puts("\n"); +#endif + + return 0; +} + +/* U-Boot specific functions, need to extend MTD to support these */ +int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor) +{ + int sr = read_sr(nor); + + if (sr < 0) + return sr; + + return (sr >> 2) & 7; +} diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c new file mode 100644 index 0000000000000000000000000000000000000000..3215e2431dc0dcc74a5223c324348d11d5507ecf --- /dev/null +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * + * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. + * Copyright (C) 2016 Jagan Teki + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include +#include +#include + +#include "sf_internal.h" + +/* Exclude chip names for SPL to save space */ +#if !CONFIG_IS_ENABLED(SPI_FLASH_TINY) +#define INFO_NAME(_name) .name = _name, +#else +#define INFO_NAME(_name) +#endif + +/* Used when the "_ext_id" is two bytes at most */ +#define INFO(_name, _jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + INFO_NAME(_name) \ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 8) & 0xff, \ + (_ext_id) & 0xff, \ + }, \ + .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), + +#define INFO6(_name, _jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + INFO_NAME(_name) \ + .id = { \ + ((_jedec_id) >> 16) & 0xff, \ + ((_jedec_id) >> 8) & 0xff, \ + (_jedec_id) & 0xff, \ + ((_ext_id) >> 16) & 0xff, \ + ((_ext_id) >> 8) & 0xff, \ + (_ext_id) & 0xff, \ + }, \ + .id_len = 6, \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), + +/* NOTE: double check command sets and memory organization when you add + * more nor chips. This current list focusses on newer chips, which + * have been converging on command sets which including JEDEC ID. + * + * All newly added entries should describe *hardware* and should use SECT_4K + * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage + * scenarios excluding small sectors there is config option that can be + * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. + * For historical (and compatibility) reasons (before we got above config) some + * old entries may be missing 4K flag. + */ +const struct flash_info spi_nor_ids[] = { +#ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ + /* Atmel -- some are (confusingly) marketed as "DataFlash" */ + { INFO("at26df321", 0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, + { INFO("at25df321a", 0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, + + { INFO("at45db011d", 0x1f2200, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("at45db021d", 0x1f2300, 0, 64 * 1024, 8, SECT_4K) }, + { INFO("at45db041d", 0x1f2400, 0, 64 * 1024, 8, SECT_4K) }, + { INFO("at45db081d", 0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, + { INFO("at45db161d", 0x1f2600, 0, 64 * 1024, 32, SECT_4K) }, + { INFO("at45db321d", 0x1f2700, 0, 64 * 1024, 64, SECT_4K) }, + { INFO("at45db641d", 0x1f2800, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, +#endif +#ifdef CONFIG_SPI_FLASH_EON /* EON */ + /* EON -- en25xxx */ + { INFO("en25q32b", 0x1c3016, 0, 64 * 1024, 64, 0) }, + { INFO("en25q64", 0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("en25qh128", 0x1c7018, 0, 64 * 1024, 256, 0) }, + { INFO("en25s64", 0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, +#endif +#ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ + /* GigaDevice */ + { + INFO("gd25q16", 0xc84015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("gd25q32", 0xc84016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("gd25lq32", 0xc86016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("gd25q64", 0xc84017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, +#endif +#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ + /* ISSI */ + { INFO("is25lq040b", 0x9d4013, 0, 64 * 1024, 8, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25lp032", 0x9d6016, 0, 64 * 1024, 64, 0) }, + { INFO("is25lp064", 0x9d6017, 0, 64 * 1024, 128, 0) }, + { INFO("is25lp128", 0x9d6018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ) }, + { INFO("is25lp256", 0x9d6019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ) }, + { INFO("is25wp032", 0x9d7016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wp064", 0x9d7017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wp128", 0x9d7018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif +#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ + /* Macronix */ + { INFO("mx25l2005a", 0xc22012, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("mx25l4005a", 0xc22013, 0, 64 * 1024, 8, SECT_4K) }, + { INFO("mx25l8005", 0xc22014, 0, 64 * 1024, 16, 0) }, + { INFO("mx25l1606e", 0xc22015, 0, 64 * 1024, 32, SECT_4K) }, + { INFO("mx25l3205d", 0xc22016, 0, 64 * 1024, 64, SECT_4K) }, + { INFO("mx25l6405d", 0xc22017, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("mx25u2033e", 0xc22532, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("mx25u1635e", 0xc22535, 0, 64 * 1024, 32, SECT_4K) }, + { INFO("mx25u6435f", 0xc22537, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("mx25l12805d", 0xc22018, 0, 64 * 1024, 256, 0) }, + { INFO("mx25l12855e", 0xc22618, 0, 64 * 1024, 256, 0) }, + { INFO("mx25l25635e", 0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("mx25u25635f", 0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, + { INFO("mx25l25655e", 0xc22619, 0, 64 * 1024, 512, 0) }, + { INFO("mx66l51235l", 0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66u51235f", 0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66l1g45g", 0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, +#endif + +#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ + /* Micron */ + { INFO("n25q016a", 0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) }, + { INFO("n25q032", 0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, + { INFO("n25q032a", 0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, + { INFO("n25q064", 0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, + { INFO("n25q064a", 0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, + { INFO("n25q128a11", 0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, + { INFO("n25q128a13", 0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, + { INFO("n25q256a", 0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("n25q256ax1", 0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("n25q512a", 0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("n25q512ax3", 0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("n25q00", 0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, + { INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, + { INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, +#endif +#ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ + /* Spansion/Cypress -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ + { INFO("s25sl032p", 0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("s25sl064p", 0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("s25fl256s0", 0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, + { INFO("s25fl256s1", 0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO6("s25fl512s", 0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl512s_256k", 0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl512s_64k", 0x010220, 0x4d01, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl512s_512k", 0x010220, 0x4f00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, 0) }, + { INFO("s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, 0) }, + { INFO6("s25fl128s", 0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25sl008a", 0x010213, 0, 64 * 1024, 16, 0) }, + { INFO("s25sl016a", 0x010214, 0, 64 * 1024, 32, 0) }, + { INFO("s25sl032a", 0x010215, 0, 64 * 1024, 64, 0) }, + { INFO("s25sl064a", 0x010216, 0, 64 * 1024, 128, 0) }, + { INFO("s25fl116k", 0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("s25fl164k", 0x014017, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("s25fl208k", 0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) }, + { INFO("s25fl128l", 0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, +#endif +#ifdef CONFIG_SPI_FLASH_SST /* SST */ + /* SST -- large erase sizes are "overlays", "sectors" are 4K */ + { INFO("sst25vf040b", 0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, + { INFO("sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, + { INFO("sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, + { INFO("sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, + { INFO("sst25vf064c", 0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("sst25wf512", 0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, + { INFO("sst25wf010", 0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, + { INFO("sst25wf020", 0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, + { INFO("sst25wf020a", 0x621612, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("sst25wf040b", 0x621613, 0, 64 * 1024, 8, SECT_4K) }, + { INFO("sst25wf040", 0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, + { INFO("sst25wf080", 0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, + { INFO("sst26vf064b", 0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("sst26wf016", 0xbf2651, 0, 64 * 1024, 32, SECT_4K) }, + { INFO("sst26wf032", 0xbf2622, 0, 64 * 1024, 64, SECT_4K) }, + { INFO("sst26wf064", 0xbf2643, 0, 64 * 1024, 128, SECT_4K) }, +#endif +#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ + /* ST Microelectronics -- newer production may have feature updates */ + { INFO("m25p10", 0x202011, 0, 32 * 1024, 4, 0) }, + { INFO("m25p20", 0x202012, 0, 64 * 1024, 4, 0) }, + { INFO("m25p40", 0x202013, 0, 64 * 1024, 8, 0) }, + { INFO("m25p80", 0x202014, 0, 64 * 1024, 16, 0) }, + { INFO("m25p16", 0x202015, 0, 64 * 1024, 32, 0) }, + { INFO("m25p32", 0x202016, 0, 64 * 1024, 64, 0) }, + { INFO("m25p64", 0x202017, 0, 64 * 1024, 128, 0) }, + { INFO("m25p128", 0x202018, 0, 256 * 1024, 64, 0) }, + { INFO("m25pe16", 0x208015, 0, 64 * 1024, 32, SECT_4K) }, + { INFO("m25px16", 0x207115, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("m25px64", 0x207117, 0, 64 * 1024, 128, 0) }, +#endif +#ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ + { INFO("w25p80", 0xef2014, 0x0, 64 * 1024, 16, 0) }, + { INFO("w25p16", 0xef2015, 0x0, 64 * 1024, 32, 0) }, + { INFO("w25p32", 0xef2016, 0x0, 64 * 1024, 64, 0) }, + { INFO("w25x05", 0xef3010, 0, 64 * 1024, 1, SECT_4K) }, + { INFO("w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K) }, + { INFO("w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K) }, + { + INFO("w25q16dw", 0xef6015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { INFO("w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K) }, + { INFO("w25q20cl", 0xef4012, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("w25q20bw", 0xef5012, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("w25q20ew", 0xef6012, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("w25q32", 0xef4016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { + INFO("w25q32dw", 0xef6016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q32jv", 0xef7016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { INFO("w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K) }, + { + INFO("w25q64dw", 0xef6017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q64jv", 0xef7017, 0, 64 * 1024, 128, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q128fw", 0xef6018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q128jv", 0xef7018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q256fw", 0xef6019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q256jw", 0xef7019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { INFO("w25q80", 0xef5014, 0, 64 * 1024, 16, SECT_4K) }, + { INFO("w25q80bl", 0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q16cl", 0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q64cv", 0xef4017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q128", 0xef4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q256", 0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif +#ifdef CONFIG_SPI_FLASH_XMC + /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ + { INFO("XM25QH64A", 0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif + { }, +}; diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c new file mode 100644 index 0000000000000000000000000000000000000000..c19d468d62cfa8f00a7496aff72dd72f574e4d83 --- /dev/null +++ b/drivers/mtd/spi/spi-nor-tiny.c @@ -0,0 +1,804 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with + * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c + * + * Copyright (C) 2005, Intec Automation Inc. + * Copyright (C) 2014, Freescale Semiconductor, Inc. + * + * Synced from Linux v4.19 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sf_internal.h" + +/* Define max times to check status register before we give up. */ + +/* + * For everything but full-chip erase; probably could be much smaller, but kept + * around for safety for now + */ + +#define HZ CONFIG_SYS_HZ + +#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) + +static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op + *op, void *buf) +{ + if (op->data.dir == SPI_MEM_DATA_IN) + op->data.buf.in = buf; + else + op->data.buf.out = buf; + return spi_mem_exec_op(nor->spi, op); +} + +static int spi_nor_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(len, NULL, 1)); + int ret; + + ret = spi_nor_read_write_reg(nor, &op, val); + if (ret < 0) + dev_dbg(&flash->spimem->spi->dev, "error %d reading %x\n", ret, + code); + + return ret; +} + +static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(len, NULL, 1)); + + return spi_nor_read_write_reg(nor, &op, buf); +} + +static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, + u_char *buf) +{ + struct spi_mem_op op = + SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, from, 1), + SPI_MEM_OP_DUMMY(nor->read_dummy, 1), + SPI_MEM_OP_DATA_IN(len, buf, 1)); + size_t remaining = len; + int ret; + + /* get transfer protocols. */ + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); + op.dummy.buswidth = op.addr.buswidth; + op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); + + /* convert the dummy cycles to the number of bytes */ + op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + + while (remaining) { + op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; + ret = spi_mem_adjust_op_size(nor->spi, &op); + if (ret) + return ret; + + ret = spi_mem_exec_op(nor->spi, &op); + if (ret) + return ret; + + op.addr.val += op.data.nbytes; + remaining -= op.data.nbytes; + op.data.buf.in += op.data.nbytes; + } + + return len; +} + +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) +/* + * Read configuration register, returning its value in the + * location. Return the configuration register value. + * Returns negative if error occurred. + */ +static int read_cr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = spi_nor_read_reg(nor, SPINOR_OP_RDCR, &val, 1); + if (ret < 0) { + dev_dbg(nor->dev, "error %d reading CR\n", ret); + return ret; + } + + return val; +} +#endif + +/* + * Write status register 1 byte + * Returns negative if error occurred. + */ +static inline int write_sr(struct spi_nor *nor, u8 val) +{ + nor->cmd_buf[0] = val; + return spi_nor_write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); +} + +/* + * Set write enable latch with Write Enable command. + * Returns negative if error occurred. + */ +static inline int write_enable(struct spi_nor *nor) +{ + return spi_nor_write_reg(nor, SPINOR_OP_WREN, NULL, 0); +} + +/* + * Send write disable instruction to the chip. + */ +static inline int write_disable(struct spi_nor *nor) +{ + return spi_nor_write_reg(nor, SPINOR_OP_WRDI, NULL, 0); +} + +static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) +{ + return mtd->priv; +} + +static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + if (table[i][0] == opcode) + return table[i][1]; + + /* No conversion found, keep input op code. */ + return opcode; +} + +static inline u8 spi_nor_convert_3to4_read(u8 opcode) +{ + static const u8 spi_nor_3to4_read[][2] = { + { SPINOR_OP_READ, SPINOR_OP_READ_4B }, + { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B }, + { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B }, + { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, + { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, + { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, + }; + + return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, + ARRAY_SIZE(spi_nor_3to4_read)); +} + +static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, + const struct flash_info *info) +{ + nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); +} + +/* Enable/disable 4-byte addressing mode. */ +static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, + int enable) +{ + int status; + bool need_wren = false; + u8 cmd; + + switch (JEDEC_MFR(info)) { + case SNOR_MFR_ST: + case SNOR_MFR_MICRON: + /* Some Micron need WREN command; all will accept it */ + need_wren = true; + case SNOR_MFR_MACRONIX: + case SNOR_MFR_WINBOND: + if (need_wren) + write_enable(nor); + + cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; + status = spi_nor_write_reg(nor, cmd, NULL, 0); + if (need_wren) + write_disable(nor); + + if (!status && !enable && + JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + /* + * On Winbond W25Q256FV, leaving 4byte mode causes + * the Extended Address Register to be set to 1, so all + * 3-byte-address reads come from the second 16M. + * We must clear the register to enable normal behavior. + */ + write_enable(nor); + nor->cmd_buf[0] = 0; + spi_nor_write_reg(nor, SPINOR_OP_WREAR, + nor->cmd_buf, 1); + write_disable(nor); + } + + return status; + default: + /* Spansion style */ + nor->cmd_buf[0] = enable << 7; + return spi_nor_write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); + } +} + +#if defined(CONFIG_SPI_FLASH_SPANSION) || \ + defined(CONFIG_SPI_FLASH_WINBOND) || \ + defined(CONFIG_SPI_FLASH_MACRONIX) +/* + * Read the status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. + */ +static int read_sr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = spi_nor_read_reg(nor, SPINOR_OP_RDSR, &val, 1); + if (ret < 0) { + pr_debug("error %d reading SR\n", (int)ret); + return ret; + } + + return val; +} + +/* + * Read the flag status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. + */ +static int read_fsr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = spi_nor_read_reg(nor, SPINOR_OP_RDFSR, &val, 1); + if (ret < 0) { + pr_debug("error %d reading FSR\n", ret); + return ret; + } + + return val; +} + +static int spi_nor_sr_ready(struct spi_nor *nor) +{ + int sr = read_sr(nor); + + if (sr < 0) + return sr; + + return !(sr & SR_WIP); +} + +static int spi_nor_fsr_ready(struct spi_nor *nor) +{ + int fsr = read_fsr(nor); + + if (fsr < 0) + return fsr; + return fsr & FSR_READY; +} + +static int spi_nor_ready(struct spi_nor *nor) +{ + int sr, fsr; + + sr = spi_nor_sr_ready(nor); + if (sr < 0) + return sr; + fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; + if (fsr < 0) + return fsr; + return sr && fsr; +} + +/* + * Service routine to read status register until ready, or timeout occurs. + * Returns non-zero if error. + */ +static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, + unsigned long timeout) +{ + unsigned long timebase; + int ret; + + timebase = get_timer(0); + + while (get_timer(timebase) < timeout) { + ret = spi_nor_ready(nor); + if (ret < 0) + return ret; + if (ret) + return 0; + } + + dev_err(nor->dev, "flash operation timed out\n"); + + return -ETIMEDOUT; +} + +static int spi_nor_wait_till_ready(struct spi_nor *nor) +{ + return spi_nor_wait_till_ready_with_timeout(nor, + DEFAULT_READY_WAIT_JIFFIES); +} +#endif /* CONFIG_SPI_FLASH_SPANSION */ + +/* + * Erase an address range on the nor chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + return -ENOTSUPP; +} + +static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) +{ + int tmp; + u8 id[SPI_NOR_MAX_ID_LEN]; + const struct flash_info *info; + + tmp = spi_nor_read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + if (tmp < 0) { + dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); + return ERR_PTR(tmp); + } + + info = spi_nor_ids; + for (; info->sector_size != 0; info++) { + if (info->id_len) { + if (!memcmp(info->id, id, info->id_len)) + return info; + } + } + dev_dbg(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); +} + +static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + int ret; + + dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); + + while (len) { + loff_t addr = from; + + ret = spi_nor_read_data(nor, addr, len, buf); + if (ret == 0) { + /* We shouldn't see 0-length reads */ + ret = -EIO; + goto read_err; + } + if (ret < 0) + goto read_err; + + *retlen += ret; + buf += ret; + from += ret; + len -= ret; + } + ret = 0; + +read_err: + return ret; +} + +/* + * Write an address range to the nor chip. Data must be written in + * FLASH_PAGESIZE chunks. The address range may be any size provided + * it is within the physical boundaries. + */ +static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + return -ENOTSUPP; +} + +#ifdef CONFIG_SPI_FLASH_MACRONIX +/** + * macronix_quad_enable() - set QE bit in Status Register. + * @nor: pointer to a 'struct spi_nor' + * + * Set the Quad Enable (QE) bit in the Status Register. + * + * bit 6 of the Status Register is the QE bit for Macronix like QSPI memories. + * + * Return: 0 on success, -errno otherwise. + */ +static int macronix_quad_enable(struct spi_nor *nor) +{ + int ret, val; + + val = read_sr(nor); + if (val < 0) + return val; + if (val & SR_QUAD_EN_MX) + return 0; + + write_enable(nor); + + write_sr(nor, val | SR_QUAD_EN_MX); + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + ret = read_sr(nor); + if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { + dev_err(nor->dev, "Macronix Quad bit not set\n"); + return -EINVAL; + } + + return 0; +} +#endif + +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) +/* + * Write status Register and configuration register with 2 bytes + * The first byte will be written to the status register, while the + * second byte will be written to the configuration register. + * Return negative if error occurred. + */ +static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr) +{ + int ret; + + write_enable(nor); + + ret = spi_nor_write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); + if (ret < 0) { + dev_dbg(nor->dev, + "error while writing configuration register\n"); + return -EINVAL; + } + + ret = spi_nor_wait_till_ready(nor); + if (ret) { + dev_dbg(nor->dev, + "timeout while writing configuration register\n"); + return ret; + } + + return 0; +} + +/** + * spansion_read_cr_quad_enable() - set QE bit in Configuration Register. + * @nor: pointer to a 'struct spi_nor' + * + * Set the Quad Enable (QE) bit in the Configuration Register. + * This function should be used with QSPI memories supporting the Read + * Configuration Register (35h) instruction. + * + * bit 1 of the Configuration Register is the QE bit for Spansion like QSPI + * memories. + * + * Return: 0 on success, -errno otherwise. + */ +static int spansion_read_cr_quad_enable(struct spi_nor *nor) +{ + u8 sr_cr[2]; + int ret; + + /* Check current Quad Enable bit value. */ + ret = read_cr(nor); + if (ret < 0) { + dev_dbg(dev, "error while reading configuration register\n"); + return -EINVAL; + } + + if (ret & CR_QUAD_EN_SPAN) + return 0; + + sr_cr[1] = ret | CR_QUAD_EN_SPAN; + + /* Keep the current value of the Status Register. */ + ret = read_sr(nor); + if (ret < 0) { + dev_dbg(dev, "error while reading status register\n"); + return -EINVAL; + } + sr_cr[0] = ret; + + ret = write_sr_cr(nor, sr_cr); + if (ret) + return ret; + + /* Read back and check it. */ + ret = read_cr(nor); + if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { + dev_dbg(nor->dev, "Spansion Quad bit not set\n"); + return -EINVAL; + } + + return 0; +} +#endif /* CONFIG_SPI_FLASH_SPANSION */ + +struct spi_nor_read_command { + u8 num_mode_clocks; + u8 num_wait_states; + u8 opcode; + enum spi_nor_protocol proto; +}; + +enum spi_nor_read_command_index { + SNOR_CMD_READ, + SNOR_CMD_READ_FAST, + + /* Quad SPI */ + SNOR_CMD_READ_1_1_4, + + SNOR_CMD_READ_MAX +}; + +struct spi_nor_flash_parameter { + struct spi_nor_hwcaps hwcaps; + struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; +}; + +static void +spi_nor_set_read_settings(struct spi_nor_read_command *read, + u8 num_mode_clocks, + u8 num_wait_states, + u8 opcode, + enum spi_nor_protocol proto) +{ + read->num_mode_clocks = num_mode_clocks; + read->num_wait_states = num_wait_states; + read->opcode = opcode; + read->proto = proto; +} + +static int spi_nor_init_params(struct spi_nor *nor, + const struct flash_info *info, + struct spi_nor_flash_parameter *params) +{ + /* (Fast) Read settings. */ + params->hwcaps.mask = SNOR_HWCAPS_READ; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ], + 0, 0, SPINOR_OP_READ, + SNOR_PROTO_1_1_1); + + if (!(info->flags & SPI_NOR_NO_FR)) { + params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_FAST], + 0, 8, SPINOR_OP_READ_FAST, + SNOR_PROTO_1_1_1); + } + + if (info->flags & SPI_NOR_QUAD_READ) { + params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4], + 0, 8, SPINOR_OP_READ_1_1_4, + SNOR_PROTO_1_1_4); + } + + return 0; +} + +static int spi_nor_select_read(struct spi_nor *nor, + const struct spi_nor_flash_parameter *params, + u32 shared_hwcaps) +{ + int best_match = shared_hwcaps & SNOR_HWCAPS_READ_MASK; + int cmd; + const struct spi_nor_read_command *read; + + if (best_match < 0) + return -EINVAL; + + if (best_match & SNOR_HWCAPS_READ_1_1_4) + cmd = SNOR_CMD_READ_1_1_4; + else if (best_match & SNOR_HWCAPS_READ_FAST) + cmd = SNOR_CMD_READ_FAST; + else + cmd = SNOR_CMD_READ; + + read = ¶ms->reads[cmd]; + nor->read_opcode = read->opcode; + nor->read_proto = read->proto; + + /* + * In the spi-nor framework, we don't need to make the difference + * between mode clock cycles and wait state clock cycles. + * Indeed, the value of the mode clock cycles is used by a QSPI + * flash memory to know whether it should enter or leave its 0-4-4 + * (Continuous Read / XIP) mode. + * eXecution In Place is out of the scope of the mtd sub-system. + * Hence we choose to merge both mode and wait state clock cycles + * into the so called dummy clock cycles. + */ + nor->read_dummy = read->num_mode_clocks + read->num_wait_states; + return 0; +} + +static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, + const struct spi_nor_flash_parameter *params, + const struct spi_nor_hwcaps *hwcaps) +{ + u32 shared_mask; + int err; + + /* + * Keep only the hardware capabilities supported by both the SPI + * controller and the SPI flash memory. + */ + shared_mask = hwcaps->mask & params->hwcaps.mask; + + /* Select the (Fast) Read command. */ + err = spi_nor_select_read(nor, params, shared_mask); + if (err) { + dev_dbg(nor->dev, + "can't select read settings supported by both the SPI controller and memory.\n"); + return err; + } + + /* Enable Quad I/O if needed. */ + if (spi_nor_get_protocol_width(nor->read_proto) == 4) { + switch (JEDEC_MFR(info)) { +#ifdef CONFIG_SPI_FLASH_MACRONIX + case SNOR_MFR_MACRONIX: + err = macronix_quad_enable(nor); + break; +#endif + case SNOR_MFR_ST: + case SNOR_MFR_MICRON: + break; + + default: +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + /* Kept only for backward compatibility purpose. */ + err = spansion_read_cr_quad_enable(nor); +#endif + break; + } + } + if (err) { + dev_dbg(nor->dev, "quad mode not supported\n"); + return err; + } + + return 0; +} + +static int spi_nor_init(struct spi_nor *nor) +{ + if (nor->addr_width == 4 && + (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && + !(nor->info->flags & SPI_NOR_4B_OPCODES)) { + /* + * If the RESET# pin isn't hooked up properly, or the system + * otherwise doesn't perform a reset command in the boot + * sequence, it's impossible to 100% protect against unexpected + * reboots (e.g., crashes). Warn the user (or hopefully, system + * designer) that this is bad. + */ + if (nor->flags & SNOR_F_BROKEN_RESET) + printf("enabling reset hack; may not recover from unexpected reboots\n"); + set_4byte(nor, nor->info, 1); + } + + return 0; +} + +int spi_nor_scan(struct spi_nor *nor) +{ + struct spi_nor_flash_parameter params; + const struct flash_info *info = NULL; + struct mtd_info *mtd = &nor->mtd; + struct spi_nor_hwcaps hwcaps = { + .mask = SNOR_HWCAPS_READ | + SNOR_HWCAPS_READ_FAST + }; + struct spi_slave *spi = nor->spi; + int ret; + + /* Reset SPI protocol for all commands. */ + nor->reg_proto = SNOR_PROTO_1_1_1; + nor->read_proto = SNOR_PROTO_1_1_1; + nor->write_proto = SNOR_PROTO_1_1_1; + + if (spi->mode & SPI_RX_QUAD) + hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; + + info = spi_nor_read_id(nor); + if (IS_ERR_OR_NULL(info)) + return -ENOENT; + /* Parse the Serial Flash Discoverable Parameters table. */ + ret = spi_nor_init_params(nor, info, ¶ms); + if (ret) + return ret; + + mtd->name = "spi-flash"; + mtd->priv = nor; + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; + mtd->size = info->sector_size * info->n_sectors; + mtd->_erase = spi_nor_erase; + mtd->_read = spi_nor_read; + mtd->_write = spi_nor_write; + + nor->size = mtd->size; + + if (info->flags & USE_FSR) + nor->flags |= SNOR_F_USE_FSR; + if (info->flags & USE_CLSR) + nor->flags |= SNOR_F_USE_CLSR; + + if (info->flags & SPI_NOR_NO_FR) + params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST; + + /* + * Configure the SPI memory: + * - select op codes for (Fast) Read, Page Program and Sector Erase. + * - set the number of dummy cycles (mode cycles + wait states). + * - set the SPI protocols for register and memory accesses. + * - set the Quad Enable bit if needed (required by SPI x-y-4 protos). + */ + ret = spi_nor_setup(nor, info, ¶ms, &hwcaps); + if (ret) + return ret; + + if (nor->addr_width) { + /* already configured from SFDP */ + } else if (info->addr_width) { + nor->addr_width = info->addr_width; + } else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; + if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || + info->flags & SPI_NOR_4B_OPCODES) + spi_nor_set_4byte_opcodes(nor, info); + } else { + nor->addr_width = 3; + } + + if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { + dev_dbg(dev, "address width is too large: %u\n", + nor->addr_width); + return -EINVAL; + } + + /* Send all the required SPI flash commands to initialize device */ + nor->info = info; + ret = spi_nor_init(nor); + if (ret) + return ret; + + return 0; +} + +/* U-Boot specific functions, need to extend MTD to support these */ +int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor) +{ + return -ENOTSUPP; +} diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c deleted file mode 100644 index 0c2392f28a43146a6241e23bc63a6c57d5647cf1..0000000000000000000000000000000000000000 --- a/drivers/mtd/spi/spi_flash.c +++ /dev/null @@ -1,1337 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * SPI Flash Core - * - * Copyright (C) 2015 Jagan Teki - * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. - * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik - * Copyright (C) 2008 Atmel Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sf_internal.h" - -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 - -int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash) -{ - u8 status; - int ret; - - ret = read_sr(flash, &status); - if (ret) - return ret; - - return (status >> 2) & 7; -} - -#ifdef CONFIG_SPI_FLASH_BAR -/* - * This "clean_bar" is necessary in a situation when one was accessing - * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit. - * - * After it the BA24 bit shall be cleared to allow access to correct - * memory region after SW reset (by calling "reset" command). - * - * Otherwise, the BA24 bit may be left set and then after reset, the - * ROM would read/write/erase SPL from 16 MiB * bank_sel address. - */ -static int clean_bar(struct spi_flash *flash) -{ - u8 cmd, bank_sel = 0; - - if (flash->bank_curr == 0) - return 0; - cmd = flash->bank_write_cmd; - flash->bank_curr = 0; - - return spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); -} - -static int 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 read_bar(struct spi_flash *flash, const struct spi_flash_info *info) -{ - u8 curr_bank = 0; - int ret; - - if (flash->size <= SPI_FLASH_16MB_BOUN) - goto bar_end; - - switch (JEDEC_MFR(info)) { - 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) -{ - switch (flash->dual_flash) { - case SF_DUAL_STACKED_FLASH: - if (*addr >= (flash->size >> 1)) { - *addr -= flash->size >> 1; - flash->flags |= SNOR_F_USE_UPAGE; - } else { - flash->flags &= ~SNOR_F_USE_UPAGE; - } - 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_wait_till_ready(struct spi_flash *flash, - unsigned long timeout) -{ - unsigned long timebase; - int 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_wait_till_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->erase_size; - if (offset % erase_size || len % erase_size) { - printf("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 = 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; - } - -#ifdef CONFIG_SPI_FLASH_BAR - ret = clean_bar(flash); -#endif - - 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 = 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, - spi->max_write_size - sizeof(cmd)); - - 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; - } - -#ifdef CONFIG_SPI_FLASH_BAR - ret = clean_bar(flash); -#endif - - 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; -} - -/* - * TODO: remove the weak after all the other spi_flash_copy_mmap - * implementations removed from drivers - */ -void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len) -{ -#ifdef CONFIG_DMA - if (!dma_memcpy(data, offset, len)) - return; -#endif - 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 cmdsz; - u32 remain_len, read_len, read_addr; - int bank_sel = 0; - int ret = 0; - - /* Handle memory-mapped SPI */ - if (flash->memory_map) { - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: unable to claim SPI bus\n"); - return log_ret(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; - u8 cmd[cmdsz]; - - 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 = write_bar(flash, read_addr); - if (ret < 0) - return log_ret(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; - - if (spi->max_read_size) - read_len = min(read_len, spi->max_read_size); - - 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; - } - -#ifdef CONFIG_SPI_FLASH_BAR - ret = clean_bar(flash); -#endif - - return log_ret(ret); -} - -#ifdef CONFIG_SPI_FLASH_SST -static bool sst26_process_bpr(u32 bpr_size, u8 *cmd, u32 bit, enum lock_ctl ctl) -{ - switch (ctl) { - case SST26_CTL_LOCK: - cmd[bpr_size - (bit / 8) - 1] |= BIT(bit % 8); - break; - case SST26_CTL_UNLOCK: - cmd[bpr_size - (bit / 8) - 1] &= ~BIT(bit % 8); - break; - case SST26_CTL_CHECK: - return !!(cmd[bpr_size - (bit / 8) - 1] & BIT(bit % 8)); - } - - return false; -} - -/* - * sst26wf016/sst26wf032/sst26wf064 have next block protection: - * 4x - 8 KByte blocks - read & write protection bits - upper addresses - * 1x - 32 KByte blocks - write protection bits - * rest - 64 KByte blocks - write protection bits - * 1x - 32 KByte blocks - write protection bits - * 4x - 8 KByte blocks - read & write protection bits - lower addresses - * - * We'll support only per 64k lock/unlock so lower and upper 64 KByte region - * will be treated as single block. - */ - -/* - * Lock, unlock or check lock status of the flash region of the flash (depending - * on the lock_ctl value) - */ -static int sst26_lock_ctl(struct spi_flash *flash, u32 ofs, size_t len, enum lock_ctl ctl) -{ - u32 i, bpr_ptr, rptr_64k, lptr_64k, bpr_size; - bool lower_64k = false, upper_64k = false; - u8 cmd, bpr_buff[SST26_MAX_BPR_REG_LEN] = {}; - int ret; - - /* Check length and offset for 64k alignment */ - if ((ofs & (SZ_64K - 1)) || (len & (SZ_64K - 1))) - return -EINVAL; - - if (ofs + len > flash->size) - return -EINVAL; - - /* SST26 family has only 16 Mbit, 32 Mbit and 64 Mbit IC */ - if (flash->size != SZ_2M && - flash->size != SZ_4M && - flash->size != SZ_8M) - return -EINVAL; - - bpr_size = 2 + (flash->size / SZ_64K / 8); - - cmd = SST26_CMD_READ_BPR; - ret = spi_flash_read_common(flash, &cmd, 1, bpr_buff, bpr_size); - if (ret < 0) { - printf("SF: fail to read block-protection register\n"); - return ret; - } - - rptr_64k = min_t(u32, ofs + len , flash->size - SST26_BOUND_REG_SIZE); - lptr_64k = max_t(u32, ofs, SST26_BOUND_REG_SIZE); - - upper_64k = ((ofs + len) > (flash->size - SST26_BOUND_REG_SIZE)); - lower_64k = (ofs < SST26_BOUND_REG_SIZE); - - /* Lower bits in block-protection register are about 64k region */ - bpr_ptr = lptr_64k / SZ_64K - 1; - - /* Process 64K blocks region */ - while (lptr_64k < rptr_64k) { - if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) - return EACCES; - - bpr_ptr++; - lptr_64k += SZ_64K; - } - - /* 32K and 8K region bits in BPR are after 64k region bits */ - bpr_ptr = (flash->size - 2 * SST26_BOUND_REG_SIZE) / SZ_64K; - - /* Process lower 32K block region */ - if (lower_64k) - if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) - return EACCES; - - bpr_ptr++; - - /* Process upper 32K block region */ - if (upper_64k) - if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) - return EACCES; - - bpr_ptr++; - - /* Process lower 8K block regions */ - for (i = 0; i < SST26_BPR_8K_NUM; i++) { - if (lower_64k) - if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) - return EACCES; - - /* In 8K area BPR has both read and write protection bits */ - bpr_ptr += 2; - } - - /* Process upper 8K block regions */ - for (i = 0; i < SST26_BPR_8K_NUM; i++) { - if (upper_64k) - if (sst26_process_bpr(bpr_size, bpr_buff, bpr_ptr, ctl)) - return EACCES; - - /* In 8K area BPR has both read and write protection bits */ - bpr_ptr += 2; - } - - /* If we check region status we don't need to write BPR back */ - if (ctl == SST26_CTL_CHECK) - return 0; - - cmd = SST26_CMD_WRITE_BPR; - ret = spi_flash_write_common(flash, &cmd, 1, bpr_buff, bpr_size); - if (ret < 0) { - printf("SF: fail to write block-protection register\n"); - return ret; - } - - return 0; -} - -static int sst26_unlock(struct spi_flash *flash, u32 ofs, size_t len) -{ - return sst26_lock_ctl(flash, ofs, len, SST26_CTL_UNLOCK); -} - -static int sst26_lock(struct spi_flash *flash, u32 ofs, size_t len) -{ - return sst26_lock_ctl(flash, ofs, len, SST26_CTL_LOCK); -} - -/* - * Returns EACCES (positive value) if region is locked, 0 if region is unlocked, - * and negative on errors. - */ -static int sst26_is_locked(struct spi_flash *flash, u32 ofs, size_t len) -{ - /* - * is_locked function is used for check before reading or erasing flash - * region, so offset and length might be not 64k allighned, so adjust - * them to be 64k allighned as sst26_lock_ctl works only with 64k - * allighned regions. - */ - ofs -= ofs & (SZ_64K - 1); - len = len & (SZ_64K - 1) ? (len & ~(SZ_64K - 1)) + SZ_64K : len; - - return sst26_lock_ctl(flash, ofs, len, SST26_CTL_CHECK); -} - -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_wait_till_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_wait_till_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, - u64 *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, loff_t ofs, u64 len, - u8 sr) -{ - loff_t lock_offs; - u64 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->erase_size, flash->erase_size, - 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 - -static const struct spi_flash_info *spi_flash_read_id(struct spi_flash *flash) -{ - int tmp; - u8 id[SPI_FLASH_MAX_ID_LEN]; - const struct spi_flash_info *info; - - tmp = spi_flash_cmd(flash->spi, CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN); - if (tmp < 0) { - printf("SF: error %d reading JEDEC ID\n", tmp); - return ERR_PTR(tmp); - } - - info = spi_flash_ids; - for (; info->name != NULL; info++) { - if (info->id_len) { - if (!memcmp(info->id, id, info->id_len)) - return info; - } - } - - printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n", - id[0], id[1], id[2]); - return ERR_PTR(-ENODEV); -} - -static int set_quad_mode(struct spi_flash *flash, - const struct spi_flash_info *info) -{ - switch (JEDEC_MFR(info)) { -#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: - case SPI_FLASH_CFI_MFR_MICRON: - debug("SF: QEB is volatile for %02x flash\n", JEDEC_MFR(info)); - return 0; -#endif - default: - printf("SF: Need set QEB func for %02x flash\n", - JEDEC_MFR(info)); - return -1; - } -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int spi_flash_decode_fdt(struct spi_flash *flash) -{ -#ifdef CONFIG_DM_SPI_FLASH - fdt_addr_t addr; - fdt_size_t size; - - addr = dev_read_addr_size(flash->dev, "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_info *info = NULL; - int ret; - - info = spi_flash_read_id(flash); - if (IS_ERR_OR_NULL(info)) - return -ENOENT; - - /* - * Flash powers up read-only, so clear BP# bits. - * - * Note on some flash (like Macronix), QE (quad enable) bit is in the - * same status register as BP# bits, and we need preserve its original - * value during a reboot cycle as this is required by some platforms - * (like Intel ICH SPI controller working under descriptor mode). - */ - if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_ATMEL || - (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST) || - (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX)) { - u8 sr = 0; - - if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX) { - read_sr(flash, &sr); - sr &= STATUS_QEB_MXIC; - } - write_sr(flash, sr); - } - - flash->name = info->name; - flash->memory_map = spi->memory_map; - - if (info->flags & SST_WR) - flash->flags |= SNOR_F_SST_WR; - -#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 - -#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) - /* NOR protection support for STmicro/Micron chips and similar */ - if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_STMICRO || - JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MICRON || - JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST) { - flash->flash_lock = stm_lock; - flash->flash_unlock = stm_unlock; - flash->flash_is_locked = stm_is_locked; - } -#endif - -/* sst26wf series block protection implementation differs from other series */ -#if defined(CONFIG_SPI_FLASH_SST) - if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST && info->id[1] == 0x26) { - flash->flash_lock = sst26_lock; - flash->flash_unlock = sst26_unlock; - flash->flash_is_locked = sst26_is_locked; - } -#endif - - /* Compute the flash size */ - flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; - flash->page_size = info->page_size; - /* - * The Spansion S25FS512S, 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 (JEDEC_EXT(info) == 0x4d00) { - if ((JEDEC_ID(info) != 0x0215) && - (JEDEC_ID(info) != 0x0216) && - (JEDEC_ID(info) != 0x0220)) - flash->page_size = 512; - } - flash->page_size <<= flash->shift; - flash->sector_size = info->sector_size << flash->shift; - flash->size = flash->sector_size * info->n_sectors << flash->shift; -#ifdef CONFIG_SF_DUAL_FLASH - if (flash->dual_flash & SF_DUAL_STACKED_FLASH) - flash->size <<= 1; -#endif - -#ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS - /* Compute erase sector and command */ - if (info->flags & SECT_4K) { - flash->erase_cmd = CMD_ERASE_4K; - flash->erase_size = 4096 << flash->shift; - } else -#endif - { - flash->erase_cmd = CMD_ERASE_64K; - flash->erase_size = flash->sector_size; - } - - /* Now erase size becomes valid sector size */ - flash->sector_size = flash->erase_size; - - /* Look for read commands */ - flash->read_cmd = CMD_READ_ARRAY_FAST; - if (spi->mode & SPI_RX_SLOW) - flash->read_cmd = CMD_READ_ARRAY_SLOW; - else if (spi->mode & SPI_RX_QUAD && info->flags & RD_QUAD) - flash->read_cmd = CMD_READ_QUAD_OUTPUT_FAST; - else if (spi->mode & SPI_RX_DUAL && info->flags & RD_DUAL) - flash->read_cmd = CMD_READ_DUAL_OUTPUT_FAST; - - /* Look for write commands */ - if (info->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, info); - if (ret) { - debug("SF: Fail to set QEB for %02x\n", - JEDEC_MFR(info)); - 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 (info->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 = read_bar(flash, info); - if (ret < 0) - return ret; -#endif - -#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) - ret = spi_flash_decode_fdt(flash); - if (ret) { - debug("SF: FDT decode error\n"); - return -EINVAL; - } -#endif - -#ifndef CONFIG_SPL_BUILD - printf("SF: Detected %s with page size ", flash->name); - print_size(flash->page_size, ", erase size "); - print_size(flash->erase_size, ", total "); - print_size(flash->size, ""); - if (flash->memory_map) - printf(", mapped at %p", flash->memory_map); - puts("\n"); -#endif - -#ifndef CONFIG_SPI_FLASH_BAR - if (((flash->dual_flash == SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN)) || - ((flash->dual_flash > SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN << 1))) { - puts("SF: Warning - Only lower 16MiB accessible,"); - puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); - } -#endif - - return 0; -} diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c deleted file mode 100644 index ad0a0c8150145eeffb23b3f362fbb674ae3c7968..0000000000000000000000000000000000000000 --- a/drivers/mtd/spi/spi_flash_ids.c +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * SPI Flash ID's. - * - * Copyright (C) 2016 Jagan Teki - * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. - */ - -#include -#include -#include - -#include "sf_internal.h" - -/* Used when the "_ext_id" is two bytes at most */ -#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ - .id = { \ - ((_jedec_id) >> 16) & 0xff, \ - ((_jedec_id) >> 8) & 0xff, \ - (_jedec_id) & 0xff, \ - ((_ext_id) >> 8) & 0xff, \ - (_ext_id) & 0xff, \ - }, \ - .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ - .sector_size = (_sector_size), \ - .n_sectors = (_n_sectors), \ - .page_size = 256, \ - .flags = (_flags), - -#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ - .id = { \ - ((_jedec_id) >> 16) & 0xff, \ - ((_jedec_id) >> 8) & 0xff, \ - (_jedec_id) & 0xff, \ - ((_ext_id) >> 16) & 0xff, \ - ((_ext_id) >> 8) & 0xff, \ - (_ext_id) & 0xff, \ - }, \ - .id_len = 6, \ - .sector_size = (_sector_size), \ - .n_sectors = (_n_sectors), \ - .page_size = 256, \ - .flags = (_flags), - -const struct spi_flash_info spi_flash_ids[] = { -#ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ - {"at45db011d", INFO(0x1f2200, 0x0, 64 * 1024, 4, SECT_4K) }, - {"at45db021d", INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K) }, - {"at45db041d", INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_4K) }, - {"at45db081d", INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K) }, - {"at45db161d", INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K) }, - {"at45db321d", INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K) }, - {"at45db641d", INFO(0x1f2800, 0x0, 64 * 1024, 128, SECT_4K) }, - {"at25df321a", INFO(0x1f4701, 0x0, 64 * 1024, 64, SECT_4K) }, - {"at25df321", INFO(0x1f4700, 0x0, 64 * 1024, 64, SECT_4K) }, - {"at26df081a", INFO(0x1f4501, 0x0, 64 * 1024, 16, SECT_4K) }, -#endif -#ifdef CONFIG_SPI_FLASH_EON /* EON */ - {"en25q32b", INFO(0x1c3016, 0x0, 64 * 1024, 64, 0) }, - {"en25q64", INFO(0x1c3017, 0x0, 64 * 1024, 128, SECT_4K) }, - {"en25q128b", INFO(0x1c3018, 0x0, 64 * 1024, 256, 0) }, - {"en25s64", INFO(0x1c3817, 0x0, 64 * 1024, 128, 0) }, -#endif -#ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ - {"gd25q16c", INFO(0xc84015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, - {"gd25q64b", INFO(0xc84017, 0x0, 64 * 1024, 128, SECT_4K) }, - {"gd25q32b", INFO(0xc84016, 0x0, 64 * 1024, 64, SECT_4K) }, - {"gd25lq32", INFO(0xc86016, 0x0, 64 * 1024, 64, SECT_4K) }, -#endif -#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ - {"is25lq040b", INFO(0x9d4013, 0x0, 64 * 1024, 8, 0) }, - {"is25lp032", INFO(0x9d6016, 0x0, 64 * 1024, 64, 0) }, - {"is25lp064", INFO(0x9d6017, 0x0, 64 * 1024, 128, 0) }, - {"is25lp128", INFO(0x9d6018, 0x0, 64 * 1024, 256, 0) }, - {"is25lp256", INFO(0x9d6019, 0x0, 64 * 1024, 512, 0) }, - {"is25wp032", INFO(0x9d7016, 0x0, 64 * 1024, 64, RD_FULL | SECT_4K) }, - {"is25wp064", INFO(0x9d7017, 0x0, 64 * 1024, 128, RD_FULL | SECT_4K) }, - {"is25wp128", INFO(0x9d7018, 0x0, 64 * 1024, 256, RD_FULL | SECT_4K) }, -#endif -#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ - {"mx25l2006e", INFO(0xc22012, 0x0, 64 * 1024, 4, 0) }, - {"mx25l4005", INFO(0xc22013, 0x0, 64 * 1024, 8, 0) }, - {"mx25l8005", INFO(0xc22014, 0x0, 64 * 1024, 16, 0) }, - {"mx25l1605d", INFO(0xc22015, 0x0, 64 * 1024, 32, 0) }, - {"mx25l3205d", INFO(0xc22016, 0x0, 64 * 1024, 64, 0) }, - {"mx25l6405d", INFO(0xc22017, 0x0, 64 * 1024, 128, 0) }, - {"mx25l12805", INFO(0xc22018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"mx25l25635f", INFO(0xc22019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP) }, - {"mx25l51235f", INFO(0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, - {"mx25l1633e", INFO(0xc22415, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, - {"mx25u6435f", INFO(0xc22537, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP) }, - {"mx25l12855e", INFO(0xc22618, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"mx25u1635e", INFO(0xc22535, 0x0, 64 * 1024, 32, SECT_4K) }, - {"mx25u25635f", INFO(0xc22539, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP) }, - {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, - {"mx66l1g45g", INFO(0xc2201b, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP) }, -#endif -#ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ - {"s25fl008a", INFO(0x010213, 0x0, 64 * 1024, 16, 0) }, - {"s25fl016a", INFO(0x010214, 0x0, 64 * 1024, 32, 0) }, - {"s25fl032a", INFO(0x010215, 0x0, 64 * 1024, 64, 0) }, - {"s25fl064a", INFO(0x010216, 0x0, 64 * 1024, 128, 0) }, - {"s25fl208k", INFO(0x014014, 0x0, 64 * 1024, 16, 0) }, - {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 32, 0) }, - {"s25fl164k", INFO(0x014017, 0x0140, 64 * 1024, 128, 0) }, - {"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024, 64, RD_FULL | WR_QPP) }, - {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"s25fl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP) }, - {"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) }, - {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) }, - {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) }, - {"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, - {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) }, - {"s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, - {"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP) }, - {"s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP) }, - {"s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, RD_FULL | WR_QPP) }, -#endif -#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ - {"m25p10", INFO(0x202011, 0x0, 32 * 1024, 4, 0) }, - {"m25p20", INFO(0x202012, 0x0, 64 * 1024, 4, 0) }, - {"m25p40", INFO(0x202013, 0x0, 64 * 1024, 8, 0) }, - {"m25p80", INFO(0x202014, 0x0, 64 * 1024, 16, 0) }, - {"m25p16", INFO(0x202015, 0x0, 64 * 1024, 32, 0) }, - {"m25pE16", INFO(0x208015, 0x1000, 64 * 1024, 32, 0) }, - {"m25pX16", INFO(0x207115, 0x1000, 64 * 1024, 32, RD_QUAD | RD_DUAL) }, - {"m25p32", INFO(0x202016, 0x0, 64 * 1024, 64, 0) }, - {"m25p64", INFO(0x202017, 0x0, 64 * 1024, 128, 0) }, - {"m25p128", INFO(0x202018, 0x0, 256 * 1024, 64, 0) }, - {"m25pX64", INFO(0x207117, 0x0, 64 * 1024, 128, SECT_4K) }, - {"n25q016a", INFO(0x20bb15, 0x0, 64 * 1024, 32, SECT_4K) }, - {"n25q32", INFO(0x20ba16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, - {"n25q32a", INFO(0x20bb16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, - {"n25q64", INFO(0x20ba17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, - {"n25q64a", INFO(0x20bb17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, - {"n25q128", INFO(0x20ba18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"n25q128a", INFO(0x20bb18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, - {"n25q256", INFO(0x20ba19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"n25q256a", INFO(0x20bb19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"n25q512", INFO(0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"n25q512a", INFO(0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"n25q1024", INFO(0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"n25q1024a", INFO(0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"mt25qu02g", INFO(0x20bb22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"mt25ql02g", INFO(0x20ba22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, - {"mt35xu512g", INFO6(0x2c5b1a, 0x104100, 128 * 1024, 512, E_FSR | SECT_4K) }, -#endif -#ifdef CONFIG_SPI_FLASH_SST /* SST */ - {"sst25vf040b", INFO(0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, - {"sst25vf080b", INFO(0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) }, - {"sst25vf016b", INFO(0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WR) }, - {"sst25vf032b", INFO(0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WR) }, - {"sst25vf064c", INFO(0xbf254b, 0x0, 64 * 1024, 128, SECT_4K) }, - {"sst25wf512", INFO(0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WR) }, - {"sst25wf010", INFO(0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WR) }, - {"sst25wf020", INFO(0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WR) }, - {"sst25wf040", INFO(0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, - {"sst25wf040b", INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K) }, - {"sst25wf080", INFO(0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) }, - {"sst26wf016", INFO(0xbf2651, 0x0, 64 * 1024, 32, SECT_4K) }, - {"sst26wf032", INFO(0xbf2622, 0x0, 64 * 1024, 64, SECT_4K) }, - {"sst26wf064", INFO(0xbf2643, 0x0, 64 * 1024, 128, SECT_4K) }, -#endif -#ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ - {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) }, - {"w25p16", INFO(0xef2015, 0x0, 64 * 1024, 32, 0) }, - {"w25p32", INFO(0xef2016, 0x0, 64 * 1024, 64, 0) }, - {"w25x40", INFO(0xef3013, 0x0, 64 * 1024, 8, SECT_4K) }, - {"w25x16", INFO(0xef3015, 0x0, 64 * 1024, 32, SECT_4K) }, - {"w25x32", INFO(0xef3016, 0x0, 64 * 1024, 64, SECT_4K) }, - {"w25x64", INFO(0xef3017, 0x0, 64 * 1024, 128, SECT_4K) }, - {"w25q80bl", INFO(0xef4014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q16cl", INFO(0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q32bv", INFO(0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q64cv", INFO(0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q128bv", INFO(0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q256", INFO(0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q80bw", INFO(0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q16dw", INFO(0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q16jv", INFO(0xef7015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q32dw", INFO(0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q32jv", INFO(0xef7016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q64dw", INFO(0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q64jv", INFO(0xef7017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q128fw", INFO(0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q128jv", INFO(0xef7018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q256fw", INFO(0xef6019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, - {"w25q256jw", INFO(0xef7019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, -#endif -#ifdef CONFIG_SPI_FLASH_XMC /* Wuhan Xinxin Semiconductor Manufacturing Corp */ - { "xm25qh64a", INFO(0x207017, 0x0, 64 * 1024, 128, SECT_4K | RD_DUAL | RD_QUAD) }, - { "xm25qh128a", INFO(0x207018, 0x0, 64 * 1024, 256, SECT_4K | RD_DUAL | RD_QUAD) }, -#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, w25q16jv) - * (w25q32bv, w25q32fv_spi) - * (w25q64cv, w25q64fv_spi) - * (w25q128bv, w25q128fv_spi) - * (w25q32dw, w25q32fv_qpi) - * (w25q64dw, w25q64fv_qpi) - * (w25q128fw, w25q128fv_qpi) - * (w25q256fw, w25q256fv_qpi) - */ -}; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index de4d62dd8fd1e24c25889001900b0578c8b449bd..ac7fbab84199ebf53b38f22696d99ce1b9f2824c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -16,8 +16,6 @@ config DM_SPI typically use driver-private data instead of extending the spi_slave structure. -if DM_SPI - config SPI_MEM bool "SPI memory extension" help @@ -25,6 +23,8 @@ config SPI_MEM This extension is meant to simplify interaction with SPI memories by providing an high-level interface to send memory-like commands. +if DM_SPI + config ALTERA_SPI bool "Altera SPI driver" help @@ -111,6 +111,7 @@ config FSL_DSPI config ICH_SPI bool "Intel ICH SPI driver" + imply SPI_FLASH_BAR help Enable the Intel ICH SPI driver. This driver can be used to access the SPI NOR flash on platforms embedding this Intel @@ -140,6 +141,7 @@ config MT7621_SPI config MTK_QSPI bool "Mediatek QSPI driver" + imply SPI_FLASH_BAR help Enable the Mediatek QSPI driver. This driver can be used to access the SPI NOR flash on platforms embedding this @@ -172,6 +174,7 @@ config PL022_SPI config RENESAS_RPC_SPI bool "Renesas RPC SPI driver" depends on RCAR_GEN3 + imply SPI_FLASH_BAR help Enable the Renesas RPC SPI driver, used to access SPI NOR flash on Renesas RCar Gen3 SoCs. This uses driver model and requires a @@ -213,6 +216,7 @@ config SANDBOX_SPI config STM32_QSPI bool "STM32F7 QSPI driver" depends on STM32F7 + imply SPI_FLASH_BAR help Enable the STM32F7 Quad-SPI (QSPI) driver. This driver can be used to access the SPI NOR flash chips on platforms embedding @@ -273,6 +277,7 @@ config ZYNQ_SPI config ZYNQ_QSPI bool "Zynq QSPI driver" depends on ARCH_ZYNQ + imply SPI_FLASH_BAR help Enable the Zynq Quad-SPI (QSPI) driver. This driver can be used to access the SPI NOR flash on platforms embedding this @@ -316,6 +321,7 @@ config FSL_ESPI config FSL_QSPI bool "Freescale QSPI driver" + imply SPI_FLASH_BAR help Enable the Freescale Quad-SPI (QSPI) driver. This driver can be used to access the SPI NOR flash on platforms embedding this diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 4acec3ea17d7aa666b8a9586aa1a2c67f25ccc58..39026712931b48131334439ace3ddca544c0a012 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SOFT_SPI) += soft_spi.o obj-$(CONFIG_SPI_MEM) += spi-mem.o else obj-y += spi.o +obj-$(CONFIG_SPI_MEM) += spi-mem-nodm.o obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o endif diff --git a/drivers/spi/spi-mem-nodm.c b/drivers/spi/spi-mem-nodm.c new file mode 100644 index 0000000000000000000000000000000000000000..4447d44991352a83ff68d96b652d3c191bf634be --- /dev/null +++ b/drivers/spi/spi-mem-nodm.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include +#include + +int spi_mem_exec_op(struct spi_slave *slave, + const struct spi_mem_op *op) +{ + unsigned int pos = 0; + const u8 *tx_buf = NULL; + u8 *rx_buf = NULL; + u8 *op_buf; + int op_len; + u32 flag; + int ret; + int i; + + if (op->data.nbytes) { + if (op->data.dir == SPI_MEM_DATA_IN) + rx_buf = op->data.buf.in; + else + tx_buf = op->data.buf.out; + } + + op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + op_buf = calloc(1, op_len); + + ret = spi_claim_bus(slave); + if (ret < 0) + return ret; + + op_buf[pos++] = op->cmd.opcode; + + if (op->addr.nbytes) { + for (i = 0; i < op->addr.nbytes; i++) + op_buf[pos + i] = op->addr.val >> + (8 * (op->addr.nbytes - i - 1)); + + pos += op->addr.nbytes; + } + + if (op->dummy.nbytes) + memset(op_buf + pos, 0xff, op->dummy.nbytes); + + /* 1st transfer: opcode + address + dummy cycles */ + flag = SPI_XFER_BEGIN; + /* Make sure to set END bit if no tx or rx data messages follow */ + if (!tx_buf && !rx_buf) + flag |= SPI_XFER_END; + + ret = spi_xfer(slave, op_len * 8, op_buf, NULL, flag); + if (ret) + return ret; + + /* 2nd transfer: rx or tx data path */ + if (tx_buf || rx_buf) { + ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf, + rx_buf, SPI_XFER_END); + if (ret) + return ret; + } + + spi_release_bus(slave); + + for (i = 0; i < pos; i++) + debug("%02x ", op_buf[i]); + debug("| [%dB %s] ", + tx_buf || rx_buf ? op->data.nbytes : 0, + tx_buf || rx_buf ? (tx_buf ? "out" : "in") : "-"); + for (i = 0; i < op->data.nbytes; i++) + debug("%02x ", tx_buf ? tx_buf[i] : rx_buf[i]); + debug("[ret %d]\n", ret); + + free(op_buf); + + if (ret < 0) + return ret; + + return 0; +} + +int spi_mem_adjust_op_size(struct spi_slave *slave, + struct spi_mem_op *op) +{ + unsigned int len; + + len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + if (slave->max_write_size && len > slave->max_write_size) + return -EINVAL; + + if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) + op->data.nbytes = min(op->data.nbytes, + slave->max_read_size); + else if (slave->max_write_size) + op->data.nbytes = min(op->data.nbytes, + slave->max_write_size - len); + + if (!op->data.nbytes) + return -EINVAL; + + return 0; +} diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index af9aef009a73d2169410cedb0c704900d27a2e42..1bb0987edb728fb35a37695c756a58586000d9e3 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -210,6 +210,10 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) if (!spi_mem_supports_op(slave, op)) return -ENOTSUPP; + ret = spi_claim_bus(slave); + if (ret < 0) + return ret; + if (ops->mem_ops) { #ifndef __UBOOT__ /* @@ -232,6 +236,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) mutex_lock(&ctlr->io_mutex); #endif ret = ops->mem_ops->exec_op(slave, op); + #ifndef __UBOOT__ mutex_unlock(&ctlr->io_mutex); mutex_unlock(&ctlr->bus_lock_mutex); @@ -245,8 +250,10 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) * read path) and expect the core to use the regular SPI * interface in other cases. */ - if (!ret || ret != -ENOTSUPP) + if (!ret || ret != -ENOTSUPP) { + spi_release_bus(slave); return ret; + } } #ifndef __UBOOT__ @@ -323,15 +330,6 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) return -EIO; #else - /* U-Boot does not support parallel SPI data lanes */ - if ((op->cmd.buswidth != 1) || - (op->addr.nbytes && op->addr.buswidth != 1) || - (op->dummy.nbytes && op->dummy.buswidth != 1) || - (op->data.nbytes && op->data.buswidth != 1)) { - printf("Dual/Quad raw SPI transfers not supported\n"); - return -ENOTSUPP; - } - if (op->data.nbytes) { if (op->data.dir == SPI_MEM_DATA_IN) rx_buf = op->data.buf.in; @@ -342,10 +340,6 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; op_buf = calloc(1, op_len); - ret = spi_claim_bus(slave); - if (ret < 0) - return ret; - op_buf[pos++] = op->cmd.opcode; if (op->addr.nbytes) { @@ -421,6 +415,25 @@ int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op) if (ops->mem_ops && ops->mem_ops->adjust_op_size) return ops->mem_ops->adjust_op_size(slave, op); + if (!ops->mem_ops || !ops->mem_ops->exec_op) { + unsigned int len; + + len = sizeof(op->cmd.opcode) + op->addr.nbytes + + op->dummy.nbytes; + if (slave->max_write_size && len > slave->max_write_size) + return -EINVAL; + + if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) + op->data.nbytes = min(op->data.nbytes, + slave->max_read_size); + else if (slave->max_write_size) + op->data.nbytes = min(op->data.nbytes, + slave->max_write_size - len); + + if (!op->data.nbytes) + return -EINVAL; + } + return 0; } EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size); diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c index 3b92254a5ce16adb668ced4e3038a2b5102dd643..8b60d7c3b2245f79b8f95c868a952956804627cc 100644 --- a/drivers/spi/stm32_qspi.c +++ b/drivers/spi/stm32_qspi.c @@ -271,9 +271,9 @@ static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, { unsigned int ccr_reg; - priv->command = flash->read_cmd | CMD_HAS_ADR | CMD_HAS_DATA + priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA | CMD_HAS_DUMMY; - priv->dummycycles = flash->dummy_byte * 8; + priv->dummycycles = flash->read_dummy; ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); diff --git a/include/configs/T102xQDS.h b/include/configs/T102xQDS.h index f3b0fe0144ffdff5d434478f3102b3f02a29d714..c63dfd31868024b57a82f780bfbf6ec24cd1fda8 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 673d1112e22aec0606061d9d44b1977d6954193c..c72be9fb387aded30efdf7652094e028f8e99524 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 7375d6ff4607ad38506b9c69bc0b863e910d3f28..4cecab3401e9e54e561174a6d3fb0f32a5abf195 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 1dcf2779d75515254443a17f50f2f6a27025b74d..69ec109831a0f51606ffae402525d3bfec1b389e 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 ddb60b3d6d943a1f29f7438eeda845ab08016846..1d6a390b72dfe01f773c08e9d7fc57f1b7448eb8 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 5d247886aeda8a3bf347dac549213068f10e63c1..e01bf5bf1bbbe699d31c545d2394bc9f3490fb04 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 6cafdc66859b4674a95e166aad905b39381e6855..6e23fa29b33bd9b4ed0d2e7933f1d281904befb7 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 a8f7300c1eb24fc8f64233667ebe4d115458bbe8..c762c93ac0aa47c67fc28b0be14c61751d11ac49 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 10dc0c68435b5d8d9d99c09583e72a0ae44c678c..6be8df109bd63d61bfe39411b0ae04b1fab7d1c8 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 2822811da5df808038191991e490681d68919a22..a23a4edaee223653c40a3946a5552a096f533df2 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 e307855d041a21288cefce6dc3a02ea0691f55b5..4fc9226712d9f916639cdebc1363c27aac31a375 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 f4f64edc4a228a6f91635dfa961eb46786692534..94517158055529676a52120e7e276f1613408e67 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 612d6439d13dd823baf73c60642778920a4b195d..36e494ee95a9e797f1eb55a6c0bf3661ea77812c 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 01f297b2c167956548696e2ab8f62fbafedc0479..c59f5eff7a985f457ce1ace163cf5cf6f38d33b1 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 7913ef72140ac0909348e5fad75c3b0cc914d485..02233d6a6614532c4e70de785f35744f69ce83e4 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 f9319a2234ff530060f98fc4a674226c08b41cb8..0e73239f568c86e0efe12af9e47abe3ac5ab5741 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 710b8991a4c22e4515ab69056f641a2e2f2b78aa..b90be65a4fb2124a7867b92179dde8831a554705 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 a47f6d17bb5f2571982c26650b96c237fad68b5d..259df43fb00f0320be668aa685d3aa8d7e1fe2a9 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 0000000000000000000000000000000000000000..3555518bd3f16bdeaecebb2543754ce27cabc55c --- /dev/null +++ b/include/linux/mtd/cfi.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright © 2000-2010 David Woodhouse 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 0000000000000000000000000000000000000000..88e80af57941556474c87276bbaa11e5364caf82 --- /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 +#include +#include + +/* + * 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 e427e960d54f5c87041b7ac45f9d3ff8015bcfa6..7f691e8559cde003fc4e0dc2d4011e3304f4112c 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -11,6 +11,7 @@ #include /* Because we dereference struct udevice here */ #include +#include #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