00001
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include <avr32/io.h>
00051 #include "mmu.h"
00052 #include "macro.h"
00053 #include "usart.h"
00054
00055
00056 int mmu_add_entry(long vpn, long pfn, int pos, int type);
00057 int mmu_read_entry(long * vpn, long * pfn, int pos, int type);
00058 int mmu_get_addrmask_from_page_size(long tlbelo, long *address_mask);
00059
00060
00081 int mmu_init(int enable, int mode, int segmentation)
00082 {
00083 long regval = 0;
00084 long regval_read = 0;
00085
00086 AVR32_READ_SR_REG(AVR32_MMUCR, regval);
00087
00088 regval = (enable<<AVR32_MMUCR_E_OFFSET)|
00089 (mode<<AVR32_MMUCR_M_OFFSET)|
00090 (segmentation<<AVR32_MMUCR_S_OFFSET);
00091
00092 AVR32_SET_SR_REG(AVR32_MMUCR, regval);
00093
00094 AVR32_READ_SR_REG(AVR32_MMUCR, regval_read);
00095
00096 if (regval != regval_read) {
00097 return MMU_ERROR;
00098 }
00099
00100 return MMU_OK;
00101 }
00102
00103
00110 int mmu_reset()
00111 {
00112 long regval;
00113 int timer = 10;
00114
00115 AVR32_SET_SR_REG(AVR32_MMUCR, AVR32_MMUCR_S_MASK|AVR32_MMUCR_I_MASK);
00116
00117
00118 do {
00119 AVR32_READ_SR_REG(AVR32_MMUCR, regval);
00120 --timer;
00121 } while ((regval & AVR32_MMUCR_I_MASK) != 0 && timer > 0);
00122
00123 if (regval != AVR32_MMUCR_S_MASK || timer == 0) {
00124 return MMU_ERROR;
00125 }
00126
00127 AVR32_SET_SR_REG(AVR32_TLBARHI, 0);
00128 AVR32_SET_SR_REG(AVR32_TLBARLO, 0);
00129
00130 return MMU_OK;
00131 }
00132
00133
00147 int mmu_search_virtual_ptr(void *virtual_ptr, long *physical_addr)
00148 {
00149 long addr_mask;
00150 long vpn;
00151 long pfn;
00152 int retval;
00153 int i;
00154
00155 for (i = 0; i < MMU_DTLB_ENTRIES; i++) {
00156
00157 retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_DATA);
00158 if (retval != MMU_OK) {
00159 return retval;
00160 }
00161
00162 retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00163 if (retval == MMU_OK) {
00164 if (((long)virtual_ptr & addr_mask) == (vpn & addr_mask)
00165 && (vpn & AVR32_TLBEHI_V_MASK)) {
00166 *physical_addr = (pfn & addr_mask)
00167 |((long)virtual_ptr & ~addr_mask);
00168 return MMU_OK;
00169 }
00170 }
00171 }
00172
00173 for (i = 0; i < MMU_ITLB_ENTRIES; i++) {
00174
00175 retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_INSTRUCTION);
00176 if (retval != MMU_OK) {
00177 return retval;
00178 }
00179
00180 retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00181 if (retval == MMU_OK) {
00182 if (((long)virtual_ptr & addr_mask) == (vpn & addr_mask)
00183 && (vpn & AVR32_TLBEHI_V_MASK)) {
00184 *physical_addr = (pfn & addr_mask)
00185 |((long)virtual_ptr & ~addr_mask);
00186 return MMU_OK;
00187 }
00188 }
00189 }
00190
00191
00192
00193 return MMU_TLB_MISS;
00194 }
00195
00196
00210 int mmu_search_physical_ptr(void *physical_ptr, long *virtual_addr)
00211 {
00212 long addr_mask;
00213 long vpn;
00214 long pfn;
00215 int retval;
00216 int i;
00217
00218 for (i = 0; i < MMU_DTLB_ENTRIES; i++) {
00219
00220 retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_DATA);
00221 if (retval != MMU_OK) {
00222 return retval;
00223 }
00224
00225 retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00226 if (retval == MMU_OK) {
00227 if (((long)physical_ptr & addr_mask) == (pfn & addr_mask)
00228 && (vpn & AVR32_TLBEHI_V_MASK)) {
00229 *virtual_addr = (vpn & addr_mask)
00230 |((long)physical_ptr & ~addr_mask);
00231 return MMU_OK;
00232 }
00233 }
00234 }
00235
00236 for (i = 0; i < MMU_ITLB_ENTRIES; i++) {
00237
00238 retval = mmu_read_entry(&vpn, &pfn, i, MMU_TLB_TYPE_INSTRUCTION);
00239 if (retval != MMU_OK) {
00240 return retval;
00241 }
00242
00243 retval = mmu_get_addrmask_from_page_size(pfn, &addr_mask);
00244 if (retval == MMU_OK) {
00245 if (((long)physical_ptr & addr_mask) == (pfn & addr_mask)
00246 && (vpn & AVR32_TLBEHI_V_MASK)) {
00247 *virtual_addr = (vpn & addr_mask)
00248 |((long)physical_ptr & ~addr_mask);
00249 return MMU_OK;
00250 }
00251 }
00252 }
00253
00254
00255 return MMU_TLB_MISS;
00256 }
00257
00258
00266 int mmu_lock_entries(int entries, int type)
00267 {
00268 if (entries < 0 ||
00269 ((type == MMU_TLB_TYPE_DATA &&
00270 entries >= MMU_DTLB_ENTRIES) ||
00271 (type == MMU_TLB_TYPE_INSTRUCTION &&
00272 entries >= MMU_ITLB_ENTRIES))) {
00273 return MMU_ERROR_ARGUMENT;
00274 }
00275
00276 long regValue = 0;
00277
00278 AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00279
00280 if (type == MMU_TLB_TYPE_INSTRUCTION) {
00281 regValue &= ~(AVR32_MMUCR_ILA_MASK);
00282 regValue |= (entries<<AVR32_MMUCR_ILA_OFFSET);
00283 } else {
00284 regValue &= ~(AVR32_MMUCR_DLA_MASK);
00285 regValue |= (entries<<AVR32_MMUCR_DLA_OFFSET);
00286 }
00287
00288 AVR32_SET_SR_REG(AVR32_MMUCR, regValue);
00289
00290 return MMU_OK;
00291 }
00292
00293
00304 int mmu_add_tlb_entry(long physical_addr_base,
00305 long virtual_addr_base, struct mmu_tlb_t *options)
00306 {
00307 if (!(options->valid == MMU_ENABLE
00308 || options->valid == MMU_DISABLE)) {
00309 return MMU_ERROR_ARGUMENT;
00310 }
00311 else if (!(options->type == MMU_TLB_TYPE_INSTRUCTION
00312 || options->type == MMU_TLB_TYPE_DATA)) {
00313 return MMU_ERROR_ARGUMENT;
00314 }
00315 else if (options->asid > 0xFF
00316 || options->asid < 0) {
00317 return MMU_ERROR_ARGUMENT;
00318 }
00319 else if (!(options->cachable == MMU_ENABLE
00320 || options->cachable == MMU_DISABLE)) {
00321 return MMU_ERROR_ARGUMENT;
00322 }
00323 else if (!(options->global == MMU_ENABLE
00324 || options->global == MMU_DISABLE)) {
00325 return MMU_ERROR_ARGUMENT;
00326 }
00327 else if (!(options->bufferable == MMU_ENABLE
00328 || options->bufferable == MMU_DISABLE)) {
00329 return MMU_ERROR_ARGUMENT;
00330 }
00331 else if (options->access > 0x0D
00332 || options->access < 0) {
00333 return MMU_ERROR_ARGUMENT;
00334 }
00335 else if (!(options->page_size == MMU_PAGE_SIZE_1KB
00336 || options->page_size == MMU_PAGE_SIZE_4KB
00337 || options->page_size == MMU_PAGE_SIZE_64KB
00338 || options->page_size == MMU_PAGE_SIZE_1MB)) {
00339 return MMU_ERROR_ARGUMENT;
00340 }
00341 else if (!(options->dirty == MMU_ENABLE
00342 || options->dirty == MMU_DISABLE)) {
00343 return MMU_ERROR_ARGUMENT;
00344 }
00345 else if (!(options->write_through == MMU_ENABLE
00346 || options->write_through == MMU_DISABLE)) {
00347 return MMU_ERROR_ARGUMENT;
00348 }
00349 else if (options->position < 0 ||
00350 ((options->type == MMU_TLB_TYPE_DATA &&
00351 options->position >= MMU_DTLB_ENTRIES) ||
00352 (options->type == MMU_TLB_TYPE_INSTRUCTION &&
00353 options->position >= MMU_ITLB_ENTRIES))) {
00354 return MMU_ERROR_ARGUMENT;
00355 }
00356
00357 unsigned long vpn;
00358 unsigned long pfn;
00359 unsigned long addr_mask;
00360
00361 if (options->page_size == MMU_PAGE_SIZE_1KB) {
00362 addr_mask = 0xFFFFFC00;
00363 }
00364 else if (options->page_size == MMU_PAGE_SIZE_4KB) {
00365 addr_mask = 0xFFFFF000;
00366 }
00367 else if (options->page_size == MMU_PAGE_SIZE_64KB) {
00368 addr_mask = 0xFFFF0000;
00369 }
00370 else if (options->page_size == MMU_PAGE_SIZE_1MB) {
00371 addr_mask = 0xFFF00000;
00372 } else {
00373 return MMU_ERROR_ARGUMENT;
00374 }
00375
00376 vpn =
00377 (virtual_addr_base & addr_mask)|
00378 (options->valid<<AVR32_TLBEHI_V_OFFSET)|
00379 (options->type<<AVR32_TLBEHI_I_OFFSET)|
00380 (options->asid<<AVR32_TLBEHI_ASID_OFFSET);
00381
00382 pfn =
00383 (physical_addr_base & addr_mask)|
00384 (options->cachable<<AVR32_TLBELO_C_OFFSET)|
00385 (options->global<<AVR32_TLBELO_G_OFFSET)|
00386 (options->bufferable<<AVR32_TLBELO_B_OFFSET)|
00387 (options->access<<AVR32_TLBELO_AP_OFFSET)|
00388 (options->page_size<<AVR32_TLBELO_SZ_OFFSET)|
00389 (options->dirty<<AVR32_TLBELO_D_OFFSET)|
00390 (options->write_through<<AVR32_TLBELO_W_OFFSET);
00391
00392 int retVal = MMU_OK;
00393
00394 retVal = mmu_add_entry(vpn, pfn, options->position, options->type);
00395
00396 return retVal;
00397 }
00398
00399
00406 void mmu_read_bear_and_tlbehi(long *bear, long *vpn)
00407 {
00408 AVR32_READ_SR_REG(AVR32_TLBEAR, *bear);
00409 AVR32_READ_SR_REG(AVR32_TLBEHI, *vpn);
00410 }
00411
00412
00424 int mmu_find_index_to_entry(long physical_addr, long virtual_addr, long *index)
00425 {
00426 long vpn = virtual_addr & 0xFFFFfc00;
00427 long pfn = physical_addr & 0xFFFFfc00;
00428
00429 AVR32_SET_SR_REG(AVR32_TLBEHI, vpn);
00430 AVR32_SET_SR_REG(AVR32_TLBELO, pfn);
00431
00432 #ifdef __GNUC__
00433 __builtin_tlbs();
00434 #elif __ICCAVR32__
00435 __search_TLB_entry();
00436 #else
00437 #error No known compiler used
00438 #endif
00439
00440 long regValue = 0;
00441
00442 AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00443
00444 if ((regValue & AVR32_MMUCR_N_MASK) != 0) {
00445 return MMU_TLB_MISS;
00446 }
00447
00448
00449 if ((vpn & AVR32_TLBEHI_I_MASK) != 0) {
00450 *index = 0x3F & (regValue>>AVR32_MMUCR_IRP_OFFSET);
00451 } else {
00452 *index = 0x3F & (regValue>>AVR32_MMUCR_DRP_OFFSET);
00453 }
00454
00455 return MMU_OK;
00456 }
00457
00458
00470 int mmu_invalidate_entry(int index, int type)
00471 {
00472 if (index < 0 ||
00473 ((type == MMU_TLB_TYPE_DATA &&
00474 index >= MMU_DTLB_ENTRIES) ||
00475 (type == MMU_TLB_TYPE_INSTRUCTION &&
00476 index >= MMU_ITLB_ENTRIES))) {
00477 return MMU_ERROR_ARGUMENT;
00478 }
00479
00480 long regValue = 0;
00481
00482 AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00483
00484 if (type == MMU_TLB_TYPE_INSTRUCTION) {
00485 regValue &= ~(0x3F<<AVR32_MMUCR_IRP_OFFSET);
00486 regValue |= (index<<AVR32_MMUCR_IRP_OFFSET);
00487 } else {
00488 regValue &= ~(0x3F<<AVR32_MMUCR_DRP_OFFSET);
00489 regValue |= (index<<AVR32_MMUCR_DRP_OFFSET);
00490 }
00491
00492 AVR32_SET_SR_REG(AVR32_MMUCR, regValue);
00493
00494 #ifdef __GNUC__
00495 __builtin_tlbr();
00496 #elif __ICCAVR32__
00497 __read_TLB_entry();
00498 #else
00499 #error No known compiler used
00500 #endif
00501
00502 AVR32_CLEAR_SR_BIT(AVR32_TLBEHI, AVR32_TLBEHI_V_OFFSET);
00503
00504 #ifdef __GNUC__
00505 __builtin_tlbw();
00506 #elif __ICCAVR32__
00507 __write_TLB_entry();
00508 #else
00509 #error No known compiler used
00510 #endif
00511
00512 return MMU_OK;
00513 }
00514
00515
00529 int mmu_add_entry(long vpn, long pfn, int pos, int type)
00530 {
00531
00532 if (pos < 0 ||
00533 ((type == MMU_TLB_TYPE_DATA &&
00534 pos >= MMU_DTLB_ENTRIES) ||
00535 (type == MMU_TLB_TYPE_INSTRUCTION &&
00536 pos >= MMU_ITLB_ENTRIES))) {
00537 return MMU_ERROR_ARGUMENT;
00538 }
00539
00540 long regValue = 0;
00541
00542 AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00543
00544 regValue &= 0x0000001F;
00545
00546 if (type == MMU_TLB_TYPE_INSTRUCTION) {
00547 regValue |= (pos<<AVR32_MMUCR_IRP_OFFSET);
00548 }
00549 else if (type == MMU_TLB_TYPE_DATA) {
00550 regValue |= (pos<<AVR32_MMUCR_DRP_OFFSET);
00551 } else {
00552 return MMU_ERROR_ARGUMENT;
00553 }
00554
00555 AVR32_SET_SR_REG(AVR32_MMUCR, regValue);
00556 AVR32_SET_SR_REG(AVR32_TLBEHI, vpn);
00557 AVR32_SET_SR_REG(AVR32_TLBELO, pfn);
00558
00559 #ifdef __GNUC__
00560 __builtin_tlbw();
00561 #elif __ICCAVR32__
00562 __write_TLB_entry();
00563 #else
00564 #error No known compiler used
00565 #endif
00566
00567 return MMU_OK;
00568 }
00569
00570
00585 int mmu_read_entry(long *vpn, long *pfn, int pos, int type)
00586 {
00587 long regValue = 0;
00588 if (pos < 0 ||
00589 ((type == MMU_TLB_TYPE_DATA &&
00590 pos >= MMU_DTLB_ENTRIES) ||
00591 (type == MMU_TLB_TYPE_INSTRUCTION &&
00592 pos >= MMU_ITLB_ENTRIES))) {
00593 return MMU_ERROR_ARGUMENT;
00594 }
00595
00596 AVR32_READ_SR_REG(AVR32_MMUCR, regValue);
00597
00598 if (type== MMU_TLB_TYPE_INSTRUCTION) {
00599 regValue &= ~(0x3F<<AVR32_MMUCR_IRP_OFFSET);
00600 regValue |= (pos<<AVR32_MMUCR_IRP_OFFSET);
00601 } else {
00602 regValue &= ~(0x3F<<AVR32_MMUCR_DRP_OFFSET);
00603 regValue |= (pos<<AVR32_MMUCR_DRP_OFFSET);
00604 }
00605
00606 AVR32_SET_SR_REG(AVR32_MMUCR, regValue);
00607
00608 #ifdef __GNUC__
00609 __builtin_tlbr();
00610 #elif __ICCAVR32__
00611 __read_TLB_entry();
00612 #else
00613 #error No known compiler used
00614 #endif
00615
00616 AVR32_READ_SR_REG(AVR32_TLBEHI, *vpn);
00617 AVR32_READ_SR_REG(AVR32_TLBELO, *pfn);
00618
00619 return MMU_OK;
00620 }
00621
00622
00633 int mmu_get_addrmask_from_page_size(long tlbelo, long *address_mask)
00634 {
00635 int page_size = (tlbelo & AVR32_TLBELO_SZ_MASK) >> AVR32_TLBELO_SZ_OFFSET;
00636
00637 if (page_size == MMU_PAGE_SIZE_1KB) {
00638 *address_mask = 0xFFFFfc00;
00639 }
00640 else if (page_size == MMU_PAGE_SIZE_4KB) {
00641 *address_mask = 0xFFFFf000;
00642 }
00643 else if (page_size == MMU_PAGE_SIZE_64KB) {
00644 *address_mask = 0xFFFF0000;
00645 }
00646 else if (page_size == MMU_PAGE_SIZE_1MB) {
00647 *address_mask = 0xFFF00000;
00648 } else {
00649 return MMU_ERROR_ARGUMENT;
00650 }
00651
00652 return MMU_OK;
00653 }
00654