1 /*
2 * Copyright (c) 2018-2020 Arm Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * \file gfc100_eflash_drv.c
19 *
20 * \brief Generic driver for GFC100 flash controller
21 */
22
23 #include "gfc100_eflash_drv.h"
24 #include "gfc100_process_spec_api.h"
25
26 #define BITMASK(width) ((1U<<(width))-1)
27
28 /** The MSB Addr[21] selects between memory ranges*/
29 #define GFC100_EXTENDED_AREA_OFFSET (1U << 21)
30
31 /* Process specific register map offset */
32 #define GFC100_PROCESS_SPEC_REG_MAP_OFF 0x1000U
33
34 #define WORD_ALIGN_16B_MASK 0xFU /* Masks the first 4 bits */
35 #define WORD_ALIGN_4B_MASK 0x3U /* Masks the first 2 bits */
36 #define IS_ADDR_4B_ALIGNED(addr) (((uint32_t)addr & WORD_ALIGN_4B_MASK) == 0U)
37
38 /** Currently only 128 bit word width is supported by the driver */
39 #define GFC100_SUPPORTED_WORD_BIT_WIDTH 128U
40
41 /** Read is done with maximum word width */
42 #define BITS_IN_BYTE 8U
43 #define GFC100_READ_BYTE_SIZE \
44 (GFC100_SUPPORTED_WORD_BIT_WIDTH / BITS_IN_BYTE)
45
46 /** Write is done in 4 byte chunks */
47 #define GFC100_WRITE_BYTE_SIZE 4U
48
49 /** GFC100 generic controller register map */
50 struct gfc100_reg_map_t {
51 volatile uint32_t irq_enable_set; /* 0x000 RW Interrupt enable */
52 volatile uint32_t irq_enable_clr; /* 0x004 RW Interrupt disable */
53 volatile uint32_t irq_status_set; /* 0x008 RW Interrupt status set */
54 volatile uint32_t irq_status_clr; /* 0x00C RW Interrupt status clear */
55 volatile uint32_t irq_masked_status; /* 0x010 RO Interrupt masked status */
56 volatile uint32_t ctrl; /* 0x014 RW Control */
57 volatile uint32_t status; /* 0x018 RO Status */
58 volatile uint32_t addr; /* 0x01C RW Address */
59 volatile uint32_t data0; /* 0x020 RW Data 0 */
60 volatile uint32_t data1; /* 0x024 RO Data 1 */
61 volatile uint32_t data2; /* 0x028 RO Data 2 */
62 volatile uint32_t data3; /* 0x02C RO Data 3 */
63 volatile uint32_t reserved[1000]; /* 0x030 Reserved */
64 volatile uint32_t pidr4; /* 0xFD0 RO Peripheral id register 4 */
65 volatile uint32_t reserved2[3]; /* 0xFD4 Reserved */
66 volatile uint32_t pidr0; /* 0xFE0 RO Peripheral id register 0 */
67 volatile uint32_t pidr1; /* 0xFE4 RO Peripheral id register 1 */
68 volatile uint32_t pidr2; /* 0xFE8 RO Peripheral id register 2 */
69 volatile uint32_t pidr3; /* 0xFEC RO Peripheral id register 3 */
70 volatile uint32_t cidr0; /* 0xFF0 RO Component id register 0 */
71 volatile uint32_t cidr1; /* 0xFF4 RO Component id register 1 */
72 volatile uint32_t cidr2; /* 0xFF8 RO Component id register 2 */
73 volatile uint32_t cidr3; /* 0xFFC RO Component id register 3 */
74 };
75
76 /* Bit definition for the interrupt registers */
77 #define GFC100_CMD_ACCEPT_IRQ_POS 0U
78 #define GFC100_CMD_ACCEPT_IRQ_MASK (1U<<GFC100_CMD_ACCEPT_IRQ_POS)
79 #define GFC100_CMD_SUCCESS_IRQ_POS 1U
80 #define GFC100_CMD_SUCCESS_IRQ_MASK (1U<<GFC100_CMD_SUCCESS_IRQ_POS)
81 #define GFC100_CMD_FAIL_IRQ_POS 2U
82 #define GFC100_CMD_FAIL_IRQ_MASK (1U<<GFC100_CMD_FAIL_IRQ_POS)
83 #define GFC100_CMD_REJECT_IRQ_POS 3U
84 #define GFC100_CMD_REJECT_IRQ_MASK (1U<<GFC100_CMD_REJECT_IRQ_POS)
85 #define GFC100_CMD_OVERFLOW_IRQ_POS 4U
86 #define GFC100_CMD_OVERFLOW_IRQ_MASK (1U<<GFC100_CMD_OVERFLOW_IRQ_POS)
87
88 #define GFC100_IRQ_MAX_NUMBER 5U
89 #define GFC100_ALL_IRQ_MASK BITMASK(GFC100_IRQ_MAX_NUMBER)
90
91 /* Bit definitons for the control register */
92 #define GFC100_CTRL_CMD_POS 0U
93 #define GFC100_CTRL_CMD_WIDTH 3U
94 #define GFC100_CTRL_CMD_MASK \
95 (BITMASK(GFC100_CTRL_CMD_WIDTH)<<GFC100_CTRL_CMD_POS)
96 #define CMD_READ 0x1U
97 #define CMD_WRITE 0x2U
98 #define CMD_ROW_WRITE 0x3U
99 #define CMD_ERASE 0x4U
100 #define CMD_MASS_ERASE 0x7U
101 #define GFC100_CTRL_CMD_ABORT_POS 4U
102 #define GFC100_CTRL_CMD_ABORT_WIDTH 1U
103 #define GFC100_CTRL_CMD_ABORT_MASK \
104 (BITMASK(GFC100_CTRL_CMD_ABORT_WIDTH)<<GFC100_CTRL_CMD_ABORT_POS)
105
106 /* Bit definition for the status registers */
107 #define GFC100_CMD_STAT_PENDING_POS 0U
108 #define GFC100_CMD_STAT_PENDING_MASK (1U<<GFC100_CMD_STAT_PENDING_POS)
109 #define GFC100_CMD_STAT_ACCEPT_POS 1U
110 #define GFC100_CMD_STAT_ACCEPT_MASK (1U<<GFC100_CMD_STAT_ACCEPT_POS)
111 #define GFC100_CMD_STAT_SUCCESS_POS 2U
112 #define GFC100_CMD_STAT_SUCCESS_MASK (1U<<GFC100_CMD_STAT_SUCCESS_POS)
113 #define GFC100_CMD_STAT_FAIL_POS 3U
114 #define GFC100_CMD_STAT_FAIL_MASK (1U<<GFC100_CMD_STAT_FAIL_POS)
115 #define GFC100_CMD_STAT_FINISH_POS 4U
116 #define GFC100_CMD_STAT_FINISH_MASK (1U<<GFC100_CMD_STAT_FINISH_POS)
117 #define GFC100_CMD_STAT_ARB_LOCKED_POS 5U
118 #define GFC100_CMD_STAT_ARB_LOCKED_MASK (1U<<GFC100_CMD_STAT_ARB_LOCKED_POS)
119
120 #define GFC100_CMD_SUCCEEDED_OR_FAILED \
121 (GFC100_CMD_STAT_SUCCESS_MASK | GFC100_CMD_STAT_FAIL_MASK)
122 #define GFC100_CMD_HAS_FINISHED \
123 (GFC100_CMD_SUCCEEDED_OR_FAILED | GFC100_CMD_STAT_FINISH_MASK)
124
125 /**
126 * \brief Enables or disables IRQs
127 *
128 * \param[in] dev GFC100 device struct \ref gfc100_eflash_dev_t
129 * \param[in] irq_mask IRQs to enable/disable
130 * \param[in] enable True if the given IRQs need to be enabled, false
131 * if they need to be disabled
132 */
gfc100_eflash_irq_enable(struct gfc100_eflash_dev_t * dev,uint32_t irq_mask,bool enable)133 static void gfc100_eflash_irq_enable(struct gfc100_eflash_dev_t *dev,
134 uint32_t irq_mask, bool enable)
135 {
136 struct gfc100_reg_map_t *reg_map =
137 (struct gfc100_reg_map_t *)dev->cfg->base;
138
139 if (enable) {
140 reg_map->irq_enable_set = (irq_mask & GFC100_ALL_IRQ_MASK);
141 } else {
142 reg_map->irq_enable_clr = (irq_mask & GFC100_ALL_IRQ_MASK);
143 }
144 }
145
gfc100_eflash_init(struct gfc100_eflash_dev_t * dev,uint32_t sys_clk)146 void gfc100_eflash_init(struct gfc100_eflash_dev_t *dev, uint32_t sys_clk)
147 {
148 /* The driver polls the status register of the controller rather
149 * than using interrupts, so interrupts need to be disabled.
150 */
151 gfc100_eflash_irq_enable(dev, GFC100_ALL_IRQ_MASK, false);
152
153 /* Call process specific API to the set timing parameters */
154 gfc100_proc_spec_set_eflash_timing(
155 dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF, sys_clk);
156
157 /* Store flash size */
158 dev->data->flash_size = gfc100_get_eflash_size(dev);
159
160 dev->data->is_initialized = true;
161 }
162
163 /**
164 * \brief Clears IRQ status
165 *
166 * \param[in] reg_map GFC100 register map struct \ref gfc100_reg_map_t
167 */
clear_irq_status(struct gfc100_reg_map_t * reg_map)168 static inline void clear_irq_status(struct gfc100_reg_map_t *reg_map)
169 {
170 reg_map->irq_status_clr = GFC100_ALL_IRQ_MASK;
171 }
172
173 /**
174 * \brief Waits for command ready flags after issuing a command
175 *
176 * \param[in] reg_map GFC100 register map struct \ref gfc100_reg_map_t
177 *
178 * \return Returns status register of the device
179 */
check_cmd_result(struct gfc100_reg_map_t * reg_map)180 static uint32_t check_cmd_result(struct gfc100_reg_map_t *reg_map)
181 {
182 uint32_t status = 0;
183
184 while (!(status = (reg_map->status & GFC100_CMD_HAS_FINISHED))) {};
185
186 if (status & GFC100_CMD_STAT_FINISH_MASK) {
187 /* FINISH bit means the FAIL and SUCCESS status cannot be updated
188 * as the interrupt status register still holds the status
189 * of the previous command.
190 * Clearing the interrupts is needed to the get the result
191 * of the current command.
192 */
193 clear_irq_status(reg_map);
194
195 /* Wait for the SUCCESS or FAIL bit to get set */
196 while (!(status =
197 (reg_map->status & GFC100_CMD_SUCCEEDED_OR_FAILED))) {};
198 }
199
200 return status;
201 }
202
203 /**
204 * \brief Triggers read command and blocks until command has finished
205 *
206 * \param[in] reg_map GFC100 register map struct \ref gfc100_reg_map_t
207 *
208 * \return Returns status regster of the device
209 */
trigger_read_cmd(struct gfc100_reg_map_t * reg_map,uint32_t addr)210 static uint32_t trigger_read_cmd(struct gfc100_reg_map_t *reg_map,
211 uint32_t addr)
212 {
213 /* Wait until the previous command is pending */
214 while ((reg_map->status & GFC100_CMD_STAT_PENDING_MASK)) {};
215
216 /* Set the address to read from */
217 reg_map->addr = addr;
218
219 /* Initiate read command */
220 reg_map->ctrl = (CMD_READ << GFC100_CTRL_CMD_POS);
221
222 return (check_cmd_result(reg_map));
223 }
224
225 /**
226 * \brief Copies data from GFC100 data registers
227 *
228 * \param[in] reg_map GFC100 register map struct \ref gfc100_reg_map_t
229 * \param[out] to_ptr Pointer to copy the data to
230 * \param[in] size Number of bytes that needs to be copied
231 * \param[in] offset Offset to the first byte that needs to be copied
232 *
233 * \return Returns the number of bytes that were copied
234 *
235 * \note The function checks the offset and the maximum size the data
236 * registers can hold and adjusts the size with them, so copies only
237 * the number of available bytes
238 */
copy_from_data_regs(struct gfc100_reg_map_t * reg_map,void * to_ptr,uint32_t size,uint32_t offset)239 static uint32_t copy_from_data_regs(struct gfc100_reg_map_t *reg_map,
240 void *to_ptr, uint32_t size,
241 uint32_t offset)
242 {
243 offset &= (GFC100_READ_BYTE_SIZE - 1);
244 uint8_t *dst = (uint8_t *)to_ptr;
245 volatile uint8_t *src = ((uint8_t *)®_map->data0) + offset;
246 uint32_t i;
247
248 /* Read is always done in 16 bytes chunks from a 16 byte aligned address.
249 * If address is not aligned then HW will align it, so the SW needs to make
250 * sure the right bytes are read from the right location.
251 */
252
253 /* Maximum 16 bytes can be copied from the 16 byte aligned address.
254 * If the read size with the offset overlaps the 16 byte boundary,
255 * only the bytes up to the boundary can be copied. */
256 if (size + offset > GFC100_READ_BYTE_SIZE) {
257 size = GFC100_READ_BYTE_SIZE - offset;
258 }
259
260 /* If the address or the size is not aligned then memcpy can
261 * generate unaligned accesses which is not desired
262 * on the APB, so instead of using memcpy this for cycle is used.
263 */
264 for (i=0; i<size; i++) {
265 *dst = *src;
266 src++;
267 dst++;
268 }
269
270 return size;
271 }
272
gfc100_eflash_read(struct gfc100_eflash_dev_t * dev,uint32_t addr,void * data,uint32_t * len)273 enum gfc100_error_t gfc100_eflash_read(struct gfc100_eflash_dev_t *dev,
274 uint32_t addr, void *data, uint32_t *len)
275 {
276 struct gfc100_reg_map_t *reg_map =
277 (struct gfc100_reg_map_t *)dev->cfg->base;
278 uint32_t remaining_len = *len;
279 uint32_t status = 0U;
280 uint32_t curr_read_len = 0U;
281 uint32_t addr_align_off = 0U;
282
283 if (dev->data->is_initialized == false) {
284 return GFC100_ERROR_NOT_INITED;
285 }
286
287 if ((addr + *len) > dev->data->flash_size) {
288 return GFC100_ERROR_OUT_OF_RANGE;
289 }
290
291 if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
292 /* Previous command is still pending */
293 return GFC100_ERROR_CMD_PENDING;
294 }
295
296 if (gfc100_proc_spec_get_eflash_word_width(dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF)
297 != GFC100_SUPPORTED_WORD_BIT_WIDTH) {
298 /* Curently only 128 bit word width is supported by the driver */
299 return GFC100_ERROR_INVALID_WORD_WIDTH;
300 }
301
302 while (remaining_len && !(status & GFC100_CMD_STAT_FAIL_MASK)) {
303 status = trigger_read_cmd(reg_map, addr);
304
305 addr_align_off = addr & WORD_ALIGN_16B_MASK;
306
307 curr_read_len = copy_from_data_regs(reg_map, data, remaining_len,
308 addr_align_off);
309 remaining_len -= curr_read_len;
310 addr += curr_read_len;
311 data = (void *)((uintptr_t)data + curr_read_len);
312
313 /* Clear IRQ status before issuing the next command */
314 clear_irq_status(reg_map);
315 }
316
317 if (status & GFC100_CMD_STAT_FAIL_MASK) {
318 /* If there was error, then this last read was not successful */
319 remaining_len += curr_read_len;
320 }
321
322 /* Adjust length to sign how many bytes were actually read */
323 *len -= remaining_len;
324
325 return ((status & GFC100_CMD_STAT_FAIL_MASK) ?
326 GFC100_ERROR_CMD_FAIL : GFC100_ERROR_NONE);
327 }
328
329 /**
330 * \brief Triggers write command and blocks until command has finished
331 *
332 * \param[in] reg_map GFC100 register map struct \ref gfc100_reg_map_t
333 * \param[in] addr Flash address to write to
334 * \param[in] data Data to write to the flash
335 *
336 * \return Returns status regster of the device
337 */
trigger_write_cmd(struct gfc100_reg_map_t * reg_map,uint32_t addr,uint32_t data)338 static uint32_t trigger_write_cmd(struct gfc100_reg_map_t *reg_map,
339 uint32_t addr, uint32_t data)
340 {
341 uint32_t status;
342
343 /* Set address and data to write */
344 reg_map->addr = addr;
345 reg_map->data0 = data;
346
347 /* Initiate write command */
348 reg_map->ctrl = (CMD_WRITE << GFC100_CTRL_CMD_POS);
349
350 status = check_cmd_result(reg_map);
351
352 return status;
353 }
354
gfc100_eflash_write(struct gfc100_eflash_dev_t * dev,uint32_t addr,const void * data,uint32_t * len)355 enum gfc100_error_t gfc100_eflash_write(struct gfc100_eflash_dev_t *dev,
356 uint32_t addr, const void *data,
357 uint32_t *len)
358 {
359 struct gfc100_reg_map_t *reg_map =
360 (struct gfc100_reg_map_t *)dev->cfg->base;
361 uint32_t status = 0U;
362 uint32_t remaining_len = *len;
363
364 if (dev->data->is_initialized == false) {
365 return GFC100_ERROR_NOT_INITED;
366 }
367
368 if ((addr + *len) > dev->data->flash_size) {
369 return GFC100_ERROR_OUT_OF_RANGE;
370 }
371
372 if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
373 /* Previous command is still pending */
374 return GFC100_ERROR_CMD_PENDING;
375 }
376
377 if (!IS_ADDR_4B_ALIGNED(addr) || !IS_ADDR_4B_ALIGNED(*len)) {
378 /* Both address and length needs to be 4 byte aligned */
379 return GFC100_ERROR_UNALIGNED_PARAM;
380 }
381
382 while (remaining_len && !(status & GFC100_CMD_STAT_FAIL_MASK)) {
383 status = trigger_write_cmd(reg_map, addr, *(uint32_t *)data);
384 addr += GFC100_WRITE_BYTE_SIZE;
385 data = (void *)((uint32_t)data + GFC100_WRITE_BYTE_SIZE);
386 remaining_len -= GFC100_WRITE_BYTE_SIZE;
387 /* Clear IRQ status before issuing the next command */
388 clear_irq_status(reg_map);
389 }
390
391 if (status & GFC100_CMD_STAT_FAIL_MASK) {
392 /* If there was error, then this last write was not successful */
393 remaining_len += GFC100_WRITE_BYTE_SIZE;
394 }
395
396 /* Adjust length to sign how many bytes were actually read */
397 *len -= remaining_len;
398
399 return ((status & GFC100_CMD_STAT_FAIL_MASK) ?
400 GFC100_ERROR_CMD_FAIL : GFC100_ERROR_NONE);
401 }
402
403
gfc100_eflash_row_write(struct gfc100_eflash_dev_t * dev,uint32_t addr,const void * data,uint32_t * len)404 enum gfc100_error_t gfc100_eflash_row_write(struct gfc100_eflash_dev_t *dev,
405 uint32_t addr, const void *data,
406 uint32_t *len)
407 {
408 struct gfc100_reg_map_t *reg_map =
409 (struct gfc100_reg_map_t *)dev->cfg->base;
410 uint32_t status = 0U;
411 uint32_t remaining_len = *len;
412 uint32_t flag = GFC100_CMD_STAT_ACCEPT_MASK;
413
414 if (dev->data->is_initialized == false) {
415 return GFC100_ERROR_NOT_INITED;
416 }
417
418 if ((addr + *len) > dev->data->flash_size) {
419 return GFC100_ERROR_OUT_OF_RANGE;
420 }
421
422 if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
423 /* Previous command is still pending */
424 return GFC100_ERROR_CMD_PENDING;
425 }
426
427 if (!IS_ADDR_4B_ALIGNED(addr) || !IS_ADDR_4B_ALIGNED(*len)) {
428 /* Both address and length needs to be 4 byte aligned */
429 return GFC100_ERROR_UNALIGNED_PARAM;
430 }
431
432 while (remaining_len) {
433 /* Set address and data to write */
434 reg_map->addr = addr;
435 reg_map->data0 = *(uint32_t *)data;
436
437 /* Initiate write command */
438 reg_map->ctrl = (CMD_ROW_WRITE << GFC100_CTRL_CMD_POS);
439
440 /* When the first command is sent we only need accept flag to be set.
441 * After the first command we need two flags, accept flag from the
442 * current, and success flag from the previous command.
443 * Note: If interrupts are enabled or execution speed is limited for
444 * other reason, there is a chance that the requested row write command
445 * is not only accepted but executed already before the ACCEPT flag
446 * is checked. If this happens, the code execution will stall.
447 */
448 while (!(((status = reg_map->status) & flag) == flag)) {
449 if (status & GFC100_CMD_STAT_FAIL_MASK) {
450 /* Adjust length to sign how many bytes were actually read */
451 *len -= remaining_len;
452 clear_irq_status(reg_map);
453 return GFC100_ERROR_CMD_FAIL;
454 }
455 }
456 flag = (GFC100_CMD_STAT_ACCEPT_MASK | GFC100_CMD_STAT_SUCCESS_MASK);
457
458 /* Adjust data pointers and the length */
459 addr += GFC100_WRITE_BYTE_SIZE;
460 data = (void *)((uintptr_t)data + GFC100_WRITE_BYTE_SIZE);
461 remaining_len -= GFC100_WRITE_BYTE_SIZE;
462
463 /* Clear IRQ status before issuing the next command */
464 clear_irq_status(reg_map);
465 }
466
467 /* Wait for the success flag of the last command to arrive */
468 while (!(reg_map->status & GFC100_CMD_STAT_SUCCESS_MASK)) {};
469
470 /* Adjust length to sign how many bytes were actually read */
471 *len -= remaining_len;
472
473 clear_irq_status(reg_map);
474
475 return GFC100_ERROR_NONE;
476 }
477
gfc100_eflash_erase(struct gfc100_eflash_dev_t * dev,uint32_t addr,enum gfc100_erase_type_t erase)478 enum gfc100_error_t gfc100_eflash_erase(struct gfc100_eflash_dev_t *dev,
479 uint32_t addr,
480 enum gfc100_erase_type_t erase)
481 {
482 struct gfc100_reg_map_t *reg_map =
483 (struct gfc100_reg_map_t *)dev->cfg->base;
484 uint32_t status = 0U;
485
486 if (dev->data->is_initialized == false) {
487 return GFC100_ERROR_NOT_INITED;
488 }
489
490 if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
491 /* Previous command is still pending */
492 return GFC100_ERROR_CMD_PENDING;
493 }
494
495 switch (erase) {
496 case GFC100_ERASE_PAGE:
497 if (addr > dev->data->flash_size) {
498 return GFC100_ERROR_OUT_OF_RANGE;
499 }
500 reg_map->addr = addr;
501 reg_map->ctrl = (CMD_ERASE << GFC100_CTRL_CMD_POS);
502 status = check_cmd_result(reg_map);
503 /* Clear IRQ status before issuing the next command */
504 clear_irq_status(reg_map);
505 break;
506 case GFC100_MASS_ERASE_MAIN_AREA:
507 reg_map->addr = 0U;
508 reg_map->ctrl = (CMD_MASS_ERASE << GFC100_CTRL_CMD_POS);
509 status = check_cmd_result(reg_map);
510 /* Clear IRQ status before issuing the next command */
511 clear_irq_status(reg_map);
512 break;
513 case GFC100_MASS_ERASE_ALL:
514 reg_map->addr = GFC100_EXTENDED_AREA_OFFSET;
515 reg_map->ctrl = (CMD_MASS_ERASE << GFC100_CTRL_CMD_POS);
516 status = check_cmd_result(reg_map);
517 /* Clear IRQ status before issuing the next command */
518 clear_irq_status(reg_map);
519 break;
520 default:
521 return GFC100_ERROR_INVALID_PARAM;
522 }
523
524 return ((status == GFC100_CMD_STAT_FAIL_MASK) ?
525 GFC100_ERROR_CMD_FAIL : GFC100_ERROR_NONE);
526 }
527
gfc100_is_controller_locked(struct gfc100_eflash_dev_t * dev)528 bool gfc100_is_controller_locked(struct gfc100_eflash_dev_t *dev)
529 {
530 struct gfc100_reg_map_t *reg_map =
531 (struct gfc100_reg_map_t *)dev->cfg->base;
532
533 return (bool)(reg_map->status & GFC100_CMD_STAT_ARB_LOCKED_MASK);
534 }
535
gfc100_get_eflash_size(struct gfc100_eflash_dev_t * dev)536 uint32_t gfc100_get_eflash_size(struct gfc100_eflash_dev_t *dev)
537 {
538 return (gfc100_proc_spec_get_eflash_size(
539 dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
540 }
541
gfc100_get_eflash_page_size(struct gfc100_eflash_dev_t * dev)542 uint32_t gfc100_get_eflash_page_size(struct gfc100_eflash_dev_t *dev)
543 {
544 return (gfc100_proc_spec_get_eflash_page_size(
545 dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
546 }
547
gfc100_get_num_of_info_pages(struct gfc100_eflash_dev_t * dev)548 uint32_t gfc100_get_num_of_info_pages(struct gfc100_eflash_dev_t *dev)
549 {
550 return (gfc100_proc_spec_get_num_of_info_pages(
551 dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
552 }
553
gfc100_get_proc_spec_error(struct gfc100_eflash_dev_t * dev)554 uint32_t gfc100_get_proc_spec_error(struct gfc100_eflash_dev_t *dev)
555 {
556 return (gfc100_proc_spec_get_error_cause(
557 dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
558 }
559