vg_lite_hal.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /****************************************************************************
  2. *
  3. * The MIT License (MIT)
  4. *
  5. * Copyright (c) 2014 - 2020 Vivante Corporation
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. *
  25. *****************************************************************************/
  26. #include "vg_lite_platform.h"
  27. #include "vg_lite_kernel.h"
  28. #include "vg_lite_hal.h"
  29. #include "vg_lite_hw.h"
  30. #include "vg_lite_os.h"
  31. #if !_BAREMETAL
  32. #include "rtthread.h"
  33. #else
  34. #include "xil_cache.h"
  35. #endif
  36. #if _BAREMETAL
  37. /* The followings should be configured by FPGA. */
  38. static uint32_t registerMemBase = 0x43c80000;
  39. #else
  40. static uint32_t registerMemBase = 0x40240000;
  41. #endif
  42. #define HEAP_NODE_USED 0xABBAF00D
  43. volatile void* contiguousMem = NULL;
  44. uint32_t gpuMemBase = 0;
  45. /* Default heap size is 16MB. */
  46. static int heap_size = MAX_CONTIGUOUS_SIZE;
  47. void vg_lite_init_mem(uint32_t register_mem_base,
  48. uint32_t gpu_mem_base,
  49. volatile void * contiguous_mem_base,
  50. uint32_t contiguous_mem_size)
  51. {
  52. registerMemBase = register_mem_base;
  53. gpuMemBase = gpu_mem_base;
  54. contiguousMem = contiguous_mem_base;
  55. heap_size = contiguous_mem_size;
  56. }
  57. /* Implementation of list. ****************************************/
  58. typedef struct list_head {
  59. struct list_head *next;
  60. struct list_head *prev;
  61. }list_head_t;
  62. #define INIT_LIST_HEAD(entry) \
  63. (entry)->next = (entry);\
  64. (entry)->prev = (entry);
  65. /* Add the list item in front of "head". */
  66. static inline void add_list(list_head_t *to_add, list_head_t *head)
  67. {
  68. /* Link the new item. */
  69. to_add->next = head;
  70. to_add->prev = head->prev;
  71. /* Modify the neighbor. */
  72. head->prev = to_add;
  73. if (to_add->prev != NULL) {
  74. to_add->prev->next = to_add;
  75. }
  76. }
  77. /* Remove an entry out of the list. */
  78. static inline void delete_list(list_head_t *entry)
  79. {
  80. if (entry->prev != NULL) {
  81. entry->prev->next = entry->next;
  82. }
  83. if (entry->next != NULL) {
  84. entry->next->prev = entry->prev;
  85. }
  86. }
  87. /* End of list implementation. ***********/
  88. static inline void _memset(void *mem, unsigned char value, int size)
  89. {
  90. int i;
  91. for (i = 0; i < size; i++) {
  92. ((unsigned char*)mem)[i] = value;
  93. }
  94. }
  95. typedef struct heap_node {
  96. list_head_t list; /* TODO: Linux specific, needs to rewrite. */
  97. uint32_t offset;
  98. unsigned long size;
  99. uint32_t status;
  100. }heap_node_t;
  101. struct memory_heap {
  102. uint32_t free;
  103. list_head_t list;
  104. };
  105. struct mapped_memory {
  106. void * logical;
  107. uint32_t physical;
  108. int page_count;
  109. struct page ** pages;
  110. };
  111. struct vg_lite_device {
  112. /* void * gpu; */
  113. uint32_t gpu; /* Always use physical for register access in RTOS. */
  114. /* struct page * pages; */
  115. volatile void * contiguous;
  116. unsigned int order;
  117. unsigned int heap_size;
  118. void * virtual;
  119. uint32_t physical;
  120. uint32_t size;
  121. struct memory_heap heap;
  122. int irq_enabled;
  123. #if defined(VG_DRIVER_SINGLE_THREAD)
  124. volatile uint32_t int_flags;
  125. #if _BAREMETAL
  126. /* wait_queue_head_t int_queue; */
  127. xSemaphoreHandle int_queue;
  128. #else
  129. /* wait_queue_head_t int_queue; */
  130. rt_sem_t int_queue;
  131. #endif
  132. #endif /* VG_DRIVER_SINGLE_THREAD */
  133. void * device;
  134. int registered;
  135. int major;
  136. struct class * class;
  137. int created;
  138. };
  139. struct client_data {
  140. struct vg_lite_device * device;
  141. struct vm_area_struct * vm;
  142. void * contiguous_mapped;
  143. };
  144. static struct vg_lite_device Device, * device;
  145. void vg_lite_hal_delay(uint32_t ms)
  146. {
  147. vg_lite_os_sleep(ms);
  148. }
  149. void vg_lite_hal_barrier(void)
  150. {
  151. /*Memory barrier. */
  152. #if _BAREMETAL
  153. Xil_DCacheFlush();
  154. #else
  155. __asm("DSB");
  156. #endif
  157. }
  158. static int vg_lite_init(void);
  159. vg_lite_error_t vg_lite_hal_initialize(void)
  160. {
  161. int32_t error = VG_LITE_SUCCESS;
  162. /* TODO: Turn on the power. */
  163. vg_lite_init();
  164. /* TODO: Turn on the clock. */
  165. error = vg_lite_os_initialize();
  166. return (vg_lite_error_t)error;
  167. }
  168. void vg_lite_hal_deinitialize(void)
  169. {
  170. /* TODO: Remove clock. */
  171. vg_lite_os_deinitialize();
  172. /* TODO: Remove power. */
  173. }
  174. static int split_node(heap_node_t * node, unsigned long size)
  175. {
  176. /* TODO: the original is linux specific list based, needs rewrite.
  177. */
  178. heap_node_t * split;
  179. /*
  180. * If the newly allocated object fits exactly the size of the free
  181. * node, there is no need to split.
  182. */
  183. if (node->size - size == 0)
  184. return 0;
  185. /* Allocate a new node. */
  186. split = (heap_node_t *)vg_lite_os_malloc(sizeof(heap_node_t));
  187. if (split == NULL)
  188. return -1;
  189. /* Fill in the data of this node of the remaning size. */
  190. split->offset = node->offset + size;
  191. split->size = node->size - size;
  192. split->status = 0;
  193. /* Add the new node behind the current node. */
  194. add_list(&split->list, &node->list);
  195. /* Adjust the size of the current node. */
  196. node->size = size;
  197. return 0;
  198. }
  199. vg_lite_error_t vg_lite_hal_allocate_contiguous(unsigned long size, void ** logical, uint32_t * physical,void ** node)
  200. {
  201. unsigned long aligned_size;
  202. heap_node_t * pos;
  203. /* Align the size to 64 bytes. */
  204. aligned_size = (size + 63) & ~63;
  205. /* Check if there is enough free memory available. */
  206. if (aligned_size > device->heap.free) {
  207. return VG_LITE_OUT_OF_MEMORY;
  208. }
  209. /* Walk the heap backwards. */
  210. for (pos = (heap_node_t*)device->heap.list.prev;
  211. &pos->list != &device->heap.list;
  212. pos = (heap_node_t*) pos->list.prev) {
  213. /* Check if the current node is free and is big enough. */
  214. if (pos->status == 0 && pos->size >= aligned_size) {
  215. /* See if we the current node is big enough to split. */
  216. if (0 != split_node(pos, aligned_size))
  217. {
  218. return VG_LITE_OUT_OF_RESOURCES;
  219. }
  220. /* Mark the current node as used. */
  221. pos->status = HEAP_NODE_USED;
  222. /* Return the logical/physical address. */
  223. /* *logical = (uint8_t *) private_data->contiguous_mapped + pos->offset; */
  224. *logical = (uint8_t *)device->virtual + pos->offset;
  225. *physical = gpuMemBase + (uint32_t)(*logical);/* device->physical + pos->offset; */
  226. device->heap.free -= aligned_size;
  227. *node = pos;
  228. return VG_LITE_SUCCESS;
  229. }
  230. }
  231. /* Out of memory. */
  232. return VG_LITE_OUT_OF_MEMORY;
  233. }
  234. void vg_lite_hal_free_contiguous(void * memory_handle)
  235. {
  236. /* TODO: no list available in RTOS. */
  237. heap_node_t * pos, * node;
  238. /* Get pointer to node. */
  239. node = memory_handle;
  240. if (node->status != HEAP_NODE_USED) {
  241. return;
  242. }
  243. /* Mark node as free. */
  244. node->status = 0;
  245. /* Add node size to free count. */
  246. device->heap.free += node->size;
  247. /* Check if next node is free. */
  248. pos = node;
  249. for (pos = (heap_node_t *)pos->list.next;
  250. &pos->list != &device->heap.list;
  251. pos = (heap_node_t *)pos->list.next) {
  252. if (pos->status == 0) {
  253. /* Merge the nodes. */
  254. node->size += pos->size;
  255. if(node->offset > pos->offset)
  256. node->offset = pos->offset;
  257. /* Delete the next node from the list. */
  258. delete_list(&pos->list);
  259. vg_lite_os_free(pos);
  260. }
  261. break;
  262. }
  263. /* Check if the previous node is free. */
  264. pos = node;
  265. for (pos = (heap_node_t *)pos->list.prev;
  266. &pos->list != &device->heap.list;
  267. pos = (heap_node_t *)pos->list.prev) {
  268. if (pos->status == 0) {
  269. /* Merge the nodes. */
  270. pos->size += node->size;
  271. if(pos->offset > node->offset)
  272. pos->offset = node->offset;
  273. /* Delete the current node from the list. */
  274. delete_list(&node->list);
  275. vg_lite_os_free(node);
  276. }
  277. break;
  278. }
  279. /* when release command buffer node and ts buffer node to exit,release the linked list*/
  280. if(device->heap.list.next == device->heap.list.prev) {
  281. delete_list(&pos->list);
  282. vg_lite_os_free(pos);
  283. }
  284. }
  285. void vg_lite_hal_free_os_heap(void)
  286. {
  287. struct heap_node *pos, *n;
  288. /* Check for valid device. */
  289. if (device != NULL) {
  290. /* Process each node. */
  291. for (pos = (heap_node_t *)device->heap.list.next,
  292. n = (heap_node_t *)pos->list.next;
  293. &pos->list != &device->heap.list;
  294. pos = n, n = (heap_node_t *)n->list.next) {
  295. /* Remove it from the linked list. */
  296. delete_list(&pos->list);
  297. /* Free up the memory. */
  298. vg_lite_os_free(pos);
  299. }
  300. }
  301. }
  302. /* Portable: read register value. */
  303. uint32_t vg_lite_hal_peek(uint32_t address)
  304. {
  305. /* Read data from the GPU register. */
  306. return (uint32_t) (*(volatile uint32_t *) (device->gpu + address));
  307. }
  308. /* Portable: write register. */
  309. void vg_lite_hal_poke(uint32_t address, uint32_t data)
  310. {
  311. /* Write data to the GPU register. */
  312. uint32_t *LocalAddr = (uint32_t *)(device->gpu + address);
  313. *LocalAddr = data;
  314. }
  315. vg_lite_error_t vg_lite_hal_query_mem(vg_lite_kernel_mem_t *mem)
  316. {
  317. if(device != NULL){
  318. mem->bytes = device->heap.free;
  319. return VG_LITE_SUCCESS;
  320. }
  321. mem->bytes = 0;
  322. return VG_LITE_NO_CONTEXT;
  323. }
  324. void vg_lite_IRQHandler(void)
  325. {
  326. vg_lite_os_IRQHandler();
  327. }
  328. int32_t vg_lite_hal_wait_interrupt(uint32_t timeout, uint32_t mask, uint32_t * value)
  329. {
  330. return vg_lite_os_wait_interrupt(timeout,mask,value);
  331. }
  332. void * vg_lite_hal_map(unsigned long bytes, void * logical, uint32_t physical, uint32_t * gpu)
  333. {
  334. (void) bytes;
  335. (void) logical;
  336. (void) physical;
  337. (void) gpu;
  338. return (void *)0;
  339. }
  340. void vg_lite_hal_unmap(void * handle)
  341. {
  342. (void) handle;
  343. }
  344. #if !defined(VG_DRIVER_SINGLE_THREAD)
  345. vg_lite_error_t vg_lite_hal_submit(uint32_t context,uint32_t physical, uint32_t offset, uint32_t size, vg_lite_os_async_event_t *event)
  346. {
  347. return (vg_lite_error_t)vg_lite_os_submit(context,physical,offset,size,event);
  348. }
  349. vg_lite_error_t vg_lite_hal_wait(uint32_t timeout, vg_lite_os_async_event_t *event)
  350. {
  351. return (vg_lite_error_t)vg_lite_os_wait(timeout,event);
  352. }
  353. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  354. static void vg_lite_exit(void)
  355. {
  356. heap_node_t * pos;
  357. heap_node_t * n;
  358. /* Check for valid device. */
  359. if (device != NULL) {
  360. /* TODO: unmap register mem should be unnecessary. */
  361. device->gpu = 0;
  362. /* Process each node. */
  363. for (pos = (heap_node_t *)device->heap.list.next, n = (heap_node_t *)pos->list.next;
  364. &pos->list != &device->heap.list;
  365. pos = n, n = (heap_node_t *)n->list.next) {
  366. /* Remove it from the linked list. */
  367. delete_list(&pos->list);
  368. /* Free up the memory. */
  369. vg_lite_os_free(pos);
  370. }
  371. /* Free up the device structure. */
  372. vg_lite_os_free(device);
  373. }
  374. }
  375. static int vg_lite_init(void)
  376. {
  377. heap_node_t * node;
  378. /* Initialize memory and objects ***************************************/
  379. /* Create device structure. */
  380. device = &Device;
  381. /* Zero out the enture structure. */
  382. _memset(device, 0, sizeof(struct vg_lite_device));
  383. /* Setup register memory. **********************************************/
  384. device->gpu = registerMemBase;
  385. /* Initialize contiguous memory. ***************************************/
  386. /* Allocate the contiguous memory. */
  387. device->heap_size = heap_size;
  388. device->contiguous = (volatile void *)contiguousMem;
  389. _memset((void *)device->contiguous, 0, heap_size);
  390. /* Make 64byte aligned. */
  391. while ((((uint32_t)device->contiguous) & 63) != 0)
  392. {
  393. device->contiguous = ((unsigned char*) device->contiguous) + 4;
  394. device->heap_size -= 4;
  395. }
  396. /* Check if we allocated any contiguous memory or not. */
  397. if (device->contiguous == NULL) {
  398. vg_lite_exit();
  399. return -1;
  400. }
  401. device->virtual = (void *)device->contiguous;
  402. device->physical = gpuMemBase + (uint32_t)device->virtual;
  403. device->size = device->heap_size;
  404. /* Create the heap. */
  405. INIT_LIST_HEAD(&device->heap.list);
  406. device->heap.free = device->size;
  407. node = (heap_node_t *)vg_lite_os_malloc(sizeof(heap_node_t));
  408. if (node == NULL) {
  409. vg_lite_exit();
  410. return -1;
  411. }
  412. node->offset = 0;
  413. node->size = device->size;
  414. node->status = 0;
  415. add_list(&node->list, &device->heap.list);
  416. #if defined(VG_DRIVER_SINGLE_THREAD)
  417. #if !_BAREMETAL /*for rt500*/
  418. device->int_queue = rt_sem_create("diq", 0, RT_IPC_FLAG_PRIO);
  419. device->int_flags = 0;
  420. #endif
  421. #endif /* VG_DRIVER_SINGLE_THREAD */
  422. /* Success. */
  423. return 0;
  424. }