S3C2440驱动篇—RTC驱动分析

发布时间:2024-06-14  

Linux-2.6.32.2内核自带RTC驱动,但mach_smdk2440.c中没有添加该设备集,因此没有被激活,加入该平台设备,RTC平台设备定义在arch/arm/plat-s3c24xx/devs.c。

static struct platform_device *smdk2440_devices[] __initdata = {

       &s3c_device_usb,          /* arch/arm/mach-s3c2440/mach-smdk2440.c */

       &s3c_device_lcd,

       &s3c_device_wdt,

       &s3c_device_i2c0,

       &s3c_device_iis,

       &s3c_device_rtc,

};

驱动实现:

  1. #include    

  2. #include    

  3. #include    

  4. #include    

  5. #include    

  6. #include    

  7. #include    

  8. #include    

  9. #include    

  10. #include    

  11.   

  12. #include    

  13. #include    

  14. #include    

  15. #include    

  16. #include    

  17.   

  18. /* I have yet to find an S3C implementation with more than one 

  19.  * of these rtc blocks in */  

  20.   

  21. static struct resource *s3c_rtc_mem;  

  22.   

  23. static void __iomem *s3c_rtc_base;  

  24. static int s3c_rtc_alarmno = NO_IRQ;  

  25. static int s3c_rtc_tickno  = NO_IRQ;  

  26.   

  27. static DEFINE_SPINLOCK(s3c_rtc_pie_lock);  

  28.   

  29. /* IRQ Handlers */  

  30.   

  31. static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)  

  32. {  

  33.     struct rtc_device *rdev = id;  

  34.   

  35.     /* 报警中断到来时,设定报警相关信息,函数实现位于drivers/rtc/interface.c */  

  36.     rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);  

  37.     return IRQ_HANDLED;  

  38. }  

  39.   

  40. static irqreturn_t s3c_rtc_tickirq(int irq, void *id)  

  41. {  

  42.     struct rtc_device *rdev = id;  

  43.   

  44.     rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);  

  45.     return IRQ_HANDLED;  

  46. }  

  47.   

  48. /* Update control registers 设置RTCALM全局报警使能位*/  

  49. static void s3c_rtc_setaie(int to)  

  50. {  

  51.     unsigned int tmp;  

  52.   

  53.     pr_debug("%s: aie=%dn", __func__, to);  

  54.   

  55.     tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;  

  56.   

  57.     if (to)  

  58.         tmp |= S3C2410_RTCALM_ALMEN;  

  59.   

  60.     writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);  

  61. }  

  62.   

  63. /* 节拍时间计数器使能 */  

  64. static int s3c_rtc_setpie(struct device *dev, int enabled)  

  65. {  

  66.     unsigned int tmp;  

  67.   

  68.     pr_debug("%s: pie=%dn", __func__, enabled);  

  69.   

  70.     spin_lock_irq(&s3c_rtc_pie_lock);  

  71.     tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;  

  72.   

  73.     if (enabled)  

  74.         tmp |= S3C2410_TICNT_ENABLE;  

  75.   

  76.     writeb(tmp, s3c_rtc_base + S3C2410_TICNT);  

  77.     spin_unlock_irq(&s3c_rtc_pie_lock);  

  78.   

  79.     return 0;  

  80. }  

  81.   

  82. /* 节拍时间计数值设置*/  

  83. static int s3c_rtc_setfreq(struct device *dev, int freq)  

  84. {  

  85.     unsigned int tmp;  

  86.   

  87.     if (!is_power_of_2(freq))  

  88.         return -EINVAL;  

  89.   

  90.     spin_lock_irq(&s3c_rtc_pie_lock);  

  91.   

  92.     tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;  

  93.     tmp |= (128 / freq)-1;  

  94.   

  95.     writeb(tmp, s3c_rtc_base + S3C2410_TICNT);  

  96.     spin_unlock_irq(&s3c_rtc_pie_lock);  

  97.   

  98.     return 0;  

  99. }  

  100.   

  101. /* Time read/write */  

  102. /* 读取RTC中时间:分、时、日期、月、年、秒 */  

  103. static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)  

  104. {  

  105.     unsigned int have_retried = 0;  

  106.     void __iomem *base = s3c_rtc_base;  

  107.   

  108.  retry_get_time:  

  109.     rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);  

  110.     rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);  

  111.     rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);  

  112.     rtc_tm->tm_mon  = readb(base + S3C2410_RTCMON);  

  113.     rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);  

  114.     rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);  

  115.   

  116.     /* the only way to work out wether the system was mid-update 

  117.      * when we read it is to check the second counter, and if it 

  118.      * is zero, then we re-try the entire read 

  119.      */  

  120.     /* 如果读到秒为0,可能有进位,根据2440手册知道,要重新读一次 */  

  121.     if (rtc_tm->tm_sec == 0 && !have_retried) {  

  122.         have_retried = 1;  

  123.         goto retry_get_time;  

  124.     }  

  125.   

  126.     pr_debug("read time %02x.%02x.%02x %02x/%02x/%02xn",  

  127.          rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,  

  128.          rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);  

  129.   

  130.     /* 将BCD码转换为二进制数 */  

  131.     rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);  

  132.     rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);  

  133.     rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);  

  134.     rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);  

  135.     rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);  

  136.     rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);  

  137.   

  138.     /*这里为什么要加100年和减1月,查看数据手册得知区别1900年和2000年闰年的因素,1900年不是闰年而2000年是闰年*/  

  139.     rtc_tm->tm_year += 100;  

  140.     rtc_tm->tm_mon -= 1;  

  141.   

  142.     return 0;  

  143. }  

  144.   

  145. /* 与s3c_rtc_gettime功能相反 */  

  146. static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)  

  147. {  

  148.     void __iomem *base = s3c_rtc_base;  

  149.     int year = tm->tm_year - 100;  

  150.   

  151.     pr_debug("set time %02d.%02d.%02d %02d/%02d/%02dn",  

  152.          tm->tm_year, tm->tm_mon, tm->tm_mday,  

  153.          tm->tm_hour, tm->tm_min, tm->tm_sec);  

  154.   

  155.     /* we get around y2k by simply not supporting it */  

  156.   

  157.     if (year < 0 || year >= 100) {  

  158.         dev_err(dev, "rtc only supports 100 yearsn");  

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>