Subversion Repositories shark

Rev

Rev 422 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
422 giacomo 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 */