Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
0002 /* Microsemi Ocelot PTP clock driver
0003  *
0004  * Copyright (c) 2017 Microsemi Corporation
0005  * Copyright 2020 NXP
0006  */
0007 #include <linux/time64.h>
0008 
0009 #include <soc/mscc/ocelot_ptp.h>
0010 #include <soc/mscc/ocelot_sys.h>
0011 #include <soc/mscc/ocelot.h>
0012 
0013 int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
0014 {
0015     struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0016     unsigned long flags;
0017     time64_t s;
0018     u32 val;
0019     s64 ns;
0020 
0021     spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0022 
0023     val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0024     val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
0025     val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
0026     ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0027 
0028     s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
0029     s <<= 32;
0030     s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
0031     ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
0032 
0033     spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0034 
0035     /* Deal with negative values */
0036     if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
0037         s--;
0038         ns &= 0xf;
0039         ns += 999999984;
0040     }
0041 
0042     set_normalized_timespec64(ts, s, ns);
0043     return 0;
0044 }
0045 EXPORT_SYMBOL(ocelot_ptp_gettime64);
0046 
0047 int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
0048              const struct timespec64 *ts)
0049 {
0050     struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0051     unsigned long flags;
0052     u32 val;
0053 
0054     spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0055 
0056     val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0057     val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
0058     val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
0059 
0060     ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0061 
0062     ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
0063              TOD_ACC_PIN);
0064     ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
0065              TOD_ACC_PIN);
0066     ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
0067 
0068     val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0069     val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
0070     val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
0071 
0072     ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0073 
0074     spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0075 
0076     if (ocelot->ops->tas_clock_adjust)
0077         ocelot->ops->tas_clock_adjust(ocelot);
0078 
0079     return 0;
0080 }
0081 EXPORT_SYMBOL(ocelot_ptp_settime64);
0082 
0083 int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
0084 {
0085     if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
0086         struct ocelot *ocelot = container_of(ptp, struct ocelot,
0087                              ptp_info);
0088         unsigned long flags;
0089         u32 val;
0090 
0091         spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0092 
0093         val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0094         val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
0095              PTP_PIN_CFG_DOM);
0096         val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
0097 
0098         ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0099 
0100         ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
0101         ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
0102         ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
0103 
0104         val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0105         val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
0106              PTP_PIN_CFG_DOM);
0107         val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
0108 
0109         ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0110 
0111         spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0112 
0113         if (ocelot->ops->tas_clock_adjust)
0114             ocelot->ops->tas_clock_adjust(ocelot);
0115     } else {
0116         /* Fall back using ocelot_ptp_settime64 which is not exact. */
0117         struct timespec64 ts;
0118         u64 now;
0119 
0120         ocelot_ptp_gettime64(ptp, &ts);
0121 
0122         now = ktime_to_ns(timespec64_to_ktime(ts));
0123         ts = ns_to_timespec64(now + delta);
0124 
0125         ocelot_ptp_settime64(ptp, &ts);
0126     }
0127 
0128     return 0;
0129 }
0130 EXPORT_SYMBOL(ocelot_ptp_adjtime);
0131 
0132 int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
0133 {
0134     struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0135     u32 unit = 0, direction = 0;
0136     unsigned long flags;
0137     u64 adj = 0;
0138 
0139     spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0140 
0141     if (!scaled_ppm)
0142         goto disable_adj;
0143 
0144     if (scaled_ppm < 0) {
0145         direction = PTP_CFG_CLK_ADJ_CFG_DIR;
0146         scaled_ppm = -scaled_ppm;
0147     }
0148 
0149     adj = PSEC_PER_SEC << 16;
0150     do_div(adj, scaled_ppm);
0151     do_div(adj, 1000);
0152 
0153     /* If the adjustment value is too large, use ns instead */
0154     if (adj >= (1L << 30)) {
0155         unit = PTP_CFG_CLK_ADJ_FREQ_NS;
0156         do_div(adj, 1000);
0157     }
0158 
0159     /* Still too big */
0160     if (adj >= (1L << 30))
0161         goto disable_adj;
0162 
0163     ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
0164     ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
0165              PTP_CLK_CFG_ADJ_CFG);
0166 
0167     spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0168     return 0;
0169 
0170 disable_adj:
0171     ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
0172 
0173     spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0174     return 0;
0175 }
0176 EXPORT_SYMBOL(ocelot_ptp_adjfine);
0177 
0178 int ocelot_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
0179               enum ptp_pin_function func, unsigned int chan)
0180 {
0181     switch (func) {
0182     case PTP_PF_NONE:
0183     case PTP_PF_PEROUT:
0184         break;
0185     case PTP_PF_EXTTS:
0186     case PTP_PF_PHYSYNC:
0187         return -1;
0188     }
0189     return 0;
0190 }
0191 EXPORT_SYMBOL(ocelot_ptp_verify);
0192 
0193 int ocelot_ptp_enable(struct ptp_clock_info *ptp,
0194               struct ptp_clock_request *rq, int on)
0195 {
0196     struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0197     struct timespec64 ts_phase, ts_period;
0198     enum ocelot_ptp_pins ptp_pin;
0199     unsigned long flags;
0200     bool pps = false;
0201     int pin = -1;
0202     s64 wf_high;
0203     s64 wf_low;
0204     u32 val;
0205 
0206     switch (rq->type) {
0207     case PTP_CLK_REQ_PEROUT:
0208         /* Reject requests with unsupported flags */
0209         if (rq->perout.flags & ~(PTP_PEROUT_DUTY_CYCLE |
0210                      PTP_PEROUT_PHASE))
0211             return -EOPNOTSUPP;
0212 
0213         pin = ptp_find_pin(ocelot->ptp_clock, PTP_PF_PEROUT,
0214                    rq->perout.index);
0215         if (pin == 0)
0216             ptp_pin = PTP_PIN_0;
0217         else if (pin == 1)
0218             ptp_pin = PTP_PIN_1;
0219         else if (pin == 2)
0220             ptp_pin = PTP_PIN_2;
0221         else if (pin == 3)
0222             ptp_pin = PTP_PIN_3;
0223         else
0224             return -EBUSY;
0225 
0226         ts_period.tv_sec = rq->perout.period.sec;
0227         ts_period.tv_nsec = rq->perout.period.nsec;
0228 
0229         if (ts_period.tv_sec == 1 && ts_period.tv_nsec == 0)
0230             pps = true;
0231 
0232         /* Handle turning off */
0233         if (!on) {
0234             spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0235             val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
0236             ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
0237             spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0238             break;
0239         }
0240 
0241         if (rq->perout.flags & PTP_PEROUT_PHASE) {
0242             ts_phase.tv_sec = rq->perout.phase.sec;
0243             ts_phase.tv_nsec = rq->perout.phase.nsec;
0244         } else {
0245             /* Compatibility */
0246             ts_phase.tv_sec = rq->perout.start.sec;
0247             ts_phase.tv_nsec = rq->perout.start.nsec;
0248         }
0249         if (ts_phase.tv_sec || (ts_phase.tv_nsec && !pps)) {
0250             dev_warn(ocelot->dev,
0251                  "Absolute start time not supported!\n");
0252             dev_warn(ocelot->dev,
0253                  "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n");
0254             return -EINVAL;
0255         }
0256 
0257         /* Calculate waveform high and low times */
0258         if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) {
0259             struct timespec64 ts_on;
0260 
0261             ts_on.tv_sec = rq->perout.on.sec;
0262             ts_on.tv_nsec = rq->perout.on.nsec;
0263 
0264             wf_high = timespec64_to_ns(&ts_on);
0265         } else {
0266             if (pps) {
0267                 wf_high = 1000;
0268             } else {
0269                 wf_high = timespec64_to_ns(&ts_period);
0270                 wf_high = div_s64(wf_high, 2);
0271             }
0272         }
0273 
0274         wf_low = timespec64_to_ns(&ts_period);
0275         wf_low -= wf_high;
0276 
0277         /* Handle PPS request */
0278         if (pps) {
0279             spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0280             ocelot_write_rix(ocelot, ts_phase.tv_nsec,
0281                      PTP_PIN_WF_LOW_PERIOD, ptp_pin);
0282             ocelot_write_rix(ocelot, wf_high,
0283                      PTP_PIN_WF_HIGH_PERIOD, ptp_pin);
0284             val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
0285             val |= PTP_PIN_CFG_SYNC;
0286             ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
0287             spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0288             break;
0289         }
0290 
0291         /* Handle periodic clock */
0292         if (wf_high > 0x3fffffff || wf_high <= 0x6)
0293             return -EINVAL;
0294         if (wf_low > 0x3fffffff || wf_low <= 0x6)
0295             return -EINVAL;
0296 
0297         spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0298         ocelot_write_rix(ocelot, wf_low, PTP_PIN_WF_LOW_PERIOD,
0299                  ptp_pin);
0300         ocelot_write_rix(ocelot, wf_high, PTP_PIN_WF_HIGH_PERIOD,
0301                  ptp_pin);
0302         val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
0303         ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
0304         spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0305         break;
0306     default:
0307         return -EOPNOTSUPP;
0308     }
0309     return 0;
0310 }
0311 EXPORT_SYMBOL(ocelot_ptp_enable);
0312 
0313 int ocelot_init_timestamp(struct ocelot *ocelot,
0314               const struct ptp_clock_info *info)
0315 {
0316     struct ptp_clock *ptp_clock;
0317     int i;
0318 
0319     ocelot->ptp_info = *info;
0320 
0321     for (i = 0; i < OCELOT_PTP_PINS_NUM; i++) {
0322         struct ptp_pin_desc *p = &ocelot->ptp_pins[i];
0323 
0324         snprintf(p->name, sizeof(p->name), "switch_1588_dat%d", i);
0325         p->index = i;
0326         p->func = PTP_PF_NONE;
0327     }
0328 
0329     ocelot->ptp_info.pin_config = &ocelot->ptp_pins[0];
0330 
0331     ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
0332     if (IS_ERR(ptp_clock))
0333         return PTR_ERR(ptp_clock);
0334     /* Check if PHC support is missing at the configuration level */
0335     if (!ptp_clock)
0336         return 0;
0337 
0338     ocelot->ptp_clock = ptp_clock;
0339 
0340     ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
0341     ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
0342     ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
0343 
0344     ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
0345 
0346     /* There is no device reconfiguration, PTP Rx stamping is always
0347      * enabled.
0348      */
0349     ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
0350 
0351     return 0;
0352 }
0353 EXPORT_SYMBOL(ocelot_init_timestamp);
0354 
0355 int ocelot_deinit_timestamp(struct ocelot *ocelot)
0356 {
0357     if (ocelot->ptp_clock)
0358         ptp_clock_unregister(ocelot->ptp_clock);
0359     return 0;
0360 }
0361 EXPORT_SYMBOL(ocelot_deinit_timestamp);