blob: 66e97d0c79bc5ad5d12e4dead6014d62aaefe291 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * mck_memorybus: devfreq device driver for MCK memory controller.
3 *
4 * Copyright (C) 2013 Marvell International Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __LINUX_MCK_MEMORYBUS_H__
12#define __LINUX_MCK_MEMORYBUS_H__
13
14#define DDR_FREQ_MAX 20
15
16#define DEFAULT_MCK_BASE_ADDR (0xc0100000)
17#define DEFAULT_MCK_REG_SIZE (SZ_2K)
18#define DEFAULT_PERCNT_IN_USE (4)
19
20#define MCK4_VER_SHIFT (12)
21#define MCK4_VER_MASK (0xf << MCK4_VER_SHIFT)
22
23#define MCK4_SDRAM_CTRL4 (0x058)
24#define MCK4_SDRAM_CTRL4_BL_SHIFT (22)
25#define MCK4_SDRAM_CTRL4_BL_MASK (0x3 << MCK4_SDRAM_CTRL4_BL_SHIFT)
26
27#define MCK4_PERF_CONFIG (0x440)
28#define MCK4_PERF_STATUS (0x444)
29#define MCK4_PERF_CONTRL (0x448)
30#define MCK4_PERF_CNT_0 (0x450)
31#define MCK4_PERF_CNT_1 (0x454)
32#define MCK4_PERF_CNT_2 (0x458)
33#define MCK4_PERF_CNT_3 (0x45C)
34#define MCK4_PERF_CNT_BASE MCK4_PERF_CNT_0
35#define MCK4_INTR_STATUS (0x480)
36#define MCK4_INTR_EN (0x484)
37
38#define MCK4_PERCNT_NUM (4)
39
40#define MCK5_VER_SHIFT (24)
41#define MCK5_VER_MASK (0xf << MCK5_VER_SHIFT)
42
43#define MCK5_CH0_SDRAM_CFG1 (0x300)
44#define MCK5_CH0_SDRAM_CFG1_BL_SHIFT (20)
45#define MCK5_CH0_SDRAM_CFG1_BL_MASK (0x3 << MCK5_CH0_SDRAM_CFG1_BL_SHIFT)
46
47#define MCK5_PERF_CONFIG (0x100)
48#define MCK5_PERF_STATUS (0x108)
49#define MCK5_PERF_CONTRL (0x10C)
50#define MCK5_PERF_CNT_0 (0x110)
51#define MCK5_PERF_CNT_1 (0x114)
52#define MCK5_PERF_CNT_2 (0x118)
53#define MCK5_PERF_CNT_3 (0x11C)
54#define MCK5_PERF_CNT_4 (0x120)
55#define MCK5_PERF_CNT_5 (0x124)
56#define MCK5_PERF_CNT_6 (0x128)
57#define MCK5_PERF_CNT_7 (0x12C)
58#define MCK5_PERF_CNT_BASE MCK5_PERF_CNT_0
59#define MCK5_INTR_STATUS (0x140)
60#define MCK5_INTR_EN (0x144)
61
62#define MCK5_PERCNT_NUM (8)
63
64#define MCK5_WCB_DRAINING (0x1 << 28)
65#define MCK5_WP_STATUS (0x10)
66
67#define MCK5_WCB_DRAIN_REQ (0x1 << 1)
68#define MCK5_USER_CMD0 (0x20)
69
70#define PC_INT_EN (0)
71
72#define NZAS_MC_MC_Control_0 (0x044)
73#define NZAS_MC_MC_Control_0_BL_SHIFT (16)
74#define NZAS_MC_MC_Control_0_BL_MASK (0x7 << NZAS_MC_MC_Control_0_BL_SHIFT)
75#define NZAS_MC_WCB_DRAINING (0x1 << 13)
76#define NZAS_MC_WP_STATUS (0x04)
77
78#define APMU_MC_HW_SLP_TYPE (0x00b0)
79#define MODE_4X_EN (0x1 << 8)
80
81#define AXI_MON_CTRL (0x0)
82#define AXI_MON_X (0x4)
83#define AXI_MON_Y (0x8)
84#define AXI_MON_DATA (0xC)
85
86#define NR_AXI_MON_PORT (4)
87
88#define DDR_TZ_RANGE0_LOW (0x080)
89#define DDR_ADC_ERR_INFO (0x150)
90#define DDR_ADC_ERR_ADDR_L (0x154)
91#define DDR_ADC_ERR_ADDR_H (0x158)
92#define DDR_ADC_ERR_ID (0x15C)
93#define DDR_ADC_INFO_CLR (0x1 << 24)
94#define DDR_INTR_EN_OVFL (0x1 << 0)
95#define DDR_INTR_EN_OVFL_ADC (0x5 << 0)
96
97enum mck_version {
98 MCK_UNKNOWN = 0,
99 MCK5 = 5,
100 NZAS_MC = 6,
101};
102
103/* struct of pmu related registers' offset */
104struct mck_pmu_regs_offset {
105 unsigned int cfg; /* PC Configuration register */
106 unsigned int cnt_stat; /* PC Status register */
107 unsigned int ctrl; /* PC Control register */
108 unsigned int cnt_base; /* PC register 0 */
109 unsigned int intr_stat; /* MCK Interrupt Status register */
110 unsigned int intr_en; /* MCK Interrupt Enable register*/
111
112#ifndef CONFIG_OPTEE
113 unsigned int adc_err_info; /* adc_err_info */
114 unsigned int adc_err_addr_l; /* adc_err_addr_l */
115 unsigned int adc_err_addr_h; /* adc_err_addr_h */
116 unsigned int adc_err_id; /* adc_err_id */
117#endif
118};
119
120/*
121 * reg[0] ddr_totalticks
122 * reg[1] ddr_DPC_idle
123 * reg[2] ddr_rw_cmd
124 * reg[3] ddr_nobus_notidle
125 */
126struct perf_counters {
127 u64 *reg;
128};
129
130struct mck_ppmu {
131 void __iomem *hw_base;
132 /* the version of mck controller */
133 unsigned int version;
134 /* number of performance counters which are used for profiler */
135 unsigned int pmucnt_in_use;
136 /* offset of all pmu related registers */
137 struct mck_pmu_regs_offset mck_regs;
138 /*
139 * SW u64 performance counters for each DDR frequencies.
140 * It can store all events number from SOD without overflow.
141 * To get a accurate value, please call update before read it.
142 */
143 struct perf_counters ddr_ticks[DDR_FREQ_MAX];
144};
145
146struct ddr_stats_data {
147 /* snapshot of ddr_ticks for ddr stats */
148 struct perf_counters ddr_ticks_base[DDR_FREQ_MAX];
149 /* diff value of current ddr_ticks and ddr_ticks_base */
150 struct perf_counters ddr_ticks_diff[DDR_FREQ_MAX];
151 /* indicating if ddr stats are working */
152 int is_ddr_stats_working;
153
154 u32 axi_read_bytes[NR_AXI_MON_PORT];
155 u32 axi_write_bytes[NR_AXI_MON_PORT];
156 u32 max_read_latency[NR_AXI_MON_PORT];
157 u32 max_write_latency[NR_AXI_MON_PORT];
158 unsigned long ddr_cycles;
159 unsigned long data_cycles;
160};
161
162/* snapshot of ddr_ticks to get tick diff in profiling window */
163struct ddr_profiler_data {
164 u64 total_ticks_base[DDR_FREQ_MAX];
165 u64 data_ticks_base[DDR_FREQ_MAX];
166};
167
168struct ddr_devfreq_data {
169 struct devfreq *devfreq;
170 struct clk *ddr_clk;
171 void __iomem *axi_mon_base;
172 struct mck_ppmu dmc;
173 unsigned int bst_len; /* ddr burst length */
174 unsigned long last_polled_at;
175 spinlock_t lock;
176
177 /* used for performance optimization */
178 u32 high_upthrd_swp;
179 u32 high_upthrd;
180 u32 cpu_up;
181 u32 gpu_up;
182 /* notifier block for ddr upthreshold change */
183 struct notifier_block freq_transition;
184
185 /* DDR frequency table used for platform */
186 unsigned int ddr_freq_tbl[DDR_FREQ_MAX]; /* unit Khz */
187 unsigned int ddr_freq_tbl_len;
188 unsigned int cur_ddr_idx;
189
190 /* for ddr_profiling file node */
191 struct ddr_stats_data ddr_stats;
192
193 /* for ddr freq profiler */
194 struct ddr_profiler_data ddr_profiler;
195
196 int irq;
197 struct work_struct overflow_work;
198
199 /* used for debug interface */
200 atomic_t is_disabled;
201 atomic_t is_stopped;
202
203 struct timespec64 start_ts;
204 struct timespec64 stop_ts;
205 u32 mode_4x_en;
206
207 unsigned int workload;
208 unsigned int intr_en_val;
209};
210
211void __iomem *get_apmu_base_va(void);
212
213extern void get_fc_spinlock(void);
214extern void put_fc_spinlock(void);
215extern void put_fc_lock(void __iomem *apmu_base);
216extern int get_fc_lock(void __iomem *apmu_base, int has_hwdfcwr);
217#endif /* __LINUX_MCK_MEMORYBUS_H__ */