diff --git a/dts/arm/nordic/nrf51822.dtsi b/dts/arm/nordic/nrf51822.dtsi index b64de1d4985c862..8c954be93572703 100644 --- a/dts/arm/nordic/nrf51822.dtsi +++ b/dts/arm/nordic/nrf51822.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -73,6 +74,11 @@ reg = <0x40001000 0x1000>; interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index c5a184d5e288c4e..78e242883aa0d0b 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -86,6 +87,11 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; ble-2mbps-supported; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 1ca4a9ea378a373..6b62ed809c73ab7 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -90,6 +91,11 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; ble-2mbps-supported; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 63b85676587735c..bcd7b4cbf8190c4 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -102,6 +103,11 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index f93e449b0b2cc94..594f3415d2f4c62 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -10,6 +10,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -98,6 +99,11 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 13ee05226b76f22..cdcc2d9f728280b 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -90,6 +91,11 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; ble-2mbps-supported; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index f22cb36bc14a484..75bd01b0f09fce5 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -97,6 +98,11 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 4cfb7abc511efcf..f81ebf4c034f245 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -92,6 +93,11 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf5340_cpunet.dtsi b/dts/arm/nordic/nrf5340_cpunet.dtsi index 8a95b3e99850a8b..7eba4606a6e6bd6 100644 --- a/dts/arm/nordic/nrf5340_cpunet.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -100,6 +101,11 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci: bt_hci { + compatible = "zephyr,bt-hci-controller"; + status = "okay"; + }; }; rng: random@41009000 { diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 20b73b5b1d67086..54d837dd2466d5f 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "zephyr/dt-bindings/bluetooth/hci.h" #include #include #include @@ -21,7 +22,7 @@ #include #include -#include +#include #ifdef CONFIG_CLOCK_CONTROL_NRF #include @@ -66,6 +67,16 @@ #include LOG_MODULE_REGISTER(bt_ctlr_hci_driver); +#define DT_DRV_COMPAT zephyr_bt_hci_controller + +struct hci_driver_data { + bt_hci_recv_t recv; +}; + +struct hci_driver_config { + struct bt_hci_info info; +}; + static struct k_sem sem_prio_recv; static struct k_fifo recv_fifo; @@ -120,8 +131,10 @@ static inline uint8_t bt_hci_evt_get_flags(uint8_t evt) * tree) 'recv blocking' API to the normal single-receiver * `bt_recv` API. */ -static int bt_recv_prio(struct net_buf *buf) +static int bt_recv_prio(const struct device *dev, struct net_buf *buf) { + struct hci_driver_data *data = dev->data; + if (bt_buf_get_type(buf) == BT_BUF_EVT) { struct bt_hci_evt_hdr *hdr = (void *)buf->data; uint8_t evt_flags = bt_hci_evt_get_flags(hdr->evt); @@ -133,7 +146,7 @@ static int bt_recv_prio(struct net_buf *buf) } } - return bt_recv(buf); + return data->recv(dev, buf); } #if defined(CONFIG_BT_CTLR_ISO) @@ -167,6 +180,8 @@ isoal_status_t sink_sdu_emit_hci(const struct isoal_sink *sink_ctx, const struct isoal_emitted_sdu_frag *sdu_frag, const struct isoal_emitted_sdu *sdu) { + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct hci_driver_data *data = dev->data; struct bt_hci_iso_ts_data_hdr *data_hdr; uint16_t packet_status_flag; struct bt_hci_iso_hdr *hdr; @@ -249,7 +264,7 @@ isoal_status_t sink_sdu_emit_hci(const struct isoal_sink *sink_ctx, hdr->len = sys_cpu_to_le16(len); /* send fragment up the chain */ - bt_recv(buf); + data->recv(dev, buf); } return ISOAL_STATUS_OK; @@ -319,6 +334,8 @@ static struct net_buf *process_prio_evt(struct node_rx_pdu *node_rx, */ static void prio_recv_thread(void *p1, void *p2, void *p3) { + const struct device *dev = p1; + while (1) { struct node_rx_pdu *node_rx; struct net_buf *buf; @@ -355,7 +372,7 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) false, K_FOREVER); hci_num_cmplt_encode(buf, handle, num_cmplt); LOG_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt); - bt_recv_prio(buf); + bt_recv_prio(dev, buf); k_yield(); #endif /* CONFIG_BT_CONN || CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */ } @@ -379,7 +396,7 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) ll_rx_mem_release((void **)&node_rx); } - bt_recv_prio(buf); + bt_recv_prio(dev, buf); /* bt_recv_prio would not release normal evt * buf. */ @@ -658,6 +675,9 @@ static inline struct net_buf *process_hbuf(struct node_rx_pdu *n) */ static void recv_thread(void *p1, void *p2, void *p3) { + const struct device *dev = p1; + struct hci_driver_data *data = dev->data; + #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) /* @todo: check if the events structure really needs to be static */ static struct k_poll_event events[2] = { @@ -716,7 +736,7 @@ static void recv_thread(void *p1, void *p2, void *p3) LOG_DBG("Packet in: type:%u len:%u", bt_buf_get_type(frag), frag->len); - bt_recv(frag); + data->recv(dev, frag); } else { net_buf_unref(frag); } @@ -726,7 +746,7 @@ static void recv_thread(void *p1, void *p2, void *p3) } } -static int cmd_handle(struct net_buf *buf) +static int cmd_handle(const struct device *dev, struct net_buf *buf) { struct node_rx_pdu *node_rx = NULL; struct net_buf *evt; @@ -734,7 +754,7 @@ static int cmd_handle(struct net_buf *buf) evt = hci_cmd_handle(buf, (void **) &node_rx); if (evt) { LOG_DBG("Replying with event of %u bytes", evt->len); - bt_recv_prio(evt); + bt_recv_prio(dev, evt); if (node_rx) { LOG_DBG("RX node enqueue"); @@ -747,7 +767,7 @@ static int cmd_handle(struct net_buf *buf) } #if defined(CONFIG_BT_CONN) -static int acl_handle(struct net_buf *buf) +static int acl_handle(const struct device *dev, struct net_buf *buf) { struct net_buf *evt; int err; @@ -755,7 +775,7 @@ static int acl_handle(struct net_buf *buf) err = hci_acl_handle(buf, &evt); if (evt) { LOG_DBG("Replying with event of %u bytes", evt->len); - bt_recv_prio(evt); + bt_recv_prio(dev, evt); } return err; @@ -763,7 +783,7 @@ static int acl_handle(struct net_buf *buf) #endif /* CONFIG_BT_CONN */ #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) -static int iso_handle(struct net_buf *buf) +static int iso_handle(const struct device *dev, struct net_buf *buf) { struct net_buf *evt; int err; @@ -771,14 +791,14 @@ static int iso_handle(struct net_buf *buf) err = hci_iso_handle(buf, &evt); if (evt) { LOG_DBG("Replying with event of %u bytes", evt->len); - bt_recv_prio(evt); + bt_recv_prio(dev, evt); } return err; } #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */ -static int hci_driver_send(struct net_buf *buf) +static int hci_driver_send(const struct device *dev, struct net_buf *buf) { uint8_t type; int err; @@ -794,15 +814,15 @@ static int hci_driver_send(struct net_buf *buf) switch (type) { #if defined(CONFIG_BT_CONN) case BT_BUF_ACL_OUT: - err = acl_handle(buf); + err = acl_handle(dev, buf); break; #endif /* CONFIG_BT_CONN */ case BT_BUF_CMD: - err = cmd_handle(buf); + err = cmd_handle(dev, buf); break; #if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO) case BT_BUF_ISO_OUT: - err = iso_handle(buf); + err = iso_handle(dev, buf); break; #endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */ default: @@ -819,8 +839,9 @@ static int hci_driver_send(struct net_buf *buf) return err; } -static int hci_driver_open(void) +static int hci_driver_open(const struct device *dev, bt_hci_recv_t recv) { + struct hci_driver_data *data = dev->data; uint32_t err; DEBUG_INIT(); @@ -834,6 +855,8 @@ static int hci_driver_open(void) return err; } + data->recv = recv; + #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) k_poll_signal_init(&hbuf_signal); hci_init(&hbuf_signal); @@ -843,13 +866,13 @@ static int hci_driver_open(void) k_thread_create(&prio_recv_thread_data, prio_recv_thread_stack, K_KERNEL_STACK_SIZEOF(prio_recv_thread_stack), - prio_recv_thread, NULL, NULL, NULL, + prio_recv_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); k_thread_name_set(&prio_recv_thread_data, "BT RX pri"); k_thread_create(&recv_thread_data, recv_thread_stack, K_KERNEL_STACK_SIZEOF(recv_thread_stack), - recv_thread, NULL, NULL, NULL, + recv_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT); k_thread_name_set(&recv_thread_data, "BT RX"); @@ -858,8 +881,10 @@ static int hci_driver_open(void) return 0; } -static int hci_driver_close(void) +static int hci_driver_close(const struct device *dev) { + struct hci_driver_data *data = dev->data; + /* Resetting the LL stops all roles */ ll_deinit(); @@ -869,24 +894,34 @@ static int hci_driver_close(void) /* Abort RX thread */ k_thread_abort(&recv_thread_data); + /* Clear the (host) receive callback */ + data->recv = NULL; + return 0; } -static const struct bt_hci_driver drv = { - .name = "Controller", - .bus = BT_HCI_DRIVER_BUS_VIRTUAL, - .quirks = BT_QUIRK_NO_AUTO_DLE, - .open = hci_driver_open, - .close = hci_driver_close, - .send = hci_driver_send, -}; - -static int hci_driver_init(void) +static void hci_driver_get_info(const struct device *dev, struct bt_hci_info *info) { + const struct hci_driver_config *cfg = dev->config; - bt_hci_driver_register(&drv); - - return 0; + *info = cfg->info; + info->quirks = BT_HCI_QUIRK_NO_AUTO_DLE; } -SYS_INIT(hci_driver_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +static const struct bt_hci_driver_api hci_driver_api = { + .get_info = hci_driver_get_info, + .open = hci_driver_open, + .close = hci_driver_close, + .send = hci_driver_send, +}; + +#define BT_HCI_CONTROLLER_INIT(inst) \ + static const struct hci_driver_config config_##inst = { \ + .info = BT_DT_HCI_INFO_INST_GET(inst), \ + }; \ + static struct hci_driver_data data_##inst; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &data_##inst, &config_##inst, POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &hci_driver_api) + +/* Only a single instance is supported */ +BT_HCI_CONTROLLER_INIT(0)