/* Copyright (c) 2010, 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.
 */

/*
per-axi
DESCRIPTION
Functions related to AXI bus performance counter manipulations.
*/

#include <linux/io.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include "asm/uaccess.h"
#include "per-axi.h"
#include "perf.h"

/*
Definitions for AXI register addresses, macros to set and get register values
*/
#define AXI_BASE_SIZE						0x00004000
#define AXI_REG_BASE					(AXI_BASE + 0x00000000)
#define AXI_REG_BASE_PHYS					0xa8200000

#define __inpdw(port)	ioread32(port)
#define in_dword_masked(addr, mask) (__inpdw(addr) & (mask))
#define __outpdw(port, val) (iowrite32((uint32_t) (val), port))
#define out_dword(addr, val)        __outpdw(addr, val)

#define HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_ADDR \
						(AXI_REG_BASE + 0x00003434)
#define HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_RMSK		0xffff
#define HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_IN	\
	in_dword_masked(HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_ADDR, \
				HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_RMSK)

#define HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_ADDR (AXI_REG_BASE + 0x00003438)
#define HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_RMSK		0xffff
#define HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_IN	\
	in_dword_masked(HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_ADDR, \
				HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_RMSK)

#define HWIO_AXI_MONITOR_SELECTION_REG0_ADDR	(AXI_REG_BASE + 0x00003428)
#define HWIO_AXI_MONITOR_SELECTION_REG1_ADDR    (AXI_REG_BASE + 0x0000342c)
#define HWIO_AXI_MONITOR_TENURE_SELECTION_REG_ADDR (AXI_REG_BASE + 0x00003430)
#define HWIO_AXI_MONITOR_SELECTION_REG0_ETC_BMSK		0x4000
#define HWIO_AXI_MONITOR_SELECTION_REG0_ECC_BMSK		0x2000
#define HWIO_AXI_MONITOR_SELECTION_REG0_EEC1_BMSK		0x800
#define HWIO_AXI_MONITOR_SELECTION_REG0_EEC0_BMSK		0x200
#define HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_OUT(v)                       \
	out_dword(HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_ADDR, v)
#define HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_OUT(v)                       \
	out_dword(HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_ADDR, v)
#define HWIO_AXI_MONITOR_SELECTION_REG0_OUT(v)                              \
	out_dword(HWIO_AXI_MONITOR_SELECTION_REG0_ADDR, v)
#define HWIO_AXI_MONITOR_SELECTION_REG1_OUT(v)                              \
	out_dword(HWIO_AXI_MONITOR_SELECTION_REG1_ADDR, v)
#define HWIO_AXI_MONITOR_TENURE_SELECTION_REG_OUT(v)                        \
	out_dword(HWIO_AXI_MONITOR_TENURE_SELECTION_REG_ADDR, v)
#define HWIO_AXI_MONITOR_SELECTION_REG0_RMSK			0xffff
#define HWIO_AXI_MONITOR_SELECTION_REG0_IN                                  \
	in_dword_masked(HWIO_AXI_MONITOR_SELECTION_REG0_ADDR,               \
	HWIO_AXI_MONITOR_SELECTION_REG0_RMSK)

#define HWIO_AXI_CONFIGURATION_REG_ADDR		(AXI_REG_BASE + 0x00000008)
#define HWIO_AXI_CONFIGURATION_REG_OUT(v)                                   \
	out_dword(HWIO_AXI_CONFIGURATION_REG_ADDR, v)
#define HWIO_AXI_CONFIGURATION_REG_PPDM_BMSK			0x0
#define HWIO_AXI_CONFIGURATION_REG_DISABLE			0x2
#define AXI_EVTSEL_ENABLE_MASK					0x6a00
#define AXI_EVTSEL_DISABLE_MASK					0x95ff
#define AXI_EVTSEL_RESET_MASK					0xfe40

