diff --git a/bsp/zynqmp-a53-dfzu2eg/.config b/bsp/zynqmp-a53-dfzu2eg/.config index 4f99de3aaf2..39514065601 100644 --- a/bsp/zynqmp-a53-dfzu2eg/.config +++ b/bsp/zynqmp-a53-dfzu2eg/.config @@ -11,18 +11,8 @@ # rt_vsnprintf options # # CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set -CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y -# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set -CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32 -CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32 -CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6 -CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9 -CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4 +# CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG is not set +# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set # end of rt_vsnprintf options # @@ -194,7 +184,8 @@ CONFIG_RT_USING_INTERRUPT_INFO=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x50201 +CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y +CONFIG_RT_VER_NUM=0x50300 CONFIG_RT_USING_STDC_ATOMIC=y CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 # end of RT-Thread Kernel @@ -295,7 +286,7 @@ CONFIG_RT_USING_DFS_ROMFS=y # # Device Drivers # -# CONFIG_RT_USING_DM is not set +CONFIG_RT_USING_DM=y CONFIG_RT_USING_DEV_BUS=y CONFIG_RT_USING_DEVICE_IPC=y CONFIG_RT_UNAMED_PIPE_NUMBER=64 @@ -308,8 +299,13 @@ CONFIG_RT_USING_SERIAL_V1=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=256 # CONFIG_RT_USING_SERIAL_BYPASS is not set +# CONFIG_RT_SERIAL_EARLY_HVC is not set +# CONFIG_RT_SERIAL_PL011 is not set +# CONFIG_RT_SERIAL_8250 is not set +CONFIG_RT_SERIAL_XILINX_PS=y # CONFIG_RT_USING_CAN is not set -# CONFIG_RT_USING_CPUTIME is not set +CONFIG_RT_USING_CLOCK_TIME=y +CONFIG_RT_CLOCK_TIME_ARM_ARCH=y # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set # CONFIG_RT_USING_PHY_V2 is not set @@ -323,38 +319,68 @@ CONFIG_RT_USING_RANDOM=y # CONFIG_RT_USING_INPUT_CAPTURE is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set -CONFIG_RT_USING_PM=y -CONFIG_PM_TICKLESS_THRESHOLD_TIME=2 -# CONFIG_PM_USING_CUSTOM_CONFIG is not set -# CONFIG_PM_ENABLE_DEBUG is not set -# CONFIG_PM_ENABLE_SUSPEND_SLEEP_MODE is not set -# CONFIG_PM_ENABLE_THRESHOLD_SLEEP_MODE is not set +# CONFIG_RT_USING_PM is not set CONFIG_RT_USING_RTC=y -# CONFIG_RT_USING_ALARM is not set -CONFIG_RT_USING_SOFT_RTC=y +CONFIG_RT_USING_ALARM=y +CONFIG_RT_ALARM_STACK_SIZE=8192 +CONFIG_RT_ALARM_TIMESLICE=5 +CONFIG_RT_ALARM_PRIORITY=10 +# CONFIG_RT_ALARM_USING_LOCAL_TIME is not set +# CONFIG_RT_USING_SOFT_RTC is not set +# CONFIG_RT_RTC_GOLDFISH is not set +# CONFIG_RT_RTC_PL031 is not set +CONFIG_RT_RTC_ZYNQMP=y # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set # CONFIG_RT_USING_WDT is not set # CONFIG_RT_USING_AUDIO is not set # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set -# CONFIG_RT_USING_LCD is not set +# CONFIG_RT_USING_GRAPHIC is not set # CONFIG_RT_USING_HWCRYPTO is not set # CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_LED is not set +# CONFIG_RT_USING_INPUT is not set +# CONFIG_RT_USING_MBOX is not set +# CONFIG_RT_USING_HWSPINLOCK is not set +# CONFIG_RT_USING_PHYE is not set # CONFIG_RT_USING_BLK is not set -CONFIG_RT_USING_VIRTIO=y -CONFIG_RT_USING_VIRTIO10=y -CONFIG_RT_USING_VIRTIO_MMIO_ALIGN=y -CONFIG_RT_USING_VIRTIO_BLK=y -# CONFIG_RT_USING_VIRTIO_NET is not set -CONFIG_RT_USING_VIRTIO_CONSOLE=y -CONFIG_RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR=4 -CONFIG_RT_USING_VIRTIO_GPU=y -CONFIG_RT_USING_VIRTIO_INPUT=y -CONFIG_RT_USING_PIN=y -CONFIG_RT_USING_KTIME=y -# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_SCSI is not set +# CONFIG_RT_USING_FIRMWARE is not set +# CONFIG_RT_USING_HWCACHE is not set +# CONFIG_RT_USING_REGULATOR is not set +CONFIG_RT_USING_RESET=y +# CONFIG_RT_RESET_SIMPLE is not set + +# +# Power Management (PM) Domains device drivers +# +# end of Power Management (PM) Domains device drivers + +# CONFIG_RT_USING_POWER_RESET is not set +# CONFIG_RT_USING_POWER_SUPPLY is not set +# CONFIG_RT_USING_THERMAL is not set +# CONFIG_RT_USING_DMA is not set +# CONFIG_RT_USING_MFD is not set +CONFIG_RT_USING_OFW=y +CONFIG_RT_USING_BUILTIN_FDT=y +CONFIG_RT_BUILTIN_FDT_PATH="zynqmp.dtb" +CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128 +CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8 +# CONFIG_RT_USING_PCI is not set +CONFIG_RT_USING_PIC=y +# CONFIG_RT_USING_PIC_STATISTICS is not set +CONFIG_MAX_HANDLERS=256 +CONFIG_RT_PIC_ARM_GIC=y +# CONFIG_RT_PIC_ARM_GIC_V3 is not set +CONFIG_RT_PIC_ARM_GIC_MAX_NR=1 +# CONFIG_RT_USING_PIN is not set +CONFIG_RT_USING_CLK=y # CONFIG_RT_USING_CHERRYUSB is not set + +# +# SoC (System on Chip) Drivers +# # end of Device Drivers # @@ -445,14 +471,14 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_RT_USING_RT_LINK is not set # end of Utilities -# CONFIG_RT_USING_VBUS is not set - # # Memory management # +# CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC is not set CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000 CONFIG_RT_PAGE_MAX_ORDER=11 -# CONFIG_RT_USING_MEMBLOCK is not set +CONFIG_RT_USING_MEMBLOCK=y +CONFIG_RT_INIT_MEMORY_REGIONS=128 # # Debugging @@ -471,6 +497,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # end of Using USB legacy version # CONFIG_RT_USING_FDT is not set +# CONFIG_RT_USING_RUST is not set # end of RT-Thread Components # @@ -1506,14 +1533,3 @@ CONFIG_RT_PAGE_MAX_ORDER=11 # end of RT-Thread online packages CONFIG_SOC_ZYNQMP_AARCH64=y - -# -# Hardware Drivers Config -# -CONFIG_BSP_SUPPORT_FPU=y -CONFIG_BSP_USING_UART=y -CONFIG_BSP_USING_UART0=y -CONFIG_BSP_USING_GIC=y -CONFIG_BSP_USING_GICV2=y -# CONFIG_BSP_USING_GICV3 is not set -# end of Hardware Drivers Config diff --git a/bsp/zynqmp-a53-dfzu2eg/Kconfig b/bsp/zynqmp-a53-dfzu2eg/Kconfig index 076d85af545..8e3acf95685 100644 --- a/bsp/zynqmp-a53-dfzu2eg/Kconfig +++ b/bsp/zynqmp-a53-dfzu2eg/Kconfig @@ -6,20 +6,18 @@ RTT_DIR := ../../ PKGS_DIR := packages +SOC_DM_RTC_DIR := $(BSP_DIR)/drivers/rtc +SOC_DM_SERIAL_DIR := $(BSP_DIR)/drivers/serial + source "$(RTT_DIR)/Kconfig" osource "$PKGS_DIR/Kconfig" config SOC_ZYNQMP_AARCH64 bool select ARCH_ARMV8 - select ARCH_CPU_64BIT - select ARCH_ARM_MMU - select RT_USING_CACHE select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN - select RT_USING_GIC - select BSP_USING_GIC - select ARCH_MM_MMU + select ARCH_CPU_64BIT + select RT_USING_CACHE + select RT_USING_STDC_ATOMIC default y - -source "$(BSP_DIR)/drivers/Kconfig" diff --git a/bsp/zynqmp-a53-dfzu2eg/README.md b/bsp/zynqmp-a53-dfzu2eg/README.md index 6f69deb1c63..2b6ea5dc2d6 100644 --- a/bsp/zynqmp-a53-dfzu2eg/README.md +++ b/bsp/zynqmp-a53-dfzu2eg/README.md @@ -95,7 +95,7 @@ setenv gatewayip 192.168.1.1 setenv netmask 255.255.255.0 setenv serverip 192.168.1.3 tftpboot 0x00200000 rtthread.bin -go 0x00200000 +booti 0x00200000 - ${fdt_addr} ``` 其中`192.168.1.3`为TFTP服务器的PC机的IP地址,大家可以根据自己的实际情况进行修改。 @@ -141,6 +141,7 @@ msh /> | 驱动 | 支持情况 | 备注 | | ------ | ---- | :------: | | UART | 支持 | UART0 | +| RTC | 支持 | - | | GPIO | 暂不支持 | - | | SPI | 暂不支持 | - | | SDIO | 暂不支持 | - | diff --git a/bsp/zynqmp-a53-dfzu2eg/SConstruct b/bsp/zynqmp-a53-dfzu2eg/SConstruct index 3791a1bfac4..e1c083d2aff 100644 --- a/bsp/zynqmp-a53-dfzu2eg/SConstruct +++ b/bsp/zynqmp-a53-dfzu2eg/SConstruct @@ -11,6 +11,9 @@ else: sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] from building import * +import dtc + +dtc.dts_to_dtb(RTT_ROOT, ["zynqmp.dts"], include_paths = [os.getcwd()], ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property"]) TARGET = 'rtthread.' + rtconfig.TARGET_EXT TRACE_CONFIG = "" diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/Kconfig b/bsp/zynqmp-a53-dfzu2eg/drivers/Kconfig deleted file mode 100644 index a1194aff55d..00000000000 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/Kconfig +++ /dev/null @@ -1,32 +0,0 @@ -menu "Hardware Drivers Config" - config BSP_SUPPORT_FPU - bool "Using Float" - default y - - menuconfig BSP_USING_UART - bool "Using UART" - select RT_USING_SERIAL - default y - - if BSP_USING_UART - config BSP_USING_UART0 - bool "Enabel UART 0" - default y - endif - - config BSP_USING_GIC - bool - default y - - choice - prompt "GIC Version" - default BSP_USING_GICV2 - - config BSP_USING_GICV2 - bool "GICv2" - - config BSP_USING_GICV3 - bool "GICv3" - endchoice - -endmenu diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/SConscript b/bsp/zynqmp-a53-dfzu2eg/drivers/SConscript index 7f60b2bffae..ff2e26958cf 100644 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/SConscript +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/SConscript @@ -4,7 +4,13 @@ from building import * cwd = GetCurrentDir() src = Glob('*.c') -CPPPATH = [cwd , cwd + '/zynqmp'] +CPPPATH = [cwd, cwd + "/../../../components/drivers/rtc"] + +if GetDepend(['RT_RTC_ZYNQMP']): + src += ['rtc/rtc-zynqmp.c'] + +if GetDepend(['RT_SERIAL_XILINX_PS']): + src += ['serial/xilinx_uartps.c'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/board.c b/bsp/zynqmp-a53-dfzu2eg/drivers/board.c index 08a280d9412..b23e504ce83 100644 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/board.c +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/board.c @@ -6,72 +6,12 @@ * Change Logs: * Date Author Notes * 2024-04-11 liYony the first version + * 2024-07-07 GuEe-GUI init common */ -#include -#include -#include -#include -#include -#include - -extern size_t MMUTable[]; - -#ifdef RT_USING_SMART -struct mem_desc platform_mem_desc[] = { - {KERNEL_VADDR_START, KERNEL_VADDR_START + 0x7FF00000 - 1, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM} -}; -#else -struct mem_desc platform_mem_desc[] = -{ - {0x00200000, 0x7FF00000 - 1, 0x00200000, NORMAL_MEM}, - {GIC400_DISTRIBUTOR_PPTR, GIC400_DISTRIBUTOR_PPTR + GIC400_SIZE - 1, GIC400_DISTRIBUTOR_PPTR, DEVICE_MEM}, - {GIC400_CONTROLLER_PPTR, GIC400_CONTROLLER_PPTR + GIC400_SIZE - 1, GIC400_CONTROLLER_PPTR, DEVICE_MEM}, -}; -#endif - -const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]); - -void idle_wfi(void) -{ - asm volatile("wfi"); -} +#include void rt_hw_board_init(void) { -#ifdef RT_USING_SMART - rt_hw_mmu_map_init(&rt_kernel_space, (void *)0xfffffffff0000000, 0x10000000, MMUTable, PV_OFFSET); -#else - rt_hw_mmu_map_init(&rt_kernel_space, (void *)0xffffd0000000, 0x10000000, MMUTable, 0); -#endif - rt_region_t init_page_region; - init_page_region.start = PAGE_START; - init_page_region.end = PAGE_END; - rt_page_init(init_page_region); - - rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, platform_mem_desc_size); - -#ifdef RT_USING_HEAP - /* initialize system heap */ - rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); -#endif - /* initialize hardware interrupt */ - rt_hw_interrupt_init(); - - /* initialize uart */ - rt_hw_uart_init(); - - /* initialize timer for os tick */ - rt_hw_gtimer_init(); - - rt_thread_idle_sethook(idle_wfi); -#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) - /* set console device */ - rt_console_set_device(RT_CONSOLE_DEVICE_NAME); -#endif - rt_kprintf("heap: [0x%08x - 0x%08x]\n", HEAP_BEGIN, HEAP_END); - -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); -#endif + rt_hw_common_setup(); } diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/board.h b/bsp/zynqmp-a53-dfzu2eg/drivers/board.h index 53f4a3a89de..633d44a7fcb 100644 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/board.h +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/board.h @@ -11,26 +11,6 @@ #ifndef __BOARD_H__ #define __BOARD_H__ -#include - -extern unsigned char __bss_end; - -#define HEAP_BEGIN ((void*)&__bss_end) - -#ifdef RT_USING_SMART -#define HEAP_END ((size_t)KERNEL_VADDR_START + 64 * 1024 * 1024) -#define PAGE_START HEAP_END -#define PAGE_END ((size_t)KERNEL_VADDR_START + 128 * 1024 * 1024) -#else -#define KERNEL_VADDR_START 0x0 - -#define HEAP_END (KERNEL_VADDR_START + 64 * 1024 * 1024) -#define PAGE_START HEAP_END -#define PAGE_END ((size_t)PAGE_START + 64 * 1024 * 1024) -#endif - void rt_hw_board_init(void); -int rt_hw_uart_init(void); - #endif /* __BOARD_H__ */ diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/drv_uart.c b/bsp/zynqmp-a53-dfzu2eg/drivers/drv_uart.c deleted file mode 100644 index efaed8a1c2c..00000000000 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/drv_uart.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2024-04-11 liYony the first version - */ - -#include -#include -#include -#include "board.h" -#include "zynqmp_uart.h" - -#define ZYNQMP_UART_DEVICE_DEFAULT(base, irq, clk) {{ \ - .ops = &_zynqmp_ops, \ - .config = RT_SERIAL_CONFIG_DEFAULT \ - }, \ - .hw_base = base, \ - .irqno = irq, \ - .in_clk = clk \ -} - -struct zynqmp_uart_device -{ - struct rt_serial_device device; - rt_ubase_t hw_base; - rt_uint32_t irqno; - rt_uint32_t in_clk; -}; - -static void _uart_set_fifo_threshold(rt_ubase_t base, rt_uint8_t trigger_level) -{ - rt_uint32_t reg_triger; - - /* Assert validates the input arguments */ - RT_ASSERT(base != RT_NULL); - RT_ASSERT(trigger_level <= (rt_uint8_t)XUARTPS_RXWM_MASK); - - reg_triger = ((rt_uint32_t)trigger_level) & (rt_uint32_t)XUARTPS_RXWM_MASK; - - /* - * Write the new value for the FIFO control register to it such that the - * threshold is changed - */ - writel(reg_triger, base + XUARTPS_RXWM_OFFSET); -} - -static void _uart_set_interrupt_mask(rt_ubase_t base, rt_uint32_t mask) -{ - rt_uint32_t temp_mask = mask; - - RT_ASSERT(base != RT_NULL); - - temp_mask &= (rt_uint32_t)XUARTPS_IXR_MASK; - - writel(temp_mask, base + XUARTPS_IER_OFFSET); - writel((~temp_mask), base + XUARTPS_IDR_OFFSET); -} - -static rt_err_t _uart_baudrate_init(rt_ubase_t base, struct serial_configure *cfg, rt_uint32_t in_clk) -{ - rt_uint32_t iter_baud_div; /* Iterator for available baud divisor values */ - rt_uint32_t brgr_value; /* Calculated value for baud rate generator */ - rt_uint32_t calc_baudrate; /* Calculated baud rate */ - rt_uint32_t baud_error; /* Diff between calculated and requested baud rate */ - rt_uint32_t best_brgr = 0U; /* Best value for baud rate generator */ - rt_uint8_t best_baud_div = 0U; /* Best value for baud divisor */ - rt_uint32_t best_error = 0xFFFFFFFFU; - rt_uint32_t percent_error; - rt_uint32_t mode_reg; - rt_uint32_t input_clk; - rt_uint32_t temp_reg; - - /* Asserts validate the input arguments */ - RT_ASSERT(base != RT_NULL); - RT_ASSERT(cfg->baud_rate <= (rt_uint32_t)XUARTPS_MAX_RATE); - RT_ASSERT(cfg->baud_rate >= (rt_uint32_t)XUARTPS_MIN_RATE); - - /* - * Make sure the baud rate is not impossilby large. - * Fastest possible baud rate is Input Clock / 2. - */ - if ((cfg->baud_rate * 2) > in_clk) - { - return -RT_EINVAL; - } - /* Check whether the input clock is divided by 8 */ - mode_reg = readl(base + XUARTPS_MR_OFFSET); - - input_clk = in_clk; - if (mode_reg & XUARTPS_MR_CLKSEL) - { - input_clk = in_clk / 8; - } - - /* - * Determine the Baud divider. It can be 4to 254. - * Loop through all possible combinations - */ - for (iter_baud_div = 4; iter_baud_div < 255; iter_baud_div++) - { - - /* Calculate the value for BRGR register */ - brgr_value = input_clk / (cfg->baud_rate * (iter_baud_div + 1)); - - /* Calculate the baud rate from the BRGR value */ - calc_baudrate = input_clk / (brgr_value * (iter_baud_div + 1)); - - /* Avoid unsigned integer underflow */ - if (cfg->baud_rate > calc_baudrate) - { - baud_error = cfg->baud_rate - calc_baudrate; - } - else - { - baud_error = calc_baudrate - cfg->baud_rate; - } - - /* Find the calculated baud rate closest to requested baud rate. */ - if (best_error > baud_error) - { - - best_brgr = brgr_value; - best_baud_div = iter_baud_div; - best_error = baud_error; - } - } - - /* Make sure the best error is not too large. */ - percent_error = (best_error * 100) / cfg->baud_rate; - if (XUARTPS_MAX_BAUD_ERROR_RATE < percent_error) - { - return -RT_EINVAL; - } - - /* Disable TX and RX to avoid glitches when setting the baud rate. */ - temp_reg = (((readl(base + XUARTPS_CR_OFFSET)) & ((rt_uint32_t)(~XUARTPS_CR_EN_DIS_MASK))) | - ((rt_uint32_t)XUARTPS_CR_RX_DIS | (rt_uint32_t)XUARTPS_CR_TX_DIS)); - writel(temp_reg, base + XUARTPS_CR_OFFSET); - - /* Set the baud rate divisor */ - writel(best_brgr, base + XUARTPS_BAUDGEN_OFFSET); - writel(best_baud_div, base + XUARTPS_BAUDDIV_OFFSET); - - /* RX and TX SW reset */ - writel(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST, base + XUARTPS_CR_OFFSET); - - /* Enable device */ - temp_reg = (((readl(base + XUARTPS_CR_OFFSET)) & ((rt_uint32_t)(~XUARTPS_CR_EN_DIS_MASK))) | - ((rt_uint32_t)XUARTPS_CR_RX_EN | (rt_uint32_t)XUARTPS_CR_TX_EN)); - writel(temp_reg, base + XUARTPS_CR_OFFSET); - - return RT_EOK; -} - -static rt_err_t zynqmp_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) -{ - struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial; - - RT_ASSERT(uart != RT_NULL); - - if (_uart_baudrate_init(uart->hw_base, cfg, uart->in_clk) != RT_EOK) - { - return -RT_ERROR; - } - - rt_uint32_t mode_reg = 0U; - - /* Set the parity mode */ - mode_reg = readl(uart->hw_base + XUARTPS_MR_OFFSET); - - /* Mask off what's already there */ - mode_reg &= (~((rt_uint32_t)XUARTPS_MR_CHARLEN_MASK | - (rt_uint32_t)XUARTPS_MR_STOPMODE_MASK | - (rt_uint32_t)XUARTPS_MR_PARITY_MASK)); - - switch (cfg->data_bits) - { - case DATA_BITS_6: - mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_6_BIT; - break; - case DATA_BITS_7: - mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_7_BIT; - break; - case DATA_BITS_8: - mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_8_BIT; - break; - default: - mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_8_BIT; - break; - } - - switch (cfg->stop_bits) - { - case STOP_BITS_1: - mode_reg |= (rt_uint32_t)XUARTPS_MR_STOPMODE_1_BIT; - break; - case STOP_BITS_2: - mode_reg |= (rt_uint32_t)XUARTPS_MR_STOPMODE_2_BIT; - break; - default: - mode_reg |= (rt_uint32_t)XUARTPS_MR_STOPMODE_1_BIT; - break; - } - - switch (cfg->parity) - { - case PARITY_NONE: - mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_NONE; - break; - case PARITY_ODD: - mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_ODD; - break; - case PARITY_EVEN: - mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_EVEN; - break; - default: - mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_NONE; - break; - } - - /* Write the mode register out */ - writel(mode_reg, uart->hw_base + XUARTPS_MR_OFFSET); - - /* Set the RX FIFO trigger at 8 data bytes. */ - writel(0x08U, uart->hw_base + XUARTPS_RXWM_OFFSET); - - /* Set the RX timeout to 1, which will be 4 character time */ - writel(0x01U, uart->hw_base + XUARTPS_RXTOUT_OFFSET); - - /* Disable all interrupts, polled mode is the default */ - writel(XUARTPS_IXR_MASK, uart->hw_base + XUARTPS_IDR_OFFSET); - - return RT_EOK; -} - -static rt_err_t zynqmp_uart_control(struct rt_serial_device *serial, int cmd, void *arg) -{ - struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial; - - RT_ASSERT(uart != RT_NULL); - - switch (cmd) - { - case RT_DEVICE_CTRL_CLR_INT: - /* Disable the UART Interrupt */ - rt_hw_interrupt_mask(uart->irqno); - _uart_set_interrupt_mask(uart->hw_base, 0U); - break; - case RT_DEVICE_CTRL_SET_INT: - /* Enable the UART Interrupt */ - _uart_set_fifo_threshold(uart->hw_base, 1); - rt_hw_interrupt_umask(uart->irqno); - _uart_set_interrupt_mask(uart->hw_base, XUARTPS_IXR_RXOVR); - break; - } - - return RT_EOK; -} - -static int zynqmp_uart_putc(struct rt_serial_device *serial, char c) -{ - struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial; - - RT_ASSERT(uart != RT_NULL); - - /* Wait until there is space in TX FIFO */ - while ((readl(uart->hw_base + XUARTPS_SR_OFFSET) & - XUARTPS_SR_TXFULL) == XUARTPS_SR_TXFULL) - { - ; - } - - /* Write the byte into the TX FIFO */ - writel((rt_uint32_t)c, uart->hw_base + XUARTPS_FIFO_OFFSET); - - return 1; -} - -static int zynqmp_uart_getc(struct rt_serial_device *serial) -{ - struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial; - - RT_ASSERT(uart != RT_NULL); - - /* Wait until there is data */ - if ((readl(uart->hw_base + XUARTPS_SR_OFFSET) & - XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY) - { - return -1; - } - - int ch = readl(uart->hw_base + XUARTPS_FIFO_OFFSET); - - return ch; -} - -static const struct rt_uart_ops _zynqmp_ops = -{ - zynqmp_uart_configure, - zynqmp_uart_control, - zynqmp_uart_putc, - zynqmp_uart_getc, -}; - -#ifdef BSP_USING_UART0 -static struct zynqmp_uart_device _uart0_device = - ZYNQMP_UART_DEVICE_DEFAULT(ZYNQMP_UART0_BASE, ZYNQMP_UART0_IRQNUM, ZYNQMP_UART0_CLK_FREQ_HZ); -#endif - -static void rt_hw_uart_isr(int irqno, void *param) -{ - struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)param; - - RT_ASSERT(uart != RT_NULL); - struct rt_serial_device *serial = &(uart->device); - rt_uint32_t isr_status; - - isr_status = readl(uart->hw_base + XUARTPS_IMR_OFFSET); - isr_status &= readl(uart->hw_base + XUARTPS_ISR_OFFSET); - if (isr_status & (rt_uint32_t)XUARTPS_IXR_RXOVR) - { - writel(XUARTPS_IXR_RXOVR, uart->hw_base + XUARTPS_ISR_OFFSET); - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); - } -} - -int rt_hw_uart_init(void) -{ - struct zynqmp_uart_device *uart = RT_NULL; - -#ifdef BSP_USING_UART0 - uart = &_uart0_device; - _uart0_device.hw_base = (rt_size_t)rt_ioremap((void*)_uart0_device.hw_base, ZYNQMP_UART0_SIZE); - /* register UART0 device */ - rt_hw_serial_register(&uart->device, "uart0", - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, - uart); - rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, uart, "uart0"); -#endif - - return 0; -} diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/drv_uart.h b/bsp/zynqmp-a53-dfzu2eg/drivers/drv_uart.h deleted file mode 100644 index 20d2ca3c18a..00000000000 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/drv_uart.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2024-04-11 liYony the first version - */ - -#ifndef __DRV_UART_H__ -#define __DRV_UART_H__ - -#include - -int rt_hw_uart_init(void); - -#endif /* __DRV_UART_H__ */ diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/rtc/Kconfig b/bsp/zynqmp-a53-dfzu2eg/drivers/rtc/Kconfig new file mode 100755 index 00000000000..6d85b6aed6e --- /dev/null +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/rtc/Kconfig @@ -0,0 +1,5 @@ +config RT_RTC_ZYNQMP + bool "Xilinx Zynq Ultrascale+ MPSoC RTC" + depends on RT_USING_RTC + select RT_USING_ALARM + default y diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/rtc/rtc-zynqmp.c b/bsp/zynqmp-a53-dfzu2eg/drivers/rtc/rtc-zynqmp.c new file mode 100755 index 00000000000..50c419095e4 --- /dev/null +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/rtc/rtc-zynqmp.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-07-07 GuEe-GUI first version + */ + +#include "rtc_dm.h" + +#define DBG_TAG "rtc.zynqmp" +#define DBG_LVL DBG_INFO +#include + +#define RTC_SET_TM_WR 0x00 +#define RTC_SET_TM_RD 0x04 +#define RTC_CALIB_WR 0x08 +#define RTC_CALIB_RD 0x0c +#define RTC_CUR_TM 0x10 +#define RTC_CUR_TICK 0x14 +#define RTC_ALRM 0x18 +#define RTC_INT_STS 0x20 +#define RTC_INT_MASK 0x24 +#define RTC_INT_EN 0x28 +#define RTC_INT_DIS 0x2c +#define RTC_CTRL 0x40 + +#define RTC_FR_EN RT_BIT(20) +#define RTC_FR_DATSHIFT 16 +#define RTC_TICK_MASK 0xffff +#define RTC_INT_SEC RT_BIT(0) +#define RTC_INT_ALRM RT_BIT(1) +#define RTC_OSC_EN RT_BIT(24) +#define RTC_BATT_EN RT_BIT(31) + +#define RTC_ALRM_MASK RT_BIT(1) +#define RTC_MSEC 1000 + +struct zynqmp_rtc +{ + struct rt_device parent; + + int alarm_irq; + int sec_irq; + void *base; + + struct rt_clk *rtc_clk; + rt_uint32_t freq; +}; + +#define raw_to_zynqmp_rtc(raw) rt_container_of(raw, struct zynqmp_rtc, parent) + +static void zynqmp_get_secs(struct zynqmp_rtc *zrtc, time_t *sec) +{ + if (HWREG32(zrtc->base + RTC_INT_STS) & RTC_INT_SEC) + { + /* + * RTC has updated the CURRENT_TIME with the time written into + * SET_TIME_WRITE register. + */ + *(rt_ubase_t *)sec = HWREG32(zrtc->base + RTC_CUR_TM); + } + else + { + /* + * Time written in SET_TIME_WRITE has not yet updated into + * the seconds read register, so read the time from the + * SET_TIME_WRITE instead of CURRENT_TIME register. + * Since we add +1 sec while writing, we need to -1 sec while + * reading. + */ + *(rt_ubase_t *)sec = HWREG32(zrtc->base + RTC_SET_TM_RD) - 1; + } +} + +static void zynqmp_set_secs(struct zynqmp_rtc *zrtc, time_t *sec) +{ + /* + * The value written will be updated after 1 sec into the + * seconds read register, so we need to program time +1 sec + * to get the correct time on read. + */ + HWREG32(zrtc->base + RTC_SET_TM_WR) = *sec + 1; + + /* + * Clear the rtc interrupt status register after setting the + * time. During a read_time function, the code should read the + * RTC_INT_STATUS register and if bit 0 is still 0, it means + * that one second has not elapsed yet since RTC was set and + * the current time should be read from SET_TIME_READ register; + * otherwise, CURRENT_TIME register is read to report the time + */ + HWREG32(zrtc->base + RTC_INT_STS) = RTC_INT_SEC; +} + +static void zynqmp_get_alarm(struct zynqmp_rtc *zrtc, struct rt_rtc_wkalarm *alarm) +{ + rtc_timestamp_to_wkalarm(HWREG32(zrtc->base + RTC_ALRM), alarm); + alarm->enable = !!(HWREG32(zrtc->base + RTC_INT_MASK) & RTC_INT_ALRM); +} + +static void zynqmp_set_alarm(struct zynqmp_rtc *zrtc, struct rt_rtc_wkalarm *alarm) +{ + rt_tick_t timeout; + + HWREG32(zrtc->base + RTC_ALRM) = (rt_uint32_t)rtc_wkalarm_to_timestamp(alarm); + + if (alarm->enable) + { + timeout = rt_tick_from_millisecond(RTC_MSEC); + timeout += rt_tick_get(); + + while (RT_TRUE) + { + if (!((HWREG32(zrtc->base + RTC_INT_STS) & RTC_ALRM_MASK) == RTC_ALRM_MASK)) + { + break; + } + + if (rt_tick_get() > timeout) + { + LOG_E("%s: Clearing alarm status bit time out", + rt_dm_dev_get_name(&zrtc->parent)); + return; + } + + HWREG32(zrtc->base + RTC_INT_STS) = RTC_INT_ALRM; + } + + HWREG32(zrtc->base + RTC_INT_EN) = RTC_INT_ALRM; + } + else + { + HWREG32(zrtc->base + RTC_INT_DIS) = RTC_INT_ALRM; + } +} + +static rt_err_t zynqmp_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t err = RT_EOK; + struct zynqmp_rtc *zrtc = raw_to_zynqmp_rtc(dev); + + if (!args) + { + return -RT_EINVAL; + } + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + zynqmp_get_secs(zrtc, args); + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + zynqmp_set_secs(zrtc, args); + break; + + case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: + zynqmp_get_secs(zrtc, (time_t *)&((struct timeval *)args)->tv_sec); + break; + + case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: + zynqmp_set_secs(zrtc, (time_t *)&((struct timeval *)args)->tv_sec); + break; + + case RT_DEVICE_CTRL_RTC_GET_ALARM: + zynqmp_get_alarm(zrtc, args); + break; + + case RT_DEVICE_CTRL_RTC_SET_ALARM: + zynqmp_set_alarm(zrtc, args); + break; + + default: + err = -RT_EINVAL; + break; + } + + return err; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops zynqmp_rtc_ops = +{ + .control = zynqmp_control, +}; +#endif + +static void zynqmp_rtc_isr(int irqno, void *param) +{ + rt_uint32_t status; + struct zynqmp_rtc *zrtc = param; + + status = HWREG32(zrtc->base + RTC_INT_STS); + + /* Check if interrupt asserted */ + if (!(status & (RTC_INT_SEC | RTC_INT_ALRM))) + { + return; + } + + /* Disable RTC_INT_ALRM interrupt only */ + HWREG32(zrtc->base + RTC_INT_DIS) = RTC_INT_ALRM; + + if (status & RTC_INT_ALRM) + { + rt_alarm_update(&zrtc->parent, 1); + } +} + +static rt_err_t zynqmp_probe(struct rt_platform_device *pdev) +{ + rt_err_t err = RT_EOK; + rt_uint32_t value; + const char *dev_name; + struct rt_device *dev = &pdev->parent; + struct zynqmp_rtc *zrtc = rt_calloc(1, sizeof(*zrtc)); + + if (!zrtc) + { + return -RT_ENOMEM; + } + + zrtc->base = rt_dm_dev_iomap(dev, 0); + + if (!zrtc->base) + { + err = -RT_EIO; + goto _fail; + } + + zrtc->alarm_irq = rt_dm_dev_get_irq_by_name(dev, "alarm"); + + if (zrtc->alarm_irq < 0) + { + err = zrtc->alarm_irq; + goto _fail; + } + + zrtc->sec_irq = rt_dm_dev_get_irq_by_name(dev, "sec"); + + if (zrtc->sec_irq < 0) + { + err = zrtc->sec_irq; + goto _fail; + } + + zrtc->rtc_clk = rt_clk_get_by_name(dev, "rtc_clk"); + + if (rt_is_err(zrtc->rtc_clk)) + { + err = rt_ptr_err(zrtc->rtc_clk); + goto _fail; + } + + if (!(zrtc->freq = rt_clk_get_rate(zrtc->rtc_clk))) + { + if ((err = rt_dm_dev_prop_read_u32(dev, "calibration", &zrtc->freq))) + { + goto _fail; + } + } + + dev->user_data = zrtc; + + zrtc->parent.type = RT_Device_Class_RTC; +#ifdef RT_USING_DEVICE_OPS + zrtc->parent.ops = &zynqmp_rtc_ops; +#else + zrtc->parent.control = zynqmp_rtc_control; +#endif + + rtc_dev_set_name(&zrtc->parent); + dev_name = rt_dm_dev_get_name(&zrtc->parent); + rt_device_register(&zrtc->parent, dev_name, RT_DEVICE_FLAG_RDWR); + + rt_hw_interrupt_install(zrtc->alarm_irq, zynqmp_rtc_isr, zrtc, "rtc-zynqmp-alarm"); + rt_hw_interrupt_umask(zrtc->alarm_irq); + + rt_hw_interrupt_install(zrtc->sec_irq, zynqmp_rtc_isr, zrtc, "rtc-zynqmp-sec"); + rt_hw_interrupt_umask(zrtc->sec_irq); + + if (!HWREG32(zrtc->base + RTC_CALIB_RD)) + { + HWREG32(zrtc->base + RTC_CALIB_WR) = zrtc->freq; + } + + /* Enable RTC switch to battery when VCC_PSAUX is not available */ + value = HWREG32(zrtc->base + RTC_CTRL); + value |= RTC_BATT_EN; + HWREG32(zrtc->base + RTC_CTRL) = value; + + return RT_EOK; + +_fail: + if (zrtc->base) + { + rt_iounmap(zrtc->base); + } + + if (!rt_is_err_or_null(zrtc->rtc_clk)) + { + rt_clk_put(zrtc->rtc_clk); + } + + rt_free(zrtc); + + return err; +} + +static rt_err_t zynqmp_remove(struct rt_platform_device *pdev) +{ + struct zynqmp_rtc *zrtc = pdev->parent.user_data; + + rt_hw_interrupt_mask(zrtc->alarm_irq); + rt_pic_detach_irq(zrtc->alarm_irq, zrtc); + + rt_hw_interrupt_mask(zrtc->sec_irq); + rt_pic_detach_irq(zrtc->sec_irq, zrtc); + + rt_device_unregister(&zrtc->parent); + + rt_clk_put(zrtc->rtc_clk); + + rt_free(zrtc); + + return RT_EOK; +} + +static const struct rt_ofw_node_id zynqmp_ofw_ids[] = +{ + { .compatible = "xlnx,zynqmp-rtc" }, + { /* sentinel */ } +}; + +static struct rt_platform_driver zynqmp_driver = +{ + .name = "rtc-zynqmp", + .ids = zynqmp_ofw_ids, + + .probe = zynqmp_probe, + .remove = zynqmp_remove, +}; +RT_PLATFORM_DRIVER_EXPORT(zynqmp_driver); diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/serial/Kconfig b/bsp/zynqmp-a53-dfzu2eg/drivers/serial/Kconfig new file mode 100755 index 00000000000..6c95e71f7be --- /dev/null +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/serial/Kconfig @@ -0,0 +1,5 @@ +config RT_SERIAL_XILINX_PS + bool "Cadence (Xilinx Zynq) UART" + depends on RT_USING_CLK + depends on RT_USING_RESET + default y diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/serial/xilinx_uartps.c b/bsp/zynqmp-a53-dfzu2eg/drivers/serial/xilinx_uartps.c new file mode 100755 index 00000000000..618433e5bb0 --- /dev/null +++ b/bsp/zynqmp-a53-dfzu2eg/drivers/serial/xilinx_uartps.c @@ -0,0 +1,826 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-04-11 liYony the first version + * 2024-07-07 GuEe-GUI port to the DM + */ + +#include +#include + +#include +#include +#include + +/* Register offsets for the UART. */ +#define CDNS_UART_CR 0x00 /* Control Register */ +#define CDNS_UART_MR 0x04 /* Mode Register */ +#define CDNS_UART_IER 0x08 /* Interrupt Enable */ +#define CDNS_UART_IDR 0x0c /* Interrupt Disable */ +#define CDNS_UART_IMR 0x10 /* Interrupt Mask */ +#define CDNS_UART_ISR 0x14 /* Interrupt Status */ +#define CDNS_UART_BAUDGEN 0x18 /* Baud Rate Generator */ +#define CDNS_UART_RXTOUT 0x1c /* RX Timeout */ +#define CDNS_UART_RXWM 0x20 /* RX FIFO Trigger Level */ +#define CDNS_UART_MODEMCR 0x24 /* Modem Control */ +#define CDNS_UART_MODEMSR 0x28 /* Modem Status */ +#define CDNS_UART_SR 0x2c /* Channel Status */ +#define CDNS_UART_FIFO 0x30 /* FIFO */ +#define CDNS_UART_BAUDDIV 0x34 /* Baud Rate Divider */ +#define CDNS_UART_FLOWDEL 0x38 /* Flow Delay */ +#define CDNS_UART_IRRX_PWIDTH 0x3c /* IR Min Received Pulse Width */ +#define CDNS_UART_IRTX_PWIDTH 0x40 /* IR Transmitted pulse Width */ +#define CDNS_UART_TXWM 0x44 /* TX FIFO Trigger Level */ +#define CDNS_UART_RXBS 0x48 /* RX FIFO byte status register */ + +/* Control Register Bit Definitions */ +#define CDNS_UART_CR_STOPBRK 0x00000100 /* Stop TX break */ +#define CDNS_UART_CR_STARTBRK 0x00000080 /* Set TX break */ +#define CDNS_UART_CR_TX_DIS 0x00000020 /* TX disabled. */ +#define CDNS_UART_CR_TX_EN 0x00000010 /* TX enabled */ +#define CDNS_UART_CR_RX_DIS 0x00000008 /* RX disabled. */ +#define CDNS_UART_CR_RX_EN 0x00000004 /* RX enabled */ +#define CDNS_UART_CR_TXRST 0x00000002 /* TX logic reset */ +#define CDNS_UART_CR_RXRST 0x00000001 /* RX logic reset */ +#define CDNS_UART_CR_RST_TO 0x00000040 /* Restart Timeout Counter */ +#define CDNS_UART_RXBS_PARITY 0x00000001 /* Parity error status */ +#define CDNS_UART_RXBS_FRAMING 0x00000002 /* Framing error status */ +#define CDNS_UART_RXBS_BRK 0x00000004 /* Overrun error status */ + +/* + * Mode Register: + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + */ +#define CDNS_UART_MR_CLKSEL 0x00000001 /* Pre-scalar selection */ +#define CDNS_UART_MR_CHMODE_L_LOOP 0x00000200 /* Local loop back mode */ +#define CDNS_UART_MR_CHMODE_NORM 0x00000000 /* Normal mode */ +#define CDNS_UART_MR_CHMODE_MASK 0x00000300 /* Mask for mode bits */ + +#define CDNS_UART_MR_STOPMODE_2_BIT 0x00000080 /* 2 stop bits */ +#define CDNS_UART_MR_STOPMODE_1_BIT 0x00000000 /* 1 stop bit */ + +#define CDNS_UART_MR_PARITY_NONE 0x00000020 /* No parity mode */ +#define CDNS_UART_MR_PARITY_MARK 0x00000018 /* Mark parity mode */ +#define CDNS_UART_MR_PARITY_SPACE 0x00000010 /* Space parity mode */ +#define CDNS_UART_MR_PARITY_ODD 0x00000008 /* Odd parity mode */ +#define CDNS_UART_MR_PARITY_EVEN 0x00000000 /* Even parity mode */ + +#define CDNS_UART_MR_CHARLEN_6_BIT 0x00000006 /* 6 bits data */ +#define CDNS_UART_MR_CHARLEN_7_BIT 0x00000004 /* 7 bits data */ +#define CDNS_UART_MR_CHARLEN_8_BIT 0x00000000 /* 8 bits data */ + +/* + * Interrupt Registers: + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * All four registers have the same bit definitions. + */ +#define CDNS_UART_IXR_TOUT 0x00000100 /* RX Timeout error interrupt */ +#define CDNS_UART_IXR_PARITY 0x00000080 /* Parity error interrupt */ +#define CDNS_UART_IXR_FRAMING 0x00000040 /* Framing error interrupt */ +#define CDNS_UART_IXR_OVERRUN 0x00000020 /* Overrun error interrupt */ +#define CDNS_UART_IXR_TXFULL 0x00000010 /* TX FIFO Full interrupt */ +#define CDNS_UART_IXR_TXEMPTY 0x00000008 /* TX FIFO empty interrupt */ +#define CDNS_UART_ISR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt */ +#define CDNS_UART_IXR_RXTRIG 0x00000001 /* RX FIFO trigger interrupt */ +#define CDNS_UART_IXR_RXFULL 0x00000004 /* RX FIFO full interrupt. */ +#define CDNS_UART_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ +#define CDNS_UART_IXR_RXMASK 0x000021e7 /* Valid RX bit mask */ + +/* + * Do not enable parity error interrupt for the following + * reason: When parity error interrupt is enabled, each Rx + * parity error always results in 2 events. The first one + * being parity error interrupt and the second one with a + * proper Rx interrupt with the incoming data. Disabling + * parity error interrupt ensures better handling of parity + * error events. With this change, for a parity error case, we + * get a Rx interrupt with parity error set in ISR register + * and we still handle parity errors in the desired way. + */ + +#define CDNS_UART_RX_IRQS (CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT) + +/* Goes in read_status_mask for break detection as the HW doesn't do it*/ +#define CDNS_UART_IXR_BRK 0x00002000 +#define CDNS_UART_RXWM_MASK 0x0000003f /* Valid bits mask */ + +/* + * Modem Control register: + * The read/write Modem Control register controls the interface with the modem + * or data set, or a peripheral device emulating a modem. + */ +#define CDNS_UART_MODEMCR_FCM 0x00000020 /* Automatic flow control mode */ +#define CDNS_UART_MODEMCR_RTS 0x00000002 /* Request to send output control */ +#define CDNS_UART_MODEMCR_DTR 0x00000001 /* Data Terminal Ready */ + +/* + * Modem Status register: + * The read/write Modem Status register reports the interface with the modem + * or data set, or a peripheral device emulating a modem. + */ +#define CDNS_UART_MODEMSR_DCD RT_BIT(7) /* Data Carrier Detect */ +#define CDNS_UART_MODEMSR_RI RT_BIT(6) /* Ting Indicator */ +#define CDNS_UART_MODEMSR_DSR RT_BIT(5) /* Data Set Ready */ +#define CDNS_UART_MODEMSR_CTS RT_BIT(4) /* Clear To Send */ + +/* + * Channel Status Register: + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + */ +#define CDNS_UART_SR_RXEMPTY 0x00000002 /* RX FIFO empty */ +#define CDNS_UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ +#define CDNS_UART_SR_TXFULL 0x00000010 /* TX FIFO full */ +#define CDNS_UART_SR_RXTRIG 0x00000001 /* Rx Trigger */ +#define CDNS_UART_SR_TACTIVE 0x00000800 /* TX state machine active */ + +/* baud dividers min/max values */ +#define CDNS_UART_BDIV_MIN 4 +#define CDNS_UART_BDIV_MAX 255 +#define CDNS_UART_CD_MAX 65535 + +struct cdns_uart_soc_data +{ + rt_uint32_t quirks; +}; + +struct cdns_uart +{ + struct rt_serial_device parent; + + int irq; + void *base; + rt_ubase_t freq; + struct rt_clk *clk; + struct rt_clk *pclk; + struct rt_reset_control *rstc; + + struct rt_clk_notifier clk_rate_notifier; + struct rt_spinlock spinlock; +}; + +#define raw_to_cdns_uart(raw) rt_container_of(raw, struct cdns_uart, parent) + +static rt_uint32_t cdns_uart_calc_baud_divs(rt_ubase_t freq, rt_uint32_t baud_rate, + rt_uint32_t *rbdiv, rt_uint32_t *rcd, rt_int32_t *div8) +{ + rt_uint32_t cd, bdiv, calc_baud, bestbaud = 0, bauderror, besterror = ~0; + + if (baud_rate < freq / ((CDNS_UART_BDIV_MAX + 1) * CDNS_UART_CD_MAX)) + { + *div8 = 1; + freq /= 8; + } + else + { + *div8 = 0; + } + + for (bdiv = CDNS_UART_BDIV_MIN; bdiv <= CDNS_UART_BDIV_MAX; ++bdiv) + { + cd = RT_DIV_ROUND_CLOSEST(freq, baud_rate * (bdiv + 1)); + + if (cd < 1 || cd > CDNS_UART_CD_MAX) + { + continue; + } + + calc_baud = freq / (cd * (bdiv + 1)); + + if (baud_rate > calc_baud) + { + bauderror = baud_rate - calc_baud; + } + else + { + bauderror = calc_baud - baud_rate; + } + + if (besterror > bauderror) + { + *rbdiv = bdiv; + *rcd = cd; + bestbaud = calc_baud; + besterror = bauderror; + } + } + + if (((besterror * 100) / baud_rate) < 3) + { + bestbaud = baud_rate; + } + + return bestbaud; +} + +static rt_uint32_t cdns_uart_set_baud_rate(struct cdns_uart *cdns_uart, + struct serial_configure *cfg) +{ + rt_int32_t div8; + rt_uint32_t cd = 0, bdiv = 0, mreg, calc_baud; + + calc_baud = cdns_uart_calc_baud_divs(cdns_uart->freq, cfg->baud_rate, &bdiv, &cd, &div8); + mreg = HWREG32(cdns_uart->base + CDNS_UART_MR); + + if (div8) + { + mreg |= CDNS_UART_MR_CLKSEL; + } + else + { + mreg &= ~CDNS_UART_MR_CLKSEL; + } + + HWREG32(cdns_uart->base + CDNS_UART_MR) = mreg; + HWREG32(cdns_uart->base + CDNS_UART_BAUDGEN) = cd; + HWREG32(cdns_uart->base + CDNS_UART_BAUDDIV) = bdiv; + + return calc_baud; +} + +static rt_err_t cdns_uart_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + rt_err_t err = RT_EOK; + rt_ubase_t level; + rt_uint32_t ctrl_reg, mode_reg, minbaud, maxbaud; + struct cdns_uart *cdns_uart = raw_to_cdns_uart(serial); + + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + /* Disable the TX and RX to set baud rate */ + ctrl_reg = HWREG32(cdns_uart->base + CDNS_UART_CR); + ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; + HWREG32(cdns_uart->base + CDNS_UART_CR) = ctrl_reg; + + minbaud = cdns_uart->freq / ((CDNS_UART_BDIV_MAX + 1) * CDNS_UART_CD_MAX * 8); + maxbaud = cdns_uart->freq / (CDNS_UART_BDIV_MIN + 1); + + if (cfg->baud_rate < minbaud || cfg->baud_rate > maxbaud) + { + err = -RT_ENOSYS; + goto _out_lock; + } + + cdns_uart_set_baud_rate(cdns_uart, cfg); + + /* Set TX/RX Reset */ + ctrl_reg = HWREG32(cdns_uart->base + CDNS_UART_CR); + ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; + HWREG32(cdns_uart->base + CDNS_UART_CR) = ctrl_reg; + + while (HWREG32(cdns_uart->base + CDNS_UART_CR) & (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) + { + rt_hw_cpu_relax(); + } + + /* + * Clear the RX disable and TX disable bits and then set the TX enable + * bit and RX enable bit to enable the transmitter and receiver. + */ + ctrl_reg = HWREG32(cdns_uart->base + CDNS_UART_CR); + ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); + ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; + HWREG32(cdns_uart->base + CDNS_UART_CR) = ctrl_reg; + + HWREG32(cdns_uart->base + CDNS_UART_RXTOUT) = 10; + + mode_reg = HWREG32(cdns_uart->base + CDNS_UART_MR); + + switch (cfg->data_bits) + { + case DATA_BITS_6: + mode_reg |= CDNS_UART_MR_CHARLEN_6_BIT; + break; + + case DATA_BITS_7: + mode_reg |= CDNS_UART_MR_CHARLEN_7_BIT; + break; + + case DATA_BITS_8: + default: + mode_reg |= CDNS_UART_MR_CHARLEN_8_BIT; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_2: + mode_reg |= CDNS_UART_MR_STOPMODE_2_BIT; + break; + + case STOP_BITS_1: + default: + mode_reg |= CDNS_UART_MR_STOPMODE_1_BIT; + break; + } + + switch (cfg->parity) + { + case PARITY_ODD: + mode_reg |= CDNS_UART_MR_PARITY_ODD; + break; + + case PARITY_EVEN: + mode_reg |= CDNS_UART_MR_PARITY_EVEN; + break; + + case PARITY_NONE: + default: + mode_reg |= CDNS_UART_MR_PARITY_NONE; + break; + } + + /* Write the mode register out */ + HWREG32(cdns_uart->base + CDNS_UART_MR) = mode_reg & 1; + +_out_lock: + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + + return err; +} + +static rt_err_t cdns_uart_uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + rt_uint32_t value; + rt_ubase_t level; + struct cdns_uart *cdns_uart = raw_to_cdns_uart(serial); + + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + rt_hw_interrupt_mask(cdns_uart->irq); + + HWREG32(cdns_uart->base + CDNS_UART_IER) = 0; + HWREG32(cdns_uart->base + CDNS_UART_IDR) = ~0U; + break; + + case RT_DEVICE_CTRL_SET_INT: + /* + * Write the new value for the FIFO control register to it such that the + * threshold is changed + */ + + value = 1; /* Trigger level */ + HWREG32(cdns_uart->base + CDNS_UART_RXWM) = value & CDNS_UART_RXWM_MASK; + + rt_hw_interrupt_umask(cdns_uart->irq); + + value = CDNS_UART_IXR_RXTRIG & CDNS_UART_IXR_RXMASK; + HWREG32(cdns_uart->base + CDNS_UART_IER) = value; + HWREG32(cdns_uart->base + CDNS_UART_IDR) = ~value; + break; + } + + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + + return RT_EOK; +} + +static int cdns_uart_uart_putc(struct rt_serial_device *serial, char c) +{ + rt_ubase_t level; + struct cdns_uart *cdns_uart = raw_to_cdns_uart(serial); + + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + /* Wait until there is space in TX FIFO */ + while (!(HWREG32(cdns_uart->base + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) + { + rt_hw_cpu_relax(); + } + + /* Write the byte into the TX FIFO */ + HWREG32(cdns_uart->base + CDNS_UART_FIFO) = c; + + /* Wait until FIFO is empty */ + while (!(HWREG32(cdns_uart->base + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) + { + rt_hw_cpu_relax(); + } + + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + + return 1; +} + +static int cdns_uart_uart_getc(struct rt_serial_device *serial) +{ + int ch = -1; + rt_ubase_t level; + struct cdns_uart *cdns_uart = raw_to_cdns_uart(serial); + + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + /* Check if FIFO is empty */ + if (!(HWREG32(cdns_uart->base + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) + { + ch = HWREG32(cdns_uart->base + CDNS_UART_FIFO); + } + + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + + return ch; +} + +static const struct rt_uart_ops cdns_uart_uart_ops = +{ + .configure = cdns_uart_uart_configure, + .control = cdns_uart_uart_control, + .putc = cdns_uart_uart_putc, + .getc = cdns_uart_uart_getc, +}; + +static void cdns_uart_early_kick(struct rt_fdt_earlycon *con, int why) +{ + struct cdns_uart *cdns_uart = raw_to_cdns_uart(con->data); + + switch (why) + { + case FDT_EARLYCON_KICK_UPDATE: + cdns_uart->base = rt_ioremap((void *)con->mmio, con->size); + break; + + case FDT_EARLYCON_KICK_COMPLETED: + rt_iounmap(cdns_uart->base); + break; + + default: + break; + } +} + +static rt_err_t cdns_uart_early_setup(struct rt_fdt_earlycon *con, const char *options) +{ + rt_uint32_t freq = 0; + static struct cdns_uart cdns_uart = { }; + + if (!con->mmio) + { + return -RT_ERROR; + } + + cdns_uart.base = rt_ioremap_early((void *)con->mmio, con->size); + + HWREG32(cdns_uart.base + CDNS_UART_CR) = CDNS_UART_CR_TX_EN | + CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; + + con->console_putc = (typeof(con->console_putc))&cdns_uart_uart_putc; + con->console_kick = cdns_uart_early_kick; + con->data = &cdns_uart.parent; + cdns_uart.parent.config = options ? serial_cfg_from_args((char *)options) : + (typeof(cdns_uart.parent.config))RT_SERIAL_CONFIG_DEFAULT; + + fdt_getprop_u32(con->fdt, con->nodeoffset, "clock-frequency", &freq, RT_NULL); + + if ((cdns_uart.freq = freq)) + { + rt_int32_t div8; + rt_uint32_t cd = 0, bdiv = 0, mr = CDNS_UART_MR_PARITY_NONE; + + cdns_uart_calc_baud_divs(cdns_uart.freq, + cdns_uart.parent.config.baud_rate, &bdiv, &cd, &div8); + + if (div8) + { + mr |= CDNS_UART_MR_CLKSEL; + } + + HWREG32(cdns_uart.base + CDNS_UART_MR) = mr; + HWREG32(cdns_uart.base + CDNS_UART_BAUDGEN) = cd; + HWREG32(cdns_uart.base + CDNS_UART_BAUDDIV) = bdiv; + } + + return RT_EOK; +} +RT_FDT_EARLYCON_EXPORT(xlnx_xuartps, "cdns_uart", "xlnx,xuartps", cdns_uart_early_setup); +RT_FDT_EARLYCON_EXPORT(cdns_uart_r1p8, "cdns_uart", "cdns,uart-r1p8", cdns_uart_early_setup); +RT_FDT_EARLYCON_EXPORT(cdns_uart_r1p12, "cdns_uart", "cdns,uart-r1p12", cdns_uart_early_setup); +RT_FDT_EARLYCON_EXPORT(xlnx_zynqmp_uart, "cdns_uart", "xlnx,zynqmp-uart", cdns_uart_early_setup); + +static void cdns_uart_isr(int irqno, void *param) +{ + rt_uint32_t isr; + rt_base_t level; + rt_bool_t event = RT_FALSE; + struct cdns_uart *cdns_uart = param; + + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + isr = HWREG32(cdns_uart->base + CDNS_UART_ISR); + HWREG32(cdns_uart->base + CDNS_UART_ISR) = isr; + + if ((isr & CDNS_UART_IXR_RXMASK) && + !(HWREG32(cdns_uart->base + CDNS_UART_CR) & CDNS_UART_CR_RX_DIS)) + { + event = RT_TRUE; + } + + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + + if (event) + { + rt_hw_serial_isr(&cdns_uart->parent, RT_SERIAL_EVENT_RX_IND); + } +} + +static rt_err_t cdns_uart_clk_notify(struct rt_clk_notifier *notifier, + rt_ubase_t msg, rt_ubase_t old_rate, rt_ubase_t new_rate) +{ + rt_ubase_t level; + rt_int32_t div8; + rt_uint32_t ctrl_reg, cd = 0, bdiv = 0; + struct cdns_uart *cdns_uart; + + cdns_uart = rt_container_of(notifier, struct cdns_uart, clk_rate_notifier); + + switch (msg) + { + case RT_CLK_MSG_PRE_RATE_CHANGE: + if (!cdns_uart_calc_baud_divs(new_rate, cdns_uart->parent.config.baud_rate, &bdiv, &cd, &div8)) + { + return -RT_EIO; + } + + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + /* Disable the TX and RX to set baud rate */ + ctrl_reg = HWREG32(cdns_uart->base + CDNS_UART_CR); + ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; + HWREG32(cdns_uart->base + CDNS_UART_CR) = ctrl_reg; + + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + break; + + case RT_CLK_MSG_POST_RATE_CHANGE: + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + + cdns_uart->freq = new_rate; + cdns_uart_set_baud_rate(cdns_uart, &cdns_uart->parent.config); + + /* Fallthrough */ + case RT_CLK_MSG_ABORT_RATE_CHANGE: + if (msg == RT_CLK_MSG_ABORT_RATE_CHANGE) + { + level = rt_spin_lock_irqsave(&cdns_uart->spinlock); + } + + /* Set TX/RX Reset */ + ctrl_reg = HWREG32(cdns_uart->base + CDNS_UART_CR); + ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; + HWREG32(cdns_uart->base + CDNS_UART_CR) = ctrl_reg; + + while (HWREG32(cdns_uart->base + CDNS_UART_CR) & (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) + { + rt_hw_cpu_relax(); + } + + /* + * Clear the RX disable and TX disable bits and then set the TX + * enable bit and RX enable bit to enable the transmitter and receiver. + */ + HWREG32(cdns_uart->base + CDNS_UART_RXTOUT) = 10; + ctrl_reg = HWREG32(cdns_uart->base + CDNS_UART_CR); + ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); + ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; + HWREG32(cdns_uart->base + CDNS_UART_CR) = ctrl_reg; + + rt_spin_unlock_irqrestore(&cdns_uart->spinlock, level); + break; + + default: + break; + } + + return RT_EOK; +} + +static void cdns_uart_free(struct cdns_uart *cdns_uart) +{ + if (cdns_uart->base) + { + rt_iounmap(cdns_uart->base); + } + + if (cdns_uart->clk_rate_notifier.callback) + { + rt_clk_notifier_unregister(cdns_uart->clk, &cdns_uart->clk_rate_notifier); + } + + if (!rt_is_err_or_null(cdns_uart->clk)) + { + rt_clk_disable(cdns_uart->clk); + rt_clk_put(cdns_uart->clk); + } + + if (!rt_is_err_or_null(cdns_uart->pclk)) + { + rt_clk_disable_unprepare(cdns_uart->pclk); + rt_clk_put(cdns_uart->pclk); + } + + if (!rt_is_err_or_null(cdns_uart->rstc)) + { + rt_reset_control_put(cdns_uart->rstc); + } + + rt_free(cdns_uart); +} + +static rt_err_t cdns_uart_probe(struct rt_platform_device *pdev) +{ + rt_err_t err; + const char *name; + char isr_name[RT_NAME_MAX]; + struct rt_device *dev = &pdev->parent; + struct cdns_uart *cdns_uart = rt_calloc(1, sizeof(*cdns_uart)); + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + + if (!cdns_uart) + { + return -RT_ENOMEM; + } + + cdns_uart->base = rt_dm_dev_iomap(dev, 0); + + if (!cdns_uart->base) + { + err = -RT_EIO; + + goto _fail; + } + + cdns_uart->irq = rt_dm_dev_get_irq(dev, 0); + + if (cdns_uart->irq < 0) + { + err = cdns_uart->irq; + + goto _fail; + } + + cdns_uart->clk = rt_clk_get_by_name(dev, "uart_clk"); + + if (rt_is_err(cdns_uart->clk)) + { + err = rt_ptr_err(cdns_uart->clk); + + goto _fail; + } + + if (!cdns_uart->clk) + { + cdns_uart->clk = rt_clk_get_by_name(dev, "ref_clk"); + + if (rt_is_err(cdns_uart->clk)) + { + err = rt_ptr_err(cdns_uart->clk); + + goto _fail; + } + } + + cdns_uart->pclk = rt_clk_get_by_name(dev, "pclk"); + + if (rt_is_err(cdns_uart->pclk)) + { + err = rt_ptr_err(cdns_uart->pclk); + + goto _fail; + } + + if (!cdns_uart->pclk) + { + cdns_uart->pclk = rt_clk_get_by_name(dev, "aper_clk"); + + if (rt_is_err(cdns_uart->clk)) + { + err = rt_ptr_err(cdns_uart->clk); + + goto _fail; + } + } + + if ((err = rt_clk_prepare_enable(cdns_uart->pclk))) + { + goto _fail; + } + + if ((err = rt_clk_prepare_enable(cdns_uart->clk))) + { + goto _fail; + } + + cdns_uart->rstc = rt_reset_control_get_by_index(dev, 0); + + if (rt_is_err(cdns_uart->rstc)) + { + err = rt_ptr_err(cdns_uart->rstc); + + goto _fail; + } + + if ((err = rt_reset_control_deassert(cdns_uart->rstc))) + { + goto _fail; + } + + cdns_uart->clk_rate_notifier.callback = cdns_uart_clk_notify; + if ((err = rt_clk_notifier_register(cdns_uart->clk, &cdns_uart->clk_rate_notifier))) + { + cdns_uart->clk_rate_notifier.callback = RT_NULL; + goto _fail; + } + + cdns_uart->freq = rt_clk_get_rate(cdns_uart->clk); + + rt_spin_lock_init(&cdns_uart->spinlock); + + rt_dm_dev_bind_fwdata(&cdns_uart->parent.parent, dev->ofw_node, &cdns_uart->parent); + dev->user_data = cdns_uart; + + serial_dev_set_name(&cdns_uart->parent); + name = rt_dm_dev_get_name(&cdns_uart->parent.parent); + + cdns_uart->parent.ops = &cdns_uart_uart_ops; + cdns_uart->parent.config = config; + + rt_hw_serial_register(&cdns_uart->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, cdns_uart); + rt_snprintf(isr_name, RT_NAME_MAX, "%s-cdns_uart", name); + rt_hw_interrupt_install(cdns_uart->irq, cdns_uart_isr, cdns_uart, isr_name); + + return RT_EOK; + +_fail: + cdns_uart_free(cdns_uart); + + return err; +} + +static rt_err_t cdns_uart_remove(struct rt_platform_device *pdev) +{ + rt_uint32_t status; + struct rt_device *dev = &pdev->parent; + struct cdns_uart *cdns_uart = dev->user_data; + + /* Disable interrupts */ + status = HWREG32(cdns_uart->base + CDNS_UART_IMR); + HWREG32(cdns_uart->base + CDNS_UART_IDR) = status; + HWREG32(cdns_uart->base + CDNS_UART_ISR) = 0xffffffffU; + + /* Disable the TX and RX */ + HWREG32(cdns_uart->base + CDNS_UART_CR) = CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; + + rt_dm_dev_unbind_fwdata(dev, RT_NULL); + + rt_hw_interrupt_mask(cdns_uart->irq); + rt_pic_detach_irq(cdns_uart->irq, cdns_uart); + + rt_device_unregister(&cdns_uart->parent.parent); + + rt_reset_control_assert(cdns_uart->rstc); + + cdns_uart_free(cdns_uart); + + return RT_EOK; +} + +static const struct rt_ofw_node_id cdns_uart_ofw_ids[] = +{ + { .type = "ttyPS", .compatible = "xlnx,xuartps", }, + { .type = "ttyPS", .compatible = "cdns,uart-r1p8", }, + { .type = "ttyPS", .compatible = "cdns,uart-r1p12", }, + { .type = "ttyPS", .compatible = "xlnx,zynqmp-uart", }, + { /* sentinel */ } +}; + +static struct rt_platform_driver cdns_uart_driver = +{ + .name = "serial-cdns-uart", + .ids = cdns_uart_ofw_ids, + + .probe = cdns_uart_probe, + .remove = cdns_uart_remove, +}; + +static int cdns_uart_drv_register(void) +{ + rt_platform_driver_register(&cdns_uart_driver); + + return 0; +} +INIT_PLATFORM_EXPORT(cdns_uart_drv_register); diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/zynqmp.h b/bsp/zynqmp-a53-dfzu2eg/drivers/zynqmp.h deleted file mode 100644 index 72da0549db9..00000000000 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/zynqmp.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2024-04-11 liYony the first version - */ - -#ifndef __ZYNQMP_H__ -#define __ZYNQMP_H__ - -#include -#include - -#ifdef RT_USING_SMART -#include -#endif - -#define __REG32(x) (*((volatile unsigned int *)(x))) -#define __REG16(x) (*((volatile unsigned short *)(x))) - -/* UART */ -#define ZYNQMP_UART0_BASE 0xFF000000 -#define ZYNQMP_UART0_SIZE 0x00010000 -#define ZYNQMP_UART0_IRQNUM (32 + 21) -#define ZYNQMP_UART0_CLK_FREQ_HZ (99999001) - -/* GIC */ -#define MAX_HANDLERS 195 -#define GIC_IRQ_START 0 -#define ARM_GIC_NR_IRQS 195 -#define ARM_GIC_MAX_NR 1 - -/* GICv2 */ -#define GIC400_DISTRIBUTOR_PPTR 0xF9010000U -#define GIC400_CONTROLLER_PPTR 0xF9020000U -#define GIC400_SIZE 0x00001000U - -/* the basic constants and interfaces needed by gic */ -rt_inline rt_ubase_t platform_get_gic_dist_base(void) -{ - return GIC400_DISTRIBUTOR_PPTR; -} - -rt_inline rt_ubase_t platform_get_gic_cpu_base(void) -{ - return GIC400_CONTROLLER_PPTR; -} - -#endif /* __ZYNQMP_H__ */ diff --git a/bsp/zynqmp-a53-dfzu2eg/drivers/zynqmp/zynqmp_reg.h b/bsp/zynqmp-a53-dfzu2eg/drivers/zynqmp/zynqmp_reg.h deleted file mode 100644 index b780da8b63d..00000000000 --- a/bsp/zynqmp-a53-dfzu2eg/drivers/zynqmp/zynqmp_reg.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __ZYNQMP_REG_H__ -#define __ZYNQMP_REG_H__ - -/* bit field helpers. */ -#define __M(n) (~(~0<<(n))) -#define __RBF(number, n) ((number)&__M(n)) -#define __BF(number, n, m) __RBF((number>>m), (n-m+1)) -#define REG_BF(number, n, m) (m - -/* The following constant defines the amount of error that is allowed for - * a specified baud rate. This error is the difference between the actual - * baud rate that will be generated using the specified clock and the - * desired baud rate. - */ -#define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */ - -/* - * The following constants indicate the max and min baud rates and these - * numbers are based only on the testing that has been done. The hardware - * is capable of other baud rates. - */ -#define XUARTPS_MAX_RATE 6240000U -#define XUARTPS_MIN_RATE 110U - -/** @name Register Map - * - * Register offsets for the UART. - * @{ - */ -#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */ -#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */ -#define XUARTPS_IER_OFFSET 0x0008U /**< Interrupt Enable [12:0] */ -#define XUARTPS_IDR_OFFSET 0x000CU /**< Interrupt Disable [12:0] */ -#define XUARTPS_IMR_OFFSET 0x0010U /**< Interrupt Mask [12:0] */ -#define XUARTPS_ISR_OFFSET 0x0014U /**< Interrupt Status [12:0]*/ -#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */ -#define XUARTPS_RXTOUT_OFFSET 0x001CU /**< RX Timeout [7:0] */ -#define XUARTPS_RXWM_OFFSET 0x0020U /**< RX FIFO Trigger Level [5:0] */ -#define XUARTPS_MODEMCR_OFFSET 0x0024U /**< Modem Control [5:0] */ -#define XUARTPS_MODEMSR_OFFSET 0x0028U /**< Modem Status [8:0] */ -#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */ -#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */ -#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */ -#define XUARTPS_FLOWDEL_OFFSET 0x0038U /**< Flow Delay [5:0] */ -#define XUARTPS_TXWM_OFFSET 0x0044U /**< TX FIFO Trigger Level [5:0] */ -#define XUARTPS_RXBS_OFFSET 0x0048U /**< RX FIFO Byte Status [11:0] */ -/* @} */ - -/** @name Control Register - * - * The Control register (CR) controls the major functions of the device. - * - * Control Register Bit Definition - */ -#define XUARTPS_CR_STOPBRK 0x00000100U /**< Stop transmission of break */ -#define XUARTPS_CR_STARTBRK 0x00000080U /**< Set break */ -#define XUARTPS_CR_TORST 0x00000040U /**< RX timeout counter restart */ -#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */ -#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */ -#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ -#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ -#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /**< Enable/disable Mask */ -#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ -#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ -/* @}*/ - -/** @name Mode Register - * - * The mode register (MR) defines the mode of transfer as well as the data - * format. If this register is modified during transmission or reception, - * data validity cannot be guaranteed. - * - * Mode Register Bit Definition - * @{ - */ -#define XUARTPS_MR_CCLK 0x00000400U /**< Input clock selection */ -#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /**< Remote loopback mode */ -#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /**< Local loopback mode */ -#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /**< Auto echo mode */ -#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */ -#define XUARTPS_MR_CHMODE_SHIFT 8U /**< Mode shift */ -#define XUARTPS_MR_CHMODE_MASK 0x00000300U /**< Mode mask */ -#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /**< 2 stop bits */ -#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /**< 1.5 stop bits */ -#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */ -#define XUARTPS_MR_STOPMODE_SHIFT 6U /**< Stop bits shift */ -#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /**< Stop bits mask */ -#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */ -#define XUARTPS_MR_PARITY_MARK 0x00000018U /**< Mark parity mode */ -#define XUARTPS_MR_PARITY_SPACE 0x00000010U /**< Space parity mode */ -#define XUARTPS_MR_PARITY_ODD 0x00000008U /**< Odd parity mode */ -#define XUARTPS_MR_PARITY_EVEN 0x00000000U /**< Even parity mode */ -#define XUARTPS_MR_PARITY_SHIFT 3U /**< Parity setting shift */ -#define XUARTPS_MR_PARITY_MASK 0x00000038U /**< Parity mask */ -#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /**< 6 bits data */ -#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /**< 7 bits data */ -#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */ -#define XUARTPS_MR_CHARLEN_SHIFT 1U /**< Data Length shift */ -#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /**< Data length mask */ -#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */ -/* @} */ - -/** @name Interrupt Registers - * - * Interrupt control logic uses the interrupt enable register (IER) and the - * interrupt disable register (IDR) to set the value of the bits in the - * interrupt mask register (IMR). The IMR determines whether to pass an - * interrupt to the interrupt status register (ISR). - * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an - * interrupt. IMR and ISR are read only, and IER and IDR are write only. - * Reading either IER or IDR returns 0x00. - * - * All four registers have the same bit definitions. - * - * @{ - */ -#define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */ -#define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */ -#define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */ -#define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */ -#define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */ -#define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */ -#define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */ -#define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */ -#define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */ -#define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */ -#define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */ -#define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */ -#define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */ -#define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */ -#define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */ -/* @} */ - -/** @name Baud Rate Generator Register - * - * The baud rate generator control register (BRGR) is a 16 bit register that - * controls the receiver bit sample clock and baud rate. - * Valid values are 1 - 65535. - * - * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit - * in the MR register. - * @{ - */ -#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /**< Disable clock */ -#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /**< Valid bits mask */ -#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /**< Reset value */ - -/** @name Baud Divisor Rate register - * - * The baud rate divider register (BDIV) controls how much the bit sample - * rate is divided by. It sets the baud rate. - * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored. - * - * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by - * the MR_CCLK bit in the MR register. - * @{ - */ -#define XUARTPS_BAUDDIV_MASK 0x000000FFU /**< 8 bit baud divider mask */ -#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /**< Reset value */ -/* @} */ - -/** @name Receiver Timeout Register - * - * Use the receiver timeout register (RTR) to detect an idle condition on - * the receiver data line. - * - * @{ - */ -#define XUARTPS_RXTOUT_DISABLE 0x00000000U /**< Disable time out */ -#define XUARTPS_RXTOUT_MASK 0x000000FFU /**< Valid bits mask */ - -/** @name Receiver FIFO Trigger Level Register - * - * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at - * which the RX FIFO triggers an interrupt event. - * @{ - */ -#define XUARTPS_RXWM_DISABLE 0x00000000U /**< Disable RX trigger interrupt */ -#define XUARTPS_RXWM_MASK 0x0000003FU /**< Valid bits mask */ -#define XUARTPS_RXWM_RESET_VAL 0x00000020U /**< Reset value */ -/* @} */ - -/** @name Transmit FIFO Trigger Level Register - * - * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at - * which the TX FIFO triggers an interrupt event. - * @{ - */ -#define XUARTPS_TXWM_MASK 0x0000003FU /**< Valid bits mask */ -#define XUARTPS_TXWM_RESET_VAL 0x00000020U /**< Reset value */ -/* @} */ - -/** @name Modem Control Register - * - * This register (MODEMCR) controls the interface with the modem or data set, - * or a peripheral device emulating a modem. - * - * @{ - */ -#define XUARTPS_MODEMCR_FCM 0x00000020U /**< Flow control mode */ -#define XUARTPS_MODEMCR_RTS 0x00000002U /**< Request to send */ -#define XUARTPS_MODEMCR_DTR 0x00000001U /**< Data terminal ready */ -/* @} */ - -/** @name Modem Status Register - * - * This register (MODEMSR) indicates the current state of the control lines - * from a modem, or another peripheral device, to the CPU. In addition, four - * bits of the modem status register provide change information. These bits - * are set to a logic 1 whenever a control input from the modem changes state. - * - * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem - * status interrupt is generated and this is reflected in the modem status - * register. - * - * @{ - */ -#define XUARTPS_MODEMSR_FCMS 0x00000100U /**< Flow control mode (FCMS) */ -#define XUARTPS_MODEMSR_DCD 0x00000080U /**< Complement of DCD input */ -#define XUARTPS_MODEMSR_RI 0x00000040U /**< Complement of RI input */ -#define XUARTPS_MODEMSR_DSR 0x00000020U /**< Complement of DSR input */ -#define XUARTPS_MODEMSR_CTS 0x00000010U /**< Complement of CTS input */ -#define XUARTPS_MODEMSR_DDCD 0x00000008U /**< Delta DCD indicator */ -#define XUARTPS_MODEMSR_TERI 0x00000004U /**< Trailing Edge Ring Indicator */ -#define XUARTPS_MODEMSR_DDSR 0x00000002U /**< Change of DSR */ -#define XUARTPS_MODEMSR_DCTS 0x00000001U /**< Change of CTS */ -/* @} */ - -/** @name Channel Status Register - * - * The channel status register (CSR) is provided to enable the control logic - * to monitor the status of bits in the channel interrupt status register, - * even if these are masked out by the interrupt mask register. - * - * @{ - */ -#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */ -#define XUARTPS_SR_TTRIG 0x00002000U /**< TX FIFO Trigger Status */ -#define XUARTPS_SR_FLOWDEL 0x00001000U /**< RX FIFO fill over flow delay */ -#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */ -#define XUARTPS_SR_RACTIVE 0x00000400U /**< RX active */ -#define XUARTPS_SR_TXFULL 0x00000010U /**< TX FIFO full */ -#define XUARTPS_SR_TXEMPTY 0x00000008U /**< TX FIFO empty */ -#define XUARTPS_SR_RXFULL 0x00000004U /**< RX FIFO full */ -#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */ -#define XUARTPS_SR_RXOVR 0x00000001U /**< RX FIFO fill over trigger */ -/* @} */ - -/** @name Flow Delay Register - * - * Operation of the flow delay register (FLOWDEL) is very similar to the - * receive FIFO trigger register. An internal trigger signal activates when the - * FIFO is filled to the level set by this register. This trigger will not - * cause an interrupt, although it can be read through the channel status - * register. In hardware flow control mode, RTS is deactivated when the trigger - * becomes active. RTS only resets when the FIFO level is four less than the - * level of the flow delay trigger and the flow delay trigger is not activated. - * A value less than 4 disables the flow delay. - * @{ - */ -#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /**< Valid bit mask */ -/* @} */ - -/** @name Receiver FIFO Byte Status Register - * - * The Receiver FIFO Status register is used to have a continuous - * monitoring of the raw unmasked byte status information. The register - * contains frame, parity and break status information for the top - * four bytes in the RX FIFO. - * - * Receiver FIFO Byte Status Register Bit Definition - * @{ - */ -#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /**< Byte3 Break Error */ -#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /**< Byte3 Frame Error */ -#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /**< Byte3 Parity Error */ -#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /**< Byte2 Break Error */ -#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /**< Byte2 Frame Error */ -#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /**< Byte2 Parity Error */ -#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /**< Byte1 Break Error */ -#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /**< Byte1 Frame Error */ -#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /**< Byte1 Parity Error */ -#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /**< Byte0 Break Error */ -#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /**< Byte0 Frame Error */ -#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /**< Byte0 Parity Error */ -#define XUARTPS_RXBS_MASK 0x00000007U /**< 3 bit RX byte status mask */ -/* @} */ - -/* - * Defines for backwards compatibility, will be removed - * in the next version of the driver - */ -#define XUARTPS_MEDEMSR_DCDX XUARTPS_MODEMSR_DDCD -#define XUARTPS_MEDEMSR_RIX XUARTPS_MODEMSR_TERI -#define XUARTPS_MEDEMSR_DSRX XUARTPS_MODEMSR_DDSR -#define XUARTPS_MEDEMSR_CTSX XUARTPS_MODEMSR_DCTS - -#endif /* __ZYNQMP_UART_H__ */ diff --git a/bsp/zynqmp-a53-dfzu2eg/qemu.py b/bsp/zynqmp-a53-dfzu2eg/qemu.py new file mode 100755 index 00000000000..63db44fee80 --- /dev/null +++ b/bsp/zynqmp-a53-dfzu2eg/qemu.py @@ -0,0 +1,43 @@ +#!/bin/python +# -*- coding: utf-8 -*- +import os, sys, re + +with open('rtconfig.h', 'r') as file: + rtconfig_header = file.read() + +if os.getenv('RTT_QEMU_ROOT'): + RTT_QEMU_ROOT = os.getenv('RTT_QEMU_ROOT') +else: + RTT_QEMU_ROOT = "" + +opt = sys.argv + +q_graphic = "-nographic" +q_debug = "" + +def is_opt(key, inkey): + if str("-" + key) == inkey: + return True + return False + +for i in range(len(opt)): + if i == 0: + continue + inkey = opt[i] + + if is_opt("debug", inkey): q_debug = "-S -s" + if is_opt("graphic", inkey): q_graphic = "" + +mem = int(re.findall(r'#define\s+ARCH_HEAP_SIZE\s+(.+)', rtconfig_header)[0], 16) +mem += int(re.findall(r'#define\s+ARCH_INIT_PAGE_SIZE\s+(.+)', rtconfig_header)[0], 16) +mem = 128 + int(mem / (1024 * 1024)) + +os.system(""" +{}qemu-system-aarch64 \ + -M xlnx-zcu102 \ + -m {} \ + -kernel rtthread.bin \ + {} \ + {} \ + -serial mon:stdio +""".format(RTT_QEMU_ROOT, mem, q_graphic, q_debug)) diff --git a/bsp/zynqmp-a53-dfzu2eg/rtconfig.h b/bsp/zynqmp-a53-dfzu2eg/rtconfig.h index c7c904d165e..ce5eafec699 100644 --- a/bsp/zynqmp-a53-dfzu2eg/rtconfig.h +++ b/bsp/zynqmp-a53-dfzu2eg/rtconfig.h @@ -7,17 +7,6 @@ /* rt_vsnprintf options */ -#define RT_KLIBC_USING_VSNPRINTF_LONGLONG -#define RT_KLIBC_USING_VSNPRINTF_STANDARD -#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS -#define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS -#define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER -#define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER -#define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32 -#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32 -#define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6 -#define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9 -#define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4 /* end of rt_vsnprintf options */ /* rt_vsscanf options */ @@ -122,7 +111,8 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x50201 +#define RT_USING_CONSOLE_OUTPUT_CTL +#define RT_VER_NUM 0x50300 #define RT_USING_STDC_ATOMIC #define RT_BACKTRACE_LEVEL_MAX_NR 32 /* end of RT-Thread Kernel */ @@ -196,6 +186,7 @@ /* Device Drivers */ +#define RT_USING_DM #define RT_USING_DEV_BUS #define RT_USING_DEVICE_IPC #define RT_UNAMED_PIPE_NUMBER 64 @@ -206,23 +197,36 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 256 +#define RT_SERIAL_XILINX_PS +#define RT_USING_CLOCK_TIME +#define RT_CLOCK_TIME_ARM_ARCH #define RT_USING_NULL #define RT_USING_ZERO #define RT_USING_RANDOM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 #define RT_USING_RTC -#define RT_USING_SOFT_RTC -#define RT_USING_VIRTIO -#define RT_USING_VIRTIO10 -#define RT_USING_VIRTIO_MMIO_ALIGN -#define RT_USING_VIRTIO_BLK -#define RT_USING_VIRTIO_CONSOLE -#define RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR 4 -#define RT_USING_VIRTIO_GPU -#define RT_USING_VIRTIO_INPUT -#define RT_USING_PIN -#define RT_USING_KTIME +#define RT_USING_ALARM +#define RT_ALARM_STACK_SIZE 8192 +#define RT_ALARM_TIMESLICE 5 +#define RT_ALARM_PRIORITY 10 +#define RT_RTC_ZYNQMP +#define RT_USING_RESET + +/* Power Management (PM) Domains device drivers */ + +/* end of Power Management (PM) Domains device drivers */ +#define RT_USING_OFW +#define RT_USING_BUILTIN_FDT +#define RT_BUILTIN_FDT_PATH "zynqmp.dtb" +#define RT_FDT_EARLYCON_MSG_SIZE 128 +#define RT_USING_OFW_BUS_RANGES_NUMBER 8 +#define RT_USING_PIC +#define MAX_HANDLERS 256 +#define RT_PIC_ARM_GIC +#define RT_PIC_ARM_GIC_MAX_NR 1 +#define RT_USING_CLK + +/* SoC (System on Chip) Drivers */ + /* end of Device Drivers */ /* C/C++ and POSIX layer */ @@ -283,6 +287,8 @@ #define RT_PAGE_AFFINITY_BLOCK_SIZE 0x1000 #define RT_PAGE_MAX_ORDER 11 +#define RT_USING_MEMBLOCK +#define RT_INIT_MEMORY_REGIONS 128 /* Debugging */ @@ -500,13 +506,4 @@ /* end of RT-Thread online packages */ #define SOC_ZYNQMP_AARCH64 -/* Hardware Drivers Config */ - -#define BSP_SUPPORT_FPU -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_GIC -#define BSP_USING_GICV2 -/* end of Hardware Drivers Config */ - #endif diff --git a/bsp/zynqmp-a53-dfzu2eg/zynqmp.dts b/bsp/zynqmp-a53-dfzu2eg/zynqmp.dts new file mode 100755 index 00000000000..281f8da3f58 --- /dev/null +++ b/bsp/zynqmp-a53-dfzu2eg/zynqmp.dts @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-07-07 GuEe-GUI the first version + */ + +/dts-v1/; +#include +#include +#include + +/* Kernel and DMA heap */ +#define BASE_SIZE (SIZE_MB + (128 * SIZE_MB)) + +/ { + compatible = "xlnx,zynqmp"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + + chosen { + bootargs = "earlycon console=ttyPS0"; + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = &uart0; + }; + + memory { + reg = <0x0 (ARCH_RAM_OFFSET + ARCH_TEXT_OFFSET) 0x0 (BASE_SIZE + ARCH_HEAP_SIZE + ARCH_INIT_PAGE_SIZE)>; + device_type = "memory"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "psci"; + reg = <0x0>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "psci"; + reg = <0x1>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "psci"; + reg = <0x2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + enable-method = "psci"; + reg = <0x3>; + }; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + amba_apu: amba-apu@0 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0 0xffffffff>; + + gic: interrupt-controller@f9010000 { + compatible = "arm,gic-400", "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + reg = <0x0 0xf9010000 0x10000>, + <0x0 0xf9020000 0x20000>, + <0x0 0xf9040000 0x20000>, + <0x0 0xf9060000 0x20000>; + interrupt-controller; + interrupts = ; + }; + }; + + clk100: clk100 { + compatible = "fixed-clock"; + clock-output-names = "clk100mhz"; + #clock-cells = <0>; + clock-frequency = <100000000>; + }; + + amba: amba { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + rtc: rtc@ffa60000 { + compatible = "xlnx,zynqmp-rtc"; + reg = <0x0 0xffa60000 0x0 0x100>; + interrupts = , + ; + interrupt-names = "alarm", "sec"; + calibration = <0x7fff>; + }; + + uart0: serial@ff000000 { + compatible = "cdns,uart-r1p12", "xlnx,xuartps"; + interrupts = ; + reg = <0x0 0xff000000 0x0 0x1000>; + clocks = <&clk100 &clk100>; + clock-names = "uart_clk", "pclk"; + }; + }; +}; diff --git a/components/drivers/include/dt-bindings/interrupt-controller/arm-gic.h b/components/drivers/include/dt-bindings/interrupt-controller/arm-gic.h new file mode 100644 index 00000000000..c443cd61e08 --- /dev/null +++ b/components/drivers/include/dt-bindings/interrupt-controller/arm-gic.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H__ +#define __DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H__ + +#include + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +/* + * Interrupt specifier cell 2. + * The flags in irq.h are valid, plus those below. + */ +#define GIC_CPU_MASK_RAW(x) ((x) << 8) +#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) + +#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H__ */ diff --git a/components/drivers/include/dt-bindings/interrupt-controller/irq.h b/components/drivers/include/dt-bindings/interrupt-controller/irq.h new file mode 100644 index 00000000000..cdf8e6f4290 --- /dev/null +++ b/components/drivers/include/dt-bindings/interrupt-controller/irq.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H__ +#define __DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H__ + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H__ */ diff --git a/libcpu/aarch64/common/SConscript b/libcpu/aarch64/common/SConscript index 99645683b87..8f3c79d600e 100644 --- a/libcpu/aarch64/common/SConscript +++ b/libcpu/aarch64/common/SConscript @@ -7,6 +7,7 @@ Import('rtconfig') cwd = GetCurrentDir() src = Glob('*.c') + Glob('*.cpp') + Glob('*.S') CPPPATH = [cwd, cwd + '/include'] +bsp_path = Dir('#').abspath if GetDepend('RT_USING_SMP'): core_model = 'mp' @@ -18,6 +19,10 @@ src += Glob(core_model + '/*.S') if GetDepend('RT_USING_OFW') == False: SrcRemove(src, ['setup.c', 'cpu_psci.c', 'psci.c']) + if GetDepend('RT_BUILTIN_FDT_PATH'): + builtin_dtb = Env.Depends(target = 'builtin_fdt_gcc.o', source = bsp_path + GetDepend('RT_BUILTIN_FDT_PATH')) + Env.AlwaysBuild(builtin_dtb) + if GetDepend('RT_USING_PIC') == True: SrcRemove(src, ['gicv3.c', 'gic.c', 'gtimer.c', 'interrupt.c'])