📄 toy.c
字号:
/* * * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com * Copied and modified Carsten Langgaard's time.c * * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * * ======================================== * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. 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., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. *================================== * * Setting up the clock on the MIPS boards. * */#include <linux/module.h>#include <linux/types.h>#include <linux/config.h>#include <linux/init.h>#include <linux/kernel_stat.h>#include <linux/sched.h>#include <linux/spinlock.h>#include <linux/miscdevice.h>#include <asm/mipsregs.h>#include <asm/ptrace.h>#include <asm/time.h>#include <asm/hardirq.h>#include <asm/div64.h>#include <asm/au1000.h>#include <asm/uaccess.h>#include <linux/mc146818rtc.h>#include <linux/timex.h>#define VERSION "0.01"#define COUNTER_MINOR 16#define HDP1100_TIME_IS_OPEN 0x1#define TIME_IOC_MAGIC 'E'#define START_TOY _IO(TIME_IOC_MAGIC,0)#define SET_MATCH10_INC_VALUE _IOR(TIME_IOC_MAGIC,1,int)#define STOP_TOY _IO(TIME_IOC_MAGIC,2)/* Cycle counter value at the previous timer interrupt.. */static unsigned long last_match10,match10_inc;static spinlock_t time_lock = SPIN_LOCK_UNLOCKED;static unsigned long hdp1100_time_status = 0;void counter0_interrupt(int irq, void *dev_id, struct pt_regs *regs){ printk("#################interrupt handler\n"); if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M10) { /* should never happen! */ printk(KERN_WARNING "counter 0 match10 w status error \n"); return; } last_match10 = au_readl(SYS_TOYREAD); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M10); au_writel(last_match10 + match10_inc, SYS_TOYMATCH1); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M10);}static int hdp1100_time_open(struct inode *inode, struct file *file){ unsigned long countorctrl; countorctrl=au_readl(SYS_COUNTER_CNTRL); au_writel(countorctrl|SYS_CNTRL_EN1|SYS_CNTRL_EN0,SYS_COUNTER_CNTRL); spin_lock_irq(&time_lock); if (hdp1100_time_status & HDP1100_TIME_IS_OPEN) { spin_unlock_irq(&time_lock); return -EBUSY; } hdp1100_time_status |= HDP1100_TIME_IS_OPEN; spin_unlock_irq(&time_lock); return 0;}static int hdp1100_time_release(struct inode *inode, struct file *file){ unsigned long countorctrl; countorctrl=au_readl(SYS_COUNTER_CNTRL); au_writel(countorctrl&(~SYS_CNTRL_EN1)&(~SYS_CNTRL_EN0),SYS_COUNTER_CNTRL); spin_lock_irq(&time_lock); hdp1100_time_status &= ~HDP1100_TIME_IS_OPEN; spin_unlock_irq(&time_lock); return 0;}static int hdp1100_time_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ u32 val; int result0=0; switch (cmd) { case START_TOY: //enable_irq(AU1000_TOY_MATCH1_INT); result0=request_irq(AU1000_TOY_MATCH1_INT,counter0_interrupt,SA_INTERRUPT,"counter",NULL); if(result0) { printk(KERN_INFO"can't get request irq AU1000_TOY_MATCH1_INT"); } break; case SET_MATCH10_INC_VALUE: if (get_user(val, (int *) arg)) result0=1; match10_inc=val*32768/16; break; case STOP_TOY: //disable_irq(AU1000_TOY_MATCH1_INT); free_irq(AU1000_TOY_MATCH1_INT,NULL); break; default: return -ENOTTY; } return (result0);}static struct file_operations hdp1100_time_fops ={ owner: THIS_MODULE, ioctl: hdp1100_time_ioctl, open: hdp1100_time_open, release: hdp1100_time_release,};static struct miscdevice hdp1100_time_dev = { COUNTER_MINOR, "counter", &hdp1100_time_fops};void __init hdp1100_time_init(void){ int trim_divide = 16; unsigned long countorctrl; match10_inc=328; countorctrl=au_readl(SYS_COUNTER_CNTRL); if( countorctrl& SYS_CNTRL_BT0==0) { au_writel(countorctrl& SYS_CNTRL_BT0, SYS_COUNTER_CNTRL); } while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); au_writel(trim_divide-1, SYS_TOYTRIM); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); /* TOY now ticks at 32.768/16 kHz */ //disable_irq(AU1000_TOY_MATCH1_INT); au_writel(countorctrl&(~SYS_CNTRL_EN1)&(~SYS_CNTRL_EN0),SYS_COUNTER_CNTRL); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); au_writel(0, SYS_TOYWRITE); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M10); last_match10 = au_readl(SYS_TOYREAD); au_writel(last_match10 + match10_inc, SYS_TOYMATCH1); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M10); misc_register(&hdp1100_time_dev); }static void __exit hdp1100_time_exit(void){ misc_deregister(&hdp1100_time_dev);}module_init(hdp1100_time_init);module_exit(hdp1100_time_exit);MODULE_AUTHOR("han");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -