????2.5 platform_driver ????
????struct platform driver
????{
????int (*probe)(struct platform device *);//???
????int (*remove)(struct platform device *);//???
????void (*shutdown)(struct platform device *);//???
????int (*suspend)(struct platform device *?? pm message t state);// ????
????int (*resume)(struct platform device *);//???
????struct device driver driver;
????};
????2.6 S3C2410 ???????platform_driver ????
????static struct platform driver s3c2410wdt driver =
????{
????.probe      = s3c2410wdt probe??//S3C2410????????
????.remove     = s3c2410wdt remove??// S3C2410????????
????.shutdown   = s3c2410wdt shutdown??//S3C2410????????
????.suspend    = s3c2410wdt suspend??//S3C2410?????????
????.resume     = s3c2410wdt resume?? //S3C2410????????
????.driver     = {
????.owner  = THIS MODULE??
????.name   = "s3c2410-wdt"??//?豸??
????}??
????}??
????2.7 S3C2410 ????????????
????static struct resource s3c wdt resource[] =
????{
????[0] =
????{
????.start = S3C24XX PA WATCHDOG??     //?????I/O ??濪?λ??
????.end = S3C24XX PA WATCHDOG + S3C24XX SZ WATCHDOG - 1??
????//?????I/O ??????λ??
????.flags = IORESOURCE MEM??  //I/O ??????
????} ??
????[1] =
????{
????.start = IRQ WDT?? //????????IRQ ??
????.end = IRQ WDT?? //?????????IRQ ??
????.flags = IORESOURCE IRQ??  //IRQ ???
????}
????};
????2.8 S3C2410 ???????????miscdevice ????
????static struct miscdevice s3c2410wdt miscdev =
????{
????.minor      = WATCHDOG MINOR??//???豸??
????.name       = "watchdog"??
????.fops       = &s3c2410wdt fops??//???????????
????};
????2.9 S3C2410 ??????????????????????
????static struct file operations s3c2410wdt fops =
????{
????.owner      = THIS MODULE??
????.llseek     = no llseek??    //seek
????.write      = s3c2410wdt write??     //д????
????.ioctl      = s3c2410wdt ioctl?? //ioctl ????
????.open       = s3c2410wdt open??  //??????
????.release    = s3c2410wdt release??//??????
????};
????3 ?????ж?????
????????????????ж???????? ?? platform_driver_register() ?? platform_driver_ unregister()???????platform_driver
????3.1 S3C2410 ?????????
????static int     __init watchdog__init (void)
????{
????printk (banner);
????return   platform driver register(&s3c2410wdt driver);//       ? ??platform driver
????}
????static void     exit watchdog exit (void)
????{
????platform driver unregister (&s3c2410wdt driver);//          ?  ?? platform driver
????}
????4 ???????????
????4.1 ?????
static int s3c2410wdt probe (struct platform device *pdev)
{
struct resource *res;
int started = 0;
int ret;
int size;
DBG ("%s: probe=%p "?? _ _FUNCTION_ _?? pdev);
/* ???????????????? */
res = platform get resource (pdev?? IORESOURCE MEM?? 0);
if (res == NULL)
{
printk(KERN INFO PFX "failed to get memory region resouce ");
return  - ENOENT;
}
size = (res->end - res->start) + 1;
//????I/O ???
wdt mem = request mem region (res->start?? size?? pdev->name);
if (wdt mem == NULL)
{
printk(KERN INFO PFX "failed to get memory region ");
return  - ENOENT;
}
wdt base = ioremap (res->start?? size); //?豸???->??????
if (wdt base == 0)
{
printk(KERN INFO PFX "failed to ioremap () region ");
return  - EINVAL;
}
DBG ("probe: mapped wdt base=%p "?? wdt base);
/* ??????????ж? */
res = platform get resource (pdev?? IORESOURCE IRQ?? 0);
if (res == NULL)
{
printk(KERN INFO PFX "failed to get irq resource ");
return  - ENOENT;
}
//?????ж?
ret = request irq (res->start?? s3c2410wdt irq?? 0?? pdev->name??
pdev);
if (ret != 0)
{
printk(KERN INFO PFX "failed to install irq (%d) "?? ret);
return ret;
}
wdt clock = clk get (&pdev->dev?? "watchdog"); //???????????
if (wdt clock == NULL)
{
printk(KERN INFO PFX "failed to find watchdog clock source ");
return  - ENOENT;
}
clk enable (wdt clock);
/* ???????????????????????????????????????????????? */
if (s3c2410wdt set heartbeat (tmr margin))
{
started = s3c2410wdt set heartbeat (
CONFIG S3C2410 WATCHDOG DEFAULT TIME);
if (started == 0)
{
printk (KERN INFO PFX "tmr margin value out of range?? default
%d
used "??CONFIG S3C2410 WATCHDOG DEFAULT TIME);
}
else
{
printk (KERN INFO PFX
"default timer value is out of range?? cannot start ");
}
}
//???miscdevice
ret = misc register(&s3c2410wdt miscdev);
if (ret)
{
printk(KERN ERR PFX "cannot registermiscdev on minor=%d (%d) "??
WATCHDOG MINOR?? ret);
return ret;
}
if (tmr atboot && started == 0)
{
printk(KERN INFO PFX "Starting Watchdog Timer ");
s3c2410wdt start ();
}
return 0;
}
????4.2 ?????
static int s3c2410wdt remove (struct platform device *dev)
{
if (wdt mem != NULL)
{
release resource (wdt mem); //??????
kfree (wdt mem);//??????
wdt mem = NULL;
}
//????ж?
if (wdt irq != NULL)
{
free irq (wdt irq->start?? dev);
wdt irq = NULL;
}
//???????
if (wdt clock != NULL)
{
clk disable (wdt clock);
clk put (wdt clock);
wdt clock = NULL;
}
misc deregister(&s3c2410wdt miscdev);//???miscdevice
return 0;
}
????5 ???????????
????5.1 ??????
????static   int  s3c2410wdt suspend (struct    platform device   *dev??
????pm message t state)
????{
????/* ???濴??????????? */
????wtcon save = readl (wdt base + S3C2410 WTCON);
????wtdat save = readl (wdt base + S3C2410 WTDAT);
????s3c2410wdt stop ();
????return 0;
????}
????5.2 ???????
????static int s3c2410wdt resume (struct platform device *dev)
????{
????/* ?????????? */
????writel (wtdat save?? wdt base + S3C2410 WTDAT);
????writel (wtdat save?? wdt base + S3C2410 WTCNT);
????writel (wtcon save?? wdt base + S3C2410 WTCON);
????printk (KERN INFO PFX "watchdog %sabled "?? (wtcon save
????&S3C2410 WTCON ENABLE)? "en" : "dis");
????return 0;
????}
????6 ??????????
????6.1 ??????
static int s3c2410wdt open (struct inode *inode?? struct file *file)
{
if (down trylock (&open lock))  //??????
return  - EBUSY;
if (nowayout)
{
module get (THIS MODULE);
}
else
{
allow close = CLOSE STATE ALLOW;
}
/* ???????? */
s3c2410wdt start ();
return nonseekable open (inode?? file);
}
????6.2 ??????
static int s3c2410wdt release (struct inode *inode??struct file *file)
{
/* ??????? */
if (allow close == CLOSE STATE ALLOW)
{
s3c2410wdt stop ();
}
else
{
printk (KERN CRIT  PFX  "Unexpected  close??  not  stopping
watchdog! ");
s3c2410wdt keepalive ();
}
allow close = CLOSE STATE NOT;
up (&open lock);  //??????
return 0;
}
????7 ???watchdog??????д????
????7.1 ????????????
/*???????*/
staticints3c2410wdtstop(void)
{
unsignedlongwtcon;
wtcon=readl(wdtbase+S3C2410WTCON);
//??????????????λ
wtcon&=~(S3C2410WTCONENABLE|S3C2410WTCONRSTEN);
writel(wtcon??wdtbase+S3C2410WTCON);
return0;
}
/*????????*/
staticints3c2410wdtstart(void)
{
unsignedlongwtcon;
s3c2410wdtstop();
wtcon=readl(wdtbase+S3C2410WTCON);
//?????????128???
wtcon|=S3C2410WTCONENABLE|S3C2410WTCONDIV128;
if(softnoboot)
{
wtcon|=S3C2410WTCONINTEN;//????ж?
wtcon&=~S3C2410WTCONRSTEN;//?????λ
}
else
{
wtcon&=~S3C2410WTCONINTEN;//????ж?
wtcon|=S3C2410WTCONRSTEN;//????λ
}
DBG("%s:wdtcount=0x%08x??wtcon=%08lx "??FUNCTION??
wdtcount??wtcon);
writel(wdtcount??wdtbase+S3C2410WTDAT);
writel(wdtcount??wdtbase+S3C2410WTCNT);
writel(wtcon??wdtbase+S3C2410WTCON);
return0;
}
????7.2 д????
static ssize t s3c2410wdt write (struct file *file?? const char      user *data??
size t len?? loff t *ppos)
{
/* ??????? */
if (len)
{
if (!nowayout)
{
size t i;
allow close = CLOSE STATE NOT;
for (i = 0; i != len; i++)
{
char c;
if (get user(c?? data + i))//??????->?????
return  - EFAULT;
if (c == 'V ')  //???д????'V ' ????????
allow close = CLOSE STATE ALLOW;
}
}
s3c2410wdt keepalive ();
}
return len;
}