⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abl_arm922t_cp15_driver.c

📁 SHARP_ARM720T_LH79524/5软件开发包_支持TFT_LCD_NAND_FLASH_ETH_USB
💻 C
📖 第 1 页 / 共 3 页
字号:
                            return virtual_addr;
                        }
                    }
                    break;
                }
                break;

            case ARM922T_L1D_TYPE_SECTION:
                /* Section type */
                /*******************************************************
                 * Section base -- upper 12 bits of entry is physical 
                 * memory base lower 20 bits of virtual address is 
                 * offset from that base
                 ******************************************************/
                if ((tlb_entry & ARM922T_L2D_SN_BASE_MASK) 
                    == (addr & ARM922T_L2D_SN_BASE_MASK))
                {
                    return (void *)((index << 20) |
                        (addr & ~(ARM922T_L2D_SN_BASE_MASK)));
                }
                break;

            case ARM922T_L1D_TYPE_FPAGE:
                /* Fine page tables, loop through entries */
                page_table = (UNS_32 *)(tlb_entry &
                    ARM922T_L2D_FP_BASE_MASK);
                for (index2 = 0; index2 < ARM922T_FPT_ENTRIES; index2++)
                {
                    level2 = page_table[index2];
                    if (level2)
                    {
                        virtual_addr = (void *)
                            cp15_decode_level2(level2, addr);

                        if (virtual_addr)
                        {
                            return virtual_addr;
                        }
                    }
                }
                break;

            default:
                break;
        }
    }

    return 0;
}

/***********************************************************************
 *
 * Function: cp15_force_cache_coherence
 *
 * Purpose:
 *     Force the CPU to recognize the block of code that was just
 *     written to memory between start_adr and end_adr even if caching
 *     and write buffering is on.
 *
 * Processing:
 *     Cache lines are 32-bytes (8 words); clean and invalidate each
 *     line of D-cache and invalidate each line of I-cache within the
 *     address range.
 *
 *     Invalidate the I-TLB within the the address range. The I-TLB has
 *     256 word granularity.
 *
 * Parameters: 
 *     start_adr:  The first address in the code block
 *     end_adr:    The last address in the code block
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void cp15_force_cache_coherence(UNS_32 *start_adr,
                                UNS_32 *end_adr)
{
    register UNS_32 * addr;
   
    /*******************************************************************
     * Cache lines are 32-bytes (8 words); clean and invalidate each
     * line of D-cache and invalidate each line of I-cache within the
     * address range. Make sure addresses are 32-bit aligned.
     ******************************************************************/
    for (addr = (UNS_32 *)((UNS_32)start_adr & 0xFFFFFFE0);
         addr < end_adr;
         addr += 8)
    {
        /* p15 is MMU coprocessor, Cache OPS is c7, TLB OPS is c8 */
#ifdef __GNUC__
        asm ("MOV r0, %0" : : "r" (addr));
        /* Clean and Invalidate D-Cache single entry using MVA format */
        asm ("MCR p15, 0, r0, c7, c14, 1");
        /* Invalidate I-Cache single entry using MVA format */
        asm ("MCR p15, 0, r0, c7, c5, 1");
#endif
#ifdef __ghs__
        invalcache(addr);
#endif
#ifdef __arm
        __asm
        {
            MOV     r0, addr
            /* Clean and Invalidate D-Cache single entry using MVA 
               format */
            MCR     p15, 0, r0, c7, c14, 1
            /* Invalidate I-Cache single entry using MVA format */
            MCR     p15, 0, r0, c7, c5, 1
        }
#endif
#ifdef __ICCARM__
     
        /* Use IAR intrinsic functions */
        __MCR(15, 0, (UNS_32)addr, 7, 14, 1);
        __MCR(15, 0, (UNS_32)addr, 7, 5, 1);
#endif

    }
    /*******************************************************************
     * Invalidate the I-TLB within the the address range. The I-TLB has
     * 256 word granularity. Make sure addresses are '256 word' aligned.
     ******************************************************************/
    for (addr = (UNS_32 *)((UNS_32)start_adr & 0xFFFFFC00);
         addr < end_adr;
         addr += 256)
    {
#ifdef __GNUC__
        asm ("MOV r0, %0" : : "r" (addr));
        /* Invalidate I-TLB using MVA format */
        asm ("MCR p15, 0, r0, c8, c5, 1");
        asm ("NOP");
        asm ("NOP");
#endif
#ifdef __ghs__
        invaltlb(addr);
#endif
#ifdef __arm
        __asm
        {
            MOV     r0, addr
            /* Invalidate I-TLB using MVA format */
            MCR      p15, 0, r0, c8, c5, 1
            NOP
            NOP
        }
#endif
#ifdef __ICCARM__

		/* Invalidate I-TLB using MVA format */
		/* Use IAR intrinsic functions */
        __MCR(15, 0, (UNS_32)addr, 8, 5, 1);
        __no_operation();
        __no_operation();
#endif
    }
}

