cache.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020 SiFive, Inc
  4. *
  5. * Authors:
  6. * Pragnesh Patel <pragnesh.patel@sifive.com>
  7. */
  8. #include <common.h>
  9. #include <asm/io.h>
  10. #include <linux/bitops.h>
  11. /* Register offsets */
  12. #define L2_CACHE_CONFIG 0x000
  13. #define L2_CACHE_ENABLE 0x008
  14. #define MASK_NUM_WAYS GENMASK(15, 8)
  15. #define NUM_WAYS_SHIFT 8
  16. DECLARE_GLOBAL_DATA_PTR;
  17. static fdt_addr_t l2cc_get_base_addr(void)
  18. {
  19. const void *blob = gd->fdt_blob;
  20. int node = fdt_node_offset_by_compatible(blob, -1,
  21. "sifive,fu540-c000-ccache");
  22. if (node < 0)
  23. return FDT_ADDR_T_NONE;
  24. return fdtdec_get_addr_size_auto_parent(blob, 0, node, "reg", 0,
  25. NULL, false);
  26. }
  27. int cache_enable_ways(void)
  28. {
  29. fdt_addr_t base;
  30. u32 config;
  31. u32 ways;
  32. volatile u32 *enable;
  33. base = l2cc_get_base_addr();
  34. if (base == FDT_ADDR_T_NONE)
  35. return FDT_ADDR_T_NONE;
  36. config = readl((volatile u32 *)base + L2_CACHE_CONFIG);
  37. ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT;
  38. if(ways != 0x10) ways = 0x10; //0x10 will enable 16-ways of L2 cache
  39. enable = (volatile u32 *)(base + L2_CACHE_ENABLE);
  40. /* memory barrier */
  41. mb();
  42. (*enable) = ways - 1;
  43. /* memory barrier */
  44. mb();
  45. return 0;
  46. }
  47. #if CONFIG_IS_ENABLED(SIFIVE_FU540_L2CC_FLUSH)
  48. #define L2_CACHE_FLUSH64 0x200
  49. #define L2_CACHE_BASE_ADDR 0x2010000
  50. void flush_dcache_range(unsigned long start, unsigned long end)
  51. {
  52. unsigned long line;
  53. volatile unsigned long *flush64;
  54. /* make sure the address is in the range */
  55. if(start > end ||
  56. start < CONFIG_SIFIVE_FU540_L2CC_FLUSH_START ||
  57. end > (CONFIG_SIFIVE_FU540_L2CC_FLUSH_START +
  58. CONFIG_SIFIVE_FU540_L2CC_FLUSH_SIZE))
  59. return;
  60. /*In order to improve the performance, change base addr to a fixed value*/
  61. flush64 = (volatile unsigned long *)(L2_CACHE_BASE_ADDR + L2_CACHE_FLUSH64);
  62. /* memory barrier */
  63. mb();
  64. for (line = start; line < end; line += CONFIG_SYS_CACHELINE_SIZE) {
  65. (*flush64) = line;
  66. /* memory barrier */
  67. mb();
  68. }
  69. return;
  70. }
  71. void invalidate_dcache_range(unsigned long start, unsigned long end)
  72. {
  73. flush_dcache_range(start,end);
  74. }
  75. #endif //SIFIVE_FU540_L2CC_FLUSH