watchdog driver test(S3C2440+linux-2.6.29)

driver.h

 

#ifndef _DRIVER_H
#define _DRIVER_H


#define WDT_ON 0
#define WDT_OFF 1
#define WDT_MODE 2
#define WDT_FEED 3

#endif

 

driver.c

 

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/kernel.h>

#include <linux/platform_device.h>
#include "driver.h"
struct wdt_driver {
 unsigned long phys;
 void __iomem *virt_base;
 unsigned long wtcon;
 unsigned long wtdat;
 unsigned long wtcnt;

 struct cdev cdev;
 unsigned minor,major;
 dev_t devno;
 unsigned long irq;

 void (*wdt_on)(struct wdt_driver *wdt);
 void (*wdt_off)(struct wdt_driver *wdt);
 void (*wdt_mode)(struct wdt_driver *wdt,unsigned long n);
 void (*wdt_feed)(struct wdt_driver *wdt);

};
int open_wdt(struct inode *inod, struct file * filp)
{
 printk("has open the wdt/n");
 return 0;
}
int ioctl_wdt(struct inode *inod,struct file * filp,unsigned int cmd,unsigned long arg)
{
 struct wdt_driver *wdt=container_of(inod->i_cdev,struct wdt_driver,cdev);
 switch(cmd)
 {
  case WDT_ON:
   wdt->wdt_on(wdt);
   break;
  case WDT_OFF:
   wdt->wdt_off(wdt);
   break;
  case WDT_MODE:
   wdt->wdt_mode(wdt,arg);
   break;
  case WDT_FEED:
   wdt->wdt_feed(wdt);
   break;
  default:
   return -EINVAL;
 }
 return 0;

}
struct wdt_driver *wdt;
struct class *myclass;
struct file_operations f_ops={
owner : THIS_MODULE,
  open  : open_wdt,
  ioctl : ioctl_wdt,
};
void wdt_on(struct wdt_driver *wdt)
{
 unsigned long ret;
 ret=ioread32(wdt->wtcon);
 ret|=(1<<5);
 iowrite32(ret,wdt->wtcon);

}
void wdt_off(struct wdt_driver *wdt)
{
 unsigned long ret;
 ret=ioread32(wdt->wtcon);
 ret&=~(1<<5);
 iowrite32(ret,wdt->wtcon);
}
void wdt_mode(struct wdt_driver *wdt ,unsigned long reset)
{
 unsigned long ret;
 ret=ioread32(wdt->wtcon);
 if(reset)
 {

  ret&=~(1<<2);
  ret|=1;
  iowrite32(ret,wdt->wtcon);
  printk("reset mode opened/n");
 }
 else
 {
  ret&=(~1);
  ret|=(1<<2);
  iowrite32(ret,wdt->wtcon);
 }
}
void wdt_feed(struct wdt_driver *wdt)
{
 iowrite32(0x8000,wdt->wtcnt);
}
irqreturn_t irqhandled(int irqno,void *devno)
{
 printk("the watchdog has interrupt/n");
 return IRQ_HANDLED;
}
int init_wdt_device(struct wdt_driver *wdt)
{
 wdt->irq=IRQ_S3C2440_WDT;
 wdt->virt_base=ioremap(wdt->phys,SZ_4K);
 if(NULL==wdt->virt_base)
 {
  printk("<kernel> has no virtul mem/n");
  goto ERR1;
 }
 wdt->wtcon=(unsigned long)wdt->virt_base+(unsigned long )0x00;
 wdt->wtdat=(unsigned long)wdt->virt_base+0x04;
 wdt->wtcnt=(unsigned long)wdt->virt_base+0x08;

 if(request_irq(wdt->irq,irqhandled,0,"watchdog",NULL))
 {
  printk("<kernel> request the irq failed/n");
  goto ERR2;
 }
 wdt->wdt_on=wdt_on;
 wdt->wdt_off=wdt_off;
 wdt->wdt_mode=wdt_mode;
 wdt->wdt_feed=wdt_feed;

 iowrite32(0x8004,wdt->wtcon);
 iowrite32(0x8000,wdt->wtcnt);
 return 0;
ERR2:
 iounmap((void __iomem*)wdt->virt_base);
ERR1:
 return -EBUSY;

}
int init_wdt(struct platform_device *pdev)
{
 wdt=kmalloc(sizeof(struct wdt_driver),GFP_KERNEL);
 if(NULL==wdt)
 {
  printk("<kernel>has no enough mem/n");
  goto ERR1;
 }
 memset(wdt,0,sizeof(struct wdt_driver));
 wdt->major=0;
 wdt->minor=0;
 if(wdt->major)
 {
  wdt->devno=MKDEV(wdt->major,wdt->minor);
  register_chrdev_region(wdt->devno,1,"wdt_driver");      
 }
 else
 {
  alloc_chrdev_region(&wdt->devno,wdt->minor,1,"wdt_driver");
  printk("<kernel alloc>major=%d,minor=%d/n",MAJOR(wdt->devno),MINOR(wdt->minor));
 }
 myclass = class_create(THIS_MODULE, "test-udev-class");
 device_create(myclass, NULL, wdt->devno, "%s", "watchdog");

 cdev_init(&wdt->cdev,&f_ops);
 wdt->phys=pdev->resource->start;
 if(init_wdt_device(wdt))
 {
  printk("<kernel>init the wdt device failed/n");
  goto ERR2;
 }
 if(cdev_add(&wdt->cdev,wdt->devno,1))
 {
  printk("add the device failed/n");
  goto ERR3;
 }
 return 0;
ERR3:

class_destroy(myclass);
device_destroy(myclass,wdt->devno);
unregister_chrdev_region(wdt->devno,1);

ERR2:
 kfree(wdt);
 return -ENODEV;
ERR1:
 return -ENOMEM;

}

