Skip to content

Commit

Permalink
drivers: add eGPIO SHIM
Browse files Browse the repository at this point in the history
Cherry-picked from magp-nordic/pull/2 with my local changes.

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 24, 2024
1 parent bfcfd2a commit c63639b
Show file tree
Hide file tree
Showing 12 changed files with 317 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 @@ -144,6 +144,7 @@ source "drivers/gpio/Kconfig.neorv32"
source "drivers/gpio/Kconfig.npcx"
source "drivers/gpio/Kconfig.npm1300"
source "drivers/gpio/Kconfig.npm6001"
source "drivers/gpio/Kconfig.nrfe"
source "drivers/gpio/Kconfig.nrfx"
source "drivers/gpio/Kconfig.numaker"
source "drivers/gpio/Kconfig.numicro"
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

config 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.
204 changes: 204 additions & 0 deletions drivers/gpio/gpio_nrfe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* 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);
#else
volatile uint32_t bound_sem = 1;
#endif

static void ep_bound(void *priv)
{
#ifdef CONFIG_MULTITHREADING
k_sem_give(&bound_sem);
#else
bound_sem = 0;
#endif
}

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_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)
{
nrfe_gpio_data_packet_t msg = {.opcode = NRFE_GPIO_PIN_CONFIGURE,
.pin = pin,
.port = get_port_cfg(port)->port_num,
.flags = flags};

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

if (ret < 0) {
return ret;
}

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;

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

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

if (ret < 0) {
return ret;
}

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

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

if (ret < 0) {
return ret;
}

return ret;
}

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

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

if (ret < 0) {
return ret;
}

return ret;
}

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

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

if (ret < 0) {
return ret;
}

return ret;
}

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

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

if (ret < 0) {
return ret;
}

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)) {
return ret;
}

ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
if (ret < 0) {
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})
18 changes: 18 additions & 0 deletions modules/hal_nordic/nrfe/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) 2016 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

config HAS_NRFE
bool

menu "nrfe drivers"
depends on HAS_NRFE

config NRFE_GPIO
bool

config NRFE_GPIO2
bool "eGPIO2 driver instance"
depends on $(dt_nodelabel_has_compat,egpio2,$(DT_COMPAT_NORDIC_NRF_EGPIO))
select NRFE_GPIO

endmenu # "nrfe drivers"
3 changes: 3 additions & 0 deletions soc/nordic/common/Kconfig.peripherals
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ config HAS_HW_NRF_GPIOTE130
config HAS_HW_NRF_GPIOTE131
def_bool $(dt_nodelabel_enabled_with_compat,gpiote131,$(DT_COMPAT_NORDIC_NRF_GPIOTE))

config HAS_HW_NRF_EGPIO2
def_bool $(dt_nodelabel_enabled_with_compat,egpio2,$(DT_COMPAT_NORDIC_NRF_EGPIO))

config HAS_HW_NRF_GRTC
def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_GRTC))

Expand Down
1 change: 1 addition & 0 deletions soc/nordic/common/vpr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ config RISCV_CORE_NORDIC_VPR
select RISCV_ISA_EXT_M
select RISCV_ISA_EXT_C
select RISCV_ISA_EXT_ZICSR
select RISCV_ISA_EXT_ZIFENCEI
select RISCV_SOC_HAS_ISR_STACKING
select RISCV_HAS_CLIC
select RISCV_SOC_CONTEXT_SAVE
Expand Down
1 change: 1 addition & 0 deletions soc/nordic/nrf54l/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

config SOC_SERIES_NRF54LX
select SOC_COMPATIBLE_NRF54LX
select HAS_NRFE
select HAS_NRFX
select HAS_NORDIC_DRIVERS
select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE
Expand Down

0 comments on commit c63639b

Please sign in to comment.