mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
interconnect: qcom: Add sync_state for QNOC
Add sync_state functionality to remove threshold held during initial boot up and clean up any linger proxy resources that were voted for from bootloaders. Change-Id: Ib2fe3f3e54775b85c3ee8107c9aafdcd32841017 Signed-off-by: David Dai <daidavid1@codeaurora.org> Signed-off-by: Mike Tipton <mdtipton@codeaurora.org>
This commit is contained in:
parent
9787cfc9b5
commit
0a20a2a4e7
|
|
@ -28,6 +28,7 @@ static DEFINE_MUTEX(bcm_voter_lock);
|
|||
* @ws_list: list containing bcms that have different wake/sleep votes
|
||||
* @voter_node: list of bcm voters
|
||||
* @tcs_wait: mask for which buckets require TCS completion
|
||||
* @init: flag to determine when init has completed.
|
||||
*/
|
||||
struct bcm_voter {
|
||||
struct device *dev;
|
||||
|
|
@ -37,6 +38,7 @@ struct bcm_voter {
|
|||
struct list_head ws_list;
|
||||
struct list_head voter_node;
|
||||
u32 tcs_wait;
|
||||
bool init;
|
||||
};
|
||||
|
||||
static int cmp_vcd(void *priv, const struct list_head *a, const struct list_head *b)
|
||||
|
|
@ -58,7 +60,7 @@ static u64 bcm_div(u64 num, u32 base)
|
|||
return num;
|
||||
}
|
||||
|
||||
static void bcm_aggregate(struct qcom_icc_bcm *bcm)
|
||||
static void bcm_aggregate(struct qcom_icc_bcm *bcm, bool init)
|
||||
{
|
||||
struct qcom_icc_node *node;
|
||||
size_t i, bucket;
|
||||
|
|
@ -86,10 +88,18 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm)
|
|||
}
|
||||
|
||||
if (bcm->keepalive) {
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 16000;
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 16000;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 16000;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 16000;
|
||||
if (init) {
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 16000;
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 16000;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 16000;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 16000;
|
||||
} else if (bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 &&
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_AMC] == 0) {
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1;
|
||||
bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1;
|
||||
bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,7 +265,7 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
|
|||
|
||||
mutex_lock(&voter->lock);
|
||||
list_for_each_entry(bcm, &voter->commit_list, list)
|
||||
bcm_aggregate(bcm);
|
||||
bcm_aggregate(bcm, voter->init);
|
||||
|
||||
/*
|
||||
* Pre sort the BCMs based on VCD for ease of generating a command list
|
||||
|
|
@ -332,6 +342,21 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_bcm_voter_commit);
|
||||
|
||||
/**
|
||||
* qcom_icc_bcm_voter_clear_init - clear init flag used during boot up
|
||||
* @voter: voter that we need to clear the init flag for
|
||||
*/
|
||||
void qcom_icc_bcm_voter_clear_init(struct bcm_voter *voter)
|
||||
{
|
||||
if (!voter)
|
||||
return;
|
||||
|
||||
mutex_lock(&voter->lock);
|
||||
voter->init = false;
|
||||
mutex_unlock(&voter->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_bcm_voter_clear_init);
|
||||
|
||||
static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
|
@ -343,6 +368,7 @@ static int qcom_icc_bcm_voter_probe(struct platform_device *pdev)
|
|||
|
||||
voter->dev = &pdev->dev;
|
||||
voter->np = np;
|
||||
voter->init = true;
|
||||
|
||||
if (of_property_read_u32(np, "qcom,tcs-wait", &voter->tcs_wait))
|
||||
voter->tcs_wait = QCOM_ICC_TAG_ACTIVE_ONLY;
|
||||
|
|
|
|||
|
|
@ -23,5 +23,6 @@ static struct qcom_icc_bcm _name = { \
|
|||
struct bcm_voter *of_bcm_voter_get(struct device *dev, const char *name);
|
||||
void qcom_icc_bcm_voter_add(struct bcm_voter *voter, struct qcom_icc_bcm *bcm);
|
||||
int qcom_icc_bcm_voter_commit(struct bcm_voter *voter);
|
||||
void qcom_icc_bcm_voter_clear_init(struct bcm_voter *voter);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,12 +7,16 @@
|
|||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "bcm-voter.h"
|
||||
#include "icc-rpmh.h"
|
||||
|
||||
static LIST_HEAD(qnoc_probe_list);
|
||||
static DEFINE_MUTEX(probe_list_lock);
|
||||
|
||||
/**
|
||||
* qcom_icc_pre_aggregate - cleans up stale values from prior icc_set
|
||||
* @node: icc node to operate on
|
||||
|
|
@ -258,6 +262,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
|
|||
data->num_nodes = num_nodes;
|
||||
platform_set_drvdata(pdev, qp);
|
||||
|
||||
mutex_lock(&probe_list_lock);
|
||||
list_add_tail(&qp->probe_list, &qnoc_probe_list);
|
||||
mutex_unlock(&probe_list_lock);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
icc_nodes_remove(provider);
|
||||
|
|
@ -275,4 +283,46 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_icc_rpmh_remove);
|
||||
|
||||
void qcom_icc_rpmh_sync_state(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
const struct of_device_id *oft = dev->driver->of_match_table;
|
||||
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
|
||||
struct qcom_icc_bcm *bcm;
|
||||
struct bcm_voter *voter;
|
||||
static int probe_count;
|
||||
int num_providers;
|
||||
|
||||
for (num_providers = 0; oft[num_providers].data; num_providers++)
|
||||
;
|
||||
|
||||
mutex_lock(&probe_list_lock);
|
||||
probe_count++;
|
||||
|
||||
if (probe_count < num_providers) {
|
||||
mutex_unlock(&probe_list_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(qp, &qnoc_probe_list, probe_list) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < qp->num_voters; i++)
|
||||
qcom_icc_bcm_voter_clear_init(qp->voters[i]);
|
||||
|
||||
for (i = 0; i < qp->num_bcms; i++) {
|
||||
bcm = qp->bcms[i];
|
||||
if (!bcm->keepalive)
|
||||
continue;
|
||||
|
||||
voter = qp->voters[bcm->voter_idx];
|
||||
qcom_icc_bcm_voter_add(voter, bcm);
|
||||
qcom_icc_bcm_voter_commit(voter);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&probe_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_icc_rpmh_sync_state);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ struct qcom_icc_provider {
|
|||
struct qcom_icc_bcm **bcms;
|
||||
size_t num_bcms;
|
||||
struct bcm_voter *voter;
|
||||
struct list_head probe_list;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -136,5 +137,5 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev);
|
|||
void qcom_icc_pre_aggregate(struct icc_node *node);
|
||||
int qcom_icc_rpmh_probe(struct platform_device *pdev);
|
||||
int qcom_icc_rpmh_remove(struct platform_device *pdev);
|
||||
|
||||
void qcom_icc_rpmh_sync_state(struct device *dev);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user