On 15.09.2022 01:39:43, Matej Vasilevski wrote: [...] > /* Check for big-endianity and set according IO-accessors */ > if ((ctucan_read32(priv, CTUCANFD_DEVICE_ID) & 0xFFFF) != CTUCANFD_ID) { > @@ -1425,6 +1582,49 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr, int irq, unsigne > > priv->can.clock.freq = can_clk_rate; > > + /* Obtain timestamping counter bit size */ > + timestamp_bit_size = FIELD_GET(REG_ERR_CAPT_TS_BITS, > + ctucan_read32(priv, CTUCANFD_ERR_CAPT)); > + > + /* The register value is actually bit_size - 1 */ > + if (timestamp_bit_size) { > + timestamp_bit_size += 1; > + } else { > + /* For 2.x versions of the IP core, we will assume 64-bit counter > + * if there was a 0 in the register. > + */ > + u32 version_reg = ctucan_read32(priv, CTUCANFD_DEVICE_ID); > + u32 major = FIELD_GET(REG_DEVICE_ID_VER_MAJOR, version_reg); > + > + if (major == 2) > + timestamp_bit_size = 64; > + else > + priv->timestamp_possible = false; > + } > + > + /* Setup conversion constants and work delay */ > + priv->cc.mask = CYCLECOUNTER_MASK(timestamp_bit_size); > + if (priv->timestamp_possible) { > + u64 max_cycles; > + u64 work_delay_ns; > + u32 maxsec = min_t(u32, CTUCANFD_MAX_WORK_DELAY_SEC, > + div_u64(priv->cc.mask, timestamp_freq)); > + > + priv->cc.read = ctucan_read_timestamp_cc_wrapper; > + clocks_calc_mult_shift(&priv->cc.mult, &priv->cc.shift, > + timestamp_freq, NSEC_PER_SEC, maxsec); > + > + /* shortened copy of clocks_calc_max_nsecs() */ > + max_cycles = div_u64(ULLONG_MAX, priv->cc.mult); > + max_cycles = min(max_cycles, priv->cc.mask); > + work_delay_ns = clocksource_cyc2ns(max_cycles, priv->cc.mult, > + priv->cc.shift) >> 1; I just ported the code to another driver with dynamic frequency and width. I noticed that the shift of 1 is not enough. With 2 it works. regards, MArc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung West/Dortmund | Phone: +49-231-2826-924 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |