1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* Copyright (c) 2017 The Linux Foundation. All rights reserved. */ |
3 | |
4 | #ifndef _A6XX_GMU_H_ |
5 | #define _A6XX_GMU_H_ |
6 | |
7 | #include <linux/completion.h> |
8 | #include <linux/iopoll.h> |
9 | #include <linux/interrupt.h> |
10 | #include <linux/notifier.h> |
11 | #include <linux/soc/qcom/qcom_aoss.h> |
12 | #include "msm_drv.h" |
13 | #include "a6xx_hfi.h" |
14 | |
15 | struct a6xx_gmu_bo { |
16 | struct drm_gem_object *obj; |
17 | void *virt; |
18 | size_t size; |
19 | u64 iova; |
20 | }; |
21 | |
22 | /* |
23 | * These define the different GMU wake up options - these define how both the |
24 | * CPU and the GMU bring up the hardware |
25 | */ |
26 | |
27 | /* THe GMU has already been booted and the rentention registers are active */ |
28 | #define GMU_WARM_BOOT 0 |
29 | |
30 | /* the GMU is coming up for the first time or back from a power collapse */ |
31 | #define GMU_COLD_BOOT 1 |
32 | |
33 | /* |
34 | * These define the level of control that the GMU has - the higher the number |
35 | * the more things that the GMU hardware controls on its own. |
36 | */ |
37 | |
38 | /* The GMU does not do any idle state management */ |
39 | #define GMU_IDLE_STATE_ACTIVE 0 |
40 | |
41 | /* The GMU manages SPTP power collapse */ |
42 | #define GMU_IDLE_STATE_SPTP 2 |
43 | |
44 | /* The GMU does automatic IFPC (intra-frame power collapse) */ |
45 | #define GMU_IDLE_STATE_IFPC 3 |
46 | |
47 | struct a6xx_gmu { |
48 | struct device *dev; |
49 | |
50 | /* For serializing communication with the GMU: */ |
51 | struct mutex lock; |
52 | |
53 | struct msm_gem_address_space *aspace; |
54 | |
55 | void __iomem *mmio; |
56 | void __iomem *rscc; |
57 | |
58 | int hfi_irq; |
59 | int gmu_irq; |
60 | |
61 | struct device *gxpd; |
62 | struct device *cxpd; |
63 | |
64 | int idle_level; |
65 | |
66 | struct a6xx_gmu_bo hfi; |
67 | struct a6xx_gmu_bo debug; |
68 | struct a6xx_gmu_bo icache; |
69 | struct a6xx_gmu_bo dcache; |
70 | struct a6xx_gmu_bo dummy; |
71 | struct a6xx_gmu_bo log; |
72 | |
73 | int nr_clocks; |
74 | struct clk_bulk_data *clocks; |
75 | struct clk *core_clk; |
76 | struct clk *hub_clk; |
77 | |
78 | /* current performance index set externally */ |
79 | int current_perf_index; |
80 | |
81 | int nr_gpu_freqs; |
82 | unsigned long gpu_freqs[16]; |
83 | u32 gx_arc_votes[16]; |
84 | |
85 | int nr_gmu_freqs; |
86 | unsigned long gmu_freqs[4]; |
87 | u32 cx_arc_votes[4]; |
88 | |
89 | unsigned long freq; |
90 | |
91 | struct a6xx_hfi_queue queues[2]; |
92 | |
93 | bool initialized; |
94 | bool hung; |
95 | bool legacy; /* a618 or a630 */ |
96 | |
97 | /* For power domain callback */ |
98 | struct notifier_block pd_nb; |
99 | struct completion pd_gate; |
100 | |
101 | struct qmp *qmp; |
102 | }; |
103 | |
104 | static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) |
105 | { |
106 | return msm_readl(gmu->mmio + (offset << 2)); |
107 | } |
108 | |
109 | static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value) |
110 | { |
111 | msm_writel(value, gmu->mmio + (offset << 2)); |
112 | } |
113 | |
114 | static inline void |
115 | gmu_write_bulk(struct a6xx_gmu *gmu, u32 offset, const u32 *data, u32 size) |
116 | { |
117 | memcpy_toio(gmu->mmio + (offset << 2), data, size); |
118 | wmb(); |
119 | } |
120 | |
121 | static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or) |
122 | { |
123 | u32 val = gmu_read(gmu, offset: reg); |
124 | |
125 | val &= ~mask; |
126 | |
127 | gmu_write(gmu, offset: reg, value: val | or); |
128 | } |
129 | |
130 | static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi) |
131 | { |
132 | u64 val; |
133 | |
134 | val = (u64) msm_readl(gmu->mmio + (lo << 2)); |
135 | val |= ((u64) msm_readl(gmu->mmio + (hi << 2)) << 32); |
136 | |
137 | return val; |
138 | } |
139 | |
140 | #define gmu_poll_timeout(gmu, addr, val, cond, interval, timeout) \ |
141 | readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \ |
142 | interval, timeout) |
143 | |
144 | static inline u32 gmu_read_rscc(struct a6xx_gmu *gmu, u32 offset) |
145 | { |
146 | return msm_readl(gmu->rscc + (offset << 2)); |
147 | } |
148 | |
149 | static inline void gmu_write_rscc(struct a6xx_gmu *gmu, u32 offset, u32 value) |
150 | { |
151 | msm_writel(value, gmu->rscc + (offset << 2)); |
152 | } |
153 | |
154 | #define gmu_poll_timeout_rscc(gmu, addr, val, cond, interval, timeout) \ |
155 | readl_poll_timeout((gmu)->rscc + ((addr) << 2), val, cond, \ |
156 | interval, timeout) |
157 | |
158 | /* |
159 | * These are the available OOB (out of band requests) to the GMU where "out of |
160 | * band" means that the CPU talks to the GMU directly and not through HFI. |
161 | * Normally this works by writing a ITCM/DTCM register and then triggering a |
162 | * interrupt (the "request" bit) and waiting for an acknowledgment (the "ack" |
163 | * bit). The state is cleared by writing the "clear' bit to the GMU interrupt. |
164 | * |
165 | * These are used to force the GMU/GPU to stay on during a critical sequence or |
166 | * for hardware workarounds. |
167 | */ |
168 | |
169 | enum a6xx_gmu_oob_state { |
170 | /* |
171 | * Let the GMU know that a boot or slumber operation has started. The value in |
172 | * REG_A6XX_GMU_BOOT_SLUMBER_OPTION lets the GMU know which operation we are |
173 | * doing |
174 | */ |
175 | GMU_OOB_BOOT_SLUMBER = 0, |
176 | /* |
177 | * Let the GMU know to not turn off any GPU registers while the CPU is in a |
178 | * critical section |
179 | */ |
180 | GMU_OOB_GPU_SET, |
181 | /* |
182 | * Set a new power level for the GPU when the CPU is doing frequency scaling |
183 | */ |
184 | GMU_OOB_DCVS_SET, |
185 | /* |
186 | * Used to keep the GPU on for CPU-side reads of performance counters. |
187 | */ |
188 | GMU_OOB_PERFCOUNTER_SET, |
189 | }; |
190 | |
191 | void a6xx_hfi_init(struct a6xx_gmu *gmu); |
192 | int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); |
193 | void a6xx_hfi_stop(struct a6xx_gmu *gmu); |
194 | int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu); |
195 | int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index); |
196 | |
197 | bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); |
198 | bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); |
199 | void a6xx_sptprac_disable(struct a6xx_gmu *gmu); |
200 | int a6xx_sptprac_enable(struct a6xx_gmu *gmu); |
201 | |
202 | #endif |
203 | |