1 // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 /* Microsemi Ocelot PTP clock driver 3 * 4 * Copyright (c) 2017 Microsemi Corporation 5 * Copyright 2020 NXP 6 */ 7 #include <soc/mscc/ocelot_ptp.h> 8 #include <soc/mscc/ocelot_sys.h> 9 #include <soc/mscc/ocelot.h> 10 11 int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts) 12 { 13 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info); 14 unsigned long flags; 15 time64_t s; 16 u32 val; 17 s64 ns; 18 19 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 20 21 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN); 22 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM); 23 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE); 24 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN); 25 26 s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff; 27 s <<= 32; 28 s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN); 29 ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN); 30 31 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 32 33 /* Deal with negative values */ 34 if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) { 35 s--; 36 ns &= 0xf; 37 ns += 999999984; 38 } 39 40 set_normalized_timespec64(ts, s, ns); 41 return 0; 42 } 43 EXPORT_SYMBOL(ocelot_ptp_gettime64); 44 45 int ocelot_ptp_settime64(struct ptp_clock_info *ptp, 46 const struct timespec64 *ts) 47 { 48 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info); 49 unsigned long flags; 50 u32 val; 51 52 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 53 54 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN); 55 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM); 56 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE); 57 58 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN); 59 60 ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB, 61 TOD_ACC_PIN); 62 ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB, 63 TOD_ACC_PIN); 64 ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN); 65 66 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN); 67 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM); 68 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD); 69 70 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN); 71 72 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 73 return 0; 74 } 75 EXPORT_SYMBOL(ocelot_ptp_settime64); 76 77 int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) 78 { 79 if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) { 80 struct ocelot *ocelot = container_of(ptp, struct ocelot, 81 ptp_info); 82 unsigned long flags; 83 u32 val; 84 85 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 86 87 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN); 88 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | 89 PTP_PIN_CFG_DOM); 90 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE); 91 92 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN); 93 94 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN); 95 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN); 96 ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN); 97 98 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN); 99 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | 100 PTP_PIN_CFG_DOM); 101 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA); 102 103 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN); 104 105 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 106 } else { 107 /* Fall back using ocelot_ptp_settime64 which is not exact. */ 108 struct timespec64 ts; 109 u64 now; 110 111 ocelot_ptp_gettime64(ptp, &ts); 112 113 now = ktime_to_ns(timespec64_to_ktime(ts)); 114 ts = ns_to_timespec64(now + delta); 115 116 ocelot_ptp_settime64(ptp, &ts); 117 } 118 return 0; 119 } 120 EXPORT_SYMBOL(ocelot_ptp_adjtime); 121 122 int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) 123 { 124 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info); 125 u32 unit = 0, direction = 0; 126 unsigned long flags; 127 u64 adj = 0; 128 129 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 130 131 if (!scaled_ppm) 132 goto disable_adj; 133 134 if (scaled_ppm < 0) { 135 direction = PTP_CFG_CLK_ADJ_CFG_DIR; 136 scaled_ppm = -scaled_ppm; 137 } 138 139 adj = PSEC_PER_SEC << 16; 140 do_div(adj, scaled_ppm); 141 do_div(adj, 1000); 142 143 /* If the adjustment value is too large, use ns instead */ 144 if (adj >= (1L << 30)) { 145 unit = PTP_CFG_CLK_ADJ_FREQ_NS; 146 do_div(adj, 1000); 147 } 148 149 /* Still too big */ 150 if (adj >= (1L << 30)) 151 goto disable_adj; 152 153 ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ); 154 ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction, 155 PTP_CLK_CFG_ADJ_CFG); 156 157 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 158 return 0; 159 160 disable_adj: 161 ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG); 162 163 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 164 return 0; 165 } 166 EXPORT_SYMBOL(ocelot_ptp_adjfine); 167 168 int ocelot_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, 169 enum ptp_pin_function func, unsigned int chan) 170 { 171 switch (func) { 172 case PTP_PF_NONE: 173 case PTP_PF_PEROUT: 174 break; 175 case PTP_PF_EXTTS: 176 case PTP_PF_PHYSYNC: 177 return -1; 178 } 179 return 0; 180 } 181 EXPORT_SYMBOL(ocelot_ptp_verify); 182 183 int ocelot_ptp_enable(struct ptp_clock_info *ptp, 184 struct ptp_clock_request *rq, int on) 185 { 186 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info); 187 struct timespec64 ts_phase, ts_period; 188 enum ocelot_ptp_pins ptp_pin; 189 unsigned long flags; 190 bool pps = false; 191 int pin = -1; 192 s64 wf_high; 193 s64 wf_low; 194 u32 val; 195 196 switch (rq->type) { 197 case PTP_CLK_REQ_PEROUT: 198 /* Reject requests with unsupported flags */ 199 if (rq->perout.flags & ~(PTP_PEROUT_DUTY_CYCLE | 200 PTP_PEROUT_PHASE)) 201 return -EOPNOTSUPP; 202 203 pin = ptp_find_pin(ocelot->ptp_clock, PTP_PF_PEROUT, 204 rq->perout.index); 205 if (pin == 0) 206 ptp_pin = PTP_PIN_0; 207 else if (pin == 1) 208 ptp_pin = PTP_PIN_1; 209 else if (pin == 2) 210 ptp_pin = PTP_PIN_2; 211 else if (pin == 3) 212 ptp_pin = PTP_PIN_3; 213 else 214 return -EBUSY; 215 216 ts_period.tv_sec = rq->perout.period.sec; 217 ts_period.tv_nsec = rq->perout.period.nsec; 218 219 if (ts_period.tv_sec == 1 && ts_period.tv_nsec == 0) 220 pps = true; 221 222 /* Handle turning off */ 223 if (!on) { 224 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 225 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE); 226 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin); 227 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 228 break; 229 } 230 231 if (rq->perout.flags & PTP_PEROUT_PHASE) { 232 ts_phase.tv_sec = rq->perout.phase.sec; 233 ts_phase.tv_nsec = rq->perout.phase.nsec; 234 } else { 235 /* Compatibility */ 236 ts_phase.tv_sec = rq->perout.start.sec; 237 ts_phase.tv_nsec = rq->perout.start.nsec; 238 } 239 if (ts_phase.tv_sec || (ts_phase.tv_nsec && !pps)) { 240 dev_warn(ocelot->dev, 241 "Absolute start time not supported!\n"); 242 dev_warn(ocelot->dev, 243 "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n"); 244 return -EINVAL; 245 } 246 247 /* Calculate waveform high and low times */ 248 if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) { 249 struct timespec64 ts_on; 250 251 ts_on.tv_sec = rq->perout.on.sec; 252 ts_on.tv_nsec = rq->perout.on.nsec; 253 254 wf_high = timespec64_to_ns(&ts_on); 255 } else { 256 if (pps) { 257 wf_high = 1000; 258 } else { 259 wf_high = timespec64_to_ns(&ts_period); 260 wf_high = div_s64(wf_high, 2); 261 } 262 } 263 264 wf_low = timespec64_to_ns(&ts_period); 265 wf_low -= wf_high; 266 267 /* Handle PPS request */ 268 if (pps) { 269 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 270 ocelot_write_rix(ocelot, ts_phase.tv_nsec, 271 PTP_PIN_WF_LOW_PERIOD, ptp_pin); 272 ocelot_write_rix(ocelot, wf_high, 273 PTP_PIN_WF_HIGH_PERIOD, ptp_pin); 274 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK); 275 val |= PTP_PIN_CFG_SYNC; 276 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin); 277 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 278 break; 279 } 280 281 /* Handle periodic clock */ 282 if (wf_high > 0x3fffffff || wf_high <= 0x6) 283 return -EINVAL; 284 if (wf_low > 0x3fffffff || wf_low <= 0x6) 285 return -EINVAL; 286 287 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 288 ocelot_write_rix(ocelot, wf_low, PTP_PIN_WF_LOW_PERIOD, 289 ptp_pin); 290 ocelot_write_rix(ocelot, wf_high, PTP_PIN_WF_HIGH_PERIOD, 291 ptp_pin); 292 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK); 293 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin); 294 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 295 break; 296 default: 297 return -EOPNOTSUPP; 298 } 299 return 0; 300 } 301 EXPORT_SYMBOL(ocelot_ptp_enable); 302 303 int ocelot_init_timestamp(struct ocelot *ocelot, 304 const struct ptp_clock_info *info) 305 { 306 struct ptp_clock *ptp_clock; 307 int i; 308 309 ocelot->ptp_info = *info; 310 311 for (i = 0; i < OCELOT_PTP_PINS_NUM; i++) { 312 struct ptp_pin_desc *p = &ocelot->ptp_pins[i]; 313 314 snprintf(p->name, sizeof(p->name), "switch_1588_dat%d", i); 315 p->index = i; 316 p->func = PTP_PF_NONE; 317 } 318 319 ocelot->ptp_info.pin_config = &ocelot->ptp_pins[0]; 320 321 ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev); 322 if (IS_ERR(ptp_clock)) 323 return PTR_ERR(ptp_clock); 324 /* Check if PHC support is missing at the configuration level */ 325 if (!ptp_clock) 326 return 0; 327 328 ocelot->ptp_clock = ptp_clock; 329 330 ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG); 331 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW); 332 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH); 333 334 ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC); 335 336 /* There is no device reconfiguration, PTP Rx stamping is always 337 * enabled. 338 */ 339 ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 340 341 return 0; 342 } 343 EXPORT_SYMBOL(ocelot_init_timestamp); 344 345 int ocelot_deinit_timestamp(struct ocelot *ocelot) 346 { 347 if (ocelot->ptp_clock) 348 ptp_clock_unregister(ocelot->ptp_clock); 349 return 0; 350 } 351 EXPORT_SYMBOL(ocelot_deinit_timestamp); 352