tlclk.c revision 5e40508e5fee2dac7b04d5bc5b5ef3b452f0a899
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/sched.h>
33#include <linux/kernel.h>	/* printk() */
34#include <linux/fs.h>		/* everything... */
35#include <linux/errno.h>	/* error codes */
36#include <linux/slab.h>
37#include <linux/ioport.h>
38#include <linux/interrupt.h>
39#include <linux/spinlock.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);
189
190static struct tlclk_alarms *alarm_events;
191
192static DEFINE_SPINLOCK(event_lock);
193
194static int tlclk_major = TLCLK_MAJOR;
195
196static irqreturn_t tlclk_interrupt(int irq, void *dev_id);
197
198static DECLARE_WAIT_QUEUE_HEAD(wq);
199
200static int tlclk_open(struct inode *inode, struct file *filp)
201{
202	int result;
203
204	/* Make sure there is no interrupt pending while
205	 * initialising interrupt handler */
206	inb(TLCLK_REG6);
207
208	/* This device is wired through the FPGA IO space of the ATCA blade
209	 * we can't share this IRQ */
210	result = request_irq(telclk_interrupt, &tlclk_interrupt,
211			     IRQF_DISABLED, "telco_clock", tlclk_interrupt);
212	if (result == -EBUSY) {
213		printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
214		return -EBUSY;
215	}
216	inb(TLCLK_REG6);	/* Clear interrupt events */
217
218	return 0;
219}
220
221static int tlclk_release(struct inode *inode, struct file *filp)
222{
223	free_irq(telclk_interrupt, tlclk_interrupt);
224
225	return 0;
226}
227
228static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
229		loff_t *f_pos)
230{
231	if (count < sizeof(struct tlclk_alarms))
232		return -EIO;
233
234	wait_event_interruptible(wq, got_event);
235	if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms)))
236		return -EFAULT;
237
238	memset(alarm_events, 0, sizeof(struct tlclk_alarms));
239	got_event = 0;
240
241	return  sizeof(struct tlclk_alarms);
242}
243
244static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
245	    loff_t *f_pos)
246{
247	return 0;
248}
249
250static const struct file_operations tlclk_fops = {
251	.read = tlclk_read,
252	.write = tlclk_write,
253	.open = tlclk_open,
254	.release = tlclk_release,
255
256};
257
258static struct miscdevice tlclk_miscdev = {
259	.minor = MISC_DYNAMIC_MINOR,
260	.name = "telco_clock",
261	.fops = &tlclk_fops,
262};
263
264static ssize_t show_current_ref(struct device *d,
265		struct device_attribute *attr, char *buf)
266{
267	unsigned long ret_val;
268	unsigned long flags;
269
270	spin_lock_irqsave(&event_lock, flags);
271	ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3);
272	spin_unlock_irqrestore(&event_lock, flags);
273
274	return sprintf(buf, "0x%lX\n", ret_val);
275}
276
277static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
278
279
280static ssize_t show_telclock_version(struct device *d,
281		struct device_attribute *attr, char *buf)
282{
283	unsigned long ret_val;
284	unsigned long flags;
285
286	spin_lock_irqsave(&event_lock, flags);
287	ret_val = inb(TLCLK_REG5);
288	spin_unlock_irqrestore(&event_lock, flags);
289
290	return sprintf(buf, "0x%lX\n", ret_val);
291}
292
293static DEVICE_ATTR(telclock_version, S_IRUGO,
294		show_telclock_version, NULL);
295
296static ssize_t show_alarms(struct device *d,
297		struct device_attribute *attr,  char *buf)
298{
299	unsigned long ret_val;
300	unsigned long flags;
301
302	spin_lock_irqsave(&event_lock, flags);
303	ret_val = (inb(TLCLK_REG2) & 0xf0);
304	spin_unlock_irqrestore(&event_lock, flags);
305
306	return sprintf(buf, "0x%lX\n", ret_val);
307}
308
309static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
310
311static ssize_t store_received_ref_clk3a(struct device *d,
312		 struct device_attribute *attr, const char *buf, size_t count)
313{
314	unsigned long tmp;
315	unsigned char val;
316	unsigned long flags;
317
318	sscanf(buf, "%lX", &tmp);
319	dev_dbg(d, ": tmp = 0x%lX\n", tmp);
320
321	val = (unsigned char)tmp;
322	spin_lock_irqsave(&event_lock, flags);
323	SET_PORT_BITS(TLCLK_REG1, 0xef, val);
324	spin_unlock_irqrestore(&event_lock, flags);
325
326	return strnlen(buf, count);
327}
328
329static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
330		store_received_ref_clk3a);
331
332
333static ssize_t store_received_ref_clk3b(struct device *d,
334		 struct device_attribute *attr, const char *buf, size_t count)
335{
336	unsigned long tmp;
337	unsigned char val;
338	unsigned long flags;
339
340	sscanf(buf, "%lX", &tmp);
341	dev_dbg(d, ": tmp = 0x%lX\n", tmp);
342
343	val = (unsigned char)tmp;
344	spin_lock_irqsave(&event_lock, flags);
345	SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1);
346	spin_unlock_irqrestore(&event_lock, flags);
347
348	return strnlen(buf, count);
349}
350
351static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
352		store_received_ref_clk3b);
353
354
355static ssize_t store_enable_clk3b_output(struct device *d,
356		 struct device_attribute *attr, const char *buf, size_t count)
357{
358	unsigned long tmp;
359	unsigned char val;
360	unsigned long flags;
361
362	sscanf(buf, "%lX", &tmp);
363	dev_dbg(d, ": tmp = 0x%lX\n", tmp);
364
365	val = (unsigned char)tmp;
366	spin_lock_irqsave(&event_lock, flags);
367	SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
368	spin_unlock_irqrestore(&event_lock, flags);
369
370	return strnlen(buf, count);
371}
372
373static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
374		store_enable_clk3b_output);
375
376static ssize_t store_enable_clk3a_output(struct device *d,
377		 struct device_attribute *attr, const char *buf, size_t count)
378{
379	unsigned long flags;
380	unsigned long tmp;
381	unsigned char val;
382
383	sscanf(buf, "%lX", &tmp);
384	dev_dbg(d, "tmp = 0x%lX\n", tmp);
385
386	val = (unsigned char)tmp;
387	spin_lock_irqsave(&event_lock, flags);
388	SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
389	spin_unlock_irqrestore(&event_lock, flags);
390
391	return strnlen(buf, count);
392}
393
394static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
395		store_enable_clk3a_output);
396
397static ssize_t store_enable_clkb1_output(struct device *d,
398		 struct device_attribute *attr, const char *buf, size_t count)
399{
400	unsigned long flags;
401	unsigned long tmp;
402	unsigned char val;
403
404	sscanf(buf, "%lX", &tmp);
405	dev_dbg(d, "tmp = 0x%lX\n", tmp);
406
407	val = (unsigned char)tmp;
408	spin_lock_irqsave(&event_lock, flags);
409	SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
410	spin_unlock_irqrestore(&event_lock, flags);
411
412	return strnlen(buf, count);
413}
414
415static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
416		store_enable_clkb1_output);
417
418
419static ssize_t store_enable_clka1_output(struct device *d,
420		 struct device_attribute *attr, const char *buf, size_t count)
421{
422	unsigned long flags;
423	unsigned long tmp;
424	unsigned char val;
425
426	sscanf(buf, "%lX", &tmp);
427	dev_dbg(d, "tmp = 0x%lX\n", tmp);
428
429	val = (unsigned char)tmp;
430	spin_lock_irqsave(&event_lock, flags);
431	SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
432	spin_unlock_irqrestore(&event_lock, flags);
433
434	return strnlen(buf, count);
435}
436
437static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
438		store_enable_clka1_output);
439
440static ssize_t store_enable_clkb0_output(struct device *d,
441		 struct device_attribute *attr, const char *buf, size_t count)
442{
443	unsigned long flags;
444	unsigned long tmp;
445	unsigned char val;
446
447	sscanf(buf, "%lX", &tmp);
448	dev_dbg(d, "tmp = 0x%lX\n", tmp);
449
450	val = (unsigned char)tmp;
451	spin_lock_irqsave(&event_lock, flags);
452	SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
453	spin_unlock_irqrestore(&event_lock, flags);
454
455	return strnlen(buf, count);
456}
457
458static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
459		store_enable_clkb0_output);
460
461static ssize_t store_enable_clka0_output(struct device *d,
462		 struct device_attribute *attr, const char *buf, size_t count)
463{
464	unsigned long flags;
465	unsigned long tmp;
466	unsigned char val;
467
468	sscanf(buf, "%lX", &tmp);
469	dev_dbg(d, "tmp = 0x%lX\n", tmp);
470
471	val = (unsigned char)tmp;
472	spin_lock_irqsave(&event_lock, flags);
473	SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
474	spin_unlock_irqrestore(&event_lock, flags);
475
476	return strnlen(buf, count);
477}
478
479static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
480		store_enable_clka0_output);
481
482static ssize_t store_select_amcb2_transmit_clock(struct device *d,
483		struct device_attribute *attr, const char *buf, size_t count)
484{
485	unsigned long flags;
486	unsigned long tmp;
487	unsigned char val;
488
489	sscanf(buf, "%lX", &tmp);
490	dev_dbg(d, "tmp = 0x%lX\n", tmp);
491
492	val = (unsigned char)tmp;
493	spin_lock_irqsave(&event_lock, flags);
494		if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
495			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
496			SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
497		} else if (val >= CLK_8_592MHz) {
498			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
499			switch (val) {
500			case CLK_8_592MHz:
501				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
502				break;
503			case CLK_11_184MHz:
504				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
505				break;
506			case CLK_34_368MHz:
507				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
508				break;
509			case CLK_44_736MHz:
510				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
511				break;
512			}
513		} else
514			SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
515
516	spin_unlock_irqrestore(&event_lock, flags);
517
518	return strnlen(buf, count);
519}
520
521static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
522	store_select_amcb2_transmit_clock);
523
524static ssize_t store_select_amcb1_transmit_clock(struct device *d,
525		 struct device_attribute *attr, const char *buf, size_t count)
526{
527	unsigned long tmp;
528	unsigned char val;
529	unsigned long flags;
530
531	sscanf(buf, "%lX", &tmp);
532	dev_dbg(d, "tmp = 0x%lX\n", tmp);
533
534	val = (unsigned char)tmp;
535	spin_lock_irqsave(&event_lock, flags);
536		if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
537			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
538			SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
539		} else if (val >= CLK_8_592MHz) {
540			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
541			switch (val) {
542			case CLK_8_592MHz:
543				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
544				break;
545			case CLK_11_184MHz:
546				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
547				break;
548			case CLK_34_368MHz:
549				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
550				break;
551			case CLK_44_736MHz:
552				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
553				break;
554			}
555		} else
556			SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
557	spin_unlock_irqrestore(&event_lock, flags);
558
559	return strnlen(buf, count);
560}
561
562static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
563		store_select_amcb1_transmit_clock);
564
565static ssize_t store_select_redundant_clock(struct device *d,
566		 struct device_attribute *attr, const char *buf, size_t count)
567{
568	unsigned long tmp;
569	unsigned char val;
570	unsigned long flags;
571
572	sscanf(buf, "%lX", &tmp);
573	dev_dbg(d, "tmp = 0x%lX\n", tmp);
574
575	val = (unsigned char)tmp;
576	spin_lock_irqsave(&event_lock, flags);
577	SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
578	spin_unlock_irqrestore(&event_lock, flags);
579
580	return strnlen(buf, count);
581}
582
583static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
584		store_select_redundant_clock);
585
586static ssize_t store_select_ref_frequency(struct device *d,
587		 struct device_attribute *attr, const char *buf, size_t count)
588{
589	unsigned long tmp;
590	unsigned char val;
591	unsigned long flags;
592
593	sscanf(buf, "%lX", &tmp);
594	dev_dbg(d, "tmp = 0x%lX\n", tmp);
595
596	val = (unsigned char)tmp;
597	spin_lock_irqsave(&event_lock, flags);
598	SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
599	spin_unlock_irqrestore(&event_lock, flags);
600
601	return strnlen(buf, count);
602}
603
604static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
605		store_select_ref_frequency);
606
607static ssize_t store_filter_select(struct device *d,
608		 struct device_attribute *attr, const char *buf, size_t count)
609{
610	unsigned long tmp;
611	unsigned char val;
612	unsigned long flags;
613
614	sscanf(buf, "%lX", &tmp);
615	dev_dbg(d, "tmp = 0x%lX\n", tmp);
616
617	val = (unsigned char)tmp;
618	spin_lock_irqsave(&event_lock, flags);
619	SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
620	spin_unlock_irqrestore(&event_lock, flags);
621
622	return strnlen(buf, count);
623}
624
625static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
626
627static ssize_t store_hardware_switching_mode(struct device *d,
628		 struct device_attribute *attr, const char *buf, size_t count)
629{
630	unsigned long tmp;
631	unsigned char val;
632	unsigned long flags;
633
634	sscanf(buf, "%lX", &tmp);
635	dev_dbg(d, "tmp = 0x%lX\n", tmp);
636
637	val = (unsigned char)tmp;
638	spin_lock_irqsave(&event_lock, flags);
639	SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
640	spin_unlock_irqrestore(&event_lock, flags);
641
642	return strnlen(buf, count);
643}
644
645static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
646		store_hardware_switching_mode);
647
648static ssize_t store_hardware_switching(struct device *d,
649		 struct device_attribute *attr, const char *buf, size_t count)
650{
651	unsigned long tmp;
652	unsigned char val;
653	unsigned long flags;
654
655	sscanf(buf, "%lX", &tmp);
656	dev_dbg(d, "tmp = 0x%lX\n", tmp);
657
658	val = (unsigned char)tmp;
659	spin_lock_irqsave(&event_lock, flags);
660	SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
661	spin_unlock_irqrestore(&event_lock, flags);
662
663	return strnlen(buf, count);
664}
665
666static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
667		store_hardware_switching);
668
669static ssize_t store_refalign (struct device *d,
670		 struct device_attribute *attr, const char *buf, size_t count)
671{
672	unsigned long tmp;
673	unsigned long flags;
674
675	sscanf(buf, "%lX", &tmp);
676	dev_dbg(d, "tmp = 0x%lX\n", tmp);
677	spin_lock_irqsave(&event_lock, flags);
678	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
679	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
680	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
681	spin_unlock_irqrestore(&event_lock, flags);
682
683	return strnlen(buf, count);
684}
685
686static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
687
688static ssize_t store_mode_select (struct device *d,
689		 struct device_attribute *attr, const char *buf, size_t count)
690{
691	unsigned long tmp;
692	unsigned char val;
693	unsigned long flags;
694
695	sscanf(buf, "%lX", &tmp);
696	dev_dbg(d, "tmp = 0x%lX\n", tmp);
697
698	val = (unsigned char)tmp;
699	spin_lock_irqsave(&event_lock, flags);
700	SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
701	spin_unlock_irqrestore(&event_lock, flags);
702
703	return strnlen(buf, count);
704}
705
706static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
707
708static ssize_t store_reset (struct device *d,
709		 struct device_attribute *attr, const char *buf, size_t count)
710{
711	unsigned long tmp;
712	unsigned char val;
713	unsigned long flags;
714
715	sscanf(buf, "%lX", &tmp);
716	dev_dbg(d, "tmp = 0x%lX\n", tmp);
717
718	val = (unsigned char)tmp;
719	spin_lock_irqsave(&event_lock, flags);
720	SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
721	spin_unlock_irqrestore(&event_lock, flags);
722
723	return strnlen(buf, count);
724}
725
726static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
727
728static struct attribute *tlclk_sysfs_entries[] = {
729	&dev_attr_current_ref.attr,
730	&dev_attr_telclock_version.attr,
731	&dev_attr_alarms.attr,
732	&dev_attr_received_ref_clk3a.attr,
733	&dev_attr_received_ref_clk3b.attr,
734	&dev_attr_enable_clk3a_output.attr,
735	&dev_attr_enable_clk3b_output.attr,
736	&dev_attr_enable_clkb1_output.attr,
737	&dev_attr_enable_clka1_output.attr,
738	&dev_attr_enable_clkb0_output.attr,
739	&dev_attr_enable_clka0_output.attr,
740	&dev_attr_select_amcb1_transmit_clock.attr,
741	&dev_attr_select_amcb2_transmit_clock.attr,
742	&dev_attr_select_redundant_clock.attr,
743	&dev_attr_select_ref_frequency.attr,
744	&dev_attr_filter_select.attr,
745	&dev_attr_hardware_switching_mode.attr,
746	&dev_attr_hardware_switching.attr,
747	&dev_attr_refalign.attr,
748	&dev_attr_mode_select.attr,
749	&dev_attr_reset.attr,
750	NULL
751};
752
753static struct attribute_group tlclk_attribute_group = {
754	.name = NULL,		/* put in device directory */
755	.attrs = tlclk_sysfs_entries,
756};
757
758static struct platform_device *tlclk_device;
759
760static int __init tlclk_init(void)
761{
762	int ret;
763
764	ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
765	if (ret < 0) {
766		printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
767		return ret;
768	}
769	tlclk_major = ret;
770	alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
771	if (!alarm_events)
772		goto out1;
773
774	/* Read telecom clock IRQ number (Set by BIOS) */
775	if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
776		printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
777			TLCLK_BASE);
778		ret = -EBUSY;
779		goto out2;
780	}
781	telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
782
783	if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
784		printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw.\n",
785			telclk_interrupt);
786		ret = -ENXIO;
787		goto out3;
788	}
789
790	init_timer(&switchover_timer);
791
792	ret = misc_register(&tlclk_miscdev);
793	if (ret < 0) {
794		printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
795		goto out3;
796	}
797
798	tlclk_device = platform_device_register_simple("telco_clock",
799				-1, NULL, 0);
800	if (IS_ERR(tlclk_device)) {
801		printk(KERN_ERR "tlclk: platform_device_register failed.\n");
802		ret = PTR_ERR(tlclk_device);
803		goto out4;
804	}
805
806	ret = sysfs_create_group(&tlclk_device->dev.kobj,
807			&tlclk_attribute_group);
808	if (ret) {
809		printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n");
810		goto out5;
811	}
812
813	return 0;
814out5:
815	platform_device_unregister(tlclk_device);
816out4:
817	misc_deregister(&tlclk_miscdev);
818out3:
819	release_region(TLCLK_BASE, 8);
820out2:
821	kfree(alarm_events);
822out1:
823	unregister_chrdev(tlclk_major, "telco_clock");
824	return ret;
825}
826
827static void __exit tlclk_cleanup(void)
828{
829	sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group);
830	platform_device_unregister(tlclk_device);
831	misc_deregister(&tlclk_miscdev);
832	unregister_chrdev(tlclk_major, "telco_clock");
833
834	release_region(TLCLK_BASE, 8);
835	del_timer_sync(&switchover_timer);
836	kfree(alarm_events);
837
838}
839
840static void switchover_timeout(unsigned long data)
841{
842	if ((data & 1)) {
843		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
844			alarm_events->switchover_primary++;
845	} else {
846		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
847			alarm_events->switchover_secondary++;
848	}
849
850	/* Alarm processing is done, wake up read task */
851	del_timer(&switchover_timer);
852	got_event = 1;
853	wake_up(&wq);
854}
855
856static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
857{
858	unsigned long flags;
859
860	spin_lock_irqsave(&event_lock, flags);
861	/* Read and clear interrupt events */
862	int_events = inb(TLCLK_REG6);
863
864	/* Primary_Los changed from 0 to 1 ? */
865	if (int_events & PRI_LOS_01_MASK) {
866		if (inb(TLCLK_REG2) & SEC_LOST_MASK)
867			alarm_events->lost_clocks++;
868		else
869			alarm_events->lost_primary_clock++;
870	}
871
872	/* Primary_Los changed from 1 to 0 ? */
873	if (int_events & PRI_LOS_10_MASK) {
874		alarm_events->primary_clock_back++;
875		SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
876	}
877	/* Secondary_Los changed from 0 to 1 ? */
878	if (int_events & SEC_LOS_01_MASK) {
879		if (inb(TLCLK_REG2) & PRI_LOST_MASK)
880			alarm_events->lost_clocks++;
881		else
882			alarm_events->lost_secondary_clock++;
883	}
884	/* Secondary_Los changed from 1 to 0 ? */
885	if (int_events & SEC_LOS_10_MASK) {
886		alarm_events->secondary_clock_back++;
887		SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
888	}
889	if (int_events & HOLDOVER_10_MASK)
890		alarm_events->pll_end_holdover++;
891
892	if (int_events & UNLOCK_01_MASK)
893		alarm_events->pll_lost_sync++;
894
895	if (int_events & UNLOCK_10_MASK)
896		alarm_events->pll_sync++;
897
898	/* Holdover changed from 0 to 1 ? */
899	if (int_events & HOLDOVER_01_MASK) {
900		alarm_events->pll_holdover++;
901
902		/* TIMEOUT in ~10ms */
903		switchover_timer.expires = jiffies + msecs_to_jiffies(10);
904		switchover_timer.data = inb(TLCLK_REG1);
905		add_timer(&switchover_timer);
906	} else {
907		got_event = 1;
908		wake_up(&wq);
909	}
910	spin_unlock_irqrestore(&event_lock, flags);
911
912	return IRQ_HANDLED;
913}
914
915module_init(tlclk_init);
916module_exit(tlclk_cleanup);
917