diff --git a/boards/sifli/sf32lb52_devkit_lcd/sf32lb52_devkit_lcd.dts b/boards/sifli/sf32lb52_devkit_lcd/sf32lb52_devkit_lcd.dts index e3d1443f876a9..3f122dd662141 100644 --- a/boards/sifli/sf32lb52_devkit_lcd/sf32lb52_devkit_lcd.dts +++ b/boards/sifli/sf32lb52_devkit_lcd/sf32lb52_devkit_lcd.dts @@ -21,6 +21,7 @@ zephyr,code-partition = &code; zephyr,console = &usart1; zephyr,shell-uart = &usart1; + zephyr,bt-hci = &mailbox; }; buttons { @@ -119,3 +120,8 @@ pinctrl-0 = <&usart1_default>; pinctrl-names = "default"; }; + +&mailbox { + status = "okay"; +}; + diff --git a/drivers/bluetooth/hci/CMakeLists.txt b/drivers/bluetooth/hci/CMakeLists.txt index 82c6b590d023d..6e94d760f34b2 100644 --- a/drivers/bluetooth/hci/CMakeLists.txt +++ b/drivers/bluetooth/hci/CMakeLists.txt @@ -51,6 +51,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_DA1453X hci_da1453x.c) zephyr_library_sources_ifdef(CONFIG_BT_DA1469X hci_da1469x.c) zephyr_library_sources_ifdef(CONFIG_BT_NXP hci_nxp.c) zephyr_library_sources_ifdef(CONFIG_BT_H4_NXP_CTLR hci_nxp_setup.c) +zephyr_library_sources_ifdef(CONFIG_BT_SF32LB hci_sf32lb.c) if(CONFIG_BT_USERCHAN) zephyr_library_sources(userchan.c) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index d62c3bb0b18e1..7179ed3889211 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -361,6 +361,7 @@ config BT_DRV_RX_STACK_SIZE default BT_RX_STACK_SIZE if (BT_H4 || BT_HCI_RAW_H4) default BT_STM32_IPM_RX_STACK_SIZE if BT_STM32_IPM default HCI_NXP_RX_STACK_SIZE if HCI_NXP_RX_THREAD + default 1024 if BT_SF32LB default 512 help Stack size for the HCI driver's RX thread. @@ -402,3 +403,11 @@ config BT_H4_NXP_CTLR_WAIT_TIME_AFTER_BAUDRATE_UPDATE Waiting time after controller baudrate is updated. Unit is millisecond. endif #BT_H4_NXP_CTLR + +config BT_SF32LB + bool "SiFli Bluetooth Controller" + default y + depends on DT_HAS_SIFLI_SF32LB_MAILBOX_ENABLED + select USE_SIFLI_IPC_QUEUE + help + Bluetooth HCI over ipc mailbox in SiFli SF32LB chipsets. diff --git a/drivers/bluetooth/hci/hci_sf32lb.c b/drivers/bluetooth/hci/hci_sf32lb.c new file mode 100644 index 0000000000000..42d4644852937 --- /dev/null +++ b/drivers/bluetooth/hci/hci_sf32lb.c @@ -0,0 +1,616 @@ +/* + * Copyright (c) SiFli Technologies(Nanjing) Co., Ltd + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT sifli_sf32lb_mailbox + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "common/bt_str.h" +#include "bf0_hal.h" +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_driver); + +#define IPC_TIMEOUT_MS 10 +#define H4TL_PACKET_HOST 0x61 +#define H4TL_PACKET_CTRL 0x62 + +struct h4_data { + struct { + struct net_buf *buf; + struct k_fifo fifo; + + uint16_t remaining; + uint16_t discard; + + bool have_hdr; + bool discardable; + + uint8_t hdr_len; + + uint8_t type; + union { + struct bt_hci_evt_hdr evt; + struct bt_hci_acl_hdr acl; + struct bt_hci_iso_hdr iso; + struct bt_hci_sco_hdr sco; + uint8_t hdr[4]; + }; + } rx; + + struct { + uint8_t type; + struct net_buf *buf; + struct k_fifo fifo; + } tx; + + struct k_sem sem; + bt_hci_recv_t recv; + ipc_queue_handle_t ipc_port; +}; + +struct h4_config { + const struct device *mbox; + k_thread_stack_t *rx_thread_stack; + size_t rx_thread_stack_size; + struct k_thread *rx_thread; + ipc_queue_handle_t ipc_port; +}; + +static inline void process_tx(const struct device *dev); +static inline void process_rx(const struct device *dev); + +static int32_t mbox_rx_ind(ipc_queue_handle_t handle, size_t size) +{ + const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(mailbox)); + struct h4_data *h4 = dev->data; + + LOG_DBG("mbox_rx_ind"); + k_sem_give(&(h4->sem)); + return 0; +} + +static void mbox_sf32lb_isr(const struct device *dev) +{ + LOG_DBG("mbox_sf32lb_isr %p", (void *)dev); + LCPU2HCPU_IRQHandler(); +} + +static void zbt_config_mailbox(const struct device *dev) +{ + ipc_queue_cfg_t q_cfg; + struct h4_data *h4 = dev->data; + +#ifndef CONFIG_SIFLI_LXT_DISABLE + /* Enable LXT32K */ + HAL_PMU_EnableXTAL32(); + if (HAL_PMU_LXTReady() != HAL_OK) { + HAL_ASSERT(0); + } + /* RTC/GTIME/LPTIME Using same low power clock source */ + HAL_RTC_ENABLE_LXT(); +#endif + HAL_HPAON_StartGTimer(); + + k_sem_init(&(h4->sem), 0, 1); + + q_cfg.qid = 0; + q_cfg.tx_buf_size = HCPU2LCPU_MB_CH1_BUF_SIZE; + q_cfg.tx_buf_addr = HCPU2LCPU_MB_CH1_BUF_START_ADDR; + q_cfg.tx_buf_addr_alias = HCPU_ADDR_2_LCPU_ADDR(HCPU2LCPU_MB_CH1_BUF_START_ADDR); + +#ifndef SF32LB52X + /* Config IPC queue. */ + q_cfg.rx_buf_addr = LCPU_ADDR_2_HCPU_ADDR(LCPU2HCPU_MB_CH1_BUF_START_ADDR); +#else + uint8_t rev_id = __HAL_SYSCFG_GET_REVID(); + + if (rev_id < HAL_CHIP_REV_ID_A4) { + q_cfg.rx_buf_addr = LCPU_ADDR_2_HCPU_ADDR(LCPU2HCPU_MB_CH1_BUF_START_ADDR); + } else { + q_cfg.rx_buf_addr = LCPU_ADDR_2_HCPU_ADDR(LCPU2HCPU_MB_CH1_BUF_REV_B_START_ADDR); + } +#endif + + q_cfg.rx_ind = NULL; + q_cfg.user_data = 0; + + if (q_cfg.rx_ind == NULL) { + q_cfg.rx_ind = mbox_rx_ind; + } + + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), mbox_sf32lb_isr, + DEVICE_DT_INST_GET(0), 0); + h4->ipc_port = ipc_queue_init(&q_cfg); + __ASSERT(IPC_QUEUE_INVALID_HANDLE != h4->ipc_port, "Invalid Handle"); + if (ipc_queue_open(h4->ipc_port)) { + __ASSERT(0, "Could not open IPC"); + } +} + +void sf32lb_hci_trace(uint8_t type, const uint8_t *data, uint16_t len, uint8_t h4tl_packet) +{ + /*TODO: Add HCI trace functions*/ +} + +static inline void h4_get_type(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + /* Get packet type */ + if (ipc_queue_read(h4->ipc_port, &h4->rx.type, 1) != 1) { + LOG_WRN("Unable to read H:4 packet type"); + h4->rx.type = BT_HCI_H4_NONE; + return; + } + + switch (h4->rx.type) { + case BT_HCI_H4_EVT: + h4->rx.remaining = sizeof(h4->rx.evt); + h4->rx.hdr_len = h4->rx.remaining; + break; + case BT_HCI_H4_ACL: + h4->rx.remaining = sizeof(h4->rx.acl); + h4->rx.hdr_len = h4->rx.remaining; + break; + case BT_HCI_H4_SCO: + if (IS_ENABLED(CONFIG_BT_CLASSIC)) { + h4->rx.remaining = sizeof(h4->rx.sco); + h4->rx.hdr_len = h4->rx.remaining; + } else { + goto error; + } + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + h4->rx.remaining = sizeof(h4->rx.iso); + h4->rx.hdr_len = h4->rx.remaining; + } else { + goto error; + } + break; + default: + goto error; + } + return; +error: + LOG_ERR("Unknown H:4 type 0x%02x", h4->rx.type); + h4->rx.type = BT_HCI_H4_NONE; +} + +static void h4_read_hdr(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + int bytes_read = h4->rx.hdr_len - h4->rx.remaining; + int ret; + + ret = ipc_queue_read(h4->ipc_port, h4->rx.hdr + bytes_read, h4->rx.remaining); + if (unlikely(ret < 0)) { + LOG_ERR("Unable to read from UART (ret %d)", ret); + } else { + h4->rx.remaining -= ret; + } +} + +static inline void get_acl_hdr(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + h4_read_hdr(dev); + + if (!h4->rx.remaining) { + struct bt_hci_acl_hdr *hdr = &h4->rx.acl; + + h4->rx.remaining = sys_le16_to_cpu(hdr->len); + LOG_DBG("Got ACL header. Payload %u bytes", h4->rx.remaining); + h4->rx.have_hdr = true; + } +} + +static inline void get_sco_hdr(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + h4_read_hdr(dev); + + if (!h4->rx.remaining) { + struct bt_hci_sco_hdr *hdr = &h4->rx.sco; + + h4->rx.remaining = hdr->len; + LOG_DBG("Got SCO header. Payload %u bytes", h4->rx.remaining); + h4->rx.have_hdr = true; + } +} + +static inline void get_iso_hdr(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + h4_read_hdr(dev); + + if (!h4->rx.remaining) { + struct bt_hci_iso_hdr *hdr = &h4->rx.iso; + + h4->rx.remaining = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); + LOG_DBG("Got ISO header. Payload %u bytes", h4->rx.remaining); + + h4->rx.have_hdr = true; + } +} + +static inline void get_evt_hdr(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + struct bt_hci_evt_hdr *hdr = &h4->rx.evt; + + h4_read_hdr(dev); + + if (h4->rx.hdr_len == sizeof(*hdr) && h4->rx.remaining < sizeof(*hdr)) { + switch (h4->rx.evt.evt) { + case BT_HCI_EVT_LE_META_EVENT: + h4->rx.remaining++; + h4->rx.hdr_len++; + break; +#if defined(CONFIG_BT_CLASSIC) + case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: + case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: + h4->rx.discardable = true; + break; +#endif + default: + break; + } + } + + if (!h4->rx.remaining) { + if (h4->rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && + ((h4->rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT) || + (h4->rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT))) { + LOG_DBG("Marking adv report as discardable"); + h4->rx.discardable = true; + } + + h4->rx.remaining = hdr->len - (h4->rx.hdr_len - sizeof(*hdr)); + LOG_DBG("Got event header. Payload %u bytes", hdr->len); + h4->rx.have_hdr = true; + } +} + +static inline void copy_hdr(struct h4_data *h4) +{ + net_buf_add_mem(h4->rx.buf, h4->rx.hdr, h4->rx.hdr_len); +} + +static void reset_rx(struct h4_data *h4) +{ + h4->rx.type = BT_HCI_H4_NONE; + h4->rx.remaining = 0U; + h4->rx.have_hdr = false; + h4->rx.hdr_len = 0U; + h4->rx.discardable = false; +} + +static struct net_buf *get_rx(struct h4_data *h4, k_timeout_t timeout) +{ + LOG_DBG("type 0x%02x, evt 0x%02x", h4->rx.type, h4->rx.evt.evt); + + switch (h4->rx.type) { + case BT_HCI_H4_EVT: + return bt_buf_get_evt(h4->rx.evt.evt, h4->rx.discardable, timeout); + case BT_HCI_H4_ACL: + return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); + case BT_HCI_H4_SCO: + if (IS_ENABLED(CONFIG_BT_CLASSIC)) { + LOG_ERR("SCO not supported by host stack."); + } + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + return bt_buf_get_rx(BT_BUF_ISO_IN, timeout); + } + break; + default: + LOG_ERR("Invalid rx type 0x%02x", h4->rx.type); + } + + return NULL; +} + +static void rx_thread(void *p1, void *p2, void *p3) +{ + const struct device *dev = p1; + struct h4_data *data = dev->data; + + while (1) { + int len; + + k_sem_take(&(data->sem), K_FOREVER); + len = ipc_queue_get_rx_size(data->ipc_port); + while (len) { + struct h4_data *h4 = dev->data; + struct net_buf *buf; + + LOG_DBG("rx_thread len %d", len); + process_rx(dev); + buf = k_fifo_get(&h4->rx.fifo, K_NO_WAIT); + while (buf) { + LOG_DBG("Calling bt_recv(%p),len=%d,data=%p", (void *)buf, buf->len, + (void *)buf->data); + + if (buf->len == 0 || buf->data == NULL) { + break; + } + + if (h4->recv) { + sf32lb_hci_trace(buf->data[0], &buf->data[1], buf->len - 1, + H4TL_PACKET_CTRL); + h4->recv(dev, buf); + } else { + net_buf_unref(buf); + } + + buf = k_fifo_get(&h4->rx.fifo, K_NO_WAIT); + }; + len = ipc_queue_get_rx_size(data->ipc_port); + } + process_tx(dev); + } +} + +static size_t h4_discard(const struct device *dev, size_t len) +{ + struct h4_data *h4 = dev->data; + uint8_t buf[33]; + int err; + + err = ipc_queue_read(h4->ipc_port, buf, MIN(len, sizeof(buf))); + if (unlikely(err < 0)) { + LOG_ERR("Unable to read from UART (err %d)", err); + err = 0; + } + return err; +} + +static inline void read_payload(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + struct net_buf *buf; + int read; + + if (!h4->rx.buf) { + size_t buf_tailroom; + + h4->rx.buf = get_rx(h4, K_NO_WAIT); + if (!h4->rx.buf) { + if (h4->rx.discardable) { + LOG_WRN("Discarding event 0x%02x", h4->rx.evt.evt); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); + return; + } + LOG_WRN("Failed to allocate, deferring to rx_thread"); + return; + } + LOG_DBG("Allocated rx.buf %p", (void *)h4->rx.buf); + + buf_tailroom = net_buf_tailroom(h4->rx.buf); + if (buf_tailroom < h4->rx.remaining) { + LOG_ERR("Not enough space in buffer %u/%zu", h4->rx.remaining, + buf_tailroom); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); + return; + } + copy_hdr(h4); + } + + read = ipc_queue_read(h4->ipc_port, net_buf_tail(h4->rx.buf), h4->rx.remaining); + if (unlikely(read < 0)) { + LOG_ERR("Failed to read UART (err %d)", read); + return; + } + + net_buf_add(h4->rx.buf, read); + h4->rx.remaining -= read; + + LOG_DBG("got %d bytes, remaining %u", read, h4->rx.remaining); + LOG_DBG("Payload (len %u): %s", h4->rx.buf->len, bt_hex(h4->rx.buf->data, h4->rx.buf->len)); + + if (h4->rx.remaining) { + return; + } + + buf = h4->rx.buf; + h4->rx.buf = NULL; + + reset_rx(h4); + + LOG_DBG("Putting buf %p to rx fifo", (void *)buf); + k_fifo_put(&h4->rx.fifo, buf); +} + +static inline void read_header(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + switch (h4->rx.type) { + case BT_HCI_H4_NONE: + h4_get_type(dev); + return; + case BT_HCI_H4_EVT: + get_evt_hdr(dev); + break; + case BT_HCI_H4_ACL: + get_acl_hdr(dev); + break; + case BT_HCI_H4_SCO: + if (IS_ENABLED(CONFIG_BT_CLASSIC)) { + get_sco_hdr(dev); + } else { + LOG_ERR("SCO got unexpected\n"); + CODE_UNREACHABLE; + } + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + get_iso_hdr(dev); + } else { + LOG_ERR("ISO got unexpected\n"); + CODE_UNREACHABLE; + } + break; + default: + LOG_ERR("Invalid rx type %d\n", h4->rx.type); + CODE_UNREACHABLE; + return; + } + + if (h4->rx.have_hdr && h4->rx.buf) { + if (h4->rx.remaining > net_buf_tailroom(h4->rx.buf)) { + LOG_ERR("Not enough space in buffer"); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); + } else { + copy_hdr(h4); + } + } +} + +static inline void process_tx(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + int bytes; + + if (!h4->tx.buf) { + h4->tx.buf = k_fifo_get(&h4->tx.fifo, K_NO_WAIT); + if (!h4->tx.buf) { + return; + } + } else { + LOG_WRN("Other tx is running"); + return; + } + + while (h4->tx.buf) { + LOG_DBG("process_tx data %p, type %d len %d", (void *)h4->tx.buf->data, + h4->tx.buf->data[0], h4->tx.buf->len); + sf32lb_hci_trace(h4->tx.buf->data[0], &h4->tx.buf->data[1], h4->tx.buf->len - 1, + H4TL_PACKET_HOST); + bytes = ipc_queue_write(h4->ipc_port, h4->tx.buf->data, h4->tx.buf->len, + IPC_TIMEOUT_MS); + if (unlikely(bytes < 0)) { + LOG_ERR("Unable to write to UART (err %d)", bytes); + } else { + LOG_DBG("process_tx bytes %d", bytes); + net_buf_pull(h4->tx.buf, bytes); + } + if (h4->tx.buf->len) { + return; + } + h4->tx.type = BT_HCI_H4_NONE; + LOG_DBG("process_tx net_buf_unref"); + net_buf_unref(h4->tx.buf); + h4->tx.buf = k_fifo_get(&h4->tx.fifo, K_NO_WAIT); + } +} + +static inline void process_rx(const struct device *dev) +{ + struct h4_data *h4 = dev->data; + + LOG_DBG("remaining %u discard %u have_hdr %u rx.buf %p len %u", h4->rx.remaining, + h4->rx.discard, h4->rx.have_hdr, (void *)h4->rx.buf, + h4->rx.buf ? h4->rx.buf->len : 0); + + if (h4->rx.discard) { + h4->rx.discard -= h4_discard(dev, h4->rx.discard); + return; + } + + if (h4->rx.have_hdr) { + read_payload(dev); + } else { + read_header(dev); + } +} + +static int h4_send(const struct device *dev, struct net_buf *buf) +{ + struct h4_data *h4 = dev->data; + + LOG_DBG("buf %p type %u len %u", (void *)buf, buf->data[0], buf->len); + + k_fifo_put(&h4->tx.fifo, buf); + k_sem_give(&(h4->sem)); + + return 0; +} + +static int h4_open(const struct device *dev, bt_hci_recv_t recv) +{ + struct h4_data *h4 = dev->data; + const struct h4_config *cfg = dev->config; + k_tid_t tid; + + h4->recv = recv; + + zbt_config_mailbox(dev); + lcpu_power_on(); + k_sleep(K_MSEC(50)); + + LOG_DBG("h4 open %p", (void *)recv); + tid = k_thread_create(cfg->rx_thread, cfg->rx_thread_stack, cfg->rx_thread_stack_size, + rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, + K_NO_WAIT); + k_thread_name_set(tid, "hci_rx_th"); + return 0; +} + +static const DEVICE_API(bt_hci, h4_driver_api) = { + .open = h4_open, + .send = h4_send, +}; + +#define BT_MBOX_DEVICE_INIT(inst) \ + static K_KERNEL_STACK_DEFINE(rx_thread_stack_##inst, CONFIG_BT_DRV_RX_STACK_SIZE); \ + static struct k_thread rx_thread_##inst; \ + static const struct h4_config h4_config_##inst = { \ + .rx_thread_stack = rx_thread_stack_##inst, \ + .rx_thread_stack_size = K_KERNEL_STACK_SIZEOF(rx_thread_stack_##inst), \ + .rx_thread = &rx_thread_##inst, \ + }; \ + static struct h4_data h4_data_##inst = { \ + .rx = \ + { \ + .fifo = Z_FIFO_INITIALIZER(h4_data_##inst.rx.fifo), \ + }, \ + .tx = \ + { \ + .fifo = Z_FIFO_INITIALIZER(h4_data_##inst.tx.fifo), \ + }, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &h4_data_##inst, &h4_config_##inst, POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &h4_driver_api) + +BT_MBOX_DEVICE_INIT(0) diff --git a/dts/arm/sifli/sf32lb52x-ram012.dtsi b/dts/arm/sifli/sf32lb52x-ram012.dtsi index d1eaf280e5a97..646794631ff50 100644 --- a/dts/arm/sifli/sf32lb52x-ram012.dtsi +++ b/dts/arm/sifli/sf32lb52x-ram012.dtsi @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include / { @@ -13,7 +14,21 @@ soc { ram012: memory@20000000 { compatible = "mmio-sram"; - reg = <0x20000000 DT_SIZE_K(512)>; + reg = <0x20000000 DT_SIZE_K(511)>; + }; + sram0_shared: memory@2007fc00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2007fc00 DT_SIZE_K(1)>; + device_type = "memory"; + zephyr,memory-region = "sram0_shared"; + zephyr,memory-attr = <(DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE))>; + }; + sram1_shared: memory@20400000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20400000 DT_SIZE_K(64)>; + device_type = "memory"; + zephyr,memory-region = "sram1_shared"; + zephyr,memory-attr = <(DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE))>; }; }; }; diff --git a/dts/arm/sifli/sf32lb52x.dtsi b/dts/arm/sifli/sf32lb52x.dtsi index f17a6434b0b95..d3e34d84a8551 100644 --- a/dts/arm/sifli/sf32lb52x.dtsi +++ b/dts/arm/sifli/sf32lb52x.dtsi @@ -129,6 +129,13 @@ status = "disabled"; }; + mailbox: mailbox@50082000 { + compatible = "sifli,sf32lb-mailbox"; + reg = <0x50082000 0x1000>; + interrupts = <58 1>; + status = "disabled"; + }; + usart1: serial@50084000 { compatible = "sifli,sf32lb-usart"; reg = <0x50084000 0x400>; diff --git a/dts/bindings/bluetooth/sifli,sf32lb-mailbox.yaml b/dts/bindings/bluetooth/sifli,sf32lb-mailbox.yaml new file mode 100644 index 0000000000000..9189822dc1a5d --- /dev/null +++ b/dts/bindings/bluetooth/sifli,sf32lb-mailbox.yaml @@ -0,0 +1,16 @@ +# Mailbox Bluetooth HCI device + +description: Bluetooth HCI behind a mailbox IPC device (H:4) + +compatible: "sifli,sf32lb-mailbox" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "mailbox" + bt-hci-bus: + default: "virtual" + +mail-cells: + - channel diff --git a/modules/hal_sifli/CMakeLists.txt b/modules/hal_sifli/CMakeLists.txt index bee6ac50ff4c6..f4586ddcda3e0 100644 --- a/modules/hal_sifli/CMakeLists.txt +++ b/modules/hal_sifli/CMakeLists.txt @@ -5,6 +5,7 @@ if(CONFIG_HAS_SIFLI_HAL) # Allow using CMSIS headers from HAL without compiling HAL library. # This gives us access to register definitions and CMSIS HAL glue code. zephyr_compile_definitions(SOC_BF0_HCPU) + if(CONFIG_SOC_SERIES_SF32LB52X) zephyr_compile_definitions(SF32LB52X) endif() @@ -22,7 +23,11 @@ if(CONFIG_HAS_SIFLI_HAL) HAL_TICK_PER_SECOND=${CONFIG_SYS_CLOCK_TICKS_PER_SEC} ) - zephyr_library_include_directories(${CMAKE_CURRENT_LIST_DIR}) + if (CONFIG_USE_SIFLI_IPC_QUEUE) + zephyr_compile_definitions(USING_IPC_QUEUE) + endif() + + zephyr_include_directories(${CMAKE_CURRENT_LIST_DIR}) zephyr_include_directories(${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/include) zephyr_library_sources( @@ -43,7 +48,9 @@ if(CONFIG_HAS_SIFLI_HAL) CONFIG_USE_SIFLI_HAL_ADC ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_adc.c ) zephyr_library_sources_ifdef( - CONFIG_USE_SIFLI_HAL_AON ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_hpaon.c + CONFIG_USE_SIFLI_HAL_AON + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_hpaon.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_lpaon.c ) zephyr_library_sources_ifdef( CONFIG_USE_SIFLI_HAL_ATIM ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_tim_ex.c @@ -90,6 +97,9 @@ if(CONFIG_HAS_SIFLI_HAL) zephyr_library_sources_ifdef( CONFIG_USE_SIFLI_HAL_LCD ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_lcdc.c ) + zephyr_library_sources_ifdef( + CONFIG_USE_SIFLI_HAL_LCPU_CONFIGURE ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_lcpu_config.c + ) zephyr_library_sources_ifdef( CONFIG_USE_SIFLI_HAL_LCPU_PATCH ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_patch.c ) @@ -148,6 +158,35 @@ if(CONFIG_HAS_SIFLI_HAL) zephyr_library_sources_ifdef( CONFIG_USE_SIFLI_HAL_WDT ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_wdt.c ) + if(CONFIG_USE_SIFLI_IPC_QUEUE) + zephyr_library_sources( + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/common/circular_buf.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/common/ipc_hw.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/common/ipc_queue.c + ) + zephyr_include_directories( + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/common + ) + endif() + if(CONFIG_SOC_SERIES_SF32LB52X) + zephyr_library_sources_ifdef( + CONFIG_BT_SF32LB + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/cmsis/sf32lb52x/bf0_lcpu_init.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/cmsis/sf32lb52x/lcpu_config_type.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/cmsis/sf32lb52x/lcpu_patch.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/cmsis/sf32lb52x/lcpu_patch_rev_b.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/cmsis/sf32lb52x/bt_rf_fulcal.c + ) + if(CONFIG_USE_SIFLI_IPC_QUEUE) + zephyr_library_sources( + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/sf32lb52x/ipc_hw_port.c + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/sf32lb52x/lcpu.c + ) + zephyr_include_directories( + ${ZEPHYR_HAL_SIFLI_MODULE_DIR}/ipc_queue/sf32lb52x + ) + endif() + endif() if(CONFIG_USE_SIFLI_HAL_AES OR CONFIG_USE_SIFLI_HAL_HASH) zephyr_library_sources(${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_aes.c) @@ -156,5 +195,6 @@ if(CONFIG_HAS_SIFLI_HAL) if(CONFIG_USE_SIFLI_HAL_SD OR CONFIG_USE_SIFLI_HAL_SDHCI) zephyr_library_sources(${ZEPHYR_HAL_SIFLI_MODULE_DIR}/hal/src/bf0_hal_sd_ex.c) endif() + endif() endif() diff --git a/modules/hal_sifli/Kconfig b/modules/hal_sifli/Kconfig index e5c795262d1b5..1dfebf98e66e9 100644 --- a/modules/hal_sifli/Kconfig +++ b/modules/hal_sifli/Kconfig @@ -234,6 +234,15 @@ config USE_SIFLI_HAL_WDT help Enable WDT SiFli HAL module driver +config USE_SIFLI_IPC_QUEUE + bool "IPC_QUEUE SiFli IPC queue" + select USE_SIFLI_HAL_MAILBOX + select USE_SIFLI_HAL_LCPU_CONFIGURE + select USE_SIFLI_HAL_LCPU_PATCH + select USE_SIFLI_HAL_AON + help + Enable IPC queue module for SiFli core communication + endif # USE_SIFLI_HAL endif # HAS_SIFLI_HAL diff --git a/modules/hal_sifli/hal.c b/modules/hal_sifli/hal.c index 5805a330dba81..9120f7ac695c0 100644 --- a/modules/hal_sifli/hal.c +++ b/modules/hal_sifli/hal.c @@ -4,6 +4,12 @@ */ #include +#include /* System clock (48MHz by RC48 at boot) */ uint32_t SystemCoreClock = 48000000UL; + +void HAL_Delay_us(uint32_t us) +{ + k_sleep(K_USEC(us)); +} diff --git a/soc/sifli/sf32/Kconfig.defconfig b/soc/sifli/sf32/Kconfig.defconfig index 0c58765f253bf..712a92ecdc14e 100644 --- a/soc/sifli/sf32/Kconfig.defconfig +++ b/soc/sifli/sf32/Kconfig.defconfig @@ -6,6 +6,18 @@ if SOC_FAMILY_SF32 config BUILD_OUTPUT_HEX default y +config USE_SIFLI_HAL + default y + +config BT_HCI_ACL_FLOW_CONTROL + default n + +config MAIN_STACK_SIZE + default 2048 if BT_SF32LB + +config BT_BUF_ACL_TX_COUNT + default 8 if BT_SF32LB + rsource "*/Kconfig.defconfig" endif # SOC_FAMILY_SF32 diff --git a/soc/sifli/sf32/sf32lb52x/Kconfig b/soc/sifli/sf32/sf32lb52x/Kconfig index a2b30022b8bf4..1e760a1294e3d 100644 --- a/soc/sifli/sf32/sf32lb52x/Kconfig +++ b/soc/sifli/sf32/sf32lb52x/Kconfig @@ -12,6 +12,10 @@ config SOC_SERIES_SF32LB52X select CPU_HAS_DCACHE select SOC_EARLY_INIT_HOOK +config SIFLI_LXT_DISABLE + bool + default n + if SOC_SERIES_SF32LB52X config SF32LB52X_BOOTROM_FLASH_ON_DELAY_MS diff --git a/west.yml b/west.yml index c36b20ec94fb9..56c7bb83a3b36 100644 --- a/west.yml +++ b/west.yml @@ -235,7 +235,7 @@ manifest: groups: - hal - name: hal_sifli - revision: 7be421088b6fa2910917f3f8b656ded01e21b4e8 + revision: f457f7bea184d5ee4ec4ca45bffe49dd5e72ab1a path: modules/hal/sifli groups: - hal