跳转到内容

RK3506 GAMC PPS调试日志 ​

更新: 10/23/2026 字数: 0 字 时长: 0 分钟

寄存器 ​

c
#define GMAC_BASE 				0xff4C8B00
#define GMAC_MAP_SIZE 			0x100

#define GMAC_TS_CTRL 			0x00
#define GMAC_ST_SEC 			0x08
#define GMAC_ST_NSEC 			0x0C
#define GMAC_TIMESTAMP_STATUS 	0x20

#define GMAC_PPS_CTRL 			0x70
#define GMAC_PPS0_TAT_SEC 		0x80
#define GMAC_PPS0_TAT_NSEC 		0x84
#define GMAC_PPS0_INTVL 		0x88
#define GMAC_PPS0_WIDTH 		0x8C

#define TRGTBUSY 				(0x1 << 31)
#define TSCTRLSSR 				(0x1 << 9)

配置流程 ​

参考源码kernel/drivers/net/ethernet/stmicro/stmmac/dwmac5.c

  1. 配置 PPS 模式

    c
    temp_reg = 	(0x2 << 5) | 	// TRGMODSEL: 设置为可触发中断并输出PPS信号
    			(0x1 << 4);		// PPSEN: 灵活PPS模式
    
    writel(temp_reg, base + GMAC_PPS_CTRL);
  2. 设置 PPS 周期

    c
    period = tv_sec * 1000000000;
    period += tv_nsec;
    
    do_div(period, sub_second_inc);
    
    if (period <= 1)
        return -EINVAL;
    
    writel(period - 1, base + GMAC_PPS0_INTVL);		// 设置上升沿的时间间隔
    
    period >>= 1;
    if (period <= 1)
        return -EINVAL;
    
    writel(period - 1, base + GMAC_PPS0_WIDTH);		// 设置信号宽度是间隔的一半
  3. 获取当前时间并设置目标时间

    c
    void ptp_get_sys_time(uint32_t *pSec, uint32_t *pNs)
    {
    	*pSec = readl(base + GMAC_ST_SEC);
    	*pNs = readl(base + GMAC_ST_NSEC);
    
    	if ((*pSec + 1u) == readl(base + GMAC_ST_SEC))
    	{
    		*pSec = readl(base + GMAC_ST_SEC);
    		*pNs = readl(base + GMAC_ST_NSEC);
    	}
    
    	if (!(readl(base + GMAC_TS_CTRL) & TSCTRLSSR))
    	{
    		*pNs &= 0x7FFFFFFF;
    	}
    }
    
    int pps_set_tgt_time(uint32_t tgt_sec, uint32_t tgt_ns)
    {
    	int res = 0;
    	uint32_t timeout = 0u;
    
    	if (init_done == 0u)
        {
            return(1);
        }
    
    	while ((readl(base + GMAC_PPS0_TAT_NSEC) & TRGTBUSY) == TRGTBUSY)
    	{
    		if (timeout++ > ETH_MAXIMUM_POLL)
    		{
    			res = 1;
    			break;
    		}
    	}
    
    	if (res == 0)
    	{
    		if (!(readl(base + GMAC_TS_CTRL) & TSCTRLSSR))
    		{
    			tgt_ns = (tgt_ns * 1000) / 465;
    		}
    		// 设置的时间间隔小于 1s 需要先写纳秒寄存器
    		writel(tgt_ns, base + GMAC_PPS0_TAT_NSEC);
    		writel(tgt_sec, base + GMAC_PPS0_TAT_SEC);
    	}
    	return res;
    }
  4. 启动

    writel(0x52, base + GMAC_PPS_CTRL);