blob: 19bea9211c729805f9217e7e01aed9f98d54014a [file] [log] [blame]
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2017 Intel Corporation. All rights reserved.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#ifdef __SOF_LIB_CACHE_H__
#ifndef __ARCH_LIB_CACHE_H__
#define __ARCH_LIB_CACHE_H__
#include <xtensa/config/core-isa.h>
#define DCACHE_LINE_SIZE XCHAL_DCACHE_LINESIZE
#if !defined(__ASSEMBLER__) && !defined(LINKER)
#include <xtensa/hal.h>
#include <sof/compiler_attributes.h>
#include <stddef.h>
#include <stdint.h>
#ifdef CONFIG_COMPILER_WORKAROUND_CACHE_ATTR
#include <sof/drivers/cache_attr.h>
#endif
#define SRAM_UNCACHED_ALIAS 0x20000000
#ifdef CONFIG_IMX
#ifdef CONFIG_COMPILER_WORKAROUND_CACHE_ATTR
/*
* We want to avoid buggy compiler optimization (function inlining).
* So we replace the call to glb_addr_attr() from glb_is_cached()
* with a function pointer that is initialized in
* src/arch/xtensa/driver/cache_attr.c
*/
#define is_cached(address) glb_is_cached(address)
#else /* CONFIG_COMPILER_WORKAROUND_CACHE_ATTR */
/*
* The _memmap_cacheattr_reset linker script variable has
* dedicate cache attribute for every 512M in 4GB space
* 1: write through
* 2: cache bypass
* 4: write back
* F: invalid access
*/
extern uint32_t _memmap_cacheattr_reset;
/*
* Since each hex digit keeps the attributes for a 512MB region,
* we have the following address ranges:
* Address range - hex digit
* 0 - 1FFFFFFF - 0
* 20000000 - 3FFFFFFF - 1
* 40000000 - 5FFFFFFF - 2
* 60000000 - 7FFFFFFF - 3
* 80000000 - 9FFFFFFF - 4
* A0000000 - BFFFFFFF - 5
* C0000000 - DFFFFFFF - 6
* E0000000 - FFFFFFFF - 7
*/
/*
* Based on the above information, get the address region id (0-7)
*/
#define _addr_range(address) (((uintptr_t)(address) >> 29) & 0x7)
/*
* Get the position of the cache attribute for a certain memory region.
* There are 4 bits per hex digit.
*/
#define _addr_shift(address) ((_addr_range(address)) << 2)
/*
* For the given address, get the corresponding hex digit
* from the linker script variable that contains the cache attributes
*/
#define _addr_attr(address) ((((uint32_t)(&_memmap_cacheattr_reset)) >> \
(_addr_shift(address))) & 0xF)
/*
* Check if the address is cacheable or not, by verifying the _addr_attr,
* which for cacheable addresses might be 1 or 4
*/
#define is_cached(address) ((_addr_attr(address) == 1) || \
(_addr_attr(address) == 4))
#endif /* CONFIG_COMPILER_WORKAROUND_CACHE_ATTR */
#else /* CONFIG_IMX */
#define is_cached(address) (!!((uintptr_t)(address) & SRAM_UNCACHED_ALIAS))
#endif
static inline void dcache_writeback_region(void __sparse_cache *addr, size_t size)
{
#if XCHAL_DCACHE_SIZE > 0
if (is_cached(addr))
xthal_dcache_region_writeback((__sparse_force void *)addr, size);
#endif
}
static inline void dcache_writeback_all(void)
{
#if XCHAL_DCACHE_SIZE > 0
xthal_dcache_all_writeback();
#endif
}
static inline void dcache_invalidate_region(void __sparse_cache *addr, size_t size)
{
#if XCHAL_DCACHE_SIZE > 0
if (is_cached(addr))
xthal_dcache_region_invalidate((__sparse_force void *)addr, size);
#endif
}
static inline void dcache_invalidate_all(void)
{
#if XCHAL_DCACHE_SIZE > 0
xthal_dcache_all_invalidate();
#endif
}
static inline void icache_invalidate_region(void *addr, size_t size)
{
#if XCHAL_ICACHE_SIZE > 0
xthal_icache_region_invalidate(addr, size);
#endif
}
static inline void icache_invalidate_all(void)
{
#if XCHAL_ICACHE_SIZE > 0
xthal_icache_all_invalidate();
#endif
}
static inline void dcache_writeback_invalidate_region(void __sparse_cache *addr, size_t size)
{
#if XCHAL_DCACHE_SIZE > 0
if (is_cached(addr))
xthal_dcache_region_writeback_inv((__sparse_force void *)addr, size);
#endif
}
static inline void dcache_writeback_invalidate_all(void)
{
#if XCHAL_DCACHE_SIZE > 0
xthal_dcache_all_writeback_inv();
#endif
}
#endif /* !defined(__ASSEMBLER__) && !defined(LINKER) */
#endif /* __ARCH_LIB_CACHE_H__ */
#else
#error "This file shouldn't be included from outside of sof/lib/cache.h"
#endif /* __SOF_LIB_CACHE_H__ */