diff options
author | GuanXuetao <gxt@mprc.pku.edu.cn> | 2011-01-15 05:23:09 -0500 |
---|---|---|
committer | GuanXuetao <gxt@mprc.pku.edu.cn> | 2011-03-16 21:19:13 -0400 |
commit | 96cf5185a95e0b304596fe19edcf8dfcd5c10699 (patch) | |
tree | aebdf44fdfa8841577171df18cb1b0745b54d64e | |
parent | 77c93b2f2388b974253af4149aa025b4751f92ad (diff) |
unicore32 additional architecture files: low-level lib: misc
This patch implements the rest low-level libraries.
Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Acked-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | arch/unicore32/include/asm/assembler.h | 131 | ||||
-rw-r--r-- | arch/unicore32/include/asm/bitops.h | 47 | ||||
-rw-r--r-- | arch/unicore32/include/asm/checksum.h | 41 | ||||
-rw-r--r-- | arch/unicore32/include/asm/delay.h | 52 | ||||
-rw-r--r-- | arch/unicore32/include/asm/futex.h | 143 | ||||
-rw-r--r-- | arch/unicore32/include/asm/io.h | 52 | ||||
-rw-r--r-- | arch/unicore32/include/asm/mutex.h | 20 | ||||
-rw-r--r-- | arch/unicore32/lib/Makefile | 27 | ||||
-rw-r--r-- | arch/unicore32/lib/delay.S | 51 | ||||
-rw-r--r-- | arch/unicore32/lib/findbit.S | 98 |
10 files changed, 662 insertions, 0 deletions
diff --git a/arch/unicore32/include/asm/assembler.h b/arch/unicore32/include/asm/assembler.h new file mode 100644 index 000000000000..8e87ed7faeba --- /dev/null +++ b/arch/unicore32/include/asm/assembler.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/assembler.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Do not include any C declarations in this file - it is included by | ||
13 | * assembler source. | ||
14 | */ | ||
15 | #ifndef __ASSEMBLY__ | ||
16 | #error "Only include this from assembly code" | ||
17 | #endif | ||
18 | |||
19 | #include <asm/ptrace.h> | ||
20 | |||
21 | /* | ||
22 | * Little Endian independent macros for shifting bytes within registers. | ||
23 | */ | ||
24 | #define pull >> | ||
25 | #define push << | ||
26 | #define get_byte_0 << #0 | ||
27 | #define get_byte_1 >> #8 | ||
28 | #define get_byte_2 >> #16 | ||
29 | #define get_byte_3 >> #24 | ||
30 | #define put_byte_0 << #0 | ||
31 | #define put_byte_1 << #8 | ||
32 | #define put_byte_2 << #16 | ||
33 | #define put_byte_3 << #24 | ||
34 | |||
35 | #define cadd cmpadd | ||
36 | #define cand cmpand | ||
37 | #define csub cmpsub | ||
38 | #define cxor cmpxor | ||
39 | |||
40 | /* | ||
41 | * Enable and disable interrupts | ||
42 | */ | ||
43 | .macro disable_irq, temp | ||
44 | mov \temp, asr | ||
45 | andn \temp, \temp, #0xFF | ||
46 | or \temp, \temp, #PSR_I_BIT | PRIV_MODE | ||
47 | mov.a asr, \temp | ||
48 | .endm | ||
49 | |||
50 | .macro enable_irq, temp | ||
51 | mov \temp, asr | ||
52 | andn \temp, \temp, #0xFF | ||
53 | or \temp, \temp, #PRIV_MODE | ||
54 | mov.a asr, \temp | ||
55 | .endm | ||
56 | |||
57 | #define USER(x...) \ | ||
58 | 9999: x; \ | ||
59 | .pushsection __ex_table, "a"; \ | ||
60 | .align 3; \ | ||
61 | .long 9999b, 9001f; \ | ||
62 | .popsection | ||
63 | |||
64 | .macro notcond, cond, nexti = .+8 | ||
65 | .ifc \cond, eq | ||
66 | bne \nexti | ||
67 | .else; .ifc \cond, ne | ||
68 | beq \nexti | ||
69 | .else; .ifc \cond, ea | ||
70 | bub \nexti | ||
71 | .else; .ifc \cond, ub | ||
72 | bea \nexti | ||
73 | .else; .ifc \cond, fs | ||
74 | bns \nexti | ||
75 | .else; .ifc \cond, ns | ||
76 | bfs \nexti | ||
77 | .else; .ifc \cond, fv | ||
78 | bnv \nexti | ||
79 | .else; .ifc \cond, nv | ||
80 | bfv \nexti | ||
81 | .else; .ifc \cond, ua | ||
82 | beb \nexti | ||
83 | .else; .ifc \cond, eb | ||
84 | bua \nexti | ||
85 | .else; .ifc \cond, eg | ||
86 | bsl \nexti | ||
87 | .else; .ifc \cond, sl | ||
88 | beg \nexti | ||
89 | .else; .ifc \cond, sg | ||
90 | bel \nexti | ||
91 | .else; .ifc \cond, el | ||
92 | bsg \nexti | ||
93 | .else; .ifnc \cond, al | ||
94 | .error "Unknown cond in notcond macro argument" | ||
95 | .endif; .endif; .endif; .endif; .endif; .endif; .endif | ||
96 | .endif; .endif; .endif; .endif; .endif; .endif; .endif | ||
97 | .endif | ||
98 | .endm | ||
99 | |||
100 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort | ||
101 | .rept \rept | ||
102 | notcond \cond, .+8 | ||
103 | 9999 : | ||
104 | .if \inc == 1 | ||
105 | \instr\()b.u \reg, [\ptr], #\inc | ||
106 | .elseif \inc == 4 | ||
107 | \instr\()w.u \reg, [\ptr], #\inc | ||
108 | .else | ||
109 | .error "Unsupported inc macro argument" | ||
110 | .endif | ||
111 | |||
112 | .pushsection __ex_table, "a" | ||
113 | .align 3 | ||
114 | .long 9999b, \abort | ||
115 | .popsection | ||
116 | .endr | ||
117 | .endm | ||
118 | |||
119 | .macro strusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f | ||
120 | usracc st, \reg, \ptr, \inc, \cond, \rept, \abort | ||
121 | .endm | ||
122 | |||
123 | .macro ldrusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f | ||
124 | usracc ld, \reg, \ptr, \inc, \cond, \rept, \abort | ||
125 | .endm | ||
126 | |||
127 | .macro nop8 | ||
128 | .rept 8 | ||
129 | nop | ||
130 | .endr | ||
131 | .endm | ||
diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h new file mode 100644 index 000000000000..1628a6328994 --- /dev/null +++ b/arch/unicore32/include/asm/bitops.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/bitops.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __UNICORE_BITOPS_H__ | ||
14 | #define __UNICORE_BITOPS_H__ | ||
15 | |||
16 | #define find_next_bit __uc32_find_next_bit | ||
17 | #define find_next_zero_bit __uc32_find_next_zero_bit | ||
18 | |||
19 | #define find_first_bit __uc32_find_first_bit | ||
20 | #define find_first_zero_bit __uc32_find_first_zero_bit | ||
21 | |||
22 | #define _ASM_GENERIC_BITOPS_FLS_H_ | ||
23 | #define _ASM_GENERIC_BITOPS___FLS_H_ | ||
24 | #define _ASM_GENERIC_BITOPS_FFS_H_ | ||
25 | #define _ASM_GENERIC_BITOPS___FFS_H_ | ||
26 | /* | ||
27 | * On UNICORE, those functions can be implemented around | ||
28 | * the cntlz instruction for much better code efficiency. | ||
29 | */ | ||
30 | |||
31 | static inline int fls(int x) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | asm("cntlz\t%0, %1" : "=r" (ret) : "r" (x) : "cc"); | ||
36 | ret = 32 - ret; | ||
37 | |||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | #define __fls(x) (fls(x) - 1) | ||
42 | #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); }) | ||
43 | #define __ffs(x) (ffs(x) - 1) | ||
44 | |||
45 | #include <asm-generic/bitops.h> | ||
46 | |||
47 | #endif /* __UNICORE_BITOPS_H__ */ | ||
diff --git a/arch/unicore32/include/asm/checksum.h b/arch/unicore32/include/asm/checksum.h new file mode 100644 index 000000000000..f55c3f937c3e --- /dev/null +++ b/arch/unicore32/include/asm/checksum.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/checksum.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * IP checksum routines | ||
13 | */ | ||
14 | #ifndef __UNICORE_CHECKSUM_H__ | ||
15 | #define __UNICORE_CHECKSUM_H__ | ||
16 | |||
17 | /* | ||
18 | * computes the checksum of the TCP/UDP pseudo-header | ||
19 | * returns a 16-bit checksum, already complemented | ||
20 | */ | ||
21 | |||
22 | static inline __wsum | ||
23 | csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | ||
24 | unsigned short proto, __wsum sum) | ||
25 | { | ||
26 | __asm__( | ||
27 | "add.a %0, %1, %2\n" | ||
28 | "addc.a %0, %0, %3\n" | ||
29 | "addc.a %0, %0, %4 << #8\n" | ||
30 | "addc.a %0, %0, %5\n" | ||
31 | "addc %0, %0, #0\n" | ||
32 | : "=&r"(sum) | ||
33 | : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto)) | ||
34 | : "cc"); | ||
35 | return sum; | ||
36 | } | ||
37 | #define csum_tcpudp_nofold csum_tcpudp_nofold | ||
38 | |||
39 | #include <asm-generic/checksum.h> | ||
40 | |||
41 | #endif | ||
diff --git a/arch/unicore32/include/asm/delay.h b/arch/unicore32/include/asm/delay.h new file mode 100644 index 000000000000..164ae61cd6f7 --- /dev/null +++ b/arch/unicore32/include/asm/delay.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/delay.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Delay routines, using a pre-computed "loops_per_second" value. | ||
13 | */ | ||
14 | #ifndef __UNICORE_DELAY_H__ | ||
15 | #define __UNICORE_DELAY_H__ | ||
16 | |||
17 | #include <asm/param.h> /* HZ */ | ||
18 | |||
19 | extern void __delay(int loops); | ||
20 | |||
21 | /* | ||
22 | * This function intentionally does not exist; if you see references to | ||
23 | * it, it means that you're calling udelay() with an out of range value. | ||
24 | * | ||
25 | * With currently imposed limits, this means that we support a max delay | ||
26 | * of 2000us. Further limits: HZ<=1000 and bogomips<=3355 | ||
27 | */ | ||
28 | extern void __bad_udelay(void); | ||
29 | |||
30 | /* | ||
31 | * division by multiplication: you don't have to worry about | ||
32 | * loss of precision. | ||
33 | * | ||
34 | * Use only for very small delays ( < 1 msec). Should probably use a | ||
35 | * lookup table, really, as the multiplications take much too long with | ||
36 | * short delays. This is a "reasonable" implementation, though (and the | ||
37 | * first constant multiplications gets optimized away if the delay is | ||
38 | * a constant) | ||
39 | */ | ||
40 | extern void __udelay(unsigned long usecs); | ||
41 | extern void __const_udelay(unsigned long); | ||
42 | |||
43 | #define MAX_UDELAY_MS 2 | ||
44 | |||
45 | #define udelay(n) \ | ||
46 | (__builtin_constant_p(n) ? \ | ||
47 | ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \ | ||
48 | __const_udelay((n) * ((2199023U*HZ)>>11))) : \ | ||
49 | __udelay(n)) | ||
50 | |||
51 | #endif /* __UNICORE_DELAY_H__ */ | ||
52 | |||
diff --git a/arch/unicore32/include/asm/futex.h b/arch/unicore32/include/asm/futex.h new file mode 100644 index 000000000000..07dea6170558 --- /dev/null +++ b/arch/unicore32/include/asm/futex.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/futex.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __UNICORE_FUTEX_H__ | ||
14 | #define __UNICORE_FUTEX_H__ | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | |||
18 | #include <linux/futex.h> | ||
19 | #include <linux/preempt.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include <linux/errno.h> | ||
22 | |||
23 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | ||
24 | __asm__ __volatile__( \ | ||
25 | "1: ldw.u %1, [%2]\n" \ | ||
26 | " " insn "\n" \ | ||
27 | "2: stw.u %0, [%2]\n" \ | ||
28 | " mov %0, #0\n" \ | ||
29 | "3:\n" \ | ||
30 | " .pushsection __ex_table,\"a\"\n" \ | ||
31 | " .align 3\n" \ | ||
32 | " .long 1b, 4f, 2b, 4f\n" \ | ||
33 | " .popsection\n" \ | ||
34 | " .pushsection .fixup,\"ax\"\n" \ | ||
35 | "4: mov %0, %4\n" \ | ||
36 | " b 3b\n" \ | ||
37 | " .popsection" \ | ||
38 | : "=&r" (ret), "=&r" (oldval) \ | ||
39 | : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \ | ||
40 | : "cc", "memory") | ||
41 | |||
42 | static inline int | ||
43 | futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | ||
44 | { | ||
45 | int op = (encoded_op >> 28) & 7; | ||
46 | int cmp = (encoded_op >> 24) & 15; | ||
47 | int oparg = (encoded_op << 8) >> 20; | ||
48 | int cmparg = (encoded_op << 20) >> 20; | ||
49 | int oldval = 0, ret; | ||
50 | |||
51 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
52 | oparg = 1 << oparg; | ||
53 | |||
54 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
55 | return -EFAULT; | ||
56 | |||
57 | pagefault_disable(); /* implies preempt_disable() */ | ||
58 | |||
59 | switch (op) { | ||
60 | case FUTEX_OP_SET: | ||
61 | __futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg); | ||
62 | break; | ||
63 | case FUTEX_OP_ADD: | ||
64 | __futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg); | ||
65 | break; | ||
66 | case FUTEX_OP_OR: | ||
67 | __futex_atomic_op("or %0, %1, %3", ret, oldval, uaddr, oparg); | ||
68 | break; | ||
69 | case FUTEX_OP_ANDN: | ||
70 | __futex_atomic_op("and %0, %1, %3", | ||
71 | ret, oldval, uaddr, ~oparg); | ||
72 | break; | ||
73 | case FUTEX_OP_XOR: | ||
74 | __futex_atomic_op("xor %0, %1, %3", ret, oldval, uaddr, oparg); | ||
75 | break; | ||
76 | default: | ||
77 | ret = -ENOSYS; | ||
78 | } | ||
79 | |||
80 | pagefault_enable(); /* subsumes preempt_enable() */ | ||
81 | |||
82 | if (!ret) { | ||
83 | switch (cmp) { | ||
84 | case FUTEX_OP_CMP_EQ: | ||
85 | ret = (oldval == cmparg); | ||
86 | break; | ||
87 | case FUTEX_OP_CMP_NE: | ||
88 | ret = (oldval != cmparg); | ||
89 | break; | ||
90 | case FUTEX_OP_CMP_LT: | ||
91 | ret = (oldval < cmparg); | ||
92 | break; | ||
93 | case FUTEX_OP_CMP_GE: | ||
94 | ret = (oldval >= cmparg); | ||
95 | break; | ||
96 | case FUTEX_OP_CMP_LE: | ||
97 | ret = (oldval <= cmparg); | ||
98 | break; | ||
99 | case FUTEX_OP_CMP_GT: | ||
100 | ret = (oldval > cmparg); | ||
101 | break; | ||
102 | default: | ||
103 | ret = -ENOSYS; | ||
104 | } | ||
105 | } | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static inline int | ||
110 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
111 | { | ||
112 | int val; | ||
113 | |||
114 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
115 | return -EFAULT; | ||
116 | |||
117 | pagefault_disable(); /* implies preempt_disable() */ | ||
118 | |||
119 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" | ||
120 | "1: ldw.u %0, [%3]\n" | ||
121 | " cmpxor.a %0, %1\n" | ||
122 | " bne 3f\n" | ||
123 | "2: stw.u %2, [%3]\n" | ||
124 | "3:\n" | ||
125 | " .pushsection __ex_table,\"a\"\n" | ||
126 | " .align 3\n" | ||
127 | " .long 1b, 4f, 2b, 4f\n" | ||
128 | " .popsection\n" | ||
129 | " .pushsection .fixup,\"ax\"\n" | ||
130 | "4: mov %0, %4\n" | ||
131 | " b 3b\n" | ||
132 | " .popsection" | ||
133 | : "=&r" (val) | ||
134 | : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT) | ||
135 | : "cc", "memory"); | ||
136 | |||
137 | pagefault_enable(); /* subsumes preempt_enable() */ | ||
138 | |||
139 | return val; | ||
140 | } | ||
141 | |||
142 | #endif /* __KERNEL__ */ | ||
143 | #endif /* __UNICORE_FUTEX_H__ */ | ||
diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h new file mode 100644 index 000000000000..d73457c1800a --- /dev/null +++ b/arch/unicore32/include/asm/io.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/io.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef __UNICORE_IO_H__ | ||
13 | #define __UNICORE_IO_H__ | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
16 | |||
17 | #include <asm/byteorder.h> | ||
18 | #include <asm/memory.h> | ||
19 | #include <asm/system.h> | ||
20 | |||
21 | #include <asm-generic/io.h> | ||
22 | |||
23 | /* | ||
24 | * __uc32_ioremap and __uc32_ioremap_cached takes CPU physical address. | ||
25 | */ | ||
26 | extern void __iomem *__uc32_ioremap(unsigned long, size_t); | ||
27 | extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t); | ||
28 | extern void __uc32_iounmap(volatile void __iomem *addr); | ||
29 | |||
30 | /* | ||
31 | * ioremap and friends. | ||
32 | * | ||
33 | * ioremap takes a PCI memory address, as specified in | ||
34 | * Documentation/IO-mapping.txt. | ||
35 | * | ||
36 | */ | ||
37 | #define ioremap(cookie, size) __uc32_ioremap(cookie, size) | ||
38 | #define ioremap_cached(cookie, size) __uc32_ioremap_cached(cookie, size) | ||
39 | #define iounmap(cookie) __uc32_iounmap(cookie) | ||
40 | |||
41 | extern void __iomem *ioport_map(unsigned long port, unsigned int nr); | ||
42 | extern void ioport_unmap(void __iomem *addr); | ||
43 | |||
44 | /* | ||
45 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | ||
46 | * access | ||
47 | */ | ||
48 | #undef xlate_dev_mem_ptr | ||
49 | #define xlate_dev_mem_ptr(p) __va(p) | ||
50 | |||
51 | #endif /* __KERNEL__ */ | ||
52 | #endif /* __UNICORE_IO_H__ */ | ||
diff --git a/arch/unicore32/include/asm/mutex.h b/arch/unicore32/include/asm/mutex.h new file mode 100644 index 000000000000..fab7d0e8adf6 --- /dev/null +++ b/arch/unicore32/include/asm/mutex.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/mutex.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * UniCore optimized mutex locking primitives | ||
13 | * | ||
14 | * Please look into asm-generic/mutex-xchg.h for a formal definition. | ||
15 | */ | ||
16 | #ifndef __UNICORE_MUTEX_H__ | ||
17 | #define __UNICORE_MUTEX_H__ | ||
18 | |||
19 | # include <asm-generic/mutex-xchg.h> | ||
20 | #endif | ||
diff --git a/arch/unicore32/lib/Makefile b/arch/unicore32/lib/Makefile new file mode 100644 index 000000000000..87229a558b36 --- /dev/null +++ b/arch/unicore32/lib/Makefile | |||
@@ -0,0 +1,27 @@ | |||
1 | # | ||
2 | # linux/arch/unicore32/lib/Makefile | ||
3 | # | ||
4 | # Copyright (C) 2001-2010 GUAN Xue-tao | ||
5 | # | ||
6 | |||
7 | lib-y := backtrace.o delay.o findbit.o | ||
8 | lib-y += strncpy_from_user.o strnlen_user.o | ||
9 | lib-y += clear_user.o copy_page.o | ||
10 | lib-y += copy_from_user.o copy_to_user.o | ||
11 | |||
12 | GNU_LIBC_A := $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libc.a) | ||
13 | GNU_LIBC_A_OBJS := memchr.o memcpy.o memmove.o memset.o | ||
14 | GNU_LIBC_A_OBJS += strchr.o strrchr.o | ||
15 | GNU_LIBC_A_OBJS += rawmemchr.o # needed by strrchr.o | ||
16 | |||
17 | GNU_LIBGCC_A := $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a) | ||
18 | GNU_LIBGCC_A_OBJS := _ashldi3.o _ashrdi3.o _lshrdi3.o | ||
19 | GNU_LIBGCC_A_OBJS += _divsi3.o _modsi3.o _ucmpdi2.o _umodsi3.o _udivsi3.o | ||
20 | |||
21 | lib-y += $(GNU_LIBC_A_OBJS) $(GNU_LIBGCC_A_OBJS) | ||
22 | |||
23 | $(addprefix $(obj)/, $(GNU_LIBC_A_OBJS)): | ||
24 | $(Q)$(AR) p $(GNU_LIBC_A) $(notdir $@) > $@ | ||
25 | |||
26 | $(addprefix $(obj)/, $(GNU_LIBGCC_A_OBJS)): | ||
27 | $(Q)$(AR) p $(GNU_LIBGCC_A) $(notdir $@) > $@ | ||
diff --git a/arch/unicore32/lib/delay.S b/arch/unicore32/lib/delay.S new file mode 100644 index 000000000000..24664c009e78 --- /dev/null +++ b/arch/unicore32/lib/delay.S | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/lib/delay.S | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/linkage.h> | ||
13 | #include <asm/assembler.h> | ||
14 | #include <asm/param.h> | ||
15 | .text | ||
16 | |||
17 | .LC0: .word loops_per_jiffy | ||
18 | .LC1: .word (2199023*HZ)>>11 | ||
19 | |||
20 | /* | ||
21 | * r0 <= 2000 | ||
22 | * lpj <= 0x01ffffff (max. 3355 bogomips) | ||
23 | * HZ <= 1000 | ||
24 | */ | ||
25 | |||
26 | ENTRY(__udelay) | ||
27 | ldw r2, .LC1 | ||
28 | mul r0, r2, r0 | ||
29 | ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 | ||
30 | ldw r2, .LC0 | ||
31 | ldw r2, [r2] @ max = 0x01ffffff | ||
32 | mov r0, r0 >> #14 @ max = 0x0001ffff | ||
33 | mov r2, r2 >> #10 @ max = 0x00007fff | ||
34 | mul r0, r2, r0 @ max = 2^32-1 | ||
35 | mov.a r0, r0 >> #6 | ||
36 | cmoveq pc, lr | ||
37 | |||
38 | /* | ||
39 | * loops = r0 * HZ * loops_per_jiffy / 1000000 | ||
40 | * | ||
41 | * Oh, if only we had a cycle counter... | ||
42 | */ | ||
43 | |||
44 | @ Delay routine | ||
45 | ENTRY(__delay) | ||
46 | sub.a r0, r0, #2 | ||
47 | bua __delay | ||
48 | mov pc, lr | ||
49 | ENDPROC(__udelay) | ||
50 | ENDPROC(__const_udelay) | ||
51 | ENDPROC(__delay) | ||
diff --git a/arch/unicore32/lib/findbit.S b/arch/unicore32/lib/findbit.S new file mode 100644 index 000000000000..c360ce905d8b --- /dev/null +++ b/arch/unicore32/lib/findbit.S | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/lib/findbit.S | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/linkage.h> | ||
13 | #include <asm/assembler.h> | ||
14 | .text | ||
15 | |||
16 | /* | ||
17 | * Purpose : Find a 'zero' bit | ||
18 | * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit); | ||
19 | */ | ||
20 | __uc32_find_first_zero_bit: | ||
21 | cxor.a r1, #0 | ||
22 | beq 3f | ||
23 | mov r2, #0 | ||
24 | 1: ldb r3, [r0+], r2 >> #3 | ||
25 | xor.a r3, r3, #0xff @ invert bits | ||
26 | bne .L_found @ any now set - found zero bit | ||
27 | add r2, r2, #8 @ next bit pointer | ||
28 | 2: csub.a r2, r1 @ any more? | ||
29 | bub 1b | ||
30 | 3: mov r0, r1 @ no free bits | ||
31 | mov pc, lr | ||
32 | |||
33 | /* | ||
34 | * Purpose : Find next 'zero' bit | ||
35 | * Prototype: int find_next_zero_bit | ||
36 | * (void *addr, unsigned int maxbit, int offset) | ||
37 | */ | ||
38 | ENTRY(__uc32_find_next_zero_bit) | ||
39 | cxor.a r1, #0 | ||
40 | beq 3b | ||
41 | and.a ip, r2, #7 | ||
42 | beq 1b @ If new byte, goto old routine | ||
43 | ldb r3, [r0+], r2 >> #3 | ||
44 | xor r3, r3, #0xff @ now looking for a 1 bit | ||
45 | mov.a r3, r3 >> ip @ shift off unused bits | ||
46 | bne .L_found | ||
47 | or r2, r2, #7 @ if zero, then no bits here | ||
48 | add r2, r2, #1 @ align bit pointer | ||
49 | b 2b @ loop for next bit | ||
50 | ENDPROC(__uc32_find_next_zero_bit) | ||
51 | |||
52 | /* | ||
53 | * Purpose : Find a 'one' bit | ||
54 | * Prototype: int find_first_bit | ||
55 | * (const unsigned long *addr, unsigned int maxbit); | ||
56 | */ | ||
57 | __uc32_find_first_bit: | ||
58 | cxor.a r1, #0 | ||
59 | beq 3f | ||
60 | mov r2, #0 | ||
61 | 1: ldb r3, [r0+], r2 >> #3 | ||
62 | mov.a r3, r3 | ||
63 | bne .L_found @ any now set - found zero bit | ||
64 | add r2, r2, #8 @ next bit pointer | ||
65 | 2: csub.a r2, r1 @ any more? | ||
66 | bub 1b | ||
67 | 3: mov r0, r1 @ no free bits | ||
68 | mov pc, lr | ||
69 | |||
70 | /* | ||
71 | * Purpose : Find next 'one' bit | ||
72 | * Prototype: int find_next_zero_bit | ||
73 | * (void *addr, unsigned int maxbit, int offset) | ||
74 | */ | ||
75 | ENTRY(__uc32_find_next_bit) | ||
76 | cxor.a r1, #0 | ||
77 | beq 3b | ||
78 | and.a ip, r2, #7 | ||
79 | beq 1b @ If new byte, goto old routine | ||
80 | ldb r3, [r0+], r2 >> #3 | ||
81 | mov.a r3, r3 >> ip @ shift off unused bits | ||
82 | bne .L_found | ||
83 | or r2, r2, #7 @ if zero, then no bits here | ||
84 | add r2, r2, #1 @ align bit pointer | ||
85 | b 2b @ loop for next bit | ||
86 | ENDPROC(__uc32_find_next_bit) | ||
87 | |||
88 | /* | ||
89 | * One or more bits in the LSB of r3 are assumed to be set. | ||
90 | */ | ||
91 | .L_found: | ||
92 | rsub r1, r3, #0 | ||
93 | and r3, r3, r1 | ||
94 | cntlz r3, r3 | ||
95 | rsub r3, r3, #31 | ||
96 | add r0, r2, r3 | ||
97 | mov pc, lr | ||
98 | |||