Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: dsa: microchip: ptp: manipulating absolute time using ptp hw clock

This patch is used for reconstructing the absolute time from the 32bit
hardware time stamping value. The do_aux ioctl is used for reading the
ptp hardware clock and store it to global variable.
The timestamped value in tail tag during rx and register during tx are
32 bit value (2 bit seconds and 30 bit nanoseconds). The time taken to
read entire ptp clock will be time consuming. In order to speed up, the
software clock is maintained. This clock time will be added to 32 bit
timestamp to get the absolute time stamp.

Signed-off-by: Christian Eggers <ceggers@arri.de>
Co-developed-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Christian Eggers and committed by
David S. Miller
bb01ad30 c2977c61

+62 -1
+59 -1
drivers/net/dsa/microchip/ksz_ptp.c
··· 28 28 static int ksz_ptp_enable_mode(struct ksz_device *dev) 29 29 { 30 30 struct ksz_tagger_data *tagger_data = ksz_tagger_data(dev->ds); 31 + struct ksz_ptp_data *ptp_data = &dev->ptp_data; 31 32 struct ksz_port *prt; 32 33 struct dsa_port *dp; 33 34 bool tag_en = false; 35 + int ret; 34 36 35 37 dsa_switch_for_each_user_port(dp, dev->ds) { 36 38 prt = &dev->ports[dp->index]; ··· 40 38 tag_en = true; 41 39 break; 42 40 } 41 + } 42 + 43 + if (tag_en) { 44 + ret = ptp_schedule_worker(ptp_data->clock, 0); 45 + if (ret) 46 + return ret; 47 + } else { 48 + ptp_cancel_worker_sync(ptp_data->clock); 43 49 } 44 50 45 51 tagger_data->hwtstamp_set_state(dev->ds, tag_en); ··· 231 221 goto unlock; 232 222 233 223 ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_LOAD_TIME, PTP_LOAD_TIME); 224 + if (ret) 225 + goto unlock; 226 + 227 + spin_lock_bh(&ptp_data->clock_lock); 228 + ptp_data->clock_time = *ts; 229 + spin_unlock_bh(&ptp_data->clock_lock); 234 230 235 231 unlock: 236 232 mutex_unlock(&ptp_data->lock); ··· 287 271 { 288 272 struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp); 289 273 struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data); 274 + struct timespec64 delta64 = ns_to_timespec64(delta); 290 275 s32 sec, nsec; 291 276 u16 data16; 292 277 int ret; ··· 320 303 data16 |= PTP_STEP_DIR; 321 304 322 305 ret = ksz_write16(dev, REG_PTP_CLK_CTRL, data16); 306 + if (ret) 307 + goto unlock; 308 + 309 + spin_lock_bh(&ptp_data->clock_lock); 310 + ptp_data->clock_time = timespec64_add(ptp_data->clock_time, delta64); 311 + spin_unlock_bh(&ptp_data->clock_lock); 323 312 324 313 unlock: 325 314 mutex_unlock(&ptp_data->lock); 326 315 return ret; 327 316 } 328 317 318 + /* Function is pointer to the do_aux_work in the ptp_clock capability */ 319 + static long ksz_ptp_do_aux_work(struct ptp_clock_info *ptp) 320 + { 321 + struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp); 322 + struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data); 323 + struct timespec64 ts; 324 + int ret; 325 + 326 + mutex_lock(&ptp_data->lock); 327 + ret = _ksz_ptp_gettime(dev, &ts); 328 + if (ret) 329 + goto out; 330 + 331 + spin_lock_bh(&ptp_data->clock_lock); 332 + ptp_data->clock_time = ts; 333 + spin_unlock_bh(&ptp_data->clock_lock); 334 + 335 + out: 336 + mutex_unlock(&ptp_data->lock); 337 + 338 + return HZ; /* reschedule in 1 second */ 339 + } 340 + 329 341 static int ksz_ptp_start_clock(struct ksz_device *dev) 330 342 { 331 - return ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ENABLE, PTP_CLK_ENABLE); 343 + struct ksz_ptp_data *ptp_data = &dev->ptp_data; 344 + int ret; 345 + 346 + ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ENABLE, PTP_CLK_ENABLE); 347 + if (ret) 348 + return ret; 349 + 350 + ptp_data->clock_time.tv_sec = 0; 351 + ptp_data->clock_time.tv_nsec = 0; 352 + 353 + return 0; 332 354 } 333 355 334 356 int ksz_ptp_clock_register(struct dsa_switch *ds) ··· 378 322 379 323 ptp_data = &dev->ptp_data; 380 324 mutex_init(&ptp_data->lock); 325 + spin_lock_init(&ptp_data->clock_lock); 381 326 382 327 ptp_data->caps.owner = THIS_MODULE; 383 328 snprintf(ptp_data->caps.name, 16, "Microchip Clock"); ··· 387 330 ptp_data->caps.settime64 = ksz_ptp_settime; 388 331 ptp_data->caps.adjfine = ksz_ptp_adjfine; 389 332 ptp_data->caps.adjtime = ksz_ptp_adjtime; 333 + ptp_data->caps.do_aux_work = ksz_ptp_do_aux_work; 390 334 391 335 ret = ksz_ptp_start_clock(dev); 392 336 if (ret)
+3
drivers/net/dsa/microchip/ksz_ptp.h
··· 17 17 struct ptp_clock *clock; 18 18 /* Serializes all operations on the PTP hardware clock */ 19 19 struct mutex lock; 20 + /* lock for accessing the clock_time */ 21 + spinlock_t clock_lock; 22 + struct timespec64 clock_time; 20 23 }; 21 24 22 25 int ksz_ptp_clock_register(struct dsa_switch *ds);