wm_psram.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include <string.h>
  2. #include "wm_regs.h"
  3. #include "wm_psram.h"
  4. #include "wm_dma.h"
  5. /* Nonzero if either X or Y is not aligned on a "long" boundary. */
  6. #define UNALIGNED(X, Y) \
  7. (((uint32_t)X & (sizeof (uint32_t) - 1)) | ((uint32_t)Y & (sizeof (uint32_t) - 1)))
  8. /* How many bytes are copied each iteration of the 4X unrolled loop. */
  9. #define BIGBLOCKSIZE (sizeof (uint32_t) << 2)
  10. /* Threshhold for punting to the byte copier. */
  11. #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
  12. static volatile uint32_t dma_rx_tx_done = 0;
  13. static uint32_t psram_channel = 0;
  14. static void wm_psram_dma_go(uint8_t ch)
  15. {
  16. DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_ON;
  17. dma_rx_tx_done = 0;
  18. }
  19. static void wm_psram_dma_stop(uint8_t ch)
  20. {
  21. if(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON)
  22. {
  23. DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_OFF;
  24. while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON);
  25. }
  26. }
  27. static void wm_psram_dma_init(uint8_t ch, uint32_t count, void * src, void *dst)
  28. {
  29. DMA_INTMASK_REG &= ~(0x02<<(ch*2));
  30. DMA_SRCADDR_REG(ch) = (uint32_t)src;
  31. DMA_DESTADDR_REG(ch) = (uint32_t)dst;
  32. DMA_CTRL_REG(ch) = DMA_CTRL_SRC_ADDR_INC|DMA_CTRL_DEST_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | DMA_CTRL_BURST_SIZE1;
  33. DMA_MODE_REG(ch) = 0;
  34. DMA_CTRL_REG(ch) &= ~0xFFFF00;
  35. DMA_CTRL_REG(ch) |= (count<<8);
  36. }
  37. void psram_DMA_Channel0_IRQHandler()
  38. {
  39. tls_reg_write32(HR_DMA_INT_SRC, 0x02);
  40. dma_rx_tx_done += 1;
  41. }
  42. void psram_init(psram_mode_t mode)
  43. {
  44. volatile unsigned int value = 0x600;
  45. value |= 2<<4;
  46. if(mode == PSRAM_QPI)
  47. {
  48. value |= 0x03;
  49. }
  50. /*reset psram*/
  51. value |= 0x01;
  52. tls_reg_write32(HR_PSRAM_CTRL_ADDR, value);
  53. do{
  54. value = tls_reg_read32(HR_PSRAM_CTRL_ADDR);
  55. }while(value&0x01);
  56. psram_channel = tls_dma_request(0, 0);
  57. tls_dma_irq_register(psram_channel, psram_DMA_Channel0_IRQHandler, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
  58. }
  59. int memcpy_dma(unsigned char *dst, unsigned char *src, int num)
  60. {
  61. int offset = 0;
  62. unsigned char *psram_access_start = src;
  63. int left_bytes = num&0x03;
  64. int dw_length = (num&(~0x03))>>2;
  65. if (!TOO_SMALL(num) && !UNALIGNED (src, dst))
  66. {
  67. if(dw_length)
  68. {
  69. wm_psram_dma_stop(psram_channel);
  70. wm_psram_dma_init(psram_channel, dw_length*4, src,dst);
  71. wm_psram_dma_go(psram_channel);
  72. while(dma_rx_tx_done == 0);
  73. offset += dw_length *4;
  74. psram_access_start += dw_length *4;
  75. }
  76. else
  77. {
  78. while(dw_length--)
  79. {
  80. M32((dst+offset)) = M32(psram_access_start);
  81. psram_access_start += 4;
  82. offset+=4;
  83. }
  84. }
  85. while(left_bytes--)
  86. {
  87. M8((dst+offset)) = M8(psram_access_start);
  88. psram_access_start += 1;
  89. offset+=1;
  90. }
  91. }
  92. else
  93. {
  94. while (num--)
  95. {
  96. M8(dst++) = M8(psram_access_start++);
  97. offset++;
  98. }
  99. }
  100. return offset;
  101. }