Bluetooth: controller: support FEMs via devicetree

A FEM in this case is an external Front-End Module. This is basically
a range booster with some extra amplification in the TX and RX paths.

This feature is supported for the Nordic open source controller. See
the changes to the ubx_bmd345eval_nrf52840 board for a quick summary
of what you have to do to take advantage of this.

(This patch doesn't actually remove the feature in the openisa HAL,
though, because that never implemented the required GPIO handling
routines.)

We are using the 'fem' property previously added to the
nordic,nrf-radio's devicetree binding, which points to the FEM that is
in use. If you have this property and the node it points to is
enabled, the controller subsystem respects it. Otherwise, FEM support
is disabled.

This obsoletes the following Kconfig options, which are now unused:

- CONFIG_BT_CTLR_GPIO_PA
- CONFIG_BT_CTLR_GPIO_PA_PIN
- CONFIG_BT_CTLR_GPIO_PA_POL_INV
- CONFIG_BT_CTLR_GPIO_PA_OFFSET

- CONFIG_BT_CTLR_GPIO_LNA
- CONFIG_BT_CTLR_GPIO_LNA_PIN
- CONFIG_BT_CTLR_GPIO_LNA_POL_INV
- CONFIG_BT_CTLR_GPIO_LNA_OFFSET

- CONFIG_BT_CTLR_FEM_NRF21540
- CONFIG_BT_CTLR_GPIO_PDN_PIN
- CONFIG_BT_CTLR_GPIO_PDN_POL_INV
- CONFIG_BT_CTLR_GPIO_CSN_PIN
- CONFIG_BT_CTLR_GPIO_CSN_POL_INV
- CONFIG_BT_CTLR_GPIO_PDN_CSN_OFFSET

The PA and LNA pins are now specified via fem-specific devicetree
properties in the FEM node:

- The "generic" PA/LNA case is handled with the ctx-gpios and
  crx-gpios properties of the generic-fem-two-ctrl-pins compatible,
  respectively.

- If the fem is an nRF21540, use the tx-en-gpios and rx-en-gpios
  properties instead (and also respectively). This allows us to specify
  FEM properties in a way that makes sense for the hardware datasheet,
  while still handling them in a uniform way within the controller.

We support this in the nRF5 HAL with a new radio_nrf5_fem.h
sub-header, which pulls in radio_nrf5_fem_generic.h or
radio_nrf5_fem_nrf21540.h depending on the fem node's compatible, if
one is defined. These in turn let us replace the implementation
routines in radio.c with DT equivalents.

Keep in-tree users and devicetree binding documentation up to date.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2021-11-08 10:17:27 -08:00 committed by Carles Cufí
commit 7ff74e0ab9
14 changed files with 357 additions and 177 deletions

View file

@ -115,6 +115,14 @@
<5 &adc 7>; /* A5 = P0.31 = AIN7 */
};
nrf_radio_fem: fem {
compatible = "generic-fem-two-ctrl-pins";
ctx-gpios = <&gpio1 5 0>;
ctx-settle-time-us = <5>;
crx-gpios = <&gpio1 6 0>;
crx-settle-time-us = <5>;
};
/* These aliases are provided for compatibility with samples */
aliases {
led0 = &led0;
@ -130,6 +138,10 @@
};
};
&radio {
fem = <&nrf_radio_fem>;
};
&adc {
status = "okay";
};

View file

@ -28,11 +28,3 @@ CONFIG_UART_CONSOLE=y
# additional board options
CONFIG_GPIO_AS_PINRESET=y
# PA GPIO Pin
CONFIG_BT_CTLR_GPIO_PA=y
CONFIG_BT_CTLR_GPIO_PA_PIN=37
# LNA GPIO Pin
CONFIG_BT_CTLR_GPIO_LNA=y
CONFIG_BT_CTLR_GPIO_LNA_PIN=38

View file

