mcsi.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <arch.h>
  7. #include <arch_helpers.h>
  8. #include <assert.h>
  9. #include <common/debug.h>
  10. #include <lib/mmio.h>
  11. #include <scu.h>
  12. #include <mcucfg.h>
  13. #include <drivers/delay_timer.h>
  14. #include <mcsi/mcsi.h>
  15. #define MAX_CLUSTERS 5
  16. static unsigned long cci_base_addr;
  17. static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS];
  18. void mcsi_init(unsigned long cci_base,
  19. unsigned int num_cci_masters)
  20. {
  21. int i;
  22. assert(cci_base);
  23. assert(num_cci_masters < MAX_CLUSTERS);
  24. cci_base_addr = cci_base;
  25. for (i = 0; i < num_cci_masters; i++)
  26. cci_cluster_ix_to_iface[i] = SLAVE_IFACE_OFFSET(i);
  27. }
  28. void mcsi_cache_flush(void)
  29. {
  30. /* timeout is 10ms */
  31. int timeout = 10000;
  32. /* to make flush by SF safe, need to disable BIU DCM */
  33. mmio_clrbits_32(CCI_CLK_CTRL, 1 << 8);
  34. mmio_write_32(cci_base_addr + FLUSH_SF, 0x1);
  35. for (; timeout; timeout--, udelay(1)) {
  36. if ((mmio_read_32(cci_base_addr + FLUSH_SF) & 0x1) == 0x0)
  37. break;
  38. }
  39. if (!timeout) {
  40. INFO("SF lush timeout\n");
  41. return;
  42. }
  43. /* enable BIU DCM as it was */
  44. mmio_setbits_32(CCI_CLK_CTRL, 1 << 8);
  45. }
  46. static inline unsigned long get_slave_iface_base(unsigned long mpidr)
  47. {
  48. /*
  49. * We assume the TF topology code allocates affinity instances
  50. * consecutively from zero.
  51. * It is a programming error if this is called without initializing
  52. * the slave interface to use for this cluster.
  53. */
  54. unsigned int cluster_id =
  55. (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
  56. assert(cluster_id < MAX_CLUSTERS);
  57. assert(cci_cluster_ix_to_iface[cluster_id] != 0);
  58. return cci_base_addr + cci_cluster_ix_to_iface[cluster_id];
  59. }
  60. void cci_enable_cluster_coherency(unsigned long mpidr)
  61. {
  62. unsigned long slave_base;
  63. unsigned int support_ability;
  64. unsigned int config = 0;
  65. unsigned int pending = 0;
  66. assert(cci_base_addr);
  67. slave_base = get_slave_iface_base(mpidr);
  68. support_ability = mmio_read_32(slave_base);
  69. pending = (mmio_read_32(
  70. cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING;
  71. while (pending) {
  72. pending = (mmio_read_32(
  73. cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING;
  74. }
  75. if (support_ability & SNP_SUPPORT)
  76. config |= SNOOP_EN_BIT;
  77. if (support_ability & DVM_SUPPORT)
  78. config |= DVM_EN_BIT;
  79. mmio_write_32(slave_base, support_ability | config);
  80. /* Wait for the dust to settle down */
  81. while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
  82. ;
  83. }
  84. #if ERRATA_MCSIB_SW
  85. #pragma weak mcsib_sw_workaround_main
  86. #endif
  87. void cci_disable_cluster_coherency(unsigned long mpidr)
  88. {
  89. unsigned long slave_base;
  90. unsigned int config = 0;
  91. assert(cci_base_addr);
  92. slave_base = get_slave_iface_base(mpidr);
  93. while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
  94. ;
  95. config = mmio_read_32(slave_base);
  96. config &= ~(DVM_EN_BIT | SNOOP_EN_BIT);
  97. /* Disable Snoops and DVM messages */
  98. mmio_write_32(slave_base, config);
  99. #if ERRATA_MCSIB_SW
  100. mcsib_sw_workaround_main();
  101. #endif
  102. /* Wait for the dust to settle down */
  103. while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
  104. ;
  105. }
  106. void cci_secure_switch(unsigned int status)
  107. {
  108. unsigned int config;
  109. config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG);
  110. if (status == NS_ACC)
  111. config |= SECURE_ACC_EN;
  112. else
  113. config &= ~SECURE_ACC_EN;
  114. mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config);
  115. }
  116. void cci_pmu_secure_switch(unsigned int status)
  117. {
  118. unsigned int config;
  119. config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG);
  120. if (status == NS_ACC)
  121. config |= PMU_SECURE_ACC_EN;
  122. else
  123. config &= ~PMU_SECURE_ACC_EN;
  124. mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config);
  125. }
  126. void cci_init_sf(void)
  127. {
  128. while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
  129. ;
  130. /* init sf1 */
  131. mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF1_INIT);
  132. while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF1_INIT)
  133. ;
  134. while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF1_INIT_DONE))
  135. ;
  136. /* init sf2 */
  137. mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF2_INIT);
  138. while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF2_INIT)
  139. ;
  140. while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF2_INIT_DONE))
  141. ;
  142. }
  143. void cci_interrupt_en(void)
  144. {
  145. mmio_setbits_32(cci_base_addr + CENTRAL_CTRL_REG, INT_EN);
  146. }
  147. unsigned long cci_reg_access(unsigned int op, unsigned long offset,
  148. unsigned long val)
  149. {
  150. unsigned long ret = 0;
  151. if ((cci_base_addr == 0) || (offset > MSCI_MEMORY_SZ))
  152. panic();
  153. switch (op) {
  154. case MCSI_REG_ACCESS_READ:
  155. ret = mmio_read_32(cci_base_addr + offset);
  156. break;
  157. case MCSI_REG_ACCESS_WRITE:
  158. mmio_write_32(cci_base_addr + offset, val);
  159. dsb();
  160. break;
  161. case MCSI_REG_ACCESS_SET_BITMASK:
  162. mmio_setbits_32(cci_base_addr + offset, val);
  163. dsb();
  164. break;
  165. case MCSI_REG_ACCESS_CLEAR_BITMASK:
  166. mmio_clrbits_32(cci_base_addr + offset, val);
  167. dsb();
  168. break;
  169. default:
  170. break;
  171. }
  172. return ret;
  173. }