/* 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 #include #include #include #include #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; }