diff --git a/drivers/modem/hl7800.c b/drivers/modem/hl7800.c index eee570ee543..8ea29347cf5 100644 --- a/drivers/modem/hl7800.c +++ b/drivers/modem/hl7800.c @@ -480,10 +480,10 @@ struct hl7800_iface_ctx { struct gpio_callback mdm_uart_dsr_cb; struct gpio_callback mdm_gpio6_cb; struct gpio_callback mdm_uart_cts_cb; - uint32_t vgpio_state; - uint32_t dsr_state; - uint32_t gpio6_state; - uint32_t cts_state; + int vgpio_state; + int dsr_state; + int gpio6_state; + int cts_state; /* RX specific attributes */ struct mdm_receiver_context mdm_ctx; @@ -560,6 +560,9 @@ struct hl7800_iface_ctx { int32_t local_time_offset; bool local_time_valid; bool configured; + void (*wake_up_callback)(int state); + void (*gpio6_callback)(int state); + void (*cts_callback)(int state); #ifdef CONFIG_MODEM_HL7800_GPS struct k_work_delayable gps_work; @@ -658,17 +661,26 @@ static struct stale_socket *dequeue_stale_socket(void) static bool convert_time_string_to_struct(struct tm *tm, int32_t *offset, char *time_string); +static int read_pin(int default_state, const struct device *port, gpio_pin_t pin) +{ + int state = gpio_pin_get(port, pin); + + if (state < 0) { + LOG_ERR("Unable to read port: %s pin: %d status: %d", port->name, pin, state); + state = default_state; + } + + return state; +} + #ifdef CONFIG_MODEM_HL7800_LOW_POWER_MODE static bool is_cmd_ready(void) { - ictx.vgpio_state = (uint32_t)gpio_pin_get(ictx.gpio_port_dev[MDM_VGPIO], - pinconfig[MDM_VGPIO].pin); + ictx.vgpio_state = read_pin(0, ictx.gpio_port_dev[MDM_VGPIO], pinconfig[MDM_VGPIO].pin); - ictx.gpio6_state = (uint32_t)gpio_pin_get(ictx.gpio_port_dev[MDM_GPIO6], - pinconfig[MDM_GPIO6].pin); + ictx.gpio6_state = read_pin(0, ictx.gpio_port_dev[MDM_GPIO6], pinconfig[MDM_GPIO6].pin); - ictx.cts_state = (uint32_t)gpio_pin_get( - ictx.gpio_port_dev[MDM_UART_CTS], pinconfig[MDM_UART_CTS].pin); + ictx.cts_state = read_pin(1, ictx.gpio_port_dev[MDM_UART_CTS], pinconfig[MDM_UART_CTS].pin); return ictx.vgpio_state && ictx.gpio6_state && !ictx.cts_state; } @@ -856,16 +868,37 @@ char *hl7800_sprint_ip_addr(const struct sockaddr *addr) } } +void mdm_hl7800_register_wake_test_point_callback(void (*func)(int state)) +{ + ictx.wake_up_callback = func; +} + +void mdm_hl7800_register_gpio6_callback(void (*func)(int state)) +{ + ictx.gpio6_callback = func; +} + +void mdm_hl7800_register_cts_callback(void (*func)(int state)) +{ + ictx.cts_callback = func; +} + static void modem_assert_wake(bool assert) { + int state; + if (assert) { HL7800_IO_DBG_LOG("MDM_WAKE_PIN -> ASSERTED"); - gpio_pin_set(ictx.gpio_port_dev[MDM_WAKE], - pinconfig[MDM_WAKE].pin, MDM_WAKE_ASSERTED); + state = MDM_WAKE_ASSERTED; } else { HL7800_IO_DBG_LOG("MDM_WAKE_PIN -> NOT_ASSERTED"); - gpio_pin_set(ictx.gpio_port_dev[MDM_WAKE], - pinconfig[MDM_WAKE].pin, MDM_WAKE_NOT_ASSERTED); + state = MDM_WAKE_NOT_ASSERTED; + } + + gpio_pin_set(ictx.gpio_port_dev[MDM_WAKE], pinconfig[MDM_WAKE].pin, state); + + if (ictx.wake_up_callback != NULL) { + ictx.wake_up_callback(state); } } @@ -4662,8 +4695,7 @@ static void mdm_vgpio_work_cb(struct k_work *item) void mdm_vgpio_callback_isr(const struct device *port, struct gpio_callback *cb, uint32_t pins) { - ictx.vgpio_state = (uint32_t)gpio_pin_get(ictx.gpio_port_dev[MDM_VGPIO], - pinconfig[MDM_VGPIO].pin); + ictx.vgpio_state = read_pin(1, ictx.gpio_port_dev[MDM_VGPIO], pinconfig[MDM_VGPIO].pin); HL7800_IO_DBG_LOG("VGPIO:%d", ictx.vgpio_state); if (!ictx.vgpio_state) { prepare_io_for_reset(); @@ -4690,9 +4722,7 @@ void mdm_vgpio_callback_isr(const struct device *port, struct gpio_callback *cb, void mdm_uart_dsr_callback_isr(const struct device *port, struct gpio_callback *cb, uint32_t pins) { - ictx.dsr_state = (uint32_t)gpio_pin_get( - ictx.gpio_port_dev[MDM_UART_DSR], pinconfig[MDM_UART_DSR].pin); - + ictx.dsr_state = read_pin(1, ictx.gpio_port_dev[MDM_UART_DSR], pinconfig[MDM_UART_DSR].pin); HL7800_IO_DBG_LOG("MDM_UART_DSR:%d", ictx.dsr_state); } @@ -4716,8 +4746,7 @@ void mdm_gpio6_callback_isr(const struct device *port, struct gpio_callback *cb, uint32_t pins) { #ifdef CONFIG_MODEM_HL7800_LOW_POWER_MODE - ictx.gpio6_state = (uint32_t)gpio_pin_get(ictx.gpio_port_dev[MDM_GPIO6], - pinconfig[MDM_GPIO6].pin); + ictx.gpio6_state = read_pin(1, ictx.gpio_port_dev[MDM_GPIO6], pinconfig[MDM_GPIO6].pin); HL7800_IO_DBG_LOG("MDM_GPIO6:%d", ictx.gpio6_state); if (!ictx.gpio6_state) { /* HL7800 is not awake, shut down UART to save power */ @@ -4731,6 +4760,12 @@ void mdm_gpio6_callback_isr(const struct device *port, struct gpio_callback *cb, power_on_uart(); } + if ((ictx.gpio6_callback != NULL) && + ((ictx.desired_sleep_level == HL7800_SLEEP_HIBERNATE) || + (ictx.desired_sleep_level == HL7800_SLEEP_LITE_HIBERNATE))) { + ictx.gpio6_callback(ictx.gpio6_state); + } + check_hl7800_awake(); #else HL7800_IO_DBG_LOG("Spurious gpio6 interrupt from the modem"); @@ -4742,6 +4777,11 @@ void mdm_uart_cts_callback(const struct device *port, struct gpio_callback *cb, { ictx.cts_state = (uint32_t)gpio_pin_get( ictx.gpio_port_dev[MDM_UART_CTS], pinconfig[MDM_UART_CTS].pin); + + if ((ictx.cts_callback != NULL) && (ictx.desired_sleep_level == HL7800_SLEEP_SLEEP)) { + ictx.cts_callback(ictx.cts_state); + } + /* CTS toggles A LOT, * comment out the debug print unless we really need it. */ diff --git a/include/drivers/modem/hl7800.h b/include/drivers/modem/hl7800.h index e02f66865a0..13e01d66ef7 100644 --- a/include/drivers/modem/hl7800.h +++ b/include/drivers/modem/hl7800.h @@ -465,6 +465,37 @@ int32_t mdm_hl7800_perform_site_survey(void); */ int mdm_hl7800_set_desired_sleep_level(enum mdm_hl7800_sleep level); +/** + * @brief Allows mapping of WAKE_UP signal + * to a user accessible test point on the development board. + * + * @param func to be called when application requests modem wake/sleep. + * The state parameter of the callback is 1 when modem should stay awake, + * 0 when modem can sleep + */ +void mdm_hl7800_register_wake_test_point_callback(void (*func)(int state)); + +/** + * @brief Allows mapping of P1.12_GPIO6 signal + * to a user accessible test point on the development board. + * + * @param func to be called when modem wakes/sleeps is sleep level is + * hibernate or lite hibernate. + * The state parameter of the callback follows gpio_pin_get definitions, + * but will default high if there is an error reading pin + */ +void mdm_hl7800_register_gpio6_callback(void (*func)(int state)); + +/** + * @brief Allows mapping of UART1_CTS signal + * to a user accessible test point on the development board. + * + * @param func to be called when CTS state changes if sleep level is sleep. + * The state parameter of the callback follows gpio_pin_get definitions, + * but will default low if there is an error reading pin + */ +void mdm_hl7800_register_cts_callback(void (*func)(int state)); + #ifdef __cplusplus } #endif