]> git.hungrycats.org Git - linux/commitdiff
[PATCH] no arch specific headers for upd4990a
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 21 Mar 2003 10:27:39 +0000 (02:27 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 21 Mar 2003 10:27:39 +0000 (02:27 -0800)
include/linux/upd4990a.h [new file with mode: 0644]

diff --git a/include/linux/upd4990a.h b/include/linux/upd4990a.h
new file mode 100644 (file)
index 0000000..ad50634
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  Constant and architecture independent procedures
+ *  for NEC uPD4990A serial I/O real-time clock.
+ *
+ *  Copyright 2001  TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>
+ *                 Kyoto University Microcomputer Club (KMC).
+ *
+ *  References:
+ *     uPD4990A serial I/O real-time clock users' manual (Japanese)
+ *     No. S12828JJ4V0UM00 (4th revision), NEC Corporation, 1999.
+ */
+
+#ifndef _LINUX_uPD4990A_H
+#define _LINUX_uPD4990A_H
+
+#include <asm/byteorder.h>
+
+#include <asm/upd4990a.h>
+
+/* Serial commands (4 bits) */
+#define UPD4990A_REGISTER_HOLD                 (0x0)
+#define UPD4990A_REGISTER_SHIFT                        (0x1)
+#define UPD4990A_TIME_SET_AND_COUNTER_HOLD     (0x2)
+#define UPD4990A_TIME_READ                     (0x3)
+#define UPD4990A_TP_64HZ                       (0x4)
+#define UPD4990A_TP_256HZ                      (0x5)
+#define UPD4990A_TP_2048HZ                     (0x6)
+#define UPD4990A_TP_4096HZ                     (0x7)
+#define UPD4990A_TP_1S                         (0x8)
+#define UPD4990A_TP_10S                                (0x9)
+#define UPD4990A_TP_30S                                (0xA)
+#define UPD4990A_TP_60S                                (0xB)
+#define UPD4990A_INTERRUPT_RESET               (0xC)
+#define UPD4990A_INTERRUPT_TIMER_START         (0xD)
+#define UPD4990A_INTERRUPT_TIMER_STOP          (0xE)
+#define UPD4990A_TEST_MODE_SET                 (0xF)
+
+/* Parallel commands (3 bits)
+   0-6 are same with serial commands.  */
+#define UPD4990A_PAR_SERIAL_MODE               7
+
+#ifndef UPD4990A_DELAY
+# include <linux/delay.h>
+# define UPD4990A_DELAY(usec)  udelay((usec))
+#endif
+#ifndef UPD4990A_OUTPUT_DATA
+# define UPD4990A_OUTPUT_DATA(bit)                     \
+       do {                                            \
+               UPD4990A_OUTPUT_DATA_CLK((bit), 0);     \
+               UPD4990A_DELAY(1); /* t-DSU */          \
+               UPD4990A_OUTPUT_DATA_CLK((bit), 1);     \
+               UPD4990A_DELAY(1); /* t-DHLD */ \
+       } while (0)
+#endif
+
+static __inline__ void upd4990a_serial_command(int command)
+{
+       UPD4990A_OUTPUT_DATA(command >> 0);
+       UPD4990A_OUTPUT_DATA(command >> 1);
+       UPD4990A_OUTPUT_DATA(command >> 2);
+       UPD4990A_OUTPUT_DATA(command >> 3);
+       UPD4990A_DELAY(1);      /* t-HLD */
+       UPD4990A_OUTPUT_STROBE(1);
+       UPD4990A_DELAY(1);      /* t-STB & t-d1 */
+       UPD4990A_OUTPUT_STROBE(0);
+       /* 19 microseconds extra delay is needed
+          iff previous mode is TIME READ command  */
+}
+
+struct upd4990a_raw_data {
+       u8      sec;            /* BCD */
+       u8      min;            /* BCD */
+       u8      hour;           /* BCD */
+       u8      mday;           /* BCD */
+#if   defined __LITTLE_ENDIAN_BITFIELD
+       unsigned wday :4;       /* 0-6 */
+       unsigned mon :4;        /* 1-based */
+#elif defined __BIG_ENDIAN_BITFIELD
+       unsigned mon :4;        /* 1-based */
+       unsigned wday :4;       /* 0-6 */
+#else
+# error Unknown bitfield endian!
+#endif
+       u8      year;           /* BCD */
+};
+
+static __inline__ void upd4990a_get_time(struct upd4990a_raw_data *buf,
+                                         int leave_register_hold)
+{
+       int byte;
+
+       upd4990a_serial_command(UPD4990A_TIME_READ);
+       upd4990a_serial_command(UPD4990A_REGISTER_SHIFT);
+       UPD4990A_DELAY(19);     /* t-d2 - t-d1 */
+
+       for (byte = 0; byte < 6; byte++) {
+               u8 tmp;
+               int bit;
+
+               for (tmp = 0, bit = 0; bit < 8; bit++) {
+                       tmp = (tmp | (UPD4990A_READ_DATA() << 8)) >> 1;
+                       UPD4990A_OUTPUT_CLK(1);
+                       UPD4990A_DELAY(1);
+                       UPD4990A_OUTPUT_CLK(0);
+                       UPD4990A_DELAY(1);
+               }
+               ((u8 *) buf)[byte] = tmp;
+       }
+
+       /* The uPD4990A users' manual says that we should issue `Register
+          Hold' command after each data retrieval, or next `Time Read'
+          command may not work correctly.  */
+       if (!leave_register_hold)
+               upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+}
+
+static __inline__ void upd4990a_set_time(const struct upd4990a_raw_data *data,
+                                         int time_set_only)
+{
+       int byte;
+
+       if (!time_set_only)
+               upd4990a_serial_command(UPD4990A_REGISTER_SHIFT);
+
+       for (byte = 0; byte < 6; byte++) {
+               int bit;
+               u8 tmp = ((const u8 *) data)[byte];
+
+               for (bit = 0; bit < 8; bit++, tmp >>= 1)
+                       UPD4990A_OUTPUT_DATA(tmp);
+       }
+
+       upd4990a_serial_command(UPD4990A_TIME_SET_AND_COUNTER_HOLD);
+
+       /* Release counter hold and start the clock.  */
+       if (!time_set_only)
+               upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
+}
+
+#endif /* _LINUX_uPD4990A_H */