diff --git a/bdk/bdk.h b/bdk/bdk.h index 3782509..0be2d5a 100644 --- a/bdk/bdk.h +++ b/bdk/bdk.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/bdk/soc/actmon.c b/bdk/soc/actmon.c new file mode 100644 index 0000000..4df80eb --- /dev/null +++ b/bdk/soc/actmon.c @@ -0,0 +1,173 @@ +/* + * 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 . + */ + +#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 + +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 unk[5]; +} actmon_dev_reg_t; + +u32 sample_period = 0; + +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 = 0; + regs->count_weight = 5; + + regs->ctrl = ACTMON_DEV_CTRL_ENB | ACTMON_DEV_CTRL_ENB_PERIODIC; +} + +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 / (ACTMON_FREQ / 1000); + + 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 / (ACTMON_FREQ / 1000); + + return avg_load; +} + +void atmon_dev_all_disable() +{ + // TODO: do a global reset? +} + +void actmon_init() +{ + clock_enable_actmon(); + + // Set period to 200ms. + ACTMON(ACTMON_GLB_PERIOD_CTRL) &= ~ACTMON_GLB_PERIOD_USEC; + ACTMON(ACTMON_GLB_PERIOD_CTRL) |= ACTMON_GLB_PERIOD_SAMPLE(200); +} + +void actmon_end() +{ + clock_disable_actmon(); +} \ No newline at end of file diff --git a/bdk/soc/actmon.h b/bdk/soc/actmon.h new file mode 100644 index 0000000..dc9d0c5 --- /dev/null +++ b/bdk/soc/actmon.h @@ -0,0 +1,62 @@ +/* + * 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 . + */ + +#ifndef __ACTMON_H_ +#define __ACTMON_H_ + +#include + +typedef enum _actmon_dev_t +{ + ACTMON_DEV_CPU, + ACTMON_DEV_BPMP, + ACTMON_DEV_AHB, + ACTMON_DEV_APB, + ACTMON_DEV_CPU_FREQ, + ACTMON_DEV_MC_ALL, + ACTMON_DEV_MC_CPU, + + ACTMON_DEV_NUM, +} actmon_dev_t; + +typedef enum _actmon_hist_src_t +{ + ACTMON_HIST_SRC_NONE = 0, + ACTMON_HIST_SRC_AHB = 1, + ACTMON_HIST_SRC_APB = 2, + ACTMON_HIST_SRC_BPMP = 3, + ACTMON_HIST_SRC_CPU = 4, + ACTMON_HIST_SRC_MC_ALL = 5, + ACTMON_HIST_SRC_MC_CPU = 6, + ACTMON_HIST_SRC_CPU_FREQ = 7, + ACTMON_HIST_SRC_NA = 8, + ACTMON_HIST_SRC_APB_MMIO = 9, +} actmon_hist_src_t; + +void actmon_hist_enable(actmon_hist_src_t src); +void actmon_hist_disable(); +void actmon_hist_get(u32 *histogram); +void actmon_dev_enable(actmon_dev_t dev); +void actmon_dev_disable(actmon_dev_t dev); +u32 actmon_dev_get_load(actmon_dev_t dev); +u32 actmon_dev_get_load_avg(actmon_dev_t dev); +void atmon_dev_all_disable(); +void actmon_init(); +void actmon_end(); + +#endif \ No newline at end of file diff --git a/bdk/soc/clock.c b/bdk/soc/clock.c index 65fdf51..d01ffd2 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2022 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, @@ -100,6 +100,10 @@ static clock_t _clock_sdmmc_legacy_tm = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66 }; +static clock_t _clock_actmon = { + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz. +}; + void clock_enable(const clock_t *clk) { // Put clock into reset. @@ -279,6 +283,16 @@ void clock_disable_pwm() clock_disable(&_clock_pwm); } +void clock_enable_actmon() +{ + clock_enable(&_clock_actmon); +} + +void clock_disable_actmon() +{ + clock_disable(&_clock_actmon); +} + void clock_enable_pllx() { // Configure and enable PLLX if disabled. diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index 00bbfd7..23ee53f 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2022 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, @@ -660,6 +660,9 @@ void clock_enable_coresight(); void clock_disable_coresight(); void clock_enable_pwm(); void clock_disable_pwm(); +void clock_enable_actmon(); +void clock_disable_actmon(); + void clock_enable_pllx(); void clock_enable_pllc(u32 divn); void clock_disable_pllc();