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.

at v3.1-rc6 583 lines 16 kB view raw
1/* 2 * PTP 1588 clock using the eTSEC 3 * 4 * Copyright (C) 2010 OMICRON electronics GmbH 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20#include <linux/device.h> 21#include <linux/hrtimer.h> 22#include <linux/init.h> 23#include <linux/interrupt.h> 24#include <linux/kernel.h> 25#include <linux/module.h> 26#include <linux/of.h> 27#include <linux/of_platform.h> 28#include <linux/timex.h> 29#include <linux/io.h> 30 31#include <linux/ptp_clock_kernel.h> 32 33#include "gianfar.h" 34 35/* 36 * gianfar ptp registers 37 * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010 38 */ 39struct gianfar_ptp_registers { 40 u32 tmr_ctrl; /* Timer control register */ 41 u32 tmr_tevent; /* Timestamp event register */ 42 u32 tmr_temask; /* Timer event mask register */ 43 u32 tmr_pevent; /* Timestamp event register */ 44 u32 tmr_pemask; /* Timer event mask register */ 45 u32 tmr_stat; /* Timestamp status register */ 46 u32 tmr_cnt_h; /* Timer counter high register */ 47 u32 tmr_cnt_l; /* Timer counter low register */ 48 u32 tmr_add; /* Timer drift compensation addend register */ 49 u32 tmr_acc; /* Timer accumulator register */ 50 u32 tmr_prsc; /* Timer prescale */ 51 u8 res1[4]; 52 u32 tmroff_h; /* Timer offset high */ 53 u32 tmroff_l; /* Timer offset low */ 54 u8 res2[8]; 55 u32 tmr_alarm1_h; /* Timer alarm 1 high register */ 56 u32 tmr_alarm1_l; /* Timer alarm 1 high register */ 57 u32 tmr_alarm2_h; /* Timer alarm 2 high register */ 58 u32 tmr_alarm2_l; /* Timer alarm 2 high register */ 59 u8 res3[48]; 60 u32 tmr_fiper1; /* Timer fixed period interval */ 61 u32 tmr_fiper2; /* Timer fixed period interval */ 62 u32 tmr_fiper3; /* Timer fixed period interval */ 63 u8 res4[20]; 64 u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */ 65 u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */ 66 u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */ 67 u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */ 68}; 69 70/* Bit definitions for the TMR_CTRL register */ 71#define ALM1P (1<<31) /* Alarm1 output polarity */ 72#define ALM2P (1<<30) /* Alarm2 output polarity */ 73#define FS (1<<28) /* FIPER start indication */ 74#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */ 75#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */ 76#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */ 77#define TCLK_PERIOD_MASK (0x3ff) 78#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */ 79#define FRD (1<<14) /* FIPER Realignment Disable */ 80#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */ 81#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */ 82#define ETEP2 (1<<9) /* External trigger 2 edge polarity */ 83#define ETEP1 (1<<8) /* External trigger 1 edge polarity */ 84#define COPH (1<<7) /* Generated clock output phase. */ 85#define CIPH (1<<6) /* External oscillator input clock phase */ 86#define TMSR (1<<5) /* Timer soft reset. */ 87#define BYP (1<<3) /* Bypass drift compensated clock */ 88#define TE (1<<2) /* 1588 timer enable. */ 89#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */ 90#define CKSEL_MASK (0x3) 91 92/* Bit definitions for the TMR_TEVENT register */ 93#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */ 94#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */ 95#define ALM2 (1<<17) /* Current time = alarm time register 2 */ 96#define ALM1 (1<<16) /* Current time = alarm time register 1 */ 97#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */ 98#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */ 99#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */ 100 101/* Bit definitions for the TMR_TEMASK register */ 102#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */ 103#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */ 104#define ALM2EN (1<<17) /* Timer ALM2 event enable */ 105#define ALM1EN (1<<16) /* Timer ALM1 event enable */ 106#define PP1EN (1<<7) /* Periodic pulse event 1 enable */ 107#define PP2EN (1<<6) /* Periodic pulse event 2 enable */ 108 109/* Bit definitions for the TMR_PEVENT register */ 110#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */ 111#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */ 112#define RXP (1<<0) /* PTP frame has been received */ 113 114/* Bit definitions for the TMR_PEMASK register */ 115#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */ 116#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */ 117#define RXPEN (1<<0) /* Receive PTP packet event enable */ 118 119/* Bit definitions for the TMR_STAT register */ 120#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ 121#define STAT_VEC_MASK (0x3f) 122 123/* Bit definitions for the TMR_PRSC register */ 124#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ 125#define PRSC_OCK_MASK (0xffff) 126 127 128#define DRIVER "gianfar_ptp" 129#define DEFAULT_CKSEL 1 130#define N_ALARM 1 /* first alarm is used internally to reset fipers */ 131#define N_EXT_TS 2 132#define REG_SIZE sizeof(struct gianfar_ptp_registers) 133 134struct etsects { 135 struct gianfar_ptp_registers *regs; 136 spinlock_t lock; /* protects regs */ 137 struct ptp_clock *clock; 138 struct ptp_clock_info caps; 139 struct resource *rsrc; 140 int irq; 141 u64 alarm_interval; /* for periodic alarm */ 142 u64 alarm_value; 143 u32 tclk_period; /* nanoseconds */ 144 u32 tmr_prsc; 145 u32 tmr_add; 146 u32 cksel; 147 u32 tmr_fiper1; 148 u32 tmr_fiper2; 149}; 150 151/* 152 * Register access functions 153 */ 154 155/* Caller must hold etsects->lock. */ 156static u64 tmr_cnt_read(struct etsects *etsects) 157{ 158 u64 ns; 159 u32 lo, hi; 160 161 lo = gfar_read(&etsects->regs->tmr_cnt_l); 162 hi = gfar_read(&etsects->regs->tmr_cnt_h); 163 ns = ((u64) hi) << 32; 164 ns |= lo; 165 return ns; 166} 167 168/* Caller must hold etsects->lock. */ 169static void tmr_cnt_write(struct etsects *etsects, u64 ns) 170{ 171 u32 hi = ns >> 32; 172 u32 lo = ns & 0xffffffff; 173 174 gfar_write(&etsects->regs->tmr_cnt_l, lo); 175 gfar_write(&etsects->regs->tmr_cnt_h, hi); 176} 177 178/* Caller must hold etsects->lock. */ 179static void set_alarm(struct etsects *etsects) 180{ 181 u64 ns; 182 u32 lo, hi; 183 184 ns = tmr_cnt_read(etsects) + 1500000000ULL; 185 ns = div_u64(ns, 1000000000UL) * 1000000000ULL; 186 ns -= etsects->tclk_period; 187 hi = ns >> 32; 188 lo = ns & 0xffffffff; 189 gfar_write(&etsects->regs->tmr_alarm1_l, lo); 190 gfar_write(&etsects->regs->tmr_alarm1_h, hi); 191} 192 193/* Caller must hold etsects->lock. */ 194static void set_fipers(struct etsects *etsects) 195{ 196 set_alarm(etsects); 197 gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); 198 gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); 199} 200 201/* 202 * Interrupt service routine 203 */ 204 205static irqreturn_t isr(int irq, void *priv) 206{ 207 struct etsects *etsects = priv; 208 struct ptp_clock_event event; 209 u64 ns; 210 u32 ack = 0, lo, hi, mask, val; 211 212 val = gfar_read(&etsects->regs->tmr_tevent); 213 214 if (val & ETS1) { 215 ack |= ETS1; 216 hi = gfar_read(&etsects->regs->tmr_etts1_h); 217 lo = gfar_read(&etsects->regs->tmr_etts1_l); 218 event.type = PTP_CLOCK_EXTTS; 219 event.index = 0; 220 event.timestamp = ((u64) hi) << 32; 221 event.timestamp |= lo; 222 ptp_clock_event(etsects->clock, &event); 223 } 224 225 if (val & ETS2) { 226 ack |= ETS2; 227 hi = gfar_read(&etsects->regs->tmr_etts2_h); 228 lo = gfar_read(&etsects->regs->tmr_etts2_l); 229 event.type = PTP_CLOCK_EXTTS; 230 event.index = 1; 231 event.timestamp = ((u64) hi) << 32; 232 event.timestamp |= lo; 233 ptp_clock_event(etsects->clock, &event); 234 } 235 236 if (val & ALM2) { 237 ack |= ALM2; 238 if (etsects->alarm_value) { 239 event.type = PTP_CLOCK_ALARM; 240 event.index = 0; 241 event.timestamp = etsects->alarm_value; 242 ptp_clock_event(etsects->clock, &event); 243 } 244 if (etsects->alarm_interval) { 245 ns = etsects->alarm_value + etsects->alarm_interval; 246 hi = ns >> 32; 247 lo = ns & 0xffffffff; 248 spin_lock(&etsects->lock); 249 gfar_write(&etsects->regs->tmr_alarm2_l, lo); 250 gfar_write(&etsects->regs->tmr_alarm2_h, hi); 251 spin_unlock(&etsects->lock); 252 etsects->alarm_value = ns; 253 } else { 254 gfar_write(&etsects->regs->tmr_tevent, ALM2); 255 spin_lock(&etsects->lock); 256 mask = gfar_read(&etsects->regs->tmr_temask); 257 mask &= ~ALM2EN; 258 gfar_write(&etsects->regs->tmr_temask, mask); 259 spin_unlock(&etsects->lock); 260 etsects->alarm_value = 0; 261 etsects->alarm_interval = 0; 262 } 263 } 264 265 if (val & PP1) { 266 ack |= PP1; 267 event.type = PTP_CLOCK_PPS; 268 ptp_clock_event(etsects->clock, &event); 269 } 270 271 if (ack) { 272 gfar_write(&etsects->regs->tmr_tevent, ack); 273 return IRQ_HANDLED; 274 } else 275 return IRQ_NONE; 276} 277 278/* 279 * PTP clock operations 280 */ 281 282static int ptp_gianfar_adjfreq(struct ptp_clock_info *ptp, s32 ppb) 283{ 284 u64 adj; 285 u32 diff, tmr_add; 286 int neg_adj = 0; 287 struct etsects *etsects = container_of(ptp, struct etsects, caps); 288 289 if (ppb < 0) { 290 neg_adj = 1; 291 ppb = -ppb; 292 } 293 tmr_add = etsects->tmr_add; 294 adj = tmr_add; 295 adj *= ppb; 296 diff = div_u64(adj, 1000000000ULL); 297 298 tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; 299 300 gfar_write(&etsects->regs->tmr_add, tmr_add); 301 302 return 0; 303} 304 305static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta) 306{ 307 s64 now; 308 unsigned long flags; 309 struct etsects *etsects = container_of(ptp, struct etsects, caps); 310 311 spin_lock_irqsave(&etsects->lock, flags); 312 313 now = tmr_cnt_read(etsects); 314 now += delta; 315 tmr_cnt_write(etsects, now); 316 317 spin_unlock_irqrestore(&etsects->lock, flags); 318 319 set_fipers(etsects); 320 321 return 0; 322} 323 324static int ptp_gianfar_gettime(struct ptp_clock_info *ptp, struct timespec *ts) 325{ 326 u64 ns; 327 u32 remainder; 328 unsigned long flags; 329 struct etsects *etsects = container_of(ptp, struct etsects, caps); 330 331 spin_lock_irqsave(&etsects->lock, flags); 332 333 ns = tmr_cnt_read(etsects); 334 335 spin_unlock_irqrestore(&etsects->lock, flags); 336 337 ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); 338 ts->tv_nsec = remainder; 339 return 0; 340} 341 342static int ptp_gianfar_settime(struct ptp_clock_info *ptp, 343 const struct timespec *ts) 344{ 345 u64 ns; 346 unsigned long flags; 347 struct etsects *etsects = container_of(ptp, struct etsects, caps); 348 349 ns = ts->tv_sec * 1000000000ULL; 350 ns += ts->tv_nsec; 351 352 spin_lock_irqsave(&etsects->lock, flags); 353 354 tmr_cnt_write(etsects, ns); 355 set_fipers(etsects); 356 357 spin_unlock_irqrestore(&etsects->lock, flags); 358 359 return 0; 360} 361 362static int ptp_gianfar_enable(struct ptp_clock_info *ptp, 363 struct ptp_clock_request *rq, int on) 364{ 365 struct etsects *etsects = container_of(ptp, struct etsects, caps); 366 unsigned long flags; 367 u32 bit, mask; 368 369 switch (rq->type) { 370 case PTP_CLK_REQ_EXTTS: 371 switch (rq->extts.index) { 372 case 0: 373 bit = ETS1EN; 374 break; 375 case 1: 376 bit = ETS2EN; 377 break; 378 default: 379 return -EINVAL; 380 } 381 spin_lock_irqsave(&etsects->lock, flags); 382 mask = gfar_read(&etsects->regs->tmr_temask); 383 if (on) 384 mask |= bit; 385 else 386 mask &= ~bit; 387 gfar_write(&etsects->regs->tmr_temask, mask); 388 spin_unlock_irqrestore(&etsects->lock, flags); 389 return 0; 390 391 case PTP_CLK_REQ_PPS: 392 spin_lock_irqsave(&etsects->lock, flags); 393 mask = gfar_read(&etsects->regs->tmr_temask); 394 if (on) 395 mask |= PP1EN; 396 else 397 mask &= ~PP1EN; 398 gfar_write(&etsects->regs->tmr_temask, mask); 399 spin_unlock_irqrestore(&etsects->lock, flags); 400 return 0; 401 402 default: 403 break; 404 } 405 406 return -EOPNOTSUPP; 407} 408 409static struct ptp_clock_info ptp_gianfar_caps = { 410 .owner = THIS_MODULE, 411 .name = "gianfar clock", 412 .max_adj = 512000, 413 .n_alarm = N_ALARM, 414 .n_ext_ts = N_EXT_TS, 415 .n_per_out = 0, 416 .pps = 1, 417 .adjfreq = ptp_gianfar_adjfreq, 418 .adjtime = ptp_gianfar_adjtime, 419 .gettime = ptp_gianfar_gettime, 420 .settime = ptp_gianfar_settime, 421 .enable = ptp_gianfar_enable, 422}; 423 424/* OF device tree */ 425 426static int get_of_u32(struct device_node *node, char *str, u32 *val) 427{ 428 int plen; 429 const u32 *prop = of_get_property(node, str, &plen); 430 431 if (!prop || plen != sizeof(*prop)) 432 return -1; 433 *val = *prop; 434 return 0; 435} 436 437static int gianfar_ptp_probe(struct platform_device *dev) 438{ 439 struct device_node *node = dev->dev.of_node; 440 struct etsects *etsects; 441 struct timespec now; 442 int err = -ENOMEM; 443 u32 tmr_ctrl; 444 unsigned long flags; 445 446 etsects = kzalloc(sizeof(*etsects), GFP_KERNEL); 447 if (!etsects) 448 goto no_memory; 449 450 err = -ENODEV; 451 452 etsects->caps = ptp_gianfar_caps; 453 etsects->cksel = DEFAULT_CKSEL; 454 455 if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) || 456 get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) || 457 get_of_u32(node, "fsl,tmr-add", &etsects->tmr_add) || 458 get_of_u32(node, "fsl,tmr-fiper1", &etsects->tmr_fiper1) || 459 get_of_u32(node, "fsl,tmr-fiper2", &etsects->tmr_fiper2) || 460 get_of_u32(node, "fsl,max-adj", &etsects->caps.max_adj)) { 461 pr_err("device tree node missing required elements\n"); 462 goto no_node; 463 } 464 465 etsects->irq = platform_get_irq(dev, 0); 466 467 if (etsects->irq == NO_IRQ) { 468 pr_err("irq not in device tree\n"); 469 goto no_node; 470 } 471 if (request_irq(etsects->irq, isr, 0, DRIVER, etsects)) { 472 pr_err("request_irq failed\n"); 473 goto no_node; 474 } 475 476 etsects->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); 477 if (!etsects->rsrc) { 478 pr_err("no resource\n"); 479 goto no_resource; 480 } 481 if (request_resource(&ioport_resource, etsects->rsrc)) { 482 pr_err("resource busy\n"); 483 goto no_resource; 484 } 485 486 spin_lock_init(&etsects->lock); 487 488 etsects->regs = ioremap(etsects->rsrc->start, 489 resource_size(etsects->rsrc)); 490 if (!etsects->regs) { 491 pr_err("ioremap ptp registers failed\n"); 492 goto no_ioremap; 493 } 494 getnstimeofday(&now); 495 ptp_gianfar_settime(&etsects->caps, &now); 496 497 tmr_ctrl = 498 (etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | 499 (etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT; 500 501 spin_lock_irqsave(&etsects->lock, flags); 502 503 gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl); 504 gfar_write(&etsects->regs->tmr_add, etsects->tmr_add); 505 gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); 506 gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); 507 gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); 508 set_alarm(etsects); 509 gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE|FRD); 510 511 spin_unlock_irqrestore(&etsects->lock, flags); 512 513 etsects->clock = ptp_clock_register(&etsects->caps); 514 if (IS_ERR(etsects->clock)) { 515 err = PTR_ERR(etsects->clock); 516 goto no_clock; 517 } 518 519 dev_set_drvdata(&dev->dev, etsects); 520 521 return 0; 522 523no_clock: 524no_ioremap: 525 release_resource(etsects->rsrc); 526no_resource: 527 free_irq(etsects->irq, etsects); 528no_node: 529 kfree(etsects); 530no_memory: 531 return err; 532} 533 534static int gianfar_ptp_remove(struct platform_device *dev) 535{ 536 struct etsects *etsects = dev_get_drvdata(&dev->dev); 537 538 gfar_write(&etsects->regs->tmr_temask, 0); 539 gfar_write(&etsects->regs->tmr_ctrl, 0); 540 541 ptp_clock_unregister(etsects->clock); 542 iounmap(etsects->regs); 543 release_resource(etsects->rsrc); 544 free_irq(etsects->irq, etsects); 545 kfree(etsects); 546 547 return 0; 548} 549 550static struct of_device_id match_table[] = { 551 { .compatible = "fsl,etsec-ptp" }, 552 {}, 553}; 554 555static struct platform_driver gianfar_ptp_driver = { 556 .driver = { 557 .name = "gianfar_ptp", 558 .of_match_table = match_table, 559 .owner = THIS_MODULE, 560 }, 561 .probe = gianfar_ptp_probe, 562 .remove = gianfar_ptp_remove, 563}; 564 565/* module operations */ 566 567static int __init ptp_gianfar_init(void) 568{ 569 return platform_driver_register(&gianfar_ptp_driver); 570} 571 572module_init(ptp_gianfar_init); 573 574static void __exit ptp_gianfar_exit(void) 575{ 576 platform_driver_unregister(&gianfar_ptp_driver); 577} 578 579module_exit(ptp_gianfar_exit); 580 581MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>"); 582MODULE_DESCRIPTION("PTP clock using the eTSEC"); 583MODULE_LICENSE("GPL");