00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef INCLUDED_BY_HAL_C
00022
00023 #include <linux/mc146818rtc.h>
00024 static inline unsigned char RT_CMOS_READ(unsigned char addr)
00025 {
00026 outb_p(addr, RTC_PORT(0));
00027 return inb_p(RTC_PORT(1));
00028 }
00029
00030
00031 #define MIN_RTC_FREQ 2
00032 #define MAX_RTC_FREQ 8192
00033 #define RTC_FREQ MAX_RTC_FREQ
00034
00035 static void rt_broadcast_rtc_interrupt(void)
00036 {
00037 #ifdef CONFIG_SMP
00038 apic_wait_icr_idle();
00039 apic_write_around(APIC_ICR, APIC_DM_FIXED | APIC_DEST_ALLBUT | RTAI_APIC_TIMER_VECTOR | APIC_DEST_LOGICAL);
00040 ((void (*)(void))rtai_realtime_irq[RTAI_APIC_TIMER_IPI].handler)();
00041 #endif
00042 }
00043
00044 static void (*usr_rtc_handler)(void);
00045
00046 static void rtc_handler(int irq, int rtc_freq)
00047 {
00048 #ifdef TEST_RTC
00049 static int stp, cnt;
00050 if (++cnt == rtc_freq) {
00051 rt_printk("<> IRQ %d, %d: CNT %d <>\n", irq, ++stp, cnt);
00052 cnt = 0;
00053 }
00054 #endif
00055 RT_CMOS_READ(RTC_INTR_FLAGS);
00056 rt_enable_irq(RTC_IRQ);
00057 if (usr_rtc_handler) {
00058 usr_rtc_handler();
00059 }
00060 }
00061
00062 void rt_request_rtc(long rtc_freq, void *handler)
00063 {
00064 int pwr2;
00065
00066 if (rtc_freq <= 0) {
00067 rtc_freq = RTC_FREQ;
00068 }
00069 if (rtc_freq > MAX_RTC_FREQ) {
00070 rtc_freq = MAX_RTC_FREQ;
00071 } else if (rtc_freq < MIN_RTC_FREQ) {
00072 rtc_freq = MIN_RTC_FREQ;
00073 }
00074 pwr2 = 1;
00075 if (rtc_freq > MIN_RTC_FREQ) {
00076 while (rtc_freq > (1 << pwr2)) {
00077 pwr2++;
00078 }
00079 if (rtc_freq <= ((3*(1 << (pwr2 - 1)) + 1)>>1)) {
00080 pwr2--;
00081 }
00082 }
00083
00084 rt_disable_irq(RTC_IRQ);
00085 rt_release_irq(RTC_IRQ);
00086 rtai_cli();
00087 CMOS_WRITE(CMOS_READ(RTC_FREQ_SELECT), RTC_FREQ_SELECT);
00088 CMOS_WRITE(CMOS_READ(RTC_CONTROL), RTC_CONTROL);
00089 CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - pwr2), RTC_FREQ_SELECT);
00090 CMOS_WRITE((CMOS_READ(RTC_CONTROL) & 0x8F) | RTC_PIE, RTC_CONTROL);
00091 rtai_sti();
00092 usr_rtc_handler = handler ? handler : rt_broadcast_rtc_interrupt;
00093 rt_request_irq(RTC_IRQ, (void *)rtc_handler, (void *)rtc_freq, 0);
00094 rt_enable_irq(RTC_IRQ);
00095 CMOS_READ(RTC_INTR_FLAGS);
00096 return;
00097 }
00098
00099 void rt_release_rtc(void)
00100 {
00101 rt_disable_irq(RTC_IRQ);
00102 usr_rtc_handler = NULL;
00103 rt_release_irq(RTC_IRQ);
00104 rtai_cli();
00105 CMOS_WRITE(CMOS_READ(RTC_FREQ_SELECT), RTC_FREQ_SELECT);
00106 CMOS_WRITE(CMOS_READ(RTC_CONTROL), RTC_CONTROL);
00107 rtai_sti();
00108 return;
00109 }
00110
00111 EXPORT_SYMBOL(rt_request_rtc);
00112 EXPORT_SYMBOL(rt_release_rtc);
00113
00114 #endif