mali_dlbu.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * This confidential and proprietary software may be used only as
  3. * authorised by a licensing agreement from ARM Limited
  4. * (C) COPYRIGHT 2012-2013 ARM Limited
  5. * ALL RIGHTS RESERVED
  6. * The entire notice above must be reproduced on all authorised
  7. * copies and copies may only be made to the extent permitted
  8. * by a licensing agreement from ARM Limited.
  9. */
  10. #include "mali_dlbu.h"
  11. #include "mali_memory.h"
  12. #include "mali_pp.h"
  13. #include "mali_group.h"
  14. #include "mali_osk.h"
  15. #include "mali_hw_core.h"
  16. /**
  17. * Size of DLBU registers in bytes
  18. */
  19. #define MALI_DLBU_SIZE 0x400
  20. u32 mali_dlbu_phys_addr = 0;
  21. static mali_io_address mali_dlbu_cpu_addr = 0;
  22. /**
  23. * DLBU register numbers
  24. * Used in the register read/write routines.
  25. * See the hardware documentation for more information about each register
  26. */
  27. typedef enum mali_dlbu_register {
  28. MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address;
  29. 31:12 Physical address to the page used for the DLBU
  30. 0 DLBU enable - set this bit to 1 enables the AXI bus
  31. between PPs and L2s, setting to 0 disables the router and
  32. no further transactions are sent to DLBU */
  33. MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address;
  34. 31:12 Virtual address to the page used for the DLBU */
  35. MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address;
  36. 31:12 Virtual address to the tile list. This address is used when
  37. calculating the call address sent to PP.*/
  38. MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension;
  39. 23:16 Number of tiles in Y direction-1
  40. 7:0 Number of tiles in X direction-1 */
  41. MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration;
  42. 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024
  43. 21:16 2^n number of tiles to be binned to one tile list in Y direction
  44. 5:0 2^n number of tiles to be binned to one tile list in X direction */
  45. MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions;
  46. 31:24 start position in Y direction for group 1
  47. 23:16 start position in X direction for group 1
  48. 15:8 start position in Y direction for group 0
  49. 7:0 start position in X direction for group 0 */
  50. MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask;
  51. 7 enable PP7 for load balancing
  52. 6 enable PP6 for load balancing
  53. 5 enable PP5 for load balancing
  54. 4 enable PP4 for load balancing
  55. 3 enable PP3 for load balancing
  56. 2 enable PP2 for load balancing
  57. 1 enable PP1 for load balancing
  58. 0 enable PP0 for load balancing */
  59. } mali_dlbu_register;
  60. typedef enum {
  61. PP0ENABLE = 0,
  62. PP1ENABLE,
  63. PP2ENABLE,
  64. PP3ENABLE,
  65. PP4ENABLE,
  66. PP5ENABLE,
  67. PP6ENABLE,
  68. PP7ENABLE
  69. } mali_dlbu_pp_enable;
  70. struct mali_dlbu_core {
  71. struct mali_hw_core hw_core; /**< Common for all HW cores */
  72. u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU
  73. see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */
  74. };
  75. _mali_osk_errcode_t mali_dlbu_initialize(void)
  76. {
  77. MALI_DEBUG_PRINT(2, ("Mali DLBU: Initializing\n"));
  78. if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) {
  79. MALI_SUCCESS;
  80. }
  81. return _MALI_OSK_ERR_FAULT;
  82. }
  83. void mali_dlbu_terminate(void)
  84. {
  85. MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n"));
  86. mali_mmu_release_table_page(mali_dlbu_phys_addr, mali_dlbu_cpu_addr);
  87. }
  88. struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
  89. {
  90. struct mali_dlbu_core *core = NULL;
  91. MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description));
  92. core = _mali_osk_malloc(sizeof(struct mali_dlbu_core));
  93. if (NULL != core) {
  94. if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) {
  95. core->pp_cores_mask = 0;
  96. if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) {
  97. return core;
  98. }
  99. MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description));
  100. mali_hw_core_delete(&core->hw_core);
  101. }
  102. _mali_osk_free(core);
  103. } else {
  104. MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n"));
  105. }
  106. return NULL;
  107. }
  108. void mali_dlbu_delete(struct mali_dlbu_core *dlbu)
  109. {
  110. MALI_DEBUG_ASSERT_POINTER(dlbu);
  111. mali_dlbu_reset(dlbu);
  112. mali_hw_core_delete(&dlbu->hw_core);
  113. _mali_osk_free(dlbu);
  114. }
  115. _mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu)
  116. {
  117. u32 dlbu_registers[7];
  118. _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
  119. MALI_DEBUG_ASSERT_POINTER(dlbu);
  120. MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description));
  121. dlbu_registers[0] = mali_dlbu_phys_addr | 1; /* bit 0 enables the whole core */
  122. dlbu_registers[1] = MALI_DLBU_VIRT_ADDR;
  123. dlbu_registers[2] = 0;
  124. dlbu_registers[3] = 0;
  125. dlbu_registers[4] = 0;
  126. dlbu_registers[5] = 0;
  127. dlbu_registers[6] = dlbu->pp_cores_mask;
  128. /* write reset values to core registers */
  129. mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, dlbu_registers, 7);
  130. err = _MALI_OSK_ERR_OK;
  131. return err;
  132. }
  133. void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu)
  134. {
  135. MALI_DEBUG_ASSERT_POINTER(dlbu);
  136. mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
  137. }
  138. void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
  139. {
  140. struct mali_pp_core *pp_core;
  141. u32 bcast_id;
  142. MALI_DEBUG_ASSERT_POINTER( dlbu );
  143. MALI_DEBUG_ASSERT_POINTER( group );
  144. pp_core = mali_group_get_pp_core(group);
  145. bcast_id = mali_pp_core_get_bcast_id(pp_core);
  146. dlbu->pp_cores_mask |= bcast_id;
  147. MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n", bcast_id , dlbu->pp_cores_mask));
  148. }
  149. /* Remove a group from the DLBU */
  150. void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
  151. {
  152. struct mali_pp_core *pp_core;
  153. u32 bcast_id;
  154. MALI_DEBUG_ASSERT_POINTER( dlbu );
  155. MALI_DEBUG_ASSERT_POINTER( group );
  156. pp_core = mali_group_get_pp_core(group);
  157. bcast_id = mali_pp_core_get_bcast_id(pp_core);
  158. dlbu->pp_cores_mask &= ~bcast_id;
  159. MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", bcast_id, dlbu->pp_cores_mask));
  160. }
  161. /* Configure the DLBU for \a job. This needs to be done before the job is started on the groups in the DLBU. */
  162. void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job)
  163. {
  164. u32 *registers;
  165. MALI_DEBUG_ASSERT(job);
  166. registers = mali_pp_job_get_dlbu_registers(job);
  167. MALI_DEBUG_PRINT(4, ("Mali DLBU: Starting job\n"));
  168. /* Writing 4 registers:
  169. * DLBU registers except the first two (written once at DLBU initialisation / reset) and the PP_ENABLE_MASK register */
  170. mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4);
  171. }