Merge branch 'akpm'
[linux-2.6/next.git] / arch / blackfin / mm / maccess.c
blobe2532114c5fd75bde75e31038012b6eefa93c80d
1 /*
2 * safe read and write memory routines callable while atomic
4 * Copyright 2005-2008 Analog Devices Inc.
6 * Licensed under the GPL-2 or later.
7 */
9 #include <linux/uaccess.h>
10 #include <asm/dma.h>
12 static int validate_memory_access_address(unsigned long addr, int size)
14 if (size < 0 || addr == 0)
15 return -EFAULT;
16 return bfin_mem_access_type(addr, size);
19 long probe_kernel_read(void *dst, const void *src, size_t size)
21 unsigned long lsrc = (unsigned long)src;
22 int mem_type;
24 mem_type = validate_memory_access_address(lsrc, size);
25 if (mem_type < 0)
26 return mem_type;
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;
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;
55 return -EFAULT;
58 long probe_kernel_write(void *dst, const void *src, size_t size)
60 unsigned long ldst = (unsigned long)dst;
61 int mem_type;
63 mem_type = validate_memory_access_address(ldst, size);
64 if (mem_type < 0)
65 return mem_type;
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;
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;
96 return -EFAULT;