Commit 4e09cc1e2c5d22735d0fa3d2d1eaecd27e19948e

Authored by Jagannadha Sutradharudu Teki
1 parent 12f00caf61

sf: Add extended read commands support

Current sf uses FAST_READ command, this patch adds support to
use the different/extended read command.

This implementation will determine the fastest command by taking
the supported commands from the flash and the controller, controller
is always been a priority.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>

Showing 5 changed files with 126 additions and 86 deletions Side-by-side Diff

drivers/mtd/spi/sf_internal.h
... ... @@ -36,6 +36,8 @@
36 36 /* Read commands */
37 37 #define CMD_READ_ARRAY_SLOW 0x03
38 38 #define CMD_READ_ARRAY_FAST 0x0b
  39 +#define CMD_READ_DUAL_OUTPUT_FAST 0x3b
  40 +#define CMD_READ_DUAL_IO_FAST 0xbb
39 41 #define CMD_READ_ID 0x9f
40 42  
41 43 /* Bank addr access commands */
drivers/mtd/spi/sf_ops.c
... ... @@ -285,7 +285,7 @@
285 285 return 0;
286 286 }
287 287  
288   - cmd[0] = CMD_READ_ARRAY_FAST;
  288 + cmd[0] = flash->read_cmd;
289 289 cmd[4] = 0x00;
290 290  
291 291 while (len) {
drivers/mtd/spi/sf_probe.c
... ... @@ -27,6 +27,7 @@
27 27 * @ext_jedec: Device ext_jedec ID
28 28 * @sector_size: Sector size of this device
29 29 * @nr_sectors: No.of sectors on this device
  30 + * @e_rd_cmd: Enum list for read commands
30 31 * @flags: Importent param, for flash specific behaviour
31 32 */
32 33 struct spi_flash_params {
33 34  
34 35  
35 36  
36 37  
37 38  
38 39  
39 40  
40 41  
... ... @@ -35,110 +36,111 @@
35 36 u16 ext_jedec;
36 37 u32 sector_size;
37 38 u32 nr_sectors;
  39 + u8 e_rd_cmd;
38 40 u16 flags;
39 41 };
40 42  
41 43 static const struct spi_flash_params spi_flash_params_table[] = {
42 44 #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */
43   - {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, SECT_4K},
44   - {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, SECT_4K},
45   - {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, SECT_4K},
46   - {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, SECT_4K},
47   - {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, SECT_4K},
48   - {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, SECT_4K},
49   - {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, SECT_4K},
50   - {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, SECT_4K},
  45 + {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, 0, SECT_4K},
  46 + {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, 0, SECT_4K},
  47 + {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, 0, SECT_4K},
  48 + {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, 0, SECT_4K},
  49 + {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, 0, SECT_4K},
  50 + {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, 0, SECT_4K},
  51 + {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, 0, SECT_4K},
  52 + {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, 0, SECT_4K},
51 53 #endif
52 54 #ifdef CONFIG_SPI_FLASH_EON /* EON */
53   - {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0},
54   - {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, SECT_4K},
55   - {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0},
56   - {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0},
  55 + {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0, 0},
  56 + {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, 0, SECT_4K},
  57 + {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0, 0},
  58 + {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0, 0},
57 59 #endif
58 60 #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */
59   - {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, SECT_4K},
60   - {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, SECT_4K},
  61 + {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, 0, SECT_4K},
  62 + {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, 0, SECT_4K},
61 63 #endif
62 64 #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
63   - {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, 0},
64   - {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0},
65   - {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0},
66   - {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0},
67   - {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0},
68   - {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0},
69   - {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, 0},
70   - {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, 0},
71   - {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, 0},
72   - {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, 0},
  65 + {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, 0, 0},
  66 + {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0, 0},
  67 + {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0, 0},
  68 + {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0, 0},
  69 + {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0, 0},
  70 + {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0, 0},
  71 + {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, 0, 0},
  72 + {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, 0, 0},
  73 + {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, 0, 0},
  74 + {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, 0, 0},
73 75 #endif
74 76 #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */
75   - {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0},
76   - {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0},
77   - {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0},
78   - {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0},
79   - {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, 0},
80   - {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, 0},
81   - {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, 0},
82   - {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, 0},
83   - {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, 0},
84   - {"S25FL256S_256K", 0x010219, 0x4d00, 64 * 1024, 512, 0},
85   - {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, 0},
86   - {"S25FL512S_256K", 0x010220, 0x4d00, 64 * 1024, 1024, 0},
87   - {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, 0},
  77 + {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0, 0},
  78 + {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0, 0},
  79 + {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0, 0},
  80 + {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0, 0},
  81 + {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, 0, 0},
  82 + {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, 0, 0},
  83 + {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, 0, 0},
  84 + {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, 0, 0},
  85 + {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, 0, 0},
  86 + {"S25FL256S_256K", 0x010219, 0x4d00, 64 * 1024, 512, RD_EXTN, 0},
  87 + {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_EXTN, 0},
  88 + {"S25FL512S_256K", 0x010220, 0x4d00, 64 * 1024, 1024, 0, 0},
  89 + {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, 0, 0},
88 90 #endif
89 91 #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
90   - {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0},
91   - {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0},
92   - {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0},
93   - {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0},
94   - {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0},
95   - {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0},
96   - {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0},
97   - {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0},
98   - {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, SECT_4K},
99   - {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, SECT_4K},
100   - {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, SECT_4K},
101   - {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, SECT_4K},
102   - {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, SECT_4K},
103   - {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, SECT_4K},
104   - {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, SECT_4K},
105   - {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, SECT_4K},
106   - {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K},
107   - {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K},
108   - {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K},
109   - {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K},
  92 + {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0, 0},
  93 + {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0, 0},
  94 + {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0, 0},
  95 + {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0, 0},
  96 + {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0, 0},
  97 + {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0, 0},
  98 + {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0, 0},
  99 + {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0, 0},
  100 + {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, 0, SECT_4K},
  101 + {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, 0, SECT_4K},
  102 + {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, 0, SECT_4K},
  103 + {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, 0, SECT_4K},
  104 + {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, 0, SECT_4K},
  105 + {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, 0, SECT_4K},
  106 + {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, 0, SECT_4K},
  107 + {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, 0, SECT_4K},
  108 + {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, 0, E_FSR | SECT_4K},
  109 + {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, 0, E_FSR | SECT_4K},
  110 + {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, 0, E_FSR | SECT_4K},
  111 + {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, 0, E_FSR | SECT_4K},
110 112 #endif
111 113 #ifdef CONFIG_SPI_FLASH_SST /* SST */
112   - {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WP},
113   - {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WP},
114   - {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WP},
115   - {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WP},
116   - {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, SECT_4K},
117   - {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WP},
118   - {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WP},
119   - {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WP},
120   - {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WP},
121   - {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WP},
  114 + {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, 0, SECT_4K | SST_WP},
  115 + {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, 0, SECT_4K | SST_WP},
  116 + {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, 0, SECT_4K | SST_WP},
  117 + {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, 0, SECT_4K | SST_WP},
  118 + {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, 0, SECT_4K},
  119 + {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, 0, SECT_4K | SST_WP},
  120 + {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, 0, SECT_4K | SST_WP},
  121 + {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, 0, SECT_4K | SST_WP},
  122 + {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, 0, SECT_4K | SST_WP},
  123 + {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, 0, SECT_4K | SST_WP},
122 124 #endif
123 125 #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */
124   - {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0},
125   - {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0},
126   - {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0},
127   - {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, SECT_4K},
128   - {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, SECT_4K},
129   - {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, SECT_4K},
130   - {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, SECT_4K},
131   - {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, SECT_4K},
132   - {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, SECT_4K},
133   - {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, SECT_4K},
134   - {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, SECT_4K},
135   - {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, SECT_4K},
136   - {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, SECT_4K},
137   - {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, SECT_4K},
138   - {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, SECT_4K},
139   - {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, SECT_4K},
140   - {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, SECT_4K},
141   - {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, SECT_4K},
  126 + {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0, 0},
  127 + {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0, 0},
  128 + {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0, 0},
  129 + {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, 0, SECT_4K},
  130 + {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, 0, SECT_4K},
  131 + {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, 0, SECT_4K},
  132 + {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, 0, SECT_4K},
  133 + {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, 0, SECT_4K},
  134 + {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, 0, SECT_4K},
  135 + {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, 0, SECT_4K},
  136 + {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, 0, SECT_4K},
  137 + {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, 0, SECT_4K},
  138 + {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, 0, SECT_4K},
  139 + {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, 0, SECT_4K},
  140 + {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, 0, SECT_4K},
  141 + {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, 0, SECT_4K},
  142 + {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, 0, SECT_4K},
  143 + {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, 0, SECT_4K},
142 144 #endif
143 145 /*
144 146 * Note:
145 147  
... ... @@ -155,12 +157,20 @@
155 157 */
156 158 };
157 159  
  160 +/* Read commands array */
  161 +static u8 spi_read_cmds_array[] = {
  162 + CMD_READ_ARRAY_SLOW,
  163 + CMD_READ_DUAL_OUTPUT_FAST,
  164 + CMD_READ_DUAL_IO_FAST,
  165 +};
  166 +
158 167 static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
159 168 u8 *idcode)
160 169 {
161 170 const struct spi_flash_params *params;
162 171 struct spi_flash *flash;
163 172 int i;
  173 + u8 cmd;
164 174 u16 jedec = idcode[1] << 8 | idcode[2];
165 175 u16 ext_jedec = idcode[3] << 8 | idcode[4];
166 176  
... ... @@ -220,6 +230,16 @@
220 230 } else {
221 231 flash->erase_cmd = CMD_ERASE_64K;
222 232 flash->erase_size = flash->sector_size;
  233 + }
  234 +
  235 + /* Look for the fastest read cmd */
  236 + cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
  237 + if (cmd) {
  238 + cmd = spi_read_cmds_array[cmd - 1];
  239 + flash->read_cmd = cmd;
  240 + } else {
  241 + /* Go for for default supported read cmd */
  242 + flash->read_cmd = CMD_READ_ARRAY_FAST;
223 243 }
224 244  
225 245 /* Poll cmd seclection */
... ... @@ -31,6 +31,12 @@
31 31 #define SPI_XFER_MMAP_END 0x10 /* Memory Mapped End */
32 32 #define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END)
33 33  
  34 +/* SPI RX operation modes */
  35 +#define SPI_OPM_RX_AS 1 << 0
  36 +#define SPI_OPM_RX_DOUT 1 << 1
  37 +#define SPI_OPM_RX_DIO 1 << 2
  38 +#define SPI_OPM_RX_EXTN SPI_OPM_RX_AS | SPI_OPM_RX_DOUT | SPI_OPM_RX_DIO
  39 +