#define HWIO_AXI_MONITOR_EVENT_LOWER_REG0_ADDR	(AXI_REG_BASE + 0x00003450)
#define HWIO_AXI_MONITOR_EVENT_LOWER_REG0_RMSK			0xffff
#define HWIO_AXI_MONITOR_EVENT_LOWER_REG0_SHFT			0
#define HWIO_AXI_MONITOR_EVENT_LOWER_REG0_IN                                \
	in_dword_masked(HWIO_AXI_MONITOR_EVENT_LOWER_REG0_ADDR,		\
	HWIO_AXI_MONITOR_EVENT_LOWER_REG0_RMSK)
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG0_ADDR	(AXI_REG_BASE + 0x00003454)
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG0_RMSK			0xffff
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG0_SHFT			0
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG0_IN                                \
	in_dword_masked(HWIO_AXI_MONITOR_EVENT_UPPER_REG0_ADDR,		\
	HWIO_AXI_MONITOR_EVENT_UPPER_REG0_RMSK)

#define HWIO_AXI_MONITOR_EVENT_LOWER_REG1_ADDR	(AXI_REG_BASE + 0x00003458)
#define HWIO_AXI_MONITOR_EVENT_LOWER_REG1_RMSK			0xffff
#define HWIO_AXI_MONITOR_EVENT_LOWER_REG1_SHFT			0
#define HWIO_AXI_MONITOR_EVENT_LOWER_REG1_IN                                \
	in_dword_masked(HWIO_AXI_MONITOR_EVENT_LOWER_REG1_ADDR,		\
	HWIO_AXI_MONITOR_EVENT_LOWER_REG1_RMSK)
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG1_ADDR	(AXI_REG_BASE + 0x0000345c)
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG1_RMSK			0xffff
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG1_SHFT			0
#define HWIO_AXI_MONITOR_EVENT_UPPER_REG1_IN                                \
	in_dword_masked(HWIO_AXI_MONITOR_EVENT_UPPER_REG1_ADDR,		\
	HWIO_AXI_MONITOR_EVENT_UPPER_REG1_RMSK)

#define HWIO_AXI_MONITOR_TENURE_LOWER_REG_ADDR	(AXI_REG_BASE + 0x00003448)
#define HWIO_AXI_MONITOR_TENURE_LOWER_REG_RMSK			0xffff
#define HWIO_AXI_MONITOR_TENURE_LOWER_REG_SHFT			0
#define HWIO_AXI_MONITOR_TENURE_LOWER_REG_IN                                \
	in_dword_masked(HWIO_AXI_MONITOR_TENURE_LOWER_REG_ADDR,		\
	HWIO_AXI_MONITOR_TENURE_LOWER_REG_RMSK)
#define HWIO_AXI_MONITOR_TENURE_UPPER_REG_ADDR	(AXI_REG_BASE + 0x00003444)
#define HWIO_AXI_MONITOR_TENURE_UPPER_REG_RMSK			0xffff
#define HWIO_AXI_MONITOR_TENURE_UPPER_REG_SHFT			0
#define HWIO_AXI_MONITOR_TENURE_UPPER_REG_IN                                \
	in_dword_masked(HWIO_AXI_MONITOR_TENURE_UPPER_REG_ADDR,		\
	HWIO_AXI_MONITOR_TENURE_UPPER_REG_RMSK)

#define HWIO_AXI_MONITOR_MIN_REG_ADDR		(AXI_REG_BASE + 0x0000343c)
#define HWIO_AXI_MONITOR_MIN_REG_RMSK				0xffff
#define HWIO_AXI_MONITOR_MIN_REG_SHFT				0
#define HWIO_AXI_MONITOR_MIN_REG_IN                                         \
	in_dword_masked(HWIO_AXI_MONITOR_MIN_REG_ADDR,			\
	HWIO_AXI_MONITOR_MIN_REG_RMSK)
