mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge pull request #818 from JacobPease/main
Added true bootloader to fpga/zsbl directory.
This commit is contained in:
		
						commit
						9ed78b5f08
					
				@ -16,7 +16,7 @@ OBJECTS		:= $(OBJECTS:.$(CPPEXT)=.$(OBJEXT))
 | 
			
		||||
OBJECTS		:= $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS))
 | 
			
		||||
 | 
			
		||||
TARGETDIR	:= bin
 | 
			
		||||
TARGET		:= $(TARGETDIR)/fpga-test-sdc
 | 
			
		||||
TARGET		:= $(TARGETDIR)/boot
 | 
			
		||||
ROOT		:= ..
 | 
			
		||||
LIBRARY_DIRS	:= 
 | 
			
		||||
LIBRARY_FILES	:=
 | 
			
		||||
@ -24,11 +24,13 @@ LIBRARY_FILES	:=
 | 
			
		||||
MARCH           :=-march=rv64imfdc_zifencei
 | 
			
		||||
MABI            :=-mabi=lp64d
 | 
			
		||||
LINK_FLAGS      :=$(MARCH) $(MABI) -nostartfiles
 | 
			
		||||
LINKER		:=linker.x
 | 
			
		||||
LINKER		:=linker1000.x
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
AFLAGS =$(MARCH) $(MABI) -W
 | 
			
		||||
CFLAGS =$(MARCH) $(MABI) -mcmodel=medany  -O2
 | 
			
		||||
# Override directive allows us to prepend other options on the command line
 | 
			
		||||
# e.g. $ make CFLAGS=-g
 | 
			
		||||
override CFLAGS +=$(MARCH) $(MABI) -mcmodel=medany -O2 -g
 | 
			
		||||
AS=riscv64-unknown-elf-as
 | 
			
		||||
CC=riscv64-unknown-elf-gcc
 | 
			
		||||
AR=riscv64-unknown-elf-ar
 | 
			
		||||
@ -104,7 +106,7 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT)
 | 
			
		||||
# convert to hex
 | 
			
		||||
$(TARGET).memfile: $(TARGET)
 | 
			
		||||
	@echo 'Making object dump file.'
 | 
			
		||||
	@riscv64-unknown-elf-objdump -D $< > $<.objdump
 | 
			
		||||
	riscv64-unknown-elf-objdump -DS $< > $<.objdump
 | 
			
		||||
	@echo 'Making memory file'
 | 
			
		||||
	riscv64-unknown-elf-elf2hex --bit-width 64 --input $^ --output $@
 | 
			
		||||
	extractFunctionRadix.sh $<.objdump
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,12 @@ _start:
 | 
			
		||||
	# set the stack pointer to the top of memory - 8 bytes (pointer size)
 | 
			
		||||
	li sp, 0x87FFFFF8
 | 
			
		||||
 | 
			
		||||
	jal ra, main
 | 
			
		||||
	li a0, 0x00000000
 | 
			
		||||
	li a1, 0x80000000
 | 
			
		||||
	#li a2, 128*1024*1024/512 # copy 128MB
 | 
			
		||||
	li a2, 127*1024*1024/512 # copy 127MB upper 1MB contains the return address (ra)
 | 
			
		||||
	#li a2, 800 # copy 400KB
 | 
			
		||||
	jal ra, copyFlash
 | 
			
		||||
	
 | 
			
		||||
	fence.i
 | 
			
		||||
	# now toggle led so we know the copy completed.
 | 
			
		||||
@ -81,18 +86,16 @@ delay2:
 | 
			
		||||
	# now that the card is copied and the led toggled we
 | 
			
		||||
	# jump to the copied contents of the sd card.
 | 
			
		||||
 | 
			
		||||
jumpToLinux:
 | 
			
		||||
	csrr a0, mhartid
 | 
			
		||||
        li s0, 0x80000000
 | 
			
		||||
        la a1, _dtb
 | 
			
		||||
        jr s0
 | 
			
		||||
jumpToLinux:	
 | 
			
		||||
	csrrs	a0, 0xF14, x0   # copy hart ID to a0
 | 
			
		||||
	li	a1, 0x87000000  # end of memory? not 100% sure on this but it's 112MB
 | 
			
		||||
	la	a2, end_of_bios
 | 
			
		||||
	li	t0, 0x80000000  # start of code
 | 
			
		||||
	
 | 
			
		||||
	jalr	x0, t0, 0
 | 
			
		||||
 | 
			
		||||
end_of_bios:	
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.section .rodata
 | 
			
		||||
.globl _dtb
 | 
			
		||||
.align 4, 0
 | 
			
		||||
_dtb:
 | 
			
		||||
#.incbin "wally-vcu118.dtb"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										422
									
								
								fpga/zsbl/boot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										422
									
								
								fpga/zsbl/boot.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,422 @@
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include "boot.h"
 | 
			
		||||
#include "gpt.h"
 | 
			
		||||
 | 
			
		||||
/* Card type flags (card_type) */
 | 
			
		||||
#define CT_MMC          0x01            /* MMC ver 3 */
 | 
			
		||||
#define CT_SD1          0x02            /* SD ver 1 */
 | 
			
		||||
#define CT_SD2          0x04            /* SD ver 2 */
 | 
			
		||||
#define CT_SDC          (CT_SD1|CT_SD2) /* SD */
 | 
			
		||||
#define CT_BLOCK        0x08            /* Block addressing */
 | 
			
		||||
 | 
			
		||||
#define CMD0    (0)             /* GO_IDLE_STATE */
 | 
			
		||||
#define CMD1    (1)             /* SEND_OP_COND */
 | 
			
		||||
#define CMD2    (2)             /* SEND_CID */
 | 
			
		||||
#define CMD3    (3)             /* RELATIVE_ADDR */
 | 
			
		||||
#define CMD4    (4)
 | 
			
		||||
#define CMD5    (5)             /* SLEEP_WAKE (SDC) */
 | 
			
		||||
#define CMD6    (6)             /* SWITCH_FUNC */
 | 
			
		||||
#define CMD7    (7)             /* SELECT */
 | 
			
		||||
#define CMD8    (8)             /* SEND_IF_COND */
 | 
			
		||||
#define CMD9    (9)             /* SEND_CSD */
 | 
			
		||||
#define CMD10   (10)            /* SEND_CID */
 | 
			
		||||
#define CMD11   (11)
 | 
			
		||||
#define CMD12   (12)            /* STOP_TRANSMISSION */
 | 
			
		||||
