lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aKSYMxObH1n9luEs@lizhi-Precision-Tower-5810>
Date: Tue, 19 Aug 2025 11:28:51 -0400
From: Frank Li <Frank.li@....com>
To: Wei Fang <wei.fang@....com>
Cc: robh@...nel.org, krzk+dt@...nel.org, conor+dt@...nel.org,
	richardcochran@...il.com, claudiu.manoil@....com,
	vladimir.oltean@....com, xiaoning.wang@....com,
	andrew+netdev@...n.ch, davem@...emloft.net, edumazet@...gle.com,
	kuba@...nel.org, pabeni@...hat.com, vadim.fedorenko@...ux.dev,
	shawnguo@...nel.org, s.hauer@...gutronix.de, festevam@...il.com,
	fushi.peng@....com, devicetree@...r.kernel.org,
	netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
	imx@...ts.linux.dev, kernel@...gutronix.de
Subject: Re: [PATCH v4 net-next 06/15] ptp: netc: add periodic pulse output
 support

On Tue, Aug 19, 2025 at 08:36:11PM +0800, Wei Fang wrote:
> NETC Timer has three pulse channels, all of which support periodic pulse
> output. Bind the channel to a ALARM register and then sets a future time
> into the ALARM register. When the current time is greater than the ALARM
> value, the FIPER register will be triggered to count down, and when the
> count reaches 0, the pulse will be triggered. The PPS signal is also
> implemented in this way.
>
> i.MX95 only has ALARM1 can be used as an indication to the FIPER start
> down counting, but i.MX943 has ALARM1 and ALARM2 can be used. Therefore,
> only one channel can work for i.MX95, two channels for i.MX943 as most.
>
> In addition, change the PPS channel to be dynamically selected from fixed
> number (0) because add PTP_CLK_REQ_PEROUT support.
>
> Signed-off-by: Wei Fang <wei.fang@....com>

