在linux/arch/arm/mach-s3c2410/time.c 里
内核的主要工作是初始化了这样一个结构
struct sys_timer s3c24xx_timer = {
.init = s3c2410_timer_init,
.offset = s3c2410_gettimeoffset,
.resume = s3c2410_timer_setup
};
下面是s3c2410_timer_init的实现
static void __init s3c2410_timer_init (void)
{
s3c2410_timer_setup(); //这里做了一些时钟初始化设置,但是针对timer4的
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); //设置中断处理函数
}
s3c24xx_timer又在linux/arch/arm/mach-s3c2410/mach-smdk2410.c中被调用
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
MAINTAINER("Jonas Dietsche")
BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(smdk2410_map_io)
INITIRQ(smdk2410_init_irq)
.timer = &s3c24xx_timer, //这里!!!
MACHINE_END
我觉得执行完上述代码后时钟就应该设置好了。所以我想先在s3c2410_timer_setup()里参照timer4的加入对timer1的初始化,然后在s3c2410_timer_init里再添加一个setup_irq()
我正好打算写一个PWM的驱动,所以也就试了timer,结果是可以的,没问题。这是我用来测试的驱动程序,你可以参考一下。加载这个ko后,在timer0中断时会在console打印一个字符串。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("Dual BSD/GPS");
int timer_major = 0;
int timer_minor = 0;
static DECLARE_WAIT_QUEUE_HEAD(timer0_wait);
struct cdev cdev;
static int timer_ioctl(struct inode* node, struct file* f, unsigned int cmd, unsigned long arg)
{
return 0;
}
struct file_operations timer_fops = {
.owner = THIS_MODULE,
.ioctl = timer_ioctl,
};
static irqreturn_t timer0_irq(int irq, void* dev_id, struct pt_regs* reg)
{
printk(KERN_ALERT "timer0 irq ");
wake_up_interruptible(&timer0_wait);
return IRQ_HANDLED;
}
static void setup_led_ios(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPB7_OUTP);
s3c2410_gpio_pullup(S3C2410_GPB7, 1);
}
static void setup_timer0(void)
{
unsigned long nTCON;
unsigned long nTCNT;
unsigned long nTCFG0;
unsigned long nTCFG1;
nTCON = __raw_readl(S3C2410_TCON);
nTCFG0 = __raw_readl(S3C2410_TCFG0);
nTCFG1 = __raw_readl(S3C2410_TCFG1);
nTCFG1 &= ~S3C2410_TCFG1_MUX0_MASK;
nTCFG1 |= S3C2410_TCFG1_MUX0_DIV16;
nTCFG0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
nTCFG0 |= 0xFF;
nTCNT = 0xFFFF;
__raw_writel(nTCFG1, S3C2410_TCFG1);
__raw_writel(nTCFG0, S3C2410_TCFG0);
__raw_writel(nTCNT--, S3C2410_TCNTB(0));
nTCON &= ~(0xF);
nTCON |= S3C2410_TCON_T0RELOAD;
nTCON |= S3C2410_TCON_T0MANUALUPD;
__raw_writel(nTCON, S3C2410_TCON);
__raw_writel(nTCNT, S3C2410_TCNTB(0));
__raw_writel(nTCNT, S3C2410_TCMPB(0));
nTCON |= S3C2410_TCON_T0START;
nTCON &= ~S3C2410_TCON_T0MANUALUPD;
__raw_writel(nTCON, S3C2410_TCON);
}
static int sbc2410_timer_init(void)
{
int result;
dev_t dev = 0;
printk(KERN_ALERT "sbc2410 timer-led driver ");
result = alloc_chrdev_region(&dev, timer_minor, 1, "timerled");
timer_major = MAJOR(dev);
if (request_irq(IRQ_TIMER0, timer0_irq, SA_INTERRUPT, "timer0", NULL))
{
printk(KERN_ALERT "request_irq error ");
return -1;
}
setup_led_ios();
setup_timer0();
cdev_init(&cdev, &timer_fops);
cdev_add(&cdev, dev, 1);
return 0;
}
static void sbc2410_timer_exit(void)
{
dev_t dev = MKDEV(timer_major, timer_minor);
cdev_del(&cdev);
unregister_chrdev_region(dev, 0);
printk(KERN_ALERT "sbc2410 timer driver exit. ");
}
module_init(sbc2410_timer_init);
module_exit(sbc2410_timer_exit);
阅读(815) | 评论(0) | 转发(0) |