r5k-sc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:2k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
  3.  * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
  4.  */
  5. #include <linux/init.h>
  6. #include <linux/kernel.h>
  7. #include <linux/sched.h>
  8. #include <linux/mm.h>
  9. #include <asm/mipsregs.h>
  10. #include <asm/bcache.h>
  11. #include <asm/page.h>
  12. #include <asm/pgtable.h>
  13. #include <asm/system.h>
  14. #include <asm/mmu_context.h>
  15. #include <asm/cacheops.h>
  16. /* Secondary cache size in bytes, if present.  */
  17. static unsigned long scache_size;
  18. #define SC_LINE 32
  19. #define SC_PAGE (128*SC_LINE)
  20. #define cache_op(base,op)                   
  21. __asm__ __volatile__("
  22. .set noreorder;                 
  23. .set mips3;                     
  24. cache %1, (%0);                 
  25. .set mips0;                     
  26. .set reorder"                   
  27. :                               
  28. : "r" (base),                   
  29.   "i" (op));
  30. static inline void blast_r5000_scache(void)
  31. {
  32. unsigned long start = KSEG0;
  33. unsigned long end = KSEG0 + scache_size;
  34. while(start < end) {
  35. cache_op(start, R5K_Page_Invalidate_S);
  36. start += SC_PAGE;
  37. }
  38. }
  39. static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
  40. {
  41. unsigned long end, a;
  42. if (size >= scache_size) {
  43. blast_r5000_scache();
  44. return;
  45. }
  46. /* On the R5000 secondary cache we cannot
  47.  * invalidate less than a page at a time.
  48.  * The secondary cache is physically indexed, write-through.
  49.  */
  50. a = addr & ~(SC_PAGE - 1);
  51. end = (addr + size - 1) & ~(SC_PAGE - 1);
  52. while (a <= end) {
  53. cache_op(a, R5K_Page_Invalidate_S);
  54. a += SC_PAGE;
  55. }
  56. }
  57. static void r5k_sc_enable(void)
  58. {
  59.         unsigned long flags;
  60. __save_and_cli(flags);
  61. change_cp0_config(CONF_SE, CONF_SE);
  62. blast_r5000_scache();
  63. __restore_flags(flags);
  64. }
  65. static void r5k_sc_disable(void)
  66. {
  67.         unsigned long flags;
  68. __save_and_cli(flags);
  69. blast_r5000_scache();
  70. change_cp0_config(CONF_SE, 0);
  71. __restore_flags(flags);
  72. }
  73. static inline int __init r5k_sc_probe(void)
  74. {
  75. unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
  76. if(config & CONF_SC)
  77. return(0);
  78. scache_size = (512*1024) << ((config >> 20)&3);
  79. printk("R5000 SCACHE size %ldK, linesize 32 bytes.n",
  80. scache_size >> 10);
  81. return 1;
  82. }
  83. struct bcache_ops r5k_sc_ops = {
  84. r5k_sc_enable,
  85. r5k_sc_disable,
  86. r5k_dma_cache_inv_sc,
  87. r5k_dma_cache_inv_sc
  88. };
  89. void __init r5k_sc_init(void)
  90. {
  91. if (r5k_sc_probe()) {
  92. r5k_sc_enable();
  93. bcops = &r5k_sc_ops;
  94. }
  95. }