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