• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <string.h>
17 #include "wm_regs.h"
18 #include "wm_dma.h"
19 #include "wm_psram.h"
20 
21 /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
22 #define UNALIGNED(X, Y) \
23     (((uint32_t)(X) & (sizeof (uint32_t) - 1)) | ((uint32_t)(Y) & (sizeof (uint32_t) - 1)))
24 /* How many bytes are copied each iteration of the 4X unrolled loop.  */
25 #define BIGBLOCKSIZE    (sizeof (uint32_t) << 2)
26 /* Threshhold for punting to the byte copier.  */
27 #define TOO_SMALL(LEN)  ((LEN) < BIGBLOCKSIZE)
28 
29 volatile static uint32_t dma_rx_tx_done = 0;
30 static uint32_t psram_channel = 0;
31 
wm_psram_dma_go(uint8_t ch)32 static void wm_psram_dma_go(uint8_t ch)
33 {
34     DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_ON;
35     dma_rx_tx_done = 0;
36 }
37 
wm_psram_dma_stop(uint8_t ch)38 static void wm_psram_dma_stop(uint8_t ch)
39 {
40     if (DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON) {
41         DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_OFF;
42 
43         while (DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON);
44     }
45 }
46 
wm_psram_dma_init(uint8_t ch,uint32_t count,void * src,void * dst)47 static void wm_psram_dma_init(uint8_t ch, uint32_t count, void * src, void *dst)
48 {
49     DMA_INTMASK_REG &= ~(0x02<<(ch*2));
50     DMA_SRCADDR_REG(ch) = (uint32_t)src;
51     DMA_DESTADDR_REG(ch) = (uint32_t)dst;
52 
53     DMA_CTRL_REG(ch) = DMA_CTRL_SRC_ADDR_INC|DMA_CTRL_DEST_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | DMA_CTRL_BURST_SIZE1;
54     DMA_MODE_REG(ch) = 0;
55     DMA_CTRL_REG(ch) &= ~0xFFFF00;
56     DMA_CTRL_REG(ch) |= (count<<8);
57 }
58 
psram_DMA_Channel0_IRQHandler(void)59 void psram_DMA_Channel0_IRQHandler(void)
60 {
61     tls_reg_write32(HR_DMA_INT_SRC, 0x02);
62     dma_rx_tx_done += 1;
63 }
64 
psram_init(psram_mode_t mode)65 void psram_init(psram_mode_t mode)
66 {
67     volatile unsigned int value = 0x600;
68 
69     value |= 2<<4;
70 
71     if (mode == PSRAM_QPI) {
72         value |= 0x03;
73     }
74 
75     /* reset psram */
76     value |= 0x01;
77     tls_reg_write32(HR_PSRAM_CTRL_ADDR, value);
78     do {
79         value = tls_reg_read32(HR_PSRAM_CTRL_ADDR);
80     }while (value&0x01);
81 
82     psram_channel = tls_dma_request(0, 0);
83     tls_dma_irq_register(psram_channel, psram_DMA_Channel0_IRQHandler, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
84 }
85 
memcpy_dma(unsigned char * dst,unsigned char * src,int num)86 int memcpy_dma(unsigned char *dst, unsigned char *src, int num)
87 {
88     int offset = 0;
89     int Num = num;
90     unsigned char *psram_access_start = src;
91 
92     int left_bytes = Num&0x03;
93     int dw_length = (Num&(~0x03))>>2;
94 
95     if (!TOO_SMALL(Num) && !UNALIGNED (src, dst)) {
96         if (dw_length) {
97             wm_psram_dma_stop(psram_channel);
98             wm_psram_dma_init(psram_channel, dw_length*4, src, dst);
99             wm_psram_dma_go(psram_channel);
100             while (dma_rx_tx_done == 0);
101             offset += dw_length *4;
102             psram_access_start += dw_length *4;
103         } else {
104             while (dw_length--) {
105                 M32((dst+offset)) = M32(psram_access_start);
106                 psram_access_start += 4;
107                 offset+=4;
108             }
109         }
110         while (left_bytes--) {
111             M8((dst+offset)) = M8(psram_access_start);
112             psram_access_start += 1;
113             offset+=1;
114         }
115     } else {
116         while (Num--) {
117             M8(dst++) = M8(psram_access_start++);
118             offset++;
119         }
120     }
121     return offset;
122 }