2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
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.
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.
12 #include "mali_hw_core.h"
13 #include "mali_group.h"
15 #include "regs/mali_gp_regs.h"
16 #include "mali_kernel_common.h"
17 #include "mali_kernel_core.h"
18 #if defined(CONFIG_MALI400_PROFILING)
19 #include "mali_osk_profiling.h"
22 static struct mali_gp_core *mali_global_gp_core = NULL;
24 /* Interrupt handlers */
25 static void mali_gp_irq_probe_trigger(void *data);
26 static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data);
28 struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group)
30 struct mali_gp_core* core = NULL;
32 MALI_DEBUG_ASSERT(NULL == mali_global_gp_core);
33 MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description));
35 core = _mali_osk_malloc(sizeof(struct mali_gp_core));
38 core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
39 core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
40 if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE))
42 _mali_osk_errcode_t ret;
44 ret = mali_gp_reset(core);
46 if (_MALI_OSK_ERR_OK == ret)
48 ret = mali_group_add_gp_core(group, core);
49 if (_MALI_OSK_ERR_OK == ret)
51 /* Setup IRQ handlers (which will do IRQ probing if needed) */
52 core->irq = _mali_osk_irq_init(resource->irq,
53 mali_group_upper_half_gp,
55 mali_gp_irq_probe_trigger,
56 mali_gp_irq_probe_ack,
58 "mali_gp_irq_handlers");
59 if (NULL != core->irq)
61 MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core));
62 mali_global_gp_core = core;
68 MALI_PRINT_ERROR(("Mali GP: Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
70 mali_group_remove_gp_core(group);
74 MALI_PRINT_ERROR(("Mali GP: Failed to add core %s to group\n", core->hw_core.description));
77 mali_hw_core_delete(&core->hw_core);
84 MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n"));
90 void mali_gp_delete(struct mali_gp_core *core)
92 MALI_DEBUG_ASSERT_POINTER(core);
94 _mali_osk_irq_term(core->irq);
95 mali_hw_core_delete(&core->hw_core);
96 mali_global_gp_core = NULL;
100 void mali_gp_stop_bus(struct mali_gp_core *core)
102 MALI_DEBUG_ASSERT_POINTER(core);
104 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
107 _mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core)
111 MALI_DEBUG_ASSERT_POINTER(core);
113 /* Send the stop bus command. */
114 mali_gp_stop_bus(core);
116 /* Wait for bus to be stopped */
117 for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
119 if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED)
125 if (MALI_REG_POLL_COUNT_FAST == i)
127 MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description));
128 return _MALI_OSK_ERR_FAULT;
130 return _MALI_OSK_ERR_OK;
133 void mali_gp_hard_reset(struct mali_gp_core *core)
135 const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW;
136 const u32 reset_invalid_value = 0xC0FFE000;
137 const u32 reset_check_value = 0xC01A0000;
138 const u32 reset_default_value = 0;
141 MALI_DEBUG_ASSERT_POINTER(core);
142 MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description));
144 mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value);
146 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET);
148 for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
150 mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value);
151 if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register))
157 if (MALI_REG_POLL_COUNT_FAST == i)
159 MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n"));
162 mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */
163 /* Re-enable interrupts */
164 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
165 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
169 void mali_gp_reset_async(struct mali_gp_core *core)
171 MALI_DEBUG_ASSERT_POINTER(core);
173 MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description));
175 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
176 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
177 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
181 _mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core)
186 MALI_DEBUG_ASSERT_POINTER(core);
188 for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
190 rawstat = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT);
191 if (rawstat & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED)
197 if (i == MALI_REG_POLL_COUNT_FAST)
199 MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, rawstat: 0x%08x\n",
200 core->hw_core.description, rawstat));
201 return _MALI_OSK_ERR_FAULT;
204 /* Re-enable interrupts */
205 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
206 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
208 return _MALI_OSK_ERR_OK;
211 _mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core)
213 mali_gp_reset_async(core);
214 return mali_gp_reset_wait(core);
217 void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job)
220 u32 *frame_registers = mali_gp_job_get_frame_registers(job);
222 core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job);
223 core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job);
225 MALI_DEBUG_ASSERT_POINTER(core);
227 if (mali_gp_job_has_vs_job(job))
229 startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS;
232 if (mali_gp_job_has_plbu_job(job))
234 startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU;
237 MALI_DEBUG_ASSERT(0 != startcmd);
239 mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME);
241 if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
243 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
244 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
246 if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
248 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
249 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
252 MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd));
254 /* Barrier to make sure the previous register write is finished */
255 _mali_osk_write_mem_barrier();
257 /* This is the command that starts the core. */
258 mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd);
260 /* Barrier to make sure the previous register write is finished */
261 _mali_osk_write_mem_barrier();
264 void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr)
268 MALI_DEBUG_ASSERT_POINTER(core);
270 irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT);
272 if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
274 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG));
275 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */
276 mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr);
277 mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr);
279 MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n"));
281 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC);
282 _mali_osk_write_mem_barrier();
285 * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response.
286 * A timeout or a page fault on Mali-200 PP core can cause this behaviour.
290 u32 mali_gp_core_get_version(struct mali_gp_core *core)
292 MALI_DEBUG_ASSERT_POINTER(core);
293 return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION);
296 struct mali_gp_core *mali_gp_get_global_gp_core(void)
298 return mali_global_gp_core;
301 /* ------------- interrupt handling below ------------------ */
302 static void mali_gp_irq_probe_trigger(void *data)
304 struct mali_gp_core *core = (struct mali_gp_core *)data;
306 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
307 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG);
308 _mali_osk_mem_barrier();
311 static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data)
313 struct mali_gp_core *core = (struct mali_gp_core *)data;
316 irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
317 if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout)
319 mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG);
320 _mali_osk_mem_barrier();
321 return _MALI_OSK_ERR_OK;
324 return _MALI_OSK_ERR_FAULT;
327 /* ------ local helper functions below --------- */
328 #if MALI_STATE_TRACKING
329 u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size)
333 n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description);
339 void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend)
344 if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
346 val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
347 mali_gp_job_set_perf_counter_value0(job, val0);
349 #if defined(CONFIG_MALI400_PROFILING)
350 _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0);
355 if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
357 val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
358 mali_gp_job_set_perf_counter_value1(job, val1);
360 #if defined(CONFIG_MALI400_PROFILING)
361 _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1);