#define CMD13   (13)
 | 
			
		||||
#define CMD15   (15)
 | 
			
		||||
#define CMD16   (16)            /* SET_BLOCKLEN */
 | 
			
		||||
#define CMD17   (17)            /* READ_SINGLE_BLOCK */
 | 
			
		||||
#define CMD18   (18)            /* READ_MULTIPLE_BLOCK */
 | 
			
		||||
#define CMD19   (19)
 | 
			
		||||
#define CMD20   (20)
 | 
			
		||||
#define CMD23   (23)
 | 
			
		||||
#define CMD24   (24)
 | 
			
		||||
#define CMD25   (25)
 | 
			
		||||
#define CMD27   (27)
 | 
			
		||||
#define CMD28   (28)
 | 
			
		||||
#define CMD29   (29)
 | 
			
		||||
#define CMD30   (30)
 | 
			
		||||
#define CMD32   (32)
 | 
			
		||||
#define CMD33   (33)
 | 
			
		||||
#define CMD38   (38)
 | 
			
		||||
#define CMD42   (42)
 | 
			
		||||
#define CMD55   (55)            /* APP_CMD */
 | 
			
		||||
#define CMD56   (56)
 | 
			
		||||
#define ACMD6   (0x80+6)        /* define the data bus width */
 | 
			
		||||
#define ACMD41  (0x80+41)       /* SEND_OP_COND (ACMD) */
 | 
			
		||||
 | 
			
		||||
// Capability bits
 | 
			
		||||
#define SDC_CAPABILITY_SD_4BIT  0x0001
 | 
			
		||||
#define SDC_CAPABILITY_SD_RESET 0x0002
 | 
			
		||||
#define SDC_CAPABILITY_ADDR     0xff00
 | 
			
		||||
 | 
			
		||||
// Control bits
 | 
			
		||||
#define SDC_CONTROL_SD_4BIT     0x0001
 | 
			
		||||
#define SDC_CONTROL_SD_RESET    0x0002
 | 
			
		||||
 | 
			
		||||
// Card detect bits
 | 
			
		||||
#define SDC_CARD_INSERT_INT_EN  0x0001
 | 
			
		||||
#define SDC_CARD_INSERT_INT_REQ 0x0002
 | 
			
		||||
#define SDC_CARD_REMOVE_INT_EN  0x0004
 | 
			
		||||
#define SDC_CARD_REMOVE_INT_REQ 0x0008
 | 
			
		||||
 | 
			
		||||
// Command status bits
 | 
			
		||||
#define SDC_CMD_INT_STATUS_CC   0x0001  // Command complete
 | 
			
		||||
#define SDC_CMD_INT_STATUS_EI   0x0002  // Any error
 | 
			
		||||
#define SDC_CMD_INT_STATUS_CTE  0x0004  // Timeout
 | 
			
		||||
#define SDC_CMD_INT_STATUS_CCRC 0x0008  // CRC error
 | 
			
		||||
#define SDC_CMD_INT_STATUS_CIE  0x0010  // Command code check error
 | 
			
		||||
 | 
			
		||||
// Data status bits
 | 
			
		||||
#define SDC_DAT_INT_STATUS_TRS  0x0001  // Transfer complete
 | 
			
		||||
#define SDC_DAT_INT_STATUS_ERR  0x0002  // Any error
 | 
			
		||||
#define SDC_DAT_INT_STATUS_CTE  0x0004  // Timeout
 | 
			
		||||
#define SDC_DAT_INT_STATUS_CRC  0x0008  // CRC error
 | 
			
		||||
#define SDC_DAT_INT_STATUS_CFE  0x0010  // Data FIFO underrun or overrun
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define ERR_EOF             30
 | 
			
		||||
#define ERR_NOT_ELF         31
 | 
			
		||||
#define ERR_ELF_BITS        32
 | 
			
		||||
#define ERR_ELF_ENDIANNESS  33
 | 
			
		||||
#define ERR_CMD_CRC         34
 | 
			
		||||
#define ERR_CMD_CHECK       35
 | 
			
		||||
#define ERR_DATA_CRC        36
 | 
			
		||||
#define ERR_DATA_FIFO       37
 | 
			
		||||
#define ERR_BUF_ALIGNMENT   38
 | 
			
		||||
#define FR_DISK_ERR         39
 | 
			
		||||
#define FR_TIMEOUT          40
 | 
			
		||||
 | 
			
		||||
struct sdc_regs {
 | 
			
		||||
    volatile uint32_t argument;
 | 
			
		||||
    volatile uint32_t command;
 | 
			
		||||
    volatile uint32_t response1;
 | 
			
		||||
    volatile uint32_t response2;
 | 
			
		||||
    volatile uint32_t response3;
 | 
			
		||||
    volatile uint32_t response4;
 | 
			
		||||
    volatile uint32_t data_timeout;
 | 
			
		||||
    volatile uint32_t control;
 | 
			
		||||
    volatile uint32_t cmd_timeout;
 | 
			
		||||
    volatile uint32_t clock_divider;
 | 
			
		||||
    volatile uint32_t software_reset;
 | 
			
		||||
    volatile uint32_t power_control;
 | 
			
		||||
    volatile uint32_t capability;
 | 
			
		||||
    volatile uint32_t cmd_int_status;
 | 
			
		||||
    volatile uint32_t cmd_int_enable;
 | 
			
		||||
    volatile uint32_t dat_int_status;
 | 
			
		||||
    volatile uint32_t dat_int_enable;
 | 
			
		||||
    volatile uint32_t block_size;
 | 
			
		||||
    volatile uint32_t block_count;
 | 
			
		||||
    volatile uint32_t card_detect;
 | 
			
		||||
    volatile uint32_t res_50;
 | 
			
		||||
    volatile uint32_t res_54;
 | 
			
		||||
    volatile uint32_t res_58;
 | 
			
		||||
    volatile uint32_t res_5c;
 | 
			
		||||
    volatile uint64_t dma_addres;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_BLOCK_CNT 0x1000
 | 
			
		||||
 | 
			
		||||
#define SDC 0x00013000;
 | 
			
		||||
 | 
			
		||||
// static struct sdc_regs * const regs __attribute__((section(".rodata"))) = (struct sdc_regs *)0x00013000;
 | 
			
		||||
 | 
			
		||||
// static int errno __attribute__((section(".bss")));
 | 
			
		||||
// static DSTATUS drv_status __attribute__((section(".bss")));
 | 
			
