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