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");