		||||
// static BYTE card_type __attribute__((section(".bss")));
 | 
			
		||||
// static uint32_t response[4] __attribute__((section(".bss")));
 | 
			
		||||
// static int alt_mem __attribute__((section(".bss")));
 | 
			
		||||
 | 
			
		||||
/*static const char * errno_to_str(void) {
 | 
			
		||||
    switch (errno) {
 | 
			
		||||
    case ERR_EOF: return "Unexpected EOF";
 | 
			
		||||
    case ERR_NOT_ELF: return "Not an ELF file";
 | 
			
		||||
    case ERR_ELF_BITS: return "Wrong ELF word size";
 | 
			
		||||
    case ERR_ELF_ENDIANNESS: return "Wrong ELF endianness";
 | 
			
		||||
    case ERR_CMD_CRC: return "Command CRC error";
 | 
			
		||||
    case ERR_CMD_CHECK: return "Command code check error";
 | 
			
		||||
    case ERR_DATA_CRC: return "Data CRC error";
 | 
			
		||||
    case ERR_DATA_FIFO: return "Data FIFO error";
 | 
			
		||||
    case ERR_BUF_ALIGNMENT: return "Bad buffer alignment";
 | 
			
		||||
    case FR_DISK_ERR: return "Disk error";
 | 
			
		||||
    case FR_TIMEOUT: return "Timeout";
 | 
			
		||||
    }
 | 
			
		||||
    return "Unknown error code";
 | 
			
		||||
    }*/
 | 
			
		||||
 | 
			
