mt_innercache.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <linux/module.h>
  2. #include <linux/interrupt.h>
  3. #include <linux/cpu.h>
  4. #include <linux/smp.h>
  5. #include <mt-plat/sync_write.h>
  6. #include "mt_innercache.h"
  7. /*
  8. * inner_dcache_flush_all: Flush (clean + invalidate) the entire L1 data cache.
  9. *
  10. * This can be used ONLY by the M4U driver!!
  11. * Other drivers should NOT use this function at all!!
  12. * Others should use DMA-mapping APIs!!
  13. *
  14. * After calling the function, the buffer should not be touched anymore.
  15. * And the M4U driver should then call outer_flush_all() immediately.
  16. * Here is the example:
  17. * // Cannot touch the buffer from here.
  18. * inner_dcache_flush_all();
  19. * outer_flush_all();
  20. * // Can touch the buffer from here.
  21. * If preemption occurs and the driver cannot guarantee that no other process will touch the buffer,
  22. * the driver should use LOCK to protect this code segment.
  23. */
  24. void inner_dcache_flush_all(void)
  25. {
  26. __inner_flush_dcache_all();
  27. }
  28. EXPORT_SYMBOL(inner_dcache_flush_all);
  29. void inner_dcache_flush_L1(void)
  30. {
  31. __inner_flush_dcache_L1();
  32. }
  33. void inner_dcache_flush_L2(void)
  34. {
  35. __inner_flush_dcache_L2();
  36. }
  37. /* ARCH ARM32 */
  38. int get_cluster_core_count(void)
  39. {
  40. unsigned int cores;
  41. asm volatile ("MRC p15, 1, %0, c9, c0, 2\n":"=r" (cores)
  42. : : "cc");
  43. return (cores >> 24) + 1;
  44. }
  45. /*
  46. * smp_inner_dcache_flush_all: Flush (clean + invalidate) the entire L1 data cache.
  47. *
  48. * This can be used ONLY by the M4U driver!!
  49. * Other drivers should NOT use this function at all!!
  50. * Others should use DMA-mapping APIs!!
  51. *
  52. * This is the smp version of inner_dcache_flush_all().
  53. * It will use IPI to do flush on all CPUs.
  54. * Must not call this function with disabled interrupts or from a
  55. * hardware interrupt handler or from a bottom half handler.
  56. */
  57. void smp_inner_dcache_flush_all(void)
  58. {
  59. int i, j, num_core, total_core, online_cpu;
  60. struct cpumask mask;
  61. if (in_interrupt()) {
  62. pr_err("Cannot invoke smp_inner_dcache_flush_all() in interrupt/softirq context\n");
  63. return;
  64. }
  65. get_online_cpus();
  66. preempt_disable();
  67. on_each_cpu((smp_call_func_t) inner_dcache_flush_L1, NULL, true);
  68. num_core = get_cluster_core_count();
  69. total_core = num_possible_cpus();
  70. /*
  71. printk("In %s:%d: num_core = %d, total_core = %d\n", __func__, __LINE__, num_core, total_core);
  72. */
  73. for (i = 0; i < total_core; i += num_core) {
  74. cpumask_clear(&mask);
  75. for (j = i; j < (i + num_core); j++) {
  76. /* check the online status, then set bit */
  77. if (cpu_online(j))
  78. cpumask_set_cpu(j, &mask);
  79. }
  80. online_cpu = cpumask_first_and(cpu_online_mask, &mask);
  81. /*
  82. printk("online mask = 0x%x, mask = 0x%x, id =%d\n",
  83. *(unsigned int *)cpu_online_mask->bits, *(unsigned int *)mask.bits, online_cpu);
  84. */
  85. smp_call_function_single(online_cpu, (smp_call_func_t) inner_dcache_flush_L2, NULL,
  86. true);
  87. }
  88. preempt_enable();
  89. put_online_cpus();
  90. }
  91. EXPORT_SYMBOL(smp_inner_dcache_flush_all);
  92. #if 0
  93. static ssize_t cache_test_show(struct device_driver *driver, char *buf)
  94. {
  95. __disable_icache();
  96. __enable_icache();
  97. __disable_dcache();
  98. __enable_dcache();
  99. __disable_cache();
  100. __enable_cache();
  101. __inner_inv_dcache_L1();
  102. __inner_inv_dcache_L2();
  103. __inner_inv_dcache_all();
  104. __inner_clean_dcache_L1();
  105. __inner_clean_dcache_L2();
  106. __inner_clean_dcache_all();
  107. __inner_flush_dcache_L1();
  108. __inner_flush_dcache_L2();
  109. __inner_flush_dcache_all();
  110. __disable_dcache__inner_flush_dcache_L1();
  111. __disable_dcache__inner_flush_dcache_L1__inner_clean_dcache_L2();
  112. __disable_dcache__inner_flush_dcache_L1__inner_flush_dcache_L2();
  113. return strlen(buf);
  114. }
  115. static ssize_t cache_test_store(struct device_driver *driver, const char *buf, size_t count)
  116. {
  117. return count;
  118. }
  119. #endif