mmu.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. * File : mmu.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2015-04-15 ArdaFu Add code for IAR
  23. */
  24. #include "mmu.h"
  25. #ifdef __CC_ARM
  26. void mmu_setttbase(rt_uint32_t i)
  27. {
  28. register rt_uint32_t value;
  29. /* Invalidates all TLBs.Domain access is selected as
  30. * client by configuring domain access register,
  31. * in that case access controlled by permission value
  32. * set by page table entry
  33. */
  34. value = 0;
  35. __asm
  36. {
  37. mcr p15, 0, value, c8, c7, 0
  38. }
  39. value = 0x55555555;
  40. __asm
  41. {
  42. mcr p15, 0, value, c3, c0, 0
  43. mcr p15, 0, i, c2, c0, 0
  44. }
  45. }
  46. void mmu_set_domain(rt_uint32_t i)
  47. {
  48. __asm
  49. {
  50. mcr p15,0, i, c3, c0, 0
  51. }
  52. }
  53. void mmu_enable()
  54. {
  55. register rt_uint32_t value;
  56. __asm
  57. {
  58. mrc p15, 0, value, c1, c0, 0
  59. orr value, value, #0x01
  60. mcr p15, 0, value, c1, c0, 0
  61. }
  62. }
  63. void mmu_disable()
  64. {
  65. register rt_uint32_t value;
  66. __asm
  67. {
  68. mrc p15, 0, value, c1, c0, 0
  69. bic value, value, #0x01
  70. mcr p15, 0, value, c1, c0, 0
  71. }
  72. }
  73. void mmu_enable_icache()
  74. {
  75. register rt_uint32_t value;
  76. __asm
  77. {
  78. mrc p15, 0, value, c1, c0, 0
  79. orr value, value, #0x1000
  80. mcr p15, 0, value, c1, c0, 0
  81. }
  82. }
  83. void mmu_enable_dcache()
  84. {
  85. register rt_uint32_t value;
  86. __asm
  87. {
  88. mrc p15, 0, value, c1, c0, 0
  89. orr value, value, #0x04
  90. mcr p15, 0, value, c1, c0, 0
  91. }
  92. }
  93. void mmu_disable_icache()
  94. {
  95. register rt_uint32_t value;
  96. __asm
  97. {
  98. mrc p15, 0, value, c1, c0, 0
  99. bic value, value, #0x1000
  100. mcr p15, 0, value, c1, c0, 0
  101. }
  102. }
  103. void mmu_disable_dcache()
  104. {
  105. register rt_uint32_t value;
  106. __asm
  107. {
  108. mrc p15, 0, value, c1, c0, 0
  109. bic value, value, #0x04
  110. mcr p15, 0, value, c1, c0, 0
  111. }
  112. }
  113. void mmu_enable_alignfault()
  114. {
  115. register rt_uint32_t value;
  116. __asm
  117. {
  118. mrc p15, 0, value, c1, c0, 0
  119. orr value, value, #0x02
  120. mcr p15, 0, value, c1, c0, 0
  121. }
  122. }
  123. void mmu_disable_alignfault()
  124. {
  125. register rt_uint32_t value;
  126. __asm
  127. {
  128. mrc p15, 0, value, c1, c0, 0
  129. bic value, value, #0x02
  130. mcr p15, 0, value, c1, c0, 0
  131. }
  132. }
  133. void mmu_clean_invalidated_cache_index(int index)
  134. {
  135. __asm
  136. {
  137. mcr p15, 0, index, c7, c14, 2
  138. }
  139. }
  140. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  141. {
  142. unsigned int ptr;
  143. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  144. while(ptr < buffer + size)
  145. {
  146. __asm
  147. {
  148. MCR p15, 0, ptr, c7, c14, 1
  149. }
  150. ptr += CACHE_LINE_SIZE;
  151. }
  152. }
  153. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  154. {
  155. unsigned int ptr;
  156. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  157. while (ptr < buffer + size)
  158. {
  159. __asm
  160. {
  161. MCR p15, 0, ptr, c7, c10, 1
  162. }
  163. ptr += CACHE_LINE_SIZE;
  164. }
  165. }
  166. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  167. {
  168. unsigned int ptr;
  169. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  170. while (ptr < buffer + size)
  171. {
  172. __asm
  173. {
  174. MCR p15, 0, ptr, c7, c6, 1
  175. }
  176. ptr += CACHE_LINE_SIZE;
  177. }
  178. }
  179. void mmu_invalidate_tlb()
  180. {
  181. register rt_uint32_t value;
  182. value = 0;
  183. __asm
  184. {
  185. mcr p15, 0, value, c8, c7, 0
  186. }
  187. }
  188. void mmu_invalidate_icache()
  189. {
  190. register rt_uint32_t value;
  191. value = 0;
  192. __asm
  193. {
  194. mcr p15, 0, value, c7, c5, 0
  195. }
  196. }
  197. void mmu_invalidate_dcache_all()
  198. {
  199. register rt_uint32_t value;
  200. value = 0;
  201. __asm
  202. {
  203. mcr p15, 0, value, c7, c6, 0
  204. }
  205. }
  206. #elif defined(__GNUC__)
  207. void mmu_setttbase(register rt_uint32_t i)
  208. {
  209. register rt_uint32_t value;
  210. /* Invalidates all TLBs.Domain access is selected as
  211. * client by configuring domain access register,
  212. * in that case access controlled by permission value
  213. * set by page table entry
  214. */
  215. value = 0;
  216. asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
  217. value = 0x55555555;
  218. asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
  219. asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
  220. }
  221. void mmu_set_domain(register rt_uint32_t i)
  222. {
  223. asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i));
  224. }
  225. void mmu_enable()
  226. {
  227. register rt_uint32_t i;
  228. /* read control register */
  229. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  230. i |= 0x1;
  231. /* write back to control register */
  232. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  233. }
  234. void mmu_disable()
  235. {
  236. register rt_uint32_t i;
  237. /* read control register */
  238. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  239. i &= ~0x1;
  240. /* write back to control register */
  241. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  242. }
  243. void mmu_enable_icache()
  244. {
  245. register rt_uint32_t i;
  246. /* read control register */
  247. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  248. i |= (1 << 12);
  249. /* write back to control register */
  250. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  251. }
  252. void mmu_enable_dcache()
  253. {
  254. register rt_uint32_t i;
  255. /* read control register */
  256. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  257. i |= (1 << 2);
  258. /* write back to control register */
  259. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  260. }
  261. void mmu_disable_icache()
  262. {
  263. register rt_uint32_t i;
  264. /* read control register */
  265. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  266. i &= ~(1 << 12);
  267. /* write back to control register */
  268. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  269. }
  270. void mmu_disable_dcache()
  271. {
  272. register rt_uint32_t i;
  273. /* read control register */
  274. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  275. i &= ~(1 << 2);
  276. /* write back to control register */
  277. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  278. }
  279. void mmu_enable_alignfault()
  280. {
  281. register rt_uint32_t i;
  282. /* read control register */
  283. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  284. i |= (1 << 1);
  285. /* write back to control register */
  286. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  287. }
  288. void mmu_disable_alignfault()
  289. {
  290. register rt_uint32_t i;
  291. /* read control register */
  292. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  293. i &= ~(1 << 1);
  294. /* write back to control register */
  295. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  296. }
  297. void mmu_clean_invalidated_cache_index(int index)
  298. {
  299. asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index));
  300. }
  301. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  302. {
  303. unsigned int ptr;
  304. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  305. while(ptr < buffer + size)
  306. {
  307. asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr));
  308. ptr += CACHE_LINE_SIZE;
  309. }
  310. }
  311. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  312. {
  313. unsigned int ptr;
  314. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  315. while (ptr < buffer + size)
  316. {
  317. asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr));
  318. ptr += CACHE_LINE_SIZE;
  319. }
  320. }
  321. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  322. {
  323. unsigned int ptr;
  324. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  325. while (ptr < buffer + size)
  326. {
  327. asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr));
  328. ptr += CACHE_LINE_SIZE;
  329. }
  330. }
  331. void mmu_invalidate_tlb()
  332. {
  333. asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0));
  334. }
  335. void mmu_invalidate_icache()
  336. {
  337. asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
  338. }
  339. void mmu_invalidate_dcache_all()
  340. {
  341. asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (0));
  342. }
  343. #elif defined(__ICCARM__)
  344. void mmu_setttbase(register rt_uint32_t i)
  345. {
  346. register rt_uint32_t value;
  347. /* Invalidates all TLBs.Domain access is selected as
  348. * client by configuring domain access register,
  349. * in that case access controlled by permission value
  350. * set by page table entry
  351. */
  352. value = 0;
  353. asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
  354. value = 0x55555555;
  355. asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
  356. asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
  357. }
  358. void mmu_set_domain(register rt_uint32_t i)
  359. {
  360. asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i));
  361. }
  362. void mmu_enable()
  363. {
  364. register rt_uint32_t i;
  365. /* read control register */
  366. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  367. i |= 0x1;
  368. /* write back to control register */
  369. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  370. }
  371. void mmu_disable()
  372. {
  373. register rt_uint32_t i;
  374. /* read control register */
  375. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  376. i &= ~0x1;
  377. /* write back to control register */
  378. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  379. }
  380. void mmu_enable_icache()
  381. {
  382. register rt_uint32_t i;
  383. /* read control register */
  384. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  385. i |= (1 << 12);
  386. /* write back to control register */
  387. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  388. }
  389. void mmu_enable_dcache()
  390. {
  391. register rt_uint32_t i;
  392. /* read control register */
  393. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  394. i |= (1 << 2);
  395. /* write back to control register */
  396. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  397. }
  398. void mmu_disable_icache()
  399. {
  400. register rt_uint32_t i;
  401. /* read control register */
  402. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  403. i &= ~(1 << 12);
  404. /* write back to control register */
  405. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  406. }
  407. void mmu_disable_dcache()
  408. {
  409. register rt_uint32_t i;
  410. /* read control register */
  411. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  412. i &= ~(1 << 2);
  413. /* write back to control register */
  414. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  415. }
  416. void mmu_enable_alignfault()
  417. {
  418. register rt_uint32_t i;
  419. /* read control register */
  420. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  421. i |= (1 << 1);
  422. /* write back to control register */
  423. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  424. }
  425. void mmu_disable_alignfault()
  426. {
  427. register rt_uint32_t i;
  428. /* read control register */
  429. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  430. i &= ~(1 << 1);
  431. /* write back to control register */
  432. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  433. }
  434. void mmu_clean_invalidated_cache_index(int index)
  435. {
  436. asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index));
  437. }
  438. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  439. {
  440. unsigned int ptr;
  441. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  442. while(ptr < buffer + size)
  443. {
  444. asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr));
  445. ptr += CACHE_LINE_SIZE;
  446. }
  447. }
  448. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  449. {
  450. unsigned int ptr;
  451. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  452. while (ptr < buffer + size)
  453. {
  454. asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr));
  455. ptr += CACHE_LINE_SIZE;
  456. }
  457. }
  458. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  459. {
  460. unsigned int ptr;
  461. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  462. while (ptr < buffer + size)
  463. {
  464. asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr));
  465. ptr += CACHE_LINE_SIZE;
  466. }
  467. }
  468. void mmu_invalidate_tlb()
  469. {
  470. asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0));
  471. }
  472. void mmu_invalidate_icache()
  473. {
  474. asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
  475. }
  476. void mmu_invalidate_dcache_all()
  477. {
  478. asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (0));
  479. }
  480. #endif
  481. /* level1 page table */
  482. #if defined(__ICCARM__)
  483. #pragma data_alignment=(16*1024)
  484. static volatile unsigned int _page_table[4*1024];;
  485. #else
  486. static volatile unsigned int _page_table[4*1024] \
  487. __attribute__((aligned(16*1024)));
  488. #endif
  489. void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd,
  490. rt_uint32_t paddrStart, rt_uint32_t attr)
  491. {
  492. volatile rt_uint32_t *pTT;
  493. volatile int nSec;
  494. int i = 0;
  495. pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20);
  496. nSec=(vaddrEnd>>20)-(vaddrStart>>20);
  497. for(i=0; i<=nSec; i++)
  498. {
  499. *pTT = attr |(((paddrStart>>20)+i)<<20);
  500. pTT++;
  501. }
  502. }
  503. void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
  504. {
  505. /* disable I/D cache */
  506. mmu_disable_dcache();
  507. mmu_disable_icache();
  508. mmu_disable();
  509. mmu_invalidate_tlb();
  510. /* set page table */
  511. for (; size > 0; size--)
  512. {
  513. mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
  514. mdesc->paddr_start, mdesc->attr);
  515. mdesc++;
  516. }
  517. /* set MMU table address */
  518. mmu_setttbase((rt_uint32_t)_page_table);
  519. /* enables MMU */
  520. mmu_enable();
  521. /* enable Instruction Cache */
  522. mmu_enable_icache();
  523. /* enable Data Cache */
  524. mmu_enable_dcache();
  525. mmu_invalidate_icache();
  526. mmu_invalidate_dcache_all();
  527. }