• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
48 MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>");
49 MODULE_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 
120 struct 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:
150 Upon loading the driver will create a sysfs directory under
151 /sys/devices/platform/telco_clock.
152 
153 This directory exports the following interfaces.  There operation is
154 documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
155 alarms				:
156 current_ref			:
157 received_ref_clk3a		:
158 received_ref_clk3b		:
159 enable_clk3a_output		:
160 enable_clk3b_output		:
161 enable_clka0_output		:
162 enable_clka1_output		:
163 enable_clkb0_output		:
164 enable_clkb1_output		:
165 filter_select			:
166 hardware_switching		:
167 hardware_switching_mode		:
168 telclock_version		:
169 mode_select			:
170 refalign			:
171 reset				:
172 select_amcb1_transmit_clock	:
173 select_amcb2_transmit_clock	:
174 select_redundant_clock		:
175 select_ref_frequency		:
176 
177 All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
178 has the same effect as echo 0x99 > refalign.
179 */
180 
181 static unsigned int telclk_interrupt;
182 
183 static int int_events;		/* Event that generate a interrupt */
184 static int got_event;		/* if events processing have been done */
185 
186 static void switchover_timeout(unsigned long data);
187 static struct timer_list switchover_timer =
188 	TIMER_INITIALIZER(switchover_timeout , 0, 0);
189 static unsigned long tlclk_timer_data;
190 
191 static struct tlclk_alarms *alarm_events;
192 
193 static DEFINE_SPINLOCK(event_lock);
194 
195 static int tlclk_major = TLCLK_MAJOR;
196 
197 static irqreturn_t tlclk_interrupt(int irq, void *dev_id);
198 
199 static DECLARE_WAIT_QUEUE_HEAD(wq);
200 
201 static unsigned long useflags;
202 static DEFINE_MUTEX(tlclk_mutex);
203 
tlclk_open(struct inode * inode,struct file * filp)204 static 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 
230 out:
231 	unlock_kernel();
232 	return result;
233 }
234 
tlclk_release(struct inode * inode,struct file * filp)235 static 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 
tlclk_read(struct file * filp,char __user * buf,size_t count,loff_t * f_pos)243 static 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 
265 static const struct file_operations tlclk_fops = {
266 	.read = tlclk_read,
267 	.open = tlclk_open,
268 	.release = tlclk_release,
269 
270 };
271 
272 static struct miscdevice tlclk_miscdev = {
273 	.minor = MISC_DYNAMIC_MINOR,
274 	.name = "telco_clock",
275 	.fops = &tlclk_fops,
276 };
277 
show_current_ref(struct device * d,struct device_attribute * attr,char * buf)278 static 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 
291 static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
292 
293 
show_telclock_version(struct device * d,struct device_attribute * attr,char * buf)294 static 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 
307 static DEVICE_ATTR(telclock_version, S_IRUGO,
308 		show_telclock_version, NULL);
309 
show_alarms(struct device * d,struct device_attribute * attr,char * buf)310 static 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 
323 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
324 
store_received_ref_clk3a(struct device * d,struct device_attribute * attr,const char * buf,size_t count)325 static 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 
343 static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
344 		store_received_ref_clk3a);
345 
346 
store_received_ref_clk3b(struct device * d,struct device_attribute * attr,const char * buf,size_t count)347 static 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 
365 static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
366 		store_received_ref_clk3b);
367 
368 
store_enable_clk3b_output(struct device * d,struct device_attribute * attr,const char * buf,size_t count)369 static 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 
387 static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
388 		store_enable_clk3b_output);
389 
store_enable_clk3a_output(struct device * d,struct device_attribute * attr,const char * buf,size_t count)390 static 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 
408 static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
409 		store_enable_clk3a_output);
410 
store_enable_clkb1_output(struct device * d,struct device_attribute * attr,const char * buf,size_t count)411 static 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 
429 static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
430 		store_enable_clkb1_output);
431 
432 
store_enable_clka1_output(struct device * d,struct device_attribute * attr,const char * buf,size_t count)433 static 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 
451 static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
452 		store_enable_clka1_output);
453 
store_enable_clkb0_output(struct device * d,struct device_attribute * attr,const char * buf,size_t count)454 static 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 
472 static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
473 		store_enable_clkb0_output);
474 
store_enable_clka0_output(struct device * d,struct device_attribute * attr,const char * buf,size_t count)475 static 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 
493 static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
494 		store_enable_clka0_output);
495 
store_select_amcb2_transmit_clock(struct device * d,struct device_attribute * attr,const char * buf,size_t count)496 static 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 
535 static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
536 	store_select_amcb2_transmit_clock);
537 
store_select_amcb1_transmit_clock(struct device * d,struct device_attribute * attr,const char * buf,size_t count)538 static 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 
576 static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
577 		store_select_amcb1_transmit_clock);
578 
store_select_redundant_clock(struct device * d,struct device_attribute * attr,const char * buf,size_t count)579 static 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 
597 static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
598 		store_select_redundant_clock);
599 
store_select_ref_frequency(struct device * d,struct device_attribute * attr,const char * buf,size_t count)600 static 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 
618 static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
619 		store_select_ref_frequency);
620 
store_filter_select(struct device * d,struct device_attribute * attr,const char * buf,size_t count)621 static 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 
639 static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
640 
store_hardware_switching_mode(struct device * d,struct device_attribute * attr,const char * buf,size_t count)641 static 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 
659 static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
660 		store_hardware_switching_mode);
661 
store_hardware_switching(struct device * d,struct device_attribute * attr,const char * buf,size_t count)662 static 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 
680 static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
681 		store_hardware_switching);
682 
store_refalign(struct device * d,struct device_attribute * attr,const char * buf,size_t count)683 static 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 
700 static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
701 
store_mode_select(struct device * d,struct device_attribute * attr,const char * buf,size_t count)702 static 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 
720 static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
721 
store_reset(struct device * d,struct device_attribute * attr,const char * buf,size_t count)722 static 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 
740 static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
741 
742 static 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 
767 static struct attribute_group tlclk_attribute_group = {
768 	.name = NULL,		/* put in device directory */
769 	.attrs = tlclk_sysfs_entries,
770 };
771 
772 static struct platform_device *tlclk_device;
773 
tlclk_init(void)774 static 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;
828 out5:
829 	platform_device_unregister(tlclk_device);
830 out4:
831 	misc_deregister(&tlclk_miscdev);
832 out3:
833 	release_region(TLCLK_BASE, 8);
834 out2:
835 	kfree(alarm_events);
836 out1:
837 	unregister_chrdev(tlclk_major, "telco_clock");
838 	return ret;
839 }
840 
tlclk_cleanup(void)841 static 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 
switchover_timeout(unsigned long data)854 static 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 
tlclk_interrupt(int irq,void * dev_id)872 static 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 
932 module_init(tlclk_init);
933 module_exit(tlclk_cleanup);
934