Skip to content
Snippets Groups Projects
Forked from Reform / reform-boundary-uboot
18881 commits behind the upstream repository.
  • Thomas Chou's avatar
    21ff7344
    nios2: convert cache flush to use dm cpu data · 21ff7344
    Thomas Chou authored
    
    Convert cache flush to use dm cpu data.
    
    The original cache flush functions are written in assembly
    and use CONFIG_SYS_{I,D}CACHE_SIZE... macros. It is difficult
    to convert to use cache configuration in dm cpu data which is
    extracted from device tree.
    
    The cacheflush.c of Linux nios2 arch uses cpuinfo structure,
    which is very close to our dm cpu data. So we copy and modify
    it to arch/nios2/lib/cache.c to replace the old cache.S.
    
    Signed-off-by: default avatarThomas Chou <thomas@wytron.com.tw>
    21ff7344
    History
    nios2: convert cache flush to use dm cpu data
    Thomas Chou authored
    
    Convert cache flush to use dm cpu data.
    
    The original cache flush functions are written in assembly
    and use CONFIG_SYS_{I,D}CACHE_SIZE... macros. It is difficult
    to convert to use cache configuration in dm cpu data which is
    extracted from device tree.
    
    The cacheflush.c of Linux nios2 arch uses cpuinfo structure,
    which is very close to our dm cpu data. So we copy and modify
    it to arch/nios2/lib/cache.c to replace the old cache.S.
    
    Signed-off-by: default avatarThomas Chou <thomas@wytron.com.tw>
cache.c 2.91 KiB
/*
 * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
 * Copyright (C) 2009, Wind River Systems Inc
 * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/cache.h>

DECLARE_GLOBAL_DATA_PTR;

static void __flush_dcache(unsigned long start, unsigned long end)
{
	unsigned long addr;

	start &= ~(gd->arch.dcache_line_size - 1);
	end += (gd->arch.dcache_line_size - 1);
	end &= ~(gd->arch.dcache_line_size - 1);

	for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
		__asm__ __volatile__ ("   flushda 0(%0)\n"
					: /* Outputs */
					: /* Inputs  */ "r"(addr)
					/* : No clobber */);
	}
}

static void __flush_dcache_all(unsigned long start, unsigned long end)
{
	unsigned long addr;

	start &= ~(gd->arch.dcache_line_size - 1);
	end += (gd->arch.dcache_line_size - 1);
	end &= ~(gd->arch.dcache_line_size - 1);

	if (end > start + gd->arch.dcache_size)
		end = start + gd->arch.dcache_size;

	for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
		__asm__ __volatile__ ("   flushd 0(%0)\n"
					: /* Outputs */
					: /* Inputs  */ "r"(addr)
					/* : No clobber */);
	}
}

static void __invalidate_dcache(unsigned long start, unsigned long end)
{
	unsigned long addr;

	start &= ~(gd->arch.dcache_line_size - 1);
	end += (gd->arch.dcache_line_size - 1);
	end &= ~(gd->arch.dcache_line_size - 1);

	for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
		__asm__ __volatile__ ("   initda 0(%0)\n"
					: /* Outputs */
					: /* Inputs  */ "r"(addr)
					/* : No clobber */);
	}
}

static void __flush_icache(unsigned long start, unsigned long end)
{
	unsigned long addr;

	start &= ~(gd->arch.icache_line_size - 1);
	end += (gd->arch.icache_line_size - 1);
	end &= ~(gd->arch.icache_line_size - 1);

	if (end > start + gd->arch.icache_size)
		end = start + gd->arch.icache_size;

	for (addr = start; addr < end; addr += gd->arch.icache_line_size) {
		__asm__ __volatile__ ("   flushi %0\n"
					: /* Outputs */
					: /* Inputs  */ "r"(addr)
					/* : No clobber */);
	}
	__asm__ __volatile(" flushp\n");
}

void flush_dcache_all(void)
{
	__flush_dcache_all(0, gd->arch.dcache_size);
	__flush_icache(0, gd->arch.icache_size);
}

void flush_dcache_range(unsigned long start, unsigned long end)
{
	if (gd->arch.has_initda)
		__flush_dcache(start, end);
	else
		__flush_dcache_all(start, end);
}

void flush_cache(unsigned long start, unsigned long size)
{
	if (gd->arch.has_initda)
		__flush_dcache(start, start + size);
	else
		__flush_dcache_all(start, start + size);
	__flush_icache(start, start + size);
}

void invalidate_dcache_range(unsigned long start, unsigned long end)
{
	if (gd->arch.has_initda)
		__invalidate_dcache(start, end);
	else
		__flush_dcache_all(start, end);
}

int dcache_status(void)
{
	return 1;
}

void dcache_enable(void)
{
	flush_dcache_all();
}

void dcache_disable(void)
{
	flush_dcache_all();
}