📄 drvdll.c
字号:
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2007 MStar Semiconductor, Inc.
// All rights reserved.
//
// Unless otherwise stipulated in writing, any and all information contained
// herein regardless in any format shall remain the sole proprietary of
// MStar Semiconductor Inc. and be kept in strict confidence
// (¨MStar Confidential Information〃) by the recipient.
// Any unauthorized act including without limitation unauthorized disclosure,
// copying, use, reproduction, sale, distribution, modification, disassembling,
// reverse engineering and compiling of the contents of MStar Confidential
// Information is unlawful and strictly prohibited. MStar hereby reserves the
// rights to any and all damages, losses, costs and expenses resulting therefrom.
//
////////////////////////////////////////////////////////////////////////////////
#include <intrins.h>
#include "Datatype.h"
#include "R8051XC.h"
#include "hwreg.h"
#define REG_DLL_CTRL (DLL_REG_BASE + 0x00)
#define DLL_CTRL_ENABLE (1 << 0)
#define DLL_CTRL_SOFT_RST (1 << 1)
#define REG_DLL_DET1T (DLL_REG_BASE + 0x02) // detect 1T
#define DET1T_SETDLY 0x07
#define DET1T_GO (1 << 4)
#define DET1T_RDY (1 << 5)
#define REG_DLL_PD (DLL_REG_BASE + 0x03) // detect phase
#define PD_SELMUX 0x1F
#define PD_GO (1 << 6)
#define PD_RDY (1 << 7)
#define REG_DLL_DLY_OE (DLL_REG_BASE + 0x04)
#define REG_DLL_DLY32_OE (DLL_REG_BASE + 0x06)
#define REG_DLL_DET1T_STAT (DLL_REG_BASE + 0x0A)
#define REG_DLL_PD_STAT (DLL_REG_BASE + 0x0E)
static U8 code u8OE[] = { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
static void MDrv_DLL_SetDly32OE(U8 u8SelectMux)
{
// assume DLL_DLY32_OE is 0xFFFFFFFF
if (u8SelectMux < 8)
{
XBYTE[REG_DLL_DLY32_OE + 3] = 0;
XBYTE[REG_DLL_DLY32_OE + 2] = 0;
XBYTE[REG_DLL_DLY32_OE + 1] = 0;
XBYTE[REG_DLL_DLY32_OE + 0] = u8OE[u8SelectMux];
}
else if (u8SelectMux < 16)
{
XBYTE[REG_DLL_DLY32_OE + 3] = 0;
XBYTE[REG_DLL_DLY32_OE + 2] = 0;
XBYTE[REG_DLL_DLY32_OE + 1] = u8OE[u8SelectMux & 0x07];
}
else if (u8SelectMux < 24)
{
XBYTE[REG_DLL_DLY32_OE + 3] = 0;
XBYTE[REG_DLL_DLY32_OE + 2] = u8OE[u8SelectMux & 0x07];
}
else
{
XBYTE[REG_DLL_DLY32_OE + 3] = u8OE[u8SelectMux & 0x07];
}
}
void MDrv_DLL_Init(void)
{
U8 n;
U8 i;
U8 j;
// reset DLL
XBYTE[REG_DLL_CTRL] = DLL_CTRL_SOFT_RST;
XBYTE[REG_DLL_CTRL] = DLL_CTRL_ENABLE;
// detect 1T
for (n = 0; n < 32; n++)
{
i = n & 3;
if (!i)
{
XBYTE[REG_DLL_DET1T] = DET1T_GO | (n >> 2);
while (!(XBYTE[REG_DLL_DET1T] & DET1T_RDY))
/* forever */;
j = 0;
}
// find "0..0 1..1 0..0" pattern in 32-bit DLL_DET1T_STAT
i = XBYTE[REG_DLL_DET1T_STAT + 3 - i]; // little endian
for (B = 0x80; B > 0; B >>= 1)
{
UD = i & B; /* bit mask */
switch (j)
{
case 0:
case 1:
if (UD)
j = 0;
else
j++;
break;
case 2:
if (UD)
j++;
break;
case 3:
if (UD)
j++;
else
j = 0;
break;
case 4:
if (!UD)
j++;
break;
case 5:
if (UD)
j = 0;
else
goto detect_1T_done;
break;
}
}
}
detect_1T_done:
if (n < 32)
{
// detect phase
for (n = 0; n < 32; n++)
{
XBYTE[REG_DLL_PD] = PD_GO | n;
while (!(XBYTE[REG_DLL_PD] & PD_RDY))
/* forever */;
i = XBYTE[REG_DLL_PD_STAT];
j = XBYTE[REG_DLL_PD_STAT];
// okay cases: 5'b10000 5'b11000 5'b11100 5'b11110
if ( (i == 0x10 || i == 0x18 || i == 0x1C || i == 0x1E) &&
(j == 0x10 || j == 0x18 || j == 0x1C || j == 0x1E) )
break;
}
}
if (n == 32)
{
// detect 1T or phase fail
XBYTE[REG_DLL_CTRL] = 0;
}
else
{
// set DLL_DLY_OE & DLL_DLY32_OE for power saving
XBYTE[REG_DLL_DLY_OE + 0] = u8OE[XBYTE[REG_DLL_DET1T] & 0x07];
XBYTE[REG_DLL_DLY_OE + 1] = 0;
MDrv_DLL_SetDly32OE(n);
}
}
// Fine tune DLL phase while MIU is idle
void MDrv_DLL_Monitor(void)
{
U8 u8PDStat1;
U8 u8PDStat2;
U8 u8SelectMux;
XBYTE[REG_DLL_DLY32_OE + 3] = 0xFF;
XBYTE[REG_DLL_DLY32_OE + 2] = 0xFF;
XBYTE[REG_DLL_DLY32_OE + 1] = 0xFF;
XBYTE[REG_DLL_DLY32_OE + 0] = 0xFF;
XBYTE[REG_DLL_DLY_OE + 1] = 0xFF;
u8SelectMux = XBYTE[REG_DLL_PD] & 0x1F;
while (1)
{
XBYTE[REG_DLL_PD] = PD_GO | u8SelectMux;
while (!(XBYTE[REG_DLL_PD] & PD_RDY))
/* forever */;
u8PDStat1 = XBYTE[REG_DLL_PD_STAT];
u8PDStat2 = XBYTE[REG_DLL_PD_STAT];
if (((u8PDStat1 == 0x0) || (u8PDStat1 == 0x1))
&& ((u8PDStat2 == 0x0) || (u8PDStat2 == 0x1)))
{
u8SelectMux = (u8SelectMux + 1) & 0x1F;
}
else if (((u8PDStat1 == 0x1F) || (u8PDStat1 == 0x0F))
&& ((u8PDStat2 == 0x1F) || (u8PDStat2 == 0x0F)))
{
u8SelectMux = (u8SelectMux - 1) & 0x1F;
}
else
{
XBYTE[REG_DLL_DLY_OE + 1] = 0;
MDrv_DLL_SetDly32OE(u8SelectMux);
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -