#include <sys/param.h>
#include <mips/cpuregs.h>
#include <mips/cache.h>
#include <mips/cache_r4k.h>
#include <mips/cache_r10k.h>
__asm(".set mips3");
#define round_line(x) (((x) + 64 - 1) & ~(64 - 1))
#define trunc_line(x) ((x) & ~(64 - 1))
void
r10k_icache_sync_all(void)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
vaddr_t eva = va + mci->mci_picache_way_size;
mips_dcache_wbinv_all();
__asm volatile("sync");
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
va++;
cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
va += 63;
}
}
void
r10k_icache_sync_range(register_t va, vsize_t size)
{
vaddr_t eva = round_line(va + size);
va = trunc_line(va);
mips_dcache_wb_range(va, (eva - va));
__asm volatile("sync");
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
va += 64;
}
}
void
r10k_icache_sync_range_index(vaddr_t va, vsize_t size)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t eva, orig_va;
orig_va = va;
eva = round_line(va + size);
va = trunc_line(va);
mips_dcache_wbinv_range_index(va, (eva - va));
__asm volatile("sync");
va = MIPS_PHYS_TO_KSEG0(orig_va & mci->mci_picache_way_mask);
eva = round_line(va + size);
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
va++;
cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
va += 63;
}
}
#undef round_line
#undef trunc_line
#define round_line(x) (((x) + 32 - 1) & ~(32 - 1))
#define trunc_line(x) ((x) & ~(32 - 1))
void
r10k_pdcache_wbinv_all(void)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
vaddr_t eva = va + mci->mci_pdcache_way_size;
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
va++;
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
va += 31;
}
}
void
r10k_pdcache_wbinv_range(register_t va, vsize_t size)
{
vaddr_t eva = round_line(va + size);
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
va += 32;
}
}
void
r10k_pdcache_wbinv_range_index(vaddr_t va, vsize_t size)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t eva;
va = MIPS_PHYS_TO_KSEG0(va & mci->mci_pdcache_way_mask);
eva = round_line(va + size);
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
va++;
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
va += 31;
}
}
void
r10k_pdcache_inv_range(register_t va, vsize_t size)
{
vaddr_t eva = round_line(va + size);
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
va += 32;
}
}
void
r10k_pdcache_wb_range(register_t va, vsize_t size)
{
vaddr_t eva = round_line(va + size);
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
va += 32;
}
}
#undef round_line
#undef trunc_line
#define round_line(x) (((x) + mci->mci_sdcache_line_size - 1) & ~(mci->mci_sdcache_line_size - 1))
#define trunc_line(x) ((x) & ~(mci->mci_sdcache_line_size - 1))
void
r10k_sdcache_wbinv_all(void)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
vaddr_t eva = va + mci->mci_sdcache_way_size;
vsize_t line_size = mci->mci_sdcache_line_size;
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va++;
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += line_size - 1;
}
}
void
r10k_sdcache_wbinv_range(register_t va, vsize_t size)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t eva = round_line(va + size);
vsize_t line_size = mci->mci_sdcache_line_size;
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
va += line_size;
}
}
void
r10k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t eva;
vsize_t line_size = mci->mci_sdcache_line_size;
va = MIPS_PHYS_TO_KSEG0(va & mci->mci_sdcache_way_mask);
eva = round_line(va + size);
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va++;
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
va += line_size - 1;
}
}
void
r10k_sdcache_inv_range(register_t va, vsize_t size)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t eva = round_line(va + size);
vsize_t line_size = mci->mci_sdcache_line_size;
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
va += line_size;
}
}
void
r10k_sdcache_wb_range(register_t va, vsize_t size)
{
const struct mips_cache_info * const mci = &mips_cache_info;
vaddr_t eva = round_line(va + size);
vsize_t line_size = mci->mci_sdcache_line_size;
va = trunc_line(va);
while (va < eva) {
cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
va += line_size;
}
}
#undef round_line
#undef trunc_line