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 *)&reg_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