Re: Patch of a new driver for kernel 2.4.x that need review

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday 22 June 2005 21:49, Willy Tarreau wrote:
> Hi Pekka,
>
> On Thu, Jun 23, 2005 at 07:16:17AM +0300, Pekka J Enberg wrote:
> > Hi Willy,
> >
> > Willy Tarreau writes:
> > >I dont agree with you here : enums are good to simply specify an
> > >ordering.
> > >But they must not be used to specify static mapping. Eg: if REG4 *must*
> > >be
> > >equal to BASE+4, you should not use enums, otherwise it will render the
> > >code unreadable. I personnaly don't want to count the position of REG7
> > > in the enum to discover that it's at BASE+7.
> >
> > Sorry, what do you have to count with the following?
> >
> > enum {
> >       TLCLK_REG0 = TLCLK_BASE,
> >       TLCLK_REG1 = TLCLK_BASE+1,
> >       TLCLK_REG2 = TLCLK_BASE+2,
> > };
>
> Sorry for the noise, I replied in a second mail that I was perfectly OK
> with this usage. What I though you wanted to propose was the simplest for
> of enum where only the first value is specified, and which is a nightmare
> to debug afterwards. Bill Gatliff also suggested that gdb can display and
> use the symbolic values while it's not the case on defines.
>
> Regards,
> Willy
>

I'm helping out Sebastien a bit with maintaining this driver attached is an update that attempts to 
address the commens from this thread.  The 2.6 version of this driver will be posted separately.

--mgross

diff -urN -X dontdiff_osdl vanilla/linux-2.4.31/drivers/char/Config.in linux-2.4/drivers/char/Config.in
--- vanilla/linux-2.4.31/drivers/char/Config.in	2004-08-07 16:26:04.000000000 -0700
+++ linux-2.4/drivers/char/Config.in	2005-07-06 12:30:28.000000000 -0700
@@ -401,4 +401,6 @@
    dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV
 fi
 
+tristate 'Telecom clock support' CONFIG_TELCLOCK
+
 endmenu
diff -urN -X dontdiff_osdl vanilla/linux-2.4.31/drivers/char/Makefile linux-2.4/drivers/char/Makefile
--- vanilla/linux-2.4.31/drivers/char/Makefile	2004-08-07 16:26:04.000000000 -0700
+++ linux-2.4/drivers/char/Makefile	2005-07-06 12:30:28.000000000 -0700
@@ -323,6 +323,7 @@
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
 obj-$(CONFIG_INDYDOG) += indydog.o
 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_TELCLOCK) += tlclk.o
 
 subdir-$(CONFIG_MWAVE) += mwave
 ifeq ($(CONFIG_MWAVE),y)
