Skip to content

NXP imx95 add basic pm support #91410

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
13 changes: 7 additions & 6 deletions drivers/firmware/scmi/clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <zephyr/drivers/firmware/scmi/clk.h>
#include <string.h>
#include <zephyr/kernel.h>

/* TODO: if extended attributes are supported this should be moved
* to the header file so that users will have access to it.
Expand Down Expand Up @@ -57,7 +58,7 @@ int scmi_clock_rate_get(struct scmi_protocol *proto,
reply.len = sizeof(reply_buffer);
reply.content = &reply_buffer;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down Expand Up @@ -98,7 +99,7 @@ int scmi_clock_rate_set(struct scmi_protocol *proto, struct scmi_clock_rate_conf
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down Expand Up @@ -134,7 +135,7 @@ int scmi_clock_parent_get(struct scmi_protocol *proto, uint32_t clk_id, uint32_t
reply.len = sizeof(reply_buffer);
reply.content = &reply_buffer;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down Expand Up @@ -172,7 +173,7 @@ int scmi_clock_parent_set(struct scmi_protocol *proto, uint32_t clk_id, uint32_t
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down Expand Up @@ -223,7 +224,7 @@ int scmi_clock_config_set(struct scmi_protocol *proto,
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down Expand Up @@ -260,7 +261,7 @@ int scmi_clock_protocol_attributes(struct scmi_protocol *proto, uint32_t *attrib
reply.len = sizeof(reply_buffer);
reply.content = &reply_buffer;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down
28 changes: 26 additions & 2 deletions drivers/firmware/scmi/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/drivers/firmware/scmi/transport.h>
#include <zephyr/logging/log.h>
#include <zephyr/device.h>
#include "mailbox.h"

LOG_MODULE_REGISTER(scmi_core);

Expand Down Expand Up @@ -87,12 +88,34 @@ static int scmi_core_setup_chan(const struct device *transport,
return 0;
}

static int scmi_interrupt_enable(struct scmi_channel *chan, bool enable)
{
struct scmi_mbox_channel *mbox_chan;
struct mbox_dt_spec *tx_reply;
bool compInt;

mbox_chan = chan->data;
compInt = enable ? SCMI_SHMEM_CHAN_FLAG_IRQ_BIT : 0;

if (mbox_chan->tx_reply.dev) {
tx_reply = &mbox_chan->tx_reply;
} else {
tx_reply = &mbox_chan->tx;
}

/* re-set completion interrupt */
scmi_shmem_update_flags(mbox_chan->shmem, SCMI_SHMEM_CHAN_FLAG_IRQ_BIT, compInt);

return mbox_set_enabled_dt(tx_reply, enable);
}

static int scmi_send_message_pre_kernel(struct scmi_protocol *proto,
struct scmi_message *msg,
struct scmi_message *reply)
{
int ret;

scmi_interrupt_enable(proto->tx, false);
ret = scmi_transport_send_message(proto->transport, proto->tx, msg);
if (ret < 0) {
return ret;
Expand All @@ -113,6 +136,7 @@ static int scmi_send_message_pre_kernel(struct scmi_protocol *proto,
return ret;
}

scmi_interrupt_enable(proto->tx, true);
return ret;
}

Expand Down Expand Up @@ -159,7 +183,7 @@ static int scmi_send_message_post_kernel(struct scmi_protocol *proto,
}

int scmi_send_message(struct scmi_protocol *proto, struct scmi_message *msg,
struct scmi_message *reply)
struct scmi_message *reply, bool pre_kernel)
{
if (!proto->tx) {
return -ENODEV;
Expand All @@ -169,7 +193,7 @@ int scmi_send_message(struct scmi_protocol *proto, struct scmi_message *msg,
return -EINVAL;
}

if (k_is_pre_kernel()) {
if (pre_kernel) {
return scmi_send_message_pre_kernel(proto, msg, reply);
} else {
return scmi_send_message_post_kernel(proto, msg, reply);
Expand Down
39 changes: 38 additions & 1 deletion drivers/firmware/scmi/nxp/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <string.h>
#include <zephyr/drivers/firmware/scmi/nxp/cpu.h>
#include <zephyr/kernel.h>

DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, nxp_scmi_cpu), NULL);

Expand Down Expand Up @@ -33,7 +34,43 @@ int scmi_cpu_sleep_mode_set(struct scmi_cpu_sleep_mode_config *cfg)
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, true);
if (ret < 0) {
return ret;
}

if (status != SCMI_SUCCESS) {
return scmi_status_to_errno(status);
}

return 0;
}

int scmi_cpu_pd_lpm_set(struct scmi_cpu_pd_lpm_config *cfg)
{
struct scmi_protocol *proto = &SCMI_PROTOCOL_NAME(SCMI_PROTOCOL_CPU_DOMAIN);
struct scmi_message msg, reply;
int status, ret;

/* sanity checks */
if (!proto || !cfg) {
return -EINVAL;
}

if (proto->id != SCMI_PROTOCOL_CPU_DOMAIN) {
return -EINVAL;
}

msg.hdr = SCMI_MESSAGE_HDR_MAKE(SCMI_CPU_DOMAIN_MSG_CPU_PD_LPM_CONFIG_SET, SCMI_COMMAND,
proto->id, 0x0);
msg.len = sizeof(*cfg);
msg.content = cfg;

reply.hdr = msg.hdr;
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply, true);
if (ret < 0) {
return ret;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/firmware/scmi/pinctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <zephyr/drivers/firmware/scmi/pinctrl.h>
#include <zephyr/kernel.h>

DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, arm_scmi_pinctrl), NULL);

