Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 Intel Corporation. |
| 3 | * Copyright (c) 2021 Nordic Semiconductor ASA |
| 4 | * |
| 5 | * SPDX-License-Identifier: Apache-2.0 |
| 6 | */ |
| 7 | |
Gerard Marull-Paretas | 5113c14 | 2022-05-06 11:12:04 +0200 | [diff] [blame] | 8 | #include <zephyr/pm/state.h> |
| 9 | #include <zephyr/toolchain.h> |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 10 | |
Gerard Marull-Paretas | 7eb50be | 2021-12-21 11:38:12 +0100 | [diff] [blame] | 11 | BUILD_ASSERT(DT_NODE_EXISTS(DT_PATH(cpus)), |
| 12 | "cpus node not defined in Devicetree"); |
| 13 | |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 14 | /** |
| 15 | * Check CPU power state consistency. |
| 16 | * |
| 17 | * @param i Power state index. |
| 18 | * @param node_id CPU node identifier. |
| 19 | */ |
| 20 | #define CHECK_POWER_STATE_CONSISTENCY(i, node_id) \ |
| 21 | BUILD_ASSERT( \ |
| 22 | DT_PROP_BY_PHANDLE_IDX_OR(node_id, cpu_power_states, i, \ |
| 23 | min_residency_us, 0U) >= \ |
| 24 | DT_PROP_BY_PHANDLE_IDX_OR(node_id, cpu_power_states, i, \ |
| 25 | exit_latency_us, 0U), \ |
Krzysztof Chruscinski | 47ae656 | 2022-02-28 14:06:36 +0100 | [diff] [blame] | 26 | "Found CPU power state with min_residency < exit_latency") |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 27 | |
| 28 | /** |
| 29 | * @brief Check CPU power states consistency |
| 30 | * |
| 31 | * All states should have a minimum residency >= than the exit latency. |
| 32 | * |
| 33 | * @param node_id A CPU node identifier. |
| 34 | */ |
| 35 | #define CHECK_POWER_STATES_CONSISTENCY(node_id) \ |
Gerard Marull-Paretas | a05371d | 2023-07-25 11:43:52 +0200 | [diff] [blame] | 36 | LISTIFY(DT_PROP_LEN_OR(node_id, cpu_power_states, 0), \ |
Krzysztof Chruscinski | 47ae656 | 2022-02-28 14:06:36 +0100 | [diff] [blame] | 37 | CHECK_POWER_STATE_CONSISTENCY, (;), node_id); \ |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 38 | |
| 39 | /* Check that all power states are consistent */ |
Gerard Marull-Paretas | 7eb50be | 2021-12-21 11:38:12 +0100 | [diff] [blame] | 40 | DT_FOREACH_CHILD(DT_PATH(cpus), CHECK_POWER_STATES_CONSISTENCY) |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 41 | |
Andy Ross | 0c30db1 | 2022-01-27 11:07:49 -0800 | [diff] [blame] | 42 | #define DEFINE_CPU_STATES(n) \ |
| 43 | static const struct pm_state_info pmstates_##n[] \ |
| 44 | = PM_STATE_INFO_LIST_FROM_DT_CPU(n); |
Gerard Marull-Paretas | 2e0899e | 2022-07-06 14:57:06 +0200 | [diff] [blame] | 45 | #define CPU_STATE_REF(n) pmstates_##n |
Andy Ross | 0c30db1 | 2022-01-27 11:07:49 -0800 | [diff] [blame] | 46 | |
| 47 | DT_FOREACH_CHILD(DT_PATH(cpus), DEFINE_CPU_STATES); |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 48 | |
| 49 | /** CPU power states information for each CPU */ |
| 50 | static const struct pm_state_info *cpus_states[] = { |
Gerard Marull-Paretas | a05371d | 2023-07-25 11:43:52 +0200 | [diff] [blame] | 51 | DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), CPU_STATE_REF, (,)) |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 52 | }; |
| 53 | |
| 54 | /** Number of states for each CPU */ |
| 55 | static const uint8_t states_per_cpu[] = { |
Gerard Marull-Paretas | a05371d | 2023-07-25 11:43:52 +0200 | [diff] [blame] | 56 | DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_NUM_CPU_POWER_STATES, (,)) |
Gerard Marull-Paretas | 8385d1b | 2021-12-20 15:25:19 +0100 | [diff] [blame] | 57 | }; |
| 58 | |
| 59 | uint8_t pm_state_cpu_get_all(uint8_t cpu, const struct pm_state_info **states) |
| 60 | { |
| 61 | if (cpu >= ARRAY_SIZE(cpus_states)) { |
| 62 | return 0; |
| 63 | } |
| 64 | |
| 65 | *states = cpus_states[cpu]; |
| 66 | |
| 67 | return states_per_cpu[cpu]; |
| 68 | } |