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

Commit f53f8ea1 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "PM/devfreq: Add bw_vbif governor"

parents de20d38b b8004afb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARMBW_HWMON) += armbw-pm.o
obj-$(CONFIG_DEVFREQ_GOV_MSM_BW_HWMON)	+= governor_bw_hwmon.o
obj-$(CONFIG_DEVFREQ_GOV_MSM_CACHE_HWMON)	+= governor_cache_hwmon.o
obj-$(CONFIG_DEVFREQ_GOV_MSM_GPUBW_MON)	+= governor_gpubw_mon.o
obj-$(CONFIG_DEVFREQ_GOV_MSM_GPUBW_MON)	+= governor_bw_vbif.o

# DEVFREQ Drivers
obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ)	+= exynos4_bus.o
+129 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/devfreq.h>
#include <linux/module.h>
#include "governor.h"

unsigned long (*extern_get_bw)(void) = NULL;

DEFINE_MUTEX(df_lock);
static struct devfreq *df;

/*
 * This function is 'get_target_freq' API for the governor.
 * It just calls an external function that should be registered
 * by KGSL driver to get and return a value for frequency.
 */
static int devfreq_vbif_get_freq(struct devfreq *df,
				unsigned long *freq,
				u32 *flag)
{
	if (extern_get_bw) {
		*freq = extern_get_bw();
		return 0;
	} else {
		return -ENODEV;
	}
}

/*
 * Registers a function to be used to request a frequency
 * value from legacy vbif based bus bandwidth governor.
 * This function is called by KGSL driver.
 */
void devfreq_vbif_register_callback(void *p)
{
	extern_get_bw = p;
}


int devfreq_vbif_update_bw(void)
{
	int ret = 0;

	mutex_lock(&df_lock);
	if (df) {
		mutex_lock(&df->lock);
		ret = update_devfreq(df);
		mutex_unlock(&df->lock);
	}
	mutex_unlock(&df_lock);
	return ret;
}

static int devfreq_vbif_ev_handler(struct devfreq *devfreq,
					unsigned int event, void *data)
{
	int ret;

	switch (event) {
	case DEVFREQ_GOV_START:
		mutex_lock(&df_lock);
		df = devfreq;
		mutex_unlock(&df_lock);

		ret = devfreq_vbif_update_bw();
		if (ret) {
			pr_err("Unable to update BW! Gov start failed!\n");
			return ret;
		}
		/*
		 * Normally at this point governors start the polling with
		 * devfreq_monitor_start(df);
		 * This governor doesn't poll, but expect external calls
		 * of its devfreq_vbif_update_bw() function
		 */
		pr_debug("Enabled MSM VBIF governor\n");
		break;

	case DEVFREQ_GOV_STOP:
		mutex_lock(&df_lock);
		df = NULL;
		mutex_unlock(&df_lock);

		pr_debug("Disabled MSM VBIF governor\n");
		break;
	}

	return 0;
}

static struct devfreq_governor devfreq_vbif = {
	.name = "bw_vbif",
	.get_target_freq = devfreq_vbif_get_freq,
	.event_handler = devfreq_vbif_ev_handler,
};

static int __init devfreq_vbif_init(void)
{
	return devfreq_add_governor(&devfreq_vbif);
}
subsys_initcall(devfreq_vbif_init);

static void __exit devfreq_vbif_exit(void)
{
	int ret;

	ret = devfreq_remove_governor(&devfreq_vbif);
	if (ret)
		pr_err("%s: failed remove governor %d\n", __func__, ret);

	return;
}
module_exit(devfreq_vbif_exit);

MODULE_DESCRIPTION("VBIF based GPU bus BW voting governor");
MODULE_LICENSE("GPL v2");

+5 −0
Original line number Diff line number Diff line
@@ -63,4 +63,9 @@ struct msm_busmon_extended_profile {
	struct devfreq_dev_profile profile;
};

#ifdef CONFIG_DEVFREQ_GOV_MSM_GPUBW_MON
int devfreq_vbif_update_bw(void);
int devfreq_vbif_register_callback(void *);
#endif

#endif