03day02wdt

  1 #include <linux/module.h>
  2 #include <linux/init.h>
  3 #include <linux/kernel.h>
  4 
  5 #include <linux/interrupt.h> //request_irq   注册中断
  6 #include <mach/irqs.h>   // EXYNOS4_IRQ_WDT   中断号
  7 #include <mach/map.h> // 0x10060000
  8 #include <linux/io.h>   //ioremap
  9 #include <linux/ioport.h> //request_mem_region
 10 #include <mach/regs-clock.h> 
 11 
 12 /*
 13 把内核中的看门狗 删除
 14 make menuconfig --> Device Drivers-->Watchdog Timer Support  --->S3C2410 Watchdog
 15 该选项去掉,
 16 内核中已经有了看门狗驱动,已经申请了对应的中断,为了避免冲突,需要把看门狗去掉
 17 
 18 把看门狗 当做 定时器
 19 
 20 */
 21 
 22 /*
 23 参照硬件手册446页中,提供给wdt的时钟频率是 100Mhz
 24 
 25 WDT  看门狗 控制器
 26 CON寄存器  8:15位    一级分频   +1
 27 3:4  位    二级分频    16  32  64  128 分频
 28 100倍分频    128分频
 29 */
 30 
 31 #define DEVNAME "ldm"  //中断的名称
 32 //14位 用于打开wdt 的时钟
 33 //10038960
 34 #define WDT_CLOCK  (*(volatile u32 *)(ioremap(0x10038960, 4)))
 35 
 36 enum 
 37 {
 38     PCLK  =  100000000, //总线的频率 100MHz
 39     PRESCALER = 99,  //1级分频为100分频
 40     DIV  = 3 ,// 2级分频为128分频
 41     WDT_HZ = PCLK /(PRESCALER + 1) / 128,
 42 };
 43 
 44 //0x10060000
 45 struct  wdt_reg {
 46     u32   con;
 47     u32   dat;
 48     u32   cnt;
 49     u32   clrint;
 50 };
 51 
 52 struct wdt_reg * reg;
 53 
 54 //中断处理函数
 55 irqreturn_t wdt_handle(int  irqno, void * data)
 56 {
 57     printk("wdt_handle   &&&&&&&&&&&&&&&&
");
 58     //清除中断标志
 59     reg->clrint = 0x1111;
 60 
 61     return  IRQ_HANDLED;
 62 }
 63 
 64 
 65 static int test_init(void)
 66 {
 67     int ret = 0;
 68     printk("%s:%d
", __FILE__, __LINE__);
 69     //硬件手册中 487页    14位用于控制wdt  的时钟开关
 70     //打开时钟
 71     WDT_CLOCK   |=  1 << 14;
 72     //(volatile  u32  *)ioremap(0x10038960, 4);
 73 
 74     //申请寄存器的访问范围  在/proc/iomem
 75     if(!request_mem_region(EXYNOS4_PA_WATCHDOG,  sizeof(struct   wdt_reg), DEVNAME)) {
 76         ret = -EBUSY; //该空间已经被使用
 77         printk("request_mem_region  failed
");
 78         goto  err_request_mem_region;
 79     }
 80 
 81     //配置wdt  中各种寄存器
 82     reg = ioremap(EXYNOS4_PA_WATCHDOG, sizeof(struct wdt_reg)); //物理地址转换为虚拟地址
 83 
 84     //申请中断
 85     ret = request_irq(EXYNOS4_IRQ_WDT, wdt_handle, 0, 
 86         DEVNAME,   NULL);
 87     if(ret < 0) {
 88         printk("request_irq  failed
");
 89         goto  err_request_irq;
 90     }
 91 
 92 
 93     reg->dat = WDT_HZ;
 94     reg->cnt = WDT_HZ;
 95 
 96     //                                                            使能中断                    开启WDT
 97     reg->con = PRESCALER << 8 | DIV << 3 | 1<< 2           |        1<< 5;
 98 
 99     return 0;
100 
101     //注册中断
102 err_request_irq:
103     iounmap(reg);
104     reg->con &= ~(1 << 5);   //关闭 wdt
105     release_mem_region(EXYNOS4_PA_WATCHDOG, sizeof(struct  wdt_reg));
106 err_request_mem_region:
107     WDT_CLOCK &= ~(1 << 14); //关闭时钟
108     return ret;
109 }
110  
111 
112 static void test_exit(void)
113 {
114     printk("%s:%d
", __FILE__, __LINE__);
115     free_irq(EXYNOS4_IRQ_WDT, NULL);
116     iounmap(reg);
117     release_mem_region(EXYNOS4_PA_WATCHDOG, sizeof(struct  wdt_reg));
118 
119 }
120 
121 
122 module_init(test_init);
123 module_exit(test_exit);
124 
125 MODULE_LICENSE("GPL");
原文地址:https://www.cnblogs.com/baoshulin/p/6416184.html