proc-xscale.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:27k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/mm/proc-xscale.S
  3.  *
  4.  *  Author: Nicolas Pitre
  5.  *  Created: November 2000
  6.  *  Copyright: (C) 2000, 2001 MontaVista Software Inc.
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License version 2 as
  10.  * published by the Free Software Foundation.
  11.  *
  12.  * MMU functions for the Intel XScale CPUs
  13.  *
  14.  * 2001 Aug 21:
  15.  * some contributions by Brett Gaines <brett.w.gaines@intel.com>
  16.  * Copyright 2001 by Intel Corp.
  17.  *
  18.  * 2001 Sep 08:
  19.  * Completely revisited, many important fixes
  20.  * Nicolas Pitre <nico@cam.org>
  21.  */
  22. #include <linux/config.h>
  23. #include <linux/linkage.h>
  24. #include <asm/assembler.h>
  25. #include <asm/constants.h>
  26. #include <asm/procinfo.h>
  27. #include <asm/hardware.h>
  28. #include <asm/proc/pgtable.h>
  29. /*
  30.  * Some knobs for cache allocation policy.
  31.  * Allocate on write may or may not be beneficial depending on the memory
  32.  * usage pattern of your main application.  Write through cache is definitely
  33.  * a performance loss in most cases, but might be used for special purposes.
  34.  */
  35. #define PMD_CACHE_WRITE_ALLOCATE 1
  36. #define PTE_CACHE_WRITE_ALLOCATE 1
  37. #define CACHE_WRITE_THROUGH 0
  38. /*
  39.  * There are errata that say that dirty status bits in the cache may get
  40.  * corrupted. The workaround significantly affects performance, and the bug
  41.  * _might_ just not be that visible or critical to you, so it is configurable.
  42.  * Let's hope a future core revision will tell us this was only a bad dream.
  43.  * But in the mean time the risk and tradeoff is yours to decide....
  44.  */
  45. #ifdef CONFIG_XSCALE_CACHE_ERRATA
  46. #undef CACHE_WRITE_THROUGH
  47. #define CACHE_WRITE_THROUGH 1
  48. #endif
  49. /* 
  50.  * This is the maximum size of an area which will be flushed.  If the area
  51.  * is larger than this, then we flush the whole cache
  52.  */
  53. #define MAX_AREA_SIZE 32768
  54. /*
  55.  * the cache line size of the I and D cache
  56.  */
  57. #define CACHELINESIZE 32
  58. /*
  59.  * the size of the data cache
  60.  */
  61. #define CACHESIZE 32768
  62. /*
  63.  * and the page size
  64.  */
  65. #define PAGESIZE 4096
  66. /*
  67.  * Virtual address used to allocate the cache when flushed
  68.  *
  69.  * This must be an address range which is _never_ used.  It should 
  70.  * apparently have a mapping in the corresponding page table for 
  71.  * compatibility with future CPUs that _could_ require it.  For instance we
  72.  * don't care.
  73.  *
  74.  * This must be aligned on a 2*CACHESIZE boundary.  The code selects one of
  75.  * the 2 areas in alternance each time the clean_d_cache macro is used.
  76.  * Without this the XScale core exhibits cache eviction problems and no one
  77.  * knows why.  
  78.  *
  79.  * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
  80.  */
  81. #define CLEAN_ADDR 0xfffe0000
  82. /*
  83.  * This macro is used to wait for a CP15 write and is needed
  84.  * when we have to ensure that the last operation to the co-pro
  85.  * was completed before continuing with operation.
  86.  */
  87. .macro cpwait, rd
  88. mrc p15, 0, rd, c2, c0, 0 @ arbitrary read of cp15
  89. mov rd, rd @ wait for completion
  90. sub  pc, pc, #4 @ flush instruction pipeline
  91. .endm
  92. .macro cpwait_ret, lr, rd
  93. mrc p15, 0, rd, c2, c0, 0 @ arbitrary read of cp15
  94. sub pc, lr, rd, LSR #32 @ wait for completion and
  95. @ flush instruction pipeline
  96. .endm
  97. #if !CACHE_WRITE_THROUGH
  98. /*
  99.  * This macro cleans the entire dcache using line allocate.
  100.  * The main loop has been unrolled to reduce loop overhead.
  101.  * rd and rs are two scratch registers.
  102.  */
  103. .macro  clean_d_cache, rd, rs
  104. ldr rs, =clean_addr
  105. ldr rd, [rs]
  106. eor rd, rd, #CACHESIZE
  107. str rd, [rs]
  108. add rs, rd, #CACHESIZE
  109. 1: mcr p15, 0, rd, c7, c2, 5 @ allocate D cache line
  110. add rd, rd, #CACHELINESIZE
  111. mcr p15, 0, rd, c7, c2, 5 @ allocate D cache line
  112. add rd, rd, #CACHELINESIZE
  113. mcr p15, 0, rd, c7, c2, 5 @ allocate D cache line
  114. add rd, rd, #CACHELINESIZE
  115. mcr p15, 0, rd, c7, c2, 5 @ allocate D cache line
  116. add rd, rd, #CACHELINESIZE
  117. teq rd, rs
  118. bne 1b
  119. .endm
  120. .macro clean_d_line, rd
  121. mcr p15, 0, rd, c7, c10, 1
  122. .endm
  123. .data
  124. clean_addr: .word CLEAN_ADDR
  125. #else
  126. /*
  127.  * If cache is write-through, there is no need to clean it.
  128.  * Simply invalidating will do.
  129.  */
  130. .macro  clean_d_cache, rd, rs
  131. mcr p15, 0, rd, c7, c6, 0
  132. .endm
  133. /* let's try to skip this needless operations at least within loops */
  134. .macro clean_d_line, rd
  135. .endm
  136. #endif
  137. .text
  138. /*
  139.  * cpu_xscale_data_abort()
  140.  *
  141.  * obtain information about current aborted instruction.
  142.  * Note: we read user space.  This means we might cause a data
  143.  * abort here if the I-TLB and D-TLB aren't seeing the same
  144.  * picture.  Unfortunately, this does happen.  We live with it.
  145.  *
  146.  *  r2 = address of aborted instruction
  147.  *  r3 = cpsr
  148.  *
  149.  * Returns:
  150.  *  r0 = address of abort
  151.  *  r1 != 0 if writing
  152.  *  r3 = FSR
  153.  *  r4 = corrupted
  154.  */
  155. .align 5
  156. ENTRY(cpu_xscale_data_abort)
  157. mrc p15, 0, r3, c5, c0, 0 @ get FSR
  158. mrc p15, 0, r0, c6, c0, 0 @ get FAR
  159. ldr r1, [r2] @ read aborted instruction
  160. and r3, r3, #255
  161. tst r1, r1, lsr #21 @ C = bit 20
  162. sbc r1, r1, r1 @ r1 = C - 1
  163. mov pc, lr
  164. /*
  165.  * cpu_xscale_check_bugs()
  166.  */
  167. ENTRY(cpu_xscale_check_bugs)
  168. mrs ip, cpsr
  169. bic ip, ip, #F_BIT
  170. msr cpsr, ip
  171. mov pc, lr
  172. #ifndef CONFIG_XSCALE_CACHE_ERRATA
  173. /*
  174.  * cpu_xscale_proc_init()
  175.  *
  176.  * Nothing too exciting at the moment
  177.  */
  178. ENTRY(cpu_xscale_proc_init)
  179. mov pc, lr
  180. #else
  181. /*
  182.  * We enable the cache here, but we make sure all the status bits for dirty
  183.  * lines are cleared as well (see PXA250 erratum #120).
  184.  */
  185. ENTRY(cpu_xscale_proc_init)
  186. @ enable data cache
  187. ldr r0, cr_p
  188. ldmia r0, {r1, r2}
  189. orr r1, r1, #0x4
  190. orr r2, r2, #0x4
  191. stmia r0, {r1, r2}
  192. mcr p15, 0, r1, c1, c0, 0
  193. cpwait r0
  194. @ invalidate data cache
  195. mcr p15, 0, r0, c7, c6, 0
  196. @ fill main cache with write-through lines
  197. bic r0, pc, #0x1f
  198. add r1, r0, #CACHESIZE
  199. 1: ldr r2, [r0], #32
  200. cmp r0, r1
  201. bne 1b
  202. @ enable test feature to force all fills to the mini-cache
  203. mov r1, #0x8
  204. mcr p15, 0, r1, c15, c15, 3
  205. @ fill mini-cache with write-through lines (2kbytes, 64 lines)
  206. add r1, r0, #2048
  207. 2: ldr r2, [r0], #32
  208. cmp r0, r1
  209. bne 2b
  210. @ disable test feature to force all fills to the mini-cache
  211. mov r1, #0x0
  212. mcr p15, 0, r1, c15, c15, 3
  213. @ invalidate data cache again
  214. mcr p15, 0, r1, c7, c6, 0
  215. mov pc, lr
  216. cr_p: .long SYMBOL_NAME(cr_alignment)
  217. #endif
  218. /*
  219.  * cpu_xscale_proc_fin()
  220.  */
  221. ENTRY(cpu_xscale_proc_fin)
  222. str lr, [sp, #-4]!
  223. mov r0, #F_BIT|I_BIT|SVC_MODE
  224. msr cpsr_c, r0
  225. mrc p15, 0, r0, c1, c0, 0 @ ctrl register
  226. bic r0, r0, #0x1800 @ ...IZ...........
  227. bic r0, r0, #0x0006 @ .............CA.
  228. mcr p15, 0, r0, c1, c0, 0 @ disable caches
  229. bl cpu_xscale_cache_clean_invalidate_all @ clean caches
  230. ldr pc, [sp], #4
  231. /*
  232.  * cpu_xscale_reset(loc)
  233.  *
  234.  * Perform a soft reset of the system.  Put the CPU into the
  235.  * same state as it would be if it had been reset, and branch
  236.  * to what would be the reset vector.
  237.  *
  238.  * loc: location to jump to for soft reset
  239.  */
  240. .align 5
  241. ENTRY(cpu_xscale_reset)
  242. mov r1, #F_BIT|I_BIT|SVC_MODE
  243. msr cpsr_c, r1 @ reset CPSR
  244. mrc p15, 0, r1, c1, c0, 0 @ ctrl register
  245. bic r1, r1, #0x0086 @ ........B....CA.
  246. bic r1, r1, #0x1900 @ ...IZ..S........
  247. mcr p15, 0, r1, c1, c0, 0 @ ctrl register
  248. mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
  249. bic r1, r1, #0x0001 @ ...............M
  250. mcr p15, 0, r1, c1, c0, 0 @ ctrl register
  251. @ CAUTION: MMU turned off from this point. We count on the pipeline 
  252. @ already containing those two last instructions to survive.
  253. mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
  254. mov pc, r0
  255. /*
  256.  * cpu_xscale_do_idle(type)
  257.  *
  258.  * Cause the processor to idle
  259.  *
  260.  * type: 
  261.  *   0 = slow idle
  262.  *   1 = fast idle
  263.  *   2 = switch to slow processor clock
  264.  *   3 = switch to fast processor clock
  265.  *
  266.  * For now we do nothing but go to idle mode for every case
  267.  *
  268.  * XScale supports clock switching, but using idle mode support
  269.  * allows external hardware to react to system state changes.
  270.  */
  271. .align 5
  272. ENTRY(cpu_xscale_do_idle)
  273. mov r0, #1
  274. mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
  275. mov pc, lr
  276. /* ================================= CACHE ================================ */
  277. /*
  278.  * cpu_xscale_cache_clean_invalidate_all (void)
  279.  *
  280.  * clean and invalidate all cache lines
  281.  *
  282.  * Note:
  283.  *  1. We should preserve r0 at all times.
  284.  *  2. Even if this function implies cache "invalidation" by its name,
  285.  *     we don't need to actually use explicit invalidation operations
  286.  *     since the goal is to discard all valid references from the cache
  287.  *     and the cleaning of it already has that effect.
  288.  *  3. Because of 2 above and the fact that kernel space memory is always
  289.  *     coherent across task switches there is no need to worry about
  290.  *     inconsistencies due to interrupts, ence no irq disabling.
  291.  */
  292. .align 5
  293. ENTRY(cpu_xscale_cache_clean_invalidate_all)
  294. mov r2, #1
  295. cpu_xscale_cache_clean_invalidate_all_r2:
  296. clean_d_cache r0, r1
  297. teq r2, #0
  298. mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
  299. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  300. mov pc, lr
  301. /*
  302.  * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
  303.  *
  304.  * clean and invalidate all cache lines associated with this area of memory
  305.  *
  306.  * start: Area start address
  307.  * end:   Area end address
  308.  * flags: nonzero for I cache as well
  309.  */
  310. .align 5
  311. ENTRY(cpu_xscale_cache_clean_invalidate_range)
  312. bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
  313. sub r3, r1, r0
  314. cmp r3, #MAX_AREA_SIZE
  315. bhi cpu_xscale_cache_clean_invalidate_all_r2
  316. 1: clean_d_line r0 @ Clean D cache line
  317. mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
  318. add r0, r0, #CACHELINESIZE
  319. cmp r0, r1
  320. blo 1b
  321. teq r2, #0
  322. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  323. moveq pc, lr
  324. sub r0, r0, r3
  325. 1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
  326. add r0, r0, #CACHELINESIZE
  327. cmp r0, r1
  328. blo 1b
  329. mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
  330. mov pc, lr
  331. /*
  332.  * cpu_xscale_flush_ram_page(page)
  333.  *
  334.  * clean all cache lines associated with this memory page
  335.  *
  336.  * page: page to clean
  337.  */
  338. .align 5
  339. ENTRY(cpu_xscale_flush_ram_page)
  340. #if !CACHE_WRITE_THROUGH
  341. mov r1, #PAGESIZE
  342. 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  343. add r0, r0, #CACHELINESIZE
  344. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  345. add r0, r0, #CACHELINESIZE
  346. subs r1, r1, #2 * CACHELINESIZE
  347. bne 1b
  348. #endif
  349. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  350. mov pc, lr
  351. /* ================================ D-CACHE =============================== */
  352. /*
  353.  * cpu_xscale_dcache_invalidate_range(start, end)
  354.  *
  355.  * throw away all D-cached data in specified region without an obligation
  356.  * to write them back.  Note however that on XScale we must clean all
  357.  * entries also due to hardware errata (80200 A0 & A1 only).
  358.  *
  359.  * start: virtual start address
  360.  * end:   virtual end address
  361.  */
  362. .align 5
  363. ENTRY(cpu_xscale_dcache_invalidate_range)
  364. mrc p15, 0, r2, c0, c0, 0 @ Read part no.
  365. eor r2, r2, #0x69000000
  366. eor r2, r2, #0x00052000 @ 80200 XX part no.
  367. bics r2, r2, #0x1 @ Clear LSB in revision field
  368. moveq r2, #0
  369. beq cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1
  370. tst r0, #CACHELINESIZE - 1
  371. mcrne p15, 0, r0, c7, c10, 1 @ Clean D cache line
  372. tst r1, #CACHELINESIZE - 1
  373. mcrne p15, 0, r1, c7, c10, 1 @ Clean D cache line
  374. bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
  375. 1: mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
  376. add r0, r0, #CACHELINESIZE
  377. cmp r0, r1
  378. blo 1b
  379. mov pc, lr
  380. /*
  381.  * cpu_xscale_dcache_clean_range(start, end)
  382.  *
  383.  * For the specified virtual address range, ensure that all caches contain
  384.  * clean data, such that peripheral accesses to the physical RAM fetch
  385.  * correct data.
  386.  *
  387.  * start: virtual start address
  388.  * end:   virtual end address
  389.  */
  390. .align 5
  391. ENTRY(cpu_xscale_dcache_clean_range)
  392. #if !CACHE_WRITE_THROUGH
  393. bic r0, r0, #CACHELINESIZE - 1
  394. sub r2, r1, r0
  395. cmp r2, #MAX_AREA_SIZE
  396. movhi r2, #0
  397. bhi cpu_xscale_cache_clean_invalidate_all_r2
  398. 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  399. add r0, r0, #CACHELINESIZE
  400. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  401. add r0, r0, #CACHELINESIZE
  402. cmp r0, r1
  403. blo 1b
  404. #endif
  405. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  406. mov pc, lr
  407. /*
  408.  * cpu_xscale_clean_dcache_page(page)
  409.  *
  410.  * Cleans a single page of dcache so that if we have any future aliased
  411.  * mappings, they will be consistent at the time that they are created.
  412.  *
  413.  * Note:
  414.  *  1. we don't need to flush the write buffer in this case. [really? -Nico]
  415.  *  2. we don't invalidate the entries since when we write the page
  416.  *     out to disk, the entries may get reloaded into the cache.
  417.  */
  418. .align 5
  419. ENTRY(cpu_xscale_dcache_clean_page)
  420. #if !CACHE_WRITE_THROUGH
  421. mov r1, #PAGESIZE
  422. 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  423. add r0, r0, #CACHELINESIZE
  424. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  425. add r0, r0, #CACHELINESIZE
  426. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  427. add r0, r0, #CACHELINESIZE
  428. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  429. add r0, r0, #CACHELINESIZE
  430. subs r1, r1, #4 * CACHELINESIZE
  431. bne 1b
  432. #endif
  433. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  434. mov pc, lr
  435. /*
  436.  * cpu_xscale_dcache_clean_entry(addr)
  437.  *
  438.  * Clean the specified entry of any caches such that the MMU
  439.  * translation fetches will obtain correct data.
  440.  *
  441.  * addr: cache-unaligned virtual address
  442.  */
  443. .align 5
  444. ENTRY(cpu_xscale_dcache_clean_entry)
  445. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  446. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  447. mov pc, lr
  448. /* ================================ I-CACHE =============================== */
  449. /*
  450.  * cpu_xscale_icache_invalidate_range(start, end)
  451.  *
  452.  * invalidate a range of virtual addresses from the Icache
  453.  *
  454.  * start: virtual start address
  455.  * end:   virtual end address
  456.  *
  457.  * Note: This is vaguely defined as supposed to bring the dcache and the 
  458.  *       icache in sync by the way this function is used.
  459.  */
  460. .align 5
  461. ENTRY(cpu_xscale_icache_invalidate_range)
  462. bic r0, r0, #CACHELINESIZE - 1
  463. 1: clean_d_line r0 @ Clean D cache line
  464. mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
  465. add r0, r0, #CACHELINESIZE
  466. cmp r0, r1
  467. blo 1b
  468. mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
  469. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  470. mov pc, lr
  471. /*
  472.  * cpu_xscale_icache_invalidate_page(page)
  473.  *
  474.  * invalidate all Icache lines associated with this area of memory
  475.  *
  476.  * page: page to invalidate
  477.  */
  478. .align 5
  479. ENTRY(cpu_xscale_icache_invalidate_page)
  480. mov r1, #PAGESIZE
  481. 1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
  482. add r0, r0, #CACHELINESIZE
  483. mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
  484. add r0, r0, #CACHELINESIZE
  485. mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
  486. add r0, r0, #CACHELINESIZE
  487. mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
  488. add r0, r0, #CACHELINESIZE
  489. subs r1, r1, #4 * CACHELINESIZE
  490. bne 1b
  491. mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
  492. mov pc, lr
  493. /* ================================ CACHE LOCKING============================ 
  494.  *
  495.  * The XScale MicroArchitecture implements support for locking entries into
  496.  * the data and instruction cache.  The following functions implement the core
  497.  * low level instructions needed to accomplish the locking.  The developer's
  498.  * manual states that the code that performs the locking must be in non-cached
  499.  * memory.  To accomplish this, the code in xscale-cache-lock.c copies the
  500.  * following functions from the cache into a non-cached memory region that
  501.  * is allocated through consistent_alloc().
  502.  *
  503.  */
  504. .align 5
  505. /*
  506.  * xscale_icache_lock
  507.  *
  508.  * r0: starting address to lock
  509.  * r1: end address to lock
  510.  */
  511. ENTRY(xscale_icache_lock)
  512. iLockLoop:
  513. bic r0, r0, #CACHELINESIZE - 1
  514. mcr p15, 0, r0, c9, c1, 0 @ lock into cache
  515. cmp r0, r1 @ are we done?
  516. add r0, r0, #CACHELINESIZE @ advance to next cache line
  517. bls iLockLoop
  518. mov pc, lr
  519. /*
  520.  * xscale_icache_unlock
  521.  */
  522. ENTRY(xscale_icache_unlock)
  523. mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
  524. mov pc, lr
  525. /*
  526.  * xscale_dcache_lock
  527.  *
  528.  * r0: starting address to lock
  529.  * r1: end address to lock
  530.  */
  531. ENTRY(xscale_dcache_lock)
  532. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  533. mov r2, #1
  534. mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
  535. cpwait ip @ Wait for completion
  536. mrs r2, cpsr
  537. orr r3, r2, #F_BIT | I_BIT
  538. dLockLoop:
  539. msr cpsr_c, r3
  540. mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty 
  541. mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
  542. msr cpsr_c, r2
  543. ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from 
  544. @ location [r0]. Post-increment
  545. @ r3 to next cache line
  546. cmp r0, r1 @ Are we done?
  547. bls dLockLoop
  548. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  549. mov r2, #0
  550. mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
  551. cpwait_ret lr, ip
  552. /*
  553.  * xscale_dcache_unlock
  554.  */
  555. ENTRY(xscale_dcache_unlock)
  556. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  557. mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
  558. mov pc, lr
  559. /*
  560.  * Needed to determine the length of the code that needs to be copied.
  561.  */
  562. .align 5
  563. ENTRY(xscale_cache_dummy)
  564. mov pc, lr
  565. /* ================================== TLB ================================= */
  566. /*
  567.  * cpu_xscale_tlb_invalidate_all()
  568.  *
  569.  * Invalidate all TLB entries
  570.  */
  571. .align 5
  572. ENTRY(cpu_xscale_tlb_invalidate_all)
  573. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  574. mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
  575. cpwait_ret lr, ip
  576. /*
  577.  * cpu_xscale_tlb_invalidate_range(start, end)
  578.  *
  579.  * invalidate TLB entries covering the specified range
  580.  *
  581.  * start: range start address
  582.  * end:   range end address
  583.  */
  584. .align 5
  585. ENTRY(cpu_xscale_tlb_invalidate_range)
  586. bic r0, r0, #(PAGESIZE - 1) & 0x00ff
  587. bic r0, r0, #(PAGESIZE - 1) & 0xff00
  588. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  589. 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  590. mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
  591. add r0, r0, #PAGESIZE
  592. cmp r0, r1
  593. blo 1b
  594. cpwait_ret lr, ip
  595. /*
  596.  * cpu_xscale_tlb_invalidate_page(page, flags)
  597.  *
  598.  * invalidate the TLB entries for the specified page.
  599.  *
  600.  * page:  page to invalidate
  601.  * flags: non-zero if we include the I TLB
  602.  */
  603. .align 5
  604. ENTRY(cpu_xscale_tlb_invalidate_page)
  605. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  606. teq r1, #0
  607. mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
  608. mcrne p15, 0, r3, c8, c5, 1 @ invalidate I TLB entry
  609. cpwait_ret lr, ip
  610. /* ================================ TLB LOCKING==============================
  611.  *
  612.  * The XScale MicroArchitecture implements support for locking entries into
  613.  * the Instruction and Data TLBs.  The following functions provide the
  614.  * low level support for supporting these under Linux.  xscale-lock.c 
  615.  * implements some higher level management code.  Most of the following
  616.  * is taken straight out of the Developer's Manual.
  617.  */
  618. /*
  619.  * Lock I-TLB entry
  620.  *
  621.  * r0: Virtual address to translate and lock
  622.  */
  623. .align 5
  624. ENTRY(xscale_itlb_lock)
  625. mrs r2, cpsr
  626. orr r3, r2, #F_BIT | I_BIT
  627. msr cpsr_c, r3 @ Disable interrupts
  628. mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
  629. mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
  630. msr cpsr_c, r2 @ Restore interrupts
  631. cpwait_ret lr, ip
  632. /*
  633.  * Lock D-TLB entry
  634.  *
  635.  * r0: Virtual address to translate and lock
  636.  */
  637. .align 5
  638. ENTRY(xscale_dtlb_lock)
  639. mrs r2, cpsr
  640. orr r3, r2, #F_BIT | I_BIT
  641. msr cpsr_c, r3 @ Disable interrupts
  642. mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
  643. mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
  644. msr cpsr_c, r2 @ Restore interrupts
  645. cpwait_ret lr, ip
  646. /*
  647.  * Unlock all I-TLB entries
  648.  */
  649. .align 5
  650. ENTRY(xscale_itlb_unlock)
  651. mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
  652. mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
  653. cpwait_ret lr, ip
  654. /*
  655.  * Unlock all D-TLB entries
  656.  */
  657. ENTRY(xscale_dtlb_unlock)
  658. mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
  659. mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
  660. cpwait_ret lr, ip
  661. /* =============================== PageTable ============================== */
  662. /*
  663.  * cpu_xscale_set_pgd(pgd)
  664.  *
  665.  * Set the translation base pointer to be as described by pgd.
  666.  *
  667.  * pgd: new page tables
  668.  */
  669. .align 5
  670. ENTRY(cpu_xscale_set_pgd)
  671. clean_d_cache r1, r2
  672. mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
  673. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  674. mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
  675. mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
  676. cpwait_ret lr, ip
  677. /*
  678.  * cpu_xscale_set_pmd(pmdp, pmd)
  679.  *
  680.  * Set a level 1 translation table entry, and clean it out of
  681.  * any caches such that the MMUs can load it correctly.
  682.  *
  683.  * pmdp: pointer to PMD entry
  684.  * pmd:  PMD value to store
  685.  */
  686. .align 5
  687. ENTRY(cpu_xscale_set_pmd)
  688. #if PMD_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
  689. and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
  690. cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
  691. orreq r1, r1, #PMD_SECT_TEX(1)
  692. #elif CACHE_WRITE_THROUGH
  693. and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
  694. cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
  695. biceq r1, r1, #PMD_SECT_BUFFERABLE
  696. #endif
  697. str r1, [r0]
  698. mov ip, #0
  699. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  700. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  701. mov pc, lr
  702. /*
  703.  * cpu_xscale_set_pte(ptep, pte)
  704.  *
  705.  * Set a PTE and flush it out
  706.  *
  707.  * Errata 40: must set memory to write-through for user read-only pages.
  708.  */
  709. .align 5
  710. ENTRY(cpu_xscale_set_pte)
  711. str r1, [r0], #-1024 @ linux version
  712. bic r2, r1, #0xff0
  713. orr r2, r2, #PTE_TYPE_EXT @ extended page
  714. eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
  715. tst r3, #L_PTE_USER | L_PTE_EXEC @ User or Exec?
  716. orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
  717. tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
  718. orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
  719. @ combined with user -> user r/w
  720. @
  721. @ Handle the X bit.  We want to set this bit for the minicache
  722. @ (U = E = B = W = 0, C = 1) or when write allocate is enabled,
  723. @ and we have a writeable, cacheable region.  If we ignore the
  724. @ U and E bits, we can allow user space to use the minicache as
  725. @ well.
  726. @
  727. @  X = C & ~W & ~B
  728. @      | C & W & B & write_allocate
  729. @
  730. eor ip, r1, #L_PTE_CACHEABLE
  731. tst ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
  732. #if PTE_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
  733. eorne ip, r1, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
  734. tstne ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
  735. #endif
  736. orreq r2, r2, #PTE_EXT_TEX(1)
  737. #if CACHE_WRITE_THROUGH
  738. bic r2, r2, #L_PTE_BUFFERABLE
  739. #else
  740. @
  741. @ Errata 40: The B bit must be cleared for a user read-only
  742. @ cacheable page.
  743. @
  744. @  B = B & ~((U|E) & C & ~W)
  745. @
  746. and ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE
  747. teq ip, #L_PTE_USER | L_PTE_CACHEABLE
  748. teqne ip, #L_PTE_EXEC | L_PTE_CACHEABLE
  749. teqne ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE
  750. biceq r2, r2, #PTE_BUFFERABLE
  751. #endif
  752. tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
  753. movne r2, #0 @ no -> fault
  754. str r2, [r0] @ hardware version
  755. @ We try to map 64K page entries when possible.  
  756. @ We do that for kernel space only since the usage pattern from
  757. @ the setting of VM area is quite simple.  User space is not worth
  758. @ the implied complexity because of ever randomly changing PTEs 
  759. @ (page aging, swapout, etc) requiring constant coherency checks.
  760. @ Since PTEs are usually set in increasing order, we test the
  761. @ possibility for a large page only when given the last PTE of a
  762. @ 64K boundary.
  763. tsteq r1, #L_PTE_USER
  764. andeq r1, r0, #(15 << 2)
  765. teqeq r1, #(15 << 2)
  766. beq 1f
  767. mov ip, #0
  768. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  769. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  770. mov pc, lr
  771. @ See if we have 16 identical PTEs but with consecutive base addresses
  772. 1: bic r3, r2, #0x0000f000
  773. mov r1, #0x0000f000
  774. 2: eor r2, r2, r3
  775. teq r2, r1
  776. bne 4f
  777. subs r1, r1, #0x00001000
  778. ldr r2, [r0, #-4]!
  779. bne 2b
  780. eors r2, r2, r3
  781. bne 4f
  782. @ Now create our LARGE PTE from the current EXT one.
  783. bic r3, r3, #PTE_TYPE_MASK
  784. orr r3, r3, #PTE_TYPE_LARGE
  785. and r2, r3, #0x30 @ EXT_AP --> LARGE_AP0
  786. orr r2, r2, r2, lsl #2 @ add LARGE_AP1
  787. orr r2, r2, r2, lsl #4 @ add LARGE_AP3 + LARGE_AP2
  788. and r1, r3, #0x3c0 @ EXT_TEX
  789. bic r3, r3, #0x3c0
  790. orr r2, r2, r1, lsl #(12 - 6) @ --> LARGE_TEX
  791. orr r2, r2, r3 @ add remaining bits
  792. @ then put it in the pagetable
  793. mov r3, r2
  794. 3: strd r2, [r0], #8
  795. tst r0, #(15 << 2)
  796. bne 3b
  797. @ Then sync the 2 corresponding cache lines
  798. sub r0, r0, #(16 << 2)
  799. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  800. 4: orr r0, r0, #(15 << 2)
  801. mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
  802. mov ip, #0
  803. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  804. mov pc, lr
  805. .ltorg
  806. cpu_manu_name:
  807. .asciz "Intel"
  808. cpu_80200_name:
  809. .asciz "XScale-80200"
  810. cpu_pxa250_name:
  811. .asciz "XScale-PXA250"
  812. .align
  813. .section ".text.init", #alloc, #execinstr
  814. __xscale_setup:
  815. mov r0, #F_BIT|I_BIT|SVC_MODE
  816. msr cpsr_c, r0
  817. mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
  818. mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
  819. mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
  820. mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
  821. mov r0, #0x1f @ Domains 0, 1 = client
  822. mcr p15, 0, r0, c3, c0, 0 @ load domain access register
  823. mov r0, #1 @ Allow user space to access
  824. mcr p15, 0, r0, c15, c1, 0 @ ... CP 0 only.
  825. #if CACHE_WRITE_THROUGH
  826. mov r0, #0x20
  827. #else
  828. mov r0, #0x00
  829. #endif
  830. mcr p15, 0, r0, c1, c1, 0 @ set auxiliary control reg
  831. mrc p15, 0, r0, c1, c0, 0 @ get control register
  832. bic r0, r0, #0x0200 @ ......R.........
  833. bic r0, r0, #0x0082 @ ........B.....A.
  834. orr r0, r0, #0x0005 @ .............C.M
  835. orr r0, r0, #0x3900 @ ..VIZ..S........
  836. #ifdef CONFIG_XSCALE_CACHE_ERRATA
  837. bic r0, r0, #0x0004 @ see cpu_xscale_proc_init
  838. #endif
  839. mov pc, lr
  840. .text
  841. /*
  842.  * Purpose : Function pointers used to access above functions - all calls
  843.  *      come through these
  844.  */
  845. .type xscale_processor_functions, #object
  846. ENTRY(xscale_processor_functions)
  847. .word cpu_xscale_data_abort
  848. .word cpu_xscale_check_bugs
  849. .word cpu_xscale_proc_init
  850. .word cpu_xscale_proc_fin
  851. .word cpu_xscale_reset
  852. .word cpu_xscale_do_idle
  853. /* cache */
  854. .word cpu_xscale_cache_clean_invalidate_all
  855. .word cpu_xscale_cache_clean_invalidate_range
  856. .word cpu_xscale_flush_ram_page
  857. /* dcache */
  858. .word cpu_xscale_dcache_invalidate_range
  859. .word cpu_xscale_dcache_clean_range
  860. .word cpu_xscale_dcache_clean_page
  861. .word cpu_xscale_dcache_clean_entry
  862. /* icache */
  863. .word cpu_xscale_icache_invalidate_range
  864. .word cpu_xscale_icache_invalidate_page
  865. /* tlb */
  866. .word cpu_xscale_tlb_invalidate_all
  867. .word cpu_xscale_tlb_invalidate_range
  868. .word cpu_xscale_tlb_invalidate_page
  869. /* pgtable */
  870. .word cpu_xscale_set_pgd
  871. .word cpu_xscale_set_pmd
  872. .word cpu_xscale_set_pte
  873. .size xscale_processor_functions, . - xscale_processor_functions
  874. .type cpu_80200_info, #object
  875. cpu_80200_info:
  876. .long cpu_manu_name
  877. .long cpu_80200_name
  878. .size cpu_80200_info, . - cpu_80200_info
  879. .type cpu_pxa250_info, #object
  880. cpu_pxa250_info:
  881. .long cpu_manu_name
  882. .long cpu_pxa250_name
  883. .size cpu_pxa250_info, . - cpu_pxa250_info
  884. .type cpu_arch_name, #object
  885. cpu_arch_name:
  886. .asciz "armv5"
  887. .size cpu_arch_name, . - cpu_arch_name
  888. .type cpu_elf_name, #object
  889. cpu_elf_name:
  890. .asciz "v5"
  891. .size cpu_elf_name, . - cpu_elf_name
  892. .align
  893. .section ".proc.info", #alloc, #execinstr
  894. .type __80200_proc_info,#object
  895. __80200_proc_info:
  896. .long 0x69052000
  897. .long 0xfffffff0
  898. #if CACHE_WRITE_THROUGH
  899. .long 0x00000c0a
  900. #else
  901. .long 0x00000c0e
  902. #endif
  903. b __xscale_setup
  904. .long cpu_arch_name
  905. .long cpu_elf_name
  906. .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
  907. .long cpu_80200_info
  908. .long xscale_processor_functions
  909. .size __80200_proc_info, . - __80200_proc_info
  910. .type __pxa250_proc_info,#object
  911. __pxa250_proc_info:
  912. .long 0x69052100
  913. .long 0xfffff7f0
  914. #if CACHE_WRITE_THROUGH
  915. .long 0x00000c0a
  916. #else
  917. .long 0x00000c0e
  918. #endif
  919. b __xscale_setup
  920. .long cpu_arch_name
  921. .long cpu_elf_name
  922. .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
  923. .long cpu_pxa250_info
  924. .long xscale_processor_functions
  925. .size __pxa250_proc_info, . - __pxa250_proc_info