cache-sifive-ccache.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2021 SiFive
  4. */
  5. #include <common.h>
  6. #include <cache.h>
  7. #include <dm.h>
  8. #include <asm/io.h>
  9. #include <dm/device.h>
  10. #include <linux/bitfield.h>
  11. #define SIFIVE_CCACHE_CONFIG 0x000
  12. #define SIFIVE_CCACHE_CONFIG_WAYS GENMASK(15, 8)
  13. #define SIFIVE_CCACHE_WAY_ENABLE 0x008
  14. /* Prefetch */
  15. #define SIFIVE_PREFET_HARD_BASE(hart) ((hart)*0x2000)
  16. /* Prefetch Control Register */
  17. #define SIFIVE_PREFT_EN_MASK BIT(0)
  18. #define SIFIVE_PREFT_CROSS_PAGE_DIS_MASK BIT(1)
  19. #define SIFIVE_PREFT_DIST_MASK GENMASK(7, 2)
  20. #define SIFIVE_PREFT_MAX_ALLOC_DIST_MASK GENMASK(13, 8)
  21. #define SIFIVE_PREFT_LIN_TO_EXP_THRD_MASK GENMASK(19, 14)
  22. #define SIFIVE_PREFT_AGE_OUT_EN_MASK BIT(20)
  23. #define SIFIVE_PREFT_NUM_LDS_AGE_OUT_MASK GENMASK(27, 21)
  24. #define SIFIVE_PREFT_CROSS_PAGE_EN_MASK BIT(28)
  25. /* Prefetch Advanced Control Register */
  26. #define SIFIVE_PREFT_ADV_Q_FULL_THRD GENMASK(3, 0)
  27. #define SIFIVE_PREFT_ADV_HIT_CACHE_THRD GENMASK(8, 4)
  28. #define SIFIVE_PREFT_ADV_HIT_MSHR_THRD GENMASK(12, 9)
  29. #define SIFIVE_PREFT_ADV_WINDOW_MASK GENMASK(18, 13)
  30. #define SIFIVE_PREFET_HARD_MASK 0x1e
  31. #define SIFIVE_MAX_HART_ID 0x20
  32. #define SIFIVE_PREFT_DIST_VAL 0x3
  33. #define SIFIVE_PREFT_DIST_MAX 0x3f
  34. #define SIFIVE_PREFT_EN 0x1
  35. struct sifive_ccache {
  36. void __iomem *base;
  37. void __iomem *pre_base;
  38. u32 pre_hart_mask;
  39. u32 pre_dist_size;
  40. };
  41. static int sifive_prefetcher_parse(struct udevice *dev)
  42. {
  43. struct sifive_ccache *priv = dev_get_priv(dev);
  44. if (!priv->pre_base)
  45. return -EINVAL;
  46. if (!dev_read_bool(dev, "prefetch-enable"))
  47. return -ENOENT;
  48. priv->pre_hart_mask = dev_read_u32_default(dev, "prefetch-hart-mask",
  49. SIFIVE_PREFET_HARD_MASK);
  50. priv->pre_dist_size = dev_read_u32_default(dev, "prefetch-dist-size",
  51. SIFIVE_PREFT_DIST_VAL);
  52. return 0;
  53. }
  54. static void sifive_prefetcher_cfg_by_id(struct udevice *dev, u32 hart)
  55. {
  56. struct sifive_ccache *priv = dev_get_priv(dev);
  57. void __iomem *reg;
  58. u32 val;
  59. /* Prefetch Control Register */
  60. reg = priv->pre_base + SIFIVE_PREFET_HARD_BASE(hart);
  61. val = readl(reg);
  62. val &= ~SIFIVE_PREFT_MAX_ALLOC_DIST_MASK;
  63. val |= SIFIVE_PREFT_DIST_MAX << __ffs(SIFIVE_PREFT_MAX_ALLOC_DIST_MASK);
  64. writel(val, reg);
  65. val = readl(reg);
  66. val &= ~SIFIVE_PREFT_DIST_MASK;
  67. val |= priv->pre_dist_size << __ffs(SIFIVE_PREFT_DIST_MASK);
  68. writel(val, reg);
  69. val |= SIFIVE_PREFT_EN << __ffs(SIFIVE_PREFT_EN_MASK);
  70. writel(val, reg);
  71. }
  72. static int sifive_prefetcher_enable(struct udevice *dev)
  73. {
  74. struct sifive_ccache *priv = dev_get_priv(dev);
  75. u32 hart;
  76. int ret;
  77. ret = sifive_prefetcher_parse(dev);
  78. if (ret)
  79. return ret;
  80. for (hart = 0; hart < SIFIVE_MAX_HART_ID; hart++) {
  81. if (BIT(hart) & priv->pre_hart_mask)
  82. sifive_prefetcher_cfg_by_id(dev, hart);
  83. }
  84. return 0;
  85. }
  86. static int sifive_ccache_enable(struct udevice *dev)
  87. {
  88. struct sifive_ccache *priv = dev_get_priv(dev);
  89. u32 config;
  90. u32 ways;
  91. /* Enable all ways of composable cache */
  92. config = readl(priv->base + SIFIVE_CCACHE_CONFIG);
  93. ways = FIELD_GET(SIFIVE_CCACHE_CONFIG_WAYS, config);
  94. writel(ways - 1, priv->base + SIFIVE_CCACHE_WAY_ENABLE);
  95. sifive_prefetcher_enable(dev);
  96. return 0;
  97. }
  98. static int sifive_ccache_get_info(struct udevice *dev, struct cache_info *info)
  99. {
  100. struct sifive_ccache *priv = dev_get_priv(dev);
  101. info->base = (phys_addr_t)priv->base;
  102. return 0;
  103. }
  104. static const struct cache_ops sifive_ccache_ops = {
  105. .enable = sifive_ccache_enable,
  106. .get_info = sifive_ccache_get_info,
  107. };
  108. static int sifive_ccache_probe(struct udevice *dev)
  109. {
  110. struct sifive_ccache *priv = dev_get_priv(dev);
  111. fdt_addr_t addr;
  112. priv->base = dev_read_addr_ptr(dev);
  113. if (!priv->base)
  114. return -EINVAL;
  115. addr = dev_read_addr_name(dev, "prefetcher");
  116. if (addr != FDT_ADDR_T_NONE)
  117. priv->pre_base = (void *)(uintptr_t)addr;
  118. return 0;
  119. }
  120. static const struct udevice_id sifive_ccache_ids[] = {
  121. { .compatible = "sifive,fu540-c000-ccache" },
  122. { .compatible = "sifive,fu740-c000-ccache" },
  123. {}
  124. };
  125. U_BOOT_DRIVER(sifive_ccache) = {
  126. .name = "sifive_ccache",
  127. .id = UCLASS_CACHE,
  128. .of_match = sifive_ccache_ids,
  129. .probe = sifive_ccache_probe,
  130. .priv_auto = sizeof(struct sifive_ccache),
  131. .ops = &sifive_ccache_ops,
  132. };