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 <magdalena.pastula@nordicsemi.no>
Signed-off-by: Jakub Zymelka <jakub.zymelka@nordicsemi.com>
  • Loading branch information
magp-nordic authored and jaz1-nordic committed Jun 13, 2024
1 parent 60f1a77 commit 4e7470c
Show file tree
Hide file tree
Showing 12 changed files with 380 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/gpio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ 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_NRFE gpio_nrfe.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NRFX gpio_nrfx.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NUMAKER gpio_numaker.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NUMICRO gpio_numicro.c)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ source "drivers/gpio/Kconfig.npcx"
source "drivers/gpio/Kconfig.npm1300"
source "drivers/gpio/Kconfig.npm6001"
source "drivers/gpio/Kconfig.nrfx"
source "drivers/gpio/Kconfig.nrfe"
source "drivers/gpio/Kconfig.numaker"
source "drivers/gpio/Kconfig.numicro"
source "drivers/gpio/Kconfig.nxp_s32"
Expand Down
10 changes: 10 additions & 0 deletions drivers/gpio/Kconfig.nrfe
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

menuconfig GPIO_NRFE
bool "nRF eGPIO driver"
default y
depends on DT_HAS_NORDIC_NRF_EGPIO_ENABLED
select NRFE_GPIO2 if HAS_HW_NRF_EGPIO2
help
Enable eGPIO driver for nRF line of MCUs.
267 changes: 267 additions & 0 deletions drivers/gpio/gpio_nrfe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
/*
* Copyright (c) 2024, Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT nordic_nrf_egpio

#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>

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

#include <zephyr/ipc/ipc_service.h>

#include <nrfe_gpio.h>

#ifdef CONFIG_MULTITHREADING
K_SEM_DEFINE(bound_sem, 0, 1);
K_SEM_DEFINE(confirm_sem, 0, 1);
#else
volatile uint32_t bound_sem = 1;
volatile uint32_t confirm_sem = 1;
#endif

static void ep_bound(void *priv)
{
#ifdef CONFIG_MULTITHREADING
k_sem_give(&bound_sem);
#else
bound_sem = 0;
#endif
printk("Ep bounded\n");
}

static void ep_recv(const void *data, size_t len, void *priv)
{
struct nrfe_gpio_data_packet_t *packet = (struct nrfe_gpio_data_packet_t *)data;

switch (packet->opcode) {
case NRFE_GPIO_CONFIRM:
{
#ifdef CONFIG_MULTITHREADING
k_sem_give(&confirm_sem);
#else
confirm_sem = 0;
#endif
break;
}

default:
break;
}
}

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

struct ipc_ept ep;

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

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

static inline const struct gpio_nrfe_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_t msg = {.opcode = NRFE_GPIO_CONFIGURE,
.pin = pin,
.port = get_port_cfg(port)->port_num,
.flags = flags};

int ret = ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t));

if (ret < 0) {
return ret;
}

#ifdef CONFIG_MULTITHREADING
k_sem_take(&confirm_sem, K_FOREVER);
#else
while (confirm_sem != 0) {
};
#endif

return 0;
}

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_t msg = {
.opcode = NRFE_GPIO_SET, .pin = set_mask, .port = get_port_cfg(port)->port_num};

int ret = ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t));

if (ret < 0) {
return ret;
}

#ifdef CONFIG_MULTITHREADING
k_sem_take(&confirm_sem, K_FOREVER);
#else
while (confirm_sem != 0) {
};
#endif

msg.opcode = NRFE_GPIO_CLEAR;
msg.pin = clear_mask;

ret = ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t));

if (ret < 0) {
return ret;
}

#ifdef CONFIG_MULTITHREADING
k_sem_take(&confirm_sem, K_FOREVER);
#else
while (confirm_sem != 0) {
};
#endif

return ret;
}

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

int ret = ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t));

if (ret < 0) {
return ret;
}

#ifdef CONFIG_MULTITHREADING
k_sem_take(&confirm_sem, K_FOREVER);
#else
while (confirm_sem != 0) {
};
#endif

return ret;
}

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

int ret = ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t));

if (ret < 0) {
return ret;
}

#ifdef CONFIG_MULTITHREADING
k_sem_take(&confirm_sem, K_FOREVER);
#else
while (confirm_sem != 0) {
};
#endif

return ret;
}

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

int ret = ipc_service_send(&ep, (void *)(&msg), sizeof(struct nrfe_gpio_data_packet_t));

if (ret < 0) {
return ret;
}

#ifdef CONFIG_MULTITHREADING
k_sem_take(&confirm_sem, K_FOREVER);
#else
while (confirm_sem != 0) {
};
#endif

return ret;
}

static int gpio_nrfe_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)) {
printk("ipc_service_open_instance() failure\n");
return ret;
}

ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
if (ret < 0) {
printk("ipc_service_register_endpoint() failure\n");
return ret;
}

/* Wait for endpoint to be bound */
#ifdef CONFIG_MULTITHREADING
k_sem_take(&bound_sem, K_FOREVER);
#else
while (bound_sem != 0) {
};
#endif

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,
};