#define HWIO_AXI_MONITOR_MAX_REG_ADDR		(AXI_REG_BASE + 0x00003440)
#define HWIO_AXI_MONITOR_MAX_REG_RMSK				0xffff
#define HWIO_AXI_MONITOR_MAX_REG_SHFT				0
#define HWIO_AXI_MONITOR_MAX_REG_IN                                         \
	in_dword_masked(HWIO_AXI_MONITOR_MAX_REG_ADDR,			\
	HWIO_AXI_MONITOR_MAX_REG_RMSK)
#define HWIO_AXI_MONITOR_LAST_TENURE_REG_ADDR	(AXI_REG_BASE + 0x0000344c)
#define HWIO_AXI_MONITOR_LAST_TENURE_REG_RMSK			0xffff
#define HWIO_AXI_MONITOR_LAST_TENURE_REG_SHFT			0
#define HWIO_AXI_MONITOR_LAST_TENURE_REG_IN                                 \
	in_dword_masked(HWIO_AXI_MONITOR_LAST_TENURE_REG_ADDR,		\
	HWIO_AXI_MONITOR_LAST_TENURE_REG_RMSK)
#define HWIO_AXI_MONITOR_TENURE_UPPER_REG_OUT(v)                            \
	out_dword(HWIO_AXI_MONITOR_TENURE_UPPER_REG_ADDR, v)
#define HWIO_AXI_MONITOR_TENURE_LOWER_REG_OUT(v)                            \
	out_dword(HWIO_AXI_MONITOR_TENURE_LOWER_REG_ADDR, v)

#define HWIO_AXI_RESET_ALL		0x9400
#define HWIO_AXI_ENABLE_ALL_NOCYCLES	0x4a00
#define HWIO_AXI_DISABLE_ALL		0xb500
uint32_t AXI_BASE;

unsigned int is_first = 1;
struct perf_mon_axi_data pm_axi_info;
struct perf_mon_axi_cnts axi_cnts;

/*
FUNCTION get_axi_sel_reg0

DESCRIPTION
	Retrieve the value of AXI_SEL_REG0

DEPENDENCIES

RETURN VALUE
	AXI_SEL_REG0
SIDE EFFECTS
*/
unsigned long get_axi_sel_reg0(void)
{
	return pm_axi_info.sel_reg0;
}

/*
FUNCTION get_axi_sel_reg1

DESCRIPTION
	Retrieve the value of AXI_SEL_REG1

DEPENDENCIES

RETURN VALUE
	AXI_SEL_REG1
SIDE EFFECTS
*/
unsigned long get_axi_sel_reg1(void)
{
	return pm_axi_info.sel_reg1;
}

/*
FUNCTION get_axi_ten_sel_reg

DESCRIPTION
	Retrieve the value of AXI_TEN_REG

DEPENDENCIES

RETURN VALUE
	AXI_TEN_REG
SIDE EFFECTS
*/
unsigned long get_axi_ten_sel_reg(void)
{
	return pm_axi_info.ten_sel_reg;
}

/*
FUNCTION get_axi_valid

DESCRIPTION
	Retrieve the value of AXI valid bit

DEPENDENCIES

RETURN VALUE
	AXI Valid bit
SIDE EFFECTS
*/
unsigned long get_axi_valid(void)
{
	return pm_axi_info.valid;
}

/*
FUNCTION get_axi_enable

DESCRIPTION
	Retrieve the value of AXI enable bit

DEPENDENCIES

RETURN VALUE
	AXI enable bit
SIDE EFFECTS
*/
unsigned long get_axi_enable(void)
{
	return pm_axi_info.enable;
}

/*
FUNCTION get_axi_clear

DESCRIPTION
	Retrieve the value of AXI clear bit

DEPENDENCIES

RETURN VALUE
	AXI clear bit
SIDE EFFECTS
*/
unsigned long get_axi_clear(void)
{
	return pm_axi_info.clear;
}

