aboutsummaryrefslogtreecommitdiffstats
path: root/arch/openrisc
diff options
context:
space:
mode:
authorJonas Bonn <jonas@southpole.se>2011-06-04 15:44:40 -0400
committerJonas Bonn <jonas@southpole.se>2011-07-22 12:46:40 -0400
commit224cd129fdbb40a01de4aaf46cd77d80e65d81e5 (patch)
treeafd1b32161acd06b7a82a8355c71c454375b8a83 /arch/openrisc
parent58e0166a4772aaeb10c9b0f6d59f19099d2047df (diff)
OpenRISC: Library routines
Signed-off-by: Jonas Bonn <jonas@southpole.se> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/openrisc')
-rw-r--r--arch/openrisc/lib/delay.c60
-rw-r--r--arch/openrisc/lib/string.S204
2 files changed, 264 insertions, 0 deletions
diff --git a/arch/openrisc/lib/delay.c b/arch/openrisc/lib/delay.c
new file mode 100644
index 000000000000..01d9740ae6f3
--- /dev/null
+++ b/arch/openrisc/lib/delay.c
@@ -0,0 +1,60 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation
14 *
15 * Precise Delay Loops
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <asm/delay.h>
22#include <asm/timex.h>
23#include <asm/processor.h>
24
25int __devinit read_current_timer(unsigned long *timer_value)
26{
27 *timer_value = mfspr(SPR_TTCR);
28 return 0;
29}
30
31void __delay(unsigned long cycles)
32{
33 cycles_t target = get_cycles() + cycles;
34
35 while (get_cycles() < target)
36 cpu_relax();
37}
38EXPORT_SYMBOL(__delay);
39
40inline void __const_udelay(unsigned long xloops)
41{
42 unsigned long long loops;
43
44 loops = xloops * loops_per_jiffy * HZ;
45
46 __delay(loops >> 32);
47}
48EXPORT_SYMBOL(__const_udelay);
49
50void __udelay(unsigned long usecs)
51{
52 __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
53}
54EXPORT_SYMBOL(__udelay);
55
56void __ndelay(unsigned long nsecs)
57{
58 __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
59}
60EXPORT_SYMBOL(__ndelay);
diff --git a/arch/openrisc/lib/string.S b/arch/openrisc/lib/string.S
new file mode 100644
index 000000000000..465f04bc7deb
--- /dev/null
+++ b/arch/openrisc/lib/string.S
@@ -0,0 +1,204 @@
1/*
2 * OpenRISC string.S
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/linkage.h>
19#include <asm/errno.h>
20
21 /*
22 * this can be optimized by doing gcc inline assemlby with
23 * proper constraints (no need to save args registers...)
24 *
25 */
26
27
28/*
29 *
30 * int __copy_tofrom_user(void *to, const void *from, unsigned long size);
31 *
32 * NOTE: it returns number of bytes NOT copied !!!
33 *
34 */
35 .global __copy_tofrom_user
36__copy_tofrom_user:
37 l.addi r1,r1,-12
38 l.sw 0(r1),r6
39 l.sw 4(r1),r4
40 l.sw 8(r1),r3
41
42 l.addi r11,r5,0
432: l.sfeq r11,r0
44 l.bf 1f
45 l.addi r11,r11,-1
468: l.lbz r6,0(r4)
479: l.sb 0(r3),r6
48 l.addi r3,r3,1
49 l.j 2b
50 l.addi r4,r4,1
511:
52 l.addi r11,r11,1 // r11 holds the return value
53
54 l.lwz r6,0(r1)
55 l.lwz r4,4(r1)
56 l.lwz r3,8(r1)
57 l.jr r9
58 l.addi r1,r1,12
59
60 .section .fixup, "ax"
6199:
62 l.j 1b
63 l.nop
64 .previous
65
66 .section __ex_table, "a"
67 .long 8b, 99b // read fault
68 .long 9b, 99b // write fault
69 .previous
70
71/*
72 * unsigned long clear_user(void *addr, unsigned long size) ;
73 *
74 * NOTE: it returns number of bytes NOT cleared !!!
75 */
76 .global __clear_user
77__clear_user:
78 l.addi r1,r1,-8
79 l.sw 0(r1),r4
80 l.sw 4(r1),r3
81
822: l.sfeq r4,r0
83 l.bf 1f
84 l.addi r4,r4,-1
859: l.sb 0(r3),r0
86 l.j 2b
87 l.addi r3,r3,1
88
891:
90 l.addi r11,r4,1
91
92 l.lwz r4,0(r1)
93 l.lwz r3,4(r1)
94 l.jr r9
95 l.addi r1,r1,8
96
97 .section .fixup, "ax"
9899:
99 l.j 1b
100 l.nop
101 .previous
102
103 .section __ex_table, "a"
104 .long 9b, 99b // write fault
105 .previous
106
107/*
108 * long strncpy_from_user(char *dst, const char *src, long count)
109 *
110 *
111 */
112 .global __strncpy_from_user
113__strncpy_from_user:
114 l.addi r1,r1,-16
115 l.sw 0(r1),r6
116 l.sw 4(r1),r5
117 l.sw 8(r1),r4
118 l.sw 12(r1),r3
119
120 l.addi r11,r5,0
1212: l.sfeq r5,r0
122 l.bf 1f
123 l.addi r5,r5,-1
1248: l.lbz r6,0(r4)
125 l.sfeq r6,r0
126 l.bf 1f
1279: l.sb 0(r3),r6
128 l.addi r3,r3,1
129 l.j 2b
130 l.addi r4,r4,1
1311:
132 l.lwz r6,0(r1)
133 l.addi r5,r5,1
134 l.sub r11,r11,r5 // r11 holds the return value
135
136 l.lwz r6,0(r1)
137 l.lwz r5,4(r1)
138 l.lwz r4,8(r1)
139 l.lwz r3,12(r1)
140 l.jr r9
141 l.addi r1,r1,16
142
143 .section .fixup, "ax"
14499:
145 l.movhi r11,hi(-EFAULT)
146 l.ori r11,r11,lo(-EFAULT)
147
148 l.lwz r6,0(r1)
149 l.lwz r5,4(r1)
150 l.lwz r4,8(r1)
151 l.lwz r3,12(r1)
152 l.jr r9
153 l.addi r1,r1,16
154 .previous
155
156 .section __ex_table, "a"
157 .long 8b, 99b // read fault
158 .previous
159
160/*
161 * extern int __strnlen_user(const char *str, long len, unsigned long top);
162 *
163 *
164 * RTRN: - length of a string including NUL termination character
165 * - on page fault 0
166 */
167
168 .global __strnlen_user
169__strnlen_user:
170 l.addi r1,r1,-8
171 l.sw 0(r1),r6
172 l.sw 4(r1),r3
173
174 l.addi r11,r0,0
1752: l.sfeq r11,r4
176 l.bf 1f
177 l.addi r11,r11,1
1788: l.lbz r6,0(r3)
179 l.sfeq r6,r0
180 l.bf 1f
181 l.sfgeu r3,r5 // are we over the top ?
182 l.bf 99f
183 l.j 2b
184 l.addi r3,r3,1
185
1861:
187 l.lwz r6,0(r1)
188 l.lwz r3,4(r1)
189 l.jr r9
190 l.addi r1,r1,8
191
192 .section .fixup, "ax"
19399:
194 l.addi r11,r0,0
195
196 l.lwz r6,0(r1)
197 l.lwz r3,4(r1)
198 l.jr r9
199 l.addi r1,r1,8
200 .previous
201
202 .section __ex_table, "a"
203 .long 8b, 99b // read fault
204 .previous