Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rw6xx: Add Support for Standby Power Mode #84945

Merged
merged 14 commits into from
Mar 21, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 93 additions & 5 deletions drivers/serial/uart_mcux_flexcomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/pm/policy.h>
#include <zephyr/irq.h>
#include <zephyr/pm/device.h>
#include <fsl_usart.h>
#include <soc.h>
#include <fsl_device_registers.h>
Expand Down Expand Up @@ -86,8 +88,33 @@ struct mcux_flexcomm_data {
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
struct uart_config uart_config;
#endif
#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
bool pm_policy_state_lock;
#endif
};

#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
static void mcux_flexcomm_pm_policy_state_lock_get(const struct device *dev)
{
struct mcux_flexcomm_data *data = dev->data;

if (!data->pm_policy_state_lock) {
data->pm_policy_state_lock = true;
pm_policy_device_power_lock_get(dev);
}
}

static void mcux_flexcomm_pm_policy_state_lock_put(const struct device *dev)
{
struct mcux_flexcomm_data *data = dev->data;

if (data->pm_policy_state_lock) {
data->pm_policy_state_lock = false;
pm_policy_device_power_lock_put(dev);
}
}
#endif

static int mcux_flexcomm_poll_in(const struct device *dev, unsigned char *c)
{
const struct mcux_flexcomm_config *config = dev->config;
Expand Down Expand Up @@ -179,6 +206,14 @@ static void mcux_flexcomm_irq_tx_enable(const struct device *dev)
const struct mcux_flexcomm_config *config = dev->config;
uint32_t mask = kUSART_TxLevelInterruptEnable;

/* Indicates that this device started a transaction that should
* not be interrupted by putting the SoC in states that would
* interfere with this transfer.
*/
#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
mcux_flexcomm_pm_policy_state_lock_get(dev);
#endif

USART_EnableInterrupts(config->base, mask);
}

Expand All @@ -187,6 +222,10 @@ static void mcux_flexcomm_irq_tx_disable(const struct device *dev)
const struct mcux_flexcomm_config *config = dev->config;
uint32_t mask = kUSART_TxLevelInterruptEnable;

#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
mcux_flexcomm_pm_policy_state_lock_put(dev);
#endif

USART_DisableInterrupts(config->base, mask);
}

Expand Down Expand Up @@ -467,11 +506,19 @@ static int mcux_flexcomm_uart_tx(const struct device *dev, const uint8_t *buf,
/* Enable TX DMA requests */
USART_EnableTxDMA(config->base, true);

/* Do not allow the system to suspend until the transmission has completed */
#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
mcux_flexcomm_pm_policy_state_lock_get(dev);
#endif

/* Trigger the DMA to start transfer */
ret = dma_start(config->tx_dma.dev, config->tx_dma.channel);
if (ret) {
irq_unlock(key);
return ret;
#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
mcux_flexcomm_pm_policy_state_lock_put(dev);
#endif
return ret;
}

/* Schedule a TX abort for @param timeout */
Expand Down Expand Up @@ -993,15 +1040,18 @@ static void mcux_flexcomm_isr(const struct device *dev)
data->tx_data.xfer_buf = NULL;

async_user_callback(dev, &tx_done_event);

#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
mcux_flexcomm_pm_policy_state_lock_put(dev);
#endif
}

}
#endif /* CONFIG_UART_ASYNC_API */
}
#endif /* CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT */


static int mcux_flexcomm_init(const struct device *dev)
static int mcux_flexcomm_init_common(const struct device *dev)
{
const struct mcux_flexcomm_config *config = dev->config;
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
Expand Down Expand Up @@ -1067,6 +1117,42 @@ static int mcux_flexcomm_init(const struct device *dev)
return 0;
}

static uint32_t usart_intenset;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is not used outside the scope of mcux_flexcomm_pm_action, move it inside, also does not need to be static

static int mcux_flexcomm_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct mcux_flexcomm_config *config = dev->config;

usart_intenset = USART_GetEnabledInterrupts(config->base);

switch (action) {
case PM_DEVICE_ACTION_RESUME:
break;
case PM_DEVICE_ACTION_SUSPEND:
break;
case PM_DEVICE_ACTION_TURN_OFF:
break;
case PM_DEVICE_ACTION_TURN_ON:
int ret = mcux_flexcomm_init_common(dev);

if (ret) {
return ret;
}
USART_EnableInterrupts(config->base, usart_intenset);
break;
default:
return -ENOTSUP;
}
return 0;
}

static int mcux_flexcomm_init(const struct device *dev)
{
/* Rest of the init is done from the PM_DEVICE_TURN_ON action
* which is invoked by pm_device_driver_init().
*/
return pm_device_driver_init(dev, mcux_flexcomm_pm_action);
}

static DEVICE_API(uart, mcux_flexcomm_driver_api) = {
.poll_in = mcux_flexcomm_poll_in,
.poll_out = mcux_flexcomm_poll_out,
Expand Down Expand Up @@ -1202,9 +1288,11 @@ static const struct mcux_flexcomm_config mcux_flexcomm_##n##_config = { \
\
static const struct mcux_flexcomm_config mcux_flexcomm_##n##_config; \
\
PM_DEVICE_DT_INST_DEFINE(n, mcux_flexcomm_pm_action); \
\
DEVICE_DT_INST_DEFINE(n, \
mcux_flexcomm_init, \
NULL, \
&mcux_flexcomm_init, \
PM_DEVICE_DT_INST_GET(n), \
&mcux_flexcomm_##n##_data, \
&mcux_flexcomm_##n##_config, \
PRE_KERNEL_1, \
Expand Down
5 changes: 5 additions & 0 deletions dts/arm/nxp/nxp_rw6xx_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@
resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>;
dmas = <&dma0 0>, <&dma0 1>;
dma-names = "rx", "tx";
zephyr,disabling-power-states = <&suspend>;
status = "disabled";
};

Expand All @@ -236,6 +237,7 @@
resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>;
dmas = <&dma0 2>, <&dma0 3>;
dma-names = "rx", "tx";
zephyr,disabling-power-states = <&suspend>;
status = "disabled";
};

Expand All @@ -247,6 +249,7 @@
resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>;
dmas = <&dma0 4>, <&dma0 5>;
dma-names = "rx", "tx";
zephyr,disabling-power-states = <&suspend>;
status = "disabled";
};

Expand All @@ -258,6 +261,7 @@
resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>;
dmas = <&dma0 6>, <&dma0 7>;
dma-names = "rx", "tx";
zephyr,disabling-power-states = <&suspend>;
status = "disabled";
};

Expand All @@ -269,6 +273,7 @@
resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>;
dmas = <&dma0 26>, <&dma0 27>;
dma-names = "rx", "tx";
zephyr,disabling-power-states = <&suspend>;
status = "disabled";
};

Expand Down