aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte/swarm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/sibyte/swarm
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/sibyte/swarm')
-rw-r--r--arch/mips/sibyte/swarm/Makefile3
-rw-r--r--arch/mips/sibyte/swarm/dbg_io.c76
-rw-r--r--arch/mips/sibyte/swarm/rtc_m41t81.c224
-rw-r--r--arch/mips/sibyte/swarm/rtc_xicor1241.c203
-rw-r--r--arch/mips/sibyte/swarm/setup.c163
-rw-r--r--arch/mips/sibyte/swarm/time.c244
6 files changed, 913 insertions, 0 deletions
diff --git a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile
new file mode 100644
index 000000000000..2d626039195c
--- /dev/null
+++ b/arch/mips/sibyte/swarm/Makefile
@@ -0,0 +1,3 @@
1lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o
2
3lib-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/sibyte/swarm/dbg_io.c b/arch/mips/sibyte/swarm/dbg_io.c
new file mode 100644
index 000000000000..75ce14c8eb69
--- /dev/null
+++ b/arch/mips/sibyte/swarm/dbg_io.c
@@ -0,0 +1,76 @@
1/*
2 * kgdb debug routines for SiByte boards.
3 *
4 * Copyright (C) 2001 MontaVista Software Inc.
5 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14/* -------------------- BEGINNING OF CONFIG --------------------- */
15
16#include <linux/delay.h>
17#include <asm/io.h>
18#include <asm/sibyte/sb1250.h>
19#include <asm/sibyte/sb1250_regs.h>
20#include <asm/sibyte/sb1250_uart.h>
21#include <asm/sibyte/sb1250_int.h>
22#include <asm/addrspace.h>
23
24/*
25 * We use the second serial port for kgdb traffic.
26 * 115200, 8, N, 1.
27 */
28
29#define BAUD_RATE 115200
30#define CLK_DIVISOR V_DUART_BAUD_RATE(BAUD_RATE)
31#define DATA_BITS V_DUART_BITS_PER_CHAR_8 /* or 7 */
32#define PARITY V_DUART_PARITY_MODE_NONE /* or even */
33#define STOP_BITS M_DUART_STOP_BIT_LEN_1 /* or 2 */
34
35static int duart_initialized = 0; /* 0: need to be init'ed by kgdb */
36
37/* -------------------- END OF CONFIG --------------------- */
38extern int kgdb_port;
39
40#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
41#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
42
43void putDebugChar(unsigned char c);
44unsigned char getDebugChar(void);
45static void
46duart_init(int clk_divisor, int data, int parity, int stop)
47{
48 duart_out(R_DUART_MODE_REG_1, data | parity);
49 duart_out(R_DUART_MODE_REG_2, stop);
50 duart_out(R_DUART_CLK_SEL, clk_divisor);
51
52 duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); /* enable rx and tx */
53}
54
55void
56putDebugChar(unsigned char c)
57{
58 if (!duart_initialized) {
59 duart_initialized = 1;
60 duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
61 }
62 while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
63 duart_out(R_DUART_TX_HOLD, c);
64}
65
66unsigned char
67getDebugChar(void)
68{
69 if (!duart_initialized) {
70 duart_initialized = 1;
71 duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
72 }
73 while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
74 return duart_in(R_DUART_RX_HOLD);
75}
76
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
new file mode 100644
index 000000000000..0e633ee8d83c
--- /dev/null
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -0,0 +1,224 @@
1/*
2 * Copyright (C) 2000, 2001 Broadcom Corporation
3 *
4 * Copyright (C) 2002 MontaVista Software Inc.
5 * Author: jsun@mvista.com or jsun@junsun.net
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13#include <linux/bcd.h>
14#include <linux/types.h>
15#include <linux/time.h>
16
17#include <asm/time.h>
18#include <asm/addrspace.h>
19#include <asm/io.h>
20
21#include <asm/sibyte/sb1250.h>
22#include <asm/sibyte/sb1250_regs.h>
23#include <asm/sibyte/sb1250_smbus.h>
24
25
26/* M41T81 definitions */
27
28/*
29 * Register bits
30 */
31
32#define M41T81REG_SC_ST 0x80 /* stop bit */
33#define M41T81REG_HR_CB 0x40 /* century bit */
34#define M41T81REG_HR_CEB 0x80 /* century enable bit */
35#define M41T81REG_CTL_S 0x20 /* sign bit */
36#define M41T81REG_CTL_FT 0x40 /* frequency test bit */
37#define M41T81REG_CTL_OUT 0x80 /* output level */
38#define M41T81REG_WD_RB0 0x01 /* watchdog resolution bit 0 */
39#define M41T81REG_WD_RB1 0x02 /* watchdog resolution bit 1 */
40#define M41T81REG_WD_BMB0 0x04 /* watchdog multiplier bit 0 */
41#define M41T81REG_WD_BMB1 0x08 /* watchdog multiplier bit 1 */
42#define M41T81REG_WD_BMB2 0x10 /* watchdog multiplier bit 2 */
43#define M41T81REG_WD_BMB3 0x20 /* watchdog multiplier bit 3 */
44#define M41T81REG_WD_BMB4 0x40 /* watchdog multiplier bit 4 */
45#define M41T81REG_AMO_ABE 0x20 /* alarm in "battery back-up mode" enable bit */
46#define M41T81REG_AMO_SQWE 0x40 /* square wave enable */
47#define M41T81REG_AMO_AFE 0x80 /* alarm flag enable flag */
48#define M41T81REG_ADT_RPT5 0x40 /* alarm repeat mode bit 5 */
49#define M41T81REG_ADT_RPT4 0x80 /* alarm repeat mode bit 4 */
50#define M41T81REG_AHR_RPT3 0x80 /* alarm repeat mode bit 3 */
51#define M41T81REG_AHR_HT 0x40 /* halt update bit */
52#define M41T81REG_AMN_RPT2 0x80 /* alarm repeat mode bit 2 */
53#define M41T81REG_ASC_RPT1 0x80 /* alarm repeat mode bit 1 */
54#define M41T81REG_FLG_AF 0x40 /* alarm flag (read only) */
55#define M41T81REG_FLG_WDF 0x80 /* watchdog flag (read only) */
56#define M41T81REG_SQW_RS0 0x10 /* sqw frequency bit 0 */
57#define M41T81REG_SQW_RS1 0x20 /* sqw frequency bit 1 */
58#define M41T81REG_SQW_RS2 0x40 /* sqw frequency bit 2 */
59#define M41T81REG_SQW_RS3 0x80 /* sqw frequency bit 3 */
60
61
62/*
63 * Register numbers
64 */
65
66#define M41T81REG_TSC 0x00 /* tenths/hundredths of second */
67#define M41T81REG_SC 0x01 /* seconds */
68#define M41T81REG_MN 0x02 /* minute */
69#define M41T81REG_HR 0x03 /* hour/century */
70#define M41T81REG_DY 0x04 /* day of week */
71#define M41T81REG_DT 0x05 /* date of month */
72#define M41T81REG_MO 0x06 /* month */
73#define M41T81REG_YR 0x07 /* year */
74#define M41T81REG_CTL 0x08 /* control */
75#define M41T81REG_WD 0x09 /* watchdog */
76#define M41T81REG_AMO 0x0A /* alarm: month */
77#define M41T81REG_ADT 0x0B /* alarm: date */
78#define M41T81REG_AHR 0x0C /* alarm: hour */
79#define M41T81REG_AMN 0x0D /* alarm: minute */
80#define M41T81REG_ASC 0x0E /* alarm: second */
81#define M41T81REG_FLG 0x0F /* flags */
82#define M41T81REG_SQW 0x13 /* square wave register */
83
84#define M41T81_CCR_ADDRESS 0x68
85#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
86
87static int m41t81_read(uint8_t addr)
88{
89 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
90 ;
91
92 bus_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
93 bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE),
94 SMB_CSR(R_SMB_START));
95
96 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
97 ;
98
99 bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
100 SMB_CSR(R_SMB_START));
101
102 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
103 ;
104
105 if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
106 /* Clear error bit by writing a 1 */
107 bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
108 return -1;
109 }
110
111 return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
112}
113
114static int m41t81_write(uint8_t addr, int b)
115{
116 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
117 ;
118
119 bus_writeq((addr & 0xFF), SMB_CSR(R_SMB_CMD));
120 bus_writeq((b & 0xff), SMB_CSR(R_SMB_DATA));
121 bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
122 SMB_CSR(R_SMB_START));
123
124 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
125 ;
126
127 if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
128 /* Clear error bit by writing a 1 */
129 bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
130 return -1;
131 }
132
133 /* read the same byte again to make sure it is written */
134 bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
135 SMB_CSR(R_SMB_START));
136
137 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
138 ;
139
140 return 0;
141}
142
143int m41t81_set_time(unsigned long t)
144{
145 struct rtc_time tm;
146
147 to_tm(t, &tm);
148
149 /*
150 * Note the write order matters as it ensures the correctness.
151 * When we write sec, 10th sec is clear. It is reasonable to
152 * believe we should finish writing min within a second.
153 */
154
155 tm.tm_sec = BIN2BCD(tm.tm_sec);
156 m41t81_write(M41T81REG_SC, tm.tm_sec);
157
158 tm.tm_min = BIN2BCD(tm.tm_min);
159 m41t81_write(M41T81REG_MN, tm.tm_min);
160
161 tm.tm_hour = BIN2BCD(tm.tm_hour);
162 tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0);
163 m41t81_write(M41T81REG_HR, tm.tm_hour);
164
165 /* tm_wday starts from 0 to 6 */
166 if (tm.tm_wday == 0) tm.tm_wday = 7;
167 tm.tm_wday = BIN2BCD(tm.tm_wday);
168 m41t81_write(M41T81REG_DY, tm.tm_wday);
169
170 tm.tm_mday = BIN2BCD(tm.tm_mday);
171 m41t81_write(M41T81REG_DT, tm.tm_mday);
172
173 /* tm_mon starts from 0, *ick* */
174 tm.tm_mon ++;
175 tm.tm_mon = BIN2BCD(tm.tm_mon);
176 m41t81_write(M41T81REG_MO, tm.tm_mon);
177
178 /* we don't do century, everything is beyond 2000 */
179 tm.tm_year %= 100;
180 tm.tm_year = BIN2BCD(tm.tm_year);
181 m41t81_write(M41T81REG_YR, tm.tm_year);
182
183 return 0;
184}
185
186unsigned long m41t81_get_time(void)
187{
188 unsigned int year, mon, day, hour, min, sec;
189
190 /*
191 * min is valid if two reads of sec are the same.
192 */
193 for (;;) {
194 sec = m41t81_read(M41T81REG_SC);
195 min = m41t81_read(M41T81REG_MN);
196 if (sec == m41t81_read(M41T81REG_SC)) break;
197 }
198 hour = m41t81_read(M41T81REG_HR) & 0x3f;
199 day = m41t81_read(M41T81REG_DT);
200 mon = m41t81_read(M41T81REG_MO);
201 year = m41t81_read(M41T81REG_YR);
202
203 sec = BCD2BIN(sec);
204 min = BCD2BIN(min);
205 hour = BCD2BIN(hour);
206 day = BCD2BIN(day);
207 mon = BCD2BIN(mon);
208 year = BCD2BIN(year);
209
210 year += 2000;
211
212 return mktime(year, mon, day, hour, min, sec);
213}
214
215int m41t81_probe(void)
216{
217 unsigned int tmp;
218
219 /* enable chip if it is not enabled yet */
220 tmp = m41t81_read(M41T81REG_SC);
221 m41t81_write(M41T81REG_SC, tmp & 0x7f);
222
223 return (m41t81_read(M41T81REG_SC) != -1);
224}
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
new file mode 100644
index 000000000000..981d21f16e64
--- /dev/null
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -0,0 +1,203 @@
1/*
2 * Copyright (C) 2000, 2001 Broadcom Corporation
3 *
4 * Copyright (C) 2002 MontaVista Software Inc.
5 * Author: jsun@mvista.com or jsun@junsun.net
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <linux/bcd.h>
13#include <linux/types.h>
14#include <linux/time.h>
15
16#include <asm/time.h>
17#include <asm/addrspace.h>
18#include <asm/io.h>
19
20#include <asm/sibyte/sb1250.h>
21#include <asm/sibyte/sb1250_regs.h>
22#include <asm/sibyte/sb1250_smbus.h>
23
24
25/* Xicor 1241 definitions */
26
27/*
28 * Register bits
29 */
30
31#define X1241REG_SR_BAT 0x80 /* currently on battery power */
32#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
33#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
34#define X1241REG_SR_RTCF 0x01 /* clock failed */
35#define X1241REG_BL_BP2 0x80 /* block protect 2 */
36#define X1241REG_BL_BP1 0x40 /* block protect 1 */
37#define X1241REG_BL_BP0 0x20 /* block protect 0 */
38#define X1241REG_BL_WD1 0x10
39#define X1241REG_BL_WD0 0x08
40#define X1241REG_HR_MIL 0x80 /* military time format */
41
42/*
43 * Register numbers
44 */
45
46#define X1241REG_BL 0x10 /* block protect bits */
47#define X1241REG_INT 0x11 /* */
48#define X1241REG_SC 0x30 /* Seconds */
49#define X1241REG_MN 0x31 /* Minutes */
50#define X1241REG_HR 0x32 /* Hours */
51#define X1241REG_DT 0x33 /* Day of month */
52#define X1241REG_MO 0x34 /* Month */
53#define X1241REG_YR 0x35 /* Year */
54#define X1241REG_DW 0x36 /* Day of Week */
55#define X1241REG_Y2K 0x37 /* Year 2K */
56#define X1241REG_SR 0x3F /* Status register */
57
58#define X1241_CCR_ADDRESS 0x6F
59
60#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
61
62static int xicor_read(uint8_t addr)
63{
64 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
65 ;
66
67 bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
68 bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
69 bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
70 SMB_CSR(R_SMB_START));
71
72 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
73 ;
74
75 bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
76 SMB_CSR(R_SMB_START));
77
78 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
79 ;
80
81 if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
82 /* Clear error bit by writing a 1 */
83 bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
84 return -1;
85 }
86
87 return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
88}
89
90static int xicor_write(uint8_t addr, int b)
91{
92 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
93 ;
94
95 bus_writeq(addr, SMB_CSR(R_SMB_CMD));
96 bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
97 bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
98 SMB_CSR(R_SMB_START));
99
100 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
101 ;
102
103 if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
104 /* Clear error bit by writing a 1 */
105 bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
106 return -1;
107 } else {
108 return 0;
109 }
110}
111
112int xicor_set_time(unsigned long t)
113{
114 struct rtc_time tm;
115 int tmp;
116
117 to_tm(t, &tm);
118
119 /* unlock writes to the CCR */
120 xicor_write(X1241REG_SR, X1241REG_SR_WEL);
121 xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
122
123 /* trivial ones */
124 tm.tm_sec = BIN2BCD(tm.tm_sec);
125 xicor_write(X1241REG_SC, tm.tm_sec);
126
127 tm.tm_min = BIN2BCD(tm.tm_min);
128 xicor_write(X1241REG_MN, tm.tm_min);
129
130 tm.tm_mday = BIN2BCD(tm.tm_mday);
131 xicor_write(X1241REG_DT, tm.tm_mday);
132
133 /* tm_mon starts from 0, *ick* */
134 tm.tm_mon ++;
135 tm.tm_mon = BIN2BCD(tm.tm_mon);
136 xicor_write(X1241REG_MO, tm.tm_mon);
137
138 /* year is split */
139 tmp = tm.tm_year / 100;
140 tm.tm_year %= 100;
141 xicor_write(X1241REG_YR, tm.tm_year);
142 xicor_write(X1241REG_Y2K, tmp);
143
144 /* hour is the most tricky one */
145 tmp = xicor_read(X1241REG_HR);
146 if (tmp & X1241REG_HR_MIL) {
147 /* 24 hour format */
148 tm.tm_hour = BIN2BCD(tm.tm_hour);
149 tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f);
150 } else {
151 /* 12 hour format, with 0x2 for pm */
152 tmp = tmp & ~0x3f;
153 if (tm.tm_hour >= 12) {
154 tmp |= 0x20;
155 tm.tm_hour -= 12;
156 }
157 tm.tm_hour = BIN2BCD(tm.tm_hour);
158 tmp |= tm.tm_hour;
159 }
160 xicor_write(X1241REG_HR, tmp);
161
162 xicor_write(X1241REG_SR, 0);
163
164 return 0;
165}
166
167unsigned long xicor_get_time(void)
168{
169 unsigned int year, mon, day, hour, min, sec, y2k;
170
171 sec = xicor_read(X1241REG_SC);
172 min = xicor_read(X1241REG_MN);
173 hour = xicor_read(X1241REG_HR);
174
175 if (hour & X1241REG_HR_MIL) {
176 hour &= 0x3f;
177 } else {
178 if (hour & 0x20)
179 hour = (hour & 0xf) + 0x12;
180 }
181
182 day = xicor_read(X1241REG_DT);
183 mon = xicor_read(X1241REG_MO);
184 year = xicor_read(X1241REG_YR);
185 y2k = xicor_read(X1241REG_Y2K);
186
187 sec = BCD2BIN(sec);
188 min = BCD2BIN(min);
189 hour = BCD2BIN(hour);
190 day = BCD2BIN(day);
191 mon = BCD2BIN(mon);
192 year = BCD2BIN(year);
193 y2k = BCD2BIN(y2k);
194
195 year += (y2k * 100);
196
197 return mktime(year, mon, day, hour, min, sec);
198}
199
200int xicor_probe(void)
201{
202 return (xicor_read(X1241REG_SC) != -1);
203}
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
new file mode 100644
index 000000000000..457aeb7be858
--- /dev/null
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
3 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Setup code for the SWARM board
22 */
23
24#include <linux/config.h>
25#include <linux/spinlock.h>
26#include <linux/mm.h>
27#include <linux/bootmem.h>
28#include <linux/blkdev.h>
29#include <linux/init.h>
30#include <linux/kernel.h>
31#include <linux/tty.h>
32#include <linux/initrd.h>
33
34#include <asm/irq.h>
35#include <asm/io.h>
36#include <asm/bootinfo.h>
37#include <asm/mipsregs.h>
38#include <asm/reboot.h>
39#include <asm/time.h>
40#include <asm/traps.h>
41#include <asm/sibyte/sb1250.h>
42#include <asm/sibyte/sb1250_regs.h>
43#include <asm/sibyte/sb1250_genbus.h>
44#include <asm/sibyte/board.h>
45
46extern void sb1250_setup(void);
47
48extern int xicor_probe(void);
49extern int xicor_set_time(unsigned long);
50extern unsigned long xicor_get_time(void);
51
52extern int m41t81_probe(void);
53extern int m41t81_set_time(unsigned long);
54extern unsigned long m41t81_get_time(void);
55
56const char *get_system_type(void)
57{
58 return "SiByte " SIBYTE_BOARD_NAME;
59}
60
61void __init swarm_timer_setup(struct irqaction *irq)
62{
63 /*
64 * we don't set up irqaction, because we will deliver timer
65 * interrupts through low-level (direct) meachanism.
66 */
67
68 /* We only need to setup the generic timer */
69 sb1250_time_init();
70}
71
72int swarm_be_handler(struct pt_regs *regs, int is_fixup)
73{
74 if (!is_fixup && (regs->cp0_cause & 4)) {
75 /* Data bus error - print PA */
76#ifdef CONFIG_MIPS64
77 printk("DBE physical address: %010lx\n",
78 __read_64bit_c0_register($26, 1));
79#else
80 printk("DBE physical address: %010llx\n",
81 __read_64bit_c0_split($26, 1));
82#endif
83 }
84 return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
85}
86
87static int __init swarm_setup(void)
88{
89 sb1250_setup();
90
91 panic_timeout = 5; /* For debug. */
92
93 board_timer_setup = swarm_timer_setup;
94 board_be_handler = swarm_be_handler;
95
96 if (xicor_probe()) {
97 printk("swarm setup: Xicor 1241 RTC detected.\n");
98 rtc_get_time = xicor_get_time;
99 rtc_set_time = xicor_set_time;
100 }
101
102 if (m41t81_probe()) {
103 printk("swarm setup: M41T81 RTC detected.\n");
104 rtc_get_time = m41t81_get_time;
105 rtc_set_time = m41t81_set_time;
106 }
107
108 printk("This kernel optimized for "
109#ifdef CONFIG_SIMULATION
110 "simulation"
111#else
112 "board"
113#endif
114 " runs "
115#ifdef CONFIG_SIBYTE_CFE
116 "with"
117#else
118 "without"
119#endif
120 " CFE\n");
121
122#ifdef CONFIG_VT
123 screen_info = (struct screen_info) {
124 0, 0, /* orig-x, orig-y */
125 0, /* unused */
126 52, /* orig_video_page */
127 3, /* orig_video_mode */
128 80, /* orig_video_cols */
129 4626, 3, 9, /* unused, ega_bx, unused */
130 25, /* orig_video_lines */
131 0x22, /* orig_video_isVGA */
132 16 /* orig_video_points */
133 };
134 /* XXXKW for CFE, get lines/cols from environment */
135#endif
136
137 return 0;
138}
139
140early_initcall(swarm_setup);
141
142#ifdef LEDS_PHYS
143
144#ifdef CONFIG_SIBYTE_CARMEL
145/* XXXKW need to detect Monterey/LittleSur/etc */
146#undef LEDS_PHYS
147#define LEDS_PHYS MLEDS_PHYS
148#endif
149
150#define setled(index, c) \
151 ((unsigned char *)(IOADDR(LEDS_PHYS)+0x20))[(3-(index))<<3] = (c)
152void setleds(char *str)
153{
154 int i;
155 for (i = 0; i < 4; i++) {
156 if (!str[i]) {
157 setled(i, ' ');
158 } else {
159 setled(i, str[i]);
160 }
161 }
162}
163#endif
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
new file mode 100644
index 000000000000..c1f1a9defeeb
--- /dev/null
+++ b/arch/mips/sibyte/swarm/time.c
@@ -0,0 +1,244 @@
1/*
2 * Copyright (C) 2000, 2001 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19/*
20 * Time routines for the swarm board. We pass all the hard stuff
21 * through to the sb1250 handling code. Only thing we really keep
22 * track of here is what time of day we think it is. And we don't
23 * really even do a good job of that...
24 */
25
26
27#include <linux/bcd.h>
28#include <linux/init.h>
29#include <linux/time.h>
30#include <linux/sched.h>
31#include <linux/spinlock.h>
32#include <asm/system.h>
33#include <asm/addrspace.h>
34#include <asm/io.h>
35
36#include <asm/sibyte/sb1250.h>
37#include <asm/sibyte/sb1250_regs.h>
38#include <asm/sibyte/sb1250_smbus.h>
39
40static unsigned long long sec_bias = 0;
41static unsigned int usec_bias = 0;
42
43/* Xicor 1241 definitions */
44
45/*
46 * Register bits
47 */
48
49#define X1241REG_SR_BAT 0x80 /* currently on battery power */
50#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
51#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
52#define X1241REG_SR_RTCF 0x01 /* clock failed */
53#define X1241REG_BL_BP2 0x80 /* block protect 2 */
54#define X1241REG_BL_BP1 0x40 /* block protect 1 */
55#define X1241REG_BL_BP0 0x20 /* block protect 0 */
56#define X1241REG_BL_WD1 0x10
57#define X1241REG_BL_WD0 0x08
58#define X1241REG_HR_MIL 0x80 /* military time format */
59
60/*
61 * Register numbers
62 */
63
64#define X1241REG_BL 0x10 /* block protect bits */
65#define X1241REG_INT 0x11 /* */
66#define X1241REG_SC 0x30 /* Seconds */
67#define X1241REG_MN 0x31 /* Minutes */
68#define X1241REG_HR 0x32 /* Hours */
69#define X1241REG_DT 0x33 /* Day of month */
70#define X1241REG_MO 0x34 /* Month */
71#define X1241REG_YR 0x35 /* Year */
72#define X1241REG_DW 0x36 /* Day of Week */
73#define X1241REG_Y2K 0x37 /* Year 2K */
74#define X1241REG_SR 0x3F /* Status register */
75
76#define X1241_CCR_ADDRESS 0x6F
77
78#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
79
80static int xicor_read(uint8_t addr)
81{
82 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
83 ;
84
85 bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
86 bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
87 bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
88 SMB_CSR(R_SMB_START));
89
90 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
91 ;
92
93 bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
94 SMB_CSR(R_SMB_START));
95
96 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
97 ;
98
99 if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
100 /* Clear error bit by writing a 1 */
101 bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
102 return -1;
103 }
104
105 return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
106}
107
108static int xicor_write(uint8_t addr, int b)
109{
110 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
111 ;
112
113 bus_writeq(addr, SMB_CSR(R_SMB_CMD));
114 bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
115 bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
116 SMB_CSR(R_SMB_START));
117
118 while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
119 ;
120
121 if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
122 /* Clear error bit by writing a 1 */
123 bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
124 return -1;
125 } else {
126 return 0;
127 }
128}
129
130/*
131 * In order to set the CMOS clock precisely, set_rtc_mmss has to be
132 * called 500 ms after the second nowtime has started, because when
133 * nowtime is written into the registers of the CMOS clock, it will
134 * jump to the next second precisely 500 ms later. Check the Motorola
135 * MC146818A or Dallas DS12887 data sheet for details.
136 *
137 * BUG: This routine does not handle hour overflow properly; it just
138 * sets the minutes. Usually you'll only notice that after reboot!
139 */
140int set_rtc_mmss(unsigned long nowtime)
141{
142 int retval = 0;
143 int real_seconds, real_minutes, cmos_minutes;
144
145 cmos_minutes = xicor_read(X1241REG_MN);
146 cmos_minutes = BCD2BIN(cmos_minutes);
147
148 /*
149 * since we're only adjusting minutes and seconds,
150 * don't interfere with hour overflow. This avoids
151 * messing with unknown time zones but requires your
152 * RTC not to be off by more than 15 minutes
153 */
154 real_seconds = nowtime % 60;
155 real_minutes = nowtime / 60;
156 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
157 real_minutes += 30; /* correct for half hour time zone */
158 real_minutes %= 60;
159
160 /* unlock writes to the CCR */
161 xicor_write(X1241REG_SR, X1241REG_SR_WEL);
162 xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
163
164 if (abs(real_minutes - cmos_minutes) < 30) {
165 real_seconds = BIN2BCD(real_seconds);
166 real_minutes = BIN2BCD(real_minutes);
167 xicor_write(X1241REG_SC, real_seconds);
168 xicor_write(X1241REG_MN, real_minutes);
169 } else {
170 printk(KERN_WARNING
171 "set_rtc_mmss: can't update from %d to %d\n",
172 cmos_minutes, real_minutes);
173 retval = -1;
174 }
175
176 xicor_write(X1241REG_SR, 0);
177
178 printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
179
180 return retval;
181}
182
183static unsigned long __init get_swarm_time(void)
184{
185 unsigned int year, mon, day, hour, min, sec, y2k;
186
187 sec = xicor_read(X1241REG_SC);
188 min = xicor_read(X1241REG_MN);
189 hour = xicor_read(X1241REG_HR);
190
191 if (hour & X1241REG_HR_MIL) {
192 hour &= 0x3f;
193 } else {
194 if (hour & 0x20)
195 hour = (hour & 0xf) + 0x12;
196 }
197
198 sec = BCD2BIN(sec);
199 min = BCD2BIN(min);
200 hour = BCD2BIN(hour);
201
202 day = xicor_read(X1241REG_DT);
203 mon = xicor_read(X1241REG_MO);
204 year = xicor_read(X1241REG_YR);
205 y2k = xicor_read(X1241REG_Y2K);
206
207 day = BCD2BIN(day);
208 mon = BCD2BIN(mon);
209 year = BCD2BIN(year);
210 y2k = BCD2BIN(y2k);
211
212 year += (y2k * 100);
213
214 return mktime(year, mon, day, hour, min, sec);
215}
216
217/*
218 * Bring up the timer at 100 Hz.
219 */
220void __init swarm_time_init(void)
221{
222 unsigned int flags;
223 int status;
224
225 /* Set up the scd general purpose timer 0 to cpu 0 */
226 sb1250_time_init();
227
228 /* Establish communication with the Xicor 1241 RTC */
229 /* XXXKW how do I share the SMBus with the I2C subsystem? */
230
231 bus_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
232 bus_writeq(0, SMB_CSR(R_SMB_CONTROL));
233
234 if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
235 printk("x1241: couldn't detect on SWARM SMBus 1\n");
236 } else {
237 if (status & X1241REG_SR_RTCF)
238 printk("x1241: battery failed -- time is probably wrong\n");
239 write_seqlock_irqsave(&xtime_lock, flags);
240 xtime.tv_sec = get_swarm_time();
241 xtime.tv_nsec = 0;
242 write_sequnlock_irqrestore(&xtime_lock, flags);
243 }
244}