/*
FUNCTION pm_axi_cnts_write

DESCRIPTION
	Write handler for the /proc axi results directory.

DEPENDENCIES

RETURN VALUE
	Number of characters to output.

SIDE EFFECTS
*/
int pm_axi_cnts_write(struct file *file, const char *buff,
    unsigned long cnt, void *data)
{
	char *newbuf;
	struct PerfMonAxiCnts *p =
	(struct PerfMonAxiCnts *)data;

	if (p == 0)
		return cnt;
	/*
	* Alloc the user data in kernel space. and then copy user to kernel
	*/
	newbuf = kmalloc(cnt + 1, GFP_KERNEL);
	if (0 == newbuf)
		return cnt;
	if (copy_from_user(newbuf, buff, cnt) != 0) {
		printk(KERN_INFO "%s copy_from_user failed\n", __func__);
		return cnt;
	}
	return cnt;
}

/*
FUNCTION pm_axi_update_cnts

DESCRIPTION
	Read the current AXI counter values. Check for overflows and
	adjust the values stored accordingly.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void pm_axi_update_cnts(void)
{
	if (is_first) {
		pm_axi_start();
	} else {
		if (pm_axi_info.valid == 1) {
			pm_axi_info.valid = 0;
			pm_axi_update();
		} else {
			pm_axi_enable();
		}
	}
	is_first = 0;
	axi_cnts.cycles += pm_get_axi_cycle_count();
	axi_cnts.cnt0 += pm_get_axi_evt0_count();
	axi_cnts.cnt1 += pm_get_axi_evt1_count();
	axi_cnts.tenure_total += pm_get_axi_ten_total_count();

	axi_cnts.tenure_min = pm_get_axi_ten_min_count();
	axi_cnts.tenure_max = pm_get_axi_ten_max_count();
	axi_cnts.tenure_last = pm_get_axi_ten_last_count();

	pm_axi_start();
}

/*
FUNCTION pm_axi_clear_cnts

DESCRIPTION
	Clear the locally stored AXI counter values.
	Also clear the AXI counter registers.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void pm_axi_clear_cnts(void)
{
	axi_cnts.cycles = 0;
	axi_cnts.cnt0 = 0;
	axi_cnts.cnt1 = 0;
	axi_cnts.tenure_total = 0;
	axi_cnts.tenure_min = 0;
	axi_cnts.tenure_max = 0;
	axi_cnts.tenure_last = 0;
	pm_axi_start();
}

/*
FUNCTION pm_axi_read_decimal

DESCRIPTION
	Read handler for the /proc axi results directory in decimal format.

DEPENDENCIES

RETURN VALUE
	Number of characters to output.

SIDE EFFECTS
*/
int pm_axi_read_decimal(char *page, char **start, off_t off, int count,
   int *eof, void *data)
{
	struct perf_mon_axi_cnts *p = (struct perf_mon_axi_cnts *)data;

	return sprintf(page, "cnt0:%llu cnt1:%llu tenure:%llu ten_max:%llu \
				ten_min:%llu ten_last:%llu cycles:%llu\n",
				p->cnt0,
				p->cnt1,
				p->tenure_total,
				p->tenure_max,
				p->tenure_min,
				p->tenure_last,
				p->cycles);
}

/*
FUNCTION pm_axi_read_hex

DESCRIPTION
	Read handler for the /proc axi results directory in hex format.

DEPENDENCIES

RETURN VALUE
	Number of characters to output.

SIDE EFFECTS
*/
int pm_axi_read_hex(char *page, char **start, off_t off, int count,
   int *eof, void *data)
{
	struct perf_mon_axi_cnts *p = (struct perf_mon_axi_cnts *)data;

	return sprintf(page, "cnt0:%llx cnt1:%llx tenure:%llx ten_max:%llx \
				ten_min:%llx ten_last:%llx cycles:%llx\n",
				p->cnt0,
				p->cnt1,
				p->tenure_total,
				p->tenure_max,
				p->tenure_min,
				p->tenure_last,
				p->cycles);

}

