1#include "fw_pvt.h"
2#include "viddec_fw_parser_ipclib_config.h"
3
4extern uint32_t timer;
5
6/*------------------------------------------------------------------------------
7 * Function:  memcpy
8 * This is a memory-copy function.
9 *------------------------------------------------------------------------------
10 */
11/* NOTE: we are inventing memcpy since we don't want to include string libs as part of FW Due to size limitations*/
12void *memcpy(void *dest, const void *src, uint32_t n)
13{
14    uint8_t *ptr8_frm, *ptr8_to;
15    uint32_t *ptr32_frm, *ptr32_to;
16    uint32_t bytes_left=n,trail = 0;
17    uint32_t align=0;
18
19    ptr8_frm = (uint8_t *)src;
20    ptr8_to = (uint8_t *)dest;
21
22    trail = ((uint32_t)ptr8_frm) & 0x3;
23    if((trail == (((uint32_t)ptr8_to) & 0x3)) && (n > 4))
24    {
25        /* check to see what's the offset bytes to go to a word alignment */
26        bytes_left -= trail;
27        while(align > 0){
28            *ptr8_to ++ = *ptr8_frm ++;
29            trail--;
30        }
31        /* check to see if rest of bytes is a multiple of 4. */
32        trail = bytes_left & 0x3;
33        bytes_left = (bytes_left >> 2) << 2;
34        ptr32_to = (uint32_t *)ptr8_to;
35        ptr32_frm = (uint32_t *)ptr8_frm;
36        /* copy word by word */
37        while(bytes_left > 0){
38            *ptr32_to ++ = *ptr32_frm ++;
39            bytes_left -= 4;
40        }
41        /* If there are any trailing bytes do a byte copy */
42        ptr8_to = (uint8_t *)ptr32_to;
43        ptr8_frm = (uint8_t *)ptr32_frm;
44        while(trail > 0){
45            *ptr8_to ++ = *ptr8_frm ++;
46            trail--;
47        }
48    }
49    else
50    {/* case when src and dest addr are not on same alignment.
51        Just do a byte copy */
52        while(bytes_left > 0){
53            *ptr8_to ++ = *ptr8_frm ++;
54            bytes_left -= 1;
55        }
56    }
57    return dest;
58}
59
60/*------------------------------------------------------------------------------
61 * Function:  memset
62 * This is a function to copy specificed value into memory array.
63 *------------------------------------------------------------------------------
64 */
65/* NOTE: we are inventing memset since we don't want to include string libs as part of FW Due to size limitations*/
66void *memset(void *s, int32_t c, uint32_t n)
67{
68    uint8_t *ptr8 = (uint8_t *)s;
69    uint32_t *ptr32, data;
70    uint32_t mask = 0, bytes_left = n;
71
72    mask = c & 0xFF;
73    mask |= (mask << 8);
74    mask |= (mask << 16);
75    if(n >= 4)
76    {
77        uint32_t trail=0;
78        trail = 4 - (((uint32_t)ptr8) & 0x3);
79        if(trail < 4)
80        {
81            ptr32 = (uint32_t *)(((uint32_t)ptr8) & ~0x3);
82            data = (*ptr32 >> (8*trail)) << (8*trail);
83            data |= (mask >> (32 - (8*trail)));
84            *ptr32 = data;
85            bytes_left -= trail;
86            ptr8 += trail;
87        }
88        ptr32 = (uint32_t *)((uint32_t)ptr8);
89        while(bytes_left >= 4)
90        {
91            *ptr32 = mask;
92            ptr32++;
93            bytes_left -=4;
94        }
95        if(bytes_left > 0)
96        {
97            data = (*ptr32 << (8*bytes_left)) >> (8*bytes_left);
98            data |= (mask << (32 - (8*bytes_left)));
99            *ptr32=data;
100        }
101    }
102
103    return s;
104}
105
106/*------------------------------------------------------------------------------
107 * Function:  cp_using_dma
108 * This is a function to copy data from local memory to/from system memory.
109 * Params:
110 *         [in] ddr_addr  : Word aligned ddr address.
111 *         [in] local_addr: Word aligned local address.
112 *         [in] size      : No of bytes to transfer.
113 *         [in] to_ddr    : Direction of copy, if true copy to ddr else copy to local memory.
114 *         [in] swap      : Enable or disable byte swap(endian).
115 *         [out] return   : Actual number of bytes copied, which can be more than what was requested
116 *                          since we can only copy words at a time.
117 * Limitations: DMA can transfer Words only, Local addr & DDR addr should be word aligned.
118 *------------------------------------------------------------------------------
119 */
120uint32_t cp_using_dma(uint32_t ddr_addr, uint32_t local_addr, uint32_t size, char to_ddr, char swap)
121{
122    uint32_t val=0, wrote = size;
123
124    while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_BUSY) != 0)
125    {
126        /* wait if DMA is busy with a transcation Error condition??*/
127    }
128
129    reg_write(DMA_SYSTEM_ADDRESS, (ddr_addr & ~3) & ~GV_DDR_MEM_MASK);
130    reg_write(DMA_LOCAL_ADDRESS, (local_addr & 0xfffc));
131    //wrote += (ddr_addr & 0x3);
132    wrote = (wrote+3)>>2;/* make number of bytes multiple of 4 */
133    val=(wrote & 0xffff) << 2;
134    reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE);
135    val |= DMA_CTRL_STATUS_START;
136	/* If size > 64 use 128 byte burst speed */
137    if(wrote > 64)
138        val |= (1<<18);
139    if(swap) /* Endian swap if needed */
140        val |= DMA_CTRL_STATUS_SWAP;
141    if(to_ddr)
142        val = val | DMA_CTRL_STATUS_DIRCN;
143    reg_write(DMA_CONTROL_STATUS, val);
144    while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_DONE) == 0)
145    {
146		/* wait till DMA is done */
147    }
148    reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE);
149
150    return (wrote << 2);
151}
152
153/*------------------------------------------------------------------------------
154 * Function:  cp_using_dma
155 * This is a function to copy data from local memory to/from system memory.
156 * Params:
157 *         [in] ddr_addr  : Word aligned ddr address.
158 *         [in] local_addr: Word aligned local address.
159 *         [in] size      : No of bytes to transfer.
160 *         [in] to_ddr    : Direction of copy, if true copy to ddr else copy to local memory.
161 *         [in] swap      : Enable or disable byte swap(endian).
162 *         [out] return   : Actual number of bytes copied, which can be more than what was requested
163 *                          since we can only copy words at a time.
164 * Limitations: DMA can transfer Words only, Local addr & DDR addr should be word aligned.
165 *------------------------------------------------------------------------------
166 */
167uint32_t cp_using_dma_phys(uint32_t ddr_addr, uint32_t local_addr, uint32_t size, char to_ddr, char swap)
168{
169    uint32_t val=0, wrote = size;
170
171    while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_BUSY) != 0)
172    {
173        /* wait if DMA is busy with a transcation Error condition??*/
174    }
175
176    reg_write(DMA_SYSTEM_ADDRESS, (ddr_addr & ~3));
177    reg_write(DMA_LOCAL_ADDRESS, (local_addr & 0xfffc));
178    //wrote += (ddr_addr & 0x3);
179    wrote = (wrote+3)>>2;/* make number of bytes multiple of 4 */
180    val=(wrote & 0xffff) << 2;
181    reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE);
182    val |= DMA_CTRL_STATUS_START;
183	/* If size > 64 use 128 byte burst speed */
184    if(wrote > 64)
185        val |= (1<<18);
186    if(swap) /* Endian swap if needed */
187        val |= DMA_CTRL_STATUS_SWAP;
188    if(to_ddr)
189        val = val | DMA_CTRL_STATUS_DIRCN;
190    reg_write(DMA_CONTROL_STATUS, val);
191    while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_DONE) == 0)
192    {
193		/* wait till DMA is done */
194    }
195    reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE);
196
197    return (wrote << 2);
198}
199
200void update_ctrl_reg(uint8_t enable, uint32_t mask)
201{
202    uint32_t read_val = 0;
203    read_val = reg_read(CONFIG_CP_CONTROL_REG);
204    if(enable)
205    {
206        read_val = read_val | mask;
207    }
208    else
209    {
210        read_val = read_val & ~mask;
211    }
212    reg_write(CONFIG_CP_CONTROL_REG, read_val);
213    return;
214
215}
216
217extern uint32_t sven_get_timestamp();
218
219uint32_t set_wdog(uint32_t offset)
220{
221#ifdef B0_TIMER_FIX
222    update_ctrl_reg(0, WATCH_DOG_ENABLE);
223    reg_write(INT_REG, INT_WDOG_ENABLE);
224    reg_write(WATCH_DOG_COUNTER, offset & WATCH_DOG_MASK);
225    update_ctrl_reg(1, WATCH_DOG_ENABLE);
226    return offset & WATCH_DOG_MASK;
227#else
228    return sven_get_timestamp();
229#endif
230}
231
232void get_wdog(uint32_t *value)
233{
234#ifdef B0_TIMER_FIX
235    *value = reg_read(WATCH_DOG_COUNTER) & WATCH_DOG_MASK;
236    reg_write(INT_REG, ~INT_WDOG_ENABLE);
237    update_ctrl_reg(0, WATCH_DOG_ENABLE);
238#else
239    *value = sven_get_timestamp();
240#endif
241}
242
243uint32_t get_total_ticks(uint32_t start, uint32_t end)
244{
245    uint32_t value;
246#ifdef B0_TIMER_FIX
247    value = (start-end) + (start*timer);
248    timer=0;
249#else
250    value = end-start;/* convert to 1 MHz clocks */
251#endif
252    return value;
253}
254