Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010
0003  *
0004  * Copyright (C) 2005 Kontron Canada
0005  *
0006  * All rights reserved.
0007  *
0008  * This program is free software; you can redistribute it and/or modify
0009  * it under the terms of the GNU General Public License as published by
0010  * the Free Software Foundation; either version 2 of the License, or (at
0011  * your option) any later version.
0012  *
0013  * This program is distributed in the hope that it will be useful, but
0014  * WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
0016  * NON INFRINGEMENT.  See the GNU General Public License for more
0017  * details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this program; if not, write to the Free Software
0021  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0022  *
0023  * Send feedback to <sebastien.bouchard@ca.kontron.com> and the current
0024  * Maintainer  <mark.gross@intel.com>
0025  *
0026  * Description : This is the TELECOM CLOCK module driver for the ATCA
0027  * MPCBL0010 ATCA computer.
0028  */
0029 
0030 #include <linux/module.h>
0031 #include <linux/init.h>
0032 #include <linux/kernel.h>   /* printk() */
0033 #include <linux/fs.h>       /* everything... */
0034 #include <linux/errno.h>    /* error codes */
0035 #include <linux/sched.h>
0036 #include <linux/slab.h>
0037 #include <linux/ioport.h>
0038 #include <linux/interrupt.h>
0039 #include <linux/spinlock.h>
0040 #include <linux/mutex.h>
0041 #include <linux/timer.h>
0042 #include <linux/sysfs.h>
0043 #include <linux/device.h>
0044 #include <linux/miscdevice.h>
0045 #include <linux/platform_device.h>
0046 #include <asm/io.h>     /* inb/outb */
0047 #include <linux/uaccess.h>
0048 
0049 MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>");
0050 MODULE_LICENSE("GPL");
0051 
0052 /*Hardware Reset of the PLL */
0053 #define RESET_ON    0x00
0054 #define RESET_OFF   0x01
0055 
0056 /* MODE SELECT */
0057 #define NORMAL_MODE     0x00
0058 #define HOLDOVER_MODE   0x10
0059 #define FREERUN_MODE    0x20
0060 
0061 /* FILTER SELECT */
0062 #define FILTER_6HZ  0x04
0063 #define FILTER_12HZ 0x00
0064 
0065 /* SELECT REFERENCE FREQUENCY */
0066 #define REF_CLK1_8kHz       0x00
0067 #define REF_CLK2_19_44MHz   0x02
0068 
0069 /* Select primary or secondary redundant clock */
0070 #define PRIMARY_CLOCK   0x00
0071 #define SECONDARY_CLOCK 0x01
0072 
0073 /* CLOCK TRANSMISSION DEFINE */
0074 #define CLK_8kHz    0xff
0075 #define CLK_16_384MHz   0xfb
0076 
0077 #define CLK_1_544MHz    0x00
0078 #define CLK_2_048MHz    0x01
0079 #define CLK_4_096MHz    0x02
0080 #define CLK_6_312MHz    0x03
0081 #define CLK_8_192MHz    0x04
0082 #define CLK_19_440MHz   0x06
0083 
0084 #define CLK_8_592MHz    0x08
0085 #define CLK_11_184MHz   0x09
0086 #define CLK_34_368MHz   0x0b
0087 #define CLK_44_736MHz   0x0a
0088 
0089 /* RECEIVED REFERENCE */
0090 #define AMC_B1 0
0091 #define AMC_B2 1
0092 
0093 /* HARDWARE SWITCHING DEFINE */
0094 #define HW_ENABLE   0x80
0095 #define HW_DISABLE  0x00
0096 
0097 /* HARDWARE SWITCHING MODE DEFINE */
0098 #define PLL_HOLDOVER    0x40
0099 #define LOST_CLOCK  0x00
0100 
0101 /* ALARMS DEFINE */
0102 #define UNLOCK_MASK 0x10
0103 #define HOLDOVER_MASK   0x20
0104 #define SEC_LOST_MASK   0x40
0105 #define PRI_LOST_MASK   0x80
0106 
0107 /* INTERRUPT CAUSE DEFINE */
0108 
0109 #define PRI_LOS_01_MASK     0x01
0110 #define PRI_LOS_10_MASK     0x02
0111 
0112 #define SEC_LOS_01_MASK     0x04
0113 #define SEC_LOS_10_MASK     0x08
0114 
0115 #define HOLDOVER_01_MASK    0x10
0116 #define HOLDOVER_10_MASK    0x20
0117 
0118 #define UNLOCK_01_MASK      0x40
0119 #define UNLOCK_10_MASK      0x80
0120 
0121 struct tlclk_alarms {
0122     __u32 lost_clocks;
0123     __u32 lost_primary_clock;
0124     __u32 lost_secondary_clock;
0125     __u32 primary_clock_back;
0126     __u32 secondary_clock_back;
0127     __u32 switchover_primary;
0128     __u32 switchover_secondary;
0129     __u32 pll_holdover;
0130     __u32 pll_end_holdover;
0131     __u32 pll_lost_sync;
0132     __u32 pll_sync;
0133 };
0134 /* Telecom clock I/O register definition */
0135 #define TLCLK_BASE 0xa08
0136 #define TLCLK_REG0 TLCLK_BASE
0137 #define TLCLK_REG1 (TLCLK_BASE+1)
0138 #define TLCLK_REG2 (TLCLK_BASE+2)
0139 #define TLCLK_REG3 (TLCLK_BASE+3)
0140 #define TLCLK_REG4 (TLCLK_BASE+4)
0141 #define TLCLK_REG5 (TLCLK_BASE+5)
0142 #define TLCLK_REG6 (TLCLK_BASE+6)
0143 #define TLCLK_REG7 (TLCLK_BASE+7)
0144 
0145 #define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port)
0146 
0147 /* 0 = Dynamic allocation of the major device number */
0148 #define TLCLK_MAJOR 0
0149 
0150 /* sysfs interface definition:
0151 Upon loading the driver will create a sysfs directory under
0152 /sys/devices/platform/telco_clock.
0153 
0154 This directory exports the following interfaces.  There operation is
0155 documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
0156 alarms              :
0157 current_ref         :
0158 received_ref_clk3a      :
0159 received_ref_clk3b      :
0160 enable_clk3a_output     :
0161 enable_clk3b_output     :
0162 enable_clka0_output     :
0163 enable_clka1_output     :
0164 enable_clkb0_output     :
0165 enable_clkb1_output     :
0166 filter_select           :
0167 hardware_switching      :
0168 hardware_switching_mode     :
0169 telclock_version        :
0170 mode_select         :
0171 refalign            :
0172 reset               :
0173 select_amcb1_transmit_clock :
0174 select_amcb2_transmit_clock :
0175 select_redundant_clock      :
0176 select_ref_frequency        :
0177 
0178 All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
0179 has the same effect as echo 0x99 > refalign.
0180 */
0181 
0182 static unsigned int telclk_interrupt;
0183 
0184 static int int_events;      /* Event that generate a interrupt */
0185 static int got_event;       /* if events processing have been done */
0186 
0187 static void switchover_timeout(struct timer_list *t);
0188 static struct timer_list switchover_timer;
0189 static unsigned long tlclk_timer_data;
0190 
0191 static struct tlclk_alarms *alarm_events;
0192 
0193 static DEFINE_SPINLOCK(event_lock);
0194 
0195 static int tlclk_major = TLCLK_MAJOR;
0196 
0197 static irqreturn_t tlclk_interrupt(int irq, void *dev_id);
0198 
0199 static DECLARE_WAIT_QUEUE_HEAD(wq);
0200 
0201 static unsigned long useflags;
0202 static DEFINE_MUTEX(tlclk_mutex);
0203 
0204 static int tlclk_open(struct inode *inode, struct file *filp)
0205 {
0206     int result;
0207 
0208     mutex_lock(&tlclk_mutex);
0209     if (test_and_set_bit(0, &useflags)) {
0210         result = -EBUSY;
0211         /* this legacy device is always one per system and it doesn't
0212          * know how to handle multiple concurrent clients.
0213          */
0214         goto out;
0215     }
0216 
0217     /* Make sure there is no interrupt pending while
0218      * initialising interrupt handler */
0219     inb(TLCLK_REG6);
0220 
0221     /* This device is wired through the FPGA IO space of the ATCA blade
0222      * we can't share this IRQ */
0223     result = request_irq(telclk_interrupt, &tlclk_interrupt,
0224                  0, "telco_clock", tlclk_interrupt);
0225     if (result == -EBUSY)
0226         printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
0227     else
0228         inb(TLCLK_REG6);    /* Clear interrupt events */
0229 
0230 out:
0231     mutex_unlock(&tlclk_mutex);
0232     return result;
0233 }
0234 
0235 static int tlclk_release(struct inode *inode, struct file *filp)
0236 {
0237     free_irq(telclk_interrupt, tlclk_interrupt);
0238     clear_bit(0, &useflags);
0239 
0240     return 0;
0241 }
0242 
0243 static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
0244         loff_t *f_pos)
0245 {
0246     if (count < sizeof(struct tlclk_alarms))
0247         return -EIO;
0248     if (mutex_lock_interruptible(&tlclk_mutex))
0249         return -EINTR;
0250 
0251 
0252     wait_event_interruptible(wq, got_event);
0253     if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) {
0254         mutex_unlock(&tlclk_mutex);
0255         return -EFAULT;
0256     }
0257 
0258     memset(alarm_events, 0, sizeof(struct tlclk_alarms));
0259     got_event = 0;
0260 
0261     mutex_unlock(&tlclk_mutex);
0262     return  sizeof(struct tlclk_alarms);
0263 }
0264 
0265 static const struct file_operations tlclk_fops = {
0266     .read = tlclk_read,
0267     .open = tlclk_open,
0268     .release = tlclk_release,
0269     .llseek = noop_llseek,
0270 
0271 };
0272 
0273 static struct miscdevice tlclk_miscdev = {
0274     .minor = MISC_DYNAMIC_MINOR,
0275     .name = "telco_clock",
0276     .fops = &tlclk_fops,
0277 };
0278 
0279 static ssize_t show_current_ref(struct device *d,
0280         struct device_attribute *attr, char *buf)
0281 {
0282     unsigned long ret_val;
0283     unsigned long flags;
0284 
0285     spin_lock_irqsave(&event_lock, flags);
0286     ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3);
0287     spin_unlock_irqrestore(&event_lock, flags);
0288 
0289     return sprintf(buf, "0x%lX\n", ret_val);
0290 }
0291 
0292 static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
0293 
0294 
0295 static ssize_t show_telclock_version(struct device *d,
0296         struct device_attribute *attr, char *buf)
0297 {
0298     unsigned long ret_val;
0299     unsigned long flags;
0300 
0301     spin_lock_irqsave(&event_lock, flags);
0302     ret_val = inb(TLCLK_REG5);
0303     spin_unlock_irqrestore(&event_lock, flags);
0304 
0305     return sprintf(buf, "0x%lX\n", ret_val);
0306 }
0307 
0308 static DEVICE_ATTR(telclock_version, S_IRUGO,
0309         show_telclock_version, NULL);
0310 
0311 static ssize_t show_alarms(struct device *d,
0312         struct device_attribute *attr,  char *buf)
0313 {
0314     unsigned long ret_val;
0315     unsigned long flags;
0316 
0317     spin_lock_irqsave(&event_lock, flags);
0318     ret_val = (inb(TLCLK_REG2) & 0xf0);
0319     spin_unlock_irqrestore(&event_lock, flags);
0320 
0321     return sprintf(buf, "0x%lX\n", ret_val);
0322 }
0323 
0324 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
0325 
0326 static ssize_t store_received_ref_clk3a(struct device *d,
0327          struct device_attribute *attr, const char *buf, size_t count)
0328 {
0329     unsigned long tmp;
0330     unsigned char val;
0331     unsigned long flags;
0332 
0333     sscanf(buf, "%lX", &tmp);
0334     dev_dbg(d, ": tmp = 0x%lX\n", tmp);
0335 
0336     val = (unsigned char)tmp;
0337     spin_lock_irqsave(&event_lock, flags);
0338     SET_PORT_BITS(TLCLK_REG1, 0xef, val);
0339     spin_unlock_irqrestore(&event_lock, flags);
0340 
0341     return strnlen(buf, count);
0342 }
0343 
0344 static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
0345         store_received_ref_clk3a);
0346 
0347 
0348 static ssize_t store_received_ref_clk3b(struct device *d,
0349          struct device_attribute *attr, const char *buf, size_t count)
0350 {
0351     unsigned long tmp;
0352     unsigned char val;
0353     unsigned long flags;
0354 
0355     sscanf(buf, "%lX", &tmp);
0356     dev_dbg(d, ": tmp = 0x%lX\n", tmp);
0357 
0358     val = (unsigned char)tmp;
0359     spin_lock_irqsave(&event_lock, flags);
0360     SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1);
0361     spin_unlock_irqrestore(&event_lock, flags);
0362 
0363     return strnlen(buf, count);
0364 }
0365 
0366 static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
0367         store_received_ref_clk3b);
0368 
0369 
0370 static ssize_t store_enable_clk3b_output(struct device *d,
0371          struct device_attribute *attr, const char *buf, size_t count)
0372 {
0373     unsigned long tmp;
0374     unsigned char val;
0375     unsigned long flags;
0376 
0377     sscanf(buf, "%lX", &tmp);
0378     dev_dbg(d, ": tmp = 0x%lX\n", tmp);
0379 
0380     val = (unsigned char)tmp;
0381     spin_lock_irqsave(&event_lock, flags);
0382     SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
0383     spin_unlock_irqrestore(&event_lock, flags);
0384 
0385     return strnlen(buf, count);
0386 }
0387 
0388 static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
0389         store_enable_clk3b_output);
0390 
0391 static ssize_t store_enable_clk3a_output(struct device *d,
0392          struct device_attribute *attr, const char *buf, size_t count)
0393 {
0394     unsigned long flags;
0395     unsigned long tmp;
0396     unsigned char val;
0397 
0398     sscanf(buf, "%lX", &tmp);
0399     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0400 
0401     val = (unsigned char)tmp;
0402     spin_lock_irqsave(&event_lock, flags);
0403     SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
0404     spin_unlock_irqrestore(&event_lock, flags);
0405 
0406     return strnlen(buf, count);
0407 }
0408 
0409 static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
0410         store_enable_clk3a_output);
0411 
0412 static ssize_t store_enable_clkb1_output(struct device *d,
0413          struct device_attribute *attr, const char *buf, size_t count)
0414 {
0415     unsigned long flags;
0416     unsigned long tmp;
0417     unsigned char val;
0418 
0419     sscanf(buf, "%lX", &tmp);
0420     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0421 
0422     val = (unsigned char)tmp;
0423     spin_lock_irqsave(&event_lock, flags);
0424     SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
0425     spin_unlock_irqrestore(&event_lock, flags);
0426 
0427     return strnlen(buf, count);
0428 }
0429 
0430 static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
0431         store_enable_clkb1_output);
0432 
0433 
0434 static ssize_t store_enable_clka1_output(struct device *d,
0435          struct device_attribute *attr, const char *buf, size_t count)
0436 {
0437     unsigned long flags;
0438     unsigned long tmp;
0439     unsigned char val;
0440 
0441     sscanf(buf, "%lX", &tmp);
0442     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0443 
0444     val = (unsigned char)tmp;
0445     spin_lock_irqsave(&event_lock, flags);
0446     SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
0447     spin_unlock_irqrestore(&event_lock, flags);
0448 
0449     return strnlen(buf, count);
0450 }
0451 
0452 static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
0453         store_enable_clka1_output);
0454 
0455 static ssize_t store_enable_clkb0_output(struct device *d,
0456          struct device_attribute *attr, const char *buf, size_t count)
0457 {
0458     unsigned long flags;
0459     unsigned long tmp;
0460     unsigned char val;
0461 
0462     sscanf(buf, "%lX", &tmp);
0463     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0464 
0465     val = (unsigned char)tmp;
0466     spin_lock_irqsave(&event_lock, flags);
0467     SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
0468     spin_unlock_irqrestore(&event_lock, flags);
0469 
0470     return strnlen(buf, count);
0471 }
0472 
0473 static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
0474         store_enable_clkb0_output);
0475 
0476 static ssize_t store_enable_clka0_output(struct device *d,
0477          struct device_attribute *attr, const char *buf, size_t count)
0478 {
0479     unsigned long flags;
0480     unsigned long tmp;
0481     unsigned char val;
0482 
0483     sscanf(buf, "%lX", &tmp);
0484     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0485 
0486     val = (unsigned char)tmp;
0487     spin_lock_irqsave(&event_lock, flags);
0488     SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
0489     spin_unlock_irqrestore(&event_lock, flags);
0490 
0491     return strnlen(buf, count);
0492 }
0493 
0494 static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
0495         store_enable_clka0_output);
0496 
0497 static ssize_t store_select_amcb2_transmit_clock(struct device *d,
0498         struct device_attribute *attr, const char *buf, size_t count)
0499 {
0500     unsigned long flags;
0501     unsigned long tmp;
0502     unsigned char val;
0503 
0504     sscanf(buf, "%lX", &tmp);
0505     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0506 
0507     val = (unsigned char)tmp;
0508     spin_lock_irqsave(&event_lock, flags);
0509     if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
0510         SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
0511         SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
0512     } else if (val >= CLK_8_592MHz) {
0513         SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
0514         switch (val) {
0515         case CLK_8_592MHz:
0516             SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
0517             break;
0518         case CLK_11_184MHz:
0519             SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
0520             break;
0521         case CLK_34_368MHz:
0522             SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
0523             break;
0524         case CLK_44_736MHz:
0525             SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
0526             break;
0527         }
0528     } else {
0529         SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
0530     }
0531     spin_unlock_irqrestore(&event_lock, flags);
0532 
0533     return strnlen(buf, count);
0534 }
0535 
0536 static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
0537     store_select_amcb2_transmit_clock);
0538 
0539 static ssize_t store_select_amcb1_transmit_clock(struct device *d,
0540          struct device_attribute *attr, const char *buf, size_t count)
0541 {
0542     unsigned long tmp;
0543     unsigned char val;
0544     unsigned long flags;
0545 
0546     sscanf(buf, "%lX", &tmp);
0547     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0548 
0549     val = (unsigned char)tmp;
0550     spin_lock_irqsave(&event_lock, flags);
0551     if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
0552         SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
0553         SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
0554     } else if (val >= CLK_8_592MHz) {
0555         SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
0556         switch (val) {
0557         case CLK_8_592MHz:
0558             SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
0559             break;
0560         case CLK_11_184MHz:
0561             SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
0562             break;
0563         case CLK_34_368MHz:
0564             SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
0565             break;
0566         case CLK_44_736MHz:
0567             SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
0568             break;
0569         }
0570     } else {
0571         SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
0572     }
0573     spin_unlock_irqrestore(&event_lock, flags);
0574 
0575     return strnlen(buf, count);
0576 }
0577 
0578 static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
0579         store_select_amcb1_transmit_clock);
0580 
0581 static ssize_t store_select_redundant_clock(struct device *d,
0582          struct device_attribute *attr, const char *buf, size_t count)
0583 {
0584     unsigned long tmp;
0585     unsigned char val;
0586     unsigned long flags;
0587 
0588     sscanf(buf, "%lX", &tmp);
0589     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0590 
0591     val = (unsigned char)tmp;
0592     spin_lock_irqsave(&event_lock, flags);
0593     SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
0594     spin_unlock_irqrestore(&event_lock, flags);
0595 
0596     return strnlen(buf, count);
0597 }
0598 
0599 static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
0600         store_select_redundant_clock);
0601 
0602 static ssize_t store_select_ref_frequency(struct device *d,
0603          struct device_attribute *attr, const char *buf, size_t count)
0604 {
0605     unsigned long tmp;
0606     unsigned char val;
0607     unsigned long flags;
0608 
0609     sscanf(buf, "%lX", &tmp);
0610     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0611 
0612     val = (unsigned char)tmp;
0613     spin_lock_irqsave(&event_lock, flags);
0614     SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
0615     spin_unlock_irqrestore(&event_lock, flags);
0616 
0617     return strnlen(buf, count);
0618 }
0619 
0620 static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
0621         store_select_ref_frequency);
0622 
0623 static ssize_t store_filter_select(struct device *d,
0624          struct device_attribute *attr, const char *buf, size_t count)
0625 {
0626     unsigned long tmp;
0627     unsigned char val;
0628     unsigned long flags;
0629 
0630     sscanf(buf, "%lX", &tmp);
0631     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0632 
0633     val = (unsigned char)tmp;
0634     spin_lock_irqsave(&event_lock, flags);
0635     SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
0636     spin_unlock_irqrestore(&event_lock, flags);
0637 
0638     return strnlen(buf, count);
0639 }
0640 
0641 static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
0642 
0643 static ssize_t store_hardware_switching_mode(struct device *d,
0644          struct device_attribute *attr, const char *buf, size_t count)
0645 {
0646     unsigned long tmp;
0647     unsigned char val;
0648     unsigned long flags;
0649 
0650     sscanf(buf, "%lX", &tmp);
0651     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0652 
0653     val = (unsigned char)tmp;
0654     spin_lock_irqsave(&event_lock, flags);
0655     SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
0656     spin_unlock_irqrestore(&event_lock, flags);
0657 
0658     return strnlen(buf, count);
0659 }
0660 
0661 static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
0662         store_hardware_switching_mode);
0663 
0664 static ssize_t store_hardware_switching(struct device *d,
0665          struct device_attribute *attr, const char *buf, size_t count)
0666 {
0667     unsigned long tmp;
0668     unsigned char val;
0669     unsigned long flags;
0670 
0671     sscanf(buf, "%lX", &tmp);
0672     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0673 
0674     val = (unsigned char)tmp;
0675     spin_lock_irqsave(&event_lock, flags);
0676     SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
0677     spin_unlock_irqrestore(&event_lock, flags);
0678 
0679     return strnlen(buf, count);
0680 }
0681 
0682 static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
0683         store_hardware_switching);
0684 
0685 static ssize_t store_refalign (struct device *d,
0686          struct device_attribute *attr, const char *buf, size_t count)
0687 {
0688     unsigned long tmp;
0689     unsigned long flags;
0690 
0691     sscanf(buf, "%lX", &tmp);
0692     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0693     spin_lock_irqsave(&event_lock, flags);
0694     SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
0695     SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
0696     SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
0697     spin_unlock_irqrestore(&event_lock, flags);
0698 
0699     return strnlen(buf, count);
0700 }
0701 
0702 static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
0703 
0704 static ssize_t store_mode_select (struct device *d,
0705          struct device_attribute *attr, const char *buf, size_t count)
0706 {
0707     unsigned long tmp;
0708     unsigned char val;
0709     unsigned long flags;
0710 
0711     sscanf(buf, "%lX", &tmp);
0712     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0713 
0714     val = (unsigned char)tmp;
0715     spin_lock_irqsave(&event_lock, flags);
0716     SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
0717     spin_unlock_irqrestore(&event_lock, flags);
0718 
0719     return strnlen(buf, count);
0720 }
0721 
0722 static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
0723 
0724 static ssize_t store_reset (struct device *d,
0725          struct device_attribute *attr, const char *buf, size_t count)
0726 {
0727     unsigned long tmp;
0728     unsigned char val;
0729     unsigned long flags;
0730 
0731     sscanf(buf, "%lX", &tmp);
0732     dev_dbg(d, "tmp = 0x%lX\n", tmp);
0733 
0734     val = (unsigned char)tmp;
0735     spin_lock_irqsave(&event_lock, flags);
0736     SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
0737     spin_unlock_irqrestore(&event_lock, flags);
0738 
0739     return strnlen(buf, count);
0740 }
0741 
0742 static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
0743 
0744 static struct attribute *tlclk_sysfs_entries[] = {
0745     &dev_attr_current_ref.attr,
0746     &dev_attr_telclock_version.attr,
0747     &dev_attr_alarms.attr,
0748     &dev_attr_received_ref_clk3a.attr,
0749     &dev_attr_received_ref_clk3b.attr,
0750     &dev_attr_enable_clk3a_output.attr,
0751     &dev_attr_enable_clk3b_output.attr,
0752     &dev_attr_enable_clkb1_output.attr,
0753     &dev_attr_enable_clka1_output.attr,
0754     &dev_attr_enable_clkb0_output.attr,
0755     &dev_attr_enable_clka0_output.attr,
0756     &dev_attr_select_amcb1_transmit_clock.attr,
0757     &dev_attr_select_amcb2_transmit_clock.attr,
0758     &dev_attr_select_redundant_clock.attr,
0759     &dev_attr_select_ref_frequency.attr,
0760     &dev_attr_filter_select.attr,
0761     &dev_attr_hardware_switching_mode.attr,
0762     &dev_attr_hardware_switching.attr,
0763     &dev_attr_refalign.attr,
0764     &dev_attr_mode_select.attr,
0765     &dev_attr_reset.attr,
0766     NULL
0767 };
0768 
0769 static const struct attribute_group tlclk_attribute_group = {
0770     .name = NULL,       /* put in device directory */
0771     .attrs = tlclk_sysfs_entries,
0772 };
0773 
0774 static struct platform_device *tlclk_device;
0775 
0776 static int __init tlclk_init(void)
0777 {
0778     int ret;
0779 
0780     telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
0781 
0782     alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
0783     if (!alarm_events) {
0784         ret = -ENOMEM;
0785         goto out1;
0786     }
0787 
0788     ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
0789     if (ret < 0) {
0790         printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
0791         kfree(alarm_events);
0792         return ret;
0793     }
0794     tlclk_major = ret;
0795 
0796     /* Read telecom clock IRQ number (Set by BIOS) */
0797     if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
0798         printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
0799             TLCLK_BASE);
0800         ret = -EBUSY;
0801         goto out2;
0802     }
0803 
0804     if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
0805         printk(KERN_ERR "telclk_interrupt = 0x%x non-mcpbl0010 hw.\n",
0806             telclk_interrupt);
0807         ret = -ENXIO;
0808         goto out3;
0809     }
0810 
0811     timer_setup(&switchover_timer, switchover_timeout, 0);
0812 
0813     ret = misc_register(&tlclk_miscdev);
0814     if (ret < 0) {
0815         printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
0816         goto out3;
0817     }
0818 
0819     tlclk_device = platform_device_register_simple("telco_clock",
0820                 -1, NULL, 0);
0821     if (IS_ERR(tlclk_device)) {
0822         printk(KERN_ERR "tlclk: platform_device_register failed.\n");
0823         ret = PTR_ERR(tlclk_device);
0824         goto out4;
0825     }
0826 
0827     ret = sysfs_create_group(&tlclk_device->dev.kobj,
0828             &tlclk_attribute_group);
0829     if (ret) {
0830         printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n");
0831         goto out5;
0832     }
0833 
0834     return 0;
0835 out5:
0836     platform_device_unregister(tlclk_device);
0837 out4:
0838     misc_deregister(&tlclk_miscdev);
0839 out3:
0840     release_region(TLCLK_BASE, 8);
0841 out2:
0842     kfree(alarm_events);
0843     unregister_chrdev(tlclk_major, "telco_clock");
0844 out1:
0845     return ret;
0846 }
0847 
0848 static void __exit tlclk_cleanup(void)
0849 {
0850     sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group);
0851     platform_device_unregister(tlclk_device);
0852     misc_deregister(&tlclk_miscdev);
0853     unregister_chrdev(tlclk_major, "telco_clock");
0854 
0855     release_region(TLCLK_BASE, 8);
0856     del_timer_sync(&switchover_timer);
0857     kfree(alarm_events);
0858 
0859 }
0860 
0861 static void switchover_timeout(struct timer_list *unused)
0862 {
0863     unsigned long flags = tlclk_timer_data;
0864 
0865     if ((flags & 1)) {
0866         if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
0867             alarm_events->switchover_primary++;
0868     } else {
0869         if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
0870             alarm_events->switchover_secondary++;
0871     }
0872 
0873     /* Alarm processing is done, wake up read task */
0874     del_timer(&switchover_timer);
0875     got_event = 1;
0876     wake_up(&wq);
0877 }
0878 
0879 static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
0880 {
0881     unsigned long flags;
0882 
0883     spin_lock_irqsave(&event_lock, flags);
0884     /* Read and clear interrupt events */
0885     int_events = inb(TLCLK_REG6);
0886 
0887     /* Primary_Los changed from 0 to 1 ? */
0888     if (int_events & PRI_LOS_01_MASK) {
0889         if (inb(TLCLK_REG2) & SEC_LOST_MASK)
0890             alarm_events->lost_clocks++;
0891         else
0892             alarm_events->lost_primary_clock++;
0893     }
0894 
0895     /* Primary_Los changed from 1 to 0 ? */
0896     if (int_events & PRI_LOS_10_MASK) {
0897         alarm_events->primary_clock_back++;
0898         SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
0899     }
0900     /* Secondary_Los changed from 0 to 1 ? */
0901     if (int_events & SEC_LOS_01_MASK) {
0902         if (inb(TLCLK_REG2) & PRI_LOST_MASK)
0903             alarm_events->lost_clocks++;
0904         else
0905             alarm_events->lost_secondary_clock++;
0906     }
0907     /* Secondary_Los changed from 1 to 0 ? */
0908     if (int_events & SEC_LOS_10_MASK) {
0909         alarm_events->secondary_clock_back++;
0910         SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
0911     }
0912     if (int_events & HOLDOVER_10_MASK)
0913         alarm_events->pll_end_holdover++;
0914 
0915     if (int_events & UNLOCK_01_MASK)
0916         alarm_events->pll_lost_sync++;
0917 
0918     if (int_events & UNLOCK_10_MASK)
0919         alarm_events->pll_sync++;
0920 
0921     /* Holdover changed from 0 to 1 ? */
0922     if (int_events & HOLDOVER_01_MASK) {
0923         alarm_events->pll_holdover++;
0924 
0925         /* TIMEOUT in ~10ms */
0926         switchover_timer.expires = jiffies + msecs_to_jiffies(10);
0927         tlclk_timer_data = inb(TLCLK_REG1);
0928         mod_timer(&switchover_timer, switchover_timer.expires);
0929     } else {
0930         got_event = 1;
0931         wake_up(&wq);
0932     }
0933     spin_unlock_irqrestore(&event_lock, flags);
0934 
0935     return IRQ_HANDLED;
0936 }
0937 
0938 module_init(tlclk_init);
0939 module_exit(tlclk_cleanup);