Skip to content

Commit

Permalink
drivers: add eGPIO SHIM
Browse files Browse the repository at this point in the history
Signed-off-by: Magdalena Pastula <[email protected]>
  • Loading branch information
magp-nordic committed Jun 13, 2024
1 parent 17c3770 commit f79b54b
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 1 deletion.
3 changes: 2 additions & 1 deletion drivers/gpio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_NEORV32 gpio_neorv32.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NPCX gpio_npcx.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NPM1300 gpio_npm1300.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NPM6001 gpio_npm6001.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NRFX gpio_nrfx.c)
zephyr_library_sources_ifdef(CONFIG_NRFE_GPIO egpio_nrfx.c)
zephyr_library_sources_ifdef(CONFIG_NRFX_GPIO gpio_nrfx.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NUMAKER gpio_numaker.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NUMICRO gpio_numicro.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NXP_S32 gpio_nxp_s32.c)
Expand Down
15 changes: 15 additions & 0 deletions drivers/gpio/Kconfig.nrfx
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,18 @@ config GPIO_NRFX_INTERRUPT
The option can be used to disable the GPIO interrupt support to
significantly reduce memory footprint in case of application that does
not need GPIO interrupts.

choice GPIO_NRFX_TYPE
prompt "nRF GPIO driver type"
depends on GPIO_NRFX
default NRFX_GPIO
help
Type of GPIO driver to use.

config NRFX_GPIO
bool "Stardard GPIO"

config NRFE_GPIO
bool "Emulated GPIO"

endchoice
193 changes: 193 additions & 0 deletions drivers/gpio/egpio_nrfx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* Copyright (c) 2024, Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT nordic_nrf_gpio

#include <nrfx_gpiote.h>
#include <string.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
#include <zephyr/irq.h>

#include <zephyr/drivers/gpio/gpio_utils.h>

#include <zephyr/kernel.h>
#include <zephyr/device.h>

#include <zephyr/ipc/ipc_service.h>

#include <app/nrfe_gpio.h>

K_SEM_DEFINE(bound_sem, 0, 1);

static void ep_bound(void *priv)
{
k_sem_give(&bound_sem);
}

static void ep_recv(const void *data, size_t len, void *priv)
{
}

static struct ipc_ept_cfg ep_cfg = {
.cb = {
.bound = ep_bound,
.received = ep_recv,
},
};

struct ipc_ept ep;

struct gpio_nrfx_data {
/* gpio_driver_data needs to be first */
struct gpio_driver_data common;
};

struct gpio_nrfx_cfg {
/* gpio_driver_config needs to be first */
struct gpio_driver_config common;
uint8_t port_num;
};

static inline const struct gpio_nrfx_cfg *get_port_cfg(const struct device *port)
{
return port->config;
}

static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
gpio_flags_t flags)
{
struct nrfe_gpio_data_packet msg = {.opcode = NRFE_GPIO_PIN_CONFIGURE,
.pin = pin,
.port = get_port_cfg(port)->port_num,
.flags = flags};

return ipc_service_send(&ep, (void*)(&msg), sizeof(struct nrfe_gpio_data_packet));
}

static int gpio_nrfx_port_set_masked_raw(const struct device *port,
gpio_port_pins_t mask,
gpio_port_value_t value)
{

const uint32_t set_mask = value & mask;
const uint32_t clear_mask = (~set_mask) & mask;

struct nrfe_gpio_data_packet msg = {.opcode = NRFE_GPIO_PIN_SET,
.pin = set_mask,
.port = get_port_cfg(port)->port_num};

int ret_val = ipc_service_send(&ep, (void*)(&msg), sizeof(struct nrfe_gpio_data_packet));

if (ret_val < 0) {
return ret_val;
}

msg.opcode = NRFE_GPIO_PIN_CLEAR;
msg.pin = clear_mask;

return ipc_service_send(&ep, (void*)(&msg), sizeof(struct nrfe_gpio_data_packet));
}

