Commit bf3cc1dd authored by Miles Bader's avatar Miles Bader Committed by Linus Torvalds

[PATCH] Cleanup v850 cache-flushing code a bit

(1) Add support for the V850E/ME2 processor

(2) Clean up the cache-flushing function naming a bit

(3) Similar to previous patches, rename everything from `nb85e' to `v850e'.
    This patch renames some files, and so contains a number of whole-file
    add/removes.
parent 701096cf
/* /*
* arch/v850/kernel/nb85e_cache.c -- Cache control for NB85E_CACHE212 and * arch/v850/kernel/v850e_cache.c -- Cache control for V850E cache memories
* NB85E_CACHE213 cache memories
* *
* Copyright (C) 2003 NEC Electronics Corporation * Copyright (C) 2003 NEC Electronics Corporation
* Copyright (C) 2003 Miles Bader <miles@gnu.org> * Copyright (C) 2003 Miles Bader <miles@gnu.org>
...@@ -12,19 +11,31 @@ ...@@ -12,19 +11,31 @@
* Written by Miles Bader <miles@gnu.org> * Written by Miles Bader <miles@gnu.org>
*/ */
/* This file implements cache control for the rather simple cache used on
some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
CPU. V850E2 processors have their own (better) cache
implementation. */
#include <asm/entry.h> #include <asm/entry.h>
#include <asm/nb85e_cache.h> #include <asm/v850e_cache.h>
#define WAIT_UNTIL_CLEAR(value) while (value) {} #define WAIT_UNTIL_CLEAR(value) while (value) {}
/* Set caching params via the BHC and DCC registers. */ /* Set caching params via the BHC and DCC registers. */
void nb85e_cache_enable (u16 bhc, u16 dcc) void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc)
{ {
unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR; unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR;
register u16 bhc_val asm ("r6") = bhc; register u16 bhc_val asm ("r6") = bhc;
/* Read the instruction cache control register (ICC) and confirm
that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */
WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
V850E_CACHE_ICC = icc;
#ifdef V850E_CACHE_DCC
/* Configure data-cache. */ /* Configure data-cache. */
NB85E_CACHE_DCC = dcc; V850E_CACHE_DCC = dcc;
#endif /* V850E_CACHE_DCC */
/* Configure caching for various memory regions by writing the BHC /* Configure caching for various memory regions by writing the BHC
register. The documentation says that an instruction _cannot_ register. The documentation says that an instruction _cannot_
...@@ -32,9 +43,12 @@ void nb85e_cache_enable (u16 bhc, u16 dcc) ...@@ -32,9 +43,12 @@ void nb85e_cache_enable (u16 bhc, u16 dcc)
instruction itself exists; to work around this, we store instruction itself exists; to work around this, we store
appropriate instructions into the on-chip RAM area (which is never appropriate instructions into the on-chip RAM area (which is never
cached), and briefly jump there to do the work. */ cached), and briefly jump there to do the work. */
r0_ram[0] = 0xf0720760; /* st.h r0, 0xfffff072[r0] */ #ifdef V850E_CACHE_WRITE_IBS
r0_ram[1] = 0xf06a3760; /* st.h r6, 0xfffff06a[r0] */ *r0_ram++ = 0xf0720760; /* st.h r0, 0xfffff072[r0] */
r0_ram[2] = 0x5640006b; /* jmp [r11] */ #endif
*r0_ram++ = 0xf06a3760; /* st.h r6, 0xfffff06a[r0] */
*r0_ram = 0x5640006b; /* jmp [r11] */
asm ("mov hilo(1f), r11; jmp [%1]; 1:;" asm ("mov hilo(1f), r11; jmp [%1]; 1:;"
:: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11"); :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11");
} }
...@@ -43,11 +57,11 @@ static void clear_icache (void) ...@@ -43,11 +57,11 @@ static void clear_icache (void)
{ {
/* 1. Read the instruction cache control register (ICC) and confirm /* 1. Read the instruction cache control register (ICC) and confirm
that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */ that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */
WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3); WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
/* 2. Read the ICC register and confirm that bit 12 (LOCK0) is /* 2. Read the ICC register and confirm that bit 12 (LOCK0) is
cleared. Bit 13 of the ICC register is always cleared. */ cleared. Bit 13 of the ICC register is always cleared. */
WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x1000); WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x1000);
/* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows, /* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows,
when clearing way 0 and way 1 at the same time: when clearing way 0 and way 1 at the same time:
...@@ -55,13 +69,17 @@ static void clear_icache (void) ...@@ -55,13 +69,17 @@ static void clear_icache (void)
(b) Read the TCLR0 and TCLR1 bits to confirm that these bits (b) Read the TCLR0 and TCLR1 bits to confirm that these bits
are cleared. are cleared.
(c) Perform (a) and (b) above again. */ (c) Perform (a) and (b) above again. */
NB85E_CACHE_ICC |= 0x3; V850E_CACHE_ICC |= 0x3;
WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3); WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
#ifdef V850E_CACHE_REPEAT_ICC_WRITE
/* Do it again. */ /* Do it again. */
NB85E_CACHE_ICC |= 0x3; V850E_CACHE_ICC |= 0x3;
WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3); WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
#endif
} }
#ifdef V850E_CACHE_DCC
/* Flush or clear (or both) the data cache, depending on the value of FLAGS; /* Flush or clear (or both) the data cache, depending on the value of FLAGS;
the procedure is the same for both, just the control bits used differ (and the procedure is the same for both, just the control bits used differ (and
both may be performed simultaneously). */ both may be performed simultaneously). */
...@@ -69,47 +87,54 @@ static void dcache_op (unsigned short flags) ...@@ -69,47 +87,54 @@ static void dcache_op (unsigned short flags)
{ {
/* 1. Read the data cache control register (DCC) and confirm that bits /* 1. Read the data cache control register (DCC) and confirm that bits
0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared. */ 0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared. */
WAIT_UNTIL_CLEAR (NB85E_CACHE_DCC & 0x33); WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & 0x33);
/* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both /* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both
depending on the way for which tags are to be cleared. */ depending on the way for which tags are to be cleared. */
NB85E_CACHE_DCC &= ~0xC000; V850E_CACHE_DCC &= ~0xC000;
/* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on /* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on
the way for which tags are to be cleared. the way for which tags are to be cleared.
... ...
Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending
on the way to be data flushed. */ on the way to be data flushed. */
NB85E_CACHE_DCC |= flags; V850E_CACHE_DCC |= flags;
/* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending /* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending
on the way for which tags were cleared [flushed] and confirm on the way for which tags were cleared [flushed] and confirm
that that bit is cleared. */ that that bit is cleared. */
WAIT_UNTIL_CLEAR (NB85E_CACHE_DCC & flags); WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & flags);
} }
#endif /* V850E_CACHE_DCC */
/* Flushes the contents of the dcache to memory. */ /* Flushes the contents of the dcache to memory. */
static inline void flush_dcache (void) static inline void flush_dcache (void)
{ {
#ifdef V850E_CACHE_DCC
/* We only need to do something if in write-back mode. */ /* We only need to do something if in write-back mode. */
if (NB85E_CACHE_DCC & 0x0400) if (V850E_CACHE_DCC & 0x0400)
dcache_op (0x30); dcache_op (0x30);
#endif /* V850E_CACHE_DCC */
} }
/* Flushes the contents of the dcache to memory, and then clears it. */ /* Flushes the contents of the dcache to memory, and then clears it. */
static inline void clear_dcache (void) static inline void clear_dcache (void)
{ {
#ifdef V850E_CACHE_DCC
/* We only need to do something if the dcache is enabled. */ /* We only need to do something if the dcache is enabled. */
if (NB85E_CACHE_DCC & 0x0C00) if (V850E_CACHE_DCC & 0x0C00)
dcache_op (0x33); dcache_op (0x33);
#endif /* V850E_CACHE_DCC */
} }
/* Clears the dcache without flushing to memory first. */ /* Clears the dcache without flushing to memory first. */
static inline void clear_dcache_no_flush (void) static inline void clear_dcache_no_flush (void)
{ {
#ifdef V850E_CACHE_DCC
/* We only need to do something if the dcache is enabled. */ /* We only need to do something if the dcache is enabled. */
if (NB85E_CACHE_DCC & 0x0C00) if (V850E_CACHE_DCC & 0x0C00)
dcache_op (0x3); dcache_op (0x3);
#endif /* V850E_CACHE_DCC */
} }
static inline void cache_exec_after_store (void) static inline void cache_exec_after_store (void)
...@@ -121,58 +146,28 @@ static inline void cache_exec_after_store (void) ...@@ -121,58 +146,28 @@ static inline void cache_exec_after_store (void)
/* Exported functions. */ /* Exported functions. */
void inline nb85e_cache_flush_all (void) void flush_icache (void)
{
clear_icache ();
clear_dcache ();
}
void nb85e_cache_flush_mm (struct mm_struct *mm)
{
/* nothing */
}
void nb85e_cache_flush_range (struct mm_struct *mm,
unsigned long start, unsigned long end)
{
/* nothing */
}
void nb85e_cache_flush_page (struct vm_area_struct *vma,
unsigned long page_addr)
{
/* nothing */
}
void nb85e_cache_flush_dcache_page (struct page *page)
{
/* nothing */
}
void nb85e_cache_flush_icache (void)
{ {
cache_exec_after_store (); cache_exec_after_store ();
} }
void nb85e_cache_flush_icache_range (unsigned long start, unsigned long end) void flush_icache_range (unsigned long start, unsigned long end)
{ {
cache_exec_after_store (); cache_exec_after_store ();
} }
void nb85e_cache_flush_icache_page (struct vm_area_struct *vma, void flush_icache_page (struct vm_area_struct *vma, struct page *page)
struct page *page)
{ {
cache_exec_after_store (); cache_exec_after_store ();
} }
void nb85e_cache_flush_icache_user_range (struct vm_area_struct *vma, void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
struct page *page,
unsigned long adr, int len) unsigned long adr, int len)
{ {
cache_exec_after_store (); cache_exec_after_store ();
} }
void nb85e_cache_flush_sigtramp (unsigned long addr) void flush_cache_sigtramp (unsigned long addr)
{ {
cache_exec_after_store (); cache_exec_after_store ();
} }
/* /*
* include/asm-v850/cacheflush.h * include/asm-v850/cacheflush.h
* *
* Copyright (C) 2001,02 NEC Corporation * Copyright (C) 2001,02,03 NEC Electronics Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org> * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
* *
* This file is subject to the terms and conditions of the GNU General * This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this * Public License. See the file COPYING in the main directory of this
...@@ -21,21 +21,40 @@ ...@@ -21,21 +21,40 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#ifndef flush_cache_all /* The following are all used by the kernel in ways that only affect
/* If there's no flush_cache_all macro defined by <asm/machdep.h>, then systems with MMUs, so we don't need them. */
this processor has no cache, so just define these as nops. */
#define flush_cache_all() ((void)0) #define flush_cache_all() ((void)0)
#define flush_cache_mm(mm) ((void)0) #define flush_cache_mm(mm) ((void)0)
#define flush_cache_range(vma, start, end) ((void)0) #define flush_cache_range(vma, start, end) ((void)0)
#define flush_cache_page(vma, vmaddr) ((void)0) #define flush_cache_page(vma, vmaddr) ((void)0)
#define flush_dcache_page(page) ((void)0) #define flush_dcache_page(page) ((void)0)
#ifdef CONFIG_NO_CACHE
/* Some systems have no cache at all, in which case we don't need these
either. */
#define flush_icache() ((void)0) #define flush_icache() ((void)0)
#define flush_icache_range(start, end) ((void)0) #define flush_icache_range(start, end) ((void)0)
#define flush_icache_page(vma,pg) ((void)0) #define flush_icache_page(vma,pg) ((void)0)
#define flush_icache_user_range(vma,pg,adr,len) ((void)0) #define flush_icache_user_range(vma,pg,adr,len) ((void)0)
#define flush_cache_sigtramp(vaddr) ((void)0) #define flush_cache_sigtramp(vaddr) ((void)0)
#endif /* !flush_cache_all */ #else /* !CONFIG_NO_CACHE */
struct page;
struct mm_struct;
struct vm_area_struct;
/* Otherwise, somebody had better define them. */
extern void flush_icache (void);
extern void flush_icache_range (unsigned long start, unsigned long end);
extern void flush_icache_page (struct vm_area_struct *vma, struct page *page);
extern void flush_icache_user_range (struct vm_area_struct *vma,
struct page *page,
unsigned long adr, int len);
extern void flush_cache_sigtramp (unsigned long addr);
#endif /* CONFIG_NO_CACHE */
#endif /* __V850_CACHEFLUSH_H__ */ #endif /* __V850_CACHEFLUSH_H__ */
/*
* include/asm-v850/nb85e_cache_cache.h -- Cache control for NB85E_CACHE212 and
* NB85E_CACHE213 cache memories
*
* Copyright (C) 2001,03 NEC Electronics Corporation
* Copyright (C) 2001,03 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
#ifndef __V850_NB85E_CACHE_H__
#define __V850_NB85E_CACHE_H__
#include <asm/types.h>
/* Cache control registers. */
#define NB85E_CACHE_BHC_ADDR 0xFFFFF06A
#define NB85E_CACHE_BHC (*(volatile u16 *)NB85E_CACHE_BHC_ADDR)
#define NB85E_CACHE_ICC_ADDR 0xFFFFF070
#define NB85E_CACHE_ICC (*(volatile u16 *)NB85E_CACHE_ICC_ADDR)
#define NB85E_CACHE_ISI_ADDR 0xFFFFF072
#define NB85E_CACHE_ISI (*(volatile u16 *)NB85E_CACHE_ISI_ADDR)
#define NB85E_CACHE_DCC_ADDR 0xFFFFF078
#define NB85E_CACHE_DCC (*(volatile u16 *)NB85E_CACHE_DCC_ADDR)
/* Size of a cache line in bytes. */
#define NB85E_CACHE_LINE_SIZE 16
/* For <asm/cache.h> */
#define L1_CACHE_BYTES NB85E_CACHE_LINE_SIZE
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
/* Set caching params via the BHC and DCC registers. */
void nb85e_cache_enable (u16 bhc, u16 dcc);
struct page;
struct mm_struct;
struct vm_area_struct;
extern void nb85e_cache_flush_all (void);
extern void nb85e_cache_flush_mm (struct mm_struct *mm);
extern void nb85e_cache_flush_range (struct mm_struct *mm,
unsigned long start,
unsigned long end);
extern void nb85e_cache_flush_page (struct vm_area_struct *vma,
unsigned long page_addr);
extern void nb85e_cache_flush_dcache_page (struct page *page);
extern void nb85e_cache_flush_icache (void);
extern void nb85e_cache_flush_icache_range (unsigned long start,
unsigned long end);
extern void nb85e_cache_flush_icache_page (struct vm_area_struct *vma,
struct page *page);
extern void nb85e_cache_flush_icache_user_range (struct vm_area_struct *vma,
struct page *page,
unsigned long adr, int len);
extern void nb85e_cache_flush_sigtramp (unsigned long addr);
#define flush_cache_all nb85e_cache_flush_all
#define flush_cache_mm nb85e_cache_flush_mm
#define flush_cache_range nb85e_cache_flush_range
#define flush_cache_page nb85e_cache_flush_page
#define flush_dcache_page nb85e_cache_flush_dcache_page
#define flush_icache nb85e_cache_flush_icache
#define flush_icache_range nb85e_cache_flush_icache_range
#define flush_icache_page nb85e_cache_flush_icache_page
#define flush_icache_user_range nb85e_cache_flush_icache_user_range
#define flush_cache_sigtramp nb85e_cache_flush_sigtramp
#endif /* __KERNEL__ && !__ASSEMBLY__ */
#endif /* __V850_NB85E_CACHE_H__ */
/*
* include/asm-v850/v850e_cache.h -- Cache control for V850E cache memories
*
* Copyright (C) 2001,03 NEC Electronics Corporation
* Copyright (C) 2001,03 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*/
/* This file implements cache control for the rather simple cache used on
some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
CPU. V850E2 processors have their own (better) cache
implementation. */
#ifndef __V850_V850E_CACHE_H__
#define __V850_V850E_CACHE_H__
#include <asm/types.h>
/* Cache control registers. */
#define V850E_CACHE_BHC_ADDR 0xFFFFF06A
#define V850E_CACHE_BHC (*(volatile u16 *)V850E_CACHE_BHC_ADDR)
#define V850E_CACHE_ICC_ADDR 0xFFFFF070
#define V850E_CACHE_ICC (*(volatile u16 *)V850E_CACHE_ICC_ADDR)
#define V850E_CACHE_ISI_ADDR 0xFFFFF072
#define V850E_CACHE_ISI (*(volatile u16 *)V850E_CACHE_ISI_ADDR)
#define V850E_CACHE_DCC_ADDR 0xFFFFF078
#define V850E_CACHE_DCC (*(volatile u16 *)V850E_CACHE_DCC_ADDR)
/* Size of a cache line in bytes. */
#define V850E_CACHE_LINE_SIZE 16
/* For <asm/cache.h> */
#define L1_CACHE_BYTES V850E_CACHE_LINE_SIZE
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
/* Set caching params via the BHC, ICC, and DCC registers. */
void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc);
#endif /* __KERNEL__ && !__ASSEMBLY__ */
#endif /* __V850_V850E_CACHE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment