drivers: gpio: nrfx: add support for ports with pad on FAST_ACTIVE1
This patch allows to _safely_ configure GPIO ports that have their pad on FAST_ACTIVE1 domain. Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
parent
0b18f31246
commit
56c5b1e2da
1 changed files with 108 additions and 8 deletions
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
|
||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||
#include <nrf/gpd.h>
|
||||
#endif
|
||||
|
||||
struct gpio_nrfx_data {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_data common;
|
||||
|
|
@ -27,6 +31,9 @@ struct gpio_nrfx_cfg {
|
|||
uint32_t edge_sense;
|
||||
uint8_t port_num;
|
||||
nrfx_gpiote_t gpiote;
|
||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||
uint8_t pad_pd;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline struct gpio_nrfx_data *get_port_data(const struct device *port)
|
||||
|
|
@ -55,9 +62,59 @@ static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags)
|
|||
return NRF_GPIO_PIN_NOPULL;
|
||||
}
|
||||
|
||||
static int gpio_nrfx_gpd_retain_set(const struct device *port, uint32_t mask, gpio_flags_t flags)
|
||||
{
|
||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
|
||||
|
||||
if (cfg->pad_pd == NRF_GPD_FAST_ACTIVE1) {
|
||||
int ret;
|
||||
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
cfg->port->RETAINSET = mask;
|
||||
}
|
||||
|
||||
ret = nrf_gpd_release(NRF_GPD_FAST_ACTIVE1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(port);
|
||||
ARG_UNUSED(mask);
|
||||
ARG_UNUSED(flags);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_nrfx_gpd_retain_clear(const struct device *port, uint32_t mask)
|
||||
{
|
||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
|
||||
|
||||
if (cfg->pad_pd == NRF_GPD_FAST_ACTIVE1) {
|
||||
int ret;
|
||||
|
||||
ret = nrf_gpd_request(NRF_GPD_FAST_ACTIVE1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
cfg->port->RETAINCLR = mask;
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(port);
|
||||
ARG_UNUSED(mask);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
|
||||
gpio_flags_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
nrfx_err_t err = NRFX_SUCCESS;
|
||||
uint8_t ch;
|
||||
bool free_ch = false;
|
||||
|
|
@ -95,6 +152,11 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = gpio_nrfx_gpd_retain_clear(port, BIT(pin));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
||||
nrf_gpio_port_out_set(cfg->port, BIT(pin));
|
||||
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
||||
|
|
@ -110,7 +172,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
|
|||
: NRF_GPIO_PIN_INPUT_DISCONNECT;
|
||||
|
||||
nrf_gpio_reconfigure(abs_pin, &dir, &input, &pull, &drive, NULL);
|
||||
return 0;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Get the GPIOTE channel associated with this pin, if any. It needs
|
||||
|
|
@ -137,7 +200,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
|
|||
err = nrfx_gpiote_input_configure(&cfg->gpiote,
|
||||
abs_pin, &input_pin_config);
|
||||
if (err != NRFX_SUCCESS) {
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +226,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
|
|||
}
|
||||
|
||||
if (err != NRFX_SUCCESS) {
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +236,9 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
|
|||
__ASSERT_NO_MSG(err == NRFX_SUCCESS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
end:
|
||||
(void)gpio_nrfx_gpd_retain_set(port, BIT(pin), flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_nrfx_port_get_raw(const struct device *port,
|
||||
|
|
@ -189,34 +256,52 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port,
|
|||
gpio_port_value_t value)
|
||||
{
|
||||
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
|
||||
int ret;
|
||||
|
||||
const uint32_t set_mask = value & mask;
|
||||
const uint32_t clear_mask = (~set_mask) & mask;
|
||||
|
||||
ret = gpio_nrfx_gpd_retain_clear(port, mask);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nrf_gpio_port_out_set(reg, set_mask);
|
||||
nrf_gpio_port_out_clear(reg, clear_mask);
|
||||
|
||||
return 0;
|
||||
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
|
||||
}
|
||||
|
||||
static int gpio_nrfx_port_set_bits_raw(const struct device *port,
|
||||
gpio_port_pins_t mask)
|
||||
{
|
||||
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
|
||||
int ret;
|
||||
|
||||
ret = gpio_nrfx_gpd_retain_clear(port, mask);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nrf_gpio_port_out_set(reg, mask);
|
||||
|
||||
return 0;
|
||||
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
|
||||
}
|
||||
|
||||
static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
|
||||
gpio_port_pins_t mask)
|
||||
{
|
||||
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
|
||||
int ret;
|
||||
|
||||
ret = gpio_nrfx_gpd_retain_clear(port, mask);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nrf_gpio_port_out_clear(reg, mask);
|
||||
|
||||
return 0;
|
||||
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
|
||||
}
|
||||
|
||||
static int gpio_nrfx_port_toggle_bits(const struct device *port,
|
||||
|
|
@ -226,11 +311,17 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port,
|
|||
const uint32_t value = nrf_gpio_port_out_read(reg) ^ mask;
|
||||
const uint32_t set_mask = value & mask;
|
||||
const uint32_t clear_mask = (~value) & mask;
|
||||
int ret;
|
||||
|
||||
ret = gpio_nrfx_gpd_retain_clear(port, mask);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nrf_gpio_port_out_set(reg, set_mask);
|
||||
nrf_gpio_port_out_clear(reg, clear_mask);
|
||||
|
||||
return 0;
|
||||
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIO_NRFX_INTERRUPT
|
||||
|
|
@ -450,6 +541,14 @@ static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = {
|
|||
"Please enable GPIOTE instance for used GPIO port!")), \
|
||||
())
|
||||
|
||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||
#define PAD_PD(inst) \
|
||||
.pad_pd = DT_INST_PHA_BY_NAME_OR(inst, power_domains, pad, id, \
|
||||
NRF_GPD_SLOW_MAIN),
|
||||
#else
|
||||
#define PAD_PD(inst)
|
||||
#endif
|
||||
|
||||
#define GPIO_NRF_DEVICE(id) \
|
||||
GPIOTE_CHECK(id); \
|
||||
static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
|
||||
|
|
@ -461,6 +560,7 @@ static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = {
|
|||
.port_num = DT_INST_PROP(id, port), \
|
||||
.edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
|
||||
.gpiote = GPIOTE_INSTANCE(id), \
|
||||
PAD_PD(id) \
|
||||
}; \
|
||||
\
|
||||
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
|
||||
|
|
|
|||
Loading…
Reference in a new issue