Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Marvell PP2.2 TAI support
0004  *
0005  * Note:
0006  *   Do NOT use the event capture support.
0007  *   Do Not even set the MPP muxes to allow PTP_EVENT_REQ to be used.
0008  *   It will disrupt the operation of this driver, and there is nothing
0009  *   that this driver can do to prevent that.  Even using PTP_EVENT_REQ
0010  *   as an output will be seen as a trigger input, which can't be masked.
0011  *   When ever a trigger input is seen, the action in the TCFCR0_TCF
0012  *   field will be performed - whether it is a set, increment, decrement
0013  *   read, or frequency update.
0014  *
0015  * Other notes (useful, not specified in the documentation):
0016  * - PTP_PULSE_OUT (PTP_EVENT_REQ MPP)
0017  *   It looks like the hardware can't generate a pulse at nsec=0. (The
0018  *   output doesn't trigger if the nsec field is zero.)
0019  *   Note: when configured as an output via the register at 0xfX441120,
0020  *   the input is still very much alive, and will trigger the current TCF
0021  *   function.
0022  * - PTP_CLK_OUT (PTP_TRIG_GEN MPP)
0023  *   This generates a "PPS" signal determined by the CCC registers. It
0024  *   seems this is not aligned to the TOD counter in any way (it may be
0025  *   initially, but if you specify a non-round second interval, it won't,
0026  *   and you can't easily get it back.)
0027  * - PTP_PCLK_OUT
0028  *   This generates a 50% duty cycle clock based on the TOD counter, and
0029  *   seems it can be set to any period of 1ns resolution. It is probably
0030  *   limited by the TOD step size. Its period is defined by the PCLK_CCC
0031  *   registers. Again, its alignment to the second is questionable.
0032  *
0033  * Consequently, we support none of these.
0034  */
0035 #include <linux/io.h>
0036 #include <linux/ptp_clock_kernel.h>
0037 #include <linux/slab.h>
0038 
0039 #include "mvpp2.h"
0040 
0041 #define CR0_SW_NRESET           BIT(0)
0042 
0043 #define TCFCR0_PHASE_UPDATE_ENABLE  BIT(8)
0044 #define TCFCR0_TCF_MASK         (7 << 2)
0045 #define TCFCR0_TCF_UPDATE       (0 << 2)
0046 #define TCFCR0_TCF_FREQUPDATE       (1 << 2)
0047 #define TCFCR0_TCF_INCREMENT        (2 << 2)
0048 #define TCFCR0_TCF_DECREMENT        (3 << 2)
0049 #define TCFCR0_TCF_CAPTURE      (4 << 2)
0050 #define TCFCR0_TCF_NOP          (7 << 2)
0051 #define TCFCR0_TCF_TRIGGER      BIT(0)
0052 
0053 #define TCSR_CAPTURE_1_VALID        BIT(1)
0054 #define TCSR_CAPTURE_0_VALID        BIT(0)
0055 
0056 struct mvpp2_tai {
0057     struct ptp_clock_info caps;
0058     struct ptp_clock *ptp_clock;
0059     void __iomem *base;
0060     spinlock_t lock;
0061     u64 period;     // nanosecond period in 32.32 fixed point
0062     /* This timestamp is updated every two seconds */
0063     struct timespec64 stamp;
0064 };
0065 
0066 static void mvpp2_tai_modify(void __iomem *reg, u32 mask, u32 set)
0067 {
0068     u32 val;
0069 
0070     val = readl_relaxed(reg) & ~mask;
0071     val |= set & mask;
0072     writel(val, reg);
0073 }
0074 
0075 static void mvpp2_tai_write(u32 val, void __iomem *reg)
0076 {
0077     writel_relaxed(val & 0xffff, reg);
0078 }
0079 
0080 static u32 mvpp2_tai_read(void __iomem *reg)
0081 {
0082     return readl_relaxed(reg) & 0xffff;
0083 }
0084 
0085 static struct mvpp2_tai *ptp_to_tai(struct ptp_clock_info *ptp)
0086 {
0087     return container_of(ptp, struct mvpp2_tai, caps);
0088 }
0089 
0090 static void mvpp22_tai_read_ts(struct timespec64 *ts, void __iomem *base)
0091 {
0092     ts->tv_sec = (u64)mvpp2_tai_read(base + 0) << 32 |
0093              mvpp2_tai_read(base + 4) << 16 |
0094              mvpp2_tai_read(base + 8);
0095 
0096     ts->tv_nsec = mvpp2_tai_read(base + 12) << 16 |
0097               mvpp2_tai_read(base + 16);
0098 
0099     /* Read and discard fractional part */
0100     readl_relaxed(base + 20);
0101     readl_relaxed(base + 24);
0102 }
0103 
0104 static void mvpp2_tai_write_tlv(const struct timespec64 *ts, u32 frac,
0105                     void __iomem *base)
0106 {
0107     mvpp2_tai_write(ts->tv_sec >> 32, base + MVPP22_TAI_TLV_SEC_HIGH);
0108     mvpp2_tai_write(ts->tv_sec >> 16, base + MVPP22_TAI_TLV_SEC_MED);
0109     mvpp2_tai_write(ts->tv_sec, base + MVPP22_TAI_TLV_SEC_LOW);
0110     mvpp2_tai_write(ts->tv_nsec >> 16, base + MVPP22_TAI_TLV_NANO_HIGH);
0111     mvpp2_tai_write(ts->tv_nsec, base + MVPP22_TAI_TLV_NANO_LOW);
0112     mvpp2_tai_write(frac >> 16, base + MVPP22_TAI_TLV_FRAC_HIGH);
0113     mvpp2_tai_write(frac, base + MVPP22_TAI_TLV_FRAC_LOW);
0114 }
0115 
0116 static void mvpp2_tai_op(u32 op, void __iomem *base)
0117 {
0118     /* Trigger the operation. Note that an external unmaskable
0119      * event on PTP_EVENT_REQ will also trigger this action.
0120      */
0121     mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0,
0122              TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER,
0123              op | TCFCR0_TCF_TRIGGER);
0124     mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK,
0125              TCFCR0_TCF_NOP);
0126 }
0127 
0128 /* The adjustment has a range of +0.5ns to -0.5ns in 2^32 steps, so has units
0129  * of 2^-32 ns.
0130  *
0131  * units(s) = 1 / (2^32 * 10^9)
0132  * fractional = abs_scaled_ppm / (2^16 * 10^6)
0133  *
0134  * What we want to achieve:
0135  *  freq_adjusted = freq_nominal * (1 + fractional)
0136  *  freq_delta = freq_adjusted - freq_nominal => positive = faster
0137  *  freq_delta = freq_nominal * (1 + fractional) - freq_nominal
0138  * So: freq_delta = freq_nominal * fractional
0139  *
0140  * However, we are dealing with periods, so:
0141  *  period_adjusted = period_nominal / (1 + fractional)
0142  *  period_delta = period_nominal - period_adjusted => positive = faster
0143  *  period_delta = period_nominal * fractional / (1 + fractional)
0144  *
0145  * Hence:
0146  *  period_delta = period_nominal * abs_scaled_ppm /
0147  *         (2^16 * 10^6 + abs_scaled_ppm)
0148  *
0149  * To avoid overflow, we reduce both sides of the divide operation by a factor
0150  * of 16.
0151  */
0152 static u64 mvpp22_calc_frac_ppm(struct mvpp2_tai *tai, long abs_scaled_ppm)
0153 {
0154     u64 val = tai->period * abs_scaled_ppm >> 4;
0155 
0156     return div_u64(val, (1000000 << 12) + (abs_scaled_ppm >> 4));
0157 }
0158 
0159 static s32 mvpp22_calc_max_adj(struct mvpp2_tai *tai)
0160 {
0161     return 1000000;
0162 }
0163 
0164 static int mvpp22_tai_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
0165 {
0166     struct mvpp2_tai *tai = ptp_to_tai(ptp);
0167     unsigned long flags;
0168     void __iomem *base;
0169     bool neg_adj;
0170     s32 frac;
0171     u64 val;
0172 
0173     neg_adj = scaled_ppm < 0;
0174     if (neg_adj)
0175         scaled_ppm = -scaled_ppm;
0176 
0177     val = mvpp22_calc_frac_ppm(tai, scaled_ppm);
0178 
0179     /* Convert to a signed 32-bit adjustment */
0180     if (neg_adj) {
0181         /* -S32_MIN warns, -val < S32_MIN fails, so go for the easy
0182          * solution.
0183          */
0184         if (val > 0x80000000)
0185             return -ERANGE;
0186 
0187         frac = -val;
0188     } else {
0189         if (val > S32_MAX)
0190             return -ERANGE;
0191 
0192         frac = val;
0193     }
0194 
0195     base = tai->base;
0196     spin_lock_irqsave(&tai->lock, flags);
0197     mvpp2_tai_write(frac >> 16, base + MVPP22_TAI_TLV_FRAC_HIGH);
0198     mvpp2_tai_write(frac, base + MVPP22_TAI_TLV_FRAC_LOW);
0199     mvpp2_tai_op(TCFCR0_TCF_FREQUPDATE, base);
0200     spin_unlock_irqrestore(&tai->lock, flags);
0201 
0202     return 0;
0203 }
0204 
0205 static int mvpp22_tai_adjtime(struct ptp_clock_info *ptp, s64 delta)
0206 {
0207     struct mvpp2_tai *tai = ptp_to_tai(ptp);
0208     struct timespec64 ts;
0209     unsigned long flags;
0210     void __iomem *base;
0211     u32 tcf;
0212 
0213     /* We can't deal with S64_MIN */
0214     if (delta == S64_MIN)
0215         return -ERANGE;
0216 
0217     if (delta < 0) {
0218         delta = -delta;
0219         tcf = TCFCR0_TCF_DECREMENT;
0220     } else {
0221         tcf = TCFCR0_TCF_INCREMENT;
0222     }
0223 
0224     ts = ns_to_timespec64(delta);
0225 
0226     base = tai->base;
0227     spin_lock_irqsave(&tai->lock, flags);
0228     mvpp2_tai_write_tlv(&ts, 0, base);
0229     mvpp2_tai_op(tcf, base);
0230     spin_unlock_irqrestore(&tai->lock, flags);
0231 
0232     return 0;
0233 }
0234 
0235 static int mvpp22_tai_gettimex64(struct ptp_clock_info *ptp,
0236                  struct timespec64 *ts,
0237                  struct ptp_system_timestamp *sts)
0238 {
0239     struct mvpp2_tai *tai = ptp_to_tai(ptp);
0240     unsigned long flags;
0241     void __iomem *base;
0242     u32 tcsr;
0243     int ret;
0244 
0245     base = tai->base;
0246     spin_lock_irqsave(&tai->lock, flags);
0247     /* XXX: the only way to read the PTP time is for the CPU to trigger
0248      * an event. However, there is no way to distinguish between the CPU
0249      * triggered event, and an external event on PTP_EVENT_REQ. So this
0250      * is incompatible with external use of PTP_EVENT_REQ.
0251      */
0252     ptp_read_system_prets(sts);
0253     mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0,
0254              TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER,
0255              TCFCR0_TCF_CAPTURE | TCFCR0_TCF_TRIGGER);
0256     ptp_read_system_postts(sts);
0257     mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK,
0258              TCFCR0_TCF_NOP);
0259 
0260     tcsr = readl(base + MVPP22_TAI_TCSR);
0261     if (tcsr & TCSR_CAPTURE_1_VALID) {
0262         mvpp22_tai_read_ts(ts, base + MVPP22_TAI_TCV1_SEC_HIGH);
0263         ret = 0;
0264     } else if (tcsr & TCSR_CAPTURE_0_VALID) {
0265         mvpp22_tai_read_ts(ts, base + MVPP22_TAI_TCV0_SEC_HIGH);
0266         ret = 0;
0267     } else {
0268         /* We don't seem to have a reading... */
0269         ret = -EBUSY;
0270     }
0271     spin_unlock_irqrestore(&tai->lock, flags);
0272 
0273     return ret;
0274 }
0275 
0276 static int mvpp22_tai_settime64(struct ptp_clock_info *ptp,
0277                 const struct timespec64 *ts)
0278 {
0279     struct mvpp2_tai *tai = ptp_to_tai(ptp);
0280     unsigned long flags;
0281     void __iomem *base;
0282 
0283     base = tai->base;
0284     spin_lock_irqsave(&tai->lock, flags);
0285     mvpp2_tai_write_tlv(ts, 0, base);
0286 
0287     /* Trigger an update to load the value from the TLV registers
0288      * into the TOD counter. Note that an external unmaskable event on
0289      * PTP_EVENT_REQ will also trigger this action.
0290      */
0291     mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0,
0292              TCFCR0_PHASE_UPDATE_ENABLE |
0293              TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER,
0294              TCFCR0_TCF_UPDATE | TCFCR0_TCF_TRIGGER);
0295     mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK,
0296              TCFCR0_TCF_NOP);
0297     spin_unlock_irqrestore(&tai->lock, flags);
0298 
0299     return 0;
0300 }
0301 
0302 static long mvpp22_tai_aux_work(struct ptp_clock_info *ptp)
0303 {
0304     struct mvpp2_tai *tai = ptp_to_tai(ptp);
0305 
0306     mvpp22_tai_gettimex64(ptp, &tai->stamp, NULL);
0307 
0308     return msecs_to_jiffies(2000);
0309 }
0310 
0311 static void mvpp22_tai_set_step(struct mvpp2_tai *tai)
0312 {
0313     void __iomem *base = tai->base;
0314     u32 nano, frac;
0315 
0316     nano = upper_32_bits(tai->period);
0317     frac = lower_32_bits(tai->period);
0318 
0319     /* As the fractional nanosecond is a signed offset, if the MSB (sign)
0320      * bit is set, we have to increment the whole nanoseconds.
0321      */
0322     if (frac >= 0x80000000)
0323         nano += 1;
0324 
0325     mvpp2_tai_write(nano, base + MVPP22_TAI_TOD_STEP_NANO_CR);
0326     mvpp2_tai_write(frac >> 16, base + MVPP22_TAI_TOD_STEP_FRAC_HIGH);
0327     mvpp2_tai_write(frac, base + MVPP22_TAI_TOD_STEP_FRAC_LOW);
0328 }
0329 
0330 static void mvpp22_tai_init(struct mvpp2_tai *tai)
0331 {
0332     void __iomem *base = tai->base;
0333 
0334     mvpp22_tai_set_step(tai);
0335 
0336     /* Release the TAI reset */
0337     mvpp2_tai_modify(base + MVPP22_TAI_CR0, CR0_SW_NRESET, CR0_SW_NRESET);
0338 }
0339 
0340 int mvpp22_tai_ptp_clock_index(struct mvpp2_tai *tai)
0341 {
0342     return ptp_clock_index(tai->ptp_clock);
0343 }
0344 
0345 void mvpp22_tai_tstamp(struct mvpp2_tai *tai, u32 tstamp,
0346                struct skb_shared_hwtstamps *hwtstamp)
0347 {
0348     struct timespec64 ts;
0349     int delta;
0350 
0351     /* The tstamp consists of 2 bits of seconds and 30 bits of nanoseconds.
0352      * We use our stored timestamp (tai->stamp) to form a full timestamp,
0353      * and we must read the seconds exactly once.
0354      */
0355     ts.tv_sec = READ_ONCE(tai->stamp.tv_sec);
0356     ts.tv_nsec = tstamp & 0x3fffffff;
0357 
0358     /* Calculate the delta in seconds between our stored timestamp and
0359      * the value read from the queue. Allow timestamps one second in the
0360      * past, otherwise consider them to be in the future.
0361      */
0362     delta = ((tstamp >> 30) - (ts.tv_sec & 3)) & 3;
0363     if (delta == 3)
0364         delta -= 4;
0365     ts.tv_sec += delta;
0366 
0367     memset(hwtstamp, 0, sizeof(*hwtstamp));
0368     hwtstamp->hwtstamp = timespec64_to_ktime(ts);
0369 }
0370 
0371 void mvpp22_tai_start(struct mvpp2_tai *tai)
0372 {
0373     long delay;
0374 
0375     delay = mvpp22_tai_aux_work(&tai->caps);
0376 
0377     ptp_schedule_worker(tai->ptp_clock, delay);
0378 }
0379 
0380 void mvpp22_tai_stop(struct mvpp2_tai *tai)
0381 {
0382     ptp_cancel_worker_sync(tai->ptp_clock);
0383 }
0384 
0385 static void mvpp22_tai_remove(void *priv)
0386 {
0387     struct mvpp2_tai *tai = priv;
0388 
0389     if (!IS_ERR(tai->ptp_clock))
0390         ptp_clock_unregister(tai->ptp_clock);
0391 }
0392 
0393 int mvpp22_tai_probe(struct device *dev, struct mvpp2 *priv)
0394 {
0395     struct mvpp2_tai *tai;
0396     int ret;
0397 
0398     tai = devm_kzalloc(dev, sizeof(*tai), GFP_KERNEL);
0399     if (!tai)
0400         return -ENOMEM;
0401 
0402     spin_lock_init(&tai->lock);
0403 
0404     tai->base = priv->iface_base;
0405 
0406     /* The step size consists of three registers - a 16-bit nanosecond step
0407      * size, and a 32-bit fractional nanosecond step size split over two
0408      * registers. The fractional nanosecond step size has units of 2^-32ns.
0409      *
0410      * To calculate this, we calculate:
0411      *   (10^9 + freq / 2) / (freq * 2^-32)
0412      * which gives us the nanosecond step to the nearest integer in 16.32
0413      * fixed point format, and the fractional part of the step size with
0414      * the MSB inverted.  With rounding of the fractional nanosecond, and
0415      * simplification, this becomes:
0416      *   (10^9 << 32 + freq << 31 + (freq + 1) >> 1) / freq
0417      *
0418      * So:
0419      *   div = (10^9 << 32 + freq << 31 + (freq + 1) >> 1) / freq
0420      *   nano = upper_32_bits(div);
0421      *   frac = lower_32_bits(div) ^ 0x80000000;
0422      * Will give the values for the registers.
0423      *
0424      * This is all seems perfect, but alas it is not when considering the
0425      * whole story.  The system is clocked from 25MHz, which is multiplied
0426      * by a PLL to 1GHz, and then divided by three, giving 333333333Hz
0427      * (recurring).  This gives exactly 3ns, but using 333333333Hz with
0428      * the above gives an error of 13*2^-32ns.
0429      *
0430      * Consequently, we use the period rather than calculating from the
0431      * frequency.
0432      */
0433     tai->period = 3ULL << 32;
0434 
0435     mvpp22_tai_init(tai);
0436 
0437     tai->caps.owner = THIS_MODULE;
0438     strscpy(tai->caps.name, "Marvell PP2.2", sizeof(tai->caps.name));
0439     tai->caps.max_adj = mvpp22_calc_max_adj(tai);
0440     tai->caps.adjfine = mvpp22_tai_adjfine;
0441     tai->caps.adjtime = mvpp22_tai_adjtime;
0442     tai->caps.gettimex64 = mvpp22_tai_gettimex64;
0443     tai->caps.settime64 = mvpp22_tai_settime64;
0444     tai->caps.do_aux_work = mvpp22_tai_aux_work;
0445 
0446     ret = devm_add_action(dev, mvpp22_tai_remove, tai);
0447     if (ret)
0448         return ret;
0449 
0450     tai->ptp_clock = ptp_clock_register(&tai->caps, dev);
0451     if (IS_ERR(tai->ptp_clock))
0452         return PTR_ERR(tai->ptp_clock);
0453 
0454     priv->tai = tai;
0455 
0456     return 0;
0457 }