/*
FUNCTION pm_axi_set_proc_entry

DESCRIPTION
	Create a generic entry for the /proc axi settings directory.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void pm_axi_set_proc_entry(char *name, unsigned long *var,
    struct proc_dir_entry *d, int hex)
{
	struct proc_dir_entry *pe;
	pe = create_proc_entry(name, 0777, d);
	if (0 == pe)
		return;
	if (hex) {
		pe->read_proc = per_process_read;
		pe->write_proc = per_process_write_hex;
	} else {
		pe->read_proc = per_process_read_decimal;
		pe->write_proc = per_process_write_dec;
	}
	pe->data = (void *)var;
}

/*
FUNCTION pm_axi_get_cnt_proc_entry

DESCRIPTION
	Create a generic entry for the /proc axi results directory.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void pm_axi_get_cnt_proc_entry(char *name, struct perf_mon_axi_cnts *var,
    struct proc_dir_entry *d, int hex)
{
	struct proc_dir_entry *pe;
	pe = create_proc_entry(name, 0777, d);
	if (0 == pe)
		return;
	if (hex) {
		pe->read_proc = pm_axi_read_hex;
		pe->write_proc = pm_axi_cnts_write;
	} else {
		pe->read_proc = pm_axi_read_decimal;
		pe->write_proc = pm_axi_cnts_write;
	}
	pe->data = (void *)var;
}

/*
FUNCTION pm_axi_clear_tenure

DESCRIPTION
	Clear AXI tenure cntr manually. Temporary solution till hardware bug
	is fixed

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void pm_axi_clear_tenure(void)
{
	HWIO_AXI_MONITOR_TENURE_UPPER_REG_OUT(0x0);
	HWIO_AXI_MONITOR_TENURE_LOWER_REG_OUT(0x0);
}

/*
FUNCTION pm_axi_init

DESCRIPTION
	Map AXI region to virtual memory.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void pm_axi_init()
{
	/*Map the AXI regs*/
	#ifdef CONFIG_ARCH_QSD8X50
	{
		/*Map the AXI regs*/
		AXI_BASE = (uint32_t)ioremap(AXI_REG_BASE_PHYS, AXI_BASE_SIZE);
		if (!AXI_BASE)
			printk(KERN_ERR "Mem map failed\n");
	}
	#else
	{
		AXI_BASE = (uint32_t)kmalloc(AXI_BASE_SIZE, GFP_KERNEL);
	}
	#endif

}

/*
FUNCTION pm_axi_start

DESCRIPTION
	Set event0, event1 and tenure registers based on the /proc entries.
	Set cycle cntr to fffffffe to start counters.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void
pm_axi_start()
{
	unsigned long sel_reg0, sel_reg1, ten_sel_reg;
	sel_reg0 = get_axi_sel_reg0();
	sel_reg1 = get_axi_sel_reg1();
	ten_sel_reg = get_axi_ten_sel_reg();
	HWIO_AXI_CONFIGURATION_REG_OUT(HWIO_AXI_CONFIGURATION_REG_PPDM_BMSK);
	/*Set AXI Cycle Counter to enable AXI Monitors*/
	HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_OUT(0xffff);
	HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_OUT(0xfffe);
	/*Set master/slave*/
	HWIO_AXI_MONITOR_SELECTION_REG1_OUT(sel_reg1);
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(HWIO_AXI_RESET_ALL);
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(HWIO_AXI_ENABLE_ALL_NOCYCLES);
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(HWIO_AXI_MONITOR_SELECTION_REG0_IN
		| sel_reg0);
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(HWIO_AXI_MONITOR_SELECTION_REG0_IN
		| HWIO_AXI_MONITOR_SELECTION_REG0_ECC_BMSK);
	HWIO_AXI_CONFIGURATION_REG_OUT(HWIO_AXI_CONFIGURATION_REG_PPDM_BMSK);
}