/***********************************************************************
 *
 * Function: cp15_init_mmu_trans_table
 *
 * Purpose: Initializes the MMU page table
 *
 * Processing:
 *     Return error if MMU is enabled. Return error if target
 *     Translation Table address is not 16K aligned. Clear the
 *     Translation Table area. Build the Translation Table from the
 *     initialization data in the Section Block array. Return no error.
 *
 * Parameters:  
 *      tt:    address of Translation Table in RAM.
 *      ttsbp: address of the beginning of the initialization array
 *
 * Outputs: None.
 *
 * Returns:  
 *     This function returns _ERROR when the MMU is enabled, or the
 *     target address is not 16K aligned. Otherwise, it returns
 *     _NO_ERROR.
 *
 * Notes: 
 *     This function is not intended to be used when the MMU is
 *     enabled.
 *
 **********************************************************************/
BOOL_32 cp15_init_mmu_trans_table(TRANSTABLE_T *tt,
                                  TT_SECTION_BLOCK_T *ttsbp)
{
    register UNS_32 control;
    UNS_32 idx;
    UNS_32 va_idx;
    UNS_32 pa_addr;
    UNS_32 *uiptr;
    UNS_32 ret = _NO_ERROR;

    /*******************************************************************
     * The following check returns an error if the MMU is enabled.
     * This condition is not necessarily an error, but an existing
     * Translation Table for an enabled MMU should not be overwritten
     * while the MMU is enabled. 
     ******************************************************************/

    /* Read the control register */
#ifdef __GNUC__
    asm ("MRC p15, 0, %0, c1, c0, 0" : "=r" (control));
#endif
#ifdef __ghs__
    control = getstatus ();
#endif
#ifdef __arm
    __asm
    {
        MRC p15, 0, control, c1, c0, 0;
    }
#endif
#ifdef __ICCARM__
    /* Use IAR intrinsic functions */
    control = __MRC(15, 0, 1, 0, 0); 
#endif

    /* Exit if MMU is already enabeld */
    if ((control & ARM922T_MMU_CONTROL_M) != 0)
    {
        return (_ERROR);
    }

    /* Make sure table address is on a 16K boundary */
    if (((INT_32) tt & ~(ARM922T_TT_ADDR_MASK)) != 0)
    {
        return (_ERROR);
    }

    /*******************************************************************
     * Clear the entire Translation Table.
     * This results in L1D_TYPE_FAULT being the default for any
     * uninitialized entries.
     ******************************************************************/
    uiptr = (UNS_32 *) tt;
    for (idx = 0; idx < ARM922T_TT_ENTRIES; idx++)
        *uiptr++ = ARM922T_L1D_TYPE_FAULT;

    /* Build the translation table from user provided
       TT_SECTION_BLOCK_TYPE array */
    while (ttsbp->num_sections != 0)
    {
        switch ((ttsbp->entry) & ARM922T_L1D_TYPE_PG_SN_MASK)
        {
            case ARM922T_L1D_TYPE_SECTION:
                va_idx = ttsbp->virt_addr >> 20;
                pa_addr = ttsbp->phys_addr & ARM922T_L2D_SN_BASE_MASK;
                for (idx = 0; idx < ttsbp->num_sections; idx++)
                {
                    tt->vidx[va_idx] = (pa_addr | ttsbp->entry);
                    va_idx++;
                    pa_addr += 0x100000;
                }
                break;

            case (ARM922T_L1D_TYPE_CPAGE):
                va_idx = ttsbp->virt_addr >> 20;
                pa_addr = ttsbp->phys_addr & ARM922T_L2D_CP_BASE_MASK;
                for (idx = 0; idx < ttsbp->num_sections; idx++)
                {
                    tt->vidx[va_idx] = pa_addr | ttsbp->entry;
                    va_idx++;
                    pa_addr += 0x100000;
                }
                break;

            case ARM922T_L1D_TYPE_FAULT:
            default:
                break;
        }

        ttsbp++;
    }

    return ret;
}

