Commit 65e4add7 authored by Flavio Ceolin's avatar Flavio Ceolin Committed by Anas Nashif
Browse files

soc: cc13x2: Use residency policy



cc13x2_cc26x2 had its own power policy that was implementing the same
logic available in the default residency policy. Also, this policy was
unnecessarily setting up a timeout to wakeup the system. This is not
necessary, the power subsystem takes care of this.

Signed-off-by: default avatarFlavio Ceolin <flavio.ceolin@intel.com>
parent 05a7039a
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -99,14 +99,8 @@ void pm_power_state_set(struct pm_state_info info)
		break;

	case PM_STATE_STANDBY:
		/* schedule the wakeup event */
		ClockP_start(ClockP_handle((ClockP_Struct *)
			&PowerCC26X2_module.clockObj));

		/* go to standby mode */
		Power_sleep(PowerCC26XX_STANDBY);
		ClockP_stop(ClockP_handle((ClockP_Struct *)
			&PowerCC26X2_module.clockObj));
		break;
	case PM_STATE_SUSPEND_TO_RAM:
		__fallthrough;
+0 −1
Original line number Diff line number Diff line
@@ -2,4 +2,3 @@

zephyr_sources_ifdef(CONFIG_PM_POLICY_DUMMY policy_dummy.c)
zephyr_sources_ifdef(CONFIG_PM_POLICY_RESIDENCY_DEFAULT policy_residency.c)
zephyr_sources_ifdef(CONFIG_PM_POLICY_RESIDENCY_CC13X2_CC26X2 policy_residency_cc13x2_cc26x2.c)
+1 −7
Original line number Diff line number Diff line
@@ -7,8 +7,7 @@ choice

config PM_POLICY_RESIDENCY
	bool "PM Policy based on CPU residency"
	select PM_POLICY_RESIDENCY_DEFAULT if !SOC_SERIES_CC13X2_CC26X2
	select PM_POLICY_RESIDENCY_CC13X2_CC26X2 if SOC_SERIES_CC13X2_CC26X2
	select PM_POLICY_RESIDENCY_DEFAULT
	help
	  Select this option for PM policy based on CPU residencies.

@@ -28,8 +27,3 @@ config PM_POLICY_RESIDENCY_DEFAULT
	bool
	help
	  Use the default residency policy implementation

config PM_POLICY_RESIDENCY_CC13X2_CC26X2
	bool
	help
	  Use the residency policy implementation for TI CC13x2/CC26x2
+0 −139
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019 Linaro Limited.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <kernel.h>
#include <sys/__assert.h>
#include <pm/pm.h>
#include <pm/policy.h>

#include <ti/devices/cc13x2_cc26x2/driverlib/sys_ctrl.h>

#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26X2.h>

#include <ti/drivers/dpl/ClockP.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/dpl/SwiP.h>

#define LOG_LEVEL CONFIG_PM_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_DECLARE(power);

/* Wakeup delay from standby in microseconds */
#define WAKEDELAYSTANDBY    240

#define STATE_ACTIVE \
	(struct pm_state_info){PM_STATE_ACTIVE, 0, 0}


extern PowerCC26X2_ModuleState PowerCC26X2_module;

/* PM Policy based on SoC/Platform residency requirements */
static const struct pm_state_info residency_info[] =
	PM_STATE_INFO_DT_ITEMS_LIST(DT_NODELABEL(cpu0));

struct pm_state_info pm_policy_next_state(int32_t ticks)
{
	uint32_t constraints;
	bool disallowed = false;
	int i;

	/* check operating conditions, optimally choose DCDC versus GLDO */
	SysCtrl_DCDC_VoltageConditionalControl();

	/* query the declared constraints */
	constraints = Power_getConstraintMask();

	if ((ticks != K_TICKS_FOREVER) && (ticks <
		k_us_to_ticks_ceil32(residency_info[0].min_residency_us))) {
		LOG_DBG("Not enough time for PM operations: %d", ticks);
		return STATE_ACTIVE;
	}

	for (i = ARRAY_SIZE(residency_info) - 1; i >= 0; i--) {
		if (!pm_constraint_get(residency_info[i].state)) {
			continue;
		}

		if ((ticks <
		     k_us_to_ticks_ceil32(residency_info[i].min_residency_us))
		    && (ticks != K_TICKS_FOREVER)) {
			continue;
		}

		/* Verify if Power module has constraints set to
		 * disallow a state
		 */
		switch (residency_info[i].state) {
		case PM_STATE_SUSPEND_TO_IDLE: /* Idle mode */
			if ((constraints & (1 <<
					    PowerCC26XX_DISALLOW_IDLE)) != 0) {
				disallowed = true;
			}
			break;
		case PM_STATE_STANDBY: /* Standby mode */
			if ((constraints & (1 <<
					PowerCC26XX_DISALLOW_STANDBY)) != 0) {
				disallowed = true;
			}
			/* Set timeout for wakeup event */
			__ASSERT(
				residency_info[i].min_residency_us > 1000,
				"PM_STATE_STANDBY must be greater than 1000.");
			if (ticks != K_TICKS_FOREVER) {
				/* NOTE: Ideally we'd like to set a
				 * timer to wake up just a little
				 * earlier to take care of the wakeup
				 * sequence, ie. by WAKEDELAYSTANDBY
				 * microsecs. However, given
				 * k_timer_start (called later by
				 * ClockP_start) does not currently
				 * have sub-millisecond accuracy, wakeup
				 * would be at up to (WAKEDELAYSTANDBY
				 * + 1 ms) ahead of the next timeout.
				 * This also has the implication that
				 * PM_STATE_STANDBY
				 * must be greater than 1.
				 */
				ticks -= (WAKEDELAYSTANDBY *
					  CONFIG_SYS_CLOCK_TICKS_PER_SEC
					  + 1000000) / 1000000;
#if (CONFIG_SYS_CLOCK_TICKS_PER_SEC <= 1000)
				/*
				 * ClockP_setTimeout cannot handle any
				 * more ticks
				 */
				ticks = MIN(ticks, UINT32_MAX / 1000 *
					    CONFIG_SYS_CLOCK_TICKS_PER_SEC);
#endif
				ClockP_setTimeout(ClockP_handle(
						(ClockP_Struct *)
						&PowerCC26X2_module.clockObj),
						ticks);
			}
			break;
		default:
			/* This should never be reached */
			LOG_ERR("Invalid sleep state detected\n");
		}

		if (disallowed) {
			disallowed = false;
			continue;
		}

		LOG_DBG("Selected power state %d "
			"(ticks: %d, min_residency: %u)",
			residency_info[i].state, ticks,
			k_us_to_ticks_ceil32(
				residency_info[i].min_residency_us));
		return residency_info[i];
	}

	LOG_DBG("No suitable power state found!");
	return STATE_ACTIVE;
}