cache.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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/global_data.h>
  10. #include <asm/io.h>
  11. #include <linux/bitops.h>
  12. /* Register offsets */
  13. #define L2_CACHE_CONFIG 0x000
  14. #define L2_CACHE_ENABLE 0x008
  15. #define MASK_NUM_WAYS GENMASK(15, 8)
  16. #define NUM_WAYS_SHIFT 8
  17. DECLARE_GLOBAL_DATA_PTR;
  18. static fdt_addr_t l2cc_get_base_addr(void)
  19. {
  20. const void *blob = gd->fdt_blob;
  21. int node = fdt_node_offset_by_compatible(blob, -1,
  22. "sifive,fu540-c000-ccache");
  23. if (node < 0)
  24. return FDT_ADDR_T_NONE;
  25. return fdtdec_get_addr_size_auto_parent(blob, 0, node, "reg", 0,
  26. NULL, false);
  27. }
  28. int cache_enable_ways(void)
  29. {
  30. fdt_addr_t base;
  31. u32 config;
  32. u32 ways;
  33. volatile u32 *enable;
  34. base = l2cc_get_base_addr();
  35. if (base == FDT_ADDR_T_NONE)
  36. return FDT_ADDR_T_NONE;
  37. config = readl((volatile u32 *)base + L2_CACHE_CONFIG);
  38. ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT;
  39. enable = (volatile u32 *)(base + L2_CACHE_ENABLE);
  40. /* memory barrier */
  41. mb();
  42. #if CONFIG_IS_ENABLED(SIFIVE_FU540_L2CC_WAYENABLE_DIY)
  43. if (CONFIG_SIFIVE_FU540_L2CC_WAYENABLE_DIY_NUM >= ways)
  44. (*enable) = ways;
  45. (*enable) = CONFIG_SIFIVE_FU540_L2CC_WAYENABLE_DIY_NUM;
  46. #else
  47. (*enable) = ways - 1;
  48. #endif //SIFIVE_FU540_L2CC_WAYENABLE_DIY
  49. /* memory barrier */
  50. mb();
  51. return 0;
  52. }
  53. u32 cache_enable_ways_debug(u32 ways_input)
  54. {
  55. fdt_addr_t base = l2cc_get_base_addr();
  56. volatile u32 *enable = (volatile u32 *)(base + L2_CACHE_ENABLE);
  57. if (base == FDT_ADDR_T_NONE)
  58. return 0xffffffff;
  59. printf("cache config(0x%p): 0x%x --> ", enable, readl(enable));
  60. mb();
  61. (*enable) = ways_input;
  62. mb();
  63. printf("0x%x \n", readl(enable));
  64. mb();
  65. return readl(enable);
  66. }
  67. #if CONFIG_IS_ENABLED(SIFIVE_FU540_L2CC_FLUSH)
  68. #define L2_CACHE_FLUSH64 0x200
  69. void flush_dcache_range(unsigned long start, unsigned long end)
  70. {
  71. fdt_addr_t base;
  72. unsigned long line;
  73. volatile unsigned long *flush64;
  74. /* make sure the address is in the range */
  75. if(start > end ||
  76. start < CONFIG_SIFIVE_FU540_L2CC_FLUSH_START ||
  77. end > (CONFIG_SIFIVE_FU540_L2CC_FLUSH_START +
  78. CONFIG_SIFIVE_FU540_L2CC_FLUSH_SIZE))
  79. return;
  80. base = l2cc_get_base_addr();
  81. if (base == FDT_ADDR_T_NONE)
  82. return;
  83. flush64 = (volatile unsigned long *)(base + L2_CACHE_FLUSH64);
  84. /* memory barrier */
  85. mb();
  86. for (line = start; line < end; line += CONFIG_SYS_CACHELINE_SIZE)
  87. (*flush64) = line;
  88. /* memory barrier */
  89. mb();
  90. return;
  91. }
  92. #endif //SIFIVE_FU540_L2CC_FLUSH