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

Commit 656f4290 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cpufreq: qcom: Update logic to register for GT Limits Management interrupt"

parents 46ea85a9 a9ddac8c
Loading
Loading
Loading
Loading
+21 −30
Original line number Diff line number Diff line
@@ -23,8 +23,7 @@
#define CORE_COUNT_VAL(val)		(((val) & (GENMASK(18, 16))) >> 16)
#define LUT_ROW_SIZE			32
#define CLK_HW_DIV			2
#define EQ_IRQ_STATUS			BIT(0)
#define LT_IRQ_STATUS			BIT(1)
#define GT_IRQ_STATUS			BIT(2)
#define MAX_FN_SIZE			12
#define LIMITS_POLLING_DELAY_MS		10

@@ -37,7 +36,7 @@ enum {
	REG_VOLT_LUT_TABLE,
	REG_PERF_STATE,
	REG_CYCLE_CNTR,
	REG_LLM_DCVS_VC_VOTE,
	REG_DOMAIN_STATE,
	REG_INTR_EN,
	REG_INTR_CLR,
	REG_INTR_STATUS,
@@ -86,7 +85,7 @@ static const u16 cpufreq_qcom_epss_std_offsets[REG_ARRAY_SIZE] = {
	[REG_VOLT_LUT_TABLE]	= 0x200,
	[REG_PERF_STATE]	= 0x320,
	[REG_CYCLE_CNTR]	= 0x3c4,
	[REG_LLM_DCVS_VC_VOTE]	= 0x024,
	[REG_DOMAIN_STATE]	= 0x020,
	[REG_INTR_EN]		= 0x304,
	[REG_INTR_CLR]		= 0x308,
	[REG_INTR_STATUS]	= 0x30C,
@@ -95,6 +94,8 @@ static const u16 cpufreq_qcom_epss_std_offsets[REG_ARRAY_SIZE] = {
static struct cpufreq_counter qcom_cpufreq_counter[NR_CPUS];
static struct cpufreq_qcom *qcom_freq_domain_map[NR_CPUS];

static unsigned int qcom_cpufreq_hw_get(unsigned int cpu);

static ssize_t dcvsh_freq_limit_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
@@ -105,48 +106,40 @@ static ssize_t dcvsh_freq_limit_show(struct device *dev,

static unsigned long limits_mitigation_notify(struct cpufreq_qcom *c)
{
	int i;
	u32 max_vc;
	unsigned long freq;

	max_vc = readl_relaxed(c->reg_bases[REG_LLM_DCVS_VC_VOTE]) &
						GENMASK(13, 8);
	freq = readl_relaxed(c->reg_bases[REG_DOMAIN_STATE]) &
				GENMASK(7, 0);
	freq = DIV_ROUND_CLOSEST_ULL(freq * c->xo_rate, 1000);

	for (i = 0; i < lut_max_entries; i++) {
		if (c->table[i].driver_data != max_vc)
			continue;
		else {
			sched_update_cpu_freq_min_max(&c->related_cpus, 0,
					c->table[i].frequency);
			trace_dcvsh_freq(cpumask_first(&c->related_cpus),
						c->table[i].frequency);
			c->dcvsh_freq_limit = c->table[i].frequency;
			return c->table[i].frequency;
		}
	}
	sched_update_cpu_freq_min_max(&c->related_cpus, 0, freq);
	trace_dcvsh_freq(cpumask_first(&c->related_cpus), freq);
	c->dcvsh_freq_limit = freq;

	return 0;
	return freq;
}

static void limits_dcvsh_poll(struct work_struct *work)
{
	struct cpufreq_qcom *c = container_of(work, struct cpufreq_qcom,
						freq_poll_work.work);
	struct cpufreq_policy *policy;
	unsigned long freq_limit;
	unsigned long freq_limit, dcvsh_freq;
	u32 regval, cpu;

	mutex_lock(&c->dcvsh_lock);

	cpu = cpumask_first(&c->related_cpus);
	policy = cpufreq_cpu_get_raw(cpu);

	freq_limit = limits_mitigation_notify(c);
	if (freq_limit != policy->cpuinfo.max_freq || !freq_limit) {

	dcvsh_freq = qcom_cpufreq_hw_get(cpu);

	if (freq_limit != dcvsh_freq) {
		mod_delayed_work(system_highpri_wq, &c->freq_poll_work,
				msecs_to_jiffies(LIMITS_POLLING_DELAY_MS));
	} else {
		regval = readl_relaxed(c->reg_bases[REG_INTR_CLR]);
		regval &= ~LT_IRQ_STATUS;
		regval |= GT_IRQ_STATUS;
		writel_relaxed(regval, c->reg_bases[REG_INTR_CLR]);

		c->is_irq_enabled = true;
@@ -162,7 +155,7 @@ static irqreturn_t dcvsh_handle_isr(int irq, void *data)
	u32 regval;

	regval = readl_relaxed(c->reg_bases[REG_INTR_STATUS]);
	if (!(regval & LT_IRQ_STATUS))
	if (!(regval & GT_IRQ_STATUS))
		return IRQ_HANDLED;

	mutex_lock(&c->dcvsh_lock);
@@ -301,7 +294,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
					"dcvsh-irq-%d", policy->cpu);
		ret = devm_request_threaded_irq(cpu_dev, c->dcvsh_irq, NULL,
			dcvsh_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT |
			IRQF_NO_SUSPEND | IRQF_SHARED, c->dcvsh_irq_name, c);
			IRQF_NO_SUSPEND, c->dcvsh_irq_name, c);
		if (ret) {
			dev_err(cpu_dev, "Failed to register irq %d\n", ret);
			return ret;
@@ -309,7 +302,6 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)

		c->is_irq_requested = true;
		c->is_irq_enabled = true;
		writel_relaxed(LT_IRQ_STATUS, c->reg_bases[REG_INTR_EN]);
		c->freq_limit_attr.attr.name = "dcvsh_freq_limit";
		c->freq_limit_attr.show = dcvsh_freq_limit_show;
		c->freq_limit_attr.attr.mode = 0444;
@@ -401,7 +393,6 @@ static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev,
		else
			c->table[i].frequency = c->cpu_hw_rate / 1000;

		c->table[i].driver_data = vc;
		cur_freq = c->table[i].frequency;

		dev_dbg(dev, "index=%d freq=%d, core_count %d\n",