PageRenderTime 33ms CodeModel.GetById 15ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/gpu/mali/mali/common/mali_mmu.c

https://bitbucket.org/ndreys/linux-sunxi
C | 619 lines | 443 code | 100 blank | 76 comment | 64 complexity | 8e20e54644182be5e8ef364bbe37d2a4 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * Copyright (C) 2010-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_kernel_common.h"
 12#include "mali_osk.h"
 13#include "mali_osk_bitops.h"
 14#include "mali_osk_list.h"
 15#include "mali_ukk.h"
 16
 17#include "mali_mmu.h"
 18#include "mali_hw_core.h"
 19#include "mali_group.h"
 20#include "mali_mmu_page_directory.h"
 21
 22/**
 23 * Size of the MMU registers in bytes
 24 */
 25#define MALI_MMU_REGISTERS_SIZE 0x24
 26
 27/**
 28 * MMU register numbers
 29 * Used in the register read/write routines.
 30 * See the hardware documentation for more information about each register
 31 */
 32typedef enum mali_mmu_register {
 33	MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */
 34	MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */
 35	MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */
 36	MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */
 37	MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */
 38	MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */
 39	MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */
 40	MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */
 41	MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */
 42} mali_mmu_register;
 43
 44/**
 45 * MMU interrupt register bits
 46 * Each cause of the interrupt is reported
 47 * through the (raw) interrupt status registers.
 48 * Multiple interrupts can be pending, so multiple bits
 49 * can be set at once.
 50 */
 51typedef enum mali_mmu_interrupt
 52{
 53	MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */
 54	MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */
 55} mali_mmu_interrupt;
 56
 57/**
 58 * MMU commands
 59 * These are the commands that can be sent
 60 * to the MMU unit.
 61 */
 62typedef enum mali_mmu_command
 63{
 64	MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
 65	MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
 66	MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**<  Enable stall on page fault */
 67	MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
 68	MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
 69	MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
 70	MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */
 71} mali_mmu_command;
 72
 73typedef enum mali_mmu_status_bits
 74{
 75	MALI_MMU_STATUS_BIT_PAGING_ENABLED      = 1 << 0,
 76	MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE   = 1 << 1,
 77	MALI_MMU_STATUS_BIT_STALL_ACTIVE        = 1 << 2,
 78	MALI_MMU_STATUS_BIT_IDLE                = 1 << 3,
 79	MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4,
 80	MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5,
 81} mali_mmu_status_bits;
 82
 83/**
 84 * Definition of the MMU struct
 85 * Used to track a MMU unit in the system.
 86 * Contains information about the mapping of the registers
 87 */
 88struct mali_mmu_core
 89{
 90	struct mali_hw_core hw_core; /**< Common for all HW cores */
 91	struct mali_group *group;    /**< Parent core group */
 92	_mali_osk_irq_t *irq;        /**< IRQ handler */
 93};
 94
 95/**
 96 * The MMU interrupt handler
 97 * Upper half of the MMU interrupt processing.
 98 * Called by the kernel when the MMU has triggered an interrupt.
 99 * The interrupt function supports IRQ sharing. So it'll probe the MMU in question
100 * @param irq The irq number (not used)
101 * @param dev_id Points to the MMU object being handled
102 * @param regs Registers of interrupted process (not used)
103 * @return Standard Linux interrupt result.
104 *         Subset used by the driver is IRQ_HANDLED processed
105 *                                      IRQ_NONE Not processed
106 */
107static _mali_osk_errcode_t mali_mmu_upper_half(void * data);
108
109/**
110 * The MMU reset hander
111 * Bottom half of the MMU interrupt processing for page faults and bus errors
112 * @param work The item to operate on, NULL in our case
113 */
114static void mali_mmu_bottom_half(void *data);
115
116static void mali_mmu_probe_trigger(void *data);
117static _mali_osk_errcode_t mali_mmu_probe_ack(void *data);
118
119MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu);
120
121/* page fault queue flush helper pages
122 * note that the mapping pointers are currently unused outside of the initialization functions */
123static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
124static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
125static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
126
127/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */
128static u32 mali_empty_page_directory = MALI_INVALID_PAGE;
129
130_mali_osk_errcode_t mali_mmu_initialize(void)
131{
132	/* allocate the helper pages */
133	mali_empty_page_directory = mali_allocate_empty_page();
134	if(0 == mali_empty_page_directory)
135	{
136		mali_empty_page_directory = MALI_INVALID_PAGE;
137		return _MALI_OSK_ERR_NOMEM;
138	}
139
140	if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory,
141	                                &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page))
142	{
143		mali_free_empty_page(mali_empty_page_directory);
144		return _MALI_OSK_ERR_FAULT;
145	}
146
147	return _MALI_OSK_ERR_OK;
148}
149
150void mali_mmu_terminate(void)
151{
152	MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n"));
153
154	/* Free global helper pages */
155	mali_free_empty_page(mali_empty_page_directory);
156
157	/* Free the page fault flush pages */
158	mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory,
159	                            &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page);
160}
161
162struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource)
163{
164	struct mali_mmu_core* mmu = NULL;
165
166	MALI_DEBUG_ASSERT_POINTER(resource);
167
168	MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description));
169
170	mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
171	if (NULL != mmu)
172	{
173		if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE))
174		{
175			if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu))
176			{
177				/* Setup IRQ handlers (which will do IRQ probing if needed) */
178				mmu->irq = _mali_osk_irq_init(resource->irq,
179							      mali_mmu_upper_half,
180							      mali_mmu_bottom_half,
181							      mali_mmu_probe_trigger,
182							      mali_mmu_probe_ack,
183							      mmu,
184							      "mali_mmu_irq_handlers");
185				if (NULL != mmu->irq)
186				{
187					return mmu;
188				}
189				else
190				{
191					MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
192				}
193			}
194			mali_hw_core_delete(&mmu->hw_core);
195		}
196
197		_mali_osk_free(mmu);
198	}
199	else
200	{
201		MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n"));
202	}
203
204	return NULL;
205}
206
207void mali_mmu_delete(struct mali_mmu_core *mmu)
208{
209	_mali_osk_irq_term(mmu->irq);
210	mali_hw_core_delete(&mmu->hw_core);
211	_mali_osk_free(mmu);
212}
213
214void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group)
215{
216	mmu->group = group;
217}
218
219static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
220{
221	const int max_loop_count = 100;
222	const int delay_in_usecs = 1;
223	int i;
224
225	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
226
227	for (i = 0; i < max_loop_count; ++i)
228	{
229		if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED)
230		{
231			break;
232		}
233		_mali_osk_time_ubusydelay(delay_in_usecs);
234	}
235	if (max_loop_count == i)
236	{
237		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)));
238	}
239}
240
241mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
242{
243	const int max_loop_count = 100;
244	const int delay_in_usecs = 999;
245	int i;
246	u32 mmu_status;
247
248	/* There are no group when it is called from mali_mmu_create */
249	if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group);
250
251	mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
252
253	if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) )
254	{
255		MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n"));
256		return MALI_TRUE;
257	}
258
259	if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
260	{
261		MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n"));
262		return MALI_FALSE;
263	}
264
265	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
266
267	for (i = 0; i < max_loop_count; ++i)
268	{
269		mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
270		if ( mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE))
271		{
272			break;
273		}
274		if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED )))
275		{
276			break;
277		}
278		_mali_osk_time_ubusydelay(delay_in_usecs);
279	}
280	if (max_loop_count == i)
281	{
282		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)));
283		return MALI_FALSE;
284	}
285
286	if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
287	{
288		MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it has a pagefault.\n"));
289		return MALI_FALSE;
290	}
291
292	return MALI_TRUE;
293}
294
295void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
296{
297	const int max_loop_count = 100;
298	const int delay_in_usecs = 1;
299	int i;
300	u32 mmu_status;
301	/* There are no group when it is called from mali_mmu_create */
302	if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group);
303
304	mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
305
306	if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
307	{
308		MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n"));
309		return;
310	}
311	if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)
312	{
313		MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n"));
314		return;
315	}
316
317	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
318
319	for (i = 0; i < max_loop_count; ++i)
320	{
321		u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
322		if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) )
323		{
324			break;
325		}
326		if ( status &  MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
327		{
328			break;
329		}
330		if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
331		{
332			break;
333		}
334		_mali_osk_time_ubusydelay(delay_in_usecs);
335	}
336	if (max_loop_count == 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)));
337}
338
339void mali_mmu_page_fault_done(struct mali_mmu_core *mmu)
340{
341	MALI_ASSERT_GROUP_LOCKED(mmu->group);
342	MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description));
343	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
344}
345
346MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu)
347{
348	const int max_loop_count = 100;
349	const int delay_in_usecs = 1;
350	int i;
351	/* The _if_ is neccessary when called from mali_mmu_create and NULL==group */
352	if (mmu->group)MALI_ASSERT_GROUP_LOCKED(mmu->group);
353
354	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
355	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET);
356
357	for (i = 0; i < max_loop_count; ++i)
358	{
359		if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0)
360		{
361			break;
362		}
363		_mali_osk_time_ubusydelay(delay_in_usecs);
364	}
365	if (max_loop_count == i)
366	{
367		MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
368		return _MALI_OSK_ERR_FAULT;
369	}
370
371	return _MALI_OSK_ERR_OK;
372}
373
374_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
375{
376	_mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
377	mali_bool stall_success;
378	MALI_DEBUG_ASSERT_POINTER(mmu);
379	/* The _if_ is neccessary when called from mali_mmu_create and NULL==group */
380	if (mmu->group)
381	{
382		MALI_ASSERT_GROUP_LOCKED(mmu->group);
383	}
384
385	stall_success = mali_mmu_enable_stall(mmu);
386
387	/* The stall can not fail in current hw-state */
388	MALI_DEBUG_ASSERT(stall_success);
389
390	MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
391
392	if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu))
393	{
394		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
395		/* no session is active, so just activate the empty page directory */
396		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
397		mali_mmu_enable_paging(mmu);
398		err = _MALI_OSK_ERR_OK;
399	}
400	mali_mmu_disable_stall(mmu);
401
402	return err;
403}
404
405
406/* ------------- interrupt handling below ------------------ */
407
408static _mali_osk_errcode_t mali_mmu_upper_half(void * data)
409{
410	struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
411	u32 int_stat;
412
413	MALI_DEBUG_ASSERT_POINTER(mmu);
414
415	/* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
416	int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
417	if (0 != int_stat)
418	{
419		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0);
420		mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
421
422		if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
423		{
424			_mali_osk_irq_schedulework(mmu->irq);
425		}
426
427		if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
428		{
429			/* clear interrupt flag */
430			mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
431			/* reenable it */
432			mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK,
433			                            mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
434			MALI_PRINT_ERROR(("Mali MMU: Read bus error\n"));
435		}
436		return _MALI_OSK_ERR_OK;
437	}
438
439	return _MALI_OSK_ERR_FAULT;
440}
441
442static void mali_mmu_bottom_half(void * data)
443{
444	struct mali_mmu_core *mmu = (struct mali_mmu_core*)data;
445	u32 raw, status, fault_address;
446
447	MALI_DEBUG_ASSERT_POINTER(mmu);
448
449	MALI_DEBUG_PRINT(3, ("Mali MMU: Page fault bottom half: Locking subsystems\n"));
450
451	mali_group_lock(mmu->group); /* Unlocked in mali_group_bottom_half */
452
453	if ( MALI_FALSE == mali_group_power_is_on(mmu->group) )
454	{
455		MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.",mmu->hw_core.description));
456		mali_group_unlock(mmu->group);
457		return;
458	}
459
460	raw = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT);
461	status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
462
463	if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) &&  (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) )
464	{
465		MALI_DEBUG_PRINT(2, ("Mali MMU: Page fault bottom half: No Irq found.\n"));
466		mali_group_unlock(mmu->group);
467		/* MALI_DEBUG_ASSERT(0); */
468		return;
469	}
470
471	/* An actual page fault has occurred. */
472
473	fault_address = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
474
475	MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n",
476	           (void*)fault_address,
477	           (status >> 6) & 0x1F,
478	           (status & 32) ? "write" : "read",
479	           mmu->hw_core.description));
480
481	mali_group_bottom_half(mmu->group, GROUP_EVENT_MMU_PAGE_FAULT); /* Unlocks the group lock */
482}
483
484mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
485{
486	mali_bool stall_success;
487	MALI_ASSERT_GROUP_LOCKED(mmu->group);
488
489	stall_success = mali_mmu_enable_stall(mmu);
490
491	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
492
493	if (MALI_FALSE == stall_success)
494	{
495		/* False means that it is in Pagefault state. Not possible to disable_stall then */
496		return MALI_FALSE;
497	}
498
499	mali_mmu_disable_stall(mmu);
500	return MALI_TRUE;
501}
502
503void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu)
504{
505	MALI_ASSERT_GROUP_LOCKED(mmu->group);
506	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
507}
508
509
510void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address)
511{
512	MALI_ASSERT_GROUP_LOCKED(mmu->group);
513	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address));
514}
515
516static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory)
517{
518	MALI_ASSERT_GROUP_LOCKED(mmu->group);
519	/* The MMU must be in stalled or page fault mode, for this writing to work */
520	MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)
521							  & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
522	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
523	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
524
525}
526
527mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
528{
529	mali_bool stall_success;
530	MALI_DEBUG_ASSERT_POINTER(mmu);
531	MALI_ASSERT_GROUP_LOCKED(mmu->group);
532
533	MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));
534	stall_success = mali_mmu_enable_stall(mmu);
535
536	if ( MALI_FALSE==stall_success ) return MALI_FALSE;
537	mali_mmu_activate_address_space(mmu, pagedir->page_directory);
538	mali_mmu_disable_stall(mmu);
539	return MALI_TRUE;
540}
541
542void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu)
543{
544	mali_bool stall_success;
545	MALI_DEBUG_ASSERT_POINTER(mmu);
546	MALI_ASSERT_GROUP_LOCKED(mmu->group);
547	MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
548
549	stall_success = mali_mmu_enable_stall(mmu);
550	/* This function can only be called when the core is idle, so it could not fail. */
551	MALI_DEBUG_ASSERT( stall_success );
552	mali_mmu_activate_address_space(mmu, mali_empty_page_directory);
553	mali_mmu_disable_stall(mmu);
554}
555
556void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu)
557{
558	mali_bool stall_success;
559	MALI_DEBUG_ASSERT_POINTER(mmu);
560	MALI_ASSERT_GROUP_LOCKED(mmu->group);
561
562	MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description));
563	stall_success = mali_mmu_enable_stall(mmu);
564	/* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */
565	mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory);
566	if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu);
567}
568
569/* Is called when we want the mmu to give an interrupt */
570static void mali_mmu_probe_trigger(void *data)
571{
572	struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
573	mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
574}
575
576/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
577static _mali_osk_errcode_t mali_mmu_probe_ack(void *data)
578{
579	struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
580	u32 int_stat;
581
582	int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
583
584	MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
585	if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
586	{
587		MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
588		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
589	}
590	else
591	{
592		MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
593	}
594
595	if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
596	{
597		MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
598		mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
599	}
600	else
601	{
602		MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
603	}
604
605	if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
606	                 (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR))
607	{
608		return _MALI_OSK_ERR_OK;
609	}
610
611	return _MALI_OSK_ERR_FAULT;
612}
613
614#if 0
615void mali_mmu_print_state(struct mali_mmu_core *mmu)
616{
617	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)));
618}
619#endif