linux/arch/sh/mm/flush-sh4.c
<<
>>
Prefs
   1#include <linux/mm.h>
   2#include <asm/mmu_context.h>
   3#include <asm/cache_insns.h>
   4#include <asm/cacheflush.h>
   5#include <asm/traps.h>
   6
   7/*
   8 * Write back the dirty D-caches, but not invalidate them.
   9 *
  10 * START: Virtual Address (U0, P1, or P3)
  11 * SIZE: Size of the region.
  12 */
  13static void sh4__flush_wback_region(void *start, int size)
  14{
  15        reg_size_t aligned_start, v, cnt, end;
  16
  17        aligned_start = register_align(start);
  18        v = aligned_start & ~(L1_CACHE_BYTES-1);
  19        end = (aligned_start + size + L1_CACHE_BYTES-1)
  20                & ~(L1_CACHE_BYTES-1);
  21        cnt = (end - v) / L1_CACHE_BYTES;
  22
  23        while (cnt >= 8) {
  24                __ocbwb(v); v += L1_CACHE_BYTES;
  25                __ocbwb(v); v += L1_CACHE_BYTES;
  26                __ocbwb(v); v += L1_CACHE_BYTES;
  27                __ocbwb(v); v += L1_CACHE_BYTES;
  28                __ocbwb(v); v += L1_CACHE_BYTES;
  29                __ocbwb(v); v += L1_CACHE_BYTES;
  30                __ocbwb(v); v += L1_CACHE_BYTES;
  31                __ocbwb(v); v += L1_CACHE_BYTES;
  32                cnt -= 8;
  33        }
  34
  35        while (cnt) {
  36                __ocbwb(v); v += L1_CACHE_BYTES;
  37                cnt--;
  38        }
  39}
  40
  41/*
  42 * Write back the dirty D-caches and invalidate them.
  43 *
  44 * START: Virtual Address (U0, P1, or P3)
  45 * SIZE: Size of the region.
  46 */
  47static void sh4__flush_purge_region(void *start, int size)
  48{
  49        reg_size_t aligned_start, v, cnt, end;
  50
  51        aligned_start = register_align(start);
  52        v = aligned_start & ~(L1_CACHE_BYTES-1);
  53        end = (aligned_start + size + L1_CACHE_BYTES-1)
  54                & ~(L1_CACHE_BYTES-1);
  55        cnt = (end - v) / L1_CACHE_BYTES;
  56
  57        while (cnt >= 8) {
  58                __ocbp(v); v += L1_CACHE_BYTES;
  59                __ocbp(v); v += L1_CACHE_BYTES;
  60                __ocbp(v); v += L1_CACHE_BYTES;
  61                __ocbp(v); v += L1_CACHE_BYTES;
  62                __ocbp(v); v += L1_CACHE_BYTES;
  63                __ocbp(v); v += L1_CACHE_BYTES;
  64                __ocbp(v); v += L1_CACHE_BYTES;
  65                __ocbp(v); v += L1_CACHE_BYTES;
  66                cnt -= 8;
  67        }
  68        while (cnt) {
  69                __ocbp(v); v += L1_CACHE_BYTES;
  70                cnt--;
  71        }
  72}
  73
  74/*
  75 * No write back please
  76 */
  77static void sh4__flush_invalidate_region(void *start, int size)
  78{
  79        reg_size_t aligned_start, v, cnt, end;
  80
  81        aligned_start = register_align(start);
  82        v = aligned_start & ~(L1_CACHE_BYTES-1);
  83        end = (aligned_start + size + L1_CACHE_BYTES-1)
  84                & ~(L1_CACHE_BYTES-1);
  85        cnt = (end - v) / L1_CACHE_BYTES;
  86
  87        while (cnt >= 8) {
  88                __ocbi(v); v += L1_CACHE_BYTES;
  89                __ocbi(v); v += L1_CACHE_BYTES;
  90                __ocbi(v); v += L1_CACHE_BYTES;
  91                __ocbi(v); v += L1_CACHE_BYTES;
  92                __ocbi(v); v += L1_CACHE_BYTES;
  93                __ocbi(v); v += L1_CACHE_BYTES;
  94                __ocbi(v); v += L1_CACHE_BYTES;
  95                __ocbi(v); v += L1_CACHE_BYTES;
  96                cnt -= 8;
  97        }
  98
  99        while (cnt) {
 100                __ocbi(v); v += L1_CACHE_BYTES;
 101                cnt--;
 102        }
 103}
 104
 105void __init sh4__flush_region_init(void)
 106{
 107        __flush_wback_region            = sh4__flush_wback_region;
 108        __flush_invalidate_region       = sh4__flush_invalidate_region;
 109        __flush_purge_region            = sh4__flush_purge_region;
 110}
 111