2023-02-15 12:29:34 +08:00
/*
* SPDX - FileCopyrightText : 2023 Espressif Systems ( Shanghai ) CO LTD
*
* SPDX - License - Identifier : Apache - 2.0
*/
# include <sys/param.h>
# include <inttypes.h>
# include "sdkconfig.h"
# include "esp_check.h"
# include "esp_log.h"
2023-07-13 15:09:12 +08:00
# include "esp_rom_caps.h"
2023-02-15 12:29:34 +08:00
# include "soc/soc_caps.h"
# include "hal/mmu_hal.h"
# include "hal/cache_hal.h"
# include "esp_cache.h"
# include "esp_private/critical_section.h"
static const char * TAG = " cache " ;
DEFINE_CRIT_SECTION_LOCK_STATIC ( s_spinlock ) ;
esp_err_t esp_cache_msync ( void * addr , size_t size , int flags )
{
ESP_RETURN_ON_FALSE_ISR ( addr , ESP_ERR_INVALID_ARG , TAG , " null pointer " ) ;
2023-09-14 12:14:08 +08:00
uint32_t addr_end = 0 ;
bool ovf = __builtin_add_overflow ( ( uint32_t ) addr , size , & addr_end ) ;
ESP_EARLY_LOGV ( TAG , " addr_end: 0x%x \n " , addr_end ) ;
ESP_RETURN_ON_FALSE_ISR ( ! ovf , ESP_ERR_INVALID_ARG , TAG , " wrong size, total size overflow " ) ;
2023-07-05 19:55:32 +08:00
bool both_dir = ( flags & ESP_CACHE_MSYNC_FLAG_DIR_C2M ) & & ( flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C ) ;
ESP_RETURN_ON_FALSE_ISR ( ! both_dir , ESP_ERR_INVALID_ARG , TAG , " both C2M and M2C directions are selected, you should only select one " ) ;
2023-09-14 12:14:08 +08:00
uint32_t vaddr = ( uint32_t ) addr ;
bool valid = false ;
uint32_t cache_level = 0 ;
uint32_t cache_id = 0 ;
valid = cache_hal_vaddr_to_cache_level_id ( vaddr , size , & cache_level , & cache_id ) ;
ESP_RETURN_ON_FALSE_ISR ( valid , ESP_ERR_INVALID_ARG , TAG , " invalid addr or null pointer " ) ;
uint32_t data_cache_line_size = cache_hal_get_cache_line_size ( CACHE_TYPE_DATA , cache_level ) ;
2023-07-20 12:20:42 +08:00
if ( ( flags & ESP_CACHE_MSYNC_FLAG_UNALIGNED ) = = 0 ) {
bool aligned_addr = ( ( ( uint32_t ) addr % data_cache_line_size ) = = 0 ) & & ( ( size % data_cache_line_size ) = = 0 ) ;
2023-09-14 12:14:08 +08:00
ESP_RETURN_ON_FALSE_ISR ( aligned_addr , ESP_ERR_INVALID_ARG , TAG , " start address: 0x%x, or the size: 0x%x is(are) not aligned with the data cache line size (0x%x)B " , ( uint32_t ) addr , size , data_cache_line_size ) ;
2023-07-20 12:20:42 +08:00
}
2023-07-05 19:55:32 +08:00
if ( flags & ESP_CACHE_MSYNC_FLAG_DIR_M2C ) {
2023-09-14 12:14:08 +08:00
ESP_EARLY_LOGV ( TAG , " M2C DIR " ) ;
2023-07-05 19:55:32 +08:00
esp_os_enter_critical_safe ( & s_spinlock ) ;
//Add preload feature / flag here, IDF-7800
2023-09-14 12:14:08 +08:00
valid = cache_hal_invalidate_addr ( vaddr , size ) ;
2023-07-05 19:55:32 +08:00
esp_os_exit_critical_safe ( & s_spinlock ) ;
2023-09-14 12:14:08 +08:00
assert ( valid ) ;
2023-07-05 19:55:32 +08:00
} else {
2023-09-14 12:14:08 +08:00
ESP_EARLY_LOGV ( TAG , " C2M DIR " ) ;
2023-02-15 12:29:34 +08:00
# if SOC_CACHE_WRITEBACK_SUPPORTED
2023-07-05 19:55:32 +08:00
esp_os_enter_critical_safe ( & s_spinlock ) ;
2023-09-14 12:14:08 +08:00
valid = cache_hal_writeback_addr ( vaddr , size ) ;
2023-07-13 15:09:12 +08:00
esp_os_exit_critical_safe ( & s_spinlock ) ;
2023-09-14 12:14:08 +08:00
assert ( valid ) ;
2023-07-13 15:09:12 +08:00
2023-07-05 19:55:32 +08:00
if ( flags & ESP_CACHE_MSYNC_FLAG_INVALIDATE ) {
2023-07-13 15:09:12 +08:00
esp_os_enter_critical_safe ( & s_spinlock ) ;
2023-09-14 12:14:08 +08:00
valid & = cache_hal_invalidate_addr ( vaddr , size ) ;
2023-07-13 15:09:12 +08:00
esp_os_exit_critical_safe ( & s_spinlock ) ;
2023-07-05 19:55:32 +08:00
}
2023-09-14 12:14:08 +08:00
assert ( valid ) ;
2023-02-15 12:29:34 +08:00
# endif
2023-07-05 19:55:32 +08:00
}
2023-02-15 12:29:34 +08:00
return ESP_OK ;
}