mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
soc: qcom: ddr_stats: Add API to get bandwidth vote on ddr
This change implements API to get bandwidth vote on DDR by various subsystem. Change-Id: I798fc6cf8e6035f6f5b54fa8d4f4650dc1a2b24e Signed-off-by: Tushar Nimkar <tnimkar@codeaurora.org>
This commit is contained in:
parent
c30dc7b7b1
commit
86f4115ac2
2 changed files with 90 additions and 1 deletions
|
|
@ -9,6 +9,8 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/mailbox/qmp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
|
|
@ -22,6 +24,12 @@
|
|||
#define MAGIC_KEY1 0xA1157A75
|
||||
#define MAX_NUM_MODES 0x14
|
||||
#define MSM_ARCH_TIMER_FREQ 19200000
|
||||
#define MAX_DRV 18
|
||||
#define MAX_MSG_LEN 35
|
||||
#define DRV_ABSENT 0xdeaddead
|
||||
#define DRV_INVALID 0xffffdead
|
||||
#define VOTE_MASK 0x3fff
|
||||
#define VOTE_X_SHIFT 14
|
||||
|
||||
#define GET_PDATA_OF_ATTR(attr) \
|
||||
(container_of(attr, struct ddr_stats_kobj_attr, ka)->pd)
|
||||
|
|
@ -41,7 +49,10 @@ struct ddr_stats_platform_data {
|
|||
void __iomem *reg;
|
||||
int freq_count;
|
||||
int entry_count;
|
||||
bool read_ddr_vote;
|
||||
struct mutex ddr_stats_lock;
|
||||
struct mbox_client stats_mbox_cl;
|
||||
struct mbox_chan *stats_mbox_ch;
|
||||
};
|
||||
|
||||
struct stats_entry {
|
||||
|
|
@ -199,6 +210,64 @@ int ddr_stats_get_residency(int freq_count, struct ddr_freq_residency *data)
|
|||
}
|
||||
EXPORT_SYMBOL(ddr_stats_get_residency);
|
||||
|
||||
int ddr_stats_get_ss_count(void)
|
||||
{
|
||||
return ddr_pdata->read_ddr_vote ? MAX_DRV : -EOPNOTSUPP;
|
||||
}
|
||||
EXPORT_SYMBOL(ddr_stats_get_ss_count);
|
||||
|
||||
int ddr_stats_get_ss_vote_info(int ss_count,
|
||||
struct ddr_stats_ss_vote_info *vote_info)
|
||||
{
|
||||
char buf[MAX_MSG_LEN] = {};
|
||||
struct qmp_pkt pkt;
|
||||
void __iomem *reg;
|
||||
u32 vote_offset, val[MAX_DRV];
|
||||
int ret, i;
|
||||
|
||||
if (!ddr_pdata->read_ddr_vote)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!vote_info || !(ss_count == MAX_DRV) || !ddr_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&ddr_pdata->ddr_stats_lock);
|
||||
ret = scnprintf(buf, MAX_MSG_LEN, "{class: ddr, res: drvs_ddr_votes}");
|
||||
pkt.size = (ret + 0x3) & ~0x3;
|
||||
pkt.data = buf;
|
||||
|
||||
ret = mbox_send_message(ddr_pdata->stats_mbox_ch, &pkt);
|
||||
if (ret < 0) {
|
||||
pr_err("Error sending mbox message: %d\n", ret);
|
||||
mutex_unlock(&ddr_pdata->ddr_stats_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vote_offset = sizeof(u32) + sizeof(u32) +
|
||||
(ddr_pdata->entry_count * sizeof(struct stats_entry));
|
||||
reg = ddr_pdata->reg;
|
||||
|
||||
for (i = 0; i < ss_count; i++, reg += sizeof(u32)) {
|
||||
val[i] = readl_relaxed(reg + vote_offset);
|
||||
if (val[i] == DRV_ABSENT) {
|
||||
vote_info[i].ab = DRV_ABSENT;
|
||||
vote_info[i].ib = DRV_ABSENT;
|
||||
continue;
|
||||
} else if (val[i] == DRV_INVALID) {
|
||||
vote_info[i].ab = DRV_INVALID;
|
||||
vote_info[i].ib = DRV_INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
vote_info[i].ab = (val[i] >> VOTE_X_SHIFT) & VOTE_MASK;
|
||||
vote_info[i].ib = val[i] & VOTE_MASK;
|
||||
}
|
||||
|
||||
mutex_unlock(&ddr_pdata->ddr_stats_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ddr_stats_get_ss_vote_info);
|
||||
|
||||
static ssize_t ddr_stats_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -312,6 +381,16 @@ static int ddr_stats_probe(struct platform_device *pdev)
|
|||
reg += sizeof(struct stats_entry);
|
||||
}
|
||||
|
||||
ddr_pdata->stats_mbox_cl.dev = &pdev->dev;
|
||||
ddr_pdata->stats_mbox_cl.tx_block = true;
|
||||
ddr_pdata->stats_mbox_cl.tx_tout = 1000;
|
||||
ddr_pdata->stats_mbox_cl.knows_txdone = false;
|
||||
|
||||
ddr_pdata->read_ddr_vote = true;
|
||||
ddr_pdata->stats_mbox_ch = mbox_request_channel(&ddr_pdata->stats_mbox_cl, 0);
|
||||
if (IS_ERR(ddr_pdata->stats_mbox_ch))
|
||||
ddr_pdata->read_ddr_vote = false;
|
||||
|
||||
return ddr_stats_create_sysfs(pdev, ddr_pdata);
|
||||
}
|
||||
|
||||
|
|
@ -322,6 +401,9 @@ static int ddr_stats_remove(struct platform_device *pdev)
|
|||
ddr_stats_ka = (struct ddr_stats_kobj_attr *)
|
||||
platform_get_drvdata(pdev);
|
||||
|
||||
if (ddr_pdata->read_ddr_vote)
|
||||
mbox_free_channel(ddr_stats_ka->pd->stats_mbox_ch);
|
||||
|
||||
sysfs_remove_file(ddr_stats_ka->kobj, &ddr_stats_ka->ka.attr);
|
||||
kobject_put(ddr_stats_ka->kobj);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,14 @@ struct ddr_freq_residency {
|
|||
uint64_t residency;
|
||||
};
|
||||
|
||||
struct ddr_stats_ss_vote_info {
|
||||
u32 ab; /* vote_x */
|
||||
u32 ib; /* vote_y */
|
||||
};
|
||||
|
||||
int ddr_stats_get_freq_count(void);
|
||||
int ddr_stats_get_residency(int freq_count, struct ddr_freq_residency *data);
|
||||
|
||||
int ddr_stats_get_ss_count(void);
|
||||
int ddr_stats_get_ss_vote_info(int ss_count,
|
||||
struct ddr_stats_ss_vote_info *vote_info);
|
||||
#endif /*__DDR_STATS_H_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue