• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
validate_memory_access_address(unsigned long addr,int size)12 static 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 
probe_kernel_read(void * dst,const void * src,size_t size)19 long 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 
probe_kernel_write(void * dst,const void * src,size_t size)58 long 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