/*
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * EXYNOS - PPMU support
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/io.h>

#include "exynos_ppmu.h"

void exynos_ppmu_reset(void __iomem *ppmu_base)
{
	__raw_writel(PPMU_CYCLE_RESET | PPMU_COUNTER_RESET, ppmu_base);
	__raw_writel(PPMU_ENABLE_CYCLE  |
		     PPMU_ENABLE_COUNT0 |
		     PPMU_ENABLE_COUNT1 |
		     PPMU_ENABLE_COUNT2 |
		     PPMU_ENABLE_COUNT3,
		     ppmu_base + PPMU_CNTENS);
}

void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch,
			unsigned int evt)
{
	__raw_writel(evt, ppmu_base + PPMU_BEVTSEL(ch));
}

void exynos_ppmu_start(void __iomem *ppmu_base)
{
	__raw_writel(PPMU_ENABLE, ppmu_base);
}

void exynos_ppmu_stop(void __iomem *ppmu_base)
{
	__raw_writel(PPMU_DISABLE, ppmu_base);
}

unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch)
{
	unsigned int total;

	if (ch == PPMU_PMNCNT3)
		total = ((__raw_readl(ppmu_base + PMCNT_OFFSET(ch)) << 8) |
			  __raw_readl(ppmu_base + PMCNT_OFFSET(ch + 1)));
	else
		total = __raw_readl(ppmu_base + PMCNT_OFFSET(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);
	}
}
EXPORT_SYMBOL(busfreq_mon_reset);

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);
}
EXPORT_SYMBOL(exynos_read_ppmu);

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;
}
EXPORT_SYMBOL(exynos_get_busier_ppmu);
