Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b428d5b9 authored by Lina Iyer's avatar Lina Iyer Committed by Mahesh Sivasubramanian
Browse files

drivers: qcom: system_pm: read CVAL to program PDC wake up



The PDC wakeup value must be equal or earlier than the QTimer value that
is set to wake up the system. This is to ensure that the PDC system is
awake before the timer. Read the CVAL from the timer and program the PDC
wakeup value.

Ensure the PDC value is updated after calling tick_broadcast_enter().

Change-Id: I291fd2dd80bed4de19119c548d985ace2ad0c070
Signed-off-by: default avatarLina Iyer <ilina@codeaurora.org>
parent 3c865ca8
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -1020,18 +1020,10 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx,
	}

	if (level->notify_rpm) {
		uint64_t us;
		uint32_t pred_us;

		us = get_cluster_sleep_time(cluster, NULL, from_idle,
								&pred_us);

		us = us + 1;

		clear_predict_history();
		clear_cl_predict_history();

		system_sleep_enter(us);
		if (system_sleep_enter())
			return -EBUSY;
	}
	/* Notify cluster enter event after successfully config completion */
	cluster_notify(cluster, level, true);
@@ -1237,6 +1229,13 @@ int get_cluster_id(struct lpm_cluster *cluster, int *aff_lvl)
		state_id |= (level->psci_id & cluster->psci_mode_mask)
					<< cluster->psci_mode_shift;
		(*aff_lvl)++;

		/*
		 * We may have updated the broadcast timers, update
		 * the wakeup value by reading the bc timer directly.
		 */
		if (level->notify_rpm)
			system_sleep_update_wakeup();
	}
unlock_and_return:
	spin_unlock(&cluster->sync_lock);
+20 −28
Original line number Diff line number Diff line
@@ -17,23 +17,35 @@
#include <soc/qcom/rpmh.h>
#include <soc/qcom/system_pm.h>

#define ARCH_TIMER_HZ		(19200000UL)
#include <clocksource/arm_arch_timer.h>

#define PDC_TIME_VALID_SHIFT	31
#define PDC_TIME_UPPER_MASK	0xFFFFFF

static struct rpmh_client *rpmh_client;

static int setup_wakeup(uint64_t sleep_val)
static int setup_wakeup(uint32_t lo, uint32_t hi)
{
	struct tcs_cmd cmd[2] = { { 0 } };

	cmd[0].data = (sleep_val >> 32) & PDC_TIME_UPPER_MASK;
	cmd[0].data =  hi & PDC_TIME_UPPER_MASK;
	cmd[0].data |= 1 << PDC_TIME_VALID_SHIFT;
	cmd[1].data = sleep_val & 0xFFFFFFFF;
	cmd[1].data = lo;

	return rpmh_write_control(rpmh_client, cmd, ARRAY_SIZE(cmd));
}

int system_sleep_update_wakeup(void)
{
	uint32_t lo = ~0U, hi = ~0U;

	/* Read the hardware to get the most accurate value */
	arch_timer_mem_get_cval(&lo, &hi);

	return setup_wakeup(lo, hi);
}
EXPORT_SYMBOL(system_sleep_update_wakeup);

/**
 * system_sleep_allowed() - Returns if its okay to enter system low power modes
 */
@@ -46,35 +58,15 @@ EXPORT_SYMBOL(system_sleep_allowed);
/**
 * system_sleep_enter() - Activties done when entering system low power modes
 *
 * @sleep_val: The sleep duration in us.
 *
 * Returns 0 for success or error values from writing the timer value in the
 * hardware block.
 * Returns 0 for success or error values from writing the sleep/wake values to
 * the hardware block.
 */
int system_sleep_enter(uint64_t sleep_val)
int system_sleep_enter(void)
{
	int ret;

	if (IS_ERR_OR_NULL(rpmh_client))
		return -EFAULT;

	ret = rpmh_flush(rpmh_client);
	if (ret)
		return ret;

	/*
	 * Set up the wake up value offset from the current time.
	 * Convert us to ns to allow div by 19.2 Mhz tick timer.
	 */
	if (sleep_val) {
		sleep_val *= NSEC_PER_USEC;
		do_div(sleep_val, NSEC_PER_SEC/ARCH_TIMER_HZ);
		sleep_val += arch_counter_get_cntvct();
	} else {
		sleep_val = ~0ULL;
	}

	return setup_wakeup(sleep_val);
	return rpmh_flush(rpmh_client);
}
EXPORT_SYMBOL(system_sleep_enter);

+7 −2
Original line number Diff line number Diff line
@@ -14,13 +14,15 @@
#define __SOC_QCOM_SYS_PM_H__

#ifdef CONFIG_QTI_SYSTEM_PM
int system_sleep_enter(uint64_t sleep_val);
int system_sleep_enter(void);

void system_sleep_exit(void);

bool system_sleep_allowed(void);

int system_sleep_update_wakeup(void);
#else
static inline int system_sleep_enter(uint64_t sleep_val)
static inline int system_sleep_enter(void)
{ return -ENODEV; }

static inline void system_sleep_exit(void)
@@ -29,6 +31,9 @@ static inline void system_sleep_exit(void)
static inline bool system_sleep_allowed(void)
{ return false; }

static inline int system_sleep_update_wakeup(void)
{ return -ENODEV; }

#endif /* CONFIG_QTI_SYSTEM_PM */

#endif /* __SOC_QCOM_SYS_PM_H__ */