Repository navigation
Expand file tree
/
Copy pathmpfs250.h
More file actions
782 lines (668 loc) · 32.8 KB
/
Copy pathmpfs250.h
File metadata and controls
782 lines (668 loc) · 32.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
/* mpfs250.h
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef MPFS250_DEF_INCLUDED
#define MPFS250_DEF_INCLUDED
/* Generic RISC-V definitions are included at the end of this file
* (after PLIC_BASE is defined) to enable PLIC function declarations */
/* PolarFire SoC MPFS250T board specific configuration */
/* APB/AHB Peripheral Bus Clock Frequency (used for UART baud rate divisor)
* M-mode (out of reset, no PLL): 40 MHz
* S-mode (after HSS configures PLL): 150 MHz
*/
#ifndef MSS_APB_AHB_CLK
#ifdef WOLFBOOT_RISCV_MMODE
#define MSS_APB_AHB_CLK 40000000
#else
#define MSS_APB_AHB_CLK 150000000
#endif
#endif
/* CPU Core Clock Frequency (used for mcycle-based benchmarking)
* The E51 core runs at 2x the APB bus clock on reset.
* After HSS configures the PLL, CPU runs at 600 MHz. */
#ifndef MSS_CPU_CLK
#ifdef WOLFBOOT_RISCV_MMODE
#define MSS_CPU_CLK (MSS_APB_AHB_CLK * 2)
#else
#define MSS_CPU_CLK 600000000
#endif
#endif
/* E51 reset clock in MHz, used to seed mpfs_cpu_freq_mhz for udelay().
* Bumped to the Libero PLL rate after mss_pll_init() (see hal/mpfs250_ddr.c). */
#ifndef MPFS_CPU_FREQ_RESET_MHZ
#define MPFS_CPU_FREQ_RESET_MHZ 80U
#endif
/* Full-DDRC-reinit attempts in hal_init() (per-attempt failure rate ~30%). */
#ifndef MPFS_DDR_MAX_OUTER_RETRY
#define MPFS_DDR_MAX_OUTER_RETRY 6U
#endif
/* Hardware Base Address */
#define SYSREG_BASE 0x20002000
/* Write "0xDEAD" to cause a full MSS reset*/
#define SYSREG_MSS_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x18)))
/* Peripheral Subblock Clock Control Register (offset 0x84) */
#define SYSREG_SUBBLK_CLOCK_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x84)))
#define SYSREG_SUBBLK_CLOCK_CR_ENVM (1U << 0)
#define SYSREG_SUBBLK_CLOCK_CR_MMC (1U << 3)
#define SYSREG_SUBBLK_CLOCK_CR_QSPI (1U << 19)
/* Peripheral Soft Reset Control Register (offset 0x88) */
#define SYSREG_SOFT_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x88)))
#define SYSREG_SOFT_RESET_CR_QSPI (1U << 19)
/* eNVM Control Register (offset 0xB8). Bits [5:0] set the AHB-to-eNVM
* clock divider (period = (value+1) * AHB period); bit 6 (clock-okay)
* latches once a new divider has taken effect. Must be reprogrammed for
* the faster AHB clock BEFORE the MSS PLL mux switch (HSS does this in
* mss_mux_post_mss_pll_config with LIBERO_SETTING_MSS_ENVM_CR). */
#define SYSREG_ENVM_CR (*((volatile uint32_t*)(SYSREG_BASE + 0xB8)))
#define SYSREG_ENVM_CR_CLOCK_OKAY (1U << 6)
/* MSS Peripheral control bits (shared by SUBBLK_CLOCK_CR and SOFT_RESET_CR) */
#define MSS_PERIPH_ENVM (1U << 0)
#define MSS_PERIPH_MMC (1U << 3)
#define MSS_PERIPH_MMUART0 (1U << 5)
#define MSS_PERIPH_MMUART1 (1U << 6)
#define MSS_PERIPH_MMUART2 (1U << 7)
#define MSS_PERIPH_MMUART3 (1U << 8)
#define MSS_PERIPH_MMUART4 (1U << 9)
#define MSS_PERIPH_SPI0 (1U << 10)
#define MSS_PERIPH_SPI1 (1U << 11)
#define MSS_PERIPH_QSPI (1U << 19)
#define MSS_PERIPH_GPIO0 (1U << 20)
#define MSS_PERIPH_GPIO1 (1U << 21)
#define MSS_PERIPH_GPIO2 (1U << 22)
#define MSS_PERIPH_DDRC (1U << 23)
#define MSS_PERIPH_ATHENA (1U << 28) /* Crypto hardware accelerator */
/* MSS Watchdog Timer (per-hart) */
#define MSS_WDT_E51_BASE 0x20001000UL
#define MSS_WDT_U54_1_BASE 0x20101000UL
#define MSS_WDT_U54_2_BASE 0x20103000UL
#define MSS_WDT_U54_3_BASE 0x20105000UL
#define MSS_WDT_U54_4_BASE 0x20107000UL
#define MSS_WDT_REFRESH(base) (*(volatile uint32_t*)((base) + 0x00))
#define MSS_WDT_CONTROL(base) (*(volatile uint32_t*)((base) + 0x04))
#define MSS_WDT_STATUS(base) (*(volatile uint32_t*)((base) + 0x08))
#define MSS_WDT_TIME(base) (*(volatile uint32_t*)((base) + 0x0C))
#define MSS_WDT_MVRP(base) (*(volatile uint32_t*)((base) + 0x10))
#define MSS_WDT_CTRL_ENABLE (1U << 0)
/* UART */
#define MSS_UART0_LO_BASE 0x20000000UL
#define MSS_UART1_LO_BASE 0x20100000UL
#define MSS_UART2_LO_BASE 0x20102000UL
#define MSS_UART3_LO_BASE 0x20104000UL
#define MSS_UART4_LO_BASE 0x20106000UL
#define MSS_UART0_HI_BASE 0x28000000UL
#define MSS_UART1_HI_BASE 0x28100000UL
#define MSS_UART2_HI_BASE 0x28102000UL
#define MSS_UART3_HI_BASE 0x28104000UL
#define MSS_UART4_HI_BASE 0x28106000UL
/* Debug UART port selection (0-4): M-mode defaults to UART0, S-mode to UART1 */
#ifndef DEBUG_UART_PORT
#ifdef WOLFBOOT_RISCV_MMODE
#define DEBUG_UART_PORT 0
#else
#define DEBUG_UART_PORT 1
#endif
#endif
/* Derive base address from port number */
#if DEBUG_UART_PORT == 0
#define DEBUG_UART_BASE MSS_UART0_LO_BASE
#elif DEBUG_UART_PORT == 1
#define DEBUG_UART_BASE MSS_UART1_LO_BASE
#elif DEBUG_UART_PORT == 2
#define DEBUG_UART_BASE MSS_UART2_LO_BASE
#elif DEBUG_UART_PORT == 3
#define DEBUG_UART_BASE MSS_UART3_LO_BASE
#elif DEBUG_UART_PORT == 4
#define DEBUG_UART_BASE MSS_UART4_LO_BASE
#else
#error "Invalid DEBUG_UART_PORT (must be 0-4)"
#endif
#define MMUART_RBR(base) *((volatile uint8_t*)((base)) + 0x00) /* Receiver buffer register */
#define MMUART_IER(base) *((volatile uint8_t*)((base)) + 0x04) /* Interrupt enable register */
#define MMUART_IIR(base) *((volatile uint8_t*)((base)) + 0x08) /* Interrupt ID register */
#define MMUART_LCR(base) *((volatile uint8_t*)((base)) + 0x0C) /* Line control register */
#define MMUART_MCR(base) *((volatile uint8_t*)((base)) + 0x10) /* Modem control register */
#define MMUART_LSR(base) *((volatile uint8_t*)((base)) + 0x14) /* Line status register */
#define MMUART_MM0(base) *((volatile uint8_t*)((base)) + 0x30) /* Mode register 0 */
#define MMUART_MM1(base) *((volatile uint8_t*)((base)) + 0x34) /* Mode register 1 */
#define MMUART_MM2(base) *((volatile uint8_t*)((base)) + 0x38) /* Mode register 2 */
#define MMUART_DFR(base) *((volatile uint8_t*)((base)) + 0x3C) /* Fractional divisor register */
#define MMUART_GFR(base) *((volatile uint8_t*)((base)) + 0x44) /* Global filter register */
#define MMUART_TTG(base) *((volatile uint8_t*)((base)) + 0x48) /* TX time guard register */
#define MMUART_RTO(base) *((volatile uint8_t*)((base)) + 0x4C) /* RX timeout register */
#define MMUART_DLR(base) *((volatile uint8_t*)((base)) + 0x80) /* Divisor latch LSB */
#define MMUART_DMR(base) *((volatile uint8_t*)((base)) + 0x84) /* Divisor latch MSB */
#define MMUART_THR(base) *((volatile uint8_t*)((base)) + 0x100) /* Transmitter holding register */
#define MMUART_FCR(base) *((volatile uint8_t*)((base)) + 0x104) /* FIFO control register */
/* LCR (Line Control Register) */
#define MSS_UART_DATA_8_BITS ((uint8_t)0x03)
#define MSS_UART_NO_PARITY ((uint8_t)0x00)
#define MSS_UART_ONE_STOP_BIT ((uint8_t)0x00)
/* LSR (Line Status Register) */
#define MSS_UART_DR ((uint8_t)0x01) /* Data ready */
#define MSS_UART_THRE ((uint8_t)0x20) /* Transmitter holding register empty */
#define MSS_UART_TEMT ((uint8_t)0x40) /* Transmitter empty (FIFO + shift register) */
#define ELIN_MASK (1U << 3) /* Enable LIN header detection */
#define EIRD_MASK (1U << 2) /* Enable IrDA modem */
#define EERR_MASK (1U << 0) /* Enable ERR / NACK during stop time */
#define RXRDY_TXRDYN_EN_MASK (1U << 0) /* Enable TXRDY and RXRDY signals */
#define CLEAR_RX_FIFO_MASK (1U << 1) /* Clear receiver FIFO */
#define CLEAR_TX_FIFO_MASK (1U << 2) /* Clear transmitter FIFO */
#define RTS_MASK (1U << 1) /* Request To Send */
#define LOOP_MASK (1U << 4) /* Local loopback */
#define RLOOP_MASK (1U << 5) /* Remote loopback & Automatic echo*/
#define E_MSB_RX_MASK (1U << 0) /* MSB / LSB first for receiver */
#define E_MSB_TX_MASK (1U << 1) /* MSB / LSB first for transmitter */
#define EAFM_MASK (1U << 1) /* Enable 9-bit address flag mode */
#define ETTG_MASK (1U << 5) /* Enable transmitter time guard */
#define ERTO_MASK (1U << 6) /* Enable receiver time-out */
#define ESWM_MASK (1U << 3) /* Enable single wire half-duplex mode */
#define EFBR_MASK (1U << 7) /* Enable fractional baud rate mode */
/* Line Control register bit masks */
#define SB_MASK (1U << 6) /* Set break */
#define DLAB_MASK (1U << 7) /* Divisor latch access bit */
/* ============================================================================
* EMMC/SD Card Controller (Cadence SD4HC)
* Base Address: 0x20008000
* ============================================================================ */
#define EMMC_SD_BASE 0x20008000UL
/* ============================================================================
* System Controller Mailbox
* Control Base: 0x37020000
* Mailbox RAM: 0x37020800
*
* Used for system services like reading the device serial number.
* ============================================================================ */
#define SCBCTRL_BASE 0x37020000UL
#define SCBMBOX_BASE 0x37020800UL
/* System Services Control and Status Register offsets (from SCBCTRL_BASE) */
#define SERVICES_CR_OFFSET 0x50u
#define SERVICES_SR_OFFSET 0x54u
/* Control Register bits */
#define SERVICES_CR_REQ_MASK 0x01u
#define SERVICES_CR_COMMAND_SHIFT 16
/* Status Register bits */
#define SERVICES_SR_BUSY_MASK 0x02u
#define SERVICES_SR_STATUS_SHIFT 16
/* System Service command opcodes */
#define SYS_SERV_CMD_SERIAL_NUMBER 0x00u
#define SYS_SERV_CMD_SPI_COPY 0x50u /* SCB mailbox SPI copy service */
/* Device serial number size in bytes */
#define DEVICE_SERIAL_NUMBER_SIZE 16
/* Timeout loop iteration counts (override at build time via CFLAGS) */
#ifndef MPFS_SCB_TIMEOUT
#define MPFS_SCB_TIMEOUT 10000 /* SCB mailbox polling */
#endif
#ifndef QSPI_TIMEOUT_TRIES
#define QSPI_TIMEOUT_TRIES 100000 /* QSPI controller/TX polling */
#endif
#ifndef QSPI_RX_TIMEOUT_TRIES
#define QSPI_RX_TIMEOUT_TRIES 1000000 /* QSPI RX polling (longer) */
#endif
/* System Controller register access */
#define SCBCTRL_REG(off) (*((volatile uint32_t*)(SCBCTRL_BASE + (off))))
#define SCBMBOX_REG(off) (*((volatile uint32_t*)(SCBMBOX_BASE + (off))))
#define SCBMBOX_BYTE(off) (*((volatile uint8_t*)(SCBMBOX_BASE + (off))))
/* System Controller Mailbox API */
#ifndef __ASSEMBLER__
int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data,
uint32_t mb_len, uint32_t timeout);
int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len);
int mpfs_read_serial_number(uint8_t *serial);
#endif /* __ASSEMBLER__ */
/* Crypto Engine: Athena F5200 (200 MHz) */
#define ATHENA_BASE (SYSREG_BASE + 0x125000)
/* L2 Cache Controller (CACHE_CTRL @ 0x02010000) */
#define L2_CACHE_BASE 0x02010000UL
#define L2_CONFIG (*(volatile uint64_t*)(L2_CACHE_BASE + 0x000))
#define L2_WAY_ENABLE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x008))
#define L2_WAY_MASK_DMA (*(volatile uint64_t*)(L2_CACHE_BASE + 0x800))
#define L2_WAY_MASK_AXI4_PORT0 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x808))
#define L2_WAY_MASK_AXI4_PORT1 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x810))
#define L2_WAY_MASK_AXI4_PORT2 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x818))
#define L2_WAY_MASK_AXI4_PORT3 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x820))
#define L2_WAY_MASK_E51_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x828))
#define L2_WAY_MASK_E51_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x830))
#define L2_WAY_MASK_U54_1_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x838))
#define L2_WAY_MASK_U54_1_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x840))
#define L2_WAY_MASK_U54_2_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x848))
#define L2_WAY_MASK_U54_2_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x850))
#define L2_WAY_MASK_U54_3_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x858))
#define L2_WAY_MASK_U54_3_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x860))
#define L2_WAY_MASK_U54_4_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x868))
#define L2_WAY_MASK_U54_4_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x870))
/* L2 Shutdown Control Register */
#define SYSREG_L2_SHUTDOWN_CR (*(volatile uint32_t*)(SYSREG_BASE + 0x174))
/* L2 Cache/Scratchpad constants */
#define L2_NUM_CACHE_WAYS 8 /* Ways 0-7 are cache */
#define L2_NUM_SCRATCH_WAYS 4 /* Ways 8-11 are scratchpad */
#define L2_WAY_BYTE_LENGTH 0x20000 /* 128KB per way */
#define L2_SCRATCH_BASE 0x0A000000UL
#define L2_SCRATCH_SIZE (L2_NUM_SCRATCH_WAYS * L2_WAY_BYTE_LENGTH)
#define L2_WAY_ENABLE_RESET 0x01
#define L2_WAY_ENABLE_ALL_CACHE 0xFF
#define L2_WAY_ENABLE_WITH_SCRATCH 0x0FFF
#define L2_WAY_MASK_CACHE_ONLY 0xFF
/* CLINT - Core Local Interruptor */
#ifndef CLINT_BASE
#define CLINT_BASE 0x02000000UL
#endif
/* RTC Clock Frequency (1 MHz after divisor) */
#define RTC_CLOCK_FREQ 1000000UL
/* In M-mode CLINT MTIME is not running without HSS; use mcycle (CPU clock) instead.
* In S-mode MTIME runs at 1 MHz (default RISCV_SMODE_TIMER_FREQ). */
#if defined(WOLFBOOT_RISCV_MMODE) && !defined(RISCV_SMODE_TIMER_FREQ)
#define RISCV_SMODE_TIMER_FREQ MSS_CPU_CLK
#endif
/* Hart Local Storage (HLS) - per-hart communication structure, 64 bytes at top of stack */
#define HLS_DEBUG_AREA_SIZE 64
#ifndef __ASSEMBLER__
typedef struct {
volatile uint32_t in_wfi_indicator; /* 0x00: Hart status indicator */
volatile uint32_t my_hart_id; /* 0x04: Hart ID */
volatile uint32_t shared_mem_marker; /* 0x08: Init marker */
volatile uint32_t shared_mem_status; /* 0x0C: Status */
volatile uint64_t* shared_mem; /* 0x10: Shared memory pointer */
volatile uint64_t reserved[5]; /* 0x18: Reserved/padding to 64 bytes */
} HLS_DATA; /* 64 bytes total */
#endif /* __ASSEMBLER__ */
#define HLS_MAIN_HART_STARTED 0x12344321UL
#define HLS_OTHER_HART_IN_WFI 0x12345678UL
/* DTIM address of the E51 "main hart started" gate flag polled by the
* parked secondary harts in boot_riscv_start.S. This must NOT live in
* L2-scratch (the legacy HLS location): cacheable stores to the
* scratchpad can be silently lost on dirty-line eviction, so whether the
* secondaries ever saw the flag depended on the image's cache-line
* layout (observed: a 304-byte text shift left harts 2-4 stuck in the
* eNVM gate until the kernel's HSM hart_start IPI, missing the kernel's
* 1s online window). The E51 DTIM is uncached and coherent for every
* hart. Keep clear of the SBI shared block (DTIM+0x00, src/riscv_sbi.c)
* and the hart-start mailboxes (DTIM+0x100, hal/mpfs250.c).
* No UL suffix: also used from assembly (boot_riscv_start.S). */
#define MPFS_DTIM_MAIN_STARTED_ADDR 0x010000F0
/* Number of harts on MPFS */
#define MPFS_NUM_HARTS 5
#define MPFS_FIRST_HART 0 /* E51 is hart 0 */
#define MPFS_FIRST_U54_HART 1 /* First U54 is hart 1 */
#define MPFS_LAST_U54_HART 4 /* Last U54 is hart 4 */
/* Stack configuration per hart */
#ifndef STACK_SIZE_PER_HART
#define STACK_SIZE_PER_HART 8192
#endif
/* Multi-hart function declarations */
#ifndef __ASSEMBLER__
#ifdef DEBUG_UART
void uart_init(void);
void uart_write(const char* buf, unsigned int sz);
#endif
#ifdef WOLFBOOT_RISCV_MMODE
void secondary_hart_entry(unsigned long hartid, HLS_DATA* hls);
#endif
#endif /* __ASSEMBLER__ */
/* PLIC - Platform-Level Interrupt Controller (base 0x0C000000, 64MB) */
#define PLIC_BASE 0x0C000000UL
#define PLIC_SIZE 0x04000000UL
#define PLIC_NUM_SOURCES 186
#define PLIC_NUM_HARTS 5
#define PLIC_NUM_CONTEXTS 10
#define OFFSET_TO_MSS_GLOBAL_INTS 13
#define PLIC_INT_MMC_MAIN 88
/* ============================================================================
* DDR Controller and PHY (LPDDR4) - Video Kit MPFS250T
*
* MPFS DDR subsystem consists of:
* - DDR Controller (DDRCFG_BASE @ 0x20080000) - timing, addressing, refresh
* - DDR PHY (CFG_DDR_SGMII_PHY @ 0x20007000) - physical interface, training
* - Segment registers for address translation
* - SCB PLLs for clock generation
*
* Video Kit memory: Micron MT53D512M32D2DS-053 LPDDR4 (2GB, x32 @ 1600 Mbps)
* ============================================================================ */
/* SCB Configuration Block (SCBCFG @ 0x37080000) */
#define SCBCFG_BASE 0x37080000UL
#define SCBCFG_TIMER (*(volatile uint32_t*)(SCBCFG_BASE + 0x08))
#define MSS_SCB_ACCESS_CONFIG 0x0008A080UL
/* DDR SGMII PHY Configuration (CFG_DDR_SGMII_PHY @ 0x20007000) */
#define CFG_DDR_SGMII_PHY_BASE 0x20007000UL
#define DDRPHY_STARTUP (*(volatile uint32_t*)(CFG_DDR_SGMII_PHY_BASE + 0x008))
#define DDRPHY_DYN_CNTL (*(volatile uint32_t*)(CFG_DDR_SGMII_PHY_BASE + 0xC1C))
#define DDRPHY_STARTUP_CONFIG 0x003F1F00UL
#define DDRPHY_DYN_CNTL_CONFIG 0x0000047FUL
/* DFI APB interface control (enables DDR PHY APB access) */
#define SYSREG_DFIAPB_CR (*(volatile uint32_t*)(SYSREG_BASE + 0x98))
/* L2 cache flush registers (used at boot for DDR coherency) */
#define L2_FLUSH64 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x200))
#define L2_FLUSH32 (*(volatile uint32_t*)(L2_CACHE_BASE + 0x240))
/* DDR Base Addresses */
#define SYSREGSCB_BASE 0x20003000UL
#define DDRCFG_BASE 0x20080000UL /* DDR Controller CSR APB */
#define DDR_SEG_BASE 0x20005D00UL /* From HSS mss_seg.h */
/* SCB PLL Bases */
#define SCB_MSS_PLL_BASE 0x3E001000UL
#define SCB_DDR_PLL_BASE 0x3E010000UL
/* Clock Fabric Mux bases */
#define SCB_CFM_MSS_BASE 0x3E002000UL
#define SCB_CFM_SGMII_BASE 0x3E200000UL
/* DDR Bank Controller (NV map reset during VREF training) */
#define SCB_BANKCONT_DDR_BASE 0x3E020000UL
/* Register Access Macros */
#define SYSREG_REG(off) (*(volatile uint32_t*)(SYSREG_BASE + (off)))
#define SYSREGSCB_REG(off) (*(volatile uint32_t*)(SYSREGSCB_BASE + (off)))
#define DDRCFG_REG(off) (*(volatile uint32_t*)(DDRCFG_BASE + (off)))
#define DDRPHY_REG(off) (*(volatile uint32_t*)(CFG_DDR_SGMII_PHY_BASE + (off)))
#define DDR_BANKCONT_REG(off) (*(volatile uint32_t*)(SCB_BANKCONT_DDR_BASE + (off)))
#define DDR_SEG_REG(off) (*(volatile uint32_t*)(DDR_SEG_BASE + (off)))
#define SCBCFG_REG(off) (*(volatile uint32_t*)(SCBCFG_BASE + (off)))
#define MSS_PLL_REG(off) (*(volatile uint32_t*)(SCB_MSS_PLL_BASE + (off)))
#define DDR_PLL_REG(off) (*(volatile uint32_t*)(SCB_DDR_PLL_BASE + (off)))
#define CFM_MSS_REG(off) (*(volatile uint32_t*)(SCB_CFM_MSS_BASE + (off)))
#define CFM_SGMII_REG(off) (*(volatile uint32_t*)(SCB_CFM_SGMII_BASE + (off)))
/* SYSREG Offsets */
#define SYSREG_SUBBLK_CLOCK_CR_OFF 0x84
#define SYSREG_SOFT_RESET_CR_OFF 0x88
#define SYSREG_DFIAPB_CR_OFF 0x98
#define MSSIO_CONTROL_CR_OFF 0x1BC
/* PLL Register Offsets */
#define PLL_SOFT_RESET 0x000
#define PLL_CTRL 0x004
#define PLL_REF_FB 0x008
#define PLL_FRACN 0x00C
#define PLL_DIV_0_1 0x010
#define PLL_DIV_2_3 0x014
#define PLL_CTRL2 0x018
#define PLL_PHADJ 0x020
#define PLL_SSCG_0 0x024
#define PLL_SSCG_1 0x028
#define PLL_SSCG_2 0x02C
#define PLL_SSCG_3 0x030
/* PLL Control Bits */
#define PLL_POWERDOWN_B (1UL << 0)
#define PLL_LOCK_BIT (1UL << 25)
#define PLL_INIT_OUT_RESET 0x00000003UL
/* CFM Register Offsets */
#define CFM_BCLKMUX 0x004
#define CFM_PLL_CKMUX 0x008
#define CFM_MSSCLKMUX 0x00C
#define CFM_FMETER_ADDR 0x014
#define CFM_FMETER_DATAW 0x018
/* SGMII CFM Register Offsets (at SCB_CFM_SGMII_BASE 0x3E200000) */
#define CFM_SGMII_SOFT_RESET 0x000
#define CFM_SGMII_RFCKMUX 0x004 /* Routes refclk to DDR/SGMII PLLs */
#define CFM_SGMII_SGMII_CLKMUX 0x008
#define CFM_SGMII_SPARE0 0x00C
#define CFM_SGMII_CLK_XCVR 0x010
/* DDR PHY Register Offsets */
#define PHY_SOFT_RESET 0x000
#define PHY_MODE 0x004
#define PHY_STARTUP 0x008
#define PHY_PLL_CTRL_MAIN 0x084
#define PHY_DPC_BITS 0x184
#define PHY_BANK_STATUS 0x188
#define PHY_IOC_REG0 0x204
#define PHY_IOC_REG1 0x208
#define PHY_IOC_REG2 0x20C
#define PHY_IOC_REG3 0x210
#define PHY_IOC_REG6 0x21C /* Calibration reset/clock divider */
#define PHY_DYN_CNTL 0xC1C
#define PHY_SOFT_RESET_TIP 0x800
#define PHY_RANK_SELECT 0x804
#define PHY_LANE_SELECT 0x808 /* was wrongly named PHY_BCLK_SCLK */
/* The real BCLK/SCLK training answer is at 0x870 (bclksclk_answer).
* Old PHY_BCLK_SCLK at 0x808 was lane_select, so any printf of it
* was meaningless. */
#define PHY_BCLKSCLK_ANSWER 0x870
#define PHY_TRAINING_SKIP 0x80C
#define PHY_TRAINING_START 0x810
#define PHY_TRAINING_STATUS 0x814
#define PHY_TRAINING_RESET 0x818
#define PHY_TIP_CFG 0x828
#define PHY_TIP_CFG_PARAMS 0x8D0
#define PHY_EXPERT_MODE_EN 0x878
#define PHY_EXPERT_DLYCNT_MOVE0 0x87C
#define PHY_EXPERT_DLYCNT_MOVE1 0x880
#define PHY_EXPERT_DLYCNT_DIRECTION0 0x884
#define PHY_EXPERT_DLYCNT_DIR1 0x888
#define PHY_EXPERT_DLYCNT_LOAD0 0x88C
#define PHY_EXPERT_DLYCNT_LOAD1 0x890
#define PHY_EXPERT_DFI_STATUS_TO_SHIM 0x8CC
#define PHY_LANE_ALIGN_FIFO_CTRL 0x8D8
#define PHY_EXPERT_MV_RD_DLY 0x89C
#define PHY_EXPERT_DLYCNT_PAUSE 0x8A0
#define PHY_EXPERT_PLLCNT 0x8A4
#define PHY_EXPERT_DQ_READBACK 0x8A8
#define PHY_EXPERT_ADDCMD_READBACK 0x8AC /* Bits 13:12 = rx_bclksclk, 3:0 = rx_ck */
/* 0x8B0 is expert_read_gate_controls, NOT a DFI status register.
* Previous PHY_EXPERT_DFI_STATUS define here pointed writes
* (0x6/0x4/0x0 for DQ/DQS output delay setup) at the wrong register.
* The correct register is PHY_EXPERT_DFI_STATUS_TO_SHIM at 0x8CC. */
#define PHY_EXPERT_READ_GATE_CONTROLS 0x8B0
#define PHY_EXPERT_WRCALIB 0x8BC
#define PHY_RPC95_IBUFMD_ADDCMD 0x57C /* LPDDR4 Input Buffer Mode - ADDCMD */
#define PHY_RPC96_IBUFMD_CLK 0x580 /* LPDDR4 Input Buffer Mode - CLK */
#define PHY_RPC97_IBUFMD_DQ 0x584 /* LPDDR4 Input Buffer Mode - DQ */
#define PHY_RPC98_IBUFMD_DQS 0x588 /* LPDDR4 Input Buffer Mode - DQS */
#define PHY_RPC145 0x644 /* ADDCMD delay offset (A9 loopback) */
#define PHY_RPC147 0x64C /* DDR clock loopback delay */
#define PHY_RPC156 0x670
#define PHY_RPC166 0x698
#define PHY_RPC168 0x6A0 /* RX_MD_CLKN for LPDDR4 training */
#define PHY_RPC220 0x770
/* ODT (On-Die Termination) RPC registers */
#define PHY_RPC1_ODT 0x384 /* ODT_CA */
#define PHY_RPC2_ODT 0x388 /* ODT_CLK */
#define PHY_RPC3_ODT 0x38C /* ODT_DQ (0 for WRLVL, 3 normally) */
#define PHY_RPC4_ODT 0x390 /* ODT_DQS */
/* PVT calibration bits */
#define PVT_CALIB_START (1U << 0)
#define PVT_CALIB_LOCK (1U << 14)
#define PVT_CALIB_STATUS (1U << 2)
#define PVT_IOEN_OUT (1U << 4)
/* IOSCB IO Calibration DDR base (SCB space for PVT calibration) */
#define IOSCB_IO_CALIB_DDR_BASE 0x3E040000UL
#define IOSCB_IO_CALIB_DDR_REG(off) (*(volatile uint32_t*)(IOSCB_IO_CALIB_DDR_BASE + (off)))
#define IOSCB_SOFT_RESET 0x000
#define IOSCB_IOC_REG0 0x004
#define IOSCB_IOC_REG1 0x008
/* DDR Segment Register Offsets.
* SEG is a 256-byte-stride peripheral pair (mss_seg.h:54): seg_t has
* 8 x u32 control regs + 56 x u32 fill = 256 B. SEG[0] is at base
* (DDR_SEG_BASE = 0x20005D00); SEG[1] is at base + 0x100 (= 0x20005E00).
* Phase 3.10.3 (A) finding: wolfBoot previously put SEG1_X at offset
* 0x20-0x3C (overwriting unrelated registers), so the SEG1 cached/
* non-cached DDR address-mapping registers were never written --
* 0x80000000 stores faulted with cause=7 (store access fault). */
#define SEG0_0 0x00
#define SEG0_1 0x04
#define SEG0_2 0x08
#define SEG0_3 0x0C
#define SEG0_4 0x10
#define SEG0_5 0x14
#define SEG0_6 0x18
#define SEG0_BLOCKER 0x1C
#define SEG1_0 0x100
#define SEG1_1 0x104
#define SEG1_2 0x108
#define SEG1_3 0x10C
#define SEG1_4 0x110
#define SEG1_5 0x114
#define SEG1_6 0x118
#define SEG1_7 0x11C
/* DDR Memory Map */
#define DDR_BASE_CACHED 0x80000000UL /* Cached access */
#define DDR_BASE_NONCACHED 0xC0000000UL /* Non-cached access */
#define DDR_BASE_NONCACHED_WCB 0xD0000000UL /* Non-cached with write-combining */
#define DDR_SIZE 0x80000000UL /* 2GB (Video Kit) */
/* DDR Init return codes */
#define DDR_INIT_SUCCESS 0
#define DDR_INIT_TIMEOUT -1
#define DDR_INIT_TRAINING_FAIL -2
#define DDR_INIT_MEM_TEST_FAIL -3
/* ============================================================================
* Video Kit Clock/DDR Configuration
*
* The LIBERO_SETTING_* values come from a Libero/HSS-generated
* fpga_design_config.h for the target board. Set LIBERO_FPGA_CONFIG_DIR
* at build time to point at the directory containing fpga_design_config.h
* (see arch.mk and the polarfire_mpfs250_m.config example).
* ============================================================================ */
#ifdef MPFS_DDR_INIT
#include "fpga_design_config.h"
#endif
/* DDR function declarations */
#ifndef __ASSEMBLER__
#ifdef WOLFBOOT_RISCV_MMODE
int mpfs_ddr_init(unsigned int outer_retry);
void hal_uart_reinit(void);
/* Verbose DDR/PLL/PHY/training trace (build with -DDEBUG_DDR). Defined in
* the header so both hal/mpfs250.c (WDT/L2/text-verify dumps) and
* hal/mpfs250_ddr.c (the DDR driver) can use it. */
#ifdef DEBUG_DDR
# define DBG_DDR(_f_, ...) wolfBoot_printf(_f_, ##__VA_ARGS__)
#else
# define DBG_DDR(_f_, ...) do { } while (0)
#endif
/* Full system memory barrier (AXI/peripheral ordering). */
static inline void mb(void)
{
__asm__ volatile("fence iorw, iorw" ::: "memory");
}
/* mcycle-based microsecond busy delay. Defined in hal/mpfs250.c (it must
* exist in non-DDR M-mode builds too); read from hal/mpfs250_ddr.c. */
void udelay(uint32_t us);
/* CPU/APB clock rates, defined in hal/mpfs250.c (read by udelay() and the
* UART baud divisor in every M-mode build) and updated by mss_pll_init() in
* hal/mpfs250_ddr.c when the MSS PLL is raised. */
extern uint32_t mpfs_cpu_freq_mhz;
extern uint32_t mpfs_apb_clk_hz;
#ifdef MPFS_DDR_INIT
/* MSSIO IOMUX setup: defined in hal/mpfs250.c (alongside the SDHCI platform
* helpers) but called from nwc_init() in hal/mpfs250_ddr.c. */
void mpfs_iomux_init(void);
#endif
/* PDMA-based memcpy: src must be CPU-readable (L2 Scratch / LIM / DDR
* already loaded), dst is the destination AXI address. When dst is in
* the cached DDR window (top 4 bits = 0x8) the helper rewrites it to
* the non-cached alias (top 4 bits = 0xC) before kicking PDMA, since
* PDMA-via-non-cached is the only AXI write path that consistently
* lands in DDR on this board. Returns 0 on success, non-zero on
* timeout. */
int mpfs_pdma_memcpy(void *dst, const void *src, uint32_t bytes);
#endif
#endif /* __ASSEMBLER__ */
#ifdef EXT_FLASH
/* QSPI Flash Controller
*
* Two CoreQSPI v2 controllers with identical register layouts:
* SC QSPI (MPFS_SC_SPI=1, default): 0x37020100 -- fabric-connected flash
* MSS QSPI (MPFS_SC_SPI=0): 0x21000000 -- MSS QSPI pins
*/
/* QSPI Controller Base Address */
#ifndef QSPI_BASE
#ifdef MPFS_SC_SPI
#define QSPI_BASE 0x37020100u /* SC QSPI Controller (fabric-connected flash) */
#else
#define QSPI_BASE 0x21000000u /* MSS QSPI Controller (external flash) */
#endif
#endif
/* QSPI Register Offsets */
#define QSPI_CONTROL (*(volatile uint32_t *)(QSPI_BASE + 0x00))
#define QSPI_FRAMES (*(volatile uint32_t *)(QSPI_BASE + 0x04))
#define QSPI_IEN (*(volatile uint32_t *)(QSPI_BASE + 0x0C))
#define QSPI_STATUS (*(volatile uint32_t *)(QSPI_BASE + 0x10))
#define QSPI_DIRECT (*(volatile uint32_t *)(QSPI_BASE + 0x14))
#define QSPI_ADDRUP (*(volatile uint32_t *)(QSPI_BASE + 0x18))
#define QSPI_RX_DATA (*(volatile uint8_t *)(QSPI_BASE + 0x40))
#define QSPI_TX_DATA (*(volatile uint8_t *)(QSPI_BASE + 0x44))
#define QSPI_X4_RX_DATA (*(volatile uint32_t *)(QSPI_BASE + 0x48))
#define QSPI_X4_TX_DATA (*(volatile uint32_t *)(QSPI_BASE + 0x4C))
#define QSPI_FRAMESUP (*(volatile uint32_t *)(QSPI_BASE + 0x50))
/* QSPI Control Register Bits */
#define QSPI_CTRL_EN_OFFSET 0
#define QSPI_CTRL_XIP_OFFSET 2
#define QSPI_CTRL_XIPADDR_OFFSET 3
#define QSPI_CTRL_CLKIDLE_OFFSET 10
#define QSPI_CTRL_SAMPLE_OFFSET 11
#define QSPI_CTRL_QMODE0_OFFSET 13
#define QSPI_CTRL_QMODE12_OFFSET 14
#define QSPI_CTRL_FLAGSX4_OFFSET 16
#define QSPI_CTRL_CLKRATE_OFFSET 24
#define QSPI_CTRL_EN (1u << QSPI_CTRL_EN_OFFSET)
#define QSPI_CTRL_XIP (1u << QSPI_CTRL_XIP_OFFSET)
#define QSPI_CTRL_CLKIDLE (1u << QSPI_CTRL_CLKIDLE_OFFSET)
#define QSPI_CTRL_SAMPLE_SCK (0x0u << QSPI_CTRL_SAMPLE_OFFSET)
/* QSPI Frames Register Bits */
#define QSPI_FRAMES_TOTALBYTES_OFFSET 0
#define QSPI_FRAMES_CMDBYTES_OFFSET 16
#define QSPI_FRAMES_QSPI_OFFSET 25
#define QSPI_FRAMES_IDLE_OFFSET 26
#define QSPI_FRAMES_FBYTE_OFFSET 30
#define QSPI_FRAMES_FWORD_OFFSET 31
#define QSPI_FRAMES_TOTALBYTES_MASK (0xFFFFu << QSPI_FRAMES_TOTALBYTES_OFFSET)
#define QSPI_FRAMES_CMDBYTES_MASK (0x1FFu << QSPI_FRAMES_CMDBYTES_OFFSET)
#define QSPI_FRAMES_QSPI (1u << QSPI_FRAMES_QSPI_OFFSET)
#define QSPI_FRAMES_IDLE_MASK (0xFu << QSPI_FRAMES_IDLE_OFFSET)
/* QSPI Status Register Bits */
#define QSPI_STATUS_TXDONE (1u << 0)
#define QSPI_STATUS_RXDONE (1u << 1)
#define QSPI_STATUS_RXAVAIL (1u << 2)
#define QSPI_STATUS_TXAVAIL (1u << 3)
#define QSPI_STATUS_READY (1u << 7)
/* QSPI Clock Configuration */
#define QSPI_CLK_DIV_2 0x01u
#define QSPI_CLK_DIV_4 0x02u
#define QSPI_CLK_DIV_6 0x03u
#define QSPI_CLK_DIV_8 0x04u
#define QSPI_CLK_DIV_10 0x05u
#define QSPI_CLK_DIV_12 0x06u
#define QSPI_CLK_DIV_30 0x0Fu /* ~5 MHz from 150 MHz APB */
/* Micron MT25QL01G Flash Commands */
#define QSPI_CMD_READ_ID_OPCODE 0x9Fu /* JEDEC ID Read */
#define QSPI_CMD_MIO_READ_ID_OPCODE 0xAFu /* Multiple IO Read ID */
#define QSPI_CMD_READ_STATUS_OPCODE 0x05u /* Read Status Register */
#define QSPI_CMD_WRITE_ENABLE_OPCODE 0x06u /* Write Enable */
#define QSPI_CMD_WRITE_DISABLE_OPCODE 0x04u /* Write Disable */
#define QSPI_CMD_4BYTE_READ_OPCODE 0x13u /* 4-byte address read */
#define QSPI_CMD_4BYTE_FAST_READ_OPCODE 0x0Cu /* 4-byte fast read */
#define QSPI_CMD_4BYTE_QUAD_READ_OPCODE 0xECu /* 4-byte quad I/O read */
#define QSPI_CMD_4BYTE_PAGE_PROG_OPCODE 0x12u /* 4-byte page program */
#define QSPI_CMD_4BYTE_SECTOR_ERASE 0xDCu /* 4-byte 64KB sector erase */
#define QSPI_CMD_ENTER_4BYTE_MODE 0xB7u /* Enter 4-byte address mode */
#define QSPI_CMD_EXIT_4BYTE_MODE 0xE9u /* Exit 4-byte address mode */
/* Flash Geometry - Micron MT25QL01GBBB (128MB) */
#ifndef FLASH_DEVICE_SIZE
#define FLASH_DEVICE_SIZE (128 * 1024 * 1024) /* 128MB (1Gb) */
#endif
#ifndef FLASH_PAGE_SIZE
#define FLASH_PAGE_SIZE 256 /* 256 bytes */
#endif
#ifndef FLASH_SECTOR_SIZE
#define FLASH_SECTOR_SIZE (64 * 1024) /* 64KB sectors */
#endif
/* QSPI Transfer Modes */
#define QSPI_MODE_WRITE 0
#define QSPI_MODE_READ 1
/* I/O fence: ensure MMIO store reaches the peripheral before the next read.
* Required on RISC-V RVWMO to prevent stale TXAVAIL reads after TX writes. */
#define QSPI_IO_FENCE() __asm__ __volatile__("fence iorw, iorw" ::: "memory")
/* Function declarations for QSPI (when EXT_FLASH enabled) */
#ifndef __ASSEMBLER__
int qspi_init(void);
#endif /* __ASSEMBLER__ */
#endif /* EXT_FLASH */
#endif /* MPFS250_DEF_INCLUDED */