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