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 &&&&&&&&&&&&&&&&\n"); 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\n", __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\n"); 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\n"); 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\n", __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");