linux/arch/hexagon/mm/cache.c
<<
>>
Prefs
   1/*
   2 * Cache management functions for Hexagon
   3 *
   4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 and
   8 * only version 2 as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18 * 02110-1301, USA.
  19 */
  20
  21#include <linux/mm.h>
  22#include <asm/cacheflush.h>
  23#include <asm/hexagon_vm.h>
  24
  25#define spanlines(start, end) \
  26        (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
  27
  28void flush_dcache_range(unsigned long start, unsigned long end)
  29{
  30        unsigned long lines = spanlines(start, end-1);
  31        unsigned long i, flags;
  32
  33        start &= ~(LINESIZE - 1);
  34
  35        local_irq_save(flags);
  36
  37        for (i = 0; i < lines; i++) {
  38                __asm__ __volatile__ (
  39                "       dccleaninva(%0);        "
  40                :
  41                : "r" (start)
  42                );
  43                start += LINESIZE;
  44        }
  45        local_irq_restore(flags);
  46}
  47
  48void flush_icache_range(unsigned long start, unsigned long end)
  49{
  50        unsigned long lines = spanlines(start, end-1);
  51        unsigned long i, flags;
  52
  53        start &= ~(LINESIZE - 1);
  54
  55        local_irq_save(flags);
  56
  57        for (i = 0; i < lines; i++) {
  58                __asm__ __volatile__ (
  59                        "       dccleana(%0); "
  60                        "       icinva(%0);     "
  61                        :
  62                        : "r" (start)
  63                );
  64                start += LINESIZE;
  65        }
  66        __asm__ __volatile__ (
  67                "isync"
  68        );
  69        local_irq_restore(flags);
  70}
  71EXPORT_SYMBOL(flush_icache_range);
  72
  73void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
  74{
  75        unsigned long lines = spanlines(start, end-1);
  76        unsigned long i, flags;
  77
  78        start &= ~(LINESIZE - 1);
  79
  80        local_irq_save(flags);
  81
  82        for (i = 0; i < lines; i++) {
  83                __asm__ __volatile__ (
  84                "       dccleana(%0);   "
  85                :
  86                : "r" (start)
  87                );
  88                start += LINESIZE;
  89        }
  90        local_irq_restore(flags);
  91}
  92
  93void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
  94{
  95        unsigned long lines = spanlines(start, end-1);
  96        unsigned long i, flags;
  97
  98        start &= ~(LINESIZE - 1);
  99
 100        local_irq_save(flags);
 101
 102        for (i = 0; i < lines; i++) {
 103                __asm__ __volatile__ (
 104                "       dcinva(%0);     "
 105                :
 106                : "r" (start)
 107                );
 108                start += LINESIZE;
 109        }
 110        local_irq_restore(flags);
 111}
 112
 113
 114
 115
 116/*
 117 * This is just really brutal and shouldn't be used anyways,
 118 * especially on V2.  Left here just in case.
 119 */
 120void flush_cache_all_hexagon(void)
 121{
 122        unsigned long flags;
 123        local_irq_save(flags);
 124        __vmcache_ickill();
 125        __vmcache_dckill();
 126        __vmcache_l2kill();
 127        local_irq_restore(flags);
 128        mb();
 129}
 130
 131void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
 132                       unsigned long vaddr, void *dst, void *src, int len)
 133{
 134        memcpy(dst, src, len);
 135        if (vma->vm_flags & VM_EXEC) {
 136                flush_icache_range((unsigned long) dst,
 137                (unsigned long) dst + len);
 138        }
 139}
 140