#include "llcc68_raw.h" #include #include #include #define DT_DRV_COMPAT semtech_llcc68_weihua #define LLCC68_AUTO_RF_SWITCH_MODE(inst) \ COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, tx_enable_gpios), \ (COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, rx_enable_gpios), \ (LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY), (LLCC68_RF_SWITCH_NONE))), \ (LLCC68_RF_SWITCH_NONE)) #if defined(CONFIG_LLCC68_RF_SWITCH_DEFAULT_GPIO_COMPLEMENTARY) #define LLCC68_DEFAULT_RF_SWITCH_MODE(inst) LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY #elif defined(CONFIG_LLCC68_RF_SWITCH_DEFAULT_DIO2_SINGLE) #define LLCC68_DEFAULT_RF_SWITCH_MODE(inst) LLCC68_RF_SWITCH_DIO2_SINGLE #elif defined(CONFIG_LLCC68_RF_SWITCH_DEFAULT_NONE) #define LLCC68_DEFAULT_RF_SWITCH_MODE(inst) LLCC68_RF_SWITCH_NONE #else #define LLCC68_DEFAULT_RF_SWITCH_MODE(inst) LLCC68_AUTO_RF_SWITCH_MODE(inst) #endif #define LLCC68_RF_SWITCH_MODE(inst) \ DT_ENUM_IDX_OR(DT_DRV_INST(inst), rf_switch_mode, LLCC68_DEFAULT_RF_SWITCH_MODE(inst)) static void dio1_irq_trampoline(const struct device *port, struct gpio_callback *cb, uint32_t pins) { ARG_UNUSED(port); struct llcc68_data *data = CONTAINER_OF(cb, struct llcc68_data, dio1_irq_callback); const struct llcc68_config *config = data->self->config; if ((pins & BIT(config->dio1_gpio.pin)) != 0U && data->dio1_user_handler != NULL) { data->dio1_user_handler(data->self, data->dio1_user_data); } } int llcc68_init(const struct device *dev) { const struct llcc68_config *config = dev->config; struct llcc68_data *data = dev->data; if (config->rf_switch_mode == LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY && config->tx_enable_gpio.port != NULL) { gpio_pin_configure_dt(&config->tx_enable_gpio, GPIO_OUTPUT_INACTIVE); } if (config->rf_switch_mode == LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY && config->rx_enable_gpio.port != NULL) { gpio_pin_configure_dt(&config->rx_enable_gpio, GPIO_OUTPUT_INACTIVE); } if (config->rf_switch_mode == LLCC68_RF_SWITCH_DIO2_SINGLE && config->rx_enable_gpio.port != NULL) { gpio_pin_configure_dt(&config->rx_enable_gpio, GPIO_OUTPUT_ACTIVE); } gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); gpio_pin_configure_dt(&config->busy_gpio, GPIO_INPUT); gpio_pin_configure_dt(&config->dio1_gpio, GPIO_INPUT); data->self = dev; gpio_init_callback(&data->dio1_irq_callback, dio1_irq_trampoline, BIT(config->dio1_gpio.pin)); if (gpio_add_callback(config->dio1_gpio.port, &data->dio1_irq_callback) < 0) { return -EIO; } gpio_pin_interrupt_configure_dt(&config->dio1_gpio, GPIO_INT_DISABLE); return 0; } #define LLCC68_DEFINE(inst) \ BUILD_ASSERT(LLCC68_RF_SWITCH_MODE(inst) != LLCC68_RF_SWITCH_GPIO_COMPLEMENTARY || \ (DT_INST_NODE_HAS_PROP(inst, tx_enable_gpios) && \ DT_INST_NODE_HAS_PROP(inst, rx_enable_gpios)), \ "LLCC68 gpio-complementary RF switch mode requires tx-enable-gpios " \ "and rx-enable-gpios"); \ BUILD_ASSERT(LLCC68_RF_SWITCH_MODE(inst) != LLCC68_RF_SWITCH_DIO2_SINGLE || \ !DT_INST_NODE_HAS_PROP(inst, tx_enable_gpios), \ "LLCC68 dio2-single RF switch mode uses DIO2 for TXEN and must not " \ "define tx-enable-gpios"); \ static struct llcc68_data llcc68_data_##inst; \ static const struct llcc68_config llcc68_config_##inst = \ { \ .spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | SPI_TRANSFER_MSB), \ .reset_gpio = GPIO_DT_SPEC_INST_GET(inst, reset_gpios), \ .busy_gpio = GPIO_DT_SPEC_INST_GET(inst, busy_gpios), \ .dio1_gpio = GPIO_DT_SPEC_INST_GET(inst, dio1_gpios), \ .tx_enable_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, tx_enable_gpios, {.port = NULL}), \ .rx_enable_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, rx_enable_gpios, {.port = NULL}), \ .rf_switch_mode = LLCC68_RF_SWITCH_MODE(inst), \ }; \ DEVICE_DT_INST_DEFINE(inst, \ llcc68_init, \ NULL, \ &llcc68_data_##inst, \ &llcc68_config_##inst, \ POST_KERNEL, \ CONFIG_LLCC68_INIT_PRIORITY, \ NULL) BUILD_ASSERT(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT), "No status=okay nodes for DT_DRV_COMPAT; check compatible/status"); DT_INST_FOREACH_STATUS_OKAY(LLCC68_DEFINE)