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_start, ts_period; 188 enum ocelot_ptp_pins ptp_pin; 189 unsigned long flags; 190 bool pps = false; 191 int pin = -1; 192 u32 val; 193 s64 ns; 194 195 switch (rq->type) { 196 case PTP_CLK_REQ_PEROUT: 197 /* Reject requests with unsupported flags */ 198 if (rq->perout.flags) 199 return -EOPNOTSUPP; 200 201 pin = ptp_find_pin(ocelot->ptp_clock, PTP_PF_PEROUT, 202 rq->perout.index); 203 if (pin == 0) 204 ptp_pin = PTP_PIN_0; 205 else if (pin == 1) 206 ptp_pin = PTP_PIN_1; 207 else if (pin == 2) 208 ptp_pin = PTP_PIN_2; 209 else if (pin == 3) 210 ptp_pin = PTP_PIN_3; 211 else 212 return -EBUSY; 213 214 ts_start.tv_sec = rq->perout.start.sec; 215 ts_start.tv_nsec = rq->perout.start.nsec; 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 if (ts_start.tv_sec || (ts_start.tv_nsec && !pps)) { 223 dev_warn(ocelot->dev, 224 "Absolute start time not supported!\n"); 225 dev_warn(ocelot->dev, 226 "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n"); 227 return -EINVAL; 228 } 229 230 /* Handle turning off */ 231 if (!on) { 232 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 233 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE); 234 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin); 235 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 236 break; 237 } 238 239 /* Handle PPS request */ 240 if (pps) { 241 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 242 /* Pulse generated perout.start.nsec after TOD has 243 * increased seconds. 244 * Pulse width is set to 1us. 245 */ 246 ocelot_write_rix(ocelot, ts_start.tv_nsec, 247 PTP_PIN_WF_LOW_PERIOD, ptp_pin); 248 ocelot_write_rix(ocelot, 1000, 249 PTP_PIN_WF_HIGH_PERIOD, ptp_pin); 250 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK); 251 val |= PTP_PIN_CFG_SYNC; 252 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin); 253 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 254 break; 255 } 256 257 /* Handle periodic clock */ 258 ns = timespec64_to_ns(&ts_period); 259 ns = ns >> 1; 260 if (ns > 0x3fffffff || ns <= 0x6) 261 return -EINVAL; 262 263 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags); 264 ocelot_write_rix(ocelot, ns, PTP_PIN_WF_LOW_PERIOD, ptp_pin); 265 ocelot_write_rix(ocelot, ns, PTP_PIN_WF_HIGH_PERIOD, ptp_pin); 266 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK); 267 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin); 268 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); 269 break; 270 default: 271 return -EOPNOTSUPP; 272 } 273 return 0; 274 } 275 EXPORT_SYMBOL(ocelot_ptp_enable); 276 277 int ocelot_init_timestamp(struct ocelot *ocelot, struct ptp_clock_info *info) 278 { 279 struct ptp_clock *ptp_clock; 280 int i; 281 282 ocelot->ptp_info = *info; 283 284 for (i = 0; i < OCELOT_PTP_PINS_NUM; i++) { 285 struct ptp_pin_desc *p = &ocelot->ptp_pins[i]; 286 287 snprintf(p->name, sizeof(p->name), "switch_1588_dat%d", i); 288 p->index = i; 289 p->func = PTP_PF_NONE; 290 } 291 292 ocelot->ptp_info.pin_config = &ocelot->ptp_pins[0]; 293 294 ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev); 295 if (IS_ERR(ptp_clock)) 296 return PTR_ERR(ptp_clock); 297 /* Check if PHC support is missing at the configuration level */ 298 if (!ptp_clock) 299 return 0; 300 301 ocelot->ptp_clock = ptp_clock; 302 303 ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG); 304 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW); 305 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH); 306 307 ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC); 308 309 /* There is no device reconfiguration, PTP Rx stamping is always 310 * enabled. 311 */ 312 ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 313 314 return 0; 315 } 316 EXPORT_SYMBOL(ocelot_init_timestamp); 317 318 int ocelot_deinit_timestamp(struct ocelot *ocelot) 319 { 320 if (ocelot->ptp_clock) 321 ptp_clock_unregister(ocelot->ptp_clock); 322 return 0; 323 } 324 EXPORT_SYMBOL(ocelot_deinit_timestamp); 325