mali_dma.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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_kernel_common.h"
  11. #include "mali_osk.h"
  12. #include "mali_hw_core.h"
  13. #include "mali_dma.h"
  14. /**
  15. * Size of the Mali-450 DMA unit registers in bytes.
  16. */
  17. #define MALI450_DMA_REG_SIZE 0x08
  18. /**
  19. * Value that appears in MEMSIZE if an error occurs when reading the command list.
  20. */
  21. #define MALI450_DMA_BUS_ERR_VAL 0xffffffff
  22. /**
  23. * Mali DMA registers
  24. * Used in the register read/write routines.
  25. * See the hardware documentation for more information about each register.
  26. */
  27. typedef enum mali_dma_register {
  28. MALI450_DMA_REG_SOURCE_ADDRESS = 0x0000,
  29. MALI450_DMA_REG_SOURCE_SIZE = 0x0004,
  30. } mali_dma_register;
  31. struct mali_dma_core {
  32. struct mali_hw_core hw_core; /**< Common for all HW cores */
  33. _mali_osk_spinlock_t *lock; /**< Lock protecting access to DMA core */
  34. mali_dma_pool pool; /**< Memory pool for command buffers */
  35. };
  36. static struct mali_dma_core *mali_global_dma_core = NULL;
  37. struct mali_dma_core *mali_dma_create(_mali_osk_resource_t *resource)
  38. {
  39. struct mali_dma_core* dma;
  40. _mali_osk_errcode_t err;
  41. MALI_DEBUG_ASSERT(NULL == mali_global_dma_core);
  42. dma = _mali_osk_malloc(sizeof(struct mali_dma_core));
  43. if (dma == NULL) goto alloc_failed;
  44. dma->lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_DMA_COMMAND);
  45. if (NULL == dma->lock) goto lock_init_failed;
  46. dma->pool = mali_dma_pool_create(MALI_DMA_CMD_BUF_SIZE, 4, 0);
  47. if (NULL == dma->pool) goto dma_pool_failed;
  48. err = mali_hw_core_create(&dma->hw_core, resource, MALI450_DMA_REG_SIZE);
  49. if (_MALI_OSK_ERR_OK != err) goto hw_core_failed;
  50. mali_global_dma_core = dma;
  51. MALI_DEBUG_PRINT(2, ("Mali DMA: Created Mali APB DMA unit\n"));
  52. return dma;
  53. /* Error handling */
  54. hw_core_failed:
  55. mali_dma_pool_destroy(dma->pool);
  56. dma_pool_failed:
  57. _mali_osk_spinlock_term(dma->lock);
  58. lock_init_failed:
  59. _mali_osk_free(dma);
  60. alloc_failed:
  61. MALI_DEBUG_PRINT(2, ("Mali DMA: Failed to create APB DMA unit\n"));
  62. return NULL;
  63. }
  64. void mali_dma_delete(struct mali_dma_core *dma)
  65. {
  66. MALI_DEBUG_ASSERT_POINTER(dma);
  67. MALI_DEBUG_PRINT(2, ("Mali DMA: Deleted Mali APB DMA unit\n"));
  68. mali_hw_core_delete(&dma->hw_core);
  69. _mali_osk_spinlock_term(dma->lock);
  70. mali_dma_pool_destroy(dma->pool);
  71. _mali_osk_free(dma);
  72. }
  73. static void mali_dma_bus_error(struct mali_dma_core *dma)
  74. {
  75. u32 addr = mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS);
  76. MALI_PRINT_ERROR(("Mali DMA: Bus error when reading command list from 0x%lx\n", addr));
  77. /* Clear the bus error */
  78. mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE, 0);
  79. }
  80. static mali_bool mali_dma_is_busy(struct mali_dma_core *dma)
  81. {
  82. u32 val;
  83. mali_bool dma_busy_flag = MALI_FALSE;
  84. MALI_DEBUG_ASSERT_POINTER(dma);
  85. val = mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE);
  86. if (MALI450_DMA_BUS_ERR_VAL == val) {
  87. /* Bus error reading command list */
  88. mali_dma_bus_error(dma);
  89. return MALI_FALSE;
  90. }
  91. if (val > 0) {
  92. dma_busy_flag = MALI_TRUE;
  93. }
  94. return dma_busy_flag;
  95. }
  96. static void mali_dma_start_transfer(struct mali_dma_core* dma, mali_dma_cmd_buf *buf)
  97. {
  98. u32 memsize = buf->size * 4;
  99. u32 addr = buf->phys_addr;
  100. MALI_DEBUG_ASSERT_POINTER(dma);
  101. MALI_DEBUG_ASSERT(memsize < (1 << 16));
  102. MALI_DEBUG_ASSERT(0 == (memsize & 0x3)); /* 4 byte aligned */
  103. MALI_DEBUG_ASSERT(!mali_dma_is_busy(dma));
  104. /* Writes the physical source memory address of chunk containing command headers and data */
  105. mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS, addr);
  106. /* Writes the length of transfer */
  107. mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE, memsize);
  108. }
  109. _mali_osk_errcode_t mali_dma_get_cmd_buf(mali_dma_cmd_buf *buf)
  110. {
  111. MALI_DEBUG_ASSERT_POINTER(buf);
  112. buf->virt_addr = (u32*)mali_dma_pool_alloc(mali_global_dma_core->pool, &buf->phys_addr);
  113. if (NULL == buf->virt_addr) {
  114. return _MALI_OSK_ERR_NOMEM;
  115. }
  116. /* size contains the number of words in the buffer and is incremented
  117. * as commands are added to the buffer. */
  118. buf->size = 0;
  119. return _MALI_OSK_ERR_OK;
  120. }
  121. void mali_dma_put_cmd_buf(mali_dma_cmd_buf *buf)
  122. {
  123. MALI_DEBUG_ASSERT_POINTER(buf);
  124. if (NULL == buf->virt_addr) return;
  125. mali_dma_pool_free(mali_global_dma_core->pool, buf->virt_addr, buf->phys_addr);
  126. buf->virt_addr = NULL;
  127. }
  128. _mali_osk_errcode_t mali_dma_start(struct mali_dma_core* dma, mali_dma_cmd_buf *buf)
  129. {
  130. _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
  131. _mali_osk_spinlock_lock(dma->lock);
  132. if (mali_dma_is_busy(dma)) {
  133. err = _MALI_OSK_ERR_BUSY;
  134. goto out;
  135. }
  136. mali_dma_start_transfer(dma, buf);
  137. out:
  138. _mali_osk_spinlock_unlock(dma->lock);
  139. return err;
  140. }
  141. void mali_dma_debug(struct mali_dma_core *dma)
  142. {
  143. MALI_DEBUG_ASSERT_POINTER(dma);
  144. MALI_DEBUG_PRINT(1, ("DMA unit registers:\n\t%08x, %08x\n",
  145. mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS),
  146. mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE)
  147. ));
  148. }
  149. struct mali_dma_core *mali_dma_get_global_dma_core(void)
  150. {
  151. /* Returns the global dma core object */
  152. return mali_global_dma_core;
  153. }