Files
linux-nv-oot/include/linux/platform/tegra/actmon_common.h
Laxman Dewangan 527743a5c3 platform/tegra: Add Tegra Central Activity Monitor driver
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
2022-05-01 09:26:33 -07:00

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 */