1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __SOC_FLASH_NRF_H__
8 #define __SOC_FLASH_NRF_H__
9 
10 #include <zephyr/kernel.h>
11 #include <soc.h>
12 
13 #define FLASH_OP_DONE    (0) /* 0 for compliance with the driver API. */
14 #define FLASH_OP_ONGOING  1
15 
16 struct flash_context {
17 	uint32_t data_addr;  /* Address of data to write. */
18 	uint32_t flash_addr; /* Address of flash to write or erase. */
19 	uint32_t len;        /* Size of data to write or erase [B]. */
20 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
21 	uint8_t  enable_time_limit; /* set execution limited to the execution
22 				     * window.
23 				     */
24 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
25 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE)
26 	uint32_t flash_addr_next;
27 #endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */
28 }; /*< Context type for f. @ref write_op @ref erase_op */
29 
30 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
31 
32 /* The timeout is multiplied by CONFIG_SOC_FLASH_NRF_TIMEOUT_MULTIPLIER/10
33  * because switching tasks may take a significant portion of time.
34  */
35 #define FLASH_TIMEOUT_MS ((FLASH_PAGE_ERASE_MAX_TIME_US) * \
36 			  (FLASH_PAGE_MAX_CNT) / 1000 * \
37 			  CONFIG_SOC_FLASH_NRF_TIMEOUT_MULTIPLIER / 10)
38 
39 /**
40  * @defgroup nrf_flash_sync sync backend API
41  *
42  * API declared below contains prototypes of function which shall be
43  * implemented by the synchronization backend.
44  * @{
45  */
46 
47 /**
48  * Callback which executes the flash operation.
49  *
50  * @param context pointer to flash_context structure.
51  * @retval @ref FLASH_OP_DONE once operation was done, @ref FLASH_OP_ONGOING if
52  *         operation needs more time for execution and a negative error code if
53  *         operation was aborted.
54  */
55 typedef int (*flash_op_handler_t) (void *context);
56 
57 struct flash_op_desc {
58 	flash_op_handler_t handler;
59 	struct flash_context *context; /* [in,out] */
60 };
61 
62 /**
63  * Synchronization backend driver initialization procedure.
64  *
65  * This will be run within flash driver initialization
66  */
67 int nrf_flash_sync_init(void);
68 
69 /**
70  * Set synchronization context for synchronous operations.
71  *
72  * This function set backend's internal context for expected timing parameter.
73  *
74  * @param duration Duration of the execution window [us]
75  */
76 void nrf_flash_sync_set_context(uint32_t duration);
77 
78 /**
79  * Check if the operation need to be run synchronous with radio.
80  *
81  * @retval True if operation need to be run synchronously, otherwise False
82  */
83 bool nrf_flash_sync_is_required(void);
84 
85 /**
86  * Execute the flash operation synchronously along the radio operations.
87  *
88  * Function executes callbacks op_desc->handler() in execution windows according
89  * to timing settings requested by nrf_flash_sync_set_context().
90  * This routine need to be called the handler as many time as it returns
91  * FLASH_OP_ONGOING, however an operation timeout should be implemented.
92  * When the handler() returns FLASH_OP_DONE or an error code, no further
93  * execution windows are needed so function should return as the handler()
94  * finished its operation.
95  *
96  * @retval 0 if op_desc->handler() was executed and finished its operation
97  * successfully. Otherwise (handler returned error, timeout, couldn't schedule
98  * execution...) a negative error code.
99  *
100  *                              execution window
101  *            Driver task           task
102  *                  |                 |
103  *                  |                 |
104  * nrf_flash_sync_  #                 |
105  * set_context()    #                 |
106  *                  |                 |
107  *                  |                 |
108  * call nrf_flash_  #                 |
109  * sync_exe()       #                 |
110  *                  #---------------->|
111  *                  |                 |
112  *                  |                 # execution window 0
113  *                  |                 # call flash_op_handler_t handler()
114  *                  |                 #
115  *                  |                 #
116  *                  |                 # flash_op_handler_t handler() return
117  *                  |                 #         FLASH_OP_ONGOING
118  *                  |                 # {backend request/allow
119  *                  |                 |  the next execution window}
120  *                  .                 .
121  *                  .                 .
122  *                  .                 .
123  *                  |                 |
124  *                  |                 # execution window N
125  *                  |                 # call flash_op_handler_t handler()
126  *                  |                 #
127  *                  |                 #
128  *                  |                 #
129  *                  |                 # flash_op_handler_t handler() returns
130  *                  |                 #         FLASH_OP_DONE
131  *                  |<----------------# {backend transfer execution
132  *                  #                 |  to the driver back}
133  * nrf_flash_       #                 |
134  * sync_exe()       |                 |
135  * return           |                 |
136  */
137 int nrf_flash_sync_exe(struct flash_op_desc *op_desc);
138 
139 /**
140  * @}
141  */
142 
143 /**
144  * @defgroup nrf_flash_sync_timing sync timing backend API
145  * @ingroup nrf_flash_sync
146  * @{
147  *
148  * API which is used by nrf flash driver for check where execution fill in
149  * the execution window.
150  *
151  * API is used as follows:
152  * begin of execution window
153  * call flash_op_handler_t handler()
154  *   nrf_flash_sync_get_timestamp_begin()
155  *   [does some chunk of work]
156  *   nrf_flash_sync_check_time_limit() == false
157  *   [does some chunk of work]
158  *   nrf_flash_sync_check_time_limit() == false
159  *   [does some chunk of work]
160  *   ...
161  *   nrf_flash_sync_check_time_limit() == true
162  *   [preserve work context for next execution window]
163  * return form flash_op_handler_t handler()
164  * [return from execution window]
165  * end of execution window
166  */
167 
168 /**
169  * Get timestamp and store it in synchronization backend
170  * context data as operation beginning time reference.
171  * This timestamp will be used by @ref nrf_flash_sync_check_time_limit()
172  * as the execution window begin reference.
173  */
174 void nrf_flash_sync_get_timestamp_begin(void);
175 
176 /**
177  * Estimate whether next iteration will fit in time constraints.
178  * This function fetch current timestamp and compare it with the operation
179  * beginning timestamp reference stored by
180  * @ref nrf_flash_sync_get_timestamp_begin() in the synchronization backend
181  * context data.
182  *
183  * @param iteration iteration number.
184  * @retval true if estimated time excess, false otherwise.
185  */
186 bool nrf_flash_sync_check_time_limit(uint32_t iteration);
187 
188 /**
189  * @}
190  */
191 
192 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
193 #endif /* !__SOC_FLASH_NRF_H__ */
194