Patrick Georgi | ac95903 | 2020-05-05 22:49:26 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 2 | |
Elyes HAOUAS | 361a935 | 2019-12-18 21:26:33 +0100 | [diff] [blame] | 3 | #include <commonlib/helpers.h> |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 4 | #include <spi_flash.h> |
Furquan Shaikh | c28984d | 2016-11-20 21:04:00 -0800 | [diff] [blame] | 5 | #include <spi-generic.h> |
Edward O'Callaghan | c4561e2 | 2014-06-26 15:02:40 +1000 | [diff] [blame] | 6 | |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 7 | #include "spi_flash_internal.h" |
| 8 | |
| 9 | /* M25Pxx-specific commands */ |
| 10 | #define CMD_M25PXX_WREN 0x06 /* Write Enable */ |
| 11 | #define CMD_M25PXX_WRDI 0x04 /* Write Disable */ |
| 12 | #define CMD_M25PXX_RDSR 0x05 /* Read Status Register */ |
| 13 | #define CMD_M25PXX_WRSR 0x01 /* Write Status Register */ |
| 14 | #define CMD_M25PXX_READ 0x03 /* Read Data Bytes */ |
| 15 | #define CMD_M25PXX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ |
| 16 | #define CMD_M25PXX_PP 0x02 /* Page Program */ |
Scott Radcliffe | f5fcedf | 2014-10-14 15:40:59 -0400 | [diff] [blame] | 17 | #define CMD_M25PXX_SSE 0x20 /* Subsector Erase */ |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 18 | #define CMD_M25PXX_SE 0xd8 /* Sector Erase */ |
| 19 | #define CMD_M25PXX_BE 0xc7 /* Bulk Erase */ |
| 20 | #define CMD_M25PXX_DP 0xb9 /* Deep Power-down */ |
| 21 | #define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */ |
| 22 | |
Daisuke Nojiri | f0d038f | 2015-02-17 13:35:20 -0800 | [diff] [blame] | 23 | /* |
| 24 | * Device ID = (memory_type << 8) + memory_capacity |
| 25 | */ |
| 26 | #define STM_ID_M25P10 0x2011 |
Daisuke Nojiri | f0d038f | 2015-02-17 13:35:20 -0800 | [diff] [blame] | 27 | #define STM_ID_M25P20 0x2012 |
Daisuke Nojiri | f0d038f | 2015-02-17 13:35:20 -0800 | [diff] [blame] | 28 | #define STM_ID_M25P40 0x2013 |
Daisuke Nojiri | f0d038f | 2015-02-17 13:35:20 -0800 | [diff] [blame] | 29 | #define STM_ID_M25P80 0x2014 |
Stefan Tauner | cdb9b0c | 2018-08-03 01:13:41 +0200 | [diff] [blame] | 30 | #define STM_ID_M25P16 0x2015 |
| 31 | #define STM_ID_M25P32 0x2016 |
| 32 | #define STM_ID_M25P64 0x2017 |
Daisuke Nojiri | f0d038f | 2015-02-17 13:35:20 -0800 | [diff] [blame] | 33 | #define STM_ID_M25P128 0x2018 |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 34 | #define STM_ID_M25PX80 0x7114 |
| 35 | #define STM_ID_M25PX16 0x7115 |
| 36 | #define STM_ID_M25PX32 0x7116 |
| 37 | #define STM_ID_M25PX64 0x7117 |
| 38 | #define STM_ID_M25PE80 0x8014 |
| 39 | #define STM_ID_M25PE16 0x8015 |
| 40 | #define STM_ID_M25PE32 0x8016 |
| 41 | #define STM_ID_M25PE64 0x8017 |
| 42 | #define STM_ID_N25Q016__3E 0xba15 |
Stefan Tauner | cdb9b0c | 2018-08-03 01:13:41 +0200 | [diff] [blame] | 43 | #define STM_ID_N25Q032__3E 0xba16 |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 44 | #define STM_ID_N25Q064__3E 0xba17 |
| 45 | #define STM_ID_N25Q128__3E 0xba18 |
| 46 | #define STM_ID_N25Q256__3E 0xba19 |
| 47 | #define STM_ID_N25Q016__1E 0xbb15 |
| 48 | #define STM_ID_N25Q032__1E 0xbb16 |
| 49 | #define STM_ID_N25Q064__1E 0xbb17 |
| 50 | #define STM_ID_N25Q128__1E 0xbb18 |
| 51 | #define STM_ID_N25Q256__1E 0xbb19 |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 52 | |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 53 | static const struct spi_flash_part_id flash_table_se32k[] = { |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 54 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 55 | /* M25P10 */ |
| 56 | .id[0] = STM_ID_M25P10, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 57 | .nr_sectors_shift = 2, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 58 | }, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 59 | }; |
| 60 | |
| 61 | static const struct spi_flash_part_id flash_table_se64k[] = { |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 62 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 63 | /* M25P16 */ |
| 64 | .id[0] = STM_ID_M25P16, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 65 | .nr_sectors_shift = 5, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 66 | }, |
| 67 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 68 | /* M25P20 */ |
| 69 | .id[0] = STM_ID_M25P20, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 70 | .nr_sectors_shift = 2, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 71 | }, |
| 72 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 73 | /* M25P32 */ |
| 74 | .id[0] = STM_ID_M25P32, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 75 | .nr_sectors_shift = 6, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 76 | }, |
| 77 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 78 | /* M25P40 */ |
| 79 | .id[0] = STM_ID_M25P40, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 80 | .nr_sectors_shift = 3, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 81 | }, |
| 82 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 83 | /* M25P64 */ |
| 84 | .id[0] = STM_ID_M25P64, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 85 | .nr_sectors_shift = 7, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 86 | }, |
| 87 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 88 | /* M25P80 */ |
| 89 | .id[0] = STM_ID_M25P80, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 90 | .nr_sectors_shift = 4, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 91 | }, |
| 92 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 93 | /* M25PX80 */ |
| 94 | .id[0] = STM_ID_M25PX80, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 95 | .nr_sectors_shift = 4, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 96 | }, |
| 97 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 98 | /* M25PX16 */ |
| 99 | .id[0] = STM_ID_M25PX16, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 100 | .nr_sectors_shift = 5, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 101 | }, |
| 102 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 103 | /* M25PX32 */ |
| 104 | .id[0] = STM_ID_M25PX32, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 105 | .nr_sectors_shift = 6, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 106 | }, |
| 107 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 108 | /* M25PX64 */ |
| 109 | .id[0] = STM_ID_M25PX64, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 110 | .nr_sectors_shift = 7, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 111 | }, |
| 112 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 113 | /* M25PE80 */ |
| 114 | .id[0] = STM_ID_M25PE80, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 115 | .nr_sectors_shift = 4, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 116 | }, |
| 117 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 118 | /* M25PE16 */ |
| 119 | .id[0] = STM_ID_M25PE16, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 120 | .nr_sectors_shift = 5, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 121 | }, |
| 122 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 123 | /* M25PE32 */ |
| 124 | .id[0] = STM_ID_M25PE32, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 125 | .nr_sectors_shift = 6, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 126 | }, |
| 127 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 128 | /* M25PE64 */ |
| 129 | .id[0] = STM_ID_M25PE64, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 130 | .nr_sectors_shift = 7, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 131 | }, |
| 132 | }; |
| 133 | |
| 134 | static const struct spi_flash_part_id flash_table_se256k[] = { |
| 135 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 136 | /* M25P128 */ |
| 137 | .id[0] = STM_ID_M25P128, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 138 | .nr_sectors_shift = 6, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 139 | }, |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 140 | }; |
| 141 | |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 142 | static const struct spi_flash_part_id flash_table_sse[] = { |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 143 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 144 | /* N25Q016..3E */ |
| 145 | .id[0] = STM_ID_N25Q016__3E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 146 | .nr_sectors_shift = 9, |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 147 | }, |
| 148 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 149 | /* N25Q032..3E */ |
| 150 | .id[0] = STM_ID_N25Q032__3E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 151 | .nr_sectors_shift = 10, |
Stefan Tauner | cdb9b0c | 2018-08-03 01:13:41 +0200 | [diff] [blame] | 152 | }, |
| 153 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 154 | /* N25Q064..3E */ |
| 155 | .id[0] = STM_ID_N25Q064__3E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 156 | .nr_sectors_shift = 11, |
David Imhoff | 61295b5 | 2015-05-03 16:02:56 +0200 | [diff] [blame] | 157 | }, |
| 158 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 159 | /* N25Q128..3E */ |
| 160 | .id[0] = STM_ID_N25Q128__3E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 161 | .nr_sectors_shift = 12, |
David Imhoff | 7249572 | 2015-05-03 14:06:21 +0200 | [diff] [blame] | 162 | }, |
| 163 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 164 | /* N25Q256..3E */ |
| 165 | .id[0] = STM_ID_N25Q256__3E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 166 | .nr_sectors_shift = 13, |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 167 | }, |
| 168 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 169 | /* N25Q016..1E */ |
| 170 | .id[0] = STM_ID_N25Q016__1E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 171 | .nr_sectors_shift = 9, |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 172 | }, |
| 173 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 174 | /* N25Q032..1E */ |
| 175 | .id[0] = STM_ID_N25Q032__1E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 176 | .nr_sectors_shift = 10, |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 177 | }, |
| 178 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 179 | /* N25Q064..1E */ |
| 180 | .id[0] = STM_ID_N25Q064__1E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 181 | .nr_sectors_shift = 11, |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 182 | }, |
| 183 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 184 | /* N25Q128..1E */ |
| 185 | .id[0] = STM_ID_N25Q128__1E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 186 | .nr_sectors_shift = 12, |
Mike Banon | 5112292 | 2019-01-15 03:07:36 +0300 | [diff] [blame] | 187 | }, |
| 188 | { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 189 | /* N25Q256..1E */ |
| 190 | .id[0] = STM_ID_N25Q256__1E, |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 191 | .nr_sectors_shift = 13, |
Daisuke Nojiri | f0d038f | 2015-02-17 13:35:20 -0800 | [diff] [blame] | 192 | }, |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 193 | }; |
| 194 | |
Aaron Durbin | 1c3086a | 2020-01-03 15:58:11 -0700 | [diff] [blame] | 195 | int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode) |
| 196 | { |
| 197 | if (spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4)) |
| 198 | return -1; |
| 199 | |
| 200 | /* Assuming ST parts identify with 0x1X to release from deep |
| 201 | power down and read electronic signature. */ |
| 202 | if ((idcode[3] & 0xf0) != 0x10) |
| 203 | return -1; |
| 204 | |
| 205 | /* Fix up the idcode to mimic rdid jedec instruction. */ |
| 206 | idcode[0] = 0x20; |
| 207 | idcode[1] = 0x20; |
| 208 | idcode[2] = idcode[3] + 1; |
| 209 | |
| 210 | return 0; |
| 211 | } |
| 212 | |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 213 | const struct spi_flash_vendor_info spi_flash_stmicro1_vi = { |
| 214 | .id = VENDOR_ID_STMICRO, |
| 215 | .page_size_shift = 8, |
| 216 | .sector_size_kib_shift = 5, |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 217 | .match_id_mask[0] = 0xffff, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 218 | .ids = flash_table_se32k, |
| 219 | .nr_part_ids = ARRAY_SIZE(flash_table_se32k), |
| 220 | .desc = &spi_flash_pp_0xd8_sector_desc, |
| 221 | }; |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 222 | |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 223 | const struct spi_flash_vendor_info spi_flash_stmicro2_vi = { |
| 224 | .id = VENDOR_ID_STMICRO, |
| 225 | .page_size_shift = 8, |
| 226 | .sector_size_kib_shift = 6, |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 227 | .match_id_mask[0] = 0xffff, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 228 | .ids = flash_table_se64k, |
| 229 | .nr_part_ids = ARRAY_SIZE(flash_table_se64k), |
| 230 | .desc = &spi_flash_pp_0xd8_sector_desc, |
| 231 | }; |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 232 | |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 233 | const struct spi_flash_vendor_info spi_flash_stmicro3_vi = { |
| 234 | .id = VENDOR_ID_STMICRO, |
| 235 | .page_size_shift = 8, |
| 236 | .sector_size_kib_shift = 8, |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 237 | .match_id_mask[0] = 0xffff, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 238 | .ids = flash_table_se256k, |
| 239 | .nr_part_ids = ARRAY_SIZE(flash_table_se256k), |
| 240 | .desc = &spi_flash_pp_0xd8_sector_desc, |
| 241 | }; |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 242 | |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 243 | const struct spi_flash_vendor_info spi_flash_stmicro4_vi = { |
| 244 | .id = VENDOR_ID_STMICRO, |
| 245 | .page_size_shift = 8, |
| 246 | .sector_size_kib_shift = 2, |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 247 | .match_id_mask[0] = 0xffff, |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 248 | .ids = flash_table_sse, |
| 249 | .nr_part_ids = ARRAY_SIZE(flash_table_sse), |
| 250 | .desc = &spi_flash_pp_0x20_sector_desc, |
| 251 | }; |