[RESEND] A generic RTC driver [3/3]

[RESEND] A generic RTC driver [3/3]

Post by Tom Rin » Wed, 31 Jul 2002 00:30:16



This is part 3 of 3 of the genrtc patches.  This is my own slight bit
of work.  This changes set_rtc_time(struct *rtc_time) to return an int
instead of void.  This was done so that the arch-specific code here
could do additional checks on the time and return an error if needed.
This then introduces include/asm-generic/rtc.h, include/asm-i386/rtc.h
and include/asm-alpha/rtc.h.  include/asm-generic/rtc.h contains the
get_rtc_time and set_rtc_time logic that is in drivers/char/rtc.c,
slightly modified to not duplicate the tests done by the genrtc code but
keeping the additional ones (years > 255 and > 169, as well as the
CONFIG_DECSTATION ones).  This portion has been tested on SMP i386.
This also modifies include/asm-ppc/rtc.h to return -EINVAL if no rtc
hardware is present (it would silently fail previously).

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

--- linux-2.5/drivers/char/genrtc.c-original    2002-07-24 12:23:40.000000000 -0700
+++ linux-2.5/drivers/char/genrtc.c     2002-07-24 13:22:05.000000000 -0700
@@ -33,9 +33,10 @@
  *      1.03 make it more portable            zip...@linux-m68k.org
  *      1.04 removed useless timer code       r...@linux-m68k.org
  *      1.05 portable RTC_UIE emulation       r...@linux-m68k.org
+ *      1.06 set_rtc_time can return an error tr...@kernel.crashing.org
  */

-#define RTC_VERSION    "1.05"
+#define RTC_VERSION    "1.06"

 #include <linux/module.h>
 #include <linux/config.h>
@@ -326,8 +327,7 @@
                    wtime.tm_sec < 0 || wtime.tm_sec >= 60)
                        return -EINVAL;

-               set_rtc_time(&wtime);
-               return 0;
+               return set_rtc_time(&wtime);
            }
        }

--- linux-2.5/include/asm-ppc/rtc.h-original    2002-07-24 13:25:15.000000000 -0700
+++ linux-2.5/include/asm-ppc/rtc.h     2002-07-24 13:25:36.000000000 -0700
@@ -68,7 +68,10 @@
                                time->tm_sec);

                (ppc_md.set_rtc_time)(nowtime);
