Commit 0c88a84ac6ac6840e62e0100f9cb9aa8d66ae927

Authored by Jagannadha Sutradharudu Teki
1 parent 469146c097

sf: Add GPL-2.0+ SPDX-License-Identifier for missing ones

Added GPL-2.0+ SPDX-License-Identifier for missed sf
source files.

Signed-off-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
Signed-off-by: Bo Shen <voice.shen@atmel.com>

Showing 5 changed files with 6 additions and 5 deletions Inline Diff

1 /* 1 /*
2 * Command for accessing SPI flash. 2 * Command for accessing SPI flash.
3 * 3 *
4 * Copyright (C) 2008 Atmel Corporation 4 * Copyright (C) 2008 Atmel Corporation
5 * Licensed under the GPL-2 or later. 5 *
6 * SPDX-License-Identifier: GPL-2.0+
6 */ 7 */
7 8
8 #include <common.h> 9 #include <common.h>
9 #include <div64.h> 10 #include <div64.h>
10 #include <malloc.h> 11 #include <malloc.h>
11 #include <spi_flash.h> 12 #include <spi_flash.h>
12 13
13 #include <asm/io.h> 14 #include <asm/io.h>
14 15
15 #ifndef CONFIG_SF_DEFAULT_SPEED 16 #ifndef CONFIG_SF_DEFAULT_SPEED
16 # define CONFIG_SF_DEFAULT_SPEED 1000000 17 # define CONFIG_SF_DEFAULT_SPEED 1000000
17 #endif 18 #endif
18 #ifndef CONFIG_SF_DEFAULT_MODE 19 #ifndef CONFIG_SF_DEFAULT_MODE
19 # define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 20 # define CONFIG_SF_DEFAULT_MODE SPI_MODE_3
20 #endif 21 #endif
21 #ifndef CONFIG_SF_DEFAULT_CS 22 #ifndef CONFIG_SF_DEFAULT_CS
22 # define CONFIG_SF_DEFAULT_CS 0 23 # define CONFIG_SF_DEFAULT_CS 0
23 #endif 24 #endif
24 #ifndef CONFIG_SF_DEFAULT_BUS 25 #ifndef CONFIG_SF_DEFAULT_BUS
25 # define CONFIG_SF_DEFAULT_BUS 0 26 # define CONFIG_SF_DEFAULT_BUS 0
26 #endif 27 #endif
27 28
28 static struct spi_flash *flash; 29 static struct spi_flash *flash;
29 30
30 31
31 /* 32 /*
32 * This function computes the length argument for the erase command. 33 * This function computes the length argument for the erase command.
33 * The length on which the command is to operate can be given in two forms: 34 * The length on which the command is to operate can be given in two forms:
34 * 1. <cmd> offset len - operate on <'offset', 'len') 35 * 1. <cmd> offset len - operate on <'offset', 'len')
35 * 2. <cmd> offset +len - operate on <'offset', 'round_up(len)') 36 * 2. <cmd> offset +len - operate on <'offset', 'round_up(len)')
36 * If the second form is used and the length doesn't fall on the 37 * If the second form is used and the length doesn't fall on the
37 * sector boundary, than it will be adjusted to the next sector boundary. 38 * sector boundary, than it will be adjusted to the next sector boundary.
38 * If it isn't in the flash, the function will fail (return -1). 39 * If it isn't in the flash, the function will fail (return -1).
39 * Input: 40 * Input:
40 * arg: length specification (i.e. both command arguments) 41 * arg: length specification (i.e. both command arguments)
41 * Output: 42 * Output:
42 * len: computed length for operation 43 * len: computed length for operation
43 * Return: 44 * Return:
44 * 1: success 45 * 1: success
45 * -1: failure (bad format, bad address). 46 * -1: failure (bad format, bad address).
46 */ 47 */
47 static int sf_parse_len_arg(char *arg, ulong *len) 48 static int sf_parse_len_arg(char *arg, ulong *len)
48 { 49 {
49 char *ep; 50 char *ep;
50 char round_up_len; /* indicates if the "+length" form used */ 51 char round_up_len; /* indicates if the "+length" form used */
51 ulong len_arg; 52 ulong len_arg;
52 53
53 round_up_len = 0; 54 round_up_len = 0;
54 if (*arg == '+') { 55 if (*arg == '+') {
55 round_up_len = 1; 56 round_up_len = 1;
56 ++arg; 57 ++arg;
57 } 58 }
58 59
59 len_arg = simple_strtoul(arg, &ep, 16); 60 len_arg = simple_strtoul(arg, &ep, 16);
60 if (ep == arg || *ep != '\0') 61 if (ep == arg || *ep != '\0')
61 return -1; 62 return -1;
62 63
63 if (round_up_len && flash->sector_size > 0) 64 if (round_up_len && flash->sector_size > 0)
64 *len = ROUND(len_arg, flash->sector_size); 65 *len = ROUND(len_arg, flash->sector_size);
65 else 66 else
66 *len = len_arg; 67 *len = len_arg;
67 68
68 return 1; 69 return 1;
69 } 70 }
70 71
71 /** 72 /**
72 * This function takes a byte length and a delta unit of time to compute the 73 * This function takes a byte length and a delta unit of time to compute the
73 * approximate bytes per second 74 * approximate bytes per second
74 * 75 *
75 * @param len amount of bytes currently processed 76 * @param len amount of bytes currently processed
76 * @param start_ms start time of processing in ms 77 * @param start_ms start time of processing in ms
77 * @return bytes per second if OK, 0 on error 78 * @return bytes per second if OK, 0 on error
78 */ 79 */
79 static ulong bytes_per_second(unsigned int len, ulong start_ms) 80 static ulong bytes_per_second(unsigned int len, ulong start_ms)
80 { 81 {
81 /* less accurate but avoids overflow */ 82 /* less accurate but avoids overflow */
82 if (len >= ((unsigned int) -1) / 1024) 83 if (len >= ((unsigned int) -1) / 1024)
83 return len / (max(get_timer(start_ms) / 1024, 1)); 84 return len / (max(get_timer(start_ms) / 1024, 1));
84 else 85 else
85 return 1024 * len / max(get_timer(start_ms), 1); 86 return 1024 * len / max(get_timer(start_ms), 1);
86 } 87 }
87 88
88 static int do_spi_flash_probe(int argc, char * const argv[]) 89 static int do_spi_flash_probe(int argc, char * const argv[])
89 { 90 {
90 unsigned int bus = CONFIG_SF_DEFAULT_BUS; 91 unsigned int bus = CONFIG_SF_DEFAULT_BUS;
91 unsigned int cs = CONFIG_SF_DEFAULT_CS; 92 unsigned int cs = CONFIG_SF_DEFAULT_CS;
92 unsigned int speed = CONFIG_SF_DEFAULT_SPEED; 93 unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
93 unsigned int mode = CONFIG_SF_DEFAULT_MODE; 94 unsigned int mode = CONFIG_SF_DEFAULT_MODE;
94 char *endp; 95 char *endp;
95 struct spi_flash *new; 96 struct spi_flash *new;
96 97
97 if (argc >= 2) { 98 if (argc >= 2) {
98 cs = simple_strtoul(argv[1], &endp, 0); 99 cs = simple_strtoul(argv[1], &endp, 0);
99 if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) 100 if (*argv[1] == 0 || (*endp != 0 && *endp != ':'))
100 return -1; 101 return -1;
101 if (*endp == ':') { 102 if (*endp == ':') {
102 if (endp[1] == 0) 103 if (endp[1] == 0)
103 return -1; 104 return -1;
104 105
105 bus = cs; 106 bus = cs;
106 cs = simple_strtoul(endp + 1, &endp, 0); 107 cs = simple_strtoul(endp + 1, &endp, 0);
107 if (*endp != 0) 108 if (*endp != 0)
108 return -1; 109 return -1;
109 } 110 }
110 } 111 }
111 112
112 if (argc >= 3) { 113 if (argc >= 3) {
113 speed = simple_strtoul(argv[2], &endp, 0); 114 speed = simple_strtoul(argv[2], &endp, 0);
114 if (*argv[2] == 0 || *endp != 0) 115 if (*argv[2] == 0 || *endp != 0)
115 return -1; 116 return -1;
116 } 117 }
117 if (argc >= 4) { 118 if (argc >= 4) {
118 mode = simple_strtoul(argv[3], &endp, 16); 119 mode = simple_strtoul(argv[3], &endp, 16);
119 if (*argv[3] == 0 || *endp != 0) 120 if (*argv[3] == 0 || *endp != 0)
120 return -1; 121 return -1;
121 } 122 }
122 123
123 new = spi_flash_probe(bus, cs, speed, mode); 124 new = spi_flash_probe(bus, cs, speed, mode);
124 if (!new) { 125 if (!new) {
125 printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); 126 printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
126 return 1; 127 return 1;
127 } 128 }
128 129
129 if (flash) 130 if (flash)
130 spi_flash_free(flash); 131 spi_flash_free(flash);
131 flash = new; 132 flash = new;
132 133
133 return 0; 134 return 0;
134 } 135 }
135 136
136 /** 137 /**
137 * Write a block of data to SPI flash, first checking if it is different from 138 * Write a block of data to SPI flash, first checking if it is different from
138 * what is already there. 139 * what is already there.
139 * 140 *
140 * If the data being written is the same, then *skipped is incremented by len. 141 * If the data being written is the same, then *skipped is incremented by len.
141 * 142 *
142 * @param flash flash context pointer 143 * @param flash flash context pointer
143 * @param offset flash offset to write 144 * @param offset flash offset to write
144 * @param len number of bytes to write 145 * @param len number of bytes to write
145 * @param buf buffer to write from 146 * @param buf buffer to write from
146 * @param cmp_buf read buffer to use to compare data 147 * @param cmp_buf read buffer to use to compare data
147 * @param skipped Count of skipped data (incremented by this function) 148 * @param skipped Count of skipped data (incremented by this function)
148 * @return NULL if OK, else a string containing the stage which failed 149 * @return NULL if OK, else a string containing the stage which failed
149 */ 150 */
150 static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, 151 static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
151 size_t len, const char *buf, char *cmp_buf, size_t *skipped) 152 size_t len, const char *buf, char *cmp_buf, size_t *skipped)
152 { 153 {
153 debug("offset=%#x, sector_size=%#x, len=%#zx\n", 154 debug("offset=%#x, sector_size=%#x, len=%#zx\n",
154 offset, flash->sector_size, len); 155 offset, flash->sector_size, len);
155 /* Read the entire sector so to allow for rewriting */ 156 /* Read the entire sector so to allow for rewriting */
156 if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf)) 157 if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf))
157 return "read"; 158 return "read";
158 /* Compare only what is meaningful (len) */ 159 /* Compare only what is meaningful (len) */
159 if (memcmp(cmp_buf, buf, len) == 0) { 160 if (memcmp(cmp_buf, buf, len) == 0) {
160 debug("Skip region %x size %zx: no change\n", 161 debug("Skip region %x size %zx: no change\n",
161 offset, len); 162 offset, len);
162 *skipped += len; 163 *skipped += len;
163 return NULL; 164 return NULL;
164 } 165 }
165 /* Erase the entire sector */ 166 /* Erase the entire sector */
166 if (spi_flash_erase(flash, offset, flash->sector_size)) 167 if (spi_flash_erase(flash, offset, flash->sector_size))
167 return "erase"; 168 return "erase";
168 /* Write the initial part of the block from the source */ 169 /* Write the initial part of the block from the source */
169 if (spi_flash_write(flash, offset, len, buf)) 170 if (spi_flash_write(flash, offset, len, buf))
170 return "write"; 171 return "write";
171 /* If it's a partial sector, rewrite the existing part */ 172 /* If it's a partial sector, rewrite the existing part */
172 if (len != flash->sector_size) { 173 if (len != flash->sector_size) {
173 /* Rewrite the original data to the end of the sector */ 174 /* Rewrite the original data to the end of the sector */
174 if (spi_flash_write(flash, offset + len, 175 if (spi_flash_write(flash, offset + len,
175 flash->sector_size - len, &cmp_buf[len])) 176 flash->sector_size - len, &cmp_buf[len]))
176 return "write"; 177 return "write";
177 } 178 }
178 179
179 return NULL; 180 return NULL;
180 } 181 }
181 182
182 /** 183 /**
183 * Update an area of SPI flash by erasing and writing any blocks which need 184 * Update an area of SPI flash by erasing and writing any blocks which need
184 * to change. Existing blocks with the correct data are left unchanged. 185 * to change. Existing blocks with the correct data are left unchanged.
185 * 186 *
186 * @param flash flash context pointer 187 * @param flash flash context pointer
187 * @param offset flash offset to write 188 * @param offset flash offset to write
188 * @param len number of bytes to write 189 * @param len number of bytes to write
189 * @param buf buffer to write from 190 * @param buf buffer to write from
190 * @return 0 if ok, 1 on error 191 * @return 0 if ok, 1 on error
191 */ 192 */
192 static int spi_flash_update(struct spi_flash *flash, u32 offset, 193 static int spi_flash_update(struct spi_flash *flash, u32 offset,
193 size_t len, const char *buf) 194 size_t len, const char *buf)
194 { 195 {
195 const char *err_oper = NULL; 196 const char *err_oper = NULL;
196 char *cmp_buf; 197 char *cmp_buf;
197 const char *end = buf + len; 198 const char *end = buf + len;
198 size_t todo; /* number of bytes to do in this pass */ 199 size_t todo; /* number of bytes to do in this pass */
199 size_t skipped = 0; /* statistics */ 200 size_t skipped = 0; /* statistics */
200 const ulong start_time = get_timer(0); 201 const ulong start_time = get_timer(0);
201 size_t scale = 1; 202 size_t scale = 1;
202 const char *start_buf = buf; 203 const char *start_buf = buf;
203 ulong delta; 204 ulong delta;
204 205
205 if (end - buf >= 200) 206 if (end - buf >= 200)
206 scale = (end - buf) / 100; 207 scale = (end - buf) / 100;
207 cmp_buf = malloc(flash->sector_size); 208 cmp_buf = malloc(flash->sector_size);
208 if (cmp_buf) { 209 if (cmp_buf) {
209 ulong last_update = get_timer(0); 210 ulong last_update = get_timer(0);
210 211
211 for (; buf < end && !err_oper; buf += todo, offset += todo) { 212 for (; buf < end && !err_oper; buf += todo, offset += todo) {
212 todo = min(end - buf, flash->sector_size); 213 todo = min(end - buf, flash->sector_size);
213 if (get_timer(last_update) > 100) { 214 if (get_timer(last_update) > 100) {
214 printf(" \rUpdating, %zu%% %lu B/s", 215 printf(" \rUpdating, %zu%% %lu B/s",
215 100 - (end - buf) / scale, 216 100 - (end - buf) / scale,
216 bytes_per_second(buf - start_buf, 217 bytes_per_second(buf - start_buf,
217 start_time)); 218 start_time));
218 last_update = get_timer(0); 219 last_update = get_timer(0);
219 } 220 }
220 err_oper = spi_flash_update_block(flash, offset, todo, 221 err_oper = spi_flash_update_block(flash, offset, todo,
221 buf, cmp_buf, &skipped); 222 buf, cmp_buf, &skipped);
222 } 223 }
223 } else { 224 } else {
224 err_oper = "malloc"; 225 err_oper = "malloc";
225 } 226 }
226 free(cmp_buf); 227 free(cmp_buf);
227 putc('\r'); 228 putc('\r');
228 if (err_oper) { 229 if (err_oper) {
229 printf("SPI flash failed in %s step\n", err_oper); 230 printf("SPI flash failed in %s step\n", err_oper);
230 return 1; 231 return 1;
231 } 232 }
232 233
233 delta = get_timer(start_time); 234 delta = get_timer(start_time);
234 printf("%zu bytes written, %zu bytes skipped", len - skipped, 235 printf("%zu bytes written, %zu bytes skipped", len - skipped,
235 skipped); 236 skipped);
236 printf(" in %ld.%lds, speed %ld B/s\n", 237 printf(" in %ld.%lds, speed %ld B/s\n",
237 delta / 1000, delta % 1000, bytes_per_second(len, start_time)); 238 delta / 1000, delta % 1000, bytes_per_second(len, start_time));
238 239
239 return 0; 240 return 0;
240 } 241 }
241 242
242 static int do_spi_flash_read_write(int argc, char * const argv[]) 243 static int do_spi_flash_read_write(int argc, char * const argv[])
243 { 244 {
244 unsigned long addr; 245 unsigned long addr;
245 unsigned long offset; 246 unsigned long offset;
246 unsigned long len; 247 unsigned long len;
247 void *buf; 248 void *buf;
248 char *endp; 249 char *endp;
249 int ret = 1; 250 int ret = 1;
250 251
251 if (argc < 4) 252 if (argc < 4)
252 return -1; 253 return -1;
253 254
254 addr = simple_strtoul(argv[1], &endp, 16); 255 addr = simple_strtoul(argv[1], &endp, 16);
255 if (*argv[1] == 0 || *endp != 0) 256 if (*argv[1] == 0 || *endp != 0)
256 return -1; 257 return -1;
257 offset = simple_strtoul(argv[2], &endp, 16); 258 offset = simple_strtoul(argv[2], &endp, 16);
258 if (*argv[2] == 0 || *endp != 0) 259 if (*argv[2] == 0 || *endp != 0)
259 return -1; 260 return -1;
260 len = simple_strtoul(argv[3], &endp, 16); 261 len = simple_strtoul(argv[3], &endp, 16);
261 if (*argv[3] == 0 || *endp != 0) 262 if (*argv[3] == 0 || *endp != 0)
262 return -1; 263 return -1;
263 264
264 /* Consistency checking */ 265 /* Consistency checking */
265 if (offset + len > flash->size) { 266 if (offset + len > flash->size) {
266 printf("ERROR: attempting %s past flash size (%#x)\n", 267 printf("ERROR: attempting %s past flash size (%#x)\n",
267 argv[0], flash->size); 268 argv[0], flash->size);
268 return 1; 269 return 1;
269 } 270 }
270 271
271 buf = map_physmem(addr, len, MAP_WRBACK); 272 buf = map_physmem(addr, len, MAP_WRBACK);
272 if (!buf) { 273 if (!buf) {
273 puts("Failed to map physical memory\n"); 274 puts("Failed to map physical memory\n");
274 return 1; 275 return 1;
275 } 276 }
276 277
277 if (strcmp(argv[0], "update") == 0) { 278 if (strcmp(argv[0], "update") == 0) {
278 ret = spi_flash_update(flash, offset, len, buf); 279 ret = spi_flash_update(flash, offset, len, buf);
279 } else if (strncmp(argv[0], "read", 4) == 0 || 280 } else if (strncmp(argv[0], "read", 4) == 0 ||
280 strncmp(argv[0], "write", 5) == 0) { 281 strncmp(argv[0], "write", 5) == 0) {
281 int read; 282 int read;
282 283
283 read = strncmp(argv[0], "read", 4) == 0; 284 read = strncmp(argv[0], "read", 4) == 0;
284 if (read) 285 if (read)
285 ret = spi_flash_read(flash, offset, len, buf); 286 ret = spi_flash_read(flash, offset, len, buf);
286 else 287 else
287 ret = spi_flash_write(flash, offset, len, buf); 288 ret = spi_flash_write(flash, offset, len, buf);
288 289
289 printf("SF: %zu bytes @ %#x %s: %s\n", (size_t)len, (u32)offset, 290 printf("SF: %zu bytes @ %#x %s: %s\n", (size_t)len, (u32)offset,
290 read ? "Read" : "Written", ret ? "ERROR" : "OK"); 291 read ? "Read" : "Written", ret ? "ERROR" : "OK");
291 } 292 }
292 293
293 unmap_physmem(buf, len); 294 unmap_physmem(buf, len);
294 295
295 return ret == 0 ? 0 : 1; 296 return ret == 0 ? 0 : 1;
296 } 297 }
297 298
298 static int do_spi_flash_erase(int argc, char * const argv[]) 299 static int do_spi_flash_erase(int argc, char * const argv[])
299 { 300 {
300 unsigned long offset; 301 unsigned long offset;
301 unsigned long len; 302 unsigned long len;
302 char *endp; 303 char *endp;
303 int ret; 304 int ret;
304 305
305 if (argc < 3) 306 if (argc < 3)
306 return -1; 307 return -1;
307 308
308 offset = simple_strtoul(argv[1], &endp, 16); 309 offset = simple_strtoul(argv[1], &endp, 16);
309 if (*argv[1] == 0 || *endp != 0) 310 if (*argv[1] == 0 || *endp != 0)
310 return -1; 311 return -1;
311 312
312 ret = sf_parse_len_arg(argv[2], &len); 313 ret = sf_parse_len_arg(argv[2], &len);
313 if (ret != 1) 314 if (ret != 1)
314 return -1; 315 return -1;
315 316
316 /* Consistency checking */ 317 /* Consistency checking */
317 if (offset + len > flash->size) { 318 if (offset + len > flash->size) {
318 printf("ERROR: attempting %s past flash size (%#x)\n", 319 printf("ERROR: attempting %s past flash size (%#x)\n",
319 argv[0], flash->size); 320 argv[0], flash->size);
320 return 1; 321 return 1;
321 } 322 }
322 323
323 ret = spi_flash_erase(flash, offset, len); 324 ret = spi_flash_erase(flash, offset, len);
324 printf("SF: %zu bytes @ %#x Erased: %s\n", (size_t)len, (u32)offset, 325 printf("SF: %zu bytes @ %#x Erased: %s\n", (size_t)len, (u32)offset,
325 ret ? "ERROR" : "OK"); 326 ret ? "ERROR" : "OK");
326 327
327 return ret == 0 ? 0 : 1; 328 return ret == 0 ? 0 : 1;
328 } 329 }
329 330
330 #ifdef CONFIG_CMD_SF_TEST 331 #ifdef CONFIG_CMD_SF_TEST
331 enum { 332 enum {
332 STAGE_ERASE, 333 STAGE_ERASE,
333 STAGE_CHECK, 334 STAGE_CHECK,
334 STAGE_WRITE, 335 STAGE_WRITE,
335 STAGE_READ, 336 STAGE_READ,
336 337
337 STAGE_COUNT, 338 STAGE_COUNT,
338 }; 339 };
339 340
340 static char *stage_name[STAGE_COUNT] = { 341 static char *stage_name[STAGE_COUNT] = {
341 "erase", 342 "erase",
342 "check", 343 "check",
343 "write", 344 "write",
344 "read", 345 "read",
345 }; 346 };
346 347
347 struct test_info { 348 struct test_info {
348 int stage; 349 int stage;
349 int bytes; 350 int bytes;
350 unsigned base_ms; 351 unsigned base_ms;
351 unsigned time_ms[STAGE_COUNT]; 352 unsigned time_ms[STAGE_COUNT];
352 }; 353 };
353 354
354 static void show_time(struct test_info *test, int stage) 355 static void show_time(struct test_info *test, int stage)
355 { 356 {
356 uint64_t speed; /* KiB/s */ 357 uint64_t speed; /* KiB/s */
357 int bps; /* Bits per second */ 358 int bps; /* Bits per second */
358 359
359 speed = (long long)test->bytes * 1000; 360 speed = (long long)test->bytes * 1000;
360 do_div(speed, test->time_ms[stage] * 1024); 361 do_div(speed, test->time_ms[stage] * 1024);
361 bps = speed * 8; 362 bps = speed * 8;
362 363
363 printf("%d %s: %d ticks, %d KiB/s %d.%03d Mbps\n", stage, 364 printf("%d %s: %d ticks, %d KiB/s %d.%03d Mbps\n", stage,
364 stage_name[stage], test->time_ms[stage], 365 stage_name[stage], test->time_ms[stage],
365 (int)speed, bps / 1000, bps % 1000); 366 (int)speed, bps / 1000, bps % 1000);
366 } 367 }
367 368
368 static void spi_test_next_stage(struct test_info *test) 369 static void spi_test_next_stage(struct test_info *test)
369 { 370 {
370 test->time_ms[test->stage] = get_timer(test->base_ms); 371 test->time_ms[test->stage] = get_timer(test->base_ms);
371 show_time(test, test->stage); 372 show_time(test, test->stage);
372 test->base_ms = get_timer(0); 373 test->base_ms = get_timer(0);
373 test->stage++; 374 test->stage++;
374 } 375 }
375 376
376 /** 377 /**
377 * Run a test on the SPI flash 378 * Run a test on the SPI flash
378 * 379 *
379 * @param flash SPI flash to use 380 * @param flash SPI flash to use
380 * @param buf Source buffer for data to write 381 * @param buf Source buffer for data to write
381 * @param len Size of data to read/write 382 * @param len Size of data to read/write
382 * @param offset Offset within flash to check 383 * @param offset Offset within flash to check
383 * @param vbuf Verification buffer 384 * @param vbuf Verification buffer
384 * @return 0 if ok, -1 on error 385 * @return 0 if ok, -1 on error
385 */ 386 */
386 static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len, 387 static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len,
387 ulong offset, uint8_t *vbuf) 388 ulong offset, uint8_t *vbuf)
388 { 389 {
389 struct test_info test; 390 struct test_info test;
390 int i; 391 int i;
391 392
392 printf("SPI flash test:\n"); 393 printf("SPI flash test:\n");
393 memset(&test, '\0', sizeof(test)); 394 memset(&test, '\0', sizeof(test));
394 test.base_ms = get_timer(0); 395 test.base_ms = get_timer(0);
395 test.bytes = len; 396 test.bytes = len;
396 if (spi_flash_erase(flash, offset, len)) { 397 if (spi_flash_erase(flash, offset, len)) {
397 printf("Erase failed\n"); 398 printf("Erase failed\n");
398 return -1; 399 return -1;
399 } 400 }
400 spi_test_next_stage(&test); 401 spi_test_next_stage(&test);
401 402
402 if (spi_flash_read(flash, offset, len, vbuf)) { 403 if (spi_flash_read(flash, offset, len, vbuf)) {
403 printf("Check read failed\n"); 404 printf("Check read failed\n");
404 return -1; 405 return -1;
405 } 406 }
406 for (i = 0; i < len; i++) { 407 for (i = 0; i < len; i++) {
407 if (vbuf[i] != 0xff) { 408 if (vbuf[i] != 0xff) {
408 printf("Check failed at %d\n", i); 409 printf("Check failed at %d\n", i);
409 print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0); 410 print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0);
410 return -1; 411 return -1;
411 } 412 }
412 } 413 }
413 spi_test_next_stage(&test); 414 spi_test_next_stage(&test);
414 415
415 if (spi_flash_write(flash, offset, len, buf)) { 416 if (spi_flash_write(flash, offset, len, buf)) {
416 printf("Write failed\n"); 417 printf("Write failed\n");
417 return -1; 418 return -1;
418 } 419 }
419 memset(vbuf, '\0', len); 420 memset(vbuf, '\0', len);
420 spi_test_next_stage(&test); 421 spi_test_next_stage(&test);
421 422
422 if (spi_flash_read(flash, offset, len, vbuf)) { 423 if (spi_flash_read(flash, offset, len, vbuf)) {
423 printf("Read failed\n"); 424 printf("Read failed\n");
424 return -1; 425 return -1;
425 } 426 }
426 spi_test_next_stage(&test); 427 spi_test_next_stage(&test);
427 428
428 for (i = 0; i < len; i++) { 429 for (i = 0; i < len; i++) {
429 if (buf[i] != vbuf[i]) { 430 if (buf[i] != vbuf[i]) {
430 printf("Verify failed at %d, good data:\n", i); 431 printf("Verify failed at %d, good data:\n", i);
431 print_buffer(i, buf + i, 1, min(len - i, 0x40), 0); 432 print_buffer(i, buf + i, 1, min(len - i, 0x40), 0);
432 printf("Bad data:\n"); 433 printf("Bad data:\n");
433 print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0); 434 print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0);
434 return -1; 435 return -1;
435 } 436 }
436 } 437 }
437 printf("Test passed\n"); 438 printf("Test passed\n");
438 for (i = 0; i < STAGE_COUNT; i++) 439 for (i = 0; i < STAGE_COUNT; i++)
439 show_time(&test, i); 440 show_time(&test, i);
440 441
441 return 0; 442 return 0;
442 } 443 }
443 444
444 static int do_spi_flash_test(int argc, char * const argv[]) 445 static int do_spi_flash_test(int argc, char * const argv[])
445 { 446 {
446 unsigned long offset; 447 unsigned long offset;
447 unsigned long len; 448 unsigned long len;
448 uint8_t *buf = (uint8_t *)CONFIG_SYS_TEXT_BASE; 449 uint8_t *buf = (uint8_t *)CONFIG_SYS_TEXT_BASE;
449 char *endp; 450 char *endp;
450 uint8_t *vbuf; 451 uint8_t *vbuf;
451 int ret; 452 int ret;
452 453
453 offset = simple_strtoul(argv[1], &endp, 16); 454 offset = simple_strtoul(argv[1], &endp, 16);
454 if (*argv[1] == 0 || *endp != 0) 455 if (*argv[1] == 0 || *endp != 0)
455 return -1; 456 return -1;
456 len = simple_strtoul(argv[2], &endp, 16); 457 len = simple_strtoul(argv[2], &endp, 16);
457 if (*argv[2] == 0 || *endp != 0) 458 if (*argv[2] == 0 || *endp != 0)
458 return -1; 459 return -1;
459 460
460 vbuf = malloc(len); 461 vbuf = malloc(len);
461 if (!vbuf) { 462 if (!vbuf) {
462 printf("Cannot allocate memory\n"); 463 printf("Cannot allocate memory\n");
463 return 1; 464 return 1;
464 } 465 }
465 buf = malloc(len); 466 buf = malloc(len);
466 if (!buf) { 467 if (!buf) {
467 free(vbuf); 468 free(vbuf);
468 printf("Cannot allocate memory\n"); 469 printf("Cannot allocate memory\n");
469 return 1; 470 return 1;
470 } 471 }
471 472
472 memcpy(buf, (char *)CONFIG_SYS_TEXT_BASE, len); 473 memcpy(buf, (char *)CONFIG_SYS_TEXT_BASE, len);
473 ret = spi_flash_test(flash, buf, len, offset, vbuf); 474 ret = spi_flash_test(flash, buf, len, offset, vbuf);
474 free(vbuf); 475 free(vbuf);
475 free(buf); 476 free(buf);
476 if (ret) { 477 if (ret) {
477 printf("Test failed\n"); 478 printf("Test failed\n");
478 return 1; 479 return 1;
479 } 480 }
480 481
481 return 0; 482 return 0;
482 } 483 }
483 #endif /* CONFIG_CMD_SF_TEST */ 484 #endif /* CONFIG_CMD_SF_TEST */
484 485
485 static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, 486 static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc,
486 char * const argv[]) 487 char * const argv[])
487 { 488 {
488 const char *cmd; 489 const char *cmd;
489 int ret; 490 int ret;
490 491
491 /* need at least two arguments */ 492 /* need at least two arguments */
492 if (argc < 2) 493 if (argc < 2)
493 goto usage; 494 goto usage;
494 495
495 cmd = argv[1]; 496 cmd = argv[1];
496 --argc; 497 --argc;
497 ++argv; 498 ++argv;
498 499
499 if (strcmp(cmd, "probe") == 0) { 500 if (strcmp(cmd, "probe") == 0) {
500 ret = do_spi_flash_probe(argc, argv); 501 ret = do_spi_flash_probe(argc, argv);
501 goto done; 502 goto done;
502 } 503 }
503 504
504 /* The remaining commands require a selected device */ 505 /* The remaining commands require a selected device */
505 if (!flash) { 506 if (!flash) {
506 puts("No SPI flash selected. Please run `sf probe'\n"); 507 puts("No SPI flash selected. Please run `sf probe'\n");
507 return 1; 508 return 1;
508 } 509 }
509 510
510 if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0 || 511 if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0 ||
511 strcmp(cmd, "update") == 0) 512 strcmp(cmd, "update") == 0)
512 ret = do_spi_flash_read_write(argc, argv); 513 ret = do_spi_flash_read_write(argc, argv);
513 else if (strcmp(cmd, "erase") == 0) 514 else if (strcmp(cmd, "erase") == 0)
514 ret = do_spi_flash_erase(argc, argv); 515 ret = do_spi_flash_erase(argc, argv);
515 #ifdef CONFIG_CMD_SF_TEST 516 #ifdef CONFIG_CMD_SF_TEST
516 else if (!strcmp(cmd, "test")) 517 else if (!strcmp(cmd, "test"))
517 ret = do_spi_flash_test(argc, argv); 518 ret = do_spi_flash_test(argc, argv);
518 #endif 519 #endif
519 else 520 else
520 ret = -1; 521 ret = -1;
521 522
522 done: 523 done:
523 if (ret != -1) 524 if (ret != -1)
524 return ret; 525 return ret;
525 526
526 usage: 527 usage:
527 return CMD_RET_USAGE; 528 return CMD_RET_USAGE;
528 } 529 }
529 530
530 #ifdef CONFIG_CMD_SF_TEST 531 #ifdef CONFIG_CMD_SF_TEST
531 #define SF_TEST_HELP "\nsf test offset len " \ 532 #define SF_TEST_HELP "\nsf test offset len " \
532 "- run a very basic destructive test" 533 "- run a very basic destructive test"
533 #else 534 #else
534 #define SF_TEST_HELP 535 #define SF_TEST_HELP
535 #endif 536 #endif
536 537
537 U_BOOT_CMD( 538 U_BOOT_CMD(
538 sf, 5, 1, do_spi_flash, 539 sf, 5, 1, do_spi_flash,
539 "SPI flash sub-system", 540 "SPI flash sub-system",
540 "probe [[bus:]cs] [hz] [mode] - init flash device on given SPI bus\n" 541 "probe [[bus:]cs] [hz] [mode] - init flash device on given SPI bus\n"
541 " and chip select\n" 542 " and chip select\n"
542 "sf read addr offset len - read `len' bytes starting at\n" 543 "sf read addr offset len - read `len' bytes starting at\n"
543 " `offset' to memory at `addr'\n" 544 " `offset' to memory at `addr'\n"
544 "sf write addr offset len - write `len' bytes from memory\n" 545 "sf write addr offset len - write `len' bytes from memory\n"
545 " at `addr' to flash at `offset'\n" 546 " at `addr' to flash at `offset'\n"
546 "sf erase offset [+]len - erase `len' bytes from `offset'\n" 547 "sf erase offset [+]len - erase `len' bytes from `offset'\n"
547 " `+len' round up `len' to block size\n" 548 " `+len' round up `len' to block size\n"
548 "sf update addr offset len - erase and write `len' bytes from memory\n" 549 "sf update addr offset len - erase and write `len' bytes from memory\n"
549 " at `addr' to flash at `offset'" 550 " at `addr' to flash at `offset'"
550 SF_TEST_HELP 551 SF_TEST_HELP
551 ); 552 );
552 553
drivers/mtd/spi/sf.c
1 /* 1 /*
2 * SPI flash interface 2 * SPI flash interface
3 * 3 *
4 * Copyright (C) 2008 Atmel Corporation 4 * Copyright (C) 2008 Atmel Corporation
5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik 5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6 * 6 *
7 * Licensed under the GPL-2 or later. 7 * SPDX-License-Identifier: GPL-2.0+
8 */ 8 */
9 9
10 #include <common.h> 10 #include <common.h>
11 #include <spi.h> 11 #include <spi.h>
12 12
13 static int spi_flash_read_write(struct spi_slave *spi, 13 static int spi_flash_read_write(struct spi_slave *spi,
14 const u8 *cmd, size_t cmd_len, 14 const u8 *cmd, size_t cmd_len,
15 const u8 *data_out, u8 *data_in, 15 const u8 *data_out, u8 *data_in,
16 size_t data_len) 16 size_t data_len)
17 { 17 {
18 unsigned long flags = SPI_XFER_BEGIN; 18 unsigned long flags = SPI_XFER_BEGIN;
19 int ret; 19 int ret;
20 20
21 if (data_len == 0) 21 if (data_len == 0)
22 flags |= SPI_XFER_END; 22 flags |= SPI_XFER_END;
23 23
24 ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); 24 ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
25 if (ret) { 25 if (ret) {
26 debug("SF: Failed to send command (%zu bytes): %d\n", 26 debug("SF: Failed to send command (%zu bytes): %d\n",
27 cmd_len, ret); 27 cmd_len, ret);
28 } else if (data_len != 0) { 28 } else if (data_len != 0) {
29 ret = spi_xfer(spi, data_len * 8, data_out, data_in, 29 ret = spi_xfer(spi, data_len * 8, data_out, data_in,
30 SPI_XFER_END); 30 SPI_XFER_END);
31 if (ret) 31 if (ret)
32 debug("SF: Failed to transfer %zu bytes of data: %d\n", 32 debug("SF: Failed to transfer %zu bytes of data: %d\n",
33 data_len, ret); 33 data_len, ret);
34 } 34 }
35 35
36 return ret; 36 return ret;
37 } 37 }
38 38
39 int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, 39 int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
40 size_t cmd_len, void *data, size_t data_len) 40 size_t cmd_len, void *data, size_t data_len)
41 { 41 {
42 return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len); 42 return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
43 } 43 }
44 44
45 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len) 45 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
46 { 46 {
47 return spi_flash_cmd_read(spi, &cmd, 1, response, len); 47 return spi_flash_cmd_read(spi, &cmd, 1, response, len);
48 } 48 }
49 49
50 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, 50 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
51 const void *data, size_t data_len) 51 const void *data, size_t data_len)
52 { 52 {
53 return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len); 53 return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
54 } 54 }
55 55
drivers/mtd/spi/sf_internal.h
1 /* 1 /*
2 * SPI flash internal definitions 2 * SPI flash internal definitions
3 * 3 *
4 * Copyright (C) 2008 Atmel Corporation 4 * Copyright (C) 2008 Atmel Corporation
5 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. 5 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
6 * 6 *
7 * Licensed under the GPL-2 or later. 7 * SPDX-License-Identifier: GPL-2.0+
8 */ 8 */
9 9
10 #ifndef _SF_INTERNAL_H_ 10 #ifndef _SF_INTERNAL_H_
11 #define _SF_INTERNAL_H_ 11 #define _SF_INTERNAL_H_
12 12
13 #define SPI_FLASH_16MB_BOUN 0x1000000 13 #define SPI_FLASH_16MB_BOUN 0x1000000
14 14
15 /* SECT flags */ 15 /* SECT flags */
16 #define SECT_4K (1 << 1) 16 #define SECT_4K (1 << 1)
17 #define SECT_32K (1 << 2) 17 #define SECT_32K (1 << 2)
18 #define E_FSR (1 << 3) 18 #define E_FSR (1 << 3)
19 19
20 /* Erase commands */ 20 /* Erase commands */
21 #define CMD_ERASE_4K 0x20 21 #define CMD_ERASE_4K 0x20
22 #define CMD_ERASE_32K 0x52 22 #define CMD_ERASE_32K 0x52
23 #define CMD_ERASE_CHIP 0xc7 23 #define CMD_ERASE_CHIP 0xc7
24 #define CMD_ERASE_64K 0xd8 24 #define CMD_ERASE_64K 0xd8
25 25
26 /* Write commands */ 26 /* Write commands */
27 #define CMD_WRITE_STATUS 0x01 27 #define CMD_WRITE_STATUS 0x01
28 #define CMD_PAGE_PROGRAM 0x02 28 #define CMD_PAGE_PROGRAM 0x02
29 #define CMD_WRITE_DISABLE 0x04 29 #define CMD_WRITE_DISABLE 0x04
30 #define CMD_READ_STATUS 0x05 30 #define CMD_READ_STATUS 0x05
31 #define CMD_WRITE_ENABLE 0x06 31 #define CMD_WRITE_ENABLE 0x06
32 #define CMD_READ_CONFIG 0x35 32 #define CMD_READ_CONFIG 0x35
33 #define CMD_FLAG_STATUS 0x70 33 #define CMD_FLAG_STATUS 0x70
34 34
35 /* Read commands */ 35 /* Read commands */
36 #define CMD_READ_ARRAY_SLOW 0x03 36 #define CMD_READ_ARRAY_SLOW 0x03
37 #define CMD_READ_ARRAY_FAST 0x0b 37 #define CMD_READ_ARRAY_FAST 0x0b
38 #define CMD_READ_ID 0x9f 38 #define CMD_READ_ID 0x9f
39 39
40 /* Bank addr access commands */ 40 /* Bank addr access commands */
41 #ifdef CONFIG_SPI_FLASH_BAR 41 #ifdef CONFIG_SPI_FLASH_BAR
42 # define CMD_BANKADDR_BRWR 0x17 42 # define CMD_BANKADDR_BRWR 0x17
43 # define CMD_BANKADDR_BRRD 0x16 43 # define CMD_BANKADDR_BRRD 0x16
44 # define CMD_EXTNADDR_WREAR 0xC5 44 # define CMD_EXTNADDR_WREAR 0xC5
45 # define CMD_EXTNADDR_RDEAR 0xC8 45 # define CMD_EXTNADDR_RDEAR 0xC8
46 #endif 46 #endif
47 47
48 /* Common status */ 48 /* Common status */
49 #define STATUS_WIP 0x01 49 #define STATUS_WIP 0x01
50 #define STATUS_PEC 0x80 50 #define STATUS_PEC 0x80
51 51
52 /* Flash timeout values */ 52 /* Flash timeout values */
53 #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) 53 #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ)
54 #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) 54 #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ)
55 #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ) 55 #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
56 56
57 /* SST specific */ 57 /* SST specific */
58 #ifdef CONFIG_SPI_FLASH_SST 58 #ifdef CONFIG_SPI_FLASH_SST
59 # define SST_WP 0x01 /* Supports AAI word program */ 59 # define SST_WP 0x01 /* Supports AAI word program */
60 # define CMD_SST_BP 0x02 /* Byte Program */ 60 # define CMD_SST_BP 0x02 /* Byte Program */
61 # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ 61 # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */
62 62
63 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, 63 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
64 const void *buf); 64 const void *buf);
65 #endif 65 #endif
66 66
67 /* Send a single-byte command to the device and read the response */ 67 /* Send a single-byte command to the device and read the response */
68 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); 68 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
69 69
70 /* 70 /*
71 * Send a multi-byte command to the device and read the response. Used 71 * Send a multi-byte command to the device and read the response. Used
72 * for flash array reads, etc. 72 * for flash array reads, etc.
73 */ 73 */
74 int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, 74 int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
75 size_t cmd_len, void *data, size_t data_len); 75 size_t cmd_len, void *data, size_t data_len);
76 76
77 /* 77 /*
78 * Send a multi-byte command to the device followed by (optional) 78 * Send a multi-byte command to the device followed by (optional)
79 * data. Used for programming the flash array, etc. 79 * data. Used for programming the flash array, etc.
80 */ 80 */
81 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, 81 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
82 const void *data, size_t data_len); 82 const void *data, size_t data_len);
83 83
84 84
85 /* Flash erase(sectors) operation, support all possible erase commands */ 85 /* Flash erase(sectors) operation, support all possible erase commands */
86 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); 86 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
87 87
88 /* Program the status register */ 88 /* Program the status register */
89 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); 89 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
90 90
91 /* Set quad enbale bit */ 91 /* Set quad enbale bit */
92 int spi_flash_set_qeb(struct spi_flash *flash); 92 int spi_flash_set_qeb(struct spi_flash *flash);
93 93
94 /* Enable writing on the SPI flash */ 94 /* Enable writing on the SPI flash */
95 static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) 95 static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
96 { 96 {
97 return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0); 97 return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
98 } 98 }
99 99
100 /* Disable writing on the SPI flash */ 100 /* Disable writing on the SPI flash */
101 static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) 101 static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
102 { 102 {
103 return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); 103 return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
104 } 104 }
105 105
106 /* 106 /*
107 * Send the read status command to the device and wait for the wip 107 * Send the read status command to the device and wait for the wip
108 * (write-in-progress) bit to clear itself. 108 * (write-in-progress) bit to clear itself.
109 */ 109 */
110 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); 110 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
111 111
112 /* 112 /*
113 * Used for spi_flash write operation 113 * Used for spi_flash write operation
114 * - SPI claim 114 * - SPI claim
115 * - spi_flash_cmd_write_enable 115 * - spi_flash_cmd_write_enable
116 * - spi_flash_cmd_write 116 * - spi_flash_cmd_write
117 * - spi_flash_cmd_wait_ready 117 * - spi_flash_cmd_wait_ready
118 * - SPI release 118 * - SPI release
119 */ 119 */
120 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, 120 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
121 size_t cmd_len, const void *buf, size_t buf_len); 121 size_t cmd_len, const void *buf, size_t buf_len);
122 122
123 /* 123 /*
124 * Flash write operation, support all possible write commands. 124 * Flash write operation, support all possible write commands.
125 * Write the requested data out breaking it up into multiple write 125 * Write the requested data out breaking it up into multiple write
126 * commands as needed per the write size. 126 * commands as needed per the write size.
127 */ 127 */
128 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, 128 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
129 size_t len, const void *buf); 129 size_t len, const void *buf);
130 130
131 /* 131 /*
132 * Same as spi_flash_cmd_read() except it also claims/releases the SPI 132 * Same as spi_flash_cmd_read() except it also claims/releases the SPI
133 * bus. Used as common part of the ->read() operation. 133 * bus. Used as common part of the ->read() operation.
134 */ 134 */
135 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, 135 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
136 size_t cmd_len, void *data, size_t data_len); 136 size_t cmd_len, void *data, size_t data_len);
137 137
138 /* Flash read operation, support all possible read commands */ 138 /* Flash read operation, support all possible read commands */
139 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, 139 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
140 size_t len, void *data); 140 size_t len, void *data);
141 141
142 #endif /* _SF_INTERNAL_H_ */ 142 #endif /* _SF_INTERNAL_H_ */
143 143
drivers/mtd/spi/sf_ops.c
1 /* 1 /*
2 * SPI flash operations 2 * SPI flash operations
3 * 3 *
4 * Copyright (C) 2008 Atmel Corporation 4 * Copyright (C) 2008 Atmel Corporation
5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik 5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. 6 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
7 * 7 *
8 * Licensed under the GPL-2 or later. 8 * SPDX-License-Identifier: GPL-2.0+
9 */ 9 */
10 10
11 #include <common.h> 11 #include <common.h>
12 #include <spi.h> 12 #include <spi.h>
13 #include <spi_flash.h> 13 #include <spi_flash.h>
14 #include <watchdog.h> 14 #include <watchdog.h>
15 15
16 #include "sf_internal.h" 16 #include "sf_internal.h"
17 17
18 static void spi_flash_addr(u32 addr, u8 *cmd) 18 static void spi_flash_addr(u32 addr, u8 *cmd)
19 { 19 {
20 /* cmd[0] is actual command */ 20 /* cmd[0] is actual command */
21 cmd[1] = addr >> 16; 21 cmd[1] = addr >> 16;
22 cmd[2] = addr >> 8; 22 cmd[2] = addr >> 8;
23 cmd[3] = addr >> 0; 23 cmd[3] = addr >> 0;
24 } 24 }
25 25
26 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) 26 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
27 { 27 {
28 u8 cmd; 28 u8 cmd;
29 int ret; 29 int ret;
30 30
31 cmd = CMD_WRITE_STATUS; 31 cmd = CMD_WRITE_STATUS;
32 ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); 32 ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
33 if (ret < 0) { 33 if (ret < 0) {
34 debug("SF: fail to write status register\n"); 34 debug("SF: fail to write status register\n");
35 return ret; 35 return ret;
36 } 36 }
37 37
38 return 0; 38 return 0;
39 } 39 }
40 40
41 #ifdef CONFIG_SPI_FLASH_BAR 41 #ifdef CONFIG_SPI_FLASH_BAR
42 static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) 42 static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
43 { 43 {
44 u8 cmd; 44 u8 cmd;
45 int ret; 45 int ret;
46 46
47 if (flash->bank_curr == bank_sel) { 47 if (flash->bank_curr == bank_sel) {
48 debug("SF: not require to enable bank%d\n", bank_sel); 48 debug("SF: not require to enable bank%d\n", bank_sel);
49 return 0; 49 return 0;
50 } 50 }
51 51
52 cmd = flash->bank_write_cmd; 52 cmd = flash->bank_write_cmd;
53 ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); 53 ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
54 if (ret < 0) { 54 if (ret < 0) {
55 debug("SF: fail to write bank register\n"); 55 debug("SF: fail to write bank register\n");
56 return ret; 56 return ret;
57 } 57 }
58 flash->bank_curr = bank_sel; 58 flash->bank_curr = bank_sel;
59 59
60 return 0; 60 return 0;
61 } 61 }
62 62
63 static int spi_flash_bank(struct spi_flash *flash, u32 offset) 63 static int spi_flash_bank(struct spi_flash *flash, u32 offset)
64 { 64 {
65 u8 bank_sel; 65 u8 bank_sel;
66 int ret; 66 int ret;
67 67
68 bank_sel = offset / SPI_FLASH_16MB_BOUN; 68 bank_sel = offset / SPI_FLASH_16MB_BOUN;
69 69
70 ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); 70 ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
71 if (ret) { 71 if (ret) {
72 debug("SF: fail to set bank%d\n", bank_sel); 72 debug("SF: fail to set bank%d\n", bank_sel);
73 return ret; 73 return ret;
74 } 74 }
75 75
76 return 0; 76 return 0;
77 } 77 }
78 #endif 78 #endif
79 79
80 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) 80 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
81 { 81 {
82 struct spi_slave *spi = flash->spi; 82 struct spi_slave *spi = flash->spi;
83 unsigned long timebase; 83 unsigned long timebase;
84 int ret; 84 int ret;
85 u8 status; 85 u8 status;
86 u8 check_status = 0x0; 86 u8 check_status = 0x0;
87 u8 poll_bit = STATUS_WIP; 87 u8 poll_bit = STATUS_WIP;
88 u8 cmd = flash->poll_cmd; 88 u8 cmd = flash->poll_cmd;
89 89
90 if (cmd == CMD_FLAG_STATUS) { 90 if (cmd == CMD_FLAG_STATUS) {
91 poll_bit = STATUS_PEC; 91 poll_bit = STATUS_PEC;
92 check_status = poll_bit; 92 check_status = poll_bit;
93 } 93 }
94 94
95 ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); 95 ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
96 if (ret) { 96 if (ret) {
97 debug("SF: fail to read %s status register\n", 97 debug("SF: fail to read %s status register\n",
98 cmd == CMD_READ_STATUS ? "read" : "flag"); 98 cmd == CMD_READ_STATUS ? "read" : "flag");
99 return ret; 99 return ret;
100 } 100 }
101 101
102 timebase = get_timer(0); 102 timebase = get_timer(0);
103 do { 103 do {
104 WATCHDOG_RESET(); 104 WATCHDOG_RESET();
105 105
106 ret = spi_xfer(spi, 8, NULL, &status, 0); 106 ret = spi_xfer(spi, 8, NULL, &status, 0);
107 if (ret) 107 if (ret)
108 return -1; 108 return -1;
109 109
110 if ((status & poll_bit) == check_status) 110 if ((status & poll_bit) == check_status)
111 break; 111 break;
112 112
113 } while (get_timer(timebase) < timeout); 113 } while (get_timer(timebase) < timeout);
114 114
115 spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); 115 spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
116 116
117 if ((status & poll_bit) == check_status) 117 if ((status & poll_bit) == check_status)
118 return 0; 118 return 0;
119 119
120 /* Timed out */ 120 /* Timed out */
121 debug("SF: time out!\n"); 121 debug("SF: time out!\n");
122 return -1; 122 return -1;
123 } 123 }
124 124
125 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, 125 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
126 size_t cmd_len, const void *buf, size_t buf_len) 126 size_t cmd_len, const void *buf, size_t buf_len)
127 { 127 {
128 struct spi_slave *spi = flash->spi; 128 struct spi_slave *spi = flash->spi;
129 unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; 129 unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
130 int ret; 130 int ret;
131 131
132 if (buf == NULL) 132 if (buf == NULL)
133 timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; 133 timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
134 134
135 ret = spi_claim_bus(flash->spi); 135 ret = spi_claim_bus(flash->spi);
136 if (ret) { 136 if (ret) {
137 debug("SF: unable to claim SPI bus\n"); 137 debug("SF: unable to claim SPI bus\n");
138 return ret; 138 return ret;
139 } 139 }
140 140
141 ret = spi_flash_cmd_write_enable(flash); 141 ret = spi_flash_cmd_write_enable(flash);
142 if (ret < 0) { 142 if (ret < 0) {
143 debug("SF: enabling write failed\n"); 143 debug("SF: enabling write failed\n");
144 return ret; 144 return ret;
145 } 145 }
146 146
147 ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); 147 ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
148 if (ret < 0) { 148 if (ret < 0) {
149 debug("SF: write cmd failed\n"); 149 debug("SF: write cmd failed\n");
150 return ret; 150 return ret;
151 } 151 }
152 152
153 ret = spi_flash_cmd_wait_ready(flash, timeout); 153 ret = spi_flash_cmd_wait_ready(flash, timeout);
154 if (ret < 0) { 154 if (ret < 0) {
155 debug("SF: write %s timed out\n", 155 debug("SF: write %s timed out\n",
156 timeout == SPI_FLASH_PROG_TIMEOUT ? 156 timeout == SPI_FLASH_PROG_TIMEOUT ?
157 "program" : "page erase"); 157 "program" : "page erase");
158 return ret; 158 return ret;
159 } 159 }
160 160
161 spi_release_bus(spi); 161 spi_release_bus(spi);
162 162
163 return ret; 163 return ret;
164 } 164 }
165 165
166 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) 166 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
167 { 167 {
168 u32 erase_size; 168 u32 erase_size;
169 u8 cmd[4]; 169 u8 cmd[4];
170 int ret = -1; 170 int ret = -1;
171 171
172 erase_size = flash->erase_size; 172 erase_size = flash->erase_size;
173 if (offset % erase_size || len % erase_size) { 173 if (offset % erase_size || len % erase_size) {
174 debug("SF: Erase offset/length not multiple of erase size\n"); 174 debug("SF: Erase offset/length not multiple of erase size\n");
175 return -1; 175 return -1;
176 } 176 }
177 177
178 cmd[0] = flash->erase_cmd; 178 cmd[0] = flash->erase_cmd;
179 while (len) { 179 while (len) {
180 #ifdef CONFIG_SPI_FLASH_BAR 180 #ifdef CONFIG_SPI_FLASH_BAR
181 ret = spi_flash_bank(flash, offset); 181 ret = spi_flash_bank(flash, offset);
182 if (ret < 0) 182 if (ret < 0)
183 return ret; 183 return ret;
184 #endif 184 #endif
185 spi_flash_addr(offset, cmd); 185 spi_flash_addr(offset, cmd);
186 186
187 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], 187 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
188 cmd[2], cmd[3], offset); 188 cmd[2], cmd[3], offset);
189 189
190 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); 190 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
191 if (ret < 0) { 191 if (ret < 0) {
192 debug("SF: erase failed\n"); 192 debug("SF: erase failed\n");
193 break; 193 break;
194 } 194 }
195 195
196 offset += erase_size; 196 offset += erase_size;
197 len -= erase_size; 197 len -= erase_size;
198 } 198 }
199 199
200 return ret; 200 return ret;
201 } 201 }
202 202
203 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, 203 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
204 size_t len, const void *buf) 204 size_t len, const void *buf)
205 { 205 {
206 unsigned long byte_addr, page_size; 206 unsigned long byte_addr, page_size;
207 size_t chunk_len, actual; 207 size_t chunk_len, actual;
208 u8 cmd[4]; 208 u8 cmd[4];
209 int ret = -1; 209 int ret = -1;
210 210
211 page_size = flash->page_size; 211 page_size = flash->page_size;
212 212
213 cmd[0] = CMD_PAGE_PROGRAM; 213 cmd[0] = CMD_PAGE_PROGRAM;
214 for (actual = 0; actual < len; actual += chunk_len) { 214 for (actual = 0; actual < len; actual += chunk_len) {
215 #ifdef CONFIG_SPI_FLASH_BAR 215 #ifdef CONFIG_SPI_FLASH_BAR
216 ret = spi_flash_bank(flash, offset); 216 ret = spi_flash_bank(flash, offset);
217 if (ret < 0) 217 if (ret < 0)
218 return ret; 218 return ret;
219 #endif 219 #endif
220 byte_addr = offset % page_size; 220 byte_addr = offset % page_size;
221 chunk_len = min(len - actual, page_size - byte_addr); 221 chunk_len = min(len - actual, page_size - byte_addr);
222 222
223 if (flash->spi->max_write_size) 223 if (flash->spi->max_write_size)
224 chunk_len = min(chunk_len, flash->spi->max_write_size); 224 chunk_len = min(chunk_len, flash->spi->max_write_size);
225 225
226 spi_flash_addr(offset, cmd); 226 spi_flash_addr(offset, cmd);
227 227
228 debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", 228 debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
229 buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); 229 buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
230 230
231 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), 231 ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
232 buf + actual, chunk_len); 232 buf + actual, chunk_len);
233 if (ret < 0) { 233 if (ret < 0) {
234 debug("SF: write failed\n"); 234 debug("SF: write failed\n");
235 break; 235 break;
236 } 236 }
237 237
238 offset += chunk_len; 238 offset += chunk_len;
239 } 239 }
240 240
241 return ret; 241 return ret;
242 } 242 }
243 243
244 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, 244 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
245 size_t cmd_len, void *data, size_t data_len) 245 size_t cmd_len, void *data, size_t data_len)
246 { 246 {
247 struct spi_slave *spi = flash->spi; 247 struct spi_slave *spi = flash->spi;
248 int ret; 248 int ret;
249 249
250 ret = spi_claim_bus(flash->spi); 250 ret = spi_claim_bus(flash->spi);
251 if (ret) { 251 if (ret) {
252 debug("SF: unable to claim SPI bus\n"); 252 debug("SF: unable to claim SPI bus\n");
253 return ret; 253 return ret;
254 } 254 }
255 255
256 ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); 256 ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
257 if (ret < 0) { 257 if (ret < 0) {
258 debug("SF: read cmd failed\n"); 258 debug("SF: read cmd failed\n");
259 return ret; 259 return ret;
260 } 260 }
261 261
262 spi_release_bus(spi); 262 spi_release_bus(spi);
263 263
264 return ret; 264 return ret;
265 } 265 }
266 266
267 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, 267 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
268 size_t len, void *data) 268 size_t len, void *data)
269 { 269 {
270 u8 cmd[5], bank_sel = 0; 270 u8 cmd[5], bank_sel = 0;
271 u32 remain_len, read_len; 271 u32 remain_len, read_len;
272 int ret = -1; 272 int ret = -1;
273 273
274 /* Handle memory-mapped SPI */ 274 /* Handle memory-mapped SPI */
275 if (flash->memory_map) { 275 if (flash->memory_map) {
276 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP); 276 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
277 memcpy(data, flash->memory_map + offset, len); 277 memcpy(data, flash->memory_map + offset, len);
278 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END); 278 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
279 return 0; 279 return 0;
280 } 280 }
281 281
282 cmd[0] = CMD_READ_ARRAY_FAST; 282 cmd[0] = CMD_READ_ARRAY_FAST;
283 cmd[4] = 0x00; 283 cmd[4] = 0x00;
284 284
285 while (len) { 285 while (len) {
286 #ifdef CONFIG_SPI_FLASH_BAR 286 #ifdef CONFIG_SPI_FLASH_BAR
287 bank_sel = offset / SPI_FLASH_16MB_BOUN; 287 bank_sel = offset / SPI_FLASH_16MB_BOUN;
288 288
289 ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); 289 ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
290 if (ret) { 290 if (ret) {
291 debug("SF: fail to set bank%d\n", bank_sel); 291 debug("SF: fail to set bank%d\n", bank_sel);
292 return ret; 292 return ret;
293 } 293 }
294 #endif 294 #endif
295 remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset; 295 remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset;
296 if (len < remain_len) 296 if (len < remain_len)
297 read_len = len; 297 read_len = len;
298 else 298 else
299 read_len = remain_len; 299 read_len = remain_len;
300 300
301 spi_flash_addr(offset, cmd); 301 spi_flash_addr(offset, cmd);
302 302
303 ret = spi_flash_read_common(flash, cmd, sizeof(cmd), 303 ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
304 data, read_len); 304 data, read_len);
305 if (ret < 0) { 305 if (ret < 0) {
306 debug("SF: read failed\n"); 306 debug("SF: read failed\n");
307 break; 307 break;
308 } 308 }
309 309
310 offset += read_len; 310 offset += read_len;
311 len -= read_len; 311 len -= read_len;
312 data += read_len; 312 data += read_len;
313 } 313 }
314 314
315 return ret; 315 return ret;
316 } 316 }
317 317
318 #ifdef CONFIG_SPI_FLASH_SST 318 #ifdef CONFIG_SPI_FLASH_SST
319 static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) 319 static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
320 { 320 {
321 int ret; 321 int ret;
322 u8 cmd[4] = { 322 u8 cmd[4] = {
323 CMD_SST_BP, 323 CMD_SST_BP,
324 offset >> 16, 324 offset >> 16,
325 offset >> 8, 325 offset >> 8,
326 offset, 326 offset,
327 }; 327 };
328 328
329 debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", 329 debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
330 spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); 330 spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
331 331
332 ret = spi_flash_cmd_write_enable(flash); 332 ret = spi_flash_cmd_write_enable(flash);
333 if (ret) 333 if (ret)
334 return ret; 334 return ret;
335 335
336 ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1); 336 ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
337 if (ret) 337 if (ret)
338 return ret; 338 return ret;
339 339
340 return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); 340 return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
341 } 341 }
342 342
343 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, 343 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
344 const void *buf) 344 const void *buf)
345 { 345 {
346 size_t actual, cmd_len; 346 size_t actual, cmd_len;
347 int ret; 347 int ret;
348 u8 cmd[4]; 348 u8 cmd[4];
349 349
350 ret = spi_claim_bus(flash->spi); 350 ret = spi_claim_bus(flash->spi);
351 if (ret) { 351 if (ret) {
352 debug("SF: Unable to claim SPI bus\n"); 352 debug("SF: Unable to claim SPI bus\n");
353 return ret; 353 return ret;
354 } 354 }
355 355
356 /* If the data is not word aligned, write out leading single byte */ 356 /* If the data is not word aligned, write out leading single byte */
357 actual = offset % 2; 357 actual = offset % 2;
358 if (actual) { 358 if (actual) {
359 ret = sst_byte_write(flash, offset, buf); 359 ret = sst_byte_write(flash, offset, buf);
360 if (ret) 360 if (ret)
361 goto done; 361 goto done;
362 } 362 }
363 offset += actual; 363 offset += actual;
364 364
365 ret = spi_flash_cmd_write_enable(flash); 365 ret = spi_flash_cmd_write_enable(flash);
366 if (ret) 366 if (ret)
367 goto done; 367 goto done;
368 368
369 cmd_len = 4; 369 cmd_len = 4;
370 cmd[0] = CMD_SST_AAI_WP; 370 cmd[0] = CMD_SST_AAI_WP;
371 cmd[1] = offset >> 16; 371 cmd[1] = offset >> 16;
372 cmd[2] = offset >> 8; 372 cmd[2] = offset >> 8;
373 cmd[3] = offset; 373 cmd[3] = offset;
374 374
375 for (; actual < len - 1; actual += 2) { 375 for (; actual < len - 1; actual += 2) {
376 debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", 376 debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
377 spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, 377 spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
378 cmd[0], offset); 378 cmd[0], offset);
379 379
380 ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, 380 ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
381 buf + actual, 2); 381 buf + actual, 2);
382 if (ret) { 382 if (ret) {
383 debug("SF: sst word program failed\n"); 383 debug("SF: sst word program failed\n");
384 break; 384 break;
385 } 385 }
386 386
387 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); 387 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
388 if (ret) 388 if (ret)
389 break; 389 break;
390 390
391 cmd_len = 1; 391 cmd_len = 1;
392 offset += 2; 392 offset += 2;
393 } 393 }
394 394
395 if (!ret) 395 if (!ret)
396 ret = spi_flash_cmd_write_disable(flash); 396 ret = spi_flash_cmd_write_disable(flash);
397 397
398 /* If there is a single trailing byte, write it out */ 398 /* If there is a single trailing byte, write it out */
399 if (!ret && actual != len) 399 if (!ret && actual != len)
400 ret = sst_byte_write(flash, offset, buf + actual); 400 ret = sst_byte_write(flash, offset, buf + actual);
401 401
402 done: 402 done:
403 debug("SF: sst: program %s %zu bytes @ 0x%zx\n", 403 debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
404 ret ? "failure" : "success", len, offset - actual); 404 ret ? "failure" : "success", len, offset - actual);
405 405
406 spi_release_bus(flash->spi); 406 spi_release_bus(flash->spi);
407 return ret; 407 return ret;
408 } 408 }
409 #endif 409 #endif
410 410
drivers/mtd/spi/sf_probe.c
1 /* 1 /*
2 * SPI flash probing 2 * SPI flash probing
3 * 3 *
4 * Copyright (C) 2008 Atmel Corporation 4 * Copyright (C) 2008 Atmel Corporation
5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik 5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. 6 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
7 * 7 *
8 * Licensed under the GPL-2 or later. 8 * SPDX-License-Identifier: GPL-2.0+
9 */ 9 */
10 10
11 #include <common.h> 11 #include <common.h>
12 #include <fdtdec.h> 12 #include <fdtdec.h>
13 #include <malloc.h> 13 #include <malloc.h>
14 #include <spi.h> 14 #include <spi.h>
15 #include <spi_flash.h> 15 #include <spi_flash.h>
16 16
17 #include "sf_internal.h" 17 #include "sf_internal.h"
18 18
19 DECLARE_GLOBAL_DATA_PTR; 19 DECLARE_GLOBAL_DATA_PTR;
20 20
21 /** 21 /**
22 * struct spi_flash_params - SPI/QSPI flash device params structure 22 * struct spi_flash_params - SPI/QSPI flash device params structure
23 * 23 *
24 * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) 24 * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
25 * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) 25 * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
26 * @ext_jedec: Device ext_jedec ID 26 * @ext_jedec: Device ext_jedec ID
27 * @sector_size: Sector size of this device 27 * @sector_size: Sector size of this device
28 * @nr_sectors: No.of sectors on this device 28 * @nr_sectors: No.of sectors on this device
29 * @flags: Importent param, for flash specific behaviour 29 * @flags: Importent param, for flash specific behaviour
30 */ 30 */
31 struct spi_flash_params { 31 struct spi_flash_params {
32 const char *name; 32 const char *name;
33 u32 jedec; 33 u32 jedec;
34 u16 ext_jedec; 34 u16 ext_jedec;
35 u32 sector_size; 35 u32 sector_size;
36 u32 nr_sectors; 36 u32 nr_sectors;
37 u16 flags; 37 u16 flags;
38 }; 38 };
39 39
40 static const struct spi_flash_params spi_flash_params_table[] = { 40 static const struct spi_flash_params spi_flash_params_table[] = {
41 #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ 41 #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */
42 {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, SECT_4K}, 42 {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, SECT_4K},
43 {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, SECT_4K}, 43 {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, SECT_4K},
44 {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, SECT_4K}, 44 {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, SECT_4K},
45 {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, SECT_4K}, 45 {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, SECT_4K},
46 {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, SECT_4K}, 46 {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, SECT_4K},
47 {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, SECT_4K}, 47 {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, SECT_4K},
48 {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, SECT_4K}, 48 {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, SECT_4K},
49 #endif 49 #endif
50 #ifdef CONFIG_SPI_FLASH_EON /* EON */ 50 #ifdef CONFIG_SPI_FLASH_EON /* EON */
51 {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0}, 51 {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0},
52 {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, SECT_4K}, 52 {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, SECT_4K},
53 {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0}, 53 {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0},
54 {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0}, 54 {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0},
55 #endif 55 #endif
56 #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ 56 #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */
57 {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, SECT_4K}, 57 {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, SECT_4K},
58 {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, SECT_4K}, 58 {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, SECT_4K},
59 #endif 59 #endif
60 #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ 60 #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
61 {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0}, 61 {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0},
62 {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0}, 62 {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0},
63 {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0}, 63 {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0},
64 {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0}, 64 {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0},
65 {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0}, 65 {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0},
66 {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, 0}, 66 {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, 0},
67 {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, 0}, 67 {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, 0},
68 {"MX25L51235F", 0xc2201A, 0x0, 64 * 1024, 1024, 0}, 68 {"MX25L51235F", 0xc2201A, 0x0, 64 * 1024, 1024, 0},
69 {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, 0}, 69 {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, 0},
70 #endif 70 #endif
71 #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ 71 #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */
72 {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0}, 72 {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0},
73 {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0}, 73 {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0},
74 {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0}, 74 {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0},
75 {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0}, 75 {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0},
76 {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, 0}, 76 {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, 0},
77 {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, 0}, 77 {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, 0},
78 {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, 0}, 78 {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, 0},
79 {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, 0}, 79 {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, 0},
80 {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, 0}, 80 {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, 0},
81 {"S25FL256S_256K", 0x010219, 0x4d00, 64 * 1024, 512, 0}, 81 {"S25FL256S_256K", 0x010219, 0x4d00, 64 * 1024, 512, 0},
82 {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, 0}, 82 {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, 0},
83 {"S25FL512S_256K", 0x010220, 0x4d00, 64 * 1024, 1024, 0}, 83 {"S25FL512S_256K", 0x010220, 0x4d00, 64 * 1024, 1024, 0},
84 {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, 0}, 84 {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, 0},
85 #endif 85 #endif
86 #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ 86 #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
87 {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0}, 87 {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0},
88 {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0}, 88 {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0},
89 {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0}, 89 {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0},
90 {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0}, 90 {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0},
91 {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0}, 91 {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0},
92 {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0}, 92 {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0},
93 {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0}, 93 {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0},
94 {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0}, 94 {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0},
95 {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, SECT_4K}, 95 {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, SECT_4K},
96 {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, SECT_4K}, 96 {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, SECT_4K},
97 {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, SECT_4K}, 97 {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, SECT_4K},
98 {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, SECT_4K}, 98 {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, SECT_4K},
99 {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, SECT_4K}, 99 {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, SECT_4K},
100 {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, SECT_4K}, 100 {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, SECT_4K},
101 {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, SECT_4K}, 101 {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, SECT_4K},
102 {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, SECT_4K}, 102 {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, SECT_4K},
103 {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K}, 103 {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K},
104 {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K}, 104 {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, E_FSR | SECT_4K},
105 {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K}, 105 {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K},
106 {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K}, 106 {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, E_FSR | SECT_4K},
107 #endif 107 #endif
108 #ifdef CONFIG_SPI_FLASH_SST /* SST */ 108 #ifdef CONFIG_SPI_FLASH_SST /* SST */
109 {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WP}, 109 {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WP},
110 {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WP}, 110 {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WP},
111 {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WP}, 111 {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WP},
112 {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WP}, 112 {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WP},
113 {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, SECT_4K}, 113 {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, SECT_4K},
114 {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WP}, 114 {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WP},
115 {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WP}, 115 {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WP},
116 {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WP}, 116 {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WP},
117 {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WP}, 117 {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WP},
118 {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WP}, 118 {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WP},
119 #endif 119 #endif
120 #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ 120 #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */
121 {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0}, 121 {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0},
122 {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0}, 122 {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0},
123 {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0}, 123 {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0},
124 {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, SECT_4K}, 124 {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, SECT_4K},
125 {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, SECT_4K}, 125 {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, SECT_4K},
126 {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, SECT_4K}, 126 {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, SECT_4K},
127 {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, SECT_4K}, 127 {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, SECT_4K},
128 {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, SECT_4K}, 128 {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, SECT_4K},
129 {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, SECT_4K}, 129 {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, SECT_4K},
130 {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, SECT_4K}, 130 {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, SECT_4K},
131 {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, SECT_4K}, 131 {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, SECT_4K},
132 {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, SECT_4K}, 132 {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, SECT_4K},
133 {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, SECT_4K}, 133 {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, SECT_4K},
134 {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, SECT_4K}, 134 {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, SECT_4K},
135 {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, SECT_4K}, 135 {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, SECT_4K},
136 {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, SECT_4K}, 136 {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, SECT_4K},
137 {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, SECT_4K}, 137 {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, SECT_4K},
138 {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, SECT_4K}, 138 {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, SECT_4K},
139 #endif 139 #endif
140 /* 140 /*
141 * Note: 141 * Note:
142 * Below paired flash devices has similar spi_flash params. 142 * Below paired flash devices has similar spi_flash params.
143 * (S25FL129P_64K, S25FL128S_64K) 143 * (S25FL129P_64K, S25FL128S_64K)
144 * (W25Q80BL, W25Q80BV) 144 * (W25Q80BL, W25Q80BV)
145 * (W25Q16CL, W25Q16DV) 145 * (W25Q16CL, W25Q16DV)
146 * (W25Q32BV, W25Q32FV_SPI) 146 * (W25Q32BV, W25Q32FV_SPI)
147 * (W25Q64CV, W25Q64FV_SPI) 147 * (W25Q64CV, W25Q64FV_SPI)
148 * (W25Q128BV, W25Q128FV_SPI) 148 * (W25Q128BV, W25Q128FV_SPI)
149 * (W25Q32DW, W25Q32FV_QPI) 149 * (W25Q32DW, W25Q32FV_QPI)
150 * (W25Q64DW, W25Q64FV_QPI) 150 * (W25Q64DW, W25Q64FV_QPI)
151 * (W25Q128FW, W25Q128FV_QPI) 151 * (W25Q128FW, W25Q128FV_QPI)
152 */ 152 */
153 }; 153 };
154 154
155 static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, 155 static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
156 u8 *idcode) 156 u8 *idcode)
157 { 157 {
158 const struct spi_flash_params *params; 158 const struct spi_flash_params *params;
159 struct spi_flash *flash; 159 struct spi_flash *flash;
160 int i; 160 int i;
161 u16 jedec = idcode[1] << 8 | idcode[2]; 161 u16 jedec = idcode[1] << 8 | idcode[2];
162 u16 ext_jedec = idcode[3] << 8 | idcode[4]; 162 u16 ext_jedec = idcode[3] << 8 | idcode[4];
163 163
164 /* Get the flash id (jedec = manuf_id + dev_id, ext_jedec) */ 164 /* Get the flash id (jedec = manuf_id + dev_id, ext_jedec) */
165 for (i = 0; i < ARRAY_SIZE(spi_flash_params_table); i++) { 165 for (i = 0; i < ARRAY_SIZE(spi_flash_params_table); i++) {
166 params = &spi_flash_params_table[i]; 166 params = &spi_flash_params_table[i];
167 if ((params->jedec >> 16) == idcode[0]) { 167 if ((params->jedec >> 16) == idcode[0]) {
168 if ((params->jedec & 0xFFFF) == jedec) { 168 if ((params->jedec & 0xFFFF) == jedec) {
169 if (params->ext_jedec == 0) 169 if (params->ext_jedec == 0)
170 break; 170 break;
171 else if (params->ext_jedec == ext_jedec) 171 else if (params->ext_jedec == ext_jedec)
172 break; 172 break;
173 } 173 }
174 } 174 }
175 } 175 }
176 176
177 if (i == ARRAY_SIZE(spi_flash_params_table)) { 177 if (i == ARRAY_SIZE(spi_flash_params_table)) {
178 printf("SF: Unsupported flash IDs: "); 178 printf("SF: Unsupported flash IDs: ");
179 printf("manuf %02x, jedec %04x, ext_jedec %04x\n", 179 printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
180 idcode[0], jedec, ext_jedec); 180 idcode[0], jedec, ext_jedec);
181 return NULL; 181 return NULL;
182 } 182 }
183 183
184 flash = malloc(sizeof(*flash)); 184 flash = malloc(sizeof(*flash));
185 if (!flash) { 185 if (!flash) {
186 debug("SF: Failed to allocate spi_flash\n"); 186 debug("SF: Failed to allocate spi_flash\n");
187 return NULL; 187 return NULL;
188 } 188 }
189 memset(flash, '\0', sizeof(*flash)); 189 memset(flash, '\0', sizeof(*flash));
190 190
191 /* Assign spi data */ 191 /* Assign spi data */
192 flash->spi = spi; 192 flash->spi = spi;
193 flash->name = params->name; 193 flash->name = params->name;
194 flash->memory_map = spi->memory_map; 194 flash->memory_map = spi->memory_map;
195 195
196 /* Assign spi_flash ops */ 196 /* Assign spi_flash ops */
197 flash->write = spi_flash_cmd_write_ops; 197 flash->write = spi_flash_cmd_write_ops;
198 #ifdef CONFIG_SPI_FLASH_SST 198 #ifdef CONFIG_SPI_FLASH_SST
199 if (params->flags & SST_WP) 199 if (params->flags & SST_WP)
200 flash->write = sst_write_wp; 200 flash->write = sst_write_wp;
201 #endif 201 #endif
202 flash->erase = spi_flash_cmd_erase_ops; 202 flash->erase = spi_flash_cmd_erase_ops;
203 flash->read = spi_flash_cmd_read_ops; 203 flash->read = spi_flash_cmd_read_ops;
204 204
205 /* Compute the flash size */ 205 /* Compute the flash size */
206 flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; 206 flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256;
207 flash->sector_size = params->sector_size; 207 flash->sector_size = params->sector_size;
208 flash->size = flash->sector_size * params->nr_sectors; 208 flash->size = flash->sector_size * params->nr_sectors;
209 209
210 /* Compute erase sector and command */ 210 /* Compute erase sector and command */
211 if (params->flags & SECT_4K) { 211 if (params->flags & SECT_4K) {
212 flash->erase_cmd = CMD_ERASE_4K; 212 flash->erase_cmd = CMD_ERASE_4K;
213 flash->erase_size = 4096; 213 flash->erase_size = 4096;
214 } else if (params->flags & SECT_32K) { 214 } else if (params->flags & SECT_32K) {
215 flash->erase_cmd = CMD_ERASE_32K; 215 flash->erase_cmd = CMD_ERASE_32K;
216 flash->erase_size = 32768; 216 flash->erase_size = 32768;
217 } else { 217 } else {
218 flash->erase_cmd = CMD_ERASE_64K; 218 flash->erase_cmd = CMD_ERASE_64K;
219 flash->erase_size = flash->sector_size; 219 flash->erase_size = flash->sector_size;
220 } 220 }
221 221
222 /* Poll cmd seclection */ 222 /* Poll cmd seclection */
223 flash->poll_cmd = CMD_READ_STATUS; 223 flash->poll_cmd = CMD_READ_STATUS;
224 #ifdef CONFIG_SPI_FLASH_STMICRO 224 #ifdef CONFIG_SPI_FLASH_STMICRO
225 if (params->flags & E_FSR) 225 if (params->flags & E_FSR)
226 flash->poll_cmd = CMD_FLAG_STATUS; 226 flash->poll_cmd = CMD_FLAG_STATUS;
227 #endif 227 #endif
228 228
229 /* Configure the BAR - discover bank cmds and read current bank */ 229 /* Configure the BAR - discover bank cmds and read current bank */
230 #ifdef CONFIG_SPI_FLASH_BAR 230 #ifdef CONFIG_SPI_FLASH_BAR
231 u8 curr_bank = 0; 231 u8 curr_bank = 0;
232 if (flash->size > SPI_FLASH_16MB_BOUN) { 232 if (flash->size > SPI_FLASH_16MB_BOUN) {
233 flash->bank_read_cmd = (idcode[0] == 0x01) ? 233 flash->bank_read_cmd = (idcode[0] == 0x01) ?
234 CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR; 234 CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
235 flash->bank_write_cmd = (idcode[0] == 0x01) ? 235 flash->bank_write_cmd = (idcode[0] == 0x01) ?
236 CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR; 236 CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
237 237
238 if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1, 238 if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
239 &curr_bank, 1)) { 239 &curr_bank, 1)) {
240 debug("SF: fail to read bank addr register\n"); 240 debug("SF: fail to read bank addr register\n");
241 return NULL; 241 return NULL;
242 } 242 }
243 flash->bank_curr = curr_bank; 243 flash->bank_curr = curr_bank;
244 } else { 244 } else {
245 flash->bank_curr = curr_bank; 245 flash->bank_curr = curr_bank;
246 } 246 }
247 #endif 247 #endif
248 248
249 /* Flash powers up read-only, so clear BP# bits */ 249 /* Flash powers up read-only, so clear BP# bits */
250 #if defined(CONFIG_SPI_FLASH_ATMEL) || \ 250 #if defined(CONFIG_SPI_FLASH_ATMEL) || \
251 defined(CONFIG_SPI_FLASH_MACRONIX) || \ 251 defined(CONFIG_SPI_FLASH_MACRONIX) || \
252 defined(CONFIG_SPI_FLASH_SST) 252 defined(CONFIG_SPI_FLASH_SST)
253 spi_flash_cmd_write_status(flash, 0); 253 spi_flash_cmd_write_status(flash, 0);
254 #endif 254 #endif
255 255
256 return flash; 256 return flash;
257 } 257 }
258 258
259 #ifdef CONFIG_OF_CONTROL 259 #ifdef CONFIG_OF_CONTROL
260 int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) 260 int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
261 { 261 {
262 fdt_addr_t addr; 262 fdt_addr_t addr;
263 fdt_size_t size; 263 fdt_size_t size;
264 int node; 264 int node;
265 265
266 /* If there is no node, do nothing */ 266 /* If there is no node, do nothing */
267 node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); 267 node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
268 if (node < 0) 268 if (node < 0)
269 return 0; 269 return 0;
270 270
271 addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); 271 addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
272 if (addr == FDT_ADDR_T_NONE) { 272 if (addr == FDT_ADDR_T_NONE) {
273 debug("%s: Cannot decode address\n", __func__); 273 debug("%s: Cannot decode address\n", __func__);
274 return 0; 274 return 0;
275 } 275 }
276 276
277 if (flash->size != size) { 277 if (flash->size != size) {
278 debug("%s: Memory map must cover entire device\n", __func__); 278 debug("%s: Memory map must cover entire device\n", __func__);
279 return -1; 279 return -1;
280 } 280 }
281 flash->memory_map = (void *)addr; 281 flash->memory_map = (void *)addr;
282 282
283 return 0; 283 return 0;
284 } 284 }
285 #endif /* CONFIG_OF_CONTROL */ 285 #endif /* CONFIG_OF_CONTROL */
286 286
287 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, 287 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
288 unsigned int max_hz, unsigned int spi_mode) 288 unsigned int max_hz, unsigned int spi_mode)
289 { 289 {
290 struct spi_slave *spi; 290 struct spi_slave *spi;
291 struct spi_flash *flash = NULL; 291 struct spi_flash *flash = NULL;
292 u8 idcode[5]; 292 u8 idcode[5];
293 int ret; 293 int ret;
294 294
295 /* Setup spi_slave */ 295 /* Setup spi_slave */
296 spi = spi_setup_slave(bus, cs, max_hz, spi_mode); 296 spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
297 if (!spi) { 297 if (!spi) {
298 printf("SF: Failed to set up slave\n"); 298 printf("SF: Failed to set up slave\n");
299 return NULL; 299 return NULL;
300 } 300 }
301 301
302 /* Claim spi bus */ 302 /* Claim spi bus */
303 ret = spi_claim_bus(spi); 303 ret = spi_claim_bus(spi);
304 if (ret) { 304 if (ret) {
305 debug("SF: Failed to claim SPI bus: %d\n", ret); 305 debug("SF: Failed to claim SPI bus: %d\n", ret);
306 goto err_claim_bus; 306 goto err_claim_bus;
307 } 307 }
308 308
309 /* Read the ID codes */ 309 /* Read the ID codes */
310 ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); 310 ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
311 if (ret) { 311 if (ret) {
312 printf("SF: Failed to get idcodes\n"); 312 printf("SF: Failed to get idcodes\n");
313 goto err_read_id; 313 goto err_read_id;
314 } 314 }
315 315
316 #ifdef DEBUG 316 #ifdef DEBUG
317 printf("SF: Got idcodes\n"); 317 printf("SF: Got idcodes\n");
318 print_buffer(0, idcode, 1, sizeof(idcode), 0); 318 print_buffer(0, idcode, 1, sizeof(idcode), 0);
319 #endif 319 #endif
320 320
321 /* Validate params from spi_flash_params table */ 321 /* Validate params from spi_flash_params table */
322 flash = spi_flash_validate_params(spi, idcode); 322 flash = spi_flash_validate_params(spi, idcode);
323 if (!flash) 323 if (!flash)
324 goto err_read_id; 324 goto err_read_id;
325 325
326 #ifdef CONFIG_OF_CONTROL 326 #ifdef CONFIG_OF_CONTROL
327 if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { 327 if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
328 debug("SF: FDT decode error\n"); 328 debug("SF: FDT decode error\n");
329 goto err_read_id; 329 goto err_read_id;
330 } 330 }
331 #endif 331 #endif
332 #ifndef CONFIG_SPL_BUILD 332 #ifndef CONFIG_SPL_BUILD
333 printf("SF: Detected %s with page size ", flash->name); 333 printf("SF: Detected %s with page size ", flash->name);
334 print_size(flash->page_size, ", erase size "); 334 print_size(flash->page_size, ", erase size ");
335 print_size(flash->erase_size, ", total "); 335 print_size(flash->erase_size, ", total ");
336 print_size(flash->size, ""); 336 print_size(flash->size, "");
337 if (flash->memory_map) 337 if (flash->memory_map)
338 printf(", mapped at %p", flash->memory_map); 338 printf(", mapped at %p", flash->memory_map);
339 puts("\n"); 339 puts("\n");
340 #endif 340 #endif
341 #ifndef CONFIG_SPI_FLASH_BAR 341 #ifndef CONFIG_SPI_FLASH_BAR
342 if (flash->size > SPI_FLASH_16MB_BOUN) { 342 if (flash->size > SPI_FLASH_16MB_BOUN) {
343 puts("SF: Warning - Only lower 16MiB accessible,"); 343 puts("SF: Warning - Only lower 16MiB accessible,");
344 puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); 344 puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
345 } 345 }
346 #endif 346 #endif
347 347
348 /* Release spi bus */ 348 /* Release spi bus */
349 spi_release_bus(spi); 349 spi_release_bus(spi);
350 350
351 return flash; 351 return flash;
352 352
353 err_read_id: 353 err_read_id:
354 spi_release_bus(spi); 354 spi_release_bus(spi);
355 err_claim_bus: 355 err_claim_bus:
356 spi_free_slave(spi); 356 spi_free_slave(spi);
357 return NULL; 357 return NULL;
358 } 358 }
359 359
360 void spi_flash_free(struct spi_flash *flash) 360 void spi_flash_free(struct spi_flash *flash)
361 { 361 {
362 spi_free_slave(flash->spi); 362 spi_free_slave(flash->spi);
363 free(flash); 363 free(flash);
364 } 364 }
365 365