static int gpio_nrfx_port_set_bits_raw(const struct device *port,
gpio_port_pins_t mask)
{
struct nrfe_gpio_data_packet msg = {.opcode = NRFE_GPIO_PIN_SET,
.pin = mask,
.port = get_port_cfg(port)->port_num};

return ipc_service_send(&ep, (void*)(&msg), sizeof(struct nrfe_gpio_data_packet));
}

static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
gpio_port_pins_t mask)
{
struct nrfe_gpio_data_packet msg = {.opcode = NRFE_GPIO_PIN_CLEAR,
.pin = mask,
.port = get_port_cfg(port)->port_num};

return ipc_service_send(&ep, (void*)(&msg), sizeof(struct nrfe_gpio_data_packet));
}

static int gpio_nrfx_port_toggle_bits(const struct device *port,
gpio_port_pins_t mask)
{
struct nrfe_gpio_data_packet msg = {.opcode = NRFE_GPIO_PIN_TOGGLE,
.pin = mask,
.port = get_port_cfg(port)->port_num};

return ipc_service_send(&ep, (void*)(&msg), sizeof(struct nrfe_gpio_data_packet));
}

static int gpio_nrfx_init(const struct device *port)
{
const struct device *ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));

int ret = ipc_service_open_instance(ipc0_instance);
if ((ret < 0) && (ret != -EALREADY)) {
// LOG_ERR("ipc_service_open_instance() failure");
return ret;
}

ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
if (ret < 0) {
// LOG_ERR("ipc_service_register_endpoint() failure");
return ret;
}

k_sem_take(&bound_sem, K_FOREVER);

return 0;
}

static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = {
.pin_configure = gpio_nrfx_pin_configure,
.port_set_masked_raw = gpio_nrfx_port_set_masked_raw,
.port_set_bits_raw = gpio_nrfx_port_set_bits_raw,
.port_clear_bits_raw = gpio_nrfx_port_clear_bits_raw,
.port_toggle_bits = gpio_nrfx_port_toggle_bits,
};

#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance)
#define GPIOTE_INST(id) DT_PROP(GPIOTE_PHANDLE(id), instance)

#define GPIOTE_INSTANCE(id) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(id, gpiote_instance), \
(NRFX_GPIOTE_INSTANCE(GPIOTE_INST(id))), \
({ .p_reg = NULL }))

/* Device instantiation is done with node labels because 'port_num' is
* the peripheral number by SoC numbering. We therefore cannot use
* DT_INST APIs here without wider changes.
*/

#define GPIOTE_CHECK(id) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(id, gpiote_instance), \
(BUILD_ASSERT(DT_NODE_HAS_STATUS(GPIOTE_PHANDLE(id), okay), \
"Please enable GPIOTE instance for used GPIO port!")), \
())

#define GPIO_NRF_DEVICE(id) \
GPIOTE_CHECK(id); \
static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
.common = { \
.port_pin_mask = \
GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
}, \
.port_num = DT_INST_PROP(id, port), \
}; \
\
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
\
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
NULL, \
&gpio_nrfx_p##id##_data, \
&gpio_nrfx_p##id##_cfg, \
PRE_KERNEL_1, \
CONFIG_GPIO_INIT_PRIORITY, \
&gpio_nrfx_drv_api_funcs);

DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_DEVICE)
2 changes: 2 additions & 0 deletions modules/hal_nordic/nrfx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ zephyr_include_directories(${INC_DIR})
zephyr_include_directories(${MDK_DIR})
zephyr_include_directories(.)

zephyr_include_directories_ifdef(CONFIG_NRFE_GPIO ${ZEPHYR_CURRENT_MODULE_DIR}/nrfe)

# Define MDK defines globally
zephyr_compile_definitions_ifdef(CONFIG_SOC_SERIES_NRF51X NRF51)
zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF51822_QFAA NRF51422_XXAA)
Expand Down

0 comments on commit f79b54b

Please sign in to comment.