From e3b9008abbfe6f0ec335964b633a412768071975 Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Thu, 11 Mar 2021 00:10:32 +0100 Subject: [PATCH] libsc64 start --- fw/SummerCart64.qsf | 2 +- fw/rtl/cart/cart_control.v | 57 ++++++--- fw/rtl/n64/n64_bank_decoder.v | 14 +-- fw/rtl/top.v | 6 +- sw/bootloader/Makefile | 4 +- sw/bootloader/build.sh | 14 +-- sw/libsc64/.gitignore | 2 + sw/libsc64/Makefile.common | 37 ++++++ sw/libsc64/Makefile.libdragon | 11 ++ sw/libsc64/Makefile.libultra | 9 ++ sw/libsc64/build.sh | 11 ++ sw/libsc64/inc/boot.h | 31 +++++ sw/libsc64/inc/control.h | 20 ++++ sw/libsc64/inc/gpio.h | 26 +++++ sw/libsc64/inc/helpers.h | 15 +++ sw/libsc64/inc/init.h | 8 ++ sw/libsc64/inc/io_dma.h | 18 +++ sw/libsc64/inc/libsc64.h | 15 +++ sw/libsc64/inc/registers.h | 178 ++++++++++++++++++++++++++++ sw/libsc64/inc/save.h | 31 +++++ sw/libsc64/inc/sd.h | 34 ++++++ sw/libsc64/inc/usb.h | 8 ++ sw/libsc64/src/boot.c | 17 +++ sw/libsc64/src/control.c | 29 +++++ sw/libsc64/src/gpio.c | 63 ++++++++++ sw/libsc64/src/helpers.c | 24 ++++ sw/libsc64/src/init.c | 8 ++ sw/libsc64/src/io_dma.c | 69 +++++++++++ sw/libsc64/src/save.c | 157 +++++++++++++++++++++++++ sw/libsc64/src/sd.c | 211 ++++++++++++++++++++++++++++++++++ sw/libsc64/src/usb.c | 1 + 31 files changed, 1090 insertions(+), 40 deletions(-) create mode 100644 sw/libsc64/.gitignore create mode 100644 sw/libsc64/Makefile.common create mode 100644 sw/libsc64/Makefile.libdragon create mode 100644 sw/libsc64/Makefile.libultra create mode 100644 sw/libsc64/build.sh create mode 100644 sw/libsc64/inc/boot.h create mode 100644 sw/libsc64/inc/control.h create mode 100644 sw/libsc64/inc/gpio.h create mode 100644 sw/libsc64/inc/helpers.h create mode 100644 sw/libsc64/inc/init.h create mode 100644 sw/libsc64/inc/io_dma.h create mode 100644 sw/libsc64/inc/libsc64.h create mode 100644 sw/libsc64/inc/registers.h create mode 100644 sw/libsc64/inc/save.h create mode 100644 sw/libsc64/inc/sd.h create mode 100644 sw/libsc64/inc/usb.h create mode 100644 sw/libsc64/src/boot.c create mode 100644 sw/libsc64/src/control.c create mode 100644 sw/libsc64/src/gpio.c create mode 100644 sw/libsc64/src/helpers.c create mode 100644 sw/libsc64/src/init.c create mode 100644 sw/libsc64/src/io_dma.c create mode 100644 sw/libsc64/src/save.c create mode 100644 sw/libsc64/src/sd.c create mode 100644 sw/libsc64/src/usb.c diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 9229242..d4d363b 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -19,7 +19,7 @@ # # Quartus Prime # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition -# Date created = 00:41:07 March 01, 2021 +# Date created = 23:48:45 March 10, 2021 # # -------------------------------------------------------------------------- # # diff --git a/fw/rtl/cart/cart_control.v b/fw/rtl/cart/cart_control.v index 794f7d0..9401b7e 100644 --- a/fw/rtl/cart/cart_control.v +++ b/fw/rtl/cart/cart_control.v @@ -23,7 +23,7 @@ module cart_control ( output reg o_eeprom_enable, output reg o_eeprom_16k_mode, - output reg o_n64_reset_btn, + inout [7:0] io_gpio, input i_debug_ready, @@ -57,7 +57,7 @@ module cart_control ( localparam [3:0] REG_USB_DMA_ADDR = 4'd5; localparam [3:0] REG_USB_DMA_LEN = 4'd6; localparam [3:0] REG_DDIPL_ADDR = 4'd7; - localparam [3:0] REG_SRAM_ADDR = 4'd8; + localparam [3:0] REG_SAVE_ADDR = 4'd8; localparam [10:0] MEM_USB_FIFO_BASE = 11'h400; @@ -77,6 +77,11 @@ module cart_control ( reg [15:0] r_bootloader; reg r_skip_bootloader; + reg r_sram_768k_mode; + reg [7:0] r_gpio_o; + reg [7:0] r_gpio_i; + reg [7:0] r_gpio_dir; + reg [7:0] r_gpio_od; // Bus controller @@ -104,7 +109,6 @@ module cart_control ( o_eeprom_pi_enable <= 1'b0; o_eeprom_enable <= 1'b0; o_eeprom_16k_mode <= 1'b0; - o_n64_reset_btn <= 1'b1; o_ddipl_address <= 24'hEF_8000; o_save_address <= 24'hFF_8000; o_debug_dma_bank <= 4'd1; @@ -112,22 +116,27 @@ module cart_control ( o_debug_dma_length <= 20'd0; r_bootloader <= 16'h0000; r_skip_bootloader <= 1'b0; + r_sram_768k_mode <= 1'b0; + r_gpio_o <= 8'h00; + r_gpio_dir <= 8'h00; + r_gpio_od <= 8'h00; end else begin if (i_request && i_write && !o_busy) begin case (i_address[3:0]) REG_SCR: begin { r_skip_bootloader, - o_flashram_enable, - o_sram_enable, o_sd_enable, + o_flashram_enable, + r_sram_768k_mode, + o_sram_enable, o_eeprom_pi_enable, o_eeprom_16k_mode, o_eeprom_enable, o_ddipl_enable, - o_rom_switch, - o_sdram_writable - } <= {i_data[10:9], i_data[7:0]}; + o_sdram_writable, + o_rom_switch + } <= i_data[10:0]; end REG_BOOT: begin @@ -135,7 +144,7 @@ module cart_control ( end REG_GPIO: begin - o_n64_reset_btn <= ~i_data[0]; + {r_gpio_od, r_gpio_dir, r_gpio_o} <= {i_data[31:16], i_data[7:0]}; end REG_USB_SCR: begin @@ -154,7 +163,7 @@ module cart_control ( o_ddipl_address <= i_data[25:2]; end - REG_SRAM_ADDR: begin + REG_SAVE_ADDR: begin o_save_address <= i_data[25:2]; end @@ -165,7 +174,6 @@ module cart_control ( if (!r_reset_ff2 || !r_nmi_ff2) begin o_sdram_writable <= 1'b0; o_rom_switch <= r_skip_bootloader; - o_n64_reset_btn <= 1'b1; o_debug_fifo_flush <= 1'b1; end end @@ -185,16 +193,16 @@ module cart_control ( REG_SCR: begin o_data[10:0] <= { r_skip_bootloader, - o_flashram_enable, - 1'b0, - o_sram_enable, o_sd_enable, + o_flashram_enable, + r_sram_768k_mode, + o_sram_enable, o_eeprom_pi_enable, o_eeprom_16k_mode, o_eeprom_enable, o_ddipl_enable, - o_rom_switch, - o_sdram_writable + o_sdram_writable, + o_rom_switch }; end @@ -207,7 +215,7 @@ module cart_control ( end REG_GPIO: begin - o_data[2:0] <= {r_nmi_ff2, r_reset_ff2, ~o_n64_reset_btn}; + o_data[31:0] <= {r_gpio_od, r_gpio_dir, io_gpio, r_gpio_o}; end REG_USB_SCR: begin @@ -218,7 +226,7 @@ module cart_control ( o_data[25:0] <= {o_ddipl_address, 2'b00}; end - REG_SRAM_ADDR: begin + REG_SAVE_ADDR: begin o_data[25:0] <= {o_save_address, 2'b00}; end @@ -231,4 +239,17 @@ module cart_control ( end end + + // GPIO logic + + always @(*) begin + for (integer i = 0; i < 8; i = i + 1) begin + if (r_gpio_dir[i] && (!r_gpio_od[i] || (r_gpio_od[i] && !r_gpio_o[i]))) begin + io_gpio[i] = r_gpio_o[i]; + end else begin + io_gpio[i] = 1'bZ; + end + end + end + endmodule diff --git a/fw/rtl/n64/n64_bank_decoder.v b/fw/rtl/n64/n64_bank_decoder.v index 3a25a3c..08375bb 100644 --- a/fw/rtl/n64/n64_bank_decoder.v +++ b/fw/rtl/n64/n64_bank_decoder.v @@ -54,19 +54,19 @@ module n64_bank_decoder ( o_prefetch <= 1'b0; end - 16'b0001111000000001: begin // EEPROM - if (i_eeprom_pi_enable) begin - o_bank <= `BANK_EEPROM; - end - end - - 16'b0001111000000010: begin // SD + 16'b0001111000000001: begin // SD if (i_sd_enable) begin o_bank <= `BANK_SD; o_prefetch <= 1'b0; end end + 16'b0001111000000011: begin // EEPROM + if (i_eeprom_pi_enable) begin + o_bank <= `BANK_EEPROM; + end + end + default: begin end endcase end diff --git a/fw/rtl/top.v b/fw/rtl/top.v index dbc052b..5b04d82 100644 --- a/fw/rtl/top.v +++ b/fw/rtl/top.v @@ -51,11 +51,7 @@ module top ( // Temporary signal names - wire w_n64_reset_btn; - assign {o_rtc_scl, io_rtc_sda} = 2'bZZ; - assign io_pmod[3] = w_n64_reset_btn ? 1'bZ : 1'b0; - assign {io_pmod[7:4], io_pmod[2:0]} = 7'bZZZZZZZ; // PLL clock generator @@ -345,7 +341,7 @@ module top ( .o_eeprom_enable(w_eeprom_enable), .o_eeprom_16k_mode(w_eeprom_16k_mode), - .o_n64_reset_btn(w_n64_reset_btn), + .io_gpio(io_pmod), .i_debug_ready(1'b1), // TODO: Detect USB cable insertion diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index 4ee027b..e5f47be 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -22,7 +22,7 @@ SOURCE_DIR = src BUILD_DIR = build SRC_DIRS = $(SOURCE_DIR) $(sort $(dir $(wildcard $(SOURCE_DIR)/*/.))) -INC_DIRS = $(addprefix -I, . $(SRC_DIRS)) +INC_DIRS = $(addprefix -I, . $(SRC_DIRS)) -I./libsc64/inc SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS))) IMG_FILES = $(wildcard $(patsubst %, %/*.png, . $(SRC_DIRS))) OBJ_FILES = $(addprefix $(BUILD_DIR)/, $(notdir $(IMG_FILES:.png=.o) $(SRC_FILES:.c=.o))) @@ -32,7 +32,7 @@ VPATH = $(SRC_DIRS) COMMONFLAGS = -march=vr4300 -mtune=vr4300 ASFLAGS = $(COMMONFLAGS) CFLAGS = $(COMMONFLAGS) -std=gnu99 -Os -Wall -I$(ROOTDIR)/mips64-elf/include $(INC_DIRS) -LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld +LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld -L./libsc64/lib -lsc64_libdragon N64_FLAGS = -l $(ROM_SIZE) -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME).z64 N64_FLAGS_PADDED = -l 1028k -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME)_padded.z64 diff --git a/sw/bootloader/build.sh b/sw/bootloader/build.sh index a85afa5..34cd58e 100644 --- a/sw/bootloader/build.sh +++ b/sw/bootloader/build.sh @@ -1,10 +1,10 @@ #!/bin/bash -LIBDRAGON_DOCKER_VERSION=latest +build_in_docker() { + docker run -t \ + --mount type=bind,src=`realpath $(pwd)`,target="/src" \ + --mount type=bind,src=`realpath "$(pwd)/../libsc64"`,target="/src/libsc64" \ + $1 /bin/bash -c "cd /src && make clean && make -f $2 all" +} -docker \ - run \ - -t \ - --mount type=bind,src=`realpath "$(dirname $0)"`,target="/libdragon" \ - anacierdem/libdragon:$LIBDRAGON_DOCKER_VERSION \ - /bin/bash -c "make clean && make all" +build_in_docker "anacierdem/libdragon:latest" "Makefile" diff --git a/sw/libsc64/.gitignore b/sw/libsc64/.gitignore new file mode 100644 index 0000000..d82c721 --- /dev/null +++ b/sw/libsc64/.gitignore @@ -0,0 +1,2 @@ +/lib +/output diff --git a/sw/libsc64/Makefile.common b/sw/libsc64/Makefile.common new file mode 100644 index 0000000..ad4d9a4 --- /dev/null +++ b/sw/libsc64/Makefile.common @@ -0,0 +1,37 @@ +SRC_DIRS = src +INC_DIRS = inc +OUTPUT_DIR = lib +BUILD_DIR = output/$(LIB_BUILD_DIR) + +SRC_FILES = boot.c control.c gpio.c helpers.c init.c io_dma.c save.c sd.c usb.c + +CFLAGS += -ffunction-sections -fdata-sections -Os -Wall -MMD -MP $(patsubst %, -I%, $(INC_DIRS)) + +OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC_FILES:.c=.o))) +DEPS = $(OBJS:.o=.d) + +VPATH = $(SRC_DIRS) + +all: create_build_dirs $(OUTPUT_DIR)/$(LIB_NAME).a + +create_build_dirs: $(OUTPUT_DIR) $(BUILD_DIR) + +$(OUTPUT_DIR): + mkdir -p ./$(OUTPUT_DIR) + +$(BUILD_DIR): + mkdir -p ./$(BUILD_DIR) + +$(BUILD_DIR)/%.o: %.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(OUTPUT_DIR)/$(LIB_NAME).a: $(OBJS) + $(AR) -rcs -o $@ $(OBJS) + +clean: + rm -rf ./$(BUILD_DIR) 2> /dev/null + rm -rf ./$(OUTPUT_DIR) 2> /dev/null + +.PHONY: all clean create_build_dirs + +-include $(DEPS) diff --git a/sw/libsc64/Makefile.libdragon b/sw/libsc64/Makefile.libdragon new file mode 100644 index 0000000..ae6d190 --- /dev/null +++ b/sw/libsc64/Makefile.libdragon @@ -0,0 +1,11 @@ +TOOLCHAIN = $(N64_INST)/bin/mips64-elf- +CC = $(TOOLCHAIN)gcc +AR = $(TOOLCHAIN)ar + +LIB_NAME = libsc64_libdragon + +LIB_BUILD_DIR = libdragon + +CFLAGS += -march=vr4300 -mtune=vr4300 -DLIBDRAGON + +include Makefile.common diff --git a/sw/libsc64/Makefile.libultra b/sw/libsc64/Makefile.libultra new file mode 100644 index 0000000..c64b7aa --- /dev/null +++ b/sw/libsc64/Makefile.libultra @@ -0,0 +1,9 @@ +include $(ROOT)/usr/include/make/PRdefs + +LIB_NAME = libsc64_libultra + +LIB_BUILD_DIR = libultra + +CFLAGS += -I$(ROOT)/usr/include/nustd -DLIBULTRA + +include Makefile.common diff --git a/sw/libsc64/build.sh b/sw/libsc64/build.sh new file mode 100644 index 0000000..9cfe432 --- /dev/null +++ b/sw/libsc64/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +build_in_docker() { + docker run -t \ + --mount type=bind,src=`realpath $(pwd)`,target="/src" \ + $1 /bin/bash -c "cd /src && make -f $2 all" +} + +build_in_docker "anacierdem/libdragon:latest" "Makefile.libdragon" + +build_in_docker "polprzewodnikowy/n64sdkmod:latest" "Makefile.libultra" diff --git a/sw/libsc64/inc/boot.h b/sw/libsc64/inc/boot.h new file mode 100644 index 0000000..21be1a6 --- /dev/null +++ b/sw/libsc64/inc/boot.h @@ -0,0 +1,31 @@ +#ifndef SC64_BOOT_H__ +#define SC64_BOOT_H__ + + +#include +#include + + +typedef union sc64_boot_config_s { + uint32_t _packed_value; + struct { + uint16_t _padding: 16; + bool skip_menu: 1; + bool cic_seed_override: 1; + bool tv_type_override: 1; + bool ddipl_override: 1; + bool rom_loaded: 1; + uint8_t tv_type: 2; + uint8_t os_version: 1; + uint8_t cic_seed: 8; + }; +} sc64_boot_config_t; + + +void sc64_boot_config_set(sc64_boot_config_t *boot_config); +void sc64_boot_config_get(sc64_boot_config_t *boot_config); + +void sc64_boot_skip_bootloader(bool is_enabled); + + +#endif diff --git a/sw/libsc64/inc/control.h b/sw/libsc64/inc/control.h new file mode 100644 index 0000000..115cf81 --- /dev/null +++ b/sw/libsc64/inc/control.h @@ -0,0 +1,20 @@ +#ifndef SC64_CONTROL_H__ +#define SC64_CONTROL_H__ + + +#include +#include + + +void sc64_control_sdram_writable(bool is_enabled); +void sc64_control_embedded_flash_access(bool is_enabled); + +uint32_t sc64_control_version_get(void); + +void sc64_control_ddipl_access(bool is_enabled); + +void sc64_control_ddipl_address_set(uint32_t address); +uint32_t sc64_control_ddipl_address_get(void); + + +#endif diff --git a/sw/libsc64/inc/gpio.h b/sw/libsc64/inc/gpio.h new file mode 100644 index 0000000..1e93449 --- /dev/null +++ b/sw/libsc64/inc/gpio.h @@ -0,0 +1,26 @@ +#ifndef SC64_GPIO_H__ +#define SC64_GPIO_H__ + + +#include + + +typedef enum sc64_gpio_mode_e { + MODE_INPUT, + MODE_OUTPUT, + MODE_OPEN_DRAIN, +} sc64_gpio_mode_t; + + +void sc64_gpio_init(void); + +void sc64_gpio_mode_set(uint8_t num, sc64_gpio_mode_t mode); + +void sc64_gpio_output_write(uint8_t value); +void sc64_gpio_output_set(uint8_t mask); +void sc64_gpio_output_clear(uint8_t mask); + +uint8_t sc64_gpio_input_get(void); + + +#endif diff --git a/sw/libsc64/inc/helpers.h b/sw/libsc64/inc/helpers.h new file mode 100644 index 0000000..83f1e3e --- /dev/null +++ b/sw/libsc64/inc/helpers.h @@ -0,0 +1,15 @@ +#ifndef SC64_HELPERS_H__ +#define SC64_HELPERS_H__ + + +#include +#include + + +void sc64_helpers_reg_write(volatile uint32_t *pi_address, uint32_t mask, bool mask_mode); + +void sc64_helpers_reg_set(volatile uint32_t *pi_address, uint32_t mask); +void sc64_helpers_reg_clear(volatile uint32_t *pi_address, uint32_t mask); + + +#endif diff --git a/sw/libsc64/inc/init.h b/sw/libsc64/inc/init.h new file mode 100644 index 0000000..bc382c0 --- /dev/null +++ b/sw/libsc64/inc/init.h @@ -0,0 +1,8 @@ +#ifndef SC64_INIT_H__ +#define SC64_INIT_H__ + + +void sc64_init(void); + + +#endif diff --git a/sw/libsc64/inc/io_dma.h b/sw/libsc64/inc/io_dma.h new file mode 100644 index 0000000..4630e85 --- /dev/null +++ b/sw/libsc64/inc/io_dma.h @@ -0,0 +1,18 @@ +#ifndef SC64_IO_DMA_H__ +#define SC64_IO_DMA_H__ + + +#include +#include + + +void sc64_io_dma_init(void); + +void sc64_io_write(volatile uint32_t *pi_address, uint32_t value); +uint32_t sc64_io_read(volatile uint32_t *pi_address); + +void sc64_dma_write(void *ram_address, volatile uint32_t *pi_address, size_t length); +void sc64_dma_read(void *ram_address, volatile uint32_t *pi_address, size_t length); + + +#endif diff --git a/sw/libsc64/inc/libsc64.h b/sw/libsc64/inc/libsc64.h new file mode 100644 index 0000000..78bc5c6 --- /dev/null +++ b/sw/libsc64/inc/libsc64.h @@ -0,0 +1,15 @@ +#ifndef LIBSC64_H__ +#define LIBSC64_H__ + + +#include "boot.h" +#include "control.h" +#include "gpio.h" +#include "io_dma.h" +#include "init.h" +#include "save.h" +#include "sd.h" +#include "usb.h" + + +#endif diff --git a/sw/libsc64/inc/registers.h b/sw/libsc64/inc/registers.h new file mode 100644 index 0000000..6381077 --- /dev/null +++ b/sw/libsc64/inc/registers.h @@ -0,0 +1,178 @@ +#ifndef SC64_REGISTERS_H__ +#define SC64_REGISTERS_H__ + + +#include + + +// Bank definitions + +#define SC64_BANK_SDRAM (1) +#define SC64_BANK_EEPROM (3) + + +// Cart Interface Registers + +typedef struct sc64_cart_registers { + volatile uint32_t SCR; // Cart status and control + volatile uint32_t BOOT; // Boot behavior control + volatile uint32_t VERSION; // Cart firmware version + volatile uint32_t GPIO; // GPIO control + volatile uint32_t USB_SCR; // USB interface status and control + volatile uint32_t USB_DMA_ADDR; // USB address for DMA to PC + volatile uint32_t USB_DMA_LEN; // USB transfer length for DMA to PC + volatile uint32_t DDIPL_ADDR; // 64 Disk Drive IPL location in SDRAM + volatile uint32_t SAVE_ADDR; // SRAM/FlashRAM save emulation location in SDRAM + volatile uint32_t _unused[1015]; + volatile uint32_t USB_FIFO[1024]; // USB data from PC read FIFO memory +} sc64_cart_registers_t; + + +#define SC64_CART_BASE (0x1E000000) + +#define SC64_CART ((volatile sc64_cart_registers_t *) SC64_CART_BASE) + + +// SCR +#define SC64_CART_SCR_SKIP_BOOTLOADER (1 << 10) +#define SC64_CART_SCR_SD_ENABLE (1 << 9) +#define SC64_CART_SCR_FLASHRAM_ENABLE (1 << 8) +#define SC64_CART_SCR_SRAM_768K_MODE (1 << 7) +#define SC64_CART_SCR_SRAM_ENABLE (1 << 6) +#define SC64_CART_SCR_EEPROM_PI_ENABLE (1 << 5) +#define SC64_CART_SCR_EEPROM_16K_MODE (1 << 4) +#define SC64_CART_SCR_EEPROM_ENABLE (1 << 3) +#define SC64_CART_SCR_DDIPL_ENABLE (1 << 2) +#define SC64_CART_SCR_SDRAM_WRITABLE (1 << 1) +#define SC64_CART_SCR_ROM_SWITCH (1 << 0) + + +// GPIO +#define SC64_CART_GPIO_OFFSET_OUTPUT (0) +#define SC64_CART_GPIO_OFFSET_INPUT (8) +#define SC64_CART_GPIO_OFFSET_DIR (16) +#define SC64_CART_GPIO_OFFSET_OPEN_DRAIN (24) + + +// USB_SCR +#define SC64_CART_USB_SCR_FIFO_ITEMS(s) (((s) >> 3) & 0x7FF) +#define SC64_CART_USB_SCR_READY (1 << 1) +#define SC64_CART_USB_SCR_DMA_BUSY (1 << 0) + +#define SC64_CART_USB_SCR_FIFO_FLUSH (1 << 2) +#define SC64_CART_USB_SCR_DMA_START (1 << 0) + + +// USB_DMA_ADDR +#define SC64_CART_USB_DMA_ADDR(a) ((SC64_BANK_SDRAM << 28) | ((a) & 0x3FFFFFC)) + + +// USB_DMA_LEN +#define SC64_CART_USB_DMA_LEN(l) (((l) - 1) & 0xFFFFF) + + +// SD Card Interface Registers + +typedef struct sc64_sd_registers_s { + volatile uint32_t SCR; // Clock control and bus width selection + volatile uint32_t ARG; // SD command argument + volatile uint32_t CMD; // SD command index and flags + volatile uint32_t RSP; // SD command response + volatile uint32_t DAT; // SD data path control + volatile uint32_t DMA_SCR; // DMA status and configuration + volatile uint32_t DMA_ADDR; // DMA current address + volatile uint32_t DMA_LEN; // DMA remaining length + volatile uint32_t _unused[120]; + volatile uint32_t FIFO[128]; // SD data path FIFO buffer +} sc64_sd_registers_t; + + +#define SC64_SD_BASE (0x1E010000) + +#define SC64_SD ((volatile sc64_sd_registers_t *) SC64_SD_BASE) + + +// SCR +#define SC64_SD_SCR_DAT_WIDTH (1 << 2) +#define SC64_SD_SCR_CLK_MASK (0x3 << 0) +#define SC64_SD_SCR_CLK_STOP (0 << 0) +#define SC64_SD_SCR_CLK_400_KHZ (1 << 0) +#define SC64_SD_SCR_CLK_25_MHZ (2 << 0) +#define SC64_SD_SCR_CLK_50_MHZ (3 << 0) + + +// CMD +#define SC64_SD_CMD_RESPONSE_CRC_ERROR (1 << 8) +#define SC64_SD_CMD_TIMEOUT (1 << 7) +#define SC64_SD_CMD_BUSY (1 << 6) +#define SC64_SD_CMD_INDEX_GET(cmd) ((cmd) & 0x3F) + +#define SC64_SD_CMD_SKIP_RESPONSE (1 << 8) +#define SC64_SD_CMD_LONG_RESPONSE (1 << 7) +#define SC64_SD_CMD_START (1 << 6) +#define SC64_SD_CMD_INDEX(i) ((i) & 0x3F) + + +// DAT +#define SC64_SD_DAT_WRITE_OK (1 << 28) +#define SC64_SD_DAT_WRITE_ERROR (1 << 27) +#define SC64_SD_DAT_WRITE_BUSY (1 << 26) +#define SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) (((dat) >> 17) & 0x1FF) +#define SC64_SD_DAT_TX_FIFO_BYTES_GET(dat) (SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) * 4) +#define SC64_SD_DAT_TX_FIFO_FULL (1 << 16) +#define SC64_SD_DAT_TX_FIFO_EMPTY (1 << 15) +#define SC64_SD_DAT_TX_FIFO_UNDERRUN (1 << 14) +#define SC64_SD_DAT_RX_FIFO_ITEMS_GET(dat) (((dat) >> 5) & 0x1FF) +#define SC64_SD_DAT_RX_FIFO_BYTES_GET(dat) (SC64_SD_DAT_RX_FIFO_ITEMS_GET(dat) * 4) +#define SC64_SD_DAT_RX_FIFO_FULL (1 << 4) +#define SC64_SD_DAT_RX_FIFO_EMPTY (1 << 3) +#define SC64_SD_DAT_RX_FIFO_OVERRUN (1 << 2) +#define SC64_SD_DAT_CRC_ERROR (1 << 1) +#define SC64_SD_DAT_BUSY (1 << 0) + +#define SC64_SD_DAT_TX_FIFO_FLUSH (1 << 19) +#define SC64_SD_DAT_RX_FIFO_FLUSH (1 << 18) +#define SC64_SD_DAT_NUM_BLOCKS(nb) ((((nb) - 1) & 0xFF) << 10) +#define SC64_SD_DAT_BLOCK_SIZE(bs) (((((bs) / 4) - 1) & 0x7F) << 3) +#define SC64_SD_DAT_DIRECTION (1 << 2) +#define SC64_SD_DAT_STOP (1 << 1) +#define SC64_SD_DAT_START (1 << 0) + +#define SC64_SD_DAT_FIFO_SIZE_BYTES (1024) +#define SC64_SD_DAT_NUM_BLOCKS_MAX (256) +#define SC64_SD_DAT_BLOCK_SIZE_MAX (512) + + +// DMA_SCR +#define SC64_SD_DMA_SCR_BUSY (1 << 0) + +#define SC64_SD_DMA_SCR_DIRECTION (1 << 2) +#define SC64_SD_DMA_SCR_STOP (1 << 1) +#define SC64_SD_DMA_SCR_START (1 << 0) + + +// DMA_ADDR +#define SC64_SD_DMA_ADDR_GET(addr) ((addr) & 0x3FFFFFC) +#define SC64_SD_DMA_BANK_GET(addr) (((addr) >> 28) & 0xF) + +#define SC64_SD_DMA_BANK_ADDR(b, a) ((((b) & 0xF) << 28) | ((a) & 0x3FFFFFC)) + + +// DMA_LEN +#define SC64_SD_DMA_LEN_GET(len) (((len) & 0x7FFF) * 4) + +#define SC64_SD_DMA_LEN(l) ((((l) / 4) - 1) & 0x7FFF) + +#define SC64_SD_DMA_LEN_MAX (0x20000) + + +// EEPROM Block RAM + +#define SC64_EEPROM_BASE (0x1E030000) + +#define SC64_EEPROM ((volatile uint8_t *) SC64_EEPROM_BASE) + +#define SC64_EEPROM_SIZE ((16 * 1024) / 8) + + +#endif diff --git a/sw/libsc64/inc/save.h b/sw/libsc64/inc/save.h new file mode 100644 index 0000000..d850772 --- /dev/null +++ b/sw/libsc64/inc/save.h @@ -0,0 +1,31 @@ +#ifndef SC64_SAVE_H__ +#define SC64_SAVE_H__ + + +#include +#include + + +typedef enum sc64_save_type_e { + SC64_SAVE_DISABLED, + SC64_SAVE_EEPROM_4K, + SC64_SAVE_EEPROM_16K, + SC64_SAVE_SRAM_256K, + SC64_SAVE_SRAM_768K, + SC64_SAVE_FLASHRAM_1M, +} sc64_save_type_t; + + +void sc64_save_type_set(sc64_save_type_t save_type); +sc64_save_type_t sc64_save_type_get(void); + +void sc64_save_address_set(uint32_t address); +uint32_t sc64_save_address_get(void); + +void sc64_save_eeprom_pi_access(bool is_enabled); + +void sc64_save_write(void *ram_address); +void sc64_save_read(void *ram_address); + + +#endif diff --git a/sw/libsc64/inc/sd.h b/sw/libsc64/inc/sd.h new file mode 100644 index 0000000..8ec5884 --- /dev/null +++ b/sw/libsc64/inc/sd.h @@ -0,0 +1,34 @@ +#ifndef SC64_SD_H__ +#define SC64_SD_H__ + + +#include +#include + + +void sc64_sd_access(bool is_enabled); + + +// typedef enum sc64_sd_err_e { +// E_OK, +// E_TIMEOUT, +// E_CRC_ERROR, +// E_BAD_INDEX, +// E_PAR_ERROR, +// E_FIFO_ERROR, +// E_WRITE_ERROR, +// E_NO_INIT, +// } sc64_sd_err_t; + + +// bool sc64_sd_init(void); +// void sc64_sd_deinit(void); +// bool sc64_sd_status_get(void); +// sc64_sd_err_t sc64_sd_sectors_read(uint32_t starting_sector, size_t count, uint8_t *buffer); +// sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint8_t *buffer); +// sc64_sd_err_t sc64_sd_sectors_read_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address); +// // sc64_sd_err_t sc64_sd_sectors_write_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address); +// sc64_sd_err_t sc64_sd_dat_busy_wait(void); + + +#endif diff --git a/sw/libsc64/inc/usb.h b/sw/libsc64/inc/usb.h new file mode 100644 index 0000000..a02b0d5 --- /dev/null +++ b/sw/libsc64/inc/usb.h @@ -0,0 +1,8 @@ +#ifndef SC64_USB_H__ +#define SC64_USB_H__ + + + + + +#endif diff --git a/sw/libsc64/src/boot.c b/sw/libsc64/src/boot.c new file mode 100644 index 0000000..34da4c8 --- /dev/null +++ b/sw/libsc64/src/boot.c @@ -0,0 +1,17 @@ +#include "boot.h" +#include "helpers.h" +#include "io_dma.h" +#include "registers.h" + + +void sc64_boot_skip_bootloader(bool is_enabled) { + sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_SKIP_BOOTLOADER, is_enabled); +} + +void sc64_boot_config_set(sc64_boot_config_t *boot_config) { + sc64_io_write(&SC64_CART->BOOT, boot_config->_packed_value); +} + +void sc64_boot_config_get(sc64_boot_config_t *boot_config) { + boot_config->_packed_value = sc64_io_read(&SC64_CART->BOOT); +} diff --git a/sw/libsc64/src/control.c b/sw/libsc64/src/control.c new file mode 100644 index 0000000..c7016a2 --- /dev/null +++ b/sw/libsc64/src/control.c @@ -0,0 +1,29 @@ +#include "control.h" +#include "helpers.h" +#include "io_dma.h" +#include "registers.h" + + +void sc64_control_sdram_writable(bool is_enabled) { + sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_SDRAM_WRITABLE, is_enabled); +} + +void sc64_control_embedded_flash_access(bool is_enabled) { + sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_ROM_SWITCH, !is_enabled); +} + +uint32_t sc64_control_version_get(void) { + return sc64_io_read(&SC64_CART->VERSION); +} + +void sc64_control_ddipl_access(bool is_enabled) { + sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_DDIPL_ENABLE, is_enabled); +} + +void sc64_control_ddipl_address_set(uint32_t address) { + sc64_io_write(&SC64_CART->DDIPL_ADDR, address); +} + +uint32_t sc64_control_ddipl_address_get(void) { + return sc64_io_read(&SC64_CART->DDIPL_ADDR); +} diff --git a/sw/libsc64/src/gpio.c b/sw/libsc64/src/gpio.c new file mode 100644 index 0000000..259ead3 --- /dev/null +++ b/sw/libsc64/src/gpio.c @@ -0,0 +1,63 @@ +#include "gpio.h" +#include "io_dma.h" +#include "registers.h" + + +static uint32_t gpio_state; + + +void sc64_gpio_init(void) { + gpio_state = 0; + + sc64_io_write(&SC64_CART->GPIO, gpio_state); +} + +void sc64_gpio_mode_set(uint8_t num, sc64_gpio_mode_t mode) { + if (num >= 8) { + return; + } + + gpio_state &= ~( + ((1 << num) << SC64_CART_GPIO_OFFSET_OPEN_DRAIN) | + ((1 << num) << SC64_CART_GPIO_OFFSET_DIR) + ); + + switch (mode) { + case MODE_OUTPUT: + gpio_state |= ((1 << num) << SC64_CART_GPIO_OFFSET_DIR); + break; + case MODE_OPEN_DRAIN: + gpio_state |= ( + ((1 << num) << SC64_CART_GPIO_OFFSET_OPEN_DRAIN) | + ((1 << num) << SC64_CART_GPIO_OFFSET_DIR) + ); + break; + default: + break; + } + + sc64_io_write(&SC64_CART->GPIO, gpio_state); +} + +void sc64_gpio_output_write(uint8_t value) { + gpio_state &= ~(0xFF << SC64_CART_GPIO_OFFSET_OUTPUT); + gpio_state |= (value << SC64_CART_GPIO_OFFSET_OUTPUT); + + sc64_io_write(&SC64_CART->GPIO, gpio_state); +} + +void sc64_gpio_output_set(uint8_t mask) { + gpio_state |= (mask << SC64_CART_GPIO_OFFSET_OUTPUT); + + sc64_io_write(&SC64_CART->GPIO, gpio_state); +} + +void sc64_gpio_output_clear(uint8_t mask) { + gpio_state &= ~(mask << SC64_CART_GPIO_OFFSET_OUTPUT); + + sc64_io_write(&SC64_CART->GPIO, gpio_state); +} + +uint8_t sc64_gpio_input_get(void) { + return (uint8_t) ((sc64_io_read(&SC64_CART->GPIO) >> SC64_CART_GPIO_OFFSET_INPUT) & 0xFF); +} diff --git a/sw/libsc64/src/helpers.c b/sw/libsc64/src/helpers.c new file mode 100644 index 0000000..12c318e --- /dev/null +++ b/sw/libsc64/src/helpers.c @@ -0,0 +1,24 @@ +#include "helpers.h" +#include "io_dma.h" +#include "registers.h" + + +void sc64_helpers_reg_write(volatile uint32_t *pi_address, uint32_t mask, bool mask_mode) { + uint32_t reg = sc64_io_read(pi_address); + + if (mask_mode) { + reg |= mask; + } else { + reg &= ~mask; + } + + sc64_io_write(pi_address, reg); +} + +void sc64_helpers_reg_set(volatile uint32_t *pi_address, uint32_t mask) { + sc64_helpers_reg_write(pi_address, mask, true); +} + +void sc64_helpers_reg_clear(volatile uint32_t *pi_address, uint32_t mask) { + sc64_helpers_reg_write(pi_address, mask, false); +} diff --git a/sw/libsc64/src/init.c b/sw/libsc64/src/init.c new file mode 100644 index 0000000..c257e05 --- /dev/null +++ b/sw/libsc64/src/init.c @@ -0,0 +1,8 @@ +#include "gpio.h" +#include "io_dma.h" + + +void sc64_init(void) { + sc64_io_dma_init(); + sc64_gpio_init(); +} diff --git a/sw/libsc64/src/io_dma.c b/sw/libsc64/src/io_dma.c new file mode 100644 index 0000000..6a52fbb --- /dev/null +++ b/sw/libsc64/src/io_dma.c @@ -0,0 +1,69 @@ +#include "io_dma.h" + + +#ifndef LIBDRAGON +#ifndef LIBULTRA +#error "Please specify used library with -DLIBDRAGON or -DLIBULTRA" +#endif +#endif + + +#ifdef LIBDRAGON +#include +#endif + + +#ifdef LIBULTRA +#include + +static OSMesg pi_message; +static OSIoMesg pi_io_message; +static OSMesgQueue pi_message_queue; +#endif + + +void sc64_io_dma_init(void) { +#ifdef LIBULTRA + osCreateMesgQueue(&pi_message_queue, &pi_message, 1); +#endif +} + +void sc64_io_write(volatile uint32_t *pi_address, uint32_t value) { +#ifdef LIBDRAGON + io_write((uint32_t) pi_address, value); +#elif LIBULTRA + osPiWriteIo((u32) pi_address, value); +#endif +} + +uint32_t sc64_io_read(volatile uint32_t *pi_address) { +#ifdef LIBDRAGON + return io_read((uint32_t) pi_address); +#elif LIBULTRA + u32 value; + osPiReadIo((u32) pi_address, &value); + return value; +#endif +} + +void sc64_dma_write(void *ram_address, volatile uint32_t *pi_address, size_t length) { +#ifdef LIBDRAGON + data_cache_hit_writeback_invalidate(ram_address, length); + dma_write(ram_address, (uint32_t) pi_address, length); +#elif LIBULTRA + osWritebackDCache(ram_address, length); + osPiStartDma(&pi_io_message, OS_MESG_PRI_NORMAL, OS_WRITE, (u32) pi_address, ram_address, length, &pi_message_queue); + osRecvMesg(&pi_message_queue, NULL, OS_MESG_BLOCK); +#endif +} + +void sc64_dma_read(void *ram_address, volatile uint32_t *pi_address, size_t length) { +#ifdef LIBDRAGON + dma_read(ram_address, (uint32_t) pi_address, length); + data_cache_hit_writeback_invalidate(ram_address, length); +#elif LIBULTRA + osPiStartDma(&pi_io_message, OS_MESG_PRI_NORMAL, OS_READ, (u32) pi_address, ram_address, length, &pi_message_queue); + osRecvMesg(&pi_message_queue, NULL, OS_MESG_BLOCK); + osInvalDCache(ram_address, length); +#endif +} diff --git a/sw/libsc64/src/save.c b/sw/libsc64/src/save.c new file mode 100644 index 0000000..8ce9f31 --- /dev/null +++ b/sw/libsc64/src/save.c @@ -0,0 +1,157 @@ +#include "control.h" +#include "helpers.h" +#include "io_dma.h" +#include "registers.h" +#include "save.h" + + +static bool sc64_save_address_length_get(uint32_t *pi_address, size_t *length, bool *is_eeprom) { + sc64_save_type_t save_type = sc64_save_type_get(); + + *is_eeprom = false; + + switch (save_type) { + case SC64_SAVE_EEPROM_4K: + *pi_address = SC64_EEPROM_BASE; + *length = 512; + *is_eeprom = true; + break; + case SC64_SAVE_EEPROM_16K: + *pi_address = SC64_EEPROM_BASE; + *length = 2048; + *is_eeprom = true; + break; + case SC64_SAVE_SRAM_256K: + *pi_address = sc64_save_address_get(); + *length = (32 * 1024); + break; + case SC64_SAVE_SRAM_768K: + *pi_address = sc64_save_address_get(); + *length = (96 * 1024); + break; + case SC64_SAVE_FLASHRAM_1M: + *pi_address = sc64_save_address_get(); + *length = (128 * 1024); + break; + default: + return false; + } + + return true; +} + + +void sc64_save_type_set(sc64_save_type_t save_type) { + uint32_t scr; + + scr = sc64_io_read(&SC64_CART->SCR); + + scr &= ~( + SC64_CART_SCR_FLASHRAM_ENABLE | + SC64_CART_SCR_SRAM_768K_MODE | + SC64_CART_SCR_SRAM_ENABLE | + SC64_CART_SCR_EEPROM_16K_MODE | + SC64_CART_SCR_EEPROM_ENABLE + ); + + switch (save_type) + { + case SC64_SAVE_EEPROM_4K: + scr |= SC64_CART_SCR_EEPROM_ENABLE; + break; + case SC64_SAVE_EEPROM_16K: + scr |= SC64_CART_SCR_EEPROM_ENABLE | SC64_CART_SCR_EEPROM_16K_MODE; + break; + case SC64_SAVE_SRAM_256K: + scr |= SC64_CART_SCR_SRAM_ENABLE; + break; + case SC64_SAVE_SRAM_768K: + scr |= SC64_CART_SCR_SRAM_ENABLE | SC64_CART_SCR_SRAM_768K_MODE; + break; + case SC64_SAVE_FLASHRAM_1M: + scr |= SC64_CART_SCR_FLASHRAM_ENABLE; + break; + default: + break; + } + + sc64_io_write(&SC64_CART->SCR, scr); +} + +sc64_save_type_t sc64_save_type_get(void) { + uint32_t scr; + + scr = sc64_io_read(&SC64_CART->SCR); + + if (scr & SC64_CART_SCR_FLASHRAM_ENABLE) { + return SC64_SAVE_FLASHRAM_1M; + } else if (scr & SC64_CART_SCR_SRAM_ENABLE) { + return (scr & SC64_CART_SCR_SRAM_768K_MODE) ? SC64_SAVE_SRAM_768K : SC64_SAVE_SRAM_256K; + } else if (scr & SC64_CART_SCR_EEPROM_ENABLE) { + return (scr & SC64_CART_SCR_EEPROM_16K_MODE) ? SC64_SAVE_EEPROM_16K : SC64_SAVE_EEPROM_4K; + } + + return SC64_SAVE_DISABLED; +} + +void sc64_save_address_set(uint32_t address) { + sc64_io_write(&SC64_CART->SAVE_ADDR, address); +} + +uint32_t sc64_save_address_get(void) { + return sc64_io_read(&SC64_CART->SAVE_ADDR); +} + +void sc64_save_eeprom_pi_access(bool is_enabled) { + sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_EEPROM_PI_ENABLE, is_enabled); +} + +void sc64_save_write(void *ram_address) { + uint32_t pi_address; + size_t length; + bool is_eeprom; + uint32_t scr; + bool eeprom_pi_access; + bool sdram_writable; + + if (sc64_save_address_length_get(&pi_address, &length, &is_eeprom)) { + scr = sc64_io_read(&SC64_CART->SCR); + eeprom_pi_access = scr & SC64_CART_SCR_EEPROM_PI_ENABLE; + sdram_writable = scr & SC64_CART_SCR_SDRAM_WRITABLE; + + if (is_eeprom && !eeprom_pi_access) { + sc64_save_eeprom_pi_access(true); + } else if (!sdram_writable) { + sc64_control_sdram_writable(true); + } + + sc64_dma_write(ram_address, (volatile uint32_t *) pi_address, length); + + if (is_eeprom && !eeprom_pi_access) { + sc64_save_eeprom_pi_access(false); + } else if (!sdram_writable) { + sc64_control_sdram_writable(false); + } + } +} + +void sc64_save_read(void *ram_address) { + uint32_t pi_address; + size_t length; + bool is_eeprom; + bool eeprom_pi_access; + + if (sc64_save_address_length_get(&pi_address, &length, &is_eeprom)) { + eeprom_pi_access = sc64_io_read(&SC64_CART->SCR) & SC64_CART_SCR_EEPROM_PI_ENABLE; + + if (is_eeprom && !eeprom_pi_access) { + sc64_save_eeprom_pi_access(true); + } + + sc64_dma_read(ram_address, (volatile uint32_t *) pi_address, length); + + if (is_eeprom && !eeprom_pi_access) { + sc64_save_eeprom_pi_access(false); + } + } +} diff --git a/sw/libsc64/src/sd.c b/sw/libsc64/src/sd.c new file mode 100644 index 0000000..60db512 --- /dev/null +++ b/sw/libsc64/src/sd.c @@ -0,0 +1,211 @@ +#include "helpers.h" +#include "registers.h" +#include "sd.h" + + +void sc64_sd_access(bool is_enabled) { + sc64_helpers_reg_write(&SC64_CART->SCR, SC64_CART_SCR_SD_ENABLE, is_enabled); +} + + +// #include "registers.h" +// #include "sd.h" +// #include "io_dma.h" + + +// #define CMD8_ARG_SUPPLY_VOLTAGE_27_36_V (1 << 8) +// #define CMD8_ARG_CHECK_PATTERN_AA (0xAA << 0) + +// #define ACMD41_ARG_HCS (1 << 30) + +// #define R3_CCS (1 << 30) +// #define R3_BUSY (1 << 31) + +// #define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8) +// #define R7_CHECK_PATTERN_AA (0xAA << 0) + +// #define SD_BLOCK_SIZE (512) + + +// typedef enum sc64_sd_cmd_flags_e { +// NO_FLAGS = 0, +// ACMD = (1 << 0), +// SKIP_RESPONSE = (1 << 1), +// LONG_RESPONSE = (1 << 2), +// IGNORE_CRC = (1 << 3), +// IGNORE_INDEX = (1 << 4), +// } sc64_sd_cmd_flags_t; + + +// static bool sd_card_initialized = false; +// static bool sd_card_type_block = false; +// static bool sd_card_selected = false; +// static uint32_t sd_card_rca = 0; +// static uint8_t sd_buffer[64] __attribute__((aligned(16))); + + +// static void sc64_sd_clock_set(uint32_t clock) { +// uint32_t scr = sc64_io_read(&SC64_SD->SCR); + +// sc64_io_write(&SC64_SD->SCR, (scr & (~SC64_SD_SCR_CLK_MASK)) | (clock & SC64_SD_SCR_CLK_MASK)); +// } + +// static void sc64_sd_dat_4bit_set(bool is_4bit) { +// uint32_t scr = sc64_io_read(&SC64_SD->SCR); + +// scr &= ~SC64_SD_SCR_DAT_WIDTH; + +// if (is_4bit) { +// scr |= SC64_SD_SCR_DAT_WIDTH; +// } + +// sc64_io_write(&SC64_SD->SCR, scr); +// } + +// static void sc64_sd_peripheral_reset(void) { +// while (sc64_io_read(&SC64_SD->CMD) & SC64_SD_CMD_BUSY); +// sc64_io_write(&SC64_SD->DMA_SCR, SC64_SD_DMA_SCR_STOP); +// sc64_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH | SC64_SD_DAT_RX_FIFO_FLUSH | SC64_SD_DAT_STOP); +// sc64_io_write(&SC64_SD->SCR, 0); +// } + +// static void sc64_sd_peripheral_init(void) { +// sc64_control_sd_enable(); +// sc64_sd_peripheral_reset(); +// } + +// static void sc64_sd_peripheral_deinit(void) { +// if (sc64_control_sd_is_enabled()) { +// sc64_sd_peripheral_reset(); +// } +// sc64_control_sd_disable(); +// } + +// static bool sc64_sd_cmd_send(uint8_t index, uint32_t arg, sc64_sd_cmd_flags_t flags, uint32_t *response) { +// uint32_t reg; + +// if (flags & ACMD) { +// if (!sc64_sd_cmd_send(55, sd_card_rca, NO_FLAGS, response)) { +// return false; +// } +// } + +// sc64_io_write(&SC64_SD->ARG, arg); + +// reg = SC64_SD_CMD_START | SC64_SD_CMD_INDEX(index); +// if (flags & SKIP_RESPONSE) { +// reg |= SC64_SD_CMD_SKIP_RESPONSE; +// } +// if (flags & LONG_RESPONSE) { +// reg |= SC64_SD_CMD_LONG_RESPONSE; +// } + +// sc64_io_write(&SC64_SD->CMD, reg); + +// do { +// reg = sc64_io_read(&SC64_SD->CMD); +// } while (reg & SC64_SD_CMD_BUSY); + +// *response = sc64_io_read(&SC64_SD->RSP); + +// return ( +// (reg & SC64_SD_CMD_TIMEOUT) | +// ((!(flags & SKIP_RESPONSE)) && ( +// ((!(flags & IGNORE_CRC)) && (reg & SC64_SD_CMD_RESPONSE_CRC_ERROR)) | +// ((!(flags & IGNORE_INDEX)) && (SC64_SD_CMD_INDEX_GET(reg) != index)) +// )) +// ); +// } + + +// bool sc64_sd_init(void) { +// bool success; +// uint32_t response; +// uint32_t argument; + +// if (sd_card_initialized) { +// return true; +// } + +// sc64_sd_peripheral_init(); + +// do { +// sc64_sd_cmd_send(0, 0, SKIP_RESPONSE, &response); + +// argument = CMD8_ARG_SUPPLY_VOLTAGE_27_36_V | CMD8_ARG_CHECK_PATTERN_AA; +// success = sc64_sd_cmd_send(8, argument, NO_FLAGS, &response); +// if (success && (response != (R7_SUPPLY_VOLTAGE_27_36_V | R7_CHECK_PATTERN_AA))) { +// break; +// } + +// argument = (success ? ACMD41_ARG_HCS : 0) | 0x00FF8000; +// for (int i = 0; i < 4000; i++) { +// success = sc64_sd_cmd_send(41, argument, ACMD | IGNORE_CRC | IGNORE_INDEX, &response); +// if (!success || (response & R3_BUSY)) { +// break; +// } +// } +// if (!success || ((response & 0x00FF8000) == 0)) { +// break; +// } +// sd_card_type_block = (response & R3_CCS) ? true : false; + +// success = sc64_sd_cmd_send(2, 0, LONG_RESPONSE | IGNORE_INDEX, &response); +// if (!success) { +// break; +// } + +// success = sc64_sd_cmd_send(3, 0, NO_FLAGS, &response); +// if (!success) { +// break; +// } +// sd_card_rca = response & 0xFFFF0000; + +// success = sc64_sd_cmd_send(7, sd_card_rca, NO_FLAGS, &response); +// if (!success) { +// break; +// } +// sd_card_selected = true; + +// success = sc64_sd_cmd_send(6, 2, ACMD, &response); +// if (!success) { +// break; +// } + +// sc64_sd_clock_set(SC64_SD_SCR_CLK_25_MHZ); +// sc64_sd_dat_4bit_set(true); + +// sc64_sd_dat_prepare(1, 64, DAT_DIR_RX); +// success = sc64_sd_cmd_send(6, 0x00000001, NO_FLAGS, &response); +// if (!success) { +// sc64_sd_dat_abort(); +// break; +// } +// success = sc64_sd_dat_read(64, sd_buffer); +// if (!success) { +// break; +// } +// if (sd_buffer[13] & 0x02) { +// sc64_sd_dat_prepare(1, 64, DAT_DIR_RX); +// success = sc64_sd_cmd_send(6, 0x80000001, NO_FLAGS, &response); +// if (!success) { +// sc64_sd_dat_abort(); +// break; +// } +// success = sc64_sd_dat_read(64, sd_buffer); +// if (!success) { +// break; +// } + +// sc64_sd_clock_set(SC64_SD_SCR_CLK_50_MHZ); +// } + +// sd_card_initialized = true; + +// return true; +// } while(0); + +// sc64_sd_deinit(); + +// return false; +// } diff --git a/sw/libsc64/src/usb.c b/sw/libsc64/src/usb.c new file mode 100644 index 0000000..675b058 --- /dev/null +++ b/sw/libsc64/src/usb.c @@ -0,0 +1 @@ +#include "usb.h"