1 /*
2  * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stddef.h>
7 #include <stdint.h>
8 
9 #include <device_mec5.h>
10 #include "mec_pcfg.h"
11 #include "mec_defs.h"
12 #include "mec_ecia_api.h"
13 #include "mec_rom_api.h"
14 #include "mec_retval.h"
15 
16 /* NDRNG */
17 #ifdef MEC5_ROM_API_NDRNG_ENABLED
18 
19 #define MEC_NDRNG_GIRQ 16
20 #define MEC_NDRNG_GIRQ_POS 2
21 #define MEC_NDRNG_GIRQ_AGGR_NVIC 8
22 #define MEC_NDRNG_DIRECT_NVIC 67
23 
24 #define MEC_NDRNG_ECIA_INFO MEC5_ECIA_INFO(MEC_NDRNG_GIRQ, MEC_NDRNG_GIRQ_POS, \
25                                            MEC_NDRNG_GIRQ_AGGR_NVIC, MEC_NDRNG_DIRECT_NVIC)
26 
27 #define MEC_NDRNG_FIFO_MAX_WORDS 32u
28 
29 #define MEC_NDRNG_DFLT_CLKDIV 0
30 #define MEC_NDRNG_DFLT_OFF_TIMER_VAL 0
31 #define MEC_NDRNG_DFLT_FIFO_WAKEUP_LVL 8u
32 #define MEC_NDRNG_DFLT_INIT_WAIT_VAL 512u
33 #define MEC_NDRNG_DFLT_NB_128BIT_BLOCKS 4u
34 // return 0 (success), -4, -2, -99
35 
36 #define MEC_ROM_API_NDRNG_SOFT_RESET_ADDR       0x1f215u
37 #define MEC_ROM_API_NDRNG_FIFO_LEVEL_ADDR       0x1f219u
38 #define MEC_ROM_API_NDRNG_INIT_ADDR             0x1f21du
39 #define MEC_ROM_API_NDRNG_READ_WORD_ADDR        0x1f221u
40 #define MEC_ROM_API_NDRNG_ENABLE_ADDR           0x1f225u
41 #define MEC_ROM_API_NDRNG_INTR_EN_ADDR          0x1f229u
42 #define MEC_ROM_API_NDRNG_FIFO_LVL_CLR_ADDR     0x1f22du
43 #define MEC_ROM_API_NDRNG_IS_HEALTHY_ADDR       0x1f231u
44 #define MEC_ROM_API_NDRNG_READ_BYTES_ADDR       0x1f235u
45 #define MEC_ROM_API_NDRNG_READ_BYTES_NH_ADDR    0x1f239u
46 #define MEC_ROM_API_NDRNG_READ_WORD_NH_ADDR     0x1f23du
47 
48 #if defined(MEC172X_FAM_ID)
49 #define MEC_ROM_API_NDRNG_GET_RAND_WORDS_ADDR   0x1f2adu
50 #define MEC_ROM_API_NDRNG_INTR_CLR_STS_ADDR     0x1f2d1u
51 #define MEC_ROM_API_NDRNG_IS_FIFO_FULL_ADDR     0x1f2d5u
52 #define MEC_ROM_API_NDRNG_EMPTY_FIFO_ADDR       0x1f2d9u
53 #elif (defined(MEC174X_FAM_ID) || defined(MEC175X_FAM_ID))
54 #define MEC_ROM_API_NDRNG_GET_RAND_WORDS_ADDR   0x1f265u
55 #define MEC_ROM_API_NDRNG_INTR_CLR_STS_ADDR     0x1f289u
56 #define MEC_ROM_API_NDRNG_IS_FIFO_FULL_ADDR     0x1f28du
57 #define MEC_ROM_API_NDRNG_EMPTY_FIFO_ADDR       0x1f291u
58 #endif
59 
60 typedef int (*rom_ndrng_init_td)(bool enable_conditioning,
61                                  uint32_t fifo_wake_threshold,
62                                  uint32_t ring_pwr_down_delay,
63                                  uint32_t nb_cond,
64                                  uint32_t rng_clk_div,
65                                  uint32_t rng_init_wait);
66 
67 /* call after init to enable TRNG */
68 typedef void (*rom_ndrng_enable_td)(bool enable);
69 
70 /* does not clear enable bit */
71 typedef void (*rom_ndrng_soft_reset_td)(void);
72 
73 /* number of 32-bit words available in FIFO */
74 typedef uint32_t (*rom_ndrng_fifo_level_td)(void);
75 
76 typedef bool (*rom_ndrng_is_fifo_full_td)(void);
77 
78 /* clears FIFO full HW status bit */
79 typedef void (*rom_ndrng_level_clear_td)(void);
80 
81 /* read and discard FIFO contents */
82 typedef void (*rom_ndrng_empty_fifo_td)(void);
83 
84 typedef bool (*rom_ndrng_is_healthy_td)(void);
85 
86 /* blocking read without health check */
87 typedef int (*rom_ndrng_read_bytes_nh_td)(uint8_t *dest, int nbytes);
88 
89 /*
90  * Reads nwords from FIFO and stores in dest. Returns actual number
91  * of words read or if < 0 and error.
92  */
93 typedef uint32_t (*rom_ndrng_get_random_words_td)(void *dest, uint32_t nwords);
94 
95 /* ---- Public API ---- */
mec_hal_rom_rng_init(void)96 int mec_hal_rom_rng_init(void)
97 {
98     rom_ndrng_init_td fp = (rom_ndrng_init_td)MEC_ROM_API_NDRNG_INIT_ADDR;
99     uint32_t fifo_wake_threshold = MEC_NDRNG_DFLT_FIFO_WAKEUP_LVL;
100     uint32_t rng_power_down_delay = MEC_NDRNG_DFLT_OFF_TIMER_VAL;
101     uint32_t nb_cond = MEC_NDRNG_DFLT_NB_128BIT_BLOCKS;
102     uint32_t rng_clk_div = MEC_NDRNG_DFLT_CLKDIV;
103     uint32_t rng_init_wait = MEC_NDRNG_DFLT_INIT_WAIT_VAL;
104     int ret = 0;
105 
106     ret = fp(true, fifo_wake_threshold, rng_power_down_delay, nb_cond,
107              rng_clk_div, rng_init_wait);
108     if (ret != 0) {
109         return MEC_RET_ERR;
110     }
111 
112     return MEC_RET_OK;
113 }
114 
mec_hal_rom_rng_enable(bool enable)115 void mec_hal_rom_rng_enable(bool enable)
116 {
117     rom_ndrng_enable_td fp = (rom_ndrng_enable_td)MEC_ROM_API_NDRNG_ENABLE_ADDR;
118 
119     fp(enable);
120 }
121 
122 
mec_hal_rom_rng_is_healthy(void)123 bool mec_hal_rom_rng_is_healthy(void)
124 {
125     rom_ndrng_is_healthy_td fp = (rom_ndrng_is_healthy_td)MEC_ROM_API_NDRNG_IS_HEALTHY_ADDR;
126 
127     return fp();
128 }
129 
mec_hal_rom_rng_fifo_level(void)130 uint32_t mec_hal_rom_rng_fifo_level(void)
131 {
132     rom_ndrng_fifo_level_td fp = (rom_ndrng_fifo_level_td)MEC_ROM_API_NDRNG_FIFO_LEVEL_ADDR;
133 
134     return fp();
135 }
136 
mec_hal_rom_rng_is_fifo_full(void)137 bool mec_hal_rom_rng_is_fifo_full(void)
138 {
139     rom_ndrng_is_fifo_full_td fp = (rom_ndrng_is_fifo_full_td)MEC_ROM_API_NDRNG_IS_FIFO_FULL_ADDR;
140 
141     return fp();
142 }
143 
mec_hal_rom_rng_fifo_full_status_clear(void)144 void mec_hal_rom_rng_fifo_full_status_clear(void)
145 {
146     rom_ndrng_level_clear_td fp = (rom_ndrng_level_clear_td)MEC_ROM_API_NDRNG_FIFO_LVL_CLR_ADDR;
147 
148     fp();
149 }
150 
mec_hal_rom_rng_fifo_discard(void)151 void mec_hal_rom_rng_fifo_discard(void)
152 {
153     rom_ndrng_empty_fifo_td fp = (rom_ndrng_empty_fifo_td)MEC_ROM_API_NDRNG_EMPTY_FIFO_ADDR;
154 
155     fp();
156 }
157 
mec_hal_rom_rng_read_bytes_nh(uint8_t * dest,uint16_t nbytes_req,uint16_t * nbytes_supplied)158 int mec_hal_rom_rng_read_bytes_nh(uint8_t *dest, uint16_t nbytes_req, uint16_t *nbytes_supplied)
159 {
160     rom_ndrng_read_bytes_nh_td fp =
161         (rom_ndrng_read_bytes_nh_td)MEC_ROM_API_NDRNG_READ_BYTES_NH_ADDR;
162     int rc = 0;
163 
164     if (!dest) {
165         return MEC_RET_ERR_INVAL;
166     }
167 
168     if (nbytes_req) {
169         rc = fp(dest, nbytes_req);
170         if (rc < 0) {
171             return MEC_RET_ERR;
172         }
173     }
174 
175     if (nbytes_supplied) {
176         *nbytes_supplied = (uint16_t)(rc & 0xffffu);
177     }
178 
179     return MEC_RET_OK;
180 }
181 
182 /* fill a word (32-bit) buffer with requested number of words.
183  * This routine may block.
184  * return >= 0 is the number of words actually written to the buffer.
185  * return < 0 is an error.
186  */
mec_hal_rom_rng_get_rand_words(void * dest,uint16_t req_nw,uint16_t * actual_nw)187 int mec_hal_rom_rng_get_rand_words(void *dest, uint16_t req_nw, uint16_t *actual_nw)
188 {
189     rom_ndrng_get_random_words_td fp =
190         (rom_ndrng_get_random_words_td)MEC_ROM_API_NDRNG_GET_RAND_WORDS_ADDR;
191 
192     if (!dest || ((uint32_t)dest & 0x3u)) {
193         return MEC_RET_ERR_INVAL;
194     }
195 
196     int rc = fp(dest, req_nw);
197 
198     if (rc >= 0) {
199         if (actual_nw) {
200             *actual_nw = (uint16_t)(rc & 0xffffu);
201         }
202         return MEC_RET_OK;
203     }
204 
205     return MEC_RET_ERR;
206 }
207 
208 #endif /* MEC5_ROM_API_NDRNG_ENABLED */
209 
210 /* end mec_rom.c */
211