		||||
static void usleep(unsigned us) {
 | 
			
		||||
    uintptr_t cycles0;
 | 
			
		||||
    uintptr_t cycles1;
 | 
			
		||||
    asm volatile ("csrr %0, 0xB00" : "=r" (cycles0));
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        asm volatile ("csrr %0, 0xB00" : "=r" (cycles1));
 | 
			
		||||
        if (cycles1 - cycles0 >= us * 100) break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sdc_cmd_finish(unsigned cmd, uint32_t * response) {
 | 
			
		||||
  struct sdc_regs * regs = (struct sdc_regs *)SDC;
 | 
			
		||||
  
 | 
			
		||||
    while (1) {
 | 
			
		||||
        unsigned status = regs->cmd_int_status;
 | 
			
		||||
        if (status) {
 | 
			
		||||
            // clear interrupts
 | 
			
		||||
            regs->cmd_int_status = 0;
 | 
			
		||||
            while (regs->software_reset != 0) {}
 | 
			
		||||
            if (status == SDC_CMD_INT_STATUS_CC) {
 | 
			
		||||
                // get response
 | 
			
		||||
                response[0] = regs->response1;
 | 
			
		||||
                response[1] = regs->response2;
 | 
			
		||||
                response[2] = regs->response3;
 | 
			
		||||
                response[3] = regs->response4;
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            /* errno = FR_DISK_ERR;
 | 
			
		||||
            if (status & SDC_CMD_INT_STATUS_CTE) errno = FR_TIMEOUT;
 | 
			
		||||
            if (status & SDC_CMD_INT_STATUS_CCRC) errno = ERR_CMD_CRC;
 | 
			
		||||
            if (status & SDC_CMD_INT_STATUS_CIE) errno = ERR_CMD_CHECK;*/
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sdc_data_finish(void) {
 | 
			
		||||
    int status;
 | 
			
		||||
    struct sdc_regs * regs = (struct sdc_regs *)SDC;
 | 
			
		||||
    
 | 
			
		||||
    while ((status = regs->dat_int_status) == 0) {}
 | 
			
		||||
    regs->dat_int_status = 0;
 | 
			
		||||
    while (regs->software_reset != 0) {}
 | 
			
		||||
 | 
			
		||||
    if (status == SDC_DAT_INT_STATUS_TRS) return 0;
 | 
			
		||||
    /* errno = FR_DISK_ERR;
 | 
			
		||||
    if (status & SDC_DAT_INT_STATUS_CTE) errno = FR_TIMEOUT;
 | 
			
		||||
    if (status & SDC_DAT_INT_STATUS_CRC) errno = ERR_DATA_CRC;
 | 
			
		||||
    if (status & SDC_DAT_INT_STATUS_CFE) errno = ERR_DATA_FIFO;*/
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) {
 | 
			
		||||
  struct sdc_regs * regs = (struct sdc_regs *)SDC;
 | 
			
		||||
  
 | 
			
		||||
  unsigned command = (cmd & 0x3f) << 8;
 | 
			
		||||
    switch (cmd) {
 | 
			
		||||
    case CMD0:
 | 
			
		||||
    case CMD4:
 | 
			
		||||
    case CMD15:
 | 
			
		||||
        // No responce
 | 
			
		||||
        break;
 | 
			
		||||
    case CMD11:
 | 
			
		||||
    case CMD13:
 | 
			
		||||
    case CMD16:
 | 
			
		||||
    case CMD17:
 | 
			
		||||
    case CMD18:
 | 
			
		||||
    case CMD19:
 | 
			
		||||
    case CMD23:
 | 
			
		||||
    case CMD24:
 | 
			
		||||
    case CMD25:
 | 
			
		||||
    case CMD27:
 | 
			
		||||
    case CMD30:
 | 
			
		||||
    case CMD32:
 | 
			
		||||
    case CMD33:
 | 
			
		||||
    case CMD42:
 | 
			
		||||
    case CMD55:
 | 
			
		||||
    case CMD56:
 | 
			
		||||
    case ACMD6:
 | 
			
		||||
        // R1
 | 
			
		||||
        command |= 1; // 48 bits
 | 
			
		||||
        command |= 1 << 3; // resp CRC
 | 
			
		||||
        command |= 1 << 4; // resp OPCODE
 | 
			
		||||
        break;
 | 
			
		||||
    case CMD7:
 | 
			
		||||
    case CMD12:
 | 
			
		||||
    case CMD20:
 | 
			
		||||
    case CMD28:
 | 
			
		||||
    case CMD29:
 | 
			
		||||
    case CMD38:
 | 
			
		||||
        // R1b
 | 
			
		||||
        command |= 1; // 48 bits
 | 
			
		||||
        command |= 1 << 2; // busy
 | 
			
		||||
        command |= 1 << 3; // resp CRC
 | 
			
		||||
        command |= 1 << 4; // resp OPCODE
 | 
			
		||||
        break;
 | 
			
		||||
    case CMD2:
 | 
			
		||||
    case CMD9:
 | 
			
		||||
    case CMD10:
 | 
			
		||||
         // R2
 | 
			
		||||
        command |= 2; // 136 bits
 | 
			
		||||
        command |= 1 << 3; // resp CRC
 | 
			
		||||
        break;
 | 
			
		||||
    case ACMD41:
 | 
			
		||||
        // R3
 | 
			
		||||
        command |= 1; // 48 bits
 | 
			
		||||
        break;
 | 
			
		||||
    case CMD3:
 | 
			
		||||
        // R6
 | 
			
		||||
        command |= 1; // 48 bits
 | 
			
		||||
        command |= 1 << 2; // busy
 | 
			
		||||
        command |= 1 << 3; // resp CRC
 | 
			
		||||
        command |= 1 << 4; // resp OPCODE
 | 
			
		||||
        break;
 | 
			
		||||
    case CMD8:
 | 
			
		||||
        // R7
 | 
			
		||||
        command |= 1; // 48 bits
 | 
			
		||||
        command |= 1 << 3; // resp CRC
 | 
			
		||||
        command |= 1 << 4; // resp OPCODE
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (blocks) {
 | 
			
		||||
        command |= 1 << 5;
 | 
			
		||||
        if ((intptr_t)buf & 3) {
 | 
			
		||||
          // errno = ERR_BUF_ALIGNMENT;
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        regs->dma_addres = (uint64_t)(intptr_t)buf;
 | 
			
		||||
        regs->block_size = 511;
 | 
			
		||||
        regs->block_count = blocks - 1;
 | 
			
		||||
        regs->data_timeout = 0x1FFFFFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    regs->command = command;
 | 
			
		||||
    regs->cmd_timeout = 0xFFFFF;
 | 
			
		||||
    regs->argument = arg;
 | 
			
		||||
 | 
			
		||||
    if (sdc_cmd_finish(cmd, response) < 0) return -1;
 | 
			
		||||
    if (blocks) return sdc_data_finish();
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define send_cmd(cmd, arg, response) send_data_cmd(cmd, arg, NULL, 0, response)
 | 
			
		||||
 | 
			
		||||
static BYTE ini_sd(void) {
 | 
			
		||||
  struct sdc_regs * regs = (struct sdc_regs *)SDC;
 | 
			
		||||
    unsigned rca;
 | 
			
		||||
    BYTE card_type;
 | 
			
		||||
    uint32_t response[4];
 | 
			
		||||
 | 
			
		||||
    /* Reset controller */
 | 
			
		||||
    regs->software_reset = 1;
 | 
			
		||||
    while ((regs->software_reset & 1) == 0) {}
 | 
			
		||||
 | 
			
		||||
    // This clock divider is meant to initialize the card at
 | 
			
		||||
    // 400kHz
 | 
			
		||||
 | 
			
		||||
    // 22MHz/400kHz = 55 (base 10) = 0x37 - 0x01 = 0x36
 | 
			
		||||
    regs->clock_divider = 0x36;
 | 
			
		||||
    regs->software_reset = 0;
 | 
			
		||||
    while (regs->software_reset) {}
 | 
			
		||||
    usleep(5000);
 | 
			
		||||
 | 
			
		||||
    card_type = 0;
 | 
			
		||||
    // drv_status = STA_NOINIT;
 | 
			
		||||
 | 
			
		||||
    if (regs->capability & SDC_CAPABILITY_SD_RESET) {
 | 
			
		||||
        /* Power cycle SD card */
 | 
			
		||||
        regs->control |= SDC_CONTROL_SD_RESET;
 | 
			
		||||
        usleep(1000000);
 | 
			
		||||
        regs->control &= ~SDC_CONTROL_SD_RESET;
 | 
			
		||||
        usleep(100000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Enter Idle state */
 | 
			
		||||
    send_cmd(CMD0, 0, response);
 | 
			
		||||
 | 
			
		||||
    card_type = CT_SD1;
 | 
			
		||||
    if (send_cmd(CMD8, 0x1AA, response) == 0) {
 | 
			
		||||
        if ((response[0] & 0xfff) != 0x1AA) {
 | 
			
		||||
            // errno = ERR_CMD_CHECK;
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        card_type = CT_SD2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Wait for leaving idle state (ACMD41 with HCS bit) */
 | 
			
		||||
    while (1) {
 | 
			
		||||
        /* ACMD41, Set Operating Conditions: Host High Capacity & 3.3V */
 | 
			
		||||
      if (send_cmd(CMD55, 0, response) < 0 || send_cmd(ACMD41, 0x40300000, response) < 0) return -1;
 | 
			
		||||
        if (response[0] & (1 << 31)) {
 | 
			
		||||
            if (response[0] & (1 << 30)) card_type |= CT_BLOCK;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Enter Identification state */
 | 
			
		||||
    if (send_cmd(CMD2, 0, response) < 0) return -1;
 | 
			
		||||
 | 
			
		||||
    /* Get RCA (Relative Card Address) */
 | 
			
		||||
    rca = 0x1234;
 | 
			
		||||
    if (send_cmd(CMD3, rca << 16, response) < 0) return -1;
 | 
			
		||||
    rca = response[0] >> 16;
 | 
			
		||||
 | 
			
		||||
    /* Select card */
 | 
			
		||||
    if (send_cmd(CMD7, rca << 16, response) < 0) return -1;
 | 
			
		||||
 | 
			
		||||
    /* Clock 25MHz */
 | 
			
		||||
    // 22Mhz/2 = 11Mhz
 | 
			
		||||
    regs->clock_divider = 1;
 | 
			
		||||
    usleep(10000);
 | 
			
		||||
 | 
			
		||||
    /* Bus width 1-bit */
 | 
			
		||||
    regs->control = 0;
 | 
			
		||||
    if (send_cmd(CMD55, rca << 16, response) < 0 || send_cmd(ACMD6, 0, response) < 0) return -1;
 | 
			
		||||
 | 
			
		||||
    /* Set R/W block length to 512 */
 | 
			
		||||
    if (send_cmd(CMD16, 512, response) < 0) return -1;
 | 
			
		||||
 | 
			
		||||
    // drv_status &= ~STA_NOINIT;
 | 
			
		||||
    return card_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) {
 | 
			
		||||
 | 
			
		||||
  /* This is not needed. This has everything to do with the FAT
 | 
			
		||||
     filesystem stuff that I'm not including. All I need to do is
 | 
			
		||||
     initialize the SD card and read from it. Anything in here that is
 | 
			
		||||
     checking for potential errors, I'm going to have to temporarily
 | 
			
		||||
     do without.
 | 
			
		||||
   */
 | 
			
		||||
  // if (!count) return RES_PARERR;
 | 
			
		||||
    /* if (drv_status & STA_NOINIT) return RES_NOTRDY; */
 | 
			
		||||
 | 
			
		||||
  uint32_t response[4];
 | 
			
		||||
  struct sdc_regs * regs = (struct sdc_regs *)SDC;
 | 
			
		||||
  
 | 
			
		||||
    /* Convert LBA to byte address if needed */
 | 
			
		||||
    if (!(card_type & CT_BLOCK)) sector *= 512;
 | 
			
		||||
    while (count > 0) {
 | 
			
		||||
        UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count;
 | 
			
		||||
        unsigned bytes = bcnt * 512;
 | 
			
		||||
        if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1;
 | 
			
		||||
        if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1;
 | 
			
		||||
        sector += (card_type & CT_BLOCK) ? bcnt : bytes;
 | 
			
		||||
        count -= bcnt;
 | 
			
		||||
        buf += bytes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) {
 | 
			
		||||
  BYTE card_type;
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  
 | 
			
		||||
  card_type = ini_sd();
 | 
			
		||||
 | 
			
		||||
  // BYTE * buf = (BYTE *)Dst;
 | 
			
		||||
    
 | 
			
		||||
  // if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/;
 | 
			
		||||
  
 | 
			
		||||
  ret = gpt_load_partitions(card_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
int main() {
 | 
			
		||||
  ini_sd();
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
							
								
								
									
										26
									
								
								fpga/zsbl/boot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								fpga/zsbl/boot.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
#ifndef WALLYBOOT
 | 
			
		||||
#define WALLYBOOT 10000
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
typedef unsigned int    UINT;   /* int must be 16-bit or 32-bit */
 | 
			
		||||
typedef unsigned char   BYTE;   /* char must be 8-bit */
 | 
			
		||||
typedef uint16_t        WORD;   /* 16-bit unsigned integer */
 | 
			
		||||
typedef uint32_t        DWORD;  /* 32-bit unsigned integer */
 | 
			
		||||
typedef uint64_t        QWORD;  /* 64-bit unsigned integer */
 | 
			
		||||
typedef WORD            WCHAR;
 | 
			
		||||
 | 
			
		||||
typedef QWORD LBA_t;
 | 
			
		||||
 | 
			
		||||
// Define memory locations of boot images =====================
 | 
			
		||||
// These locations are copied from the generic configuration
 | 
			
		||||
// of OpenSBI. These addresses can be found in:
 | 
			
		||||
// buildroot/output/build/opensbi-0.9/platform/generic/config.mk
 | 
			
		||||
#define FDT_ADDRESS 0x87000000          // FW_JUMP_FDT_ADDR
 | 
			
		||||
#define OPENSBI_ADDRESS 0x80000000      // FW_TEXT_START
 | 
			
		||||
#define KERNEL_ADDRESS 0x80200000       // FW_JUMP_ADDR
 | 
			
		||||
 | 
			
		||||
// Export disk_read
 | 
			
		||||
int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type);
 | 
			
		||||
 | 
			
		||||
#endif // WALLYBOOT
 | 
			
		||||
 | 
			
		||||
@ -1,40 +0,0 @@
 | 
			
		||||
///////////////////////////////////////////
 | 
			
		||||
// copyFlash.sv
 | 
			
		||||
//
 | 
			
		||||
// Written: Ross Thompson September 25, 2021
 | 
			
		||||
// Modified: 
 | 
			
		||||
//
 | 
			
		||||
// Purpose: copies flash card into memory
 | 
			
		||||
// 
 | 
			
		||||
// A component of the Wally configurable RISC-V project.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
 | 
			
		||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
 | 
			
		||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
 | 
			
		||||
// is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 | 
			
		||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 | 
			
		||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 | 
			
		||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
///////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#include "sdcDriver.h"
 | 
			
		||||
 | 
			
		||||
void copyFlash(long int blockAddr, long int * Dst, int numBlocks) {
 | 
			
		||||
 | 
			
		||||
  setSDCCLK(4); // must be even, 1 gives no division.
 | 
			
		||||
  waitInitSDC();
 | 
			
		||||
 | 
			
		||||
  int index;
 | 
			
		||||
 | 
			
		||||
  for(index = 0; index < numBlocks; index++) {
 | 
			
		||||
    copySDC512(blockAddr+(index*512), Dst+(index*512/8));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										137
									
								
								fpga/zsbl/gpt.c
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								fpga/zsbl/gpt.c
									
									
									
									
									
								
							@ -1,119 +1,46 @@
 | 
			
		||||
#include "gpt.h"
 | 
			
		||||
 | 
			
		||||
#include "sdcDriver.h"
 | 
			
		||||
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
#include "boot.h"
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
int gpt_find_boot_partition(long int* dest, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
  //int ret = init_sd();
 | 
			
		||||
  int ret;
 | 
			
		||||
  setSDCCLK(4); // must be even, 1 gives no division.
 | 
			
		||||
  waitInitSDC();
 | 
			
		||||
  ret = 0;
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        print_uart("could not initialize sd... exiting\r\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
/* PSUEDOCODE
 | 
			
		||||
 | 
			
		||||
    print_uart("sd initialized!\r\n");
 | 
			
		||||
   Need to load GPT LBA 1 and read through the partition entries.
 | 
			
		||||
   I need to find each of the relevant partition entries, possibly
 | 
			
		||||
   by their partition names.
 | 
			
		||||
   
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
    // load LBA1
 | 
			
		||||
    size_t block_size = 512/8;
 | 
			
		||||
    long int lba1_buf[block_size];
 | 
			
		||||
int gpt_load_partitions(BYTE card_type) {
 | 
			
		||||
  // In this version of the GPT partition code
 | 
			
		||||
  // I'm going to assume that the SD card is already initialized.
 | 
			
		||||
 | 
			
		||||
    //int res = sd_copy(lba1_buf, 1, 1);
 | 
			
		||||
    int res;
 | 
			
		||||
    copySDC512(1, lba1_buf);
 | 
			
		||||
    res = 0;
 | 
			
		||||
  // size_t block_size = 512/8;
 | 
			
		||||
  // long int lba1_buf[block_size];
 | 
			
		||||
 | 
			
		||||
    if (res != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_uart("SD card failed!\r\n");
 | 
			
		||||
        print_uart("sd copy return value: ");
 | 
			
		||||
        print_uart_addr(res);
 | 
			
		||||
        print_uart("\r\n");
 | 
			
		||||
        return -2;
 | 
			
		||||
    }
 | 
			
		||||
  BYTE lba1_buf[512];
 | 
			
		||||
  
 | 
			
		||||
  int ret = 0;
 | 
			
		||||
  //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */);
 | 
			
		||||
  ret = disk_read(lba1_buf, 1, 1, card_type);
 | 
			
		||||
 | 
			
		||||
    gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;
 | 
			
		||||
  /* Possible error handling with UART message
 | 
			
		||||
  if ( ret != 0 ) {
 | 
			
		||||
    
 | 
			
		||||
  }*/
 | 
			
		||||
 | 
			
		||||
    print_uart("gpt partition table header:");
 | 
			
		||||
    print_uart("\r\n\tsignature:\t");
 | 
			
		||||
    print_uart_addr(lba1->signature);
 | 
			
		||||
    print_uart("\r\n\trevision:\t");
 | 
			
		||||
    print_uart_int(lba1->revision);
 | 
			
		||||
    print_uart("\r\n\tsize:\t\t");
 | 
			
		||||
    print_uart_int(lba1->header_size);
 | 
			
		||||
    print_uart("\r\n\tcrc_header:\t");
 | 
			
		||||
    print_uart_int(lba1->crc_header);
 | 
			
		||||
    print_uart("\r\n\treserved:\t");
 | 
			
		||||
    print_uart_int(lba1->reserved);
 | 
			
		||||
    print_uart("\r\n\tcurrent lba:\t");
 | 
			
		||||
    print_uart_addr(lba1->current_lba);
 | 
			
		||||
    print_uart("\r\n\tbackup lda:\t");
 | 
			
		||||
    print_uart_addr(lba1->backup_lba);
 | 
			
		||||
    print_uart("\r\n\tpartition entries lba:   \t");
 | 
			
		||||
    print_uart_addr(lba1->partition_entries_lba);
 | 
			
		||||
    print_uart("\r\n\tnumber partition entries:\t");
 | 
			
		||||
    print_uart_int(lba1->nr_partition_entries);
 | 
			
		||||
    print_uart("\r\n\tsize partition entries:  \t");
 | 
			
		||||
    print_uart_int(lba1->size_partition_entry);
 | 
			
		||||
    print_uart("\r\n");
 | 
			
		||||
  gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;
 | 
			
		||||
 | 
			
		||||
    long int lba2_buf[block_size];
 | 
			
		||||
  BYTE lba2_buf[512];
 | 
			
		||||
  ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1, card_type);
 | 
			
		||||
 | 
			
		||||
    //res = sd_copy(lba2_buf, lba1->partition_entries_lba, 1);
 | 
			
		||||
    copySDC512(lba1->partition_entries_lba, lba2_buf);
 | 
			
		||||
    res = 0;
 | 
			
		||||
  // Load parition entries for the relevant boot partitions.
 | 
			
		||||
  partition_entries_t *fdt = (partition_entries_t *)(lba2_buf);
 | 
			
		||||
  partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128);
 | 
			
		||||
  partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256);
 | 
			
		||||
 | 
			
		||||
    if (res != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_uart("SD card failed!\r\n");
 | 
			
		||||
        print_uart("sd copy return value: ");
 | 
			
		||||
        print_uart_addr(res);
 | 
			
		||||
        print_uart("\r\n");
 | 
			
		||||
        return -2;
 | 
			
		||||
    }
 | 
			
		||||
  ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1, card_type);
 | 
			
		||||
  ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1, card_type);
 | 
			
		||||
  ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1, card_type);
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < 4; i++)
 | 
			
		||||
    {
 | 
			
		||||
        partition_entries_t *part_entry = (partition_entries_t *)(lba2_buf + (i * 128));
 | 
			
		||||
        print_uart("gpt partition entry ");
 | 
			
		||||
        print_uart_byte(i);
 | 
			
		||||
        print_uart("\r\n\tpartition type guid:\t");
 | 
			
		||||
        for (int j = 0; j < 16; j++)
 | 
			
		||||
            print_uart_byte(part_entry->partition_type_guid[j]);
 | 
			
		||||
        print_uart("\r\n\tpartition guid:     \t");
 | 
			
		||||
        for (int j = 0; j < 16; j++)
 | 
			
		||||
            print_uart_byte(part_entry->partition_guid[j]);
 | 
			
		||||
        print_uart("\r\n\tfirst lba:\t");
 | 
			
		||||
        print_uart_addr(part_entry->first_lba);
 | 
			
		||||
        print_uart("\r\n\tlast lba:\t");
 | 
			
		||||
        print_uart_addr(part_entry->last_lba);
 | 
			
		||||
        print_uart("\r\n\tattributes:\t");
 | 
			
		||||
        print_uart_addr(part_entry->attributes);
 | 
			
		||||
        print_uart("\r\n\tname:\t");
 | 
			
		||||
        for (int j = 0; j < 72; j++)
 | 
			
		||||
            print_uart_byte(part_entry->name[j]);
 | 
			
		||||
        print_uart("\r\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partition_entries_t *boot = (partition_entries_t *)(lba2_buf);
 | 
			
		||||
    print_uart("copying boot image ");
 | 
			
		||||
    //res = sd_copy(dest, boot->first_lba, boot->last_lba - boot->first_lba + 1);
 | 
			
		||||
    copyFlash(boot->first_lba, dest, boot->last_lba - boot->first_lba + 1);
 | 
			
		||||
 | 
			
		||||
    if (res != 0)
 | 
			
		||||
    {
 | 
			
		||||
        print_uart("SD card failed!\r\n");
 | 
			
		||||
        print_uart("sd copy return value: ");
 | 
			
		||||
        print_uart_addr(res);
 | 
			
		||||
        print_uart("\r\n");
 | 
			
		||||
        return -2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    print_uart(" done!\r\n");
 | 
			
		||||
    return 0;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "boot.h"
 | 
			
		||||
 | 
			
		||||
// LBA 0: Protective MBR
 | 
			
		||||
// ignored here
 | 
			
		||||
@ -36,4 +37,4 @@ typedef struct partition_entries
 | 
			
		||||
} partition_entries_t;
 | 
			
		||||
 | 
			
		||||
// Find boot partition and load it to the destination
 | 
			
		||||
int gpt_find_boot_partition(long int* dest, uint32_t size);
 | 
			
		||||
int gpt_load_partitions(BYTE card_type);
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ SECTIONS
 | 
			
		||||
{
 | 
			
		||||
  /* Read-only sections, merged into text segment: */
 | 
			
		||||
  /* init segment to ensure we get a consistent start routine*/
 | 
			
		||||
  . = 0x0000000000000000; 
 | 
			
		||||
  . = 0x0000000000001000; 
 | 
			
		||||
  . = ALIGN(0x0); 
 | 
			
		||||
  .init : {  
 | 
			
		||||
  	*(.init) 
 | 
			
		||||
@ -72,6 +72,7 @@ SECTIONS
 | 
			
		||||
  PROVIDE (__etext = .);
 | 
			
		||||
  PROVIDE (_etext = .);
 | 
			
		||||
  PROVIDE (etext = .);
 | 
			
		||||
  . = 0x0000000000002000;
 | 
			
		||||
  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
 | 
			
		||||
  .rodata1        : { *(.rodata1) }
 | 
			
		||||
  .sdata2         :
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
#include "sdcDriver.h"
 | 
			
		||||
#include "gpt.h"
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    init_uart(30000000, 115200);
 | 
			
		||||
    print_uart("Hello World!\r\n");
 | 
			
		||||
 | 
			
		||||
    int res = gpt_find_boot_partition((long int *)0x80000000UL, 2 * 16384);
 | 
			
		||||
 | 
			
		||||
    if (res == 0)
 | 
			
		||||
    {
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (1)
 | 
			
		||||
    {
 | 
			
		||||
        // do nothing
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void handle_trap(void)
 | 
			
		||||
{
 | 
			
		||||
    // print_uart("trap\r\n");
 | 
			
		||||
}
 | 
			
		||||
@ -1,69 +0,0 @@
 | 
			
		||||
///////////////////////////////////////////
 | 
			
		||||
// SDC.sv
 | 
			
		||||
//
 | 
			
		||||
// Written: Rose Thompson September 25, 2021
 | 
			
		||||
// Modified: 
 | 
			
		||||
//
 | 
			
		||||
// Purpose: driver for sdc reader.
 | 
			
		||||
// 
 | 
			
		||||
// A component of the Wally configurable RISC-V project.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
 | 
			
		||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
 | 
			
		||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
 | 
			
		||||
// is furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 | 
			
		||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 | 
			
		||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 | 
			
		||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
///////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "sdcDriver.h"
 | 
			
		||||
 | 
			
		||||
#define SDC_MAIL_BOX 0x12100
 | 
			
		||||
 | 
			
		||||
void copySDC512(long int blockAddr, long int * Dst) {
 | 
			
		||||
 | 
			
		||||
  waitInitSDC();
 | 
			
		||||
 | 
			
		||||
  volatile long int * mailBoxAddr;
 | 
			
		||||
  volatile int * mailBoxCmd;
 | 
			
		||||
  volatile int * mailBoxStatus;
 | 
			
		||||
  volatile long int * mailBoxReadData;
 | 
			
		||||
  mailBoxStatus = (int *) (SDC_MAIL_BOX + 0x4);  
 | 
			
		||||
  mailBoxCmd = (int *) (SDC_MAIL_BOX + 0x8);
 | 
			
		||||
  mailBoxAddr = (long int *) (SDC_MAIL_BOX + 0x10);
 | 
			
		||||
  mailBoxReadData = (long int *) (SDC_MAIL_BOX + 0x18);  
 | 
			
		||||
  
 | 
			
		||||
  // write the SDC address register with the blockAddr
 | 
			
		||||
  *mailBoxAddr = blockAddr;
 | 
			
		||||
  *mailBoxCmd = 0x4;
 | 
			
		||||
 | 
			
		||||
  // wait until the mailbox has valid data
 | 
			
		||||
  // this occurs when status[1] = 0
 | 
			
		||||
  while((*mailBoxStatus & 0x2) == 0x2);
 | 
			
		||||
 | 
			
		||||
  int index;
 | 
			
		||||
  for(index = 0; index < 512/8; index++) {
 | 
			
		||||
    Dst[index] = *mailBoxReadData;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
volatile void waitInitSDC(){
 | 
			
		||||
  volatile int * mailBoxStatus;
 | 
			
		||||
  mailBoxStatus = (int *) (SDC_MAIL_BOX + 0x4);
 | 
			
		||||
  while((*mailBoxStatus & 0x1) != 0x1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void setSDCCLK(int divider){
 | 
			
		||||
  divider = (1 - (divider >> 1));
 | 
			
		||||
  volatile int * mailBoxCLK;
 | 
			
		||||
  mailBoxCLK = (int *) (SDC_MAIL_BOX + 0x0);
 | 
			
		||||
  *mailBoxCLK = divider;
 | 
			
		||||
}
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
#ifndef __SDCDRIVER_H
 | 
			
		||||
#define __SDCDRIVER_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void copySDC512(long int, long int *);
 | 
			
		||||
volatile void waitInitSDC();
 | 
			
		||||
void setSDCCLK(int);
 | 
			
		||||
void copyFlash(long int, long int *, int);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// The hart that non-SMP tests should run on
 | 
			
		||||
#ifndef NONSMP_HART
 | 
			
		||||
#define NONSMP_HART 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The maximum number of HARTs this code supports
 | 
			
		||||
#define CLINT_CTRL_ADDR 0x2000000
 | 
			
		||||
#ifndef MAX_HARTS
 | 
			
		||||
#define MAX_HARTS 256
 | 
			
		||||
#endif
 | 
			
		||||
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS * 4)
 | 
			
		||||
 | 
			
		||||
/* If your test needs to temporarily block multiple-threads, do this:
 | 
			
		||||
 *    smp_pause(reg1, reg2)
 | 
			
		||||
 *    ... single-threaded work ...
 | 
			
		||||
 *    smp_resume(reg1, reg2)
 | 
			
		||||
 *    ... multi-threaded work ...
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define smp_pause(reg1, reg2) \
 | 
			
		||||
    li reg2, 0x8;             \
 | 
			
		||||
    csrw mie, reg2;           \
 | 
			
		||||
    li reg1, NONSMP_HART;     \
 | 
			
		||||
    csrr reg2, mhartid;       \
 | 
			
		||||
    bne reg1, reg2, 42f
 | 
			
		||||
 | 
			
		||||
#define smp_resume(reg1, reg2)   \
 | 
			
		||||
    li reg1, CLINT_CTRL_ADDR;    \
 | 
			
		||||
    41:;                         \
 | 
			
		||||
    li reg2, 1;                  \
 | 
			
		||||
    sw reg2, 0(reg1);            \
 | 
			
		||||
    addi reg1, reg1, 4;          \
 | 
			
		||||
    li reg2, CLINT_END_HART_IPI; \
 | 
			
		||||
    blt reg1, reg2, 41b;         \
 | 
			
		||||
    42:;                         \
 | 
			
		||||
    wfi;                         \
 | 
			
		||||
    csrr reg2, mip;              \
 | 
			
		||||
    andi reg2, reg2, 0x8;        \
 | 
			
		||||
    beqz reg2, 42b;              \
 | 
			
		||||
    li reg1, CLINT_CTRL_ADDR;    \
 | 
			
		||||
    csrr reg2, mhartid;          \
 | 
			
		||||
    slli reg2, reg2, 2;          \
 | 
			
		||||
    add reg2, reg2, reg1;        \
 | 
			
		||||
    sw zero, 0(reg2);            \
 | 
			
		||||
    41:;                         \
 | 
			
		||||
    lw reg2, 0(reg1);            \
 | 
			
		||||
    bnez reg2, 41b;              \
 | 
			
		||||
    addi reg1, reg1, 4;          \
 | 
			
		||||
    li reg2, CLINT_END_HART_IPI; \
 | 
			
		||||
    blt reg1, reg2, 41b
 | 
			
		||||
@ -1,91 +0,0 @@
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
 | 
			
		||||
void write_reg_u8(uintptr_t addr, uint8_t value)
 | 
			
		||||
{
 | 
			
		||||
    volatile uint8_t *loc_addr = (volatile uint8_t *)addr;
 | 
			
		||||
    *loc_addr = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t read_reg_u8(uintptr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return *(volatile uint8_t *)addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_transmit_empty()
 | 
			
		||||
{
 | 
			
		||||
    return read_reg_u8(UART_LINE_STATUS) & 0x20;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void write_serial(char a)
 | 
			
		||||
{
 | 
			
		||||
    while (is_transmit_empty() == 0) {};
 | 
			
		||||
 | 
			
		||||
    write_reg_u8(UART_THR, a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_uart(uint32_t freq, uint32_t baud)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t divisor = freq / (baud << 4);
 | 
			
		||||
 | 
			
		||||
    write_reg_u8(UART_INTERRUPT_ENABLE, 0x00); // Disable all interrupts
 | 
			
		||||
    write_reg_u8(UART_LINE_CONTROL, 0x80);     // Enable DLAB (set baud rate divisor)
 | 
			
		||||
    write_reg_u8(UART_DLAB_LSB, divisor);         // divisor (lo byte)
 | 
			
		||||
    write_reg_u8(UART_DLAB_MSB, (divisor >> 8) & 0xFF);  // divisor (hi byte)
 | 
			
		||||
    write_reg_u8(UART_LINE_CONTROL, 0x03);     // 8 bits, no parity, one stop bit
 | 
			
		||||
    write_reg_u8(UART_FIFO_CONTROL, 0xC7);     // Enable FIFO, clear them, with 14-byte threshold
 | 
			
		||||
    write_reg_u8(UART_MODEM_CONTROL, 0x20);    // Autoflow mode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_uart(const char *str)
 | 
			
		||||
{
 | 
			
		||||
    const char *cur = &str[0];
 | 
			
		||||
    while (*cur != '\0')
 | 
			
		||||
    {
 | 
			
		||||
        write_serial((uint8_t)*cur);
 | 
			
		||||
        ++cur;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t bin_to_hex_table[16] = {
 | 
			
		||||
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
 | 
			
		||||
 | 
			
		||||
void bin_to_hex(uint8_t inp, uint8_t res[2])
 | 
			
		||||
{
 | 
			
		||||
    res[1] = bin_to_hex_table[inp & 0xf];
 | 
			
		||||
    res[0] = bin_to_hex_table[(inp >> 4) & 0xf];
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_uart_int(uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 3; i > -1; i--)
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t cur = (addr >> (i * 8)) & 0xff;
 | 
			
		||||
        uint8_t hex[2];
 | 
			
		||||
        bin_to_hex(cur, hex);
 | 
			
		||||
        write_serial(hex[0]);
 | 
			
		||||
        write_serial(hex[1]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_uart_addr(uint64_t addr)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 7; i > -1; i--)
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t cur = (addr >> (i * 8)) & 0xff;
 | 
			
		||||
        uint8_t hex[2];
 | 
			
		||||
        bin_to_hex(cur, hex);
 | 
			
		||||
        write_serial(hex[0]);
 | 
			
		||||
        write_serial(hex[1]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_uart_byte(uint8_t byte)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t hex[2];
 | 
			
		||||
    bin_to_hex(byte, hex);
 | 
			
		||||
    write_serial(hex[0]);
 | 
			
		||||
    write_serial(hex[1]);
 | 
			
		||||
}
 | 
			
		||||
@ -1,27 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define UART_BASE 0x10000000
 | 
			
		||||
 | 
			
		||||
#define UART_RBR UART_BASE + 0
 | 
			
		||||
#define UART_THR UART_BASE + 0
 | 
			
		||||
#define UART_INTERRUPT_ENABLE UART_BASE + 4
 | 
			
		||||
#define UART_INTERRUPT_IDENT UART_BASE + 8
 | 
			
		||||
#define UART_FIFO_CONTROL UART_BASE + 8
 | 
			
		||||
#define UART_LINE_CONTROL UART_BASE + 12
 | 
			
		||||
#define UART_MODEM_CONTROL UART_BASE + 16
 | 
			
		||||
#define UART_LINE_STATUS UART_BASE + 20
 | 
			
		||||
#define UART_MODEM_STATUS UART_BASE + 24
 | 
			
		||||
#define UART_DLAB_LSB UART_BASE + 0
 | 
			
		||||
#define UART_DLAB_MSB UART_BASE + 4
 | 
			
		||||
 | 
			
		||||
void init_uart();
 | 
			
		||||
 | 
			
		||||
void print_uart(const char* str);
 | 
			
		||||
 | 
			
		||||
void print_uart_int(uint32_t addr);
 | 
			
		||||
 | 
			
		||||
void print_uart_addr(uint64_t addr);
 | 
			
		||||
 | 
			
		||||
void print_uart_byte(uint8_t byte);
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user