base/arch/x86_64/hal/rtc.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005-2008  Paolo Mantegazza  (mantegazza@aero.polimi.it)
00003  * (RTC specific part with) Giuseppe Quaranta (quaranta@aero.polimi.it)
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License as
00007  * published by the Free Software Foundation; either version 2 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 //#define TEST_RTC
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); // 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 /* INCLUDED_BY_HAL_C */

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7