|  | /* | 
|  | * Copyright (c) 2023, Nordic Semiconductor ASA | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include "spi_nrfx_common.h" | 
|  | #include <zephyr/kernel.h> | 
|  |  | 
|  | int spi_nrfx_wake_init(const nrfx_gpiote_t *gpiote, uint32_t wake_pin) | 
|  | { | 
|  | nrf_gpio_pin_pull_t pull_config = NRF_GPIO_PIN_PULLDOWN; | 
|  | uint8_t ch; | 
|  | nrfx_gpiote_trigger_config_t trigger_config = { | 
|  | .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, | 
|  | .p_in_channel = &ch, | 
|  | }; | 
|  | nrfx_gpiote_input_pin_config_t input_config = { | 
|  | .p_pull_config = &pull_config, | 
|  | .p_trigger_config = &trigger_config, | 
|  | .p_handler_config = NULL, | 
|  | }; | 
|  | nrfx_err_t res; | 
|  |  | 
|  | res = nrfx_gpiote_channel_alloc(gpiote, &ch); | 
|  | if (res != NRFX_SUCCESS) { | 
|  | return -ENODEV; | 
|  | } | 
|  |  | 
|  | res = nrfx_gpiote_input_configure(gpiote, wake_pin, &input_config); | 
|  | if (res != NRFX_SUCCESS) { | 
|  | nrfx_gpiote_channel_free(gpiote, ch); | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int spi_nrfx_wake_request(const nrfx_gpiote_t *gpiote, uint32_t wake_pin) | 
|  | { | 
|  | nrf_gpiote_event_t trigger_event = nrfx_gpiote_in_event_get(gpiote, wake_pin); | 
|  | uint32_t start_cycles; | 
|  | uint32_t max_wait_cycles = | 
|  | DIV_ROUND_UP(CONFIG_SPI_NRFX_WAKE_TIMEOUT_US * | 
|  | CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, | 
|  | 1000000); | 
|  | int err = 0; | 
|  |  | 
|  | /* Enable the trigger (a high-to-low transition) without its interrupt. | 
|  | * The expected time to wait is quite short so it is not worth paying | 
|  | * the overhead of context switching to handle the interrupt. | 
|  | */ | 
|  | nrfx_gpiote_trigger_enable(gpiote, wake_pin, false); | 
|  | /* Enable pull-up on the WAKE line. After the slave device sees the | 
|  | * WAKE line going high, it will force the line to go low. This will | 
|  | * be caught by the enabled trigger and the loop below waits for that. | 
|  | */ | 
|  | nrf_gpio_cfg_input(wake_pin, NRF_GPIO_PIN_PULLUP); | 
|  |  | 
|  | start_cycles = k_cycle_get_32(); | 
|  | while (!nrf_gpiote_event_check(gpiote->p_reg, trigger_event)) { | 
|  | uint32_t elapsed_cycles = k_cycle_get_32() - start_cycles; | 
|  |  | 
|  | if (elapsed_cycles >= max_wait_cycles) { | 
|  | err = -ETIMEDOUT; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | nrfx_gpiote_trigger_disable(gpiote, wake_pin); | 
|  | nrf_gpio_cfg_input(wake_pin, NRF_GPIO_PIN_PULLDOWN); | 
|  |  | 
|  | return err; | 
|  | } |