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 v2.6.32-rc2 933 lines 24 kB view raw
1/* 2 * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010 3 * 4 * Copyright (C) 2005 Kontron Canada 5 * 6 * All rights reserved. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or (at 11 * your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 16 * NON INFRINGEMENT. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * 23 * Send feedback to <sebastien.bouchard@ca.kontron.com> and the current 24 * Maintainer <mark.gross@intel.com> 25 * 26 * Description : This is the TELECOM CLOCK module driver for the ATCA 27 * MPCBL0010 ATCA computer. 28 */ 29 30#include <linux/module.h> 31#include <linux/init.h> 32#include <linux/kernel.h> /* printk() */ 33#include <linux/fs.h> /* everything... */ 34#include <linux/errno.h> /* error codes */ 35#include <linux/slab.h> 36#include <linux/ioport.h> 37#include <linux/interrupt.h> 38#include <linux/spinlock.h> 39#include <linux/smp_lock.h> 40#include <linux/timer.h> 41#include <linux/sysfs.h> 42#include <linux/device.h> 43#include <linux/miscdevice.h> 44#include <linux/platform_device.h> 45#include <asm/io.h> /* inb/outb */ 46#include <asm/uaccess.h> 47 48MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>"); 49MODULE_LICENSE("GPL"); 50 51/*Hardware Reset of the PLL */ 52#define RESET_ON 0x00 53#define RESET_OFF 0x01 54 55/* MODE SELECT */ 56#define NORMAL_MODE 0x00 57#define HOLDOVER_MODE 0x10 58#define FREERUN_MODE 0x20 59 60/* FILTER SELECT */ 61#define FILTER_6HZ 0x04 62#define FILTER_12HZ 0x00 63 64/* SELECT REFERENCE FREQUENCY */ 65#define REF_CLK1_8kHz 0x00 66#define REF_CLK2_19_44MHz 0x02 67 68/* Select primary or secondary redundant clock */ 69#define PRIMARY_CLOCK 0x00 70#define SECONDARY_CLOCK 0x01 71 72/* CLOCK TRANSMISSION DEFINE */ 73#define CLK_8kHz 0xff 74#define CLK_16_384MHz 0xfb 75 76#define CLK_1_544MHz 0x00 77#define CLK_2_048MHz 0x01 78#define CLK_4_096MHz 0x02 79#define CLK_6_312MHz 0x03 80#define CLK_8_192MHz 0x04 81#define CLK_19_440MHz 0x06 82 83#define CLK_8_592MHz 0x08 84#define CLK_11_184MHz 0x09 85#define CLK_34_368MHz 0x0b 86#define CLK_44_736MHz 0x0a 87 88/* RECEIVED REFERENCE */ 89#define AMC_B1 0 90#define AMC_B2 1 91 92/* HARDWARE SWITCHING DEFINE */ 93#define HW_ENABLE 0x80 94#define HW_DISABLE 0x00 95 96/* HARDWARE SWITCHING MODE DEFINE */ 97#define PLL_HOLDOVER 0x40 98#define LOST_CLOCK 0x00 99 100/* ALARMS DEFINE */ 101#define UNLOCK_MASK 0x10 102#define HOLDOVER_MASK 0x20 103#define SEC_LOST_MASK 0x40 104#define PRI_LOST_MASK 0x80 105 106/* INTERRUPT CAUSE DEFINE */ 107 108#define PRI_LOS_01_MASK 0x01 109#define PRI_LOS_10_MASK 0x02 110 111#define SEC_LOS_01_MASK 0x04 112#define SEC_LOS_10_MASK 0x08 113 114#define HOLDOVER_01_MASK 0x10 115#define HOLDOVER_10_MASK 0x20 116 117#define UNLOCK_01_MASK 0x40 118#define UNLOCK_10_MASK 0x80 119 120struct tlclk_alarms { 121 __u32 lost_clocks; 122 __u32 lost_primary_clock; 123 __u32 lost_secondary_clock; 124 __u32 primary_clock_back; 125 __u32 secondary_clock_back; 126 __u32 switchover_primary; 127 __u32 switchover_secondary; 128 __u32 pll_holdover; 129 __u32 pll_end_holdover; 130 __u32 pll_lost_sync; 131 __u32 pll_sync; 132}; 133/* Telecom clock I/O register definition */ 134#define TLCLK_BASE 0xa08 135#define TLCLK_REG0 TLCLK_BASE 136#define TLCLK_REG1 (TLCLK_BASE+1) 137#define TLCLK_REG2 (TLCLK_BASE+2) 138#define TLCLK_REG3 (TLCLK_BASE+3) 139#define TLCLK_REG4 (TLCLK_BASE+4) 140#define TLCLK_REG5 (TLCLK_BASE+5) 141#define TLCLK_REG6 (TLCLK_BASE+6) 142#define TLCLK_REG7 (TLCLK_BASE+7) 143 144#define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port) 145 146/* 0 = Dynamic allocation of the major device number */ 147#define TLCLK_MAJOR 0 148 149/* sysfs interface definition: 150Upon loading the driver will create a sysfs directory under 151/sys/devices/platform/telco_clock. 152 153This directory exports the following interfaces. There operation is 154documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4. 155alarms : 156current_ref : 157received_ref_clk3a : 158received_ref_clk3b : 159enable_clk3a_output : 160enable_clk3b_output : 161enable_clka0_output : 162enable_clka1_output : 163enable_clkb0_output : 164enable_clkb1_output : 165filter_select : 166hardware_switching : 167hardware_switching_mode : 168telclock_version : 169mode_select : 170refalign : 171reset : 172select_amcb1_transmit_clock : 173select_amcb2_transmit_clock : 174select_redundant_clock : 175select_ref_frequency : 176 177All sysfs interfaces are integers in hex format, i.e echo 99 > refalign 178has the same effect as echo 0x99 > refalign. 179*/ 180 181static unsigned int telclk_interrupt; 182 183static int int_events; /* Event that generate a interrupt */ 184static int got_event; /* if events processing have been done */ 185 186static void switchover_timeout(unsigned long data); 187static struct timer_list switchover_timer = 188 TIMER_INITIALIZER(switchover_timeout , 0, 0); 189static unsigned long tlclk_timer_data; 190 191static struct tlclk_alarms *alarm_events; 192 193static DEFINE_SPINLOCK(event_lock); 194 195static int tlclk_major = TLCLK_MAJOR; 196 197static irqreturn_t tlclk_interrupt(int irq, void *dev_id); 198 199static DECLARE_WAIT_QUEUE_HEAD(wq); 200 201static unsigned long useflags; 202static DEFINE_MUTEX(tlclk_mutex); 203 204static int tlclk_open(struct inode *inode, struct file *filp) 205{ 206 int result; 207 208 lock_kernel(); 209 if (test_and_set_bit(0, &useflags)) { 210 result = -EBUSY; 211 /* this legacy device is always one per system and it doesn't 212 * know how to handle multiple concurrent clients. 213 */ 214 goto out; 215 } 216 217 /* Make sure there is no interrupt pending while 218 * initialising interrupt handler */ 219 inb(TLCLK_REG6); 220 221 /* This device is wired through the FPGA IO space of the ATCA blade 222 * we can't share this IRQ */ 223 result = request_irq(telclk_interrupt, &tlclk_interrupt, 224 IRQF_DISABLED, "telco_clock", tlclk_interrupt); 225 if (result == -EBUSY) 226 printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n"); 227 else 228 inb(TLCLK_REG6); /* Clear interrupt events */ 229 230out: 231 unlock_kernel(); 232 return result; 233} 234 235static int tlclk_release(struct inode *inode, struct file *filp) 236{ 237 free_irq(telclk_interrupt, tlclk_interrupt); 238 clear_bit(0, &useflags); 239 240 return 0; 241} 242 243static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, 244 loff_t *f_pos) 245{ 246 if (count < sizeof(struct tlclk_alarms)) 247 return -EIO; 248 if (mutex_lock_interruptible(&tlclk_mutex)) 249 return -EINTR; 250 251 252 wait_event_interruptible(wq, got_event); 253 if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) { 254 mutex_unlock(&tlclk_mutex); 255 return -EFAULT; 256 } 257 258 memset(alarm_events, 0, sizeof(struct tlclk_alarms)); 259 got_event = 0; 260 261 mutex_unlock(&tlclk_mutex); 262 return sizeof(struct tlclk_alarms); 263} 264 265static const struct file_operations tlclk_fops = { 266 .read = tlclk_read, 267 .open = tlclk_open, 268 .release = tlclk_release, 269 270}; 271 272static struct miscdevice tlclk_miscdev = { 273 .minor = MISC_DYNAMIC_MINOR, 274 .name = "telco_clock", 275 .fops = &tlclk_fops, 276}; 277 278static ssize_t show_current_ref(struct device *d, 279 struct device_attribute *attr, char *buf) 280{ 281 unsigned long ret_val; 282 unsigned long flags; 283 284 spin_lock_irqsave(&event_lock, flags); 285 ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3); 286 spin_unlock_irqrestore(&event_lock, flags); 287 288 return sprintf(buf, "0x%lX\n", ret_val); 289} 290 291static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL); 292 293 294static ssize_t show_telclock_version(struct device *d, 295 struct device_attribute *attr, char *buf) 296{ 297 unsigned long ret_val; 298 unsigned long flags; 299 300 spin_lock_irqsave(&event_lock, flags); 301 ret_val = inb(TLCLK_REG5); 302 spin_unlock_irqrestore(&event_lock, flags); 303 304 return sprintf(buf, "0x%lX\n", ret_val); 305} 306 307static DEVICE_ATTR(telclock_version, S_IRUGO, 308 show_telclock_version, NULL); 309 310static ssize_t show_alarms(struct device *d, 311 struct device_attribute *attr, char *buf) 312{ 313 unsigned long ret_val; 314 unsigned long flags; 315 316 spin_lock_irqsave(&event_lock, flags); 317 ret_val = (inb(TLCLK_REG2) & 0xf0); 318 spin_unlock_irqrestore(&event_lock, flags); 319 320 return sprintf(buf, "0x%lX\n", ret_val); 321} 322 323static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 324 325static ssize_t store_received_ref_clk3a(struct device *d, 326 struct device_attribute *attr, const char *buf, size_t count) 327{ 328 unsigned long tmp; 329 unsigned char val; 330 unsigned long flags; 331 332 sscanf(buf, "%lX", &tmp); 333 dev_dbg(d, ": tmp = 0x%lX\n", tmp); 334 335 val = (unsigned char)tmp; 336 spin_lock_irqsave(&event_lock, flags); 337 SET_PORT_BITS(TLCLK_REG1, 0xef, val); 338 spin_unlock_irqrestore(&event_lock, flags); 339 340 return strnlen(buf, count); 341} 342 343static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL, 344 store_received_ref_clk3a); 345 346 347static ssize_t store_received_ref_clk3b(struct device *d, 348 struct device_attribute *attr, const char *buf, size_t count) 349{ 350 unsigned long tmp; 351 unsigned char val; 352 unsigned long flags; 353 354 sscanf(buf, "%lX", &tmp); 355 dev_dbg(d, ": tmp = 0x%lX\n", tmp); 356 357 val = (unsigned char)tmp; 358 spin_lock_irqsave(&event_lock, flags); 359 SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1); 360 spin_unlock_irqrestore(&event_lock, flags); 361 362 return strnlen(buf, count); 363} 364 365static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL, 366 store_received_ref_clk3b); 367 368 369static ssize_t store_enable_clk3b_output(struct device *d, 370 struct device_attribute *attr, const char *buf, size_t count) 371{ 372 unsigned long tmp; 373 unsigned char val; 374 unsigned long flags; 375 376 sscanf(buf, "%lX", &tmp); 377 dev_dbg(d, ": tmp = 0x%lX\n", tmp); 378 379 val = (unsigned char)tmp; 380 spin_lock_irqsave(&event_lock, flags); 381 SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7); 382 spin_unlock_irqrestore(&event_lock, flags); 383 384 return strnlen(buf, count); 385} 386 387static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL, 388 store_enable_clk3b_output); 389 390static ssize_t store_enable_clk3a_output(struct device *d, 391 struct device_attribute *attr, const char *buf, size_t count) 392{ 393 unsigned long flags; 394 unsigned long tmp; 395 unsigned char val; 396 397 sscanf(buf, "%lX", &tmp); 398 dev_dbg(d, "tmp = 0x%lX\n", tmp); 399 400 val = (unsigned char)tmp; 401 spin_lock_irqsave(&event_lock, flags); 402 SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6); 403 spin_unlock_irqrestore(&event_lock, flags); 404 405 return strnlen(buf, count); 406} 407 408static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL, 409 store_enable_clk3a_output); 410 411static ssize_t store_enable_clkb1_output(struct device *d, 412 struct device_attribute *attr, const char *buf, size_t count) 413{ 414 unsigned long flags; 415 unsigned long tmp; 416 unsigned char val; 417 418 sscanf(buf, "%lX", &tmp); 419 dev_dbg(d, "tmp = 0x%lX\n", tmp); 420 421 val = (unsigned char)tmp; 422 spin_lock_irqsave(&event_lock, flags); 423 SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3); 424 spin_unlock_irqrestore(&event_lock, flags); 425 426 return strnlen(buf, count); 427} 428 429static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL, 430 store_enable_clkb1_output); 431 432 433static ssize_t store_enable_clka1_output(struct device *d, 434 struct device_attribute *attr, const char *buf, size_t count) 435{ 436 unsigned long flags; 437 unsigned long tmp; 438 unsigned char val; 439 440 sscanf(buf, "%lX", &tmp); 441 dev_dbg(d, "tmp = 0x%lX\n", tmp); 442 443 val = (unsigned char)tmp; 444 spin_lock_irqsave(&event_lock, flags); 445 SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2); 446 spin_unlock_irqrestore(&event_lock, flags); 447 448 return strnlen(buf, count); 449} 450 451static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL, 452 store_enable_clka1_output); 453 454static ssize_t store_enable_clkb0_output(struct device *d, 455 struct device_attribute *attr, const char *buf, size_t count) 456{ 457 unsigned long flags; 458 unsigned long tmp; 459 unsigned char val; 460 461 sscanf(buf, "%lX", &tmp); 462 dev_dbg(d, "tmp = 0x%lX\n", tmp); 463 464 val = (unsigned char)tmp; 465 spin_lock_irqsave(&event_lock, flags); 466 SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1); 467 spin_unlock_irqrestore(&event_lock, flags); 468 469 return strnlen(buf, count); 470} 471 472static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL, 473 store_enable_clkb0_output); 474 475static ssize_t store_enable_clka0_output(struct device *d, 476 struct device_attribute *attr, const char *buf, size_t count) 477{ 478 unsigned long flags; 479 unsigned long tmp; 480 unsigned char val; 481 482 sscanf(buf, "%lX", &tmp); 483 dev_dbg(d, "tmp = 0x%lX\n", tmp); 484 485 val = (unsigned char)tmp; 486 spin_lock_irqsave(&event_lock, flags); 487 SET_PORT_BITS(TLCLK_REG2, 0xfe, val); 488 spin_unlock_irqrestore(&event_lock, flags); 489 490 return strnlen(buf, count); 491} 492 493static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL, 494 store_enable_clka0_output); 495 496static ssize_t store_select_amcb2_transmit_clock(struct device *d, 497 struct device_attribute *attr, const char *buf, size_t count) 498{ 499 unsigned long flags; 500 unsigned long tmp; 501 unsigned char val; 502 503 sscanf(buf, "%lX", &tmp); 504 dev_dbg(d, "tmp = 0x%lX\n", tmp); 505 506 val = (unsigned char)tmp; 507 spin_lock_irqsave(&event_lock, flags); 508 if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { 509 SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28); 510 SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); 511 } else if (val >= CLK_8_592MHz) { 512 SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38); 513 switch (val) { 514 case CLK_8_592MHz: 515 SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); 516 break; 517 case CLK_11_184MHz: 518 SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); 519 break; 520 case CLK_34_368MHz: 521 SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); 522 break; 523 case CLK_44_736MHz: 524 SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); 525 break; 526 } 527 } else 528 SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3); 529 530 spin_unlock_irqrestore(&event_lock, flags); 531 532 return strnlen(buf, count); 533} 534 535static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL, 536 store_select_amcb2_transmit_clock); 537 538static ssize_t store_select_amcb1_transmit_clock(struct device *d, 539 struct device_attribute *attr, const char *buf, size_t count) 540{ 541 unsigned long tmp; 542 unsigned char val; 543 unsigned long flags; 544 545 sscanf(buf, "%lX", &tmp); 546 dev_dbg(d, "tmp = 0x%lX\n", tmp); 547 548 val = (unsigned char)tmp; 549 spin_lock_irqsave(&event_lock, flags); 550 if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) { 551 SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5); 552 SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val); 553 } else if (val >= CLK_8_592MHz) { 554 SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); 555 switch (val) { 556 case CLK_8_592MHz: 557 SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); 558 break; 559 case CLK_11_184MHz: 560 SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); 561 break; 562 case CLK_34_368MHz: 563 SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); 564 break; 565 case CLK_44_736MHz: 566 SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); 567 break; 568 } 569 } else 570 SET_PORT_BITS(TLCLK_REG3, 0xf8, val); 571 spin_unlock_irqrestore(&event_lock, flags); 572 573 return strnlen(buf, count); 574} 575 576static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL, 577 store_select_amcb1_transmit_clock); 578 579static ssize_t store_select_redundant_clock(struct device *d, 580 struct device_attribute *attr, const char *buf, size_t count) 581{ 582 unsigned long tmp; 583 unsigned char val; 584 unsigned long flags; 585 586 sscanf(buf, "%lX", &tmp); 587 dev_dbg(d, "tmp = 0x%lX\n", tmp); 588 589 val = (unsigned char)tmp; 590 spin_lock_irqsave(&event_lock, flags); 591 SET_PORT_BITS(TLCLK_REG1, 0xfe, val); 592 spin_unlock_irqrestore(&event_lock, flags); 593 594 return strnlen(buf, count); 595} 596 597static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL, 598 store_select_redundant_clock); 599 600static ssize_t store_select_ref_frequency(struct device *d, 601 struct device_attribute *attr, const char *buf, size_t count) 602{ 603 unsigned long tmp; 604 unsigned char val; 605 unsigned long flags; 606 607 sscanf(buf, "%lX", &tmp); 608 dev_dbg(d, "tmp = 0x%lX\n", tmp); 609 610 val = (unsigned char)tmp; 611 spin_lock_irqsave(&event_lock, flags); 612 SET_PORT_BITS(TLCLK_REG1, 0xfd, val); 613 spin_unlock_irqrestore(&event_lock, flags); 614 615 return strnlen(buf, count); 616} 617 618static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL, 619 store_select_ref_frequency); 620 621static ssize_t store_filter_select(struct device *d, 622 struct device_attribute *attr, const char *buf, size_t count) 623{ 624 unsigned long tmp; 625 unsigned char val; 626 unsigned long flags; 627 628 sscanf(buf, "%lX", &tmp); 629 dev_dbg(d, "tmp = 0x%lX\n", tmp); 630 631 val = (unsigned char)tmp; 632 spin_lock_irqsave(&event_lock, flags); 633 SET_PORT_BITS(TLCLK_REG0, 0xfb, val); 634 spin_unlock_irqrestore(&event_lock, flags); 635 636 return strnlen(buf, count); 637} 638 639static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select); 640 641static ssize_t store_hardware_switching_mode(struct device *d, 642 struct device_attribute *attr, const char *buf, size_t count) 643{ 644 unsigned long tmp; 645 unsigned char val; 646 unsigned long flags; 647 648 sscanf(buf, "%lX", &tmp); 649 dev_dbg(d, "tmp = 0x%lX\n", tmp); 650 651 val = (unsigned char)tmp; 652 spin_lock_irqsave(&event_lock, flags); 653 SET_PORT_BITS(TLCLK_REG0, 0xbf, val); 654 spin_unlock_irqrestore(&event_lock, flags); 655 656 return strnlen(buf, count); 657} 658 659static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL, 660 store_hardware_switching_mode); 661 662static ssize_t store_hardware_switching(struct device *d, 663 struct device_attribute *attr, const char *buf, size_t count) 664{ 665 unsigned long tmp; 666 unsigned char val; 667 unsigned long flags; 668 669 sscanf(buf, "%lX", &tmp); 670 dev_dbg(d, "tmp = 0x%lX\n", tmp); 671 672 val = (unsigned char)tmp; 673 spin_lock_irqsave(&event_lock, flags); 674 SET_PORT_BITS(TLCLK_REG0, 0x7f, val); 675 spin_unlock_irqrestore(&event_lock, flags); 676 677 return strnlen(buf, count); 678} 679 680static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL, 681 store_hardware_switching); 682 683static ssize_t store_refalign (struct device *d, 684 struct device_attribute *attr, const char *buf, size_t count) 685{ 686 unsigned long tmp; 687 unsigned long flags; 688 689 sscanf(buf, "%lX", &tmp); 690 dev_dbg(d, "tmp = 0x%lX\n", tmp); 691 spin_lock_irqsave(&event_lock, flags); 692 SET_PORT_BITS(TLCLK_REG0, 0xf7, 0); 693 SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08); 694 SET_PORT_BITS(TLCLK_REG0, 0xf7, 0); 695 spin_unlock_irqrestore(&event_lock, flags); 696 697 return strnlen(buf, count); 698} 699 700static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign); 701 702static ssize_t store_mode_select (struct device *d, 703 struct device_attribute *attr, const char *buf, size_t count) 704{ 705 unsigned long tmp; 706 unsigned char val; 707 unsigned long flags; 708 709 sscanf(buf, "%lX", &tmp); 710 dev_dbg(d, "tmp = 0x%lX\n", tmp); 711 712 val = (unsigned char)tmp; 713 spin_lock_irqsave(&event_lock, flags); 714 SET_PORT_BITS(TLCLK_REG0, 0xcf, val); 715 spin_unlock_irqrestore(&event_lock, flags); 716 717 return strnlen(buf, count); 718} 719 720static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select); 721 722static ssize_t store_reset (struct device *d, 723 struct device_attribute *attr, const char *buf, size_t count) 724{ 725 unsigned long tmp; 726 unsigned char val; 727 unsigned long flags; 728 729 sscanf(buf, "%lX", &tmp); 730 dev_dbg(d, "tmp = 0x%lX\n", tmp); 731 732 val = (unsigned char)tmp; 733 spin_lock_irqsave(&event_lock, flags); 734 SET_PORT_BITS(TLCLK_REG4, 0xfd, val); 735 spin_unlock_irqrestore(&event_lock, flags); 736 737 return strnlen(buf, count); 738} 739 740static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset); 741 742static struct attribute *tlclk_sysfs_entries[] = { 743 &dev_attr_current_ref.attr, 744 &dev_attr_telclock_version.attr, 745 &dev_attr_alarms.attr, 746 &dev_attr_received_ref_clk3a.attr, 747 &dev_attr_received_ref_clk3b.attr, 748 &dev_attr_enable_clk3a_output.attr, 749 &dev_attr_enable_clk3b_output.attr, 750 &dev_attr_enable_clkb1_output.attr, 751 &dev_attr_enable_clka1_output.attr, 752 &dev_attr_enable_clkb0_output.attr, 753 &dev_attr_enable_clka0_output.attr, 754 &dev_attr_select_amcb1_transmit_clock.attr, 755 &dev_attr_select_amcb2_transmit_clock.attr, 756 &dev_attr_select_redundant_clock.attr, 757 &dev_attr_select_ref_frequency.attr, 758 &dev_attr_filter_select.attr, 759 &dev_attr_hardware_switching_mode.attr, 760 &dev_attr_hardware_switching.attr, 761 &dev_attr_refalign.attr, 762 &dev_attr_mode_select.attr, 763 &dev_attr_reset.attr, 764 NULL 765}; 766 767static struct attribute_group tlclk_attribute_group = { 768 .name = NULL, /* put in device directory */ 769 .attrs = tlclk_sysfs_entries, 770}; 771 772static struct platform_device *tlclk_device; 773 774static int __init tlclk_init(void) 775{ 776 int ret; 777 778 ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops); 779 if (ret < 0) { 780 printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major); 781 return ret; 782 } 783 tlclk_major = ret; 784 alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); 785 if (!alarm_events) 786 goto out1; 787 788 /* Read telecom clock IRQ number (Set by BIOS) */ 789 if (!request_region(TLCLK_BASE, 8, "telco_clock")) { 790 printk(KERN_ERR "tlclk: request_region 0x%X failed.\n", 791 TLCLK_BASE); 792 ret = -EBUSY; 793 goto out2; 794 } 795 telclk_interrupt = (inb(TLCLK_REG7) & 0x0f); 796 797 if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */ 798 printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw.\n", 799 telclk_interrupt); 800 ret = -ENXIO; 801 goto out3; 802 } 803 804 init_timer(&switchover_timer); 805 806 ret = misc_register(&tlclk_miscdev); 807 if (ret < 0) { 808 printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret); 809 goto out3; 810 } 811 812 tlclk_device = platform_device_register_simple("telco_clock", 813 -1, NULL, 0); 814 if (IS_ERR(tlclk_device)) { 815 printk(KERN_ERR "tlclk: platform_device_register failed.\n"); 816 ret = PTR_ERR(tlclk_device); 817 goto out4; 818 } 819 820 ret = sysfs_create_group(&tlclk_device->dev.kobj, 821 &tlclk_attribute_group); 822 if (ret) { 823 printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n"); 824 goto out5; 825 } 826 827 return 0; 828out5: 829 platform_device_unregister(tlclk_device); 830out4: 831 misc_deregister(&tlclk_miscdev); 832out3: 833 release_region(TLCLK_BASE, 8); 834out2: 835 kfree(alarm_events); 836out1: 837 unregister_chrdev(tlclk_major, "telco_clock"); 838 return ret; 839} 840 841static void __exit tlclk_cleanup(void) 842{ 843 sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group); 844 platform_device_unregister(tlclk_device); 845 misc_deregister(&tlclk_miscdev); 846 unregister_chrdev(tlclk_major, "telco_clock"); 847 848 release_region(TLCLK_BASE, 8); 849 del_timer_sync(&switchover_timer); 850 kfree(alarm_events); 851 852} 853 854static void switchover_timeout(unsigned long data) 855{ 856 unsigned long flags = *(unsigned long *) data; 857 858 if ((flags & 1)) { 859 if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08)) 860 alarm_events->switchover_primary++; 861 } else { 862 if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08)) 863 alarm_events->switchover_secondary++; 864 } 865 866 /* Alarm processing is done, wake up read task */ 867 del_timer(&switchover_timer); 868 got_event = 1; 869 wake_up(&wq); 870} 871 872static irqreturn_t tlclk_interrupt(int irq, void *dev_id) 873{ 874 unsigned long flags; 875 876 spin_lock_irqsave(&event_lock, flags); 877 /* Read and clear interrupt events */ 878 int_events = inb(TLCLK_REG6); 879 880 /* Primary_Los changed from 0 to 1 ? */ 881 if (int_events & PRI_LOS_01_MASK) { 882 if (inb(TLCLK_REG2) & SEC_LOST_MASK) 883 alarm_events->lost_clocks++; 884 else 885 alarm_events->lost_primary_clock++; 886 } 887 888 /* Primary_Los changed from 1 to 0 ? */ 889 if (int_events & PRI_LOS_10_MASK) { 890 alarm_events->primary_clock_back++; 891 SET_PORT_BITS(TLCLK_REG1, 0xFE, 1); 892 } 893 /* Secondary_Los changed from 0 to 1 ? */ 894 if (int_events & SEC_LOS_01_MASK) { 895 if (inb(TLCLK_REG2) & PRI_LOST_MASK) 896 alarm_events->lost_clocks++; 897 else 898 alarm_events->lost_secondary_clock++; 899 } 900 /* Secondary_Los changed from 1 to 0 ? */ 901 if (int_events & SEC_LOS_10_MASK) { 902 alarm_events->secondary_clock_back++; 903 SET_PORT_BITS(TLCLK_REG1, 0xFE, 0); 904 } 905 if (int_events & HOLDOVER_10_MASK) 906 alarm_events->pll_end_holdover++; 907 908 if (int_events & UNLOCK_01_MASK) 909 alarm_events->pll_lost_sync++; 910 911 if (int_events & UNLOCK_10_MASK) 912 alarm_events->pll_sync++; 913 914 /* Holdover changed from 0 to 1 ? */ 915 if (int_events & HOLDOVER_01_MASK) { 916 alarm_events->pll_holdover++; 917 918 /* TIMEOUT in ~10ms */ 919 switchover_timer.expires = jiffies + msecs_to_jiffies(10); 920 tlclk_timer_data = inb(TLCLK_REG1); 921 switchover_timer.data = (unsigned long) &tlclk_timer_data; 922 mod_timer(&switchover_timer, switchover_timer.expires); 923 } else { 924 got_event = 1; 925 wake_up(&wq); 926 } 927 spin_unlock_irqrestore(&event_lock, flags); 928 929 return IRQ_HANDLED; 930} 931 932module_init(tlclk_init); 933module_exit(tlclk_cleanup);