linux/arch/blackfin/mm/maccess.c
<<
>>
Prefs
   1/*
   2 * safe read and write memory routines callable while atomic
   3 *
   4 * Copyright 2005-2008 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <linux/uaccess.h>
  10#include <asm/dma.h>
  11
  12static int validate_memory_access_address(unsigned long addr, int size)
  13{
  14        if (size < 0 || addr == 0)
  15                return -EFAULT;
  16        return bfin_mem_access_type(addr, size);
  17}
  18
  19long probe_kernel_read(void *dst, const void *src, size_t size)
  20{
  21        unsigned long lsrc = (unsigned long)src;
  22        int mem_type;
  23
  24        mem_type = validate_memory_access_address(lsrc, size);
  25        if (mem_type < 0)
  26                return mem_type;
  27
  28        if (lsrc >= SYSMMR_BASE) {
  29                if (size == 2 && lsrc % 2 == 0) {
  30                        u16 mmr = bfin_read16(src);
  31                        memcpy(dst, &mmr, sizeof(mmr));
  32                        return 0;
  33                } else if (size == 4 && lsrc % 4 == 0) {
  34                        u32 mmr = bfin_read32(src);
  35                        memcpy(dst, &mmr, sizeof(mmr));
  36                        return 0;
  37                }
  38        } else {
  39                switch (mem_type) {
  40                case BFIN_MEM_ACCESS_CORE:
  41                case BFIN_MEM_ACCESS_CORE_ONLY:
  42                        return __probe_kernel_read(dst, src, size);
  43                        /* XXX: should support IDMA here with SMP */
  44                case BFIN_MEM_ACCESS_DMA:
  45                        if (dma_memcpy(dst, src, size))
  46                                return 0;
  47                        break;
  48                case BFIN_MEM_ACCESS_ITEST:
  49                        if (isram_memcpy(dst, src, size))
  50                                return 0;
  51                        break;
  52                }
  53        }
  54
  55        return -EFAULT;
  56}
  57
  58long probe_kernel_write(void *dst, const void *src, size_t size)
  59{
  60        unsigned long ldst = (unsigned long)dst;
  61        int mem_type;
  62
  63        mem_type = validate_memory_access_address(ldst, size);
  64        if (mem_type < 0)
  65                return mem_type;
  66
  67        if (ldst >= SYSMMR_BASE) {
  68                if (size == 2 && ldst % 2 == 0) {
  69                        u16 mmr;
  70                        memcpy(&mmr, src, sizeof(mmr));
  71                        bfin_write16(dst, mmr);
  72                        return 0;
  73                } else if (size == 4 && ldst % 4 == 0) {
  74                        u32 mmr;
  75                        memcpy(&mmr, src, sizeof(mmr));
  76                        bfin_write32(dst, mmr);
  77                        return 0;
  78                }
  79        } else {
  80                switch (mem_type) {
  81                case BFIN_MEM_ACCESS_CORE:
  82                case BFIN_MEM_ACCESS_CORE_ONLY:
  83                        return __probe_kernel_write(dst, src, size);
  84                        /* XXX: should support IDMA here with SMP */
  85                case BFIN_MEM_ACCESS_DMA:
  86                        if (dma_memcpy(dst, src, size))
  87                                return 0;
  88                        break;
  89                case BFIN_MEM_ACCESS_ITEST:
  90                        if (isram_memcpy(dst, src, size))
  91                                return 0;
  92                        break;
  93                }
  94        }
  95
  96        return -EFAULT;
  97}
  98