/*
FUNCTION pm_axi_update

DESCRIPTION
	Set event0, event1 and tenure registers based on the /proc entries.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void
pm_axi_update()
{
	HWIO_AXI_CONFIGURATION_REG_OUT(HWIO_AXI_CONFIGURATION_REG_PPDM_BMSK);
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(HWIO_AXI_MONITOR_SELECTION_REG0_IN
		| HWIO_AXI_RESET_ALL);
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(HWIO_AXI_MONITOR_SELECTION_REG0_IN
	& HWIO_AXI_DISABLE_ALL);
	pm_axi_start();
}

/*
FUNCTION pm_axi_disable

DESCRIPTION
	Disable all cntrs.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void
pm_axi_disable(void)
{
	unsigned long sel_reg0;
	/*Disable cntrs*/
	sel_reg0 = get_axi_sel_reg0();
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(sel_reg0 & AXI_EVTSEL_DISABLE_MASK);
	/*Disable clk*/
	HWIO_AXI_CONFIGURATION_REG_OUT(HWIO_AXI_CONFIGURATION_REG_DISABLE);
}

/*
FUNCTION pm_axi_enable

DESCRIPTION
	Enable all cntrs.

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
void
pm_axi_enable(void)
{
	unsigned long sel_reg0;
	/*Enable cntrs*/
	sel_reg0 = get_axi_sel_reg0();
	HWIO_AXI_MONITOR_SELECTION_REG0_OUT(sel_reg0 | 0x6a00);
	/*Enable clk*/
	HWIO_AXI_CONFIGURATION_REG_OUT(HWIO_AXI_CONFIGURATION_REG_PPDM_BMSK);
}

/*
FUNCTION pm_axi_disable_cnts

DESCRIPTION
	Read cycle cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_cycle_count(void)
{
	if (HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_IN == 0x0 &&
		HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_IN == 0x0) {
		/*Set AXI Cycle Counter to enable AXI Monitors*/
		HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_OUT(0xffff);
		HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_OUT(0xfffe);
	}
	return 0xfffffffe - ((HWIO_AXI_MONITOR_CYCLE_COUNT_UPPER_REG_IN << 16)
	+ HWIO_AXI_MONITOR_CYCLE_COUNT_LOWER_REG_IN);
}

/*
FUNCTION pm_get_axi_evt0_count

DESCRIPTION
	Read Event0 cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_evt0_count(void)
{
	return (HWIO_AXI_MONITOR_EVENT_UPPER_REG0_IN << 16)
		+ HWIO_AXI_MONITOR_EVENT_LOWER_REG0_IN;
}

/*
FUNCTION pm_get_axi_evt1_count

DESCRIPTION
	Read Event1 cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_evt1_count(void)
{
	return (HWIO_AXI_MONITOR_EVENT_UPPER_REG1_IN << 16)
		+ HWIO_AXI_MONITOR_EVENT_LOWER_REG1_IN;
}

/*
FUNCTION pm_get_axi_ten_min_count

DESCRIPTION
	Read min tenure cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_ten_min_count(void)
{
	return HWIO_AXI_MONITOR_MIN_REG_IN;
}

/*
FUNCTION pm_get_axi_ten_max_count

DESCRIPTION
	Read max tenure cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_ten_max_count(void)
{
	return HWIO_AXI_MONITOR_MAX_REG_IN;
}

/*
FUNCTION pm_get_axi_ten_total_count

DESCRIPTION
	Read total tenure cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_ten_total_count(void)
{
	return (HWIO_AXI_MONITOR_TENURE_UPPER_REG_IN << 16)
		+ HWIO_AXI_MONITOR_TENURE_LOWER_REG_IN;
}

/*
FUNCTION pm_get_axi_ten_last_count

DESCRIPTION
	Read last tenure cntr value

DEPENDENCIES

RETURN VALUE

SIDE EFFECTS
*/
unsigned long
pm_get_axi_ten_last_count(void)
{
	return HWIO_AXI_MONITOR_LAST_TENURE_REG_IN;
}
