aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/msm/kgsl_gmu.h
blob: 19fa9728ca673a0cd90a471d682db229d717eaf6 (plain)
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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 __KGSL_GMU_H
#define __KGSL_GMU_H

#include "kgsl_hfi.h"

#define FW_VER_MAJOR(ver)		(((ver)>>28) & 0xFF)
#define FW_VER_MINOR(ver)		(((ver)>>16) & 0xFFF)
#define FW_VERSION(major, minor)	\
		(((major) << 28) | (((minor) & 0xFFF) << 16))

#define GMU_INT_WDOG_BITE		BIT(0)
#define GMU_INT_RSCC_COMP		BIT(1)
#define GMU_INT_FENCE_ERR		BIT(3)
#define GMU_INT_DBD_WAKEUP		BIT(4)
#define GMU_INT_HOST_AHB_BUS_ERR	BIT(5)
#define GMU_AO_INT_MASK		\
		(GMU_INT_WDOG_BITE |	\
		GMU_INT_HOST_AHB_BUS_ERR |	\
		GMU_INT_FENCE_ERR)

#define MAX_GMUFW_SIZE	0x2000	/* in bytes */
#define FENCE_RANGE_MASK	((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0))

#define FENCE_STATUS_WRITEDROPPED0_MASK 0x1
#define FENCE_STATUS_WRITEDROPPED1_MASK 0x2

/* Bitmask for GPU low power mode enabling and hysterisis*/
#define SPTP_ENABLE_MASK (BIT(2) | BIT(0))
#define IFPC_ENABLE_MASK (BIT(1) | BIT(0))
#define HW_NAP_ENABLE_MASK	BIT(0)
#define MIN_BW_ENABLE_MASK	BIT(12)
#define MIN_BW_HYST		0xFA0

/* Bitmask for RPMH capability enabling */
#define RPMH_INTERFACE_ENABLE	BIT(0)
#define LLC_VOTE_ENABLE			BIT(4)
#define DDR_VOTE_ENABLE			BIT(8)
#define MX_VOTE_ENABLE			BIT(9)
#define CX_VOTE_ENABLE			BIT(10)
#define GFX_VOTE_ENABLE			BIT(11)
#define RPMH_ENABLE_MASK	(RPMH_INTERFACE_ENABLE	| \
				LLC_VOTE_ENABLE		| \
				DDR_VOTE_ENABLE		| \
				MX_VOTE_ENABLE		| \
				CX_VOTE_ENABLE		| \
				GFX_VOTE_ENABLE)

/* Bitmask for GPU idle status check */
#define GPUBUSYIGNAHB		BIT(23)
#define CXGXCPUBUSYIGNAHB	BIT(30)

/* GMU timeouts */
#define GMU_IDLE_TIMEOUT        100 /* ms */

/* Constants for GMU OOBs */
#define OOB_BOOT_OPTION         0
#define OOB_SLUMBER_OPTION      1

/* Bitmasks for GMU OOBs */
#define OOB_BOOT_SLUMBER_SET_MASK	BIT(22)
#define OOB_BOOT_SLUMBER_CHECK_MASK	BIT(30)
#define OOB_BOOT_SLUMBER_CLEAR_MASK	BIT(30)
#define OOB_DCVS_SET_MASK		BIT(23)
#define OOB_DCVS_CHECK_MASK		BIT(31)
#define OOB_DCVS_CLEAR_MASK		BIT(31)
#define OOB_GPU_SET_MASK		BIT(16)
#define OOB_GPU_CHECK_MASK		BIT(24)
#define OOB_GPU_CLEAR_MASK		BIT(24)
#define OOB_PERFCNTR_SET_MASK		BIT(17)
#define OOB_PERFCNTR_CHECK_MASK		BIT(25)
#define OOB_PERFCNTR_CLEAR_MASK		BIT(25)
#define OOB_PREEMPTION_SET_MASK		BIT(18)
#define OOB_PREEMPTION_CHECK_MASK	BIT(26)
#define OOB_PREEMPTION_CLEAR_MASK	BIT(26)

/*
 * Wait time before trying to write the register again.
 * Hopefully the GMU has finished waking up during this delay.
 * This delay must be less than the IFPC main hysteresis or
 * the GMU will start shutting down before we try again.
 */
#define GMU_WAKEUP_DELAY_US 10
/* Max amount of tries to wake up the GMU. */
#define GMU_WAKEUP_RETRY_MAX 60

/* Bits for the flags field in the gmu structure */
enum gmu_flags {
	GMU_BOOT_INIT_DONE = 0,
	GMU_CLK_ON = 1,
	GMU_HFI_ON = 2,
	GMU_FAULT = 3,
	GMU_DCVS_REPLAY = 4,
};

/**
 * struct gmu_memdesc - Gmu shared memory object descriptor
 * @hostptr: Kernel virtual address
 * @gmuaddr: GPU virtual address
 * @physaddr: Physical address of the memory object
 * @size: Size of the memory object
 * @attr: memory attributes for this memory
 */
struct gmu_memdesc {
	void *hostptr;
	uint64_t gmuaddr;
	phys_addr_t physaddr;
	uint64_t size;
	uint32_t attr;
};

struct gmu_bw_votes {
	uint32_t cmds_wait_bitmask;
	uint32_t cmds_per_bw_vote;
	uint32_t cmd_addrs[MAX_BW_CMDS];
	uint32_t cmd_data[MAX_GX_LEVELS][MAX_BW_CMDS];
};