Reviewed-by: Frank Li <Frank.Li@....com>
>
> ---
> v2: no changes
> v3 changes:
> 1. Improve the commit message
> 2. Add revision to struct netc_timer
> 3. Use priv->tmr_emask to instead of reading TMR_EMASK register
> 4. Add pps_channel to struct netc_timer and NETC_TMR_INVALID_CHANNEL
> 5. Add some helper functions: netc_timer_enable/disable_periodic_pulse(),
>    and netc_timer_select_pps_channel()
> 6. Dynamically select PPS channel instead of fixed to channel 0.
> v4:
> 1. Simplify the commit message
> 2. Fix dereference unassigned pointer "ps" in netc_timer_enable_pps().
> ---
>  drivers/ptp/ptp_netc.c | 356 +++++++++++++++++++++++++++++++++++------
>  1 file changed, 306 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c
> index ded2509700b5..da9603c65dda 100644
> --- a/drivers/ptp/ptp_netc.c
> +++ b/drivers/ptp/ptp_netc.c
> @@ -52,12 +52,18 @@
>  #define NETC_TMR_CUR_TIME_H		0x00f4
>
>  #define NETC_TMR_REGS_BAR		0
> +#define NETC_GLOBAL_OFFSET		0x10000
> +#define NETC_GLOBAL_IPBRR0		0xbf8
> +#define  IPBRR0_IP_REV			GENMASK(15, 0)
> +#define NETC_REV_4_1			0x0401
>
>  #define NETC_TMR_FIPER_NUM		3
> +#define NETC_TMR_INVALID_CHANNEL	NETC_TMR_FIPER_NUM
>  #define NETC_TMR_DEFAULT_PRSC		2
>  #define NETC_TMR_DEFAULT_ALARM		GENMASK_ULL(63, 0)
>  #define NETC_TMR_DEFAULT_FIPER		GENMASK(31, 0)
>  #define NETC_TMR_FIPER_MAX_PW		GENMASK(4, 0)
> +#define NETC_TMR_ALARM_NUM		2
>
>  /* 1588 timer reference clock source select */
>  #define NETC_TMR_CCM_TIMER1		0 /* enet_timer1_clk_root, from CCM */
> @@ -66,6 +72,19 @@
>
>  #define NETC_TMR_SYSCLK_333M		333333333U
>
> +enum netc_pp_type {
> +	NETC_PP_PPS = 1,
> +	NETC_PP_PEROUT,
> +};
> +
> +struct netc_pp {
> +	enum netc_pp_type type;
> +	bool enabled;
> +	int alarm_id;
> +	u32 period; /* pulse period, ns */
> +	u64 stime; /* start time, ns */
> +};
> +
>  struct netc_timer {
>  	void __iomem *base;
>  	struct pci_dev *pdev;
> @@ -80,8 +99,12 @@ struct netc_timer {
>  	u64 period;
>
>  	int irq;
> +	int revision;
>  	u32 tmr_emask;
> -	bool pps_enabled;
> +	u8 pps_channel;
> +	u8 fs_alarm_num;
> +	u8 fs_alarm_bitmap;
> +	struct netc_pp pp[NETC_TMR_FIPER_NUM]; /* periodic pulse */
>  };
>
>  #define netc_timer_rd(p, o)		netc_read((p)->base + (o))
> @@ -190,6 +213,7 @@ static u32 netc_timer_calculate_fiper_pw(struct netc_timer *priv,
>  static void netc_timer_set_pps_alarm(struct netc_timer *priv, int channel,
>  				     u32 integral_period)
>  {
> +	struct netc_pp *pp = &priv->pp[channel];
>  	u64 alarm;
>
>  	/* Get the alarm value */
> @@ -197,7 +221,116 @@ static void netc_timer_set_pps_alarm(struct netc_timer *priv, int channel,
>  	alarm = roundup_u64(alarm, NSEC_PER_SEC);
>  	alarm = roundup_u64(alarm, integral_period);
>
> -	netc_timer_alarm_write(priv, alarm, 0);
> +	netc_timer_alarm_write(priv, alarm, pp->alarm_id);
> +}
> +
> +static void netc_timer_set_perout_alarm(struct netc_timer *priv, int channel,
> +					u32 integral_period)
> +{
> +	u64 cur_time = netc_timer_cur_time_read(priv);
> +	struct netc_pp *pp = &priv->pp[channel];
> +	u64 alarm, delta, min_time;
> +	u32 period = pp->period;
> +	u64 stime = pp->stime;
> +
> +	min_time = cur_time + NSEC_PER_MSEC + period;
> +	if (stime < min_time) {
> +		delta = min_time - stime;
> +		stime += roundup_u64(delta, period);
> +	}
> +
> +	alarm = roundup_u64(stime - period, integral_period);
> +	netc_timer_alarm_write(priv, alarm, pp->alarm_id);
> +}
> +
> +static int netc_timer_get_alarm_id(struct netc_timer *priv)
> +{
> +	int i;
> +
> +	for (i = 0; i < priv->fs_alarm_num; i++) {
> +		if (!(priv->fs_alarm_bitmap & BIT(i))) {
> +			priv->fs_alarm_bitmap |= BIT(i);
> +			break;
> +		}
> +	}
> +
> +	return i;
> +}
> +
> +static u64 netc_timer_get_gclk_period(struct netc_timer *priv)
> +{
> +	/* TMR_GCLK_freq = (clk_freq / oclk_prsc) Hz.
> +	 * TMR_GCLK_period = NSEC_PER_SEC / TMR_GCLK_freq.
> +	 * TMR_GCLK_period = (NSEC_PER_SEC * oclk_prsc) / clk_freq
> +	 */
> +
> +	return div_u64(mul_u32_u32(NSEC_PER_SEC, priv->oclk_prsc),
> +		       priv->clk_freq);
> +}
> +
> +static void netc_timer_enable_periodic_pulse(struct netc_timer *priv,
> +					     u8 channel)
> +{
> +	u32 fiper_pw, fiper, fiper_ctrl, integral_period;
> +	struct netc_pp *pp = &priv->pp[channel];
> +	int alarm_id = pp->alarm_id;
> +
> +	integral_period = netc_timer_get_integral_period(priv);
> +	/* Set to desired FIPER interval in ns - TCLK_PERIOD */
> +	fiper = pp->period - integral_period;
> +	fiper_pw = netc_timer_calculate_fiper_pw(priv, fiper);
> +
> +	fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> +	fiper_ctrl &= ~(FIPER_CTRL_DIS(channel) | FIPER_CTRL_PW(channel) |
> +			FIPER_CTRL_FS_ALARM(channel));
> +	fiper_ctrl |= FIPER_CTRL_SET_PW(channel, fiper_pw);
> +	fiper_ctrl |= alarm_id ? FIPER_CTRL_FS_ALARM(channel) : 0;
> +
> +	priv->tmr_emask |= TMR_TEVNET_PPEN(channel) |
> +			   TMR_TEVENT_ALMEN(alarm_id);
> +
> +	if (pp->type == NETC_PP_PPS)
> +		netc_timer_set_pps_alarm(priv, channel, integral_period);
> +	else
> +		netc_timer_set_perout_alarm(priv, channel, integral_period);
> +
> +	netc_timer_wr(priv, NETC_TMR_TEMASK, priv->tmr_emask);
> +	netc_timer_wr(priv, NETC_TMR_FIPER(channel), fiper);
> +	netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl);
> +}
> +
> +static void netc_timer_disable_periodic_pulse(struct netc_timer *priv,
> +					      u8 channel)
> +{
> +	struct netc_pp *pp = &priv->pp[channel];
> +	int alarm_id = pp->alarm_id;
> +	u32 fiper_ctrl;
> +
> +	if (!pp->enabled)
> +		return;
> +
> +	priv->tmr_emask &= ~(TMR_TEVNET_PPEN(channel) |
> +			     TMR_TEVENT_ALMEN(alarm_id));
> +
> +	fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> +	fiper_ctrl |= FIPER_CTRL_DIS(channel);
> +
> +	netc_timer_alarm_write(priv, NETC_TMR_DEFAULT_ALARM, alarm_id);
> +	netc_timer_wr(priv, NETC_TMR_TEMASK, priv->tmr_emask);
> +	netc_timer_wr(priv, NETC_TMR_FIPER(channel), NETC_TMR_DEFAULT_FIPER);
> +	netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl);
> +}
> +
> +static u8 netc_timer_select_pps_channel(struct netc_timer *priv)
> +{
> +	int i;
> +
> +	for (i = 0; i < NETC_TMR_FIPER_NUM; i++) {
> +		if (!priv->pp[i].enabled)
> +			return i;
> +	}
> +
> +	return NETC_TMR_INVALID_CHANNEL;
>  }
>
>  /* Note that users should not use this API to output PPS signal on
> @@ -208,77 +341,178 @@ static void netc_timer_set_pps_alarm(struct netc_timer *priv, int channel,
>  static int netc_timer_enable_pps(struct netc_timer *priv,
>  				 struct ptp_clock_request *rq, int on)
>  {
> -	u32 fiper, fiper_ctrl;
> +	struct device *dev = &priv->pdev->dev;
>  	unsigned long flags;
> +	struct netc_pp *pp;
> +	int err = 0;
>
>  	spin_lock_irqsave(&priv->lock, flags);
>
> -	fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> -
>  	if (on) {
> -		u32 integral_period, fiper_pw;
> +		int alarm_id;
> +		u8 channel;
> +
> +		if (priv->pps_channel < NETC_TMR_FIPER_NUM) {
> +			channel = priv->pps_channel;
> +		} else {
> +			channel = netc_timer_select_pps_channel(priv);
> +			if (channel == NETC_TMR_INVALID_CHANNEL) {
> +				dev_err(dev, "No available FIPERs\n");
> +				err = -EBUSY;
> +				goto unlock_spinlock;
> +			}
> +		}
>
> -		if (priv->pps_enabled)
> +		pp = &priv->pp[channel];
> +		if (pp->enabled)
>  			goto unlock_spinlock;
>
> -		integral_period = netc_timer_get_integral_period(priv);
> -		fiper = NSEC_PER_SEC - integral_period;
> -		fiper_pw = netc_timer_calculate_fiper_pw(priv, fiper);
> -		fiper_ctrl &= ~(FIPER_CTRL_DIS(0) | FIPER_CTRL_PW(0) |
> -				FIPER_CTRL_FS_ALARM(0));
> -		fiper_ctrl |= FIPER_CTRL_SET_PW(0, fiper_pw);
> -		priv->tmr_emask |= TMR_TEVNET_PPEN(0) | TMR_TEVENT_ALMEN(0);
> -		priv->pps_enabled = true;
> -		netc_timer_set_pps_alarm(priv, 0, integral_period);
> +		alarm_id = netc_timer_get_alarm_id(priv);
> +		if (alarm_id == priv->fs_alarm_num) {
> +			dev_err(dev, "No available ALARMs\n");
> +			err = -EBUSY;
> +			goto unlock_spinlock;
> +		}
> +
> +		pp->enabled = true;
> +		pp->type = NETC_PP_PPS;
> +		pp->alarm_id = alarm_id;
> +		pp->period = NSEC_PER_SEC;
> +		priv->pps_channel = channel;
> +
> +		netc_timer_enable_periodic_pulse(priv, channel);
>  	} else {
> -		if (!priv->pps_enabled)
> +		/* pps_channel is invalid if PPS is not enabled, so no
> +		 * processing is needed.
> +		 */
> +		if (priv->pps_channel >= NETC_TMR_FIPER_NUM)
>  			goto unlock_spinlock;
>
> -		fiper = NETC_TMR_DEFAULT_FIPER;
> -		priv->tmr_emask &= ~(TMR_TEVNET_PPEN(0) |
> -				     TMR_TEVENT_ALMEN(0));
> -		fiper_ctrl |= FIPER_CTRL_DIS(0);
> -		priv->pps_enabled = false;
> -		netc_timer_alarm_write(priv, NETC_TMR_DEFAULT_ALARM, 0);
> +		netc_timer_disable_periodic_pulse(priv, priv->pps_channel);
> +		pp = &priv->pp[priv->pps_channel];
> +		priv->fs_alarm_bitmap &= ~BIT(pp->alarm_id);
> +		memset(pp, 0, sizeof(*pp));
> +		priv->pps_channel = NETC_TMR_INVALID_CHANNEL;
>  	}
>
> -	netc_timer_wr(priv, NETC_TMR_TEMASK, priv->tmr_emask);
> -	netc_timer_wr(priv, NETC_TMR_FIPER(0), fiper);
> -	netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl);
> +unlock_spinlock:
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +
> +	return err;
> +}
> +
> +static int net_timer_enable_perout(struct netc_timer *priv,
> +				   struct ptp_clock_request *rq, int on)
> +{
> +	struct device *dev = &priv->pdev->dev;
> +	u32 channel = rq->perout.index;
> +	unsigned long flags;
> +	struct netc_pp *pp;
> +	int err = 0;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	pp = &priv->pp[channel];
> +	if (pp->type == NETC_PP_PPS) {
> +		dev_err(dev, "FIPER%u is being used for PPS\n", channel);
> +		err = -EBUSY;
> +		goto unlock_spinlock;
> +	}
> +
> +	if (on) {
> +		u64 period_ns, gclk_period, max_period, min_period;
> +		struct timespec64 period, stime;
> +		u32 integral_period;
> +		int alarm_id;
> +
> +		period.tv_sec = rq->perout.period.sec;
> +		period.tv_nsec = rq->perout.period.nsec;
> +		period_ns = timespec64_to_ns(&period);
> +
> +		integral_period = netc_timer_get_integral_period(priv);
> +		max_period = (u64)NETC_TMR_DEFAULT_FIPER + integral_period;
> +		gclk_period = netc_timer_get_gclk_period(priv);
> +		min_period = gclk_period * 4 + integral_period;
> +		if (period_ns > max_period || period_ns < min_period) {
> +			dev_err(dev, "The period range is %llu ~ %llu\n",
> +				min_period, max_period);
> +			err = -EINVAL;
> +			goto unlock_spinlock;
> +		}
> +
> +		if (pp->enabled) {
> +			alarm_id = pp->alarm_id;
> +		} else {
> +			alarm_id = netc_timer_get_alarm_id(priv);
> +			if (alarm_id == priv->fs_alarm_num) {
> +				dev_err(dev, "No available ALARMs\n");
> +				err = -EBUSY;
> +				goto unlock_spinlock;
> +			}
> +
> +			pp->type = NETC_PP_PEROUT;
> +			pp->enabled = true;
> +			pp->alarm_id = alarm_id;
> +		}
> +
> +		stime.tv_sec = rq->perout.start.sec;
> +		stime.tv_nsec = rq->perout.start.nsec;
> +		pp->stime = timespec64_to_ns(&stime);
> +		pp->period = period_ns;
> +
> +		netc_timer_enable_periodic_pulse(priv, channel);
> +	} else {
> +		netc_timer_disable_periodic_pulse(priv, channel);
> +		priv->fs_alarm_bitmap &= ~BIT(pp->alarm_id);
> +		memset(pp, 0, sizeof(*pp));
> +	}
>
>  unlock_spinlock:
>  	spin_unlock_irqrestore(&priv->lock, flags);
>
> -	return 0;
> +	return err;
>  }
>
> -static void netc_timer_disable_pps_fiper(struct netc_timer *priv)
> +static void netc_timer_disable_fiper(struct netc_timer *priv)
>  {
> -	u32 fiper_ctrl;
> +	u32 fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> +	int i;
>
> -	if (!priv->pps_enabled)
> -		return;
> +	for (i = 0; i < NETC_TMR_FIPER_NUM; i++) {
> +		if (!priv->pp[i].enabled)
> +			continue;
> +
> +		fiper_ctrl |= FIPER_CTRL_DIS(i);
> +		netc_timer_wr(priv, NETC_TMR_FIPER(i), NETC_TMR_DEFAULT_FIPER);
> +	}
>
> -	fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> -	fiper_ctrl |= FIPER_CTRL_DIS(0);
> -	netc_timer_wr(priv, NETC_TMR_FIPER(0), NETC_TMR_DEFAULT_FIPER);
>  	netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl);
>  }
>
> -static void netc_timer_enable_pps_fiper(struct netc_timer *priv)
> +static void netc_timer_enable_fiper(struct netc_timer *priv)
>  {
> -	u32 fiper_ctrl, integral_period, fiper;
> +	u32 integral_period = netc_timer_get_integral_period(priv);
> +	u32 fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> +	int i;
>
> -	if (!priv->pps_enabled)
> -		return;
> +	for (i = 0; i < NETC_TMR_FIPER_NUM; i++) {
> +		struct netc_pp *pp = &priv->pp[i];
> +		u32 fiper;
>
> -	integral_period = netc_timer_get_integral_period(priv);
> -	fiper_ctrl = netc_timer_rd(priv, NETC_TMR_FIPER_CTRL);
> -	fiper_ctrl &= ~FIPER_CTRL_DIS(0);
> -	fiper = NSEC_PER_SEC - integral_period;
> +		if (!pp->enabled)
> +			continue;
> +
> +		fiper_ctrl &= ~FIPER_CTRL_DIS(i);
> +
> +		if (pp->type == NETC_PP_PPS)
> +			netc_timer_set_pps_alarm(priv, i, integral_period);
> +		else if (pp->type == NETC_PP_PEROUT)
> +			netc_timer_set_perout_alarm(priv, i, integral_period);
> +
> +		fiper = pp->period - integral_period;
> +		netc_timer_wr(priv, NETC_TMR_FIPER(i), fiper);
> +	}
>
> -	netc_timer_set_pps_alarm(priv, 0, integral_period);
> -	netc_timer_wr(priv, NETC_TMR_FIPER(0), fiper);
>  	netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl);
>  }
>
> @@ -290,6 +524,8 @@ static int netc_timer_enable(struct ptp_clock_info *ptp,
>  	switch (rq->type) {
>  	case PTP_CLK_REQ_PPS:
>  		return netc_timer_enable_pps(priv, rq, on);
> +	case PTP_CLK_REQ_PEROUT:
> +		return net_timer_enable_perout(priv, rq, on);
>  	default:
>  		return -EOPNOTSUPP;
>  	}
> @@ -308,9 +544,9 @@ static void netc_timer_adjust_period(struct netc_timer *priv, u64 period)
>  	tmr_ctrl = u32_replace_bits(old_tmr_ctrl, integral_period,
>  				    TMR_CTRL_TCLK_PERIOD);
>  	if (tmr_ctrl != old_tmr_ctrl) {
> -		netc_timer_disable_pps_fiper(priv);
> +		netc_timer_disable_fiper(priv);
>  		netc_timer_wr(priv, NETC_TMR_CTRL, tmr_ctrl);
> -		netc_timer_enable_pps_fiper(priv);
> +		netc_timer_enable_fiper(priv);
>  	}
>
>  	netc_timer_wr(priv, NETC_TMR_ADD, fractional_period);
> @@ -337,7 +573,7 @@ static int netc_timer_adjtime(struct ptp_clock_info *ptp, s64 delta)
>
>  	spin_lock_irqsave(&priv->lock, flags);
>
> -	netc_timer_disable_pps_fiper(priv);
> +	netc_timer_disable_fiper(priv);
>
>  	/* Adjusting TMROFF instead of TMR_CNT is that the timer
>  	 * counter keeps increasing during reading and writing
> @@ -347,7 +583,7 @@ static int netc_timer_adjtime(struct ptp_clock_info *ptp, s64 delta)
>  	tmr_off += delta;
>  	netc_timer_offset_write(priv, tmr_off);
>
> -	netc_timer_enable_pps_fiper(priv);
> +	netc_timer_enable_fiper(priv);
>
>  	spin_unlock_irqrestore(&priv->lock, flags);
>
> @@ -384,10 +620,10 @@ static int netc_timer_settime64(struct ptp_clock_info *ptp,
>
>  	spin_lock_irqsave(&priv->lock, flags);
>
> -	netc_timer_disable_pps_fiper(priv);
> +	netc_timer_disable_fiper(priv);
>  	netc_timer_offset_write(priv, 0);
>  	netc_timer_cnt_write(priv, ns);
> -	netc_timer_enable_pps_fiper(priv);
> +	netc_timer_enable_fiper(priv);
>
>  	spin_unlock_irqrestore(&priv->lock, flags);
>
> @@ -401,6 +637,7 @@ static const struct ptp_clock_info netc_timer_ptp_caps = {
>  	.n_pins		= 0,
>  	.n_alarm	= 2,
>  	.pps		= 1,
> +	.n_per_out	= 3,
>  	.adjfine	= netc_timer_adjfine,
>  	.adjtime	= netc_timer_adjtime,
>  	.gettimex64	= netc_timer_gettimex64,
> @@ -558,6 +795,9 @@ static irqreturn_t netc_timer_isr(int irq, void *data)
>  	if (tmr_event & TMR_TEVENT_ALMEN(0))
>  		netc_timer_alarm_write(priv, NETC_TMR_DEFAULT_ALARM, 0);
>
> +	if (tmr_event & TMR_TEVENT_ALMEN(1))
> +		netc_timer_alarm_write(priv, NETC_TMR_DEFAULT_ALARM, 1);
> +
>  	if (tmr_event & TMR_TEVENT_PPEN_ALL) {
>  		event.type = PTP_CLOCK_PPS;
>  		ptp_clock_event(priv->clock, &event);
> @@ -602,6 +842,15 @@ static void netc_timer_free_msix_irq(struct netc_timer *priv)
>  	pci_free_irq_vectors(pdev);
>  }
>
> +static int netc_timer_get_global_ip_rev(struct netc_timer *priv)
> +{
> +	u32 val;
> +
> +	val = netc_timer_rd(priv, NETC_GLOBAL_OFFSET + NETC_GLOBAL_IPBRR0);
> +
> +	return val & IPBRR0_IP_REV;
> +}
> +
>  static int netc_timer_probe(struct pci_dev *pdev,
>  			    const struct pci_device_id *id)
>  {
> @@ -614,12 +863,19 @@ static int netc_timer_probe(struct pci_dev *pdev,
>  		return err;
>
>  	priv = pci_get_drvdata(pdev);
> +	priv->revision = netc_timer_get_global_ip_rev(priv);
> +	if (priv->revision == NETC_REV_4_1)
> +		priv->fs_alarm_num = 1;
> +	else
> +		priv->fs_alarm_num = NETC_TMR_ALARM_NUM;
> +
>  	err = netc_timer_parse_dt(priv);
>  	if (err)
>  		goto timer_pci_remove;
>
>  	priv->caps = netc_timer_ptp_caps;
>  	priv->oclk_prsc = NETC_TMR_DEFAULT_PRSC;
> +	priv->pps_channel = NETC_TMR_INVALID_CHANNEL;
>  	spin_lock_init(&priv->lock);
>
>  	err = netc_timer_init_msix_irq(priv);
> --
> 2.34.1
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