1 /*
2 * Copyright (c) 2024 STMicroelectronics
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT st_stm32wb0_flash_controller
8
9 #include <zephyr/init.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/flash.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/math_extras.h>
15
16 /* <soc.h> also brings "stm32wb0x_hal_flash.h"
17 * and "system_stm32wb0x.h", which provide macros
18 * used by the driver, such as FLASH_PAGE_SIZE or
19 * _MEMORY_FLASH_SIZE_ respectively.
20 */
21 #include <soc.h>
22 #include <stm32_ll_bus.h>
23 #include <stm32_ll_rcc.h>
24 #include <stm32_ll_system.h>
25
26 #include <zephyr/logging/log.h>
27 LOG_MODULE_REGISTER(flash_stm32wb0x, CONFIG_FLASH_LOG_LEVEL);
28
29 /**
30 * Driver private definitions & assertions
31 */
32 #define SYSTEM_FLASH_SIZE _MEMORY_FLASH_SIZE_
33 #define PAGES_IN_FLASH (SYSTEM_FLASH_SIZE / FLASH_PAGE_SIZE)
34
35 #define WRITE_BLOCK_SIZE \
36 DT_PROP(DT_INST(0, soc_nv_flash), write_block_size)
37
38 /* Size of flash words, in bytes (equal to write block size) */
39 #define WORD_SIZE WRITE_BLOCK_SIZE
40
41 #define ERASE_BLOCK_SIZE \
42 DT_PROP(DT_INST(0, soc_nv_flash), erase_block_size)
43
44 /**
45 * Driver private structures
46 */
47 struct flash_wb0x_data {
48 /** Used to serialize write/erase operations */
49 struct k_sem write_lock;
50
51 /** Flash size, in bytes */
52 size_t flash_size;
53 };
54
55 /**
56 * Driver private utility functions
57 */
read_mem_u32(const uint32_t * ptr)58 static inline uint32_t read_mem_u32(const uint32_t *ptr)
59 {
60 /**
61 * Fetch word using sys_get_le32, which performs byte-sized
62 * reads instead of word-sized. This is important as ptr may
63 * be unaligned. We also want to use le32 because the data is
64 * stored in little-endian inside the flash.
65 */
66 return sys_get_le32((const uint8_t *)ptr);
67 }
68
get_flash_size_in_bytes(void)69 static inline size_t get_flash_size_in_bytes(void)
70 {
71 /* FLASH.SIZE contains the highest flash address supported
72 * on this MCU, which is also the number of words in flash
73 * minus one.
74 */
75 const uint32_t words_in_flash =
76 READ_BIT(FLASH->SIZE, FLASH_FLASH_SIZE_FLASH_SIZE) + 1;
77
78 return words_in_flash * WORD_SIZE;
79 }
80
81 /**
82 * @brief Returns the associated error to IRQ flags.
83 *
84 * @returns a negative error value
85 */
error_from_irq_flags(uint32_t flags)86 static int error_from_irq_flags(uint32_t flags)
87 {
88 /**
89 * Only two errors are expected:
90 * - illegal command
91 * - command error
92 */
93 if (flags & FLASH_FLAG_ILLCMD) {
94 return -EINVAL;
95 }
96
97 if (flags & FLASH_FLAG_CMDERR) {
98 return -EIO;
99 }
100
101 /*
102 * Unexpected error flag -> "out of domain"
103 * In practice, this should never be reached.
104 */
105 return -EDOM;
106 }
107
is_valid_flash_range(const struct device * dev,off_t offset,uint32_t len)108 static bool is_valid_flash_range(const struct device *dev,
109 off_t offset, uint32_t len)
110 {
111 const struct flash_wb0x_data *data = dev->data;
112 uint32_t offset_plus_len;
113
114 /* (offset + len) must not overflow */
115 return !u32_add_overflow(offset, len, &offset_plus_len)
116 /* offset must be a valid offset in flash */
117 && IN_RANGE(offset, 0, data->flash_size - 1)
118 /* (offset + len) must be in [0; flash size]
119 * because it is equal to the last accessed
120 * byte in flash plus one (an access of `len`
121 * bytes starting at `offset` touches bytes
122 * `offset` to `offset + len` EXCLUDED)
123 */
124 && IN_RANGE(offset_plus_len, 0, data->flash_size);
125 }
126
is_writeable_flash_range(const struct device * dev,off_t offset,uint32_t len)127 static bool is_writeable_flash_range(const struct device *dev,
128 off_t offset, uint32_t len)
129 {
130 if ((offset % WRITE_BLOCK_SIZE) != 0
131 || (len % WRITE_BLOCK_SIZE) != 0) {
132 return false;
133 }
134
135 return is_valid_flash_range(dev, offset, len);
136 }
137
is_erasable_flash_range(const struct device * dev,off_t offset,uint32_t len)138 static bool is_erasable_flash_range(const struct device *dev,
139 off_t offset, uint32_t len)
140 {
141 if ((offset % ERASE_BLOCK_SIZE) != 0
142 || (len % ERASE_BLOCK_SIZE) != 0) {
143 return false;
144 }
145
146 return is_valid_flash_range(dev, offset, len);
147 }
148
149 /**
150 * Driver private functions
151 */
152
poll_flash_controller(void)153 static uint32_t poll_flash_controller(void)
154 {
155 uint32_t flags;
156
157 /* Poll until an interrupt flag is raised */
158 do {
159 flags = FLASH->IRQRAW;
160 } while (flags == 0);
161
162 /* Acknowledge the flag(s) we have seen */
163 FLASH->IRQRAW = flags;
164
165 return flags;
166 }
167
execute_flash_command(uint8_t cmd)168 static int execute_flash_command(uint8_t cmd)
169 {
170 uint32_t irq_flags;
171
172 /* Clear all pending interrupt bits */
173 FLASH->IRQRAW = FLASH->IRQRAW;
174
175 /* Start command */
176 FLASH->COMMAND = cmd;
177
178 /* Wait for CMDSTART */
179 irq_flags = poll_flash_controller();
180
181 /* If command didn't start, an error occurred */
182 if (!(irq_flags & FLASH_IT_CMDSTART)) {
183 return error_from_irq_flags(irq_flags);
184 }
185
186 /**
187 * Both CMDSTART and CMDDONE may be set if the command was
188 * executed fast enough. In this case, we're already done.
189 * Otherwise, we need to poll again until CMDDONE/error occurs.
190 */
191 if (!(irq_flags & FLASH_IT_CMDDONE)) {
192 irq_flags = poll_flash_controller();
193 }
194
195 if (!(irq_flags & FLASH_IT_CMDDONE)) {
196 return error_from_irq_flags(irq_flags);
197 } else {
198 return 0;
199 }
200 }
201
erase_page_range(uint32_t start_page,uint32_t page_count)202 int erase_page_range(uint32_t start_page, uint32_t page_count)
203 {
204 int res = 0;
205
206 __ASSERT_NO_MSG(start_page < PAGES_IN_FLASH);
207 __ASSERT_NO_MSG((start_page + page_count - 1) < PAGES_IN_FLASH);
208
209 for (uint32_t i = start_page;
210 i < (start_page + page_count);
211 i++) {
212 /* ADDRESS[16:9] = XADR[10:3] (address of page to erase)
213 * ADDRESS[8:0] = 0 (row & word address, must be 0)
214 */
215 FLASH->ADDRESS = (i << 9);
216
217 res = execute_flash_command(FLASH_CMD_ERASE_PAGES);
218 if (res < 0) {
219 break;
220 }
221 }
222
223 return res;
224 }
225
write_word_range(const void * buf,uint32_t start_word,uint32_t num_words)226 int write_word_range(const void *buf, uint32_t start_word, uint32_t num_words)
227 {
228 /* Special value to load in DATAx registers to skip
229 * writing corresponding word with BURSTWRITE command.
230 */
231 const uint32_t BURST_IGNORE_VALUE = 0xFFFFFFFF;
232 const size_t WORDS_IN_BURST = 4;
233 uint32_t dst_addr = start_word;
234 uint32_t remaining = num_words;
235 /**
236 * Note that @p buf may not be aligned to 32-bit boundary.
237 * However, declaring src_ptr as uint32_t* makes the address
238 * increment by 4 every time we do src_ptr++, which makes it
239 * behave like the other counters in this function.
240 */
241 const uint32_t *src_ptr = buf;
242 int res = 0;
243
244 /**
245 * Write to flash is performed as a 3 step process:
246 * - write single words using WRITE commands until the write
247 * write address is aligned to flash quadword boundary
248 *
249 * - after write address is aligned to quadword, we can use
250 * the BURSTWRITE commands to write 4 words at a time
251 *
252 * - once less than 4 words remain to write, a last BURSTWRITE
253 * is used with unneeded DATAx registers filled with 0xFFFFFFFF
254 * (this makes BURSTWRITE ignore write to these addresses)
255 */
256
257 /* (1) Align to quadword boundary with WRITE commands */
258 while (remaining > 0 && (dst_addr % WORDS_IN_BURST) != 0) {
259 FLASH->ADDRESS = dst_addr;
260 FLASH->DATA0 = read_mem_u32(src_ptr);
261
262 res = execute_flash_command(FLASH_CMD_WRITE);
263 if (res < 0) {
264 return res;
265 }
266
267 src_ptr++;
268 dst_addr++;
269 remaining--;
270 }
271
272 /* (2) Write bursts of quadwords */
273 while (remaining >= WORDS_IN_BURST) {
274 __ASSERT_NO_MSG((dst_addr % WORDS_IN_BURST) == 0);
275
276 FLASH->ADDRESS = dst_addr;
277 FLASH->DATA0 = read_mem_u32(src_ptr + 0);
278 FLASH->DATA1 = read_mem_u32(src_ptr + 1);
279 FLASH->DATA2 = read_mem_u32(src_ptr + 2);
280 FLASH->DATA3 = read_mem_u32(src_ptr + 3);
281
282 res = execute_flash_command(FLASH_CMD_BURSTWRITE);
283 if (res < 0) {
284 return res;
285 }
286
287 src_ptr += WORDS_IN_BURST;
288 dst_addr += WORDS_IN_BURST;
289 remaining -= WORDS_IN_BURST;
290 }
291
292 /* (3) Write trailing (between 1 and 3 words) */
293 if (remaining > 0) {
294 __ASSERT_NO_MSG(remaining < WORDS_IN_BURST);
295 __ASSERT_NO_MSG((dst_addr % WORDS_IN_BURST) == 0);
296
297 FLASH->ADDRESS = dst_addr;
298 FLASH->DATA0 = read_mem_u32(src_ptr + 0);
299
300 FLASH->DATA1 = (remaining >= 2)
301 ? read_mem_u32(src_ptr + 1)
302 : BURST_IGNORE_VALUE;
303
304 FLASH->DATA2 = (remaining == 3)
305 ? read_mem_u32(src_ptr + 2)
306 : BURST_IGNORE_VALUE;
307
308 FLASH->DATA3 = BURST_IGNORE_VALUE;
309
310 remaining = 0;
311
312 res = execute_flash_command(FLASH_CMD_BURSTWRITE);
313 }
314
315 return res;
316 }
317
318 /**
319 * Driver subsystem API implementation
320 */
flash_wb0x_read(const struct device * dev,off_t offset,void * buffer,size_t len)321 int flash_wb0x_read(const struct device *dev, off_t offset,
322 void *buffer, size_t len)
323 {
324 if (!len) {
325 return 0;
326 }
327
328 if (!is_valid_flash_range(dev, offset, len)) {
329 return -EINVAL;
330 }
331
332 const uint8_t *flash_base = ((void *)DT_REG_ADDR(DT_INST(0, st_stm32_nv_flash)));
333
334 memcpy(buffer, flash_base + (uint32_t)offset, len);
335
336 return 0;
337 }
338
flash_wb0x_write(const struct device * dev,off_t offset,const void * buffer,size_t len)339 int flash_wb0x_write(const struct device *dev, off_t offset,
340 const void *buffer, size_t len)
341 {
342 struct flash_wb0x_data *data = dev->data;
343 int res;
344
345 if (!len) {
346 return 0;
347 }
348
349 if (!is_writeable_flash_range(dev, offset, len)) {
350 return -EINVAL;
351 }
352
353 /* Acquire driver lock */
354 res = k_sem_take(&data->write_lock, K_NO_WAIT);
355 if (res < 0) {
356 return res;
357 }
358
359 const uint32_t start_word = (uint32_t)offset / WORD_SIZE;
360 const uint32_t num_words = len / WORD_SIZE;
361
362 res = write_word_range(buffer, start_word, num_words);
363
364 /* Release driver lock */
365 k_sem_give(&data->write_lock);
366
367 return res;
368 }
369
flash_wb0x_erase(const struct device * dev,off_t offset,size_t size)370 int flash_wb0x_erase(const struct device *dev, off_t offset, size_t size)
371 {
372 struct flash_wb0x_data *data = dev->data;
373 int res;
374
375 if (!size) {
376 return 0;
377 }
378
379 if (!is_erasable_flash_range(dev, offset, size)) {
380 return -EINVAL;
381 }
382
383 /* Acquire driver lock */
384 res = k_sem_take(&data->write_lock, K_NO_WAIT);
385 if (res < 0) {
386 return res;
387 }
388
389 const uint32_t start_page = (uint32_t)offset / ERASE_BLOCK_SIZE;
390 const uint32_t page_count = size / ERASE_BLOCK_SIZE;
391
392 res = erase_page_range(start_page, page_count);
393
394 /* Release driver lock */
395 k_sem_give(&data->write_lock);
396
397 return res;
398 }
399
flash_wb0x_get_parameters(const struct device * dev)400 const struct flash_parameters *flash_wb0x_get_parameters(
401 const struct device *dev)
402 {
403 static const struct flash_parameters fp = {
404 .write_block_size = WRITE_BLOCK_SIZE,
405 .erase_value = 0xff,
406 };
407
408 return &fp;
409 }
410
411 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
flash_wb0x_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)412 void flash_wb0x_pages_layout(const struct device *dev,
413 const struct flash_pages_layout **layout,
414 size_t *layout_size)
415 {
416 /**
417 * STM32WB0 flash: single bank, 2KiB pages
418 * (the number of pages depends on MCU)
419 */
420 static const struct flash_pages_layout fpl[] = {{
421 .pages_count = PAGES_IN_FLASH,
422 .pages_size = FLASH_PAGE_SIZE
423 }};
424
425 *layout = fpl;
426 *layout_size = ARRAY_SIZE(fpl);
427 }
428 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
429
430 static DEVICE_API(flash, flash_wb0x_api) = {
431 .erase = flash_wb0x_erase,
432 .write = flash_wb0x_write,
433 .read = flash_wb0x_read,
434 .get_parameters = flash_wb0x_get_parameters,
435 #ifdef CONFIG_FLASH_PAGE_LAYOUT
436 .page_layout = flash_wb0x_pages_layout,
437 #endif
438 /* extended operations not supported */
439 };
440
stm32wb0x_flash_init(const struct device * dev)441 int stm32wb0x_flash_init(const struct device *dev)
442 {
443 struct flash_wb0x_data *data = dev->data;
444
445 k_sem_init(&data->write_lock, 1, 1);
446
447 data->flash_size = get_flash_size_in_bytes();
448
449 return 0;
450 }
451
452 /**
453 * Driver device instantiation
454 */
455 static struct flash_wb0x_data wb0x_flash_drv_data;
456
457 DEVICE_DT_INST_DEFINE(0, stm32wb0x_flash_init, NULL,
458 &wb0x_flash_drv_data, NULL, POST_KERNEL,
459 CONFIG_FLASH_INIT_PRIORITY, &flash_wb0x_api);
460