Commit 5ff676f9 authored by Derek Snell's avatar Derek Snell Committed by Benjamin Cabé
Browse files

drivers: i2c_mcux_flexcomm: adds PM TURN_ON low-power recovery support

Enables Sleep mode (PM3) in RW61x.

Signed-off-by: default avatarDerek Snell <derek.snell@nxp.com>
parent b41806ba
Loading
Loading
Loading
Loading
+45 −5
Changes for drivers/i2c/i2c_mcux_flexcomm.c: 45 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ LOG_MODULE_REGISTER(mcux_flexcomm);

#include "i2c-priv.h"

#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>

#define I2C_TRANSFER_TIMEOUT_MSEC                                                                  \
	COND_CODE_0(CONFIG_I2C_NXP_TRANSFER_TIMEOUT, (K_FOREVER),                                  \
		    (K_MSEC(CONFIG_I2C_NXP_TRANSFER_TIMEOUT)))
@@ -154,6 +157,10 @@ static int mcux_flexcomm_transfer(const struct device *dev,

	k_sem_take(&data->lock, K_FOREVER);

#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
	pm_policy_device_power_lock_get(dev);
#endif

	/* Iterate over all the messages */
	for (int i = 0; i < num_msgs; i++) {
		if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
@@ -208,6 +215,10 @@ static int mcux_flexcomm_transfer(const struct device *dev,
		msgs++;
	}

#ifdef CONFIG_PM_POLICY_DEVICE_CONSTRAINTS
	pm_policy_device_power_lock_put(dev);
#endif

	k_sem_give(&data->lock);

	return ret;
@@ -555,7 +566,7 @@ static void mcux_flexcomm_isr(const struct device *dev)
	I2C_MasterTransferHandleIRQ(base, &data->handle);
}

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;
	struct mcux_flexcomm_data *data = dev->data;
@@ -579,9 +590,6 @@ static int mcux_flexcomm_init(const struct device *dev)
		return error;
	}

	k_sem_init(&data->lock, 1, 1);
	k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);

	if (!device_is_ready(config->clock_dev)) {
		LOG_ERR("clock control device not ready");
		return -ENODEV;
@@ -611,6 +619,37 @@ static int mcux_flexcomm_init(const struct device *dev)
	return 0;
}

static int i2c_mcux_flexcomm_pm_action(const struct device *dev, enum pm_device_action action)
{
	switch (action) {
	case PM_DEVICE_ACTION_RESUME:
		break;
	case PM_DEVICE_ACTION_SUSPEND:
		break;
	case PM_DEVICE_ACTION_TURN_OFF:
		return 0;
	case PM_DEVICE_ACTION_TURN_ON:
		mcux_flexcomm_init_common(dev);
		return 0;
	default:
		return -ENOTSUP;
	}
	return 0;
}

static int mcux_flexcomm_init(const struct device *dev)
{
	struct mcux_flexcomm_data *data = dev->data;

	k_sem_init(&data->lock, 1, 1);
	k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);

	/* 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, i2c_mcux_flexcomm_pm_action);
}

static DEVICE_API(i2c, mcux_flexcomm_driver_api) = {
	.configure = mcux_flexcomm_configure,
	.transfer = mcux_flexcomm_transfer,
@@ -650,9 +689,10 @@ static DEVICE_API(i2c, mcux_flexcomm_driver_api) = {
		.reset = RESET_DT_SPEC_INST_GET(id),			\
	};								\
	static struct mcux_flexcomm_data mcux_flexcomm_data_##id;	\
	PM_DEVICE_DT_INST_DEFINE(id, i2c_mcux_flexcomm_pm_action);	\
	I2C_DEVICE_DT_INST_DEFINE(id,					\
			    mcux_flexcomm_init,				\
			    NULL,					\
			    PM_DEVICE_DT_INST_GET(id),			\
			    &mcux_flexcomm_data_##id,			\
			    &mcux_flexcomm_config_##id,			\
			    POST_KERNEL,				\