diff --git a/.gitignore b/.gitignore index f1e6d5a9..13c4499c 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ *.su *.swp *.tab.[ch] - +board/hobot/xj3/qos_hex.h # Build tree /build-* diff --git a/Makefile b/Makefile index 8dcbc870..afbd94f9 100644 --- a/Makefile +++ b/Makefile @@ -949,7 +949,13 @@ u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE u-boot.bin: u-boot-dtb.bin FORCE $(call if_changed,copy) else -u-boot.bin: u-boot-nodtb.bin FORCE +qos/qos.bin: qos/qos + @: +qos/qos: + $(Q)$(MAKE) obj=qos -f $(srctree)/scripts/Makefile.qos all +qos_hex: qos/qos.bin + $(srctree)/tools/bin2c qos/qos.bin $(srctree)/board/hobot/xj3/qos_hex.h qos_hex +u-boot.bin: u-boot-nodtb.bin qos_hex FORCE $(call if_changed,copy) endif @@ -1598,7 +1604,8 @@ CLEAN_DIRS += $(MODVERDIR) \ $(filter-out include, $(shell ls -1 $d 2>/dev/null)))) CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h \ - boot* u-boot* MLO* SPL System.map fit-dtb.blob + boot* u-boot* MLO* SPL System.map fit-dtb.blob \ + board/hobot/xj3/qos_hex.h qos/qos qos/qos.bin # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include/generated spl tpl \ diff --git a/board/hobot/common/board.c b/board/hobot/common/board.c index 83500802..bf42be78 100755 --- a/board/hobot/common/board.c +++ b/board/hobot/common/board.c @@ -1914,6 +1914,9 @@ int board_early_init_r(void) int board_early_init_f(void) { #ifdef CONFIG_TARGET_XJ3 +#ifdef SET_QOS_IN_UBOOT + update_qos(); +#endif // SET_QOS_IN_UBOOT init_io_vol(); #endif bif_change_reset2gpio(); diff --git a/board/hobot/xj3/xj3.c b/board/hobot/xj3/xj3.c index a360318a..57b9ca6b 100755 --- a/board/hobot/xj3/xj3.c +++ b/board/hobot/xj3/xj3.c @@ -17,6 +17,7 @@ #include #include #include +#include "qos_hex.h" DECLARE_GLOBAL_DATA_PTR; uint32_t x3_ddr_part_num = 0xffffffff; @@ -457,6 +458,23 @@ int init_io_vol(void) return 0; } +#ifdef SET_QOS_IN_UBOOT +int update_qos(void) +{ +#define WRITE_QOS_VALUE 0x0302000c +#define READ_QOS_VALUE 0x0302000c +#define WRITE_QOS_ADDR 0xA2D10004 +#define READ_QOS_ADDR 0xA2D10000 +#define QOS_BIN_ADDR 0x8000A000 + if (readl(READ_QOS_ADDR) == READ_QOS_VALUE && + readl(WRITE_QOS_ADDR) == WRITE_QOS_VALUE) + return 0; + memcpy((void *)QOS_BIN_ADDR, qos_hex, sizeof(qos_hex)); + ((void(*)(unsigned int, unsigned int))QOS_BIN_ADDR)(WRITE_QOS_VALUE, READ_QOS_VALUE); + return 0; +} +#endif + void change_sys_pclk_250M(void) { uint32_t reg = readl(HB_SYS_PCLK); diff --git a/build.sh b/build.sh index 904fcfc2..9b78a3f5 100755 --- a/build.sh +++ b/build.sh @@ -198,6 +198,8 @@ function build() function all() { + make mrproper + make ARCH=${ARCH_UBOOT} O=${BUILD_OUTPUT_PATH} distclean build } diff --git a/include/hb_info.h b/include/hb_info.h index 39db74eb..6e9f31da 100755 --- a/include/hb_info.h +++ b/include/hb_info.h @@ -21,6 +21,7 @@ #define DEBUG_LOG(fmt, ...) #endif +//#define SET_QOS_IN_UBOOT #define HB_SWINFO_MEM_ADDR 0x020ff000 #define HB_SWINFO_MEM_MAGIC 0x57534248 #define HB_SWINFO_BOOT_OFFSET 0x4 @@ -283,5 +284,6 @@ uint32_t hb_board_type_get_by_pin(int pin_nums); char *hb_reset_reason_get(void); int hb_get_socuid(char* socuid); int init_io_vol(void); +int update_qos(void); #endif /* __HB_INFO_H__ */ diff --git a/qos/qos.lds b/qos/qos.lds new file mode 100644 index 00000000..ed8915f9 --- /dev/null +++ b/qos/qos.lds @@ -0,0 +1,61 @@ + +MEMORY { .sram : ORIGIN = 0x8000a000, + LENGTH = 0xc00 } + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(setup_c_runtime) +SECTIONS +{ + .text : { + . = ALIGN(8); + *(.__image_copy_start) + setup.o (.text*) + *(.text*) + KEEP(*(SORT(.text*))); + } >.sram + + .rodata : { + . = ALIGN(8); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } >.sram + + .data : { + . = ALIGN(8); + *(.data*) + KEEP(*(SORT(.data*))); + } >.sram + + .image_copy_end : { + . = ALIGN(8); + *(.__image_copy_end) + } >.sram + + .end : { + . = ALIGN(8); + *(.__end) + } >.sram + + _image_binary_end = .; + + .bss_start (NOLOAD) : { + . = ALIGN(8); + KEEP(*(.__bss_start)); + } >.sram + + .bss (NOLOAD) : { + *(.bss*) + . = ALIGN(8); + } >.sram + + .bss_end (NOLOAD) : { + KEEP(*(.__bss_end)); + } >.sram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/qos/set_qos.c b/qos/set_qos.c new file mode 100644 index 00000000..620174a0 --- /dev/null +++ b/qos/set_qos.c @@ -0,0 +1,68 @@ +/* + * Copyright 2021 Horizon Robotics, Inc. + */ +#define ISB asm volatile ("isb sy" : : : "memory") +#define DSB asm volatile ("dsb sy" : : : "memory") +#define DMB asm volatile ("dmb sy" : : : "memory") +#define isb() ISB +#define dsb() DSB +#define dmb() DMB +/* + * Generic virtual read/write. Note that we don't support half-word + * read/writes. We define __arch_*[bl] here, and leave __arch_*w + * to the architecture specific code. + */ +#define __arch_getl(a) (*(volatile unsigned int *)(a)) +#define __arch_putl(v, a) (*(volatile unsigned int *)(a) = (v)) +/* + * TODO: The kernel offers some more advanced versions of barriers, it might + * have some advantages to use them instead of the simple one here. + */ +#define mb() dsb() +#define __iormb() dmb() +#define __iowmb() dmb() + +#define writel(v, c) ({ unsigned int __v = v; __iowmb(); __arch_putl(__v, c); __v; }) +#define readl(c) ({ unsigned int __v = __arch_getl(c); __iormb(); __v; }) + +static void set_ddrc_qos(unsigned int write_qos, unsigned int read_qos) +{ +#define REG_DDR_PORT_READ_QOS_CTRL 0xA2D10000 +#define REG_DDR_PORT_WRITE_QOS_CTRL 0xA2D10004 + // [0]: ACE + // [1]: NOC + // [2]: CNN0 + // [3]: CNN1 + // [4]: VIO0 + // [5]: VSP + // [6]: VIO1 + // [7]: peri + + writel(read_qos, REG_DDR_PORT_READ_QOS_CTRL); + writel(write_qos, REG_DDR_PORT_WRITE_QOS_CTRL); +} + +void do_update_qos(unsigned int write_qos, unsigned int read_qos) +{ + unsigned int port_num = 0; + unsigned long reg_addr = 0; + + //a. diable axi port n + for(port_num = 0; port_num < 8; port_num++) { + reg_addr = 0xA2D00490 + 0xB0 * port_num; + writel(0, reg_addr); + } + + //b. polling axi port n is in idle state + do { + }while(0x0 != (readl(0xA2D003FC))); + + //c. Set QoS + set_ddrc_qos(write_qos, read_qos); + + //d. enable axi port n + for(port_num = 0; port_num < 8; port_num++) { + reg_addr = 0xA2D00490 + 0xB0 * port_num; + writel(1, reg_addr); + } +} diff --git a/qos/setup.S b/qos/setup.S new file mode 100644 index 00000000..e92a8cdb --- /dev/null +++ b/qos/setup.S @@ -0,0 +1,37 @@ +//#include +#include +#include +ENTRY(setup_c_runtime) + stp x29, x30, [sp,#-96]! + stp x27, x28, [sp,#80] + stp x25, x26, [sp,#64] + stp x23, x24, [sp,#48] + stp x21, x22, [sp,#32] + stp x19, x20, [sp,#16] + + mov x25, sp + + mov x20, #0xb000 + movk x20, #0x8000,LSL #16 + mov sp, x20 + stp x25, x0, [sp, #-16]! + + bl do_update_qos + + ldp x25, x0, [sp],#16 + mov sp, x25 + ldp x19, x20, [sp,#16] + ldp x21, x22, [sp,#32] + ldp x23, x24, [sp,#48] + ldp x25, x26, [sp,#64] + ldp x27, x28, [sp,#80] + ldp x29, x30, [sp],#96 + mov w0, #0x0 // #0 + ret +ENDPROC(setup_c_runtime) + +ENTRY(_asm_invalidate_icache_all) +ic ialluis +isb sy +ret +ENDPROC(_asm_invalidate_icache_all) diff --git a/scripts/Makefile.qos b/scripts/Makefile.qos new file mode 100644 index 00000000..880ddefa --- /dev/null +++ b/scripts/Makefile.qos @@ -0,0 +1,59 @@ + +src := $(obj) + +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) + +QOS_BIN := qos + +include $(srctree)/scripts/Kbuild.include +#-include include/config/auto.conf +#-include $(obj)/include/autoconf.mk + +#include $(srctree)/config.mk +#include $(srctree)/arch/$(ARCH)/Makefile +#include $(srctree)/scripts/Makefile.lib + +KBUILD_CFLAGS += -ffunction-sections -fdata-sections +LDFLAGS_FINAL += --gc-sections + +cpp_flags := -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -fno-PIE -g -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-x18 -pipe -march=armv8-a -D__LINUX_ARM_ARCH__=8 +c_flags := $(KBUILD_CFLAGS) $(cpp_flags) \ + -I $(srctree)/include/ \ + -I $(srctree)/arch/arm/include/ + +LDSCRIPT := $(srctree)/$(obj)/qos.lds + +head-y := $(addprefix $(obj)/,$(head-y)) +qos-init := $(head-y) + +ALL-y += $(obj)/$(QOS_BIN).bin + +quiet_cmd_ddr_qos = SET_QOS $@ +cmd_ddr_qos = $(CC) $(c_flags) -c $< -o $@ + +$(obj)/set_qos.o: $(obj)/set_qos.c + $(CC) $(c_flags) -c $< -o $@ + +$(obj)/setup.o: $(obj)/setup.S + $(CC) $(c_flags) -c $< -o $@ + +qos-main += $(obj)/set_qos.o +qos-main += $(obj)/setup.o + +OBJCOPYFLAGS_$(QOS_BIN) = -O binary +qos_objcopy := (cd $(obj) && $(OBJCOPY) $(OBJCOPYFLAGS_$(QOS_BIN)) qos qos.bin) + +LDFLAGS_$(QOS_BIN) += -T $(srctree)/$(obj)/qos.lds $(LDFLAGS_FINAL) + +qos := (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(QOS_BIN)) \ + $(patsubst $(obj)/%,%,$(qos-main)) \ + -Map $(QOS_BIN).map -o $(QOS_BIN)) +$(info "src tree:$(srctree), obj:$(obj)") +$(obj)/$(QOS_BIN): $(qos-main) $(srctree)/$(obj)/qos.lds + $(qos) + +$(obj)/$(QOS_BIN).bin : $(obj)/$(QOS_BIN) + $(qos_objcopy) + +all: $(ALL-y) diff --git a/tools/bin2c b/tools/bin2c new file mode 100755 index 00000000..9ebc8256 Binary files /dev/null and b/tools/bin2c differ