linuxOS_D21X/source/linux-5.10/drivers/net/ethernet/artinchip/aicmac_hwtstamp.c

154 lines
3.7 KiB
C
Raw Normal View History

2024-11-29 08:13:19 +00:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2021 ArtInChip Technology Co., Ltd.
* Author: Keliang Liu <keliang.liu@artinchip.com>
*/
#include <linux/io.h>
#include <linux/delay.h>
#include "aicmac_hwtstamp.h"
#include "aicmac_1588.h"
void aicmac_hwtstamp_config_hw_tstamping(void __iomem *ioaddr, u32 data)
{
2024-11-29 08:33:21 +00:00
writel(data, ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
}
void aicmac_hwtstamp_config_sub_second_increment(void __iomem *ioaddr,
u32 ptp_clock, u32 *ssinc)
{
2024-11-29 08:33:21 +00:00
u32 value = readl(ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
unsigned long data;
u32 reg_value;
/* For GMAC3.x, 4.x versions, in "fine adjustement mode" set sub-second
* increment to twice the number of nanoseconds of a clock cycle.
* The calculation of the default_addend value by the caller will set it
* to mid-range = 2^31 when the remainder of this division is zero,
* which will make the accumulator overflow once every 2 ptp_clock
* cycles, adding twice the number of nanoseconds of a clock cycle :
* 2000000000ULL / ptp_clock.
*/
if (value & PTP_TCR_TSCFUPDT)
data = (2000000000ULL / ptp_clock);
else
data = (1000000000ULL / ptp_clock);
/* 0.465ns accuracy */
if (!(value & PTP_TCR_TSCTRLSSR))
data = (data * 1000) / 465;
data &= PTP_SSIR_SSINC_MASK;
reg_value = data;
2024-11-29 08:33:21 +00:00
writel(reg_value, ioaddr + PTP_SUB_SEC_INCR);
2024-11-29 08:13:19 +00:00
if (ssinc)
*ssinc = data;
}
int aicmac_hwtstamp_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
{
int limit;
u32 value;
2024-11-29 08:33:21 +00:00
writel(sec, ioaddr + PTP_UPDT_TIME_SEC);
writel(nsec, ioaddr + PTP_UPDT_TIME_NANO_SEC);
2024-11-29 08:13:19 +00:00
/* issue command to initialize the system time value */
2024-11-29 08:33:21 +00:00
value = readl(ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
value |= PTP_TCR_TSINIT;
2024-11-29 08:33:21 +00:00
writel(value, ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
/* wait for present system time initialize to complete */
limit = 10;
while (limit--) {
2024-11-29 08:33:21 +00:00
if (!(readl(ioaddr + PTP_TMSTMP_CTL) & PTP_TCR_TSINIT))
2024-11-29 08:13:19 +00:00
break;
mdelay(10);
}
if (limit < 0)
return -EBUSY;
return 0;
}
int aicmac_hwtstamp_config_addend(void __iomem *ioaddr, u32 addend)
{
u32 value;
int limit;
2024-11-29 08:33:21 +00:00
writel(addend, ioaddr + PTP_TMSMP_ADDEND);
2024-11-29 08:13:19 +00:00
/* issue command to update the addend value */
2024-11-29 08:33:21 +00:00
value = readl(ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
value |= PTP_TCR_TSADDREG;
2024-11-29 08:33:21 +00:00
writel(value, ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
/* wait for present addend update to complete */
limit = 10;
while (limit--) {
2024-11-29 08:33:21 +00:00
if (!(readl(ioaddr + PTP_TMSTMP_CTL) & PTP_TCR_TSADDREG))
2024-11-29 08:13:19 +00:00
break;
mdelay(10);
}
if (limit < 0)
return -EBUSY;
return 0;
}
int aicmac_hwtstamp_adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec,
int add_sub)
{
u32 value;
int limit;
if (add_sub) {
/* If the new sec value needs to be subtracted with
* the system time, then MAC_STSUR reg should be
* programmed with (2^32 <new_sec_value>)
*/
2024-11-29 08:33:21 +00:00
value = readl(ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
if (value & PTP_TCR_TSCTRLSSR)
nsec = (PTP_DIGITAL_ROLLOVER_MODE - nsec);
else
nsec = (PTP_BINARY_ROLLOVER_MODE - nsec);
}
2024-11-29 08:33:21 +00:00
writel(sec, ioaddr + PTP_UPDT_TIME_SEC);
2024-11-29 08:13:19 +00:00
value = (add_sub << PTP_STNSUR_ADDSUB_SHIFT) | nsec;
2024-11-29 08:33:21 +00:00
writel(value, ioaddr + PTP_UPDT_TIME_NANO_SEC);
2024-11-29 08:13:19 +00:00
/* issue command to initialize the system time value */
2024-11-29 08:33:21 +00:00
value = readl(ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
value |= PTP_TCR_TSUPDT;
2024-11-29 08:33:21 +00:00
writel(value, ioaddr + PTP_TMSTMP_CTL);
2024-11-29 08:13:19 +00:00
/* wait for present system time adjust/update to complete */
limit = 10;
while (limit--) {
2024-11-29 08:33:21 +00:00
if (!(readl(ioaddr + PTP_TMSTMP_CTL) & PTP_TCR_TSUPDT))
2024-11-29 08:13:19 +00:00
break;
mdelay(10);
}
if (limit < 0)
return -EBUSY;
return 0;
}
void aicmac_hwtstamp_get_systime(void __iomem *ioaddr, u64 *systime)
{
u64 ns;
/* Get the TSSS value */
2024-11-29 08:33:21 +00:00
ns = readl(ioaddr + PTP_SYS_TIME_NANO_SEC);
2024-11-29 08:13:19 +00:00
/* Get the TSS and convert sec time value to nanosecond */
2024-11-29 08:33:21 +00:00
ns += readl(ioaddr + PTP_SYS_TIME_SEC) * 1000000000ULL;
2024-11-29 08:13:19 +00:00
if (systime)
*systime = ns;
}