(1)rtc平台设备驱动源码如下,gzliu_2440_rtc.c:
相关的函数及结构体参见:http://blog.youkuaiyun.com/gzliu_hit/article/details/6699277
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/mach/time.h>
#include <asm/hardware/clock.h>
#include <asm/arch/regs-rtc.h>
// 包含RTC_AF的声明
#include <linux/mc146818rtc.h>
#undef S3C24XX_VA_RTC
#define S3C24XX_VA_RTC s3c2440_rtc_base
static struct resource *s3c2440_rtc_mem = NULL;
static void __iomem *s3c2440_rtc_base = NULL;
static int s3c2440_rtc_alarm_irq = NO_IRQ;
static int s3c2440_rtc_tick_irq = NO_IRQ;
static int s3c2440_rtc_freq = 1; // rtc tick中断频率
static DEFINE_SPINLOCK(s3c2440_rtc_pie_lock);
static int s3c2440_rtc_proc(char *buf)
{
unsigned int rtcalm = readb(S3C2410_RTCALM);
unsigned int ticnt = readb (S3C2410_TICNT);
char *p = buf;
printk("@@@@@@@@@@@@@@@@@@@@@@\ngzliu s3c2440_rtc_proc()\n@@@@@@@@@@@@@@@@@@@@@@@@\n");
p += sprintf(p, "alarm_IRQ\t: %s\n", (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
p += sprintf(p, "periodic_IRQ\t: %s\n", (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
p += sprintf(p, "periodic_freq\t: %d\n", s3c2440_rtc_freq);
return p - buf;
}
static int s3c2440_rtc_getalarm(struct rtc_wkalrm *alrm)
{
struct rtc_time *alm_tm = &alrm->time;
unsigned int alm_en;
printk("@@@@@@@@@@@@@@@@@@@@@@\ngzliu s3c2440_rtc_getalarm()\n@@@@@@@@@@@@@@@@@@@@@@@@\n");
alm_tm->tm_sec = readb(S3C2410_ALMSEC);
alm_tm->tm_min = readb(S3C2410_ALMMIN);
alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
alm_tm->tm_mon = readb(S3C2410_ALMMON);
alm_tm->tm_mday = readb(S3C2410_ALMDATE);
alm_tm->tm_year = readb(S3C2410_ALMYEAR);
alm_en = readb(S3C2410_RTCALM);
pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", alm_en, alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
/* decode the alarm enable field */
if (alm_en & S3C2410_RTCALM_SECEN)
{
BCD_TO_BIN(alm_tm->tm_sec);
}
else
{
alm_tm->tm_sec = 0xff;
}
if (alm_en & S3C2410_RTCALM_MINEN)
{
BCD_TO_BIN(alm_tm->tm_min);
}
else
{
alm_tm->tm_min = 0xff;
}
if (alm_en & S3C2410_RTCALM_HOUREN)
{
BCD_TO_BIN(alm_tm->tm_hour);
}
else
{
alm_tm->tm_hour = 0xff;
}
if (alm_en & S3C2410_RTCALM_DAYEN)
{
BCD_TO_BIN(alm_tm->tm_mday);
}
else
{
alm_tm->tm_mday = 0xff;
}
if (alm_en & S3C2410_RTCALM_MONEN)
{
BCD_TO_BIN(alm_tm->tm_mon);
alm_tm->tm_mon -= 1;
}
else
{
alm_tm->tm_mon = 0xff;
}
if (alm_en & S3C2410_RTCALM_YEAREN)
{
BCD_TO_BIN(alm_tm->tm_year);
}
else
{
alm_tm->tm_year = 0xffff;
}
/* todo - set alrm->enabled ? */
return 0;
}/* s3c2440_rtc_getalarm(struct rtc_wkalrm *alrm) */
static int s3c2440_rtc_setalarm(struct rtc_wkalrm *alrm)
{
struct rtc_time *tm = &alrm->time;
unsigned int alrm_en;
printk("@@@@@@@@@@@@@@@@@@@@@@\ngzliu s3c2440_rtc_setalarm()\n@@@@@@@@@@@@@@@@@@@@@@@@\n");
pr_debug("s3c2410_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", alrm->enabled, tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
if (alrm->enabled || 1)
{
alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
writeb(0x00, S3C2410_RTCALM);
if (tm->tm_sec < 60 && tm->tm_sec >= 0)
{
alrm_en |= S3C2410_RTCALM_SECEN;
writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
}
if (tm->tm_min < 60 && tm->tm_min >= 0)
{
alrm_en |= S3C2410_RTCALM_