Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 1 | /* |
Vinayak Kariappa Chettimada | 4c123a5 | 2018-01-09 15:03:33 +0100 | [diff] [blame] | 2 | * Copyright (c) 2017-2018 Nordic Semiconductor ASA |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 3 | * Copyright (c) 2016 Linaro Limited |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 4 | * Copyright (c) 2016 Intel Corporation |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 5 | * |
David B. Kinder | ac74d8b | 2017-01-18 17:01:01 -0800 | [diff] [blame] | 6 | * SPDX-License-Identifier: Apache-2.0 |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 7 | */ |
| 8 | |
| 9 | #include <errno.h> |
| 10 | |
Flavio Santes | b04cdcd | 2016-12-04 14:59:37 -0600 | [diff] [blame] | 11 | #include <kernel.h> |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 12 | #include <device.h> |
| 13 | #include <init.h> |
| 14 | #include <soc.h> |
Anas Nashif | fe051a9 | 2019-06-25 15:53:50 -0400 | [diff] [blame] | 15 | #include <drivers/flash.h> |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 16 | #include <string.h> |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 17 | #include <nrfx_nvmc.h> |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 18 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 19 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Anas Nashif | 5eb90ec | 2019-06-26 10:33:39 -0400 | [diff] [blame] | 20 | #include <sys/__assert.h> |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 21 | #include <bluetooth/hci.h> |
Vinayak Kariappa Chettimada | 87fe440 | 2018-12-17 10:46:13 +0100 | [diff] [blame] | 22 | #include "controller/hal/ticker.h" |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 23 | #include "controller/ticker/ticker.h" |
| 24 | #include "controller/include/ll.h" |
| 25 | |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 26 | #define FLASH_SLOT_ERASE FLASH_PAGE_ERASE_MAX_TIME_US |
| 27 | #define FLASH_INTERVAL_ERASE FLASH_SLOT_ERASE |
| 28 | #define FLASH_SLOT_WRITE 7500 |
| 29 | #define FLASH_INTERVAL_WRITE FLASH_SLOT_WRITE |
| 30 | |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 31 | #define FLASH_RADIO_ABORT_DELAY_US 500 |
| 32 | #define FLASH_TIMEOUT_MS ((FLASH_PAGE_ERASE_MAX_TIME_US)\ |
| 33 | * (FLASH_PAGE_MAX_CNT) / 1000) |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 34 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 35 | |
| 36 | #define FLASH_OP_DONE (0) /* 0 for compliance with the driver API. */ |
| 37 | #define FLASH_OP_ONGOING (-1) |
| 38 | |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 39 | struct flash_context { |
| 40 | u32_t data_addr; /* Address of data to write. */ |
| 41 | u32_t flash_addr; /* Address of flash to write or erase. */ |
| 42 | u32_t len; /* Size off data to write or erase [B]. */ |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 43 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 44 | u8_t enable_time_limit; /* execution limited to timeslot. */ |
| 45 | u32_t interval; /* timeslot interval. */ |
| 46 | u32_t slot; /* timeslot length. */ |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 47 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 48 | }; /*< Context type for f. @ref write_op @ref erase_op */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 49 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 50 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 51 | typedef int (*flash_op_handler_t) (void *context); |
| 52 | |
| 53 | struct flash_op_desc { |
| 54 | flash_op_handler_t handler; |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 55 | struct flash_context *context; /* [in,out] */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 56 | int result; |
| 57 | }; |
| 58 | |
| 59 | /* semaphore for synchronization of flash operations */ |
| 60 | static struct k_sem sem_sync; |
| 61 | |
| 62 | static int write_op(void *context); /* instance of flash_op_handler_t */ |
| 63 | static int write_in_timeslice(off_t addr, const void *data, size_t len); |
| 64 | |
| 65 | static int erase_op(void *context); /* instance of flash_op_handler_t */ |
| 66 | static int erase_in_timeslice(u32_t addr, u32_t size); |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 67 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 68 | |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 69 | #if defined(CONFIG_MULTITHREADING) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 70 | /* semaphore for locking flash resources (tickers) */ |
| 71 | static struct k_sem sem_lock; |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 72 | #define SYNC_INIT() k_sem_init(&sem_lock, 1, 1) |
| 73 | #define SYNC_LOCK() k_sem_take(&sem_lock, K_FOREVER) |
| 74 | #define SYNC_UNLOCK() k_sem_give(&sem_lock) |
| 75 | #else |
| 76 | #define SYNC_INIT() |
| 77 | #define SYNC_LOCK() |
| 78 | #define SYNC_UNLOCK() |
| 79 | #endif |
Andrzej Puzdrowski | 279115e | 2019-04-01 18:00:42 +0200 | [diff] [blame] | 80 | |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 81 | static bool write_protect; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 82 | |
| 83 | static int write(off_t addr, const void *data, size_t len); |
| 84 | static int erase(u32_t addr, u32_t size); |
| 85 | |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 86 | static inline bool is_aligned_32(u32_t data) |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 87 | { |
| 88 | return (data & 0x3) ? false : true; |
| 89 | } |
| 90 | |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 91 | static inline bool is_regular_addr_valid(off_t addr, size_t len) |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 92 | { |
Andrzej Puzdrowski | 279115e | 2019-04-01 18:00:42 +0200 | [diff] [blame] | 93 | size_t flash_size = nrfx_nvmc_flash_size_get(); |
| 94 | |
Andrzej Puzdrowski | dbe5633 | 2019-11-08 15:53:49 +0100 | [diff] [blame] | 95 | if (addr >= flash_size || |
| 96 | addr < 0 || |
Andrzej Puzdrowski | 279115e | 2019-04-01 18:00:42 +0200 | [diff] [blame] | 97 | len > flash_size || |
Andrzej Puzdrowski | dbe5633 | 2019-11-08 15:53:49 +0100 | [diff] [blame] | 98 | (addr) + len > flash_size) { |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 99 | return false; |
| 100 | } |
Andrzej Puzdrowski | dbe5633 | 2019-11-08 15:53:49 +0100 | [diff] [blame] | 101 | |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 102 | return true; |
| 103 | } |
| 104 | |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 105 | |
| 106 | static inline bool is_uicr_addr_valid(off_t addr, size_t len) |
| 107 | { |
| 108 | #ifdef CONFIG_SOC_FLASH_NRF_UICR |
| 109 | if (addr >= (off_t)NRF_UICR + sizeof(*NRF_UICR) || |
| 110 | addr < (off_t)NRF_UICR || |
| 111 | len > sizeof(*NRF_UICR) || |
| 112 | addr + len > (off_t)NRF_UICR + sizeof(*NRF_UICR)) { |
| 113 | return false; |
| 114 | } |
| 115 | |
| 116 | return true; |
| 117 | #else |
| 118 | return false; |
| 119 | #endif /* CONFIG_SOC_FLASH_NRF_UICR */ |
| 120 | } |
| 121 | |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 122 | static void nvmc_wait_ready(void) |
| 123 | { |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 124 | while (!nrfx_nvmc_write_done_check()) { |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 128 | static int flash_nrf_read(struct device *dev, off_t addr, |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 129 | void *data, size_t len) |
| 130 | { |
Andrzej Puzdrowski | dbe5633 | 2019-11-08 15:53:49 +0100 | [diff] [blame] | 131 | if (is_regular_addr_valid(addr, len)) { |
| 132 | addr += DT_FLASH_BASE_ADDRESS; |
| 133 | } else if (!is_uicr_addr_valid(addr, len)) { |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 134 | return -EINVAL; |
| 135 | } |
| 136 | |
Jorge Ramirez-Ortiz | 28e60ef | 2017-02-02 19:46:50 +0100 | [diff] [blame] | 137 | if (!len) { |
| 138 | return 0; |
| 139 | } |
| 140 | |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 141 | memcpy(data, (void *)addr, len); |
| 142 | |
| 143 | return 0; |
| 144 | } |
| 145 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 146 | static int flash_nrf_write(struct device *dev, off_t addr, |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 147 | const void *data, size_t len) |
| 148 | { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 149 | int ret; |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 150 | |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 151 | if (write_protect) { |
| 152 | return -EACCES; |
| 153 | } |
| 154 | |
Andrzej Puzdrowski | dbe5633 | 2019-11-08 15:53:49 +0100 | [diff] [blame] | 155 | if (is_regular_addr_valid(addr, len)) { |
| 156 | addr += DT_FLASH_BASE_ADDRESS; |
| 157 | } else if (!is_uicr_addr_valid(addr, len)) { |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 158 | return -EINVAL; |
| 159 | } |
| 160 | |
Jorge Ramirez-Ortiz | 28e60ef | 2017-02-02 19:46:50 +0100 | [diff] [blame] | 161 | if (!len) { |
| 162 | return 0; |
| 163 | } |
| 164 | |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 165 | SYNC_LOCK(); |
Ricardo Salveti | c7e6076 | 2016-09-13 13:32:55 -0300 | [diff] [blame] | 166 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 167 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 168 | if (ticker_is_initialized(0)) { |
| 169 | ret = write_in_timeslice(addr, data, len); |
| 170 | } else |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 171 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 172 | { |
| 173 | ret = write(addr, data, len); |
Ricardo Salveti | c7e6076 | 2016-09-13 13:32:55 -0300 | [diff] [blame] | 174 | } |
| 175 | |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 176 | SYNC_UNLOCK(); |
Ricardo Salveti | c7e6076 | 2016-09-13 13:32:55 -0300 | [diff] [blame] | 177 | |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 178 | return ret; |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 179 | } |
| 180 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 181 | static int flash_nrf_erase(struct device *dev, off_t addr, size_t size) |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 182 | { |
Andrzej Puzdrowski | 279115e | 2019-04-01 18:00:42 +0200 | [diff] [blame] | 183 | u32_t pg_size = nrfx_nvmc_flash_page_size_get(); |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 184 | u32_t n_pages = size / pg_size; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 185 | int ret; |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 186 | |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 187 | if (write_protect) { |
| 188 | return -EACCES; |
| 189 | } |
| 190 | |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 191 | if (is_regular_addr_valid(addr, size)) { |
| 192 | /* Erase can only be done per page */ |
| 193 | if (((addr % pg_size) != 0) || ((size % pg_size) != 0)) { |
| 194 | return -EINVAL; |
| 195 | } |
| 196 | |
| 197 | if (!n_pages) { |
| 198 | return 0; |
| 199 | } |
Andrzej Puzdrowski | dbe5633 | 2019-11-08 15:53:49 +0100 | [diff] [blame] | 200 | |
| 201 | addr += DT_FLASH_BASE_ADDRESS; |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 202 | #ifdef CONFIG_SOC_FLASH_NRF_UICR |
| 203 | } else if (addr != (off_t)NRF_UICR || size != sizeof(*NRF_UICR)) { |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 204 | return -EINVAL; |
| 205 | } |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 206 | #else |
| 207 | } else { |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 208 | return -EINVAL; |
| 209 | } |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 210 | #endif /* CONFIG_SOC_FLASH_NRF_UICR */ |
Jorge Ramirez-Ortiz | 28e60ef | 2017-02-02 19:46:50 +0100 | [diff] [blame] | 211 | |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 212 | SYNC_LOCK(); |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 213 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 214 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 215 | if (ticker_is_initialized(0)) { |
| 216 | ret = erase_in_timeslice(addr, size); |
| 217 | } else |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 218 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 219 | { |
| 220 | ret = erase(addr, size); |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 221 | } |
| 222 | |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 223 | SYNC_UNLOCK(); |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 224 | |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 225 | return ret; |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 226 | } |
| 227 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 228 | static int flash_nrf_write_protection(struct device *dev, bool enable) |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 229 | { |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 230 | /* virtual write-erase protection */ |
| 231 | write_protect = enable; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 232 | |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 233 | return 0; |
| 234 | } |
| 235 | |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 236 | #if defined(CONFIG_FLASH_PAGE_LAYOUT) |
| 237 | static struct flash_pages_layout dev_layout; |
| 238 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 239 | static void flash_nrf_pages_layout(struct device *dev, |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 240 | const struct flash_pages_layout **layout, |
| 241 | size_t *layout_size) |
| 242 | { |
| 243 | *layout = &dev_layout; |
| 244 | *layout_size = 1; |
| 245 | } |
| 246 | #endif /* CONFIG_FLASH_PAGE_LAYOUT */ |
| 247 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 248 | static const struct flash_driver_api flash_nrf_api = { |
| 249 | .read = flash_nrf_read, |
| 250 | .write = flash_nrf_write, |
| 251 | .erase = flash_nrf_erase, |
| 252 | .write_protection = flash_nrf_write_protection, |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 253 | #if defined(CONFIG_FLASH_PAGE_LAYOUT) |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 254 | .page_layout = flash_nrf_pages_layout, |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 255 | #endif |
Andrzej Puzdrowski | 296a355 | 2017-09-29 13:03:40 +0200 | [diff] [blame] | 256 | .write_block_size = 1, |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 257 | }; |
| 258 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 259 | static int nrf_flash_init(struct device *dev) |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 260 | { |
Carles Cufi | 408ea14 | 2018-06-16 11:27:36 +0200 | [diff] [blame] | 261 | SYNC_INIT(); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 262 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 263 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 264 | k_sem_init(&sem_sync, 0, 1); |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 265 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 266 | |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 267 | #if defined(CONFIG_FLASH_PAGE_LAYOUT) |
Andrzej Puzdrowski | 279115e | 2019-04-01 18:00:42 +0200 | [diff] [blame] | 268 | dev_layout.pages_count = nrfx_nvmc_flash_page_count_get(); |
| 269 | dev_layout.pages_size = nrfx_nvmc_flash_page_size_get(); |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 270 | #endif |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 271 | write_protect = true; |
Andrzej Puzdrowski | a7863f2 | 2017-08-17 11:25:27 +0200 | [diff] [blame] | 272 | |
Ricardo Salveti | 9d03329 | 2016-07-25 23:34:52 -0300 | [diff] [blame] | 273 | return 0; |
| 274 | } |
| 275 | |
Varun Sharma | 77c643a | 2018-12-09 23:17:34 +0530 | [diff] [blame] | 276 | DEVICE_AND_API_INIT(nrf_flash, DT_FLASH_DEV_NAME, nrf_flash_init, |
| 277 | NULL, NULL, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, |
| 278 | &flash_nrf_api); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 279 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 280 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 281 | |
| 282 | static void time_slot_callback_work(u32_t ticks_at_expire, u32_t remainder, |
| 283 | u16_t lazy, void *context) |
| 284 | { |
| 285 | struct flash_op_desc *op_desc; |
| 286 | u8_t instance_index; |
| 287 | u8_t ticker_id; |
| 288 | int result; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 289 | |
Andrzej Kaczmarek | 246f4ee | 2017-08-11 12:15:38 +0200 | [diff] [blame] | 290 | __ASSERT(ll_radio_state_is_idle(), |
| 291 | "Radio is on during flash operation.\n"); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 292 | |
| 293 | op_desc = context; |
| 294 | if (op_desc->handler(op_desc->context) == FLASH_OP_DONE) { |
| 295 | ll_timeslice_ticker_id_get(&instance_index, &ticker_id); |
| 296 | |
| 297 | /* Stop the time slot ticker */ |
| 298 | result = ticker_stop(instance_index, |
| 299 | 0, |
| 300 | ticker_id, |
| 301 | NULL, |
| 302 | NULL); |
| 303 | |
| 304 | if (result != TICKER_STATUS_SUCCESS && |
| 305 | result != TICKER_STATUS_BUSY) { |
| 306 | __ASSERT(0, "Failed to stop ticker.\n"); |
| 307 | } |
| 308 | |
| 309 | ((struct flash_op_desc *)context)->result = 0; |
| 310 | |
| 311 | /* notify thread that data is available */ |
| 312 | k_sem_give(&sem_sync); |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | static void time_slot_callback_helper(u32_t ticks_at_expire, u32_t remainder, |
| 317 | u16_t lazy, void *context) |
| 318 | { |
| 319 | u8_t instance_index; |
| 320 | u8_t ticker_id; |
| 321 | int err; |
| 322 | |
| 323 | ll_radio_state_abort(); |
| 324 | |
| 325 | ll_timeslice_ticker_id_get(&instance_index, &ticker_id); |
| 326 | |
| 327 | /* start a secondary one-shot ticker after ~ 500 us, */ |
| 328 | /* this will let any radio role to gracefully release the Radio h/w */ |
| 329 | |
| 330 | err = ticker_start(instance_index, /* Radio instance ticker */ |
| 331 | 0, /* user_id */ |
| 332 | 0, /* ticker_id */ |
| 333 | ticks_at_expire, /* current tick */ |
Vinayak Kariappa Chettimada | 4c123a5 | 2018-01-09 15:03:33 +0100 | [diff] [blame] | 334 | HAL_TICKER_US_TO_TICKS(FLASH_RADIO_ABORT_DELAY_US), |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 335 | 0, /* periodic (on-shot) */ |
| 336 | 0, /* per. remaind. (on-shot) */ |
| 337 | 0, /* lazy, voluntary skips */ |
| 338 | 0, |
| 339 | time_slot_callback_work, /* handler for executing */ |
| 340 | /* the flash operation */ |
| 341 | context, /* the context for the flash operation */ |
| 342 | NULL, /* no op callback */ |
| 343 | NULL); |
| 344 | |
| 345 | if (err != TICKER_STATUS_SUCCESS && err != TICKER_STATUS_BUSY) { |
| 346 | ((struct flash_op_desc *)context)->result = -ECANCELED; |
| 347 | |
| 348 | /* abort flash timeslots */ |
| 349 | err = ticker_stop(instance_index, 0, ticker_id, NULL, NULL); |
| 350 | if (err != TICKER_STATUS_SUCCESS && |
| 351 | err != TICKER_STATUS_BUSY) { |
| 352 | __ASSERT(0, "Failed to stop ticker.\n"); |
| 353 | } |
| 354 | |
| 355 | /* notify thread that data is available */ |
| 356 | k_sem_give(&sem_sync); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | static int work_in_time_slice(struct flash_op_desc *p_flash_op_desc) |
| 361 | { |
| 362 | u8_t instance_index; |
| 363 | u8_t ticker_id; |
| 364 | int result; |
| 365 | u32_t err; |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 366 | struct flash_context *context = p_flash_op_desc->context; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 367 | |
| 368 | ll_timeslice_ticker_id_get(&instance_index, &ticker_id); |
| 369 | |
| 370 | err = ticker_start(instance_index, |
| 371 | 3, /* user id for thread mode */ |
| 372 | /* (MAYFLY_CALL_ID_PROGRAM) */ |
| 373 | ticker_id, /* flash ticker id */ |
| 374 | ticker_ticks_now_get(), /* current tick */ |
| 375 | 0, /* first int. immediately */ |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 376 | /* period */ |
| 377 | HAL_TICKER_US_TO_TICKS(context->interval), |
| 378 | /* period remainder */ |
| 379 | HAL_TICKER_REMAINDER(context->interval), |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 380 | 0, /* lazy, voluntary skips */ |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 381 | HAL_TICKER_US_TO_TICKS(context->slot), |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 382 | time_slot_callback_helper, |
| 383 | p_flash_op_desc, |
| 384 | NULL, /* no op callback */ |
| 385 | NULL); |
| 386 | |
| 387 | if (err != TICKER_STATUS_SUCCESS && err != TICKER_STATUS_BUSY) { |
| 388 | result = -ECANCELED; |
| 389 | } else if (k_sem_take(&sem_sync, K_MSEC(FLASH_TIMEOUT_MS)) != 0) { |
| 390 | /* wait for operation's complete overrun*/ |
| 391 | result = -ETIMEDOUT; |
| 392 | } else { |
| 393 | result = p_flash_op_desc->result; |
| 394 | } |
| 395 | |
| 396 | return result; |
| 397 | } |
| 398 | |
| 399 | static int erase_in_timeslice(u32_t addr, u32_t size) |
| 400 | { |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 401 | struct flash_context context = { |
| 402 | .flash_addr = addr, |
| 403 | .len = size, |
| 404 | .enable_time_limit = 1, /* enable time limit */ |
| 405 | .interval = FLASH_INTERVAL_ERASE, |
| 406 | .slot = FLASH_SLOT_ERASE |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 407 | }; |
| 408 | |
| 409 | struct flash_op_desc flash_op_desc = { |
| 410 | .handler = erase_op, |
| 411 | .context = &context |
| 412 | }; |
| 413 | |
| 414 | return work_in_time_slice(&flash_op_desc); |
| 415 | } |
| 416 | |
| 417 | static int write_in_timeslice(off_t addr, const void *data, size_t len) |
| 418 | { |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 419 | struct flash_context context = { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 420 | .data_addr = (u32_t) data, |
| 421 | .flash_addr = addr, |
| 422 | .len = len, |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 423 | .enable_time_limit = 1, /* enable time limit */ |
| 424 | .interval = FLASH_INTERVAL_WRITE, |
| 425 | .slot = FLASH_SLOT_WRITE |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 426 | }; |
| 427 | |
| 428 | struct flash_op_desc flash_op_desc = { |
| 429 | .handler = write_op, |
| 430 | .context = &context |
| 431 | }; |
| 432 | |
| 433 | return work_in_time_slice(&flash_op_desc); |
| 434 | } |
| 435 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 436 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 437 | |
| 438 | static int erase_op(void *context) |
| 439 | { |
Andrzej Puzdrowski | 279115e | 2019-04-01 18:00:42 +0200 | [diff] [blame] | 440 | u32_t pg_size = nrfx_nvmc_flash_page_size_get(); |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 441 | struct flash_context *e_ctx = context; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 442 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 443 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Patrik Flykt | 8ff96b5 | 2018-11-29 11:12:22 -0800 | [diff] [blame] | 444 | u32_t ticks_begin = 0U; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 445 | u32_t ticks_diff; |
Patrik Flykt | 8ff96b5 | 2018-11-29 11:12:22 -0800 | [diff] [blame] | 446 | u32_t i = 0U; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 447 | |
| 448 | if (e_ctx->enable_time_limit) { |
| 449 | ticks_begin = ticker_ticks_now_get(); |
| 450 | } |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 451 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 452 | |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 453 | #ifdef CONFIG_SOC_FLASH_NRF_UICR |
| 454 | if (e_ctx->flash_addr == (off_t)NRF_UICR) { |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 455 | (void)nrfx_nvmc_uicr_erase(); |
Andrzej Puzdrowski | cd4fbde | 2018-11-15 15:50:03 +0100 | [diff] [blame] | 456 | return FLASH_OP_DONE; |
| 457 | } |
| 458 | #endif |
| 459 | |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 460 | do { |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 461 | (void)nrfx_nvmc_page_erase(e_ctx->flash_addr); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 462 | |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 463 | e_ctx->len -= pg_size; |
| 464 | e_ctx->flash_addr += pg_size; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 465 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 466 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 467 | i++; |
| 468 | |
| 469 | if (e_ctx->enable_time_limit) { |
Vinayak Kariappa Chettimada | 3637d50 | 2018-02-16 11:22:21 +0100 | [diff] [blame] | 470 | ticks_diff = |
| 471 | ticker_ticks_diff_get(ticker_ticks_now_get(), |
| 472 | ticks_begin); |
| 473 | if (ticks_diff + ticks_diff/i > |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 474 | HAL_TICKER_US_TO_TICKS(e_ctx->slot)) { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 475 | break; |
| 476 | } |
| 477 | } |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 478 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 479 | |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 480 | } while (e_ctx->len > 0); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 481 | |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 482 | return (e_ctx->len > 0) ? FLASH_OP_ONGOING : FLASH_OP_DONE; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 483 | } |
| 484 | |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 485 | static void shift_write_context(u32_t shift, struct flash_context *w_ctx) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 486 | { |
| 487 | w_ctx->flash_addr += shift; |
| 488 | w_ctx->data_addr += shift; |
| 489 | w_ctx->len -= shift; |
| 490 | } |
| 491 | |
| 492 | static int write_op(void *context) |
| 493 | { |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 494 | struct flash_context *w_ctx = context; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 495 | u32_t count; |
| 496 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 497 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Patrik Flykt | 8ff96b5 | 2018-11-29 11:12:22 -0800 | [diff] [blame] | 498 | u32_t ticks_begin = 0U; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 499 | u32_t ticks_diff; |
Patrik Flykt | 8ff96b5 | 2018-11-29 11:12:22 -0800 | [diff] [blame] | 500 | u32_t i = 1U; |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 501 | |
| 502 | if (w_ctx->enable_time_limit) { |
| 503 | ticks_begin = ticker_ticks_now_get(); |
| 504 | } |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 505 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 506 | |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 507 | /* If not aligned, write unaligned beginning */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 508 | if (!is_aligned_32(w_ctx->flash_addr)) { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 509 | count = sizeof(u32_t) - (w_ctx->flash_addr & 0x3); |
| 510 | if (count > w_ctx->len) { |
| 511 | count = w_ctx->len; |
| 512 | } |
| 513 | |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 514 | nrfx_nvmc_bytes_write(w_ctx->flash_addr, |
| 515 | (const void *)w_ctx->data_addr, |
| 516 | count); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 517 | |
| 518 | shift_write_context(count, w_ctx); |
| 519 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 520 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 521 | if (w_ctx->enable_time_limit) { |
Vinayak Kariappa Chettimada | 3637d50 | 2018-02-16 11:22:21 +0100 | [diff] [blame] | 522 | ticks_diff = |
| 523 | ticker_ticks_diff_get(ticker_ticks_now_get(), |
| 524 | ticks_begin); |
Patrik Flykt | 21358ba | 2019-03-28 14:57:54 -0600 | [diff] [blame] | 525 | if (ticks_diff * 2U > |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 526 | HAL_TICKER_US_TO_TICKS(w_ctx->slot)) { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 527 | nvmc_wait_ready(); |
| 528 | return FLASH_OP_ONGOING; |
| 529 | } |
| 530 | } |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 531 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 532 | } |
| 533 | |
| 534 | /* Write all the 4-byte aligned data */ |
| 535 | while (w_ctx->len >= sizeof(u32_t)) { |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 536 | nrfx_nvmc_word_write(w_ctx->flash_addr, |
| 537 | UNALIGNED_GET((u32_t *)w_ctx->data_addr)); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 538 | |
| 539 | shift_write_context(sizeof(u32_t), w_ctx); |
| 540 | |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 541 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 542 | i++; |
| 543 | |
| 544 | if (w_ctx->enable_time_limit) { |
Vinayak Kariappa Chettimada | 3637d50 | 2018-02-16 11:22:21 +0100 | [diff] [blame] | 545 | ticks_diff = |
| 546 | ticker_ticks_diff_get(ticker_ticks_now_get(), |
| 547 | ticks_begin); |
| 548 | if (ticks_diff + ticks_diff/i > |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 549 | HAL_TICKER_US_TO_TICKS(w_ctx->slot)) { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 550 | nvmc_wait_ready(); |
| 551 | return FLASH_OP_ONGOING; |
| 552 | } |
| 553 | } |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 554 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 555 | } |
| 556 | |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 557 | /* Write remaining unaligned data */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 558 | if (w_ctx->len) { |
Andrzej Puzdrowski | 560b458 | 2019-04-01 17:26:05 +0200 | [diff] [blame] | 559 | nrfx_nvmc_bytes_write(w_ctx->flash_addr, |
| 560 | (const void *)w_ctx->data_addr, |
| 561 | w_ctx->len); |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 562 | |
| 563 | shift_write_context(w_ctx->len, w_ctx); |
| 564 | } |
| 565 | |
| 566 | nvmc_wait_ready(); |
| 567 | |
| 568 | return FLASH_OP_DONE; |
| 569 | } |
| 570 | |
| 571 | static int erase(u32_t addr, u32_t size) |
| 572 | { |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 573 | struct flash_context context = { |
| 574 | .flash_addr = addr, |
| 575 | .len = size, |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 576 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 577 | .enable_time_limit = 0 /* disable time limit */ |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 578 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 579 | }; |
| 580 | |
| 581 | return erase_op(&context); |
| 582 | } |
| 583 | |
| 584 | static int write(off_t addr, const void *data, size_t len) |
| 585 | { |
Vinayak Kariappa Chettimada | 9da6a85 | 2018-09-19 15:40:35 +0200 | [diff] [blame] | 586 | struct flash_context context = { |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 587 | .data_addr = (u32_t) data, |
| 588 | .flash_addr = addr, |
| 589 | .len = len, |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 590 | #if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC) |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 591 | .enable_time_limit = 0 /* disable time limit */ |
Carles Cufi | 8aa9a37 | 2018-03-20 18:41:39 +0100 | [diff] [blame] | 592 | #endif /* CONFIG_SOC_FLASH_NRF_RADIO_SYNC */ |
Andrzej Puzdrowski | 8b7a844 | 2017-06-22 09:49:12 +0200 | [diff] [blame] | 593 | }; |
| 594 | |
| 595 | return write_op(&context); |
| 596 | } |