starfive_starlink_cache.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Cache Management Operations for StarFive's Starlink cache controller
  4. *
  5. * Copyright (C) 2024 Shanghai StarFive Technology Co., Ltd.
  6. *
  7. * Author: Joshua Yeong <joshua.yeong@starfivetech.com>
  8. */
  9. #include <linux/bitfield.h>
  10. #include <linux/cacheflush.h>
  11. #include <linux/iopoll.h>
  12. #include <linux/of_address.h>
  13. #include <asm/dma-noncoherent.h>
  14. #define STARLINK_CACHE_FLUSH_START_ADDR 0x0
  15. #define STARLINK_CACHE_FLUSH_END_ADDR 0x8
  16. #define STARLINK_CACHE_FLUSH_CTL 0x10
  17. #define STARLINK_CACHE_ALIGN 0x40
  18. #define STARLINK_CACHE_ADDRESS_RANGE_MASK GENMASK(39, 0)
  19. #define STARLINK_CACHE_FLUSH_CTL_MODE_MASK GENMASK(2, 1)
  20. #define STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK BIT(0)
  21. #define STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE 0
  22. #define STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE 1
  23. #define STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED 2
  24. #define STARLINK_CACHE_FLUSH_POLL_DELAY_US 1
  25. #define STARLINK_CACHE_FLUSH_TIMEOUT_US 5000000
  26. static void __iomem *starlink_cache_base;
  27. static void starlink_cache_flush_complete(void)
  28. {
  29. volatile void __iomem *ctl = starlink_cache_base + STARLINK_CACHE_FLUSH_CTL;
  30. u64 v;
  31. int ret;
  32. ret = readq_poll_timeout_atomic(ctl, v, !(v & STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK),
  33. STARLINK_CACHE_FLUSH_POLL_DELAY_US,
  34. STARLINK_CACHE_FLUSH_TIMEOUT_US);
  35. if (ret)
  36. WARN(1, "StarFive Starlink cache flush operation timeout\n");
  37. }
  38. static void starlink_cache_dma_cache_wback(phys_addr_t paddr, unsigned long size)
  39. {
  40. writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
  41. starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
  42. writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
  43. starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
  44. mb();
  45. writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
  46. STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED),
  47. starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
  48. starlink_cache_flush_complete();
  49. }
  50. static void starlink_cache_dma_cache_invalidate(phys_addr_t paddr, unsigned long size)
  51. {
  52. writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
  53. starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
  54. writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
  55. starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
  56. mb();
  57. writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
  58. STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE),
  59. starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
  60. starlink_cache_flush_complete();
  61. }
  62. static void starlink_cache_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size)
  63. {
  64. writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
  65. starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
  66. writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
  67. starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
  68. mb();
  69. writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
  70. STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE),
  71. starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
  72. starlink_cache_flush_complete();
  73. }
  74. static const struct riscv_nonstd_cache_ops starlink_cache_ops = {
  75. .wback = &starlink_cache_dma_cache_wback,
  76. .inv = &starlink_cache_dma_cache_invalidate,
  77. .wback_inv = &starlink_cache_dma_cache_wback_inv,
  78. };
  79. static const struct of_device_id starlink_cache_ids[] = {
  80. { .compatible = "starfive,jh8100-starlink-cache" },
  81. { /* sentinel */ }
  82. };
  83. static int __init starlink_cache_init(void)
  84. {
  85. struct device_node *np;
  86. u32 block_size;
  87. int ret;
  88. np = of_find_matching_node(NULL, starlink_cache_ids);
  89. if (!of_device_is_available(np))
  90. return -ENODEV;
  91. ret = of_property_read_u32(np, "cache-block-size", &block_size);
  92. if (ret)
  93. return ret;
  94. if (block_size % STARLINK_CACHE_ALIGN)
  95. return -EINVAL;
  96. starlink_cache_base = of_iomap(np, 0);
  97. if (!starlink_cache_base)
  98. return -ENOMEM;
  99. riscv_cbom_block_size = block_size;
  100. riscv_noncoherent_supported();
  101. riscv_noncoherent_register_cache_ops(&starlink_cache_ops);
  102. return 0;
  103. }
  104. arch_initcall(starlink_cache_init);