diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 8d7afd64b6386..de90238cf76e5 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3530,6 +3530,19 @@ Bouffalolab Platforms: labels: - "platform: bouffalolab" +realtek ameba Platforms: + status: maintained + maintainers: + - zjian-zhang + files: + - drivers/*/*ameba* + - boards/realtek/ + - soc/realtek/ + - dts/arm/realtek/ + - dts/bindings/*/*ameba* + labels: + - "platform: ameba" + Broadcom Platforms: status: odd fixes files: @@ -5000,6 +5013,14 @@ West: labels: - "platform: Ambiq" +"West project: hal_realtek": + status: maintained + maintainers: + - zjian-zhang + files: [] + labels: + - "platform: ameba" + "West project: hal_atmel": status: maintained maintainers: diff --git a/boards/realtek/rtl872xd_evb/Kconfig.rtl872xd_evb b/boards/realtek/rtl872xd_evb/Kconfig.rtl872xd_evb new file mode 100644 index 0000000000000..a4b60a0b205a2 --- /dev/null +++ b/boards/realtek/rtl872xd_evb/Kconfig.rtl872xd_evb @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RTL872XD_EVB + select SOC_AMEBAD diff --git a/boards/realtek/rtl872xd_evb/board.cmake b/boards/realtek/rtl872xd_evb/board.cmake new file mode 100644 index 0000000000000..79ab10f7e1d8f --- /dev/null +++ b/boards/realtek/rtl872xd_evb/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=Cortex-M33" "--speed=4000") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/realtek/rtl872xd_evb/board.yml b/boards/realtek/rtl872xd_evb/board.yml new file mode 100644 index 0000000000000..3c261913f58e2 --- /dev/null +++ b/boards/realtek/rtl872xd_evb/board.yml @@ -0,0 +1,5 @@ +board: + name: rtl872xd_evb + vendor: realtek + socs: + - name: amebad diff --git a/boards/realtek/rtl872xd_evb/doc/index.rst b/boards/realtek/rtl872xd_evb/doc/index.rst new file mode 100644 index 0000000000000..132bd21383c08 --- /dev/null +++ b/boards/realtek/rtl872xd_evb/doc/index.rst @@ -0,0 +1,77 @@ +.. zephyr:board:: rtl872xd_evb + +Overview +******** + +The Realtek RTL872xD Series is a Combo SoC that supports dual-band Wi-Fi 4 (2.4GHz + 5GHz) and +BLE 5.0 specifications. With ultra-low power consumption, complete encryption strategy and abundant +peripheral resources, it is widely in various products such as Home appliance control panel, +Smart door, Smart toy, Smart voice, Smart remote control, Bluetooth gateway, Headset, Wi-Fi gamepad, +Smart POS, etc. For more information, check `RTL872XD-EVB`_. + +The features include the following: + +- Dual cores: Real-M300 and Real-M200 +- 512KB + 64KB on-chip SRAM +- 802.11 a/b/g/n 1 x 1, 2.4GHz + 5GHz +- Supports BLE 5.0 +- Peripheral Interface: + + - Multi-communication interfaces: SPI x 2, UART x 4, I2C x 1 + - Hardware Key-scan interface supports up to 36 keys + - Hardware Quad-decoder supports statistical and comparison functions + - Hardware IR transceiver can easily adapt to various IR protocols + - SDIO/USB high speed interface (both host and slave) + - Supports real-time clock together with 18 channels of PWM output + - Supports 5 channels of touch pad and 6 channels of GDMA + - Supports 7 channels of normal 12-bit ADC and 1 channel of VBAT + - Integrated LCDC supports both RGB and I8080 interfaces + - Integrated hardware crypto engine supports AES256/192/128 and SHA256 + - Integrated audio codec + +For more information, Get application note and datasheet at `RTL872xCS/D Series`_ depending on chip you use. + +Supported Features +================== + +.. zephyr:board-supported-hw:: + +Building +******** + +Here is an example for building the :zephyr:code-sample:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rtl872xd_evb + :goals: build + +Flashing +******** + +When the build finishes, downloading images into flash by `AmebaImageTool`_: + +See the ApplicationNote chapter Image Tool from documentation links for more details. + +#. Environment Requirements: EX. WinXP, Win 7 or later, Microsoft .NET Framework 4.0. +#. Connect chip and PC with USB wire. +#. Choose the Device profiles according to the chip you use. +#. Select the corresponding serial port and transmission baud rate. The default baud rate is 1500000. +#. Select the images to be programmed and set the start address and end address according to the flash layout, refer to [ameba_flashcfg.c/Flash_layout]. +#. Click the Download button and start. The progress bar will show the download progress of each image and the log window will show the operation status. + +.. note:: + + For an empty chip, the bootloader and app image shall be downloaded. + +Debugging +********* + +Using SWD through PB3(SWD_CLK) and PA27(SWD_DAT). + +References +********** + +.. _`RTL872XD-EVB`: https://www.realmcu.com/en/Home/Products/RTL872xCS-RTL872xD-Series# +.. _`RTL872xCS/D Series`: https://www.realmcu.com +.. _`AmebaImageTool`: https://github.com/Ameba-AIoT/ameba-rtos/tree/master/tools/ameba/ImageTool_Legacy/AmebaImageTool.exe diff --git a/boards/realtek/rtl872xd_evb/doc/rtl872xda_evb.webp b/boards/realtek/rtl872xd_evb/doc/rtl872xda_evb.webp new file mode 100644 index 0000000000000..a50446aa08f89 Binary files /dev/null and b/boards/realtek/rtl872xd_evb/doc/rtl872xda_evb.webp differ diff --git a/boards/realtek/rtl872xd_evb/rtl872xd_evb-pinctrl.dtsi b/boards/realtek/rtl872xd_evb/rtl872xd_evb-pinctrl.dtsi new file mode 100644 index 0000000000000..268edcab40bc7 --- /dev/null +++ b/boards/realtek/rtl872xd_evb/rtl872xd_evb-pinctrl.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + compatible = "realtek,ameba-pinctrl"; + + /*PA30 is SWD_CLK, PA31 is SWD_DAT(both pull-up internally)*/ + loguart_default: loguart_default { + group1 { + pinmux = , /* RXD */ + ; /* TXD */ + bias-pull-up; + }; + }; +}; diff --git a/boards/realtek/rtl872xd_evb/rtl872xd_evb.dts b/boards/realtek/rtl872xd_evb/rtl872xd_evb.dts new file mode 100644 index 0000000000000..b8819f262329f --- /dev/null +++ b/boards/realtek/rtl872xd_evb/rtl872xd_evb.dts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "rtl872xd_evb-pinctrl.dtsi" + +/ { + model = "RealTek AmebaD RTL872XD EVB"; + compatible = "realtek,rtl872xd_evb"; + + chosen { + zephyr,console = &loguart; + zephyr,shell-uart = &loguart; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0e000020 DT_SIZE_M(4)>; +}; + +&loguart { + status = "okay"; +}; diff --git a/boards/realtek/rtl872xd_evb/rtl872xd_evb.yaml b/boards/realtek/rtl872xd_evb/rtl872xd_evb.yaml new file mode 100644 index 0000000000000..fa0b4d3cbe1bb --- /dev/null +++ b/boards/realtek/rtl872xd_evb/rtl872xd_evb.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +identifier: rtl872xd_evb +name: Realtek rtl872xd evaluation board +vendor: realtek +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 512 +flash: 4096 +supported: + - pinctrl + - serial diff --git a/boards/realtek/rtl872xd_evb/rtl872xd_evb_defconfig b/boards/realtek/rtl872xd_evb/rtl872xd_evb_defconfig new file mode 100644 index 0000000000000..1bc4e83ed3c7b --- /dev/null +++ b/boards/realtek/rtl872xd_evb/rtl872xd_evb_defconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_RUNTIME_NMI=y + +CONFIG_CORTEX_M_SYSTICK=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# This board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable LogUart +CONFIG_SERIAL=y diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 728a883e1093c..66311e543ac52 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_ADP5585 gpio_adp5585.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ADS1X4S0X gpio_ads1x4s0x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_PIO gpio_altera_pio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_AMBIQ gpio_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_AMEBA gpio_ameba.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ANDES_ATCGPIO100 gpio_andes_atcgpio100.c) zephyr_library_sources_ifdef(CONFIG_GPIO_AW9523B gpio_aw9523b.c) zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e95aded5613a8..9339808d0f630 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -202,4 +202,6 @@ source "drivers/gpio/Kconfig.xlnx_ps" source "drivers/gpio/Kconfig.xmc4xxx" # zephyr-keep-sorted-stop +source "drivers/gpio/Kconfig.ameba" + endif # GPIO diff --git a/drivers/gpio/Kconfig.ameba b/drivers/gpio/Kconfig.ameba new file mode 100644 index 0000000000000..58a27a8f039bf --- /dev/null +++ b/drivers/gpio/Kconfig.ameba @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_AMEBA + bool "GPIO controller driver for Realtek Ameba series SoC" + default y + depends on DT_HAS_REALTEK_AMEBA_GPIO_ENABLED + help + Enable GPIO controller driver for Realtek Ameba series SoC + +config GPIO_DEBOUNCE_EN + bool "Ameba GPIO Interrupt Debounce Enable" + depends on GPIO_AMEBA + default y + help + When Enable GPIO Interrupt Debounce, the external signal can be debounced to + remove any spurious glitches that are less than one period(about 32us) of + the external debouncing clock. diff --git a/drivers/gpio/gpio_ameba.c b/drivers/gpio/gpio_ameba.c new file mode 100644 index 0000000000000..788d501da4140 --- /dev/null +++ b/drivers/gpio/gpio_ameba.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT realtek_ameba_gpio + +/* Include before to avoid redefining unlikely() macro */ +#include +#include + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(gpio_ameba, CONFIG_GPIO_LOG_LEVEL); + +#define GPIO_PINNAME(PORT, PIN) (((PORT) << 5) | ((PIN) & 0x1F)) + +struct gpio_ameba_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + /* port base address */ + uint32_t base; + /* IO port */ + int port; +}; + +struct gpio_ameba_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + /* port ISR callback routine address */ + sys_slist_t callbacks; +}; + +static int gpio_ameba_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_ameba_config *cfg = dev->config; + + *value = GPIO_PortRead(cfg->port, cfg->common.port_pin_mask); + + return 0; +} + +static int gpio_ameba_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) +{ + const struct gpio_ameba_config *cfg = dev->config; + + GPIO_PortDirection(cfg->port, mask, GPIO_Mode_OUT); + GPIO_PortWrite(cfg->port, mask, value); + + return 0; +} + +static int gpio_ameba_port_set_bits_raw(const struct device *dev, uint32_t mask) +{ + const struct gpio_ameba_config *cfg = dev->config; + + GPIO_PortWrite(cfg->port, mask, cfg->common.port_pin_mask); + + return 0; +} + +static int gpio_ameba_port_clear_bits_raw(const struct device *dev, uint32_t mask) +{ + const struct gpio_ameba_config *cfg = dev->config; + + GPIO_PortWrite(cfg->port, mask, 0); + + return 0; +} + +static int gpio_ameba_port_toggle_bits(const struct device *dev, uint32_t mask) +{ + const struct gpio_ameba_config *cfg = dev->config; + u32 gpio_pin; + u32 value; + uint8_t i; + + for (i = 0; i < 32; i++) { + if (mask & 0x1) { + gpio_pin = GPIO_PINNAME(cfg->port, i); + value = GPIO_ReadDataBit(gpio_pin); + GPIO_WriteBit(gpio_pin, (~value) & 0x1); + } + mask >>= 1; + if (mask == 0) { + break; + } + } + + return 0; +} + +static int gpio_ameba_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_ameba_config *cfg = dev->config; + + GPIO_InitTypeDef gpio_initstruct; + u32 gpio_pin; + + if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { + return -ENOTSUP; + } + + if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == 0) { + return -ENOTSUP; + } + + gpio_pin = GPIO_PINNAME(cfg->port, pin); + gpio_initstruct.GPIO_Pin = gpio_pin; + + if (flags & GPIO_INPUT) { + gpio_initstruct.GPIO_Mode = GPIO_Mode_IN; + } else { + gpio_initstruct.GPIO_Mode = GPIO_Mode_OUT; + } + + if (flags & GPIO_PULL_UP) { + gpio_initstruct.GPIO_PuPd = GPIO_PuPd_UP; + } else if (flags & GPIO_PULL_DOWN) { + gpio_initstruct.GPIO_PuPd = GPIO_PuPd_DOWN; + } else { + gpio_initstruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + } + + GPIO_Init(&gpio_initstruct); + + if (flags & GPIO_OUTPUT) { + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + gpio_ameba_port_set_bits_raw(dev, BIT(pin)); + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { + gpio_ameba_port_clear_bits_raw(dev, BIT(pin)); + } + } + + return 0; +} + +static int gpio_ameba_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_ameba_config *cfg = dev->config; + u32 gpio_pin; + + gpio_pin = GPIO_PINNAME(cfg->port, pin); + GPIO_InitTypeDef gpio_initstruct; + + gpio_initstruct.GPIO_Pin = gpio_pin; + + GPIO_INTConfig(gpio_pin, DISABLE); + + LOG_DBG("Config GPIO int:%d-%d, mode:%x, flag:0x%x\n", cfg->port, pin, mode, trig); + gpio_initstruct.GPIO_Pin = gpio_pin; + gpio_initstruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + gpio_initstruct.GPIO_Mode = GPIO_Mode_INT; + gpio_initstruct.GPIO_ITDebounce = GPIO_INT_DEBOUNCE_DISABLE; + + if (mode != GPIO_INT_MODE_DISABLED) { + if (mode & GPIO_INT_MODE_EDGE) { + switch (trig) { + case GPIO_INT_TRIG_LOW: + gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_EDGE; + gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_LOW; + break; + case GPIO_INT_TRIG_HIGH: + gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_EDGE; + gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_HIGH; + break; + case GPIO_INT_TRIG_BOTH: + gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_BOTHEDGE; + break; + default: + LOG_ERR("GPIO Edge interrupt type invalid \r\n"); + return -ENOTSUP; + } + } else { + gpio_initstruct.GPIO_ITTrigger = GPIO_INT_Trigger_LEVEL; + switch (trig) { + case GPIO_INT_TRIG_LOW: + gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_LOW; + gpio_initstruct.GPIO_PuPd = GPIO_PuPd_UP; + break; + case GPIO_INT_TRIG_HIGH: + gpio_initstruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_HIGH; + gpio_initstruct.GPIO_PuPd = GPIO_PuPd_DOWN; + break; + default: + LOG_ERR("GPIO level interrupt doesn't support both high and low"); + return -ENOTSUP; + } + } + +#if defined(CONFIG_GPIO_DEBOUNCE_EN) + gpio_initstruct.GPIO_ITDebounce = GPIO_INT_DEBOUNCE_ENABLE; + /* GPIO_DebounceClock(cfg->port, DEBOUNCE_DIV_CNT); */ + GPIO_Init(&gpio_initstruct); + DelayUs(64); + GPIO_INTConfig(gpio_pin, ENABLE); +#else + GPIO_Init(&gpio_initstruct); + GPIO_INTConfig(gpio_pin, ENABLE); +#endif + } else { + GPIO_Direction(gpio_pin, GPIO_Mode_IN); + PAD_PullCtrl(gpio_pin, gpio_initstruct.GPIO_PuPd); + + GPIO_INTMode(gpio_pin, DISABLE, 0, 0, 0); + } + + return 0; +} + +static int gpio_ameba_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct gpio_ameba_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +static uint32_t gpio_ameba_get_pending_int(const struct device *dev) +{ + uint32_t irq_status; + const struct gpio_ameba_config *cfg = dev->config; + uint32_t port = cfg->port; + + irq_status = GPIO_INTStatusGet(port); + + return irq_status; +} + +static void gpio_ameba_isr(const struct device *dev) +{ + uint32_t int_status; + struct gpio_ameba_data *data = dev->data; + const struct gpio_ameba_config *cfg = dev->config; + uint32_t port = cfg->port; + + /* Get the int status */ + int_status = GPIO_INTStatusGet(port); + + /* Clear pending edge interrupt */ + GPIO_INTStatusClearEdge(port); + + /* Call the registered callbacks */ + gpio_fire_callbacks(&data->callbacks, dev, int_status); +} + +static const struct gpio_driver_api gpio_ameba_driver_api = { + .pin_configure = gpio_ameba_configure, + .port_get_raw = gpio_ameba_port_get_raw, + .port_set_masked_raw = gpio_ameba_port_set_masked_raw, + .port_set_bits_raw = gpio_ameba_port_set_bits_raw, + .port_clear_bits_raw = gpio_ameba_port_clear_bits_raw, + .port_toggle_bits = gpio_ameba_port_toggle_bits, + .pin_interrupt_configure = gpio_ameba_pin_interrupt_configure, + .manage_callback = gpio_ameba_manage_callback, + .get_pending_int = gpio_ameba_get_pending_int, +}; + +#define GPIO_AMEBA_INIT(n) \ + static int gpio_ameba_port##n##_init(const struct device *dev) \ + { \ + const struct gpio_ameba_config *cfg = dev->config; \ + LOG_INF("GPIO%d INIT, IRQ %d\n", cfg->port, DT_INST_IRQN(n)); \ + \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), gpio_ameba_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + \ + return 0; \ + } \ + static struct gpio_ameba_data gpio_ameba_port##n##_data; \ + \ + static const struct gpio_ameba_config gpio_ameba_port##n##_config = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .base = DT_INST_REG_ADDR(n), \ + .port = n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_ameba_port##n##_init, NULL, &gpio_ameba_port##n##_data, \ + &gpio_ameba_port##n##_config, POST_KERNEL, \ + CONFIG_GPIO_INIT_PRIORITY, &gpio_ameba_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_AMEBA_INIT) diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 839c288c394ef..9ed8e033b54c5 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -45,6 +45,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_EMSDP pinctrl_emsdp.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_CC32XX pinctrl_ti_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_AMEBA pinctrl_ameba.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCI_IO_MUX pinctrl_mci_io_mux.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_ENE_KB1200 pinctrl_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index e13c4e427ff71..13a2d4c6b0368 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -72,6 +72,7 @@ source "drivers/pinctrl/Kconfig.emsdp" source "drivers/pinctrl/Kconfig.ti_cc32xx" source "drivers/pinctrl/Kconfig.numaker" source "drivers/pinctrl/Kconfig.eos_s3" +source "drivers/pinctrl/Kconfig.ameba" source "drivers/pinctrl/Kconfig.mci_io_mux" source "drivers/pinctrl/Kconfig.ene" source "drivers/pinctrl/Kconfig.zynqmp" diff --git a/drivers/pinctrl/Kconfig.ameba b/drivers/pinctrl/Kconfig.ameba new file mode 100644 index 0000000000000..3a168ee8467d0 --- /dev/null +++ b/drivers/pinctrl/Kconfig.ameba @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_AMEBA + bool "Pin controller driver for Realtek Ameba series SoC" + default y + depends on DT_HAS_REALTEK_AMEBA_PINCTRL_ENABLED + help + Enable pin controller driver for Realtek Ameba series SoC diff --git a/drivers/pinctrl/pinctrl_ameba.c b/drivers/pinctrl/pinctrl_ameba.c new file mode 100644 index 0000000000000..6ecb09efdd64e --- /dev/null +++ b/drivers/pinctrl/pinctrl_ameba.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Include before to avoid redefining unlikely() macro */ +#include +#include + +#include + +#define AMEBA_GET_PORT_NUM(pin_mux) ((pin_mux >> 13) & 0x03) +#define AMEBA_GET_PIN_NUM(pin_mux) ((pin_mux >> 8) & 0x1f) +#define AMEBA_GET_PIMNUX_ID(pin_mux) (pin_mux & 0xFF) + +#define AMEBA_GPIO_PINNAME(PORT, PIN) (((PORT) << 5) | ((PIN) & 0x1F)) + +static int ameba_configure_pin(const pinctrl_soc_pin_t *pin) +{ + uint32_t port_idx, pin_idx; + uint8_t gpio_pin; + uint32_t function_id; + + port_idx = AMEBA_GET_PORT_NUM(pin->pinmux); + pin_idx = AMEBA_GET_PIN_NUM(pin->pinmux); + function_id = AMEBA_GET_PIMNUX_ID(pin->pinmux); + gpio_pin = AMEBA_GPIO_PINNAME(port_idx, pin_idx); + + Pinmux_Config(gpio_pin, function_id); + + if (pin->pull_up) { + PAD_PullCtrl(gpio_pin, GPIO_PuPd_UP); + PAD_SleepPullCtrl(gpio_pin, GPIO_PuPd_UP); + } else if (pin->pull_down) { + PAD_PullCtrl(gpio_pin, GPIO_PuPd_DOWN); + PAD_SleepPullCtrl(gpio_pin, GPIO_PuPd_DOWN); + } else { + PAD_PullCtrl(gpio_pin, GPIO_PuPd_NOPULL); + PAD_SleepPullCtrl(gpio_pin, GPIO_PuPd_NOPULL); + } + + /* default slew rate fast */ + if (pin->slew_rate_slow) { + PAD_SlewRateCtrl(gpio_pin, PAD_SlewRate_Slow); + } + + /* Set the PAD driving strength to PAD_DRV_ABILITITY_LOW, default PAD_DRV_ABILITITY_HIGH */ + if (pin->drive_strength_low) { + PAD_DrvStrength(gpio_pin, PAD_DRV_ABILITITY_LOW); + } + + /* default enable digital path input. */ + if (pin->digital_input_disable) { + PAD_InputCtrl(gpio_pin, DISABLE); + } + + /* default enable schmitt */ + if (pin->schmitt_disable) { + PAD_SchmitCtrl(gpio_pin, DISABLE); + } + + if (pin->swd_off) { + Pinmux_Swdoff(); + } + + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + int ret = 0; + + ARG_UNUSED(reg); + + for (int i = 0; i < pin_cnt; i++) { + ret = ameba_configure_pin(&pins[i]); + + if (ret < 0) { + return ret; + } + } + + return 0; +} diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 9881217d5b009..916b0d475e297 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_AESC uart_aesc.c) zephyr_library_sources_ifdef(CONFIG_UART_ALTERA uart_altera.c) zephyr_library_sources_ifdef(CONFIG_UART_ALTERA_JTAG uart_altera_jtag.c) zephyr_library_sources_ifdef(CONFIG_UART_AMBIQ uart_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_UART_AMEBA_LOGUART uart_ameba_loguart.c) zephyr_library_sources_ifdef(CONFIG_UART_APBUART uart_apbuart.c) zephyr_library_sources_ifdef(CONFIG_UART_BCM2711_MU uart_bcm2711.c) zephyr_library_sources_ifdef(CONFIG_UART_BFLB uart_bflb.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ea3fbed123bac..82162de6795ec 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -161,6 +161,7 @@ rsource "Kconfig.aesc" rsource "Kconfig.altera" rsource "Kconfig.altera_jtag" rsource "Kconfig.ambiq" +rsource "Kconfig.ameba_loguart" rsource "Kconfig.apbuart" rsource "Kconfig.b91" rsource "Kconfig.bcm2711" diff --git a/drivers/serial/Kconfig.ameba_loguart b/drivers/serial/Kconfig.ameba_loguart new file mode 100644 index 0000000000000..5e42cf6ec07fe --- /dev/null +++ b/drivers/serial/Kconfig.ameba_loguart @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config UART_AMEBA_LOGUART + bool "Ameba LOGUART driver" + default y + depends on DT_HAS_REALTEK_AMEBA_LOGUART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + help + This option enables the LOGUART driver for Realtek Ameba SoCs. diff --git a/drivers/serial/uart_ameba_loguart.c b/drivers/serial/uart_ameba_loguart.c new file mode 100644 index 0000000000000..b862106d7784f --- /dev/null +++ b/drivers/serial/uart_ameba_loguart.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for Realtek Ameba LOGUART + */ + +/* Include before to avoid redefining unlikely() macro */ +#include +#include + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(loguart_ameba, CONFIG_UART_LOG_LEVEL); + +/* + * Extract information from devicetree. + * + * This driver only supports one instance of this IP block, so the + * instance number is always 0. + */ +#define DT_DRV_COMPAT realtek_ameba_loguart + +/* Device config structure */ +struct loguart_ameba_config { +#if defined(CONFIG_UART_INTERRUPT_DRIVEN) + uart_irq_config_func_t irq_config_func; +#endif +}; + +/* Device data structure */ +struct loguart_ameba_data { + struct uart_config config; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t user_cb; + void *user_data; + bool tx_int_en; + bool rx_int_en; +#endif +}; + +/** + * @brief Poll the device for input. + * + * @param dev UART device struct + * @param c Pointer to character + * + * @return 0 if a character arrived, -1 if the input buffer if empty. + */ +static int loguart_ameba_poll_in(const struct device *dev, unsigned char *c) +{ + ARG_UNUSED(dev); + + if (!LOGUART_Readable()) { + return -1; + } + + *c = LOGUART_GetChar(false); + return 0; +} + +/** + * @brief Output a character in polled mode. + * + * @param dev UART device struct + * @param c Character to send + */ +static void loguart_ameba_poll_out(const struct device *dev, unsigned char c) +{ + ARG_UNUSED(dev); + LOGUART_PutChar(c); +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +static int loguart_ameba_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len) +{ + ARG_UNUSED(dev); + + uint8_t num_tx = 0U; + unsigned int key; + + if (!LOGUART_Writable()) { + return num_tx; + } + + /* Lock interrupts to prevent nested interrupts or thread switch */ + + key = irq_lock(); + + while ((len - num_tx > 0) && LOGUART_Writable()) { + LOGUART_PutChar((uint8_t)tx_data[num_tx++]); + } + + irq_unlock(key); + + return num_tx; +} + +static int loguart_ameba_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + ARG_UNUSED(dev); + + uint8_t num_rx = 0U; + + while ((size - num_rx > 0) && LOGUART_Readable()) { + rx_data[num_rx++] = LOGUART_GetChar(false); + } + + /* Clear timeout int flag */ + if (LOGUART_GetStatus(LOGUART_DEV) & LOGUART_BIT_TIMEOUT_INT) { + LOGUART_INTClear(LOGUART_DEV, LOGUART_BIT_TOICF); + } + + return num_rx; +} + +static void loguart_ameba_irq_tx_enable(const struct device *dev) +{ + u32 sts; + struct loguart_ameba_data *data = dev->data; + + /* Disable IRQ Interrupts and Save Previous Status. */ + sts = irq_disable_save(); + + data->tx_int_en = true; + /* KM4: TX_PATH1 */ + LOGUART_INTConfig(LOGUART_DEV, LOGUART_TX_EMPTY_PATH_1_INTR, ENABLE); + + /* Enable IRQ Interrupts according to Previous Status. */ + irq_enable_restore(sts); +} + +static void loguart_ameba_irq_tx_disable(const struct device *dev) +{ + u32 sts; + struct loguart_ameba_data *data = dev->data; + + /* Disable IRQ Interrupts and Save Previous Status. */ + sts = irq_disable_save(); + + LOGUART_INTConfig(LOGUART_DEV, LOGUART_TX_EMPTY_PATH_1_INTR, DISABLE); + data->tx_int_en = false; + + /* Enable IRQ Interrupts according to Previous Status. */ + irq_enable_restore(sts); +} + +static int loguart_ameba_irq_tx_ready(const struct device *dev) +{ + struct loguart_ameba_data *data = dev->data; + + /* KM4: TX_PATH1 */ + return (LOGUART_GetStatus(LOGUART_DEV) & LOGUART_BIT_TP1F_EMPTY) && data->tx_int_en; +} + +static int loguart_ameba_irq_tx_complete(const struct device *dev) +{ + return loguart_ameba_irq_tx_ready(dev); +} + +static void loguart_ameba_irq_rx_enable(const struct device *dev) +{ + struct loguart_ameba_data *data = dev->data; + + data->rx_int_en = true; + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ERBI | LOGUART_BIT_ETOI, ENABLE); +} + +static void loguart_ameba_irq_rx_disable(const struct device *dev) +{ + struct loguart_ameba_data *data = dev->data; + + data->rx_int_en = false; + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ERBI | LOGUART_BIT_ETOI, DISABLE); +} + +static int loguart_ameba_irq_rx_ready(const struct device *dev) +{ + struct loguart_ameba_data *data = dev->data; + + return (LOGUART_GetStatus(LOGUART_DEV) & + (LOGUART_BIT_DRDY | LOGUART_BIT_RXFIFO_INT | LOGUART_BIT_TIMEOUT_INT)) && + data->rx_int_en; +} + +static void loguart_ameba_irq_err_enable(const struct device *dev) +{ + ARG_UNUSED(dev); + + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ELSI, ENABLE); +} + +static void loguart_ameba_irq_err_disable(const struct device *dev) +{ + ARG_UNUSED(dev); + + LOGUART_INTConfig(LOGUART_DEV, LOGUART_BIT_ELSI, DISABLE); +} + +static int loguart_ameba_irq_is_pending(const struct device *dev) +{ + return loguart_ameba_irq_tx_ready(dev) || loguart_ameba_irq_rx_ready(dev); +} + +static int loguart_ameba_irq_update(const struct device *dev) +{ + return 1; +} + +static void loguart_ameba_irq_callback_set(const struct device *dev, + uart_irq_callback_user_data_t cb, void *cb_data) +{ + struct loguart_ameba_data *data = dev->data; + + data->user_cb = cb; + data->user_data = cb_data; +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +/** + * @brief Initialize UART channel + * + * This routine is called to reset the chip in a quiescent state. + * It is assumed that this function is called only once per UART. + * + * @param dev UART device struct + * + * @return 0 on success + */ +static int loguart_ameba_init(const struct device *dev) +{ + LOGUART_RxCmd(LOGUART_DEV, DISABLE); + LOGUART_INT_NP2AP(); +#if defined(CONFIG_UART_INTERRUPT_DRIVEN) + const struct loguart_ameba_config *config = dev->config; + + config->irq_config_func(dev); +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + LOGUART_RxCmd(LOGUART_DEV, ENABLE); + + return 0; +} + +#if defined(CONFIG_UART_INTERRUPT_DRIVEN) +#define AMEBA_LOGUART_IRQ_HANDLER_DECL \ + static void loguart_ameba_irq_config_func(const struct device *dev); +#define AMEBA_LOGUART_IRQ_HANDLER \ + static void loguart_ameba_irq_config_func(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), loguart_ameba_isr, \ + DEVICE_DT_INST_GET(0), 0); \ + irq_enable(DT_INST_IRQN(0)); \ + } +#define AMEBA_LOGUART_IRQ_HANDLER_FUNC .irq_config_func = loguart_ameba_irq_config_func, +#else +#define AMEBA_LOGUART_IRQ_HANDLER_DECL /* Not used */ +#define AMEBA_LOGUART_IRQ_HANDLER /* Not used */ +#define AMEBA_LOGUART_IRQ_HANDLER_FUNC /* Not used */ +#endif + +#if defined(CONFIG_UART_INTERRUPT_DRIVEN) + +static void loguart_ameba_isr(const struct device *dev) +{ + struct loguart_ameba_data *data = dev->data; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + if (data->user_cb) { + data->user_cb(dev, data->user_data); + } +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +} +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api loguart_ameba_driver_api = { + .poll_in = loguart_ameba_poll_in, + .poll_out = loguart_ameba_poll_out, +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = loguart_ameba_fifo_fill, + .fifo_read = loguart_ameba_fifo_read, + .irq_tx_enable = loguart_ameba_irq_tx_enable, + .irq_tx_disable = loguart_ameba_irq_tx_disable, + .irq_tx_ready = loguart_ameba_irq_tx_ready, + .irq_rx_enable = loguart_ameba_irq_rx_enable, + .irq_rx_disable = loguart_ameba_irq_rx_disable, + .irq_tx_complete = loguart_ameba_irq_tx_complete, + .irq_rx_ready = loguart_ameba_irq_rx_ready, + .irq_err_enable = loguart_ameba_irq_err_enable, + .irq_err_disable = loguart_ameba_irq_err_disable, + .irq_is_pending = loguart_ameba_irq_is_pending, + .irq_update = loguart_ameba_irq_update, + .irq_callback_set = loguart_ameba_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +AMEBA_LOGUART_IRQ_HANDLER_DECL +AMEBA_LOGUART_IRQ_HANDLER + +static const struct loguart_ameba_config loguart_config = {AMEBA_LOGUART_IRQ_HANDLER_FUNC}; + +static struct loguart_ameba_data loguart_data = {.config = { + .stop_bits = UART_CFG_STOP_BITS_1, + .data_bits = UART_CFG_DATA_BITS_8, + .baudrate = DT_INST_PROP(0, current_speed), + .parity = UART_CFG_PARITY_NONE, + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, + }}; + +DEVICE_DT_INST_DEFINE(0, loguart_ameba_init, NULL, &loguart_data, &loguart_config, PRE_KERNEL_1, + CONFIG_SERIAL_INIT_PRIORITY, &loguart_ameba_driver_api); diff --git a/dts/arm/realtek/amebad/amebad.dtsi b/dts/arm/realtek/amebad/amebad.dtsi new file mode 100644 index 0000000000000..0ec2d9324c03a --- /dev/null +++ b/dts/arm/realtek/amebad/amebad.dtsi @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m33"; + reg = <0>; + d-cache-line-size = <32>; + #address-cells = <1>; + #size-cells = <1>; + }; + }; + + clocks { + clk_sys: clk_sys { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + }; + }; + + soc { + sram0: memory@10003020 { + compatible = "mmio-sram"; + reg = <0x10003020 0x00074000>; + }; + + ram_image2_entry: memory@10003000 { + compatible = "zephyr,memory-region"; + reg = <0x10003000 0x20>; + zephyr,memory-region = "KM4_IMG2_ENTRY"; + }; + + pinctrl: pinctrl@48000400 { + compatible = "realtek,ameba-pinctrl"; + reg = <0x48000400 0x200>; + }; + + loguart: serial@48012000 { + compatible = "realtek,ameba-loguart"; + reg = <0x48012000 0x100>; + interrupts = <3 0>; + current-speed = <1500000>; + status = "disabled"; + }; + + spic: flash-controller@48080000 { + compatible = "realtek,ameba-flash-controller"; + reg = <0x48080000 0x200>; + + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + + flash0: flash@E000020 { + compatible = "soc-nv-flash"; + erase-block-size = ; + write-block-size = <4>; + }; + }; + + gpioa: gpio@48014000 { + compatible = "realtek,ameba-gpio"; + reg = <0x48014000 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <4 0>; + status = "disabled"; + }; + + gpiob: gpio@48014400 { + compatible = "realtek,ameba-gpio"; + reg = <0x48014400 0x400>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <8 0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/bindings/gpio/realtek,ameba-gpio.yaml b/dts/bindings/gpio/realtek,ameba-gpio.yaml new file mode 100644 index 0000000000000..4eab82fd2316e --- /dev/null +++ b/dts/bindings/gpio/realtek,ameba-gpio.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +description: Realtek Ameba GPIO controller + +compatible: "realtek,ameba-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/pinctrl/realtek,ameba-pinctrl.yaml b/dts/bindings/pinctrl/realtek,ameba-pinctrl.yaml new file mode 100644 index 0000000000000..bf9d285b88689 --- /dev/null +++ b/dts/bindings/pinctrl/realtek,ameba-pinctrl.yaml @@ -0,0 +1,88 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +description: | + Realtek Ameba pinctrl is a singleton node responsible for controlling pin function selection + and pin properties. For example, you can use this node to route UART0 TX to pin PB_17 + and enable the pull-up resistor on the pin. + + All device pin configurations should be placed in child nodes of the 'pinctrl' node, + as shown in this example: + /* put this example in places like a board-pinctrl.dtsi file in your board directory, + * or a devicetree overlay in your application. + */ + &pinctrl { + /* configuration for uart0 device, default state */ + uart0_default: uart0_default { + /* 'group1' name is arbitrary, if pin's settings are not same, + * add other group like group2 {} + */ + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a particular state of a device; + in this case, the default (that is, active) state. You would specify the low-power configuration + for the same device in a separate child node. + + As shown, pin configurations are organized in groups within each child node. Each group can + specify a list of pin function selections in the 'pinmux' property. The AMEBA_PINMUX macro is + used to specify a pin function selection and pin configuration. You could choose pinmux specified + function to specified pin. And you could configure driver direction, driver state and pull state + for the specified pad. + + To link this pin configuration with a device, use a pinctrl-N property for some number N, + like this example you could place in your board's DTS file: + &uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + }; + +compatible: "realtek,ameba-pinctrl" + +include: base.yaml + +properties: + reg: + required: true +child-binding: + description: | + Realtek Ameba pin controller pin group for a pinctrl state. + child-binding: + description: | + Realtek Ameba pin controller pin configuration node. + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - input-schmitt-disable + properties: + pinmux: + required: true + type: array + description: | + Pin mux selections for this group. An array of pins sharing the same group properties. + Each element of the array is an integer constructed from the pin number and + the alternative function of the pin. + slew-rate-slow: + type: boolean + description: | + Pin output slew rate.If not set, default value is fast. + drive-strength-low: + type: boolean + description: | + Drive strength of the output pin.If not set, default ability is high. + digital-input-disable: + type: boolean + description: | + Disable the digital input function. + swd-off: + type: boolean + description: | + Disable the SWD function. diff --git a/dts/bindings/serial/realtek,ameba-loguart.yaml b/dts/bindings/serial/realtek,ameba-loguart.yaml new file mode 100644 index 0000000000000..68926503fc74a --- /dev/null +++ b/dts/bindings/serial/realtek,ameba-loguart.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +description: Ameba LOGUART +compatible: "realtek,ameba-loguart" + +include: [uart-controller.yaml, base.yaml, pinctrl-device.yaml] + +bus: uart + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/include/zephyr/dt-bindings/pinctrl/amebad-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/amebad-pinctrl.h new file mode 100644 index 0000000000000..da68b684ae864 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/amebad-pinctrl.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_AMEBAD_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_AMEBAD_PINCTRL_H_ + +/* PINMUX Function definitions */ +#define AMEBA_GPIO 0 +#define AMEBA_UART 1 +#define AMEBA_UART_RTSCTS 2 +#define AMEBA_LOGUART 2 +#define AMEBA_SPIM 3 +#define AMEBA_SPIS 3 +#define AMEBA_RTC 4 +#define AMEBA_TIMINPUT 4 +#define AMEBA_IR 5 +#define AMEBA_SPIF 6 +#define AMEBA_I2C 7 +#define AMEBA_SDIOD 8 +#define AMEBA_SDIOH 8 +#define AMEBA_PWM 9 +#define AMEBA_PWM_HS 9 +#define AMEBA_PWM_LP 10 +#define AMEBA_SWD 11 +#define AMEBA_I2S 12 +#define AMEBA_DMIC 12 +#define AMEBA_LCD 13 +#define AMEBA_USB 14 +#define AMEBA_QDEC 15 +#define AMEBA_SGPIO 16 +#define AMEBA_RFE 18 +#define AMEBA_BTCOEX 19 +#define AMEBA_WIFIFW 20 +#define AMEBA_EXT_PCM 20 +#define AMEBA_EXT_BT 20 +#define AMEBA_BB_PIN 21 +#define AMEBA_SIC 22 +#define AMEBA_TIMINPUT_HS 22 +#define AMEBA_DBGPORT 23 +#define AMEBA_BBDBG 25 +#define AMEBA_EXT32K 28 +#define AMEBA_RTCOUT 28 +#define AMEBA_KEYSCAN_ROW 29 +#define AMEBA_KEYSCAN_COL 30 +#define AMEBA_WAKEUP 31 + +/* Define pins number: bit[14:13] port, bit[12:8] pin, bit[7:0] function ID */ +#define AMEBA_PORT_PIN(port, line) ((((port) - 'A') << 5) + (line)) +#define AMEBA_PINMUX(port, line, funcid) (((AMEBA_PORT_PIN(port, line)) << 8) | (funcid)) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_AMEBAD_PINCTRL_H_ */ diff --git a/soc/realtek/ameba/CMakeLists.txt b/soc/realtek/ameba/CMakeLists.txt new file mode 100644 index 0000000000000..b770b597e60a6 --- /dev/null +++ b/soc/realtek/ameba/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(common) + +add_subdirectory(common) +add_subdirectory(${CONFIG_SOC}) diff --git a/soc/realtek/ameba/Kconfig b/soc/realtek/ameba/Kconfig new file mode 100644 index 0000000000000..b51759e890077 --- /dev/null +++ b/soc/realtek/ameba/Kconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_REALTEK_AMEBA + select BUILD_OUTPUT_HEX + select SOC_EARLY_INIT_HOOK + +if SOC_FAMILY_REALTEK_AMEBA + +rsource "*/Kconfig" + +endif # SOC_FAMILY_REALTEK_AMEBA diff --git a/soc/realtek/ameba/Kconfig.defconfig b/soc/realtek/ameba/Kconfig.defconfig new file mode 100644 index 0000000000000..d4e73efa3d45d --- /dev/null +++ b/soc/realtek/ameba/Kconfig.defconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_REALTEK_AMEBA + +rsource "*/Kconfig.defconfig" + +endif # SOC_FAMILY_REALTEK_AMEBA diff --git a/soc/realtek/ameba/Kconfig.soc b/soc/realtek/ameba/Kconfig.soc new file mode 100644 index 0000000000000..2c1a5f11b3160 --- /dev/null +++ b/soc/realtek/ameba/Kconfig.soc @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_REALTEK_AMEBA + bool + +config SOC_FAMILY + default "realtek_ameba" if SOC_FAMILY_REALTEK_AMEBA + +rsource "*/Kconfig.soc" diff --git a/soc/realtek/ameba/amebad/CMakeLists.txt b/soc/realtek/ameba/amebad/CMakeLists.txt new file mode 100644 index 0000000000000..c6443d35e9197 --- /dev/null +++ b/soc/realtek/ameba/amebad/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_include_directories(.) + +zephyr_sources(soc.c) + +zephyr_linker_sources(SECTIONS boot_section.ld) +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/realtek/ameba/amebad/Kconfig b/soc/realtek/ameba/amebad/Kconfig new file mode 100644 index 0000000000000..34589cf5bd58e --- /dev/null +++ b/soc/realtek/ameba/amebad/Kconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_AMEBAD + select ARM + select CPU_CORTEX_M33 + select CPU_HAS_DCACHE + select CPU_HAS_ICACHE + select CPU_HAS_ARM_SAU + select CPU_HAS_FPU + select CPU_HAS_VFP + select ARMV8_M_DSP + select CPU_HAS_ARM_MPU + select ARM_MPU + select ARM_TRUSTZONE_M + select ARM_ON_EXIT_CPU_IDLE diff --git a/soc/realtek/ameba/amebad/Kconfig.defconfig b/soc/realtek/ameba/amebad/Kconfig.defconfig new file mode 100644 index 0000000000000..fc99e462b5522 --- /dev/null +++ b/soc/realtek/ameba/amebad/Kconfig.defconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_AMEBAD + +config NUM_IRQS + default 64 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/clocks/clk_sys,clock-frequency) + +config CACHE_MANAGEMENT + default y + +endif #SOC_AMEBAD diff --git a/soc/realtek/ameba/amebad/Kconfig.soc b/soc/realtek/ameba/amebad/Kconfig.soc new file mode 100644 index 0000000000000..5ebb034fe2365 --- /dev/null +++ b/soc/realtek/ameba/amebad/Kconfig.soc @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_AMEBAD + bool + select SOC_FAMILY_REALTEK_AMEBA + +config SOC + default "amebad" if SOC_AMEBAD diff --git a/soc/realtek/ameba/amebad/boot_section.ld b/soc/realtek/ameba/amebad/boot_section.ld new file mode 100644 index 0000000000000..ed1d7a4c02163 --- /dev/null +++ b/soc/realtek/ameba/amebad/boot_section.ld @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + SECTION_PROLOGUE(.ram_image2.entry,,SUBALIGN(32)) + { + __image2_entry_func__ = .; + KEEP(*(SORT(.image2.entry.data*))) + . = ALIGN(32); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + SECTION_PROLOGUE(.psram_image2.text.data,,) + { + __image2_backtrace_start__ = .; + *(*.sramdram.only.text) + + . = ALIGN (4); + __ipc_table_start__ = .; + KEEP(*(*.ipc.table.data*)) + __ipc_table_end__ = .; + /*-----------------*/ + __image2_backtrace_end__ = .; + + . = ALIGN (32); + } GROUP_LINK_IN(ROMABLE_REGION) diff --git a/soc/realtek/ameba/amebad/soc.c b/soc/realtek/ameba/amebad/soc.c new file mode 100644 index 0000000000000..45cde922282e3 --- /dev/null +++ b/soc/realtek/ameba/amebad/soc.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include "ameba_system.h" + +void z_arm_reset(void); + +IMAGE2_ENTRY_SECTION +RAM_START_FUNCTION Img2EntryFun0 = {z_arm_reset, NULL, /* BOOT_RAM_WakeFromPG, */ + (uint32_t)NewVectorTable}; + +static void app_vdd1833_detect(void) +{ + u32 temp; + + if (FALSE == is_power_supply18()) { + temp = HAL_READ32(SYSTEM_CTRL_BASE_HP, REG_HS_RFAFE_IND_VIO1833); + temp |= BIT_RFAFE_IND_VIO1833; + HAL_WRITE32(SYSTEM_CTRL_BASE_HP, REG_HS_RFAFE_IND_VIO1833, temp); + } + + printk("REG_HS_RFAFE_IND_VIO1833 (0 is 1.8V): %x\n", + HAL_READ32(SYSTEM_CTRL_BASE_HP, REG_HS_RFAFE_IND_VIO1833)); +} + +void soc_early_init_hook(void) +{ + /* + * Cache is enabled by default at reset, disable it before + * sys_cache*-functions can enable them. + */ + Cache_Enable(DISABLE); + sys_cache_data_enable(); + sys_cache_instr_enable(); + + SystemSetCpuClk(CLK_KM4_200M); + + app_vdd1833_detect(); +} diff --git a/soc/realtek/ameba/amebad/soc.h b/soc/realtek/ameba/amebad/soc.h new file mode 100644 index 0000000000000..f29948817bd3d --- /dev/null +++ b/soc/realtek/ameba/amebad/soc.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_REALTEK_AMEBA_AMEBAD_H_ +#define ZEPHYR_SOC_REALTEK_AMEBA_AMEBAD_H_ + +#ifndef _ASMLANGUAGE + +#include +#include "cmsis_cpu.h" + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_SOC_REALTEK_AMEBA_AMEBAD_H_ */ diff --git a/soc/realtek/ameba/amebad/soc_cpu_idle.h b/soc/realtek/ameba/amebad/soc_cpu_idle.h new file mode 100644 index 0000000000000..a730b7e37c297 --- /dev/null +++ b/soc/realtek/ameba/amebad/soc_cpu_idle.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Workaround for WFI fused instruction issue */ +#define SOC_ON_EXIT_CPU_IDLE __NOP(); diff --git a/soc/realtek/ameba/common/CMakeLists.txt b/soc/realtek/ameba/common/CMakeLists.txt new file mode 100644 index 0000000000000..10252c5c3308a --- /dev/null +++ b/soc/realtek/ameba/common/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(os_wrapper) diff --git a/soc/realtek/ameba/common/os_wrapper/CMakeLists.txt b/soc/realtek/ameba/common/os_wrapper/CMakeLists.txt new file mode 100644 index 0000000000000..4a9540b9b93de --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Realtek Semiconductor Corp. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(include) diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper.h new file mode 100644 index 0000000000000..92dde9d8cb3c7 --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_H__ +#define __OS_WRAPPER_H__ + +/** + * @brief Necessary headers + */ +#include +#include +#include + +#include "platform_autoconf.h" +#include "ameba.h" +#include + +/** + * @brief Common header file + */ +#ifdef __cplusplus +extern "C" { +#endif +#include "os_wrapper_semaphore.h" +#include "os_wrapper_critical.h" +#include "os_wrapper_memory.h" +#include "os_wrapper_mutex.h" +#include "os_wrapper_queue.h" +#include "os_wrapper_semaphore.h" +#include "os_wrapper_task.h" +#include "os_wrapper_time.h" +#include "os_wrapper_timer.h" +#ifdef __cplusplus +} +#endif + +/** + * @brief General macro definition + */ + +#define RTOS_MAX_DELAY 0xFFFFFFFFUL +#define RTOS_MAX_TIMEOUT 0xFFFFFFFFUL + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_critical.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_critical.h new file mode 100644 index 0000000000000..d1534243cbd4c --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_critical.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_CRITCAL_H__ +#define __OS_WRAPPER_CRITCAL_H__ + +/** + * @brief Check if in task interrupt + * @retval 1: interrupt; 0: context + */ +int rtos_critical_is_in_interrupt(void); + +/** + * @brief Internally handles interrupt status (PRIMASK/CPSR) save + */ +void rtos_critical_enter(void); + +/** + * @brief Internally handles interrupt status(PRIMASK/CPSR) restore + */ +void rtos_critical_exit(void); + +/** + * @brief get task enter critical state + * @retval >0: in critical state; 0: exit critical state + */ +uint32_t rtos_get_critical_state(void); +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_memory.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_memory.h new file mode 100644 index 0000000000000..f52f2e0342cdd --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_memory.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_MEMORY_H__ +#define __OS_WRAPPER_MEMORY_H__ + +/** + * @brief Initialize dynamic memory pool + */ +void rtos_mem_init(void); + +/** + * @brief Allocate memory from the heap. The buffer value is random + * @note The return buffer size/address is cacheline size aligned + * @param size: buffer size in byte + * @retval Pointer to memory the caller can now use + */ +void *rtos_mem_malloc(uint32_t size); + +/** + * @brief Allocate memory from the heap. The buffer value is zero + * @note The return buffer size/address is cacheline size aligned + * @param size: buffer size in byte + * @retval Pointer to memory the caller can now use + */ +void *rtos_mem_zmalloc(uint32_t size); + +/** + * @brief Allocate memory from the heap. The buffer value is zero + * @note The return buffer size/address is cacheline size aligned + * @param elementNum: Number of elements, memory size is elementNum*elementSize + * @param elementSize: Size of each array element (in bytes). + * @retval Pointer to memory the caller can now use + */ +void *rtos_mem_calloc(uint32_t elementNum, uint32_t elementSize); + +/** + * @brief Reuse or extend memory previously allocated by the malloc(), calloc(), and realloc() + * functions + * @note The return buffer size/address is cacheline size aligned + * @param pbuf: Pointer containing the address + * @param size: The number of bytes of memory to be newly allocated. + * @retval Pointer to memory the caller can now use + */ +void *rtos_mem_realloc(void *pbuf, uint32_t size); + +/** + * @brief Deallocate memory from the heap. + * @param pbuf: a pointer to memory previously allocated + */ +void rtos_mem_free(void *pbuf); + +/** + * @brief Get free heap size. + * @retval Free heap size in byte + */ +uint32_t rtos_mem_get_free_heap_size(void); + +/** + * @brief Get minimum ever free heap size. + * @retval Minimum ever free heap size in byte + */ +uint32_t rtos_mem_get_minimum_ever_free_heap_size(void); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_mutex.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_mutex.h new file mode 100644 index 0000000000000..9f8bcc39d8c01 --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_mutex.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_MUTEX_H__ +#define __OS_WRAPPER_MUTEX_H__ + +/** + * @brief mutex handle type + */ +typedef void *rtos_mutex_t; + +#define MUTEX_WAIT_TIMEOUT 0xFFFFFFFFU /* will be replaced by common max timeout later */ + +/** + * @brief Static memory allocation implementation of rtos_mutex_create + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_create_static(rtos_mutex_t *pp_handle); + +/** + * @brief Static memory allocation implementation of rtos_mutex_delete + * @param p_handle: Address of the mutex + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_delete_static(rtos_mutex_t p_handle); + +/** + * @brief Static memory allocation implementation of rtos_mutex_recursive_create + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_recursive_create_static(rtos_mutex_t *pp_handle); + +/** + * @brief Static memory allocation implementation of rtos_mutex_recursive_delete + * @param p_handle: Address of the mutex + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_recursive_delete_static(rtos_mutex_t p_handle); + +/** + * @brief Compared to semaphores, Mutex has a priority inheritance mechanism. + * Dynamic allocate memory. + * @note Usage example: + * Create: + * rtos_mutex_t mutex_handle; + * rtos_mutex_create(&mutex_handle); + * Give: + * rtos_mutex_give(mutex_handle); + * Take: + * rtos_mutex_take(mutex_handle, 100); + * Delete: + * rtos_mutex_delete(mutex_handle); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_create(rtos_mutex_t *pp_handle); + +/** + * @brief Delete a mutex. + * @note Do not delete mutex if held by a task + * @param p_handle: Address of the mutex + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_delete(rtos_mutex_t p_handle); + +/** + * @brief Take a mutex. + * The API internally determines whether it is in the interrupt state and calls the + * corresponding RTOS interface. + * @param p_handle: Address of the mutex + * @param wait_ms: The time in milliseconds to wait, 0xFFFFFFFF means Block infinitely until the + * semaphore taken. + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_take(rtos_mutex_t p_handle, uint32_t wait_ms); + +/** + * @brief Give a semaphore. + * The API internally determines whether it is in the interrupt state and calls the + * corresponding RTOS interface. + * @param p_handle: Address of the mutex + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_give(rtos_mutex_t p_handle); + +/** + * @brief Creates a new recursive mutex, compared to semaphores, Mutex has a priority inheritance + * mechanism. Dynamic allocate memory. + * @note Usage example: + * Create: + * rtos_mutex_t mutex_handle; + * rtos_mutex_recursive_create(&mutex_handle); + * Give: + * rtos_mutex_recursive_give(mutex_handle); + * Take: + * rtos_mutex_recursive_take(mutex_handle, 100); + * Delete: + * rtos_mutex_recursive_delete(mutex_handle); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_recursive_create(rtos_mutex_t *pp_handle); + +/** + * @brief Delete a mutex. + * @param p_handle: Address of the mutex + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_recursive_delete(rtos_mutex_t p_handle); + +/** + * @brief Take a mutex. + * @note recursive mutexes cannot be used in interrupt service routines. + * @param p_handle: Address of the mutex + * @param wait_ms: The time in milliseconds to wait, 0xFFFFFFFF means Block infinitely until the + * semaphore taken. + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_recursive_take(rtos_mutex_t p_handle, uint32_t wait_ms); + +/** + * @brief Give a semaphore. + * @note Recursive mutexes cannot be used in interrupt service routines. + * @param p_handle: Address of the mutex + * @retval The status is SUCCESS or FAIL + */ +int rtos_mutex_recursive_give(rtos_mutex_t p_handle); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_queue.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_queue.h new file mode 100644 index 0000000000000..141e7a506d420 --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_queue.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_QUEUE_H__ +#define __OS_WRAPPER_QUEUE_H__ + +/** + * @brief queue handle type + */ +typedef void *rtos_queue_t; + +/** + * @brief Creates a new queue instance + * @note Usage example: + * Create: + * rtos_queue_t queue_handle; + * rtos_queue_create(&queue_handle, 5, sizeof(uint32_t)); + * Send: + * rtos_queue_send(queue_handle, p_msg, portMAX_DELAY); + * Receive: + * rtos_queue_receive(queue_handle, p_msg, portMAX_DELAY); + * Delete: + * rtos_queue_delete(queue_handle); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @param msg_num: Maximum number of messages that can be queued. + * @param msg_size: Message size (in bytes). + * @retval The status is SUCCESS or FAIL + */ +int rtos_queue_create(rtos_queue_t *pp_handle, uint32_t msg_num, uint32_t msg_size); + +/** + * @brief Delete a queue - freeing all the memory allocated for storing of items placed on the + * queue. + * @param p_handle: A handle to the queue to be deleted. + * @retval The status is SUCCESS or FAIL + */ +int rtos_queue_delete(rtos_queue_t p_handle); + +/** + * @brief Return the number of messages stored in a queue. + * @param p_handle: A handle to the queue being queried. + * @retval The number of messages available in the queue. + */ +uint32_t rtos_queue_message_waiting(rtos_queue_t p_handle); + +/** + * @brief Send a message to a message queue in a "first in, first out" manner. + * @param p_handle: Address of the message queue. + * @param p_msg: Pointer to the message. + * @param wait_ms: Waiting period to add the message, 0xFFFFFFFF means Block infinitely. + * @retval The status is SUCCESS or FAIL + */ +int rtos_queue_send(rtos_queue_t p_handle, void *p_msg, uint32_t wait_ms); + +/** + * @brief Send a message to the head of message queue in a "last in, first out" manner. + * @param p_handle: Address of the message queue. + * @param p_msg: Pointer to the message. + * @param wait_ms: Waiting period to add the message, 0xFFFFFFFF means Block infinitely. + * @retval The status is SUCCESS or FAIL + */ +int rtos_queue_send_to_front(rtos_queue_t p_handle, void *p_msg, uint32_t wait_ms); + +/** + * @brief Receive a message from a message queue in a "first in, first out" manner. + * Messages are received from the queue and removed from the queue, so the queue's state + * changes. + * @param p_handle: Address of the message queue. + * @param p_msg: Address of area to hold the received message. + * @param wait_ms: Waiting period to add the message, 0xFFFFFFFF means Block infinitely. + * @retval The status is SUCCESS or FAIL + */ +int rtos_queue_receive(rtos_queue_t p_handle, void *p_msg, uint32_t wait_ms); + +/** + * @brief Peek/read a message from a message queue in a "first in, first out" manner. + * Simply viewing the next message in the queue does not remove it from the queue, + * so the state of the queue remains unchanged. + * @param p_handle: Address of the message queue. + * @param p_msg: Address of area to hold the received message. + * @param wait_ms: Waiting period to add the message, 0xFFFFFFFF means Block infinitely. + * @retval The status is SUCCESS or FAIL + */ +int rtos_queue_peek(rtos_queue_t p_handle, void *p_msg, uint32_t wait_ms); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_semaphore.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_semaphore.h new file mode 100644 index 0000000000000..d2b3188e647b3 --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_semaphore.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_SEMA_H__ +#define __OS_WRAPPER_SEMA_H__ + +#define RTOS_SEMA_MIN_COUNT 0x0UL +#define RTOS_SEMA_MAX_COUNT 0xFFFFFFFFUL + +/** + * @brief semaphore handle type + */ +typedef void *rtos_sema_t; + +/** + * @brief Static memory allocation implementation of rtos_sema_create + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @param init_count: The count value assigned to the semaphore when it is created. + * @param max_count: The maximum count value that can be reached. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_create_static(rtos_sema_t *pp_handle, uint32_t init_count, uint32_t max_count); + +/** + * @brief Static memory allocation implementation of rtos_sema_create_binary + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_create_binary_static(rtos_sema_t *pp_handle); + +/** + * @brief Static memory allocation implementation of rtos_sema_delete + * @param p_handle: Address of the semaphore + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_delete_static(rtos_sema_t p_handle); + +/** + * @brief Creates a new counting semaphore instance + * Dynamic allocate memory. + * @note Usage example: + * Create: + * rtos_sema_t sema_handle; + * rtos_sema_create(&sema_handle, 0, 10); + * Give: + * rtos_sema_give(sema_handle); + * Take: + * rtos_sema_take(sema_handle, 100); + * Delete: + * rtos_sema_delete(sema_handle); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @param init_count: The count value assigned to the semaphore when it is created. + * @param max_count: The maximum count value that can be reached. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_create(rtos_sema_t *pp_handle, uint32_t init_count, uint32_t max_count); + +/** + * @brief Creates a new binary semaphore instance + * Dynamic allocate memory. + * @note The semaphore must first be 'given' before it can be 'taken'. + * Usage example: + * Create: + * rtos_sema_t sema_handle; + * rtos_sema_create_binary(&sema_handle); + * Give: + * rtos_sema_give(sema_handle); + * Take: + * rtos_sema_take(sema_handle, 100); + * Delete: + * rtos_sema_delete(sema_handle); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_create_binary(rtos_sema_t *pp_handle); + +/** + * @brief Delete a semaphore. + * @param p_handle: A handle to the semaphore to be deleted. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_delete(rtos_sema_t p_handle); + +/** + * @brief Take a semaphore. + * The API internally determines whether it is in the interrupt state and calls the + * corresponding RTOS interface. + * + * @note If timeout_ms is set to the maximum value, + * then if the semaphore cannot be obtained consistently, the log will be printed every 10 + * seconds. + * @param p_handle: Address of the semaphore. + * @param timeout_ms: Waiting period to add the message, 0xFFFFFFFF means Block infinitely. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_take(rtos_sema_t p_handle, uint32_t timeout_ms); + +/** + * @brief Give a semaphore. + * The API internally determines whether it is in the interrupt state and calls the + * corresponding RTOS interface. + * @param p_handle: Address of the semaphore. + * @retval The status is SUCCESS or FAIL + */ +int rtos_sema_give(rtos_sema_t p_handle); + +/** + * @brief Get a semaphore's count. If the semaphore is a binary semaphore then returns 1 if the + * semaphore is available, and 0 if the semaphore is not available. + * @param p_handle: Address of the semaphore. + * @retval Current semaphore count. + */ +uint32_t rtos_sema_get_count(rtos_sema_t p_handle); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_task.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_task.h new file mode 100644 index 0000000000000..82ad32e331851 --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_task.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_TASK_H__ +#define __OS_WRAPPER_TASK_H__ + +/* CONFIG_NUM_COOP_PRIORITIES shall be 0 */ +#define RTOS_TASK_MAX_PRIORITIES (CONFIG_NUM_PREEMPT_PRIORITIES) +#define RTOS_MINIMAL_STACK_SIZE (1024) +#define RTOS_MINIMAL_SECURE_STACK_SIZE (1024) + +#define RTOS_SCHED_SUSPENDED 0x0UL +#define RTOS_SCHED_NOT_STARTED 0x1UL +#define RTOS_SCHED_RUNNING 0x2UL + +/** + * @brief task handle and function type + */ +typedef void *rtos_task_t; +typedef void (*rtos_task_function_t)(void *); + +/** + * @brief Start os kernel scheduler + * @retval return SUCCESS Only + */ +int rtos_sched_start(void); + +/** + * @brief Stop os kernel scheduler + * @retval return SUCCESS Only + */ +int rtos_sched_stop(void); + +/** + * @brief Suspend os kernel scheduler + * @retval return SUCCESS Only + */ +int rtos_sched_suspend(void); + +/** + * @brief Resume os kernel scheduler + * @retval return SUCCESS Only + */ +int rtos_sched_resume(void); + +/** + * @brief Get scheduler status. + * @retval RTOS_SCHED_SUSPENDED / RTOS_SCHED_NOT_STARTED / RTOS_SCHED_RUNNING + */ +int rtos_sched_get_state(void); + +/** + * @brief Create os level task routine. + * @note Usage example: + * Create: + * rtos_task_t handle; + * rtos_task_create(&handle, "test_task", task, NULL, 1024, 2); + * Suspend: + * rtos_task_suspend(handle); + * Resume: + * rtos_task_resume(handle); + * Delete: + * rtos_task_delete(handle); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @param p_name: A descriptive name for the task. + * @param p_routine: Pointer to the task entry function. Tasks must be implemented to never return + * (i.e. continuous loop). + * @param p_param: Pointer that will be used as the parameter + * @param stack_size_in_byte: The size of the task stack specified + * @param priority: The priority at which the task should run (higher value, higher priority) + * @retval SUCCESS(0) / FAIL(-1) + */ +int rtos_task_create(rtos_task_t *pp_handle, const char *p_name, rtos_task_function_t p_routine, + void *p_param, uint16_t stack_size_in_byte, uint16_t priority); + +/** + * @brief Delete os level task routine. + * @param p_handle: Task handle. If a null pointer is passed, the task itself is deleted. + * @retval return SUCCESS Only + */ +int rtos_task_delete(rtos_task_t p_handle); + +/** + * @brief Suspend os level task routine. + * @param p_handle: Task handle. + * @retval return SUCCESS Only + */ +int rtos_task_suspend(rtos_task_t p_handle); + +/** + * @brief Resume os level task routine. + * @param p_handle: Task handle. + * @retval return SUCCESS Only + */ +int rtos_task_resume(rtos_task_t p_handle); + +/** + * @brief Yield current os level task routine. + * @retval return SUCCESS Only + */ +int rtos_task_yield(void); + +/** + * @brief Get current os level task routine handle. + * @retval The task handle pointer + */ +rtos_task_t rtos_task_handle_get(void); + +/** + * @brief Get os level task routine priority. + * @param p_handle: Task handle. + * @retval Task priority value + */ +uint32_t rtos_task_priority_get(rtos_task_t p_handle); + +/** + * @brief Set os level task routine priority. + * @param p_handle: Task handle. + * @param priority: The priority at which the task should run (higher value, higher priority) + * @retval return SUCCESS Only + */ +int rtos_task_priority_set(rtos_task_t p_handle, uint16_t priority); + +/** + * @brief Print current task status + */ +void rtos_task_out_current_status(void); + +/** + * @brief Allocate a secure context for the task. + * @note trustzone is required. Otherwise it's just an empty implementation. + */ +void rtos_create_secure_context(uint32_t size); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_time.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_time.h new file mode 100644 index 0000000000000..4c08f10f0d88b --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_time.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_TIME_H__ +#define __OS_WRAPPER_TIME_H__ + +#define RTOS_TICK_RATE_HZ 1000UL +#define RTOS_TICK_RATE_MS (1000UL / RTOS_TICK_RATE_HZ) + +#define RTOS_TIME_GET_PASSING_TIME_MS(start) (rtos_time_get_current_system_time_ms() - (start)) + +#define RTOS_TIME_GET_TIME_INTERVAL_MS(start, end) ((end) - (start)) +#define RTOS_TIME_SET_MS_TO_SYSTIME(time) (time / RTOS_TICK_RATE_MS) + +/** + * @brief If the current system is in a scheduling and non-interrupted state, it will switch to + * other tasks. Otherwise, the nop instruction will be executed. + * @param ms: Delay time in milliseconds + */ +void rtos_time_delay_ms(uint32_t ms); + +/** + * @brief The system will execute the nop instruction without scheduling. + * @param us: Delay time in microseconds + */ +void rtos_time_delay_us(uint32_t us); + +/** + * @brief Get the count of ticks since rtos_sched_start was called, and convert the return value to + * milliseconds. + * @note This interface does not consider systick overflow issues. + */ +uint32_t rtos_time_get_current_system_time_ms(void); + +/** + * @brief Return value to in microseconds. + * @note This interface does not consider systick overflow issues. + */ +uint64_t rtos_time_get_current_system_time_us(void); + +/** + * @brief Return value to in nanoseconds. + * @note This interface does not consider systick overflow issues. The accuracy is the clk + * frequency of the CPU + */ +uint64_t rtos_time_get_current_system_time_ns(void); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_timer.h b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_timer.h new file mode 100644 index 0000000000000..3485619c15291 --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/os_wrapper_timer.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OS_WRAPPER_TIMER_H__ +#define __OS_WRAPPER_TIMER_H__ + +#define RTOS_TIMER_MAX_DELAY 0xFFFFFFFFUL + +/** + * @brief timer handle type + */ +typedef void *rtos_timer_t; + +/** + * @brief Static memory allocation implementation of rtos_timer_create + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @param p_timer_name: A descriptive name for the timer. + * @param timer_id: An identifier that is assigned to the timer being created. Typically this would + * be used in the timer callback function to identify which timer expired when the same callback + * function is assigned to more than one timer. + * @param interval_ms: The timer period in milliseconds. + * @param reload: Used to set the timer as a periodic or one-shot timer. + * @param p_timer_callback: The function to call when the timer expires. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_create_static(rtos_timer_t *pp_handle, const char *p_timer_name, uint32_t timer_id, + uint32_t interval_ms, uint8_t reload, + void (*p_timer_callback)(void *)); + +/** + * @brief Static memory allocation implementation of rtos_timer_delete + * @param p_handle: The handle of the timer being deleted. + * @param wait_ms: Specifies the time that the calling task should be held in the Blocked state + * to wait for the delete command to be successfully sent to the timer command + * queue. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_delete_static(rtos_timer_t p_handle, uint32_t wait_ms); + +/** + * @brief Create a new software timer instance. This allocates the storage required by the new + * timer, initializes the new timers internal state, and returns a handle by which the new timer can + * be referenced. + * @note Usage example: + * Create: + * rtos_timer_t timer_handle; + * rtos_timer_create(&timer_handle, "timer_test", timer_id, delay_ms, is_reload, + * timer_cb_function); Start: rtos_timer_start(timer_handle, wait_ms); Stop: + * rtos_timer_stop(timer_handle, wait_ms); + * Delete: + * rtos_timer_delete(timer_handle, wait_ms); + * @param pp_handle: The handle itself is a pointer, and the pp_handle means a pointer to the + * handle. + * @param p_timer_name: A descriptive name for the timer. + * @param timer_id: An identifier that is assigned to the timer being created. Typically this would + * be used in the timer callback function to identify which timer expired when the same callback + * function is assigned to more than one timer. + * @param interval_ms: The timer period in milliseconds. + * @param reload: Used to set the timer as a periodic or one-shot timer. + * @param p_timer_callback: The function to call when the timer expires. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_create(rtos_timer_t *pp_handle, const char *p_timer_name, uint32_t timer_id, + uint32_t interval_ms, uint8_t reload, void (*p_timer_callback)(void *)); + +/** + * @brief Delete a timer that was previously created using a call to rtos_timer_create. + * @param p_handle: The handle of the timer being deleted. + * @param wait_ms: Specifies the time that the calling task should be held in the Blocked state + * to wait for the delete command to be successfully sent to the timer command + * queue. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_delete(rtos_timer_t p_handle, uint32_t wait_ms); + +/** + * @brief Start a timer that was previously created using a call to rtos_timer_create. + * @param p_handle: The handle of the created timer + * @param wait_ms: Specifies the time that the calling task should be held in the Blocked state + * to wait for the start command to be successfully sent to the timer command + * queue. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_start(rtos_timer_t p_handle, uint32_t wait_ms); + +/** + * @brief Stopping a timer ensures the timer is not in the active state. + * @param p_handle: The handle of the created timer + * @param wait_ms: Specifies the time that the calling task should be held in the Blocked state + * to wait for the stop command to be successfully sent to the timer command queue. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_stop(rtos_timer_t p_handle, uint32_t wait_ms); + +/** + * @brief changes the period of a timer that was previously created using a call to + * rtos_timer_create. + * @param p_handle: The handle of the created timer + * @param interval_ms: The new period for xTimer. + * @param wait_ms: Specifies the time that the calling task should be held in the Blocked state + * to wait for the change command to be successfully sent to the timer command + * queue. + * @retval The status is SUCCESS or FAIL + */ +int rtos_timer_change_period(rtos_timer_t p_handle, uint32_t interval_ms, uint32_t wait_ms); + +/** + * @brief Queries a timer to see if it is active or dormant. A timer will be dormant if: + * 1) It has been created but not started, or + * 2) It is an expired one-shot timer that has not been restarted. + * @note non-interrupt safety + * @param p_handle: The handle of the created timer + * @retval Timer is active or not. + */ +uint32_t rtos_timer_is_timer_active(rtos_timer_t p_handle); + +/** + * @brief Get the ID assigned to the timer when created. + * @note non-interrupt safety + * @param p_handle: Pointer to the created timer handle. + * @retval the ID assigned to the timer. + */ +uint32_t rtos_timer_get_id(rtos_timer_t p_handle); + +#endif diff --git a/soc/realtek/ameba/common/os_wrapper/include/platform_stdlib.h b/soc/realtek/ameba/common/os_wrapper/include/platform_stdlib.h new file mode 100644 index 0000000000000..84f34943284ba --- /dev/null +++ b/soc/realtek/ameba/common/os_wrapper/include/platform_stdlib.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __PLATFORM_STDLIB_H__ +#define __PLATFORM_STDLIB_H__ + +#include +#include +#include +#include +#include /* va_list */ + +#endif diff --git a/soc/realtek/ameba/common/pinctrl_soc.h b/soc/realtek/ameba/common/pinctrl_soc.h new file mode 100644 index 0000000000000..52bd8aab63ad0 --- /dev/null +++ b/soc/realtek/ameba/common/pinctrl_soc.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Realtek Semiconductor Corp. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_REALTEK_AMEBA_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_REALTEK_AMEBA_COMMON_PINCTRL_SOC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct pinctrl_soc_pin { + uint32_t pinmux: 15; + /* bit[14:13] port + * bit[12:8] pin + * bit[7:0] function ID + */ + uint32_t pull_down: 1; + uint32_t pull_up: 1; + uint32_t schmitt_disable: 1; + uint32_t slew_rate_slow: 1; + uint32_t drive_strength_low: 1; + uint32_t digital_input_disable: 1; + uint32_t swd_off: 1; +}; + +typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { \ + .pinmux = DT_PROP_BY_IDX(node_id, prop, idx), \ + .pull_down = DT_PROP(node_id, bias_pull_down), \ + .pull_up = DT_PROP(node_id, bias_pull_up), \ + .schmitt_disable = DT_PROP(node_id, input_schmitt_disable), \ + .slew_rate_slow = DT_PROP(node_id, slew_rate_slow), \ + .drive_strength_low = DT_PROP(node_id, drive_strength_low), \ + .digital_input_disable = DT_PROP(node_id, digital_input_disable), \ + .swd_off = DT_PROP(node_id, swd_off), \ + }, + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_REALTEK_AMEBA_COMMON_PINCTRL_SOC_H_ */ diff --git a/soc/realtek/ameba/soc.yml b/soc/realtek/ameba/soc.yml new file mode 100644 index 0000000000000..58a4eb2b9522a --- /dev/null +++ b/soc/realtek/ameba/soc.yml @@ -0,0 +1,4 @@ +family: +- name: realtek_ameba + socs: + - name: amebad diff --git a/west.yml b/west.yml index fc43ee8198522..62787314defa6 100644 --- a/west.yml +++ b/west.yml @@ -23,6 +23,8 @@ manifest: url-base: https://github.com/zephyrproject-rtos - name: babblesim url-base: https://github.com/BabbleSim + - name: nuwa + url-base: https://github.com/zjian-zhang group-filter: [-babblesim, -optional] @@ -224,6 +226,12 @@ manifest: path: modules/hal/quicklogic groups: - hal + - name: hal_realtek + remote: nuwa + path: modules/hal/realtek + revision: e3d9fcdfe0f8e65d5ba25bc36196f3b2f3047f2b + groups: + - hal - name: hal_renesas path: modules/hal/renesas revision: 9b99067e29a1b44b53192c2c797db330f5703462