summaryrefslogtreecommitdiffstats
path: root/include/linux/platform/tegra/actmon_common.h
blob: d1ed3866b616d15b0cae83b79391062b25d7aece (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Copyright (C) 2016-2018, NVIDIA Corporation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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.
 *
 */
#ifndef ACTMON_COMMON_H

#include <asm/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 {
	MC_ALL, /* Should match with device sequence in dt */
	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 *, 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;

	struct dev_reg_ops ops;
	void (*actmon_dev_set_rate)(struct actmon_dev *, unsigned long);
	unsigned long (*actmon_dev_get_rate)(struct actmon_dev *);
	unsigned long (*actmon_dev_post_change_rate)(struct actmon_dev *,
			void *v);
	void (*actmon_dev_clk_enable)(struct actmon_dev *);
	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 */