mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 09:42:19 +03:00
Actmon is a hardware block that can be used to track the activity of certain hardware units. It can boost EMC clock depending on the memory traffic among various client. It is called central actmon as it monitors central activity for example MC activity. Add central activity monitor driver. Bug 3625675 Change-Id: I1a5918e7d84bc247f694f53f965c28888b773c91 Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2705395 GVS: Gerrit_Virtual_Submit
199 lines
5.5 KiB
C
199 lines
5.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
// Copyright (c) 2022, NVIDIA CORPORATION, All rights reserved.
|
|
|
|
#ifndef ACTMON_COMMON_H
|
|
|
|
#include <linux/io.h>
|
|
|
|
/* START: These device register offsets have common value across socs */
|
|
#define ACTMON_CMN_DEV_CTRL 0x00
|
|
#define ACTMON_CMN_DEV_CTRL_ENB (0x1 << 31)
|
|
#define ACTMON_CMN_DEV_CTRL_UP_WMARK_NUM_SHIFT 26
|
|
#define ACTMON_CMN_DEV_CTRL_UP_WMARK_NUM_MASK (0x7 << 26)
|
|
#define ACTMON_CMN_DEV_CTRL_DOWN_WMARK_NUM_SHIFT 21
|
|
#define ACTMON_CMN_DEV_CTRL_DOWN_WMARK_NUM_MASK (0x7 << 21)
|
|
|
|
/* Common dev interrupt status bits across socs */
|
|
#define ACTMON_CMN_DEV_INTR_UP_WMARK (0x1 << 31)
|
|
#define ACTMON_CMN_DEV_INTR_DOWN_WMARK (0x1 << 30)
|
|
/* END: common device regs across socs */
|
|
|
|
#define ACTMON_DEFAULT_AVG_WINDOW_LOG2 7
|
|
#define ACTMON_DEFAULT_AVG_BAND 6 /* 1/10 of % */
|
|
#define ACTMON_DEFAULT_SAMPLING_PERIOD 7
|
|
|
|
#define DEFAULT_SUSPEND_FREQ 204000
|
|
#define DEFAULT_BOOST_UP_COEF 200
|
|
#define DEFAULT_BOOST_DOWN_COEF 50
|
|
#define DEFAULT_BOOST_UP_THRESHOLD 30
|
|
#define DEFAULT_BOOST_DOWN_THRESHOLD 20
|
|
#define DEFAULT_UP_WMARK_WINDOW 3
|
|
#define DEFAULT_DOWN_WMARK_WINDOW 2
|
|
#define DEFAULT_EWMA_COEF_K 6
|
|
#define DEFAULT_COUNT_WEIGHT 0x53
|
|
#define FREQ_SAMPLER 1
|
|
#define LOAD_SAMPLER 0
|
|
#define DEFAULT_ACTMON_TYPE FREQ_SAMPLER
|
|
/* Maximum frequency EMC is running at when sourced from PLLP. This is
|
|
* really a short-cut, but it is true for all Tegra3 platforms
|
|
*/
|
|
#define EMC_PLLP_FREQ_MAX 204000
|
|
|
|
enum actmon_devices { /* Should match with device sequence in dt */
|
|
MC_ALL, /* instance 1 */
|
|
MC_CPU, /* instance 0 */
|
|
MAX_DEVICES,
|
|
};
|
|
|
|
enum actmon_type {
|
|
ACTMON_LOAD_SAMPLER,
|
|
ACTMON_FREQ_SAMPLER,
|
|
};
|
|
|
|
enum actmon_state {
|
|
ACTMON_UNINITIALIZED = -1,
|
|
ACTMON_OFF = 0,
|
|
ACTMON_ON = 1,
|
|
ACTMON_SUSPENDED = 2,
|
|
};
|
|
struct actmon_dev;
|
|
struct actmon_drv_data;
|
|
struct dev_reg_ops {
|
|
void (*set_init_avg)(u32 value, void __iomem *base);
|
|
void (*set_avg_up_wm)(u32 value, void __iomem *base);
|
|
void (*set_avg_dn_wm)(u32 value, void __iomem *base);
|
|
void (*set_dev_up_wm)(u32 value, void __iomem *base);
|
|
void (*set_dev_dn_wm)(u32 value, void __iomem *base);
|
|
void (*enb_dev_wm)(u32 *value);
|
|
void (*disb_dev_up_wm)(u32 *value);
|
|
void (*disb_dev_dn_wm)(u32 *value);
|
|
void (*set_intr_st)(u32 value, void __iomem *base);
|
|
void (*init_dev_cntrl)(struct actmon_dev *dev, void __iomem *base);
|
|
void (*enb_dev_intr)(u32 value, void __iomem *base);
|
|
void (*enb_dev_intr_all)(void __iomem *base);
|
|
void (*set_cnt_wt)(u32 value, void __iomem *base);
|
|
u32 (*get_intr_st)(void __iomem *base);
|
|
u32 (*get_dev_intr_enb)(void __iomem *base);
|
|
u32 (*get_dev_intr)(void __iomem *base);
|
|
u32 (*get_raw_cnt)(void __iomem *base);
|
|
u32 (*get_avg_cnt)(void __iomem *base);
|
|
u32 (*get_cum_cnt)(void __iomem *base);
|
|
};
|
|
|
|
/* Units:
|
|
* - frequency in kHz
|
|
* - coefficients, and thresholds in %
|
|
* - sampling period in ms
|
|
* - window in sample periods (value = setting + 1)
|
|
*/
|
|
struct actmon_dev {
|
|
struct device_node *dn;
|
|
u32 reg_offs;
|
|
u32 glb_status_irq_mask;
|
|
const char *dev_name;
|
|
const char *con_id;
|
|
void *clnt;
|
|
|
|
unsigned long max_freq;
|
|
unsigned long target_freq;
|
|
unsigned long cur_freq;
|
|
unsigned long suspend_freq;
|
|
|
|
unsigned long avg_actv_freq;
|
|
unsigned long avg_band_freq;
|
|
unsigned int avg_sustain_coef;
|
|
u32 avg_count;
|
|
u32 avg_dependency_threshold;
|
|
|
|
unsigned long boost_freq;
|
|
unsigned long boost_freq_step;
|
|
unsigned int boost_up_coef;
|
|
unsigned int boost_down_coef;
|
|
unsigned int boost_up_threshold;
|
|
unsigned int boost_down_threshold;
|
|
|
|
u8 up_wmark_window;
|
|
u8 down_wmark_window;
|
|
u8 avg_window_log2;
|
|
u32 count_weight;
|
|
|
|
enum actmon_type type;
|
|
enum actmon_state state;
|
|
enum actmon_state saved_state;
|
|
|
|
bool bwmgr_disable;
|
|
struct clk *dram_clk_handle;
|
|
|
|
struct dev_reg_ops ops;
|
|
void (*actmon_dev_set_rate)(struct actmon_dev *adev, unsigned long freq);
|
|
unsigned long (*actmon_dev_get_rate)(struct actmon_dev *adev);
|
|
unsigned long (*actmon_dev_post_change_rate)(struct actmon_dev *adev,
|
|
void *v);
|
|
void (*actmon_dev_clk_enable)(struct actmon_dev *adev);
|
|
spinlock_t lock;
|
|
struct notifier_block rate_change_nb;
|
|
struct kobj_attribute avgact_attr;
|
|
};
|
|
|
|
struct actmon_reg_ops {
|
|
void (*set_sample_prd)(u32 value, void __iomem *base);
|
|
void (*set_glb_intr)(u32 value, void __iomem *base);
|
|
u32 (*get_glb_intr_st)(void __iomem *base);
|
|
};
|
|
struct actmon_drv_data {
|
|
void __iomem *base;
|
|
struct platform_device *pdev;
|
|
int virq;
|
|
struct clk *actmon_clk;
|
|
u8 sample_period;
|
|
unsigned long freq;
|
|
struct reset_control *actmon_rst;
|
|
struct actmon_dev devices[MAX_DEVICES];
|
|
int (*actmon_dev_platform_init)(struct actmon_dev *adev,
|
|
struct platform_device *pdev);
|
|
int (*clock_init)(struct platform_device *pdev);
|
|
int (*clock_deinit)(struct platform_device *pdev);
|
|
int (*reset_init)(struct platform_device *pdev);
|
|
int (*reset_deinit)(struct platform_device *pdev);
|
|
void (*dev_free_resource)(struct actmon_dev *adev,
|
|
struct platform_device *pdev);
|
|
struct actmon_reg_ops ops;
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct dentry *dfs_root;
|
|
#endif
|
|
struct kobject *actmon_kobj;
|
|
};
|
|
|
|
static inline void actmon_wmb(void)
|
|
{
|
|
dsb(sy);
|
|
}
|
|
|
|
static inline u32 actmon_dev_readl(void __iomem *base,
|
|
u32 offset)
|
|
{
|
|
return __raw_readl(base + offset);
|
|
}
|
|
|
|
static inline void actmon_dev_writel(void __iomem *base, u32
|
|
offset, u32 val)
|
|
{
|
|
__raw_writel(val, base + offset);
|
|
}
|
|
|
|
#if defined(CONFIG_TEGRA_CENTRAL_ACTMON)
|
|
int tegra_actmon_register(struct actmon_drv_data *actmon);
|
|
int tegra_actmon_remove(struct platform_device *pdev);
|
|
#else
|
|
static inline int tegra_actmon_register(struct actmon_drv_data *actmon)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline int tegra_actmon_remove(struct platform_device *pdev)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
#endif /* ACTMON_COMMON_H */
|