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

Commit c1df7478 authored by Hareesh Gundu's avatar Hareesh Gundu Committed by Gerrit - the friendly Code Review server
Browse files

msm: kgsl: Add support for cx-ipeak victim registration



CX-ipeak victim registration will allow to throttle GPU
frequency based on CX-ipeak HW interrupt. There will
be callback from CX-ipeak driver upon HW interrupt to
handle frequency throttling.

Change-Id: I08f6bb277f23abc2aa5372097485845d6082c075
Signed-off-by: default avatarHareesh Gundu <hareeshg@codeaurora.org>
parent 55303f9f
Loading
Loading
Loading
Loading
+48 −2
Original line number Original line Diff line number Diff line
@@ -313,6 +313,22 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device,
EXPORT_SYMBOL(kgsl_pwrctrl_buslevel_update);
EXPORT_SYMBOL(kgsl_pwrctrl_buslevel_update);


#if IS_ENABLED(CONFIG_QCOM_CX_IPEAK)
#if IS_ENABLED(CONFIG_QCOM_CX_IPEAK)
static int kgsl_pwr_cx_ipeak_freq_limit(void *ptr, unsigned int freq)
{
	struct kgsl_pwr_limit *cx_ipeak_pwr_limit = ptr;

	if (IS_ERR_OR_NULL(cx_ipeak_pwr_limit))
		return -EINVAL;

	/* CX-ipeak safe interrupt to remove freq limit */
	if (freq == 0) {
		kgsl_pwr_limits_set_default(cx_ipeak_pwr_limit);
		return 0;
	}

	return kgsl_pwr_limits_set_freq(cx_ipeak_pwr_limit, freq);
}

static int kgsl_pwrctrl_cx_ipeak_vote(struct kgsl_device *device,
static int kgsl_pwrctrl_cx_ipeak_vote(struct kgsl_device *device,
		u64 old_freq, u64 new_freq)
		u64 old_freq, u64 new_freq)
{
{
@@ -425,6 +441,29 @@ static int kgsl_pwrctrl_cx_ipeak_init(struct kgsl_device *device)
		++i;
		++i;
	}
	}


	/* cx_ipeak limits for GPU freq throttling */
	pwr->cx_ipeak_pwr_limit = kgsl_pwr_limits_add(KGSL_DEVICE_3D0);
	if (IS_ERR_OR_NULL(pwr->cx_ipeak_pwr_limit)) {
		dev_err(device->dev,
				"Failed to get cx_ipeak power limit\n");
		of_node_put(child);
		goto error;
	}

	cx_ipeak_client = &pwr->gpu_ipeak_client[0];
	if (!IS_ERR_OR_NULL(cx_ipeak_client->client)) {
		ret = cx_ipeak_victim_register(cx_ipeak_client->client,
				kgsl_pwr_cx_ipeak_freq_limit,
				pwr->cx_ipeak_pwr_limit);
		if (ret) {
			dev_err(device->dev,
					"Failed to register GPU-CX-Ipeak victim\n");
			kgsl_pwr_limits_del(pwr->cx_ipeak_pwr_limit);
			of_node_put(child);
			goto error;
		}
	}

	of_node_put(node);
	of_node_put(node);
	return 0;
	return 0;


@@ -2379,6 +2418,9 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
		}
		}
	}
	}


	INIT_LIST_HEAD(&pwr->limits);
	spin_lock_init(&pwr->limits_lock);

	result = kgsl_pwrctrl_cx_ipeak_init(device);
	result = kgsl_pwrctrl_cx_ipeak_init(device);
	if (result)
	if (result)
		goto error_cleanup_bus_ib;
		goto error_cleanup_bus_ib;
@@ -2386,8 +2428,6 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
	INIT_WORK(&pwr->thermal_cycle_ws, kgsl_thermal_cycle);
	INIT_WORK(&pwr->thermal_cycle_ws, kgsl_thermal_cycle);
	timer_setup(&pwr->thermal_timer, kgsl_thermal_timer, 0);
	timer_setup(&pwr->thermal_timer, kgsl_thermal_timer, 0);


	INIT_LIST_HEAD(&pwr->limits);
	spin_lock_init(&pwr->limits_lock);
	pwr->sysfs_pwr_limit = kgsl_pwr_limits_add(KGSL_DEVICE_3D0);
	pwr->sysfs_pwr_limit = kgsl_pwr_limits_add(KGSL_DEVICE_3D0);


	kgsl_pwrctrl_vbif_init(device);
	kgsl_pwrctrl_vbif_init(device);
@@ -2418,6 +2458,12 @@ void kgsl_pwrctrl_close(struct kgsl_device *device)
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	int i;
	int i;


	kgsl_pwr_limits_del(pwr->cx_ipeak_pwr_limit);
	pwr->cx_ipeak_pwr_limit = NULL;

	if (!IS_ERR_OR_NULL(pwr->gpu_ipeak_client[0].client))
		cx_ipeak_victim_unregister(pwr->gpu_ipeak_client[0].client);

	for (i = 0; i < ARRAY_SIZE(pwr->gpu_ipeak_client); i++) {
	for (i = 0; i < ARRAY_SIZE(pwr->gpu_ipeak_client); i++) {
		if (!IS_ERR_OR_NULL(pwr->gpu_ipeak_client[i].client)) {
		if (!IS_ERR_OR_NULL(pwr->gpu_ipeak_client[i].client)) {
			cx_ipeak_unregister(pwr->gpu_ipeak_client[i].client);
			cx_ipeak_unregister(pwr->gpu_ipeak_client[i].client);
+3 −1
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* SPDX-License-Identifier: GPL-2.0-only */
/*
/*
 * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
 */
 */
#ifndef __KGSL_PWRCTRL_H
#ifndef __KGSL_PWRCTRL_H
#define __KGSL_PWRCTRL_H
#define __KGSL_PWRCTRL_H
@@ -177,6 +177,7 @@ struct gpu_cx_ipeak_client {
 * @limits - list head for limits
 * @limits - list head for limits
 * @limits_lock - spin lock to protect limits list
 * @limits_lock - spin lock to protect limits list
 * @sysfs_pwr_limit - pointer to the sysfs limits node
 * @sysfs_pwr_limit - pointer to the sysfs limits node
 * @cx_ipeak_pwr_limit - pointer to the cx_ipeak limits node
 * isense_clk_indx - index of isense clock, 0 if no isense
 * isense_clk_indx - index of isense clock, 0 if no isense
 * isense_clk_on_level - isense clock rate is XO rate below this level.
 * isense_clk_on_level - isense clock rate is XO rate below this level.
 * tzone_name - pointer to thermal zone name of GPU temperature sensor
 * tzone_name - pointer to thermal zone name of GPU temperature sensor
@@ -236,6 +237,7 @@ struct kgsl_pwrctrl {
	struct list_head limits;
	struct list_head limits;
	spinlock_t limits_lock;
	spinlock_t limits_lock;
	struct kgsl_pwr_limit *sysfs_pwr_limit;
	struct kgsl_pwr_limit *sysfs_pwr_limit;
	struct kgsl_pwr_limit *cx_ipeak_pwr_limit;
	unsigned int gpu_bimc_int_clk_freq;
	unsigned int gpu_bimc_int_clk_freq;
	bool gpu_bimc_interface_enabled;
	bool gpu_bimc_interface_enabled;
	const char *tzone_name;
	const char *tzone_name;