int plat_probe(struct platform_device *pdev)
{    
 printk("<kernel> the plat_driver has probe with the device/n");   
 init_wdt(pdev);
 return 0;
}
int plat_remove(struct platform_device *dev)
{
 iowrite32(0,wdt->wtcon);
 cdev_del(&wdt->cdev);
 class_destroy(myclass);
 device_destroy(myclass,wdt->devno);
 unregister_chrdev_region(wdt->devno,1);
 iounmap((void __iomem *)wdt->virt_base);
 free_irq(wdt->irq,NULL);    
 kfree(wdt);
 return 0;
}
struct platform_driver drv={
probe  : plat_probe,
   remove : plat_remove,
   driver : {
name : "watchdog"
   }

};
int init_driver(void)
{
 platform_driver_register(&drv);
 return 0;
}

void exit_driver(void)
{
 platform_driver_unregister(&drv); 
}

module_init(init_driver);
module_exit(exit_driver);
MODULE_LICENSE("GPL");

 

device.c

 

#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/platform_device.h>
struct resource wdt_res ={
    start :0x53000000,
    end   :0x530000ff,
};

void wdt_release(struct device *dev)
{
   printk("has the wdt device unregister/n");

}
struct platform_device wdt={
     name : "watchdog",
     id   :  10,
     dev  :  {
           bus_id  : "wdt_dev",
           release : wdt_release,
  },
      resource : &wdt_res,

};
int init_device(void)
{
    platform_device_register(&wdt);
    return 0;
}

void exit_device(void)
{
    platform_device_unregister(&wdt);
}

module_init(init_device);
module_exit(exit_device);
MODULE_LICENSE("GPL");

test.c

 

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include "driver.h"

int main(int argc, char **argv)
{
 int fd;
 unsigned cmd;
        fd=open("/dev/watchdog",O_RDWR);
 if(fd<0)
 {
           printf("has no the watchdog file/n");
           return -1;
 }
 printf("fd=%d/n",fd);
        ioctl(fd, WDT_MODE, 1);/*enable the watchdog has send the reset signal and disable the interrupt*/
//      ioctl(fd,WDT_MODE,0);/*disable send reset signal*/
        ioctl(fd, WDT_ON);
        while(1) {
       ioctl(fd, WDT_FEED);/***feed the watchdog****/
       usleep(100 * 1000);
          }
        close(fd);
 return 0;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值