ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / include / linux / upd4990a.h
1 /*
2  *  Constant and architecture independent procedures
3  *  for NEC uPD4990A serial I/O real-time clock.
4  *
5  *  Copyright 2001  TAKAI Kousuke <tak@kmc.kyoto-u.ac.jp>
6  *                  Kyoto University Microcomputer Club (KMC).
7  *
8  *  References:
9  *      uPD4990A serial I/O real-time clock users' manual (Japanese)
10  *      No. S12828JJ4V0UM00 (4th revision), NEC Corporation, 1999.
11  */
12
13 #ifndef _LINUX_uPD4990A_H
14 #define _LINUX_uPD4990A_H
15
16 #include <asm/byteorder.h>
17
18 #include <asm/upd4990a.h>
19
20 /* Serial commands (4 bits) */
21 #define UPD4990A_REGISTER_HOLD                  (0x0)
22 #define UPD4990A_REGISTER_SHIFT                 (0x1)
23 #define UPD4990A_TIME_SET_AND_COUNTER_HOLD      (0x2)
24 #define UPD4990A_TIME_READ                      (0x3)
25 #define UPD4990A_TP_64HZ                        (0x4)
26 #define UPD4990A_TP_256HZ                       (0x5)
27 #define UPD4990A_TP_2048HZ                      (0x6)
28 #define UPD4990A_TP_4096HZ                      (0x7)
29 #define UPD4990A_TP_1S                          (0x8)
30 #define UPD4990A_TP_10S                         (0x9)
31 #define UPD4990A_TP_30S                         (0xA)
32 #define UPD4990A_TP_60S                         (0xB)
33 #define UPD4990A_INTERRUPT_RESET                (0xC)
34 #define UPD4990A_INTERRUPT_TIMER_START          (0xD)
35 #define UPD4990A_INTERRUPT_TIMER_STOP           (0xE)
36 #define UPD4990A_TEST_MODE_SET                  (0xF)
37
38 /* Parallel commands (3 bits)
39    0-6 are same with serial commands.  */
40 #define UPD4990A_PAR_SERIAL_MODE                7
41
42 #ifndef UPD4990A_DELAY
43 # include <linux/delay.h>
44 # define UPD4990A_DELAY(usec)   udelay((usec))
45 #endif
46 #ifndef UPD4990A_OUTPUT_DATA
47 # define UPD4990A_OUTPUT_DATA(bit)                      \
48         do {                                            \
49                 UPD4990A_OUTPUT_DATA_CLK((bit), 0);     \
50                 UPD4990A_DELAY(1); /* t-DSU */          \
51                 UPD4990A_OUTPUT_DATA_CLK((bit), 1);     \
52                 UPD4990A_DELAY(1); /* t-DHLD */ \
53         } while (0)
54 #endif
55
56 static __inline__ void upd4990a_serial_command(int command)
57 {
58         UPD4990A_OUTPUT_DATA(command >> 0);
59         UPD4990A_OUTPUT_DATA(command >> 1);
60         UPD4990A_OUTPUT_DATA(command >> 2);
61         UPD4990A_OUTPUT_DATA(command >> 3);
62         UPD4990A_DELAY(1);      /* t-HLD */
63         UPD4990A_OUTPUT_STROBE(1);
64         UPD4990A_DELAY(1);      /* t-STB & t-d1 */
65         UPD4990A_OUTPUT_STROBE(0);
66         /* 19 microseconds extra delay is needed
67            iff previous mode is TIME READ command  */
68 }
69
70 struct upd4990a_raw_data {
71         u8      sec;            /* BCD */
72         u8      min;            /* BCD */
73         u8      hour;           /* BCD */
74         u8      mday;           /* BCD */
75 #if   defined __LITTLE_ENDIAN_BITFIELD
76         unsigned wday :4;       /* 0-6 */
77         unsigned mon :4;        /* 1-based */
78 #elif defined __BIG_ENDIAN_BITFIELD
79         unsigned mon :4;        /* 1-based */
80         unsigned wday :4;       /* 0-6 */
81 #else
82 # error Unknown bitfield endian!
83 #endif
84         u8      year;           /* BCD */
85 };
86
87 static __inline__ void upd4990a_get_time(struct upd4990a_raw_data *buf,
88                                           int leave_register_hold)
89 {
90         int byte;
91
92         upd4990a_serial_command(UPD4990A_TIME_READ);
93         upd4990a_serial_command(UPD4990A_REGISTER_SHIFT);
94         UPD4990A_DELAY(19);     /* t-d2 - t-d1 */
95
96         for (byte = 0; byte < 6; byte++) {
97                 u8 tmp;
98                 int bit;
99
100                 for (tmp = 0, bit = 0; bit < 8; bit++) {
101                         tmp = (tmp | (UPD4990A_READ_DATA() << 8)) >> 1;
102                         UPD4990A_OUTPUT_CLK(1);
103                         UPD4990A_DELAY(1);
104                         UPD4990A_OUTPUT_CLK(0);
105                         UPD4990A_DELAY(1);
106                 }
107                 ((u8 *) buf)[byte] = tmp;
108         }
109
110         /* The uPD4990A users' manual says that we should issue `Register
111            Hold' command after each data retrieval, or next `Time Read'
112            command may not work correctly.  */
113         if (!leave_register_hold)
114                 upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
115 }
116
117 static __inline__ void upd4990a_set_time(const struct upd4990a_raw_data *data,
118                                           int time_set_only)
119 {
120         int byte;
121
122         if (!time_set_only)
123                 upd4990a_serial_command(UPD4990A_REGISTER_SHIFT);
124
125         for (byte = 0; byte < 6; byte++) {
126                 int bit;
127                 u8 tmp = ((const u8 *) data)[byte];
128
129                 for (bit = 0; bit < 8; bit++, tmp >>= 1)
130                         UPD4990A_OUTPUT_DATA(tmp);
131         }
132
133         upd4990a_serial_command(UPD4990A_TIME_SET_AND_COUNTER_HOLD);
134
135         /* Release counter hold and start the clock.  */
136         if (!time_set_only)
137                 upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
138 }
139
140 #endif /* _LINUX_uPD4990A_H */