Expand Down Expand Up @@ -50,7 +51,7 @@ int scmi_pinctrl_settings_configure(struct scmi_pinctrl_settings *settings)
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/firmware/scmi/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <zephyr/drivers/firmware/scmi/power.h>
#include <string.h>
#include <zephyr/kernel.h>

DT_SCMI_PROTOCOL_DEFINE_NODEV(DT_INST(0, arm_scmi_power), NULL);

Expand Down Expand Up @@ -39,7 +40,7 @@ int scmi_power_state_get(uint32_t domain_id, uint32_t *power_state)
reply.len = sizeof(reply_buffer);
reply.content = &reply_buffer;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down Expand Up @@ -82,7 +83,7 @@ int scmi_power_state_set(struct scmi_power_state_config *cfg)
reply.len = sizeof(status);
reply.content = &status;

ret = scmi_send_message(proto, &msg, &reply);
ret = scmi_send_message(proto, &msg, &reply, k_is_pre_kernel());
if (ret < 0) {
return ret;
}
Expand Down
27 changes: 26 additions & 1 deletion dts/arm/nxp/nxp_imx95_m7.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
#address-cells = <1>;
#size-cells = <0>;

cpu@0 {
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-m7";
cpu-power-states = <&wait &stop &suspend>;
reg = <0>;

#address-cells = <1>;
Expand All @@ -27,6 +28,30 @@
compatible = "arm,armv7m-mpu";
reg = <0xe000ed90 0x40>;
};

};

power-states {
wait: power-state-wait {
compatible = "zephyr,power-state";
power-state-name = "runtime-idle";
min-residency-us = <100>;
exit-latency-us = <50>;
};

stop: power-state-stop {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
min-residency-us = <1000>;
exit-latency-us = <200>;
};

suspend: power-state-suspend {
compatible = "zephyr,power-state";
power-state-name = "standby";
min-residency-us = <5000>;
exit-latency-us = <1000>;
};
};
};

Expand Down
29 changes: 29 additions & 0 deletions include/zephyr/drivers/firmware/scmi/nxp/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#define SCMI_PROTOCOL_CPU_DOMAIN 130

#define SCMI_CPU_MAX_PDCONFIGS_T 7U

/**
* @struct scmi_cpu_sleep_mode_config
*
Expand All @@ -33,6 +35,23 @@ struct scmi_cpu_sleep_mode_config {
uint32_t sleep_mode;
};

struct scmi_pd_lpm_settings {
uint32_t domainId;
uint32_t lpmSetting;
uint32_t retMask;
};

/**
* @struct scmi_cpu_pd_lpm_config
*
* @brief Describes cpu power domain low power mode setting
*/
struct scmi_cpu_pd_lpm_config {
uint32_t cpu_id;
uint32_t num_cfg;
struct scmi_pd_lpm_settings cfgs[SCMI_CPU_MAX_PDCONFIGS_T];
};

/**
* @brief CPU domain protocol command message IDs
*/
Expand Down Expand Up @@ -64,4 +83,14 @@ enum scmi_cpu_domain_message {
*/
int scmi_cpu_sleep_mode_set(struct scmi_cpu_sleep_mode_config *cfg);

/**
* @brief Send the SCMI_CPU_DOMAIN_MSG_CPU_PD_LPM_CONFIG_SET command and get its reply
*
* @param cfg pointer to structure containing configuration
* to be set
*
* @retval 0 if successful
* @retval negative errno if failure
*/
int scmi_cpu_pd_lpm_set(struct scmi_cpu_pd_lpm_config *cfg);
#endif /* _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_CPU_H_ */
4 changes: 3 additions & 1 deletion include/zephyr/drivers/firmware/scmi/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ int scmi_status_to_errno(int scmi_status);
*
* @retval 0 if successful
* @retval negative errno if failure
* @param pre_kernel current kernel state
*/
int scmi_send_message(struct scmi_protocol *proto,
struct scmi_message *msg, struct scmi_message *reply);
struct scmi_message *msg, struct scmi_message *reply,
bool pre_kernel);

#endif /* _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_PROTOCOL_H_ */
1 change: 1 addition & 0 deletions soc/nxp/imx/imx9/imx95/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ config SOC_MIMX9596_M7
select SOC_LATE_INIT_HOOK
select HAS_MCUX
select HAS_MCUX_CACHE
select HAS_PM

config SOC_MIMX9596_A55
select ARM64
Expand Down
6 changes: 6 additions & 0 deletions soc/nxp/imx/imx9/imx95/Kconfig.defconfig.mimx95.m7
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,11 @@ config CACHE_MANAGEMENT

config ETH_NXP_IMX_MSGINTR
default 2
if PM
# PM code that runs from the idle loop has a large
# footprint. Hence increase the size when PM is enabled.
config IDLE_STACK_SIZE
default 640
endif

endif # SOC_MIMX9596_M7
Loading