diff -urN -X dontdiff_osdl vanilla/linux-2.4.31/drivers/char/tlclk.c linux-2.4/drivers/char/tlclk.c
--- vanilla/linux-2.4.31/drivers/char/tlclk.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4/drivers/char/tlclk.c	2005-07-06 13:21:24.000000000 -0700
@@ -0,0 +1,459 @@
+/*
+ * Telecom Clock driver for Wainwright board
+ *
+ * Copyright (C) 2005 Kontron Canada
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <[email protected]>
+ *
+ * Description : This is the TELECOM CLOCK module driver for the ATCA platform.
+ */
+#ifndef __KERNEL__
+#  define __KERNEL__
+#endif
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>	/* printk() */
+#include <linux/fs.h>		/* everything... */
+#include <linux/errno.h>	/* error codes */
+#include <linux/delay.h>	/* udelay */
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/devfs_fs_kernel.h>	/* Devfs support */
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/tqueue.h>	/* interrupt task */
+#include <asm/io.h>		/* inb/outb */
+
+#include "tlclk.h"	/* TELECOM IOCTL DEFINE */
+
+MODULE_AUTHOR("Sebastien Bouchard <[email protected]>");
+MODULE_LICENSE("GPL");
+
+/* Telecom clock I/O register definition */
+#define TLCLK_BASE 0xa08            
+#define TLCLK_REG0 TLCLK_BASE
+#define TLCLK_REG1 (TLCLK_BASE+1)
+#define TLCLK_REG2 (TLCLK_BASE+2)
+#define TLCLK_REG3 (TLCLK_BASE+3)
+#define TLCLK_REG4 (TLCLK_BASE+4)
+#define TLCLK_REG5 (TLCLK_BASE+5)
+#define TLCLK_REG6 (TLCLK_BASE+6)
+#define TLCLK_REG7 (TLCLK_BASE+7)
+
+#define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port)
+
+/* 0 = Dynamic allocation of the major device number */
+#define TLCLK_MAJOR 252
+
+/* Contain the interrupt used for telecom clock */
+static int telclk_interrupt; 
+
+static int int_events;		/* Event that generate a interrupt */
+static int got_event;		/* if events processing have been done */
+
+static struct timer_list switchover_timer;
+
+struct tlclk_alarms *alarm_events;
+
+spinlock_t event_lock = SPIN_LOCK_UNLOCKED;
+
+/* DEVFS support or not */
+#ifdef CONFIG_DEVFS_FS
+devfs_handle_t devfs_handle;
+#else
+static int tlclk_major = TLCLK_MAJOR;
+#endif
+
+static void switchover_timeout(unsigned long data);
+void tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+DECLARE_WAIT_QUEUE_HEAD(wq);
+/*
+*  Function : Module I/O functions
+*  Description : Almost all the control stuff is done here, check I/O dn for
+*  help.
+*/
+static int
+tlclk_ioctl(struct inode *inode,
+	    struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	unsigned char val;
+	val = (unsigned char) arg;
+
+	if (_IOC_TYPE(cmd) != TLCLK_IOC_MAGIC)
+		return -ENOTTY;
+
+	if (_IOC_NR(cmd) > TLCLK_IOC_MAXNR)
+		return -ENOTTY;
+
+	switch (cmd) {
+	case IOCTL_RESET:
+		SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
+		break;
+	case IOCTL_MODE_SELECT:
+		SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
+		break;
+	case IOCTL_REFALIGN:
+		/* GENERATING 0 to 1 transistion */
+		SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
+		udelay(2);
+		SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
+		udelay(2);
+		SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
+		break;
+	case IOCTL_HARDWARE_SWITCHING:
+		SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
+		break;
+	case IOCTL_HARDWARE_SWITCHING_MODE:
+		SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
+		break;
+	case IOCTL_FILTER_SELECT:
+		SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
+		break;
+	case IOCTL_SELECT_REF_FREQUENCY:
+		spin_lock_irqsave(&event_lock, flags);
+		SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
+		spin_unlock_irqrestore(&event_lock, flags);
+		break;
+	case IOCTL_SELECT_REDUNDANT_CLOCK:
+		spin_lock_irqsave(&event_lock, flags);
+		SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
+		spin_unlock_irqrestore(&event_lock, flags);
+		break;
+	case IOCTL_SELECT_AMCB1_TRANSMIT_CLOCK:
+		if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
+			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
+			SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
+		} else if (val >= CLK_8_592MHz) {
+			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
+			switch (val) {
+			case CLK_8_592MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+				break;
+			case CLK_11_184MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
+				break;
+			case CLK_34_368MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
+				break;
+			case CLK_44_736MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+				break;
+			}
+		} else
+			SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
+		break;
+	case IOCTL_SELECT_AMCB2_TRANSMIT_CLOCK:
+		if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
+			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
+			SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
+		} else if (val >= CLK_8_592MHz) {
+			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
+			switch (val) {
+			case CLK_8_592MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+				break;
+			case CLK_11_184MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
+				break;
+			case CLK_34_368MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
+				break;
+			case CLK_44_736MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+				break;
+			}
+		} else
+			SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
+		break;
+	case IOCTL_TEST_MODE:
+		SET_PORT_BITS(TLCLK_REG4, 0xfd, 2);
+		break;
+	case IOCTL_ENABLE_CLKA0_OUTPUT:
+		SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
+		break;
+	case IOCTL_ENABLE_CLKB0_OUTPUT:
+		SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
+		break;
+	case IOCTL_ENABLE_CLKA1_OUTPUT:
+		SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
+		break;
+	case IOCTL_ENABLE_CLKB1_OUTPUT:
+		SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
+		break;
+	case IOCTL_ENABLE_CLK3A_OUTPUT:
+		SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
+		break;
+	case IOCTL_ENABLE_CLK3B_OUTPUT:
+		SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
+		break;
+	case IOCTL_READ_ALARMS:
+		return (inb(TLCLK_REG2) & 0xf0);
+		break;
+	case IOCTL_READ_INTERRUPT_SWITCH:
+		return inb(TLCLK_REG6);
+		break;
+	case IOCTL_READ_CURRENT_REF:
+		return ((inb(TLCLK_REG1) & 0x08) >> 3);
+		break;
+	}
+
+	return 0;
+}
+
+/*
+*  Function : Module Opening
+*  Description : Called when a program open the 
+*  /dev/telclock file related to the module.
+*/
+static int
+tlclk_open(struct inode *inode, struct file *filp)
+{
+	int result;
+#ifdef MODULE
+	if (!MOD_IN_USE) {
+		MOD_INC_USE_COUNT;
+#endif
+		/* Make sure there is no interrupt pending will 
+		   *  initialising interrupt handler */
+		inb(TLCLK_REG6);
+
+		result = request_irq(telclk_interrupt, &tlclk_interrupt,
+					SA_SHIRQ, "telclock", tlclk_interrupt);
+		printk("\ntelclock: Reserving IRQ%d...\n", telclk_interrupt);
+		if (result == -EBUSY) {
+			printk(KERN_ERR
+				"telclock: Interrupt can't be reserved!\n");
+			return -EBUSY;
+		}
+		inb(TLCLK_REG6);	/* Clear interrupt events */
+#ifdef MODULE
+	} else
+		return -EBUSY;
+#endif
+	return 0;
+}
+
+/*
+*  Function : Module Releasing
+*  Description : Called when a program stop using the module.
+*/
+static int
+tlclk_release(struct inode *inode, struct file *filp)
+{
+	MOD_DEC_USE_COUNT;
+	if (!MOD_IN_USE)
+		free_irq(telclk_interrupt, tlclk_interrupt);
+	return 0;
+}
+
+ssize_t
+tlclk_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
+{
+	int count0 = sizeof(struct tlclk_alarms);
+	wait_event_interruptible(wq, got_event);
+	if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms)))
+		return -EFAULT;
+
+	memset(alarm_events, 0, sizeof(struct tlclk_alarms));
+	got_event = 0;
+	
+	return count0;
+}
+
+ssize_t
+tlclk_write(struct file * filp, const char *buf, size_t count, loff_t * f_pos)
+{
+	return 0;
+}
+
+/*
+* This is where you set what function is called when an action is done to your
+*  /dev file.
+*/
+static struct file_operations tlclk_fops = {
+	.read = tlclk_read,
+	.write = tlclk_write,
+	.ioctl = tlclk_ioctl,
+	.open = tlclk_open,
+	.release = tlclk_release,
+
+};
+/*
+* Function : Module Initialisation                      
+* Description : Called at module loading, 
+* all the OS registering stuff is her
+*/
+static int __init
+tlclk_init(void)
+{
+/* DEVFS or NOT? */
+#ifdef CONFIG_DEVFS_FS
+	devfs_handle = devfs_register(NULL, "telclock",
+					DEVFS_FL_AUTO_DEVNUM, TLCLK_MAJOR,
+					0,
+					S_IFCHR | S_IRUGO | S_IWUGO,
+					&tlclk_fops, NULL);
+	if (!devfs_handle)
+		goto out1;
+#else
+	tlclk_major = register_chrdev(tlclk_major, "telclock", &tlclk_fops);
+
+	if (tlclk_major < 0) {
+		printk(KERN_ERR "telclock: can't get major! %d\n", tlclk_major);
+		return tlclk_major;
+	}
+#endif
+
+	alarm_events = kmalloc(sizeof(struct tlclk_alarms), GFP_KERNEL);
+	
+	if (!alarm_events)
+		goto out1;
+	
+	memset(alarm_events, 0, sizeof(struct tlclk_alarms));
+
+/* Read telecom clock IRQ number (Set by BIOS) */
+
+	printk(KERN_WARNING "telclock: Reserving I/O region...\n");
+
+	if ( !request_region(TLCLK_BASE, 8, "telclock") ) {
+		printk(KERN_ERR "telclock: request_region failed!\n");
+			goto out2;
+	}
+	telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
+
+	init_timer(&switchover_timer);
+	switchover_timer.function = switchover_timeout;
+	switchover_timer.data = 0;
+
+	return 0;
+out2:
+	kfree(alarm_events);
+out1:
+	return -EBUSY;
+}
+
+/*
+*  Function : Module Cleaning 
+*  Description : Called when unloading the module
+*/
+static void __exit
+tlclk_cleanup(void)
+{
+#ifdef CONFIG_DEVFS_FS
+	devfs_unregister(devfs_handle);
+#else
+	unregister_chrdev(tlclk_major, "telclock");
+#endif
+	release_region(TLCLK_BASE, 8);
+	del_timer_sync(&switchover_timer);
+	kfree(alarm_events);
+	
+}
+static void
+switchover_timeout(unsigned long data)
+{
+	if ((data & 1)) {
+		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+			alarm_events->switchover_primary++;
+	} else {
+		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+			alarm_events->switchover_secondary++;
+	}
+
+	/* Alarm processing is done, wake up read task */
+	del_timer(&switchover_timer);
+	got_event = 1;
+	wake_up(&wq);
+}
+/*
+*  Function : Interrupt Handler 
+*  Description :
+*  Handling of alarms interrupt.
+*  
+*/
+void
+tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&event_lock, flags);
+	/* Read and clear interrupt events */
+	int_events = inb(TLCLK_REG6);
+	spin_unlock_irqrestore(&event_lock, flags);
+	
+	/* Primary_Los changed from 0 to 1 ? */
+	if (int_events & PRI_LOS_01_MASK) {
+		if (inb(TLCLK_REG2) & SEC_LOST_MASK)
+			alarm_events->lost_clocks++;
+		else
+			alarm_events->lost_primary_clock++;
+	}
+
+	/* Primary_Los changed from 1 to 0 ? */
+	if (int_events & PRI_LOS_10_MASK) {
+		alarm_events->primary_clock_back++;
+		spin_lock_irqsave(&event_lock, flags);
+		SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
+		spin_unlock_irqrestore(&event_lock, flags);
+	}
+	/* Secondary_Los changed from 0 to 1 ? */
+	if (int_events & SEC_LOS_01_MASK) {
+		if (inb(TLCLK_REG2) & PRI_LOST_MASK)
+			alarm_events->lost_clocks++;
+		else
+			alarm_events->lost_secondary_clock++;
+	}
+	/* Secondary_Los changed from 1 to 0 ? */
+	if (int_events & SEC_LOS_10_MASK) {
+		alarm_events->secondary_clock_back++;
+		spin_lock_irqsave(&event_lock, flags);
+		SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
+		spin_unlock_irqrestore(&event_lock, flags);
+	}
+	if (int_events & HOLDOVER_10_MASK)
+		alarm_events->pll_end_holdover++;
+
+	if (int_events & UNLOCK_01_MASK)
+		alarm_events->pll_lost_sync++;
+
+	if (int_events & UNLOCK_10_MASK)
+		alarm_events->pll_sync++;
+
+	/* Holdover changed from 0 to 1 ? */
+	if (int_events & HOLDOVER_01_MASK) {
+		alarm_events->pll_holdover++;
+
+		switchover_timer.expires = jiffies + 1;	/* TIMEOUT in ~10ms */
+		switchover_timer.data = inb(TLCLK_REG1);
+		add_timer(&switchover_timer);
+	} else {
+		got_event = 1;
+		wake_up(&wq);
+	}
+}
+
+module_init(tlclk_init);
+module_exit(tlclk_cleanup);
diff -urN -X dontdiff_osdl vanilla/linux-2.4.31/drivers/char/tlclk.h linux-2.4/drivers/char/tlclk.h
--- vanilla/linux-2.4.31/drivers/char/tlclk.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4/drivers/char/tlclk.h	2005-07-06 12:30:28.000000000 -0700
@@ -0,0 +1,167 @@
+/*
+ * Telecom Clock driver for Wainwright board
+ *
+ * Copyright (C) 2005 Kontron Canada
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <[email protected]>
+ *
+ */
+ 
+/* Ioctl definitions  */
+
+/* Use 0xA1 as magic number */
+#define TLCLK_IOC_MAGIC 0xA1
+
+/*Hardware Reset of the PLL */
+
+#define RESET_ON 0x00
+#define RESET_OFF 0x01
+#define IOCTL_RESET _IO(TLCLK_IOC_MAGIC,  1)
+
+#define IOCTL_REFALIGN _IO(TLCLK_IOC_MAGIC,  2)
+
+/* MODE SELECT */
+
+#define NORMAL_MODE 0x00
+#define HOLDOVER_MODE 0x10
+#define FREERUN_MODE 0x20
+
+#define IOCTL_MODE_SELECT _IOR(TLCLK_IOC_MAGIC,  3, char)
+
+/* FILTER SELECT */
+
+#define FILTER_6HZ 0x04
+#define FILTER_12HZ 0x00
+
+#define IOCTL_FILTER_SELECT _IOR(TLCLK_IOC_MAGIC,  4, char)
+
+/* SELECT REFERENCE FREQUENCY */
+
+#define REF_CLK1_8kHz 0x00
+#define REF_CLK2_19_44MHz 0x02
+
+#define IOCTL_SELECT_REF_FREQUENCY _IOR(TLCLK_IOC_MAGIC,  6, char)
+
+/* Select primary or secondary redundant clock */
+
+#define PRIMARY_CLOCK 0x00
+#define SECONDARY_CLOCK 0x01
+#define IOCTL_SELECT_REDUNDANT_CLOCK _IOR(TLCLK_IOC_MAGIC,  7, char)
+
+/* CLOCK TRANSMISSION DEFINE */
+
+#define CLK_8kHz 0xff
+#define CLK_16_384MHz 0xfb
+
+#define CLK_1_544MHz 0x00
+#define CLK_2_048MHz 0x01
+#define CLK_4_096MHz 0x02
+#define CLK_6_312MHz 0x03
+#define CLK_8_192MHz 0x04
+#define CLK_19_440MHz 0x06
+
+#define CLK_8_592MHz 0x08
+#define CLK_11_184MHz 0x09
+#define CLK_34_368MHz 0x0b
+#define CLK_44_736MHz 0x0a
+
+#define IOCTL_SELECT_AMCB1_TRANSMIT_CLOCK _IOR(TLCLK_IOC_MAGIC,  9, char)
+#define IOCTL_SELECT_AMCB2_TRANSMIT_CLOCK _IOR(TLCLK_IOC_MAGIC,  10, char)
+
+/* RECEIVED REFERENCE */
+
+#define AMC_B1 0
+#define AMC_B2 1
+
+#define IOCTL_SELECT_RECEIVED_REF_CLK3A _IOR(TLCLK_IOC_MAGIC,  11, char)
+#define IOCTL_SELECT_RECEIVED_REF_CLK3B _IOR(TLCLK_IOC_MAGIC,  12, char)
+
+/* OEM COMMAND - NOT IN FINAL VERSION */
+
+#define IOCTL_TEST_MODE _IO(TLCLK_IOC_MAGIC,  13)
+
+/* HARDWARE SWITCHING DEFINE */
+
+#define HW_ENABLE 0x80
+#define HW_DISABLE 0x00
+
+#define IOCTL_HARDWARE_SWITCHING _IOR(TLCLK_IOC_MAGIC,  14, char)
+
+/* HARDWARE SWITCHING MODE DEFINE */
+
+#define PLL_HOLDOVER 0x40
+#define LOST_CLOCK 0x00
+
+#define IOCTL_HARDWARE_SWITCHING_MODE _IOR(TLCLK_IOC_MAGIC,  15, char)
+
+/* CLOCK OUTPUT DEFINE */
+
+#define IOCTL_ENABLE_CLKA0_OUTPUT _IOR(TLCLK_IOC_MAGIC,  16, char)
+#define IOCTL_ENABLE_CLKB0_OUTPUT _IOR(TLCLK_IOC_MAGIC,  17, char)
+#define IOCTL_ENABLE_CLKA1_OUTPUT _IOR(TLCLK_IOC_MAGIC,  18, char)
+#define IOCTL_ENABLE_CLKB1_OUTPUT _IOR(TLCLK_IOC_MAGIC,  19, char)
+
+#define IOCTL_ENABLE_CLK3A_OUTPUT _IOR(TLCLK_IOC_MAGIC,  20, char)
+#define IOCTL_ENABLE_CLK3B_OUTPUT _IOR(TLCLK_IOC_MAGIC,  21, char)
+
+/* ALARMS DEFINE */
+
+#define UNLOCK_MASK 0x10
+#define HOLDOVER_MASK 0x20
+#define SEC_LOST_MASK 0x40
+#define PRI_LOST_MASK 0x80
+
+#define IOCTL_READ_ALARMS _IO(TLCLK_IOC_MAGIC,  22)
+
+/* INTERRUPT CAUSE DEFINE */
+
+#define PRI_LOS_01_MASK 0x01
+#define PRI_LOS_10_MASK 0x02
+
+#define SEC_LOS_01_MASK 0x04
+#define SEC_LOS_10_MASK 0x08
+
+#define HOLDOVER_01_MASK 0x10
+#define HOLDOVER_10_MASK 0x20
+
+#define UNLOCK_01_MASK 0x40
+#define UNLOCK_10_MASK 0x80
+
+#define IOCTL_READ_INTERRUPT_SWITCH _IO(TLCLK_IOC_MAGIC,  23)
+
+#define IOCTL_READ_CURRENT_REF _IO(TLCLK_IOC_MAGIC,  25)
+
+/* MAX NUMBER OF IOCTL */
+#define TLCLK_IOC_MAXNR 25
+
+struct tlclk_alarms {
+	unsigned int lost_clocks;
+	unsigned int lost_primary_clock;
+	unsigned int lost_secondary_clock;
+	unsigned int primary_clock_back;
+	unsigned int secondary_clock_back;
+	unsigned int switchover_primary;
+	unsigned int switchover_secondary;
+	unsigned int pll_holdover;
+	unsigned int pll_end_holdover;
+	unsigned int pll_lost_sync;
+	unsigned int pll_sync;
+};
+

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux