Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
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 
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 
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)
70  p_wr_data = &controller->flash_wr_data;
71  p_wr_ctrl = &controller->flash_wr_ctrl;
72  break;
73 #endif
74 
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 
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)
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 
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)
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 
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_RW uint32_t flash_stts
FLASH_STTS.
Definition: qm_soc_regs.h:1150
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
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
uint32_t ctrl
Control Register.
Definition: qm_soc_regs.h:1470
Flash write disable.
Definition: qm_flash.h:35
Total number of flash regions.
Definition: qm_flash.h:27
uint32_t tmg_ctrl
Flash Timing Control Register.
Definition: qm_soc_regs.h:1468
qm_flash_t
Number of Flash controllers.
Definition: qm_soc_regs.h:1141
int qm_flash_mass_erase(const qm_flash_t flash, const uint8_t include_rom)
Perform mass erase.
Definition: qm_flash.c:314
QM_RW uint32_t flash_wr_ctrl
FLASH_WR_CTRL.
Definition: qm_soc_regs.h:1148
qm_flash_disable_t write_disable
Write Disable.
Definition: qm_flash.h:55
int qm_flash_save_context(const qm_flash_t flash, qm_flash_context_t *const ctx)
Save flash context.
Definition: qm_flash.c:337
Flash System region.
Definition: qm_flash.h:23
Flash Data region (Quark D2000 only).
Definition: qm_flash.h:25
QM_RW uint32_t tmg_ctrl
TMG_CTRL.
Definition: qm_soc_regs.h:1145
QM_RW uint32_t ctrl
CTRL.
Definition: qm_soc_regs.h:1151
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
Flash context type.
Definition: qm_soc_regs.h:1466
QM_RW uint32_t rom_wr_data
ROM_WR_DATA.
Definition: qm_soc_regs.h:1147
QM_RW uint32_t rom_wr_ctrl
ROM_WR_CTRL.
Definition: qm_soc_regs.h:1146
Flash register map.
Definition: qm_soc_regs.h:1144
Flash OTP region.
Definition: qm_flash.h:22
qm_flash_region_t
Flash region enum.
Definition: qm_flash.h:21
QM_RW uint32_t flash_wr_data
FLASH_WR_DATA.
Definition: qm_soc_regs.h:1149
uint8_t us_count
Number of clocks in a microsecond.
Definition: qm_flash.h:48
Flash configuration structure.
Definition: qm_flash.h:41
uint8_t wait_states
Read wait state.
Definition: qm_flash.h:42
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
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
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