| #include "fw_pvt.h" |
| #include "viddec_fw_parser_ipclib_config.h" |
| |
| extern uint32_t timer; |
| |
| /*------------------------------------------------------------------------------ |
| * Function: memcpy |
| * This is a memory-copy function. |
| *------------------------------------------------------------------------------ |
| */ |
| /* NOTE: we are inventing memcpy since we don't want to include string libs as part of FW Due to size limitations*/ |
| void *memcpy(void *dest, const void *src, uint32_t n) |
| { |
| uint8_t *ptr8_frm, *ptr8_to; |
| uint32_t *ptr32_frm, *ptr32_to; |
| uint32_t bytes_left=n,trail = 0; |
| uint32_t align=0; |
| |
| ptr8_frm = (uint8_t *)src; |
| ptr8_to = (uint8_t *)dest; |
| |
| trail = ((uint32_t)ptr8_frm) & 0x3; |
| if((trail == (((uint32_t)ptr8_to) & 0x3)) && (n > 4)) |
| { |
| /* check to see what's the offset bytes to go to a word alignment */ |
| bytes_left -= trail; |
| while(align > 0){ |
| *ptr8_to ++ = *ptr8_frm ++; |
| trail--; |
| } |
| /* check to see if rest of bytes is a multiple of 4. */ |
| trail = bytes_left & 0x3; |
| bytes_left = (bytes_left >> 2) << 2; |
| ptr32_to = (uint32_t *)ptr8_to; |
| ptr32_frm = (uint32_t *)ptr8_frm; |
| /* copy word by word */ |
| while(bytes_left > 0){ |
| *ptr32_to ++ = *ptr32_frm ++; |
| bytes_left -= 4; |
| } |
| /* If there are any trailing bytes do a byte copy */ |
| ptr8_to = (uint8_t *)ptr32_to; |
| ptr8_frm = (uint8_t *)ptr32_frm; |
| while(trail > 0){ |
| *ptr8_to ++ = *ptr8_frm ++; |
| trail--; |
| } |
| } |
| else |
| {/* case when src and dest addr are not on same alignment. |
| Just do a byte copy */ |
| while(bytes_left > 0){ |
| *ptr8_to ++ = *ptr8_frm ++; |
| bytes_left -= 1; |
| } |
| } |
| return dest; |
| } |
| |
| /*------------------------------------------------------------------------------ |
| * Function: memset |
| * This is a function to copy specificed value into memory array. |
| *------------------------------------------------------------------------------ |
| */ |
| /* NOTE: we are inventing memset since we don't want to include string libs as part of FW Due to size limitations*/ |
| void *memset(void *s, int32_t c, uint32_t n) |
| { |
| uint8_t *ptr8 = (uint8_t *)s; |
| uint32_t *ptr32, data; |
| uint32_t mask = 0, bytes_left = n; |
| |
| mask = c & 0xFF; |
| mask |= (mask << 8); |
| mask |= (mask << 16); |
| if(n >= 4) |
| { |
| uint32_t trail=0; |
| trail = 4 - (((uint32_t)ptr8) & 0x3); |
| if(trail < 4) |
| { |
| ptr32 = (uint32_t *)(((uint32_t)ptr8) & ~0x3); |
| data = (*ptr32 >> (8*trail)) << (8*trail); |
| data |= (mask >> (32 - (8*trail))); |
| *ptr32 = data; |
| bytes_left -= trail; |
| ptr8 += trail; |
| } |
| ptr32 = (uint32_t *)((uint32_t)ptr8); |
| while(bytes_left >= 4) |
| { |
| *ptr32 = mask; |
| ptr32++; |
| bytes_left -=4; |
| } |
| if(bytes_left > 0) |
| { |
| data = (*ptr32 << (8*bytes_left)) >> (8*bytes_left); |
| data |= (mask << (32 - (8*bytes_left))); |
| *ptr32=data; |
| } |
| } |
| |
| return s; |
| } |
| |
| /*------------------------------------------------------------------------------ |
| * Function: cp_using_dma |
| * This is a function to copy data from local memory to/from system memory. |
| * Params: |
| * [in] ddr_addr : Word aligned ddr address. |
| * [in] local_addr: Word aligned local address. |
| * [in] size : No of bytes to transfer. |
| * [in] to_ddr : Direction of copy, if true copy to ddr else copy to local memory. |
| * [in] swap : Enable or disable byte swap(endian). |
| * [out] return : Actual number of bytes copied, which can be more than what was requested |
| * since we can only copy words at a time. |
| * Limitations: DMA can transfer Words only, Local addr & DDR addr should be word aligned. |
| *------------------------------------------------------------------------------ |
| */ |
| uint32_t cp_using_dma(uint32_t ddr_addr, uint32_t local_addr, uint32_t size, char to_ddr, char swap) |
| { |
| uint32_t val=0, wrote = size; |
| |
| while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_BUSY) != 0) |
| { |
| /* wait if DMA is busy with a transcation Error condition??*/ |
| } |
| |
| reg_write(DMA_SYSTEM_ADDRESS, (ddr_addr & ~3) & ~GV_DDR_MEM_MASK); |
| reg_write(DMA_LOCAL_ADDRESS, (local_addr & 0xfffc)); |
| //wrote += (ddr_addr & 0x3); |
| wrote = (wrote+3)>>2;/* make number of bytes multiple of 4 */ |
| val=(wrote & 0xffff) << 2; |
| reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE); |
| val |= DMA_CTRL_STATUS_START; |
| /* If size > 64 use 128 byte burst speed */ |
| if(wrote > 64) |
| val |= (1<<18); |
| if(swap) /* Endian swap if needed */ |
| val |= DMA_CTRL_STATUS_SWAP; |
| if(to_ddr) |
| val = val | DMA_CTRL_STATUS_DIRCN; |
| reg_write(DMA_CONTROL_STATUS, val); |
| while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_DONE) == 0) |
| { |
| /* wait till DMA is done */ |
| } |
| reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE); |
| |
| return (wrote << 2); |
| } |
| |
| /*------------------------------------------------------------------------------ |
| * Function: cp_using_dma |
| * This is a function to copy data from local memory to/from system memory. |
| * Params: |
| * [in] ddr_addr : Word aligned ddr address. |
| * [in] local_addr: Word aligned local address. |
| * [in] size : No of bytes to transfer. |
| * [in] to_ddr : Direction of copy, if true copy to ddr else copy to local memory. |
| * [in] swap : Enable or disable byte swap(endian). |
| * [out] return : Actual number of bytes copied, which can be more than what was requested |
| * since we can only copy words at a time. |
| * Limitations: DMA can transfer Words only, Local addr & DDR addr should be word aligned. |
| *------------------------------------------------------------------------------ |
| */ |
| uint32_t cp_using_dma_phys(uint32_t ddr_addr, uint32_t local_addr, uint32_t size, char to_ddr, char swap) |
| { |
| uint32_t val=0, wrote = size; |
| |
| while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_BUSY) != 0) |
| { |
| /* wait if DMA is busy with a transcation Error condition??*/ |
| } |
| |
| reg_write(DMA_SYSTEM_ADDRESS, (ddr_addr & ~3)); |
| reg_write(DMA_LOCAL_ADDRESS, (local_addr & 0xfffc)); |
| //wrote += (ddr_addr & 0x3); |
| wrote = (wrote+3)>>2;/* make number of bytes multiple of 4 */ |
| val=(wrote & 0xffff) << 2; |
| reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE); |
| val |= DMA_CTRL_STATUS_START; |
| /* If size > 64 use 128 byte burst speed */ |
| if(wrote > 64) |
| val |= (1<<18); |
| if(swap) /* Endian swap if needed */ |
| val |= DMA_CTRL_STATUS_SWAP; |
| if(to_ddr) |
| val = val | DMA_CTRL_STATUS_DIRCN; |
| reg_write(DMA_CONTROL_STATUS, val); |
| while((reg_read(DMA_CONTROL_STATUS) & DMA_CTRL_STATUS_DONE) == 0) |
| { |
| /* wait till DMA is done */ |
| } |
| reg_write(DMA_CONTROL_STATUS, DMA_CTRL_STATUS_DONE); |
| |
| return (wrote << 2); |
| } |
| |
| void update_ctrl_reg(uint8_t enable, uint32_t mask) |
| { |
| uint32_t read_val = 0; |
| read_val = reg_read(CONFIG_CP_CONTROL_REG); |
| if(enable) |
| { |
| read_val = read_val | mask; |
| } |
| else |
| { |
| read_val = read_val & ~mask; |
| } |
| reg_write(CONFIG_CP_CONTROL_REG, read_val); |
| return; |
| |
| } |
| |
| extern uint32_t sven_get_timestamp(); |
| |
| uint32_t set_wdog(uint32_t offset) |
| { |
| #ifdef B0_TIMER_FIX |
| update_ctrl_reg(0, WATCH_DOG_ENABLE); |
| reg_write(INT_REG, INT_WDOG_ENABLE); |
| reg_write(WATCH_DOG_COUNTER, offset & WATCH_DOG_MASK); |
| update_ctrl_reg(1, WATCH_DOG_ENABLE); |
| return offset & WATCH_DOG_MASK; |
| #else |
| return sven_get_timestamp(); |
| #endif |
| } |
| |
| void get_wdog(uint32_t *value) |
| { |
| #ifdef B0_TIMER_FIX |
| *value = reg_read(WATCH_DOG_COUNTER) & WATCH_DOG_MASK; |
| reg_write(INT_REG, ~INT_WDOG_ENABLE); |
| update_ctrl_reg(0, WATCH_DOG_ENABLE); |
| #else |
| *value = sven_get_timestamp(); |
| #endif |
| } |
| |
| uint32_t get_total_ticks(uint32_t start, uint32_t end) |
| { |
| uint32_t value; |
| #ifdef B0_TIMER_FIX |
| value = (start-end) + (start*timer); |
| timer=0; |
| #else |
| value = end-start;/* convert to 1 MHz clocks */ |
| #endif |
| return value; |
| } |