Linux下如何编写RTC驱动(2)

  if (ret == 0) {//如果读取到有效数据
          /* Check for any data updates */
          if (rtc->ops->read_callback)
               data = rtc->ops->read_callback(rtc->dev.parent, data);//调用read_callback并用它返回的值更新数据

          if (sizeof(int) != sizeof(long) &&
              count == sizeof(unsigned int))
               ret = put_user(data, (unsigned int __user *)buf) ?:
                    sizeof(unsigned int);
          else
               ret = put_user(data, (unsigned long __user *)buf) ?:
                    sizeof(unsigned long);
     }
     return ret;
}


3.中断处理函数报告事件类型。

RTC支持各种中断,中断处理函数中应该向系统中报告中断的事件类型。

一个RTC中断处理函数的例子如下:

  static irqreturn_t sep0611_rtc_isr(int irq, void *id)
{
            unsigned int int_stat;
            struct rtc_device *rdev = id;
            void __iomem *base = sep0611_rtc_base;

            int_stat = readl(base + SEP0611_RTC_INT_STS);

            writel(int_stat, base + SEP0611_RTC_INT_STS);
            if (int_stat & ALARM_FLAG) {
                rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
            }

            if (int_stat & SAMP_FLAG) {
                /*reload the samp_count every time after a samp_int triggers*/
                writel(SAMP_COUNT << 16, base + SEP0611_RTC_SAMP);

                rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
            }

            if (int_stat & SEC_FLAG) {
                rtc_update_irq(rdev, 1, RTC_UF | RTC_IRQF);
            }

            return IRQ_HANDLED;
}

相关宏的定义如下:

#define RTC_IRQF 0x80 /* any of the following is active */
#define RTC_PF 0x40
#define RTC_AF 0x20
#define RTC_UF 0x10

rtc_update_irq的原型是:

void rtc_update_irq(struct rtc_device *rtc,
          unsigned long num, unsigned long events)
{
     spin_lock(&rtc->irq_lock);
     rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
     spin_unlock(&rtc->irq_lock);

     spin_lock(&rtc->irq_task_lock);
     if (rtc->irq_task)
          rtc->irq_task->func(rtc->irq_task->private_data);
     spin_unlock(&rtc->irq_task_lock);

     wake_up_interruptible(&rtc->irq_queue);
     kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjzdj.html