/***********************************************************************
 *
 * Function: cp15_set_vmmu_addr
 *
 * Purpose: Set the virtual address of the MMU table
 *
 * Processing:
 *     Set the saved virtual MMU table address to the passed value.
 *
 * Parameters:  
 *      addr: Virtual address of start of MMU table
 *
 * Outputs: None.
 *
 * Returns: Nothing
 *
 * Notes:
 *     This function must be called if the driver MMU functions are
 *     being used. This should be set after the call to the
 *     cp15_init_mmu_trans_table() function.
 *
 **********************************************************************/
void cp15_set_vmmu_addr(UNS_32 *addr)
{
    virtual_tlb_addr = addr;
}

/***********************************************************************
 *
 * Function: cp15_get_ttb
 *
 * Purpose: Return the physical address of the MMU translation table
 *
 * Processing:
 *     Read the TTB register from coprocessor 15 and return it to the
 *     caller.
 *
 * Parameters: None
 *
 * Outputs: None.
 *
 * Returns: The base address of the MMU translation table
 *
 * Notes: None
 *
 **********************************************************************/
UNS_32 *cp15_get_ttb(void)
{
    register UNS_32 ttb;

#ifdef __GNUC__
    asm ("MRC p15, 0, %0, c2, c0, 0" : "=r" (ttb));
#endif
#ifdef __ghs__
    ttb = getttb();
#endif
#ifdef __arm
    __asm
    {
        MRC p15, 0, ttb, c2, c0, 0;
    }
#endif
#ifdef __ICCARM__
    /* use IAR CC intrinsic function to read CP15 reg */
	ttb = __MRC(15, 0, 2, 0, 0); 
#endif
    
    return (UNS_32 *) ttb;
}

/***********************************************************************
 *
 * Function: cp15_dcache_flush
 *
 * Purpose: Force an data cache flush
 *
 * Processing:
 *     Flush each data cache entry using the segment/index method.
 *
 * Parameters: None
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void cp15_dcache_flush(void)
{
#ifdef __GNUC__
    
#endif
#ifdef __ghs__
    
#endif
#ifdef __arm
    INT_32 segment, index, comp, cache_sz, total_seg;

    __asm
    {
        MRC p15, 0, cache_sz, c0, c0, 1
    }
    
    /* For 8KB cache the size field is 4 and for 16 it is 5.
    */
    total_seg = (1 << (ARM922T_MMU_DC_SIZE(cache_sz) - 2));
    
    for (segment = 0; segment < total_seg; segment++)
    {
        for (index = 0; index < 64; index++)
        {
            /* For each segment and index, flush the data cache */
            comp = (segment << 5) | (index << 26);
            __asm
            {
                MCR p15, 0, comp, c8, c5, 1
            }
        }
    }
#endif
#ifdef __ICCARM__

#endif
}

/***********************************************************************
 *
 * Function: cp15_write_buffer_flush
 *
 * Purpose: Force an write buffer flush
 *
 * Processing:
 *     Flush the write buffer and wait for completion of the flush.
 *
 * Parameters: None
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void cp15_write_buffer_flush(void)
{
#ifdef __GNUC__
    
#endif
#ifdef __ghs__
    
#endif
#ifdef __arm
    __asm
    {
        MOV r0, #0
        MCR p15, 0, r0, c7, c10, 4
    }
#endif
#ifdef __ICCARM__

#endif
}

/***********************************************************************
 *
 * Function: cp15_mmu_enabled
 *
 * Purpose:
 *  Checks to see if the MMU is enabled
 *
 * Processing:
 *  Read the MMU control register and check if the MMU enable bit 
 *  (bit 0) is set.
 *
 * Parameters: None
 *
 * Outputs: None
 *
 * Returns: 
 *  TRUE if the MMU is enabled
 *  FALSE if the MMU is disabled
 *
 * Notes: None
 *
 **********************************************************************/
BOOL_32 cp15_mmu_enabled(void)
{
    UNS_32 mmu_reg;

#ifdef __GNUC__
    asm ("MRC p15, 0, %0, c1, c0, 0" : "=r" (mmu_reg));
#endif

#ifdef __ghs__
    mmu_reg = getstatus ();
#endif

#ifdef __arm
    __asm

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -