1/* 2 * arch/v850/kernel/v850e2_cache.c -- Cache control for V850E2 cache 3 * memories 4 * 5 * Copyright (C) 2003 NEC Electronics Corporation 6 * Copyright (C) 2003 Miles Bader <miles@gnu.org> 7 * 8 * This file is subject to the terms and conditions of the GNU General 9 * Public License. See the file COPYING in the main directory of this 10 * archive for more details. 11 * 12 * Written by Miles Bader <miles@gnu.org> 13 */ 14 15#include <linux/mm.h> 16 17#include <asm/v850e2_cache.h> 18 19/* Cache operations we can do. The encoding corresponds directly to the 20 value we need to write into the COPR register. */ 21enum cache_op { 22 OP_SYNC_IF_DIRTY = V850E2_CACHE_COPR_CFC(0), /* 000 */ 23 OP_SYNC_IF_VALID = V850E2_CACHE_COPR_CFC(1), /* 001 */ 24 OP_SYNC_IF_VALID_AND_CLEAR = V850E2_CACHE_COPR_CFC(3), /* 011 */ 25 OP_WAY_CLEAR = V850E2_CACHE_COPR_CFC(4), /* 100 */ 26 OP_FILL = V850E2_CACHE_COPR_CFC(5), /* 101 */ 27 OP_CLEAR = V850E2_CACHE_COPR_CFC(6), /* 110 */ 28 OP_CREATE_DIRTY = V850E2_CACHE_COPR_CFC(7) /* 111 */ 29}; 30 31/* Which cache to use. This encoding also corresponds directly to the 32 value we need to write into the COPR register. */ 33enum cache { 34 ICACHE = 0, 35 DCACHE = V850E2_CACHE_COPR_LBSL 36}; 37 38/* Returns ADDR rounded down to the beginning of its cache-line. */ 39#define CACHE_LINE_ADDR(addr) \ 40 ((addr) & ~(V850E2_CACHE_LINE_SIZE - 1)) 41/* Returns END_ADDR rounded up to the `limit' of its cache-line. */ 42#define CACHE_LINE_END_ADDR(end_addr) \ 43 CACHE_LINE_ADDR(end_addr + (V850E2_CACHE_LINE_SIZE - 1)) 44 45 46/* Low-level cache ops. */ 47 48/* Apply cache-op OP to all entries in CACHE. */ 49static inline void cache_op_all (enum cache_op op, enum cache cache) 50{ 51 int cmd = op | cache | V850E2_CACHE_COPR_WSLE | V850E2_CACHE_COPR_STRT; 52 53 if (op != OP_WAY_CLEAR) { 54 /* The WAY_CLEAR operation does the whole way, but other 55 ops take begin-index and count params; we just indicate 56 the entire cache. */ 57 V850E2_CACHE_CADL = 0; 58 V850E2_CACHE_CADH = 0; 59 V850E2_CACHE_CCNT = V850E2_CACHE_WAY_SIZE - 1; 60 } 61 62 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(0); /* way 0 */ 63 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(1); /* way 1 */ 64 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(2); /* way 2 */ 65 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(3); /* way 3 */ 66} 67 68/* Apply cache-op OP to all entries in CACHE covering addresses ADDR 69 through ADDR+LEN. */ 70static inline void cache_op_range (enum cache_op op, u32 addr, u32 len, 71 enum cache cache) 72{ 73 u32 start = CACHE_LINE_ADDR (addr); 74 u32 end = CACHE_LINE_END_ADDR (addr + len); 75 u32 num_lines = (end - start) >> V850E2_CACHE_LINE_SIZE_BITS; 76 77 V850E2_CACHE_CADL = start & 0xFFFF; 78 V850E2_CACHE_CADH = start >> 16; 79 V850E2_CACHE_CCNT = num_lines - 1; 80 81 V850E2_CACHE_COPR = op | cache | V850E2_CACHE_COPR_STRT; 82} 83 84 85/* High-level ops. */ 86 87static void cache_exec_after_store_all (void) 88{ 89 cache_op_all (OP_SYNC_IF_DIRTY, DCACHE); 90 cache_op_all (OP_WAY_CLEAR, ICACHE); 91} 92 93static void cache_exec_after_store_range (u32 start, u32 len) 94{ 95 cache_op_range (OP_SYNC_IF_DIRTY, start, len, DCACHE); 96 cache_op_range (OP_CLEAR, start, len, ICACHE); 97} 98 99 100/* Exported functions. */ 101 102void flush_icache (void) 103{ 104 cache_exec_after_store_all (); 105} 106 107void flush_icache_range (unsigned long start, unsigned long end) 108{ 109 cache_exec_after_store_range (start, end - start); 110} 111 112void flush_icache_page (struct vm_area_struct *vma, struct page *page) 113{ 114 cache_exec_after_store_range (page_to_virt (page), PAGE_SIZE); 115} 116 117void flush_icache_user_range (struct vm_area_struct *vma, struct page *page, 118 unsigned long addr, int len) 119{ 120 cache_exec_after_store_range (addr, len); 121} 122 123void flush_cache_sigtramp (unsigned long addr) 124{ 125 /* For the exact size, see signal.c, but 16 bytes should be enough. */ 126 cache_exec_after_store_range (addr, 16); 127} 128