/* * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved. */ /*****************************************************************************/ #include #include #include #include "fmc100.h" /*****************************************************************************/ struct spi_nor_info *spiinfo; /*****************************************************************************/ set_read_std(0, INFINITE, 33); set_read_std(0, INFINITE, 40); set_read_std(0, INFINITE, 45); set_read_std(0, INFINITE, 50); set_read_std4b(0, INFINITE, 50); set_read_std(0, INFINITE, 54); set_read_std4b(0, INFINITE, 54); set_read_std(0, INFINITE, 55); set_read_std4b(0, INFINITE, 55); set_read_std(0, INFINITE, 66); set_read_std4b(0, INFINITE, 66); set_read_std(0, INFINITE, 80); set_read_fast(1, INFINITE, 55); set_read_fast(1, INFINITE, 80); set_read_fast4b(1, INFINITE, 80); set_read_fast(1, INFINITE, 86); set_read_fast(1, INFINITE, 100); set_read_fast(1, INFINITE, 104); set_read_fast4b(1, INFINITE, 104); set_read_fast(1, INFINITE, 108); set_read_fast4b(1, INFINITE, 108); set_read_fast(1, INFINITE, 112); set_read_fast(1, INFINITE, 133); set_read_fast4b(1, INFINITE, 133); set_read_dual(1, INFINITE, 55); set_read_dual(1, INFINITE, 64); set_read_dual(1, INFINITE, 80); set_read_dual4b(1, INFINITE, 80); set_read_dual(1, INFINITE, 84); set_read_dual(1, INFINITE, 104); set_read_dual4b(1, INFINITE, 104); set_read_dual(1, INFINITE, 108); set_read_dual4b(1, INFINITE, 108); set_read_dual(1, INFINITE, 112); set_read_dual(1, INFINITE, 133); set_read_dual4b(1, INFINITE, 133); set_read_dual_addr(1, INFINITE, 80); set_read_dual_addr4b(1, INFINITE, 80); set_read_dual_addr4b(1, INFINITE, 108); set_read_dual_addr(2, INFINITE, 84); set_read_dual_addr4b(2, INFINITE, 84); set_read_dual_addr(2, INFINITE, 108); set_read_dual_addr(1, INFINITE, 104); set_read_dual_addr4b(1, INFINITE, 104); set_read_dual_addr(1, INFINITE, 108); set_read_dual_addr(1, INFINITE, 112); set_read_dual_addr(1, INFINITE, 133); set_read_dual_addr4b(1, INFINITE, 133); set_read_dual_addr4b(2, INFINITE, 133); set_read_quad(1, INFINITE, 80); set_read_quad4b(1, INFINITE, 80); set_read_quad(1, INFINITE, 84); set_read_quad(1, INFINITE, 104); set_read_quad4b(1, INFINITE, 104); set_read_quad(1, INFINITE, 108); set_read_quad4b(1, INFINITE, 108); set_read_quad(1, INFINITE, 112); set_read_quad(1, INFINITE, 133); set_read_quad4b(1, INFINITE, 133); set_read_quad_addr(3, INFINITE, 50); set_read_quad_addr(3, INFINITE, 80); set_read_quad_addr4b(3, INFINITE, 80); set_read_quad_addr(5, INFINITE, 84); set_read_quad_addr4b(5, INFINITE, 84); set_read_quad_addr(5, INFINITE, 108); set_read_quad_addr(3, INFINITE, 104); set_read_quad_addr4b(3, INFINITE, 104); set_read_quad_addr(3, INFINITE, 108); set_read_quad_addr4b(3, INFINITE, 108); set_read_quad_addr4b(5, INFINITE, 125); set_read_quad_addr(3, INFINITE, 112); set_read_quad_addr(3, INFINITE, 133); set_read_quad_addr(3, INFINITE, 72); set_read_quad_addr4b(3, INFINITE, 133); #ifdef CONFIG_DTR_MODE_SUPPORT set_read_quad_dtr(8, INFINITE, 80); set_read_quad_dtr4b(10, INFINITE, 100); set_read_quad_dtr(10, INFINITE, 100); #endif /*****************************************************************************/ set_write_std(0, 256, 33); set_write_std(0, 256, 55); set_write_std(0, 256, 80); set_write_std4b(0, 256, 80); set_write_std(0, 256, 86); set_write_std(0, 256, 100); set_write_std(0, 256, 104); set_write_std4b(0, 256, 104); set_write_std(0, 256, 108); set_write_std(0, 256, 112); set_write_std(0, 256, 133); set_write_std4b(0, 256, 120); set_write_std4b(0, 256, 133); set_write_dual(0, 256, 75); set_write_dual4b(0, 256, 75); set_write_dual(0, 256, 108); set_write_dual4b(0, 256, 133); set_write_dual_addr(0, 256, 75); set_write_dual_addr4b(0, 256, 75); set_write_dual_addr(0, 256, 108); set_write_dual_addr4b(0, 256, 133); set_write_quad(0, 256, 55); set_write_quad(0, 256, 80); set_write_quad4b(0, 256, 80); set_write_quad(0, 256, 104); set_write_quad(0, 256, 108); set_write_quad(0, 256, 112); set_write_quad(0, 256, 133); set_write_quad4b(0, 256, 133); /* As Micron MT25Q(and MIXC) and N25Q have different QUAD I/O write code, * but they have the same ID, so we cannot compatiable it. User can open * by theirselves. */ set_write_quad_addr(0, 256, 33); set_write_quad_addr(0, 256, 80); set_write_quad_addr(0, 256, 104); set_write_quad_addr4b(0, 256, 104); set_write_quad_addr(0, 256, 108); set_write_quad_addr4b(0, 256, 108); set_write_quad_addr4b(0, 256, 120); set_write_quad_addr(0, 256, 133); set_write_quad_addr4b(0, 256, 133); /*****************************************************************************/ set_erase_sector_64k(0, _64K, 33); set_erase_sector_64k(0, _64K, 55); set_erase_sector_64k(0, _64K, 50); set_erase_sector_64k(0, _64K, 80); set_erase_sector_64k4b(0, _64K, 80); set_erase_sector_64k(0, _64K, 86); set_erase_sector_64k(0, _64K, 100); set_erase_sector_64k(0, _64K, 104); set_erase_sector_64k4b(0, _64K, 104); set_erase_sector_64k(0, _64K, 108); set_erase_sector_64k4b(0, _64K, 108); set_erase_sector_64k4b(0, _64K, 120); set_erase_sector_64k(0, _64K, 112); set_erase_sector_64k(0, _64K, 133); set_erase_sector_64k4b(0, _64K, 133); /*****************************************************************************/ #include "fmc100_spi_general.c" static struct spi_drv spi_driver_general = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_general_entry_4addr, .qe_enable = spi_general_qe_enable, }; static struct spi_drv spi_driver_no_qe = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_general_entry_4addr, .qe_enable = spi_do_not_qe_enable, }; #include "fmc100_spi_s25fl256s.c" static struct spi_drv spi_driver_s25fl256s = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_s25fl256s_entry_4addr, .qe_enable = spi_general_qe_enable, }; #include "fmc100_spi_w25q256fv.c" static struct spi_drv spi_driver_w25q256fv = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_w25q256fv_entry_4addr, .qe_enable = spi_w25q256fv_qe_enable, }; #include "fmc100_spi_nm25q128evb.c" static struct spi_drv spi_driver_nm25q128evb = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_nm25q128evb_entry_4addr, .qe_enable = spi_nm25q128evb_qe_enable, }; #include "fmc100_spi_mx25l25635e.c" static struct spi_drv spi_driver_mx25l25635e = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_general_entry_4addr, .qe_enable = spi_mx25l25635e_qe_enable, #ifdef CONFIG_DTR_MODE_SUPPORT .dtr_set_device = spi_mxic_output_driver_strength_set, #endif }; static struct spi_drv spi_driver_f25l64q = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_general_entry_4addr, .qe_enable = spi_mx25l25635e_qe_enable, }; #include "fmc100_spi_gd25qxxx.c" static struct spi_drv spi_driver_gd25qxxx = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_general_entry_4addr, .qe_enable = spi_gd25qxxx_qe_enable, }; #include "fmc100_spi_micron.c" static struct spi_drv spi_driver_micron = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_micron_entry_4addr, .qe_enable = spi_do_not_qe_enable, }; #include "fmc100_spi_xtx.c" static struct spi_drv spi_driver_xtx = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_general_entry_4addr, .qe_enable = spi_xtx_qe_enable, }; #include "fmc100_spi_puya.c" static struct spi_drv spi_driver_puya = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_puya_entry_4addr, .qe_enable = spi_puya_qe_enable, }; #include "fmc100_spi_issi.c" static struct spi_drv spi_driver_issi = { .wait_ready = spi_general_wait_ready, .write_enable = spi_general_write_enable, .entry_4addr = spi_s25fl256s_entry_4addr, .qe_enable = spi_issi_qe_enable, }; /*****************************************************************************/ #define SPI_NOR_ID_TBL_VER "1.0" /* ****** SPI Nor ID Table **************************************************** * Manufacturer Chip Name Chipsize Block Vol Operation * 1.0 Macronix/MXIC MX25L1606E 2M 64K 3V3 * Macronix/MXIC MX25V1635F 2M 64K 3V3 * Macronix/MXIC MX25L6436F 8M 64K 3V3 * Macronix/MXIC MX25R6435F 8M 64K 1V8/3V3 Add 14chips * Macronix/MXIC MX25U6435F 8M 64K 1V8 * Macronix/MXIC MX25U12835F 16M 64K 1V8 * Macronix/MXIC MX25U12832F 16M 64K 1V8 * Macronix/MXIC MX25F128XXX 16M 64K 3V3 * Macronix/MXIC MX25U25635F/45G 32M 64K 1V8 25645G-DTR * Macronix/MXIC MX25L(256/257) 32M 64K 3V3 25645G-DTR * Macronix/MXIC MX25U51245G 64M 64K 1V8 51245G-DTR * Macronix/MXIC MX25L51245G 64M 64K 3V3 * Macronix/MXIC MX66U1G45GM 128M 64K 1V8 * Spansion S25FL129P1 16M 64K 3V3 * Spansion S25FL256S 32M 64K 3V3 * Micron N25Q064A 8M 64K 3V3 * Micron N25QL064A 8M 64K 3V3 * Micron N25Q128A11/MT25QU128AB 16M 64K 1V8 * Micron N25QL128A 16M 64K 3V3 * Micron MT25QU256A 32M 64K 1V8 * Micron MT25QL256A 32M 64K 3V3 * Winbond W25Q16(B/C)V/S25FL016K 2M 64K 3V3 * Winbond W25Q32(B/F)V 4M 64K 3V3 * Winbond W25Q32FW 4M 64K 1V8 * Winbond W25Q64FW 8M 64K 1V8 * Winbond W25Q64FV(SPI)/W25Q64JV_IQ 8M 64K 3V3 * Winbond W25Q128FW 16M 64K 1V8 * Winbond W25Q128(B/F)V 16M 64K 3V3 * Winbond W25Q128JV_IM 16M 64K 3V3 DTR * Winbond W25Q256JWEIQ 32M 64K 1V8 * Winbond W25Q256JWFIM 32M 64K 1V8 * Winbond W25Q256JV-IQ 32M 64K 3V3 * ESMT/CFEON EN25Q32B 4M 64K 3V3 * ESMT/CFEON EN25Q64 8M 64K 3V3 * ESMT/CFEON EN25Q128 16M 64K 3V3 * ESMT/CFEON F25L64QA 8M 64K 3V3 * GD GD25Q64 8M 64K 3V3 * GD GD25LQ128 16M 64K 1V8 * GD GD25Q128 16M 64K 3V3 * GD GD25LQ64C 8M 64K 1V8 * GD GD25Q32 4M 64K 3V3 * GD GD25Q16C 2M 64K 3V3 * Paragon PN25F16S 2M 64K 3V3 * Paragon PN25F32S 4M 64K 3V3 * XMC XM25QH64AHIG 8M 64K 3V3 * XMC XM25QH128A 16M 64K 3V3 * XMC XM25QH128B 16M 64K 3V3 * XTX XT25F128BSSI/HGU 16M 64K 3V3 * XTX XM25QH64 8M 64K 3V3 * Puya P25Q128H-SUH-IT 16M 64K 3V3 * FM FM25Q64-SOB-T-G 8M 64K 3V3 * FM FM25Q128-SOB-T-G 16M 64K 3V3 * HUAHONG H25S64 8M 64K 3V3 * HUAHONG H25S128 16M 64K 3V3 * ISSI IS25WP512M-RMLA3 64M 64k 1V8 *****************************************************************************/ static struct spi_nor_info fmc_spi_nor_info_table[] = { /* name id id_len chipsize(Bytes) erasesize */ { "MX25L1606E", {0xc2, 0x20, 0x15}, 3, _2M, _64K, 3, { /* dummy clock:1 byte, read size:INFINITE bytes, * clock frq:33MHz */ &read_std(0, INFINITE, 33), /* 33MHz */ &read_fast(1, INFINITE, 86), /* 86MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ 0 }, { /* dummy clock:0 byte, write size:256 bytes, * clock frq:86MHz */ &write_std(0, 256, 86), /* 86MHz */ 0 }, { /* dummy clock:0byte, erase size:64K, * clock frq:86MHz */ &erase_sector_64k(0, _64K, 86), /* 86MHz */ 0 }, &spi_driver_no_qe, }, { "MX25L6436F", {0xc2, 0x20, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 133), /* 133MHz */ &read_dual(1, INFINITE, 133), /* 133MHz */ &read_dual_addr(1, INFINITE, 133), /* 133MHz */ &read_quad(1, INFINITE, 133), /* 133MHz */ &read_quad_addr(3, INFINITE, 133), /* 133MHz */ 0 }, { &write_std(0, 256, 133), /* 133MHz */ &write_quad_addr(0, 256, 133), /* 133MHz */ 0 }, { &erase_sector_64k(0, _64K, 133), /* 133MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25L51245G 3.3V */ { "MX25L51245G", {0xc2, 0x20, 0x1a}, 3, _64M, _64K, 4, { &read_std4b(0, INFINITE, 66), &read_fast4b(1, INFINITE, 133), &read_dual4b(1, INFINITE, 133), &read_dual_addr4b(1, INFINITE, 133), &read_quad4b(1, INFINITE, 133), &read_quad_addr4b(3, INFINITE, 133), 0 }, { &write_std4b(0, 256, 133), &write_quad_addr4b(0, 256, 133), 0 }, { &erase_sector_64k4b(0, _64K, 133), 0 }, &spi_driver_mx25l25635e, }, /* MX25V1635F 3.3V */ { "MX25V1635F", {0xc2, 0x23, 0x15}, 3, _2M, _64K, 3, { &read_std(0, INFINITE, 33), /* 33MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 33), /* 33MHz */ &write_quad_addr(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25R6435F Wide Voltage Range 1.65~3.6V */ { "MX25R6435F", {0xc2, 0x28, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 33), /* 33MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 33), /* 33MHz */ &write_quad_addr(0, 256, 33), /* 33MHz */ 0 }, { &erase_sector_64k(0, _64K, 33), /* 33MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25U1633F, 1.65-2.0V */ { "MX25U1633F", {0xc2, 0x25, 0x35}, 3, _2M, _64K, 3, { &read_std(0, INFINITE, 33), /* 33MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 33), /* 33MHz */ &write_quad_addr(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25U6435F, 1.65-2.0V */ { "MX25U6435F", {0xc2, 0x25, 0x37}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(1, INFINITE, 108), /* 108MHz */ &read_quad(1, INFINITE, 108), /* 108MHz */ &read_quad_addr(3, INFINITE, 108), /* 108MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad_addr(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25U12835F/MX25U12832F, 1.65-2.0V */ { "MX25U12835F/MX25U12832F", {0xc2, 0x25, 0x38}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 55), /* 55MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(1, INFINITE, 108), /* 108MHz */ &read_quad(1, INFINITE, 108), /* 108MHz */ &read_quad_addr(3, INFINITE, 108), /* 108MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad_addr(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_mx25l25635e, }, { "MX25L128XX", {0xc2, 0x20, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ #ifdef CONFIG_DTR_MODE_SUPPORT &read_quad_dtr(10, INFINITE, 100 /* 84 */), /* 100MHz */ #endif 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad_addr(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25U25635F/MX25U25645G, 1.65-2.0V */ { "MX25U25635F/45G", {0xc2, 0x25, 0x39}, 3, _32M, _64K, 4, { &read_std4b(0, INFINITE, 55), /* 55MHz */ &read_fast4b(1, INFINITE, 108), /* 108MHz */ &read_dual4b(1, INFINITE, 108), /* 108MHz */ &read_dual_addr4b(1, INFINITE, 108), /* 108MHz */ &read_quad4b(1, INFINITE, 108), /* 108MHz */ &read_quad_addr4b(3, INFINITE, 108), /* 108MHz */ #ifdef CONFIG_DTR_MODE_SUPPORT &read_quad_dtr4b(10, INFINITE, 100), /* 100MHz */ #endif 0 }, { &write_std4b(0, 256, 80), /* 80MHz */ &write_quad_addr4b(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25L25635F/MX25L25645G/MX25L25735F/MX25L25635E, 3.3V */ { "MX25L(256/257)XX", {0xc2, 0x20, 0x19}, 3, _32M, _64K, 4, { &read_std4b(0, INFINITE, 50), /* 50MHz */ &read_fast4b(1, INFINITE, 80 /* 84 */), /* 80MHz */ &read_dual4b(1, INFINITE, 80 /* 84 */), /* 80MHz */ &read_dual_addr4b(1, INFINITE, 80 /* 84 */), /* 80MHz */ &read_quad4b(1, INFINITE, 80 /* 84 */), /* 80MHz */ &read_quad_addr4b(3, INFINITE, 80 /* 84 */), /* 80MHz */ #ifdef CONFIG_DTR_MODE_SUPPORT &read_quad_dtr4b(10, INFINITE, 100 /* 84 */), /* 100MHz */ #endif 0 }, { &write_std4b(0, 256, 120 /* 133 */), /* 120MHz */ &write_quad_addr4b(0, 256, 120 /* 133 */), /* 120MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 120 /* 133 */), /* 120MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX25U51245G, 1.65-2.0V */ { "MX25U51245G", {0xc2, 0x25, 0x3a}, 3, _64M, _64K, 4, { &read_std4b(0, INFINITE, 66), /* 66MHz */ &read_fast4b(1, INFINITE, 104), /* 104MHz */ &read_dual4b(1, INFINITE, 104), /* 104MHz */ &read_dual_addr4b(1, INFINITE, 104), /* 104MHz */ &read_quad4b(1, INFINITE, 104), /* 104MHz */ &read_quad_addr4b(3, INFINITE, 104), /* 104MHz */ #ifdef CONFIG_DTR_MODE_SUPPORT &read_quad_dtr4b(10, INFINITE, 100), /* 100MHz */ #endif 0 }, { &write_std4b(0, 256, 104), /* 104MHz */ &write_quad_addr4b(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_mx25l25635e, }, /* MX66U1G45GM, 1.65-2.0V */ { "MX66U1G45GM", {0xc2, 0x25, 0x3b}, 3, _128M, _64K, 4, { &read_std4b(0, INFINITE, 50), &read_fast4b(1, INFINITE, 133), &read_dual4b(1, INFINITE, 133), &read_dual_addr4b(1, INFINITE, 133), &read_quad4b(1, INFINITE, 133), &read_quad_addr4b(3, INFINITE, 133), 0 }, { &write_std4b(0, 256, 133), &write_quad_addr4b(0, 256, 133), 0 }, { &erase_sector_64k4b(0, _64K, 133), 0 }, &spi_driver_mx25l25635e, }, /* Spansion/Cypress S25FL129P1 3.3V */ { "S25FL129P1", {0x01, 0x20, 0x18, 0x4d, 0x01, 0x80}, 6, (_64K * _256B), _64K, 3, { &read_std(0, INFINITE, 40), /* 40MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 64), /* 64MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_general, }, /* Spansion/Cypress S25FL256S 3.3V */ { "S25FL256S", {0x01, 0x02, 0x19, 0x4d, 0x01, 0x80}, 6, _32M, _64K, 4, { &read_std4b(0, INFINITE, 50), /* 50MHz */ &read_fast4b(1, INFINITE, 133), /* 133MHz */ &read_dual4b(1, INFINITE, 104), /* 104MHz */ &read_dual_addr4b(1, INFINITE, 104), /* 104MHz */ &read_quad4b(1, INFINITE, 104), /* 104MHz */ &read_quad_addr4b(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std4b(0, 256, 104), /* 104MHz */ &write_quad4b(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_s25fl256s, }, /* Micron N25Q064A 1.8V */ { "N25Q064A", {0x20, 0xbb, 0x17}, 3, (_64K * _128B), _64K, 3, { &read_std(0, INFINITE, 54), /* 54MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(2, INFINITE, 108), &read_quad(1, INFINITE, 108), /* 108MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_dual(0, 256, 108), /* 108MHz */ &write_dual_addr(0, 256, 108), /* 108MHz */ &write_quad(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_general, }, /* Micron "N25Q128A11/MT25QU128AB" 1.8V */ { "(MT)N25Q(U)128A", {0x20, 0xbb, 0x18}, 3, (_64K * _256B), _64K, 3, { &read_std(0, INFINITE, 54), /* 54MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(2, INFINITE, 108), /* 108MHz */ &read_quad(1, INFINITE, 108), /* 108MHz */ &read_quad_addr(5, INFINITE, 108), /* 108MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_dual(0, 256, 108), /* 108MHz */ &write_dual_addr(0, 256, 108), /* 108MHz */ &write_quad(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_micron, }, /* Micron N25QL064A 3.3V */ { "N25QL064A", {0x20, 0xba, 0x17}, 3, (_64K * _128B), _64K, 3, { &read_std(0, INFINITE, 54), /* 54MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(2, INFINITE, 84), /* 84MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(5, INFINITE, 84), /* 84MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_dual(0, 256, 75), /* 75MHz */ &write_dual_addr(0, 256, 75), /* 75MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 50), /* 50MHz */ 0 }, &spi_driver_micron, }, /* Micron MT(N)25QL128A 3.3V */ { "N25QL128A", {0x20, 0xba, 0x18}, 3, (_64K * _256B), _64K, 3, { &read_std(0, INFINITE, 54), /* 54MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 84), /* 84MHz */ &read_dual_addr(2, INFINITE, 84), /* 84MHz */ &read_quad(1, INFINITE, 84), /* 84MHz */ &read_quad_addr(5, INFINITE, 84), /* 84MHz */ 0 }, { &write_std(0, 256, 108), /* 108MHz */ &write_dual(0, 256, 108), /* 108MHz */ &write_dual_addr(0, 256, 108), /* 108MHz */ &write_quad(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_micron, }, /* Micron MT25QL256A 3.3V */ { "MT25QL256A", {0x20, 0xba, 0x19, 0x10, 0x44}, 5, (_64K * _512B), _64K, 4, { &read_std4b(0, INFINITE, 54), /* 54MHz */ &read_fast4b(1, INFINITE, 133), /* 133MHz */ &read_dual4b(1, INFINITE, 133), /* 133MHz */ &read_dual_addr4b(2, INFINITE, 133), /* 133MHz */ &read_quad4b(1, INFINITE, 133), /* 133MHz */ &read_quad_addr4b(5, INFINITE, 125), /* 125MHz */ 0 }, { &write_std4b(0, 256, 133), /* 133MHz */ &write_dual4b(0, 256, 133), /* 133MHz */ &write_dual_addr4b(0, 256, 133), /* 133MHz */ &write_quad4b(0, 256, 133), /* 133MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 133), /* 133MHz */ 0 }, &spi_driver_micron, }, /* Micron "MT25QU256A" 1.8V */ { "MT25QU256A", {0x20, 0xbb, 0x19}, 3, (_64K * _512B), _64K, 4, { &read_std4b(0, INFINITE, 54), /* 54MHz */ &read_fast4b(1, INFINITE, 80), /* 80MHz */ &read_dual4b(1, INFINITE, 80), /* 80MHz */ &read_dual_addr4b(2, INFINITE, 84), /* 84MHz */ &read_quad4b(1, INFINITE, 80), /* 80MHz */ &read_quad_addr4b(5, INFINITE, 84), /* 84MHz */ 0 }, { &write_std4b(0, 256, 80), /* 80MHz */ &write_dual4b(0, 256, 75), /* 75MHz */ &write_dual_addr4b(0, 256, 75), /* 75MHz */ &write_quad4b(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_micron, }, /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ { "W25Q16JV-IQ/S25FL016K", {0xef, 0x40, 0x15}, 3, (_64K * _32B), _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_general, }, { "W25Q32(B/F)V", {0xef, 0x40, 0x16}, 3, (_64K * _64B), _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_general, }, /* winbond w25q32fw is 1.8v */ { "W25Q32FW", {0xef, 0x60, 0x16}, 3, _4M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 133), /* 133MHz */ &read_dual(1, INFINITE, 133), /* 133MHz */ &read_quad(1, INFINITE, 133), /* 133MHz */ &read_quad_addr(3, INFINITE, 133), /* 133MHz */ 0 }, { &write_std(0, 256, 133), /* 133MHz */ &write_quad(0, 256, 133), /* 133MHz */ 0 }, { &erase_sector_64k(0, _64K, 133), /* 133MHz */ 0 }, &spi_driver_w25q256fv, }, { "W25Q64FV(SPI)/W25Q64JV_IQ", {0xef, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_general, }, /* winbond w25q64fw is 1.8v */ { "W25Q64FW", {0xef, 0x60, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_w25q256fv, }, /* winbond w25q128fw is 1.8v */ { "W25Q128FW", {0xef, 0x60, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_w25q256fv, }, { "W25Q128(B/F)V", {0xEF, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 33), /* 33MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, /* 70 */ 80), /* 80MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, /* 70 */ 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_w25q256fv, }, /* "W25Q128JV_IM" can support DTR mode 80MHz */ { "W25Q128JV_IM", {0xEF, 0x70, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 33), /* 33MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, /* 70 */80), /* 80MHz */ #ifdef CONFIG_DTR_MODE_SUPPORT &read_quad_dtr(8, INFINITE, 80), /* 80MHz */ #endif 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, /* 70 */ 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_w25q256fv, }, /* Winbond W25Q256(F/J)V-IQ */ { "W25Q256(F/J)V-IQ", {0xEF, 0x40, 0x19}, 3, _32M, _64K, 4, #ifdef CONFIG_AUTOMOTIVE_GRADE { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, #else { &read_std4b(0, INFINITE, 50), /* 50MHz */ &read_fast4b(1, INFINITE, 80), /* 80MHz */ &read_dual4b(1, INFINITE, 80), /* 80MHz */ &read_dual_addr4b(1, INFINITE, 80), /* 80MHz */ &read_quad4b(1, INFINITE, 80), /* 80MHz */ &read_quad_addr4b(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std4b(0, 256, 80), /* 80MHz */ &write_quad4b(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 104), /* 104MHz */ 0 }, #endif &spi_driver_w25q256fv, }, /* Winbond W25Q256JW-IQ 1.8V */ { "W25Q256JW-IQ", {0xEF, 0x60, 0x19}, 3, _32M, _64K, 4, { &read_std4b(0, INFINITE, 50), &read_fast4b(1, INFINITE, 133), &read_dual4b(1, INFINITE, 133), &read_dual_addr4b(1, INFINITE, 133), &read_quad4b(1, INFINITE, 133), &read_quad_addr4b(3, INFINITE, 133), 0 }, { &write_std4b(0, 256, 133), &write_quad4b(0, 256, 133), 0 }, { &erase_sector_64k4b(0, _64K, 133), 0 }, &spi_driver_w25q256fv, }, /* Winbond W25Q256JWFIM 1.8V */ { "W25Q256JWFIM", {0xEF, 0x80, 0x19}, 3, _32M, _64K, 4, { &read_std4b(0, INFINITE, 50), /* 50MHz */ &read_fast4b(1, INFINITE, 133), /* 133MHz */ &read_dual4b(1, INFINITE, 133), /* 133MHz */ &read_dual_addr4b(1, INFINITE, 133), /* 133MHz */ &read_quad4b(1, INFINITE, 133), /* 133MHz */ &read_quad_addr4b(3, INFINITE, 133), /* 133MHz */ 0 }, { &write_std4b(0, 256, 133), /* 133MHz */ &write_quad4b(0, 256, 133), /* 133MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 133), /* 133MHz */ 0 }, &spi_driver_w25q256fv, }, /* ESMT/CFEON */ { "EN25Q32B", {0x1c, 0x30, 0x16}, 3, (_64K * _64B), _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ /* &read_quad(3, INFINITE, 80), */ 0 }, { &write_std(0, 256, 80 /* 104 */), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80 /* 104 */), /* 80MHz */ 0 }, &spi_driver_general, }, { "EN25Q64", {0x1c, 0x30, 0x17}, 3, (_64K * _128B), _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 100), /* 100MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* CFEON EN25QH64A 3.3V */ { "EN25QH64A", {0x1c, 0x70, 0x17}, 3, (_64K * _128B), _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ #ifndef CONFIG_CLOSE_SPI_8PIN_4IO &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ #endif 0 }, { &write_std(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* CFEON EN25QH128A 3.3V */ { "EN25QH128A", {0x1c, 0x70, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ #ifndef CONFIG_CLOSE_SPI_8PIN_4IO &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ #endif 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, { "EN25Q128", {0x1c, 0x30, 0x18}, 3, (_64K * _256B), _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* ESMT */ { "F25L64QA", {0x8C, 0x41, 0x17}, 3, (_64K * _128B), _64K, 3, { &read_std(0, INFINITE, 66), /* 66MHz */ &read_fast(1, INFINITE, /* 66 */100), /* 100MHz */ &read_dual(1, INFINITE, /* 66 */80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, /* 66 */100), /* 100MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, /* 66 */100), /* 100MHz */ 0 }, &spi_driver_f25l64q, }, /* GD GD25LQ128 1.8V */ { "GD25LQ128", {0xC8, 0x60, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_gd25qxxx, }, { "GD25Q256", {0xC8, 0x40, 0x19}, 3, _32M, _64K, 4, { &read_std4b(0, INFINITE, 50), /* 50MHz */ &read_fast4b(1, INFINITE, 80), /* 80MHz */ &read_dual4b(1, INFINITE, 80), /* 80MHz */ &read_dual_addr4b(1, INFINITE, 80), /* 80MHz */ &read_quad4b(1, INFINITE, 80), /* 80MHz */ &read_quad_addr4b(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std4b(0, 256, 80), /* 80MHz */ &write_quad4b(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k4b(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_gd25qxxx, }, { "GD25Q128/GD25Q127", {0xC8, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 100), /* 100MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 100), /* 100MHz */ 0 }, &spi_driver_gd25qxxx, }, { "GD25Q64", {0xC8, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 66), /* 66MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 100), /* 100MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 100), /* 100MHz */ 0 }, &spi_driver_gd25qxxx, }, { "GD25Q16C", {0xC8, 0x40, 0x15}, 3, _2M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_gd25qxxx, }, /* GD GD25LQ16C 1.65~2.1V */ { "GD25LQ16C", {0xC8, 0x60, 0x15}, 3, _2M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_gd25qxxx, }, /* GD GD25LQ64C 1.8V */ { "GD25LQ64C", {0xC8, 0x60, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 80), /* 80MHz */ &read_dual_addr(1, INFINITE, 80), /* 80MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_gd25qxxx, }, { "GD25Q32", {0xC8, 0x40, 0x16}, 3, _4M, _64K, 3, { &read_std(0, INFINITE, 66), /* 66MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 100), /* 100MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 100), /* 100MHz */ 0 }, &spi_driver_gd25qxxx, }, /* Paragon 3.3V */ { "PN25F16S", {0xe0, 0x40, 0x15}, 3, _2M, _64K, 3, { &read_std(0, INFINITE, 55), /* 55MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(1, INFINITE, 108), /* 108MHz */ 0 }, { &write_std(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_general, }, { "PN25F32S", {0xe0, 0x40, 0x16}, 3, _4M, _64K, 3, { &read_std(0, INFINITE, 55), /* 55MHz */ &read_fast(1, INFINITE, 108), /* 108MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(1, INFINITE, 108), /* 108MHz */ &read_quad(1, INFINITE, 108), /* 108MHz */ &read_quad_addr(3, INFINITE, 108), /* 108MHz */ 0 }, { &write_std(0, 256, 108), /* 108MHz */ 0 }, { &erase_sector_64k(0, _64K, 108), /* 108MHz */ 0 }, &spi_driver_general, }, /* XMC */ { "XM25QH64AHIG", {0x20, 0x70, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* XMC 3.3v */ { "XM25QH128A", {0x20, 0x70, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* XMC */ { "XM25QH64B", {0x20, 0x60, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* XMC 3.3v */ { "XM25QH128B", {0x20, 0x60, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 104), /* 104MHz */ &read_quad_addr(3, INFINITE, 104), /* 104MHz */ 0 }, { &write_std(0, 256, 104), /* 104MHz */ &write_quad(0, 256, 104), /* 104MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_no_qe, }, /* XMC XM25QH64CHIQ 3.3V */ { "XM25QH64CHIQ", {0x20, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 50), /* 40MHz */ &read_fast(1, INFINITE, 133), /* 133MHz */ &read_dual(1, INFINITE, 133), /* 133MHz */ &read_dual_addr(1, INFINITE, 133), /* 133MHz */ &read_quad(1, INFINITE, 133), /* 133MHz */ &read_quad_addr(3, INFINITE, 133), /* 133MHz */ 0 }, { &write_std(0, 256, 133), /* 133MHz */ &write_quad(0, 256, 133), /* 133MHz */ 0 }, { &erase_sector_64k(0, _64K, 133), /* 133MHz */ 0 }, &spi_driver_general, }, /* XMC XM25QH128CHIQ 3.3v */ { "XM25QH128CHIQ", {0x20, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 50), /* 50MHz */ &read_fast(1, INFINITE, 133), /* 133MHz */ &read_dual(1, INFINITE, 133), /* 133MHz */ &read_dual_addr(1, INFINITE, 133), /* 133MHz */ &read_quad(1, INFINITE, 133), /* 133MHz */ &read_quad_addr(3, INFINITE, 133), /* 133MHz */ 0 }, { &write_std(0, 256, 133), /* 133MHz */ &write_quad(0, 256, 133), /* 133MHz */ 0 }, { &erase_sector_64k(0, _64K, 133), /* 133MHz */ 0 }, &spi_driver_general, }, /* CFX GM25Q128ASIG 3.3v */ { "GM25Q128ASIG", {0x1C, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 55), /* 55MHz */ &read_fast(1, INFINITE, 104), /* 104MHz */ &read_dual(1, INFINITE, 104), /* 104MHz */ &read_dual_addr(1, INFINITE, 104), /* 104MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 80), /* 80MHz */ 0 }, { &write_std(0, 256, 55), /* 55MHz */ &write_quad(0, 256, 80), /* 180MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_general, }, /* Nor-Men NM25Q128EVB 3.3v */ { "NM25Q128EVB", {0x52, 0x21, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 55), /* 55MHz */ &read_fast(1, INFINITE, 80), /* 104MHz */ &read_dual(1, INFINITE, 80), /* 104MHz */ &read_dual_addr(1, INFINITE, 80), /* 104MHz */ &read_quad(1, INFINITE, 80), /* 80MHz */ &read_quad_addr(3, INFINITE, 50), /* 80MHz */ 0 }, { &write_std(0, 256, 55), /* 55MHz */ &write_quad(0, 256, 80), /* 180MHz */ 0 }, { &erase_sector_64k(0, _64K, 104), /* 104MHz */ 0 }, &spi_driver_nm25q128evb, }, /* XTX 3.3v */ { "XT25F128BSSI/HGU", {0x0B, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(1, INFINITE, 108), /* 108MHz */ &read_quad(1, INFINITE, 108), /* 108MHz */ &read_quad_addr(3, INFINITE, 72), /* 72MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_xtx, }, { "XT25F64BSSI/HGU-S", {0x0B, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 80), /* 80MHz */ &read_dual(1, INFINITE, 108), /* 108MHz */ &read_dual_addr(1, INFINITE, 108), /* 108MHz */ &read_quad(1, INFINITE, 84), /* 84MHz */ &read_quad_addr(3, INFINITE, 72), /* 72MHz */ 0 }, { &write_std(0, 256, 80), /* 80MHz */ &write_quad(0, 256, 80), /* 80MHz */ 0 }, { &erase_sector_64k(0, _64K, 80), /* 80MHz */ 0 }, &spi_driver_xtx, }, /* Puya Semiconductor 3.3V */ { "P25Q128H", {0x85, 0x60, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 80), &read_fast(1, INFINITE, 104), &read_dual(1, INFINITE, 104), &read_dual_addr(1, INFINITE, 104), &read_quad(1, INFINITE, 104), &read_quad_addr(3, INFINITE, 104), 0 }, { &write_std(0, 256, 104), &write_quad(0, 256, 104), 0 }, { &erase_sector_64k(0, _64K, 104), 0 }, &spi_driver_puya, }, /* FM 3.3V */ { "FM25Q64-SOB-T-G", {0xa1, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 66), &read_fast(1, INFINITE, 104), &read_dual(1, INFINITE, 104), &read_dual_addr(1, INFINITE, 104), &read_quad(1, INFINITE, 104), &read_quad_addr(3, INFINITE, 104), 0 }, { &write_std(0, 256, 104), &write_quad(0, 256, 104), 0 }, { &erase_sector_64k(0, _64K, 104), 0 }, &spi_driver_general, }, /* FM 3.3V */ { "FM25Q128A-SOB-T-G", {0xa1, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 50), &read_fast(1, INFINITE, 104), &read_dual(1, INFINITE, 104), &read_dual_addr(1, INFINITE, 104), &read_quad(1, INFINITE, 104), &read_quad_addr(3, INFINITE, 104), 0 }, { &write_std(0, 256, 104), &write_quad(0, 256, 104), 0 }, { &erase_sector_64k(0, _64K, 104), 0 }, &spi_driver_general, }, /* HUAHONG 3.3V */ { "H25S64", {0x68, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 55), &read_fast(1, INFINITE, 55), &read_dual(1, INFINITE, 55), &read_dual_addr(1, INFINITE, 108), &read_quad(1, INFINITE, 108), &read_quad_addr(3, INFINITE, 108), 0 }, { &write_std(0, 256, 55), &write_quad(0, 256, 55), 0 }, { &erase_sector_64k(0, _64K, 55), 0 }, &spi_driver_w25q256fv, }, { "H25S128", {0x68, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 55), &read_fast(1, INFINITE, 55), &read_dual(1, INFINITE, 55), &read_dual_addr(1, INFINITE, 108), &read_quad(1, INFINITE, 108), &read_quad_addr(3, INFINITE, 108), 0 }, { &write_std(0, 256, 55), &write_quad(0, 256, 55), 0 }, { &erase_sector_64k(0, _64K, 55), 0 }, &spi_driver_w25q256fv, }, /* ISSI 1V8 */ { "IS25WP512M-RMLA3", {0x9d, 0x70, 0x1a}, 3, _64M, _64K, 4, { &read_std(0, INFINITE, 50), &read_fast(1, INFINITE, 112), &read_dual(1, INFINITE, 112), &read_dual_addr(1, INFINITE, 112), &read_quad(1, INFINITE, 112), &read_quad_addr(3, INFINITE, 112), 0 }, { &write_std(0, 256, 112), &write_quad(0, 256, 112), 0 }, { &erase_sector_64k(0, _64K, 112), 0 }, &spi_driver_issi, }, /* ZB 3.3V */ { "ZB25VQ64A", {0x5e, 0x40, 0x17}, 3, _8M, _64K, 3, { &read_std(0, INFINITE, 45), &read_fast(1, INFINITE, 104), &read_dual(1, INFINITE, 104), &read_dual_addr(1, INFINITE, 104), &read_quad(1, INFINITE, 104), &read_quad_addr(3, INFINITE, 104), 0 }, { &write_std(0, 256, 104), &write_quad(0, 256, 104), 0 }, { &erase_sector_64k(0, _64K, 104), 0 }, &spi_driver_general, }, /* ZB ZB25VQ128ASIG 3.3V */ { "ZB25VQ128ASIG", {0x5e, 0x40, 0x18}, 3, _16M, _64K, 3, { &read_std(0, INFINITE, 45), &read_fast(1, INFINITE, 104), &read_dual(1, INFINITE, 104), &read_dual_addr(1, INFINITE, 104), &read_quad(1, INFINITE, 104), &read_quad_addr(3, INFINITE, 104), 0 }, { &write_std(0, 256, 104), &write_quad(0, 256, 104), 0 }, { &erase_sector_64k(0, _64K, 104), 0 }, &spi_driver_general, }, {0, {0}, 0, 0, 0, 0, {0}, {0}, {0}, NULL}, }; /*****************************************************************************/ static struct spi_nor_info *fmc_spi_nor_serach_ids(u_char ids[], int len) { struct spi_nor_info *info = fmc_spi_nor_info_table; struct spi_nor_info *fit_info = NULL; if (len <= 0) return NULL; for (; info->name; info++) { if (memcmp(info->id, ids, info->id_len)) continue; if ((fit_info == NULL) || (fit_info->id_len < info->id_len)) fit_info = info; } return fit_info; } /*****************************************************************************/ static void fmc_spi_nor_search_rw(struct spi_nor_info *info, struct spi_op *spiop_rw, u_int iftype, u_int max_dummy, int rw_type) { int ix = 0; struct spi_op **spiop, **fitspiop; for (fitspiop = spiop = (rw_type ? info->write : info->read); (*spiop) && ix < MAX_SPI_OP; spiop++, ix++) if (((*spiop)->iftype & iftype) && ((*spiop)->dummy <= max_dummy) && ((*fitspiop)->iftype < (*spiop)->iftype)) fitspiop = spiop; memcpy(spiop_rw, (*fitspiop), sizeof(struct spi_op)); } /*****************************************************************************/ static void fmc_map_iftype_and_clock(struct fmc_spi *spi) { int ix; const int iftype_read[] = { SPI_IF_READ_STD, IF_TYPE_STD, SPI_IF_READ_FAST, IF_TYPE_STD, SPI_IF_READ_DUAL, IF_TYPE_DUAL, SPI_IF_READ_DUAL_ADDR, IF_TYPE_DIO, SPI_IF_READ_QUAD, IF_TYPE_QUAD, SPI_IF_READ_QUAD_ADDR, IF_TYPE_QIO, #ifdef CONFIG_DTR_MODE_SUPPORT SPI_IF_READ_QUAD_DTR, IF_TYPE_DTR, #endif 0, 0, }; const int iftype_write[] = { SPI_IF_WRITE_STD, IF_TYPE_STD, SPI_IF_WRITE_DUAL, IF_TYPE_DUAL, SPI_IF_WRITE_DUAL_ADDR, IF_TYPE_DIO, SPI_IF_WRITE_QUAD, IF_TYPE_QUAD, SPI_IF_WRITE_QUAD_ADDR, IF_TYPE_QIO, 0, 0, }; /* Only an even number of values is required,so increase length is 2 */ for (ix = 0; iftype_write[ix]; ix += 2) { if (spi->write->iftype == iftype_write[ix]) { spi->write->iftype = iftype_write[ix + 1]; break; } } fmc_get_fmc_best_2x_clock(&spi->write->clock); /* Only an even number of values is required,so increase length is 2 */ for (ix = 0; iftype_read[ix]; ix += 2) { if (spi->read->iftype == iftype_read[ix]) { spi->read->iftype = iftype_read[ix + 1]; break; } } #ifdef CONFIG_DTR_MODE_SUPPORT if (spi->dtr_mode_support) /* get the div4 clock */ fmc_get_fmc_best_4x_clock(&spi->read->clock); else fmc_get_fmc_best_2x_clock(&spi->read->clock); #else fmc_get_fmc_best_2x_clock(&spi->read->clock); #endif fmc_get_fmc_best_2x_clock(&spi->erase->clock); spi->erase->iftype = IF_TYPE_STD; } /*****************************************************************************/ void fmc_spi_nor_get_erase(struct spi_nor_info *info, struct spi_op *spiop_erase) { int ix; spiop_erase->size = 0; for (ix = 0; ix < MAX_SPI_OP; ix++) { if (info->erase[ix] == NULL) break; if (info->erasesize == info->erase[ix]->size) { memcpy(&spiop_erase[ix], info->erase[ix], sizeof(struct spi_op)); break; } } } /*****************************************************************************/ static void switch_to_4byte(struct fmc_spi *spi, u_char *ids, int len) { unsigned char manu_id = 0; /* auto check fmc_addr_mode 3 bytes or 4 bytes */ unsigned int start_up_addr_mode = get_fmc_boot_mode(); if(len < 3){ return; } manu_id = ids[0]; if ((spi->addrcycle == SPI_NOR_3BYTE_ADDR_LEN) && (start_up_addr_mode == SPI_NOR_ADDR_MODE_4_BYTES)) printf("\nError!!! the flash's addres len is 3bytes and start \ up address mode is 4bytes,please set the start up \ address mode to 3bytes mode"); if ((spi->addrcycle == SPI_NOR_4BYTE_ADDR_LEN) && (start_up_addr_mode == SPI_NOR_ADDR_MODE_3_BYTES)) { switch (manu_id) { case MID_WINBOND: #ifdef CONFIG_AUTOMOTIVE_GRADE if((ids[1] == 0x40) && (ids[2] == 0x19)) { /* W25Q256FV/W25Q256JV */ spi->driver->entry_4addr(spi, ENABLE); break; } #endif case MID_MXIC: case MID_MICRON: fmc_pr(BT_DBG, "\t|||-4-Byte Command Operation\n"); break; default: fmc_pr(BT_DBG, "\t|||-start up: 3-Byte mode\n"); spi->driver->entry_4addr(spi, ENABLE); break; } } else { fmc_pr(BT_DBG, "\t|||-start up: 4-Byte mode or 4-Byte Command\n"); } } /*****************************************************************************/ static void spi_data_init(struct fmc_spi *spi, struct spi_nor_info *spiinfo, unsigned char cs) { spi->name = spiinfo->name; spi->chipselect = cs; spi->chipsize = spiinfo->chipsize; spi->erasesize = spiinfo->erasesize; spi->addrcycle = spiinfo->addrcycle; spi->driver = spiinfo->driver; } /*****************************************************************************/ static void mtd_data_set(struct mtd_info_ex *mtd, struct spi_nor_info *spiinfo, struct fmc_spi *spi) { if (mtd->type == 0) { mtd->type = MTD_NORFLASH; mtd->chipsize = spi->chipsize; mtd->erasesize = spi->erasesize; mtd->pagesize = 1; mtd->addrcycle = spi->addrcycle; if (spiinfo->id_len > sizeof(mtd->ids)) { printf("BUG! ID len out of range.\n"); BUG(); } mtd->id_length = spiinfo->id_len; memcpy(mtd->ids, spiinfo->id, spiinfo->id_len); strncpy(mtd->name, spi->name, sizeof(mtd->name)); mtd->name[sizeof(mtd->name) - 1] = '\0'; } } /*****************************************************************************/ static void fmc_init_print(struct fmc_spi *spi) { const char *str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; #ifndef CONFIG_MINI_BOOT printf("Block:%sB ", ulltostr(spi->erasesize)); printf("Chip:%sB ", ulltostr(spi->chipsize)); printf("Name:\"%s\"\n", spi->name); #endif fmc_pr(BT_DBG, "\t|||-Read if: %s, cmd: %#X, clock reg: %#x\n", str[spi->read->iftype], spi->read->cmd, spi->read->clock); fmc_pr(BT_DBG, "\t|||-Write if: %s, cmd: %#X, clock reg: %#x\n", str[spi->write->iftype], spi->write->cmd, spi->write->clock); fmc_pr(BT_DBG, "\t|||-Erase if: %s, cmd: %#X, clock reg: %#x\n", str[spi->erase[0].iftype], spi->erase[0].cmd, spi->erase[0].clock); } /*****************************************************************************/ static void fmc_spi_map_op(struct spi_nor_info *spiinfo, struct fmc_spi *spi) { #ifdef CONFIG_DTR_MODE_SUPPORT if (spi->dtr_mode_support) { /* to match the best dummy/if_type/clock */ fmc_spi_nor_search_rw(spiinfo, spi->read, FMC_SPI_NOR_SUPPORT_READ, FMC_SPI_NOR_DTR_MAX_DUMMY, RW_OP_READ); } else { fmc_spi_nor_search_rw(spiinfo, spi->read, FMC_SPI_NOR_SUPPORT_READ, FMC_SPI_NOR_STR_MAX_DUMMY, RW_OP_READ); } #else /* to match the best dummy/if_type/clock */ fmc_spi_nor_search_rw(spiinfo, spi->read, FMC_SPI_NOR_SUPPORT_READ, FMC_SPI_NOR_STR_MAX_DUMMY, RW_OP_READ); #endif fmc_spi_nor_search_rw(spiinfo, spi->write, FMC_SPI_NOR_SUPPORT_WRITE, FMC_SPI_NOR_STR_MAX_DUMMY, RW_OP_WRITE); fmc_spi_nor_get_erase(spiinfo, spi->erase); fmc_map_iftype_and_clock(spi); } /*****************************************************************************/ int fmc_spi_nor_probe(struct mtd_info_ex *mtd, struct fmc_spi *spi) { unsigned char cs = 0; unsigned char ids[MAX_SPI_NOR_ID_LEN] = {0}; unsigned char ix = 0; unsigned char len = 0; unsigned int total = 0; char buffer[TMP_BUF_LEN]; unsigned char *fmc_cs = NULL; mtd->numchips = 0; #ifndef CONFIG_MINI_BOOT printf("SPI Nor ID Table Version %s\n", SPI_NOR_ID_TBL_VER); #endif for (cs = 0; cs < CONFIG_SPI_NOR_MAX_CHIP_NUM; cs++) { fmc_cs = get_cs_number(cs); if (*fmc_cs) { fmc_pr(BT_DBG, "\t|||-CS(%d) is occupied\n", cs); continue; } fmc100_read_ids(spi, cs, ids); /* can't find spi flash device, for id 0-2 */ if (!(ids[0] | ids[1] | ids[2]) || ((ids[0] & ids[1] & ids[2]) == 0xFF)) /* id 0-2 */ continue; len = sprintf(buffer, "SPI Nor(cs %d) ID: %#x %#x %#x", cs, ids[0], ids[1], ids[2]); /* id 0-2 */ spiinfo = fmc_spi_nor_serach_ids(ids, MAX_SPI_NOR_ID_LEN); /* id 3-7th */ for (ix = 3; (spiinfo) && (ix < spiinfo->id_len); ix++) len += sprintf(buffer + len, " %#x", ids[ix]); if (spiinfo) { #ifndef CONFIG_MINI_BOOT printf("%s\n", buffer); #endif fmc_pr(BT_DBG, "\t|||-CS-%d found SPI nor flash: %s\n", cs, spiinfo->name); spi_data_init(spi, spiinfo, cs); #ifdef CONFIG_DTR_MODE_SUPPORT /* to check weather current device support DTR mode */ fmc_check_spi_dtr_support(spi, ids, MAX_SPI_NOR_ID_LEN); #endif fmc_spi_map_op(spiinfo, spi); spi->driver->qe_enable(spi); switch_to_4byte(spi, ids, MAX_SPI_NOR_ID_LEN); fmc_init_print(spi); mtd_data_set(mtd, spiinfo, spi); mtd->numchips++; total += spi->chipsize; spi++; (*fmc_cs)++; } else { printf("SPI Nor(cs %d) ID: %#x %#x %#x can't find" " in the ID table !!!\n", cs, ids[0], ids[1], ids[2]); } } fmc_pr(BT_DBG, "\t||*-End probe SPI nor flash, num: %d\n", mtd->numchips); return mtd->numchips; } /*****************************************************************************/ #ifdef CONFIG_DTR_MODE_SUPPORT void spi_dtr_to_sdr_switch(struct fmc_spi *spi) { unsigned int ix = 0; unsigned int spi_dtr_dummy; struct spi_op **spiop, **fitspiop; const int iftype_read[] = { SPI_IF_READ_QUAD, IF_TYPE_QUAD, SPI_IF_READ_QUAD_ADDR, IF_TYPE_QIO, 0, 0, }; /* the dummy in SDR mode is impossible equal to DTR */ spi_dtr_dummy = spi->read->dummy; /* match the best clock and dummy value agian */ for (fitspiop = spiop = spiinfo->read; (*spiop) && ix < MAX_SPI_OP; spiop++, ix++) if (((*spiop)->iftype & FMC_SPI_NOR_SUPPORT_READ) && ((*spiop)->dummy != spi_dtr_dummy) && ((*fitspiop)->iftype < (*spiop)->iftype)) fitspiop = spiop; memcpy(spi->read, (*fitspiop), sizeof(struct spi_op)); /* to map the iftype and clock of SDR mode */ /* Only an even number of values is required,so increase length is 2 */ for (ix = 0; iftype_read[ix]; ix += 2) { if (spi->read->iftype == iftype_read[ix]) { spi->read->iftype = iftype_read[ix + 1]; break; } } fmc_get_fmc_best_2x_clock(&spi->read->clock); } #endif /* CONFIG_DTR_MODE_SUPPORT */