-       }
+
+               return 0;
+       } else
+               return -EINVAL;
 }

 static inline unsigned int get_rtc_ss(void)
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-generic/rtc.h 2002-07-24 11:06:48.000000000 -0700
@@ -0,0 +1,211 @@
+/*
+ * inclue/asm-generic/rtc.h
+ *
+ * Author: Tom Rini <tr...@mvista.com>
+ *
+ * Based on:
+ * drivers/char/rtc.c
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#ifndef __ASM_RTC_H__
+#define __ASM_RTC_H__
+
+#ifdef __KERNEL__
+
+#include <linux/mc146818rtc.h>
+#include <linux/rtc.h>
+
+#define RTC_PIE 0x40           /* periodic interrupt enable */
+#define RTC_AIE 0x20           /* alarm interrupt enable */
+#define RTC_UIE 0x10           /* update-finished interrupt enable */
+
+extern void gen_rtc_interrupt(unsigned long);
+
+/* some dummy definitions */
+#define RTC_SQWE 0x08          /* enable square-wave output */
+#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
+#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
+#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
+
+/*
+ * Returns true if a clock update is in progress
+ */
+static inline unsigned char rtc_is_updating(void)
+{
+       unsigned char uip;
+
+       spin_lock_irq(&rtc_lock);
+       uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+       spin_unlock_irq(&rtc_lock);
+       return uip;
+}
+
+static inline void get_rtc_time(struct rtc_time *time)
+{
+       unsigned long uip_watchdog = jiffies;
+       unsigned char ctrl;
+#ifdef CONFIG_DECSTATION
+       unsigned int real_year;
+#endif
+
+       /*
+        * read RTC once any update in progress is done. The update
+        * can take just over 2ms. We wait 10 to 20ms. There is no need to
+        * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+        * If you need to know *exactly* when a second has started, enable
+        * periodic update complete interrupts, (via ioctl) and then
+        * immediately read /dev/rtc which will block until you get the IRQ.
+        * Once the read clears, read the RTC time (again via ioctl). Easy.
+        */
+
+       if (rtc_is_updating() != 0)
+               while (jiffies - uip_watchdog < 2*HZ/100) {
+                       barrier();
+                       cpu_relax();
+               }
+
+       /*
+        * Only the values that we read from the RTC are set. We leave
+        * tm_wday, tm_yday and tm_isdst untouched. Even though the
+        * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+        * by the RTC when initially set to a non-zero value.
+        */
+       spin_lock_irq(&rtc_lock);
+       time->tm_sec = CMOS_READ(RTC_SECONDS);
+       time->tm_min = CMOS_READ(RTC_MINUTES);
+       time->tm_hour = CMOS_READ(RTC_HOURS);
+       time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
+       time->tm_mon = CMOS_READ(RTC_MONTH);
+       time->tm_year = CMOS_READ(RTC_YEAR);
+#ifdef CONFIG_DECSTATION
+       real_year = CMOS_READ(RTC_DEC_YEAR);
+#endif
+       ctrl = CMOS_READ(RTC_CONTROL);
+       spin_unlock_irq(&rtc_lock);
+
+       if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+       {
+               BCD_TO_BIN(time->tm_sec);
+               BCD_TO_BIN(time->tm_min);
+               BCD_TO_BIN(time->tm_hour);
+               BCD_TO_BIN(time->tm_mday);
+               BCD_TO_BIN(time->tm_mon);
+               BCD_TO_BIN(time->tm_year);
+       }
+
+#ifdef CONFIG_DECSTATION
+       time->tm_year += real_year - 72;
+#endif
+
+       /*
+        * Account for differences between how the RTC uses the values
+        * and how they are defined in a struct rtc_time;
+        */
+       if (time->tm_year <= 69)
+               time->tm_year += 100;
+
+       time->tm_mon--;
+}
+
+/* Set the current date and time in the real time clock. */
+static inline int set_rtc_time(struct rtc_time *time)
+{
+       unsigned char mon, day, hrs, min, sec;
+       unsigned char save_control, save_freq_select;
+       unsigned int yrs;
+#ifdef CONFIG_DECSTATION
+       unsigned int real_yrs, leap_yr;
+#endif
+
+       yrs = time->tm_year;
+       mon = time->tm_mon + 1;   /* tm_mon starts at zero */
+       day = time->tm_mday;
+       hrs = time->tm_hour;
+       min = time->tm_min;
+       sec = time->tm_sec;
+
+       if (yrs > 255)       /* They are unsigned */
+               return -EINVAL;
+
+       spin_lock_irq(&rtc_lock);
+#ifdef CONFIG_DECSTATION
+       real_yrs = yrs;
+       leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
+                       !((yrs + 1900) % 400));
+       yrs = 72;
+
+       /*
+        * We want to keep the year set to 73 until March
+        * for non-leap years, so that Feb, 29th is handled
+        * correctly.
+        */
+       if (!leap_yr && mon < 3) {
+               real_yrs--;
+               yrs = 73;
+       }
+#endif
+       /* These limits and adjustments are independant of
+        * whether the chip is in binary mode or not.
+        */
+       if (yrs > 169) {
+               spin_unlock_irq(&rtc_lock);
+               return -EINVAL;
+       }
+
+       if (yrs >= 100)
+               yrs -= 100;
+
+       if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+           || RTC_ALWAYS_BCD) {
+               BIN_TO_BCD(sec);
+               BIN_TO_BCD(min);
+               BIN_TO_BCD(hrs);
+               BIN_TO_BCD(day);
+               BIN_TO_BCD(mon);
+               BIN_TO_BCD(yrs);
+       }
+
+       save_control = CMOS_READ(RTC_CONTROL);
+       CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+       save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+#ifdef CONFIG_DECSTATION
+       CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
+#endif
+       CMOS_WRITE(yrs, RTC_YEAR);
+       CMOS_WRITE(mon, RTC_MONTH);
+       CMOS_WRITE(day, RTC_DAY_OF_MONTH);
+       CMOS_WRITE(hrs, RTC_HOURS);
+       CMOS_WRITE(min, RTC_MINUTES);
+       CMOS_WRITE(sec, RTC_SECONDS);
+
+       CMOS_WRITE(save_control, RTC_CONTROL);
+       CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+       spin_unlock_irq(&rtc_lock);
+
+       return 0;
+}
+
+static inline unsigned int get_rtc_ss(void)
+{
+       struct rtc_time h;
+
+       get_rtc_time(&h);
+       return h.tm_sec;
+}
+
+static inline int get_rtc_pll(struct rtc_pll_info *pll)
+{
+       return -EINVAL;
+}
+static inline int set_rtc_pll(struct rtc_pll_info *pll)
+{
+       return -EINVAL;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_RTC_H__ */
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-i386/rtc.h    2002-07-23 10:38:32.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef _I386_RTC_H
+#define _I386_RTC_H
+
+/*
+ * x86 uses the default access methods for the RTC.
+ */
+
+#include <asm-generic/rtc.h>
+
+#endif
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-alpha/rtc.h   2002-07-23 10:38:32.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef _ALPHA_RTC_H
+#define _ALPHA_RTC_H
+
+/*
+ * Alpha uses the default access methods for the RTC.
+ */
+
+#include <asm-generic/rtc.h>
+
+#endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[RESEND] A generic RTC driver [3/3]

Post by Tom Rin » Sun, 04 Aug 2002 01:50:04


This is part 3 of 3 of the genrtc patches.  This is my own slight bit
of work, as well as some work by Randolph Chung. This changes
set_rtc_time(struct *rtc_time) to return an int instead of void.
This was done so that the arch-specific code here could do additional
checks on the time and return an error if needed. This then introduces
include/asm-generic/rtc.h, include/asm-i386/rtc.h and
include/asm-alpha/rtc.h.  include/asm-generic/rtc.h contains the
get_rtc_time and set_rtc_time logic that is in drivers/char/rtc.c and
has been tested on SMP i386.  This also modifies include/asm-ppc/rtc.h
to return -ENODEV if no rtc hardware is present.

Additionally, Dave Jones pointed out to me a place where we might not be
safe when jiffies wraps, so this switches that to time_after().

From Randolph Chung, is supprt for a 64bit kernel and a 32bit userland.

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/

--- linux-2.5/include/asm-ppc/rtc.h     2002-07-24 13:25:15.000000000 -0700
+++ linux-2.5/include/asm-ppc/rtc.h     2002-07-24 13:25:36.000000000 -0700
@@ -68,7 +68,10 @@
                                time->tm_sec);

                (ppc_md.set_rtc_time)(nowtime);
