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.
11 #include "mali_kernel_common.h"
13 #include "mali_osk_bitops.h"
14 #include "mali_osk_list.h"
18 #include "mali_hw_core.h"
19 #include "mali_group.h"
20 #include "mali_mmu_page_directory.h"
23 * Size of the MMU registers in bytes
25 #define MALI_MMU_REGISTERS_SIZE 0x24
29 * These are the commands that can be sent
32 typedef enum mali_mmu_command
34 MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
35 MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
36 MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */
37 MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
38 MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
39 MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
40 MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */
43 static void mali_mmu_probe_trigger(void *data);
44 static _mali_osk_errcode_t mali_mmu_probe_ack(void *data);
46 MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu);
48 /* page fault queue flush helper pages
49 * note that the mapping pointers are currently unused outside of the initialization functions */
50 static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
51 static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
52 static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
54 /* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */
55 static u32 mali_empty_page_directory = MALI_INVALID_PAGE;
57 _mali_osk_errcode_t mali_mmu_initialize(void)
59 /* allocate the helper pages */
60 mali_empty_page_directory = mali_allocate_empty_page();
61 if(0 == mali_empty_page_directory)
63 mali_empty_page_directory = MALI_INVALID_PAGE;
64 return _MALI_OSK_ERR_NOMEM;
67 if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory,
68 &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page))
70 mali_free_empty_page(mali_empty_page_directory);
71 return _MALI_OSK_ERR_FAULT;
74 return _MALI_OSK_ERR_OK;
77 void mali_mmu_terminate(void)
79 MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n"));
81 /* Free global helper pages */
82 mali_free_empty_page(mali_empty_page_directory);
84 /* Free the page fault flush pages */
85 mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory,
86 &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page);
89 struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual)
91 struct mali_mmu_core* mmu = NULL;
93 MALI_DEBUG_ASSERT_POINTER(resource);
95 MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description));
97 mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
100 if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE))
102 if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu))
106 /* Skip reset and IRQ setup for virtual MMU */
110 if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu))
112 /* Setup IRQ handlers (which will do IRQ probing if needed) */
113 mmu->irq = _mali_osk_irq_init(resource->irq,
114 mali_group_upper_half_mmu,
116 mali_mmu_probe_trigger,
119 "mali_mmu_irq_handlers");
120 if (NULL != mmu->irq)
126 MALI_PRINT_ERROR(("Mali MMU: Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
129 mali_group_remove_mmu_core(group);
133 MALI_PRINT_ERROR(("Mali MMU: Failed to add core %s to group\n", mmu->hw_core.description));
135 mali_hw_core_delete(&mmu->hw_core);
142 MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n"));
148 void mali_mmu_delete(struct mali_mmu_core *mmu)
150 if (NULL != mmu->irq)
152 _mali_osk_irq_term(mmu->irq);
155 mali_hw_core_delete(&mmu->hw_core);
159 static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
163 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
165 for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
167 if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED)
172 if (MALI_REG_POLL_COUNT_SLOW == i)
174 MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
178 mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
181 u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
183 if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) )
185 MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n"));
189 if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
191 MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n"));
195 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
197 for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
199 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
200 if (mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) &&
201 (0 == (mmu_status & MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE)))
205 if (0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED )))
210 if (MALI_REG_POLL_COUNT_SLOW == i)
212 MALI_PRINT_ERROR(("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
216 if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
218 MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it has a pagefault.\n"));
225 void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
228 u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
230 if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
232 MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n"));
235 if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)
237 MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n"));
241 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
243 for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
245 u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
246 if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) )
250 if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
254 if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
259 if (MALI_REG_POLL_COUNT_SLOW == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
262 void mali_mmu_page_fault_done(struct mali_mmu_core *mmu)
264 MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description));
265 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
268 MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu)
272 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
273 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET);
275 for (i = 0; i < MALI_REG_POLL_COUNT_SLOW; ++i)
277 if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0)
282 if (MALI_REG_POLL_COUNT_SLOW == i)
284 MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
285 return _MALI_OSK_ERR_FAULT;
288 return _MALI_OSK_ERR_OK;
291 _mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
293 _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
294 mali_bool stall_success;
295 MALI_DEBUG_ASSERT_POINTER(mmu);
297 stall_success = mali_mmu_enable_stall(mmu);
299 /* The stall can not fail in current hw-state */
300 MALI_DEBUG_ASSERT(stall_success);
302 MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
304 if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu))
306 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
307 /* no session is active, so just activate the empty page directory */
308 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
309 mali_mmu_enable_paging(mmu);
310 err = _MALI_OSK_ERR_OK;
312 mali_mmu_disable_stall(mmu);
317 mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
319 mali_bool stall_success = mali_mmu_enable_stall(mmu);
321 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
323 if (MALI_FALSE == stall_success)
325 /* False means that it is in Pagefault state. Not possible to disable_stall then */
329 mali_mmu_disable_stall(mmu);
333 void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu)
335 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
339 void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address)
341 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address));
344 static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory)
346 /* The MMU must be in stalled or page fault mode, for this writing to work */
347 MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)
348 & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
349 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
350 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
354 mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
356 mali_bool stall_success;
357 MALI_DEBUG_ASSERT_POINTER(mmu);
359 MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));
360 stall_success = mali_mmu_enable_stall(mmu);
362 if ( MALI_FALSE==stall_success ) return MALI_FALSE;
363 mali_mmu_activate_address_space(mmu, pagedir->page_directory);
364 mali_mmu_disable_stall(mmu);
368 void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu)
370 mali_bool stall_success;
372 MALI_DEBUG_ASSERT_POINTER(mmu);
373 MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
375 stall_success = mali_mmu_enable_stall(mmu);
376 /* This function can only be called when the core is idle, so it could not fail. */
377 MALI_DEBUG_ASSERT( stall_success );
378 mali_mmu_activate_address_space(mmu, mali_empty_page_directory);
379 mali_mmu_disable_stall(mmu);
382 void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu)
384 mali_bool stall_success;
385 MALI_DEBUG_ASSERT_POINTER(mmu);
387 MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description));
388 stall_success = mali_mmu_enable_stall(mmu);
389 /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */
390 mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory);
391 if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu);
394 /* Is called when we want the mmu to give an interrupt */
395 static void mali_mmu_probe_trigger(void *data)
397 struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
398 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
401 /* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
402 static _mali_osk_errcode_t mali_mmu_probe_ack(void *data)
404 struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
407 int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
409 MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
410 if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
412 MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
413 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
417 MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
420 if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
422 MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
423 mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
427 MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
430 if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
431 (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR))
433 return _MALI_OSK_ERR_OK;
436 return _MALI_OSK_ERR_FAULT;
440 void mali_mmu_print_state(struct mali_mmu_core *mmu)
442 MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));