1 #include <alloca.h>
2 #include <stdbool.h>
3 #include <string.h>
4
5 #include <variant/variant.h>
6
7 #include <plat/pwr.h>
8 #include <plat/gpio.h>
9 #include <plat/cmsis.h>
10
11 #include <bl.h>
12 #include <gpio.h>
13
14 struct StmUdid
15 {
16 volatile uint32_t U_ID[3];
17 };
18
19 struct StmSpi {
20 volatile uint32_t CR1;
21 volatile uint32_t CR2;
22 volatile uint32_t SR;
23 volatile uint32_t DR;
24 volatile uint32_t CRCPR;
25 volatile uint32_t RXCRCR;
26 volatile uint32_t TXCRCR;
27 volatile uint32_t I2SCFGR;
28 volatile uint32_t I2SPR;
29 };
30
31 struct StmGpio {
32 volatile uint32_t MODER;
33 volatile uint32_t OTYPER;
34 volatile uint32_t OSPEEDR;
35 volatile uint32_t PUPDR;
36 volatile uint32_t IDR;
37 volatile uint32_t ODR;
38 volatile uint32_t BSRR;
39 volatile uint32_t LCKR;
40 volatile uint32_t AFR[2];
41 };
42
43 struct StmFlash
44 {
45 volatile uint32_t ACR;
46 volatile uint32_t KEYR;
47 volatile uint32_t OPTKEYR;
48 volatile uint32_t SR;
49 volatile uint32_t CR;
50 volatile uint32_t OPTCR;
51 };
52
53 struct StmCrc
54 {
55 volatile uint32_t DR;
56 volatile uint32_t IDR;
57 volatile uint32_t CR;
58 };
59
60 struct StmRcc {
61 volatile uint32_t CR;
62 volatile uint32_t PLLCFGR;
63 volatile uint32_t CFGR;
64 volatile uint32_t CIR;
65 volatile uint32_t AHB1RSTR;
66 volatile uint32_t AHB2RSTR;
67 volatile uint32_t AHB3RSTR;
68 uint8_t unused0[4];
69 volatile uint32_t APB1RSTR;
70 volatile uint32_t APB2RSTR;
71 uint8_t unused1[8];
72 volatile uint32_t AHB1ENR;
73 volatile uint32_t AHB2ENR;
74 volatile uint32_t AHB3ENR;
75 uint8_t unused2[4];
76 volatile uint32_t APB1ENR;
77 volatile uint32_t APB2ENR;
78 uint8_t unused3[8];
79 volatile uint32_t AHB1LPENR;
80 volatile uint32_t AHB2LPENR;
81 volatile uint32_t AHB3LPENR;
82 uint8_t unused4[4];
83 volatile uint32_t APB1LPENR;
84 volatile uint32_t APB2LPENR;
85 uint8_t unused5[8];
86 volatile uint32_t BDCR;
87 volatile uint32_t CSR;
88 uint8_t unused6[8];
89 volatile uint32_t SSCGR;
90 volatile uint32_t PLLI2SCFGR;
91 };
92
93 typedef void (*FlashEraseF)(volatile uint32_t *, uint32_t, volatile uint32_t *);
94 typedef void (*FlashWriteF)(volatile uint8_t *, uint8_t, volatile uint32_t *);
95
96 static struct StmSpi *SPI;
97 static struct StmRcc *RCC;
98 static struct Gpio *wakeupGpio;
99 static uint32_t mOldApb2State;
100 static uint32_t mOldAhb1State;
101
102 #define FLASH_ACR_LAT(x) ((x) & FLASH_ACR_LAT_MASK)
103 #define FLASH_ACR_LAT_MASK 0x0F
104 #define FLASH_ACR_PRFTEN 0x00000100
105 #define FLASH_ACR_ICEN 0x00000200
106 #define FLASH_ACR_DCEN 0x00000400
107 #define FLASH_ACR_ICRST 0x00000800
108 #define FLASH_ACR_DCRST 0x00001000
109
110 #define FLASH_SR_EOP 0x00000001
111 #define FLASH_SR_OPERR 0x00000002
112 #define FLASH_SR_WRPERR 0x00000010
113 #define FLASH_SR_PGAERR 0x00000020
114 #define FLASH_SR_PGPERR 0x00000040
115 #define FLASH_SR_PGSERR 0x00000080
116 #define FLASH_SR_RDERR 0x00000100
117 #define FLASH_SR_BSY 0x00010000
118
119 #define FLASH_CR_PG 0x00000001
120 #define FLASH_CR_SER 0x00000002
121 #define FLASH_CR_MER 0x00000004
122 #define FLASH_CR_SNB(x) (((x) << FLASH_CR_SNB_SHIFT) & FLASH_CR_SNB_MASK)
123 #define FLASH_CR_SNB_MASK 0x00000078
124 #define FLASH_CR_SNB_SHIFT 3
125 #define FLASH_CR_PSIZE(x) (((x) << FLASH_CR_PSIZE_SHIFT) & FLASH_CR_PSIZE_MASK)
126 #define FLASH_CR_PSIZE_MASK 0x00000300
127 #define FLASH_CR_PSIZE_SHIFT 8
128 #define FLASH_CR_PSIZE_8 0x0
129 #define FLASH_CR_PSIZE_16 0x1
130 #define FLASH_CR_PSIZE_32 0x2
131 #define FLASH_CR_PSIZE_64 0x3
132 #define FLASH_CR_STRT 0x00010000
133 #define FLASH_CR_EOPIE 0x01000000
134 #define FLASH_CR_ERRIE 0x02000000
135 #define FLASH_CR_LOCK 0x80000000
136
137 //stm defines
138 #define BL_MAX_FLASH_CODE 1024
139
140 /*
141 * Return the address of the erase code and the length of the code
142 *
143 * This code needs to run out of ram and not flash since accessing flash
144 * while erasing is undefined (best case the processor stalls, worst case
145 * it starts executing garbage)
146 *
147 * This function is used to get a pointer to the actual code that does the
148 * erase and polls for completion (so we can copy it to ram) as well as the
149 * length of the code (so we know how much space to allocate for it)
150 *
151 * void FlashEraseF(volatile uint32_t *addr, uint32_t value, volatile uint32_t *status)
152 * {
153 * *addr = value;
154 * while (*status & FLASH_SR_BSY) ;
155 * }
156 */
blGetFlashEraseCode(uint16_t ** addr,uint32_t * size)157 static void __attribute__((naked)) blGetFlashEraseCode(uint16_t **addr, uint32_t *size)
158 {
159 asm volatile (
160 " push {lr} \n"
161 " bl 9f \n"
162 " str r1, [r0, #0] \n" // *addr = value
163 "1: \n"
164 " ldr r3, [r2, #0] \n" // r3 = *status
165 " lsls r3, #15 \n" // r3 <<= 15
166 " bmi 1b \n" // if (r3 < 0) goto 1
167 " bx lr \n" // return
168 "9: \n"
169 " bic lr, #0x1 \n"
170 " adr r3, 9b \n"
171 " sub r3, lr \n"
172 " str lr, [r0] \n"
173 " str r3, [r1] \n"
174 " pop {pc} \n"
175 );
176 }
177
_blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask)178 static void _blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask)
179 {
180 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
181 uint16_t *code_src, *code;
182 uint32_t i, code_length;
183 FlashEraseF func;
184
185 blGetFlashEraseCode(&code_src, &code_length);
186
187 if (code_length < BL_MAX_FLASH_CODE) {
188 code = (uint16_t *)(((uint32_t)alloca(code_length + 1) + 1) & ~0x1);
189 func = (FlashEraseF)((uint8_t *)code+1);
190
191 for (i = 0; i < code_length / sizeof(uint16_t); i++)
192 code[i] = code_src[i];
193
194 for (i = 0; i < sector_cnt; i++) {
195 if (erase_mask[i]) {
196 flash->CR = (flash->CR & ~(FLASH_CR_SNB_MASK)) |
197 FLASH_CR_SNB(i) | FLASH_CR_SER;
198 func(&flash->CR, flash->CR | FLASH_CR_STRT, &flash->SR);
199 flash->CR &= ~(FLASH_CR_SNB_MASK | FLASH_CR_SER);
200 }
201 }
202 }
203 }
204
blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask,uint32_t key1,uint32_t key2)205 bool blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask, uint32_t key1, uint32_t key2)
206 {
207 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
208 uint32_t acr_cache, cr_cache;
209 // disable interrupts
210 // otherwise an interrupt during flash write/erase will stall the processor
211 // until the write/erase completes
212 uint32_t int_state = blDisableInts();
213
214 // wait for flash to not be busy (should never be set at this point)
215 while (flash->SR & FLASH_SR_BSY);
216
217 cr_cache = flash->CR;
218
219 if (flash->CR & FLASH_CR_LOCK) {
220 // unlock flash
221 flash->KEYR = key1;
222 flash->KEYR = key2;
223 }
224
225 if (!(flash->CR & FLASH_CR_LOCK)) {
226 flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
227 acr_cache = flash->ACR;
228
229 // disable and flush data and instruction caches
230 flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
231 flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
232
233 _blEraseSectors(sector_cnt, erase_mask);
234
235 flash->ACR = acr_cache;
236 flash->CR = cr_cache;
237
238 // restore interrupts
239 blRestoreInts(int_state);
240 return true;
241 }
242 return false;
243 }
244
245 /*
246 * Return the address of the write code and the length of the code
247 *
248 * This code needs to run out of ram and not flash since accessing flash
249 * while writing to flash is undefined (best case the processor stalls, worst
250 * case it starts executing garbage)
251 *
252 * This function is used to get a pointer to the actual code that does the
253 * write and polls for completion (so we can copy it to ram) as well as the
254 * length of the code (so we know how much space to allocate for it)
255 *
256 * void FlashWriteF(volatile uint8_t *addr, uint8_t value, volatile uint32_t *status)
257 * {
258 * *addr = value;
259 * while (*status & FLASH_SR_BSY) ;
260 * }
261 */
blGetFlashWriteCode(uint16_t ** addr,uint32_t * size)262 static void __attribute__((naked)) blGetFlashWriteCode(uint16_t **addr, uint32_t *size)
263 {
264 asm volatile (
265 " push {lr} \n"
266 " bl 9f \n"
267 " strb r1, [r0, #0] \n" // *addr = value
268 "1: \n"
269 " ldr r3, [r2, #0] \n" // r3 = *status
270 " lsls r3, #15 \n" // r3 <<= 15
271 " bmi 1b \n" // if (r3 < 0) goto 1
272 " bx lr \n" // return
273 "9: \n"
274 " bic lr, #0x1 \n"
275 " adr r3, 9b \n"
276 " sub r3, lr \n"
277 " str lr, [r0] \n"
278 " str r3, [r1] \n"
279 " pop {pc} \n"
280 );
281 }
282
blWriteBytes(uint8_t * dst,const uint8_t * src,uint32_t length)283 static void blWriteBytes(uint8_t *dst, const uint8_t *src, uint32_t length)
284 {
285 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
286 uint16_t *code_src, *code;
287 uint32_t i, code_length;
288 FlashWriteF func;
289
290 blGetFlashWriteCode(&code_src, &code_length);
291
292 if (code_length < BL_MAX_FLASH_CODE) {
293 code = (uint16_t *)(((uint32_t)alloca(code_length+1) + 1) & ~0x1);
294 func = (FlashWriteF)((uint8_t *)code+1);
295
296 for (i = 0; i < code_length / sizeof(uint16_t); i++)
297 code[i] = code_src[i];
298
299 flash->CR |= FLASH_CR_PG;
300
301 for (i = 0; i < length; i++) {
302 if (dst[i] != src[i])
303 func(&dst[i], src[i], &flash->SR);
304 }
305
306 flash->CR &= ~FLASH_CR_PG;
307 }
308 }
309
blPlatProgramFlash(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t key1,uint32_t key2)310 bool blPlatProgramFlash(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
311 {
312 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
313 uint32_t acr_cache, cr_cache;
314 // disable interrupts
315 // otherwise an interrupt during flash write will stall the processor
316 // until the write completes
317 uint32_t int_state = blDisableInts();
318
319 // wait for flash to not be busy (should never be set at this point)
320 while (flash->SR & FLASH_SR_BSY);
321
322 cr_cache = flash->CR;
323
324 if (flash->CR & FLASH_CR_LOCK) {
325 // unlock flash
326 flash->KEYR = key1;
327 flash->KEYR = key2;
328 }
329
330 if (flash->CR & FLASH_CR_LOCK) {
331 // unlock failed, restore interrupts
332 blRestoreInts(int_state);
333
334 return false;
335 }
336
337 flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
338
339 acr_cache = flash->ACR;
340
341 // disable and flush data and instruction caches
342 flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
343 flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
344
345 blWriteBytes(dst, src, length);
346
347 flash->ACR = acr_cache;
348 flash->CR = cr_cache;
349
350 blRestoreInts(int_state);
351 return true;
352 }
353
blDisableInts(void)354 uint32_t blDisableInts(void)
355 {
356 uint32_t state;
357
358 asm volatile (
359 "mrs %0, PRIMASK \n"
360 "cpsid i \n"
361 :"=r"(state)
362 );
363
364 return state;
365 }
366
blRestoreInts(uint32_t state)367 void blRestoreInts(uint32_t state)
368 {
369 asm volatile(
370 "msr PRIMASK, %0 \n"
371 ::"r"((uint32_t)state)
372 );
373 }
374
blReboot(void)375 void blReboot(void)
376 {
377 SCB->AIRCR = 0x05FA0004;
378 //we never get here
379 while(1);
380 }
381
blResetRxData()382 void blResetRxData()
383 {
384 (void)SPI->DR;
385 while (!(SPI->SR & 1));
386 (void)SPI->DR;
387 }
388
blSpiTxRxByte(uint32_t val)389 uint8_t blSpiTxRxByte(uint32_t val)
390 {
391 while (!(SPI->SR & 2));
392 SPI->DR = val;
393 while (!(SPI->SR & 1));
394 return SPI->DR;
395 }
396
blGetSnum(uint32_t * snum,uint32_t length)397 uint32_t blGetSnum(uint32_t *snum, uint32_t length)
398 {
399 struct StmUdid *reg = (struct StmUdid *)UDID_BASE;
400 uint32_t i;
401
402 if (length > 3)
403 length = 3;
404
405 for (i = 0; i < length; i++)
406 snum[i] = reg->U_ID[i];
407
408 return (length << 2);
409 }
410
blSetup()411 void blSetup()
412 {
413 SPI = (struct StmSpi*)SPI1_BASE;
414 RCC = (struct StmRcc*)RCC_BASE;
415 struct Gpio *gpio;
416 int i;
417
418 //SPI1 & GPIOA on
419 mOldApb2State = RCC->APB2ENR;
420 mOldAhb1State = RCC->AHB1ENR;
421 RCC->APB2ENR |= PERIPH_APB2_SPI1;
422 RCC->AHB1ENR |= PERIPH_AHB1_GPIOA;
423
424 //reset units
425 RCC->APB2RSTR |= PERIPH_APB2_SPI1;
426 RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA;
427 RCC->APB2RSTR &=~ PERIPH_APB2_SPI1;
428 RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
429
430 //configure GPIOA for SPI A4..A7 for AF_SPI1 use (function 5), int pin as not func, high speed, no pullups, not open drain, proper directions
431 for (i=4; i<=7; i++) {
432 gpio = gpioRequest(GPIO_PA(i));
433 gpioConfigAlt(gpio, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_OUT_PUSH_PULL, GPIO_AF_SPI1);
434 gpioRelease(gpio);
435 }
436
437 wakeupGpio = gpioRequest(SH_INT_WAKEUP);
438 gpioConfigInput(wakeupGpio, GPIO_SPEED_HIGH, GPIO_PULL_NONE);
439 }
440
blCleanup()441 void blCleanup()
442 {
443 gpioRelease(wakeupGpio);
444 //reset units & return APB2 & AHB1 to initial state
445 RCC->APB2RSTR |= PERIPH_APB2_SPI1;
446 RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA;
447 RCC->APB2RSTR &=~ PERIPH_APB2_SPI1;
448 RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
449 RCC->APB2ENR = mOldApb2State;
450 RCC->AHB1ENR = mOldAhb1State;
451 }
452
blHostActive()453 bool blHostActive()
454 {
455 return !gpioGet(wakeupGpio);
456 }
457
blConfigIo()458 void blConfigIo()
459 {
460 //config SPI
461 SPI->CR1 = 0x00000040; //spi is on, configured same as bootloader would
462 SPI->CR2 = 0x00000000; //spi is on, configured same as bootloader would
463 }
464
blSyncWait(uint32_t syncCode)465 bool blSyncWait(uint32_t syncCode)
466 {
467 uint32_t nRetries;
468 //wait for sync
469 for (nRetries = 10000; nRetries; nRetries--) {
470 if (SPI->SR & 1) {
471 if (SPI->DR == syncCode)
472 break;
473 (void)SPI->SR; //re-read to clear overlfow condition (if any)
474 }
475 }
476 return nRetries > 0;
477 }
478
479 void __attribute__((noreturn)) __blEntry(void);
__blEntry(void)480 void __attribute__((noreturn)) __blEntry(void)
481 {
482 extern char __code_start[], __bss_end[], __bss_start[], __data_end[], __data_start[], __data_data[];
483 uint32_t appBase = ((uint32_t)&__code_start) & ~1;
484
485 //make sure we're the vector table and no ints happen (BL does not use them)
486 blDisableInts();
487 SCB->VTOR = (uint32_t)&BL;
488
489 //init things a little for the higher levels
490 memset(__bss_start, 0, __bss_end - __bss_start);
491 memcpy(__data_start, __data_data, __data_end - __data_start);
492
493 blMain(appBase);
494
495 //call OS with ints off
496 blDisableInts();
497 SCB->VTOR = appBase;
498 asm volatile(
499 "LDR SP, [%0, #0] \n"
500 "LDR PC, [%0, #4] \n"
501 :
502 :"r"(appBase)
503 :"memory", "cc"
504 );
505
506 //we should never return here
507 while(1);
508 }
509
blSpuriousIntHandler(void)510 static void blSpuriousIntHandler(void)
511 {
512 //BAD!
513 blReboot();
514 }
515
516 extern uint8_t __stack_top[];
517 uint64_t __attribute__ ((section (".stack"))) _STACK[BL_STACK_SIZE / sizeof(uint64_t)];
518
519 const struct BlVecTable __attribute__((section(".blvec"))) __BL_VEC =
520 {
521 .blStackTop = (uint32_t)&__stack_top,
522 .blEntry = &__blEntry,
523 .blNmiHandler = &blSpuriousIntHandler,
524 .blHardFaultHandler = &blSpuriousIntHandler,
525 .blMmuFaultHandler = &blSpuriousIntHandler,
526 .blBusFaultHandler = &blSpuriousIntHandler,
527 .blUsageFaultHandler = &blSpuriousIntHandler,
528 };
529