-       }
+
+               return 0;
+       } else
+               return -EINVAL;
 }

 static inline unsigned int get_rtc_ss(void)
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-generic/rtc.h 2002-07-24 11:06:48.000000000 -0700
@@ -0,0 +1,211 @@
+/*
+ * inclue/asm-generic/rtc.h
+ *
+ * Author: Tom Rini <tr...@mvista.com>
+ *
+ * Based on:
+ * drivers/char/rtc.c
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#ifndef __ASM_RTC_H__
+#define __ASM_RTC_H__
+
+#ifdef __KERNEL__
+
+#include <linux/mc146818rtc.h>
+#include <linux/rtc.h>
+
+#define RTC_PIE 0x40           /* periodic interrupt enable */
+#define RTC_AIE 0x20           /* alarm interrupt enable */
+#define RTC_UIE 0x10           /* update-finished interrupt enable */
+
+extern void gen_rtc_interrupt(unsigned long);
+
+/* some dummy definitions */
+#define RTC_SQWE 0x08          /* enable square-wave output */
+#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
+#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
+#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
+
+/*
+ * Returns true if a clock update is in progress
+ */
+static inline unsigned char rtc_is_updating(void)
+{
+       unsigned char uip;
+
+       spin_lock_irq(&rtc_lock);
+       uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+       spin_unlock_irq(&rtc_lock);
+       return uip;
+}
+
+static inline void get_rtc_time(struct rtc_time *time)
+{
+       unsigned long uip_watchdog = jiffies;
+       unsigned char ctrl;
+#ifdef CONFIG_DECSTATION
+       unsigned int real_year;
+#endif
+
+       /*
+        * read RTC once any update in progress is done. The update
+        * can take just over 2ms. We wait 10 to 20ms. There is no need to
+        * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+        * If you need to know *exactly* when a second has started, enable
+        * periodic update complete interrupts, (via ioctl) and then
+        * immediately read /dev/rtc which will block until you get the IRQ.
+        * Once the read clears, read the RTC time (again via ioctl). Easy.
+        */
+
+       if (rtc_is_updating() != 0)
+               while (jiffies - uip_watchdog < 2*HZ/100) {
+                       barrier();
+                       cpu_relax();
+               }
+
+       /*
+        * Only the values that we read from the RTC are set. We leave
+        * tm_wday, tm_yday and tm_isdst untouched. Even though the
+        * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+        * by the RTC when initially set to a non-zero value.
+        */
+       spin_lock_irq(&rtc_lock);
+       time->tm_sec = CMOS_READ(RTC_SECONDS);
+       time->tm_min = CMOS_READ(RTC_MINUTES);
+       time->tm_hour = CMOS_READ(RTC_HOURS);
+       time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
+       time->tm_mon = CMOS_READ(RTC_MONTH);
+       time->tm_year = CMOS_READ(RTC_YEAR);
+#ifdef CONFIG_DECSTATION
+       real_year = CMOS_READ(RTC_DEC_YEAR);
+#endif
+       ctrl = CMOS_READ(RTC_CONTROL);
+       spin_unlock_irq(&rtc_lock);
+
+       if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+       {
+               BCD_TO_BIN(time->tm_sec);
+               BCD_TO_BIN(time->tm_min);
+               BCD_TO_BIN(time->tm_hour);
+               BCD_TO_BIN(time->tm_mday);
+               BCD_TO_BIN(time->tm_mon);
+               BCD_TO_BIN(time->tm_year);
+       }
+
+#ifdef CONFIG_DECSTATION
+       time->tm_year += real_year - 72;
+#endif
+
+       /*
+        * Account for differences between how the RTC uses the values
+        * and how they are defined in a struct rtc_time;
+        */
+       if (time->tm_year <= 69)
+               time->tm_year += 100;
+
+       time->tm_mon--;
+}
+
+/* Set the current date and time in the real time clock. */
+static inline int set_rtc_time(struct rtc_time *time)
+{
+       unsigned char mon, day, hrs, min, sec;
+       unsigned char save_control, save_freq_select;
+       unsigned int yrs;
+#ifdef CONFIG_DECSTATION
+       unsigned int real_yrs, leap_yr;
+#endif
+
+       yrs = time->tm_year;
+       mon = time->tm_mon + 1;   /* tm_mon starts at zero */
+       day = time->tm_mday;
+       hrs = time->tm_hour;
+       min = time->tm_min;
+       sec = time->tm_sec;
+
+       if (yrs > 255)       /* They are unsigned */
+               return -EINVAL;
+
+       spin_lock_irq(&rtc_lock);
+#ifdef CONFIG_DECSTATION
+       real_yrs = yrs;
+       leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
+                       !((yrs + 1900) % 400));
+       yrs = 72;
+
+       /*
+        * We want to keep the year set to 73 until March
+        * for non-leap years, so that Feb, 29th is handled
+        * correctly.
+        */
+       if (!leap_yr && mon < 3) {
+               real_yrs--;
+               yrs = 73;
+       }
+#endif
+       /* These limits and adjustments are independant of
+        * whether the chip is in binary mode or not.
+        */
+       if (yrs > 169) {
+               spin_unlock_irq(&rtc_lock);
+               return -EINVAL;
+       }
+
+       if (yrs >= 100)
+               yrs -= 100;
+
+       if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+           || RTC_ALWAYS_BCD) {
+               BIN_TO_BCD(sec);
+               BIN_TO_BCD(min);
+               BIN_TO_BCD(hrs);
+               BIN_TO_BCD(day);
+               BIN_TO_BCD(mon);
+               BIN_TO_BCD(yrs);
+       }
+
+       save_control = CMOS_READ(RTC_CONTROL);
+       CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+       save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+#ifdef CONFIG_DECSTATION
+       CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
+#endif
+       CMOS_WRITE(yrs, RTC_YEAR);
+       CMOS_WRITE(mon, RTC_MONTH);
+       CMOS_WRITE(day, RTC_DAY_OF_MONTH);
+       CMOS_WRITE(hrs, RTC_HOURS);
+       CMOS_WRITE(min, RTC_MINUTES);
+       CMOS_WRITE(sec, RTC_SECONDS);
+
+       CMOS_WRITE(save_control, RTC_CONTROL);
+       CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+       spin_unlock_irq(&rtc_lock);
+
+       return 0;
+}
+
+static inline unsigned int get_rtc_ss(void)
+{
+       struct rtc_time h;
+
+       get_rtc_time(&h);
+       return h.tm_sec;
+}
+
+static inline int get_rtc_pll(struct rtc_pll_info *pll)
+{
+       return -EINVAL;
+}
+static inline int set_rtc_pll(struct rtc_pll_info *pll)
+{
+       return -EINVAL;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_RTC_H__ */
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-i386/rtc.h    2002-07-23 10:38:32.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef _I386_RTC_H
+#define _I386_RTC_H
+
+/*
+ * x86 uses the default access methods for the RTC.
+ */
+
+#include <asm-generic/rtc.h>
+
+#endif
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-alpha/rtc.h   2002-07-23 10:38:32.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef _ALPHA_RTC_H
+#define _ALPHA_RTC_H
+
+/*
+ * Alpha uses the default access methods for the RTC.
+ */
+
+#include <asm-generic/rtc.h>
+
+#endif
--- /dev/null   1969-12-31 17:00:00.000000000 -0700
+++ linux-2.5/include/asm-parisc/rtc.h  2002-08-02 08:22:16.000000000 -0700
@@ -0,0 +1,131 @@
+/*
+ * inclue/asm-parisc/rtc.h
+ *
+ * Copyright 2002 Randolph CHung <ta...@debian.org>
+ *
+ * Based on: include/asm-ppc/rtc.h and the genrtc driver in the
+ * 2.4 parisc linux tree
+ */
+
+#ifndef __ASM_RTC_H__
+#define __ASM_RTC_H__
+
+#ifdef __KERNEL__
+
+#include <linux/rtc.h>
+
+#include <asm/pdc.h>
+
+#define SECS_PER_HOUR   (60 * 60)
+#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
+
+
+#define RTC_PIE 0x40           /* periodic interrupt enable */
+#define RTC_AIE 0x20           /* alarm interrupt enable */
+#define RTC_UIE 0x10           /* update-finished interrupt enable */
+
+extern void gen_rtc_interrupt(unsigned long);
+
+/* some dummy definitions */
+#define RTC_SQWE 0x08          /* enable square-wave output */
+#define RTC_DM_BINARY 0x04     /* all time/date values are BCD if clear */
+#define RTC_24H 0x02           /* 24 hour mode - else hours bit 7 means pm */
+#define RTC_DST_EN 0x01                /* auto switch DST - works f. USA only */
+
+# define __isleap(year) \
+  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+/* How many days come before each month (0-12).  */
+static const unsigned short int __mon_yday[2][13] =
+{
+       /* Normal years.  */
+       { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+       /* Leap years.  */
+       { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+
+static int get_rtc_time(struct rtc_time *wtime)
+{
+       struct pdc_tod tod_data;
+       long int days, rem, y;
+       const unsigned short int *ip;
+
+       if(pdc_tod_read(&tod_data) < 0)
+               return -1;
+
+      
+       // most of the remainder of this function is:
+//     Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc.
+//     This was originally a part of the GNU C Library.
+//      It is distributed under the GPL, and was swiped from offtime.c
+
+
+       days = tod_data.tod_sec / SECS_PER_DAY;
+       rem = tod_data.tod_sec % SECS_PER_DAY;
+
+       wtime->tm_hour = rem / SECS_PER_HOUR;
+       rem %= SECS_PER_HOUR;
+       wtime->tm_min = rem / 60;
+       wtime->tm_sec = rem % 60;
+
+       y = 1970;
+      
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+
+       while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+       {
+               /* Guess a corrected year, assuming 365 days per year.  */
+               long int yg = y + days / 365 - (days % 365 < 0);
+
+               /* Adjust DAYS and Y to match the guessed year.  */
+               days -= ((yg - y) * 365
+                        + LEAPS_THRU_END_OF (yg - 1)
+                        - LEAPS_THRU_END_OF (y - 1));
+               y = yg;
+       }
+       wtime->tm_year = y - 1900;
+
+       ip = __mon_yday[__isleap(y)];
+       for (y = 11; days < (long int) ip[y]; --y)
+      
...

read more »

 
 
 

1. [RESEND] A generic RTC driver [0/3]

This is essentially the same driver I've sent 3 time previously in a
single patch, and unchanged since the last time I sent it in 3 smaller
chunks.

Patch 1 is the current version of the driver (switched to C99-style
initializers, done in the current m68k CVS tree) and needed changes to
select/compile it in general.  I had previously asked the m68k community
if anyone objected to this being submitted by me, and I got Richard
Zidlicky's (who's at the top of the file) approval, as well as Geert
Uytterhoeven's approval.

Patch 2 is the PPC portion of the patch, which creates
include/asm-ppc/rtc.h.  This has been in the PPC bitkeeper tree for over
a month now.  I can have Paul Mackerras send this to you instead, if you
prefer.

Patch 3 is my own slight bit of work.  This changes set_rtc_time(struct
*rtc_time) to return an int instead of void.  This was done so that the
arch-specific code here could do additional checks on the time and
return an error if needed.  This then introduces
include/asm-generic/rtc.h, include/asm-i386/rtc.h and
include/asm-alpha/rtc.h.  include/asm-generic/rtc.h contains the
get_rtc_time and set_rtc_time logic that is in drivers/char/rtc.c and
has been tested on SMP i386.  This also modifies include/asm-ppc/rtc.h
to return -ENODEV if no rtc hardware is present.

And now onto the history of this driver.

This has been in the m68k tree for a number of years now, so the general
code behind it is quite sound.  This has also been abstracted to the
point where it works on other archs (mainly due to m68k/PPC hybrid
machines).  This is quite useful since a number of archs cannot use
drivers/char/rtc.c because they have very different hardware, or other
issues.

This should also be useful on MIPS, who at one point in the past were
about to copy the PPC rtc driver (drivers/macintosh/rtc.c) and quite
probably useful on other archs as well.

Based on some private feedback, the parisc-linux people have been using
the 2.4 version of this driver for a while, so getting it to work on 2.5
for them should be a trivial matter (it's currently in their tree,
untested as other issues need to be resolved first).  I believe with
some additional enhancements, ia64 will make use of this as well.  And
if the MIPS community ever did make an rtc driver similar to
drivers/macintosh/rtc.c, they should be able to use this one rather
trivially.

--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

2. How to communicate with LKM

3. [RESEND] A generic RTC driver [2/3]

4. System Administrator needed

5. [RESEND] A generic RTC driver [1/3]

6. matrox video card... g450??

7. [RESEND x 3] A generic RTC driver [1/3]

8. Linux 1.3.62 broke POSIX timespec compliance

9. [RESEND x 3] A generic RTC driver [2/3]

10. [RESEND x 3] A generic RTC driver [3/3]

11. [RESEND x 3] A generic RTC driver [0/3]

12. [RESEND x2] A generic RTC driver

13. [RESEND] A generic RTC driver