aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/components/flash/mflash/lpc54s018m/mflash_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/components/flash/mflash/lpc54s018m/mflash_drv.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/components/flash/mflash/lpc54s018m/mflash_drv.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/components/flash/mflash/lpc54s018m/mflash_drv.c b/lib/chibios-contrib/ext/mcux-sdk/components/flash/mflash/lpc54s018m/mflash_drv.c
new file mode 100644
index 000000000..5a058835c
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/components/flash/mflash/lpc54s018m/mflash_drv.c
@@ -0,0 +1,223 @@
1/*
2 * Copyright 2017-2020 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdbool.h>
8
9#include "mflash_drv.h"
10
11#include "fsl_spifi.h"
12#include "pin_mux.h"
13
14/* Command ID */
15#define COMMAND_NUM (6)
16#define READ (0)
17#define PROGRAM_PAGE (1)
18#define GET_STATUS (2)
19#define ERASE_SECTOR (3)
20#define WRITE_ENABLE (4)
21#define WRITE_REGISTER (5)
22
23/* Commands definition, taken from SPIFI demo */
24static spifi_command_t command[COMMAND_NUM] = {
25 /* read */
26 {MFLASH_PAGE_SIZE, false, kSPIFI_DataInput, 1, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeAddrThreeBytes, 0x0B},
27 /* program */
28 {MFLASH_PAGE_SIZE, false, kSPIFI_DataOutput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeAddrThreeBytes, 0x2},
29 /* status */
30 {1, false, kSPIFI_DataInput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeOnly, 0x05},
31 /* erase */
32 {0, false, kSPIFI_DataOutput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeAddrThreeBytes, 0x20},
33 /* write enable */
34 {0, false, kSPIFI_DataOutput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeOnly, 0x06},
35 /* write register */
36 {4, false, kSPIFI_DataOutput, 0, kSPIFI_CommandAllSerial, kSPIFI_CommandOpcodeOnly, 0x01}};
37
38/* Wait until command finishes */
39static inline void mflash_drv_check_if_finish(void)
40{
41 uint8_t val = 0;
42 do
43 {
44 SPIFI_SetCommand(MFLASH_SPIFI, &command[GET_STATUS]);
45 while ((MFLASH_SPIFI->STAT & SPIFI_STAT_INTRQ_MASK) == 0U)
46 {
47 }
48 val = SPIFI_ReadDataByte(MFLASH_SPIFI);
49 } while (val & 0x1);
50}
51
52/* return offset from sector */
53static void mflash_drv_read_mode(void)
54{
55 /* Switch back to read mode */
56 SPIFI_ResetCommand(MFLASH_SPIFI);
57 SPIFI_SetMemoryCommand(MFLASH_SPIFI, &command[READ]);
58}
59
60/* Initialize SPIFI & flash peripheral,
61 * cannot be invoked directly, requires calling wrapper in non XIP memory */
62static int32_t mflash_drv_init_internal(void)
63{
64 /* NOTE: Multithread access is not supported for SRAM target.
65 * XIP target MUST be protected by disabling global interrupts
66 * since all ISR (and API that is used inside) is placed at XIP.
67 * It is necessary to place at least "mflash_drv_drv.o", "fsl_spifi.o" to SRAM */
68 /* disable interrupts when running from XIP
69 * TODO: store/restore previous PRIMASK on stack to avoid
70 * failure in case of nested critical sections !! */
71 uint32_t primask = __get_PRIMASK();
72
73 __asm("cpsid i");
74
75 spifi_config_t config = {0};
76
77#ifndef XIP_IMAGE
78 uint32_t sourceClockFreq;
79 BOARD_InitSPIFI();
80 /* Reset peripheral */
81 RESET_PeripheralReset(kSPIFI_RST_SHIFT_RSTn);
82 /* Set SPIFI clock source */
83 CLOCK_AttachClk(kFRO_HF_to_SPIFI_CLK);
84 sourceClockFreq = CLOCK_GetSpifiClkFreq();
85 /* Set the clock divider */
86 CLOCK_SetClkDiv(kCLOCK_DivSpifiClk, sourceClockFreq / MFLASH_BAUDRATE, false);
87 /* Enable SPIFI clock */
88 CLOCK_EnableClock(kCLOCK_Spifi);
89#endif
90
91 SPIFI_GetDefaultConfig(&config);
92 config.dualMode = kSPIFI_DualMode;
93#ifdef XIP_IMAGE
94 config.disablePrefetch = false; // true;
95 config.disableCachePrefech = false; // true;
96#else
97 config.disablePrefetch = false; // true;
98 config.disableCachePrefech = false; // true;
99#endif
100
101 /* Reset the Command register */
102 SPIFI_ResetCommand(MFLASH_SPIFI);
103
104 /* Set time delay parameter */
105 MFLASH_SPIFI->CTRL = SPIFI_CTRL_TIMEOUT(config.timeout) | SPIFI_CTRL_CSHIGH(config.csHighTime) |
106 SPIFI_CTRL_D_PRFTCH_DIS(config.disablePrefetch) | SPIFI_CTRL_MODE3(config.spiMode) |
107 SPIFI_CTRL_PRFTCH_DIS(config.disableCachePrefech) | SPIFI_CTRL_DUAL(config.dualMode) |
108 SPIFI_CTRL_RFCLK(config.isReadFullClockCycle) | SPIFI_CTRL_FBCLK(config.isFeedbackClock);
109
110 mflash_drv_read_mode();
111
112 if (primask == 0)
113 {
114 __asm("cpsie i");
115 }
116
117 return 0;
118}
119
120/* API - initialize 'mflash' - calling wrapper */
121int32_t mflash_drv_init(void)
122{
123 return mflash_drv_init_internal();
124}
125
126/* Erase single sector */
127static int32_t mflash_drv_sector_erase_internal(uint32_t sector_addr)
128{
129 uint32_t primask = __get_PRIMASK();
130
131 __asm("cpsid i");
132
133 /* Reset the SPIFI to switch to command mode */
134 SPIFI_ResetCommand(MFLASH_SPIFI);
135
136 /* Write enable */
137 SPIFI_SetCommand(MFLASH_SPIFI, &command[WRITE_ENABLE]);
138 /* Set address */
139 SPIFI_SetCommandAddress(MFLASH_SPIFI, sector_addr);
140 /* Erase sector */
141 SPIFI_SetCommand(MFLASH_SPIFI, &command[ERASE_SECTOR]);
142 /* Check if finished */
143 mflash_drv_check_if_finish();
144 /* Switch to read mode to enable interrupts as soon ass possible */
145 mflash_drv_read_mode();
146
147 if (primask == 0)
148 {
149 __asm("cpsie i");
150 }
151
152 /* Flush pipeline to allow pending interrupts take place */
153 __ISB();
154
155 return 0;
156}
157
158/* API - Erase single sector - calling wrapper */
159int32_t mflash_drv_sector_erase(uint32_t sector_addr)
160{
161 return mflash_drv_sector_erase_internal(sector_addr);
162}
163
164/* Page program */
165static int32_t mflash_drv_page_program_internal(uint32_t page_addr, const uint32_t *data)
166{
167 uint32_t primask = __get_PRIMASK();
168
169 __asm("cpsid i");
170
171 /* Program page */
172 SPIFI_ResetCommand(MFLASH_SPIFI);
173 SPIFI_SetCommand(MFLASH_SPIFI, &command[WRITE_ENABLE]);
174 SPIFI_SetCommandAddress(MFLASH_SPIFI, page_addr);
175 SPIFI_SetCommand(MFLASH_SPIFI, &command[PROGRAM_PAGE]);
176
177 /* Store 4B in each loop. Sector has always 4B alignment and size multiple of 4 */
178 for (uint32_t i = 0; i < MFLASH_PAGE_SIZE / sizeof(data[0]); i++)
179 {
180 SPIFI_WriteData(MFLASH_SPIFI, data[i]);
181 }
182
183 mflash_drv_check_if_finish();
184 /* Switch to read mode to enable interrupts as soon ass possible */
185 mflash_drv_read_mode();
186
187 if (primask == 0)
188 {
189 __asm("cpsie i");
190 }
191
192 /* Flush pipeline to allow pending interrupts take place */
193 __ISB();
194
195 return 0;
196}
197
198/* API - Page program - calling wrapper */
199int32_t mflash_drv_page_program(uint32_t page_addr, uint32_t *data)
200{
201 return mflash_drv_page_program_internal(page_addr, data);
202}
203
204/* API - Read data */
205int32_t mflash_drv_read(uint32_t addr, uint32_t *buffer, uint32_t len)
206{
207 memcpy(buffer, (void *)addr, len);
208 return kStatus_Success;
209}
210
211/* API - Get pointer to FLASH region */
212void *mflash_drv_phys2log(uint32_t addr, uint32_t len)
213{
214 /* FLASH is directly mapped in the address space */
215 return (void *)(addr);
216}
217
218/* API - Get pointer to FLASH region */
219uint32_t mflash_drv_log2phys(void *ptr, uint32_t len)
220{
221 /* FLASH is directly mapped in the address space */
222 return ((uint32_t)ptr);
223}