| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <xtensa/corebits.h>
- #include <sdkconfig.h>
- #include "soc/extmem_reg.h"
- /**
- * @brief Write back the cache items of DCache, enable cache freeze during writeback.
- * Operation will be done CACHE_LINE_SIZE aligned.
- * If the region is not in DCache addr room, nothing will be done.
- * Please do not call this function in your SDK application.
- * @param uint32_t addr: start address to write back
- * @param uint32_t items: cache lines to invalidate, items * cache_line_size should
- * not exceed the bus address size(4MB)
- *
- * void cache_writeback_items_freeze(uint32_t addr, uint32_t items)
- */
- /*******************************************************************************
- This function is a cache write-back function that works around the following
- hardware errata on the ESP32-S3:
- - Core X manually triggers (via the EXTMEM_DCACHE_SYNC_CTRL_REG register) the
- write-back of one or more cache lines.
- - While the write-back is in progress, there are two scenarios that may cause
- cache hit error.
- - Core X enters the interrupt handler and access the same cache line
- being written back.
- - Core Y access the same cache line being written back.
- To workaround this errata, the following steps must be taken when manually
- triggering a cache write-back:
- - Core X must disable interrupts so that it cannot be preempted
- - Core X must freeze the cache (via the EXTMEM_DCACHE_FREEZE_REG register) to
- prevent Core Y from accessing the same cache lines that are about to be written
- back.
- - Core X now triggers the cache write-back. During the write-back...
- - If Core Y attempts the access any address in the cache region, Core Y will
- busy wait until the cache is unfrozen.
- - Core X must ensure that it does not access any address in the cache region,
- otherwise Core X will busy wait thus causing a deadlock.
- - After the write-back is complete, Core X unfreezes the cache, and reenables
- interrupts.
- Notes:
- - Please do not modify this function, it must strictly follow the current execution
- sequence, otherwise it may cause unexpected errors.
- - This function is written in assmebly to ensure that the function itself never
- accesses any cache address while the cache is frozen. Unexpected cache access
- could occur if...
- - the function triggers an window overflow onto a stack placed in PSRAM.
- Thus, we only use two window panes (a0 to a8) in this function and trigger
- all window overflows before freezing the cache.
- - the function accesses literals/read-only variables placed in Flash.
- *******************************************************************************/
- .align 4
- /*
- Create dedicated literal pool for this function. Mostly used to store out
- of range movi transformations.
- */
- .literal_position
- .global cache_writeback_items_freeze
- .type cache_writeback_items_freeze, @function
- cache_writeback_items_freeze:
- entry sp, 32
- /* REG_WRITE(EXTMEM_DCACHE_SYNC_ADDR_REG, addr); */
- movi a4, EXTMEM_DCACHE_SYNC_ADDR_REG
- s32i a2, a4, 0
- /* REG_WRITE(EXTMEM_DCACHE_SYNC_SIZE_REG, items); */
- movi a4, EXTMEM_DCACHE_SYNC_SIZE_REG
- s32i a3, a4, 0
- memw /* About to freeze the cache. Ensure all previous memory R/W are completed */
- movi a2, EXTMEM_DCACHE_FREEZE_REG
- movi a3, EXTMEM_DCACHE_SYNC_CTRL_REG
- /*
- REG_CLR_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_MODE);
- REG_SET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_ENA);
- */
- l32i a4, a2, 0 /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
- movi a5, ~(EXTMEM_DCACHE_FREEZE_MODE_M)
- and a4, a4, a5
- movi a5, EXTMEM_DCACHE_FREEZE_ENA_M
- or a4, a4, a5
- s32i a4, a2, 0 /* *(EXTMEM_DCACHE_FREEZE_REG) = a4 */
- /* while (!REG_GET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_DONE)); */
- movi a5, EXTMEM_DCACHE_FREEZE_DONE_M
- _wait_freeze_done:
- l32i a4, a2, 0 /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
- memw
- bnone a4, a5, _wait_freeze_done
- /* REG_SET_BIT(EXTMEM_DCACHE_SYNC_CTRL_REG, EXTMEM_DCACHE_WRITEBACK_ENA); */
- l32i a4, a3, 0 /* a4 = *(EXTMEM_DCACHE_SYNC_CTRL_REG) */
- movi a5, EXTMEM_DCACHE_WRITEBACK_ENA_M
- or a4, a4, a5
- s32i a4, a3, 0 /* *(EXTMEM_DCACHE_SYNC_CTRL_REG) = a4 */
- /* while(!REG_GET_BIT(EXTMEM_DCACHE_SYNC_CTRL_REG, EXTMEM_DCACHE_SYNC_DONE)); */
- movi a5, EXTMEM_DCACHE_SYNC_DONE_M
- _wait_writeback_done:
- l32i a4, a3, 0 /* a4 = *(EXTMEM_DCACHE_SYNC_CTRL_REG) */
- memw
- bnone a4, a5, _wait_writeback_done
- /* REG_CLR_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_ENA); */
- l32i a4, a2, 0 /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
- movi a5, ~(EXTMEM_DCACHE_FREEZE_ENA_M)
- and a4, a4, a5
- s32i a4, a2, 0 /* *(EXTMEM_DCACHE_FREEZE_REG) = a4 */
- /* while (REG_GET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_DONE)); */
- movi a5, EXTMEM_DCACHE_FREEZE_DONE_M
- _wait_unfreeze_done:
- l32i a4, a2, 0 /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
- memw
- bany a4, a5, _wait_unfreeze_done
- retw
- .size cache_writeback_items_freeze, . - cache_writeback_items_freeze
|