forked from CTCaer/hekate
172 lines
5.4 KiB
C
172 lines
5.4 KiB
C
/*
|
|
* Activity Monitor driver for Tegra X1
|
|
*
|
|
* Copyright (c) 2021 CTCaer
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "actmon.h"
|
|
#include "clock.h"
|
|
#include "t210.h"
|
|
|
|
/* Global registers */
|
|
#define ACTMON_GLB_STATUS 0x0
|
|
#define ACTMON_MCCPU_MON_ACT BIT(8)
|
|
#define ACTMON_MCALL_MON_ACT BIT(9)
|
|
#define ACTMON_CPU_FREQ_MON_ACT BIT(10)
|
|
#define ACTMON_APB_MON_ACT BIT(12)
|
|
#define ACTMON_AHB_MON_ACT BIT(13)
|
|
#define ACTMON_BPMP_MON_ACT BIT(14)
|
|
#define ACTMON_CPU_MON_ACT BIT(15)
|
|
#define ACTMON_MCCPU_INTR BIT(25)
|
|
#define ACTMON_MCALL_INTR BIT(26)
|
|
#define ACTMON_CPU_FREQ_INTR BIT(27)
|
|
#define ACTMON_APB_INTR BIT(28)
|
|
#define ACTMON_AHB_INTR BIT(29)
|
|
#define ACTMON_BPMP_INTR BIT(30)
|
|
#define ACTMON_CPU_INTR BIT(31)
|
|
#define ACTMON_GLB_PERIOD_CTRL 0x4
|
|
#define ACTMON_GLB_PERIOD_USEC BIT(8)
|
|
#define ACTMON_GLB_PERIOD_SAMPLE(n) (((n) - 1) & 0xFF)
|
|
|
|
/* Device Registers */
|
|
#define ACTMON_DEV_BASE ACTMON_BASE + 0x80
|
|
#define ACTMON_DEV_SIZE 0x40
|
|
/* CTRL */
|
|
#define ACTMON_DEV_CTRL_K_VAL(k) (((k) & 7) << 10)
|
|
#define ACTMON_DEV_CTRL_ENB_PERIODIC BIT(18)
|
|
#define ACTMON_DEV_CTRL_AT_END_EN BIT(19)
|
|
#define ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN BIT(20)
|
|
#define ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN BIT(21)
|
|
#define ACTMON_DEV_CTRL_WHEN_OVERFLOW_EN BIT(22)
|
|
#define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM(n) (((n) & 7) << 23)
|
|
#define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM(n) (((n) & 7) << 26)
|
|
#define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN BIT(29)
|
|
#define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN BIT(30)
|
|
#define ACTMON_DEV_CTRL_ENB BIT(31)
|
|
/* INTR_STATUS */
|
|
#define ACTMON_DEV_ISTS_AVG_ABOVE_WMARK BIT(24)
|
|
#define ACTMON_DEV_ISTS_AVG_BELOW_WMARK BIT(25)
|
|
#define ACTMON_DEV_ISTS_WHEN_OVERFLOW BIT(26)
|
|
#define ACTMON_DEV_ISTS_AT_END BIT(29)
|
|
#define ACTMON_DEV_ISTS_CONSECUTIVE_LOWER BIT(30)
|
|
#define ACTMON_DEV_ISTS_CONSECUTIVE_UPPER BIT(31)
|
|
|
|
/* Histogram Registers */
|
|
#define ACTMON_HISTOGRAM_CONFIG 0x300
|
|
#define ACTMON_HIST_CFG_ACTIVE BIT(0)
|
|
#define ACTMON_HIST_CFG_LINEAR_MODE BIT(1)
|
|
#define ACTMON_HIST_CFG_NO_UNDERFLOW_BUCKET BIT(2)
|
|
#define ACTMON_HIST_CFG_STALL_ON_SINGLE_SATURATE BIT(3)
|
|
#define ACTMON_HIST_CFG_SHIFT(s) (((s) & 0x1F) << 4)
|
|
#define ACTMON_HIST_CFG_SOURCE(s) (((s) & 0xF) << 12)
|
|
#define ACTMON_HISTOGRAM_CTRL 0x304
|
|
#define ACTMON_HIST_CTRL_CLEAR_ALL BIT(0)
|
|
#define ACTMON_HISTOGRAM_DATA_BASE 0x380
|
|
#define ACTMON_HISTOGRAM_DATA_NUM 32
|
|
|
|
#define ACTMON_FREQ 19200000
|
|
#define ACTMON_PERIOD_MS 20
|
|
#define DEV_COUNT_WEIGHT 5
|
|
|
|
typedef struct _actmon_dev_reg_t
|
|
{
|
|
vu32 ctrl;
|
|
vu32 upper_wnark;
|
|
vu32 lower_wmark;
|
|
vu32 init_avg;
|
|
vu32 avg_upper_wmark;
|
|
vu32 avg_lower_wmark;
|
|
vu32 count_weight;
|
|
vu32 count;
|
|
vu32 avg_count;
|
|
vu32 intr_status;
|
|
vu32 ctrl2;
|
|
vu32 rsvd[5];
|
|
} actmon_dev_reg_t;
|
|
|
|
void actmon_hist_enable(actmon_hist_src_t src)
|
|
{
|
|
ACTMON(ACTMON_HISTOGRAM_CONFIG) = ACTMON_HIST_CFG_SOURCE(src) | ACTMON_HIST_CFG_ACTIVE;
|
|
ACTMON(ACTMON_HISTOGRAM_CTRL) = ACTMON_HIST_CTRL_CLEAR_ALL;
|
|
}
|
|
|
|
void actmon_hist_disable()
|
|
{
|
|
ACTMON(ACTMON_HISTOGRAM_CONFIG) = 0;
|
|
}
|
|
|
|
void actmon_hist_get(u32 *histogram)
|
|
{
|
|
if (histogram)
|
|
{
|
|
for (u32 i = 0; i < ACTMON_HISTOGRAM_DATA_NUM; i++)
|
|
histogram[i] = ACTMON(ACTMON_HISTOGRAM_DATA_BASE + i * sizeof(u32));
|
|
}
|
|
}
|
|
|
|
void actmon_dev_enable(actmon_dev_t dev)
|
|
{
|
|
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
|
|
|
|
regs->init_avg = ACTMON_FREQ * ACTMON_PERIOD_MS * DEV_COUNT_WEIGHT / 100;
|
|
regs->count_weight = DEV_COUNT_WEIGHT;
|
|
|
|
regs->ctrl = ACTMON_DEV_CTRL_ENB | ACTMON_DEV_CTRL_ENB_PERIODIC | ACTMON_DEV_CTRL_K_VAL(7); // 128 samples average.
|
|
}
|
|
|
|
void actmon_dev_disable(actmon_dev_t dev)
|
|
{
|
|
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
|
|
|
|
regs->ctrl = 0;
|
|
}
|
|
|
|
u32 actmon_dev_get_load(actmon_dev_t dev)
|
|
{
|
|
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
|
|
|
|
// Get load-based sampling. 1 decimal point precision.
|
|
u32 load = regs->count * 100 / (ACTMON_FREQ / (ACTMON_PERIOD_MS * DEV_COUNT_WEIGHT));
|
|
|
|
return load;
|
|
}
|
|
|
|
u32 actmon_dev_get_load_avg(actmon_dev_t dev)
|
|
{
|
|
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
|
|
|
|
// Get load-based sampling. 1 decimal point precision.
|
|
u32 avg_load = regs->avg_count * 100 / (ACTMON_FREQ / (ACTMON_PERIOD_MS * DEV_COUNT_WEIGHT));
|
|
|
|
return avg_load;
|
|
}
|
|
|
|
void atmon_dev_all_disable()
|
|
{
|
|
// TODO: do a global reset?
|
|
}
|
|
|
|
void actmon_init()
|
|
{
|
|
clock_enable_actmon();
|
|
|
|
// Set period.
|
|
ACTMON(ACTMON_GLB_PERIOD_CTRL) = ACTMON_GLB_PERIOD_SAMPLE(ACTMON_PERIOD_MS);
|
|
}
|
|
|
|
void actmon_end()
|
|
{
|
|
clock_disable_actmon();
|
|
} |