Ok24403看门狗驱动代码详细分析.docx
- 文档编号:7518553
- 上传时间:2023-01-24
- 格式:DOCX
- 页数:18
- 大小:21.79KB
Ok24403看门狗驱动代码详细分析.docx
《Ok24403看门狗驱动代码详细分析.docx》由会员分享,可在线阅读,更多相关《Ok24403看门狗驱动代码详细分析.docx(18页珍藏版)》请在冰豆网上搜索。
Ok24403看门狗驱动代码详细分析
/*希望与各位共同学习,我的QQ是254206940.红色部分为我添加的注释,蓝色把部分为代码自带的注释,紫色部分为我没理解透的地方(主要是我不不明白为什么要那些代码,它们主要起什么作用)。
希望看到我的笔记的同行不吝赐教!
linux/drivers/char/watchdog/s3c2410_wdt.c
*
*Copyright(c)2004SimtecElectronics
*BenDooks
*
*S3C2410WatchdogTimerSupport
*
*Basedon,softdog.cbyAlanCox,
*(c)Copyright1996AlanCox
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion2oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNUGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace,Suite330,Boston,MA02111-1307USA
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#undefS3C_VA_WATCHDOG
#defineS3C_VA_WATCHDOG(0)
#include
#definePFX"s3c2410-wdt:
"
#defineCONFIG_S3C2410_WATCHDOG_ATBOOT(0)
#defineCONFIG_S3C2410_WATCHDOG_DEFAULT_TIME(15)
staticintnowayout=WATCHDOG_NOWAYOUT;
staticinttmr_margin=CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
staticinttmr_atboot=CONFIG_S3C2410_WATCHDOG_ATBOOT;
staticintsoft_noboot;
staticintdebug;
module_param(tmr_margin,int,0);
module_param(tmr_atboot,int,0);
module_param(nowayout,int,0);
module_param(soft_noboot,int,0);
module_param(debug,int,0);
MODULE_PARM_DESC(tmr_margin,"Watchdogtmr_margininseconds.default="
__MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME)")");
MODULE_PARM_DESC(tmr_atboot,
"Watchdogisstartedatboottimeifsetto1,default="
__MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
MODULE_PARM_DESC(nowayout,"Watchdogcannotbestoppedoncestarted(default="
__MODULE_STRING(WATCHDOG_NOWAYOUT)")");
MODULE_PARM_DESC(soft_noboot,"Watchdogaction,setto1toignorereboots,0toreboot(defaultdependsonONLY_TESTING)");
MODULE_PARM_DESC(debug,"Watchdogdebug,setto>1fordebug,(default0)");
typedefenumclose_state{
CLOSE_STATE_NOT,
CLOSE_STATE_ALLOW=0x4021
}close_state_t;
staticunsignedlongopen_lock;
staticstructdevice*wdt_dev;/*platformdeviceattachedto*/
staticstructresource*wdt_mem;
staticstructresource*wdt_irq;
staticstructclk*wdt_clock;
staticvoid__iomem*wdt_base;
staticunsignedintwdt_count;
staticclose_state_tallow_close;
staticDEFINE_SPINLOCK(wdt_lock);
/*watchdogcontrolroutines*/
#defineDBG(msg...)do{\
if(debug)\
printk(KERN_INFOmsg);\
}while(0)
/*functions*/
staticvoids3c2410wdt_keepalive(void)//喂狗,即将计数值赋给WTCNT寄存器
{
spin_lock(&wdt_lock);
writel(wdt_count,wdt_base+S3C2410_WTCNT);
spin_unlock(&wdt_lock);
}
staticvoid__s3c2410wdt_stop(void)
{
unsignedlongwtcon;
wtcon=readl(wdt_base+S3C2410_WTCON);
wtcon&=~(S3C2410_WTCON_ENABLE|S3C2410_WTCON_RSTEN);
writel(wtcon,wdt_base+S3C2410_WTCON);
}
//将WTCON寄存器的位[5]和位[0]清零,不输出复位信号,停止看门狗
staticvoids3c2410wdt_stop(void)//关看门狗
{
spin_lock(&wdt_lock);
__s3c2410wdt_stop();
spin_unlock(&wdt_lock);
}
staticvoids3c2410wdt_start(void)
{
unsignedlongwtcon;
spin_lock(&wdt_lock);
__s3c2410wdt_stop();//关看门狗
wtcon=readl(wdt_base+S3C2410_WTCON);
wtcon|=S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV128;
/*#defineS3C2410_WTCON_ENABLE(1<<5)
#defineS3C2410_WTCON_DIV128(3<<3)
开启看门狗,设置分频系数为128(这里并没有将其写入控制寄存器,只是设置值而已)
*/
if(soft_noboot){
wtcon|=S3C2410_WTCON_INTEN;//#defineS3C2410_WTCON_INTEN(1<<2)使能看门狗中断
wtcon&=~S3C2410_WTCON_RSTEN;//#defineS3C2410_WTCON_RSTEN(0x01),不输出复位信号
}else{
wtcon&=~S3C2410_WTCON_INTEN;//禁止看门狗中断
wtcon|=S3C2410_WTCON_RSTEN;//允许输出复位信号
}
DBG("%s:
wdt_count=0x%08x,wtcon=%08lx\n",
__func__,wdt_count,wtcon);
writel(wdt_count,wdt_base+S3C2410_WTDAT);
writel(wdt_count,wdt_base+S3C2410_WTCNT);//写入计数值
writel(wtcon,wdt_base+S3C2410_WTCON);//写WTCON寄存器,前面的设置会生效
spin_unlock(&wdt_lock);
}
staticints3c2410wdt_set_heartbeat(inttimeout)
{
unsignedintfreq=clk_get_rate(wdt_clock);
//获得时钟,这里的时钟应该是系统初始化时设置好了的。
就是pclk的值
unsignedintcount;
unsignedintdivisor=1;
unsignedlongwtcon;
if(timeout<1)
return-EINVAL;
freq/=128;
//这个地方有点不明白了,在前面没有设置WTCON寄存器的[4:
3]位,怎么就直接采用了128分频呢?
难道也是系统初始化时的设置?
count=timeout*freq;
//将看门时间timeout(秒)乘以freq,根据count的值确定是否需要设置看门狗的预分配项。
DBG("%s:
count=%d,timeout=%d,freq=%d\n",
__func__,count,timeout,freq);
/*ifthecountisbiggerthanthewatchdogregister,
thenworkoutwhatweneedtodo(andif)wecan
actuallymakethisvalue
*/
if(count>=0x10000){
for(divisor=1;divisor<=0x100;divisor++){
if((count/divisor)<0x10000)
break;
}
//因为WTDAT寄存器为16位,因此当计数值count>=0x10000时必须采用与分频项,经过这个循环后,divisor的值即为与分频因子。
if((count/divisor)>=0x10000){
dev_err(wdt_dev,"timeout%dtoobig\n",timeout);
return-EINVAL;
}
//如果count/divisor)>=0x10000,则说明看门狗时间设得太大了,将会退出。
}
tmr_margin=timeout;
DBG("%s:
timeout=%d,divisor=%d,count=%d(%08x)\n",
__func__,timeout,divisor,count,count/divisor);
count/=divisor;
//得到采用预分频后看门狗的计数脉冲数
wdt_count=count;
/*updatethepre-scaler*/
wtcon=readl(wdt_base+S3C2410_WTCON);
wtcon&=~S3C2410_WTCON_PRESCALE_MASK;
wtcon|=S3C2410_WTCON_PRESCALE(divisor-1);
//计算看门狗预分配因子
writel(count,wdt_base+S3C2410_WTDAT);
//设置看门狗计数脉冲数
writel(wtcon,wdt_base+S3C2410_WTCON);
//设置看门狗预分频因子
return0;
}
/*
*/dev/watchdoghandling
*/
staticints3c2410wdt_open(structinode*inode,structfile*file)
{
if(test_and_set_bit(0,&open_lock))//上锁,因此同时只有一个进程打开看门狗设备文件,该函数的功能为:
设置&open_lock的位0为1,返回原来位0的值。
return-EBUSY;
if(nowayout)
__module_get(THIS_MODULE);
allow_close=CLOSE_STATE_NOT;//这个状态用来干什么的呢?
/*startthetimer*/
s3c2410wdt_start();//启动看门狗
returnnonseekable_open(inode,file);
}
staticints3c2410wdt_release(structinode*inode,structfile*file)
{
/*
*Shutoffthetimer.
*Lockitinifit'samoduleandwesetnowayout
*/
if(allow_close==CLOSE_STATE_ALLOW)
s3c2410wdt_stop();
else{
dev_err(wdt_dev,"Unexpectedclose,notstoppingwatchdog\n");
s3c2410wdt_keepalive();
}
allow_close=CLOSE_STATE_NOT;
clear_bit(0,&open_lock);//释放锁
return0;
}
staticssize_ts3c2410wdt_write(structfile*file,constchar__user*data,
size_tlen,loff_t*ppos)
{
/*
*Refreshthetimer.
*/
if(len){
if(!
nowayout){
size_ti;
/*Incaseitwassetlongago*/
allow_close=CLOSE_STATE_NOT;
for(i=0;i!
=len;i++){
charc;
if(get_user(c,data+i))//用户空间到内核空间
return-EFAULT;
if(c=='V')//如果写入了V,允许关闭
allow_close=CLOSE_STATE_ALLOW;
}
}
s3c2410wdt_keepalive();
}
returnlen;
}
#defineOPTIONSWDIOF_SETTIMEOUT|WDIOF_KEEPALIVEPING|WDIOF_MAGICCLOSE
staticconststructwatchdog_infos3c2410_wdt_ident={
.options=OPTIONS,
.firmware_version=0,
.identity="S3C2410Watchdog",
};
staticlongs3c2410wdt_ioctl(structfile*file,unsignedintcmd,
unsignedlongarg)
{
void__user*argp=(void__user*)arg;
int__user*p=argp;
intnew_margin;
switch(cmd){
caseWDIOC_GETSUPPORT:
returncopy_to_user(argp,&s3c2410_wdt_ident,
sizeof(s3c2410_wdt_ident))?
-EFAULT:
0;
caseWDIOC_GETSTATUS:
caseWDIOC_GETBOOTSTATUS:
returnput_user(0,p);
caseWDIOC_KEEPALIVE:
s3c2410wdt_keepalive();
return0;
caseWDIOC_SETTIMEOUT:
if(get_user(new_margin,p))
return-EFAULT;
if(s3c2410wdt_set_heartbeat(new_margin))
return-EINVAL;
s3c2410wdt_keepalive();
returnput_user(tmr_margin,p);
caseWDIOC_GETTIMEOUT:
returnput_user(tmr_margin,p);
default:
return-ENOTTY;
}
}
/*kernelinterface*/
staticconststructfile_operationss3c2410wdt_fops={
.owner=THIS_MODULE,
.llseek=no_llseek,
.write=s3c2410wdt_write,
.unlocked_ioctl=s3c2410wdt_ioctl,
.open=s3c2410wdt_open,
.release=s3c2410wdt_release,
};
staticstructmiscdevices3c2410wdt_miscdev={
.minor=WATCHDOG_MINOR,
.name="watchdog",
.fops=&s3c2410wdt_fops,
};
/*interrupthandlercode*/
staticirqreturn_ts3c2410wdt_irq(intirqno,void*param)
{
dev_info(wdt_dev,"watchdogtimerexpired(irq)\n");
s3c2410wdt_keepalive();//喂狗
returnIRQ_HANDLED;
}
/*deviceinterface*/
staticints3c2410wdt_probe(structplatform_device*pdev)
{
/*入口参数
structplatform_devices3c_device_wdt={
.name="s3c2410-wdt",
.id=-1,
.num_resources=ARRAY_SIZE(s3c_wdt_resource),
.resource=s3c_wdt_resource,
};
#defineARRAY_SIZE(x)(sizeof(x)/sizeof((x)[0]))
说明:
num_resources:
设备占用的资源数量
staticstructresources3c_wdt_resource[]={
[0]={
.start=S3C24XX_PA_WATCHDOG,
说明:
S3C24XX_PA_WATCHDOG等于(0x53000000)
WTCON寄存器的物理地址即为0x53000000
.end=S3C24XX_PA_WATCHDOG+S3C24XX_SZ_WATCHDOG-1,
说明:
S3C24XX_SZ_WATCHDOG等于0x00100000
.flags=IORESOURCE_MEM,
说明:
该标志用来资源的类型
},
[1]={
.start=IRQ_WDT,
.end=IRQ_WDT,
说明:
#defineIRQ_WDT17/*0x00020000*/
.flags=IORESOURCE_IRQ,
}
};
*/
structresource*res;
structdevice*dev;
unsignedintwtcon;
intstarted=0;
intret;
intsize;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Ok24403 看门狗 驱动 代码 详细 分析