/* * Copyright (c) 2017 Actions Semiconductor Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief SPICACHE profile interface for Actions SoC */ #include #include #include "soc.h" #include "spicache.h" #include "board_cfg.h" #define SPI1_CACHE_SIZE (1024*32) #ifdef CONFIG_SOC_SPICACHE_PROFILE static void spicache_update_profile_data(struct spicache_profile *profile) { if (!profile->spi_id) { profile->hit_cnt = sys_read32(SPICACHE_RANGE_ADDR_HIT_COUNT); profile->miss_cnt = sys_read32(SPICACHE_RANGE_ADDR_MISS_COUNT); profile->total_hit_cnt = sys_read32(SPICACHE_TOTAL_HIT_COUNT); profile->total_miss_cnt = sys_read32(SPICACHE_TOTAL_MISS_COUNT); } else { profile->hit_cnt = sys_read32(SPI1_CACHE_MCPU_HIT_COUNT); profile->miss_cnt = sys_read32(SPI1_CACHE_MCPU_MISS_COUNT); profile->dma_hit_cnt = sys_read32(SPI1_CACHE_DMA_HIT_COUNT); profile->dma_miss_cnt = sys_read32(SPI1_CACHE_DMA_MISS_COUNT); } } int spicache_profile_get_data(struct spicache_profile *profile) { if (!profile) return -EINVAL; spicache_update_profile_data(profile); return 0; } int spicache_profile_stop(struct spicache_profile *profile) { if (!profile) return -EINVAL; profile->end_time = k_cycle_get_32(); spicache_update_profile_data(profile); if (!profile->spi_id) sys_write32(sys_read32(SPICACHE_CTL) & ~(1 << 4), SPICACHE_CTL); else sys_write32(sys_read32(SPI1_CACHE_CTL) & ~(1 << 4), SPI1_CACHE_CTL); return 0; } int spicache_profile_start(struct spicache_profile *profile) { if (!profile) return -EINVAL; if (!profile->spi_id) { sys_write32(profile->start_addr, SPICACHE_PROFILE_ADDR_START); sys_write32(profile->end_addr, SPICACHE_PROFILE_ADDR_END); } else { sys_write32(profile->start_addr, SPI1_CACHE_PROFILE_ADDR_START); sys_write32(profile->end_addr, SPI1_CACHE_PROFILE_ADDR_END); } profile->start_time = k_cycle_get_32(); if (!profile->spi_id) sys_write32(sys_read32(SPICACHE_CTL) | (1 << 4), SPICACHE_CTL); else sys_write32(sys_read32(SPI1_CACHE_CTL) | (1 << 4), SPI1_CACHE_CTL); return 0; } #endif int spicache_master_enable(int spi_id, SPI_CACHE_MASTER master_id) { if (!spi_id) { if ((master_id >= SPI0_CACHE_MASTER_DMA) && (master_id <= SPI0_CACHE_MASTER_DE)) sys_write32(sys_read32(SPICACHE_CTL) | (1<<((master_id - SPI0_CACHE_MASTER_DMA) + 9)), SPICACHE_CTL); } else { if ((master_id >= SPI1_CACHE_MASTER_GPU) && (master_id <= SPI1_CACHE_MASTER_DE)) sys_write32(sys_read32(SPI1_CACHE_CTL) | (1<<((master_id - SPI1_CACHE_MASTER_GPU) + 8)), SPI1_CACHE_CTL); } return 0; } int spicache_master_disable(int spi_id, SPI_CACHE_MASTER master_id) { if (!spi_id) { if ((master_id >= SPI0_CACHE_MASTER_DMA) && (master_id<=SPI0_CACHE_MASTER_DE)) sys_write32(sys_read32(SPICACHE_CTL) & ~(1<<((master_id - SPI0_CACHE_MASTER_DMA) + 9)), SPICACHE_CTL); } else { if ((master_id >= SPI1_CACHE_MASTER_GPU) && (master_id <= SPI1_CACHE_MASTER_DE)) sys_write32(sys_read32(SPI1_CACHE_CTL) & ~(1<<((master_id - SPI1_CACHE_MASTER_GPU) + 8)), SPI1_CACHE_CTL); } return 0; } int spicache_set_priority(int spi_id, SPI_CACHE_PRIORITY priority) { if (!spi_id) { sys_write32((sys_read32(SPICACHE_CTL) & ~(0xf<<20)) | ((priority - SPI0_CACHE_PRIORITY_POLL)<<20), SPICACHE_CTL); } else { sys_write32((sys_read32(SPI1_CACHE_CTL) & ~(0xf<<20)) | ((priority - SPI1_CACHE_PRIORITY_POLL)<<20), SPI1_CACHE_CTL); } return 0; } void spi1_cache_ops_wait_finshed(void) { while(sys_test_bit(SPI1_CACHE_OPERATE, 0)); } void spi1_cache_ops(SPI_CACHE_OPS ops, void* addr, int size) { // uint32_t end; uint32_t off = (uint32_t)addr; uint32_t op; if((off < SPI1_CACHE_WT_WNA_ADDR) || (off > SPI1_UNCACHE_END_ADDR)) return; spi1_cache_ops_wait_finshed(); switch(ops){ case SPI_CACHE_FLUSH: sys_write32((uint32_t)addr, CACHE_OPERATE_ADDR_START); sys_write32((uint32_t)addr + size - 1, CACHE_OPERATE_ADDR_END); op = 0x13; // write back // configurable address space mode sys_write32(op, SPI1_CACHE_OPERATE); spi1_cache_ops_wait_finshed(); return; case SPI_CACHE_INVALIDATE: sys_write32((uint32_t)addr, CACHE_OPERATE_ADDR_START); sys_write32((uint32_t)addr + size - 1, CACHE_OPERATE_ADDR_END); op = 0x0b; // invalid // configurable address space mode sys_write32(op, SPI1_CACHE_OPERATE); spi1_cache_ops_wait_finshed(); return; case SPI_WRITEBUF_FLUSH: sys_write32(0x1f, SPI1_CACHE_OPERATE); spi1_cache_ops_wait_finshed(); return; case SPI_CACHE_FLUSH_ALL://flush all sys_write32(0x11, SPI1_CACHE_OPERATE); return ; case SPI_CACHE_INVALID_ALL: //invalid all sys_write32(0x9, SPI1_CACHE_OPERATE); spi1_cache_ops_wait_finshed(); return ; case SPI_CACHE_FLUSH_INVALID: sys_write32((uint32_t)addr, CACHE_OPERATE_ADDR_START); sys_write32((uint32_t)addr + size - 1, CACHE_OPERATE_ADDR_END); op = 0x1b; // writeback & invalid // configurable address space mode sys_write32(op, SPI1_CACHE_OPERATE); spi1_cache_ops_wait_finshed(); return; case SPI_CACHE_FLUSH_INVALID_ALL: sys_write32(0x19, SPI1_CACHE_OPERATE); //flush and invalid all return ; default: return; } // /*address mode operate*/ // off = (off - SPI1_BASE_ADDR); // end = off + size; // off &= (~0x1f); // /*not flush all*/ // while(off < end) { // sys_write32(op|off, SPI1_CACHE_OPERATE); // off+= 0x20; // //while(sys_test_bit(SPI1_CACHE_OPERATE, 0)); // spi1_cache_ops_wait_finshed(); // } } static uint32_t system_phy_addr, sdfs_phy_addr; static uint32_t get_system_phy_addr(void) { if (system_phy_addr == 0) { system_phy_addr = soc_boot_get_info()->system_phy_addr; } return system_phy_addr; } #include static uint32_t get_sdfs_phy_addr(void) { const struct partition_entry *part; if (sdfs_phy_addr == 0) { part = partition_get_part(PARTITION_FILE_ID_SDFS); if (part) { sdfs_phy_addr = part->file_offset; } } return sdfs_phy_addr; } void * cache_to_uncache(void *vaddr) { void *pvadr = vaddr; if (buf_is_nor(vaddr)) { pvadr = (void *) (SPI0_UNCACHE_ADDR + (((uint32_t)vaddr) - SPI0_BASE_ADDR)); } else if (buf_is_psram_cache(vaddr)) { pvadr = (void *) (SPI1_UNCACHE_ADDR + (((uint32_t)vaddr) - SPI1_BASE_ADDR)); } else if (buf_is_psram_wt_wna(vaddr)) { pvadr = (void *) (SPI1_UNCACHE_ADDR + (((uint32_t)vaddr) - SPI1_CACHE_WT_WNA_ADDR)); } return pvadr; } void * cache_to_unmap_uncache(void *vaddr) { void *pvadr = vaddr; if (buf_is_nor(vaddr)) { uint32_t vaddr_val = (uint32_t)vaddr; if ((vaddr_val & 0xff000000) == CONFIG_FLASH_BASE_ADDRESS) { pvadr = (void *) (SPI0_UNCACHE_ADDR + (vaddr_val - CONFIG_FLASH_BASE_ADDRESS + get_system_phy_addr())); } else if ((vaddr_val & 0xff000000) == CONFIG_SPI_XIP_VADDR) { pvadr = (void *) ((vaddr_val - CONFIG_SPI_XIP_VADDR + SPI0_UNCACHE_ADDR)); } } return pvadr; } void * cache_to_uncache_by_master(void *vaddr, SPI_CACHE_MASTER master_id) { if ((master_id >= SPI0_CACHE_MASTER_DMA) && (master_id<=SPI0_CACHE_MASTER_DE)) return cache_to_unmap_uncache(vaddr); return cache_to_uncache(vaddr); } void * uncache_to_cache(void *paddr) { void *vaddr = paddr; if (buf_is_nor_un(paddr)) { vaddr = (void *) (SPI0_BASE_ADDR + (((uint32_t)paddr) - SPI0_UNCACHE_ADDR)); } else if (buf_is_psram_un(paddr)) { vaddr = (void *) (SPI1_BASE_ADDR + (((uint32_t)paddr) - SPI1_UNCACHE_ADDR)); } return vaddr; } void * unmap_uncache_to_cache(void *paddr) { void *vaddr = paddr; if (buf_is_nor_un(paddr)) { uint32_t offs = (uint32_t)paddr - SPI0_UNCACHE_ADDR; if ((offs >= get_system_phy_addr()) && (offs < get_sdfs_phy_addr())) { vaddr = (void *) (SPI0_BASE_ADDR + (offs- get_system_phy_addr())); } else if (offs >= get_sdfs_phy_addr()) { vaddr = (void *) (CONFIG_SD_FS_VADDR_START + (offs - get_sdfs_phy_addr())); } } return vaddr; } void * uncache_to_cache_by_master(void *paddr, SPI_CACHE_MASTER master_id) { if ((master_id >= SPI0_CACHE_MASTER_DMA) && (master_id<=SPI0_CACHE_MASTER_DE)) return unmap_uncache_to_cache(paddr); return uncache_to_cache(paddr); } void * uncache_to_wt_wna_cache(void *paddr) { void *vaddr = paddr; if (buf_is_psram_un(paddr)) { vaddr = (void *) (SPI1_CACHE_WT_WNA_ADDR + (((uint32_t)paddr) - SPI1_UNCACHE_ADDR)); } return vaddr; } void * cache_to_wt_wna_cache(void *vaddr) { void *pvadr = vaddr; if (buf_is_psram_cache(vaddr)) { pvadr = (void *) (SPI1_CACHE_WT_WNA_ADDR + (((uint32_t)vaddr) - SPI1_BASE_ADDR)); } return pvadr; } void * wt_wna_cache_to_cache(void *vaddr) { void *pvadr = vaddr; if (buf_is_psram_wt_wna(vaddr)) { pvadr = (void *) (SPI1_BASE_ADDR + (((uint32_t)vaddr) - SPI1_CACHE_WT_WNA_ADDR)); } return pvadr; }