linux/drivers/char/tlclk.c

/*
 * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010
 *
 * 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]> and the current
 * Maintainer  <[email protected]>
 *
 * Description : This is the TELECOM CLOCK module driver for the ATCA
 * MPCBL0010 ATCA computer.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>	/* printk() */
#include <linux/fs.h>		/* everything... */
#include <linux/errno.h>	/* error codes */
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <asm/io.h>		/* inb/outb */
#include <linux/uaccess.h>

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

/*Hardware Reset of the PLL */
#define RESET_ON
#define RESET_OFF

/* MODE SELECT */
#define NORMAL_MODE
#define HOLDOVER_MODE
#define FREERUN_MODE

/* FILTER SELECT */
#define FILTER_6HZ
#define FILTER_12HZ

/* SELECT REFERENCE FREQUENCY */
#define REF_CLK1_8kHz
#define REF_CLK2_19_44MHz

/* Select primary or secondary redundant clock */
#define PRIMARY_CLOCK
#define SECONDARY_CLOCK

/* CLOCK TRANSMISSION DEFINE */
#define CLK_8kHz
#define CLK_16_384MHz

#define CLK_1_544MHz
#define CLK_2_048MHz
#define CLK_4_096MHz
#define CLK_6_312MHz
#define CLK_8_192MHz
#define CLK_19_440MHz

#define CLK_8_592MHz
#define CLK_11_184MHz
#define CLK_34_368MHz
#define CLK_44_736MHz

/* RECEIVED REFERENCE */
#define AMC_B1
#define AMC_B2

/* HARDWARE SWITCHING DEFINE */
#define HW_ENABLE
#define HW_DISABLE

/* HARDWARE SWITCHING MODE DEFINE */
#define PLL_HOLDOVER
#define LOST_CLOCK

/* ALARMS DEFINE */
#define UNLOCK_MASK
#define HOLDOVER_MASK
#define SEC_LOST_MASK
#define PRI_LOST_MASK

/* INTERRUPT CAUSE DEFINE */

#define PRI_LOS_01_MASK
#define PRI_LOS_10_MASK

#define SEC_LOS_01_MASK
#define SEC_LOS_10_MASK

#define HOLDOVER_01_MASK
#define HOLDOVER_10_MASK

#define UNLOCK_01_MASK
#define UNLOCK_10_MASK

struct tlclk_alarms {};
/* Telecom clock I/O register definition */
#define TLCLK_BASE
#define TLCLK_REG0
#define TLCLK_REG1
#define TLCLK_REG2
#define TLCLK_REG3
#define TLCLK_REG4
#define TLCLK_REG5
#define TLCLK_REG6
#define TLCLK_REG7

#define SET_PORT_BITS(port, mask, val)

/* 0 = Dynamic allocation of the major device number */
#define TLCLK_MAJOR

/* sysfs interface definition:
Upon loading the driver will create a sysfs directory under
/sys/devices/platform/telco_clock.

This directory exports the following interfaces.  There operation is
documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
alarms				:
current_ref			:
received_ref_clk3a		:
received_ref_clk3b		:
enable_clk3a_output		:
enable_clk3b_output		:
enable_clka0_output		:
enable_clka1_output		:
enable_clkb0_output		:
enable_clkb1_output		:
filter_select			:
hardware_switching		:
hardware_switching_mode		:
telclock_version		:
mode_select			:
refalign			:
reset				:
select_amcb1_transmit_clock	:
select_amcb2_transmit_clock	:
select_redundant_clock		:
select_ref_frequency		:

All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
has the same effect as echo 0x99 > refalign.
*/

static unsigned int telclk_interrupt;

static int int_events;		/* Event that generate a interrupt */
static int got_event;		/* if events processing have been done */

static void switchover_timeout(struct timer_list *t);
static struct timer_list switchover_timer;
static unsigned long tlclk_timer_data;

static struct tlclk_alarms *alarm_events;

static DEFINE_SPINLOCK(event_lock);

static int tlclk_major =;

static irqreturn_t tlclk_interrupt(int irq, void *dev_id);

static DECLARE_WAIT_QUEUE_HEAD(wq);

static unsigned long useflags;
static DEFINE_MUTEX(tlclk_mutex);

static int tlclk_open(struct inode *inode, struct file *filp)
{}

static int tlclk_release(struct inode *inode, struct file *filp)
{}

static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
		loff_t *f_pos)
{}

static const struct file_operations tlclk_fops =;

static struct miscdevice tlclk_miscdev =;

static ssize_t show_current_ref(struct device *d,
		struct device_attribute *attr, char *buf)
{}

static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);


static ssize_t show_telclock_version(struct device *d,
		struct device_attribute *attr, char *buf)
{}

static DEVICE_ATTR(telclock_version, S_IRUGO,
		show_telclock_version, NULL);

static ssize_t show_alarms(struct device *d,
		struct device_attribute *attr,  char *buf)
{}

static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);

static ssize_t store_received_ref_clk3a(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
		store_received_ref_clk3a);


static ssize_t store_received_ref_clk3b(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
		store_received_ref_clk3b);


static ssize_t store_enable_clk3b_output(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
		store_enable_clk3b_output);

static ssize_t store_enable_clk3a_output(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
		store_enable_clk3a_output);

static ssize_t store_enable_clkb1_output(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
		store_enable_clkb1_output);


static ssize_t store_enable_clka1_output(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
		store_enable_clka1_output);

static ssize_t store_enable_clkb0_output(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
		store_enable_clkb0_output);

static ssize_t store_enable_clka0_output(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
		store_enable_clka0_output);

static ssize_t store_select_amcb2_transmit_clock(struct device *d,
		struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
	store_select_amcb2_transmit_clock);

static ssize_t store_select_amcb1_transmit_clock(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
		store_select_amcb1_transmit_clock);

static ssize_t store_select_redundant_clock(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
		store_select_redundant_clock);

static ssize_t store_select_ref_frequency(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
		store_select_ref_frequency);

static ssize_t store_filter_select(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);

static ssize_t store_hardware_switching_mode(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
		store_hardware_switching_mode);

static ssize_t store_hardware_switching(struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
		store_hardware_switching);

static ssize_t store_refalign (struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);

static ssize_t store_mode_select (struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);

static ssize_t store_reset (struct device *d,
		 struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);

static struct attribute *tlclk_sysfs_entries[] =;

static const struct attribute_group tlclk_attribute_group =;

static struct platform_device *tlclk_device;

static int __init tlclk_init(void)
{}

static void __exit tlclk_cleanup(void)
{}

static void switchover_timeout(struct timer_list *unused)
{}

static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
{}

module_init();
module_exit(tlclk_cleanup);