dsu.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (c) 2024, Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <arch.h>
  8. #include <arch_helpers.h>
  9. #include <common/bl_common.h>
  10. #include <common/debug.h>
  11. #include <drivers/arm/css/dsu.h>
  12. #include <plat/arm/common/plat_arm.h>
  13. #include <plat/common/platform.h>
  14. /*
  15. * Context structure that saves the state of DSU PMU registers
  16. */
  17. cluster_pmu_state_t cluster_pmu_context[PLAT_ARM_CLUSTER_COUNT];
  18. /****************************************************************************
  19. * This function, save_dsu_pmu_state, is designed to save the
  20. * current state of the Performance Monitoring Unit (PMU) for a cluster.
  21. *
  22. * The function performs the following operations:
  23. * 1. Saves the current values of several PMU registers
  24. * (CLUSTERPMCR_EL1, CLUSTERPMCNTENSET_EL1, CLUSTERPMCCNTR_EL1,
  25. * CLUSTERPMOVSSET_EL1, and CLUSTERPMSELR_EL1) into the cluster_pmu_state
  26. * structure.
  27. *
  28. * 2. Disables the PMU event counting by
  29. * clearing the E bit in the clusterpmcr_el1 register.
  30. *
  31. * 3. Iterates over the available PMU counters as
  32. * determined by the read_cluster_eventctr_num() function.
  33. * For each counter, it:
  34. * a. Selects the counter by writing its index to CLUSTERPMSELR_EL1.
  35. * b. Reads the current counter value (event count) and
  36. * the event type being counted from CLUSTERPMXEVCNTR_EL1 and
  37. * CLUSTERPMXEVTYPER_EL1 registers, respectively.
  38. *
  39. * This function is useful for preserving the DynamIQ Shared Unit's (DSU)
  40. * PMU registers over a power cycle.
  41. ***************************************************************************/
  42. void save_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_state)
  43. {
  44. unsigned int idx = 0U;
  45. unsigned int cluster_eventctr_num = read_cluster_eventctr_num();
  46. assert(cluster_pmu_state != 0);
  47. save_pmu_reg(cluster_pmu_state, clusterpmcr);
  48. write_clusterpmcr(cluster_pmu_state->clusterpmcr &
  49. ~(CLUSTERPMCR_E_BIT));
  50. save_pmu_reg(cluster_pmu_state, clusterpmcntenset);
  51. save_pmu_reg(cluster_pmu_state, clusterpmccntr);
  52. save_pmu_reg(cluster_pmu_state, clusterpmovsset);
  53. save_pmu_reg(cluster_pmu_state, clusterpmselr);
  54. for (idx = 0U ; idx < cluster_eventctr_num ; idx++) {
  55. write_clusterpmselr(idx);
  56. cluster_pmu_state->counter_val[idx] = read_clusterpmxevcntr();
  57. cluster_pmu_state->counter_type[idx] = read_clusterpmxevtyper();
  58. }
  59. }
  60. void cluster_off_dsu_pmu_context_save(void)
  61. {
  62. unsigned int cluster_pos;
  63. cluster_pos = (unsigned int) plat_cluster_id_by_mpidr(read_mpidr_el1());
  64. save_dsu_pmu_state(&cluster_pmu_context[cluster_pos]);
  65. }
  66. /*****************************************************************************
  67. * This function, restore_dsu_pmu_state, restores the state of the
  68. * Performance Monitoring Unit (PMU) from a previously saved state.
  69. *
  70. * The function performs the following operations:
  71. * 1. Restores the CLUSTERPMCR_EL1 register with the
  72. * saved value from the cluster_pmu_state structure.
  73. * 2. Iterates over the available PMU counters as determined
  74. * by the read_cluster_eventctr_num() function. For each counter, it:
  75. * a. Selects the counter by writing its index to CLUSTERPMSELR_EL1.
  76. * b. Restores the counter value (event count) and the event type to
  77. * CLUSTERPMXEVCNTR_EL1 and CLUSTERPMXEVTYPER_EL1 registers, respectively
  78. * 3. Restores several other PMU registers (CLUSTERPMSELR_EL1,
  79. * CLUSTERPMOVSCLR_EL1, CLUSTERPMOVSSET_EL1, CLUSTERPMCCNTR_EL1,
  80. * and CLUSTERPMCNTENSET_EL1) with their saved values.
  81. *
  82. *****************************************************************************/
  83. void restore_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_state)
  84. {
  85. unsigned int idx = 0U;
  86. unsigned int cluster_eventctr_num = read_cluster_eventctr_num();
  87. assert(cluster_pmu_state != 0);
  88. for (idx = 0U ; idx < cluster_eventctr_num ; idx++) {
  89. write_clusterpmselr(idx);
  90. write_clusterpmxevcntr(cluster_pmu_state->counter_val[idx]);
  91. write_clusterpmxevtyper(cluster_pmu_state->counter_type[idx]);
  92. }
  93. restore_pmu_reg(cluster_pmu_state, clusterpmselr);
  94. write_clusterpmovsclr(~(uint32_t)cluster_pmu_state->clusterpmovsset);
  95. restore_pmu_reg(cluster_pmu_state, clusterpmovsset);
  96. restore_pmu_reg(cluster_pmu_state, clusterpmccntr);
  97. restore_pmu_reg(cluster_pmu_state, clusterpmcntenset);
  98. write_clusterpmcr(cluster_pmu_state->clusterpmcr);
  99. }
  100. void cluster_on_dsu_pmu_context_restore(void)
  101. {
  102. unsigned int cluster_pos;
  103. cluster_pos = (unsigned int) plat_cluster_id_by_mpidr(read_mpidr_el1());
  104. restore_dsu_pmu_state(&cluster_pmu_context[cluster_pos]);
  105. }