1 /*
2 * Copyright 2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <stdint.h>
9 #include <RW612.h>
10 #include "cis_table.h"
11
12 #define CISTPL_VERS_1 0x15U
13 #define CISTPL_MANFID 0x20U
14 #define CISTPL_FUNCID 0x21U
15 #define CISTPL_FUNCE 0x22U
16 #define CISTPL_END 0xffU
17
18 #define TPLLV1_MAJOR 1U
19 #define TPLLV1_MINOR 0U
20
21 #define ROM_SDIO_F0_BLKSIZE 0x1UL
22 #define ROM_SDIO_FN_BLKSIZE 0x200UL
23 #define ROM_SDIO_SPEED 0xbUL
24 #define ROM_SDIO_TIMEOUT_VAL 0x14UL
25 #define ROM_SDIO_REV 0x30UL
26
27 // 4bit input only
tohex(uint8_t c)28 static uint8_t tohex(uint8_t c)
29 {
30 if (c < 10U)
31 {
32 return (uint8_t)(c + '0');
33 }
34 else
35 {
36 return (uint8_t)((c - 10U) + 'A');
37 }
38 }
39
emit1(uint32_t * p_cis_addr,uint8_t x)40 void emit1(uint32_t *p_cis_addr, uint8_t x)
41 {
42 REG8(*p_cis_addr) = x;
43 *p_cis_addr += 1U;
44 }
45
emit2(uint32_t * p_cis_addr,uint16_t x)46 void emit2(uint32_t *p_cis_addr, uint16_t x)
47 {
48 REG8(*p_cis_addr) = (uint8_t)(x & 0xffU);
49 REG8(*p_cis_addr + 1U) = (uint8_t)((x >> 8U) & 0xffU);
50 *p_cis_addr += 2U;
51 }
52
emit4(uint32_t * p_cis_addr,uint32_t x)53 void emit4(uint32_t *p_cis_addr, uint32_t x)
54 {
55 REG8(*p_cis_addr) = (uint8_t)(x & 0xffU);
56 REG8(*p_cis_addr + 1U) = (uint8_t)((x >> 8U) & 0xffU);
57 REG8(*p_cis_addr + 2U) = (uint8_t)((x >> 16U) & 0xffU);
58 REG8(*p_cis_addr + 3U) = (uint8_t)((x >> 24U) & 0xffU);
59 *p_cis_addr += 4U;
60 }
61
findlen(uint8_t * a)62 static int32_t findlen(uint8_t *a)
63 {
64 uint32_t done = 0U;
65 uint32_t i = 0U;
66 int32_t len = 0;
67
68 while (done == 0U)
69 {
70 if (a[i] == (uint8_t)'\377')
71 {
72 done = 1U;
73 }
74 i += 1U;
75 len += 1;
76 }
77
78 return len;
79 }
80
emitvers(uint32_t * p_cis_addr,uint8_t * s,uint32_t subs)81 void emitvers(uint32_t *p_cis_addr, uint8_t *s, uint32_t subs)
82 {
83 int32_t slen;
84 uint32_t i;
85 uint32_t addr;
86
87 emit1(p_cis_addr, CISTPL_VERS_1);
88 slen = findlen(s);
89
90 if(slen < 0)
91 {
92 // This is a bad failure. On the default, it cannot happen since
93 // all our strings end in 0xFF but a user provided str may have this
94 // issue.
95 return;
96 }
97
98 emit1(p_cis_addr, (uint8_t)(slen + 2));
99 emit1(p_cis_addr, TPLLV1_MAJOR);
100 emit1(p_cis_addr, TPLLV1_MINOR);
101
102 addr = *p_cis_addr; // Where we are now
103
104 for(i = 0; i < (uint32_t)slen; i++)
105 {
106 emit1(p_cis_addr, s[i]);
107 }
108
109 if (subs != 0U)
110 {
111 uint32_t id = (uint32_t)((SOCCTRL->CHIP_INFO & SOCCIU_CHIP_INFO_ID_MASK) >> SOCCIU_CHIP_INFO_ID_SHIFT);
112
113 for (i = 0; i < slen; i++)
114 {
115 if ((i < ((uint32_t)slen - 2U)) && (s[i] == (uint8_t)'X' && s[i + 1U] == (uint8_t)'X'))
116 {
117 REG8(addr + i) = (uint8_t)tohex((id >> 4U) & 0xfU);
118 REG8(addr + i + 1U) = (uint8_t)tohex(id & 0xfU);
119 }
120 }
121 }
122 }
123
emitvidpid(uint32_t * p_cis_addr,uint32_t vid,uint32_t pid)124 void emitvidpid(uint32_t *p_cis_addr, uint32_t vid, uint32_t pid)
125 {
126 emit1(p_cis_addr, CISTPL_MANFID);
127 emit1(p_cis_addr, 4U); // fixed len
128 emit2(p_cis_addr, (uint16_t)vid);
129 emit2(p_cis_addr, (uint16_t)pid);
130 }
131
emitfuncid(uint32_t * p_cis_addr)132 void emitfuncid(uint32_t *p_cis_addr)
133 {
134 emit1(p_cis_addr, CISTPL_FUNCID);
135 emit1(p_cis_addr, 2U);
136 emit1(p_cis_addr, 0xcU);
137 emit1(p_cis_addr, 0x0U);
138 }
139
emitfunce(uint32_t * p_cis_addr)140 void emitfunce(uint32_t *p_cis_addr)
141 {
142 uint32_t blksize;
143 uint32_t speed;
144 blksize = ROM_SDIO_F0_BLKSIZE;
145 speed = ROM_SDIO_SPEED;
146 emit1(p_cis_addr, CISTPL_FUNCE);
147 emit1(p_cis_addr, 4U);
148 emit1(p_cis_addr, 0x0U);
149 emit2(p_cis_addr, (uint16_t)blksize);
150 emit1(p_cis_addr, (uint8_t)speed);
151 }
152
emitfunce_extended(uint32_t * p_cis_addr,uint32_t fn)153 void emitfunce_extended(uint32_t *p_cis_addr, uint32_t fn)
154 {
155 uint32_t blksize;
156 uint32_t timeout;
157 uint32_t rev;
158 blksize = ROM_SDIO_FN_BLKSIZE;
159 timeout = ROM_SDIO_TIMEOUT_VAL;
160 rev = ROM_SDIO_REV;
161
162 emit1(p_cis_addr, CISTPL_FUNCE);
163 emit1(p_cis_addr, 0x2aU);
164 emit1(p_cis_addr, 0x01U);
165 emit1(p_cis_addr, 0x01U);
166 emit1(p_cis_addr, (uint8_t)rev);
167 emit4(p_cis_addr, 0x00000000);
168 emit4(p_cis_addr, 0x00000000);
169 emit1(p_cis_addr, 0x00);
170 emit2(p_cis_addr, (uint16_t)blksize);
171 emit4(p_cis_addr, 0x01ff8000);
172 // emit4(REG32(sdu_fnN_ocr_0(fn)));
173 emit1(p_cis_addr, 0x00U);
174 emit1(p_cis_addr, 0x00U);
175 emit1(p_cis_addr, 0x00U);
176 emit1(p_cis_addr, 0x00U);
177 emit1(p_cis_addr, 0x00U);
178 emit1(p_cis_addr, 0x00U);
179 emit2(p_cis_addr, 0x0000U);
180 emit2(p_cis_addr, 0x0000U);
181 emit2(p_cis_addr, (uint16_t)timeout);
182 emit2(p_cis_addr, 0x0000U);
183 emit2(p_cis_addr, 0x0000U);
184 emit2(p_cis_addr, 0x0000U);
185 emit2(p_cis_addr, 0x0000U);
186 emit2(p_cis_addr, 0x0000U);
187 emit2(p_cis_addr, 0x0000U);
188 }
189
modify(uint32_t tmp,uint32_t hi,uint32_t lo,uint32_t val)190 static uint32_t modify(uint32_t tmp, uint32_t hi, uint32_t lo, uint32_t val)
191 {
192 uint32_t mask;
193 uint32_t masklen;
194 masklen = (hi - lo) + 1U; // Width of the field
195 mask = (uint32_t)((1U << masklen) - 1U); // Now as a mask
196 val &= mask; // mask unshifted val
197 val <<= lo; // Now move val to field off
198 mask <<= lo; // mask moves too to field off
199 tmp &= ~mask; // Clear R[hi:lo]
200 tmp |= val; // Now M[hi:lo]
201 return tmp;
202 }
203
modify2(uint32_t tmp,uint32_t mask,uint32_t shift,uint32_t val)204 static uint32_t modify2(uint32_t tmp, uint32_t mask, uint32_t shift, uint32_t val)
205 {
206 mask >>= shift;
207 val &= mask; // mask unshifted val
208 val <<= shift; // Now move val to field off
209 mask <<= shift; // mask moves too to field off
210 tmp &= ~mask; // Clear R[hi:lo]
211 tmp |= val; // Now M[hi:lo]
212 return tmp;
213 }
214
rmw2(volatile uint32_t * addr,uint32_t mask,uint32_t shift,uint32_t val)215 void rmw2(volatile uint32_t *addr, uint32_t mask, uint32_t shift, uint32_t val)
216 {
217 *addr = modify2(*addr, mask, shift, val);
218 }
219
rmwb(uint32_t addr,uint32_t hi,uint32_t lo,uint32_t val)220 void rmwb(uint32_t addr, uint32_t hi, uint32_t lo, uint32_t val)
221 {
222 REG8(addr) = (uint8_t)modify((uint32_t)REG8(addr), hi, lo, val);
223 }
224
extract2(uint32_t data,uint32_t mask,uint32_t shift)225 static uint32_t extract2(uint32_t data, uint32_t mask, uint32_t shift)
226 {
227 uint32_t tmp;
228 tmp = data;
229 tmp >>= shift; // shift to 0
230 mask >>= shift;
231 tmp &= mask; // Knock off other bits
232 return tmp;
233 }
234
rd2(volatile uint32_t * addr,uint32_t mask,uint32_t shift)235 static uint32_t rd2(volatile uint32_t *addr, uint32_t mask, uint32_t shift)
236 {
237 uint32_t data;
238 data = *addr;
239 return extract2(data, mask, shift);
240 }
241
set_iomux_helper(uint32_t hi,uint32_t lo)242 static void set_iomux_helper(uint32_t hi, uint32_t lo)
243 {
244 uint32_t mask;
245 uint32_t masklen;
246 uint32_t val;
247 volatile uint32_t *addr;
248 if (hi < 32U)
249 {
250 addr = &SOCCTRL->MCI_IOMUX_EN0;
251 }
252 else
253 {
254 hi -= 32U;
255 lo -= 32U;
256 addr = &SOCCTRL->MCI_IOMUX_EN1;
257 }
258 masklen = (hi - lo) + 1U; // Field len
259 mask = (uint32_t)((1U << masklen) - 1U);
260 val = mask;
261 mask <<= lo;
262 do
263 {
264 rmw2(addr, mask, lo, val);
265 } while (rd2(addr, mask, lo) != val);
266 }
set_iomux(uint32_t hi,uint32_t lo)267 void set_iomux(uint32_t hi, uint32_t lo)
268 {
269 if (hi < lo)
270 {
271 return;
272 }
273 if ((hi < 32U) || (lo > 32U))
274 {
275 set_iomux_helper(hi, lo);
276 }
277 else
278 { // split
279 set_iomux_helper(31U, lo);
280 set_iomux_helper(hi, 32U);
281 }
282 }
283
284 #if 0
285 // legacy func
286 static void post_gpio(uint32_t val)
287 {
288 uint32_t port_id = 0U;
289 // vvvv this write... doesn't take. The loop... does.
290 // SOCCTRL->MCI_IOMUX_EN0 |= bit(3) | bit(2) | bit(1) | bit(0);
291 set_iomux(3U, 0U);
292 #if 0
293 do {
294 rmw2(&SOCCTRL->MCI_IOMUX_EN0, 0xf, 0, 0xf);
295 } while(rd2(&SOCCTRL->MCI_IOMUX_EN0, 0xf, 0) != 0xf);
296 #endif
297 GPIO->DIRSET[port_id] = 0xfU;
298 MCI_IO_MUX->GPIO_GRP0 &= ~0xfU;
299 MCI_IO_MUX->GPIO_GRP0 |= 0xfU;
300 GPIO->PIN[port_id] &= ~0xfU;
301 GPIO->PIN[port_id] |= val & 0xfU;
302 }
303 #endif