34 40 /* Header byte that marks the start of the message */
35 41 #define SPI_PREAMBLE_END_BYTE 0xec
36 42  
... ... @@ -43,6 +49,7 @@
43 49 *
44 50 * @bus: ID of the bus that the slave is attached to.
45 51 * @cs: ID of the chip select connected to the slave.
  52 + * @op_mode_rx: SPI RX operation mode.
46 53 * @wordlen: Size of SPI word in number of bits
47 54 * @max_write_size: If non-zero, the maximum number of bytes which can
48 55 * be written at once, excluding command bytes.
... ... @@ -51,6 +58,7 @@
51 58 struct spi_slave {
52 59 unsigned int bus;
53 60 unsigned int cs;
  61 + u8 op_mode_rx;
54 62 unsigned int wordlen;
55 63 unsigned int max_write_size;
56 64 void *memory_map;
... ... @@ -19,6 +19,14 @@
19 19 #include <linux/types.h>
20 20 #include <linux/compiler.h>
21 21  
  22 +/* Enum list - Extended read commands */
  23 +enum spi_read_cmds {
  24 + ARRAY_SLOW = 1 << 0,
  25 + DUAL_OUTPUT_FAST = 1 << 1,
  26 + DUAL_IO_FAST = 1 << 2,
  27 +};
  28 +#define RD_EXTN ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST
  29 +
22 30 /**
23 31 * struct spi_flash - SPI flash structure
24 32 *
... ... @@ -33,6 +41,7 @@
33 41 * @bank_curr: Current flash bank
34 42 * @poll_cmd: Poll cmd - for flash erase/program
35 43 * @erase_cmd: Erase cmd 4K, 32K, 64K
  44 + * @read_cmd: Read cmd - Array Fast and Extn read
36 45 * @memory_map: Address of read-only SPI flash access
37 46 * @read: Flash read ops: Read len bytes at offset into buf
38 47 * Supported cmds: Fast Array Read
... ... @@ -57,6 +66,7 @@
57 66 #endif
58 67 u8 poll_cmd;
59 68 u8 erase_cmd;
  69 + u8 read_cmd;
60 70  
61 71 void *memory_map;
62 72 int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);