/drivers/gpu/mali/mali/common/mali_mmu.c
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