tizen 2.4 release
[kernel/linux-3.0.git] / drivers / gpu / arm / mali400 / r4p0_rel0 / common / mali_pp.c
1 /*
2  * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
3  * 
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  * 
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10
11 #include "mali_pp_job.h"
12 #include "mali_pp.h"
13 #include "mali_hw_core.h"
14 #include "mali_group.h"
15 #include "regs/mali_200_regs.h"
16 #include "mali_kernel_common.h"
17 #include "mali_kernel_core.h"
18 #include "mali_dma.h"
19 #if defined(CONFIG_MALI400_PROFILING)
20 #include "mali_osk_profiling.h"
21 #endif
22
23 /* Number of frame registers on Mali-200 */
24 #define MALI_PP_MALI200_NUM_FRAME_REGISTERS ((0x04C/4)+1)
25 /* Number of frame registers on Mali-300 and later */
26 #define MALI_PP_MALI400_NUM_FRAME_REGISTERS ((0x058/4)+1)
27
28 static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES] = { NULL };
29 static u32 mali_global_num_pp_cores = 0;
30
31 /* Interrupt handlers */
32 static void mali_pp_irq_probe_trigger(void *data);
33 static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data);
34
35 struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id)
36 {
37         struct mali_pp_core* core = NULL;
38
39         MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description));
40         MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base));
41
42         if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) {
43                 MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n"));
44                 return NULL;
45         }
46
47         core = _mali_osk_malloc(sizeof(struct mali_pp_core));
48         if (NULL != core) {
49                 core->core_id = mali_global_num_pp_cores;
50                 core->bcast_id = bcast_id;
51
52                 if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) {
53                         _mali_osk_errcode_t ret;
54
55                         if (!is_virtual) {
56                                 ret = mali_pp_reset(core);
57                         } else {
58                                 ret = _MALI_OSK_ERR_OK;
59                         }
60
61                         if (_MALI_OSK_ERR_OK == ret) {
62                                 ret = mali_group_add_pp_core(group, core);
63                                 if (_MALI_OSK_ERR_OK == ret) {
64                                         /* Setup IRQ handlers (which will do IRQ probing if needed) */
65                                         MALI_DEBUG_ASSERT(!is_virtual || -1 != resource->irq);
66
67                                         core->irq = _mali_osk_irq_init(resource->irq,
68                                                                        mali_group_upper_half_pp,
69                                                                        group,
70                                                                        mali_pp_irq_probe_trigger,
71                                                                        mali_pp_irq_probe_ack,
72                                                                        core,
73                                                                        resource->description);
74                                         if (NULL != core->irq) {
75                                                 mali_global_pp_cores[mali_global_num_pp_cores] = core;
76                                                 mali_global_num_pp_cores++;
77
78                                                 return core;
79                                         } else {
80                                                 MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
81                                         }
82                                         mali_group_remove_pp_core(group);
83                                 } else {
84                                         MALI_PRINT_ERROR(("Mali PP: Failed to add core %s to group\n", core->hw_core.description));
85                                 }
86                         }
87                         mali_hw_core_delete(&core->hw_core);
88                 }
89
90                 _mali_osk_free(core);
91         } else {
92                 MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n"));
93         }
94
95         return NULL;
96 }
97
98 void mali_pp_delete(struct mali_pp_core *core)
99 {
100         u32 i;
101
102         MALI_DEBUG_ASSERT_POINTER(core);
103
104         _mali_osk_irq_term(core->irq);
105         mali_hw_core_delete(&core->hw_core);
106
107         /* Remove core from global list */
108         for (i = 0; i < mali_global_num_pp_cores; i++) {
109                 if (mali_global_pp_cores[i] == core) {
110                         mali_global_pp_cores[i] = NULL;
111                         mali_global_num_pp_cores--;
112
113                         if (i != mali_global_num_pp_cores) {
114                                 /* We removed a PP core from the middle of the array -- move the last
115                                  * PP core to the current position to close the gap */
116                                 mali_global_pp_cores[i] = mali_global_pp_cores[mali_global_num_pp_cores];
117                                 mali_global_pp_cores[mali_global_num_pp_cores] = NULL;
118                         }
119
120                         break;
121                 }
122         }
123
124         _mali_osk_free(core);
125 }
126
127 void mali_pp_stop_bus(struct mali_pp_core *core)
128 {
129         MALI_DEBUG_ASSERT_POINTER(core);
130         /* Will only send the stop bus command, and not wait for it to complete */
131         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
132 }
133
134 _mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core)
135 {
136         int i;
137
138         MALI_DEBUG_ASSERT_POINTER(core);
139
140         /* Send the stop bus command. */
141         mali_pp_stop_bus(core);
142
143         /* Wait for bus to be stopped */
144         for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
145                 if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED)
146                         break;
147         }
148
149         if (MALI_REG_POLL_COUNT_FAST == i) {
150                 MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
151                 return _MALI_OSK_ERR_FAULT;
152         }
153         return _MALI_OSK_ERR_OK;
154 }
155
156 /* Frame register reset values.
157  * Taken from the Mali400 TRM, 3.6. Pixel processor control register summary */
158 static const u32 mali_frame_registers_reset_values[_MALI_PP_MAX_FRAME_REGISTERS] = {
159         0x0, /* Renderer List Address Register */
160         0x0, /* Renderer State Word Base Address Register */
161         0x0, /* Renderer Vertex Base Register */
162         0x2, /* Feature Enable Register */
163         0x0, /* Z Clear Value Register */
164         0x0, /* Stencil Clear Value Register */
165         0x0, /* ABGR Clear Value 0 Register */
166         0x0, /* ABGR Clear Value 1 Register */
167         0x0, /* ABGR Clear Value 2 Register */
168         0x0, /* ABGR Clear Value 3 Register */
169         0x0, /* Bounding Box Left Right Register */
170         0x0, /* Bounding Box Bottom Register */
171         0x0, /* FS Stack Address Register */
172         0x0, /* FS Stack Size and Initial Value Register */
173         0x0, /* Reserved */
174         0x0, /* Reserved */
175         0x0, /* Origin Offset X Register */
176         0x0, /* Origin Offset Y Register */
177         0x75, /* Subpixel Specifier Register */
178         0x0, /* Tiebreak mode Register */
179         0x0, /* Polygon List Format Register */
180         0x0, /* Scaling Register */
181         0x0 /* Tilebuffer configuration Register */
182 };
183
184 /* WBx register reset values */
185 static const u32 mali_wb_registers_reset_values[_MALI_PP_MAX_WB_REGISTERS] = {
186         0x0, /* WBx Source Select Register */
187         0x0, /* WBx Target Address Register */
188         0x0, /* WBx Target Pixel Format Register */
189         0x0, /* WBx Target AA Format Register */
190         0x0, /* WBx Target Layout */
191         0x0, /* WBx Target Scanline Length */
192         0x0, /* WBx Target Flags Register */
193         0x0, /* WBx MRT Enable Register */
194         0x0, /* WBx MRT Offset Register */
195         0x0, /* WBx Global Test Enable Register */
196         0x0, /* WBx Global Test Reference Value Register */
197         0x0  /* WBx Global Test Compare Function Register */
198 };
199
200 /* Performance Counter 0 Enable Register reset value */
201 static const u32 mali_perf_cnt_enable_reset_value = 0;
202
203 _mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core)
204 {
205         /* Bus must be stopped before calling this function */
206         const u32 reset_invalid_value = 0xC0FFE000;
207         const u32 reset_check_value = 0xC01A0000;
208         int i;
209
210         MALI_DEBUG_ASSERT_POINTER(core);
211         MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description));
212
213         /* Set register to a bogus value. The register will be used to detect when reset is complete */
214         mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value);
215         mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
216
217         /* Force core to reset */
218         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);
219
220         /* Wait for reset to be complete */
221         for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
222                 mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value);
223                 if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) {
224                         break;
225                 }
226         }
227
228         if (MALI_REG_POLL_COUNT_FAST == i) {
229                 MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n"));
230         }
231
232         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */
233         /* Re-enable interrupts */
234         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
235         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
236
237         return _MALI_OSK_ERR_OK;
238 }
239
240 void mali_pp_reset_async(struct mali_pp_core *core)
241 {
242         MALI_DEBUG_ASSERT_POINTER(core);
243
244         MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description));
245
246         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
247         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_MASK_ALL);
248         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);
249 }
250
251 _mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core)
252 {
253         int i;
254         u32 rawstat = 0;
255
256         for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
257                 if (!(mali_pp_read_status(core) & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)) {
258                         rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT);
259                         if (rawstat == MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) {
260                                 break;
261                         }
262                 }
263         }
264
265         if (i == MALI_REG_POLL_COUNT_FAST) {
266                 MALI_PRINT_ERROR(("Mali PP: Failed to reset core %s, rawstat: 0x%08x\n",
267                                   core->hw_core.description, rawstat));
268                 return _MALI_OSK_ERR_FAULT;
269         }
270
271         /* Re-enable interrupts */
272         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
273         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
274
275         return _MALI_OSK_ERR_OK;
276 }
277
278 _mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
279 {
280         mali_pp_reset_async(core);
281         return mali_pp_reset_wait(core);
282 }
283
284 void mali_pp_job_dma_cmd_prepare(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job,
285                                  mali_bool restart_virtual, mali_dma_cmd_buf *buf)
286 {
287         u32 relative_address;
288         u32 start_index;
289         u32 nr_of_regs;
290         u32 *frame_registers = mali_pp_job_get_frame_registers(job);
291         u32 *wb0_registers = mali_pp_job_get_wb0_registers(job);
292         u32 *wb1_registers = mali_pp_job_get_wb1_registers(job);
293         u32 *wb2_registers = mali_pp_job_get_wb2_registers(job);
294         u32 counter_src0 = mali_pp_job_get_perf_counter_src0(job, sub_job);
295         u32 counter_src1 = mali_pp_job_get_perf_counter_src1(job, sub_job);
296
297         MALI_DEBUG_ASSERT_POINTER(core);
298
299         /* Write frame registers */
300
301         /*
302          * There are two frame registers which are different for each sub job:
303          * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME)
304          * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK)
305          */
306         mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]);
307
308         /* For virtual jobs, the stack address shouldn't be broadcast but written individually */
309         if (!mali_pp_job_is_virtual(job) || restart_virtual) {
310                 mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]);
311         }
312
313         /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */
314         relative_address = MALI200_REG_ADDR_RSW;
315         start_index = MALI200_REG_ADDR_RSW / sizeof(u32);
316         nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32);
317
318         mali_dma_write_array_conditional(buf, &core->hw_core,
319                                          relative_address, &frame_registers[start_index],
320                                          nr_of_regs, &mali_frame_registers_reset_values[start_index]);
321
322         /* MALI200_REG_ADDR_STACK_SIZE */
323         relative_address = MALI200_REG_ADDR_STACK_SIZE;
324         start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32);
325
326         mali_dma_write_conditional(buf, &core->hw_core,
327                                    relative_address, frame_registers[start_index],
328                                    mali_frame_registers_reset_values[start_index]);
329
330         /* Skip 2 reserved registers */
331
332         /* Write remaining registers */
333         relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X;
334         start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
335         nr_of_regs = MALI_PP_MALI400_NUM_FRAME_REGISTERS - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
336
337         mali_dma_write_array_conditional(buf, &core->hw_core,
338                                          relative_address, &frame_registers[start_index],
339                                          nr_of_regs, &mali_frame_registers_reset_values[start_index]);
340
341         /* Write WBx registers */
342         if (wb0_registers[0]) { /* M200_WB0_REG_SOURCE_SELECT register */
343                 mali_dma_write_array_conditional(buf, &core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
344         }
345
346         if (wb1_registers[0]) { /* M200_WB1_REG_SOURCE_SELECT register */
347                 mali_dma_write_array_conditional(buf, &core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
348         }
349
350         if (wb2_registers[0]) { /* M200_WB2_REG_SOURCE_SELECT register */
351                 mali_dma_write_array_conditional(buf, &core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
352         }
353
354         if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
355                 mali_dma_write(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, counter_src0);
356                 mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
357         }
358         if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
359                 mali_dma_write(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, counter_src1);
360                 mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
361         }
362
363         /* This is the command that starts the core. */
364         mali_dma_write(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
365 }
366
367 void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual)
368 {
369         u32 relative_address;
370         u32 start_index;
371         u32 nr_of_regs;
372         u32 *frame_registers = mali_pp_job_get_frame_registers(job);
373         u32 *wb0_registers = mali_pp_job_get_wb0_registers(job);
374         u32 *wb1_registers = mali_pp_job_get_wb1_registers(job);
375         u32 *wb2_registers = mali_pp_job_get_wb2_registers(job);
376         u32 counter_src0 = mali_pp_job_get_perf_counter_src0(job, sub_job);
377         u32 counter_src1 = mali_pp_job_get_perf_counter_src1(job, sub_job);
378
379         MALI_DEBUG_ASSERT_POINTER(core);
380
381         /* Write frame registers */
382
383         /*
384          * There are two frame registers which are different for each sub job:
385          * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME)
386          * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK)
387          */
388         mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]);
389
390         /* For virtual jobs, the stack address shouldn't be broadcast but written individually */
391         if (!mali_pp_job_is_virtual(job) || restart_virtual) {
392                 mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]);
393         }
394
395         /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */
396         relative_address = MALI200_REG_ADDR_RSW;
397         start_index = MALI200_REG_ADDR_RSW / sizeof(u32);
398         nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32);
399
400         mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core,
401                 relative_address, &frame_registers[start_index],
402                 nr_of_regs, &mali_frame_registers_reset_values[start_index]);
403
404         /* MALI200_REG_ADDR_STACK_SIZE */
405         relative_address = MALI200_REG_ADDR_STACK_SIZE;
406         start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32);
407
408         mali_hw_core_register_write_relaxed_conditional(&core->hw_core,
409                 relative_address, frame_registers[start_index],
410                 mali_frame_registers_reset_values[start_index]);
411
412         /* Skip 2 reserved registers */
413
414         /* Write remaining registers */
415         relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X;
416         start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
417         nr_of_regs = MALI_PP_MALI400_NUM_FRAME_REGISTERS - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
418
419         mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core,
420                 relative_address, &frame_registers[start_index],
421                 nr_of_regs, &mali_frame_registers_reset_values[start_index]);
422
423         /* Write WBx registers */
424         if (wb0_registers[0]) { /* M200_WB0_REG_SOURCE_SELECT register */
425                 mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
426         }
427
428         if (wb1_registers[0]) { /* M200_WB1_REG_SOURCE_SELECT register */
429                 mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
430         }
431
432         if (wb2_registers[0]) { /* M200_WB2_REG_SOURCE_SELECT register */
433                 mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
434         }
435
436         if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
437                 mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, counter_src0);
438                 mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
439         }
440         if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
441                 mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, counter_src1);
442                 mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
443         }
444
445 #ifdef CONFIG_MALI400_HEATMAPS_ENABLED
446         if(job->uargs.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_HEATMAP_ENABLE) {
447                 mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERFMON_CONTR, ((job->uargs.tilesx & 0x3FF) << 16) | 1);
448                 mali_hw_core_register_write_relaxed(&core->hw_core,  MALI200_REG_ADDR_MGMT_PERFMON_BASE, job->uargs.heatmap_mem & 0xFFFFFFF8);
449         }
450 #endif /* CONFIG_MALI400_HEATMAPS_ENABLED */
451
452         MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description));
453
454         /* Adding barrier to make sure all rester writes are finished */
455         _mali_osk_write_mem_barrier();
456
457         /* This is the command that starts the core. */
458         mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
459
460         /* Adding barrier to make sure previous rester writes is finished */
461         _mali_osk_write_mem_barrier();
462 }
463
464 u32 mali_pp_core_get_version(struct mali_pp_core *core)
465 {
466         MALI_DEBUG_ASSERT_POINTER(core);
467         return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION);
468 }
469
470 struct mali_pp_core* mali_pp_get_global_pp_core(u32 index)
471 {
472         if (mali_global_num_pp_cores > index) {
473                 return mali_global_pp_cores[index];
474         }
475
476         return NULL;
477 }
478
479 u32 mali_pp_get_glob_num_pp_cores(void)
480 {
481         return mali_global_num_pp_cores;
482 }
483
484 /* ------------- interrupt handling below ------------------ */
485 static void mali_pp_irq_probe_trigger(void *data)
486 {
487         struct mali_pp_core *core = (struct mali_pp_core *)data;
488         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
489         mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG);
490         _mali_osk_mem_barrier();
491 }
492
493 static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data)
494 {
495         struct mali_pp_core *core = (struct mali_pp_core *)data;
496         u32 irq_readout;
497
498         irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS);
499         if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) {
500                 mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG);
501                 _mali_osk_mem_barrier();
502                 return _MALI_OSK_ERR_OK;
503         }
504
505         return _MALI_OSK_ERR_FAULT;
506 }
507
508
509 #if 0
510 static void mali_pp_print_registers(struct mali_pp_core *core)
511 {
512         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION)));
513         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR)));
514         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
515         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT)));
516         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK)));
517         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS)));
518         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS)));
519         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE)));
520         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC)));
521         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE)));
522         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE)));
523         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC)));
524         MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE)));
525 }
526 #endif
527
528 #if 0
529 void mali_pp_print_state(struct mali_pp_core *core)
530 {
531         MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) ));
532 }
533 #endif
534
535 void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob)
536 {
537         u32 val0 = 0;
538         u32 val1 = 0;
539         u32 counter_src0 = mali_pp_job_get_perf_counter_src0(job, subjob);
540         u32 counter_src1 = mali_pp_job_get_perf_counter_src1(job, subjob);
541 #if defined(CONFIG_MALI400_PROFILING)
542         int counter_index = COUNTER_FP_0_C0 + (2 * child->core_id);
543 #endif
544
545         if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
546                 val0 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
547                 mali_pp_job_set_perf_counter_value0(job, subjob, val0);
548
549 #if defined(CONFIG_MALI400_PROFILING)
550                 _mali_osk_profiling_report_hw_counter(counter_index, val0);
551 #endif
552         }
553
554         if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
555                 val1 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
556                 mali_pp_job_set_perf_counter_value1(job, subjob, val1);
557
558 #if defined(CONFIG_MALI400_PROFILING)
559                 _mali_osk_profiling_report_hw_counter(counter_index + 1, val1);
560 #endif
561         }
562 }
563
564 #if MALI_STATE_TRACKING
565 u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size)
566 {
567         int n = 0;
568
569         n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description);
570
571         return n;
572 }
573 #endif