Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/tlclk.c
26278 views
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 <[email protected]> and the current
24
* Maintainer <[email protected]>
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 <[email protected]>");
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
.read = tlclk_read,
268
.open = tlclk_open,
269
.release = tlclk_release,
270
.llseek = noop_llseek,
271
272
};
273
274
static struct miscdevice tlclk_miscdev = {
275
.minor = MISC_DYNAMIC_MINOR,
276
.name = "telco_clock",
277
.fops = &tlclk_fops,
278
};
279
280
static ssize_t show_current_ref(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_REG1) & 0x08) >> 3);
288
spin_unlock_irqrestore(&event_lock, flags);
289
290
return sprintf(buf, "0x%lX\n", ret_val);
291
}
292
293
static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
294
295
296
static ssize_t show_telclock_version(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_REG5);
304
spin_unlock_irqrestore(&event_lock, flags);
305
306
return sprintf(buf, "0x%lX\n", ret_val);
307
}
308
309
static DEVICE_ATTR(telclock_version, S_IRUGO,
310
show_telclock_version, NULL);
311
312
static ssize_t show_alarms(struct device *d,
313
struct device_attribute *attr, char *buf)
314
{
315
unsigned long ret_val;
316
unsigned long flags;
317
318
spin_lock_irqsave(&event_lock, flags);
319
ret_val = (inb(TLCLK_REG2) & 0xf0);
320
spin_unlock_irqrestore(&event_lock, flags);
321
322
return sprintf(buf, "0x%lX\n", ret_val);
323
}
324
325
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
326
327
static ssize_t store_received_ref_clk3a(struct device *d,
328
struct device_attribute *attr, const char *buf, size_t count)
329
{
330
unsigned long tmp;
331
unsigned char val;
332
unsigned long flags;
333
334
sscanf(buf, "%lX", &tmp);
335
dev_dbg(d, ": tmp = 0x%lX\n", tmp);
336
337
val = (unsigned char)tmp;
338
spin_lock_irqsave(&event_lock, flags);
339
SET_PORT_BITS(TLCLK_REG1, 0xef, val);
340
spin_unlock_irqrestore(&event_lock, flags);
341
342
return strnlen(buf, count);
343
}
344
345
static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
346
store_received_ref_clk3a);
347
348
349
static ssize_t store_received_ref_clk3b(struct device *d,
350
struct device_attribute *attr, const char *buf, size_t count)
351
{
352
unsigned long tmp;
353
unsigned char val;
354
unsigned long flags;
355
356
sscanf(buf, "%lX", &tmp);
357
dev_dbg(d, ": tmp = 0x%lX\n", tmp);
358
359
val = (unsigned char)tmp;
360
spin_lock_irqsave(&event_lock, flags);
361
SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1);
362
spin_unlock_irqrestore(&event_lock, flags);
363
364
return strnlen(buf, count);
365
}
366
367
static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
368
store_received_ref_clk3b);
369
370
371
static ssize_t store_enable_clk3b_output(struct device *d,
372
struct device_attribute *attr, const char *buf, size_t count)
373
{
374
unsigned long tmp;
375
unsigned char val;
376
unsigned long flags;
377
378
sscanf(buf, "%lX", &tmp);
379
dev_dbg(d, ": tmp = 0x%lX\n", tmp);
380
381
val = (unsigned char)tmp;
382
spin_lock_irqsave(&event_lock, flags);
383
SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
384
spin_unlock_irqrestore(&event_lock, flags);
385
386
return strnlen(buf, count);
387
}
388
389
static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
390
store_enable_clk3b_output);
391
392
static ssize_t store_enable_clk3a_output(struct device *d,
393
struct device_attribute *attr, const char *buf, size_t count)
394
{
395
unsigned long flags;
396
unsigned long tmp;
397
unsigned char val;
398
399
sscanf(buf, "%lX", &tmp);
400
dev_dbg(d, "tmp = 0x%lX\n", tmp);
401
402
val = (unsigned char)tmp;
403
spin_lock_irqsave(&event_lock, flags);
404
SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
405
spin_unlock_irqrestore(&event_lock, flags);
406
407
return strnlen(buf, count);
408
}
409
410
static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
411
store_enable_clk3a_output);
412
413
static ssize_t store_enable_clkb1_output(struct device *d,
414
struct device_attribute *attr, const char *buf, size_t count)
415
{
416
unsigned long flags;
417
unsigned long tmp;
418
unsigned char val;
419
420
sscanf(buf, "%lX", &tmp);
421
dev_dbg(d, "tmp = 0x%lX\n", tmp);
422
423
val = (unsigned char)tmp;
424
spin_lock_irqsave(&event_lock, flags);
425
SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
426
spin_unlock_irqrestore(&event_lock, flags);
427
428
return strnlen(buf, count);
429
}
430
431
static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
432
store_enable_clkb1_output);
433
434
435
static ssize_t store_enable_clka1_output(struct device *d,
436
struct device_attribute *attr, const char *buf, size_t count)
437
{
438
unsigned long flags;
439
unsigned long tmp;
440
unsigned char val;
441
442
sscanf(buf, "%lX", &tmp);
443
dev_dbg(d, "tmp = 0x%lX\n", tmp);
444
445
val = (unsigned char)tmp;
446
spin_lock_irqsave(&event_lock, flags);
447
SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
448
spin_unlock_irqrestore(&event_lock, flags);
449
450
return strnlen(buf, count);
451
}
452
453
static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
454
store_enable_clka1_output);
455
456
static ssize_t store_enable_clkb0_output(struct device *d,
457
struct device_attribute *attr, const char *buf, size_t count)
458
{
459
unsigned long flags;
460
unsigned long tmp;
461
unsigned char val;
462
463
sscanf(buf, "%lX", &tmp);
464
dev_dbg(d, "tmp = 0x%lX\n", tmp);
465
466
val = (unsigned char)tmp;
467
spin_lock_irqsave(&event_lock, flags);
468
SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
469
spin_unlock_irqrestore(&event_lock, flags);
470
471
return strnlen(buf, count);
472
}
473
474
static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
475
store_enable_clkb0_output);
476
477
static ssize_t store_enable_clka0_output(struct device *d,
478
struct device_attribute *attr, const char *buf, size_t count)
479
{
480
unsigned long flags;
481
unsigned long tmp;
482
unsigned char val;
483
484
sscanf(buf, "%lX", &tmp);
485
dev_dbg(d, "tmp = 0x%lX\n", tmp);
486
487
val = (unsigned char)tmp;
488
spin_lock_irqsave(&event_lock, flags);
489
SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
490
spin_unlock_irqrestore(&event_lock, flags);
491
492
return strnlen(buf, count);
493
}
494
495
static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
496
store_enable_clka0_output);
497
498
static ssize_t store_select_amcb2_transmit_clock(struct device *d,
499
struct device_attribute *attr, const char *buf, size_t count)
500
{
501
unsigned long flags;
502
unsigned long tmp;
503
unsigned char val;
504
505
sscanf(buf, "%lX", &tmp);
506
dev_dbg(d, "tmp = 0x%lX\n", tmp);
507
508
val = (unsigned char)tmp;
509
spin_lock_irqsave(&event_lock, flags);
510
if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
511
SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
512
SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
513
} else if (val >= CLK_8_592MHz) {
514
SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
515
switch (val) {
516
case CLK_8_592MHz:
517
SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
518
break;
519
case CLK_11_184MHz:
520
SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
521
break;
522
case CLK_34_368MHz:
523
SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
524
break;
525
case CLK_44_736MHz:
526
SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
527
break;
528
}
529
} else {
530
SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
531
}
532
spin_unlock_irqrestore(&event_lock, flags);
533
534
return strnlen(buf, count);
535
}
536
537
static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
538
store_select_amcb2_transmit_clock);
539
540
static ssize_t store_select_amcb1_transmit_clock(struct device *d,
541
struct device_attribute *attr, const char *buf, size_t count)
542
{
543
unsigned long tmp;
544
unsigned char val;
545
unsigned long flags;
546
547
sscanf(buf, "%lX", &tmp);
548
dev_dbg(d, "tmp = 0x%lX\n", tmp);
549
550
val = (unsigned char)tmp;
551
spin_lock_irqsave(&event_lock, flags);
552
if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
553
SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
554
SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
555
} else if (val >= CLK_8_592MHz) {
556
SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
557
switch (val) {
558
case CLK_8_592MHz:
559
SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
560
break;
561
case CLK_11_184MHz:
562
SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
563
break;
564
case CLK_34_368MHz:
565
SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
566
break;
567
case CLK_44_736MHz:
568
SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
569
break;
570
}
571
} else {
572
SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
573
}
574
spin_unlock_irqrestore(&event_lock, flags);
575
576
return strnlen(buf, count);
577
}
578
579
static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
580
store_select_amcb1_transmit_clock);
581
582
static ssize_t store_select_redundant_clock(struct device *d,
583
struct device_attribute *attr, const char *buf, size_t count)
584
{
585
unsigned long tmp;
586
unsigned char val;
587
unsigned long flags;
588
589
sscanf(buf, "%lX", &tmp);
590
dev_dbg(d, "tmp = 0x%lX\n", tmp);
591
592
val = (unsigned char)tmp;
593
spin_lock_irqsave(&event_lock, flags);
594
SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
595
spin_unlock_irqrestore(&event_lock, flags);
596
597
return strnlen(buf, count);
598
}
599
600
static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
601
store_select_redundant_clock);
602
603
static ssize_t store_select_ref_frequency(struct device *d,
604
struct device_attribute *attr, const char *buf, size_t count)
605
{
606
unsigned long tmp;
607
unsigned char val;
608
unsigned long flags;
609
610
sscanf(buf, "%lX", &tmp);
611
dev_dbg(d, "tmp = 0x%lX\n", tmp);
612
613
val = (unsigned char)tmp;
614
spin_lock_irqsave(&event_lock, flags);
615
SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
616
spin_unlock_irqrestore(&event_lock, flags);
617
618
return strnlen(buf, count);
619
}
620
621
static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
622
store_select_ref_frequency);
623
624
static ssize_t store_filter_select(struct device *d,
625
struct device_attribute *attr, const char *buf, size_t count)
626
{
627
unsigned long tmp;
628
unsigned char val;
629
unsigned long flags;
630
631
sscanf(buf, "%lX", &tmp);
632
dev_dbg(d, "tmp = 0x%lX\n", tmp);
633
634
val = (unsigned char)tmp;
635
spin_lock_irqsave(&event_lock, flags);
636
SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
637
spin_unlock_irqrestore(&event_lock, flags);
638
639
return strnlen(buf, count);
640
}
641
642
static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
643
644
static ssize_t store_hardware_switching_mode(struct device *d,
645
struct device_attribute *attr, const char *buf, size_t count)
646
{
647
unsigned long tmp;
648
unsigned char val;
649
unsigned long flags;
650
651
sscanf(buf, "%lX", &tmp);
652
dev_dbg(d, "tmp = 0x%lX\n", tmp);
653
654
val = (unsigned char)tmp;
655
spin_lock_irqsave(&event_lock, flags);
656
SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
657
spin_unlock_irqrestore(&event_lock, flags);
658
659
return strnlen(buf, count);
660
}
661
662
static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
663
store_hardware_switching_mode);
664
665
static ssize_t store_hardware_switching(struct device *d,
666
struct device_attribute *attr, const char *buf, size_t count)
667
{
668
unsigned long tmp;
669
unsigned char val;
670
unsigned long flags;
671
672
sscanf(buf, "%lX", &tmp);
673
dev_dbg(d, "tmp = 0x%lX\n", tmp);
674
675
val = (unsigned char)tmp;
676
spin_lock_irqsave(&event_lock, flags);
677
SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
678
spin_unlock_irqrestore(&event_lock, flags);
679
680
return strnlen(buf, count);
681
}
682
683
static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
684
store_hardware_switching);
685
686
static ssize_t store_refalign (struct device *d,
687
struct device_attribute *attr, const char *buf, size_t count)
688
{
689
unsigned long tmp;
690
unsigned long flags;
691
692
sscanf(buf, "%lX", &tmp);
693
dev_dbg(d, "tmp = 0x%lX\n", tmp);
694
spin_lock_irqsave(&event_lock, flags);
695
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
696
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
697
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
698
spin_unlock_irqrestore(&event_lock, flags);
699
700
return strnlen(buf, count);
701
}
702
703
static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
704
705
static ssize_t store_mode_select (struct device *d,
706
struct device_attribute *attr, const char *buf, size_t count)
707
{
708
unsigned long tmp;
709
unsigned char val;
710
unsigned long flags;
711
712
sscanf(buf, "%lX", &tmp);
713
dev_dbg(d, "tmp = 0x%lX\n", tmp);
714
715
val = (unsigned char)tmp;
716
spin_lock_irqsave(&event_lock, flags);
717
SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
718
spin_unlock_irqrestore(&event_lock, flags);
719
720
return strnlen(buf, count);
721
}
722
723
static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
724
725
static ssize_t store_reset (struct device *d,
726
struct device_attribute *attr, const char *buf, size_t count)
727
{
728
unsigned long tmp;
729
unsigned char val;
730
unsigned long flags;
731
732
sscanf(buf, "%lX", &tmp);
733
dev_dbg(d, "tmp = 0x%lX\n", tmp);
734
735
val = (unsigned char)tmp;
736
spin_lock_irqsave(&event_lock, flags);
737
SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
738
spin_unlock_irqrestore(&event_lock, flags);
739
740
return strnlen(buf, count);
741
}
742
743
static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
744
745
static struct attribute *tlclk_attrs[] = {
746
&dev_attr_current_ref.attr,
747
&dev_attr_telclock_version.attr,
748
&dev_attr_alarms.attr,
749
&dev_attr_received_ref_clk3a.attr,
750
&dev_attr_received_ref_clk3b.attr,
751
&dev_attr_enable_clk3a_output.attr,
752
&dev_attr_enable_clk3b_output.attr,
753
&dev_attr_enable_clkb1_output.attr,
754
&dev_attr_enable_clka1_output.attr,
755
&dev_attr_enable_clkb0_output.attr,
756
&dev_attr_enable_clka0_output.attr,
757
&dev_attr_select_amcb1_transmit_clock.attr,
758
&dev_attr_select_amcb2_transmit_clock.attr,
759
&dev_attr_select_redundant_clock.attr,
760
&dev_attr_select_ref_frequency.attr,
761
&dev_attr_filter_select.attr,
762
&dev_attr_hardware_switching_mode.attr,
763
&dev_attr_hardware_switching.attr,
764
&dev_attr_refalign.attr,
765
&dev_attr_mode_select.attr,
766
&dev_attr_reset.attr,
767
NULL
768
};
769
ATTRIBUTE_GROUPS(tlclk);
770
771
static struct faux_device *tlclk_device;
772
773
static int __init tlclk_init(void)
774
{
775
int ret;
776
777
telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
778
779
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
780
if (!alarm_events) {
781
ret = -ENOMEM;
782
goto out1;
783
}
784
785
ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
786
if (ret < 0) {
787
printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
788
kfree(alarm_events);
789
return ret;
790
}
791
tlclk_major = ret;
792
793
/* Read telecom clock IRQ number (Set by BIOS) */
794
if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
795
printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
796
TLCLK_BASE);
797
ret = -EBUSY;
798
goto out2;
799
}
800
801
if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
802
printk(KERN_ERR "telclk_interrupt = 0x%x non-mcpbl0010 hw.\n",
803
telclk_interrupt);
804
ret = -ENXIO;
805
goto out3;
806
}
807
808
timer_setup(&switchover_timer, switchover_timeout, 0);
809
810
ret = misc_register(&tlclk_miscdev);
811
if (ret < 0) {
812
printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
813
goto out3;
814
}
815
816
tlclk_device = faux_device_create_with_groups("telco_clock", NULL, NULL, tlclk_groups);
817
if (!tlclk_device) {
818
ret = -ENODEV;
819
goto out4;
820
}
821
822
return 0;
823
out4:
824
misc_deregister(&tlclk_miscdev);
825
out3:
826
release_region(TLCLK_BASE, 8);
827
out2:
828
kfree(alarm_events);
829
unregister_chrdev(tlclk_major, "telco_clock");
830
out1:
831
return ret;
832
}
833
834
static void __exit tlclk_cleanup(void)
835
{
836
faux_device_destroy(tlclk_device);
837
misc_deregister(&tlclk_miscdev);
838
unregister_chrdev(tlclk_major, "telco_clock");
839
840
release_region(TLCLK_BASE, 8);
841
timer_delete_sync(&switchover_timer);
842
kfree(alarm_events);
843
844
}
845
846
static void switchover_timeout(struct timer_list *unused)
847
{
848
unsigned long flags = tlclk_timer_data;
849
850
if ((flags & 1)) {
851
if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
852
alarm_events->switchover_primary++;
853
} else {
854
if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
855
alarm_events->switchover_secondary++;
856
}
857
858
/* Alarm processing is done, wake up read task */
859
timer_delete(&switchover_timer);
860
got_event = 1;
861
wake_up(&wq);
862
}
863
864
static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
865
{
866
unsigned long flags;
867
868
spin_lock_irqsave(&event_lock, flags);
869
/* Read and clear interrupt events */
870
int_events = inb(TLCLK_REG6);
871
872
/* Primary_Los changed from 0 to 1 ? */
873
if (int_events & PRI_LOS_01_MASK) {
874
if (inb(TLCLK_REG2) & SEC_LOST_MASK)
875
alarm_events->lost_clocks++;
876
else
877
alarm_events->lost_primary_clock++;
878
}
879
880
/* Primary_Los changed from 1 to 0 ? */
881
if (int_events & PRI_LOS_10_MASK) {
882
alarm_events->primary_clock_back++;
883
SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
884
}
885
/* Secondary_Los changed from 0 to 1 ? */
886
if (int_events & SEC_LOS_01_MASK) {
887
if (inb(TLCLK_REG2) & PRI_LOST_MASK)
888
alarm_events->lost_clocks++;
889
else
890
alarm_events->lost_secondary_clock++;
891
}
892
/* Secondary_Los changed from 1 to 0 ? */
893
if (int_events & SEC_LOS_10_MASK) {
894
alarm_events->secondary_clock_back++;
895
SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
896
}
897
if (int_events & HOLDOVER_10_MASK)
898
alarm_events->pll_end_holdover++;
899
900
if (int_events & UNLOCK_01_MASK)
901
alarm_events->pll_lost_sync++;
902
903
if (int_events & UNLOCK_10_MASK)
904
alarm_events->pll_sync++;
905
906
/* Holdover changed from 0 to 1 ? */
907
if (int_events & HOLDOVER_01_MASK) {
908
alarm_events->pll_holdover++;
909
910
/* TIMEOUT in ~10ms */
911
switchover_timer.expires = jiffies + msecs_to_jiffies(10);
912
tlclk_timer_data = inb(TLCLK_REG1);
913
mod_timer(&switchover_timer, switchover_timer.expires);
914
} else {
915
got_event = 1;
916
wake_up(&wq);
917
}
918
spin_unlock_irqrestore(&event_lock, flags);
919
920
return IRQ_HANDLED;
921
}
922
923
module_init(tlclk_init);
924
module_exit(tlclk_cleanup);
925
926