/* 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 EGPIO_NRF_DEVICE(id) \
static const struct gpio_nrfe_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_nrfe_data gpio_nrfx_p##id##_data; \
\
DEVICE_DT_INST_DEFINE(id, gpio_nrfe_init, NULL, &gpio_nrfx_p##id##_data, \
&gpio_nrfx_p##id##_cfg, POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \
&gpio_nrfx_drv_api_funcs);

DT_INST_FOREACH_STATUS_OKAY(EGPIO_NRF_DEVICE)
61 changes: 61 additions & 0 deletions dts/bindings/gpio/nordic,nrf-egpio.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

description: NRF eGPIO node

compatible: "nordic,nrf-egpio"

include: [base.yaml]

properties:
ngpios:
type: int
default: 32
description: |
This property indicates the number of in-use slots of available slots
for GPIOs. The typical example is something like this: the hardware
register is 32 bits wide, but only 18 of the bits have a physical
counterpart. The driver is generally written so that all 32 bits can
be used, but the IP block is reused in a lot of designs, some using
all 32 bits, some using 18 and some using 12. In this case, setting
"ngpios = <18>;" informs the driver that only the first 18 GPIOs, at
local offset 0 .. 17, are in use. For cases in which there might be
holes in the slot range, this value should be the max slot number+1.
gpio-reserved-ranges:
type: array
description: |
If not all the GPIOs at offsets 0...N-1 are usable for ngpios = <N>, then
this property contains an additional set of tuples which specify which GPIOs
are unusable. This property indicates the start and size of the GPIOs
that can't be used.
For example, setting "gpio-reserved-ranges = <3 2>, <10 1>;" means that
GPIO offsets 3, 4, and 10 are not usable, even if ngpios = <18>.
"#gpio-cells":
type: int
required: true
description: Number of items to expect in a GPIO specifier
const: 2

sense-edge-mask:
type: int
description: |
Mask of pins that use the GPIO sense mechanism for edge detection.
Pins not included in the mask use GPIOTE channels in the event mode.
port:
type: int
required: true
description: |
The GPIO port number. GPIO port P0 has:
port = <0>;
And P1 has:
port = <1>;
gpio-cells:
- pin
- flags
1 change: 1 addition & 0 deletions modules/hal_nordic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ endif (CONFIG_NRF_802154_RADIO_DRIVER OR CONFIG_NRF_802154_SERIALIZATION)

add_subdirectory_ifdef(CONFIG_HAS_NRFX nrfx)
add_subdirectory_ifdef(CONFIG_HAS_NRFS nrfs)
add_subdirectory_ifdef(CONFIG_HAS_NRFE nrfe)

if(CONFIG_NRF_REGTOOL_GENERATE_UICR)
list(APPEND nrf_regtool_components GENERATE:UICR)
Expand Down
1 change: 1 addition & 0 deletions modules/hal_nordic/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,5 @@ endmenu # HAS_NORDIC_DRIVERS

rsource "nrfs/Kconfig"
rsource "nrfx/Kconfig"
rsource "nrfe/Kconfig"
rsource "Kconfig.nrf_regtool"
15 changes: 15 additions & 0 deletions modules/hal_nordic/nrfe/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

zephyr_library()

# The nrfe source directory can be override through the definition of the NRFE_DIR symbol
# during the invocation of the build system
if(NOT DEFINED NRFE_DIR)
set(NRFE_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/nrfe CACHE PATH "nrfe Directory")
endif()

set(INC_DIR ${NRFE_DIR}/include)

zephyr_include_directories(${NRFE_DIR})
zephyr_include_directories(${INC_DIR})
Loading

0 comments on commit 4e7470c

Please sign in to comment.