diff options
Diffstat (limited to 'drivers/devfreq/exynos/exynos_ppmu.c')
| -rw-r--r-- | drivers/devfreq/exynos/exynos_ppmu.c | 60 | 
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/devfreq/exynos/exynos_ppmu.c b/drivers/devfreq/exynos/exynos_ppmu.c index 85fc5ac1036..75fcc5140ff 100644 --- a/drivers/devfreq/exynos/exynos_ppmu.c +++ b/drivers/devfreq/exynos/exynos_ppmu.c @@ -54,3 +54,63 @@ unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch)  	return total;  } + +void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data) +{ +	unsigned int i; + +	for (i = 0; i < ppmu_data->ppmu_end; i++) { +		void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base; + +		/* Reset the performance and cycle counters */ +		exynos_ppmu_reset(ppmu_base); + +		/* Setup count registers to monitor read/write transactions */ +		ppmu_data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT; +		exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3, +					ppmu_data->ppmu[i].event[PPMU_PMNCNT3]); + +		exynos_ppmu_start(ppmu_base); +	} +} + +void exynos_read_ppmu(struct busfreq_ppmu_data *ppmu_data) +{ +	int i, j; + +	for (i = 0; i < ppmu_data->ppmu_end; i++) { +		void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base; + +		exynos_ppmu_stop(ppmu_base); + +		/* Update local data from PPMU */ +		ppmu_data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT); + +		for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { +			if (ppmu_data->ppmu[i].event[j] == 0) +				ppmu_data->ppmu[i].count[j] = 0; +			else +				ppmu_data->ppmu[i].count[j] = +					exynos_ppmu_read(ppmu_base, j); +		} +	} + +	busfreq_mon_reset(ppmu_data); +} + +int exynos_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data) +{ +	unsigned int count = 0; +	int i, j, busy = 0; + +	for (i = 0; i < ppmu_data->ppmu_end; i++) { +		for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { +			if (ppmu_data->ppmu[i].count[j] > count) { +				count = ppmu_data->ppmu[i].count[j]; +				busy = i; +			} +		} +	} + +	return busy; +}  | 