@ -7,6 +7,8 @@
#include <sys/dlist.h>
#include <toolchain.h>
#include <dt-bindings/gpio/gpio.h>
#include <soc.h>
#include <hal/nrf_rtc.h>
#include <hal/nrf_timer.h>
@ -23,46 +25,102 @@
#include "radio_internal.h"
/* Converts the GPIO controller in a FEM property's GPIO specification
* to its nRF register map pointer.
*
* Make sure to use NRF_DT_CHECK_GPIO_CTLR_IS_SOC to check the GPIO
* controller has the right compatible wherever you use this.
*/
#define NRF_FEM_GPIO(prop) \
((NRF_GPIO_Type *)DT_REG_ADDR(DT_GPIO_CTLR(FEM_NODE, prop)))
/* Converts GPIO specification to a PSEL value. */
#define NRF_FEM_PSEL(prop) NRF_DT_GPIOS_TO_PSEL(FEM_NODE, prop)
/* Check if GPIO flags are active low. */
#define ACTIVE_LOW(flags) ((flags) & GPIO_ACTIVE_LOW)
/* Check if GPIO flags contain unsupported values. */
#define BAD_FLAGS(flags) ((flags) & ~GPIO_ACTIVE_LOW)
/* GPIOTE OUTINIT setting for a pin's inactive level, from its
* devicetree flags.
*/
#define OUTINIT_INACTIVE(flags) \
(ACTIVE_LOW(flags) ? \
GPIOTE_CONFIG_OUTINIT_High : \
GPIOTE_CONFIG_OUTINIT_Low)
#if defined(FEM_NODE)
BUILD_ASSERT(!HAL_RADIO_GPIO_PA_OFFSET_MISSING,
"fem node " DT_NODE_PATH(FEM_NODE) " has property "
HAL_RADIO_GPIO_PA_PROP_NAME " set, so you must also set "
HAL_RADIO_GPIO_PA_OFFSET_PROP_NAME);
BUILD_ASSERT(!HAL_RADIO_GPIO_LNA_OFFSET_MISSING,
"fem node " DT_NODE_PATH(FEM_NODE) " has property "
HAL_RADIO_GPIO_LNA_PROP_NAME " set, so you must also set "
HAL_RADIO_GPIO_LNA_OFFSET_PROP_NAME);
#endif /* FEM_NODE */
/*
* "Manual" conversions of devicetree values to register bits. We
* can't use the Zephyr GPIO API here, so we need this extra
* boilerplate.
*/
#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
#if ((CONFIG_BT_CTLR_GPIO_PA_PIN) > 31)
#define NRF_GPIO_PA NRF_P1
#define NRF_GPIO_PA_PIN ((CONFIG_BT_CTLR_GPIO_PA_PIN) - 32)
#else
#define NRF_GPIO_PA NRF_P0
#define NRF_GPIO_PA_PIN CONFIG_BT_CTLR_GPIO_PA_PIN
#endif
#define NRF_GPIO_PA NRF_FEM_GPIO(HAL_RADIO_GPIO_PA_PROP)
#define NRF_GPIO_PA_PIN DT_GPIO_PIN(FEM_NODE, HAL_RADIO_GPIO_PA_PROP)
#define NRF_GPIO_PA_FLAGS DT_GPIO_FLAGS(FEM_NODE, HAL_RADIO_GPIO_PA_PROP)
#define NRF_GPIO_PA_PSEL NRF_FEM_PSEL(HAL_RADIO_GPIO_PA_PROP)
NRF_DT_CHECK_GPIO_CTLR_IS_SOC(FEM_NODE, HAL_RADIO_GPIO_PA_PROP,
HAL_RADIO_GPIO_PA_PROP_NAME);
BUILD_ASSERT(!BAD_FLAGS(NRF_GPIO_PA_FLAGS),
"fem node " DT_NODE_PATH(FEM_NODE) " has invalid GPIO flags in "
HAL_RADIO_GPIO_PA_PROP_NAME
"; only GPIO_ACTIVE_LOW or GPIO_ACTIVE_HIGH are supported");
#endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
#if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
#if ((CONFIG_BT_CTLR_GPIO_LNA_PIN) > 31)
#define NRF_GPIO_LNA NRF_P1
#define NRF_GPIO_LNA_PIN ((CONFIG_BT_CTLR_GPIO_LNA_PIN) - 32)
#else
#define NRF_GPIO_LNA NRF_P0
#define NRF_GPIO_LNA_PIN CONFIG_BT_CTLR_GPIO_LNA_PIN
#endif
#define NRF_GPIO_LNA NRF_FEM_GPIO(HAL_RADIO_GPIO_LNA_PROP)
#define NRF_GPIO_LNA_PIN DT_GPIO_PIN(FEM_NODE, HAL_RADIO_GPIO_LNA_PROP)
#define NRF_GPIO_LNA_FLAGS DT_GPIO_FLAGS(FEM_NODE, HAL_RADIO_GPIO_LNA_PROP)
#define NRF_GPIO_LNA_PSEL NRF_FEM_PSEL(HAL_RADIO_GPIO_LNA_PROP)
NRF_DT_CHECK_GPIO_CTLR_IS_SOC(FEM_NODE, HAL_RADIO_GPIO_LNA_PROP,
HAL_RADIO_GPIO_LNA_PROP_NAME);
BUILD_ASSERT(!BAD_FLAGS(NRF_GPIO_LNA_FLAGS),
"fem node " DT_NODE_PATH(FEM_NODE) " has invalid GPIO flags in "
HAL_RADIO_GPIO_LNA_PROP_NAME
"; only GPIO_ACTIVE_LOW or GPIO_ACTIVE_HIGH are supported");
#endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
#if defined(CONFIG_BT_CTLR_GPIO_PDN_PIN)
#if ((CONFIG_BT_CTLR_GPIO_PDN_PIN) > 31)
#define NRF_GPIO_PDN NRF_P1
#define NRF_GPIO_PDN_PIN ((CONFIG_BT_CTLR_GPIO_PDN_PIN) - 32)
#else
#define NRF_GPIO_PDN NRF_P0
#define NRF_GPIO_PDN_PIN CONFIG_BT_CTLR_GPIO_PDN_PIN
#endif
#endif /* CONFIG_BT_CTLR_GPIO_PDN_PIN */
#if defined(HAL_RADIO_FEM_IS_NRF21540)
#if defined(CONFIG_BT_CTLR_GPIO_CSN_PIN)
#if ((CONFIG_BT_CTLR_GPIO_CSN_PIN) > 31)
#define NRF_GPIO_CSN NRF_P1
#define NRF_GPIO_CSN_PIN ((CONFIG_BT_CTLR_GPIO_CSN_PIN) - 32)
#else
#define NRF_GPIO_CSN NRF_P0
#define NRF_GPIO_CSN_PIN CONFIG_BT_CTLR_GPIO_CSN_PIN
#endif
#endif /* CONFIG_BT_CTLR_GPIO_CSN_PIN */
#if DT_NODE_HAS_PROP(FEM_NODE, pdn_gpios)
#define NRF_GPIO_PDN NRF_FEM_GPIO(pdn_gpios)
#define NRF_GPIO_PDN_PIN DT_GPIO_PIN(FEM_NODE, pdn_gpios)
#define NRF_GPIO_PDN_FLAGS DT_GPIO_FLAGS(FEM_NODE, pdn_gpios)
#define NRF_GPIO_PDN_PSEL NRF_FEM_PSEL(pdn_gpios)
#define NRF_GPIO_PDN_OFFSET DT_PROP(FEM_NODE, pdn_settle_time_us)
NRF_DT_CHECK_GPIO_CTLR_IS_SOC(FEM_NODE, pdn_gpios, "pdn-gpios");
#endif /* DT_NODE_HAS_PROP(FEM_NODE, pdn_gpios) */
/* CSN is special because it comes from the spi-if property. */
#if defined(HAL_RADIO_FEM_NRF21540_HAS_CSN)
#define NRF_GPIO_CSN_CTLR DT_SPI_DEV_CS_GPIOS_CTLR(FEM_SPI_DEV_NODE)
#define NRF_GPIO_CSN ((NRF_GPIO_Type *)DT_REG_ADDR(NRF_GPIO_CSN_CTLR))
#define NRF_GPIO_CSN_PIN DT_SPI_DEV_CS_GPIOS_PIN(FEM_SPI_DEV_NODE)
#define NRF_GPIO_CSN_FLAGS DT_SPI_DEV_CS_GPIOS_FLAGS(FEM_SPI_DEV_NODE)
#define NRF_GPIO_CSN_PSEL (NRF_GPIO_CSN_PIN + \
(DT_PROP(NRF_GPIO_CSN_CTLR, port) << 5))
BUILD_ASSERT(DT_NODE_HAS_COMPAT(NRF_GPIO_CSN_CTLR, nordic_nrf_gpio),
"fem node " DT_NODE_PATH(FEM_NODE) " has a spi-if property, "
" but the chip select pin is not on the SoC. Check cs-gpios in "
DT_NODE_PATH(DT_BUS(FEM_SPI_DEV_NODE)));
#endif /* HAL_RADIO_FEM_NRF21540_HAS_CSN */
#endif /* HAL_RADIO_FEM_IS_NRF21540 */
/* The following two constants are used in nrfx_glue.h for marking these PPI
* channels and groups as occupied and thus unavailable to other modules.
@ -107,11 +165,11 @@ void radio_setup(void)
{
#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
NRF_GPIO_PA->DIRSET = BIT(NRF_GPIO_PA_PIN);
#if defined(HAL_RADIO_GPIO_PA_POL_INV)
NRF_GPIO_PA->OUTSET = BIT(NRF_GPIO_PA_PIN);
#else
NRF_GPIO_PA->OUTCLR = BIT(NRF_GPIO_PA_PIN);
#endif
if (ACTIVE_LOW(NRF_GPIO_PA_FLAGS)) {
NRF_GPIO_PA->OUTSET = BIT(NRF_GPIO_PA_PIN);
} else {
NRF_GPIO_PA->OUTCLR = BIT(NRF_GPIO_PA_PIN);
}
#endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
#if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
@ -120,23 +178,23 @@ void radio_setup(void)
radio_gpio_lna_off();
#endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
#if defined(CONFIG_BT_CTLR_GPIO_PDN_PIN)
#if defined(NRF_GPIO_PDN_PIN)
NRF_GPIO_PDN->DIRSET = BIT(NRF_GPIO_PDN_PIN);
#if defined(HAL_RADIO_GPIO_NRF21540_PDN_POL_INV)
NRF_GPIO_PDN->OUTSET = BIT(NRF_GPIO_PDN_PIN);
#else
NRF_GPIO_PDN->OUTCLR = BIT(NRF_GPIO_PDN_PIN);
#endif
#endif /* CONFIG_BT_CTLR_GPIO_PDN_PIN */
if (ACTIVE_LOW(NRF_GPIO_PDN_FLAGS)) {
NRF_GPIO_PDN->OUTSET = BIT(NRF_GPIO_PDN_PIN);
} else {
NRF_GPIO_PDN->OUTCLR = BIT(NRF_GPIO_PDN_PIN);
}
#endif /* NRF_GPIO_PDN_PIN */
#if defined(CONFIG_BT_CTLR_GPIO_CSN_PIN)
#if defined(NRF_GPIO_CSN_PIN)
NRF_GPIO_CSN->DIRSET = BIT(NRF_GPIO_CSN_PIN);
#if defined(HAL_RADIO_GPIO_NRF21540_CSN_POL_INV)
NRF_GPIO_CSN->OUTSET = BIT(NRF_GPIO_CSN_PIN);
#else
NRF_GPIO_CSN->OUTCLR = BIT(NRF_GPIO_CSN_PIN);
#endif
#endif /* CONFIG_BT_CTLR_GPIO_CSN_PIN */
if (ACTIVE_LOW(NRF_GPIO_CSN_FLAGS)) {
NRF_GPIO_CSN->OUTSET = BIT(NRF_GPIO_CSN_PIN);
} else {
NRF_GPIO_CSN->OUTCLR = BIT(NRF_GPIO_CSN_PIN);
}
#endif /* NRF_GPIO_CSN_PIN */
hal_radio_ram_prio_setup();
}
@ -1125,24 +1183,15 @@ uint32_t radio_tmr_sample_get(void)
#if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
void radio_gpio_pa_setup(void)
{
/* NOTE: With GPIO Pins above 31, left shift of
* CONFIG_BT_CTLR_GPIO_PA_PIN by GPIOTE_CONFIG_PSEL_Pos will
* set the NRF_GPIOTE->CONFIG[n].PORT to 1 (P1 port).
*/
NRF_GPIOTE->CONFIG[HAL_PALNA_GPIOTE_CHAN] =
(GPIOTE_CONFIG_MODE_Task <<
GPIOTE_CONFIG_MODE_Pos) |
(CONFIG_BT_CTLR_GPIO_PA_PIN <<
(NRF_GPIO_PA_PSEL <<
GPIOTE_CONFIG_PSEL_Pos) |
(GPIOTE_CONFIG_POLARITY_Toggle <<
GPIOTE_CONFIG_POLARITY_Pos) |
#if defined(HAL_RADIO_GPIO_PA_POL_INV)
(GPIOTE_CONFIG_OUTINIT_High <<
(OUTINIT_INACTIVE(NRF_GPIO_PA_FLAGS) <<
GPIOTE_CONFIG_OUTINIT_Pos);
#else
(GPIOTE_CONFIG_OUTINIT_Low <<
GPIOTE_CONFIG_OUTINIT_Pos);
#endif
#if defined(HAL_RADIO_FEM_IS_NRF21540)
hal_pa_ppi_setup();
@ -1155,24 +1204,15 @@ void radio_gpio_pa_setup(void)
#if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
void radio_gpio_lna_setup(void)
{
/* NOTE: With GPIO Pins above 31, left shift of
* CONFIG_BT_CTLR_GPIO_LNA_PIN by GPIOTE_CONFIG_PSEL_Pos will
* set the NRF_GPIOTE->CONFIG[n].PORT to 1 (P1 port).
*/
NRF_GPIOTE->CONFIG[HAL_PALNA_GPIOTE_CHAN] =
(GPIOTE_CONFIG_MODE_Task <<
GPIOTE_CONFIG_MODE_Pos) |
(CONFIG_BT_CTLR_GPIO_LNA_PIN <<
(NRF_GPIO_LNA_PSEL <<
GPIOTE_CONFIG_PSEL_Pos) |
(GPIOTE_CONFIG_POLARITY_Toggle <<
GPIOTE_CONFIG_POLARITY_Pos) |
#if defined(HAL_RADIO_GPIO_LNA_POL_INV)
(GPIOTE_CONFIG_OUTINIT_High <<
(OUTINIT_INACTIVE(NRF_GPIO_LNA_FLAGS) <<
GPIOTE_CONFIG_OUTINIT_Pos);
#else
(GPIOTE_CONFIG_OUTINIT_Low <<
GPIOTE_CONFIG_OUTINIT_Pos);
#endif
#if defined(HAL_RADIO_FEM_IS_NRF21540)
hal_lna_ppi_setup();
@ -1181,79 +1221,62 @@ void radio_gpio_lna_setup(void)
#endif
}
#if defined(CONFIG_BT_CTLR_GPIO_PDN_PIN)
void radio_gpio_pdn_setup(void)
{
/* NOTE: With GPIO Pins above 31, left shift of
* CONFIG_BT_CTLR_GPIO_PA_PIN by GPIOTE_CONFIG_PSEL_Pos will
* set the NRF_GPIOTE->CONFIG[n].PORT to 1 (P1 port).
*/
/* Note: the pdn-gpios property is optional. */
#if defined(NRF_GPIO_PDN)
NRF_GPIOTE->CONFIG[HAL_PDN_GPIOTE_CHAN] =
(GPIOTE_CONFIG_MODE_Task <<
GPIOTE_CONFIG_MODE_Pos) |
(CONFIG_BT_CTLR_GPIO_PDN_PIN <<
(NRF_GPIO_PDN_PSEL <<
GPIOTE_CONFIG_PSEL_Pos) |
(GPIOTE_CONFIG_POLARITY_Toggle <<
GPIOTE_CONFIG_POLARITY_Pos) |
#if defined(HAL_RADIO_GPIO_NRF21540_PDN_POL_INV)
(GPIOTE_CONFIG_OUTINIT_High <<
(OUTINIT_INACTIVE(NRF_GPIO_PDN_FLAGS) <<
GPIOTE_CONFIG_OUTINIT_Pos);
#else
(GPIOTE_CONFIG_OUTINIT_Low <<
GPIOTE_CONFIG_OUTINIT_Pos);
#endif
#endif /* NRF_GPIO_PDN_PIN */
}
#endif /* CONFIG_BT_CTLR_GPIO_PDN_PIN */
#if defined(CONFIG_BT_CTLR_GPIO_CSN_PIN)
void radio_gpio_csn_setup(void)
{
/* NOTE: With GPIO Pins above 31, left shift of
* CONFIG_BT_CTLR_GPIO_PA_PIN by GPIOTE_CONFIG_PSEL_Pos will
* set the NRF_GPIOTE->CONFIG[n].PORT to 1 (P1 port).
*/
/* Note: the spi-if property is optional. */
#if defined(NRF_GPIO_CSN_PIN)
NRF_GPIOTE->CONFIG[HAL_CSN_GPIOTE_CHAN] =
(GPIOTE_CONFIG_MODE_Task <<
GPIOTE_CONFIG_MODE_Pos) |
(CONFIG_BT_CTLR_GPIO_CSN_PIN <<
(NRF_GPIO_CSN_PSEL <<
GPIOTE_CONFIG_PSEL_Pos) |
(GPIOTE_CONFIG_POLARITY_Toggle <<
GPIOTE_CONFIG_POLARITY_Pos) |
#if defined(HAL_RADIO_GPIO_NRF21540_CSN_POL_INV)
(GPIOTE_CONFIG_OUTINIT_High <<
(OUTINIT_INACTIVE(NRF_GPIO_CSN_FLAGS) <<
GPIOTE_CONFIG_OUTINIT_Pos);
#else
(GPIOTE_CONFIG_OUTINIT_Low <<
GPIOTE_CONFIG_OUTINIT_Pos);
#endif
#endif /* NRF_GPIO_CSN_PIN */
}
#endif /* CONFIG_BT_CTLR_GPIO_CSN_PIN */
void radio_gpio_lna_on(void)
{
#if defined(HAL_RADIO_GPIO_LNA_POL_INV)
NRF_GPIO_LNA->OUTCLR = BIT(NRF_GPIO_LNA_PIN);
#else
NRF_GPIO_LNA->OUTSET = BIT(NRF_GPIO_LNA_PIN);
#endif
if (ACTIVE_LOW(NRF_GPIO_LNA_FLAGS)) {
NRF_GPIO_LNA->OUTCLR = BIT(NRF_GPIO_LNA_PIN);
} else {
NRF_GPIO_LNA->OUTSET = BIT(NRF_GPIO_LNA_PIN);
}
}
void radio_gpio_lna_off(void)
{
#if defined(HAL_RADIO_GPIO_LNA_POL_INV)
NRF_GPIO_LNA->OUTSET = BIT(NRF_GPIO_LNA_PIN);
#else
NRF_GPIO_LNA->OUTCLR = BIT(NRF_GPIO_LNA_PIN);
#endif
if (ACTIVE_LOW(NRF_GPIO_LNA_FLAGS)) {
NRF_GPIO_LNA->OUTSET = BIT(NRF_GPIO_LNA_PIN);
} else {
NRF_GPIO_LNA->OUTCLR = BIT(NRF_GPIO_LNA_PIN);
}
}
#endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */
void radio_gpio_pa_lna_enable(uint32_t trx_us)
{
nrf_timer_cc_set(EVENT_TIMER, 2, trx_us);
#if defined(HAL_RADIO_FEM_IS_NRF21540)
nrf_timer_cc_set(EVENT_TIMER, 3, (trx_us -
HAL_RADIO_GPIO_NRF21540_PDN_OFFSET));
#if defined(HAL_RADIO_FEM_IS_NRF21540) && DT_NODE_HAS_PROP(FEM_NODE, pdn_gpios)
nrf_timer_cc_set(EVENT_TIMER, 3, (trx_us - NRF_GPIO_PDN_OFFSET));
hal_radio_nrf_ppi_channels_enable(BIT(HAL_ENABLE_PALNA_PPI) |
BIT(HAL_DISABLE_PALNA_PPI) |
BIT(HAL_ENABLE_FEM_PPI) |

View file

@ -60,39 +60,8 @@
#define HAL_CSN_GPIOTE_CHAN 2
#endif
#if defined(CONFIG_BT_CTLR_GPIO_PA)
#define HAL_RADIO_GPIO_HAVE_PA_PIN 1
#endif
#if defined(CONFIG_BT_CTLR_GPIO_LNA)
#define HAL_RADIO_GPIO_HAVE_LNA_PIN 1
#endif
#if defined(CONFIG_BT_CTLR_GPIO_PA_POL_INV)
#define HAL_RADIO_GPIO_PA_POL_INV CONFIG_BT_CTLR_GPIO_PA_POL_INV
#endif
#if defined(CONFIG_BT_CTLR_GPIO_LNA_POL_INV)
#define HAL_RADIO_GPIO_LNA_POL_INV CONFIG_BT_CTLR_GPIO_LNA_POL_INV
#endif
#if defined(CONFIG_BT_CTLR_GPIO_PDN_POL_INV)
#define HAL_RADIO_GPIO_NRF21540_PDN_POL_INV CONFIG_BT_CTLR_GPIO_PDN_POL_INV
#endif
#if defined(CONFIG_BT_CTLR_GPIO_CSN_POL_INV)
#define HAL_RADIO_GPIO_NRF21540_CSN_POL_INV CONFIG_BT_CTLR_GPIO_CSN_POL_INV
#endif
#if defined(CONFIG_BT_CTLR_GPIO_PA_OFFSET)
#define HAL_RADIO_GPIO_PA_OFFSET CONFIG_BT_CTLR_GPIO_PA_OFFSET
#endif
#if defined(CONFIG_BT_CTLR_GPIO_LNA_OFFSET)
#define HAL_RADIO_GPIO_LNA_OFFSET CONFIG_BT_CTLR_GPIO_LNA_OFFSET
#endif
#if defined(CONFIG_BT_CTLR_GPIO_PDN_CSN_OFFSET)
#define HAL_RADIO_GPIO_NRF21540_PDN_OFFSET CONFIG_BT_CTLR_GPIO_PDN_CSN_OFFSET
#endif
#if defined(CONFIG_BT_CTLR_FEM_NRF21540)
#define HAL_RADIO_FEM_IS_NRF21540 1
#endif
/* This has to come before the ppi/dppi includes below. */
#include "radio_nrf5_fem.h"
#if defined(PPI_PRESENT)
#include "radio_nrf5_ppi.h"

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Generic helper macros for getting radio front-end module (FEM)
* settings from devicetree. The main task here is to check the
* devicetree compatible of the node the fem property points at, and
* pull in a subheader that translates from that compatible's specific
* properties to the generic macros required by the nRF5 radio HAL.
*/
#include <devicetree.h>
#include <dt-bindings/gpio/gpio.h>
#if DT_NODE_HAS_PROP(DT_NODELABEL(radio), fem)
#define FEM_NODE DT_PHANDLE(DT_NODELABEL(radio), fem)
#if DT_NODE_HAS_STATUS(FEM_NODE, okay)
#define HAL_RADIO_HAVE_FEM
#endif /* DT_NODE_HAS_STATUS(FEM_NODE, okay) */
#endif /* DT_NODE_HAS_PROP(DT_NODELABEL(radio), fem)) */
/* Does FEM_NODE have a particular DT compatible? */
#define FEM_HAS_COMPAT(compat) DT_NODE_HAS_COMPAT(FEM_NODE, compat)
/* Does FEM_NODE have a particular DT property defined? */
#define FEM_HAS_PROP(prop) DT_NODE_HAS_PROP(FEM_NODE, prop)
/*
* Device-specific settings are pulled in based FEM_NODE's compatible
* property.
*/
#ifdef HAL_RADIO_HAVE_FEM
#if FEM_HAS_COMPAT(generic_fem_two_ctrl_pins)
#include "radio_nrf5_fem_generic.h"
#elif FEM_HAS_COMPAT(nordic_nrf21540_fem)
#include "radio_nrf5_fem_nrf21540.h"
#else
#error "radio node fem property has an unsupported compatible"
#endif /* FEM_HAS_COMPAT(generic_fem_two_ctrl_pins) */
#endif /* HAL_RADIO_HAVE_FEM */
/*
* Define POL_INV macros expected by radio_nrf5_dppi as needed.
*/
#ifdef HAL_RADIO_GPIO_HAVE_PA_PIN
#if DT_GPIO_FLAGS(FEM_NODE, HAL_RADIO_GPIO_PA_PROP) & GPIO_ACTIVE_LOW
#define HAL_RADIO_GPIO_PA_POL_INV
#endif
#endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
#ifdef HAL_RADIO_GPIO_HAVE_LNA_PIN
#if DT_GPIO_FLAGS(FEM_NODE, HAL_RADIO_GPIO_LNA_PROP) & GPIO_ACTIVE_LOW
#define HAL_RADIO_GPIO_LNA_POL_INV
#endif
#endif /* HAL_RADIO_GPIO_HAVE_LNA_PIN */

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file contains helper macros for dealing with the devicetree
* radio node's fem property, in the case that it has compatible
* "generic-fem-two-ctrl-pins".
*
* Do not include it directly.
*
* For these devices:
*
* Value Property
* --------- --------
* PA pin ctx-gpios
* PA offset ctx-settle-time-us
* LNA pin crx-gpios
* LNA offset crx-settle-time-us
*/
#define HAL_RADIO_GPIO_PA_PROP_NAME "ctx-gpios"
#define HAL_RADIO_GPIO_PA_OFFSET_PROP_NAME "ctx-settle-time-us"
#define HAL_RADIO_GPIO_LNA_PROP_NAME "crx-gpios"
#define HAL_RADIO_GPIO_LNA_OFFSET_PROP_NAME "crx-settle-time-us"
#if FEM_HAS_PROP(ctx_gpios)
#define HAL_RADIO_GPIO_HAVE_PA_PIN 1
#define HAL_RADIO_GPIO_PA_PROP ctx_gpios
#define HAL_RADIO_GPIO_PA_OFFSET_MISSING (!FEM_HAS_PROP(ctx_settle_time_us))
#define HAL_RADIO_GPIO_PA_OFFSET \
DT_PROP_OR(FEM_NODE, ctx_settle_time_us, 0)
#else /* !FEM_HAS_PROP(ctx_gpios) */
#define HAL_RADIO_GPIO_PA_OFFSET_MISSING 0
#endif /* FEM_HAS_PROP(ctx_gpios) */
#if FEM_HAS_PROP(crx_gpios)
#define HAL_RADIO_GPIO_HAVE_LNA_PIN 1
#define HAL_RADIO_GPIO_LNA_PROP crx_gpios
#define HAL_RADIO_GPIO_LNA_OFFSET_MISSING (!FEM_HAS_PROP(crx_settle_time_us))
#define HAL_RADIO_GPIO_LNA_OFFSET \
DT_PROP_OR(FEM_NODE, crx_settle_time_us, 0)
#else /* !FEM_HAS_PROP(crx_gpios) */
#define HAL_RADIO_GPIO_LNA_OFFSET_MISSING 0
#endif /* FEM_HAS_PROP(crx_gpios) */

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This file contains helper macros for dealing with the devicetree
* radio node's fem property, in the case that it has compatible
* "nordic,nrf21540-fem".
*
* Do not include it directly.
*
* For nRF21540 devices:
*
* Value Property
* --------- --------
* PA pin tx-en-gpios
* PA offset tx-en-settle-time-us
* LNA pin rx-en-gpios
* LNA offset rx-en-settle-time-us
* PDN pin pdn-gpios
* PDN offset pdn-settle-time-us
*
* The spi-if property may point at a SPI device node representing the
* FEM's SPI control interface. See the binding for details.
*/
#define HAL_RADIO_FEM_IS_NRF21540 1
#define HAL_RADIO_GPIO_PA_PROP_NAME "tx-en-gpios"
#define HAL_RADIO_GPIO_PA_OFFSET_PROP_NAME "tx-en-settle-time-us"
#define HAL_RADIO_GPIO_LNA_PROP_NAME "rx-en-gpios"
#define HAL_RADIO_GPIO_LNA_OFFSET_PROP_NAME "rx-en-settle-time-us"
/* This FEM's PA and LNA offset properties have defaults set. */
#define HAL_RADIO_GPIO_PA_OFFSET_MISSING 0
#define HAL_RADIO_GPIO_LNA_OFFSET_MISSING 0
#if FEM_HAS_PROP(tx_en_gpios)
#define HAL_RADIO_GPIO_HAVE_PA_PIN 1
#define HAL_RADIO_GPIO_PA_PROP tx_en_gpios
#define HAL_RADIO_GPIO_PA_OFFSET DT_PROP(FEM_NODE, tx_en_settle_time_us)
#endif /* FEM_HAS_PROP(tx_en_gpios) */
#if FEM_HAS_PROP(rx_en_gpios)
#define HAL_RADIO_GPIO_HAVE_LNA_PIN 1
#define HAL_RADIO_GPIO_LNA_PROP rx_en_gpios
#define HAL_RADIO_GPIO_LNA_OFFSET DT_PROP(FEM_NODE, rx_en_settle_time_us)
#endif /* FEM_HAS_PROP(rx_en_gpios) */
/*
* The POL_INV macros defined below are just to keep things simple in
* radio_nrf5_dppi.h, which uses them.
*/
#if FEM_HAS_PROP(pdn_gpios)
#if DT_GPIO_FLAGS(FEM_NODE, pdn_gpios) & GPIO_ACTIVE_LOW
#define HAL_RADIO_GPIO_NRF21540_PDN_POL_INV 1
#endif /* DT_GPIO_FLAGS(FEM_NODE, pdn_gpios) & GPIO_ACTIVE_LOW */
#endif /* FEM_HAS_PROP(pdn_gpios) */
#if FEM_HAS_PROP(spi_if)
/* This is the "SPI device" node, i.e. the one with compatible
* nordic,nrf21540-fem-spi.
*/
#define FEM_SPI_DEV_NODE DT_PHANDLE(FEM_NODE, spi_if)
/* If the SPI device node has a chip select gpio... */
#if DT_SPI_DEV_HAS_CS_GPIOS(FEM_SPI_DEV_NODE)
/* set a macro indicating that, and... */
#define HAL_RADIO_FEM_NRF21540_HAS_CSN 1
/* use it to get the CSN polarity. */
#if DT_SPI_DEV_CS_GPIOS_FLAGS(FEM_SPI_DEV_NODE) & GPIO_ACTIVE_LOW
#define HAL_RADIO_GPIO_NRF21540_CSN_POL_INV 1
#endif /* DT_SPI_DEV_CS_GPIOS_FLAGS(FEM_SPI_DEV_NODE) & GPIO_ACTIVE_LOW */
#endif /* DT_SPI_DEV_HAS_CS_GPIOS(FEM_SPI_DEV_NODE) */
#endif /* FEM_HAS_PROP(spi_if) */

View file

@ -6,16 +6,11 @@
#include "hal/RV32M1/radio/radio.h"
#if defined(CONFIG_BT_CTLR_GPIO_PA)
#define HAL_RADIO_GPIO_HAVE_PA_PIN
#endif
#if defined(CONFIG_BT_CTLR_GPIO_LNA)
#define HAL_RADIO_GPIO_HAVE_LNA_PIN
#endif
#if defined(CONFIG_BT_CTLR_GPIO_PA_OFFSET)
#define HAL_RADIO_GPIO_PA_OFFSET CONFIG_BT_CTLR_GPIO_PA_OFFSET
#endif
#if defined(CONFIG_BT_CTLR_GPIO_LNA_OFFSET)
#define HAL_RADIO_GPIO_LNA_OFFSET CONFIG_BT_CTLR_GPIO_LNA_OFFSET
#endif
/* The openisa vendor HAL does not have the GPIO support functions
* required for handling radio front-end modules with PA/LNAs.
*
* If these are ever implemented, this file should be updated
* appropriately.
*/
#undef HAL_RADIO_GPIO_HAVE_PA_PIN
#undef HAL_RADIO_GPIO_HAVE_LNA_PIN

View file

@ -0,0 +1,13 @@
/ {
nrf_radio_fem: fem {
compatible = "generic-fem-two-ctrl-pins";
ctx-gpios = <&gpio0 26 0>;
ctx-settle-time-us = <5>;
crx-gpios = <&gpio0 27 0>;
crx-settle-time-us = <5>;
};
};
&radio {
fem = <&nrf_radio_fem>;
};

View file

@ -24,8 +24,6 @@ CONFIG_BT_CTLR_CONN_RSSI=n
CONFIG_BT_CTLR_ADV_INDICATION=n
CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n
CONFIG_BT_CTLR_SCAN_REQ_RSSI=n
CONFIG_BT_CTLR_GPIO_PA=n
CONFIG_BT_CTLR_GPIO_LNA=n
CONFIG_BT_CTLR_PROFILE_ISR=n
CONFIG_BT_CTLR_DEBUG_PINS=n
CONFIG_BT_HCI_VS_EXT=n

View file

@ -26,8 +26,6 @@ CONFIG_BT_CTLR_CONN_RSSI=n
CONFIG_BT_CTLR_ADV_INDICATION=n
CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n
CONFIG_BT_CTLR_SCAN_REQ_RSSI=n
CONFIG_BT_CTLR_GPIO_PA=n
CONFIG_BT_CTLR_GPIO_LNA=n
CONFIG_BT_CTLR_PROFILE_ISR=n
CONFIG_BT_CTLR_DEBUG_PINS=n
CONFIG_BT_HCI_VS_EXT=n

View file

@ -30,10 +30,6 @@ CONFIG_BT_CTLR_ADV_INDICATION=y
CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=y
CONFIG_BT_CTLR_SCAN_REQ_RSSI=y
CONFIG_BT_CTLR_SCAN_INDICATION=y
CONFIG_BT_CTLR_GPIO_PA=y
CONFIG_BT_CTLR_GPIO_PA_PIN=26
CONFIG_BT_CTLR_GPIO_LNA=y
CONFIG_BT_CTLR_GPIO_LNA_PIN=27
CONFIG_BT_CTLR_PROFILE_ISR=y
CONFIG_BT_CTLR_DEBUG_PINS=y
CONFIG_BT_CTLR_TEST=y

View file

@ -28,8 +28,6 @@ CONFIG_BT_CTLR_ADV_INDICATION=n
CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=n
CONFIG_BT_CTLR_SCAN_REQ_RSSI=n
CONFIG_BT_CTLR_PROFILE_ISR=n
CONFIG_BT_CTLR_GPIO_PA=n
CONFIG_BT_CTLR_GPIO_LNA=n
CONFIG_BT_CTLR_PROFILE_ISR=n
CONFIG_BT_CTLR_DEBUG_PINS=n
CONFIG_BT_HCI_VS_EXT=n

View file

@ -104,7 +104,7 @@ tests:
- nrf52dk_nrf52832
- nrf51dk_nrf51422
bluetooth.init.test_ctlr_dbg:
extra_args: CONF_FILE=prj_ctlr_dbg.conf
extra_args: CONF_FILE=prj_ctlr_dbg.conf DTC_OVERLAY_FILE=pa_lna.overlay
platform_allow: nrf52840dk_nrf52840 nrf52dk_nrf52832
nrf51dk_nrf51422
integration_platforms: