MALI: rockchip: upgrade midgard DDK to r11p0-00rel0
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / mali_kbase_gator_api.c
1 /*
2  *
3  * (C) COPYRIGHT 2014-2015 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16
17
18 #include "mali_kbase.h"
19 #include "mali_kbase_hw.h"
20 #include "mali_kbase_mem_linux.h"
21 #include "mali_kbase_gator_api.h"
22 #include "mali_kbase_gator_hwcnt_names.h"
23 #include "mali_kbase_instr.h"
24
25 #define MALI_MAX_CORES_PER_GROUP                4
26 #define MALI_MAX_NUM_BLOCKS_PER_GROUP   8
27 #define MALI_COUNTERS_PER_BLOCK                 64
28 #define MALI_BYTES_PER_COUNTER                  4
29
30 struct kbase_gator_hwcnt_handles {
31         struct kbase_device  *kbdev;
32         struct kbase_context *kctx;
33         u64 hwcnt_gpu_va;
34         void *hwcnt_cpu_va;
35         struct kbase_vmap_struct hwcnt_map;
36 };
37
38 const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_counters)
39 {
40         uint32_t gpu_id;
41         const char * const *hardware_counters;
42         struct kbase_device *kbdev;
43
44         if (!total_counters)
45                 return NULL;
46
47         /* Get the first device - it doesn't matter in this case */
48         kbdev = kbase_find_device(-1);
49         if (!kbdev)
50                 return NULL;
51
52         gpu_id = kbdev->gpu_props.props.core_props.product_id;
53
54         switch (gpu_id) {
55         /* If we are using a Mali-T60x device */
56         case GPU_ID_PI_T60X:
57                 hardware_counters = hardware_counters_mali_t60x;
58                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t60x);
59                 break;
60         /* If we are using a Mali-T62x device */
61         case GPU_ID_PI_T62X:
62                 hardware_counters = hardware_counters_mali_t62x;
63                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t62x);
64                 break;
65         /* If we are using a Mali-T72x device */
66         case GPU_ID_PI_T72X:
67                 hardware_counters = hardware_counters_mali_t72x;
68                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t72x);
69                 break;
70         /* If we are using a Mali-T76x device */
71         case GPU_ID_PI_T76X:
72                 hardware_counters = hardware_counters_mali_t76x;
73                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t76x);
74                 break;
75         /* If we are using a Mali-T82x device */
76         case GPU_ID_PI_T82X:
77                 hardware_counters = hardware_counters_mali_t82x;
78                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t82x);
79                 break;
80         /* If we are using a Mali-T83x device */
81         case GPU_ID_PI_T83X:
82                 hardware_counters = hardware_counters_mali_t83x;
83                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t83x);
84                 break;
85         /* If we are using a Mali-T86x device */
86         case GPU_ID_PI_T86X:
87                 hardware_counters = hardware_counters_mali_t86x;
88                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t86x);
89                 break;
90         /* If we are using a Mali-T88x device */
91         case GPU_ID_PI_TFRX:
92                 hardware_counters = hardware_counters_mali_t88x;
93                 *total_counters = ARRAY_SIZE(hardware_counters_mali_t88x);
94                  break;
95         default:
96                 hardware_counters = NULL;
97                 *total_counters = 0;
98                 dev_err(kbdev->dev, "Unrecognized gpu ID: %u\n", gpu_id);
99                 break;
100         }
101
102         /* Release the kbdev reference. */
103         kbase_release_device(kbdev);
104
105         /* If we return a string array take a reference on the module (or fail). */
106         if (hardware_counters && !try_module_get(THIS_MODULE))
107                 return NULL;
108
109         return hardware_counters;
110 }
111 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init_names);
112
113 void kbase_gator_hwcnt_term_names(void)
114 {
115         /* Release the module reference. */
116         module_put(THIS_MODULE);
117 }
118 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term_names);
119
120 struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info)
121 {
122         struct kbase_gator_hwcnt_handles *hand;
123         struct kbase_uk_hwcnt_setup setup;
124         int err;
125         uint32_t dump_size = 0, i = 0;
126         struct kbase_va_region *reg;
127         u64 flags;
128         u64 nr_pages;
129         u16 va_alignment = 0;
130
131         if (!in_out_info)
132                 return NULL;
133
134         hand = kzalloc(sizeof(*hand), GFP_KERNEL);
135         if (!hand)
136                 return NULL;
137
138         /* Get the first device */
139         hand->kbdev = kbase_find_device(-1);
140         if (!hand->kbdev)
141                 goto free_hand;
142
143         /* Create a kbase_context */
144         hand->kctx = kbase_create_context(hand->kbdev, true);
145         if (!hand->kctx)
146                 goto release_device;
147
148         in_out_info->nr_cores = hand->kbdev->gpu_props.num_cores;
149         in_out_info->nr_core_groups = hand->kbdev->gpu_props.num_core_groups;
150         in_out_info->gpu_id = hand->kbdev->gpu_props.props.core_props.product_id;
151
152         /* If we are using a v4 device (Mali-T6xx or Mali-T72x) */
153         if (kbase_hw_has_feature(hand->kbdev, BASE_HW_FEATURE_V4)) {
154                 uint32_t cg, j;
155                 uint64_t core_mask;
156
157                 /* There are 8 hardware counters blocks per core group */
158                 in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) *
159                         MALI_MAX_NUM_BLOCKS_PER_GROUP *
160                         in_out_info->nr_core_groups, GFP_KERNEL);
161
162                 if (!in_out_info->hwc_layout)
163                         goto destroy_context;
164
165                 dump_size = in_out_info->nr_core_groups *
166                         MALI_MAX_NUM_BLOCKS_PER_GROUP *
167                         MALI_COUNTERS_PER_BLOCK *
168                         MALI_BYTES_PER_COUNTER;
169
170                 for (cg = 0; cg < in_out_info->nr_core_groups; cg++) {
171                         core_mask = hand->kbdev->gpu_props.props.coherency_info.group[cg].core_mask;
172
173                         for (j = 0; j < MALI_MAX_CORES_PER_GROUP; j++) {
174                                 if (core_mask & (1u << j))
175                                         in_out_info->hwc_layout[i++] = SHADER_BLOCK;
176                                 else
177                                         in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
178                         }
179
180                         in_out_info->hwc_layout[i++] = TILER_BLOCK;
181                         in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
182
183                         in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
184
185                         if (0 == cg)
186                                 in_out_info->hwc_layout[i++] = JM_BLOCK;
187                         else
188                                 in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
189                 }
190         /* If we are using any other device */
191         } else {
192                 uint32_t nr_l2, nr_sc_bits, j;
193                 uint64_t core_mask;
194
195                 nr_l2 = hand->kbdev->gpu_props.props.l2_props.num_l2_slices;
196
197                 core_mask = hand->kbdev->gpu_props.props.coherency_info.group[0].core_mask;
198
199                 nr_sc_bits = fls64(core_mask);
200
201                 /* The job manager and tiler sets of counters
202                  * are always present */
203                 in_out_info->hwc_layout = kmalloc(sizeof(enum hwc_type) * (2 + nr_sc_bits + nr_l2), GFP_KERNEL);
204
205                 if (!in_out_info->hwc_layout)
206                         goto destroy_context;
207
208                 dump_size = (2 + nr_sc_bits + nr_l2) * MALI_COUNTERS_PER_BLOCK * MALI_BYTES_PER_COUNTER;
209
210                 in_out_info->hwc_layout[i++] = JM_BLOCK;
211                 in_out_info->hwc_layout[i++] = TILER_BLOCK;
212
213                 for (j = 0; j < nr_l2; j++)
214                         in_out_info->hwc_layout[i++] = MMU_L2_BLOCK;
215
216                 while (core_mask != 0ull) {
217                         if ((core_mask & 1ull) != 0ull)
218                                 in_out_info->hwc_layout[i++] = SHADER_BLOCK;
219                         else
220                                 in_out_info->hwc_layout[i++] = RESERVED_BLOCK;
221                         core_mask >>= 1;
222                 }
223         }
224
225         in_out_info->nr_hwc_blocks = i;
226
227         in_out_info->size = dump_size;
228
229         flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR;
230         nr_pages = PFN_UP(dump_size);
231         reg = kbase_mem_alloc(hand->kctx, nr_pages, nr_pages, 0,
232                         &flags, &hand->hwcnt_gpu_va, &va_alignment);
233         if (!reg)
234                 goto free_layout;
235
236         hand->hwcnt_cpu_va = kbase_vmap(hand->kctx, hand->hwcnt_gpu_va,
237                         dump_size, &hand->hwcnt_map);
238
239         if (!hand->hwcnt_cpu_va)
240                 goto free_buffer;
241
242         in_out_info->kernel_dump_buffer = hand->hwcnt_cpu_va;
243         memset(in_out_info->kernel_dump_buffer, 0, nr_pages * PAGE_SIZE);
244
245         /*setup.dump_buffer = (uintptr_t)in_out_info->kernel_dump_buffer;*/
246         setup.dump_buffer = hand->hwcnt_gpu_va;
247         setup.jm_bm = in_out_info->bitmask[0];
248         setup.tiler_bm = in_out_info->bitmask[1];
249         setup.shader_bm = in_out_info->bitmask[2];
250         setup.mmu_l2_bm = in_out_info->bitmask[3];
251
252         err = kbase_instr_hwcnt_enable(hand->kctx, &setup);
253         if (err)
254                 goto free_unmap;
255
256         kbase_instr_hwcnt_clear(hand->kctx);
257
258         return hand;
259
260 free_unmap:
261         kbase_vunmap(hand->kctx, &hand->hwcnt_map);
262
263 free_buffer:
264         kbase_mem_free(hand->kctx, hand->hwcnt_gpu_va);
265
266 free_layout:
267         kfree(in_out_info->hwc_layout);
268
269 destroy_context:
270         kbase_destroy_context(hand->kctx);
271
272 release_device:
273         kbase_release_device(hand->kbdev);
274
275 free_hand:
276         kfree(hand);
277
278         return NULL;
279 }
280 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_init);
281
282 void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles)
283 {
284         if (in_out_info)
285                 kfree(in_out_info->hwc_layout);
286
287         if (opaque_handles) {
288                 kbase_instr_hwcnt_disable(opaque_handles->kctx);
289                 kbase_vunmap(opaque_handles->kctx, &opaque_handles->hwcnt_map);
290                 kbase_mem_free(opaque_handles->kctx, opaque_handles->hwcnt_gpu_va);
291                 kbase_destroy_context(opaque_handles->kctx);
292                 kbase_release_device(opaque_handles->kbdev);
293                 kfree(opaque_handles);
294         }
295 }
296 KBASE_EXPORT_SYMBOL(kbase_gator_hwcnt_term);
297
298 uint32_t kbase_gator_instr_hwcnt_dump_complete(
299                 struct kbase_gator_hwcnt_handles *opaque_handles,
300                 uint32_t * const success)
301 {
302         bool ret_res, success_res;
303
304         if (opaque_handles && success) {
305                 ret_res = kbase_instr_hwcnt_dump_complete(opaque_handles->kctx,
306                                 &success_res);
307                 *success = (uint32_t)success_res;
308                 return (uint32_t)(ret_res != 0);
309         }
310         return 0;
311 }
312 KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_complete);
313
314 uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles)
315 {
316         if (opaque_handles)
317                 return (kbase_instr_hwcnt_request_dump(
318                                 opaque_handles->kctx) == 0);
319
320         return 0;
321 }
322 KBASE_EXPORT_SYMBOL(kbase_gator_instr_hwcnt_dump_irq);