/*
 * Copyright (c) 2023 Antmicro <www.antmicro.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/bluetooth/hci_driver.h>

#include <sl_btctrl_linklayer.h>
#include <sl_hci_common_transport.h>
#include <pa_conversions_efr32.h>
#include <sl_bt_ll_zephyr.h>
#include <rail.h>

#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_hci_driver_slz);

#define SL_BT_CONFIG_ACCEPT_LIST_SIZE	1
#define SL_BT_CONFIG_MAX_CONNECTIONS	1
#define SL_BT_CONFIG_USER_ADVERTISERS	1
#define SL_BT_CONTROLLER_BUFFER_MEMORY  CONFIG_BT_SILABS_HCI_BUFFER_MEMORY
#define SL_BT_SILABS_LL_STACK_SIZE	1024

static K_KERNEL_STACK_DEFINE(slz_ll_stack, SL_BT_SILABS_LL_STACK_SIZE);
static struct k_thread slz_ll_thread;

void rail_isr_installer(void)
{
#ifdef CONFIG_SOC_SERIES_EFR32MG24
	IRQ_CONNECT(SYNTH_IRQn, 0, SYNTH_IRQHandler, NULL, 0);
#else
	IRQ_CONNECT(RDMAILBOX_IRQn, 0, RDMAILBOX_IRQHandler, NULL, 0);
#endif
	IRQ_CONNECT(RAC_SEQ_IRQn, 0, RAC_SEQ_IRQHandler, NULL, 0);
	IRQ_CONNECT(RAC_RSM_IRQn, 0, RAC_RSM_IRQHandler, NULL, 0);
	IRQ_CONNECT(PROTIMER_IRQn, 0, PROTIMER_IRQHandler, NULL, 0);
	IRQ_CONNECT(MODEM_IRQn, 0, MODEM_IRQHandler, NULL, 0);
	IRQ_CONNECT(FRC_IRQn, 0, FRC_IRQHandler, NULL, 0);
	IRQ_CONNECT(BUFC_IRQn, 0, BUFC_IRQHandler, NULL, 0);
	IRQ_CONNECT(AGC_IRQn, 0, AGC_IRQHandler, NULL, 0);
}

/**
 * @brief Transmit HCI message using the currently used transport layer.
 * The HCI calls this function to transmit a full HCI message.
 * @param[in] data Packet type followed by HCI packet data.
 * @param[in] len Length of the `data` parameter
 * @return 0 - on success, or non-zero on failure.
 */
uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len)
{
	struct net_buf *buf;
	uint8_t packet_type = data[0];
	uint8_t flags;
	uint8_t event_code;

	LOG_HEXDUMP_DBG(data, len, "host packet data:");

	/* drop packet type from the frame buffer - it is no longer needed */
	data = &data[1];
	len -= 1;

	switch (packet_type) {
	case h4_event:
		event_code = data[0];
		flags = bt_hci_evt_get_flags(event_code);
		buf = bt_buf_get_evt(event_code, false, K_FOREVER);
		break;
	case h4_acl:
		buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
		break;
	default:
		LOG_ERR("Unknown HCI type: %d", packet_type);
		return -EINVAL;
	}

	net_buf_add_mem(buf, data, len);
	if ((packet_type == h4_event) && (flags & BT_HCI_EVT_FLAG_RECV_PRIO)) {
		bt_recv_prio(buf);
	} else {
		bt_recv(buf);
	}

	sl_btctrl_hci_transmit_complete(0);

	return 0;
}

static int slz_bt_send(struct net_buf *buf)
{
	int rv = 0;

	switch (bt_buf_get_type(buf)) {
	case BT_BUF_ACL_OUT:
		net_buf_push_u8(buf, h4_acl);
		break;
	case BT_BUF_CMD:
		net_buf_push_u8(buf, h4_command);
		break;
	default:
		rv = -EINVAL;
		goto done;
	}

	rv = hci_common_transport_receive(buf->data, buf->len, true);
	if (!rv) {
		goto done;
	}

done:
	net_buf_unref(buf);
	return rv;
}

static int slz_bt_open(void)
{
	int ret;

	/* Start RX thread */
	k_thread_create(&slz_ll_thread, slz_ll_stack,
			K_KERNEL_STACK_SIZEOF(slz_ll_stack),
			(k_thread_entry_t)slz_ll_thread_func, NULL, NULL, NULL,
			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0,
			K_NO_WAIT);

	rail_isr_installer();
	sl_rail_util_pa_init();

	/* sl_btctrl_init_mem returns the number of memory buffers allocated */
	ret = sl_btctrl_init_mem(SL_BT_CONTROLLER_BUFFER_MEMORY);
	if (!ret) {
		LOG_ERR("Failed to allocate memory %d", ret);
		return -ENOMEM;
	}

	ret = sl_btctrl_init_ll();
	if (ret) {
		LOG_ERR("Bluetooth link layer init failed %d", ret);
		goto deinit;
	}

	sl_btctrl_init_adv();
	sl_btctrl_init_scan();
	sl_btctrl_init_conn();
	sl_btctrl_init_adv_ext();
	sl_btctrl_init_scan_ext();

	ret = sl_btctrl_init_basic(SL_BT_CONFIG_MAX_CONNECTIONS,
			SL_BT_CONFIG_USER_ADVERTISERS,
			SL_BT_CONFIG_ACCEPT_LIST_SIZE);
	if (ret) {
		LOG_ERR("Failed to initialize the controller %d", ret);
		goto deinit;
	}

	sl_bthci_init_upper();
	sl_btctrl_hci_parser_init_default();
	sl_btctrl_hci_parser_init_conn();
	sl_btctrl_hci_parser_init_adv();
	sl_btctrl_hci_parser_init_phy();

#ifdef CONFIG_PM
	{
		RAIL_Status_t status = RAIL_InitPowerManager();

		if (status != RAIL_STATUS_NO_ERROR) {
			LOG_ERR("RAIL: failed to initialize power management, status=%d",
					status);
			ret = -EIO;
			goto deinit;
		}
	}
#endif

	LOG_DBG("SiLabs BT HCI started");

	return 0;
deinit:
	sli_btctrl_deinit_mem();
	return ret;
}

static const struct bt_hci_driver drv = {
	.name           = "sl:bt",
	.bus            = BT_HCI_DRIVER_BUS_UART,
	.open           = slz_bt_open,
	.send           = slz_bt_send,
	.quirks         = BT_QUIRK_NO_RESET
};

static int slz_bt_init(void)
{
	int ret;

	ret = bt_hci_driver_register(&drv);
	if (ret) {
		LOG_ERR("Failed to register SiLabs BT HCI %d", ret);
	}

	return ret;
}

SYS_INIT(slz_bt_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
