rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
hal_flash_device.c
Go to the documentation of this file.
1/*
2 * hal_flash_device.h
3 *
4 * QSPI NOR flash driver with JEDEC SFDP for ChibiOS
5 * Tested and developed with Microchip SST26F064A
6 *
7 * @date Aug 14, 2021
8 * @author Andrey Gusakov, (c) 2021
9 *
10 * Based on ChibiOS drivers: Macronix MX25 and Micron N25Q
11 * ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
12 *
13 */
14
15/**
16 * @file hal_flash_device.c
17 * @brief Jedec JESD216 SFDP code.
18 *
19 * @addtogroup JEDEC_SFDP
20 * @{
21 */
22
23#include <string.h>
24
25#include "hal.h"
26#include "hal_serial_nor.h"
27
28/*===========================================================================*/
29/* Driver local definitions. */
30/*===========================================================================*/
31
32/*===========================================================================*/
33/* Driver exported variables. */
34/*===========================================================================*/
35
36/**
37 * @brief Flash descriptor.
38 */
39flash_descriptor_t snor_descriptor = {
40 .attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE |
41 FLASH_ATTR_SUSPEND_ERASE_CAPABLE,
42 .page_size = 256U,
43 .sectors_count = 0U, /* It is overwritten.*/
44 .sectors = NULL,
45 .sectors_size = 0U, /* It is overwritten.*/
46 .address = 0U,
47 .size = 0U /* It is overwritten.*/
48};
49
50/* NOT TESTED YET */
51#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
52#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
53/**
54 * @brief Fast read command for memory mapped mode.
55 */
56const wspi_command_t snor_memmap_read = {
57 .cmd = JEDEC_CMD_READ,
58 .addr = 0,
59 .dummy = 0, //JEDEC_READ_DUMMY_CYCLES,
60 .cfg = WSPI_CFG_ADDR_SIZE_24 |
61#if JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI1L
62 WSPI_CFG_CMD_MODE_ONE_LINE |
63 WSPI_CFG_ADDR_MODE_ONE_LINE |
64 WSPI_CFG_DATA_MODE_ONE_LINE |
65#elif JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI2L
66 WSPI_CFG_CMD_MODE_TWO_LINES |
67 WSPI_CFG_ADDR_MODE_TWO_LINES |
68 WSPI_CFG_DATA_MODE_TWO_LINES |
69#else
70 WSPI_CFG_CMD_MODE_FOUR_LINES |
71 WSPI_CFG_ADDR_MODE_FOUR_LINES |
72 WSPI_CFG_DATA_MODE_FOUR_LINES |
73#endif
74 WSPI_CFG_ALT_MODE_NONE
75};
76#endif
77#endif
78
79/*===========================================================================*/
80/* Driver local variables and types. */
81/*===========================================================================*/
82
83/* Hack to keep ChibiOS sources untouched and use on MCU with data cache:
84 * read/write through temp buffer in non-cached ram. */
85#define NO_CACHE __attribute__((section(".ram2")))
86static NO_CACHE uint8_t tmpbuf[256] __attribute__((aligned (32)));
87
88/* Buffer for SFDP parsing */
89static uint32_t sfdpbuf[64 / 4];
90
91/* JEDEC read command.*/
92static wspi_command_t jedec_cmd_read;
93
94/* JEDEC erase command.*/
95static wspi_command_t jedec_cmd_erase;
96
97/* JEDEC page program command.*/
98static wspi_command_t jedec_cmd_program;
99
100/*===========================================================================*/
101/* Driver local functions. */
102/*===========================================================================*/
103
104static flash_error_t jedec_poll_status(SNORDriver *devp) {
105 uint8_t sts;
106
107 do {
108#if JEDEC_NICE_WAITING == TRUE
109 osalThreadSleepMilliseconds(1);
110#endif
111 /* Read status command.*/
112 bus_cmd_receive(devp, JEDEC_CMD_READ_STATUS_REGISTER,
113 1, tmpbuf);
114 sts = tmpbuf[0];
115 } while ((sts & JEDEC_FLAGS_STS_BUSY) != 0U);
116
117 return FLASH_NO_ERROR;
118}
119
120#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
121static void jedec_reset_memory(SNORDriver *devp) {
122
123 /* 1x JEDEC_CMD_RESET_ENABLE command.*/
124 static const wspi_command_t cmd_reset_enable_1 = {
125 .cmd = JEDEC_CMD_RESET_ENABLE,
126 .cfg = WSPI_CFG_CMD_MODE_ONE_LINE,
127 .addr = 0,
128 .alt = 0,
129 .dummy = 0
130 };
131
132 /* 1x JEDEC_CMD_RESET_MEMORY command.*/
133 static const wspi_command_t cmd_reset_memory_1 = {
134 .cmd = JEDEC_CMD_RESET_MEMORY,
135 .cfg = WSPI_CFG_CMD_MODE_ONE_LINE,
136 .addr = 0,
137 .alt = 0,
138 .dummy = 0
139 };
140
141 /* If the device is in one bit mode then the following commands are
142 rejected because shorter than 8 bits. If the device is in multiple
143 bits mode then the commands are accepted and the device is reset to
144 one bit mode.*/
145#if JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI4L
146 /* 4x JEDEC_CMD_RESET_ENABLE command.*/
147 static const wspi_command_t cmd_reset_enable_4 = {
148 .cmd = JEDEC_CMD_RESET_ENABLE,
149 .cfg = WSPI_CFG_CMD_MODE_FOUR_LINES,
150 .addr = 0,
151 .alt = 0,
152 .dummy = 0
153 };
154
155 /* 4x JEDEC_CMD_RESET_MEMORY command.*/
156 static const wspi_command_t cmd_reset_memory_4 = {
157 .cmd = JEDEC_CMD_RESET_MEMORY,
158 .cfg = WSPI_CFG_CMD_MODE_FOUR_LINES,
159 .addr = 0,
160 .alt = 0,
161 .dummy = 0
162 };
163
164 wspiCommand(devp->config->busp, &cmd_reset_enable_4);
165 wspiCommand(devp->config->busp, &cmd_reset_memory_4);
166#elif JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI4L
167 /* 2x JEDEC_CMD_RESET_ENABLE command.*/
168 static const wspi_command_t cmd_reset_enable_2 = {
169 .cmd = JEDEC_CMD_RESET_ENABLE,
170 .cfg = WSPI_CFG_CMD_MODE_TWO_LINES,
171 .addr = 0,
172 .alt = 0,
173 .dummy = 0
174 };
175
176 /* 2x JEDEC_CMD_RESET_MEMORY command.*/
177 static const wspi_command_t cmd_reset_memory_2 = {
178 .cmd = JEDEC_CMD_RESET_MEMORY,
179 .cfg = WSPI_CFG_CMD_MODE_TWO_LINES,
180 .addr = 0,
181 .alt = 0,
182 .dummy = 0
183 };
184
185 wspiCommand(devp->config->busp, &cmd_reset_enable_2);
186 wspiCommand(devp->config->busp, &cmd_reset_memory_2);
187#endif
188
189 /* Now the device should be in one bit mode for sure and we perform a
190 device reset.*/
191 wspiCommand(devp->config->busp, &cmd_reset_enable_1);
192 wspiCommand(devp->config->busp, &cmd_reset_memory_1);
193}
194#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
195
196static void jedec_set_config(SNORDriver *devp, uint8_t val)
197{
198 tmpbuf[0] = 0;
199 tmpbuf[1] = val;
200
201 bus_cmd_send(devp, JEDEC_CMD_WRITE_STATUS_REGISTER, 2, tmpbuf);
202}
203
204static uint8_t jedec_get_config(SNORDriver *devp) {
205 /* Read status command.*/
206 bus_cmd_receive(devp, JEDEC_CMD_READ_CONFIGURATION_REGISTER,
207 1, tmpbuf);
208 return tmpbuf[0];
209}
210
211static void jedec_write_enable(SNORDriver *devp, int enable) {
212 /* Enabling write operation.*/
213 bus_cmd(devp, enable ? JEDEC_CMD_WRITE_ENABLE : JEDEC_CMD_WRITE_DISABLE);
214}
215
216static void snor_device_fill_cmd(wspi_command_t *cmd,
217 uint32_t cfg, uint8_t opcode,
218 uint8_t mode_clocks, uint8_t dummy_clocks)
219{
220 cmd->cmd = opcode;
221 cmd->cfg = cfg;
222 cmd->dummy = 0;
223 cmd->alt = 0; /* ? */
224
225 if (mode_clocks) {
226 uint8_t mode_bytes = 0;
227
228 /* Alt bytes mode - same as address */
229 if ((cmd->cfg & WSPI_CFG_ADDR_MODE_MASK) == WSPI_CFG_ADDR_MODE_ONE_LINE) {
230 cmd->cfg |= WSPI_CFG_ALT_MODE_ONE_LINE;
231 mode_bytes = mode_clocks / 8;
232 } else if ((cmd->cfg & WSPI_CFG_ADDR_MODE_MASK) == WSPI_CFG_ADDR_MODE_TWO_LINES) {
233 cmd->cfg |= WSPI_CFG_ALT_MODE_TWO_LINES;
234 mode_bytes = mode_clocks / 4;
235 } else if ((cmd->cfg & WSPI_CFG_ADDR_MODE_MASK) == WSPI_CFG_ADDR_MODE_FOUR_LINES) {
236 cmd->cfg |= WSPI_CFG_ALT_MODE_FOUR_LINES;
237 mode_bytes = mode_clocks / 2;
238 } /* else if ((cmd->cfg & WSPI_CFG_ADDR_MODE_MASK) == WSPI_CFG_ADDR_MODE_EIGHT_LINES){
239 cmd->cfg |= WSPI_CFG_ALT_MODE_EIGHT_LINES;
240 mode_bytes = mode_clocks / 1;
241 } */
242
243 if (mode_bytes == 1)
244 cmd->cfg |= WSPI_CFG_ALT_SIZE_8;
245 else if (mode_bytes == 2)
246 cmd->cfg |= WSPI_CFG_ALT_SIZE_16;
247 else if (mode_bytes == 3)
248 cmd->cfg |= WSPI_CFG_ALT_SIZE_24;
249 else if (mode_bytes == 4)
250 cmd->cfg |= WSPI_CFG_ALT_SIZE_32;
251 else
252 osalDbgAssert(0, "Failed to calculate alternative bytes size");
253 } else {
254 cmd->cfg |= WSPI_CFG_ALT_MODE_NONE;
255 }
256
257 cmd->dummy = dummy_clocks;
258}
259
260/*===========================================================================*/
261/* Driver exported functions. */
262/*===========================================================================*/
263
264void snor_device_init(SNORDriver *devp) {
265 int i;
266 uint8_t cfg;
267 uint8_t parameter_headers_n;
268 /* use as temp buffer, should be at least 64 bytes */
269 uint8_t *buf = (uint8_t *)sfdpbuf;
270 uint32_t *sfdp = sfdpbuf;
271 /* offset in sfdp area */
272 flash_offset_t offset = 0;
273 const uint8_t sfdp_sign[4] = {0x53, 0x46, 0x44, 0x50}; /* "SFDP" */
274
275#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
276 /* Attempting a reset of the XIP mode, it could be in an unexpected state
277 because a CPU reset does not reset the memory too.*/
278 //snor_reset_xip(devp);
279
280 /* Attempting a reset of the device, it could be in an unexpected state
281 because a CPU reset does not reset the memory too.*/
282 jedec_reset_memory(devp);
283#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
284
285 /* SST26VF specific: adjust configuration register */
286 cfg = jedec_get_config(devp);
287 /* disable WP and HOLD */
288 cfg |= (1 << 1);
289 /* WP# disable */
290 cfg &= ~(1 << 7);
291 jedec_set_config(devp, cfg);
292
293 /* Global Block Protection Unlock */
294 jedec_write_enable(devp, 1);
295 bus_cmd(devp, JEDEC_CMD_GLOBAL_BLOCK_PROTECTION_UNLOCK);
296
297 /* Reading SFDP Header. */
298 snor_device_read_sfdp(devp, offset, 8, buf);
299
300 /* Checking if the device supports SFDP. */
301 osalDbgAssert(memcmp(sfdp_sign, buf, 4) == 0,
302 "chip does not support SFDP");
303
304 /* Find JEDEC Flash Parameter Header */
305 parameter_headers_n = buf[6];
306 for (i = 0; i < parameter_headers_n; i++) {
307 int length;
308 /* each header is 8 bytes lont + 8 bytes of SFDP header */
309 offset = 8 + (i * 8);
310
311 snor_device_read_sfdp(devp, offset, 8, buf);
312 if (buf[0] != 0x00) {
313 /* vendor-specific header - skip. */
314 continue;
315 }
316
317 /* get Parameter Table Pointer */
318 offset = buf[4] | (buf[5] << 8) | (buf[6] << 16);
319 /* and length */
320 length = buf[3] * 4; /* in DWORDs */
321
322 if (length != 0x40)
323 continue;
324
325 snor_device_read_sfdp(devp, offset, length, buf);
326
327 break;
328 }
329
330 osalDbgAssert(i != parameter_headers_n,
331 "JEDEC SFDP parameters block not found");
332
333 /* Setting up the device sizes.*/
334 /* Chip density defined in bits */
335 if (sfdp[1] & 0x80000000)
336 /* more than 4 gigabits */
337 snor_descriptor.size = (size_t)(1 << ((sfdp[1] & 0x7fffffff) - 3));
338 else
339 snor_descriptor.size = (size_t)((sfdp[1] + 1) >> 3);
340 /* Use sector size 1, assume smalest */
341 snor_descriptor.sectors_size = (size_t)1 << (sfdp[7] & 0xff);
342 snor_descriptor.sectors_count = snor_descriptor.size /
343 snor_descriptor.sectors_size;
344
345 /* Fastest read command */
346 /* TODO: add 4-4-4 and 2-2-2 support */
347 if (sfdp[0] & (1 << 21)) {
348 /* 1-4-4 */
350 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
351 WSPI_CFG_ADDR_MODE_FOUR_LINES |
352 WSPI_CFG_DATA_MODE_FOUR_LINES,
353 (sfdp[2] >> 8) & 0xff, (sfdp[2] >> 5) & 0x07, (sfdp[2] >> 0) & 0x1f);
354 } else if (sfdp[0] & (1 << 22)) {
355 /* 1-1-4 */
357 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
358 WSPI_CFG_ADDR_MODE_ONE_LINE |
359 WSPI_CFG_DATA_MODE_FOUR_LINES,
360 (sfdp[2] >> 24) & 0xff, (sfdp[2] >> 21) & 0x07, (sfdp[2] >> 16) & 0x1f);
361 } else if (sfdp[0] & (1 << 20)) {
362 /* 1-2-2 */
364 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
365 WSPI_CFG_ADDR_MODE_TWO_LINES |
366 WSPI_CFG_DATA_MODE_TWO_LINES,
367 (sfdp[3] >> 24) & 0xff, (sfdp[3] >> 21) & 0x07, (sfdp[3] >> 16) & 0x1f);
368 } else if (sfdp[0] & (1 << 16)) {
369 /* 1-1-2 */
371 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
372 WSPI_CFG_ADDR_MODE_ONE_LINE |
373 WSPI_CFG_DATA_MODE_TWO_LINES,
374 (sfdp[3] >> 8) & 0xff, (sfdp[3] >> 5) & 0x07, (sfdp[3] >> 0) & 0x1f);
375 }
376 if (1) {
377 /* Fallback to 1-1-1 */
379 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
380 WSPI_CFG_ADDR_MODE_ONE_LINE |
381 WSPI_CFG_DATA_MODE_ONE_LINE,
382 JEDEC_CMD_FAST_READ, 0, 8);
383 }
384
385 /* TODO: get from SFDP */
387 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
388 WSPI_CFG_ADDR_MODE_ONE_LINE,
389 JEDEC_CMD_SUBSECTOR_ERASE, 0, 0);
390
392 WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8 |
393 WSPI_CFG_ADDR_MODE_ONE_LINE |
394 WSPI_CFG_DATA_MODE_ONE_LINE,
395 JEDEC_CMD_PAGE_PROGRAM, 0, 0);
396
397 /* TODO: how to check addressing in SFDP? */
398 if (1) {
399 jedec_cmd_read.cfg |= WSPI_CFG_ADDR_SIZE_24;
400 jedec_cmd_erase.cfg |= WSPI_CFG_ADDR_SIZE_24;
401 jedec_cmd_program.cfg |= WSPI_CFG_ADDR_SIZE_24;
402 } else {
403 jedec_cmd_read.cfg |= WSPI_CFG_ADDR_SIZE_32;
404 jedec_cmd_erase.cfg |= WSPI_CFG_ADDR_SIZE_32;
405 jedec_cmd_program.cfg |= WSPI_CFG_ADDR_SIZE_32;
406 }
407}
408
409flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
410 size_t n, uint8_t *rp) {
411 while (n) {
412 size_t chunk = n < sizeof(tmpbuf) ? n : sizeof(tmpbuf);
413
414 jedec_cmd_read.addr = offset;
415 /* read through non-cached buffer */
416 if (wspiReceive(devp->config->busp, &jedec_cmd_read, chunk, tmpbuf))
417 return FLASH_ERROR_READ;
418
419 memcpy(rp, tmpbuf, chunk);
420 offset += chunk;
421 rp += chunk;
422 n -= chunk;
423 }
424
425 return FLASH_NO_ERROR;
426}
427
428flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
429 size_t n, const uint8_t *pp) {
430 /* Data is programmed page by page.*/
431 while (n > 0U) {
432 flash_error_t err;
433
434 /* Data size that can be written in a single program page operation.*/
435 size_t chunk = (size_t)(((offset | (snor_descriptor.page_size - 1)) + 1U) - offset);
436 if (chunk > n)
437 chunk = n;
438
439 /* send through non-cached buffer */
440 memcpy(tmpbuf, pp, chunk);
441
442 /* Enabling write operation.*/
443 jedec_write_enable(devp, 1);
444
445 /* Page program command.*/
447 wspiSend(devp->config->busp, &jedec_cmd_program, chunk, tmpbuf);
448
449 /* Wait for status and check errors.*/
450 err = jedec_poll_status(devp);
451 if (err != FLASH_NO_ERROR) {
452 return err;
453 }
454
455 /* Next page.*/
456 offset += chunk;
457 pp += chunk;
458 n -= chunk;
459 }
460
461 return FLASH_NO_ERROR;
462}
463
464flash_error_t snor_device_start_erase_all(SNORDriver *devp) {
465
466 /* Enabling write operation.*/
467 jedec_write_enable(devp, 1);
468
469 /* Bulk erase command.*/
470 bus_cmd(devp, JEDEC_CMD_BULK_ERASE);
471
472 return FLASH_NO_ERROR;
473}
474
475flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
476 flash_sector_t sector) {
477 flash_offset_t offset = (flash_offset_t)(sector * snor_descriptor.sectors_size);
478
479 /* Enabling write operation.*/
480 jedec_write_enable(devp, 1);
481
482 /* Sector erase command.*/
483 jedec_cmd_erase.addr = offset;
484 wspiCommand(devp->config->busp, &jedec_cmd_erase);
485
486 return FLASH_NO_ERROR;
487}
488
489flash_error_t snor_device_verify_erase(SNORDriver *devp,
490 flash_sector_t sector) {
491 flash_offset_t offset;
492 size_t n;
493
494 /* Read command.*/
495 offset = (flash_offset_t)(sector * snor_descriptor.sectors_size);
496 n = snor_descriptor.sectors_size;
497 while (n > 0U) {
498 size_t i;
499 size_t chunk = n < sizeof(tmpbuf) ? n : sizeof(tmpbuf);
500
501 jedec_cmd_read.addr = offset;
502 /* read through non-cached buffer */
503 if (wspiReceive(devp->config->busp, &jedec_cmd_read, chunk, tmpbuf)) {
504 return FLASH_ERROR_READ;
505 }
506
507 /* Checking for erased state of current buffer.*/
508 for (i = 0; i < chunk; i++) {
509 if (tmpbuf[i] != 0xFFU) {
510 /* Ready state again.*/
511 devp->state = FLASH_READY;
512
513 return FLASH_ERROR_VERIFY;
514 }
515 }
516
517 offset += chunk;
518 n -= chunk;
519 }
520
521 return FLASH_NO_ERROR;
522}
523
524flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec) {
525 uint8_t sts;
526
527 /* Read status command.*/
528 bus_cmd_receive(devp, JEDEC_CMD_READ_STATUS_REGISTER,
529 1, tmpbuf);
530 sts = tmpbuf[0];
531
532 /* Busy?.*/
533 if ((sts & JEDEC_FLAGS_STS_BUSY) != 0U) {
534 /* Recommended time before polling again, this is a simplified
535 implementation.*/
536 if (msec != NULL) {
537 *msec = 1U;
538 }
539
540 return FLASH_BUSY_ERASING;
541 }
542
543 return FLASH_NO_ERROR;
544}
545
546flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
547 size_t n, uint8_t *rp) {
548 /* JEDEC SFDP read command.*/
549 wspi_command_t jedec_cmd_read_sfdp = {
550 .cmd = JEDEC_CMD_READ_DISCOVERY_PARAMETER,
551 .cfg = WSPI_CFG_CMD_MODE_ONE_LINE |
552 WSPI_CFG_CMD_SIZE_8 |
553 WSPI_CFG_ADDR_MODE_ONE_LINE |
554 WSPI_CFG_ADDR_SIZE_24 |
555 WSPI_CFG_ALT_MODE_NONE |
556 WSPI_CFG_DATA_MODE_ONE_LINE,
557 .addr = 0,
558 .alt = 0,
559 .dummy = 8 /* cycles, not bytes! */
560 };
561
562 while (n) {
563 size_t chunk = n < sizeof(tmpbuf) ? n : sizeof(tmpbuf);
564
565 jedec_cmd_read_sfdp.addr = offset;
566 /* read through non-cached buffer */
567 if (wspiReceive(devp->config->busp, &jedec_cmd_read_sfdp, chunk, tmpbuf))
568 return FLASH_ERROR_HW_FAILURE;
569
570 memcpy(rp, tmpbuf, chunk);
571
572 offset += chunk;
573 rp += chunk;
574 n -= chunk;
575 }
576
577 return FLASH_NO_ERROR;
578}
579
580#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
581void snor_activate_xip(SNORDriver *devp) {
582 (void)devp;
583#if 0
584 static const uint8_t flash_status_xip[1] = {
585 (JEDEC_READ_DUMMY_CYCLES << 4U) | 0x07U
586 };
587
588 /* Activating XIP mode in the device.*/
589 jedec_write_enable(devp, 1);
590 bus_cmd_send(devp, JEDEC_CMD_WRITE_V_CONF_REGISTER,
591 1, flash_status_xip);
592#endif
593}
594
595void snor_reset_xip(SNORDriver *devp) {
596 (void)devp;
597#if 0
598 static const uint8_t flash_conf[1] = {
599 (JEDEC_READ_DUMMY_CYCLES << 4U) | 0x0FU
600 };
601 wspi_command_t cmd;
602 uint8_t buf[1];
603
604 /* Resetting XIP mode by reading one byte without XIP confirmation bit.*/
605 cmd.cmd = 0U;
606 cmd.alt = 0xFFU;
607 cmd.addr = 0U;
608 cmd.dummy = JEDEC_READ_DUMMY_CYCLES - 2U;
609 cmd.cfg = WSPI_CFG_CMD_MODE_NONE |
610 WSPI_CFG_ADDR_SIZE_24 |
611#if JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI1L
612 WSPI_CFG_ADDR_MODE_ONE_LINE |
613 WSPI_CFG_DATA_MODE_ONE_LINE |
614#elif JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI2L
615 WSPI_CFG_ADDR_MODE_TWO_LINES |
616 WSPI_CFG_DATA_MODE_TWO_LINES |
617#elif JEDEC_BUS_MODE == JEDEC_BUS_MODE_WSPI4L
618 WSPI_CFG_ADDR_MODE_FOUR_LINES |
619 WSPI_CFG_DATA_MODE_FOUR_LINES |
620#else
621 WSPI_CFG_ADDR_MODE_EIGHT_LINES |
622 WSPI_CFG_DATA_MODE_EIGHT_LINES |
623#endif
624 WSPI_CFG_ALT_MODE_FOUR_LINES | /* Always 4 lines, note.*/
625 WSPI_CFG_ALT_SIZE_8;
626 wspiReceive(devp->config->busp, &cmd, 1, buf);
627
628 /* Enabling write operation.*/
629 jedec_write_enable(devp, 1);
630 /* Rewriting volatile configuration register.*/
631 bus_cmd_send(devp, JEDEC_CMD_WRITE_V_CONF_REGISTER,
632 1, flash_conf);
633#endif
634}
635#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
636
637/** @} */
typedef __attribute__
Ignition Mode.
void snor_activate_xip(SNORDriver *devp)
flash_error_t snor_device_verify_erase(SNORDriver *devp, flash_sector_t sector)
flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec)
static void snor_device_fill_cmd(wspi_command_t *cmd, uint32_t cfg, uint8_t opcode, uint8_t mode_clocks, uint8_t dummy_clocks)
static void jedec_reset_memory(SNORDriver *devp)
flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset, size_t n, uint8_t *rp)
static void jedec_set_config(SNORDriver *devp, uint8_t val)
static flash_error_t jedec_poll_status(SNORDriver *devp)
static wspi_command_t jedec_cmd_read
void snor_reset_xip(SNORDriver *devp)
static wspi_command_t jedec_cmd_program
flash_error_t snor_device_start_erase_sector(SNORDriver *devp, flash_sector_t sector)
const wspi_command_t snor_memmap_read
Fast read command for memory mapped mode.
flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset, size_t n, uint8_t *rp)
static uint8_t jedec_get_config(SNORDriver *devp)
flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset, size_t n, const uint8_t *pp)
static wspi_command_t jedec_cmd_erase
flash_descriptor_t snor_descriptor
Flash descriptor.
static void jedec_write_enable(SNORDriver *devp, int enable)
void snor_device_init(SNORDriver *devp)
flash_error_t snor_device_start_erase_all(SNORDriver *devp)
static uint32_t sfdpbuf[64/4]
static union @47 NO_CACHE
static void enable(const char *param)
Definition settings.cpp:441
uint16_t offset
Definition tunerstudio.h:0