Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29304ab8a4 | ||
|
|
1a958df6d4 | ||
|
|
5161dd4c2e | ||
|
|
e6c4f22d37 | ||
|
|
0eac06f976 | ||
|
|
3cc45d541c | ||
|
|
cf5cc42b04 | ||
|
|
05785b19a5 | ||
|
|
c3c720b6ac | ||
|
|
0be67e1b88 | ||
|
|
ff838783fd | ||
|
|
0e88c0d6f9 | ||
|
|
895867d50f | ||
|
|
e0dcf977c4 | ||
|
|
9113266f9e | ||
|
|
f030875b65 | ||
|
|
e92c2c7a5f | ||
|
|
65e2430cb6 | ||
|
|
a7182f71c5 | ||
|
|
458683f436 | ||
|
|
86854fd63d | ||
|
|
6ea9e2978f | ||
|
|
effd0b0bb6 | ||
|
|
813334df13 | ||
|
|
62e3399f4b | ||
|
|
fbdc1ae34e | ||
|
|
be2e61d7bb | ||
|
|
2576bfc656 | ||
|
|
883ee18049 | ||
|
|
784c283e2e | ||
|
|
c58d99234b | ||
|
|
b43101b3b6 | ||
|
|
2e99501893 | ||
|
|
f5e5ee63ea | ||
|
|
e1b5a9a8bf | ||
|
|
cc240d3589 | ||
|
|
14a5493be1 | ||
|
|
508c4aa481 | ||
|
|
f10763a816 | ||
|
|
0b6c9668e3 | ||
|
|
150f08154c | ||
|
|
62fbcc89ec | ||
|
|
025ebd009e | ||
|
|
b649709cb0 | ||
|
|
d8d7813a92 | ||
|
|
b9fb329ea4 | ||
|
|
b629077b90 | ||
|
|
d803de4e99 | ||
|
|
22d827972d | ||
|
|
dfd2d6b446 | ||
|
|
d05af5fa57 | ||
|
|
89b8299033 | ||
|
|
84b6bbe6f0 | ||
|
|
32e5b3f020 | ||
|
|
999ac0972f | ||
|
|
c82ff92dfb | ||
|
|
fe6336ca14 | ||
|
|
d300c65fe0 | ||
|
|
f3035e9039 | ||
|
|
9b7d997794 | ||
|
|
8589013048 | ||
|
|
6397f6e31e | ||
|
|
73791d6d58 | ||
|
|
06a4dace6d | ||
|
|
e8e22b339e | ||
|
|
74dfcdf587 | ||
|
|
9f8a6e9f99 | ||
|
|
1763501ec2 | ||
|
|
409ac2dfff | ||
|
|
3c35ea6e5b | ||
|
|
1c3d3fc145 | ||
|
|
ee523e1a49 | ||
|
|
a0f51365b4 | ||
|
|
ed0a064511 | ||
|
|
34fbee8391 | ||
|
|
ce78c2e27b | ||
|
|
cee801753b | ||
|
|
84a7fc2881 | ||
|
|
28bbe0b4ad | ||
|
|
54710b5daa | ||
|
|
24241036bc | ||
|
|
53f8d3263b | ||
|
|
1f0e266734 | ||
|
|
ea6462494e | ||
|
|
e29aa87e47 | ||
|
|
3925c26ddb | ||
|
|
897a88ebd4 | ||
|
|
cf6ee68546 | ||
|
|
731be3d26f | ||
|
|
9196924385 | ||
|
|
3d9ca486f1 | ||
|
|
51b997420d | ||
|
|
320c1d85ea | ||
|
|
56f8ccebc3 | ||
|
|
0ec110f219 | ||
|
|
a003228755 | ||
|
|
18e36337df | ||
|
|
bd08a1d637 | ||
|
|
f8de51b586 | ||
|
|
fd255eab63 | ||
|
|
60b502db6d | ||
|
|
6570ab5739 | ||
|
|
afc5b11919 | ||
|
|
162244ec5c | ||
|
|
cd98d4709d | ||
|
|
a10a99cc81 | ||
|
|
34144dfd4d | ||
|
|
f0f9ce6408 | ||
|
|
ad75f98c81 | ||
|
|
2199269214 | ||
|
|
2cd211fccc | ||
|
|
df5ae1415e | ||
|
|
f220524d63 | ||
|
|
93fde8d68d | ||
|
|
6a5609fa22 | ||
|
|
6ba6907987 | ||
|
|
a8fa74c31f | ||
|
|
45869c308e | ||
|
|
1073a5e9c2 | ||
|
|
0c82c69f39 | ||
|
|
5e831c4536 | ||
|
|
f712f5e693 | ||
|
|
dd8e189d98 | ||
|
|
ebb0b5bb01 | ||
|
|
0c1093789f | ||
|
|
b2fb6bacc4 | ||
|
|
4cd89c4178 | ||
|
|
8d6150c7d3 | ||
|
|
32a9d4ff25 | ||
|
|
b2028cee4c | ||
|
|
3b3f5d101f | ||
|
|
98b8091814 | ||
|
|
6a9871b204 | ||
|
|
75122c97e9 | ||
|
|
d4c453bf57 | ||
|
|
42353cab89 | ||
|
|
8b99c680e2 | ||
|
|
6111706686 | ||
|
|
d4c88e234f | ||
|
|
95590fdef8 | ||
|
|
f26b92f4c0 | ||
|
|
800410ce1f | ||
|
|
801509f5da | ||
|
|
97b5382a15 | ||
|
|
a59792c8d7 | ||
|
|
99b2d1d593 | ||
|
|
4c68d02013 | ||
|
|
e06c67cd59 | ||
|
|
84ec880ac0 | ||
|
|
96f6dfe9e7 | ||
|
|
e8560831c3 | ||
|
|
f86c43c65d | ||
|
|
84aa16cd8c | ||
|
|
b29c3ba306 | ||
|
|
2dc9c970d7 | ||
|
|
5248673962 | ||
|
|
f6e2207713 | ||
|
|
c713ab89e9 | ||
|
|
12403e3c6b | ||
|
|
e74d63dd6e | ||
|
|
5eaef67b02 | ||
|
|
78d0e6caf6 | ||
|
|
ca0b6a2d2f | ||
|
|
2ce7b9713b | ||
|
|
9e60486c32 | ||
|
|
dbc2c68f17 | ||
|
|
beb8d43aed | ||
|
|
671cb79488 | ||
|
|
9045c06019 | ||
|
|
28da92a61f | ||
|
|
d890c35378 | ||
|
|
4030150f51 | ||
|
|
ad21b8d1f1 | ||
|
|
b0bd183e7f | ||
|
|
b3f6caccf7 | ||
|
|
7e9d615a2f | ||
|
|
79382bc0a6 | ||
|
|
84697244f1 | ||
|
|
f1a4351fed | ||
|
|
1fcde7aaba | ||
|
|
3890b107bb | ||
|
|
0a81a321a8 | ||
|
|
23b9de5a73 | ||
|
|
d2471ef677 | ||
|
|
4f378133e3 | ||
|
|
6f7f81d5a1 | ||
|
|
97d0f09096 | ||
|
|
d2adce273f | ||
|
|
6cdbd7cc0f | ||
|
|
ce306ffe9f | ||
|
|
e67872e27c | ||
|
|
6e75477e02 | ||
|
|
395032624b | ||
|
|
35f686f788 | ||
|
|
aeda4e6548 | ||
|
|
2411981d56 | ||
|
|
dd17d1e2c1 | ||
|
|
c24e6e18c9 | ||
|
|
efb709f9ec | ||
|
|
500afb7d7f | ||
|
|
4d84d3e4f8 | ||
|
|
c1ad9468df | ||
|
|
fe93103d91 | ||
|
|
d92dc60433 | ||
|
|
f91907f2b7 | ||
|
|
2dfe339962 | ||
|
|
46d28982b2 | ||
|
|
3add772584 | ||
|
|
db1edb3d5f | ||
|
|
edc1f5d82d | ||
|
|
1b8189a1ba | ||
|
|
5097b53031 | ||
|
|
822545696f | ||
|
|
6df1607be7 | ||
|
|
6f0c4ef760 | ||
|
|
da055740f2 | ||
|
|
4421e65170 | ||
|
|
9ef9b73933 | ||
|
|
d25b3a4ce7 | ||
|
|
9f179285e7 | ||
|
|
e5c9343f22 | ||
|
|
98c31bb540 | ||
|
|
2b9890877e | ||
|
|
e495d1eb21 | ||
|
|
9120c89766 | ||
|
|
c52c8a3f8a | ||
|
|
da01139096 | ||
|
|
d625055fcc | ||
|
|
f910f9e0ef | ||
|
|
d8b7afc7da | ||
|
|
ab41594c26 | ||
|
|
be7733b568 | ||
|
|
079d7c2224 | ||
|
|
27871259e9 | ||
|
|
d5ebc8fb7f | ||
|
|
4e4ba4c999 | ||
|
|
23a884ba7f | ||
|
|
62a0d3e67c | ||
|
|
e28a60708d | ||
|
|
0e445b0159 | ||
|
|
690515d2d6 | ||
|
|
ef7b943fed | ||
|
|
0207df7398 | ||
|
|
8685492464 | ||
|
|
1dbb17db61 | ||
|
|
1863a355a3 | ||
|
|
6239b16894 | ||
|
|
60a5597455 | ||
|
|
efb6c972f1 | ||
|
|
8c7cd22c3a | ||
|
|
9090b3b845 | ||
|
|
2603f134c8 | ||
|
|
34ffe7c087 | ||
|
|
8d574f84bb | ||
|
|
58373d43a7 | ||
|
|
9b5b72691e | ||
|
|
8f1ffa5253 | ||
|
|
838465636e | ||
|
|
dcc8e933d4 | ||
|
|
5a83b2a618 | ||
|
|
5795af99ce | ||
|
|
1ac45ceb8d | ||
|
|
02843f9521 | ||
|
|
66552a8cf9 | ||
|
|
3570f9ddf7 | ||
|
|
ef7dca456f | ||
|
|
1eb82c6d91 | ||
|
|
404a7066be | ||
|
|
ada68ef8b9 | ||
|
|
57abe4cd2e | ||
|
|
f2f4560575 | ||
|
|
db7845319c | ||
|
|
624255324f | ||
|
|
000eedd9aa | ||
|
|
f7940e7045 | ||
|
|
0c6927b63e | ||
|
|
5d564b6f87 | ||
|
|
64c58c19f7 | ||
|
|
3bb24e374c | ||
|
|
b06c05faee | ||
|
|
ab18f02ad6 | ||
|
|
12091e2fc0 | ||
|
|
6ea1e3451e | ||
|
|
614db415a2 | ||
|
|
84d39f3127 | ||
|
|
250e5ce76e | ||
|
|
302a6330a4 | ||
|
|
d120bb23ae | ||
|
|
daef9e5718 | ||
|
|
9bb6f8b95e | ||
|
|
f30a803656 | ||
|
|
6465bed7e8 | ||
|
|
1435c1b539 | ||
|
|
8b7f4e7efe | ||
|
|
ed17773709 | ||
|
|
da29b1e973 | ||
|
|
7d13e2b403 | ||
|
|
1f96ee0fc9 | ||
|
|
d67508a166 | ||
|
|
20ef1fe8d0 | ||
|
|
0427627414 | ||
|
|
82e4ae6ef0 | ||
|
|
84a546a30b | ||
|
|
31277d80a1 | ||
|
|
9514579812 | ||
|
|
7ff9b84ebf | ||
|
|
4a17b1a7c8 | ||
|
|
6db9fe3008 | ||
|
|
2ce16456f7 | ||
|
|
59392f3323 | ||
|
|
4d0559118c | ||
|
|
bce18eae81 | ||
|
|
fb9fefa0f8 | ||
|
|
b35f1983b6 | ||
|
|
8dcbf70c95 | ||
|
|
e2adacf958 | ||
|
|
d01737200e | ||
|
|
8397844e07 | ||
|
|
65ea573703 | ||
|
|
beb17d5292 | ||
|
|
22d53c65e8 | ||
|
|
aea23b7920 | ||
|
|
f80b3cd46d | ||
|
|
25478468fa | ||
|
|
5c76113162 | ||
|
|
90ec9ae16c | ||
|
|
2fad67f009 | ||
|
|
39763075d5 | ||
|
|
cb25d25504 | ||
|
|
84a64e82e4 | ||
|
|
25ad7dfbed | ||
|
|
ef3254102c | ||
|
|
5f1c9d4974 | ||
|
|
da89a689d0 | ||
|
|
7bc2458954 | ||
|
|
ef9b47ddcc | ||
|
|
c3fad8852d | ||
|
|
bd2424e943 | ||
|
|
7dd11b14ee | ||
|
|
89efbbe281 | ||
|
|
97df7fd2f4 | ||
|
|
81990747fd | ||
|
|
205ac51288 | ||
|
|
04059b73c8 | ||
|
|
9301769092 | ||
|
|
8f0b045a87 | ||
|
|
c1df565203 | ||
|
|
3cbbd302ab | ||
|
|
7c674100fa | ||
|
|
91b0427458 | ||
|
|
6dc5e46ee0 | ||
|
|
561450e241 | ||
|
|
cd43ea06e8 | ||
|
|
56eec08ba5 | ||
|
|
9634cc195b | ||
|
|
05872db60d | ||
|
|
4e3ae0ba8f | ||
|
|
346bdcbed7 | ||
|
|
f17b4ae3be | ||
|
|
295f38b274 | ||
|
|
4f7dcb93d5 | ||
|
|
25bb646c65 | ||
|
|
10136031c0 | ||
|
|
9496f9a230 | ||
|
|
9d4495a33c | ||
|
|
78aa8fefbe | ||
|
|
83019a4502 | ||
|
|
246f8d0fc1 | ||
|
|
2249a071a0 | ||
|
|
edc015a023 | ||
|
|
6cff85ed7f | ||
|
|
cfb5a46ddc | ||
|
|
583f27068c | ||
|
|
e2b7d72b29 | ||
|
|
a5362efe3b | ||
|
|
b0111a1c37 | ||
|
|
31c174ece7 | ||
|
|
012f8f19e6 | ||
|
|
8534b1aab1 | ||
|
|
28e54d265b | ||
|
|
e78a375b9b | ||
|
|
8fcccbd3d8 | ||
|
|
8fb360991f | ||
|
|
958fa24949 | ||
|
|
3a16b67daf | ||
|
|
d5bf823a73 | ||
|
|
ca4f4c92ab | ||
|
|
f29397102b | ||
|
|
3101410243 | ||
|
|
9b7276cd3f | ||
|
|
1fe072a058 | ||
|
|
8bcd5fdbfc | ||
|
|
cbd271d4f7 | ||
|
|
59606436bc | ||
|
|
3672fef3f3 | ||
|
|
e7e29fd14a | ||
|
|
35e7aae64c | ||
|
|
df44480cdc | ||
|
|
641dadcf1a | ||
|
|
c88cc16c2d | ||
|
|
d962c79eba | ||
|
|
1c798cf817 | ||
|
|
d04110c07d | ||
|
|
df66af1678 | ||
|
|
8b3262af4f | ||
|
|
8090690c3c | ||
|
|
aacfed2c42 | ||
|
|
b6da17dc5e | ||
|
|
73b2fb5d70 | ||
|
|
5ff3dd2bfc | ||
|
|
5a5a543db9 | ||
|
|
bc1d43ce61 | ||
|
|
55e05d5d6e | ||
|
|
153902c0b2 | ||
|
|
86b2148080 | ||
|
|
bc208061da | ||
|
|
0cddb7aa27 | ||
|
|
815a3d1d62 | ||
|
|
78045236f6 | ||
|
|
7a11d611f1 | ||
|
|
1ddc04cde8 | ||
|
|
9055606cb0 | ||
|
|
89c7b5b62b | ||
|
|
8282bdc9c8 | ||
|
|
29308e0e99 | ||
|
|
81f9a78f2a | ||
|
|
999d4ee711 | ||
|
|
1cb7b4d3f2 | ||
|
|
92a6e7fb92 | ||
|
|
87047ca0e6 | ||
|
|
cacccef7b7 | ||
|
|
530c2d8028 | ||
|
|
19d100ff0b | ||
|
|
d21942b947 | ||
|
|
ab958e5012 | ||
|
|
e9f077b639 | ||
|
|
fe93e82532 | ||
|
|
5471fd5dbe | ||
|
|
16ea8fb74a | ||
|
|
69d1c3b198 | ||
|
|
c874a2be7e | ||
|
|
0dab8f5996 | ||
|
|
851313163c | ||
|
|
6a7be43f36 | ||
|
|
5b1d04552c | ||
|
|
fac99851e6 | ||
|
|
36cd703c46 | ||
|
|
1463888d32 | ||
|
|
78ae675783 | ||
|
|
da3ea15eb8 | ||
|
|
9d68d1d4a7 | ||
|
|
450d47cb75 | ||
|
|
85b91f6e0d | ||
|
|
d1aa5903b5 | ||
|
|
35342b2e7e | ||
|
|
eb5024207d | ||
|
|
7d34774e2b | ||
|
|
354af5c6f3 | ||
|
|
58317a7db4 | ||
|
|
774212980a | ||
|
|
caa2a03bdd | ||
|
|
80fe2196b4 | ||
|
|
2647071158 | ||
|
|
2a8fd54c3b | ||
|
|
492c8c02ce | ||
|
|
8243bc44ad | ||
|
|
b275c44a3e | ||
|
|
d2b4499038 | ||
|
|
4dfe44a2d6 | ||
|
|
b0d44785d7 | ||
|
|
9b794580a0 | ||
|
|
97491492aa | ||
|
|
4cc2973db7 | ||
|
|
e36682fe8b | ||
|
|
ad9dbc64a6 | ||
|
|
3755bb8122 | ||
|
|
b076f729f3 | ||
|
|
36fcf87bff | ||
|
|
454c0a5da5 | ||
|
|
c009e4d6ea | ||
|
|
1ea479ee8c | ||
|
|
c648e71d34 | ||
|
|
4ebc11c0a2 | ||
|
|
0af3482a35 | ||
|
|
ced976f2c1 | ||
|
|
11e04c61a9 | ||
|
|
402d0973aa | ||
|
|
c69512e8f7 | ||
|
|
032f50a4d5 | ||
|
|
920798e30d | ||
|
|
7d60552e53 | ||
|
|
1e5cfc10cb | ||
|
|
c64727821c | ||
|
|
c6cbd80adc | ||
|
|
3640a0a8fc | ||
|
|
8412104f00 | ||
|
|
4b43c35653 | ||
|
|
35f771808e | ||
|
|
9539c2d9b2 | ||
|
|
dfef90be61 | ||
|
|
282d372d27 | ||
|
|
4e5f9f7d97 | ||
|
|
34d711770c | ||
|
|
6507798287 | ||
|
|
3704083c8f | ||
|
|
3c1ec4ccf8 | ||
|
|
2511e6645d | ||
|
|
fbe13a068a | ||
|
|
6197c862e7 | ||
|
|
50d936fabe | ||
|
|
f9b6e0d05f | ||
|
|
ef79c73757 | ||
|
|
8ffe8e45be | ||
|
|
d48bd24728 | ||
|
|
26cde0600a | ||
|
|
c95b5b1111 | ||
|
|
0270463d98 | ||
|
|
b4f798490d | ||
|
|
61c4e73330 | ||
|
|
bc0890302b | ||
|
|
360899f74e | ||
|
|
e6bea2b4d5 | ||
|
|
b26c956260 | ||
|
|
7298b63ead | ||
|
|
6e5ba4221d | ||
|
|
88aa13dfbd | ||
|
|
237301cc79 | ||
|
|
2676ea9fa2 | ||
|
|
49fd643a08 | ||
|
|
406051184a | ||
|
|
117e82db64 | ||
|
|
7bf05036b9 | ||
|
|
40b227df7c | ||
|
|
77849d39cd | ||
|
|
fd1f04fbf9 | ||
|
|
22020b1673 | ||
|
|
26ae33b780 | ||
|
|
a7e8ffe32e | ||
|
|
f12dd7133b | ||
|
|
f773dde730 | ||
|
|
eb92bccce2 | ||
|
|
61e6d7c8ed | ||
|
|
07644859a1 | ||
|
|
2943fd6d1f | ||
|
|
5e856b5bc2 | ||
|
|
7e6b873e41 | ||
|
|
20cb70a047 | ||
|
|
c78b36f2f7 | ||
|
|
bf669d5b18 | ||
|
|
083d0dd17e | ||
|
|
9e0d04fce2 | ||
|
|
14e57eb2fc | ||
|
|
8b3ddd2ecc | ||
|
|
e2e081c344 | ||
|
|
ec498ac053 | ||
|
|
452f26f28c | ||
|
|
644810a111 | ||
|
|
67e957ba0e | ||
|
|
7e2fc3a598 | ||
|
|
faa5b6eec4 | ||
|
|
ce64f5195f | ||
|
|
d8c42bf9ae | ||
|
|
e26c8c7c5c | ||
|
|
bedca15aec | ||
|
|
12ca47ad50 | ||
|
|
c3dadded51 | ||
|
|
7afbf28749 | ||
|
|
fc317cf851 | ||
|
|
3ab976f781 | ||
|
|
0a10a18875 | ||
|
|
62837eca9f | ||
|
|
ac5cc75533 | ||
|
|
ad8efd9da6 | ||
|
|
b3af4173c2 | ||
|
|
513fb7486a | ||
|
|
3abd6b7c1b | ||
|
|
b5f9e50e2a | ||
|
|
afc2cf5125 | ||
|
|
d086459d75 | ||
|
|
23b8f42e38 | ||
|
|
52525ff79f | ||
|
|
ecb72205af | ||
|
|
a1eafc4c61 | ||
|
|
79d0d405d3 | ||
|
|
d56669ff17 | ||
|
|
c51bf63c3e | ||
|
|
03900fe2d0 | ||
|
|
aa4b304f7a | ||
|
|
a7cb0f49b0 | ||
|
|
10c20702ee | ||
|
|
0e0f2cf6ad | ||
|
|
c87c62704c | ||
|
|
a71835f062 | ||
|
|
b56cab56bb | ||
|
|
385081b0bd | ||
|
|
60bee03c1a | ||
|
|
56936764b4 | ||
|
|
a7368bdb92 | ||
|
|
9ff3316a1a | ||
|
|
26d5b7b54d | ||
|
|
ee28782c7e | ||
|
|
d1009cb58c | ||
|
|
790a6105d1 | ||
|
|
ac77c9a04d | ||
|
|
7784d500a6 | ||
|
|
1679e685a5 | ||
|
|
1f6030f388 | ||
|
|
a8c94c69b3 | ||
|
|
f759be3623 | ||
|
|
16a19f1f6b | ||
|
|
1434a60d99 | ||
|
|
662928297f | ||
|
|
8e49dec9ed | ||
|
|
a6c845b287 | ||
|
|
d8a91a8838 | ||
|
|
d6d4504c8e | ||
|
|
2aba273fb1 | ||
|
|
cd01f9be94 | ||
|
|
024c033438 | ||
|
|
db6b6a8b02 | ||
|
|
355ef63780 | ||
|
|
d43419e2ea | ||
|
|
a3898ff2fb | ||
|
|
a342574576 | ||
|
|
3679bc5fb1 | ||
|
|
d695d15a34 | ||
|
|
6e1711f21c | ||
|
|
481a23b9a7 | ||
|
|
7f5b901386 | ||
|
|
4e4834e49f | ||
|
|
671b53f1ce | ||
|
|
4f99a88131 | ||
|
|
535fa09d69 | ||
|
|
11f59e99eb | ||
|
|
cc400c211a | ||
|
|
21d155584c | ||
|
|
ac9991b9cc | ||
|
|
e71f14a88e | ||
|
|
9e5ab966fa | ||
|
|
c621bd03f5 | ||
|
|
b2aef503ff | ||
|
|
57bd43a158 | ||
|
|
a7be71db69 | ||
|
|
94183c01c2 | ||
|
|
c54d13aa2f | ||
|
|
99b7003e09 | ||
|
|
037b2264b2 | ||
|
|
26a5690a4e | ||
|
|
960c43063a | ||
|
|
2e2908f909 | ||
|
|
e0adbdb222 | ||
|
|
98737de9ce | ||
|
|
8a1d37ca72 | ||
|
|
de85d3f4ad | ||
|
|
96c50a53f8 | ||
|
|
0ec5bb772a | ||
|
|
d404d5a1b9 | ||
|
|
41e5e4e5a2 | ||
|
|
0098b09bbc | ||
|
|
852cd2ce16 | ||
|
|
2b0315b56f | ||
|
|
a29c75e83a | ||
|
|
aeb979e059 | ||
|
|
bbec2b0c47 | ||
|
|
19012bc0a8 | ||
|
|
6cc1e3d6d9 | ||
|
|
9650197ffa | ||
|
|
241205063e | ||
|
|
a0d26dd2b5 | ||
|
|
9c081d0188 | ||
|
|
56228923bc | ||
|
|
8f92a3046f | ||
|
|
68b7600120 | ||
|
|
d89e33c9f9 | ||
|
|
17fdc97aac | ||
|
|
bbeddbca5f | ||
|
|
bf2eb3c854 | ||
|
|
025c1d9880 | ||
|
|
7d131cca9f | ||
|
|
be536c3c12 | ||
|
|
168f6cb964 | ||
|
|
365f00d4ee | ||
|
|
0f10193984 | ||
|
|
183a742929 | ||
|
|
513485f369 | ||
|
|
71e28848a1 | ||
|
|
3337ebb17e | ||
|
|
4b67b56afe | ||
|
|
3400d80b9c | ||
|
|
57c181c2ed | ||
|
|
5a1e330b58 | ||
|
|
885e4db2cd | ||
|
|
86e1b4207c | ||
|
|
953ff70651 | ||
|
|
1a23bb249d | ||
|
|
209224474e | ||
|
|
3351e596b7 | ||
|
|
5fa471ae07 | ||
|
|
fa746afad2 | ||
|
|
232ce81283 | ||
|
|
805d3cc9d2 | ||
|
|
ae80c6e986 | ||
|
|
60b5b5d39e | ||
|
|
b1b7d1039c | ||
|
|
32edd47edf | ||
|
|
5fc49d7f74 | ||
|
|
1fe987c8c2 | ||
|
|
fe75cdab0a | ||
|
|
4e28a3978a | ||
|
|
96f581d912 | ||
|
|
0ec234c7e4 | ||
|
|
4e5554d545 | ||
|
|
7a5f4fa203 | ||
|
|
60a888ad7c | ||
|
|
c6860e1e8a | ||
|
|
a66de4f52c | ||
|
|
be845fe67f | ||
|
|
b163854bce | ||
|
|
a9b07bbae1 | ||
|
|
f72ce81dd7 | ||
|
|
d0c836d5ba | ||
|
|
dcc2e35011 | ||
|
|
ad3d05cc12 | ||
|
|
c20b5a100d | ||
|
|
83d16d0e7a | ||
|
|
da91983628 | ||
|
|
cdde2bdfa7 | ||
|
|
a70008c7d8 | ||
|
|
a80af9e4a4 | ||
|
|
ece5e6042a | ||
|
|
8adde5a77b | ||
|
|
48a2f55e03 | ||
|
|
c53a1a1ec4 | ||
|
|
fcc15f55bc | ||
|
|
2defe16142 | ||
|
|
ac0a9260d0 | ||
|
|
06165207bd | ||
|
|
5582c7d752 | ||
|
|
1cf2363925 | ||
|
|
ca337f5e37 | ||
|
|
fbde0acbb6 | ||
|
|
e5f6435321 | ||
|
|
3862693d19 | ||
|
|
42168f2e97 | ||
|
|
ddf61a2bb3 | ||
|
|
b3d66d9e85 | ||
|
|
60ce24cc41 | ||
|
|
f9faf3a284 | ||
|
|
6e274c2d38 | ||
|
|
36785e3e4a | ||
|
|
25ed99486b | ||
|
|
d085013f6c | ||
|
|
b42836029f | ||
|
|
d6455cda90 | ||
|
|
214cc64027 | ||
|
|
9c6992d93a | ||
|
|
9caac25836 | ||
|
|
a404bce68e | ||
|
|
03cf431de7 | ||
|
|
e12b4119eb | ||
|
|
2b8429d895 | ||
|
|
ebec43f7b8 | ||
|
|
42f13d3822 | ||
|
|
bfeab36c73 | ||
|
|
850454462d | ||
|
|
f4acf736b6 | ||
|
|
31016c4b0a | ||
|
|
a8ec56d032 | ||
|
|
89f67ec8e4 | ||
|
|
a5e9095def | ||
|
|
f8cefec6e6 | ||
|
|
0f88be2b9b | ||
|
|
86aafc263e | ||
|
|
443afca29b | ||
|
|
afa6839a16 | ||
|
|
d153278b80 | ||
|
|
9c4c075b7f | ||
|
|
d0da856b00 | ||
|
|
e35e75b824 | ||
|
|
d5b0b6a345 | ||
|
|
0d7b1b887f | ||
|
|
3f924612e7 | ||
|
|
3e7e21ac32 | ||
|
|
9a2cd26f48 | ||
|
|
a07d2fad5b | ||
|
|
f1e5afdb3c | ||
|
|
577036f27f | ||
|
|
c6760010af | ||
|
|
668383c506 | ||
|
|
3f14b667d3 | ||
|
|
6837223d02 | ||
|
|
ef67d2b29d | ||
|
|
5bcbd9d68e | ||
|
|
39dededa26 | ||
|
|
0166fb2d09 | ||
|
|
bb777a15de | ||
|
|
09eeebda43 | ||
|
|
3db8380506 | ||
|
|
c82fda987d | ||
|
|
977224fca1 | ||
|
|
d5b7ac1670 | ||
|
|
12981aadf8 | ||
|
|
dfdb461ac5 | ||
|
|
9a47753af7 | ||
|
|
5240291080 | ||
|
|
af7dab48bb | ||
|
|
eceda412f8 | ||
|
|
1c87cc2f79 | ||
|
|
2500aa11a2 | ||
|
|
345adb5b1a | ||
|
|
0e7131563d | ||
|
|
7689f35834 | ||
|
|
89fcb14409 | ||
|
|
47e7539eae | ||
|
|
2c691e84a4 | ||
|
|
6ec9c27dd5 | ||
|
|
bea5a4aee3 | ||
|
|
a8cf2b81b5 | ||
|
|
7057769716 | ||
|
|
9c19412187 | ||
|
|
7d7380c460 | ||
|
|
858b1ad125 | ||
|
|
c60a2e65c1 | ||
|
|
6c5fa8a819 | ||
|
|
9d564f1bd6 | ||
|
|
d647d7616e | ||
|
|
b57cdae79d | ||
|
|
d98cea14c8 | ||
|
|
eb9460542e | ||
|
|
8d529ef70a | ||
|
|
b26a2d02ab | ||
|
|
f1cdea3729 | ||
|
|
0e6cd9224b | ||
|
|
e1d0b57f77 | ||
|
|
544bf4ecde | ||
|
|
97481e67a1 | ||
|
|
82f7420325 | ||
|
|
dfd2eb62e9 | ||
|
|
887061fc2e | ||
|
|
f54ab82112 | ||
|
|
573f8608e4 | ||
|
|
c3226113a1 | ||
|
|
bcc0773cd7 | ||
|
|
5bfddfb66a | ||
|
|
1d0df69964 |
No files matched your search
+15
@@ -0,0 +1,15 @@
|
||||
build-*
|
||||
*.swp
|
||||
*~
|
||||
tags
|
||||
TAGS
|
||||
local.mk
|
||||
target/*/tools/mkheader
|
||||
|
||||
# cscope files
|
||||
cscope.*
|
||||
ncscope.*
|
||||
|
||||
# temp work area
|
||||
tmp
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#Android makefile to build lk bootloader as a part of Android Build
|
||||
|
||||
TARGET_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
|
||||
BOOTLOADER_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/BOOTLOADER_OBJ
|
||||
|
||||
ifeq ($(call is-android-codename,HONEYCOMB),true)
|
||||
CROSS_TOOL := ../../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
|
||||
else
|
||||
CROSS_TOOL := ../../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
|
||||
endif
|
||||
|
||||
# Remove bootloader binary to trigger recompile when source changes
|
||||
appsbootldr_clean:
|
||||
$(hide) rm -f $(TARGET_BOOTLOADER)
|
||||
$(hide) rm -rf $(BOOTLOADER_OUT)
|
||||
|
||||
$(BOOTLOADER_OUT):
|
||||
mkdir -p $(BOOTLOADER_OUT)
|
||||
|
||||
|
||||
TARGET_EMMC := 0
|
||||
ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
|
||||
TARGET_EMMC := 1
|
||||
endif
|
||||
ifeq ($(TARGET_USERIMAGES_USE_EXT3),true)
|
||||
TARGET_EMMC := 1
|
||||
endif
|
||||
ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
|
||||
TARGET_EMMC := 1
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_BOOTIMG_SIGNED),true)
|
||||
SIGNED_KERNEL := SIGNED_KERNEL=1
|
||||
else
|
||||
SIGNED_KERNEL := SIGNED_KERNEL=0
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_EMMC),1)
|
||||
TARGET_BOOTLOADER_EMMC := $(PRODUCT_OUT)/EMMCBOOT.MBN
|
||||
BOOTLOADER_EMMC_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/BOOTLOADER_EMMC_OBJ
|
||||
|
||||
emmc_appsbootldr_clean:
|
||||
$(hide) rm -f $(TARGET_BOOTLOADER_EMMC)
|
||||
$(hide) rm -rf $(BOOTLOADER_EMMC_OUT)
|
||||
|
||||
$(BOOTLOADER_EMMC_OUT):
|
||||
mkdir -p $(BOOTLOADER_EMMC_OUT)
|
||||
|
||||
$(TARGET_BOOTLOADER): appsbootldr_clean emmc_appsbootldr_clean $(BOOTLOADER_OUT) $(BOOTLOADER_EMMC_OUT)
|
||||
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(BOOTLOADER_OUT) $(TARGET_PRODUCT) $(SIGNED_KERNEL)
|
||||
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(BOOTLOADER_EMMC_OUT) $(TARGET_PRODUCT) EMMC_BOOT=1 $(SIGNED_KERNEL)
|
||||
|
||||
else
|
||||
|
||||
$(TARGET_BOOTLOADER): appsbootldr_clean $(BOOTLOADER_OUT)
|
||||
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(BOOTLOADER_OUT) $(TARGET_PRODUCT) $(SIGNED_KERNEL)
|
||||
|
||||
endif
|
||||
|
||||
#build nandwrite as a part of Android Build
|
||||
TARGET_NANDWRITE := $(PRODUCT_OUT)/obj/nandwrite/build-$(TARGET_PRODUCT)_nandwrite/lk
|
||||
NANDWRITE_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/nandwrite
|
||||
|
||||
nandwrite_clean:
|
||||
$(hide) rm -f $(TARGET_NANDWRITE)
|
||||
$(hide) rm -rf $(NANDWRITE_OUT)
|
||||
|
||||
$(NANDWRITE_OUT):
|
||||
mkdir -p $(NANDWRITE_OUT)
|
||||
|
||||
$(TARGET_NANDWRITE): nandwrite_clean $(NANDWRITE_OUT)
|
||||
@echo $(TARGET_PRODUCT)_nandwrite
|
||||
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(NANDWRITE_OUT) $(TARGET_PRODUCT)_nandwrite BUILD_NANDWRITE=1
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
+1281
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_IMAGE_H_
|
||||
#define _BOOT_IMAGE_H_
|
||||
|
||||
typedef struct boot_img_hdr boot_img_hdr;
|
||||
|
||||
#define BOOT_MAGIC "ANDROID!"
|
||||
#define BOOT_MAGIC_SIZE 8
|
||||
#define BOOT_NAME_SIZE 16
|
||||
#define BOOT_ARGS_SIZE 512
|
||||
|
||||
struct boot_img_hdr
|
||||
{
|
||||
unsigned char magic[BOOT_MAGIC_SIZE];
|
||||
|
||||
unsigned kernel_size; /* size in bytes */
|
||||
unsigned kernel_addr; /* physical load addr */
|
||||
|
||||
unsigned ramdisk_size; /* size in bytes */
|
||||
unsigned ramdisk_addr; /* physical load addr */
|
||||
|
||||
unsigned second_size; /* size in bytes */
|
||||
unsigned second_addr; /* physical load addr */
|
||||
|
||||
unsigned tags_addr; /* physical addr for kernel tags */
|
||||
unsigned page_size; /* flash page size we assume */
|
||||
unsigned unused[2]; /* future expansion: should be 0 */
|
||||
|
||||
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
|
||||
unsigned char cmdline[BOOT_ARGS_SIZE];
|
||||
|
||||
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
|
||||
};
|
||||
|
||||
/*
|
||||
** +-----------------+
|
||||
** | boot header | 1 page
|
||||
** +-----------------+
|
||||
** | kernel | n pages
|
||||
** +-----------------+
|
||||
** | ramdisk | m pages
|
||||
** +-----------------+
|
||||
** | second stage | o pages
|
||||
** +-----------------+
|
||||
**
|
||||
** n = (kernel_size + page_size - 1) / page_size
|
||||
** m = (ramdisk_size + page_size - 1) / page_size
|
||||
** o = (second_size + page_size - 1) / page_size
|
||||
**
|
||||
** 0. all entities are page_size aligned in flash
|
||||
** 1. kernel and ramdisk are required (size != 0)
|
||||
** 2. second is optional (second_size == 0 -> no second)
|
||||
** 3. load each element (kernel, ramdisk, second) at
|
||||
** the specified physical address (kernel_addr, etc)
|
||||
** 4. prepare tags at tag_addr. kernel_args[] is
|
||||
** appended to the kernel commandline in the tags.
|
||||
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
|
||||
** 6. if second_size != 0: jump to second_addr
|
||||
** else: jump to kernel_addr
|
||||
*/
|
||||
|
||||
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
|
||||
void *ramdisk, unsigned ramdisk_size,
|
||||
void *second, unsigned second_size,
|
||||
unsigned page_size,
|
||||
unsigned *bootimg_size);
|
||||
|
||||
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DEVINFO_H_
|
||||
#define _DEVINFO_H_
|
||||
|
||||
typedef struct device_info device_info;
|
||||
|
||||
#define DEVICE_MAGIC "ANDROID-BOOT!"
|
||||
#define DEVICE_MAGIC_SIZE 13
|
||||
|
||||
struct device_info
|
||||
{
|
||||
unsigned char magic[DEVICE_MAGIC_SIZE];
|
||||
bool is_unlocked;
|
||||
bool is_tampered;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/event.h>
|
||||
#include <dev/udc.h>
|
||||
#include <target/gpiokeys.h>
|
||||
|
||||
#define MAX_RSP_SIZE 64
|
||||
|
||||
void boot_linux(void *bootimg, unsigned sz);
|
||||
|
||||
/* todo: give lk strtoul and nuke this */
|
||||
static unsigned hex2unsigned(const char *x)
|
||||
{
|
||||
unsigned n = 0;
|
||||
|
||||
while(*x) {
|
||||
switch(*x) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
n = (n << 4) | (*x - '0');
|
||||
break;
|
||||
case 'a': case 'b': case 'c':
|
||||
case 'd': case 'e': case 'f':
|
||||
n = (n << 4) | (*x - 'a' + 10);
|
||||
break;
|
||||
case 'A': case 'B': case 'C':
|
||||
case 'D': case 'E': case 'F':
|
||||
n = (n << 4) | (*x - 'A' + 10);
|
||||
break;
|
||||
default:
|
||||
return n;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
struct fastboot_cmd {
|
||||
struct fastboot_cmd *next;
|
||||
const char *prefix;
|
||||
unsigned prefix_len;
|
||||
void (*handle)(const char *arg, void *data, unsigned sz);
|
||||
};
|
||||
|
||||
struct fastboot_var {
|
||||
struct fastboot_var *next;
|
||||
const char *name;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
static struct fastboot_cmd *cmdlist;
|
||||
|
||||
void fastboot_register(const char *prefix,
|
||||
void (*handle)(const char *arg, void *data, unsigned sz))
|
||||
{
|
||||
struct fastboot_cmd *cmd;
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
if (cmd) {
|
||||
cmd->prefix = prefix;
|
||||
cmd->prefix_len = strlen(prefix);
|
||||
cmd->handle = handle;
|
||||
cmd->next = cmdlist;
|
||||
cmdlist = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
static struct fastboot_var *varlist;
|
||||
|
||||
void fastboot_publish(const char *name, const char *value)
|
||||
{
|
||||
struct fastboot_var *var;
|
||||
var = malloc(sizeof(*var));
|
||||
if (var) {
|
||||
var->name = name;
|
||||
var->value = value;
|
||||
var->next = varlist;
|
||||
varlist = var;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static event_t usb_online;
|
||||
static event_t txn_done;
|
||||
static unsigned char inbuffer[4096];
|
||||
static unsigned char outbuffer[4096];
|
||||
static unsigned char cmdbuffer[4096];
|
||||
static struct udc_endpoint *in, *out;
|
||||
static struct udc_request *req;
|
||||
int txn_status;
|
||||
|
||||
static void *download_base;
|
||||
static unsigned download_max;
|
||||
static unsigned download_size;
|
||||
|
||||
#define STATE_OFFLINE 0
|
||||
#define STATE_COMMAND 1
|
||||
#define STATE_COMPLETE 2
|
||||
#define STATE_ERROR 3
|
||||
|
||||
static unsigned fastboot_state = STATE_OFFLINE;
|
||||
|
||||
static void req_complete(struct udc_request *req, unsigned actual, int status)
|
||||
{
|
||||
txn_status = status;
|
||||
req->length = actual;
|
||||
event_signal(&txn_done, 0);
|
||||
}
|
||||
|
||||
static int usb_read(void *_buf, unsigned len)
|
||||
{
|
||||
int r;
|
||||
unsigned xfer;
|
||||
unsigned char *buf = _buf;
|
||||
int count = 0;
|
||||
|
||||
if (fastboot_state == STATE_ERROR)
|
||||
goto oops;
|
||||
|
||||
while (len > 0) {
|
||||
xfer = (len > 4096) ? 4096 : len;
|
||||
req->buf = buf;
|
||||
req->length = xfer;
|
||||
req->complete = req_complete;
|
||||
r = udc_request_queue(out, req);
|
||||
if (r < 0) {
|
||||
dprintf(INFO, "usb_read() queue failed\n");
|
||||
goto oops;
|
||||
}
|
||||
event_wait(&txn_done);
|
||||
|
||||
if (txn_status < 0) {
|
||||
dprintf(INFO, "usb_read() transaction failed\n");
|
||||
goto oops;
|
||||
}
|
||||
|
||||
count += req->length;
|
||||
buf += req->length;
|
||||
len -= req->length;
|
||||
|
||||
/* short transfer? */
|
||||
if (req->length != xfer) break;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
oops:
|
||||
fastboot_state = STATE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int usb_write(void *buf, unsigned len)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (fastboot_state == STATE_ERROR)
|
||||
goto oops;
|
||||
|
||||
req->buf = buf;
|
||||
req->length = len;
|
||||
req->complete = req_complete;
|
||||
r = udc_request_queue(in, req);
|
||||
if (r < 0) {
|
||||
dprintf(INFO, "usb_write() queue failed\n");
|
||||
goto oops;
|
||||
}
|
||||
event_wait(&txn_done);
|
||||
if (txn_status < 0) {
|
||||
dprintf(INFO, "usb_write() transaction failed\n");
|
||||
goto oops;
|
||||
}
|
||||
return req->length;
|
||||
|
||||
oops:
|
||||
fastboot_state = STATE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void fastboot_ack(const char *code, const char *reason)
|
||||
{
|
||||
char response[MAX_RSP_SIZE];
|
||||
|
||||
if (fastboot_state != STATE_COMMAND)
|
||||
return;
|
||||
|
||||
if (reason == 0)
|
||||
reason = "";
|
||||
|
||||
snprintf(response, MAX_RSP_SIZE, "%s%s", code, reason);
|
||||
fastboot_state = STATE_COMPLETE;
|
||||
|
||||
usb_write(response, strlen(response));
|
||||
|
||||
}
|
||||
|
||||
void fastboot_info(const char *reason)
|
||||
{
|
||||
char response[MAX_RSP_SIZE];
|
||||
|
||||
if (fastboot_state != STATE_COMMAND)
|
||||
return;
|
||||
|
||||
if (reason == 0)
|
||||
return;
|
||||
|
||||
snprintf(response, MAX_RSP_SIZE, "INFO%s", reason);
|
||||
|
||||
usb_write(response, strlen(response));
|
||||
}
|
||||
|
||||
void fastboot_fail(const char *reason)
|
||||
{
|
||||
fastboot_ack("FAIL", reason);
|
||||
}
|
||||
|
||||
void fastboot_okay(const char *info)
|
||||
{
|
||||
fastboot_ack("OKAY", info);
|
||||
}
|
||||
|
||||
static void cmd_getvar(const char *arg, void *data, unsigned sz)
|
||||
{
|
||||
struct fastboot_var *var;
|
||||
|
||||
for (var = varlist; var; var = var->next) {
|
||||
if (!strcmp(var->name, arg)) {
|
||||
fastboot_okay(var->value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fastboot_okay("");
|
||||
}
|
||||
|
||||
static void cmd_download(const char *arg, void *data, unsigned sz)
|
||||
{
|
||||
char response[MAX_RSP_SIZE];
|
||||
unsigned len = hex2unsigned(arg);
|
||||
int r;
|
||||
|
||||
download_size = 0;
|
||||
if (len > download_max) {
|
||||
fastboot_fail("data too large");
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(response,"DATA%08x", len);
|
||||
if (usb_write(response, strlen(response)) < 0)
|
||||
return;
|
||||
|
||||
r = usb_read(download_base, len);
|
||||
if ((r < 0) || ((unsigned) r != len)) {
|
||||
fastboot_state = STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
download_size = len;
|
||||
fastboot_okay("");
|
||||
}
|
||||
|
||||
static void cmd_getkeys(const char *arg, void *data, unsigned sz)
|
||||
{
|
||||
int res = gpiokeys_poll(KEY_ALL);
|
||||
|
||||
dprintf(ALWAYS, "KEYS: VolUp: %u VolDn: %u Center: %u\n",
|
||||
(res & KEY_UP) ? 1 : 0,
|
||||
(res & KEY_DOWN) ? 1 : 0,
|
||||
(res & KEY_SELECT) ? 1 : 0);
|
||||
|
||||
fastboot_state = STATE_COMPLETE;
|
||||
}
|
||||
|
||||
static void fastboot_command_loop(void)
|
||||
{
|
||||
struct fastboot_cmd *cmd;
|
||||
unsigned cmdlen = 0;
|
||||
unsigned outlen = 0;
|
||||
unsigned showprompt = 1;
|
||||
unsigned cmdready = 0;
|
||||
char prompt[] = "fastboot: ";
|
||||
int r;
|
||||
dprintf(INFO,"fastboot: processing commands\n");
|
||||
|
||||
again:
|
||||
cmdbuffer[0] = 0;
|
||||
cmdlen = 0;
|
||||
cmdready = 0;
|
||||
while (fastboot_state != STATE_ERROR) {
|
||||
if (showprompt == 1) {
|
||||
showprompt = 0;
|
||||
r = usb_write(prompt, strlen(prompt));
|
||||
if (r <0) goto fail;
|
||||
}
|
||||
r = usb_read(inbuffer, MAX_RSP_SIZE);
|
||||
if (r < 0) break;
|
||||
|
||||
outlen = 0;
|
||||
for (unsigned i = 0; i < r; i++) {
|
||||
if (inbuffer[i] == '\b') {
|
||||
if (cmdlen > 0) {
|
||||
outbuffer[outlen++] = '\b';
|
||||
outbuffer[outlen++] = ' ';
|
||||
outbuffer[outlen++] = '\b';
|
||||
cmdlen--;
|
||||
}
|
||||
} else if (inbuffer[i] == '\003') {
|
||||
outbuffer[outlen++] = '^';
|
||||
outbuffer[outlen++] = 'C';
|
||||
outbuffer[outlen++] = '\r';
|
||||
outbuffer[outlen++] = '\n';
|
||||
cmdlen = 0;
|
||||
showprompt = 1;
|
||||
} else if (inbuffer[i] == '\r') {
|
||||
outbuffer[outlen++] = '\r';
|
||||
outbuffer[outlen++] = '\n';
|
||||
cmdbuffer[cmdlen++] = 0;
|
||||
/*
|
||||
for (unsigned j = 0; (i + j) < r; j++) {
|
||||
cmdbuffer[cmdlen++] = inbuffer[i+j];
|
||||
}
|
||||
*/
|
||||
cmdready = 1;
|
||||
} else {
|
||||
cmdbuffer[cmdlen++] = inbuffer[i];
|
||||
outbuffer[outlen++] = inbuffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (outlen > 0) {
|
||||
outbuffer[outlen] = 0;
|
||||
r = usb_write(outbuffer, strlen(outbuffer));
|
||||
if (r <0) break;
|
||||
}
|
||||
|
||||
if (cmdready) showprompt = 1;
|
||||
|
||||
if (cmdready && cmdlen > 0) {
|
||||
dprintf(INFO, "CMD: %s\n", cmdbuffer);
|
||||
for (cmd = cmdlist; cmd; cmd = cmd->next) {
|
||||
if (memcmp(cmdbuffer, cmd->prefix, cmd->prefix_len))
|
||||
continue;
|
||||
fastboot_state = STATE_COMMAND;
|
||||
cmd->handle((const char*) cmdbuffer + cmd->prefix_len,
|
||||
(void*) download_base, download_size);
|
||||
if (fastboot_state == STATE_COMMAND) {
|
||||
dprintf(ALWAYS, "unknown failure\n");
|
||||
// fastboot_fail("unknown reason");
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
dprintf(ALWAYS, "unknown command\n");
|
||||
// fastboot_fail("unknown command");
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
fail:
|
||||
fastboot_state = STATE_OFFLINE;
|
||||
dprintf(INFO,"fastboot: oops!\n");
|
||||
}
|
||||
|
||||
static int fastboot_handler(void *arg)
|
||||
{
|
||||
for (;;) {
|
||||
event_wait(&usb_online);
|
||||
fastboot_command_loop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
|
||||
{
|
||||
if (event == UDC_EVENT_ONLINE) {
|
||||
event_signal(&usb_online, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static struct udc_endpoint *fastboot_endpoints[2];
|
||||
|
||||
static struct udc_gadget fastboot_gadget = {
|
||||
.notify = fastboot_notify,
|
||||
.ifc_class = 0xff,
|
||||
.ifc_subclass = 0x42,
|
||||
.ifc_protocol = 0x03,
|
||||
.ifc_endpoints = 2,
|
||||
.ifc_string = "fastboot",
|
||||
.ept = fastboot_endpoints,
|
||||
};
|
||||
|
||||
int fastboot_init(void *base, unsigned size)
|
||||
{
|
||||
thread_t *thr;
|
||||
dprintf(INFO, "fastboot_init()\n");
|
||||
|
||||
download_base = base;
|
||||
download_max = size;
|
||||
|
||||
event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
|
||||
in = udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
|
||||
if (!in)
|
||||
goto fail_alloc_in;
|
||||
out = udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
|
||||
if (!out)
|
||||
goto fail_alloc_out;
|
||||
|
||||
fastboot_endpoints[0] = in;
|
||||
fastboot_endpoints[1] = out;
|
||||
|
||||
req = udc_request_alloc();
|
||||
if (!req)
|
||||
goto fail_alloc_req;
|
||||
|
||||
if (udc_register_gadget(&fastboot_gadget))
|
||||
goto fail_udc_register;
|
||||
|
||||
fastboot_register("getkeys:", cmd_getkeys);
|
||||
fastboot_register("getvar:", cmd_getvar);
|
||||
fastboot_register("download:", cmd_download);
|
||||
fastboot_publish("version", "0.5");
|
||||
|
||||
thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
|
||||
thread_resume(thr);
|
||||
return 0;
|
||||
|
||||
fail_udc_register:
|
||||
udc_request_free(req);
|
||||
fail_alloc_req:
|
||||
udc_endpoint_free(out);
|
||||
fail_alloc_out:
|
||||
udc_endpoint_free(in);
|
||||
fail_alloc_in:
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __APP_FASTBOOT_H
|
||||
#define __APP_FASTBOOT_H
|
||||
|
||||
int fastboot_init(void *xfer_buffer, unsigned max);
|
||||
|
||||
/* register a command handler
|
||||
* - command handlers will be called if their prefix matches
|
||||
* - they are expected to call fastboot_okay() or fastboot_fail()
|
||||
* to indicate success/failure before returning
|
||||
*/
|
||||
void fastboot_register(const char *prefix,
|
||||
void (*handle)(const char *arg, void *data, unsigned size));
|
||||
|
||||
/* publish a variable readable by the built-in getvar command */
|
||||
void fastboot_publish(const char *name, const char *value);
|
||||
|
||||
/* only callable from within a command handler */
|
||||
void fastboot_okay(const char *result);
|
||||
void fastboot_fail(const char *reason);
|
||||
void fastboot_info(const char *reason);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,468 @@
|
||||
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <arch/arm.h>
|
||||
#include <dev/udc.h>
|
||||
#include <string.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <arch/ops.h>
|
||||
|
||||
#include <dev/flash.h>
|
||||
#include <lib/ptable.h>
|
||||
#include <dev/keys.h>
|
||||
#include <platform.h>
|
||||
#include <partition_parser.h>
|
||||
#include <mmc.h>
|
||||
|
||||
#include "recovery.h"
|
||||
#include "bootimg.h"
|
||||
#include "smem.h"
|
||||
|
||||
#define BOOT_FLAGS 1
|
||||
#define UPDATE_STATUS 2
|
||||
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
|
||||
|
||||
static const int MISC_PAGES = 3; // number of pages to save
|
||||
static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
|
||||
static char buf[4096];
|
||||
unsigned boot_into_recovery = 0;
|
||||
|
||||
extern void reset_device_info();
|
||||
extern void set_device_root();
|
||||
|
||||
int get_recovery_message(struct recovery_message *out)
|
||||
{
|
||||
struct ptentry *ptn;
|
||||
struct ptable *ptable;
|
||||
unsigned offset = 0;
|
||||
unsigned pagesize = flash_page_size();
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
|
||||
if (ptable == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: Partition table not found\n");
|
||||
return -1;
|
||||
}
|
||||
ptn = ptable_find(ptable, "misc");
|
||||
|
||||
if (ptn == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: No misc partition found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += (pagesize * MISC_COMMAND_PAGE);
|
||||
if (flash_read(ptn, offset, (void *) buf, pagesize)) {
|
||||
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(out, buf, sizeof(*out));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_recovery_message(const struct recovery_message *in)
|
||||
{
|
||||
struct ptentry *ptn;
|
||||
struct ptable *ptable;
|
||||
unsigned offset = 0;
|
||||
unsigned pagesize = flash_page_size();
|
||||
unsigned n = 0;
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
|
||||
if (ptable == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: Partition table not found\n");
|
||||
return -1;
|
||||
}
|
||||
ptn = ptable_find(ptable, "misc");
|
||||
|
||||
if (ptn == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: No misc partition found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = pagesize * (MISC_COMMAND_PAGE + 1);
|
||||
|
||||
if (flash_read(ptn, offset, (void *) SCRATCH_ADDR, n)) {
|
||||
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += (pagesize * MISC_COMMAND_PAGE);
|
||||
offset += SCRATCH_ADDR;
|
||||
memcpy((void *) offset, in, sizeof(*in));
|
||||
if (flash_write(ptn, 0, (void *)SCRATCH_ADDR, n)) {
|
||||
dprintf(CRITICAL, "ERROR: flash write fail!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_update_header_for_bootloader(struct update_header *header)
|
||||
{
|
||||
struct ptentry *ptn;
|
||||
struct ptable *ptable;
|
||||
unsigned offset = 0;
|
||||
unsigned pagesize = flash_page_size();
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
if (ptable == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: Partition table not found\n");
|
||||
return -1;
|
||||
}
|
||||
ptn = ptable_find(ptable, "cache");
|
||||
|
||||
if (ptn == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: No cache partition found\n");
|
||||
return -1;
|
||||
}
|
||||
if (flash_read(ptn, offset, buf, pagesize)) {
|
||||
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(header, buf, sizeof(*header));
|
||||
|
||||
if (strncmp((char *) header->MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update_firmware_image (struct update_header *header, char *name)
|
||||
{
|
||||
struct ptentry *ptn;
|
||||
struct ptable *ptable;
|
||||
unsigned offset = 0;
|
||||
unsigned pagesize = flash_page_size();
|
||||
unsigned pagemask = pagesize -1;
|
||||
unsigned n = 0;
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
if (ptable == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: Partition table not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptn = ptable_find(ptable, "cache");
|
||||
if (ptn == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: No cache partition found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += header->image_offset;
|
||||
n = (header->image_length + pagemask) & (~pagemask);
|
||||
|
||||
if (flash_read(ptn, offset, (void *) SCRATCH_ADDR, n)) {
|
||||
dprintf(CRITICAL, "ERROR: Cannot read radio image\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptn = ptable_find(ptable, name);
|
||||
if (ptn == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flash_write(ptn, 0, (void *) SCRATCH_ADDR, n)) {
|
||||
dprintf(CRITICAL, "ERROR: flash write fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dprintf(INFO, "Partition writen successfully!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssd_radio_update (char *name)
|
||||
{
|
||||
struct ptentry *ptn;
|
||||
struct ptable *ptable;
|
||||
unsigned int ssd_cookie[2] = {0x53534443, 0x4F4F4B49};
|
||||
unsigned pagesize = flash_page_size();
|
||||
unsigned pagemask = pagesize -1;
|
||||
unsigned n = 0;
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
if (ptable == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: Partition table not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = (sizeof(ssd_cookie) + pagemask) & (~pagemask);
|
||||
|
||||
ptn = ptable_find(ptable, name);
|
||||
if (ptn == NULL) {
|
||||
dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flash_write(ptn, 0, ssd_cookie, n)) {
|
||||
dprintf(CRITICAL, "ERROR: flash write fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dprintf(INFO, "FOTA partition written successfully!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_boot_info_apps (char type, unsigned int *status)
|
||||
{
|
||||
boot_info_for_apps apps_boot_info;
|
||||
int ret = 0;
|
||||
|
||||
ret = smem_read_alloc_entry(SMEM_BOOT_INFO_FOR_APPS,
|
||||
&apps_boot_info, sizeof(apps_boot_info));
|
||||
if (ret)
|
||||
{
|
||||
dprintf(CRITICAL, "ERROR: unable to read shared memory for apps boot info %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dprintf(INFO,"boot flag %x update status %x\n",apps_boot_info.boot_flags,
|
||||
apps_boot_info.status.update_status);
|
||||
|
||||
if(type == BOOT_FLAGS)
|
||||
*status = apps_boot_info.boot_flags;
|
||||
else if(type == UPDATE_STATUS)
|
||||
*status = apps_boot_info.status.update_status;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Bootloader / Recovery Flow
|
||||
*
|
||||
* On every boot, the bootloader will read the recovery_message
|
||||
* from flash and check the command field. The bootloader should
|
||||
* deal with the command field not having a 0 terminator correctly
|
||||
* (so as to not crash if the block is invalid or corrupt).
|
||||
*
|
||||
* The bootloader will have to publish the partition that contains
|
||||
* the recovery_message to the linux kernel so it can update it.
|
||||
*
|
||||
* if command == "boot-recovery" -> boot recovery.img
|
||||
* else if command == "update-radio" -> update radio image (below)
|
||||
* else -> boot boot.img (normal boot)
|
||||
*
|
||||
* Radio Update Flow
|
||||
* 1. the bootloader will attempt to load and validate the header
|
||||
* 2. if the header is invalid, status="invalid-update", goto #8
|
||||
* 3. display the busy image on-screen
|
||||
* 4. if the update image is invalid, status="invalid-radio-image", goto #8
|
||||
* 5. attempt to update the firmware (depending on the command)
|
||||
* 6. if successful, status="okay", goto #8
|
||||
* 7. if failed, and the old image can still boot, status="failed-update"
|
||||
* 8. write the recovery_message, leaving the recovery field
|
||||
* unchanged, updating status, and setting command to
|
||||
* "boot-recovery"
|
||||
* 9. reboot
|
||||
*
|
||||
* The bootloader will not modify or erase the cache partition.
|
||||
* It is recovery's responsibility to clean up the mess afterwards.
|
||||
*/
|
||||
|
||||
int recovery_init (void)
|
||||
{
|
||||
struct recovery_message msg;
|
||||
char partition_name[32];
|
||||
unsigned valid_command = 0;
|
||||
int update_status = 0;
|
||||
|
||||
// get recovery message
|
||||
if (get_recovery_message(&msg))
|
||||
return -1;
|
||||
if (msg.command[0] != 0 && msg.command[0] != 255) {
|
||||
dprintf(INFO, "Recovery command: %.*s\n", sizeof(msg.command), msg.command);
|
||||
}
|
||||
msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
|
||||
|
||||
if (!strcmp("boot-recovery",msg.command))
|
||||
{
|
||||
if(!strcmp("RADIO",msg.status))
|
||||
{
|
||||
/* We're now here due to radio update, so check for update status */
|
||||
int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
|
||||
|
||||
if(!ret && (update_status & 0x01))
|
||||
{
|
||||
dprintf(INFO,"radio update success\n");
|
||||
strcpy(msg.status, "OKAY");
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(INFO,"radio update failed\n");
|
||||
strcpy(msg.status, "failed-update");
|
||||
}
|
||||
strcpy(msg.command, ""); // clearing recovery command
|
||||
set_recovery_message(&msg); // send recovery message
|
||||
boot_into_recovery = 1; // Boot in recovery mode
|
||||
return 0;
|
||||
}
|
||||
|
||||
valid_command = 1;
|
||||
strcpy(msg.command, ""); // to safe against multiple reboot into recovery
|
||||
strcpy(msg.status, "OKAY");
|
||||
set_recovery_message(&msg); // send recovery message
|
||||
boot_into_recovery = 1; // Boot in recovery mode
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp("update-radio",msg.command)) {
|
||||
dprintf(INFO,"start radio update\n");
|
||||
valid_command = 1;
|
||||
strcpy(partition_name, "FOTA");
|
||||
}
|
||||
|
||||
//Todo: Add support for bootloader update too.
|
||||
|
||||
if(!valid_command) {
|
||||
//We need not to do anything
|
||||
return 0; // Boot in normal mode
|
||||
}
|
||||
|
||||
#ifdef OLD_FOTA_UPGRADE
|
||||
if (read_update_header_for_bootloader(&header)) {
|
||||
strcpy(msg.status, "invalid-update");
|
||||
goto SEND_RECOVERY_MSG;
|
||||
}
|
||||
|
||||
if (update_firmware_image (&header, partition_name)) {
|
||||
strcpy(msg.status, "failed-update");
|
||||
goto SEND_RECOVERY_MSG;
|
||||
}
|
||||
#else
|
||||
if (set_ssd_radio_update(partition_name)) {
|
||||
/* If writing to FOTA partition fails */
|
||||
strcpy(msg.command, "");
|
||||
strcpy(msg.status, "failed-update");
|
||||
goto SEND_RECOVERY_MSG;
|
||||
}
|
||||
else {
|
||||
/* Setting this to check the radio update status */
|
||||
strcpy(msg.command, "boot-recovery");
|
||||
strcpy(msg.status, "RADIO");
|
||||
goto SEND_RECOVERY_MSG;
|
||||
}
|
||||
#endif
|
||||
strcpy(msg.status, "OKAY");
|
||||
|
||||
SEND_RECOVERY_MSG:
|
||||
set_recovery_message(&msg); // send recovery message
|
||||
boot_into_recovery = 1; // Boot in recovery mode
|
||||
reboot_device(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emmc_set_recovery_msg(struct recovery_message *out)
|
||||
{
|
||||
char *ptn_name = "misc";
|
||||
unsigned long long ptn = 0;
|
||||
unsigned int size = ROUND_TO_PAGE(sizeof(*out),511);
|
||||
unsigned char data[size];
|
||||
int index = INVALID_PTN;
|
||||
|
||||
index = partition_get_index((unsigned char *) ptn_name);
|
||||
ptn = partition_get_offset(index);
|
||||
if(ptn == 0) {
|
||||
dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, out, sizeof(*out));
|
||||
if (mmc_write(ptn , size, (unsigned int*)data)) {
|
||||
dprintf(CRITICAL,"mmc write failure %s %d\n",ptn_name, sizeof(*out));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emmc_get_recovery_msg(struct recovery_message *in)
|
||||
{
|
||||
char *ptn_name = "misc";
|
||||
unsigned long long ptn = 0;
|
||||
unsigned int size = ROUND_TO_PAGE(sizeof(*in),511);
|
||||
unsigned char data[size];
|
||||
int index = INVALID_PTN;
|
||||
|
||||
index = partition_get_index((unsigned char *) ptn_name);
|
||||
ptn = partition_get_offset(index);
|
||||
if(ptn == 0) {
|
||||
dprintf(CRITICAL,"partition %s doesn't exist\n",ptn_name);
|
||||
return -1;
|
||||
}
|
||||
if (mmc_read(ptn , (unsigned int*)data, size)) {
|
||||
dprintf(CRITICAL,"mmc read failure %s %d\n",ptn_name, size);
|
||||
return -1;
|
||||
}
|
||||
memcpy(in, data, sizeof(*in));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _emmc_recovery_init(void)
|
||||
{
|
||||
int update_status = 0;
|
||||
struct recovery_message msg;
|
||||
|
||||
// get recovery message
|
||||
if(emmc_get_recovery_msg(&msg))
|
||||
return -1;
|
||||
if (msg.command[0] != 0 && msg.command[0] != 255) {
|
||||
dprintf(INFO,"Recovery command: %d %s\n", sizeof(msg.command), msg.command);
|
||||
}
|
||||
msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
|
||||
|
||||
if (!strcmp("update-radio",msg.command))
|
||||
{
|
||||
/* We're now here due to radio update, so check for update status */
|
||||
int ret = get_boot_info_apps(UPDATE_STATUS, (unsigned int *) &update_status);
|
||||
|
||||
if(!ret && (update_status & 0x01))
|
||||
{
|
||||
dprintf(INFO,"radio update success\n");
|
||||
strcpy(msg.status, "OKAY");
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(INFO,"radio update failed\n");
|
||||
strcpy(msg.status, "failed-update");
|
||||
}
|
||||
boot_into_recovery = 1; // Boot in recovery mode
|
||||
}
|
||||
if (!strcmp("reset-device-info",msg.command))
|
||||
{
|
||||
reset_device_info();
|
||||
}
|
||||
if (!strcmp("root-detect",msg.command))
|
||||
{
|
||||
set_device_root();
|
||||
}
|
||||
else
|
||||
return 0; // do nothing
|
||||
|
||||
strcpy(msg.command, ""); // clearing recovery command
|
||||
emmc_set_recovery_msg(&msg); // send recovery message
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BOOTLOADER_RECOVERY_H
|
||||
#define _BOOTLOADER_RECOVERY_H
|
||||
|
||||
#define UPDATE_MAGIC "MSM-RADIO-UPDATE"
|
||||
#define UPDATE_MAGIC_SIZE 16
|
||||
#define UPDATE_VERSION 0x00010000
|
||||
|
||||
|
||||
/* Recovery Message */
|
||||
struct recovery_message {
|
||||
char command[32];
|
||||
char status[32];
|
||||
char recovery[1024];
|
||||
};
|
||||
|
||||
|
||||
struct update_header {
|
||||
unsigned char MAGIC[UPDATE_MAGIC_SIZE];
|
||||
|
||||
unsigned version;
|
||||
unsigned size;
|
||||
|
||||
unsigned image_offset;
|
||||
unsigned image_length;
|
||||
|
||||
unsigned bitmap_width;
|
||||
unsigned bitmap_height;
|
||||
unsigned bitmap_bpp;
|
||||
|
||||
unsigned busy_bitmap_offset;
|
||||
unsigned busy_bitmap_length;
|
||||
|
||||
unsigned fail_bitmap_offset;
|
||||
unsigned fail_bitmap_length;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int get_recovery_message(struct recovery_message *out);
|
||||
int set_recovery_message(const struct recovery_message *in);
|
||||
|
||||
int read_update_header_for_bootloader(struct update_header *header);
|
||||
int update_firmware_image (struct update_header *header, char *name);
|
||||
|
||||
int recovery_init (void);
|
||||
|
||||
extern unsigned boot_into_recovery;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LK_TOP_DIR)/platform/msm_shared/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/aboot.o \
|
||||
$(LOCAL_DIR)/fastboot.o \
|
||||
$(LOCAL_DIR)/recovery.o
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
typedef struct sparse_header {
|
||||
uint32_t magic; /* 0xed26ff3a */
|
||||
uint16_t major_version; /* (0x1) - reject images with higher major versions */
|
||||
uint16_t minor_version; /* (0x0) - allow images with higer minor versions */
|
||||
uint16_t file_hdr_sz; /* 28 bytes for first revision of the file format */
|
||||
uint16_t chunk_hdr_sz; /* 12 bytes for first revision of the file format */
|
||||
uint32_t blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
|
||||
uint32_t total_blks; /* total blocks in the non-sparse output image */
|
||||
uint32_t total_chunks; /* total chunks in the sparse input image */
|
||||
uint32_t image_checksum; /* CRC32 checksum of the original data, counting "don't care" */
|
||||
/* as 0. Standard 802.3 polynomial, use a Public Domain */
|
||||
/* table implementation */
|
||||
} sparse_header_t;
|
||||
|
||||
#define SPARSE_HEADER_MAGIC 0xed26ff3a
|
||||
|
||||
#define CHUNK_TYPE_RAW 0xCAC1
|
||||
#define CHUNK_TYPE_FILL 0xCAC2
|
||||
#define CHUNK_TYPE_DONT_CARE 0xCAC3
|
||||
#define CHUNK_TYPE_CRC 0xCAC4
|
||||
|
||||
typedef struct chunk_header {
|
||||
uint16_t chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
|
||||
uint16_t reserved1;
|
||||
uint32_t chunk_sz; /* in blocks in output image */
|
||||
uint32_t total_sz; /* in bytes of chunk input file including chunk header and data */
|
||||
} chunk_header_t;
|
||||
|
||||
/* Following a Raw or Fill chunk is data. For a Raw chunk, it's the data in chunk_sz * blk_sz.
|
||||
* For a Fill chunk, it's 4 bytes of the fill data.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <app.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
extern const struct app_descriptor __apps_start;
|
||||
extern const struct app_descriptor __apps_end;
|
||||
|
||||
static void start_app(const struct app_descriptor *app);
|
||||
|
||||
/* one time setup */
|
||||
void apps_init(void)
|
||||
{
|
||||
const struct app_descriptor *app;
|
||||
|
||||
/* call all the init routines */
|
||||
for (app = &__apps_start; app != &__apps_end; app++) {
|
||||
if (app->init)
|
||||
app->init(app);
|
||||
}
|
||||
|
||||
/* start any that want to start on boot */
|
||||
for (app = &__apps_start; app != &__apps_end; app++) {
|
||||
if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
|
||||
start_app(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int app_thread_entry(void *arg)
|
||||
{
|
||||
const struct app_descriptor *app = (const struct app_descriptor *)arg;
|
||||
|
||||
app->entry(app, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void start_app(const struct app_descriptor *app)
|
||||
{
|
||||
printf("starting app %s\n", app->name);
|
||||
|
||||
thread_resume(thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2011, James Sullins
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
* Copyright (c) 2011, James Sullins
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <app.h>
|
||||
#include <debug.h>
|
||||
#include <target/gpiokeys.h>
|
||||
#include <target/restart.h>
|
||||
#include <dev/fbcon.h>
|
||||
#include <dev/display.h>
|
||||
#include <sys/types.h>
|
||||
#include <lib/fs.h>
|
||||
#include <lib/tga.h>
|
||||
#include <lib/gfxconsole.h>
|
||||
#include <lib/bootlinux.h>
|
||||
|
||||
typedef struct menu_entry
|
||||
{
|
||||
char *title;
|
||||
unsigned type;
|
||||
char *arg;
|
||||
char *name;
|
||||
} menu_entry_t;
|
||||
|
||||
unsigned num_menu_entries;
|
||||
menu_entry_t **entries;
|
||||
|
||||
gfx_surface *display_surface;
|
||||
gfx_surface *splash_surface;
|
||||
gfx_surface *background_surface;
|
||||
gfx_surface *tile_surface;
|
||||
|
||||
unsigned gfx_trans;
|
||||
|
||||
#define BOOT_FS 1
|
||||
#define BOOT_REBOOT 2
|
||||
#define BOOT_RECOVER 3
|
||||
#define BOOT_SHUTDOWN 4
|
||||
#define BOOT_DFU 5
|
||||
|
||||
void boot_splash()
|
||||
{
|
||||
unsigned splash_pos_x, splash_pos_y;
|
||||
|
||||
if (splash_surface) {
|
||||
if (splash_surface->width > display_surface->width ||
|
||||
splash_surface->height > display_surface->height) {
|
||||
printf("ERROR: Splash image will not fit on display!\n");
|
||||
return;
|
||||
}
|
||||
gfxconsole_clear();
|
||||
splash_pos_x = (display_surface->width - splash_surface->width) / 2;
|
||||
splash_pos_y = (display_surface->height - splash_surface->height) / 2;
|
||||
gfx_surface_blend(display_surface, splash_surface, splash_pos_x,
|
||||
splash_pos_y);
|
||||
}
|
||||
}
|
||||
|
||||
void show_background()
|
||||
{
|
||||
unsigned pos_x, pos_y;
|
||||
|
||||
if (background_surface) {
|
||||
if (background_surface->width > display_surface->width ||
|
||||
background_surface->height > display_surface->height) {
|
||||
printf("ERROR: Background image will not fit on display!\n");
|
||||
return;
|
||||
}
|
||||
gfxconsole_clear();
|
||||
pos_x = (display_surface->width - background_surface->width) / 2;
|
||||
pos_y = (display_surface->height - background_surface->height) / 2;
|
||||
gfx_surface_blend(display_surface, background_surface, pos_x,
|
||||
pos_y);
|
||||
}
|
||||
}
|
||||
|
||||
int moboot_menu(unsigned x, unsigned y, menu_entry_t **entries, unsigned init, unsigned total, unsigned timeout)
|
||||
{
|
||||
unsigned curpos, i, max, keys, is_pressed, has_timeout, countdown;
|
||||
time_t tick;
|
||||
unsigned wiggle_count = 0;
|
||||
|
||||
max = total - 1;
|
||||
curpos = init;
|
||||
|
||||
if (timeout) {
|
||||
has_timeout = 1;
|
||||
countdown = timeout;
|
||||
tick = current_time() + 1000;
|
||||
} else {
|
||||
has_timeout = 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < total; i++) {
|
||||
gfxconsole_setpos(x, y + i);
|
||||
if (i == curpos) {
|
||||
if (tile_surface) {
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
printf("%s", entries[i]->title);
|
||||
gfxconsole_set_colors(0x00000000, 0x00000000);
|
||||
} else {
|
||||
gfxconsole_set_colors(0x000000ff, 0x00000000);
|
||||
printf("%s", entries[i]->title);
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
}
|
||||
} else {
|
||||
if (tile_surface) {
|
||||
gfxconsole_set_colors(0x00000000, 0x00000000);
|
||||
printf("%s", entries[i]->title);
|
||||
} else {
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
printf("%s", entries[i]->title);
|
||||
}
|
||||
}
|
||||
}
|
||||
is_pressed = gpiokeys_poll(KEY_ALL);
|
||||
while (1) {
|
||||
if (has_timeout) {
|
||||
if (current_time() > tick) {
|
||||
tick += 1000;
|
||||
countdown--;
|
||||
if (!countdown) {
|
||||
return curpos;
|
||||
}
|
||||
}
|
||||
gfxconsole_setpos(x, y + total + 1);
|
||||
if (tile_surface) {
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
} else {
|
||||
gfxconsole_set_colors(0x00000000, 0x00ff0000);
|
||||
}
|
||||
printf("timeout in %d ", countdown);
|
||||
if (tile_surface) {
|
||||
gfxconsole_set_colors(0x00000000, 0x00000000);
|
||||
} else {
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
thread_sleep(10);
|
||||
keys = gpiokeys_poll(KEY_ALL);
|
||||
if (has_timeout && keys) {
|
||||
gfxconsole_setpos(x, y + total + 1);
|
||||
printf(" ");
|
||||
has_timeout = 0;
|
||||
}
|
||||
if (is_pressed && !keys) {
|
||||
if (is_pressed & KEY_SELECT) {
|
||||
return curpos;
|
||||
}
|
||||
if (is_pressed & KEY_UP) {
|
||||
if (curpos == 0) {
|
||||
curpos = max;
|
||||
} else {
|
||||
curpos--;
|
||||
}
|
||||
}
|
||||
if (is_pressed & KEY_DOWN) {
|
||||
if (curpos == max) {
|
||||
curpos = 0;
|
||||
} else {
|
||||
curpos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (keys) {
|
||||
is_pressed = keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_menu_entry(char *title, unsigned type, char *arg, char *name)
|
||||
{
|
||||
menu_entry_t *entryp = (menu_entry_t *)malloc(sizeof(menu_entry_t));
|
||||
|
||||
entryp->title = title;
|
||||
entryp->type = type;
|
||||
entryp->arg = arg;
|
||||
entryp->name = name;
|
||||
|
||||
entries[num_menu_entries++] = entryp;
|
||||
}
|
||||
|
||||
void moboot_init(const struct app_descriptor *app)
|
||||
{
|
||||
int rv, keys_pressed;
|
||||
unsigned act;
|
||||
menu_entry_t *real_entries[32];
|
||||
|
||||
char *ptr;
|
||||
int rc;
|
||||
char path[256];
|
||||
char *newpath;
|
||||
char *newtitle;
|
||||
char *newname;
|
||||
|
||||
unsigned xoff, yoff;
|
||||
|
||||
unsigned ramdisk_mounted, ramdisk_start, ramdisk_size;
|
||||
|
||||
unsigned i, j;
|
||||
|
||||
unsigned default_menu_entry = 0;
|
||||
unsigned next_menu_entry = 0;
|
||||
|
||||
char default_image[256];
|
||||
char next_image[256];
|
||||
|
||||
unsigned default_timeout;
|
||||
unsigned counted_images;
|
||||
unsigned use_next;
|
||||
ssize_t splash_sz;
|
||||
void *splash_ptr;
|
||||
ssize_t background_sz;
|
||||
void *background_ptr;
|
||||
ssize_t tile_sz;
|
||||
void *tile_ptr;
|
||||
char splash_path[256];
|
||||
|
||||
unsigned boot_flags;
|
||||
|
||||
ssize_t rdmsgsz;
|
||||
char *rdmsg;
|
||||
|
||||
keys_pressed = 0;
|
||||
|
||||
display_surface = NULL;
|
||||
|
||||
entries = real_entries;
|
||||
|
||||
gfx_trans = 0;
|
||||
|
||||
gfxconsole_clear();
|
||||
gfxconsole_setpos(0,0);
|
||||
|
||||
ramdisk_mounted = 0;
|
||||
atags_get_ramdisk(&ramdisk_start, &ramdisk_size);
|
||||
if (ramdisk_size && ramdisk_start) {
|
||||
ramdisk_init(ramdisk_start, ramdisk_size);
|
||||
if (fs_mount("/ramdisk", "/dev/ramdisk")) {
|
||||
printf("Ramdisk start=%08x size=%08x\n", ramdisk_start, ramdisk_size);
|
||||
printf("Unable to mount /ramdisk\n");
|
||||
printf("Press SELECT to continue\n");
|
||||
gpiokeys_wait_select();
|
||||
} else {
|
||||
ramdisk_mounted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fs_mount("/boot", "/dev/mmcblk0p13")) {
|
||||
printf("\nUnable to mount /boot, exiting.\n");
|
||||
while (1) {
|
||||
thread_sleep(20);
|
||||
}
|
||||
}
|
||||
|
||||
default_timeout = 5;
|
||||
if ((rv = fs_load_file("/boot/moboot.timeout", &default_image, 256)) > 0) {
|
||||
default_image[rv] = 0;
|
||||
if (default_image[rv - 1] == '\n') default_image[rv - 1] = 0;
|
||||
default_timeout = atoui(default_image);
|
||||
}
|
||||
default_image[0] = 0;
|
||||
rv = fs_load_file("/boot/moboot.default", &default_image, 256);
|
||||
if (rv > 0) {
|
||||
default_image[rv] = 0;
|
||||
if (default_image[rv - 1] == '\n') default_image[rv - 1] = 0;
|
||||
}
|
||||
use_next = 0;
|
||||
next_image[0] = 0;
|
||||
rv = fs_load_file("/boot/moboot.next", &next_image, 256);
|
||||
if (rv > 0) {
|
||||
next_image[rv] = 0;
|
||||
if (next_image[rv - 1] == '\n') next_image[rv - 1] = 0;
|
||||
}
|
||||
|
||||
tile_sz = fs_load_file_mem("/boot/moboot.background.tga", &tile_ptr);
|
||||
|
||||
background_surface = NULL;
|
||||
tile_surface = NULL;
|
||||
|
||||
if (tile_sz > 0) {
|
||||
tile_surface = tga_decode(tile_ptr, tile_sz,
|
||||
GFX_FORMAT_RGB_x888);
|
||||
struct display_info disp_info;
|
||||
if (!display_surface) {
|
||||
display_get_info(&disp_info);
|
||||
display_surface = gfx_create_surface_from_display(&disp_info);
|
||||
}
|
||||
background_surface = gfx_create_surface(NULL,
|
||||
display_surface->width,
|
||||
display_surface->height,
|
||||
display_surface->stride,
|
||||
display_surface->format);
|
||||
for (i = 0; i < display_surface->width; i += tile_surface->width) {
|
||||
for (j = 0; j < display_surface->height;
|
||||
j += tile_surface->height) {
|
||||
gfx_surface_blend(background_surface,
|
||||
tile_surface,
|
||||
i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
num_menu_entries = 0;
|
||||
|
||||
i = 0;
|
||||
counted_images = 0;
|
||||
while ((rc = fs_dirent("/boot", i, &ptr)) > 0) {
|
||||
sprintf(path, "/boot/%s", ptr);
|
||||
if (strncmp("uImage.", ptr, 7) == 0) {
|
||||
if (strncmp("uImage.moboot", ptr, 13) != 0) {
|
||||
newtitle = malloc(strlen(ptr) - 7 + 5 + 1);
|
||||
sprintf(newtitle, "boot %s", ptr + 7);
|
||||
newpath = malloc(strlen(ptr) + 6 + 1);
|
||||
sprintf(newpath, "/boot/%s", ptr);
|
||||
newname = malloc(strlen(ptr) - 7 + 1);
|
||||
sprintf(newname, "%s", ptr + 7);
|
||||
if (strcmp(default_image, ptr + 7) == 0) {
|
||||
default_menu_entry = num_menu_entries;
|
||||
}
|
||||
if (strcmp(next_image, ptr + 7) == 0) {
|
||||
next_menu_entry = num_menu_entries;
|
||||
use_next = 1;
|
||||
}
|
||||
set_menu_entry(newtitle, BOOT_FS, newpath, newname);
|
||||
counted_images++;
|
||||
}
|
||||
}
|
||||
free(ptr);
|
||||
i++;
|
||||
}
|
||||
if (rc < 0) {
|
||||
dprintf(SPEW, "/boot dirList ERROR rc = %d\n", rc);
|
||||
}
|
||||
i = 0;
|
||||
while ((rc = fs_dirent("/ramdisk/boot", i, &ptr)) > 0) {
|
||||
sprintf(path, "/ramdisk/boot/%s", ptr);
|
||||
if (strncmp("uImage.", ptr, 7) == 0) {
|
||||
if (strncmp("uImage.moboot", ptr, 13) != 0) {
|
||||
newtitle = malloc(strlen(ptr) - 7 + 5 + 1);
|
||||
sprintf(newtitle, "boot %s", ptr + 7);
|
||||
newpath = malloc(strlen(ptr) + 14 + 1);
|
||||
sprintf(newpath, "/ramdisk/boot/%s", ptr);
|
||||
newname = malloc(strlen(ptr) - 7 + 1);
|
||||
sprintf(newname, "%s", ptr + 7);
|
||||
if (strcmp(default_image, ptr + 7) == 0) {
|
||||
default_menu_entry = num_menu_entries;
|
||||
}
|
||||
if (strcmp(next_image, ptr + 7) == 0) {
|
||||
next_menu_entry = num_menu_entries;
|
||||
use_next = 1;
|
||||
}
|
||||
set_menu_entry(newtitle, BOOT_FS, newpath, newname);
|
||||
counted_images++;
|
||||
}
|
||||
}
|
||||
free(ptr);
|
||||
i++;
|
||||
}
|
||||
if (rc < 0) {
|
||||
dprintf(SPEW, "/ramdisk/boot dirList ERROR rc = %d\n", rc);
|
||||
}
|
||||
|
||||
if (counted_images == 0) {
|
||||
set_menu_entry("boot", BOOT_FS, "/boot/uImage-2.6.35-palm-tenderloin", "default");
|
||||
}
|
||||
|
||||
|
||||
if (gpiokeys_poll(KEY_ALL)) {
|
||||
keys_pressed = 1;
|
||||
printf("\nPlease release key(s)...");
|
||||
while (1) {
|
||||
thread_sleep(20);
|
||||
if (!gpiokeys_poll(KEY_ALL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx_trans = 0;
|
||||
if (tile_surface) {
|
||||
gfx_trans = 1;
|
||||
}
|
||||
|
||||
|
||||
set_menu_entry("boot webOS Recovery", BOOT_RECOVER, "", "recover");
|
||||
set_menu_entry("reboot", BOOT_REBOOT, "", "reboot");
|
||||
// set_menu_entry("DFU", BOOT_DFU, "", "");
|
||||
set_menu_entry("shutdown", BOOT_SHUTDOWN, "", "shutdown");
|
||||
|
||||
xoff = (gfxconsole_getwidth() - 12 ) / 2;
|
||||
yoff = (gfxconsole_getheight() - (num_menu_entries + 4)) / 2;
|
||||
|
||||
#if 0
|
||||
tgasz = fs_load_file_mem("/boot/moboot.tga", &tgaptr);
|
||||
|
||||
tga_surface = NULL;
|
||||
|
||||
if (tgasz > 0) {
|
||||
tga_surface = tga_decode(tgaptr, tgasz, GFX_FORMAT_RGB_x888);
|
||||
struct display_info disp_info;
|
||||
if (!display_surface) {
|
||||
display_get_info(&disp_info);
|
||||
display_surface = gfx_create_surface_from_display(&disp_info);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
gfxconsole_clear();
|
||||
|
||||
show_background();
|
||||
|
||||
if (background_surface) {
|
||||
gfxconsole_setbackground(background_surface);
|
||||
}
|
||||
|
||||
gfxconsole_settrans(gfx_trans);
|
||||
|
||||
gfxconsole_setpos(xoff,yoff);
|
||||
if (gfx_trans) {
|
||||
gfxconsole_set_colors(0xffffffff, 0x00000000);
|
||||
printf("moboot %s", MOBOOT_VERSION);
|
||||
gfxconsole_setpos(xoff,yoff);
|
||||
gfxconsole_set_colors(0x00000000, 0x00000000);
|
||||
} else {
|
||||
gfxconsole_set_colors(0x00000000, 0xffffffff);
|
||||
printf("moboot %s", MOBOOT_VERSION);
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
}
|
||||
|
||||
if (!use_next || keys_pressed) {
|
||||
act = moboot_menu(xoff, yoff + 2, entries, default_menu_entry, num_menu_entries, keys_pressed ? 0 : default_timeout);
|
||||
} else {
|
||||
act = next_menu_entry;
|
||||
use_next = 0;
|
||||
}
|
||||
|
||||
keys_pressed = 1;
|
||||
|
||||
gfxconsole_setpos(xoff, yoff + 2 + num_menu_entries + 2);
|
||||
|
||||
boot_flags = BOOTLINUX_NOFLAGS;
|
||||
|
||||
switch (entries[act]->type) {
|
||||
case BOOT_RECOVER:
|
||||
reboot_device(RESTART_REASON_RECOVER);
|
||||
break;
|
||||
case BOOT_REBOOT:
|
||||
reboot_device(RESTART_REASON_REBOOT);
|
||||
break;
|
||||
case BOOT_DFU:
|
||||
reboot_device(RESTART_REASON_DFU);
|
||||
break;
|
||||
case BOOT_SHUTDOWN:
|
||||
reboot_device(RESTART_REASON_SHUTDOWN);
|
||||
break;
|
||||
case BOOT_FS:
|
||||
gfxconsole_clear();
|
||||
gfxconsole_settrans(gfx_trans);
|
||||
show_background();
|
||||
gfxconsole_setpos(0,0);
|
||||
|
||||
if (gfx_trans) {
|
||||
gfxconsole_set_colors(0x00000000, 0x00000000);
|
||||
} else {
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
}
|
||||
|
||||
printf("Selected: '%s'\n\n", entries[act]->title);
|
||||
printf("Loading '%s'... ", entries[act]->arg);
|
||||
if ((rv = fs_load_file(entries[act]->arg,
|
||||
(void *)SCRATCH_ADDR,
|
||||
SCRATCH_SIZE * 1024 * 1024)) < 0) {
|
||||
printf("FAILED\n");
|
||||
} else {
|
||||
printf("OK\n");
|
||||
|
||||
/* check for verbose boot */
|
||||
sprintf(splash_path, "/boot/moboot.verbose.%s",
|
||||
entries[act]->name);
|
||||
|
||||
splash_sz = fs_load_file_mem(splash_path, &splash_ptr);
|
||||
|
||||
if (splash_sz > 0) {
|
||||
if (strncmp(splash_ptr, "yes", 3) == 0) {
|
||||
boot_flags |= BOOTLINUX_VERBOSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for sercon boot */
|
||||
sprintf(splash_path, "/boot/moboot.sercon.%s",
|
||||
entries[act]->name);
|
||||
|
||||
splash_sz = fs_load_file_mem(splash_path, &splash_ptr);
|
||||
|
||||
if (splash_sz > 0) {
|
||||
if (strncmp(splash_ptr, "yes", 3) == 0) {
|
||||
boot_flags |= BOOTLINUX_SERCON;
|
||||
}
|
||||
}
|
||||
|
||||
if (splash_ptr) free(splash_ptr);
|
||||
|
||||
|
||||
/* check for splash image */
|
||||
sprintf(splash_path, "/boot/moboot.splash.%s.tga",
|
||||
entries[act]->name);
|
||||
|
||||
splash_sz = fs_load_file_mem(splash_path, &splash_ptr);
|
||||
|
||||
splash_surface = NULL;
|
||||
|
||||
if (splash_sz > 0) {
|
||||
splash_surface = tga_decode(splash_ptr, splash_sz,
|
||||
GFX_FORMAT_RGB_x888);
|
||||
struct display_info disp_info;
|
||||
if (!display_surface) {
|
||||
display_get_info(&disp_info);
|
||||
display_surface = gfx_create_surface_from_display(
|
||||
&disp_info);
|
||||
}
|
||||
}
|
||||
|
||||
/* do it to it! */
|
||||
bootlinux_uimage_mem((void *)SCRATCH_ADDR, rv, boot_splash,
|
||||
boot_flags);
|
||||
}
|
||||
|
||||
gfxconsole_set_colors(0x00000000, 0x00ff0000);
|
||||
printf("\n\nBOOT FAILED!\n\nPress SELECT to continue\n");
|
||||
gfxconsole_set_colors(0x00000000, 0x000000ff);
|
||||
gpiokeys_wait_select();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
char *ptr;
|
||||
int rc;
|
||||
unsigned i = 0;
|
||||
char path[256];
|
||||
filecookie fc;
|
||||
struct file_stat fstat;
|
||||
while ((rc = fs_dirent("/boot", i, &ptr)) > 0) {
|
||||
sprintf(path, "/boot/%s", ptr);
|
||||
fs_open_file(path, &fc);
|
||||
fs_stat_file(fc, &fstat);
|
||||
dprintf(SPEW, "Mode: %06hx ATIME: %08x CTIME: %08x MTIME: %08x NAME: '%s'\n",
|
||||
fstat.mode, fstat.atime, fstat.ctime, fstat.mtime, ptr);
|
||||
fs_close_file(fc);
|
||||
free(ptr);
|
||||
i++;
|
||||
}
|
||||
if (rc < 0) {
|
||||
dprintf(SPEW, "rc = %d\n", rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
APP_START(moboot)
|
||||
.init = moboot_init,
|
||||
APP_END
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/moboot.o \
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_IMAGE_H_
|
||||
#define _BOOT_IMAGE_H_
|
||||
|
||||
typedef struct boot_img_hdr boot_img_hdr;
|
||||
|
||||
#define BOOT_MAGIC "ANDROID!"
|
||||
#define BOOT_MAGIC_SIZE 8
|
||||
#define BOOT_NAME_SIZE 16
|
||||
#define BOOT_ARGS_SIZE 512
|
||||
|
||||
struct boot_img_hdr
|
||||
{
|
||||
unsigned char magic[BOOT_MAGIC_SIZE];
|
||||
|
||||
unsigned kernel_size; /* size in bytes */
|
||||
unsigned kernel_addr; /* physical load addr */
|
||||
|
||||
unsigned ramdisk_size; /* size in bytes */
|
||||
unsigned ramdisk_addr; /* physical load addr */
|
||||
|
||||
unsigned second_size; /* size in bytes */
|
||||
unsigned second_addr; /* physical load addr */
|
||||
|
||||
unsigned tags_addr; /* physical addr for kernel tags */
|
||||
unsigned page_size; /* flash page size we assume */
|
||||
unsigned unused[2]; /* future expansion: should be 0 */
|
||||
|
||||
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
|
||||
unsigned char cmdline[BOOT_ARGS_SIZE];
|
||||
|
||||
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
|
||||
};
|
||||
|
||||
/*
|
||||
** +-----------------+
|
||||
** | boot header | 1 page
|
||||
** +-----------------+
|
||||
** | kernel | n pages
|
||||
** +-----------------+
|
||||
** | ramdisk | m pages
|
||||
** +-----------------+
|
||||
** | second stage | o pages
|
||||
** +-----------------+
|
||||
**
|
||||
** n = (kernel_size + page_size - 1) / page_size
|
||||
** m = (ramdisk_size + page_size - 1) / page_size
|
||||
** o = (second_size + page_size - 1) / page_size
|
||||
**
|
||||
** 0. all entities are page_size aligned in flash
|
||||
** 1. kernel and ramdisk are required (size != 0)
|
||||
** 2. second is optional (second_size == 0 -> no second)
|
||||
** 3. load each element (kernel, ramdisk, second) at
|
||||
** the specified physical address (kernel_addr, etc)
|
||||
** 4. prepare tags at tag_addr. kernel_args[] is
|
||||
** appended to the kernel commandline in the tags.
|
||||
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
|
||||
** 6. if second_size != 0: jump to second_addr
|
||||
** else: jump to kernel_addr
|
||||
*/
|
||||
|
||||
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
|
||||
void *ramdisk, unsigned ramdisk_size,
|
||||
void *second, unsigned second_size,
|
||||
unsigned page_size,
|
||||
unsigned *bootimg_size);
|
||||
|
||||
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <app.h>
|
||||
#include <debug.h>
|
||||
#include <lib/ptable.h>
|
||||
#include <malloc.h>
|
||||
#include <dev/flash.h>
|
||||
#include <string.h>
|
||||
#include <jtag.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <smem.h>
|
||||
#include <platform.h>
|
||||
#include "bootimg.h"
|
||||
|
||||
#define FLASH_PAGE_SIZE 2048
|
||||
#define FLASH_PAGE_BITS 11
|
||||
|
||||
unsigned page_size = 0;
|
||||
unsigned page_mask = 0;
|
||||
|
||||
static unsigned load_addr = 0xffffffff;
|
||||
|
||||
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
|
||||
|
||||
void acpu_clock_init(void);
|
||||
|
||||
int startswith(const char *str, const char *prefix)
|
||||
{
|
||||
while(*prefix){
|
||||
if (*prefix++ != *str++) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* XXX */
|
||||
void verify_flash(struct ptentry *p, void *addr, unsigned len, int extra)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
void *buf = malloc(FLASH_PAGE_SIZE + extra);
|
||||
int verify_extra = extra;
|
||||
if(verify_extra > 4)
|
||||
verify_extra = 16;
|
||||
while(len > 0) {
|
||||
flash_read_ext(p, extra, offset, buf, FLASH_PAGE_SIZE);
|
||||
if(memcmp(addr, buf, FLASH_PAGE_SIZE + verify_extra)) {
|
||||
dprintf(CRITICAL, "verify failed at 0x%08x\n", offset);
|
||||
jtag_fail("verify failed");
|
||||
return;
|
||||
}
|
||||
offset += FLASH_PAGE_SIZE;
|
||||
addr += FLASH_PAGE_SIZE;
|
||||
len -= FLASH_PAGE_SIZE;
|
||||
if(extra) {
|
||||
addr += extra;
|
||||
len -= extra;
|
||||
}
|
||||
}
|
||||
dprintf(INFO, "verify done %d extra bytes\n", verify_extra);
|
||||
jtag_okay("verify done");
|
||||
}
|
||||
|
||||
void handle_flash(const char *name, unsigned addr, unsigned sz)
|
||||
{
|
||||
struct ptentry *ptn;
|
||||
struct ptable *ptable;
|
||||
void *data = (void *) addr;
|
||||
unsigned extra = 0;
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
if (ptable == NULL) {
|
||||
jtag_fail("partition table doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
ptn = ptable_find(ptable, name);
|
||||
if (ptn == NULL) {
|
||||
jtag_fail("unknown partition name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
|
||||
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
|
||||
jtag_fail("image is not a boot image");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata") || !strcmp(ptn->name, "persist"))
|
||||
extra = ((page_size >> 9) * 16);
|
||||
else
|
||||
sz = ROUND_TO_PAGE(sz, page_mask);
|
||||
|
||||
data = (void *)target_get_scratch_address();
|
||||
|
||||
dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
|
||||
if (flash_write(ptn, extra, data, sz)) {
|
||||
jtag_fail("flash write failure");
|
||||
return;
|
||||
}
|
||||
dprintf(INFO, "partition '%s' updated\n", ptn->name);
|
||||
jtag_okay("Done");
|
||||
enter_critical_section();
|
||||
platform_uninit_timer();
|
||||
arch_disable_cache(UCACHE);
|
||||
arch_disable_mmu();
|
||||
}
|
||||
|
||||
static unsigned char *tmpbuf = 0;
|
||||
|
||||
|
||||
/*XXX*/
|
||||
void handle_dump(const char *name, unsigned offset)
|
||||
{
|
||||
struct ptentry *p;
|
||||
struct ptable *ptable;
|
||||
|
||||
if(tmpbuf == 0) {
|
||||
tmpbuf = malloc(4096);
|
||||
}
|
||||
|
||||
dprintf(INFO, "dump '%s' partition\n", name);
|
||||
|
||||
ptable = flash_get_ptable();
|
||||
|
||||
if (ptable == NULL) {
|
||||
jtag_fail("partition table doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
p = ptable_find(ptable, name);
|
||||
|
||||
if(p == 0) {
|
||||
jtag_fail("partition not found");
|
||||
return;
|
||||
} else {
|
||||
|
||||
#if 0
|
||||
/* XXX reimpl */
|
||||
if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)){
|
||||
jtag_fail("flash_read() failed");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dprintf(INFO, "page %d data:\n", p->start * 64);
|
||||
hexdump(tmpbuf, 256);
|
||||
dprintf(INFO, "page %d extra:\n", p->start * 64);
|
||||
hexdump(tmpbuf, 16);
|
||||
jtag_okay("done");
|
||||
enter_critical_section();
|
||||
platform_uninit_timer();
|
||||
arch_disable_cache(UCACHE);
|
||||
arch_disable_mmu();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_query_load_address(unsigned addr)
|
||||
{
|
||||
unsigned *return_addr = (unsigned *)addr;
|
||||
|
||||
if (return_addr)
|
||||
*return_addr = target_get_scratch_address();
|
||||
|
||||
jtag_okay("done");
|
||||
}
|
||||
|
||||
void handle_command(const char *cmd, unsigned a0, unsigned a1, unsigned a2)
|
||||
{
|
||||
if(startswith(cmd,"flash:")){
|
||||
handle_flash(cmd + 6, a0, a1);
|
||||
return;
|
||||
}
|
||||
|
||||
if(startswith(cmd,"dump:")){
|
||||
handle_dump(cmd + 5, a0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(startswith(cmd,"loadaddr:")){
|
||||
handle_query_load_address(a0);
|
||||
return;
|
||||
}
|
||||
|
||||
jtag_fail("unknown command");
|
||||
}
|
||||
|
||||
void nandwrite_init(void)
|
||||
{
|
||||
page_size = flash_page_size();
|
||||
page_mask = page_size - 1;
|
||||
jtag_cmd_loop(handle_command);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/nandwrite.o \
|
||||
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <app.h>
|
||||
#include <debug.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <compiler.h>
|
||||
#include <platform.h>
|
||||
#include <dev/pci.h>
|
||||
|
||||
#if defined(WITH_LIB_CONSOLE)
|
||||
#include <lib/console.h>
|
||||
|
||||
/*
|
||||
* enumerates pci devices
|
||||
*/
|
||||
static void pci_list(void)
|
||||
{
|
||||
pci_location_t state;
|
||||
uint16_t device_id, vendor_id;
|
||||
uint8_t header_type;
|
||||
int busses = 0, devices = 0, lines = 0, devfn, ret;
|
||||
char c;
|
||||
|
||||
printf("Scanning...\n");
|
||||
|
||||
for (state.bus = 0; state.bus <= pci_get_last_bus(); state.bus++) {
|
||||
busses++;
|
||||
|
||||
for (devfn = 0; devfn < 256; devfn++) {
|
||||
state.dev_fn = devfn;
|
||||
|
||||
ret = pci_read_config_half(&state, PCI_CONFIG_VENDOR_ID, &vendor_id);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
ret = pci_read_config_half(&state, PCI_CONFIG_DEVICE_ID, &device_id);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
ret = pci_read_config_byte(&state, PCI_CONFIG_HEADER_TYPE, &header_type);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
if (vendor_id != 0xffff) {
|
||||
printf("%02x:%02x vendor_id=%04x device_id=%04x, header_type=%02x\n", state.bus, state.dev_fn,
|
||||
vendor_id, device_id, header_type);
|
||||
devices++;
|
||||
lines++;
|
||||
}
|
||||
|
||||
if (~header_type & PCI_HEADER_TYPE_MULTI_FN) {
|
||||
// this is not a multi-function device, so advance to the next device
|
||||
devfn |= 7;
|
||||
}
|
||||
|
||||
if (lines == 23) {
|
||||
printf("... press any key to continue, q to quit ...");
|
||||
while(getc(&c) < 0);
|
||||
printf("\n");
|
||||
lines = 0;
|
||||
|
||||
if (c == 'q' || c == 'Q') goto quit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("... done. Scanned %d busses, %d device/functions\n", busses, devices);
|
||||
quit:
|
||||
return;
|
||||
|
||||
error:
|
||||
printf("Error while reading PCI config space: %02x\n", ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* a somewhat fugly pci config space examine/modify command. this should probably
|
||||
* be broken up a bit.
|
||||
*/
|
||||
static int pci_config(int argc, const cmd_args *argv)
|
||||
{
|
||||
pci_location_t loc;
|
||||
pci_config_t config;
|
||||
uint32_t offset;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (argc < 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[2].str, "dump")) {
|
||||
loc.bus = atoui(argv[3].str);
|
||||
loc.dev_fn = atoui(argv[4].str);
|
||||
|
||||
for (i=0; i < sizeof(pci_config_t); i++) {
|
||||
ret = pci_read_config_byte(&loc, i, (uint8_t *) &config + i);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
}
|
||||
|
||||
printf("Device at %02x:%02x vendor id=%04x device id=%04x\n", loc.bus,
|
||||
loc.dev_fn, config.vendor_id, config.device_id);
|
||||
printf("command=%04x status=%04x pi=%02x sub cls=%02x base cls=%02x\n",
|
||||
config.command, config.status, config.program_interface,
|
||||
config.sub_class, config.base_class);
|
||||
|
||||
for (i=0; i < 6; i+=2) {
|
||||
printf("bar%d=%08x bar%d=%08x\n", i, config.base_addresses[i],
|
||||
i+1, config.base_addresses[i+1]);
|
||||
}
|
||||
} else if (!strcmp(argv[2].str, "rb") || !strcmp(argv[2].str, "rh") || !strcmp(argv[2].str, "rw")) {
|
||||
if (argc != 6) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
loc.bus = atoui(argv[3].str);
|
||||
loc.dev_fn = atoui(argv[4].str);
|
||||
offset = atoui(argv[5].str);
|
||||
|
||||
switch (argv[2].str[1]) {
|
||||
case 'b': {
|
||||
uint8_t value;
|
||||
ret = pci_read_config_byte(&loc, offset, &value);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
printf("byte at device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h': {
|
||||
uint16_t value;
|
||||
ret = pci_read_config_half(&loc, offset, &value);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
printf("half at device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w': {
|
||||
uint32_t value;
|
||||
ret = pci_read_config_word(&loc, offset, &value);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
printf("word at device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (!strcmp(argv[2].str, "mb") || !strcmp(argv[2].str, "mh") || !strcmp(argv[2].str, "mw")) {
|
||||
if (argc != 7) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
loc.bus = atoui(argv[3].str);
|
||||
loc.dev_fn = atoui(argv[4].str);
|
||||
offset = atoui(argv[5].str);
|
||||
|
||||
switch (argv[2].str[1]) {
|
||||
case 'b': {
|
||||
uint8_t value = atoui(argv[6].str);
|
||||
ret = pci_write_config_byte(&loc, offset, value);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
printf("byte to device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h': {
|
||||
uint16_t value = atoui(argv[6].str);
|
||||
ret = pci_write_config_half(&loc, offset, value);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
printf("half to device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w': {
|
||||
uint32_t value = atoui(argv[6].str);
|
||||
ret = pci_write_config_word(&loc, offset, value);
|
||||
if (ret != _PCI_SUCCESSFUL) goto error;
|
||||
|
||||
printf("word to device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
printf("Error while reading PCI config space: %02x\n", ret);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int pci_cmd(int argc, const cmd_args *argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("pci commands:\n");
|
||||
usage:
|
||||
printf("%s list\n", argv[0].str);
|
||||
printf("%s config dump <bus> <devfn>\n", argv[0].str);
|
||||
printf("%s config <rb|rh|rw> <bus> <devfn> <offset>\n", argv[0].str);
|
||||
printf("%s config <mb|mh|mw> <bus> <devfn> <offset> <value>\n", argv[0].str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1].str, "list")) {
|
||||
pci_list();
|
||||
} else if (!strcmp(argv[1].str, "config")) {
|
||||
if (pci_config(argc, argv)) {
|
||||
goto usage;
|
||||
}
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC_COMMAND_START
|
||||
{ "pci", "pci toolbox", &pci_cmd },
|
||||
STATIC_COMMAND_END(pcitests);
|
||||
|
||||
#endif
|
||||
|
||||
APP_START(pcitests)
|
||||
APP_END
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
#INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/pci_tests.o
|
||||
@@ -0,0 +1,8 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULES += \
|
||||
lib/openssl
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/app.o
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULES += \
|
||||
lib/console
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/shell.o
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <app.h>
|
||||
#include <debug.h>
|
||||
#include <lib/console.h>
|
||||
|
||||
static void shell_init(const struct app_descriptor *app)
|
||||
{
|
||||
console_init();
|
||||
}
|
||||
|
||||
static void shell_entry(const struct app_descriptor *app, void *args)
|
||||
{
|
||||
console_start();
|
||||
}
|
||||
|
||||
APP_START(shell)
|
||||
.init = shell_init,
|
||||
.entry = shell_entry,
|
||||
APP_END
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
#include <arch/arm/cores.h>
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
.global mymemcpy
|
||||
mymemcpy:
|
||||
// check for zero length copy or the same pointer
|
||||
cmp r2, #0
|
||||
cmpne r1, r0
|
||||
bxeq lr
|
||||
|
||||
// save a few registers for use and the return code (input dst)
|
||||
stmfd sp!, {r0, r4, r5, lr}
|
||||
|
||||
// check for forwards overlap (src > dst, distance < len)
|
||||
subs r3, r0, r1
|
||||
cmpgt r2, r3
|
||||
bgt .L_forwardoverlap
|
||||
|
||||
// check for a short copy len.
|
||||
// 20 bytes is enough so that if a 16 byte alignment needs to happen there is at least a
|
||||
// wordwise copy worth of work to be done.
|
||||
cmp r2, #(16+4)
|
||||
blt .L_bytewise
|
||||
|
||||
// see if they are similarly aligned on 4 byte boundaries
|
||||
eor r3, r0, r1
|
||||
tst r3, #3
|
||||
bne .L_bytewise // dissimilarly aligned, nothing we can do (for now)
|
||||
|
||||
// check for 16 byte alignment on dst.
|
||||
// this will also catch src being not 4 byte aligned, since it is similarly 4 byte
|
||||
// aligned with dst at this point.
|
||||
tst r0, #15
|
||||
bne .L_not16bytealigned
|
||||
|
||||
// check to see if we have at least 32 bytes of data to copy.
|
||||
// if not, just revert to wordwise copy
|
||||
cmp r2, #32
|
||||
blt .L_wordwise
|
||||
|
||||
.L_bigcopy:
|
||||
// copy 32 bytes at a time. src & dst need to be at least 4 byte aligned,
|
||||
// and we need at least 32 bytes remaining to copy
|
||||
|
||||
// save r6-r7 for use in the big copy
|
||||
stmfd sp!, {r6-r7}
|
||||
|
||||
sub r2, r2, #32 // subtract an extra 32 to the len so we can avoid an extra compare
|
||||
|
||||
.L_bigcopy_loop:
|
||||
ldmia r1!, {r4, r5, r6, r7}
|
||||
stmia r0!, {r4, r5, r6, r7}
|
||||
ldmia r1!, {r4, r5, r6, r7}
|
||||
subs r2, r2, #32
|
||||
stmia r0!, {r4, r5, r6, r7}
|
||||
bge .L_bigcopy_loop
|
||||
|
||||
// restore r6-r7
|
||||
ldmfd sp!, {r6-r7}
|
||||
|
||||
// see if we are done
|
||||
adds r2, r2, #32
|
||||
beq .L_done
|
||||
|
||||
// less then 4 bytes left?
|
||||
cmp r2, #4
|
||||
blt .L_bytewise
|
||||
|
||||
.L_wordwise:
|
||||
// copy 4 bytes at a time.
|
||||
// src & dst are guaranteed to be word aligned, and at least 4 bytes are left to copy.
|
||||
subs r2, r2, #4
|
||||
|
||||
.L_wordwise_loop:
|
||||
ldr r3, [r1], #4
|
||||
subs r2, r2, #4
|
||||
str r3, [r0], #4
|
||||
bge .L_wordwise_loop
|
||||
|
||||
// correct the remaining len and test for completion
|
||||
adds r2, r2, #4
|
||||
beq .L_done
|
||||
|
||||
.L_bytewise:
|
||||
// simple bytewise copy
|
||||
ldrb r3, [r1], #1
|
||||
subs r2, r2, #1
|
||||
strb r3, [r0], #1
|
||||
bgt .L_bytewise
|
||||
|
||||
.L_done:
|
||||
// load dst for return and restore r4,r5
|
||||
#if ARM_ARCH_LEVEL >= 5
|
||||
ldmfd sp!, {r0, r4, r5, pc}
|
||||
#else
|
||||
ldmfd sp!, {r0, r4, r5, lr}
|
||||
bx lr
|
||||
#endif
|
||||
|
||||
.L_not16bytealigned:
|
||||
// dst is not 16 byte aligned, so we will copy up to 15 bytes to get it aligned.
|
||||
// src is guaranteed to be similarly word aligned with dst.
|
||||
|
||||
// set the condition flags based on the alignment.
|
||||
lsl r12, r0, #28
|
||||
rsb r12, r12, #0
|
||||
msr CPSR_f, r12 // move into NZCV fields in CPSR
|
||||
|
||||
// move as many bytes as necessary to get the dst aligned
|
||||
ldrvsb r3, [r1], #1 // V set
|
||||
ldrcsh r4, [r1], #2 // C set
|
||||
ldreq r5, [r1], #4 // Z set
|
||||
|
||||
strvsb r3, [r0], #1
|
||||
strcsh r4, [r0], #2
|
||||
streq r5, [r0], #4
|
||||
|
||||
ldmmiia r1!, {r3-r4} // N set
|
||||
stmmiia r0!, {r3-r4}
|
||||
|
||||
// fix the remaining len
|
||||
sub r2, r2, r12, lsr #28
|
||||
|
||||
// test to see what we should do now
|
||||
cmp r2, #32
|
||||
bge .L_bigcopy
|
||||
b .L_wordwise
|
||||
|
||||
// src and dest overlap 'forwards' or dst > src
|
||||
.L_forwardoverlap:
|
||||
|
||||
// do a bytewise reverse copy for now
|
||||
add r1, r1, r2
|
||||
add r0, r0, r2
|
||||
|
||||
.L_bytewisereverse:
|
||||
// simple bytewise reverse copy
|
||||
ldrb r3, [r1], #-1
|
||||
subs r2, r2, #1
|
||||
strb r3, [r0], #-1
|
||||
bgt .L_bytewisereverse
|
||||
|
||||
b .L_done
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
#include <arch/arm/cores.h>
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
/* void *memset(void *s, int c, size_t n); */
|
||||
.global mymemset
|
||||
mymemset:
|
||||
// check for zero length
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
|
||||
// save the original pointer
|
||||
mov r12, r0
|
||||
|
||||
// short memsets aren't worth optimizing
|
||||
cmp r2, #(32 + 16)
|
||||
blt .L_bytewise
|
||||
|
||||
// fill a 32 bit register with the 8 bit value
|
||||
and r1, r1, #0xff
|
||||
orr r1, r1, r1, lsl #8
|
||||
orr r1, r1, r1, lsl #16
|
||||
|
||||
// check for 16 byte alignment
|
||||
tst r0, #15
|
||||
bne .L_not16bytealigned
|
||||
|
||||
.L_bigset:
|
||||
// dump some registers to make space for our values
|
||||
stmfd sp!, { r4-r5 }
|
||||
|
||||
// fill a bunch of registers with the set value
|
||||
mov r3, r1
|
||||
mov r4, r1
|
||||
mov r5, r1
|
||||
|
||||
// prepare the count register so we can avoid an extra compare
|
||||
sub r2, r2, #32
|
||||
|
||||
// 32 bytes at a time
|
||||
.L_bigset_loop:
|
||||
stmia r0!, { r1, r3, r4, r5 }
|
||||
subs r2, r2, #32
|
||||
stmia r0!, { r1, r3, r4, r5 }
|
||||
bge .L_bigset_loop
|
||||
|
||||
// restore our dumped registers
|
||||
ldmfd sp!, { r4-r5 }
|
||||
|
||||
// see if we're done
|
||||
adds r2, r2, #32
|
||||
beq .L_done
|
||||
|
||||
.L_bytewise:
|
||||
// bytewise memset
|
||||
subs r2, r2, #1
|
||||
strb r1, [r0], #1
|
||||
bgt .L_bytewise
|
||||
|
||||
.L_done:
|
||||
// restore the base pointer as return value
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
.L_not16bytealigned:
|
||||
// dst is not 16 byte aligned, so we will set up to 15 bytes to get it aligned.
|
||||
|
||||
// set the condition flags based on the alignment.
|
||||
lsl r3, r0, #28
|
||||
rsb r3, r3, #0
|
||||
msr CPSR_f, r3 // move into NZCV fields in CPSR
|
||||
|
||||
// move as many bytes as necessary to get the dst aligned
|
||||
strvsb r1, [r0], #1 // V set
|
||||
strcsh r1, [r0], #2 // C set
|
||||
streq r1, [r0], #4 // Z set
|
||||
strmi r1, [r0], #4 // N set
|
||||
strmi r1, [r0], #4 // N set
|
||||
|
||||
// fix the remaining len
|
||||
sub r2, r2, r3, lsr #28
|
||||
|
||||
// do the large memset
|
||||
b .L_bigset
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/string_tests.o \
|
||||
$(LOCAL_DIR)/mymemcpy.o \
|
||||
$(LOCAL_DIR)/mymemset.o
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <app.h>
|
||||
#include <platform.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
static uint8_t *src;
|
||||
static uint8_t *dst;
|
||||
|
||||
static uint8_t *src2;
|
||||
static uint8_t *dst2;
|
||||
|
||||
#define BUFFER_SIZE (1024*1024)
|
||||
#define ITERATIONS 16
|
||||
|
||||
extern void *mymemcpy(void *dst, const void *src, size_t len);
|
||||
extern void *mymemset(void *dst, int c, size_t len);
|
||||
|
||||
static void *null_memcpy(void *dst, const void *src, size_t len)
|
||||
{
|
||||
return dst;
|
||||
}
|
||||
|
||||
static time_t bench_memcpy_routine(void *memcpy_routine(void *, const void *, size_t), size_t srcalign, size_t dstalign)
|
||||
{
|
||||
int i;
|
||||
time_t t0;
|
||||
|
||||
t0 = current_time();
|
||||
for (i=0; i < ITERATIONS; i++) {
|
||||
memcpy_routine(dst + dstalign, src + srcalign, BUFFER_SIZE);
|
||||
}
|
||||
return current_time() - t0;
|
||||
}
|
||||
|
||||
static void bench_memcpy(void)
|
||||
{
|
||||
time_t null, libc, mine;
|
||||
size_t srcalign, dstalign;
|
||||
|
||||
printf("memcpy speed test\n");
|
||||
thread_sleep(200); // let the debug string clear the serial port
|
||||
|
||||
for (srcalign = 0; srcalign < 64; ) {
|
||||
for (dstalign = 0; dstalign < 64; ) {
|
||||
|
||||
null = bench_memcpy_routine(&null_memcpy, srcalign, dstalign);
|
||||
libc = bench_memcpy_routine(&memcpy, srcalign, dstalign);
|
||||
mine = bench_memcpy_routine(&mymemcpy, srcalign, dstalign);
|
||||
|
||||
printf("srcalign %lu, dstalign %lu\n", srcalign, dstalign);
|
||||
printf(" null memcpy %u msecs\n", null);
|
||||
printf(" libc memcpy %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
|
||||
printf(" my memcpy %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
|
||||
|
||||
if (dstalign == 0)
|
||||
dstalign = 1;
|
||||
else
|
||||
dstalign <<= 1;
|
||||
}
|
||||
if (srcalign == 0)
|
||||
srcalign = 1;
|
||||
else
|
||||
srcalign <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void fillbuf(void *ptr, size_t len, uint32_t seed)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
((char *)ptr)[i] = seed;
|
||||
seed *= 0x1234567;
|
||||
}
|
||||
}
|
||||
|
||||
static void validate_memcpy(void)
|
||||
{
|
||||
size_t srcalign, dstalign, size;
|
||||
const size_t maxsize = 256;
|
||||
|
||||
printf("testing memcpy for correctness\n");
|
||||
|
||||
/*
|
||||
* do the simple tests to make sure that memcpy doesn't color outside
|
||||
* the lines for all alignment cases
|
||||
*/
|
||||
for (srcalign = 0; srcalign < 64; srcalign++) {
|
||||
for (dstalign = 0; dstalign < 64; dstalign++) {
|
||||
// printf("srcalign %zu, dstalign %zu\n", srcalign, dstalign);
|
||||
for (size = 0; size < maxsize; size++) {
|
||||
|
||||
// printf("srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
|
||||
|
||||
fillbuf(src, maxsize * 2, 567);
|
||||
fillbuf(src2, maxsize * 2, 567);
|
||||
fillbuf(dst, maxsize * 2, 123514);
|
||||
fillbuf(dst2, maxsize * 2, 123514);
|
||||
|
||||
memcpy(dst + dstalign, src + srcalign, size);
|
||||
mymemcpy(dst2 + dstalign, src2 + srcalign, size);
|
||||
|
||||
int comp = memcmp(dst, dst2, maxsize * 2);
|
||||
if (comp != 0) {
|
||||
printf("error! srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static time_t bench_memset_routine(void *memset_routine(void *, int, size_t), size_t dstalign)
|
||||
{
|
||||
int i;
|
||||
time_t t0;
|
||||
|
||||
t0 = current_time();
|
||||
for (i=0; i < ITERATIONS; i++) {
|
||||
memset_routine(dst + dstalign, 0, BUFFER_SIZE);
|
||||
}
|
||||
return current_time() - t0;
|
||||
}
|
||||
|
||||
static void bench_memset(void)
|
||||
{
|
||||
time_t libc, mine;
|
||||
size_t dstalign;
|
||||
|
||||
printf("memset speed test\n");
|
||||
thread_sleep(200); // let the debug string clear the serial port
|
||||
|
||||
for (dstalign = 0; dstalign < 64; dstalign++) {
|
||||
|
||||
libc = bench_memset_routine(&memset, dstalign);
|
||||
mine = bench_memset_routine(&mymemset, dstalign);
|
||||
|
||||
printf("dstalign %lu\n", dstalign);
|
||||
printf(" libc memset %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
|
||||
printf(" my memset %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
|
||||
}
|
||||
}
|
||||
|
||||
static void validate_memset(void)
|
||||
{
|
||||
size_t dstalign, size;
|
||||
int c;
|
||||
const size_t maxsize = 256;
|
||||
|
||||
printf("testing memset for correctness\n");
|
||||
|
||||
for (dstalign = 0; dstalign < 64; dstalign++) {
|
||||
printf("align %zd\n", dstalign);
|
||||
for (size = 0; size < maxsize; size++) {
|
||||
for (c = 0; c < 256; c++) {
|
||||
|
||||
fillbuf(dst, maxsize * 2, 123514);
|
||||
fillbuf(dst2, maxsize * 2, 123514);
|
||||
|
||||
memset(dst + dstalign, c, size);
|
||||
mymemset(dst2 + dstalign, c, size);
|
||||
|
||||
int comp = memcmp(dst, dst2, maxsize * 2);
|
||||
if (comp != 0) {
|
||||
printf("error! align %zu, c %d, size %zu\n", dstalign, c, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WITH_LIB_CONSOLE)
|
||||
#include <lib/console.h>
|
||||
|
||||
static int string_tests(int argc, cmd_args *argv)
|
||||
{
|
||||
src = memalign(64, BUFFER_SIZE + 256);
|
||||
dst = memalign(64, BUFFER_SIZE + 256);
|
||||
src2 = memalign(64, BUFFER_SIZE + 256);
|
||||
dst2 = memalign(64, BUFFER_SIZE + 256);
|
||||
|
||||
printf("src %p, dst %p\n", src, dst);
|
||||
printf("src2 %p, dst2 %p\n", src2, dst2);
|
||||
|
||||
if (argc < 3) {
|
||||
printf("not enough arguments:\n");
|
||||
usage:
|
||||
printf("%s validate <routine>\n", argv[0].str);
|
||||
printf("%s bench <routine>\n", argv[0].str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1].str, "validate")) {
|
||||
if (!strcmp(argv[2].str, "memcpy")) {
|
||||
validate_memcpy();
|
||||
} else if (!strcmp(argv[2].str, "memset")) {
|
||||
validate_memset();
|
||||
}
|
||||
} else if (!strcmp(argv[1].str, "bench")) {
|
||||
if (!strcmp(argv[2].str, "memcpy")) {
|
||||
bench_memcpy();
|
||||
} else if (!strcmp(argv[2].str, "memset")) {
|
||||
bench_memset();
|
||||
}
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
out:
|
||||
free(src);
|
||||
free(dst);
|
||||
free(src2);
|
||||
free(dst2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC_COMMAND_START
|
||||
{ "string", NULL, &string_tests },
|
||||
STATIC_COMMAND_END(stringtests);
|
||||
|
||||
#endif
|
||||
|
||||
APP_START(stringtests)
|
||||
APP_END
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __APP_TESTS_H
|
||||
#define __APP_TESTS_H
|
||||
|
||||
int thread_tests(void);
|
||||
void printf_tests(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <app/tests.h>
|
||||
#include <debug.h>
|
||||
|
||||
void printf_tests(void)
|
||||
{
|
||||
printf("printf tests\n");
|
||||
|
||||
printf("numbers:\n");
|
||||
printf("int8: %hhd %hhd %hhd\n", -12, 0, 254);
|
||||
printf("uint8: %hhu %hhu %hhu\n", -12, 0, 254);
|
||||
printf("int16: %hd %hd %hd\n", -1234, 0, 1234);
|
||||
printf("uint16:%hu %hu %hu\n", -1234, 0, 1234);
|
||||
printf("int: %d %d %d\n", -12345678, 0, 12345678);
|
||||
printf("uint: %u %u %u\n", -12345678, 0, 12345678);
|
||||
printf("long: %ld %ld %ld\n", -12345678, 0, 12345678);
|
||||
printf("ulong: %lu %lu %lu\n", -12345678, 0, 12345678);
|
||||
printf("long: %D %D %D\n", -12345678, 0, 12345678);
|
||||
printf("ulong: %U %U %U\n", -12345678, 0, 12345678);
|
||||
printf("longlong: %lli %lli %lli\n", -12345678LL, 0LL, 12345678LL);
|
||||
printf("ulonglong: %llu %llu %llu\n", -12345678LL, 0LL, 12345678LL);
|
||||
printf("size_t: %zd %zd %zd\n", -12345678, 0, 12345678);
|
||||
printf("usize_t: %zu %zu %zu\n", -12345678, 0, 12345678);
|
||||
|
||||
printf("hex:\n");
|
||||
printf("uint8: %hhx %hhx %hhx\n", -12, 0, 254);
|
||||
printf("uint16:%hx %hx %hx\n", -1234, 0, 1234);
|
||||
printf("uint: %x %x %x\n", -12345678, 0, 12345678);
|
||||
printf("ulong: %lx %lx %lx\n", -12345678, 0, 12345678);
|
||||
printf("ulong: %X %X %X\n", -12345678, 0, 12345678);
|
||||
printf("ulonglong: %llx %llx %llx\n", -12345678LL, 0LL, 12345678LL);
|
||||
printf("usize_t: %zx %zx %zx\n", -12345678, 0, 12345678);
|
||||
|
||||
printf("alt/sign:\n");
|
||||
printf("uint: %#x %#X\n", 0xabcdef, 0xabcdef);
|
||||
printf("int: %+d %+d\n", 12345678, -12345678);
|
||||
|
||||
printf("formatting\n");
|
||||
printf("int: a%8da\n", 12345678);
|
||||
printf("int: a%9da\n", 12345678);
|
||||
printf("int: a%-9da\n", 12345678);
|
||||
printf("int: a%10da\n", 12345678);
|
||||
printf("int: a%-10da\n", 12345678);
|
||||
printf("int: a%09da\n", 12345678);
|
||||
printf("int: a%010da\n", 12345678);
|
||||
printf("int: a%6da\n", 12345678);
|
||||
|
||||
printf("a%1sa\n", "b");
|
||||
printf("a%9sa\n", "b");
|
||||
printf("a%-9sa\n", "b");
|
||||
printf("a%5sa\n", "thisisatest");
|
||||
|
||||
int err;
|
||||
|
||||
err = printf("a");
|
||||
printf(" returned %d\n", err);
|
||||
err = printf("ab");
|
||||
printf(" returned %d\n", err);
|
||||
err = printf("abc");
|
||||
printf(" returned %d\n", err);
|
||||
err = printf("abcd");
|
||||
printf(" returned %d\n", err);
|
||||
err = printf("abcde");
|
||||
printf(" returned %d\n", err);
|
||||
err = printf("abcdef");
|
||||
printf(" returned %d\n", err);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/tests.o \
|
||||
$(LOCAL_DIR)/thread_tests.o \
|
||||
$(LOCAL_DIR)/printf_tests.o
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <app.h>
|
||||
#include <debug.h>
|
||||
#include <app/tests.h>
|
||||
#include <compiler.h>
|
||||
|
||||
#if defined(WITH_LIB_CONSOLE)
|
||||
#include <lib/console.h>
|
||||
|
||||
STATIC_COMMAND_START
|
||||
STATIC_COMMAND("printf_tests", NULL, (console_cmd)&printf_tests)
|
||||
STATIC_COMMAND("thread_tests", NULL, (console_cmd)&thread_tests)
|
||||
STATIC_COMMAND_END(tests);
|
||||
|
||||
#endif
|
||||
|
||||
static void tests_init(const struct app_descriptor *app)
|
||||
{
|
||||
}
|
||||
|
||||
APP_START(tests)
|
||||
.init = tests_init,
|
||||
.flags = 0,
|
||||
APP_END
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <rand.h>
|
||||
#include <app/tests.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/mutex.h>
|
||||
#include <kernel/event.h>
|
||||
|
||||
static int sleep_thread(void *arg)
|
||||
{
|
||||
for(;;) {
|
||||
printf("sleeper %p\n", current_thread);
|
||||
thread_sleep(rand() % 500);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sleep_test(void)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i < 16; i++)
|
||||
thread_resume(thread_create("sleeper", &sleep_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static volatile int shared = 0;
|
||||
static mutex_t m;
|
||||
static volatile int mutex_thread_count = 0;
|
||||
|
||||
static int mutex_thread(void *arg)
|
||||
{
|
||||
int i;
|
||||
const int iterations = 10000;
|
||||
|
||||
atomic_add(&mutex_thread_count, 1);
|
||||
|
||||
printf("mutex tester thread %p starting up, will go for %d iterations\n", current_thread, iterations);
|
||||
|
||||
for (i = 0; i < iterations; i++) {
|
||||
mutex_acquire(&m);
|
||||
|
||||
if (shared != 0)
|
||||
panic("someone else has messed with the shared data\n");
|
||||
|
||||
shared = (int)current_thread;
|
||||
thread_yield();
|
||||
shared = 0;
|
||||
|
||||
mutex_release(&m);
|
||||
thread_yield();
|
||||
}
|
||||
atomic_add(&mutex_thread_count, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mutex_timeout_thread(void *arg)
|
||||
{
|
||||
mutex_t *timeout_mutex = (mutex_t *)arg;
|
||||
status_t err;
|
||||
|
||||
printf("mutex_timeout_thread acquiring mutex %p with 1 second timeout\n", timeout_mutex);
|
||||
err = mutex_acquire_timeout(timeout_mutex, 1000);
|
||||
printf("mutex_acquire_timeout returns %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mutex_zerotimeout_thread(void *arg)
|
||||
{
|
||||
mutex_t *timeout_mutex = (mutex_t *)arg;
|
||||
status_t err;
|
||||
|
||||
printf("mutex_zerotimeout_thread acquiring mutex %p with zero second timeout\n", timeout_mutex);
|
||||
err = mutex_acquire_timeout(timeout_mutex, 0);
|
||||
printf("mutex_acquire_timeout returns %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mutex_test(void)
|
||||
{
|
||||
mutex_init(&m);
|
||||
|
||||
int i;
|
||||
for(i=0; i < 5; i++)
|
||||
thread_resume(thread_create("mutex tester", &mutex_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
|
||||
thread_sleep(1000);
|
||||
|
||||
while (mutex_thread_count > 0)
|
||||
thread_yield();
|
||||
|
||||
printf("done with simple mutex tests\n");
|
||||
|
||||
printf("testing mutex timeout\n");
|
||||
|
||||
mutex_t timeout_mutex;
|
||||
|
||||
mutex_init(&timeout_mutex);
|
||||
mutex_acquire(&timeout_mutex);
|
||||
|
||||
for (i=0; i < 2; i++)
|
||||
thread_resume(thread_create("mutex timeout tester", &mutex_timeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
for (i=0; i < 2; i++)
|
||||
thread_resume(thread_create("mutex timeout tester", &mutex_zerotimeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
|
||||
thread_sleep(5000);
|
||||
mutex_release(&timeout_mutex);
|
||||
|
||||
printf("done with mutex tests\n");
|
||||
|
||||
mutex_destroy(&timeout_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static event_t e;
|
||||
|
||||
static int event_signaller(void *arg)
|
||||
{
|
||||
printf("event signaller pausing\n");
|
||||
thread_sleep(1000);
|
||||
|
||||
// for (;;) {
|
||||
printf("signalling event\n");
|
||||
event_signal(&e, true);
|
||||
printf("done signalling event\n");
|
||||
thread_yield();
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int event_waiter(void *arg)
|
||||
{
|
||||
printf("event waiter starting\n");
|
||||
|
||||
for (;;) {
|
||||
printf("%p: waiting on event...\n", current_thread);
|
||||
if (event_wait(&e) < 0) {
|
||||
printf("%p: event_wait() returned error\n", current_thread);
|
||||
return -1;
|
||||
}
|
||||
printf("%p: done waiting on event...\n", current_thread);
|
||||
thread_yield();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void event_test(void)
|
||||
{
|
||||
/* make sure signalling the event wakes up all the threads */
|
||||
event_init(&e, false, 0);
|
||||
thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_sleep(2000);
|
||||
event_destroy(&e);
|
||||
|
||||
/* make sure signalling the event wakes up precisely one thread */
|
||||
event_init(&e, false, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_sleep(2000);
|
||||
event_destroy(&e);
|
||||
}
|
||||
|
||||
static int quantum_tester(void *arg)
|
||||
{
|
||||
for (;;) {
|
||||
printf("%p: in this thread. rq %d\n", current_thread, current_thread->remaining_quantum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void quantum_test(void)
|
||||
{
|
||||
thread_resume(thread_create("quantum tester 0", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("quantum tester 1", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("quantum tester 2", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("quantum tester 3", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
}
|
||||
|
||||
static event_t context_switch_event;
|
||||
static event_t context_switch_done_event;
|
||||
|
||||
static int context_switch_tester(void *arg)
|
||||
{
|
||||
int i;
|
||||
uint total_count = 0;
|
||||
const int iter = 100000;
|
||||
int thread_count = (int)arg;
|
||||
|
||||
event_wait(&context_switch_event);
|
||||
|
||||
uint count = arch_cycle_count();
|
||||
for (i = 0; i < iter; i++) {
|
||||
thread_yield();
|
||||
}
|
||||
total_count += arch_cycle_count() - count;
|
||||
thread_sleep(1000);
|
||||
printf("took %u cycles to yield %d times, %u per yield, %u per yield per thread\n",
|
||||
total_count, iter, total_count / iter, total_count / iter / thread_count);
|
||||
|
||||
event_signal(&context_switch_done_event, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void context_switch_test(void)
|
||||
{
|
||||
event_init(&context_switch_event, false, 0);
|
||||
event_init(&context_switch_done_event, false, 0);
|
||||
|
||||
thread_resume(thread_create("context switch idle", &context_switch_tester, (void *)1, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_sleep(100);
|
||||
event_signal(&context_switch_event, true);
|
||||
event_wait(&context_switch_done_event);
|
||||
thread_sleep(100);
|
||||
|
||||
event_unsignal(&context_switch_event);
|
||||
event_unsignal(&context_switch_done_event);
|
||||
thread_resume(thread_create("context switch 2a", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("context switch 2b", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_sleep(100);
|
||||
event_signal(&context_switch_event, true);
|
||||
event_wait(&context_switch_done_event);
|
||||
thread_sleep(100);
|
||||
|
||||
event_unsignal(&context_switch_event);
|
||||
event_unsignal(&context_switch_done_event);
|
||||
thread_resume(thread_create("context switch 4a", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("context switch 4b", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("context switch 4c", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("context switch 4d", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_sleep(100);
|
||||
event_signal(&context_switch_event, true);
|
||||
event_wait(&context_switch_done_event);
|
||||
thread_sleep(100);
|
||||
}
|
||||
|
||||
static volatile int atomic;
|
||||
static volatile int atomic_count;
|
||||
|
||||
static int atomic_tester(void *arg)
|
||||
{
|
||||
int add = (int)arg;
|
||||
int i;
|
||||
|
||||
TRACEF("add %d\n", add);
|
||||
|
||||
for (i=0; i < 1000000; i++) {
|
||||
atomic_add(&atomic, add);
|
||||
}
|
||||
|
||||
int old = atomic_add(&atomic_count, -1);
|
||||
TRACEF("exiting, old count %d\n", old);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void atomic_test(void)
|
||||
{
|
||||
atomic = 0;
|
||||
atomic_count = 8;
|
||||
|
||||
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
||||
|
||||
while (atomic_count > 0) {
|
||||
thread_sleep(1);
|
||||
}
|
||||
|
||||
printf("atomic count == %d (should be zero)\n", atomic);
|
||||
}
|
||||
|
||||
int thread_tests(void)
|
||||
{
|
||||
mutex_test();
|
||||
event_test();
|
||||
|
||||
thread_sleep(200);
|
||||
context_switch_test();
|
||||
|
||||
atomic_test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <arch.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/arm.h>
|
||||
#include <arch/arm/mmu.h>
|
||||
#include <platform.h>
|
||||
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
static void set_vector_base(addr_t addr)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c12, c0, 0" :: "r" (addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
void arch_early_init(void)
|
||||
{
|
||||
/* turn off the cache */
|
||||
arch_disable_cache(UCACHE);
|
||||
|
||||
/* set the vector base to our exception vectors so we dont need to double map at 0 */
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
set_vector_base(MEMBASE);
|
||||
#endif
|
||||
|
||||
#if ARM_WITH_MMU
|
||||
arm_mmu_init();
|
||||
|
||||
platform_init_mmu_mappings();
|
||||
#endif
|
||||
|
||||
/* turn the cache back on */
|
||||
arch_enable_cache(UCACHE);
|
||||
|
||||
#if ARM_WITH_NEON
|
||||
/* enable cp10 and cp11 */
|
||||
uint32_t val;
|
||||
__asm__ volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val));
|
||||
val |= (3<<22)|(3<<20);
|
||||
__asm__ volatile("mcr p15, 0, %0, c1, c0, 2" :: "r" (val));
|
||||
|
||||
/* set enable bit in fpexc */
|
||||
val = (1<<30);
|
||||
__asm__ volatile("mcr p10, 7, %0, c8, c0, 0" :: "r" (val));
|
||||
#endif
|
||||
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
/* enable the cycle count register */
|
||||
uint32_t en;
|
||||
__asm__ volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (en));
|
||||
en &= ~(1<<3); /* cycle count every cycle */
|
||||
en |= 1; /* enable all performance counters */
|
||||
__asm__ volatile("mcr p15, 0, %0, c9, c12, 0" :: "r" (en));
|
||||
|
||||
/* enable cycle counter */
|
||||
en = (1<<31);
|
||||
__asm__ volatile("mcr p15, 0, %0, c9, c12, 1" :: "r" (en));
|
||||
#endif
|
||||
}
|
||||
|
||||
void arch_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
|
||||
|
||||
/* context switch frame is as follows:
|
||||
* ulr
|
||||
* usp
|
||||
* lr
|
||||
* r11
|
||||
* r10
|
||||
* r9
|
||||
* r8
|
||||
* r7
|
||||
* r6
|
||||
* r5
|
||||
* r4
|
||||
*/
|
||||
/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */
|
||||
FUNCTION(arm_context_switch)
|
||||
/* save all the usual registers + user regs */
|
||||
/* the spsr is saved and restored in the iframe by exceptions.S */
|
||||
sub r3, sp, #(11*4) /* can't use sp in user mode stm */
|
||||
mov r12, lr
|
||||
stmia r3, { r4-r11, r12, r13, r14 }^
|
||||
|
||||
/* save old sp */
|
||||
str r3, [r0]
|
||||
|
||||
/* clear any exlusive locks that the old thread holds */
|
||||
#if ARM_ISA_ARMV7
|
||||
/* can clear it directly */
|
||||
.word 0xf57ff01f // clrex
|
||||
#elif ARM_ISA_ARMV6
|
||||
/* have to do a fake strex to clear it */
|
||||
ldr r0, =strex_spot
|
||||
strex r3, r2, [r0]
|
||||
#endif
|
||||
|
||||
/* load new regs */
|
||||
ldmia r1, { r4-r11, r12, r13, r14 }^
|
||||
mov lr, r12 /* restore lr */
|
||||
add sp, r1, #(11*4) /* restore sp */
|
||||
bx lr
|
||||
|
||||
.ltorg
|
||||
|
||||
FUNCTION(arm_save_mode_regs)
|
||||
mrs r1, cpsr
|
||||
|
||||
#if ARM_ISA_ARMv6
|
||||
cps #0x11 /* fiq */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
cps #0x12 /* irq */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
cps #0x13 /* svc */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
cps #0x17 /* abt */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
cps #0x1b /* und */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
cps #0x1f /* sys */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
#else
|
||||
// XXX implement
|
||||
b .
|
||||
#endif
|
||||
|
||||
msr cpsr_c, r1
|
||||
|
||||
bx lr
|
||||
|
||||
.data
|
||||
strex_spot:
|
||||
.word 0
|
||||
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/defines.h>
|
||||
|
||||
.text
|
||||
|
||||
#if ARM_WITH_CACHE
|
||||
|
||||
/* low level cache routines for various cpu families */
|
||||
|
||||
#if ARM_CPU_ARM1136 || ARM_CPU_ARM926
|
||||
|
||||
/* void arch_disable_cache(uint flags) */
|
||||
FUNCTION(arch_disable_cache)
|
||||
mov r12, #0 // zero register
|
||||
mrs r3, cpsr // save the old interrupt state
|
||||
#if ARM_ISA_ARMv6
|
||||
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
|
||||
#else
|
||||
orr r3, r3, #(1<<7)
|
||||
msr cpsr, r3
|
||||
#endif
|
||||
|
||||
.Ldcache_disable:
|
||||
tst r0, #DCACHE
|
||||
beq .Licache_disable
|
||||
mrc p15, 0, r1, c1, c0, 0 // cr1
|
||||
tst r1, #(1<<2) // is the dcache already disabled?
|
||||
beq .Licache_disable
|
||||
|
||||
bic r1, #(1<<2)
|
||||
mcr p15, 0, r1, c1, c0, 0 // disable dcache
|
||||
|
||||
#if ARM_CPU_ARM1136
|
||||
mcr p15, 0, r12, c7, c14, 0 // clean & invalidate dcache
|
||||
#elif ARM_CPU_ARM926
|
||||
0:
|
||||
mrc p15, 0, r15, c7, c14, 3 // clean & invalidate dcache
|
||||
bne 0b
|
||||
#else
|
||||
#error whut?
|
||||
#endif
|
||||
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
|
||||
|
||||
.Licache_disable:
|
||||
tst r0, #ICACHE
|
||||
beq .Ldone_disable
|
||||
|
||||
mrc p15, 0, r1, c1, c0, 0 // cr1
|
||||
bic r1, #(1<<12)
|
||||
mcr p15, 0, r1, c1, c0, 0 // disable icache
|
||||
|
||||
mcr p15, 0, r12, c7, c5, 0 // invalidate icache
|
||||
|
||||
.Ldone_disable:
|
||||
msr cpsr, r3
|
||||
bx lr
|
||||
|
||||
/* void arch_enable_cache(uint flags) */
|
||||
FUNCTION(arch_enable_cache)
|
||||
mov r12, #0 // zero register
|
||||
mrs r3, cpsr // save the old interrupt state
|
||||
#if ARM_ISA_ARMv6
|
||||
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
|
||||
#else
|
||||
orr r3, r3, #(1<<7)
|
||||
msr cpsr, r3
|
||||
#endif
|
||||
|
||||
.Ldcache_enable:
|
||||
tst r0, #DCACHE
|
||||
beq .Licache_enable
|
||||
mrc p15, 0, r1, c1, c0, 0 // cr1
|
||||
tst r1, #(1<<2) // is the dcache already enabled?
|
||||
bne .Licache_enable
|
||||
|
||||
mcr p15, 0, r12, c7, c6, 0 // invalidate dcache
|
||||
|
||||
orr r1, #(1<<2)
|
||||
mcr p15, 0, r1, c1, c0, 0 // enable dcache
|
||||
|
||||
.Licache_enable:
|
||||
tst r0, #ICACHE
|
||||
beq .Ldone_enable
|
||||
|
||||
mcr p15, 0, r12, c7, c5, 0 // invalidate icache
|
||||
|
||||
mrc p15, 0, r1, c1, c0, 0 // cr1
|
||||
orr r1, #(1<<12)
|
||||
mcr p15, 0, r1, c1, c0, 0 // enable icache
|
||||
|
||||
.Ldone_enable:
|
||||
msr cpsr, r3
|
||||
bx lr
|
||||
|
||||
#elif ARM_CPU_CORTEX_A8
|
||||
|
||||
/* void arch_disable_cache(uint flags) */
|
||||
FUNCTION(arch_disable_cache)
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
|
||||
mov r7, r0 // save flags
|
||||
|
||||
mrs r12, cpsr // save the old interrupt state
|
||||
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
|
||||
|
||||
.Ldcache_disable:
|
||||
tst r7, #DCACHE
|
||||
beq .Licache_disable
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
tst r0, #(1<<2) // is the dcache already disabled?
|
||||
beq .Ldcache_already_disabled
|
||||
|
||||
bic r0, #(1<<2)
|
||||
mcr p15, 0, r0, c1, c0, 0 // disable dcache
|
||||
|
||||
// flush and invalidate the dcache
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl flush_invalidate_cache_v7
|
||||
|
||||
b .Ldcache_disable_L2
|
||||
|
||||
.Ldcache_already_disabled:
|
||||
// make sure all of the caches are invalidated
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl invalidate_cache_v7
|
||||
|
||||
.Ldcache_disable_L2:
|
||||
|
||||
#if ARM_WITH_L2
|
||||
// disable the L2, if present
|
||||
mrc p15, 0, r0, c1, c0, 1 // aux cr1
|
||||
bic r0, #(1<<1)
|
||||
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
|
||||
#endif
|
||||
|
||||
.Licache_disable:
|
||||
tst r7, #ICACHE
|
||||
beq .Ldone_disable
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
bic r0, #(1<<12)
|
||||
mcr p15, 0, r0, c1, c0, 0 // disable icache
|
||||
|
||||
.Ldone_disable:
|
||||
// make sure the icache is always invalidated
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
msr cpsr, r12
|
||||
ldmfd sp!, {r4-r11, pc}
|
||||
|
||||
/* void arch_enable_cache(uint flags) */
|
||||
FUNCTION(arch_enable_cache)
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
|
||||
mov r7, r0 // save flags
|
||||
|
||||
mrs r12, cpsr // save the old interrupt state
|
||||
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
|
||||
|
||||
.Ldcache_enable:
|
||||
tst r7, #DCACHE
|
||||
beq .Licache_enable
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
tst r0, #(1<<2) // is the dcache already enabled?
|
||||
bne .Licache_enable
|
||||
|
||||
// invalidate L1 and L2
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl invalidate_cache_v7
|
||||
|
||||
#if ARM_WITH_L2
|
||||
// enable the L2, if present
|
||||
mrc p15, 0, r0, c1, c0, 1 // aux cr1
|
||||
orr r0, #(1<<1)
|
||||
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
|
||||
#endif
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
orr r0, #(1<<2)
|
||||
mcr p15, 0, r0, c1, c0, 0 // enable dcache
|
||||
|
||||
.Licache_enable:
|
||||
tst r7, #ICACHE
|
||||
beq .Ldone_enable
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
orr r0, #(1<<12)
|
||||
mcr p15, 0, r0, c1, c0, 0 // enable icache
|
||||
|
||||
.Ldone_enable:
|
||||
msr cpsr, r12
|
||||
ldmfd sp!, {r4-r11, pc}
|
||||
|
||||
// flush & invalidate cache routine, trashes r0-r6, r9-r11
|
||||
flush_invalidate_cache_v7:
|
||||
/* from ARMv7 manual, B2-17 */
|
||||
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
|
||||
ANDS R3, R0, #0x7000000
|
||||
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
|
||||
BEQ .Lfinished
|
||||
MOV R10, #0
|
||||
.Loop1:
|
||||
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
|
||||
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
|
||||
AND R1, R1, #7 // get those 3 bits alone
|
||||
CMP R1, #2
|
||||
BLT .Lskip // no cache or only instruction cache at this level
|
||||
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
|
||||
.word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
|
||||
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
|
||||
AND R2, R1, #0x7 // extract the line length field
|
||||
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
|
||||
LDR R4, =0x3FF
|
||||
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
|
||||
CLZ R5, R4 // R5 is the bit position of the way size increment
|
||||
LDR R6, =0x00007FFF
|
||||
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
|
||||
.Loop2:
|
||||
MOV R9, R4 // R9 working copy of the max way size (right aligned)
|
||||
.Loop3:
|
||||
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
|
||||
ORR R11, R11, R6, LSL R2 // factor in the index number
|
||||
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
|
||||
SUBS R9, R9, #1 // decrement the way number
|
||||
BGE .Loop3
|
||||
SUBS R6, R6, #1 // decrement the index
|
||||
BGE .Loop2
|
||||
.Lskip:
|
||||
ADD R10, R10, #2 // increment the cache number
|
||||
CMP R3, R10
|
||||
BGT .Loop1
|
||||
|
||||
.Lfinished:
|
||||
mov r10, #0
|
||||
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
|
||||
.word 0xf57ff06f // isb
|
||||
|
||||
bx lr
|
||||
|
||||
// invalidate cache routine, trashes r0-r6, r9-r11
|
||||
invalidate_cache_v7:
|
||||
/* from ARMv7 manual, B2-17 */
|
||||
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
|
||||
ANDS R3, R0, #0x7000000
|
||||
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
|
||||
BEQ .Lfinished_invalidate
|
||||
MOV R10, #0
|
||||
.Loop1_invalidate:
|
||||
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
|
||||
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
|
||||
AND R1, R1, #7 // get those 3 bits alone
|
||||
CMP R1, #2
|
||||
BLT .Lskip_invalidate // no cache or only instruction cache at this level
|
||||
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
|
||||
.word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
|
||||
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
|
||||
AND R2, R1, #0x7 // extract the line length field
|
||||
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
|
||||
LDR R4, =0x3FF
|
||||
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
|
||||
CLZ R5, R4 // R5 is the bit position of the way size increment
|
||||
LDR R6, =0x00007FFF
|
||||
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
|
||||
.Loop2_invalidate:
|
||||
MOV R9, R4 // R9 working copy of the max way size (right aligned)
|
||||
.Loop3_invalidate:
|
||||
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
|
||||
ORR R11, R11, R6, LSL R2 // factor in the index number
|
||||
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
|
||||
SUBS R9, R9, #1 // decrement the way number
|
||||
BGE .Loop3_invalidate
|
||||
SUBS R6, R6, #1 // decrement the index
|
||||
BGE .Loop2_invalidate
|
||||
.Lskip_invalidate:
|
||||
ADD R10, R10, #2 // increment the cache number
|
||||
CMP R3, R10
|
||||
BGT .Loop1_invalidate
|
||||
|
||||
.Lfinished_invalidate:
|
||||
mov r10, #0
|
||||
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
|
||||
.word 0xf57ff06f // isb
|
||||
|
||||
bx lr
|
||||
|
||||
#else
|
||||
#error unhandled cpu
|
||||
#endif
|
||||
|
||||
#if ARM_CPU_ARM926 || ARM_CPU_ARM1136 || ARM_CPU_CORTEX_A8
|
||||
/* shared cache flush routines */
|
||||
|
||||
/* void arch_flush_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_clean_cache_range)
|
||||
0:
|
||||
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
|
||||
add r0, r0, #CACHE_LINE
|
||||
subs r1, r1, #CACHE_LINE
|
||||
bhs 0b
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
|
||||
|
||||
bx lr
|
||||
|
||||
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_clean_invalidate_cache_range)
|
||||
0:
|
||||
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate cache to PoC by MVA
|
||||
add r0, r0, #CACHE_LINE
|
||||
subs r1, r1, #CACHE_LINE
|
||||
bhs 0b
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
|
||||
|
||||
bx lr
|
||||
|
||||
/* void arch_sync_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_sync_cache_range)
|
||||
push { r14 }
|
||||
bl arch_clean_cache_range
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
pop { pc }
|
||||
|
||||
#else
|
||||
#error unhandled cpu
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* no cache */
|
||||
|
||||
FUNCTION(arch_disable_cache)
|
||||
bx lr
|
||||
|
||||
FUNCTION(arch_enable_cache)
|
||||
bx lr
|
||||
|
||||
FUNCTION(arch_clean_cache_range)
|
||||
bx lr
|
||||
|
||||
FUNCTION(arch_clean_invalidate_cache_range)
|
||||
bx lr
|
||||
|
||||
FUNCTION(arch_sync_cache_range)
|
||||
bx lr
|
||||
|
||||
#endif // ARM_WITH_CACHE
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(THUMBCFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(THUMBCFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
# to override thumb setting, mark the .o file as .Ao
|
||||
$(BUILDDIR)/%.Ao: %.c $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
$(BUILDDIR)/%.Ao: %.cpp $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
# assembly is always compiled in ARM mode at the moment
|
||||
$(BUILDDIR)/%.Ao: %.S $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
ifeq ($(ENABLE_TRUSTZONE), 1)
|
||||
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) -DENABLE_TRUSTZONE $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
else
|
||||
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
endif
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define DSB .byte 0x4f, 0xf0, 0x7f, 0xf5
|
||||
#define ISB .byte 0x6f, 0xf0, 0x7f, 0xf5
|
||||
|
||||
.section ".text.boot"
|
||||
.globl _start
|
||||
_start:
|
||||
b reset
|
||||
b arm_undefined
|
||||
b arm_syscall
|
||||
b arm_prefetch_abort
|
||||
b arm_data_abort
|
||||
b arm_reserved
|
||||
b arm_irq
|
||||
b arm_fiq
|
||||
|
||||
reset:
|
||||
#ifdef HANDLE_LINUX_KERNEL_ARGS
|
||||
/* save (possible) linux kernel args to pass to kmain */
|
||||
mov r8, r0
|
||||
mov r9, r1
|
||||
mov r10, r2
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_TRUSTZONE
|
||||
/*Add reference to TZ symbol so linker includes it in final image */
|
||||
ldr r7, =_binary_tzbsp_tzbsp_bin_start
|
||||
#endif
|
||||
/* do some cpu setup */
|
||||
#if ARM_WITH_CP15
|
||||
/* Read SCTLR */
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
/* XXX this is currently for arm926, revist with armv6 cores */
|
||||
/* new thumb behavior, low exception vectors, i/d cache disable, mmu disabled */
|
||||
bic r0, r0, #(1<<15| 1<<13 | 1<<12)
|
||||
bic r0, r0, #(1<<2 | 1<<0)
|
||||
/* enable alignment faults */
|
||||
orr r0, r0, #(1<<1)
|
||||
/* Write SCTLR */
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
#ifdef ENABLE_TRUSTZONE
|
||||
/*nkazi: not needed ? Setting VBAR to location of new vector table : 0x80000 */
|
||||
ldr r0, =0x00080000
|
||||
mcr p15, 0, r0, c12, c0, 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if WITH_CPU_EARLY_INIT
|
||||
/* call platform/arch/etc specific init code */
|
||||
#ifndef ENABLE_TRUSTZONE
|
||||
/* Not needed when TrustZone is the first bootloader that runs.*/
|
||||
bl __cpu_early_init
|
||||
#endif
|
||||
/* declare return address as global to avoid using stack */
|
||||
.globl _cpu_early_init_complete
|
||||
_cpu_early_init_complete:
|
||||
|
||||
#endif
|
||||
|
||||
#if (!ENABLE_NANDWRITE)
|
||||
#if WITH_CPU_WARM_BOOT
|
||||
ldr r0, warm_boot_tag
|
||||
cmp r0, #1
|
||||
|
||||
/* if set, warm boot */
|
||||
ldreq pc, =BASE_ADDR
|
||||
|
||||
mov r0, #1
|
||||
str r0, warm_boot_tag
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* see if we need to relocate */
|
||||
mov r0, pc
|
||||
sub r0, r0, #(.Laddr - _start)
|
||||
.Laddr:
|
||||
ldr r1, =_start
|
||||
cmp r0, r1
|
||||
beq .Lstack_setup
|
||||
|
||||
/* we need to relocate ourselves to the proper spot */
|
||||
ldr r2, =__data_end
|
||||
|
||||
.Lrelocate_loop:
|
||||
ldr r3, [r0], #4
|
||||
str r3, [r1], #4
|
||||
cmp r1, r2
|
||||
bne .Lrelocate_loop
|
||||
|
||||
/* we're relocated, jump to the right address */
|
||||
ldr r0, =.Lstack_setup
|
||||
bx r0
|
||||
|
||||
.ltorg
|
||||
#if WITH_CPU_WARM_BOOT
|
||||
warm_boot_tag:
|
||||
.word 0
|
||||
#endif
|
||||
|
||||
.Lstack_setup:
|
||||
/* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1f
|
||||
|
||||
ldr r2, =abort_stack_top
|
||||
orr r1, r0, #0x12 // irq
|
||||
msr cpsr_c, r1
|
||||
ldr r13, =irq_save_spot /* save a pointer to a temporary dumping spot used during irq delivery */
|
||||
|
||||
orr r1, r0, #0x11 // fiq
|
||||
msr cpsr_c, r1
|
||||
mov sp, r2
|
||||
|
||||
orr r1, r0, #0x17 // abort
|
||||
msr cpsr_c, r1
|
||||
mov sp, r2
|
||||
|
||||
orr r1, r0, #0x1b // undefined
|
||||
msr cpsr_c, r1
|
||||
mov sp, r2
|
||||
|
||||
orr r1, r0, #0x1f // system
|
||||
msr cpsr_c, r1
|
||||
mov sp, r2
|
||||
|
||||
orr r1, r0, #0x13 // supervisor
|
||||
msr cpsr_c, r1
|
||||
mov sp, r2
|
||||
|
||||
/* copy the initialized data segment out of rom if necessary */
|
||||
ldr r0, =__data_start_rom
|
||||
ldr r1, =__data_start
|
||||
ldr r2, =__data_end
|
||||
|
||||
cmp r0, r1
|
||||
beq .L__do_bss
|
||||
|
||||
.L__copy_loop:
|
||||
cmp r1, r2
|
||||
ldrlt r3, [r0], #4
|
||||
strlt r3, [r1], #4
|
||||
blt .L__copy_loop
|
||||
|
||||
.L__do_bss:
|
||||
/* clear out the bss */
|
||||
ldr r0, =__bss_start
|
||||
ldr r1, =_end
|
||||
mov r2, #0
|
||||
.L__bss_loop:
|
||||
cmp r0, r1
|
||||
strlt r2, [r0], #4
|
||||
blt .L__bss_loop
|
||||
|
||||
#ifdef ARM_CPU_CORTEX_A8
|
||||
DSB
|
||||
ISB
|
||||
#endif
|
||||
|
||||
#ifdef HANDLE_LINUX_KERNEL_ARGS
|
||||
/* pass (possible) linux kernel args to kmain */
|
||||
mov r0, r8
|
||||
mov r1, r9
|
||||
mov r2, r10
|
||||
#endif
|
||||
|
||||
bl kmain
|
||||
b .
|
||||
|
||||
.ltorg
|
||||
|
||||
.bss
|
||||
.align 2
|
||||
/* the abort stack is for unrecoverable errors.
|
||||
* also note the initial working stack is set to here.
|
||||
* when the threading system starts up it'll switch to a new
|
||||
* dynamically allocated stack, so we don't need it for very long
|
||||
*/
|
||||
abort_stack:
|
||||
.skip 1024
|
||||
abort_stack_top:
|
||||
|
||||
.rodata:
|
||||
.align 2
|
||||
|
||||
/* define the heap end as read-only data containing the end defined in the
|
||||
* linker script. other archs that use dynamic memory length discovery can make
|
||||
* this read-write and update it during init.
|
||||
*/
|
||||
.global _heap_end
|
||||
_heap_end:
|
||||
.int _end_of_ram
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Brian Swetland
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
.global dcc_putc
|
||||
.global dcc_getc
|
||||
|
||||
#if defined(ARM_ISA_ARMV6) || defined(ARM_ISA_ARMV7)
|
||||
dcc_getc:
|
||||
mrc 14, 0, r0, c0, c1, 0
|
||||
tst r0, #(1 << 30)
|
||||
moveq r0, #-1
|
||||
mrcne 14, 0, r0, c0, c5, 0
|
||||
bx lr
|
||||
|
||||
dcc_putc:
|
||||
mrc 14, 0, r15, c0, c1, 0
|
||||
mcrcc 14, 0, r0, c0, c5, 0
|
||||
movcc r0, #0
|
||||
movcs r0, #-1
|
||||
bx lr
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
|
||||
FUNCTION(arm_undefined)
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }^
|
||||
b arm_undefined_handler
|
||||
b .
|
||||
|
||||
FUNCTION(arm_syscall)
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }^
|
||||
b arm_syscall_handler
|
||||
b .
|
||||
|
||||
FUNCTION(arm_prefetch_abort)
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }^
|
||||
b arm_prefetch_abort_handler
|
||||
b .
|
||||
|
||||
FUNCTION(arm_data_abort)
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }^
|
||||
b arm_data_abort_handler
|
||||
b .
|
||||
|
||||
FUNCTION(arm_reserved)
|
||||
b .
|
||||
|
||||
FUNCTION(arm_irq)
|
||||
/* XXX only deals with interrupting supervisor mode */
|
||||
|
||||
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
|
||||
stmia r13, { r4-r6 }
|
||||
mov r4, r13
|
||||
sub r5, lr, #4
|
||||
mrs r6, spsr
|
||||
|
||||
/* move into supervisor mode. irq/fiq disabled */
|
||||
msr cpsr_c, #(3<<6 | 0x13)
|
||||
|
||||
/* save the return address */
|
||||
stmfd sp!, { r5 }
|
||||
|
||||
/* save C trashed regs, supervisor lr */
|
||||
stmfd sp!, { r0-r3, r12, lr }
|
||||
|
||||
/* save spsr */
|
||||
stmfd sp!, { r6 }
|
||||
|
||||
/* restore r4-r6 */
|
||||
ldmia r4, { r4-r6 }
|
||||
|
||||
/* increment the global critical section count */
|
||||
ldr r1, =critical_section_count
|
||||
ldr r0, [r1]
|
||||
add r0, r0, #1
|
||||
str r0, [r1]
|
||||
|
||||
/* call into higher level code */
|
||||
mov r0, sp /* iframe */
|
||||
bl platform_irq
|
||||
|
||||
/* reschedule if the handler returns nonzero */
|
||||
cmp r0, #0
|
||||
blne thread_preempt
|
||||
|
||||
/* decrement the global critical section count */
|
||||
ldr r1, =critical_section_count
|
||||
ldr r0, [r1]
|
||||
sub r0, r0, #1
|
||||
str r0, [r1]
|
||||
|
||||
/* restore spsr */
|
||||
ldmfd sp!, { r0 }
|
||||
msr spsr_cxsf, r0
|
||||
|
||||
/* restore back to where we came from */
|
||||
ldmfd sp!, { r0-r3, r12, lr, pc }^
|
||||
|
||||
.bss
|
||||
.align 2
|
||||
.global irq_save_spot
|
||||
irq_save_spot:
|
||||
.word 0 /* r4 */
|
||||
.word 0 /* r5 */
|
||||
.word 0 /* r6 */
|
||||
|
||||
.text
|
||||
FUNCTION(arm_fiq)
|
||||
sub lr, lr, #4
|
||||
stmfd sp!, { r0-r3, r12, lr }
|
||||
|
||||
bl platform_fiq
|
||||
|
||||
ldmfd sp!, { r0-r3, r12, pc }^
|
||||
|
||||
.ltorg
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <arch/arm.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
static void dump_fault_frame(struct arm_fault_frame *frame)
|
||||
{
|
||||
dprintf(CRITICAL, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
|
||||
dprintf(CRITICAL, "r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
|
||||
dprintf(CRITICAL, "r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
|
||||
dprintf(CRITICAL, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
|
||||
dprintf(CRITICAL, "spsr 0x%08x\n", frame->spsr);
|
||||
|
||||
struct arm_mode_regs regs;
|
||||
arm_save_mode_regs(®s);
|
||||
|
||||
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
|
||||
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
|
||||
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", regs.svc_r13, regs.svc_r14);
|
||||
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
|
||||
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
|
||||
|
||||
// dump the bottom of the current stack
|
||||
addr_t stack;
|
||||
switch (frame->spsr & MODE_MASK) {
|
||||
case MODE_FIQ: stack = regs.fiq_r13; break;
|
||||
case MODE_IRQ: stack = regs.irq_r13; break;
|
||||
case MODE_SVC: stack = regs.svc_r13; break;
|
||||
case MODE_UND: stack = regs.und_r13; break;
|
||||
case MODE_SYS: stack = regs.sys_r13; break;
|
||||
default:
|
||||
stack = 0;
|
||||
}
|
||||
|
||||
if (stack != 0) {
|
||||
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
|
||||
hexdump((void *)stack, 128);
|
||||
}
|
||||
}
|
||||
|
||||
static void exception_die(struct arm_fault_frame *frame, int pc_off, const char *msg)
|
||||
{
|
||||
inc_critical_section();
|
||||
frame->pc += pc_off;
|
||||
dprintf(CRITICAL, msg);
|
||||
dump_fault_frame(frame);
|
||||
|
||||
halt();
|
||||
for(;;);
|
||||
}
|
||||
|
||||
void arm_syscall_handler(struct arm_fault_frame *frame)
|
||||
{
|
||||
exception_die(frame, -4, "unhandled syscall, halting\n");
|
||||
}
|
||||
|
||||
void arm_undefined_handler(struct arm_fault_frame *frame)
|
||||
{
|
||||
exception_die(frame, -4, "undefined abort, halting\n");
|
||||
}
|
||||
|
||||
void arm_data_abort_handler(struct arm_fault_frame *frame)
|
||||
{
|
||||
exception_die(frame, -8, "data abort, halting\n");
|
||||
}
|
||||
|
||||
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
|
||||
{
|
||||
exception_die(frame, -4, "prefetch abort, halting\n");
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARM_ARCH_THREAD_H
|
||||
#define __ARM_ARCH_THREAD_H
|
||||
|
||||
struct arch_thread {
|
||||
vaddr_t sp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_H
|
||||
#define __ARCH_ARM_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <arch/arm/cores.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void arm_context_switch(vaddr_t *old_sp, vaddr_t new_sp);
|
||||
|
||||
static inline uint32_t read_cpsr() {
|
||||
uint32_t cpsr;
|
||||
|
||||
__asm__ volatile("mrs %0, cpsr" : "=r" (cpsr));
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
struct arm_iframe {
|
||||
uint32_t spsr;
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
};
|
||||
|
||||
struct arm_fault_frame {
|
||||
uint32_t spsr;
|
||||
uint32_t usp;
|
||||
uint32_t ulr;
|
||||
uint32_t r[13];
|
||||
uint32_t pc;
|
||||
};
|
||||
|
||||
#define MODE_MASK 0x1f
|
||||
#define MODE_USR 0x10
|
||||
#define MODE_FIQ 0x11
|
||||
#define MODE_IRQ 0x12
|
||||
#define MODE_SVC 0x13
|
||||
#define MODE_MON 0x16
|
||||
#define MODE_ABT 0x17
|
||||
#define MODE_UND 0x1b
|
||||
#define MODE_SYS 0x1f
|
||||
|
||||
struct arm_mode_regs {
|
||||
uint32_t fiq_r13, fiq_r14;
|
||||
uint32_t irq_r13, irq_r14;
|
||||
uint32_t svc_r13, svc_r14;
|
||||
uint32_t abt_r13, abt_r14;
|
||||
uint32_t und_r13, und_r14;
|
||||
uint32_t sys_r13, sys_r14;
|
||||
};
|
||||
|
||||
void arm_save_mode_regs(struct arm_mode_regs *regs);
|
||||
|
||||
uint32_t arm_read_cr1(void);
|
||||
void arm_write_cr1(uint32_t val);
|
||||
uint32_t arm_read_cr1_aux(void);
|
||||
void arm_write_cr1_aux(uint32_t val);
|
||||
void arm_write_ttbr(uint32_t val);
|
||||
void arm_write_dacr(uint32_t val);
|
||||
void arm_invalidate_tlb(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARM_CORES_H
|
||||
#define __ARM_CORES_H
|
||||
|
||||
/*
|
||||
* make the gcc built in define a little easier to deal with
|
||||
* to decide what core it is generating code for
|
||||
*
|
||||
* ARM_ARCH_LEVEL gets assigned a numeric value of the general family
|
||||
*
|
||||
* ARM_ARCH_* gets defined for each feature recursively
|
||||
*/
|
||||
|
||||
#if defined(__ARM_ARCH_7M__)
|
||||
#define ARM_ARCH_7M 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_7R__)
|
||||
#define ARM_ARCH_7R 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_7A__) || defined(ARM_ARCH_7R)
|
||||
#define ARM_ARCH_7A 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_7__) || defined(ARM_ARCH_7A) || defined(ARM_ARCH_7M)
|
||||
#define ARM_ARCH_7 1
|
||||
#ifndef ARM_ARCH_LEVEL
|
||||
#define ARM_ARCH_LEVEL 7
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
#define ARM_ARCH_6M 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_6T2__) || defined(ARM_ARCH_7)
|
||||
#define ARM_ARCH_6T2 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_6ZK__)
|
||||
#define ARM_ARCH_6ZK 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_6Z__) || defined(ARM_ARCH_6ZK)
|
||||
#define ARM_ARCH_6Z 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_6K__) || defined(ARM_ARCH_6ZK) || defined(ARM_ARCH_7)
|
||||
#define ARM_ARCH_6K 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_6J__)
|
||||
#define ARM_ARCH_6J 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_6__) || defined(ARM_ARCH_6J) || defined(ARM_ARCH_6K) || defined(ARM_ARCH_6Z) || defined(ARM_ARCH_6T2) || defined(ARM_ARCH_6M)
|
||||
#define ARM_ARCH_6 1
|
||||
#ifndef ARM_ARCH_LEVEL
|
||||
#define ARM_ARCH_LEVEL 6
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_5TEJ__)
|
||||
#define ARM_ARCH_5TEJ 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_5TE__) || defined(ARM_ARCH_5TEJ) || defined(ARM_ARCH_6)
|
||||
#define ARM_ARCH_5TE 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_5E__) || defined(ARM_ARCH_5TE)
|
||||
#define ARM_ARCH_5E 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_5T__) || defined(ARM_ARCH_5TE)
|
||||
#define ARM_ARCH_5T 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_5__) || defined(ARM_ARCH_5E) || defined(ARM_ARCH_5T)
|
||||
#define ARM_ARCH_5 1
|
||||
#ifndef ARM_ARCH_LEVEL
|
||||
#define ARM_ARCH_LEVEL 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_4T__) || defined(ARM_ARCH_5T)
|
||||
#define ARM_ARCH_4T 1
|
||||
#endif
|
||||
#if defined(__ARM_ARCH_4__) || defined(ARM_ARCH_4T) || defined(ARM_ARCH_5)
|
||||
#define ARM_ARCH_4 1
|
||||
#ifndef ARM_ARCH_LEVEL
|
||||
#define ARM_ARCH_LEVEL 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* test */
|
||||
#if ARM_ARCH_LEVEL >= 7
|
||||
#warning ARM_ARCH_LEVEL >= 7
|
||||
#endif
|
||||
#if ARM_ARCH_LEVEL >= 6
|
||||
#warning ARM_ARCH_LEVEL >= 6
|
||||
#endif
|
||||
#if ARM_ARCH_LEVEL >= 5
|
||||
#warning ARM_ARCH_LEVEL >= 5
|
||||
#endif
|
||||
#if ARM_ARCH_LEVEL >= 4
|
||||
#warning ARM_ARCH_LEVEL >= 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Brian Swetland
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_DCC_H
|
||||
#define __ARCH_ARM_DCC_H
|
||||
|
||||
/* returns < 0 if no data available */
|
||||
int dcc_getc(void);
|
||||
|
||||
/* returns < 0 if output register was already full */
|
||||
int dcc_putc(unsigned c);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MMU_H
|
||||
#define __ARCH_ARM_MMU_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void arm_mmu_init(void);
|
||||
|
||||
#if defined(ARM_ISA_ARMV6) | defined(ARM_ISA_ARMV7)
|
||||
|
||||
/* C, B and TEX[2:0] encodings without TEX remap */
|
||||
/* TEX | CB */
|
||||
#define MMU_MEMORY_TYPE_STRONGLY_ORDERED ((0x0 << 12) | (0x0 << 2))
|
||||
#define MMU_MEMORY_TYPE_DEVICE_SHARED ((0x0 << 12) | (0x1 << 2))
|
||||
#define MMU_MEMORY_TYPE_DEVICE_NON_SHARED ((0x2 << 12) | (0x0 << 2))
|
||||
#define MMU_MEMORY_TYPE_NORMAL ((0x1 << 12) | (0x0 << 2))
|
||||
#define MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH ((0x0 << 12) | (0x2 << 2))
|
||||
#define MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_NO_ALLOCATE ((0x0 << 12) | (0x3 << 2))
|
||||
#define MMU_MEMORY_TYPE_NORMAL_WRITE_BACK_ALLOCATE ((0x1 << 12) | (0x3 << 2))
|
||||
|
||||
#define MMU_MEMORY_AP_NO_ACCESS (0x0 << 10)
|
||||
#define MMU_MEMORY_AP_READ_ONLY (0x7 << 10)
|
||||
#define MMU_MEMORY_AP_READ_WRITE (0x3 << 10)
|
||||
|
||||
#else
|
||||
|
||||
#error "MMU implementation needs to be updated for this ARM architecture"
|
||||
|
||||
#endif
|
||||
|
||||
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_OPS_H
|
||||
#define __ARHC_ARM_OPS_H
|
||||
|
||||
#if 0
|
||||
#include <compiler.h>
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#if ARM_ISA_ARMV7 || ARM_ISA_ARMV6
|
||||
// override of some routines
|
||||
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
|
||||
{
|
||||
__asm__("cpsie i");
|
||||
}
|
||||
|
||||
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
|
||||
{
|
||||
__asm__("cpsid i");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_CPU_H
|
||||
#define __ARCH_CPU_H
|
||||
|
||||
/* arm specific stuff */
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
#if defined(ARM_CPU_ARM1136)
|
||||
#define CACHE_LINE 32
|
||||
#elif defined(ARM_CPU_CORE_A5)
|
||||
#define CACHE_LINE 32
|
||||
#elif defined(ARM_CPU_CORE_SCORPION)
|
||||
#define CACHE_LINE 32
|
||||
#elif defined(ARM_CPU_CORE_KRAIT)
|
||||
#define CACHE_LINE 64
|
||||
#else
|
||||
#error unknown cpu
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <sys/types.h>
|
||||
#include <compiler.h>
|
||||
#include <arch.h>
|
||||
#include <arch/arm.h>
|
||||
#include <arch/arm/mmu.h>
|
||||
|
||||
#if ARM_WITH_MMU
|
||||
|
||||
#define MB (1024*1024)
|
||||
|
||||
/* the location of the table may be brought in from outside */
|
||||
#if WITH_EXTERNAL_TRANSLATION_TABLE
|
||||
#if !defined(MMU_TRANSLATION_TABLE_ADDR)
|
||||
#error must set MMU_TRANSLATION_TABLE_ADDR in the make configuration
|
||||
#endif
|
||||
static uint32_t *tt = (void *)MMU_TRANSLATION_TABLE_ADDR;
|
||||
#else
|
||||
/* the main translation table */
|
||||
static uint32_t tt[4096] __ALIGNED(16384);
|
||||
#endif
|
||||
|
||||
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
|
||||
{
|
||||
int index;
|
||||
|
||||
/* Get the index into the translation table */
|
||||
index = vaddr / MB;
|
||||
|
||||
/* Set the entry value:
|
||||
* (2<<0): Section entry
|
||||
* (0<<5): Domain = 0
|
||||
* flags: TEX, CB and AP bit settings provided by the caller.
|
||||
*/
|
||||
tt[index] = (paddr & ~(MB-1)) | (0<<5) | (2<<0) | flags;
|
||||
|
||||
arm_invalidate_tlb();
|
||||
}
|
||||
|
||||
void arm_mmu_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* set some mmu specific control bits:
|
||||
* access flag disabled, TEX remap disabled, mmu disabled
|
||||
*/
|
||||
arm_write_cr1(arm_read_cr1() & ~((1<<29)|(1<<28)|(1<<0)));
|
||||
|
||||
/* set up an identity-mapped translation table with
|
||||
* strongly ordered memory type and read/write access.
|
||||
*/
|
||||
for (i=0; i < 4096; i++) {
|
||||
arm_mmu_map_section(i * MB,
|
||||
i * MB,
|
||||
MMU_MEMORY_TYPE_STRONGLY_ORDERED |
|
||||
MMU_MEMORY_AP_READ_WRITE);
|
||||
}
|
||||
|
||||
/* set up the translation table base */
|
||||
arm_write_ttbr((uint32_t)tt);
|
||||
|
||||
/* set up the domain access register */
|
||||
arm_write_dacr(0x00000001);
|
||||
|
||||
/* turn on the mmu */
|
||||
arm_write_cr1(arm_read_cr1() | 0x1);
|
||||
}
|
||||
|
||||
void arch_disable_mmu(void)
|
||||
{
|
||||
arm_write_cr1(arm_read_cr1() & ~(1<<0));
|
||||
}
|
||||
|
||||
#endif // ARM_WITH_MMU
|
||||
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
|
||||
.text
|
||||
|
||||
/* void arch_enable_ints(void); */
|
||||
FUNCTION(arch_enable_ints)
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #(1<<7) /* clear the I bit */
|
||||
msr cpsr_c, r0
|
||||
bx lr
|
||||
|
||||
/* void arch_disable_ints(void); */
|
||||
FUNCTION(arch_disable_ints)
|
||||
mrs r0, cpsr
|
||||
orr r0, r0, #(1<<7)
|
||||
msr cpsr_c, r0
|
||||
bx lr
|
||||
|
||||
/* int atomic_swap(int *ptr, int val); */
|
||||
FUNCTION(atomic_swap)
|
||||
swp r0, r2, [r1]
|
||||
bx lr
|
||||
|
||||
/* int atomic_add(int *ptr, int val); */
|
||||
FUNCTION(atomic_add)
|
||||
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
|
||||
/* use load/store exclusive */
|
||||
.L_loop_add:
|
||||
ldrex r12, [r0]
|
||||
add r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .L_loop_add
|
||||
|
||||
/* save old value */
|
||||
mov r0, r12
|
||||
bx lr
|
||||
#else
|
||||
/* disable interrupts, do the add, and reenable */
|
||||
mrs r2, cpsr
|
||||
mov r12, r2
|
||||
orr r2, r2, #(3<<6)
|
||||
msr cpsr_c, r2
|
||||
|
||||
/* ints disabled, old cpsr state in r12 */
|
||||
|
||||
/* do the add, leave the previous value in r0 */
|
||||
mov r3, r0
|
||||
ldr r0, [r3]
|
||||
add r2, r0, r1
|
||||
str r2, [r3]
|
||||
|
||||
/* restore interrupts and exit */
|
||||
msr cpsr_c, r12
|
||||
bx lr
|
||||
#endif
|
||||
|
||||
/* int atomic_and(int *ptr, int val); */
|
||||
FUNCTION(atomic_and)
|
||||
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
|
||||
/* use load/store exclusive */
|
||||
.L_loop_and:
|
||||
ldrex r12, [r0]
|
||||
and r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .L_loop_and
|
||||
|
||||
/* save old value */
|
||||
mov r0, r12
|
||||
bx lr
|
||||
#else
|
||||
/* disable interrupts, do the and, and reenable */
|
||||
mrs r2, cpsr
|
||||
mov r12, r2
|
||||
orr r2, r2, #(3<<6)
|
||||
msr cpsr_c, r2
|
||||
|
||||
/* ints disabled, old cpsr state in r12 */
|
||||
|
||||
/* do the and, leave the previous value in r0 */
|
||||
mov r3, r0
|
||||
ldr r0, [r3]
|
||||
and r2, r0, r1
|
||||
str r2, [r3]
|
||||
|
||||
/* restore interrupts and exit */
|
||||
msr cpsr_c, r12
|
||||
bx lr
|
||||
#endif
|
||||
|
||||
/* int atomic_or(int *ptr, int val); */
|
||||
FUNCTION(atomic_or)
|
||||
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
|
||||
/* use load/store exclusive */
|
||||
.L_loop_or:
|
||||
ldrex r12, [r0]
|
||||
orr r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .L_loop_or
|
||||
|
||||
/* save old value */
|
||||
mov r0, r12
|
||||
bx lr
|
||||
#else
|
||||
/* disable interrupts, do the or, and reenable */
|
||||
mrs r2, cpsr
|
||||
mov r12, r2
|
||||
orr r2, r2, #(3<<6)
|
||||
msr cpsr_c, r2
|
||||
|
||||
/* ints disabled, old cpsr state in r12 */
|
||||
|
||||
/* do the or, leave the previous value in r0 */
|
||||
mov r3, r0
|
||||
ldr r0, [r3]
|
||||
orr r2, r0, r1
|
||||
str r2, [r3]
|
||||
|
||||
/* restore interrupts and exit */
|
||||
msr cpsr_c, r12
|
||||
bx lr
|
||||
#endif
|
||||
|
||||
/* void arch_idle(); */
|
||||
FUNCTION(arch_idle)
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
.word 0xe320f003 /* wfi */
|
||||
#elif PLATFORM_MSM7K
|
||||
/* TODO: safely handle wfi */
|
||||
#elif ARM_CPU_ARM1136 || ARM_CPU_ARM926
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c0, #4
|
||||
#elif ARM_CPU_ARM7
|
||||
/* nothing to do here */
|
||||
#else
|
||||
#error unknown cpu
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* uint32_t arm_read_cr1(void) */
|
||||
FUNCTION(arm_read_cr1)
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bx lr
|
||||
|
||||
/* void arm_write_cr1(uint32_t val) */
|
||||
FUNCTION(arm_write_cr1)
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
bx lr
|
||||
|
||||
/* uint32_t arm_read_cr1_aux(void) */
|
||||
FUNCTION(arm_read_cr1_aux)
|
||||
mrc p15, 0, r0, c1, c0, 1
|
||||
bx lr
|
||||
|
||||
/* void arm_write_cr1_aux(uint32_t val) */
|
||||
FUNCTION(arm_write_cr1_aux)
|
||||
mcr p15, 0, r0, c1, c0, 1
|
||||
bx lr
|
||||
|
||||
/* void arm_write_ttbr(uint32_t val) */
|
||||
FUNCTION(arm_write_ttbr)
|
||||
mcr p15, 0, r0, c2, c0, 0
|
||||
bx lr
|
||||
|
||||
/* void arm_write_dacr(uint32_t val) */
|
||||
FUNCTION(arm_write_dacr)
|
||||
mcr p15, 0, r0, c3, c0, 0
|
||||
bx lr
|
||||
|
||||
/* void arm_invalidate_tlb(void) */
|
||||
FUNCTION(arm_invalidate_tlb)
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c8, c7, 0
|
||||
bx lr
|
||||
|
||||
/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
|
||||
FUNCTION(arch_switch_stacks_and_call)
|
||||
mov sp, r1
|
||||
bx r0
|
||||
|
||||
/*void dmb(void) */
|
||||
FUNCTION(dmb)
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
dmb sy
|
||||
#elif ARM_CPU_ARM1136
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 5
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/*void dsb(void) */
|
||||
FUNCTION(dsb)
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
dsb sy
|
||||
#elif ARM_CPU_ARM1136
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* uint32_t arm_read_cycle_count(void); */
|
||||
FUNCTION(arm_read_cycle_count)
|
||||
|
||||
/* uint32_t arch_cycle_count(void); */
|
||||
FUNCTION(arch_cycle_count)
|
||||
#if ARM_CPU_CORTEX_A8
|
||||
mrc p15, 0, r0, c9, c13, 0
|
||||
#else
|
||||
mov r0, #0
|
||||
#endif
|
||||
bx lr
|
||||
@@ -0,0 +1,154 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
# can override this in local.mk
|
||||
ENABLE_THUMB?=true
|
||||
|
||||
DEFINES += \
|
||||
ARM_CPU_$(ARM_CPU)=1
|
||||
|
||||
# do set some options based on the cpu core
|
||||
HANDLED_CORE := false
|
||||
ifeq ($(ARM_CPU),cortex-a8)
|
||||
DEFINES += \
|
||||
ARM_WITH_CP15=1 \
|
||||
ARM_WITH_MMU=1 \
|
||||
ARM_ISA_ARMv7=1 \
|
||||
ARM_WITH_VFP=1 \
|
||||
ARM_WITH_NEON=1 \
|
||||
ARM_WITH_THUMB=1 \
|
||||
ARM_WITH_THUMB2=1 \
|
||||
ARM_WITH_CACHE=1 \
|
||||
ARM_WITH_L2=1
|
||||
CFLAGS += -mcpu=$(ARM_CPU)
|
||||
#CFLAGS += -mcpu=arm1136jf-s # compiler doesn't understand cortex yet
|
||||
HANDLED_CORE := true
|
||||
#CFLAGS += -mfpu=vfp -mfloat-abi=softfp
|
||||
endif
|
||||
ifeq ($(ARM_CPU),arm1136j-s)
|
||||
DEFINES += \
|
||||
ARM_WITH_CP15=1 \
|
||||
ARM_WITH_MMU=1 \
|
||||
ARM_ISA_ARMv6=1 \
|
||||
ARM_WITH_THUMB=1 \
|
||||
ARM_WITH_CACHE=1 \
|
||||
ARM_CPU_ARM1136=1
|
||||
CFLAGS += -mcpu=$(ARM_CPU)
|
||||
HANDLED_CORE := true
|
||||
endif
|
||||
ifeq ($(ARM_CPU),arm1176jzf-s)
|
||||
DEFINES += \
|
||||
ARM_WITH_CP15=1 \
|
||||
ARM_WITH_MMU=1 \
|
||||
ARM_ISA_ARMv6=1 \
|
||||
ARM_WITH_VFP=1 \
|
||||
ARM_WITH_THUMB=1 \
|
||||
ARM_WITH_CACHE=1 \
|
||||
ARM_CPU_ARM1136=1
|
||||
CFLAGS += -mcpu=$(ARM_CPU)
|
||||
HANDLED_CORE := true
|
||||
endif
|
||||
ifeq ($(ARM_CPU),arm926ej-s)
|
||||
DEFINES += \
|
||||
ARM_WITH_CP15=1 \
|
||||
ARM_WITH_MMU=1 \
|
||||
ARM_ISA_ARMv5E=1 \
|
||||
ARM_WITH_THUMB=1 \
|
||||
ARM_WITH_CACHE=1 \
|
||||
ARM_CPU_ARM9=1 \
|
||||
ARM_CPU_ARM926=1
|
||||
CFLAGS += -mcpu=$(ARM_CPU)
|
||||
HANDLED_CORE := true
|
||||
endif
|
||||
ifeq ($(ARM_CPU),arm7tdmi)
|
||||
DEFINES += \
|
||||
ARM_ISA_ARMv4=1 \
|
||||
ARM_WITH_THUMB=1 \
|
||||
ARM_CPU_ARM7=1
|
||||
CFLAGS += -mcpu=$(ARM_CPU)
|
||||
HANDLED_CORE := true
|
||||
endif
|
||||
|
||||
ifneq ($(HANDLED_CORE),true)
|
||||
$(warning $(LOCAL_DIR)/rules.mk doesnt have logic for arm core $(ARM_CPU))
|
||||
$(warning this is likely to be broken)
|
||||
endif
|
||||
|
||||
THUMBCFLAGS :=
|
||||
THUMBINTERWORK :=
|
||||
ifeq ($(ENABLE_THUMB),true)
|
||||
THUMBCFLAGS := -mthumb -D__thumb__
|
||||
THUMBINTERWORK := -mthumb-interwork
|
||||
endif
|
||||
|
||||
INCLUDES += \
|
||||
-I$(LOCAL_DIR)/include
|
||||
|
||||
BOOTOBJS += \
|
||||
$(LOCAL_DIR)/crt0.o
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/arch.Ao \
|
||||
$(LOCAL_DIR)/asm.o \
|
||||
$(LOCAL_DIR)/cache.o \
|
||||
$(LOCAL_DIR)/cache-ops.o \
|
||||
$(LOCAL_DIR)/ops.o \
|
||||
$(LOCAL_DIR)/exceptions.o \
|
||||
$(LOCAL_DIR)/faults.o \
|
||||
$(LOCAL_DIR)/mmu.o \
|
||||
$(LOCAL_DIR)/thread.o \
|
||||
$(LOCAL_DIR)/dcc.o
|
||||
|
||||
# set the default toolchain to arm eabi and set a #define
|
||||
TOOLCHAIN_PREFIX ?= arm-eabi-
|
||||
ifeq ($(TOOLCHAIN_PREFIX),arm-none-linux-gnueabi-)
|
||||
# XXX test for EABI better than this
|
||||
# eabi compilers dont need this
|
||||
THUMBINTERWORK:=
|
||||
endif
|
||||
|
||||
CFLAGS += $(THUMBINTERWORK)
|
||||
|
||||
# make sure some bits were set up
|
||||
MEMVARS_SET := 0
|
||||
ifneq ($(MEMBASE),)
|
||||
MEMVARS_SET := 1
|
||||
endif
|
||||
ifneq ($(MEMSIZE),)
|
||||
MEMVARS_SET := 1
|
||||
endif
|
||||
ifeq ($(MEMVARS_SET),0)
|
||||
$(error missing MEMBASE or MEMSIZE variable, please set in target rules.mk)
|
||||
endif
|
||||
|
||||
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) $(THUMBCFLAGS) -print-libgcc-file-name)
|
||||
#$(info LIBGCC = $(LIBGCC))
|
||||
|
||||
# potentially generated files that should be cleaned out with clean make rule
|
||||
GENERATED += \
|
||||
$(BUILDDIR)/system-onesegment.ld \
|
||||
$(BUILDDIR)/system-twosegment.ld
|
||||
|
||||
# rules for generating the linker scripts
|
||||
|
||||
|
||||
|
||||
$(BUILDDIR)/trustzone-test-system-onesegment.ld: $(LOCAL_DIR)/trustzone-test-system-onesegment.ld
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%ROMLITE_PREFLASHED_DATA%/$(ROMLITE_PREFLASHED_DATA)/" < $< > $@
|
||||
|
||||
$(BUILDDIR)/trustzone-system-onesegment.ld: $(LOCAL_DIR)/trustzone-system-onesegment.ld
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
|
||||
|
||||
$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/system-onesegment.ld
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
|
||||
|
||||
$(BUILDDIR)/system-twosegment.ld: $(LOCAL_DIR)/system-twosegment.ld
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)sed "s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = %MEMBASE%;
|
||||
|
||||
/* text/read-only data */
|
||||
.text.boot : { *(.text.boot) }
|
||||
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) } =0x9090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(4);
|
||||
__commands_start = .;
|
||||
KEEP (*(.commands))
|
||||
__commands_end = .;
|
||||
. = ALIGN(4);
|
||||
__apps_start = .;
|
||||
KEEP (*(.apps))
|
||||
__apps_end = .;
|
||||
. = ALIGN(4);
|
||||
__rodata_end = . ;
|
||||
}
|
||||
|
||||
/* writable data */
|
||||
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
|
||||
__data_start = .;
|
||||
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
|
||||
|
||||
__ctor_list = .;
|
||||
.ctors : { *(.ctors) }
|
||||
__ctor_end = .;
|
||||
__dtor_list = .;
|
||||
.dtors : { *(.dtors) }
|
||||
__dtor_end = .;
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
__data_end = .;
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss .bss.*) }
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = .;
|
||||
|
||||
. = %MEMBASE% + %MEMSIZE%;
|
||||
_end_of_ram = .;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = %ROMBASE%;
|
||||
|
||||
/* text/read-only data */
|
||||
.text.boot : { *(.text.boot) }
|
||||
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) } =0x9090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(4);
|
||||
__commands_start = .;
|
||||
KEEP (*(.commands))
|
||||
__commands_end = .;
|
||||
. = ALIGN(4);
|
||||
__apps_start = .;
|
||||
KEEP (*(.apps))
|
||||
__apps_end = .;
|
||||
. = ALIGN(4);
|
||||
__rodata_end = . ;
|
||||
}
|
||||
|
||||
/* writable data */
|
||||
__data_start_rom = .;
|
||||
. = %MEMBASE%;
|
||||
__data_start = .;
|
||||
.data :
|
||||
AT ( ADDR (.rodata) + SIZEOF (.rodata) )
|
||||
{ *(.data .data.* .gnu.linkonce.d.*) }
|
||||
|
||||
__ctor_list = .;
|
||||
.ctors : { *(.ctors) }
|
||||
__ctor_end = .;
|
||||
__dtor_list = .;
|
||||
.dtors : { *(.dtors) }
|
||||
__dtor_end = .;
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
__data_end = .;
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss .bss.*) }
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
|
||||
. = %MEMBASE% + %MEMSIZE%;
|
||||
_end_of_ram = . ;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <arch/arm.h>
|
||||
|
||||
struct context_switch_frame {
|
||||
vaddr_t r4;
|
||||
vaddr_t r5;
|
||||
vaddr_t r6;
|
||||
vaddr_t r7;
|
||||
vaddr_t r8;
|
||||
vaddr_t r9;
|
||||
vaddr_t r10;
|
||||
vaddr_t r11;
|
||||
vaddr_t lr;
|
||||
vaddr_t usp;
|
||||
vaddr_t ulr;
|
||||
};
|
||||
|
||||
extern void arm_context_switch(addr_t *old_sp, addr_t new_sp);
|
||||
|
||||
static void initial_thread_func(void) __NO_RETURN;
|
||||
static void initial_thread_func(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
|
||||
// dump_thread(current_thread);
|
||||
|
||||
/* exit the implicit critical section we're within */
|
||||
exit_critical_section();
|
||||
|
||||
ret = current_thread->entry(current_thread->arg);
|
||||
|
||||
// dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
|
||||
|
||||
thread_exit(ret);
|
||||
}
|
||||
|
||||
void arch_thread_initialize(thread_t *t)
|
||||
{
|
||||
// create a default stack frame on the stack
|
||||
vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
|
||||
|
||||
// make sure the top of the stack is 8 byte aligned for EABI compliance
|
||||
stack_top = ROUNDDOWN(stack_top, 8);
|
||||
|
||||
struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
|
||||
frame--;
|
||||
|
||||
// fill it in
|
||||
memset(frame, 0, sizeof(*frame));
|
||||
frame->lr = (vaddr_t)&initial_thread_func;
|
||||
|
||||
// set the stack pointer
|
||||
t->arch.sp = (vaddr_t)frame;
|
||||
}
|
||||
|
||||
void arch_context_switch(thread_t *oldthread, thread_t *newthread)
|
||||
{
|
||||
// dprintf("arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
|
||||
arm_context_switch(&oldthread->arch.sp, newthread->arch.sp);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
/*Added TRUSTZONE at 0x0. Moving rest of APPSBL to %MEMBASE% */
|
||||
. = 0x0;
|
||||
.tzbsp 0x0 : {*tzbsp_bin.o(.data)}
|
||||
. = %MEMBASE%;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
/*Moving harcoded addresses by a displacement of %MEMBASE% */
|
||||
.init : { *(.init) } = %MEMBASE% + 0x9090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
/* text/read-only data */
|
||||
|
||||
/*Moving harcoded addresses by a displacement of %MEMBASE% */
|
||||
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } = %MEMBASE% + 0x9090
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(4);
|
||||
__commands_start = .;
|
||||
KEEP (*(.commands))
|
||||
__commands_end = .;
|
||||
. = ALIGN(4);
|
||||
__apps_start = .;
|
||||
KEEP (*(.apps))
|
||||
__apps_end = .;
|
||||
. = ALIGN(4);
|
||||
__rodata_end = . ;
|
||||
}
|
||||
|
||||
/* writable data */
|
||||
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
|
||||
__data_start = .;
|
||||
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
|
||||
|
||||
__ctor_list = .;
|
||||
.ctors : { *(.ctors) }
|
||||
__ctor_end = .;
|
||||
__dtor_list = .;
|
||||
.dtors : { *(.dtors) }
|
||||
__dtor_end = .;
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
__data_end = .;
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss .bss.*) }
|
||||
|
||||
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = .;
|
||||
|
||||
|
||||
|
||||
. = %MEMBASE% + %MEMSIZE%;
|
||||
_end_of_ram = .;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
/*Added TRUSTZONE at 0x0. Moving rest of APPSBL to %MEMBASE% */
|
||||
. = 0x0;
|
||||
.tzbsp 0x0 : {*tzbsp_bin.o(.data)}
|
||||
.romlite 0xBF000 : {*romlite_toc_and_data.o(.data.rom_lite_preflashed_data)}
|
||||
. = %MEMBASE%;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
/*Moving harcoded addresses by a displacement of %MEMBASE% */
|
||||
.init : { *(.init) } = %MEMBASE% + 0x9090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
/* text/read-only data */
|
||||
|
||||
/*Moving harcoded addresses by a displacement of %MEMBASE% */
|
||||
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } = %MEMBASE% + 0x9090
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(4);
|
||||
__commands_start = .;
|
||||
KEEP (*(.commands))
|
||||
__commands_end = .;
|
||||
. = ALIGN(4);
|
||||
__apps_start = .;
|
||||
KEEP (*(.apps))
|
||||
__apps_end = .;
|
||||
. = ALIGN(4);
|
||||
__rodata_end = . ;
|
||||
}
|
||||
|
||||
/* writable data */
|
||||
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
|
||||
__data_start = .;
|
||||
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
|
||||
|
||||
__ctor_list = .;
|
||||
.ctors : { *(.ctors) }
|
||||
__ctor_end = .;
|
||||
__dtor_list = .;
|
||||
.dtors : { *(.dtors) }
|
||||
__dtor_end = .;
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
__data_end = .;
|
||||
|
||||
/* unintialized data (in same segment as writable data) */
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss .bss.*) }
|
||||
|
||||
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = .;
|
||||
|
||||
|
||||
|
||||
. = %MEMBASE% + %MEMSIZE%;
|
||||
_end_of_ram = .;
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <arch.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/x86.h>
|
||||
#include <arch/x86/mmu.h>
|
||||
#include <arch/x86/descriptor.h>
|
||||
#include <platform.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
static tss_t system_tss;
|
||||
|
||||
void arch_early_init(void)
|
||||
{
|
||||
x86_mmu_init();
|
||||
|
||||
platform_init_mmu_mappings();
|
||||
|
||||
/* enable caches here for now */
|
||||
clear_in_cr0(X86_CR0_NW | X86_CR0_CD);
|
||||
|
||||
memset(&system_tss, 0, sizeof(tss_t));
|
||||
|
||||
system_tss.esp0 = 0;
|
||||
system_tss.ss0 = DATA_SELECTOR;
|
||||
system_tss.ss1 = 0;
|
||||
system_tss.ss2 = 0;
|
||||
system_tss.eflags = 0x00003002;
|
||||
system_tss.bitmap = offsetof(tss_t, tss_bitmap);
|
||||
system_tss.trace = 1; // trap on hardware task switch
|
||||
|
||||
set_global_desc(TSS_SELECTOR, &system_tss, sizeof(tss_t), 1, 0, 0, SEG_TYPE_TSS, 0, 0);
|
||||
|
||||
x86_ltr(TSS_SELECTOR);
|
||||
}
|
||||
|
||||
void arch_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t arch_cycle_count(void)
|
||||
{
|
||||
uint32_t timestamp;
|
||||
rdtscl(timestamp);
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/defines.h>
|
||||
|
||||
.text
|
||||
|
||||
/* stubs */
|
||||
|
||||
FUNCTION(arch_disable_cache)
|
||||
ret
|
||||
|
||||
FUNCTION(arch_enable_cache)
|
||||
ret
|
||||
|
||||
FUNCTION(arch_clean_cache_range)
|
||||
ret
|
||||
|
||||
FUNCTION(arch_clean_invalidate_cache_range)
|
||||
ret
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
|
||||
@$(MKDIR)
|
||||
@echo compiling $<
|
||||
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
|
||||
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* The magic number for the Multiboot header. */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* The flags for the Multiboot header. */
|
||||
#if defined(__ELF__) && 0
|
||||
#define MULTIBOOT_HEADER_FLAGS 0x00000002
|
||||
#else
|
||||
#define MULTIBOOT_HEADER_FLAGS 0x00010002
|
||||
#endif
|
||||
|
||||
/* The magic number passed by a Multiboot-compliant boot loader. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
#define NUM_INT 0x31
|
||||
#define NUM_EXC 0x14
|
||||
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
jmp real_start
|
||||
|
||||
.align 4
|
||||
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.int MULTIBOOT_HEADER_MAGIC
|
||||
/* flags */
|
||||
.int MULTIBOOT_HEADER_FLAGS
|
||||
/* checksum */
|
||||
.int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
|
||||
#if !defined(__ELF__) || 1
|
||||
/* header_addr */
|
||||
.int multiboot_header
|
||||
/* load_addr */
|
||||
.int _start
|
||||
/* load_end_addr */
|
||||
.int __bss_start
|
||||
/* bss_end_addr */
|
||||
.int __bss_end
|
||||
/* entry_addr */
|
||||
.int real_start
|
||||
#endif
|
||||
|
||||
real_start:
|
||||
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
|
||||
jne 0f
|
||||
movl %ebx, (_multiboot_info)
|
||||
0:
|
||||
/* setup isr stub descriptors in the idt */
|
||||
movl $_isr, %esi
|
||||
movl $_idt, %edi
|
||||
movl $NUM_INT, %ecx
|
||||
|
||||
.Lloop:
|
||||
movl %esi, %ebx
|
||||
movw %bx, (%edi) /* low word in IDT(n).low */
|
||||
shrl $16, %ebx
|
||||
movw %bx, 6(%edi) /* high word in IDT(n).high */
|
||||
|
||||
addl $isr_stub_len, %esi/* index the next ISR stub */
|
||||
addl $8, %edi /* index the next IDT entry */
|
||||
|
||||
loop .Lloop
|
||||
|
||||
lidt _idtr
|
||||
xorl %eax, %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
lgdt _gdtr
|
||||
|
||||
movw $datasel, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %ss
|
||||
movw %ax, %gs
|
||||
movw %ax, %ss
|
||||
|
||||
movl $_kstack, %esp
|
||||
|
||||
/* zero the bss section */
|
||||
movl $__bss_start, %edi /* starting address of the bss */
|
||||
movl $__bss_end, %ecx /* find the length of the bss in bytes */
|
||||
subl %edi, %ecx
|
||||
shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */
|
||||
2:
|
||||
movl $0, (%edi)
|
||||
addl $4, %edi
|
||||
loop 2b
|
||||
|
||||
/* call the main module */
|
||||
call kmain
|
||||
|
||||
0: /* just sit around waiting for interrupts */
|
||||
hlt /* interrupts will unhalt the processor */
|
||||
pause
|
||||
jmp 0b /* so jump back to halt to conserve power */
|
||||
|
||||
/* interrupt service routine stubs */
|
||||
_isr:
|
||||
|
||||
.set i, 0
|
||||
.rept NUM_INT
|
||||
|
||||
.set isr_stub_start, .
|
||||
|
||||
.if i == 8 || (i >= 10 && i <= 14) || i == 17
|
||||
nop /* error code pushed by exception */
|
||||
nop /* 2 nops are the same length as push byte */
|
||||
pushl $i /* interrupt number */
|
||||
jmp interrupt_common
|
||||
.else
|
||||
pushl $0 /* fill in error code in iframe */
|
||||
pushl $i /* interrupt number */
|
||||
jmp interrupt_common
|
||||
.endif
|
||||
|
||||
/* figure out the length of a single isr stub (usually 6 or 9 bytes) */
|
||||
.set isr_stub_len, . - isr_stub_start
|
||||
|
||||
.set i, i + 1
|
||||
.endr
|
||||
|
||||
/* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
|
||||
.fill 256
|
||||
|
||||
interrupt_common:
|
||||
pushl %gs /* save segment registers */
|
||||
pushl %fs
|
||||
pushl %es
|
||||
pushl %ds
|
||||
pusha /* save general purpose registers */
|
||||
movl $datasel, %eax /* put known good value in segment registers */
|
||||
movl %eax, %gs
|
||||
movl %eax, %fs
|
||||
movl %eax, %es
|
||||
movl %eax, %ds
|
||||
movl %esp, %eax /* store stack switch pivot. push esp has errata on some cpus, so use mov/push */
|
||||
pushl %eax
|
||||
movl %esp, %eax /* store pointer to iframe, using same method */
|
||||
pushl %eax
|
||||
|
||||
incl critical_section_count
|
||||
|
||||
call platform_irq
|
||||
|
||||
cmpl $0,%eax
|
||||
je 0f
|
||||
call thread_preempt
|
||||
|
||||
0:
|
||||
decl critical_section_count
|
||||
|
||||
popl %eax /* drop pointer to iframe */
|
||||
popl %eax /* restore task_esp, stack switch can occur here if task_esp is modified */
|
||||
movl %eax, %esp
|
||||
popa /* restore general purpose registers */
|
||||
popl %ds /* restore segment registers */
|
||||
popl %es
|
||||
popl %fs
|
||||
popl %gs
|
||||
addl $8, %esp /* drop exception number and error code */
|
||||
iret
|
||||
|
||||
.data
|
||||
.align 4
|
||||
|
||||
/* define the heap end as read-write data containing the default end of the
|
||||
* heap. dynamic memory length discovery can update this value during init.
|
||||
* other archs can define this statically based on the memory layout of the
|
||||
* platform.
|
||||
*/
|
||||
.global _heap_end
|
||||
_heap_end:
|
||||
.int 4096*1024 /* default to 4MB total */
|
||||
|
||||
.global _multiboot_info
|
||||
_multiboot_info:
|
||||
.int 0
|
||||
|
||||
.global _gdtr
|
||||
_gdtr:
|
||||
.short _gdt_end - _gdt - 1
|
||||
.int _gdt
|
||||
|
||||
.global _gdt
|
||||
_gdt:
|
||||
.int 0
|
||||
.int 0
|
||||
|
||||
/* ring 0 descriptors */
|
||||
.set codesel, . - _gdt
|
||||
_code_gde:
|
||||
.short 0xffff /* limit 15:00 */
|
||||
.short 0x0000 /* base 15:00 */
|
||||
.byte 0x00 /* base 23:16 */
|
||||
.byte 0b10011010 /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
|
||||
.byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
|
||||
.byte 0x0 /* base 31:24 */
|
||||
|
||||
.set datasel, . - _gdt
|
||||
_data_gde:
|
||||
.short 0xffff /* limit 15:00 */
|
||||
.short 0x0000 /* base 15:00 */
|
||||
.byte 0x00 /* base 23:16 */
|
||||
.byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
|
||||
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
|
||||
.byte 0x0 /* base 31:24 */
|
||||
|
||||
.set videosel, . - _gdt
|
||||
_video_gde:
|
||||
.short 0xffff /* limit 15:00 */
|
||||
.short 0x8000 /* base 15:00 */
|
||||
.byte 0x0b /* base 23:16 */
|
||||
.byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
|
||||
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
|
||||
.byte 0x0 /* base 31:24 */
|
||||
|
||||
.if 1
|
||||
/* ring 3 descriptors */
|
||||
.set user_codesel, . - _gdt
|
||||
_user_code_gde:
|
||||
.short 0xffff /* limit 15:00 */
|
||||
.short 0x0000 /* base 15:00 */
|
||||
.byte 0x00 /* base 23:16 */
|
||||
.byte 0b11111010 /* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
|
||||
.byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
|
||||
.byte 0x0 /* base 31:24 */
|
||||
|
||||
.set user_datasel, . - _gdt
|
||||
_user_data_gde:
|
||||
.short 0xffff /* limit 15:00 */
|
||||
.short 0x0000 /* base 15:00 */
|
||||
.byte 0x00 /* base 23:16 */
|
||||
.byte 0b11110010 /* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
|
||||
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
|
||||
.byte 0x0 /* base 31:24 */
|
||||
.endif
|
||||
|
||||
/* TSS descriptor */
|
||||
.if 1
|
||||
.set tsssel, . - _gdt
|
||||
_tss_gde:
|
||||
.short 0 /* limit 15:00 */
|
||||
.short 0 /* base 15:00 */
|
||||
.byte 0 /* base 23:16 */
|
||||
.byte 0xe9 /* P(1) DPL(11) 0 10 B(0) 1 */
|
||||
.byte 0x00 /* G(0) 0 0 AVL(0) limit 19:16 */
|
||||
.short 0 /* base 31:24 */
|
||||
.endif
|
||||
|
||||
.global _gdt_end
|
||||
_gdt_end:
|
||||
|
||||
.global _idtr
|
||||
_idtr:
|
||||
.short _idt_end - _idt - 1 /* IDT limit */
|
||||
.int _idt
|
||||
|
||||
/* interrupt descriptor table (IDT) */
|
||||
.global _idt
|
||||
_idt:
|
||||
|
||||
.set i, 0
|
||||
.rept NUM_INT-1
|
||||
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
|
||||
.short codesel /* selector */
|
||||
.byte 0
|
||||
.byte 0x8e /* present, ring 0, 32-bit interrupt gate */
|
||||
.short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
|
||||
|
||||
.set i, i + 1
|
||||
.endr
|
||||
|
||||
/* syscall int (ring 3) */
|
||||
_idt30:
|
||||
.short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
|
||||
.short codesel /* selector */
|
||||
.byte 0
|
||||
.byte 0xee /* present, ring 3, 32-bit interrupt gate */
|
||||
.short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
|
||||
|
||||
.global _idt_end
|
||||
_idt_end:
|
||||
|
||||
.bss
|
||||
.align 4096
|
||||
|
||||
.global _kstack
|
||||
.fill 4096
|
||||
_kstack:
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <compiler.h>
|
||||
#include <arch/x86/descriptor.h>
|
||||
|
||||
/* not the best way to do this, but easy for now */
|
||||
typedef struct {
|
||||
uint16_t limit_15_0;
|
||||
uint16_t base_15_0;
|
||||
uint8_t base_23_16;
|
||||
|
||||
uint8_t type : 4;
|
||||
uint8_t s : 1;
|
||||
uint8_t dpl : 2;
|
||||
uint8_t p : 1;
|
||||
|
||||
uint8_t limit_19_16 : 4;
|
||||
uint8_t avl : 1;
|
||||
uint8_t reserved_0 : 1;
|
||||
uint8_t d_b : 1;
|
||||
uint8_t g : 1;
|
||||
|
||||
uint8_t base_31_24;
|
||||
} __PACKED seg_desc_t;
|
||||
|
||||
extern seg_desc_t _gdt[];
|
||||
|
||||
void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
|
||||
uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits)
|
||||
{
|
||||
// convert selector into index
|
||||
uint16_t index = sel >> 3;
|
||||
|
||||
_gdt[index].limit_15_0 = limit & 0x0000ffff;
|
||||
_gdt[index].limit_19_16 = (limit & 0x000f0000) >> 16;
|
||||
|
||||
_gdt[index].base_15_0 = ((uint32_t) base) & 0x0000ffff;
|
||||
_gdt[index].base_23_16 = (((uint32_t) base) & 0x00ff0000) >> 16;
|
||||
_gdt[index].base_31_24 = ((uint32_t) base) >> 24;
|
||||
|
||||
_gdt[index].type = type & 0x0f; // segment type
|
||||
_gdt[index].p = present != 0; // present
|
||||
_gdt[index].dpl = ring & 0x03; // descriptor privilege level
|
||||
_gdt[index].g = gran != 0; // granularity
|
||||
_gdt[index].s = sys != 0; // system / non-system
|
||||
_gdt[index].d_b = bits != 0; // 16 / 32 bit
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <arch/x86.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
static void dump_fault_frame(struct x86_iframe *frame)
|
||||
{
|
||||
dprintf(CRITICAL, " CS: %04x EIP: %08x EFL: %08x CR2: %08x\n",
|
||||
frame->cs, frame->eip, frame->eflags, x86_get_cr2());
|
||||
dprintf(CRITICAL, "EAX: %08x ECX: %08x EDX: %08x EBX: %08x\n",
|
||||
frame->eax, frame->ecx, frame->edx, frame->ebx);
|
||||
dprintf(CRITICAL, "ESP: %08x EBP: %08x ESI: %08x EDI: %08x\n",
|
||||
frame->esp, frame->ebp, frame->esi, frame->edi);
|
||||
dprintf(CRITICAL, " DS: %04x ES: %04x FS: %04x GS: %04x\n",
|
||||
frame->ds, frame->es, frame->fs, frame->gs);
|
||||
|
||||
// dump the bottom of the current stack
|
||||
addr_t stack = (addr_t) frame; //(addr_t) (((uint32_t *) frame) + (sizeof(struct x86_iframe) / sizeof(uint32_t) - 1));
|
||||
|
||||
if (stack != 0) {
|
||||
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
|
||||
hexdump((void *)stack, 192);
|
||||
}
|
||||
}
|
||||
|
||||
static void exception_die(struct x86_iframe *frame, const char *msg)
|
||||
{
|
||||
inc_critical_section();
|
||||
dprintf(CRITICAL, msg);
|
||||
dump_fault_frame(frame);
|
||||
|
||||
for (;;) {
|
||||
x86_cli();
|
||||
x86_hlt();
|
||||
}
|
||||
}
|
||||
|
||||
void x86_syscall_handler(struct x86_iframe *frame)
|
||||
{
|
||||
exception_die(frame, "unhandled syscall, halting\n");
|
||||
}
|
||||
|
||||
void x86_gpf_handler(struct x86_iframe *frame)
|
||||
{
|
||||
exception_die(frame, "unhandled gpf, halting\n");
|
||||
}
|
||||
|
||||
void x86_invop_handler(struct x86_iframe *frame)
|
||||
{
|
||||
exception_die(frame, "unhandled invalid op, halting\n");
|
||||
}
|
||||
|
||||
void x86_unhandled_exception(struct x86_iframe *frame)
|
||||
{
|
||||
exception_die(frame, "unhandled exception, halting\n");
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __X86_ARCH_THREAD_H
|
||||
#define __X86_ARCH_THREAD_H
|
||||
|
||||
struct arch_thread {
|
||||
vaddr_t esp;
|
||||
|
||||
// TODO: fpu context
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_CPU_H
|
||||
#define __ARCH_CPU_H
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
// TODO: define to resolve to platform setup discovered value
|
||||
#define CACHE_LINE 32
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_X86_H
|
||||
#define __ARCH_X86_H
|
||||
|
||||
#include <compiler.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void x86_mmu_init(void);
|
||||
|
||||
struct x86_iframe {
|
||||
uint32_t pivot; // stack switch pivot
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // pushed by common handler using pusha
|
||||
uint32_t ds, es, fs, gs; // pushed by common handler
|
||||
uint32_t vector; // pushed by stub
|
||||
uint32_t err_code; // pushed by interrupt or stub
|
||||
uint32_t eip, cs, eflags; // pushed by interrupt
|
||||
uint32_t user_esp, user_ss; // pushed by interrupt if priv change occurs
|
||||
};
|
||||
|
||||
/*
|
||||
* x86 TSS structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t backlink, __blh;
|
||||
uint32_t esp0;
|
||||
uint16_t ss0, __ss0h;
|
||||
uint32_t esp1;
|
||||
uint16_t ss1, __ss1h;
|
||||
uint32_t esp2;
|
||||
uint16_t ss2, __ss2h;
|
||||
uint32_t cr3;
|
||||
uint32_t eip;
|
||||
uint32_t eflags;
|
||||
uint32_t eax, ecx, edx, ebx;
|
||||
uint32_t esp, ebp, esi, edi;
|
||||
uint16_t es, __esh;
|
||||
uint16_t cs, __csh;
|
||||
uint16_t ss, __ssh;
|
||||
uint16_t ds, __dsh;
|
||||
uint16_t fs, __fsh;
|
||||
uint16_t gs, __gsh;
|
||||
uint16_t ldt, __ldth;
|
||||
uint16_t trace, bitmap;
|
||||
|
||||
uint8_t tss_bitmap[8192];
|
||||
} __PACKED tss_t;
|
||||
|
||||
#define X86_CR0_PE 0x00000001 /* protected mode enable */
|
||||
#define X86_CR0_MP 0x00000002 /* monitor coprocessor */
|
||||
#define X86_CR0_EM 0x00000004 /* emulation */
|
||||
#define X86_CR0_TS 0x00000008 /* task switched */
|
||||
#define X86_CR0_WP 0x00010000 /* supervisor write protect */
|
||||
#define X86_CR0_NW 0x20000000 /* not write-through */
|
||||
#define X86_CR0_CD 0x40000000 /* cache disable */
|
||||
#define X86_CR0_PG 0x80000000 /* enable paging */
|
||||
|
||||
static inline void set_in_cr0(uint32_t mask) {
|
||||
__asm__ __volatile__ (
|
||||
"movl %%cr0,%%eax \n\t"
|
||||
"orl %0,%%eax \n\t"
|
||||
"movl %%eax,%%cr0 \n\t"
|
||||
: : "irg" (mask)
|
||||
:"ax");
|
||||
}
|
||||
|
||||
static inline void clear_in_cr0(uint32_t mask) {
|
||||
__asm__ __volatile__ (
|
||||
"movl %%cr0, %%eax \n\t"
|
||||
"andl %0, %%eax \n\t"
|
||||
"movl %%eax, %%cr0 \n\t"
|
||||
: : "irg" (~mask)
|
||||
: "ax");
|
||||
}
|
||||
|
||||
static inline void x86_clts(void) {__asm__ __volatile__ ("clts"); }
|
||||
static inline void x86_hlt(void) {__asm__ __volatile__ ("hlt"); }
|
||||
static inline void x86_sti(void) {__asm__ __volatile__ ("sti"); }
|
||||
static inline void x86_cli(void) {__asm__ __volatile__ ("cli"); }
|
||||
static inline void x86_ltr(uint16_t sel) {
|
||||
__asm__ __volatile__ ("ltr %%ax" :: "a" (sel));
|
||||
}
|
||||
|
||||
static inline uint32_t x86_get_cr2(void) {
|
||||
uint32_t rv;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"movl %%cr2, %0"
|
||||
: "=r" (rv)
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define rdtsc(low,high) \
|
||||
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
|
||||
|
||||
#define rdtscl(low) \
|
||||
__asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
|
||||
|
||||
#define rdtscll(val) \
|
||||
__asm__ __volatile__("rdtsc" : "=A" (val))
|
||||
|
||||
static inline uint8_t inp(uint16_t _port) {
|
||||
uint8_t rv;
|
||||
__asm__ __volatile__ ("inb %1, %0"
|
||||
: "=a" (rv)
|
||||
: "d" (_port));
|
||||
return(rv);
|
||||
}
|
||||
|
||||
static inline uint16_t inpw (uint16_t _port) {
|
||||
uint16_t rv;
|
||||
__asm__ __volatile__ ("inw %1, %0"
|
||||
: "=a" (rv)
|
||||
: "d" (_port));
|
||||
return(rv);
|
||||
}
|
||||
|
||||
static inline uint32_t inpd(uint16_t _port) {
|
||||
uint32_t rv;
|
||||
__asm__ __volatile__ ("inl %1, %0"
|
||||
: "=a" (rv)
|
||||
: "d" (_port));
|
||||
return(rv);
|
||||
}
|
||||
|
||||
static inline void outp(uint16_t _port, uint8_t _data) {
|
||||
__asm__ __volatile__ ("outb %1, %0"
|
||||
:
|
||||
: "d" (_port),
|
||||
"a" (_data));
|
||||
}
|
||||
|
||||
static inline void outpw(uint16_t _port, uint16_t _data) {
|
||||
__asm__ __volatile__ ("outw %1, %0"
|
||||
:
|
||||
: "d" (_port),
|
||||
"a" (_data));
|
||||
}
|
||||
|
||||
static inline void outpd(uint16_t _port, uint32_t _data) {
|
||||
__asm__ __volatile__ ("outl %1, %0"
|
||||
:
|
||||
: "d" (_port),
|
||||
"a" (_data));
|
||||
}
|
||||
|
||||
static inline void inprep(uint16_t _port, uint8_t *_buffer, uint32_t _reads) {
|
||||
__asm__ __volatile__ ("pushal \n\t"
|
||||
"pushfl \n\t"
|
||||
"cli \n\t"
|
||||
"cld \n\t"
|
||||
"rep insb \n\t"
|
||||
"popfl \n\t"
|
||||
"popal"
|
||||
:
|
||||
: "d" (_port),
|
||||
"D" (_buffer),
|
||||
"c" (_reads));
|
||||
}
|
||||
|
||||
static inline void outprep(uint16_t _port, uint8_t *_buffer, uint32_t _writes) {
|
||||
__asm__ __volatile__ ("pushal \n\t"
|
||||
"pushfl \n\t"
|
||||
"cli \n\t"
|
||||
"cld \n\t"
|
||||
"rep outsb \n\t"
|
||||
"popfl \n\t"
|
||||
"popal"
|
||||
:
|
||||
: "d" (_port),
|
||||
"S" (_buffer),
|
||||
"c" (_writes));
|
||||
}
|
||||
|
||||
static inline void inpwrep(uint16_t _port, uint16_t *_buffer, uint32_t _reads) {
|
||||
__asm__ __volatile__ ("pushal \n\t"
|
||||
"pushfl \n\t"
|
||||
"cli \n\t"
|
||||
"cld \n\t"
|
||||
"rep insw \n\t"
|
||||
"popfl \n\t"
|
||||
"popal"
|
||||
:
|
||||
: "d" (_port),
|
||||
"D" (_buffer),
|
||||
"c" (_reads));
|
||||
}
|
||||
|
||||
static inline void outpwrep(uint16_t _port, uint16_t *_buffer,
|
||||
uint32_t _writes) {
|
||||
__asm__ __volatile__ ("pushal \n\t"
|
||||
"pushfl \n\t"
|
||||
"cli \n\t"
|
||||
"cld \n\t"
|
||||
"rep outsw \n\t"
|
||||
"popfl \n\t"
|
||||
"popal"
|
||||
:
|
||||
: "d" (_port),
|
||||
"S" (_buffer),
|
||||
"c" (_writes));
|
||||
}
|
||||
|
||||
static inline void inpdrep(uint16_t _port, uint32_t *_buffer,
|
||||
uint32_t _reads) {
|
||||
__asm__ __volatile__ ("pushal \n\t"
|
||||
"pushfl \n\t"
|
||||
"cli \n\t"
|
||||
"cld \n\t"
|
||||
"rep insl \n\t"
|
||||
"popfl \n\t"
|
||||
"popal"
|
||||
:
|
||||
: "d" (_port),
|
||||
"D" (_buffer),
|
||||
"c" (_reads));
|
||||
}
|
||||
|
||||
static inline void outpdrep(uint16_t _port, uint32_t *_buffer,
|
||||
uint32_t _writes) {
|
||||
__asm__ __volatile__ ("pushal \n\t"
|
||||
"pushfl \n\t"
|
||||
"cli \n\t"
|
||||
"cld \n\t"
|
||||
"rep outsl \n\t"
|
||||
"popfl \n\t"
|
||||
"popal"
|
||||
:
|
||||
: "d" (_port),
|
||||
"S" (_buffer),
|
||||
"c" (_writes));
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_DESCRIPTOR_H
|
||||
#define __ARCH_DESCRIPTOR_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* System Selectors
|
||||
*/
|
||||
#define CODE_SELECTOR 0x08
|
||||
#define DATA_SELECTOR 0x10
|
||||
#define VIDEO_SELECTOR 0x18
|
||||
#define TSS_SELECTOR 0x30
|
||||
|
||||
#define USER_CODE_SELECTOR 0x23
|
||||
#define USER_DATA_SELECTOR 0x2b
|
||||
|
||||
/*
|
||||
* Descriptor Types
|
||||
*/
|
||||
#define SEG_TYPE_TSS 0x9
|
||||
#define SEG_TYPE_TSS_BUSY 0xb
|
||||
#define SEG_TYPE_TASK_GATE 0x5
|
||||
#define SEG_TYPE_INT_GATE 0xe // 32 bit
|
||||
#define SEG_TYPE_DATA_RW 0x2
|
||||
#define SEG_TYPE_CODE_RW 0xa
|
||||
|
||||
typedef uint16_t seg_sel_t;
|
||||
|
||||
void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
|
||||
uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MMU_H
|
||||
#define __ARCH_ARM_MMU_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void arm_mmu_init(void);
|
||||
|
||||
#define MMU_FLAG_CACHED 0x1
|
||||
#define MMU_FLAG_BUFFERED 0x2
|
||||
#define MMU_FLAG_READWRITE 0x4
|
||||
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __ARCH_X86_OPS_H
|
||||
#define __ARHC_X86_OPS_H
|
||||
|
||||
#if 0
|
||||
#include <compiler.h>
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
// override of some routines
|
||||
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
|
||||
{
|
||||
__asm__ __volatile__ ("sti");
|
||||
}
|
||||
|
||||
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
|
||||
{
|
||||
__asm__ __volatile__ ("cli");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
.text 0x0200000 : {
|
||||
*(.text)
|
||||
*(SORT(.text$*))
|
||||
*(.gnu.linkonce.t.*)
|
||||
|
||||
__ctor_list = .;
|
||||
*(SORT(.ctor*))
|
||||
__ctor_end = .;
|
||||
__dtor_list = .;
|
||||
*(SORT(.dtor*))
|
||||
__dtor_end = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
__data_start = .;
|
||||
.data : { *(.data .data.* .gnu.linkonce.d.*) }
|
||||
.stab : { *(.stab) }
|
||||
.stabst : { *(.stabstr) }
|
||||
|
||||
. = ALIGN(4096);
|
||||
__data_end = .;
|
||||
|
||||
.rdata : {
|
||||
*(.rdata)
|
||||
*(SORT(.rdata$*))
|
||||
*(.rodata*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
__commands_start = .;
|
||||
KEEP (*(.commands))
|
||||
__commands_end = .;
|
||||
. = ALIGN(4);
|
||||
__apps_start = .;
|
||||
KEEP (*(.apps))
|
||||
__apps_end = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
__bss_start = .;
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
__bss_end = .;
|
||||
|
||||
/*. += 0x2000;
|
||||
_kstack = .;
|
||||
. += 0x1000;*/
|
||||
|
||||
_end = .;
|
||||
|
||||
/DISCARD/ : { *(.comment .note .eh_frame) }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <sys/types.h>
|
||||
#include <compiler.h>
|
||||
#include <arch.h>
|
||||
#include <arch/x86.h>
|
||||
#include <arch/x86/mmu.h>
|
||||
|
||||
void x86_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
|
||||
{
|
||||
// TODO: stuff
|
||||
//x86_invalidate_tlb();
|
||||
}
|
||||
|
||||
void x86_mmu_init(void)
|
||||
{
|
||||
// TODO: stuff
|
||||
}
|
||||
|
||||
void arch_disable_mmu(void)
|
||||
{
|
||||
// TODO: stuff
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <asm.h>
|
||||
|
||||
.text
|
||||
|
||||
/* void arch_enable_ints(void); */
|
||||
FUNCTION(arch_enable_ints)
|
||||
sti
|
||||
ret
|
||||
|
||||
/* void arch_disable_ints(void); */
|
||||
FUNCTION(arch_disable_ints)
|
||||
cli
|
||||
ret
|
||||
|
||||
/* int atomic_swap(int *ptr, int val); */
|
||||
FUNCTION(atomic_swap)
|
||||
movl 4(%esp), %edx
|
||||
movl 8(%esp), %eax
|
||||
xchgl %eax, (%edx)
|
||||
ret
|
||||
|
||||
/* int atomic_add(int *ptr, int val); */
|
||||
FUNCTION(atomic_add)
|
||||
movl 4(%esp), %edx
|
||||
movl 8(%esp), %eax
|
||||
lock
|
||||
xadd %eax, (%edx)
|
||||
ret
|
||||
|
||||
/* int atomic_and(int *ptr, int val); */
|
||||
FUNCTION(atomic_and)
|
||||
movl 4(%esp), %edx
|
||||
movl (%edx), %eax
|
||||
0:
|
||||
movl %eax, %ecx
|
||||
andl 8(%esp), %ecx
|
||||
lock
|
||||
cmpxchgl %ecx, (%edx)
|
||||
jnz 1f /* static prediction: branch forward not taken */
|
||||
ret
|
||||
1:
|
||||
jmp 0b
|
||||
|
||||
|
||||
/* int atomic_or(int *ptr, int val); */
|
||||
FUNCTION(atomic_or)
|
||||
movl 4(%esp), %edx
|
||||
movl (%edx), %eax
|
||||
0:
|
||||
movl %eax, %ecx
|
||||
orl 8(%esp), %ecx
|
||||
lock
|
||||
cmpxchgl %ecx, (%edx)
|
||||
jnz 1f /* static prediction: branch forward not taken */
|
||||
ret
|
||||
1:
|
||||
jmp 0b
|
||||
|
||||
/* void arch_idle(); */
|
||||
FUNCTION(arch_idle)
|
||||
pushf
|
||||
popl %eax
|
||||
andl $0x200, %eax
|
||||
test %eax, %eax
|
||||
je 1f /* don't halt if local interrupts are disabled */
|
||||
hlt
|
||||
1:
|
||||
ret
|
||||
|
||||
/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
|
||||
FUNCTION(arch_switch_stacks_and_call)
|
||||
movl 4(%esp), %eax
|
||||
movl 8(%esp), %edx
|
||||
movl %edx, %esp
|
||||
call *%eax /* perhaps this should be a jmp? it's not used anywhere so I don't know. */
|
||||
@@ -0,0 +1,41 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += \
|
||||
-I$(LOCAL_DIR)/include
|
||||
|
||||
BOOTOBJS += \
|
||||
$(LOCAL_DIR)/crt0.o
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/arch.o \
|
||||
$(LOCAL_DIR)/asm.o \
|
||||
$(LOCAL_DIR)/cache.o \
|
||||
$(LOCAL_DIR)/cache-ops.o \
|
||||
$(LOCAL_DIR)/ops.o \
|
||||
$(LOCAL_DIR)/thread.o \
|
||||
$(LOCAL_DIR)/mmu.o \
|
||||
$(LOCAL_DIR)/faults.o \
|
||||
$(LOCAL_DIR)/descriptor.o
|
||||
|
||||
# set the default toolchain to x86 elf and set a #define
|
||||
TOOLCHAIN_PREFIX ?= i386-elf-
|
||||
|
||||
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -print-libgcc-file-name)
|
||||
#$(info LIBGCC = $(LIBGCC))
|
||||
|
||||
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`"; \
|
||||
then echo "$(2)"; else echo "$(3)"; fi ;)
|
||||
|
||||
# disable SSP if the compiler supports it; it will break stuff
|
||||
CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
|
||||
|
||||
# potentially generated files that should be cleaned out with clean make rule
|
||||
GENERATED += \
|
||||
$(BUILDDIR)/kernel.ld
|
||||
|
||||
# rules for generating the linker scripts
|
||||
|
||||
$(BUILDDIR)/kernel.ld: $(LOCAL_DIR)/kernel.ld
|
||||
@echo generating $@
|
||||
@$(MKDIR)
|
||||
$(NOECHO)cp $< $@
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Corey Tabaka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <arch/x86.h>
|
||||
#include <arch/x86/descriptor.h>
|
||||
|
||||
/*struct context_switch_frame {
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||
uint32_t ds, es, fs, gs;
|
||||
uint32_t eip, cs, eflags;
|
||||
};*/
|
||||
struct context_switch_frame {
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||
uint32_t eflags;
|
||||
uint32_t eip;
|
||||
};
|
||||
|
||||
extern void x86_context_switch(addr_t *old_sp, addr_t new_sp);
|
||||
|
||||
static void initial_thread_func(void) __NO_RETURN;
|
||||
static void initial_thread_func(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
|
||||
// dump_thread(current_thread);
|
||||
|
||||
/* exit the implicit critical section we're within */
|
||||
exit_critical_section();
|
||||
|
||||
ret = current_thread->entry(current_thread->arg);
|
||||
|
||||
// dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
|
||||
|
||||
thread_exit(ret);
|
||||
}
|
||||
|
||||
void arch_thread_initialize(thread_t *t)
|
||||
{
|
||||
// create a default stack frame on the stack
|
||||
vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
|
||||
|
||||
// make sure the top of the stack is 8 byte aligned for EABI compliance
|
||||
stack_top = ROUNDDOWN(stack_top, 8);
|
||||
|
||||
struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
|
||||
frame--;
|
||||
|
||||
// fill it in
|
||||
memset(frame, 0, sizeof(*frame));
|
||||
|
||||
frame->eip = (vaddr_t) &initial_thread_func;
|
||||
frame->eflags = 0x3002; // IF = 0, NT = 0, IOPL = 3
|
||||
//frame->cs = CODE_SELECTOR;
|
||||
//frame->fs = DATA_SELECTOR;
|
||||
//frame->gs = DATA_SELECTOR;
|
||||
//frame->es = DATA_SELECTOR;
|
||||
//frame->ds = DATA_SELECTOR;
|
||||
|
||||
// set the stack pointer
|
||||
t->arch.esp = (vaddr_t)frame;
|
||||
}
|
||||
|
||||
void arch_context_switch(thread_t *oldthread, thread_t *newthread)
|
||||
{
|
||||
//dprintf(DEBUG, "arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"pushl $1f \n\t"
|
||||
"pushf \n\t"
|
||||
"pusha \n\t"
|
||||
"movl %%esp,(%%edx) \n\t"
|
||||
"movl %%eax,%%esp \n\t"
|
||||
"popa \n\t"
|
||||
"popf \n\t"
|
||||
"ret \n\t"
|
||||
"1: \n\t"
|
||||
|
||||
:
|
||||
: "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
|
||||
);
|
||||
|
||||
/*__asm__ __volatile__ (
|
||||
"pushf \n\t"
|
||||
"pushl %%cs \n\t"
|
||||
"pushl $1f \n\t"
|
||||
"pushl %%gs \n\t"
|
||||
"pushl %%fs \n\t"
|
||||
"pushl %%es \n\t"
|
||||
"pushl %%ds \n\t"
|
||||
"pusha \n\t"
|
||||
"movl %%esp,(%%edx) \n\t"
|
||||
"movl %%eax,%%esp \n\t"
|
||||
"popa \n\t"
|
||||
"popl %%ds \n\t"
|
||||
"popl %%es \n\t"
|
||||
"popl %%fs \n\t"
|
||||
"popl %%gs \n\t"
|
||||
"iret \n\t"
|
||||
"1: "
|
||||
:
|
||||
: "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
|
||||
);*/
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void dev_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <dev/fbcon.h>
|
||||
#include <splash.h>
|
||||
#include <platform.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "font5x12.h"
|
||||
|
||||
struct pos {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
static struct fbcon_config *config = NULL;
|
||||
|
||||
#define RGB565_BLACK 0x0000
|
||||
#define RGB565_WHITE 0xffff
|
||||
|
||||
#define RGB888_BLACK 0x000000
|
||||
#define RGB888_WHITE 0xffffff
|
||||
|
||||
#define FONT_WIDTH 5
|
||||
#define FONT_HEIGHT 12
|
||||
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
unsigned char BGCOLOR_R;
|
||||
unsigned char BGCOLOR_G;
|
||||
unsigned char BGCOLOR_B;
|
||||
unsigned char FGCOLOR_R;
|
||||
unsigned char FGCOLOR_G;
|
||||
unsigned char FGCOLOR_B;
|
||||
#else
|
||||
static uint16_t BGCOLOR;
|
||||
static uint16_t FGCOLOR;
|
||||
#endif
|
||||
|
||||
static struct pos cur_pos;
|
||||
static struct pos max_pos;
|
||||
|
||||
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
void fb_put_pixel(unsigned x, unsigned y, unsigned char red, unsigned char green, unsigned char blue)
|
||||
{
|
||||
volatile void *fb_addr = (void *)0x7f600000;
|
||||
unsigned int pixel_size = 4;
|
||||
unsigned long line_size = 1024*pixel_size;
|
||||
volatile void *pixel_loc;
|
||||
|
||||
if (x >= 1024) return;
|
||||
if (y >= 768) return;
|
||||
|
||||
pixel_loc = fb_addr + y * line_size + x * pixel_size;
|
||||
*((unsigned char *)(pixel_loc + 0)) = blue; // blue
|
||||
*((unsigned char *)(pixel_loc + 1)) = green; // grn
|
||||
*((unsigned char *)(pixel_loc + 2)) = red; // red
|
||||
*((unsigned char *)(pixel_loc + 3)) = 0; // ??
|
||||
}
|
||||
|
||||
static void fbcon_drawglyph_tp(unsigned x, unsigned y, unsigned *glyph)
|
||||
{
|
||||
unsigned xd, yd, data;
|
||||
|
||||
data = glyph[0];
|
||||
for (yd = 0; yd < (FONT_HEIGHT / 2); ++yd) {
|
||||
for (xd = 0; xd < FONT_WIDTH; ++xd) {
|
||||
if (data & 1) {
|
||||
fb_put_pixel(x+xd, y+yd, FGCOLOR_R, FGCOLOR_G, FGCOLOR_B);
|
||||
} else {
|
||||
fb_put_pixel(x+xd, y+yd, BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
|
||||
}
|
||||
data >>= 1;
|
||||
}
|
||||
fb_put_pixel(x+FONT_WIDTH, y+yd, BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
|
||||
}
|
||||
|
||||
data = glyph[1];
|
||||
for (yd = 0; yd < (FONT_HEIGHT / 2); yd++) {
|
||||
for (xd = 0; xd < FONT_WIDTH; xd++) {
|
||||
if (data & 1) {
|
||||
fb_put_pixel(x+xd, y+yd+(FONT_HEIGHT/2), FGCOLOR_R, FGCOLOR_G, FGCOLOR_B);
|
||||
} else {
|
||||
fb_put_pixel(x+xd, y+yd+(FONT_HEIGHT/2), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
|
||||
}
|
||||
data >>= 1;
|
||||
}
|
||||
fb_put_pixel(x+FONT_WIDTH, y+yd+(FONT_HEIGHT/2), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
|
||||
unsigned *glyph)
|
||||
{
|
||||
unsigned x, y, data;
|
||||
stride -= FONT_WIDTH;
|
||||
|
||||
data = glyph[0];
|
||||
for (y = 0; y < (FONT_HEIGHT / 2); ++y) {
|
||||
for (x = 0; x < FONT_WIDTH; ++x) {
|
||||
if (data & 1)
|
||||
*pixels = paint;
|
||||
data >>= 1;
|
||||
pixels++;
|
||||
}
|
||||
pixels += stride;
|
||||
}
|
||||
|
||||
data = glyph[1];
|
||||
for (y = 0; y < (FONT_HEIGHT / 2); y++) {
|
||||
for (x = 0; x < FONT_WIDTH; x++) {
|
||||
if (data & 1)
|
||||
*pixels = paint;
|
||||
data >>= 1;
|
||||
pixels++;
|
||||
}
|
||||
pixels += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void fbcon_flush(void)
|
||||
{
|
||||
if (config->update_start)
|
||||
config->update_start();
|
||||
if (config->update_done)
|
||||
while (!config->update_done());
|
||||
}
|
||||
|
||||
/* TODO: Take stride into account */
|
||||
static void fbcon_scroll_up(void)
|
||||
{
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
for (unsigned y = 0; y <= max_pos.y - FONT_HEIGHT; y += FONT_HEIGHT) {
|
||||
memcpy (config->base + y * 1024*4,
|
||||
config->base + (y + FONT_HEIGHT) * 1024*4,
|
||||
1024*4*FONT_HEIGHT);
|
||||
}
|
||||
for (unsigned y = max_pos.y; y < config->height; y++) {
|
||||
memset(config->base + y*1024*4, 0, 1024*4);
|
||||
}
|
||||
#else
|
||||
unsigned short *dst = config->base;
|
||||
unsigned short *src = dst + (config->width * FONT_HEIGHT);
|
||||
unsigned count = config->width * (config->height - FONT_HEIGHT);
|
||||
|
||||
while(count--) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
count = config->width * FONT_HEIGHT;
|
||||
while(count--) {
|
||||
*dst++ = BGCOLOR;
|
||||
}
|
||||
|
||||
#endif
|
||||
fbcon_flush();
|
||||
}
|
||||
|
||||
/* TODO: take stride into account */
|
||||
void fbcon_clear(void)
|
||||
{
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
for (unsigned y = 0; y < 1024; y++) {
|
||||
memset(config->base + y*1024*4, 0, 1024*4);
|
||||
}
|
||||
#else
|
||||
unsigned count = config->width * config->height;
|
||||
memset(config->base, BGCOLOR, count * ((config->bpp) / 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
void fbcon_set_colors(
|
||||
unsigned char bg_r,
|
||||
unsigned char bg_g,
|
||||
unsigned char bg_b,
|
||||
unsigned char fg_r,
|
||||
unsigned char fg_g,
|
||||
unsigned char fg_b
|
||||
)
|
||||
{
|
||||
BGCOLOR_R = bg_r;
|
||||
BGCOLOR_G = bg_g;
|
||||
BGCOLOR_B = bg_b;
|
||||
FGCOLOR_R = fg_r;
|
||||
FGCOLOR_G = fg_g;
|
||||
FGCOLOR_B = fg_b;
|
||||
}
|
||||
#else
|
||||
static void fbcon_set_colors(unsigned bg, unsigned fg)
|
||||
{
|
||||
BGCOLOR = bg;
|
||||
FGCOLOR = fg;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
void fbcon_setpos(unsigned x, unsigned y)
|
||||
{
|
||||
unsigned newx, newy;
|
||||
|
||||
newx = x * (FONT_WIDTH + 1);
|
||||
newy = y * (FONT_HEIGHT);
|
||||
|
||||
if (newx > max_pos.x || newy > max_pos.y) {
|
||||
return;
|
||||
} else {
|
||||
cur_pos.x = newx;
|
||||
cur_pos.y = newy;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void fbcon_putc(char c)
|
||||
{
|
||||
uint16_t *pixels;
|
||||
|
||||
/* ignore anything that happens before fbcon is initialized */
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
if((unsigned char)c > 127)
|
||||
return;
|
||||
if((unsigned char)c < 32) {
|
||||
if(c == '\n')
|
||||
goto newline;
|
||||
else if (c == '\r')
|
||||
cur_pos.x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
fbcon_drawglyph_tp(cur_pos.x, cur_pos.y,
|
||||
font5x12 + (c - 32) * 2);
|
||||
|
||||
cur_pos.x += FONT_WIDTH + 1;
|
||||
if (cur_pos.x <= max_pos.x)
|
||||
return;
|
||||
|
||||
newline:
|
||||
cur_pos.y += FONT_HEIGHT;
|
||||
cur_pos.x = 0;
|
||||
if(cur_pos.y > max_pos.y) {
|
||||
cur_pos.y -= FONT_HEIGHT;
|
||||
fbcon_scroll_up();
|
||||
} else
|
||||
fbcon_flush();
|
||||
#else
|
||||
pixels = config->base;
|
||||
pixels += cur_pos.y * FONT_HEIGHT * config->width;
|
||||
pixels += cur_pos.x * (FONT_WIDTH + 1);
|
||||
fbcon_drawglyph(pixels, FGCOLOR, config->stride,
|
||||
font5x12 + (c - 32) * 2);
|
||||
|
||||
cur_pos.x++;
|
||||
if (cur_pos.x < max_pos.x)
|
||||
return;
|
||||
|
||||
newline:
|
||||
cur_pos.y++;
|
||||
cur_pos.x = 0;
|
||||
if(cur_pos.y >= max_pos.y) {
|
||||
cur_pos.y = max_pos.y - 1;
|
||||
fbcon_scroll_up();
|
||||
} else
|
||||
fbcon_flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
void fbcon_setup(struct fbcon_config *_config)
|
||||
{
|
||||
uint32_t bg;
|
||||
uint32_t fg;
|
||||
|
||||
ASSERT(_config);
|
||||
|
||||
config = _config;
|
||||
|
||||
switch (config->format) {
|
||||
case FB_FORMAT_RGB565:
|
||||
fg = RGB565_WHITE;
|
||||
bg = RGB565_BLACK;
|
||||
break;
|
||||
case FB_FORMAT_RGB888:
|
||||
fg = RGB888_WHITE;
|
||||
bg = RGB888_BLACK;
|
||||
break;
|
||||
default:
|
||||
dprintf(CRITICAL, "unknown framebuffer pixel format\n");
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
fbcon_set_colors(0, 0, 0, 0, 0, 255);
|
||||
#else
|
||||
fbcon_set_colors(bg, fg);
|
||||
#endif
|
||||
|
||||
cur_pos.x = 0;
|
||||
cur_pos.y = 0;
|
||||
#if DISPLAY_TYPE_TOUCHPAD
|
||||
max_pos.x = config->width - FONT_WIDTH;
|
||||
max_pos.y = config->height - FONT_HEIGHT;
|
||||
#else
|
||||
max_pos.x = config->width / (FONT_WIDTH+1);
|
||||
max_pos.y = (config->height - 1) / FONT_HEIGHT;
|
||||
#endif
|
||||
#if !DISPLAY_SPLASH_SCREEN
|
||||
fbcon_clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct fbcon_config* fbcon_display(void)
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
void display_image_on_screen(void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned total_x = config->width;
|
||||
unsigned total_y = config->height;
|
||||
unsigned bytes_per_bpp = ((config->bpp) / 8);
|
||||
unsigned image_base = ((((total_y/2) - (SPLASH_IMAGE_WIDTH / 2) - 1) *
|
||||
(config->width)) + (total_x/2 - (SPLASH_IMAGE_HEIGHT / 2)));
|
||||
fbcon_clear();
|
||||
|
||||
#if DISPLAY_TYPE_MIPI
|
||||
if (bytes_per_bpp == 3)
|
||||
{
|
||||
for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
|
||||
{
|
||||
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
|
||||
imageBuffer_rgb888 + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
|
||||
SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
|
||||
}
|
||||
}
|
||||
fbcon_flush();
|
||||
#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
|
||||
if(is_cmd_mode_enabled())
|
||||
mipi_dsi_cmd_mode_trigger();
|
||||
#endif
|
||||
|
||||
#elif DISPLAY_TYPE_TOUCHPAD
|
||||
/* not supported yet */
|
||||
return;
|
||||
#else
|
||||
if (bytes_per_bpp == 2)
|
||||
{
|
||||
for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
|
||||
{
|
||||
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
|
||||
imageBuffer + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
|
||||
SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
|
||||
}
|
||||
}
|
||||
fbcon_flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
unsigned font5x12[] = {
|
||||
0x00000000, 0x00000000,
|
||||
0x08421080, 0x00020084,
|
||||
0x00052940, 0x00000000,
|
||||
0x15f52800, 0x0000295f,
|
||||
0x1c52f880, 0x00023e94,
|
||||
0x08855640, 0x0004d542,
|
||||
0x04528800, 0x000b2725,
|
||||
0x00021080, 0x00000000,
|
||||
0x04211088, 0x00821042,
|
||||
0x10841082, 0x00221108,
|
||||
0x09575480, 0x00000000,
|
||||
0x3e420000, 0x00000084,
|
||||
0x00000000, 0x00223000,
|
||||
0x3e000000, 0x00000000,
|
||||
0x00000000, 0x00471000,
|
||||
0x08844200, 0x00008442,
|
||||
0x2318a880, 0x00022a31,
|
||||
0x08429880, 0x000f9084,
|
||||
0x1108c5c0, 0x000f8444,
|
||||
0x1c4443e0, 0x00074610,
|
||||
0x14a62100, 0x000423e9,
|
||||
0x26d087e0, 0x00074610,
|
||||
0x1e10c5c0, 0x00074631,
|
||||
0x088443e0, 0x00010844,
|
||||
0x1d18c5c0, 0x00074631,
|
||||
0x3d18c5c0, 0x00074610,
|
||||
0x08e20000, 0x00471000,
|
||||
0x08e20000, 0x00223000,
|
||||
0x02222200, 0x00082082,
|
||||
0x01f00000, 0x000003e0,
|
||||
0x20820820, 0x00008888,
|
||||
0x1108c5c0, 0x00020084,
|
||||
0x2b98c5c0, 0x000f05b5,
|
||||
0x2318a880, 0x0008c63f,
|
||||
0x1d2949e0, 0x0007ca52,
|
||||
0x0210c5c0, 0x00074421,
|
||||
0x252949e0, 0x0007ca52,
|
||||
0x1e1087e0, 0x000f8421,
|
||||
0x1e1087e0, 0x00008421,
|
||||
0x0210c5c0, 0x00074639,
|
||||
0x3f18c620, 0x0008c631,
|
||||
0x084211c0, 0x00071084,
|
||||
0x10842380, 0x00032508,
|
||||
0x0654c620, 0x0008c525,
|
||||
0x02108420, 0x000f8421,
|
||||
0x2b5dc620, 0x0008c631,
|
||||
0x2b59ce20, 0x0008c739,
|
||||
0x2318c5c0, 0x00074631,
|
||||
0x1f18c5e0, 0x00008421,
|
||||
0x2318c5c0, 0x01075631,
|
||||
0x1f18c5e0, 0x0008c525,
|
||||
0x1c10c5c0, 0x00074610,
|
||||
0x084213e0, 0x00021084,
|
||||
0x2318c620, 0x00074631,
|
||||
0x1518c620, 0x0002114a,
|
||||
0x2b18c620, 0x000556b5,
|
||||
0x08a54620, 0x0008c54a,
|
||||
0x08a54620, 0x00021084,
|
||||
0x088443e0, 0x000f8442,
|
||||
0x0421084e, 0x00e10842,
|
||||
0x08210420, 0x00084108,
|
||||
0x1084210e, 0x00e42108,
|
||||
0x0008a880, 0x00000000,
|
||||
0x00000000, 0x01f00000,
|
||||
0x00000104, 0x00000000,
|
||||
0x20e00000, 0x000b663e,
|
||||
0x22f08420, 0x0007c631,
|
||||
0x22e00000, 0x00074421,
|
||||
0x23e84200, 0x000f4631,
|
||||
0x22e00000, 0x0007443f,
|
||||
0x1e214980, 0x00010842,
|
||||
0x22e00000, 0x1d187a31,
|
||||
0x26d08420, 0x0008c631,
|
||||
0x08601000, 0x00071084,
|
||||
0x10c02000, 0x0c94a108,
|
||||
0x0a908420, 0x0008a4a3,
|
||||
0x084210c0, 0x00071084,
|
||||
0x2ab00000, 0x0008d6b5,
|
||||
0x26d00000, 0x0008c631,
|
||||
0x22e00000, 0x00074631,
|
||||
0x22f00000, 0x0210be31,
|
||||
0x23e00000, 0x21087a31,
|
||||
0x26d00000, 0x00008421,
|
||||
0x22e00000, 0x00074506,
|
||||
0x04f10800, 0x00064842,
|
||||
0x23100000, 0x000b6631,
|
||||
0x23100000, 0x00022951,
|
||||
0x23100000, 0x000556b5,
|
||||
0x15100000, 0x0008a884,
|
||||
0x23100000, 0x1d185b31,
|
||||
0x11f00000, 0x000f8444,
|
||||
0x06421098, 0x01821084,
|
||||
0x08421080, 0x00021084,
|
||||
0x30421083, 0x00321084,
|
||||
0x0004d640, 0x00000000,
|
||||
0x00000000, 0x00000000,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/fbcon.o
|
||||
|
||||
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dev/keys.h>
|
||||
#include <dev/gpio.h>
|
||||
#include <dev/gpio_keypad.h>
|
||||
#include <dev/ssbi.h>
|
||||
#include <kernel/event.h>
|
||||
#include <kernel/timer.h>
|
||||
#include <reg.h>
|
||||
#include <platform/iomap.h>
|
||||
#include <platform/timer.h>
|
||||
#include <platform.h>
|
||||
|
||||
#define LINUX_MACHTYPE_8660_QT 3298
|
||||
|
||||
struct gpio_kp {
|
||||
struct gpio_keypad_info *keypad_info;
|
||||
struct timer timer;
|
||||
event_t full_scan;
|
||||
int current_output;
|
||||
unsigned int some_keys_pressed:2;
|
||||
unsigned long keys_pressed[0];
|
||||
};
|
||||
|
||||
struct gpio_qwerty_kp {
|
||||
struct qwerty_keypad_info *keypad_info;
|
||||
struct timer timer;
|
||||
event_t full_scan;
|
||||
unsigned int some_keys_pressed:2;
|
||||
unsigned long keys_pressed[0];
|
||||
};
|
||||
|
||||
static struct gpio_qwerty_kp *qwerty_keypad;
|
||||
/* TODO: Support multiple keypads? */
|
||||
static struct gpio_kp *keypad;
|
||||
|
||||
static void check_output(struct gpio_kp *kp, int out, int polarity)
|
||||
{
|
||||
struct gpio_keypad_info *kpinfo = kp->keypad_info;
|
||||
int key_index;
|
||||
int in;
|
||||
int gpio;
|
||||
int changed = 0;
|
||||
|
||||
key_index = out * kpinfo->ninputs;
|
||||
for (in = 0; in < kpinfo->ninputs; in++, key_index++) {
|
||||
gpio = kpinfo->input_gpios[in];
|
||||
changed = 0;
|
||||
if (gpio_get(gpio) ^ !polarity) {
|
||||
if (kp->some_keys_pressed < 3)
|
||||
kp->some_keys_pressed++;
|
||||
changed = !bitmap_set(kp->keys_pressed, key_index);
|
||||
} else {
|
||||
changed = bitmap_clear(kp->keys_pressed, key_index);
|
||||
}
|
||||
if (changed) {
|
||||
int state = bitmap_test(kp->keys_pressed, key_index);
|
||||
keys_post_event(kpinfo->keymap[key_index], state);
|
||||
}
|
||||
}
|
||||
|
||||
/* sets up the right state for the next poll cycle */
|
||||
gpio = kpinfo->output_gpios[out];
|
||||
if (kpinfo->flags & GPIOKPF_DRIVE_INACTIVE)
|
||||
gpio_set(gpio, !polarity);
|
||||
else
|
||||
gpio_config(gpio, GPIO_INPUT);
|
||||
}
|
||||
|
||||
static enum handler_return
|
||||
gpio_keypad_timer_func(struct timer *timer, time_t now, void *arg)
|
||||
{
|
||||
struct gpio_kp *kp = keypad;
|
||||
struct gpio_keypad_info *kpinfo = kp->keypad_info;
|
||||
int polarity = !!(kpinfo->flags & GPIOKPF_ACTIVE_HIGH);
|
||||
int out;
|
||||
int gpio;
|
||||
|
||||
out = kp->current_output;
|
||||
if (out == kpinfo->noutputs) {
|
||||
out = 0;
|
||||
kp->some_keys_pressed = 0;
|
||||
} else {
|
||||
check_output(kp, out, polarity);
|
||||
out++;
|
||||
}
|
||||
|
||||
kp->current_output = out;
|
||||
if (out < kpinfo->noutputs) {
|
||||
gpio = kpinfo->output_gpios[out];
|
||||
if (kpinfo->flags & GPIOKPF_DRIVE_INACTIVE)
|
||||
gpio_set(gpio, polarity);
|
||||
else
|
||||
gpio_config(gpio, polarity ? GPIO_OUTPUT : 0);
|
||||
timer_set_oneshot(timer, kpinfo->settle_time,
|
||||
gpio_keypad_timer_func, NULL);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (/*!kp->use_irq*/ 1 || kp->some_keys_pressed) {
|
||||
event_signal(&kp->full_scan, false);
|
||||
timer_set_oneshot(timer, kpinfo->poll_time,
|
||||
gpio_keypad_timer_func, NULL);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
return INT_RESCHEDULE;
|
||||
}
|
||||
|
||||
void gpio_keypad_init(struct gpio_keypad_info *kpinfo)
|
||||
{
|
||||
int key_count;
|
||||
int output_val;
|
||||
int output_cfg;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
ASSERT(kpinfo->keymap && kpinfo->input_gpios && kpinfo->output_gpios);
|
||||
key_count = kpinfo->ninputs * kpinfo->noutputs;
|
||||
|
||||
len = sizeof(struct gpio_kp) + (sizeof(unsigned long) *
|
||||
BITMAP_NUM_WORDS(key_count));
|
||||
keypad = malloc(len);
|
||||
ASSERT(keypad);
|
||||
|
||||
memset(keypad, 0, len);
|
||||
keypad->keypad_info = kpinfo;
|
||||
|
||||
output_val = (!!(kpinfo->flags & GPIOKPF_ACTIVE_HIGH)) ^
|
||||
(!!(kpinfo->flags & GPIOKPF_DRIVE_INACTIVE));
|
||||
output_cfg = kpinfo->flags & GPIOKPF_DRIVE_INACTIVE ? GPIO_OUTPUT : 0;
|
||||
for (i = 0; i < kpinfo->noutputs; i++) {
|
||||
gpio_set(kpinfo->output_gpios[i], output_val);
|
||||
gpio_config(kpinfo->output_gpios[i], output_cfg);
|
||||
}
|
||||
for (i = 0; i < kpinfo->ninputs; i++)
|
||||
gpio_config(kpinfo->input_gpios[i], GPIO_INPUT);
|
||||
|
||||
keypad->current_output = kpinfo->noutputs;
|
||||
|
||||
event_init(&keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
timer_initialize(&keypad->timer);
|
||||
timer_set_oneshot(&keypad->timer, 0, gpio_keypad_timer_func, NULL);
|
||||
|
||||
/* wait for the keypad to complete one full scan */
|
||||
event_wait(&keypad->full_scan);
|
||||
}
|
||||
|
||||
int pm8058_gpio_config(int gpio, struct pm8058_gpio *param)
|
||||
{
|
||||
int rc;
|
||||
write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
|
||||
unsigned char bank[8];
|
||||
static int dir_map[] = {
|
||||
PM8058_GPIO_MODE_OFF,
|
||||
PM8058_GPIO_MODE_OUTPUT,
|
||||
PM8058_GPIO_MODE_INPUT,
|
||||
PM8058_GPIO_MODE_BOTH,
|
||||
};
|
||||
|
||||
if (param == 0) {
|
||||
dprintf (INFO, "pm8058_gpio struct not defined\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Select banks and configure the gpio */
|
||||
bank[0] = PM8058_GPIO_WRITE |
|
||||
((param->vin_sel << PM8058_GPIO_VIN_SHIFT) &
|
||||
PM8058_GPIO_VIN_MASK) |
|
||||
PM8058_GPIO_MODE_ENABLE;
|
||||
bank[1] = PM8058_GPIO_WRITE |
|
||||
((1 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
|
||||
((dir_map[param->direction] << PM8058_GPIO_MODE_SHIFT) &
|
||||
PM8058_GPIO_MODE_MASK) |
|
||||
((param->direction & PM_GPIO_DIR_OUT) ?
|
||||
PM8058_GPIO_OUT_BUFFER : 0);
|
||||
bank[2] = PM8058_GPIO_WRITE |
|
||||
((2 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
|
||||
((param->pull << PM8058_GPIO_PULL_SHIFT) &
|
||||
PM8058_GPIO_PULL_MASK);
|
||||
bank[3] = PM8058_GPIO_WRITE |
|
||||
((3 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
|
||||
((param->out_strength << PM8058_GPIO_OUT_STRENGTH_SHIFT) &
|
||||
PM8058_GPIO_OUT_STRENGTH_MASK);
|
||||
bank[4] = PM8058_GPIO_WRITE |
|
||||
((4 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
|
||||
((param->function << PM8058_GPIO_FUNC_SHIFT) &
|
||||
PM8058_GPIO_FUNC_MASK);
|
||||
|
||||
rc = (*wr_function)(bank, 5, SSBI_REG_ADDR_GPIO(gpio));
|
||||
if (rc) {
|
||||
dprintf(INFO, "Failed on 1st ssbi_write(): rc=%d.\n", rc);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pm8058_gpio_config_kypd_drv(int gpio_start, int num_gpios, unsigned mach_id)
|
||||
{
|
||||
int rc;
|
||||
struct pm8058_gpio kypd_drv = {
|
||||
.direction = PM_GPIO_DIR_OUT,
|
||||
.pull = PM_GPIO_PULL_NO,
|
||||
.vin_sel = 2,
|
||||
.out_strength = PM_GPIO_STRENGTH_LOW,
|
||||
.function = PM_GPIO_FUNC_1,
|
||||
.inv_int_pol = 1,
|
||||
};
|
||||
|
||||
if(mach_id == LINUX_MACHTYPE_8660_QT)
|
||||
kypd_drv.function = PM_GPIO_FUNC_NORMAL;
|
||||
|
||||
while (num_gpios--) {
|
||||
rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
|
||||
if (rc) {
|
||||
dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pm8058_gpio_config_kypd_sns(int gpio_start, int num_gpios)
|
||||
{
|
||||
int rc;
|
||||
struct pm8058_gpio kypd_sns = {
|
||||
.direction = PM_GPIO_DIR_IN,
|
||||
.pull = PM_GPIO_PULL_UP1,
|
||||
.vin_sel = 2,
|
||||
.out_strength = PM_GPIO_STRENGTH_NO,
|
||||
.function = PM_GPIO_FUNC_NORMAL,
|
||||
.inv_int_pol = 1,
|
||||
};
|
||||
|
||||
while (num_gpios--) {
|
||||
rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
|
||||
if (rc) {
|
||||
dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ssbi_gpio_init(unsigned int mach_id)
|
||||
{
|
||||
unsigned char kypd_cntl_init;
|
||||
unsigned char kypd_scan_init = 0x20;
|
||||
int rows = (qwerty_keypad->keypad_info)->rows;
|
||||
int columns = (qwerty_keypad->keypad_info)->columns;
|
||||
write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
|
||||
unsigned char drv_bits[] = {
|
||||
0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7 };
|
||||
unsigned char sns_bits[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3 };
|
||||
|
||||
kypd_cntl_init = ((drv_bits[rows] << 2) | (sns_bits[columns] << 5) | (1 << 7));
|
||||
|
||||
if ((*wr_function)(&kypd_cntl_init, 1, SSBI_REG_KYPD_CNTL_ADDR))
|
||||
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
|
||||
|
||||
if ((*wr_function)(&kypd_scan_init, 1, SSBI_REG_KYPD_SCAN_ADDR))
|
||||
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_SCAN register\n");
|
||||
|
||||
if(mach_id == LINUX_MACHTYPE_8660_QT)
|
||||
{
|
||||
pm8058_gpio_config_kypd_sns(QT_PMIC_GPIO_KYPD_SNS, rows);
|
||||
pm8058_gpio_config_kypd_drv(QT_PMIC_GPIO_KYPD_DRV, columns, mach_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm8058_gpio_config_kypd_sns(SSBI_OFFSET_ADDR_GPIO_KYPD_SNS, columns);
|
||||
pm8058_gpio_config_kypd_drv(SSBI_OFFSET_ADDR_GPIO_KYPD_DRV, rows, mach_id);
|
||||
}
|
||||
}
|
||||
|
||||
static enum handler_return
|
||||
scan_qwerty_keypad(struct timer *timer, time_t now, void *arg)
|
||||
{
|
||||
unsigned int rows = (qwerty_keypad->keypad_info)->rows;
|
||||
unsigned int columns = (qwerty_keypad->keypad_info)->columns;
|
||||
unsigned int num_of_ssbi_reads = (qwerty_keypad->keypad_info)->num_of_reads;
|
||||
read_func rd_function = (qwerty_keypad->keypad_info)->rd_func;
|
||||
unsigned char column_new_keys = 0x00;
|
||||
unsigned char column_old_keys = 0x00;
|
||||
int shift = 0;
|
||||
static int key_detected = -1;
|
||||
|
||||
if ((*rd_function)((qwerty_keypad->keypad_info)->rec_keys, num_of_ssbi_reads,
|
||||
SSBI_REG_KYPD_REC_DATA_ADDR))
|
||||
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
|
||||
|
||||
if ((*rd_function)((qwerty_keypad->keypad_info)->old_keys, num_of_ssbi_reads,
|
||||
SSBI_REG_KYPD_OLD_DATA_ADDR))
|
||||
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
|
||||
|
||||
while (rows--) {
|
||||
columns = qwerty_keypad->keypad_info->columns;
|
||||
if (((qwerty_keypad->keypad_info)->rec_keys[rows]
|
||||
!= (qwerty_keypad->keypad_info)->old_keys[rows])
|
||||
&& ((qwerty_keypad->keypad_info)->rec_keys[rows] != 0x00)
|
||||
&& ((qwerty_keypad->keypad_info)->old_keys[rows] != 0x00)) {
|
||||
while (columns--) {
|
||||
column_new_keys = ((qwerty_keypad->keypad_info)->rec_keys[rows]);
|
||||
column_old_keys = ((qwerty_keypad->keypad_info)->old_keys[rows]);
|
||||
if (((0x01 << columns) & (~column_new_keys))
|
||||
&& !((0x01 << columns) & (~column_old_keys))) {
|
||||
shift = (rows * 8) + columns;
|
||||
if ((qwerty_keypad->keypad_info)->keymap[shift]) {
|
||||
if (shift != key_detected) {
|
||||
key_detected = shift;
|
||||
keys_post_event((qwerty_keypad->keypad_info)->keymap[shift], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event_signal(&qwerty_keypad->full_scan, false);
|
||||
return INT_RESCHEDULE;
|
||||
}
|
||||
|
||||
static enum handler_return
|
||||
scan_qt_keypad(struct timer *timer, time_t now, void *arg)
|
||||
{
|
||||
unsigned int gpio;
|
||||
unsigned int last_state=0;
|
||||
unsigned int new_state=0;
|
||||
unsigned int bits_changed;
|
||||
static int key_detected=-1;
|
||||
|
||||
/* Row GPIOs 8,9,10 are used for sensing here */
|
||||
for (gpio=8;gpio<=10;gpio++)
|
||||
{
|
||||
bool status;
|
||||
status = pm8058_gpio_get(gpio);
|
||||
if (status == 0)
|
||||
new_state |= (1<<(gpio-8));
|
||||
}
|
||||
|
||||
bits_changed = last_state ^ new_state;
|
||||
|
||||
if (bits_changed)
|
||||
{
|
||||
int shift = 0;
|
||||
for (unsigned int rows = 0; rows < (qwerty_keypad->keypad_info)->rows; rows++)
|
||||
{
|
||||
if ((bits_changed & (1<<rows)) == 0)
|
||||
continue;
|
||||
shift = rows * 8 + 3;
|
||||
}
|
||||
if ((qwerty_keypad->keypad_info)->keymap[shift])
|
||||
{
|
||||
if (shift != key_detected)
|
||||
{
|
||||
key_detected = shift;
|
||||
keys_post_event((qwerty_keypad->keypad_info)->keymap[shift], 1);
|
||||
timer_set_oneshot(timer,(qwerty_keypad->keypad_info)->poll_time,
|
||||
scan_qt_keypad, NULL);
|
||||
return INT_RESCHEDULE;
|
||||
}
|
||||
}
|
||||
}
|
||||
event_signal(&qwerty_keypad->full_scan, false);
|
||||
return INT_RESCHEDULE;
|
||||
}
|
||||
|
||||
void ssbi_keypad_init(struct qwerty_keypad_info *qwerty_kp)
|
||||
{
|
||||
unsigned int mach_id;
|
||||
int len;
|
||||
|
||||
len = sizeof(struct gpio_qwerty_kp);
|
||||
qwerty_keypad = malloc(len);
|
||||
ASSERT(qwerty_keypad);
|
||||
|
||||
memset(qwerty_keypad, 0, len);
|
||||
qwerty_keypad->keypad_info = qwerty_kp;
|
||||
|
||||
event_init(&qwerty_keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
timer_initialize(&qwerty_keypad->timer);
|
||||
|
||||
#ifdef QT_8660_KEYPAD_HW_BUG
|
||||
mach_id = board_machtype();
|
||||
#endif
|
||||
ssbi_gpio_init(mach_id);
|
||||
|
||||
if(mach_id == LINUX_MACHTYPE_8660_QT)
|
||||
{
|
||||
mdelay((qwerty_keypad->keypad_info)->settle_time);
|
||||
#ifdef QT_8660_KEYPAD_HW_BUG
|
||||
timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qt_keypad, NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qwerty_keypad, NULL);
|
||||
|
||||
/* wait for the keypad to complete one full scan */
|
||||
event_wait(&qwerty_keypad->full_scan);
|
||||
}
|
||||
|
||||
void pmic_write(unsigned address, unsigned data)
|
||||
{
|
||||
write_func wr_function = &i2c_ssbi_write_bytes;
|
||||
if (wr_function == NULL)
|
||||
return;
|
||||
if ((*wr_function)((unsigned char *) &data, 1, address))
|
||||
dprintf (CRITICAL, "Error in initializing register\n");
|
||||
|
||||
}
|
||||
void toshiba_pmic_gpio_init(unsigned gpio)
|
||||
{
|
||||
pmic_write(gpio,0x85);
|
||||
pmic_write(gpio,0x98);
|
||||
pmic_write(gpio,0xB8);
|
||||
pmic_write(gpio,0xC6);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <bits.h>
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <dev/keys.h>
|
||||
|
||||
static unsigned long key_bitmap[BITMAP_NUM_WORDS(MAX_KEYS)];
|
||||
|
||||
void keys_init(void)
|
||||
{
|
||||
memset(key_bitmap, 0, sizeof(key_bitmap));
|
||||
}
|
||||
|
||||
void keys_post_event(uint16_t code, int16_t value)
|
||||
{
|
||||
if (code >= MAX_KEYS) {
|
||||
dprintf(INFO, "Invalid keycode posted: %d\n", code);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Implement an actual event queue if it becomes necessary */
|
||||
if (value)
|
||||
bitmap_set(key_bitmap, code);
|
||||
else
|
||||
bitmap_clear(key_bitmap, code);
|
||||
|
||||
// dprintf(INFO, "key state change: %d %d\n", code, value);
|
||||
}
|
||||
|
||||
int keys_get_state(uint16_t code)
|
||||
{
|
||||
if (code >= MAX_KEYS) {
|
||||
dprintf(INFO, "Invalid keycode requested: %d\n", code);
|
||||
return -1;
|
||||
}
|
||||
return bitmap_test(key_bitmap, code);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/keys.o
|
||||
|
||||
ifeq ($(KEYS_USE_GPIO_KEYPAD),1)
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/gpio_keypad.o
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef _DEV_NET_SMC91C96_H
|
||||
#define _DEV_NET_SMC91C96_H
|
||||
|
||||
void smc91c96_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += \
|
||||
-I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/smc91c96.o
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <debug.h>
|
||||
#include <printf.h>
|
||||
#include <dev/net/smc91c96.h>
|
||||
#include "smc91c96_p.h"
|
||||
|
||||
#if !defined(SMC91C96_BASE_ADDR) || !defined(SMC91C96_IRQ)
|
||||
#error need to define SMC91C96_BASE_ADDR and SMC91C96_IRQ in project
|
||||
#endif
|
||||
|
||||
static addr_t smc91c96_base = SMC91C96_BASE_ADDR;
|
||||
static uint8_t mac_addr[6];
|
||||
|
||||
#define SMC_REG16(reg) ((volatile uint16_t *)(smc91c96_base + (reg)))
|
||||
#define SMC_REG8(reg) ((volatile uint8_t *)(smc91c96_base + (reg)))
|
||||
|
||||
static inline void smc_bank(int bank)
|
||||
{
|
||||
*SMC_REG16(SMC_BSR) = bank;
|
||||
}
|
||||
|
||||
void smc91c96_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACE;
|
||||
|
||||
// try to detect it
|
||||
if ((*SMC_REG16(SMC_BSR) & 0xff00) != 0x3300) {
|
||||
TRACEF("didn't see smc91c96 chip at 0x%x\n", (unsigned int)smc91c96_base);
|
||||
}
|
||||
|
||||
// read revision
|
||||
smc_bank(3);
|
||||
TRACEF("detected, revision 0x%x\n", *SMC_REG16(SMC_REV));
|
||||
|
||||
// read in the mac address
|
||||
smc_bank(1);
|
||||
for (i=0; i < 6; i++) {
|
||||
mac_addr[i] = *SMC_REG8(SMC_IAR0 + i);
|
||||
}
|
||||
TRACEF("mac address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
mac_addr[0], mac_addr[1], mac_addr[2],
|
||||
mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
|
||||
smc_bank(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __SMC91C96_P_H
|
||||
#define __SMC91C96_P_H
|
||||
|
||||
// LAN91C96 stuffs
|
||||
|
||||
/* registers */
|
||||
|
||||
#define SMC_BSR 14
|
||||
|
||||
/* bank 0 */
|
||||
#define SMC_TCR 0
|
||||
#define SMC_EPHSR 2
|
||||
#define SMC_RCR 4
|
||||
#define SMC_ECR 6
|
||||
#define SMC_MIR 8
|
||||
#define SMC_MCR 10
|
||||
|
||||
/* bank 1 */
|
||||
#define SMC_CR 0
|
||||
#define SMC_BAR 2
|
||||
#define SMC_IAR0 4
|
||||
#define SMC_IAR1 5
|
||||
#define SMC_IAR2 6
|
||||
#define SMC_IAR3 7
|
||||
#define SMC_IAR4 8
|
||||
#define SMC_IAR5 9
|
||||
#define SMC_GPR 10
|
||||
#define SMC_CTR 12
|
||||
|
||||
/* bank 2 */
|
||||
#define SMC_MMUCR 0
|
||||
#define SMC_AUTOTX 1
|
||||
#define SMC_PNR 2
|
||||
#define SMC_ARR 3
|
||||
#define SMC_FIFO 4
|
||||
#define SMC_PTR 6
|
||||
#define SMC_DATA0 8
|
||||
#define SMC_DATA1 10
|
||||
#define SMC_IST 12
|
||||
#define SMC_ACK 12
|
||||
#define SMC_MSK 13
|
||||
|
||||
/* bank 3 */
|
||||
#define SMC_MT0 0
|
||||
#define SMC_MT1 1
|
||||
#define SMC_MT2 2
|
||||
#define SMC_MT3 3
|
||||
#define SMC_MT4 4
|
||||
#define SMC_MT5 5
|
||||
#define SMC_MT6 6
|
||||
#define SMC_MT7 7
|
||||
#define SMC_MGMT 8
|
||||
#define SMC_REV 10
|
||||
#define SMC_ERCV 12
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __DEV_PM8921_H
|
||||
#define __DEV_PM8921_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#define PM_GPIO_DIR_OUT 0x01
|
||||
#define PM_GPIO_DIR_IN 0x02
|
||||
#define PM_GPIO_DIR_BOTH (PM_GPIO_DIR_OUT | PM_GPIO_DIR_IN)
|
||||
|
||||
#define PM_GPIO_PULL_UP_30 0
|
||||
#define PM_GPIO_PULL_UP_31_5 2
|
||||
/* 1.5uA + 30uA boost */
|
||||
#define PM_GPIO_PULL_UP_1_5_30 3
|
||||
#define PM_GPIO_PULL_DN 4
|
||||
#define PM_GPIO_PULL_NO 5
|
||||
|
||||
#define PM_GPIO_STRENGTH_NO 0
|
||||
#define PM_GPIO_STRENGTH_HIGH 1
|
||||
#define PM_GPIO_STRENGTH_MED 2
|
||||
#define PM_GPIO_STRENGTH_LOW 3
|
||||
|
||||
#define PM_GPIO_FUNC_NORMAL 0
|
||||
#define PM_GPIO_FUNC_PAIRED 1
|
||||
#define PM_GPIO_FUNC_1 2
|
||||
#define PM_GPIO_FUNC_2 3
|
||||
|
||||
/* GPIO24 for backlight_pwm which is 23 (index start at 0) */
|
||||
#define GPIO_24 23
|
||||
#define GPIO_43 42
|
||||
|
||||
/* LDO define values */
|
||||
#define LDO_P_MASK (1 << 7)
|
||||
|
||||
#define LDO_2 (2)
|
||||
#define LDO_8 (8 | LDO_P_MASK)
|
||||
#define LDO_23 (23 | LDO_P_MASK)
|
||||
|
||||
enum
|
||||
{
|
||||
LDO_VOLTAGE_1_2V = 0,
|
||||
LDO_VOLTAGE_1_8V = 1,
|
||||
LDO_VOLTAGE_3_0V = 2,
|
||||
LDO_VOLTAGE_ENTRIES
|
||||
};
|
||||
|
||||
typedef int (*pm8921_read_func)(uint8_t *data, uint32_t length, uint32_t addr);
|
||||
typedef int (*pm8921_write_func)(uint8_t *data, uint32_t length, uint32_t addr);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t initialized;
|
||||
|
||||
pm8921_read_func read;
|
||||
pm8921_write_func write;
|
||||
|
||||
} pm8921_dev_t;
|
||||
|
||||
|
||||
struct pm8921_gpio {
|
||||
int direction;
|
||||
int output_buffer;
|
||||
int output_value;
|
||||
int pull;
|
||||
int vin_sel;
|
||||
int out_strength;
|
||||
int function;
|
||||
int inv_int_pol;
|
||||
int disable_pin;
|
||||
};
|
||||
|
||||
void pm8921_init(pm8921_dev_t *);
|
||||
int pm8921_gpio_config(int gpio, struct pm8921_gpio *param);
|
||||
void pm8921_boot_done(void);
|
||||
int pm8921_ldo_set_voltage(uint32_t ldo_id, uint32_t voltage);
|
||||
int pm8921_config_reset_pwr_off(unsigned reset);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <dev/pm8921.h>
|
||||
#include "pm8921_hw.h"
|
||||
|
||||
|
||||
static pm8921_dev_t *dev;
|
||||
|
||||
static uint8_t ldo_n_voltage_mult[LDO_VOLTAGE_ENTRIES] = {
|
||||
18, /* 1.2V */
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static uint8_t ldo_p_voltage_mult[LDO_VOLTAGE_ENTRIES] = {
|
||||
0,
|
||||
6, /* 1.8V */
|
||||
30, /* 3.0V */
|
||||
};
|
||||
|
||||
/* Intialize the pmic driver */
|
||||
void pm8921_init(pm8921_dev_t *pmic)
|
||||
{
|
||||
ASSERT(pmic);
|
||||
ASSERT(pmic->read);
|
||||
ASSERT(pmic->write);
|
||||
|
||||
dev = pmic;
|
||||
|
||||
dev->initialized = 1;
|
||||
}
|
||||
|
||||
static int pm8921_masked_write(uint16_t addr,
|
||||
uint8_t mask, uint8_t val)
|
||||
{
|
||||
int rc;
|
||||
uint8_t reg;
|
||||
|
||||
rc = dev->read(®, 1, addr);
|
||||
if (rc)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
reg &= ~mask;
|
||||
reg |= val & mask;
|
||||
rc = dev->write(®, 1, addr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Set the BOOT_DONE flag */
|
||||
void pm8921_boot_done(void)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
ASSERT(dev);
|
||||
ASSERT(dev->initialized);
|
||||
|
||||
dev->read(&val, 1, PBL_ACCESS_2);
|
||||
val |= PBL_ACCESS_2_ENUM_TIMER_STOP;
|
||||
/* TODO: Remove next line when h/w is rewired for battery simulation.*/
|
||||
val |= (0x7 << 2);
|
||||
dev->write(&val, 1, PBL_ACCESS_2);
|
||||
|
||||
dev->read(&val, 1, SYS_CONFIG_2);
|
||||
val |= (SYS_CONFIG_2_BOOT_DONE | SYS_CONFIG_2_ADAPTIVE_BOOT_DISABLE);
|
||||
dev->write(&val, 1, SYS_CONFIG_2);
|
||||
}
|
||||
|
||||
/* Configure PMIC GPIO */
|
||||
int pm8921_gpio_config(int gpio, struct pm8921_gpio *param)
|
||||
{
|
||||
int ret;
|
||||
uint8_t bank[6];
|
||||
uint8_t output_buf_config;
|
||||
uint8_t output_value;
|
||||
|
||||
static uint8_t dir_map[] = {
|
||||
PM_GPIO_MODE_OFF,
|
||||
PM_GPIO_MODE_OUTPUT,
|
||||
PM_GPIO_MODE_INPUT,
|
||||
PM_GPIO_MODE_BOTH,
|
||||
};
|
||||
|
||||
if (param == NULL) {
|
||||
dprintf (CRITICAL, "pm8291_gpio struct not defined\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Select banks and configure the gpio */
|
||||
bank[0] = PM_GPIO_WRITE |
|
||||
((param->vin_sel << PM_GPIO_VIN_SHIFT) &
|
||||
PM_GPIO_VIN_MASK) |
|
||||
PM_GPIO_MODE_ENABLE;
|
||||
|
||||
/* bank1 */
|
||||
if ((param->direction & PM_GPIO_DIR_OUT) && param->output_buffer)
|
||||
output_buf_config = PM_GPIO_OUT_BUFFER_OPEN_DRAIN;
|
||||
else
|
||||
output_buf_config = 0;
|
||||
|
||||
if ((param->direction & PM_GPIO_DIR_OUT) && param->output_value)
|
||||
output_value = 1;
|
||||
else
|
||||
output_value = 0;
|
||||
|
||||
bank[1] = PM_GPIO_WRITE |
|
||||
((1 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
|
||||
((dir_map[param->direction] << PM_GPIO_MODE_SHIFT)
|
||||
& PM_GPIO_MODE_MASK) |
|
||||
output_buf_config |
|
||||
output_value;
|
||||
|
||||
bank[2] = PM_GPIO_WRITE |
|
||||
((2 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
|
||||
((param->pull << PM_GPIO_PULL_SHIFT) &
|
||||
PM_GPIO_PULL_MASK);
|
||||
|
||||
bank[3] = PM_GPIO_WRITE |
|
||||
((3 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
|
||||
((param->out_strength << PM_GPIO_OUT_STRENGTH_SHIFT) &
|
||||
PM_GPIO_OUT_STRENGTH_MASK) |
|
||||
(param->disable_pin ? PM_GPIO_PIN_DISABLE : PM_GPIO_PIN_ENABLE);
|
||||
|
||||
bank[4] = PM_GPIO_WRITE |
|
||||
((4 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
|
||||
((param->function << PM_GPIO_FUNC_SHIFT) &
|
||||
PM_GPIO_FUNC_MASK);
|
||||
|
||||
bank[5] = PM_GPIO_WRITE |
|
||||
((5 << PM_GPIO_BANK_SHIFT) & PM_GPIO_BANK_MASK) |
|
||||
(param->inv_int_pol ? 0 : PM_GPIO_NON_INT_POL_INV);
|
||||
|
||||
ret = dev->write(bank, 6, GPIO_CNTL(gpio));
|
||||
if (ret) {
|
||||
dprintf(CRITICAL, "Failed to write to PM8921 ret=%d.\n", ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pm8921_ldo_set_voltage(uint32_t ldo_id, uint32_t voltage)
|
||||
{
|
||||
uint8_t mult;
|
||||
uint8_t val = 0;
|
||||
uint32_t ldo_number = (ldo_id & ~LDO_P_MASK);
|
||||
int32_t ret = 0;
|
||||
|
||||
/* Find the voltage multiplying factor */
|
||||
if(ldo_id & LDO_P_MASK)
|
||||
mult = ldo_p_voltage_mult[voltage];
|
||||
else
|
||||
mult = ldo_n_voltage_mult[voltage];
|
||||
|
||||
/* Program the TEST reg */
|
||||
if (ldo_id & LDO_P_MASK){
|
||||
/* Bank 2, only for p ldo, use 1.25V reference */
|
||||
val = 0x0;
|
||||
val |= ( 1 << PM8921_LDO_TEST_REG_RW );
|
||||
val |= ( 2 << PM8921_LDO_TEST_REG_BANK_SEL);
|
||||
ret = dev->write(&val, 1, PM8921_LDO_TEST_REG(ldo_number));
|
||||
if (ret) {
|
||||
dprintf(CRITICAL, "Failed to write to PM8921 LDO Test Reg ret=%d.\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Bank 4, only for p ldo, disable output range ext, normal capacitance */
|
||||
val = 0x0;
|
||||
val |= ( 1 << PM8921_LDO_TEST_REG_RW );
|
||||
val |= ( 4 << PM8921_LDO_TEST_REG_BANK_SEL);
|
||||
ret = dev->write(&val, 1, PM8921_LDO_TEST_REG(ldo_number));
|
||||
if (ret) {
|
||||
dprintf(CRITICAL, "Failed to write to PM8921 LDO Test Reg ret=%d.\n", ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Program the CTRL reg */
|
||||
val = 0x0;
|
||||
val |= ( 1 << PM8921_LDO_CTRL_REG_ENABLE);
|
||||
val |= ( 1 << PM8921_LDO_CTRL_REG_PULL_DOWN);
|
||||
val |= ( 0 << PM8921_LDO_CTRL_REG_POWER_MODE);
|
||||
val |= ( mult << PM8921_LDO_CTRL_REG_VOLTAGE);
|
||||
ret = dev->write(&val, 1, PM8921_LDO_CTRL_REG(ldo_number));
|
||||
if (ret) {
|
||||
dprintf(CRITICAL, "Failed to write to PM8921 LDO Ctrl Reg ret=%d.\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure PMIC for reset and power off.
|
||||
* reset = 1: Configure reset.
|
||||
* reset = 0: Configure power off.
|
||||
*/
|
||||
int pm8921_config_reset_pwr_off(unsigned reset)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Enable SMPL(Short Momentary Power Loss) if resetting is desired. */
|
||||
rc = pm8921_masked_write(PM8921_SLEEP_CTRL_REG,
|
||||
SLEEP_CTRL_SMPL_EN_MASK,
|
||||
(reset ? SLEEP_CTRL_SMPL_EN_RESET : SLEEP_CTRL_SMPL_EN_PWR_OFF));
|
||||
if (rc)
|
||||
{
|
||||
goto read_write_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Select action to perform (reset or shutdown) when PS_HOLD goes low.
|
||||
* Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
|
||||
* USB charging is enabled.
|
||||
*/
|
||||
rc = pm8921_masked_write(PM8921_PON_CTRL_1_REG,
|
||||
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
|
||||
| PON_CTRL_1_WD_EN_MASK,
|
||||
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
|
||||
| (reset ? PON_CTRL_1_WD_EN_RESET : PON_CTRL_1_WD_EN_PWR_OFF));
|
||||
if (rc)
|
||||
{
|
||||
goto read_write_err;
|
||||
}
|
||||
|
||||
read_write_err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define PBL_ACCESS_2 0x005
|
||||
#define PBL_ACCESS_2_ENUM_TIMER_STOP (1 << 1)
|
||||
|
||||
#define SYS_CONFIG_2 0x007
|
||||
#define SYS_CONFIG_2_BOOT_DONE (1 << 6)
|
||||
#define SYS_CONFIG_2_ADAPTIVE_BOOT_DISABLE (1 << 7)
|
||||
|
||||
#define PM8921_LDO_REG_BASE 0x0AE
|
||||
#define PM8921_LDO_CTRL_REG(id) (PM8921_LDO_REG_BASE + (2 * (id-1)))
|
||||
#define PM8921_LDO_TEST_REG(id) (PM8921_LDO_CTRL_REG(id) + 1)
|
||||
|
||||
/* Bit offsets LDO CTRL register */
|
||||
#define PM8921_LDO_CTRL_REG_ENABLE 7
|
||||
#define PM8921_LDO_CTRL_REG_PULL_DOWN 6
|
||||
#define PM8921_LDO_CTRL_REG_POWER_MODE 5
|
||||
#define PM8921_LDO_CTRL_REG_VOLTAGE 0
|
||||
|
||||
/* Bit offsets LDO Test register */
|
||||
#define PM8921_LDO_TEST_REG_BANK_SEL 4
|
||||
#define PM8921_LDO_TEST_REG_RW 7
|
||||
#define PM8921_LDO_TEST_REG_BANK2_RANGE_SEL 2
|
||||
#define PM8921_LDO_TEST_REG_BANK2_FINE_STEP 1
|
||||
#define PM8921_LDO_TEST_REG_BANK4_RANGE_EXT 0
|
||||
|
||||
#define GPIO_CNTL_BASE 0x150
|
||||
#define GPIO_CNTL(n) (GPIO_CNTL_BASE + n)
|
||||
|
||||
/* GPIO Bank register programming */
|
||||
#define PM_GPIO_BANK_MASK 0x70
|
||||
#define PM_GPIO_BANK_SHIFT 4
|
||||
#define PM_GPIO_WRITE 0x80
|
||||
|
||||
/* Bank 0 */
|
||||
#define PM_GPIO_VIN_MASK 0x0E
|
||||
#define PM_GPIO_VIN_SHIFT 1
|
||||
#define PM_GPIO_MODE_ENABLE 0x01
|
||||
|
||||
/* Bank 1 */
|
||||
#define PM_GPIO_MODE_MASK 0x0C
|
||||
#define PM_GPIO_MODE_SHIFT 2
|
||||
#define PM_GPIO_OUT_BUFFER_OPEN_DRAIN 0x02
|
||||
#define PM_GPIO_OUT_INVERT 0x01
|
||||
|
||||
#define PM_GPIO_MODE_OFF 3
|
||||
#define PM_GPIO_MODE_OUTPUT 2
|
||||
#define PM_GPIO_MODE_INPUT 0
|
||||
#define PM_GPIO_MODE_BOTH 1
|
||||
|
||||
/* Bank 2 */
|
||||
#define PM_GPIO_PULL_MASK 0x0E
|
||||
#define PM_GPIO_PULL_SHIFT 1
|
||||
|
||||
/* Bank 3 */
|
||||
#define PM_GPIO_OUT_STRENGTH_MASK 0x0C
|
||||
#define PM_GPIO_OUT_STRENGTH_SHIFT 2
|
||||
#define PM_GPIO_PIN_ENABLE 0x00
|
||||
#define PM_GPIO_PIN_DISABLE 0x01
|
||||
|
||||
/* Bank 4 */
|
||||
#define PM_GPIO_FUNC_MASK 0x0E
|
||||
#define PM_GPIO_FUNC_SHIFT 1
|
||||
|
||||
/* Bank 5 */
|
||||
#define PM_GPIO_NON_INT_POL_INV 0x08
|
||||
|
||||
/* PON CTRL 1 register */
|
||||
#define PM8921_PON_CTRL_1_REG 0x01C
|
||||
|
||||
#define PON_CTRL_1_PULL_UP_MASK 0xE0
|
||||
#define PON_CTRL_1_USB_PWR_EN 0x10
|
||||
|
||||
#define PON_CTRL_1_WD_EN_MASK 0x08
|
||||
#define PON_CTRL_1_WD_EN_RESET 0x08
|
||||
#define PON_CTRL_1_WD_EN_PWR_OFF 0x00
|
||||
|
||||
/* SLEEP CTRL register */
|
||||
#define PM8921_SLEEP_CTRL_REG 0x10A
|
||||
|
||||
#define SLEEP_CTRL_SMPL_EN_MASK 0x04
|
||||
#define SLEEP_CTRL_SMPL_EN_RESET 0x04
|
||||
#define SLEEP_CTRL_SMPL_EN_PWR_OFF 0x00
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/pm8921.o
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __DEV_TWL4030_H
|
||||
#define __DEV_TWL4030_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void twl4030_init(void);
|
||||
|
||||
/* USB parts of the pmic */
|
||||
int twl4030_usb_reset(void);
|
||||
int twl4030_set_usb_pullup(bool pullup);
|
||||
int twl4030_init_hs(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/twl4030.o
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <sys/types.h>
|
||||
#include <dev/i2c.h>
|
||||
#include <dev/twl4030.h>
|
||||
#include "twl4030_hw.h"
|
||||
|
||||
// XXX move to target specific setup
|
||||
#define TWL_I2C_BUS 0
|
||||
|
||||
void twl4030_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int twl4030_usb_write(uint8_t address, uint8_t data)
|
||||
{
|
||||
return i2c_write_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, data);
|
||||
}
|
||||
|
||||
static int twl4030_usb_read(uint8_t address)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
int err = i2c_read_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, &data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int twl4030_usb_set_bits(uint8_t reg, uint8_t bits)
|
||||
{
|
||||
return twl4030_usb_write(reg + 1, bits);
|
||||
}
|
||||
|
||||
static int twl4030_usb_clear_bits(uint8_t reg, uint8_t bits)
|
||||
{
|
||||
return twl4030_usb_write(reg + 2, bits);
|
||||
}
|
||||
|
||||
static void twl4030_i2c_access(bool on)
|
||||
{
|
||||
int val;
|
||||
|
||||
if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) {
|
||||
if (on) {
|
||||
/* enable DPLL to access PHY registers over I2C */
|
||||
val |= REQ_PHY_DPLL_CLK;
|
||||
twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
|
||||
|
||||
while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) {
|
||||
spin(10);
|
||||
}
|
||||
if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK))
|
||||
printf("Timeout setting T2 HSUSB " "PHY DPLL clock\n");
|
||||
} else {
|
||||
/* let ULPI control the DPLL clock */
|
||||
val &= ~REQ_PHY_DPLL_CLK;
|
||||
twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int twl4030_usb_reset(void)
|
||||
{
|
||||
TRACE_ENTRY;
|
||||
#if 0
|
||||
twl4030_usb_clear_bits(OTG_CTRL, DMPULLDOWN | DPPULLDOWN);
|
||||
twl4030_usb_clear_bits(USB_INT_EN_RISE, ~0);
|
||||
twl4030_usb_clear_bits(USB_INT_EN_FALL, ~0);
|
||||
twl4030_usb_clear_bits(MCPC_IO_CTRL, ~TXDTYP);
|
||||
twl4030_usb_set_bits(MCPC_IO_CTRL, TXDTYP);
|
||||
twl4030_usb_clear_bits(OTHER_FUNC_CTRL, (BDIS_ACON_EN | FIVEWIRE_MODE));
|
||||
twl4030_usb_clear_bits(OTHER_IFC_CTRL, ~0);
|
||||
twl4030_usb_clear_bits(OTHER_INT_EN_RISE, ~0);
|
||||
twl4030_usb_clear_bits(OTHER_INT_EN_FALL, ~0);
|
||||
twl4030_usb_clear_bits(OTHER_IFC_CTRL2, ~0);
|
||||
twl4030_usb_clear_bits(REG_CTRL_EN, ULPI_I2C_CONFLICT_INTEN);
|
||||
twl4030_usb_clear_bits(OTHER_FUNC_CTRL2, VBAT_TIMER_EN);
|
||||
#endif
|
||||
|
||||
/* Enable writing to power configuration registers */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0xC0);
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0x0C);
|
||||
|
||||
/* put VUSB3V1 LDO in active state */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED2, 0);
|
||||
|
||||
/* input to VUSB3V1 LDO is from VBAT, not VBUS */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED1, 0x14);
|
||||
|
||||
/* turn on 3.1V regulator */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_DEV_GRP, 0x20);
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_TYPE, 0);
|
||||
|
||||
/* turn on 1.5V regulator */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_DEV_GRP, 0x20);
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_TYPE, 0);
|
||||
|
||||
/* turn on 1.8V regulator */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_DEV_GRP, 0x20);
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_TYPE, 0);
|
||||
|
||||
/* disable access to power configuration registers */
|
||||
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0);
|
||||
|
||||
/* turn on the phy */
|
||||
uint8_t pwr = twl4030_usb_read(PHY_PWR_CTRL);
|
||||
pwr &= ~PHYPWD;
|
||||
twl4030_usb_write(PHY_PWR_CTRL, pwr);
|
||||
twl4030_usb_write(PHY_CLK_CTRL,
|
||||
twl4030_usb_read(PHY_CLK_CTRL) |
|
||||
(CLOCKGATING_EN | CLK32K_EN));
|
||||
|
||||
/* set DPLL i2c access mode */
|
||||
twl4030_i2c_access(true);
|
||||
/* set ulpi mode */
|
||||
twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE);
|
||||
twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB);
|
||||
twl4030_usb_write(FUNC_CTRL, XCVRSELECT_HS); // set high speed mode
|
||||
// twl4030_usb_write(FUNC_CTRL, XCVRSELECT_FS); // set full speed mode
|
||||
twl4030_i2c_access(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int twl4030_init_hs(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int twl4030_set_usb_pullup(bool pullup)
|
||||
{
|
||||
TRACE_ENTRY;
|
||||
|
||||
if (pullup) {
|
||||
twl4030_usb_clear_bits(OTG_CTRL, DPPULLDOWN);
|
||||
twl4030_usb_set_bits(FUNC_CTRL, TERMSELECT);
|
||||
} else {
|
||||
twl4030_usb_clear_bits(FUNC_CTRL, TERMSELECT);
|
||||
twl4030_usb_set_bits(OTG_CTRL, DPPULLDOWN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __TWL4030_HW_H
|
||||
#define __TWL4030_HW_H
|
||||
|
||||
/* TWL i2c addresses */
|
||||
#define TWL_I2C_ADDR0 0x48
|
||||
#define TWL_I2C_ADDR1 0x49
|
||||
#define TWL_I2C_ADDR2 0x4a
|
||||
#define TWL_I2C_ADDR3 0x4b
|
||||
|
||||
#define TWL_USB_ADDR TWL_I2C_ADDR0
|
||||
#define TWL_INTBR_ADDR TWL_I2C_ADDR1
|
||||
#define TWL_PM_RECEIVER_ADDR TWL_I2C_ADDR3
|
||||
|
||||
/* TWL registers */
|
||||
#define PROTECT_KEY 0x44
|
||||
#define VAUX1_DEV_GRP 0x72
|
||||
#define VAUX1_TYPE 0x73
|
||||
#define VAUX1_REMAP 0x74
|
||||
#define VAUX1_DEDICATED 0x75
|
||||
#define VAUX2_DEV_GRP 0x76
|
||||
#define VAUX2_TYPE 0x77
|
||||
#define VAUX2_REMAP 0x78
|
||||
#define VAUX2_DEDICATED 0x79
|
||||
#define VAUX3_DEV_GRP 0x7a
|
||||
#define VAUX3_TYPE 0x7b
|
||||
#define VAUX3_REMAP 0x7c
|
||||
#define VAUX3_DEDICATED 0x7d
|
||||
#define VAUX4_DEV_GRP 0x7e
|
||||
#define VAUX4_TYPE 0x7f
|
||||
#define VAUX4_REMAP 0x80
|
||||
#define VAUX4_DEDICATED 0x81
|
||||
#define VMMC1_DEV_GRP 0x82
|
||||
#define VMMC1_TYPE 0x83
|
||||
#define VMMC1_REMAP 0x84
|
||||
#define VMMC1_DEDICATED 0x85
|
||||
#define VMMC2_DEV_GRP 0x86
|
||||
#define VMMC2_TYPE 0x87
|
||||
#define VMMC2_REMAP 0x88
|
||||
#define VMMC2_DEDICATED 0x89
|
||||
#define VPLL1_DEV_GRP 0x8a
|
||||
#define VPLL1_TYPE 0x8b
|
||||
#define VPLL1_REMAP 0x8c
|
||||
#define VPLL1_DEDICATED 0x8d
|
||||
#define VPLL2_DEV_GRP 0x8e
|
||||
#define VPLL2_TYPE 0x8f
|
||||
#define VPLL2_REMAP 0x90
|
||||
#define VPLL2_DEDICATED 0x91
|
||||
#define VDAC_DEV_GRP 0x96
|
||||
#define VDAC_DEDICATED 0x99
|
||||
#define VDD2_DEV_GRP 0xBE
|
||||
#define VDD2_TYPE 0xBF
|
||||
#define VDD2_REMAP 0xC0
|
||||
#define VDD2_CFG 0xC1
|
||||
#define VSIM_DEV_GRP 0x92
|
||||
#define VSIM_TYPE 0x93
|
||||
#define VSIM_REMAP 0x94
|
||||
#define VSIM_DEDICATED 0x95
|
||||
#define PMBR1 0x92
|
||||
|
||||
#define SECONDS_REG 0x1C
|
||||
#define MINUTES_REG 0x1D
|
||||
#define ALARM_SECONDS_REG 0x23
|
||||
#define ALARM_MINUTES_REG 0x24
|
||||
#define ALARM_HOURS_REG 0x25
|
||||
|
||||
#define RTC_STATUS_REG 0x2A
|
||||
#define RTC_INTERRUPTS_REG 0x2B
|
||||
|
||||
#define PWR_ISR1 0x2E
|
||||
#define PWR_IMR1 0x2F
|
||||
#define PWR_ISR2 0x30
|
||||
#define PWR_IMR2 0x31
|
||||
#define PWR_EDR1 0x33
|
||||
|
||||
#define CFG_PWRANA2 0x3F
|
||||
#define RTC_INTERRUPTS_REG 0x2B
|
||||
#define STS_HW_CONDITIONS 0x45
|
||||
|
||||
#define P1_SW_EVENTS 0x46
|
||||
#define P2_SW_EVENTS 0x47
|
||||
#define P3_SW_EVENTS 0x48
|
||||
|
||||
#define VDD1_TRIM1 0x62
|
||||
#define VDD1_TRIM2 0x63
|
||||
#define VDD1_VFLOOR 0xBB
|
||||
#define VDD1_VROOF 0xBC
|
||||
#define PB_CFG 0x4A
|
||||
#define PB_WORD_MSB 0x4B
|
||||
#define PB_WORD_LSB 0x4C
|
||||
|
||||
#define VSIM_REMAP 0x94
|
||||
#define VDAC_REMAP 0x98
|
||||
#define VINTANA1_DEV_GRP 0x9A
|
||||
#define VINTANA1_REMAP 0x9C
|
||||
#define VINTANA2_REMAP 0xA0
|
||||
#define VINTANA2_DEV_GRP 0x9E
|
||||
#define VINTDIG_DEV_GRP 0xA2
|
||||
#define VINTDIG_REMAP 0xA4
|
||||
#define VIO_DEV_GRP 0xA6
|
||||
#define VIO_REMAP 0xA8
|
||||
#define VDD1_REMAP 0xB2
|
||||
#define VDD2_REMAP 0xC0
|
||||
#define REGEN_REMAP 0xDC
|
||||
#define NRESPWRON_REMAP 0xDF
|
||||
#define CLKEN_REMAP 0xE2
|
||||
#define SYSEN_REMAP 0xE5
|
||||
#define HFCLKOUT_REMAP 0xE8
|
||||
#define HFCLKOUT_DEV_GRP 0xE6
|
||||
#define T32KCLKOUT_REMAP 0xEB
|
||||
#define TRITON_RESET_REMAP 0xEE
|
||||
#define MAINREF_REMAP 0xF1
|
||||
#define VIBRA_CTL 0x45
|
||||
|
||||
|
||||
#define VUSB1V5_DEV_GRP 0xCC
|
||||
#define VUSB1V5_TYPE 0xCD
|
||||
#define VUSB1V5_REMAP 0xCE
|
||||
#define VUSB1V8_DEV_GRP 0xCF
|
||||
#define VUSB1V8_TYPE 0xD0
|
||||
#define VUSB1V8_REMAP 0xD1
|
||||
#define VUSB3V1_DEV_GRP 0xD2
|
||||
#define VUSB3V1_TYPE 0xD3
|
||||
#define VUSB3V1_REMAP 0xD4
|
||||
#define VUSBCP_DEV_GRP 0xD5
|
||||
#define VUSBCP_TYPE 0xD6
|
||||
#define VUSBCP_REMAP 0xD7
|
||||
#define VUSB_DEDICATED1 0xD8
|
||||
#define VUSB_DEDICATED2 0xD9
|
||||
|
||||
/* USB registers */
|
||||
#define VENDOR_ID_LO 0x0
|
||||
#define VENDOR_ID_HI 0x1
|
||||
#define PRODUCT_ID_LO 0x2
|
||||
#define PRODUCT_ID_HI 0x3
|
||||
#define FUNC_CTRL 0x4
|
||||
#define FUNC_CTRL_SET 0x5
|
||||
#define FUNC_CTRL_CLR 0x6
|
||||
# define SUSPENDM (1 << 6)
|
||||
# define RESET (1 << 5)
|
||||
# define OPMODE_MASK (3 << 3) /* bits 3 and 4 */
|
||||
# define OPMODE_NORMAL (0 << 3)
|
||||
# define OPMODE_NONDRIVING (1 << 3)
|
||||
# define OPMODE_DISABLE_BIT_NRZI (2 << 3)
|
||||
# define TERMSELECT (1 << 2)
|
||||
# define XCVRSELECT_MASK (3 << 0) /* bits 0 and 1 */
|
||||
# define XCVRSELECT_HS (0 << 0)
|
||||
# define XCVRSELECT_FS (1 << 0)
|
||||
# define XCVRSELECT_LS (2 << 0)
|
||||
# define XCVRSELECT_FS4LS (3 << 0)
|
||||
#define IFC_CTRL 0x7
|
||||
#define IFC_CTRL_SET 0x8
|
||||
#define IFC_CTRL_CLR 0x9
|
||||
# define INTERFACE_PROTECT_DISABLE (1 << 7)
|
||||
# define AUTORESUME (1 << 4)
|
||||
# define CLOCKSUSPENDM (1 << 3)
|
||||
# define CARKITMODE (1 << 2)
|
||||
# define FSLSSERIALMODE_3PIN (1 << 1)
|
||||
#define OTG_CTRL 0xa
|
||||
#define OTG_CTRL_SET 0xb
|
||||
#define OTG_CTRL_CLR 0xc
|
||||
#define DRVVBUS (1 << 5)
|
||||
#define CHRGVBUS (1 << 4)
|
||||
#define DISCHRGVBUS (1 << 3)
|
||||
#define DMPULLDOWN (1 << 2)
|
||||
#define DPPULLDOWN (1 << 1)
|
||||
#define IDPULLUP (1 << 0)
|
||||
#define USB_INT_EN_RISE 0xd
|
||||
#define USB_INT_EN_RISE_SET 0xe
|
||||
#define USB_INT_EN_RISE_CLR 0xf
|
||||
#define USB_INT_EN_FALL 0x10
|
||||
#define USB_INT_EN_FALL_SET 0x11
|
||||
#define USB_INT_EN_FALL_CLR 0x12
|
||||
# define HOSTDISCONNECT (1 << 0)
|
||||
#define USB_INT_STS 0x13
|
||||
#define USB_INT_LATCH 0x14
|
||||
#define USB_DEBUG 0x15
|
||||
#define SCRATCH_REG 0x16
|
||||
#define SCRATCH_REG_SET 0x17
|
||||
#define SCRATCH_REG_CLR 0x18
|
||||
#define CARKIT_CTRL 0x19
|
||||
#define CARKIT_CTRL_SET 0x1a
|
||||
#define CARKIT_CTRL_CLR 0x1b
|
||||
#define MICEN (1 << 6)
|
||||
#define SPKRIGHTEN (1 << 5)
|
||||
#define SPKLEFTEN (1 << 4)
|
||||
#define RXDEN (1 << 3)
|
||||
#define TXDEN (1 << 2)
|
||||
#define IDGNDDRV (1 << 1)
|
||||
#define CARKITPWR (1 << 0)
|
||||
#define CARKIT_INT_DELAY 0x1c
|
||||
#define CARKIT_INT_EN 0x1d
|
||||
#define CARKIT_INT_EN_SET 0x1e
|
||||
#define CARKIT_INT_EN_CLR 0x1f
|
||||
#define CARKIT_INT_STS 0x20
|
||||
#define CARKIT_INT_LATCH 0x21
|
||||
#define CARKIT_PLS_CTRL 0x22
|
||||
#define CARKIT_PLS_CTRL_SET 0x23
|
||||
#define CARKIT_PLS_CTRL_CLR 0x24
|
||||
# define SPKRRIGHT_BIASEN (1 << 3)
|
||||
# define SPKRLEFT_BIASEN (1 << 2)
|
||||
# define RXPLSEN (1 << 1)
|
||||
# define TXPLSEN (1 << 0)
|
||||
#define TRANS_POS_WIDTH 0x25
|
||||
#define TRANS_NEG_WIDTH 0x26
|
||||
#define RCV_PLTY_RECOVERY 0x27
|
||||
#define MCPC_CTRL 0x30
|
||||
#define MCPC_CTRL_SET 0x31
|
||||
#define MCPC_CTRL_CLR 0x32
|
||||
#define RTSOL (1 << 7)
|
||||
#define EXTSWR (1 << 6)
|
||||
#define EXTSWC (1 << 5)
|
||||
#define VOICESW (1 << 4)
|
||||
#define OUT64K (1 << 3)
|
||||
#define RTSCTSSW (1 << 2)
|
||||
#define HS_UART (1 << 0)
|
||||
#define MCPC_IO_CTRL 0x033
|
||||
#define MCPC_IO_CTRL_SET 0x034
|
||||
#define MCPC_IO_CTRL_CLR 0x035
|
||||
#define MICBIASEN (1<< 5)
|
||||
#define CTS_NPU (1 << 4)
|
||||
#define RXD_PU (1 << 3)
|
||||
#define TXDTYP (1 << 2)
|
||||
#define CTSTYP (1 << 1)
|
||||
#define RTSTYP (1 << 0)
|
||||
#define MCPC_CTRL2 0x036
|
||||
#define MCPC_CTRL2_SET 0x037
|
||||
#define MCPC_CTRL2_CLR 0x038
|
||||
# define MCPC_CK_EN (1 << 0)
|
||||
#define OTHER_FUNC_CTRL 0x080
|
||||
#define OTHER_FUNC_CTRL_SET 0x081
|
||||
#define OTHER_FUNC_CTRL_CLR 0x082
|
||||
#define BDIS_ACON_EN (1<< 4)
|
||||
#define FIVEWIRE_MODE (1 << 2)
|
||||
#define OTHER_IFC_CTRL 0x083
|
||||
#define OTHER_IFC_CTRL_SET 0x084
|
||||
#define OTHER_IFC_CTRL_CLR 0x085
|
||||
# define OE_INT_EN (1 << 6)
|
||||
# define CEA2011_MODE (1 << 5)
|
||||
# define FSLSSERIALMODE_4PIN (1 << 4)
|
||||
# define HIZ_ULPI_60MHZ_OUT (1 << 3)
|
||||
# define HIZ_ULPI (1 << 2)
|
||||
# define ALT_INT_REROUTE (1 << 0)
|
||||
#define OTHER_INT_EN_RISE 0x086
|
||||
#define OTHER_INT_EN_RISE_SET 0x087
|
||||
#define OTHER_INT_EN_RISE_CLR 0x088
|
||||
#define OTHER_INT_EN_FALL 0x089
|
||||
#define OTHER_INT_EN_FALL_SET 0x08A
|
||||
#define OTHER_INT_EN_FALL_CLR 0x08B
|
||||
#define OTHER_INT_STS 0x8C
|
||||
#define OTHER_INT_LATCH 0x8D
|
||||
#define ID_INT_EN_RISE 0x08E
|
||||
#define ID_INT_EN_RISE_SET 0x08F
|
||||
#define ID_INT_EN_RISE_CLR 0x090
|
||||
#define ID_INT_EN_FALL 0x091
|
||||
#define ID_INT_EN_FALL_SET 0x092
|
||||
#define ID_INT_EN_FALL_CLR 0x093
|
||||
#define ID_INT_STS 0x094
|
||||
#define ID_INT_LATCH 0x95
|
||||
#define ID_STATUS 0x96
|
||||
#define CARKIT_SM_1_INT_EN 0x097
|
||||
#define CARKIT_SM_1_INT_EN_SET 0x098
|
||||
#define CARKIT_SM_1_INT_EN_CLR 0x099
|
||||
#define CARKIT_SM_1_INT_STS 0x09A
|
||||
#define CARKIT_SM_1_INT_LATCH 0x9B
|
||||
#define CARKIT_SM_2_INT_EN 0x09C
|
||||
#define CARKIT_SM_2_INT_EN_SET 0x09D
|
||||
#define CARKIT_SM_2_INT_EN_CLR 0x09E
|
||||
#define CARKIT_SM_2_INT_STS 0x09F
|
||||
#define CARKIT_SM_2_INT_LATCH 0xA0
|
||||
#define CARKIT_SM_CTRL 0x0A1
|
||||
#define CARKIT_SM_CTRL_SET 0x0A2
|
||||
#define CARKIT_SM_CTRL_CLR 0x0A3
|
||||
#define CARKIT_SM_CMD 0x0A4
|
||||
#define CARKIT_SM_CMD_SET 0x0A5
|
||||
#define CARKIT_SM_CMD_CLR 0x0A6
|
||||
#define CARKIT_SM_CMD_STS 0xA7
|
||||
#define CARKIT_SM_STATUS 0xA8
|
||||
#define CARKIT_SM_NEXT_STATUS 0xA9
|
||||
#define CARKIT_SM_ERR_STATUS 0xAA
|
||||
#define CARKIT_SM_CTRL_STATE 0xAB
|
||||
#define POWER_CTRL 0xAC
|
||||
#define POWER_CTRL_SET 0xAD
|
||||
#define POWER_CTRL_CLR 0xAE
|
||||
# define OTG_ENAB (1 << 5)
|
||||
#define OTHER_IFC_CTRL2 0xAF
|
||||
#define OTHER_IFC_CTRL2_SET 0xB0
|
||||
#define OTHER_IFC_CTRL2_CLR 0xB1
|
||||
# define ULPI_TXEN_POL (1 << 3)
|
||||
# define ULPI_4PIN_2430 (1 << 2)
|
||||
#define REG_CTRL_EN 0xB2
|
||||
#define REG_CTRL_EN_SET 0xB3
|
||||
#define REG_CTRL_EN_CLR 0xB4
|
||||
#define REG_CTRL_ERROR 0xB5
|
||||
#define ULPI_I2C_CONFLICT_INTEN (1 << 0)
|
||||
#define OTHER_FUNC_CTRL2 0xB8
|
||||
#define OTHER_FUNC_CTRL2_SET 0xB9
|
||||
#define OTHER_FUNC_CTRL2_CLR 0xBA
|
||||
#define VBAT_TIMER_EN (1 << 0)
|
||||
#define CARKIT_ANA_CTRL 0xBB
|
||||
#define CARKIT_ANA_CTRL_SET 0xBC
|
||||
#define CARKIT_ANA_CTRL_CLR 0xBD
|
||||
#define VBUS_DEBOUNCE 0xC0
|
||||
#define ID_DEBOUNCE 0xC1
|
||||
#define TPH_DP_CON_MIN 0xC2
|
||||
#define TPH_DP_CON_MAX 0xC3
|
||||
#define TCR_DP_CON_MIN 0xC4
|
||||
#define TCR_DP_CON_MAX 0xC5
|
||||
#define TPH_DP_PD_SHORT 0xC6
|
||||
#define TPH_CMD_DLY 0xC7
|
||||
#define TPH_DET_RST 0xC8
|
||||
#define TPH_AUD_BIAS 0xC9
|
||||
#define TCR_UART_DET_MIN 0xCA
|
||||
#define TCR_UART_DET_MAX 0xCB
|
||||
#define TPH_ID_INT_PW 0xCD
|
||||
#define TACC_ID_INT_WAIT 0xCE
|
||||
#define TACC_ID_INT_PW 0xCF
|
||||
#define TPH_CMD_WAIT 0xD0
|
||||
#define TPH_ACK_WAIT 0xD1
|
||||
#define TPH_DP_DISC_DET 0xD2
|
||||
#define VBAT_TIMER 0xD3
|
||||
#define CARKIT_4W_DEBUG 0xE0
|
||||
#define CARKIT_5W_DEBUG 0xE1
|
||||
#define CARKIT_5W_DEBUG 0xE1
|
||||
#define TEST_CTRL_CLR 0xEB
|
||||
#define TEST_CARKIT_SET 0xEC
|
||||
#define TEST_CARKIT_CLR 0xED
|
||||
#define TEST_POWER_SET 0xEE
|
||||
#define TEST_POWER_CLR 0xEF
|
||||
#define TEST_ULPI 0xF0
|
||||
#define TXVR_EN_TEST_SET 0xF2
|
||||
#define TXVR_EN_TEST_CLR 0xF3
|
||||
#define VBUS_EN_TEST 0xF4
|
||||
#define ID_EN_TEST 0xF5
|
||||
#define PSM_EN_TEST_SET 0xF6
|
||||
#define PSM_EN_TEST_CLR 0xF7
|
||||
#define PHY_TRIM_CTRL 0xFC
|
||||
#define PHY_PWR_CTRL 0xFD
|
||||
# define PHYPWD (1 << 0)
|
||||
#define PHY_CLK_CTRL 0xFE
|
||||
# define CLOCKGATING_EN (1 << 2)
|
||||
# define CLK32K_EN (1 << 1)
|
||||
# define REQ_PHY_DPLL_CLK (1 << 0)
|
||||
#define PHY_CLK_CTRL_STS 0xFF
|
||||
# define PHY_DPLL_CLK (1 << 0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/dev.o
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __DEV_SSBI_H
|
||||
#define __DEV_SSBI_H
|
||||
|
||||
//Macros for SSBI Qwerty keypad for 7x30
|
||||
|
||||
/* SSBI 2.0 controller registers */
|
||||
#define MSM_SSBI_BASE 0xAD900000
|
||||
|
||||
#define SSBI_TIMEOUT_US 100
|
||||
|
||||
#define SSBI2_CTL 0x0000
|
||||
#define SSBI2_RESET 0x0004
|
||||
#define SSBI2_CMD 0x0008
|
||||
#define SSBI2_RD 0x0010
|
||||
#define SSBI2_STATUS 0x0014
|
||||
#define SSBI2_PRIORITIES 0x0018
|
||||
#define SSBI2_MODE2 0x001C
|
||||
|
||||
/* SSBI_CMD fields */
|
||||
#define SSBI_CMD_SEND_TERM_SYM (0x01 << 27)
|
||||
#define SSBI_CMD_WAKEUP_SLAVE (0x01 << 26)
|
||||
#define SSBI_CMD_USE_ENABLE (0x01 << 25)
|
||||
#define SSBI_CMD_RDWRN (0x01 << 24)
|
||||
#define SSBI_CMD_REG_ADDR_SHFT (0x10)
|
||||
#define SSBI_CMD_REG_ADDR_MASK (0xFF << SSBI_CMD_REG_ADDR_SHFT)
|
||||
#define SSBI_CMD_REG_DATA_SHFT (0x00)
|
||||
#define SSBI_CMD_REG_DATA_MASK (0xFF << SSBI_CMD_REG_DATA_SHFT)
|
||||
|
||||
/* SSBI_STATUS fields */
|
||||
#define SSBI_STATUS_DATA_IN 0x10
|
||||
#define SSBI_STATUS_RD_CLOBBERED 0x08
|
||||
#define SSBI_STATUS_RD_READY 0x04
|
||||
#define SSBI_STATUS_READY 0x02
|
||||
#define SSBI_STATUS_MCHN_BUSY 0x01
|
||||
|
||||
/* SSBI_RD fields */
|
||||
#define SSBI_RD_USE_ENABLE 0x02000000
|
||||
#define SSBI_RD_RDWRN 0x01000000
|
||||
#define SSBI_RD_REG_ADDR_SHFT 0x10
|
||||
#define SSBI_RD_REG_ADDR_MASK (0xFF << SSBI_RD_REG_ADDR_SHFT)
|
||||
#define SSBI_RD_REG_DATA_SHFT (0x00)
|
||||
#define SSBI_RD_REG_DATA_MASK (0xFF << SSBI_RD_REG_DATA_SHFT)
|
||||
|
||||
/* SSBI_MODE2 fields */
|
||||
#define SSBI_MODE2_REG_ADDR_15_8_SHFT 0x04
|
||||
#define SSBI_MODE2_REG_ADDR_15_8_MASK (0x7F << SSBI_MODE2_REG_ADDR_15_8_SHFT)
|
||||
#define SSBI_MODE2_ADDR_WIDTH_SHFT 0x01
|
||||
#define SSBI_MODE2_ADDR_WIDTH_MASK (0x07 << SSBI_MODE2_ADDR_WIDTH_SHFT)
|
||||
#define SSBI_MODE2_SSBI2_MODE 0x00000001
|
||||
|
||||
//Keypad controller configurations
|
||||
#define SSBI_REG_KYPD_CNTL_ADDR 0x148
|
||||
#define SSBI_REG_KYPD_SCAN_ADDR 0x149
|
||||
#define SSBI_REG_KYPD_TEST_ADDR 0x14A
|
||||
#define SSBI_REG_KYPD_REC_DATA_ADDR 0x14B
|
||||
#define SSBI_REG_KYPD_OLD_DATA_ADDR 0x14C
|
||||
|
||||
|
||||
/* PMIC Arbiter 1: SSBI2 Configuration Micro ARM registers */
|
||||
#define PA1_SSBI2_CMD 0x00500000
|
||||
#define PA1_SSBI2_RD_STATUS 0x00500004
|
||||
|
||||
#define PA1_SSBI2_REG_ADDR_SHIFT 8
|
||||
#define PA1_SSBI2_CMD_RDWRN_SHIFT 24
|
||||
#define PA1_SSBI2_TRANS_DONE_SHIFT 27
|
||||
|
||||
#define PA1_SSBI2_REG_DATA_MASK 0xFF
|
||||
#define PA1_SSBI2_REG_DATA_SHIFT 0
|
||||
|
||||
#define PA1_SSBI2_CMD_READ 1
|
||||
#define PA1_SSBI2_CMD_WRITE 0
|
||||
|
||||
/* PMIC Arbiter 2: SSBI2 Configuration Micro ARM registers */
|
||||
#define PA2_SSBI2_CMD 0x00C00000
|
||||
#define PA2_SSBI2_RD_STATUS 0x00C00004
|
||||
|
||||
#define PA2_SSBI2_REG_ADDR_SHIFT 8
|
||||
#define PA2_SSBI2_CMD_RDWRN_SHIFT 24
|
||||
#define PA2_SSBI2_TRANS_DONE_SHIFT 27
|
||||
|
||||
#define PA2_SSBI2_REG_DATA_MASK 0xFF
|
||||
#define PA2_SSBI2_REG_DATA_SHIFT 0
|
||||
|
||||
#define PA2_SSBI2_CMD_READ 1
|
||||
#define PA2_SSBI2_CMD_WRITE 0
|
||||
|
||||
#define SSBI_CMD_READ(AD) \
|
||||
(SSBI_CMD_RDWRN | (((AD) & 0xFF) << SSBI_CMD_REG_ADDR_SHFT))
|
||||
|
||||
#define SSBI_CMD_WRITE(AD, DT) \
|
||||
((((AD) & 0xFF) << SSBI_CMD_REG_ADDR_SHFT) | \
|
||||
(((DT) & 0xFF) << SSBI_CMD_REG_DATA_SHFT))
|
||||
|
||||
#define SSBI_MODE2_REG_ADDR_15_8(MD, AD) \
|
||||
(((MD) & 0x0F) | ((((AD) >> 8) << SSBI_MODE2_REG_ADDR_15_8_SHFT) & \
|
||||
SSBI_MODE2_REG_ADDR_15_8_MASK))
|
||||
|
||||
int i2c_ssbi_read_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr);
|
||||
int i2c_ssbi_write_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr);
|
||||
int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr);
|
||||
int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/ssbi.o
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <reg.h>
|
||||
#include <sys/types.h>
|
||||
#include <dev/ssbi.h>
|
||||
|
||||
int i2c_ssbi_poll_for_device_ready(void)
|
||||
{
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
|
||||
while (!(readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_READY)) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In Device ready function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_ssbi_poll_for_read_completed(void)
|
||||
{
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
|
||||
while (!(readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_RD_READY)) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In read completed function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_ssbi_read_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char *buf = buffer;
|
||||
unsigned short len = length;
|
||||
unsigned short addr = slave_addr;
|
||||
unsigned long read_cmd = SSBI_CMD_READ(addr);
|
||||
unsigned long mode2 = readl(MSM_SSBI_BASE + SSBI2_MODE2);
|
||||
|
||||
//buf = alloc(len * sizeof(8));
|
||||
if (mode2 & SSBI_MODE2_SSBI2_MODE)
|
||||
writel(SSBI_MODE2_REG_ADDR_15_8(mode2, addr),
|
||||
MSM_SSBI_BASE + SSBI2_MODE2);
|
||||
|
||||
while (len) {
|
||||
ret = i2c_ssbi_poll_for_device_ready();
|
||||
if (ret) {
|
||||
dprintf (CRITICAL, "Error: device not ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
writel(read_cmd, MSM_SSBI_BASE + SSBI2_CMD);
|
||||
|
||||
ret = i2c_ssbi_poll_for_read_completed();
|
||||
if (ret) {
|
||||
dprintf (CRITICAL, "Error: read not completed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
*buf++ = readl(MSM_SSBI_BASE + SSBI2_RD) & SSBI_RD_REG_DATA_MASK;
|
||||
len--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_ssbi_write_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
unsigned char *buf = buffer;
|
||||
unsigned short len = length;
|
||||
unsigned short addr = slave_addr;
|
||||
unsigned long mode2 = readl(MSM_SSBI_BASE + SSBI2_MODE2);
|
||||
|
||||
if (mode2 & SSBI_MODE2_SSBI2_MODE)
|
||||
writel(SSBI_MODE2_REG_ADDR_15_8(mode2, addr),
|
||||
MSM_SSBI_BASE + SSBI2_MODE2);
|
||||
|
||||
while (len) {
|
||||
ret = i2c_ssbi_poll_for_device_ready();
|
||||
if (ret) {
|
||||
dprintf (CRITICAL, "Error: device not ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
writel(SSBI_CMD_WRITE(addr, *buf++), MSM_SSBI_BASE + SSBI2_CMD);
|
||||
|
||||
while (readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_MCHN_BUSY) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In Device ready function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
len--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr)
|
||||
{
|
||||
unsigned val = 0x0;
|
||||
unsigned temp = 0x0000;
|
||||
unsigned char *buf = buffer;
|
||||
unsigned short len = length;
|
||||
unsigned short addr = slave_addr;
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
|
||||
while(len)
|
||||
{
|
||||
val |= ((addr << PA1_SSBI2_REG_ADDR_SHIFT) |
|
||||
(PA1_SSBI2_CMD_READ << PA1_SSBI2_CMD_RDWRN_SHIFT));
|
||||
writel(val, PA1_SSBI2_CMD);
|
||||
while(!((temp = readl(PA1_SSBI2_RD_STATUS)) & (1 << PA1_SSBI2_TRANS_DONE_SHIFT))) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In Device ready function:Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
len--;
|
||||
*buf++ = (temp & (PA1_SSBI2_REG_DATA_MASK << PA1_SSBI2_REG_DATA_SHIFT));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr)
|
||||
{
|
||||
unsigned val;
|
||||
unsigned char *buf = buffer;
|
||||
unsigned short len = length;
|
||||
unsigned short addr = slave_addr;
|
||||
unsigned temp = 0x00;
|
||||
unsigned char written_data1 = 0x00;
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
//unsigned char written_data2 = 0x00;
|
||||
|
||||
while(len)
|
||||
{
|
||||
temp = 0x00;
|
||||
written_data1 = 0x00;
|
||||
val = (addr << PA1_SSBI2_REG_ADDR_SHIFT) |
|
||||
(PA1_SSBI2_CMD_WRITE << PA1_SSBI2_CMD_RDWRN_SHIFT) |
|
||||
(*buf & 0xFF);
|
||||
writel(val, PA1_SSBI2_CMD);
|
||||
while(!((temp = readl(PA1_SSBI2_RD_STATUS)) & (1 << PA1_SSBI2_TRANS_DONE_SHIFT))) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In Device write function:Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
len--;
|
||||
buf++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa2_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr)
|
||||
{
|
||||
unsigned val = 0x0;
|
||||
unsigned temp = 0x0000;
|
||||
unsigned char *buf = buffer;
|
||||
unsigned short len = length;
|
||||
unsigned short addr = slave_addr;
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
|
||||
while(len)
|
||||
{
|
||||
val |= ((addr << PA2_SSBI2_REG_ADDR_SHIFT) |
|
||||
(PA2_SSBI2_CMD_READ << PA2_SSBI2_CMD_RDWRN_SHIFT));
|
||||
writel(val, PA2_SSBI2_CMD);
|
||||
while(!((temp = readl(PA2_SSBI2_RD_STATUS)) & (1 << PA2_SSBI2_TRANS_DONE_SHIFT))) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In Device ready function:Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
len--;
|
||||
*buf++ = (temp & (PA2_SSBI2_REG_DATA_MASK << PA2_SSBI2_REG_DATA_SHIFT));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
|
||||
unsigned short slave_addr)
|
||||
{
|
||||
unsigned val;
|
||||
unsigned char *buf = buffer;
|
||||
unsigned short len = length;
|
||||
unsigned short addr = slave_addr;
|
||||
unsigned temp = 0x00;
|
||||
unsigned char written_data1 = 0x00;
|
||||
unsigned long timeout = SSBI_TIMEOUT_US;
|
||||
|
||||
while(len)
|
||||
{
|
||||
temp = 0x00;
|
||||
written_data1 = 0x00;
|
||||
val = (addr << PA2_SSBI2_REG_ADDR_SHIFT) |
|
||||
(PA2_SSBI2_CMD_WRITE << PA2_SSBI2_CMD_RDWRN_SHIFT) |
|
||||
(*buf & 0xFF);
|
||||
writel(val, PA2_SSBI2_CMD);
|
||||
while(!((temp = readl(PA2_SSBI2_RD_STATUS)) & (1 << PA2_SSBI2_TRANS_DONE_SHIFT))) {
|
||||
if (--timeout == 0) {
|
||||
dprintf(INFO, "In Device write function:Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
len--;
|
||||
buf++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loaded 100 of 1813 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user