drivers: sx126x: add support for the stm32wl chip

Add support for the STM32WL integrated radio, based on the sx1262. The
STM32WL implementation does not use any GPIO, and the signals are routed
to other units of the SoC and accessed with the ST HAL.

Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
diff --git a/drivers/lora/CMakeLists.txt b/drivers/lora/CMakeLists.txt
index 2ba6969..81cb146 100644
--- a/drivers/lora/CMakeLists.txt
+++ b/drivers/lora/CMakeLists.txt
@@ -13,5 +13,10 @@
 zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_RADIO_DRIVERS hal_common.c)
 zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_RADIO_DRIVERS sx12xx_common.c)
 zephyr_library_sources_ifdef(CONFIG_LORA_SX127X sx127x.c)
-zephyr_library_sources_ifdef(CONFIG_LORA_SX126X sx126x.c)
+
+if (CONFIG_LORA_SX126X OR CONFIG_LORA_STM32WL_SUBGHZ_RADIO)
+	zephyr_library_sources(sx126x.c)
+endif()
+
 zephyr_library_sources_ifdef(CONFIG_LORA_SX126X sx126x_standalone.c)
+zephyr_library_sources_ifdef(CONFIG_LORA_STM32WL_SUBGHZ_RADIO sx126x_stm32wl.c)
diff --git a/drivers/lora/Kconfig.sx12xx b/drivers/lora/Kconfig.sx12xx
index 8ec17c0..181b144 100644
--- a/drivers/lora/Kconfig.sx12xx
+++ b/drivers/lora/Kconfig.sx12xx
@@ -8,6 +8,7 @@
 DT_COMPAT_SEMTECH_SX1276 := semtech,sx1276
 DT_COMPAT_SEMTECH_SX1261 := semtech,sx1261
 DT_COMPAT_SEMTECH_SX1262 := semtech,sx1262
+DT_COMPAT_ST_STM32WL_SUBGHZ_RADIO := st,stm32wl-subghz-radio
 
 menuconfig LORA_SX12XX
 	bool "Semtech SX-series driver"
@@ -24,6 +25,7 @@
 	default LORA_SX127X if $(dt_compat_enabled,$(DT_COMPAT_SEMTECH_SX1276))
 	default LORA_SX126X if $(dt_compat_enabled,$(DT_COMPAT_SEMTECH_SX1261))
 	default LORA_SX126X if $(dt_compat_enabled,$(DT_COMPAT_SEMTECH_SX1262))
+	default LORA_STM32WL_SUBGHZ_RADIO if $(dt_compat_enabled,$(DT_COMPAT_ST_STM32WL_SUBGHZ_RADIO))
 	help
 	  Select the LoRa modem used on your board. The default value
 	  is discovered from the device tree and should be correct for
@@ -42,6 +44,12 @@
 	help
 	  Enable LoRa driver for Semtech SX1261 and SX1262.
 
+config LORA_STM32WL_SUBGHZ_RADIO
+	bool "STM32WL SUBGHZ radio driver"
+	select HAS_SEMTECH_SX126X
+	help
+	  Enable LoRa driver for STM32WL SUBGHZ radio.
+
 endchoice
 
 endif
diff --git a/drivers/lora/sx126x.c b/drivers/lora/sx126x.c
index 779d1a4..477e417 100644
--- a/drivers/lora/sx126x.c
+++ b/drivers/lora/sx126x.c
@@ -19,7 +19,8 @@
 LOG_MODULE_REGISTER(sx126x, CONFIG_LORA_LOG_LEVEL);
 
 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(semtech_sx1261) +
-	     DT_NUM_INST_STATUS_OKAY(semtech_sx1262) <= 1,
+	     DT_NUM_INST_STATUS_OKAY(semtech_sx1262) +
+	     DT_NUM_INST_STATUS_OKAY(st_stm32wl_subghz_radio) <= 1,
 	     "Multiple SX126x instances in DT");
 
 #define DIO2_TX_ENABLE DT_INST_PROP(0, dio2_tx_enable)
diff --git a/drivers/lora/sx126x_common.h b/drivers/lora/sx126x_common.h
index 903514b..4d5d92c 100644
--- a/drivers/lora/sx126x_common.h
+++ b/drivers/lora/sx126x_common.h
@@ -22,6 +22,9 @@
 #elif DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1262)
 #define DT_DRV_COMPAT semtech_sx1262
 #define SX126X_DEVICE_ID SX1262
+#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32wl_subghz_radio)
+#define DT_DRV_COMPAT st_stm32wl_subghz_radio
+#define SX126X_DEVICE_ID SX1262
 #else
 #error No SX126x instance in device tree.
 #endif
diff --git a/drivers/lora/sx126x_stm32wl.c b/drivers/lora/sx126x_stm32wl.c
new file mode 100644
index 0000000..86658dc
--- /dev/null
+++ b/drivers/lora/sx126x_stm32wl.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021 Fabio Baltieri
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+
+#include "sx126x_common.h"
+
+#include <stm32wlxx_ll_exti.h>
+#include <stm32wlxx_ll_pwr.h>
+#include <stm32wlxx_ll_rcc.h>
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(sx126x, CONFIG_LORA_LOG_LEVEL);
+
+void sx126x_reset(struct sx126x_data *dev_data)
+{
+	LL_RCC_RF_EnableReset();
+	k_sleep(K_MSEC(20));
+	LL_RCC_RF_DisableReset();
+	k_sleep(K_MSEC(10));
+}
+
+bool sx126x_is_busy(struct sx126x_data *dev_data)
+{
+	return LL_PWR_IsActiveFlag_RFBUSYS();
+}
+
+uint32_t sx126x_get_dio1_pin_state(struct sx126x_data *dev_data)
+{
+	return 0;
+}
+
+void sx126x_dio1_irq_enable(struct sx126x_data *dev_data)
+{
+	irq_enable(DT_INST_IRQN(0));
+}
+
+void sx126x_dio1_irq_disable(struct sx126x_data *dev_data)
+{
+	irq_disable(DT_INST_IRQN(0));
+}
+
+static void radio_isr(const struct device *dev)
+{
+	struct sx126x_data *dev_data = dev->data;
+
+	irq_disable(DT_INST_IRQN(0));
+	k_work_submit(&dev_data->dio1_irq_work);
+}
+
+int sx126x_variant_init(const struct device *dev)
+{
+	IRQ_CONNECT(DT_INST_IRQN(0),
+		    DT_INST_IRQ(0, priority),
+		    radio_isr, DEVICE_DT_INST_GET(0), 0);
+	LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_44);
+	irq_enable(DT_INST_IRQN(0));
+
+	return 0;
+}