Intel® Quark™ Microcontroller Software Interface 1.4.0 Intel® Quark™ Microcontroller BSP

- Main Page
- Modules
- Data Structures
- Files

- File List

qm_flash.c
1 /*
2 * {% copyright %}
3 */
4
5 #include "qm_flash.h"
6
7 #ifndef UNIT_TEST
8 #if (QUARK_SE)
9 qm_flash_reg_t *qm_flash[QM_FLASH_NUM] = {(qm_flash_reg_t *)QM_FLASH_BASE_0,
10 (qm_flash_reg_t *)QM_FLASH_BASE_1};
11 #elif(QUARK_D2000)
12 qm_flash_reg_t *qm_flash[QM_FLASH_NUM] = {(qm_flash_reg_t *)QM_FLASH_BASE_0};
13 #endif
14 #endif
15
16 static __inline__ bool qm_flash_check_otp_locked(const uint32_t flash_stts)
17 {
18 return (
19 (QM_FLASH_STTS_ROM_PROG == (flash_stts & QM_FLASH_STTS_ROM_PROG)));
20 }
21
22 int qm_flash_set_config(const qm_flash_t flash, const qm_flash_config_t *cfg)
23 {
24 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
25 QM_CHECK(cfg != NULL, -EINVAL);
26 QM_CHECK(cfg->wait_states <= QM_FLASH_MAX_WAIT_STATES, -EINVAL);
27 QM_CHECK(cfg->us_count <= QM_FLASH_MAX_US_COUNT, -EINVAL);
28 QM_CHECK(cfg->write_disable <= QM_FLASH_WRITE_DISABLE, -EINVAL);
29
30 qm_flash_reg_t *const controller = QM_FLASH[flash];
31
32 controller->tmg_ctrl =
33 (controller->tmg_ctrl & QM_FLASH_TMG_DEF_MASK) |
34 (cfg->us_count | (cfg->wait_states << QM_FLASH_WAIT_STATE_OFFSET));
35
36 if (cfg->write_disable == QM_FLASH_WRITE_DISABLE) {
37 controller->ctrl |= QM_FLASH_WRITE_DISABLE_VAL;
38 }
39
40 return 0;
41 }
42
43 int qm_flash_word_write(const qm_flash_t flash, const qm_flash_region_t region,
44 uint32_t f_addr, const uint32_t data)
45 {
46 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
47 QM_CHECK(region <= QM_FLASH_REGION_NUM, -EINVAL);
48 QM_CHECK(f_addr < QM_FLASH_MAX_ADDR, -EINVAL);
49
50 volatile uint32_t *p_wr_data, *p_wr_ctrl;
51
52 qm_flash_reg_t *const controller = QM_FLASH[flash];
53
54 /* Rom and flash write registers are laid out the same, but different */
55 /* locations in memory, so point to those to have the same function to*/
56 /* update page section based on main or rom. */
57 switch (region) {
58
59 case QM_FLASH_REGION_SYS:
60 p_wr_data = &controller->flash_wr_data;
61 p_wr_ctrl = &controller->flash_wr_ctrl;
62 #if (QUARK_D2000)
63 /* Main flash memory starts after flash data section. */
64 f_addr += QM_FLASH_REGION_DATA_0_SIZE;
65 #endif
66 break;
67
68 #if (QUARK_D2000)
69 case QM_FLASH_REGION_DATA:
70 p_wr_data = &controller->flash_wr_data;
71 p_wr_ctrl = &controller->flash_wr_ctrl;
72 break;
73 #endif
74
75 case QM_FLASH_REGION_OTP:
76
77 if (qm_flash_check_otp_locked(controller->flash_stts)) {
78 return -EACCES;
79 }
80
81 p_wr_data = &controller->rom_wr_data;
82 p_wr_ctrl = &controller->rom_wr_ctrl;
83 break;
84
85 default:
86 return -EINVAL;
87 break;
88 }
89 /* Update address to include the write_address offset. */
90 f_addr <<= WR_ADDR_OFFSET;
91
92 *p_wr_data = data;
93 *p_wr_ctrl = f_addr |= WR_REQ;
94 /* Wait for write to finish. */
95 while (!(controller->flash_stts & WR_DONE))
96 ;
97 return 0;
98 }
99
100 int qm_flash_page_write(const qm_flash_t flash, const qm_flash_region_t region,
101 uint32_t page_num, const uint32_t *const data,
102 uint32_t len)
103 {
104 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
105 QM_CHECK(region <= QM_FLASH_REGION_NUM, -EINVAL);
106 QM_CHECK(page_num <= QM_FLASH_MAX_PAGE_NUM, -EINVAL);
107 QM_CHECK(data != NULL, -EINVAL);
108 QM_CHECK(len <= QM_FLASH_PAGE_SIZE_DWORDS, -EINVAL);
109
110 uint32_t i;
111 volatile uint32_t *p_wr_data, *p_wr_ctrl;
112
113 qm_flash_reg_t *const controller = QM_FLASH[flash];
114
115 /* Rom and flash write registers are laid out the same, but different */
116 /* locations in memory, so point to those to have the same function to*/
117 /* update page section based on main or rom. */
118 switch (region) {
119
120 case QM_FLASH_REGION_SYS:
121 #if (QUARK_D2000)
122 page_num += QM_FLASH_REGION_DATA_0_PAGES;
123
124 case QM_FLASH_REGION_DATA:
125 #endif
126 p_wr_data = &controller->flash_wr_data;
127 p_wr_ctrl = &controller->flash_wr_ctrl;
128 break;
129
130 case QM_FLASH_REGION_OTP:
131
132 /* Check if OTP locked. */
133 if (qm_flash_check_otp_locked(controller->flash_stts)) {
134 return -EACCES;
135 }
136
137 p_wr_data = &controller->rom_wr_data;
138 p_wr_ctrl = &controller->rom_wr_ctrl;
139 break;
140
141 default:
142 return -EINVAL;
143 break;
144 }
145 /* Update address to include the write_address offset. */
146 page_num <<= (QM_FLASH_PAGE_SIZE_BITS + WR_ADDR_OFFSET);
147
148 /* Erase the Flash page. */
149 *p_wr_ctrl = page_num | ER_REQ;
150
151 /* Wait for the erase to complete. */
152 while (!(controller->flash_stts & ER_DONE))
153 ;
154
155 /* Write bytes into Flash. */
156 for (i = 0; i < len; i++) {
157 *p_wr_data = data[i];
158 *p_wr_ctrl = page_num;
159 *p_wr_ctrl |= WR_REQ;
160 page_num += QM_FLASH_ADDR_INC;
161 /* Wait for write to finish. */
162 while (!(controller->flash_stts & WR_DONE))
163 ;
164 }
165 return 0;
166 }
167
168 int qm_flash_page_update(const qm_flash_t flash, const qm_flash_region_t region,
169 uint32_t f_addr, uint32_t *const page_buffer,
170 const uint32_t *const data_buffer, uint32_t len)
171 {
172 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
173 QM_CHECK(region <= QM_FLASH_REGION_NUM, -EINVAL);
174 QM_CHECK(f_addr < QM_FLASH_MAX_ADDR, -EINVAL);
175 QM_CHECK(page_buffer != NULL, -EINVAL);
176 QM_CHECK(data_buffer != NULL, -EINVAL);
177 QM_CHECK(len <= QM_FLASH_PAGE_SIZE_DWORDS, -EINVAL);
178
179 uint32_t i, j;
180 volatile uint32_t *p_flash = NULL, *p_wr_data, *p_wr_ctrl;
181
182 qm_flash_reg_t *const controller = QM_FLASH[flash];
183
184 /* Rom and flash write registers are laid out the same, but different */
185 /* locations in memory, so point to those to have the same function to*/
186 /* update page section based on main or rom. */
187 switch (region) {
188
189 case QM_FLASH_REGION_SYS:
190 p_wr_data = &controller->flash_wr_data;
191 p_wr_ctrl = &controller->flash_wr_ctrl;
192 #if (QUARK_D2000)
193 p_flash = (uint32_t *)(QM_FLASH_REGION_SYS_0_BASE +
194 (f_addr & QM_FLASH_PAGE_MASK));
195 /* Main flash memory starts after flash data section. */
196 f_addr += QM_FLASH_REGION_DATA_0_SIZE;
197 #elif(QUARK_SE)
198 if (flash == QM_FLASH_0) {
199 p_flash = (uint32_t *)(QM_FLASH_REGION_SYS_0_BASE +
200 (f_addr & QM_FLASH_PAGE_MASK));
201 } else {
202 p_flash = (uint32_t *)(QM_FLASH_REGION_SYS_1_BASE +
203 (f_addr & QM_FLASH_PAGE_MASK));
204 }
205 #else
206 #error("Unsupported / unspecified processor type")
207 #endif
208 break;
209
210 #if (QUARK_D2000)
211 case QM_FLASH_REGION_DATA:
212 p_wr_data = &controller->flash_wr_data;
213 p_wr_ctrl = &controller->flash_wr_ctrl;
214 p_flash = (uint32_t *)(QM_FLASH_REGION_DATA_0_BASE +
215 (f_addr & QM_FLASH_PAGE_MASK));
216 break;
217 #endif
218
219 case QM_FLASH_REGION_OTP:
220
221 /* Check if OTP locked. */
222 if (qm_flash_check_otp_locked(controller->flash_stts)) {
223 return -EACCES;
224 }
225
226 p_wr_data = &controller->rom_wr_data;
227 p_wr_ctrl = &controller->rom_wr_ctrl;
228 p_flash = (uint32_t *)(QM_FLASH_REGION_OTP_0_BASE +
229 (f_addr & QM_FLASH_PAGE_MASK));
230 break;
231
232 default:
233 return -EINVAL;
234 break;
235 }
236
237 /* Copy Flash Page, with location to be modified, to SRAM */
238 for (i = 0; i < QM_FLASH_PAGE_SIZE_DWORDS; i++) {
239 page_buffer[i] = *p_flash;
240 p_flash++;
241 }
242
243 /* Erase the Flash page */
244 *p_wr_ctrl = ((f_addr & QM_FLASH_PAGE_MASK) << WR_ADDR_OFFSET) | ER_REQ;
245
246 /* Update sram data with new data */
247 j = (f_addr & QM_FLASH_ADDRESS_MASK) >> 2;
248 for (i = 0; i < len; i++, j++) {
249 page_buffer[j] = data_buffer[i];
250 }
251
252 /* Wait for the erase to complete */
253 while (!(controller->flash_stts & ER_DONE))
254 ;
255
256 /* Update address to include the write_address offset. */
257 f_addr &= QM_FLASH_PAGE_MASK;
258 f_addr <<= WR_ADDR_OFFSET;
259 /* Copy the modified page in SRAM into Flash. */
260 for (i = 0; i < QM_FLASH_PAGE_SIZE_DWORDS; i++) {
261 *p_wr_data = page_buffer[i];
262 *p_wr_ctrl = f_addr |= WR_REQ;
263 f_addr += QM_FLASH_ADDR_INC;
264 /* Wait for write to finish. */
265 while (!(controller->flash_stts & WR_DONE))
266 ;
267 }
268 return 0;
269 }
270
271 int qm_flash_page_erase(const qm_flash_t flash, const qm_flash_region_t region,
272 uint32_t page_num)
273 {
274 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
275 QM_CHECK(region <= QM_FLASH_REGION_NUM, -EINVAL);
276 QM_CHECK(page_num <= QM_FLASH_MAX_PAGE_NUM, -EINVAL);
277
278 qm_flash_reg_t *const controller = QM_FLASH[flash];
279
280 switch (region) {
281
282 case QM_FLASH_REGION_SYS:
283 #if (QUARK_D2000)
284 page_num += QM_FLASH_REGION_DATA_0_PAGES;
285
286 case QM_FLASH_REGION_DATA:
287 #endif
288 controller->flash_wr_ctrl =
289 (page_num << (QM_FLASH_PAGE_SIZE_BITS + WR_ADDR_OFFSET)) |
290 ER_REQ;
291 break;
292
293 case QM_FLASH_REGION_OTP:
294
295 /* Check if OTP locked. */
296 if (qm_flash_check_otp_locked(controller->flash_stts)) {
297 return -EACCES;
298 }
299
300 controller->rom_wr_ctrl =
301 (page_num << (QM_FLASH_PAGE_SIZE_BITS + WR_ADDR_OFFSET)) |
302 ER_REQ;
303 break;
304 default:
305 return -EINVAL;
306 }
307
308 while (!(controller->flash_stts & ER_DONE))
309 ;
310
311 return 0;
312 }
313
314 int qm_flash_mass_erase(const qm_flash_t flash, const uint8_t include_rom)
315 {
316 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
317
318 qm_flash_reg_t *const controller = QM_FLASH[flash];
319
320 /* Erase all the Flash pages */
321 if (include_rom) {
322
323 /* Check if OTP locked. */
324 if (qm_flash_check_otp_locked(controller->flash_stts)) {
325 return -EACCES;
326 }
327
328 controller->ctrl |= MASS_ERASE_INFO;
329 }
330 controller->ctrl |= MASS_ERASE;
331 while (!(controller->flash_stts & ER_DONE))
332 ;
333 return 0;
334 }
335
336 #if (ENABLE_RESTORE_CONTEXT)
337 int qm_flash_save_context(const qm_flash_t flash, qm_flash_context_t *const ctx)
338 {
339 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
340 QM_CHECK(ctx != NULL, -EINVAL);
341
342 qm_flash_reg_t *const controller = QM_FLASH[flash];
343
344 ctx->tmg_ctrl = controller->tmg_ctrl;
345 ctx->ctrl = controller->ctrl;
346
347 return 0;
348 }
349
350 int qm_flash_restore_context(const qm_flash_t flash,
351 const qm_flash_context_t *const ctx)
352 {
353 QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
354 QM_CHECK(ctx != NULL, -EINVAL);
355
356 qm_flash_reg_t *const controller = QM_FLASH[flash];
357
358 controller->tmg_ctrl = ctx->tmg_ctrl;
359 controller->ctrl = ctx->ctrl;
360
361 return 0;
362 }
363 #else
364 int qm_flash_save_context(const qm_flash_t flash, qm_flash_context_t *const ctx)
365 {
366 (void)flash;
367 (void)ctx;
368
369 return 0;
370 }
371
372 int qm_flash_restore_context(const qm_flash_t flash,
373 const qm_flash_context_t *const ctx)
374 {
375 (void)flash;
376 (void)ctx;
377
378 return 0;
379 }
380 #endif /* ENABLE_RESTORE_CONTEXT */
qm_flash_reg_t::flash_stts
QM_RW uint32_t flash_stts
FLASH_STTS.
Definition: qm_soc_regs.h:1150
qm_flash_restore_context
int qm_flash_restore_context(const qm_flash_t flash, const qm_flash_context_t *const ctx)
Restore flash context.
Definition: qm_flash.c:350
qm_flash_page_update
int qm_flash_page_update(const qm_flash_t flash, const qm_flash_region_t region, uint32_t f_addr, uint32_t *const page_buffer, const uint32_t *const data_buffer, uint32_t len)
Write multiple of 4 bytes of data to Flash.
Definition: qm_flash.c:168
qm_flash_context_t::ctrl
uint32_t ctrl
Control Register.
Definition: qm_soc_regs.h:1470
QM_FLASH_WRITE_DISABLE
Flash write disable.
Definition: qm_flash.h:35
QM_FLASH_REGION_NUM
Total number of flash regions.
Definition: qm_flash.h:27
qm_flash_context_t::tmg_ctrl
uint32_t tmg_ctrl
Flash Timing Control Register.
Definition: qm_soc_regs.h:1468
qm_flash_t
qm_flash_t
Number of Flash controllers.
Definition: qm_soc_regs.h:1141
qm_flash_mass_erase
int qm_flash_mass_erase(const qm_flash_t flash, const uint8_t include_rom)
Perform mass erase.
Definition: qm_flash.c:314
qm_flash_reg_t::flash_wr_ctrl
QM_RW uint32_t flash_wr_ctrl
FLASH_WR_CTRL.
Definition: qm_soc_regs.h:1148
qm_flash_config_t::write_disable
qm_flash_disable_t write_disable
Write Disable.
Definition: qm_flash.h:55
qm_flash_save_context
int qm_flash_save_context(const qm_flash_t flash, qm_flash_context_t *const ctx)
Save flash context.
Definition: qm_flash.c:337
QM_FLASH_REGION_SYS
Flash System region.
Definition: qm_flash.h:23
QM_FLASH_REGION_DATA
Flash Data region (Quark D2000 only).
Definition: qm_flash.h:25
qm_flash_reg_t::tmg_ctrl
QM_RW uint32_t tmg_ctrl
TMG_CTRL.
Definition: qm_soc_regs.h:1145
qm_flash_reg_t::ctrl
QM_RW uint32_t ctrl
CTRL.
Definition: qm_soc_regs.h:1151
qm_flash_word_write
int qm_flash_word_write(const qm_flash_t flash, const qm_flash_region_t region, uint32_t f_addr, const uint32_t data)
Write 4 bytes of data to Flash.
Definition: qm_flash.c:43
qm_flash_context_t
Flash context type.
Definition: qm_soc_regs.h:1466
qm_flash_reg_t::rom_wr_data
QM_RW uint32_t rom_wr_data
ROM_WR_DATA.
Definition: qm_soc_regs.h:1147
qm_flash_reg_t::rom_wr_ctrl
QM_RW uint32_t rom_wr_ctrl
ROM_WR_CTRL.
Definition: qm_soc_regs.h:1146
qm_flash_reg_t
Flash register map.
Definition: qm_soc_regs.h:1144
QM_FLASH_REGION_OTP
Flash OTP region.
Definition: qm_flash.h:22
qm_flash_region_t
qm_flash_region_t
Flash region enum.
Definition: qm_flash.h:21
qm_flash_reg_t::flash_wr_data
QM_RW uint32_t flash_wr_data
FLASH_WR_DATA.
Definition: qm_soc_regs.h:1149
qm_flash_config_t::us_count
uint8_t us_count
Number of clocks in a microsecond.
Definition: qm_flash.h:48
qm_flash_config_t
Flash configuration structure.
Definition: qm_flash.h:41
qm_flash_config_t::wait_states
uint8_t wait_states
Read wait state.
Definition: qm_flash.h:42
qm_flash_page_erase
int qm_flash_page_erase(const qm_flash_t flash, const qm_flash_region_t region, uint32_t page_num)
Erase one page of Flash.
Definition: qm_flash.c:271
qm_flash_page_write
int qm_flash_page_write(const qm_flash_t flash, const qm_flash_region_t region, uint32_t page_num, const uint32_t *const data, uint32_t len)
Write a flash page.
Definition: qm_flash.c:100
qm_flash_set_config
int qm_flash_set_config(const qm_flash_t flash, const qm_flash_config_t *cfg)
Configure a Flash controller.
Definition: qm_flash.c:22