struct rpmh_votes_t {
	struct arc_vote_desc gx_votes[MAX_GX_LEVELS];
	struct arc_vote_desc cx_votes[MAX_CX_LEVELS];
	struct gmu_bw_votes ddr_votes;
	struct gmu_bw_votes cnoc_votes;
};

#define MAX_GMU_CLKS 6
#define DEFAULT_GMU_FREQ_IDX 1

/*
 * These are the different ways the GMU can boot. GMU_WARM_BOOT is waking up
 * from slumber. GMU_COLD_BOOT is booting for the first time. GMU_RESET
 * is a soft reset of the GMU.
 */
enum gmu_boot {
	GMU_WARM_BOOT = 0,
	GMU_COLD_BOOT = 1,
	GMU_RESET = 2
};

enum gmu_load_mode {
	CACHED_LOAD_BOOT,
	CACHED_BOOT,
	TCM_BOOT,
	TCM_LOAD_BOOT,
	INVALID_LOAD
};

enum gmu_pwrctrl_mode {
	GMU_FW_START,
	GMU_FW_STOP,
	GMU_SUSPEND,
	GMU_DCVS_NOHFI,
	GMU_NOTIFY_SLUMBER,
	INVALID_POWER_CTRL
};

enum gpu_idle_level {
	GPU_HW_ACTIVE = 0x0,
	GPU_HW_SPTP_PC = 0x2,
	GPU_HW_IFPC = 0x3,
	GPU_HW_NAP = 0x4,
	GPU_HW_MIN_VOLT = 0x5,
	GPU_HW_MIN_DDR = 0x6,
	GPU_HW_SLUMBER = 0xF
};

/**
 * struct gmu_device - GMU device structure
 * @ver: GMU FW version, read from GMU
 * @reg_phys: GMU CSR physical address
 * @reg_virt: GMU CSR virtual address
 * @reg_len: GMU CSR range
 * @gmu2gpu_offset: address difference between GMU register set
 *	and GPU register set, the offset will be used when accessing
 *	gmu registers using offset defined in GPU register space.
 * @pdc_reg_virt: starting kernel virtual address for RPMh PDC registers
 * @gmu_interrupt_num: GMU interrupt number
 * @fw_image: descriptor of GMU memory that has GMU image in it
 * @hfi_mem: pointer to HFI shared memory
 * @dump_mem: pointer to GMU debug dump memory
 * @hfi: HFI controller
 * @lm_config: GPU LM configuration data
 * @lm_dcvs_level: Minimal DCVS level that enable LM. LM disable in
 *		lower levels
 * @bcl_config: Battery Current Limit configuration data
 * @gmu_freqs: GMU frequency table with lowest freq at index 0
 * @gpu_freqs: GPU frequency table with lowest freq at index 0
 * @num_gmupwrlevels: number GMU frequencies in GMU freq table
 * @num_gpupwrlevels: number GPU frequencies in GPU freq table
 * @num_bwlevel: number of GPU BW levels
 * @num_cnocbwlevel: number CNOC BW levels
 * @rpmh_votes: RPMh TCS command set for GPU, GMU voltage and bw scaling
 * @cx_gdsc: CX headswitch that controls power of GMU and
		subsystem peripherals
 * @gx_gdsc: GX headswitch that controls power of GPU subsystem
 * @clks: GPU subsystem clocks required for GMU functionality
 * @load_mode: GMU FW load/boot mode
 * @flags: GMU power control flags
 * @wakeup_pwrlevel: GPU wake up power/DCVS level in case different
 *		than default power level
 * @pcl: GPU BW scaling client
 * @ccl: CNOC BW scaling client
 * @idle_level: Minimal GPU idle power level
 * @fault_count: GMU fault count
 */
struct gmu_device {
	unsigned int ver;
	struct platform_device *pdev;
	unsigned long reg_phys;
	void __iomem *reg_virt;
	unsigned int reg_len;
	unsigned int gmu2gpu_offset;
	void __iomem *pdc_reg_virt;
	unsigned int gmu_interrupt_num;
	struct gmu_memdesc fw_image;
	struct gmu_memdesc *hfi_mem;
	struct gmu_memdesc *dump_mem;
	struct kgsl_hfi hfi;
	struct limits_config lm_config;
	unsigned int lm_dcvs_level;
	unsigned int bcl_config;
	unsigned int gmu_freqs[MAX_CX_LEVELS];
	unsigned int gpu_freqs[MAX_GX_LEVELS];
	unsigned int num_gmupwrlevels;
	unsigned int num_gpupwrlevels;
	unsigned int num_bwlevels;
	unsigned int num_cnocbwlevels;
	struct rpmh_votes_t rpmh_votes;
	struct regulator *cx_gdsc;
	struct regulator *gx_gdsc;
	struct clk *clks[MAX_GMU_CLKS];
	enum gmu_load_mode load_mode;
	unsigned long flags;
	unsigned int wakeup_pwrlevel;
	unsigned int pcl;
	unsigned int ccl;
	unsigned int idle_level;
	unsigned int fault_count;
};

void gmu_snapshot(struct kgsl_device *device);
bool kgsl_gmu_isenabled(struct kgsl_device *device);
int gmu_probe(struct kgsl_device *device);
void gmu_remove(struct kgsl_device *device);
int allocate_gmu_image(struct gmu_device *gmu, unsigned int size);
int gmu_start(struct kgsl_device *device);
void gmu_stop(struct kgsl_device *device);
int gmu_dcvs_set(struct gmu_device *gmu, unsigned int gpu_pwrlevel,
		unsigned int bus_level);
#endif /* __KGSL_GMU_H */