RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / mips / tx4938 / common / rtc_rx5c348.c
blob07f782fc072506397f696882ff9126ae6de5d4c1
1 /*
2 * RTC routines for RICOH Rx5C348 SPI chip.
3 * Copyright (C) 2000-2001 Toshiba Corporation
5 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
6 * terms of the GNU General Public License version 2. This program is
7 * licensed "as is" without any warranty of any kind, whether express
8 * or implied.
10 * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/string.h>
15 #include <linux/rtc.h>
16 #include <linux/time.h>
17 #include <linux/bcd.h>
18 #include <asm/time.h>
19 #include <asm/tx4938/spi.h>
21 #define EPOCH 2000
23 /* registers */
24 #define Rx5C348_REG_SECOND 0
25 #define Rx5C348_REG_MINUTE 1
26 #define Rx5C348_REG_HOUR 2
27 #define Rx5C348_REG_WEEK 3
28 #define Rx5C348_REG_DAY 4
29 #define Rx5C348_REG_MONTH 5
30 #define Rx5C348_REG_YEAR 6
31 #define Rx5C348_REG_ADJUST 7
32 #define Rx5C348_REG_ALARM_W_MIN 8
33 #define Rx5C348_REG_ALARM_W_HOUR 9
34 #define Rx5C348_REG_ALARM_W_WEEK 10
35 #define Rx5C348_REG_ALARM_D_MIN 11
36 #define Rx5C348_REG_ALARM_D_HOUR 12
37 #define Rx5C348_REG_CTL1 14
38 #define Rx5C348_REG_CTL2 15
40 /* register bits */
41 #define Rx5C348_BIT_PM 0x20 /* REG_HOUR */
42 #define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */
43 #define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */
44 #define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 */
46 /* commands */
47 #define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */
48 #define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */
49 #define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */
50 #define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */
52 static struct spi_dev_desc srtc_dev_desc = {
53 .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */
54 .tcss = 31,
55 .tcsh = 1,
56 .tcsr = 62,
57 /* 31us for Tcss (62us for Tcsr) is required for carry operation) */
58 .byteorder = 1, /* MSB-First */
59 .polarity = 0, /* High-Active */
60 .phase = 1, /* Shift-Then-Sample */
63 static int srtc_chipid;
64 static int srtc_24h;
66 static inline int
67 spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
69 unsigned char *inbufs[1], *outbufs[1];
70 unsigned int incounts[2], outcounts[2];
71 inbufs[0] = inbuf;
72 incounts[0] = count;
73 incounts[1] = 0;
74 outbufs[0] = outbuf;
75 outcounts[0] = count;
76 outcounts[1] = 0;
77 return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
78 inbufs, incounts, outbufs, outcounts, 0);
81 /* RTC-dependent code for time.c */
83 static int
84 rtc_rx5c348_set_time(unsigned long t)
86 unsigned char inbuf[8];
87 struct rtc_time tm;
88 u8 year, month, day, hour, minute, second, century;
90 /* convert */
91 to_tm(t, &tm);
93 year = tm.tm_year % 100;
94 month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */
95 day = tm.tm_mday;
96 hour = tm.tm_hour;
97 minute = tm.tm_min;
98 second = tm.tm_sec;
99 century = tm.tm_year / 100;
101 inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
102 BIN_TO_BCD(second);
103 inbuf[1] = second;
104 BIN_TO_BCD(minute);
105 inbuf[2] = minute;
107 if (srtc_24h) {
108 BIN_TO_BCD(hour);
109 inbuf[3] = hour;
110 } else {
111 /* hour 0 is AM12, noon is PM12 */
112 inbuf[3] = 0;
113 if (hour >= 12)
114 inbuf[3] = Rx5C348_BIT_PM;
115 hour = (hour + 11) % 12 + 1;
116 BIN_TO_BCD(hour);
117 inbuf[3] |= hour;
119 inbuf[4] = 0; /* ignore week */
120 BIN_TO_BCD(day);
121 inbuf[5] = day;
122 BIN_TO_BCD(month);
123 inbuf[6] = month;
124 if (century >= 20)
125 inbuf[6] |= Rx5C348_BIT_Y2K;
126 BIN_TO_BCD(year);
127 inbuf[7] = year;
128 /* write in one transfer to avoid data inconsistency */
129 return spi_rtc_io(inbuf, NULL, 8);
132 static unsigned long
133 rtc_rx5c348_get_time(void)
135 unsigned char inbuf[8], outbuf[8];
136 unsigned int year, month, day, hour, minute, second;
138 inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
139 memset(inbuf + 1, 0, 7);
140 /* read in one transfer to avoid data inconsistency */
141 if (spi_rtc_io(inbuf, outbuf, 8))
142 return 0;
143 second = outbuf[1];
144 BCD_TO_BIN(second);
145 minute = outbuf[2];
146 BCD_TO_BIN(minute);
147 if (srtc_24h) {
148 hour = outbuf[3];
149 BCD_TO_BIN(hour);
150 } else {
151 hour = outbuf[3] & ~Rx5C348_BIT_PM;
152 BCD_TO_BIN(hour);
153 hour %= 12;
154 if (outbuf[3] & Rx5C348_BIT_PM)
155 hour += 12;
157 day = outbuf[5];
158 BCD_TO_BIN(day);
159 month = outbuf[6] & ~Rx5C348_BIT_Y2K;
160 BCD_TO_BIN(month);
161 year = outbuf[7];
162 BCD_TO_BIN(year);
163 year += EPOCH;
165 return mktime(year, month, day, hour, minute, second);
168 void __init
169 rtc_rx5c348_init(int chipid)
171 unsigned char inbuf[2], outbuf[2];
172 srtc_chipid = chipid;
173 /* turn on RTC if it is not on */
174 inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
175 inbuf[1] = 0;
176 spi_rtc_io(inbuf, outbuf, 2);
177 if (outbuf[1] & Rx5C348_BIT_XSTP) {
178 inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
179 inbuf[1] = 0;
180 spi_rtc_io(inbuf, NULL, 2);
183 inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
184 inbuf[1] = 0;
185 spi_rtc_io(inbuf, outbuf, 2);
186 if (outbuf[1] & Rx5C348_BIT_24H)
187 srtc_24h = 1;
189 /* set the function pointers */
190 rtc_mips_get_time = rtc_rx5c348_get_time;
191 rtc_mips_set_time = rtc_rx5c348_set_time;