Commit 02112dbc925f664bc4d24ff098686b9d21bfbfb1
Committed by
Linus Torvalds
1 parent
e232cfdc3d
Exists in
master
and in
7 other branches
mips: use bcd2bin/bin2bcd
Changes mips to use the new bcd2bin/bin2bcd functions instead of the obsolete BCD_TO_BIN/BIN_TO_BCD/BCD2BIN/BIN2BCD macros. Signed-off-by: Adrian Bunk <bunk@kernel.org> Cc: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 5 changed files with 59 additions and 59 deletions Inline Diff
arch/mips/dec/time.c
1 | /* | 1 | /* |
2 | * linux/arch/mips/dec/time.c | 2 | * linux/arch/mips/dec/time.c |
3 | * | 3 | * |
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | 4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds |
5 | * Copyright (C) 2000, 2003 Maciej W. Rozycki | 5 | * Copyright (C) 2000, 2003 Maciej W. Rozycki |
6 | * | 6 | * |
7 | * This file contains the time handling details for PC-style clocks as | 7 | * This file contains the time handling details for PC-style clocks as |
8 | * found in some MIPS systems. | 8 | * found in some MIPS systems. |
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | #include <linux/bcd.h> | 11 | #include <linux/bcd.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/mc146818rtc.h> | 13 | #include <linux/mc146818rtc.h> |
14 | #include <linux/param.h> | 14 | #include <linux/param.h> |
15 | 15 | ||
16 | #include <asm/cpu-features.h> | 16 | #include <asm/cpu-features.h> |
17 | #include <asm/ds1287.h> | 17 | #include <asm/ds1287.h> |
18 | #include <asm/time.h> | 18 | #include <asm/time.h> |
19 | #include <asm/dec/interrupts.h> | 19 | #include <asm/dec/interrupts.h> |
20 | #include <asm/dec/ioasic.h> | 20 | #include <asm/dec/ioasic.h> |
21 | #include <asm/dec/machtype.h> | 21 | #include <asm/dec/machtype.h> |
22 | 22 | ||
23 | unsigned long read_persistent_clock(void) | 23 | unsigned long read_persistent_clock(void) |
24 | { | 24 | { |
25 | unsigned int year, mon, day, hour, min, sec, real_year; | 25 | unsigned int year, mon, day, hour, min, sec, real_year; |
26 | unsigned long flags; | 26 | unsigned long flags; |
27 | 27 | ||
28 | spin_lock_irqsave(&rtc_lock, flags); | 28 | spin_lock_irqsave(&rtc_lock, flags); |
29 | 29 | ||
30 | do { | 30 | do { |
31 | sec = CMOS_READ(RTC_SECONDS); | 31 | sec = CMOS_READ(RTC_SECONDS); |
32 | min = CMOS_READ(RTC_MINUTES); | 32 | min = CMOS_READ(RTC_MINUTES); |
33 | hour = CMOS_READ(RTC_HOURS); | 33 | hour = CMOS_READ(RTC_HOURS); |
34 | day = CMOS_READ(RTC_DAY_OF_MONTH); | 34 | day = CMOS_READ(RTC_DAY_OF_MONTH); |
35 | mon = CMOS_READ(RTC_MONTH); | 35 | mon = CMOS_READ(RTC_MONTH); |
36 | year = CMOS_READ(RTC_YEAR); | 36 | year = CMOS_READ(RTC_YEAR); |
37 | /* | 37 | /* |
38 | * The PROM will reset the year to either '72 or '73. | 38 | * The PROM will reset the year to either '72 or '73. |
39 | * Therefore we store the real year separately, in one | 39 | * Therefore we store the real year separately, in one |
40 | * of unused BBU RAM locations. | 40 | * of unused BBU RAM locations. |
41 | */ | 41 | */ |
42 | real_year = CMOS_READ(RTC_DEC_YEAR); | 42 | real_year = CMOS_READ(RTC_DEC_YEAR); |
43 | } while (sec != CMOS_READ(RTC_SECONDS)); | 43 | } while (sec != CMOS_READ(RTC_SECONDS)); |
44 | 44 | ||
45 | spin_unlock_irqrestore(&rtc_lock, flags); | 45 | spin_unlock_irqrestore(&rtc_lock, flags); |
46 | 46 | ||
47 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 47 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
48 | sec = BCD2BIN(sec); | 48 | sec = bcd2bin(sec); |
49 | min = BCD2BIN(min); | 49 | min = bcd2bin(min); |
50 | hour = BCD2BIN(hour); | 50 | hour = bcd2bin(hour); |
51 | day = BCD2BIN(day); | 51 | day = bcd2bin(day); |
52 | mon = BCD2BIN(mon); | 52 | mon = bcd2bin(mon); |
53 | year = BCD2BIN(year); | 53 | year = bcd2bin(year); |
54 | } | 54 | } |
55 | 55 | ||
56 | year += real_year - 72 + 2000; | 56 | year += real_year - 72 + 2000; |
57 | 57 | ||
58 | return mktime(year, mon, day, hour, min, sec); | 58 | return mktime(year, mon, day, hour, min, sec); |
59 | } | 59 | } |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * In order to set the CMOS clock precisely, rtc_mips_set_mmss has to | 62 | * In order to set the CMOS clock precisely, rtc_mips_set_mmss has to |
63 | * be called 500 ms after the second nowtime has started, because when | 63 | * be called 500 ms after the second nowtime has started, because when |
64 | * nowtime is written into the registers of the CMOS clock, it will | 64 | * nowtime is written into the registers of the CMOS clock, it will |
65 | * jump to the next second precisely 500 ms later. Check the Dallas | 65 | * jump to the next second precisely 500 ms later. Check the Dallas |
66 | * DS1287 data sheet for details. | 66 | * DS1287 data sheet for details. |
67 | */ | 67 | */ |
68 | int rtc_mips_set_mmss(unsigned long nowtime) | 68 | int rtc_mips_set_mmss(unsigned long nowtime) |
69 | { | 69 | { |
70 | int retval = 0; | 70 | int retval = 0; |
71 | int real_seconds, real_minutes, cmos_minutes; | 71 | int real_seconds, real_minutes, cmos_minutes; |
72 | unsigned char save_control, save_freq_select; | 72 | unsigned char save_control, save_freq_select; |
73 | 73 | ||
74 | /* irq are locally disabled here */ | 74 | /* irq are locally disabled here */ |
75 | spin_lock(&rtc_lock); | 75 | spin_lock(&rtc_lock); |
76 | /* tell the clock it's being set */ | 76 | /* tell the clock it's being set */ |
77 | save_control = CMOS_READ(RTC_CONTROL); | 77 | save_control = CMOS_READ(RTC_CONTROL); |
78 | CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); | 78 | CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); |
79 | 79 | ||
80 | /* stop and reset prescaler */ | 80 | /* stop and reset prescaler */ |
81 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | 81 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); |
82 | CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); | 82 | CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); |
83 | 83 | ||
84 | cmos_minutes = CMOS_READ(RTC_MINUTES); | 84 | cmos_minutes = CMOS_READ(RTC_MINUTES); |
85 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 85 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
86 | cmos_minutes = BCD2BIN(cmos_minutes); | 86 | cmos_minutes = bcd2bin(cmos_minutes); |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * since we're only adjusting minutes and seconds, | 89 | * since we're only adjusting minutes and seconds, |
90 | * don't interfere with hour overflow. This avoids | 90 | * don't interfere with hour overflow. This avoids |
91 | * messing with unknown time zones but requires your | 91 | * messing with unknown time zones but requires your |
92 | * RTC not to be off by more than 15 minutes | 92 | * RTC not to be off by more than 15 minutes |
93 | */ | 93 | */ |
94 | real_seconds = nowtime % 60; | 94 | real_seconds = nowtime % 60; |
95 | real_minutes = nowtime / 60; | 95 | real_minutes = nowtime / 60; |
96 | if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) | 96 | if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) |
97 | real_minutes += 30; /* correct for half hour time zone */ | 97 | real_minutes += 30; /* correct for half hour time zone */ |
98 | real_minutes %= 60; | 98 | real_minutes %= 60; |
99 | 99 | ||
100 | if (abs(real_minutes - cmos_minutes) < 30) { | 100 | if (abs(real_minutes - cmos_minutes) < 30) { |
101 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 101 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
102 | real_seconds = BIN2BCD(real_seconds); | 102 | real_seconds = bin2bcd(real_seconds); |
103 | real_minutes = BIN2BCD(real_minutes); | 103 | real_minutes = bin2bcd(real_minutes); |
104 | } | 104 | } |
105 | CMOS_WRITE(real_seconds, RTC_SECONDS); | 105 | CMOS_WRITE(real_seconds, RTC_SECONDS); |
106 | CMOS_WRITE(real_minutes, RTC_MINUTES); | 106 | CMOS_WRITE(real_minutes, RTC_MINUTES); |
107 | } else { | 107 | } else { |
108 | printk(KERN_WARNING | 108 | printk(KERN_WARNING |
109 | "set_rtc_mmss: can't update from %d to %d\n", | 109 | "set_rtc_mmss: can't update from %d to %d\n", |
110 | cmos_minutes, real_minutes); | 110 | cmos_minutes, real_minutes); |
111 | retval = -1; | 111 | retval = -1; |
112 | } | 112 | } |
113 | 113 | ||
114 | /* The following flags have to be released exactly in this order, | 114 | /* The following flags have to be released exactly in this order, |
115 | * otherwise the DS1287 will not reset the oscillator and will not | 115 | * otherwise the DS1287 will not reset the oscillator and will not |
116 | * update precisely 500 ms later. You won't find this mentioned | 116 | * update precisely 500 ms later. You won't find this mentioned |
117 | * in the Dallas Semiconductor data sheets, but who believes data | 117 | * in the Dallas Semiconductor data sheets, but who believes data |
118 | * sheets anyway ... -- Markus Kuhn | 118 | * sheets anyway ... -- Markus Kuhn |
119 | */ | 119 | */ |
120 | CMOS_WRITE(save_control, RTC_CONTROL); | 120 | CMOS_WRITE(save_control, RTC_CONTROL); |
121 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | 121 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
122 | spin_unlock(&rtc_lock); | 122 | spin_unlock(&rtc_lock); |
123 | 123 | ||
124 | return retval; | 124 | return retval; |
125 | } | 125 | } |
126 | 126 | ||
127 | void __init plat_time_init(void) | 127 | void __init plat_time_init(void) |
128 | { | 128 | { |
129 | u32 start, end; | 129 | u32 start, end; |
130 | int i = HZ / 10; | 130 | int i = HZ / 10; |
131 | 131 | ||
132 | /* Set up the rate of periodic DS1287 interrupts. */ | 132 | /* Set up the rate of periodic DS1287 interrupts. */ |
133 | ds1287_set_base_clock(HZ); | 133 | ds1287_set_base_clock(HZ); |
134 | 134 | ||
135 | if (cpu_has_counter) { | 135 | if (cpu_has_counter) { |
136 | while (!ds1287_timer_state()) | 136 | while (!ds1287_timer_state()) |
137 | ; | 137 | ; |
138 | 138 | ||
139 | start = read_c0_count(); | 139 | start = read_c0_count(); |
140 | 140 | ||
141 | while (i--) | 141 | while (i--) |
142 | while (!ds1287_timer_state()) | 142 | while (!ds1287_timer_state()) |
143 | ; | 143 | ; |
144 | 144 | ||
145 | end = read_c0_count(); | 145 | end = read_c0_count(); |
146 | 146 | ||
147 | mips_hpt_frequency = (end - start) * 10; | 147 | mips_hpt_frequency = (end - start) * 10; |
148 | printk(KERN_INFO "MIPS counter frequency %dHz\n", | 148 | printk(KERN_INFO "MIPS counter frequency %dHz\n", |
149 | mips_hpt_frequency); | 149 | mips_hpt_frequency); |
150 | } else if (IOASIC) | 150 | } else if (IOASIC) |
151 | /* For pre-R4k systems we use the I/O ASIC's counter. */ | 151 | /* For pre-R4k systems we use the I/O ASIC's counter. */ |
152 | dec_ioasic_clocksource_init(); | 152 | dec_ioasic_clocksource_init(); |
153 | 153 | ||
154 | ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); | 154 | ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); |
155 | } | 155 | } |
156 | 156 |
arch/mips/include/asm/mc146818-time.h
1 | /* | 1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | 2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Machine dependent access functions for RTC registers. | 6 | * Machine dependent access functions for RTC registers. |
7 | */ | 7 | */ |
8 | #ifndef __ASM_MC146818_TIME_H | 8 | #ifndef __ASM_MC146818_TIME_H |
9 | #define __ASM_MC146818_TIME_H | 9 | #define __ASM_MC146818_TIME_H |
10 | 10 | ||
11 | #include <linux/bcd.h> | 11 | #include <linux/bcd.h> |
12 | #include <linux/mc146818rtc.h> | 12 | #include <linux/mc146818rtc.h> |
13 | #include <linux/time.h> | 13 | #include <linux/time.h> |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * For check timing call set_rtc_mmss() 500ms; used in timer interrupt. | 16 | * For check timing call set_rtc_mmss() 500ms; used in timer interrupt. |
17 | */ | 17 | */ |
18 | #define USEC_AFTER 500000 | 18 | #define USEC_AFTER 500000 |
19 | #define USEC_BEFORE 500000 | 19 | #define USEC_BEFORE 500000 |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * In order to set the CMOS clock precisely, set_rtc_mmss has to be | 22 | * In order to set the CMOS clock precisely, set_rtc_mmss has to be |
23 | * called 500 ms after the second nowtime has started, because when | 23 | * called 500 ms after the second nowtime has started, because when |
24 | * nowtime is written into the registers of the CMOS clock, it will | 24 | * nowtime is written into the registers of the CMOS clock, it will |
25 | * jump to the next second precisely 500 ms later. Check the Motorola | 25 | * jump to the next second precisely 500 ms later. Check the Motorola |
26 | * MC146818A or Dallas DS12887 data sheet for details. | 26 | * MC146818A or Dallas DS12887 data sheet for details. |
27 | * | 27 | * |
28 | * BUG: This routine does not handle hour overflow properly; it just | 28 | * BUG: This routine does not handle hour overflow properly; it just |
29 | * sets the minutes. Usually you'll only notice that after reboot! | 29 | * sets the minutes. Usually you'll only notice that after reboot! |
30 | */ | 30 | */ |
31 | static inline int mc146818_set_rtc_mmss(unsigned long nowtime) | 31 | static inline int mc146818_set_rtc_mmss(unsigned long nowtime) |
32 | { | 32 | { |
33 | int real_seconds, real_minutes, cmos_minutes; | 33 | int real_seconds, real_minutes, cmos_minutes; |
34 | unsigned char save_control, save_freq_select; | 34 | unsigned char save_control, save_freq_select; |
35 | int retval = 0; | 35 | int retval = 0; |
36 | unsigned long flags; | 36 | unsigned long flags; |
37 | 37 | ||
38 | spin_lock_irqsave(&rtc_lock, flags); | 38 | spin_lock_irqsave(&rtc_lock, flags); |
39 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ | 39 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ |
40 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | 40 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); |
41 | 41 | ||
42 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ | 42 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ |
43 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | 43 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); |
44 | 44 | ||
45 | cmos_minutes = CMOS_READ(RTC_MINUTES); | 45 | cmos_minutes = CMOS_READ(RTC_MINUTES); |
46 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 46 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
47 | BCD_TO_BIN(cmos_minutes); | 47 | cmos_minutes = bcd2bin(cmos_minutes); |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * since we're only adjusting minutes and seconds, | 50 | * since we're only adjusting minutes and seconds, |
51 | * don't interfere with hour overflow. This avoids | 51 | * don't interfere with hour overflow. This avoids |
52 | * messing with unknown time zones but requires your | 52 | * messing with unknown time zones but requires your |
53 | * RTC not to be off by more than 15 minutes | 53 | * RTC not to be off by more than 15 minutes |
54 | */ | 54 | */ |
55 | real_seconds = nowtime % 60; | 55 | real_seconds = nowtime % 60; |
56 | real_minutes = nowtime / 60; | 56 | real_minutes = nowtime / 60; |
57 | if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) | 57 | if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) |
58 | real_minutes += 30; /* correct for half hour time zone */ | 58 | real_minutes += 30; /* correct for half hour time zone */ |
59 | real_minutes %= 60; | 59 | real_minutes %= 60; |
60 | 60 | ||
61 | if (abs(real_minutes - cmos_minutes) < 30) { | 61 | if (abs(real_minutes - cmos_minutes) < 30) { |
62 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 62 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
63 | BIN_TO_BCD(real_seconds); | 63 | real_seconds = bin2bcd(real_seconds); |
64 | BIN_TO_BCD(real_minutes); | 64 | real_minutes = bin2bcd(real_minutes); |
65 | } | 65 | } |
66 | CMOS_WRITE(real_seconds, RTC_SECONDS); | 66 | CMOS_WRITE(real_seconds, RTC_SECONDS); |
67 | CMOS_WRITE(real_minutes, RTC_MINUTES); | 67 | CMOS_WRITE(real_minutes, RTC_MINUTES); |
68 | } else { | 68 | } else { |
69 | printk(KERN_WARNING | 69 | printk(KERN_WARNING |
70 | "set_rtc_mmss: can't update from %d to %d\n", | 70 | "set_rtc_mmss: can't update from %d to %d\n", |
71 | cmos_minutes, real_minutes); | 71 | cmos_minutes, real_minutes); |
72 | retval = -1; | 72 | retval = -1; |
73 | } | 73 | } |
74 | 74 | ||
75 | /* The following flags have to be released exactly in this order, | 75 | /* The following flags have to be released exactly in this order, |
76 | * otherwise the DS12887 (popular MC146818A clone with integrated | 76 | * otherwise the DS12887 (popular MC146818A clone with integrated |
77 | * battery and quartz) will not reset the oscillator and will not | 77 | * battery and quartz) will not reset the oscillator and will not |
78 | * update precisely 500 ms later. You won't find this mentioned in | 78 | * update precisely 500 ms later. You won't find this mentioned in |
79 | * the Dallas Semiconductor data sheets, but who believes data | 79 | * the Dallas Semiconductor data sheets, but who believes data |
80 | * sheets anyway ... -- Markus Kuhn | 80 | * sheets anyway ... -- Markus Kuhn |
81 | */ | 81 | */ |
82 | CMOS_WRITE(save_control, RTC_CONTROL); | 82 | CMOS_WRITE(save_control, RTC_CONTROL); |
83 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | 83 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
84 | spin_unlock_irqrestore(&rtc_lock, flags); | 84 | spin_unlock_irqrestore(&rtc_lock, flags); |
85 | 85 | ||
86 | return retval; | 86 | return retval; |
87 | } | 87 | } |
88 | 88 | ||
89 | static inline unsigned long mc146818_get_cmos_time(void) | 89 | static inline unsigned long mc146818_get_cmos_time(void) |
90 | { | 90 | { |
91 | unsigned int year, mon, day, hour, min, sec; | 91 | unsigned int year, mon, day, hour, min, sec; |
92 | unsigned long flags; | 92 | unsigned long flags; |
93 | 93 | ||
94 | spin_lock_irqsave(&rtc_lock, flags); | 94 | spin_lock_irqsave(&rtc_lock, flags); |
95 | 95 | ||
96 | do { | 96 | do { |
97 | sec = CMOS_READ(RTC_SECONDS); | 97 | sec = CMOS_READ(RTC_SECONDS); |
98 | min = CMOS_READ(RTC_MINUTES); | 98 | min = CMOS_READ(RTC_MINUTES); |
99 | hour = CMOS_READ(RTC_HOURS); | 99 | hour = CMOS_READ(RTC_HOURS); |
100 | day = CMOS_READ(RTC_DAY_OF_MONTH); | 100 | day = CMOS_READ(RTC_DAY_OF_MONTH); |
101 | mon = CMOS_READ(RTC_MONTH); | 101 | mon = CMOS_READ(RTC_MONTH); |
102 | year = CMOS_READ(RTC_YEAR); | 102 | year = CMOS_READ(RTC_YEAR); |
103 | } while (sec != CMOS_READ(RTC_SECONDS)); | 103 | } while (sec != CMOS_READ(RTC_SECONDS)); |
104 | 104 | ||
105 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 105 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
106 | BCD_TO_BIN(sec); | 106 | sec = bcd2bin(sec); |
107 | BCD_TO_BIN(min); | 107 | min = bcd2bin(min); |
108 | BCD_TO_BIN(hour); | 108 | hour = bcd2bin(hour); |
109 | BCD_TO_BIN(day); | 109 | day = bcd2bin(day); |
110 | BCD_TO_BIN(mon); | 110 | mon = bcd2bin(mon); |
111 | BCD_TO_BIN(year); | 111 | year = bcd2bin(year); |
112 | } | 112 | } |
113 | spin_unlock_irqrestore(&rtc_lock, flags); | 113 | spin_unlock_irqrestore(&rtc_lock, flags); |
114 | year = mc146818_decode_year(year); | 114 | year = mc146818_decode_year(year); |
115 | 115 | ||
116 | return mktime(year, mon, day, hour, min, sec); | 116 | return mktime(year, mon, day, hour, min, sec); |
117 | } | 117 | } |
118 | 118 | ||
119 | #endif /* __ASM_MC146818_TIME_H */ | 119 | #endif /* __ASM_MC146818_TIME_H */ |
120 | 120 |
arch/mips/pmc-sierra/yosemite/setup.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2003 PMC-Sierra Inc. | 2 | * Copyright (C) 2003 PMC-Sierra Inc. |
3 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) | 3 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) |
4 | * | 4 | * |
5 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | 5 | * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 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 | 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 | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | * | 11 | * |
12 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | 12 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
13 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 13 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
14 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | 14 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
15 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 15 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
16 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 16 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
17 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | 17 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
18 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | 18 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
19 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 19 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
21 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 21 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
22 | * | 22 | * |
23 | * You should have received a copy of the GNU General Public License along | 23 | * You should have received a copy of the GNU General Public License along |
24 | * with this program; if not, write to the Free Software Foundation, Inc., | 24 | * with this program; if not, write to the Free Software Foundation, Inc., |
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | #include <linux/bcd.h> | 27 | #include <linux/bcd.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
32 | #include <linux/bootmem.h> | 32 | #include <linux/bootmem.h> |
33 | #include <linux/swap.h> | 33 | #include <linux/swap.h> |
34 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/timex.h> | 37 | #include <linux/timex.h> |
38 | #include <linux/termios.h> | 38 | #include <linux/termios.h> |
39 | #include <linux/tty.h> | 39 | #include <linux/tty.h> |
40 | #include <linux/serial.h> | 40 | #include <linux/serial.h> |
41 | #include <linux/serial_core.h> | 41 | #include <linux/serial_core.h> |
42 | #include <linux/serial_8250.h> | 42 | #include <linux/serial_8250.h> |
43 | 43 | ||
44 | #include <asm/time.h> | 44 | #include <asm/time.h> |
45 | #include <asm/bootinfo.h> | 45 | #include <asm/bootinfo.h> |
46 | #include <asm/page.h> | 46 | #include <asm/page.h> |
47 | #include <asm/io.h> | 47 | #include <asm/io.h> |
48 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
49 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
50 | #include <asm/reboot.h> | 50 | #include <asm/reboot.h> |
51 | #include <asm/serial.h> | 51 | #include <asm/serial.h> |
52 | #include <asm/titan_dep.h> | 52 | #include <asm/titan_dep.h> |
53 | #include <asm/m48t37.h> | 53 | #include <asm/m48t37.h> |
54 | 54 | ||
55 | #include "setup.h" | 55 | #include "setup.h" |
56 | 56 | ||
57 | unsigned char titan_ge_mac_addr_base[6] = { | 57 | unsigned char titan_ge_mac_addr_base[6] = { |
58 | // 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00 | 58 | // 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00 |
59 | 0x00, 0xe0, 0x04, 0x00, 0x00, 0x21 | 59 | 0x00, 0xe0, 0x04, 0x00, 0x00, 0x21 |
60 | }; | 60 | }; |
61 | 61 | ||
62 | unsigned long cpu_clock_freq; | 62 | unsigned long cpu_clock_freq; |
63 | unsigned long yosemite_base; | 63 | unsigned long yosemite_base; |
64 | 64 | ||
65 | static struct m48t37_rtc *m48t37_base; | 65 | static struct m48t37_rtc *m48t37_base; |
66 | 66 | ||
67 | void __init bus_error_init(void) | 67 | void __init bus_error_init(void) |
68 | { | 68 | { |
69 | /* Do nothing */ | 69 | /* Do nothing */ |
70 | } | 70 | } |
71 | 71 | ||
72 | 72 | ||
73 | unsigned long read_persistent_clock(void) | 73 | unsigned long read_persistent_clock(void) |
74 | { | 74 | { |
75 | unsigned int year, month, day, hour, min, sec; | 75 | unsigned int year, month, day, hour, min, sec; |
76 | unsigned long flags; | 76 | unsigned long flags; |
77 | 77 | ||
78 | spin_lock_irqsave(&rtc_lock, flags); | 78 | spin_lock_irqsave(&rtc_lock, flags); |
79 | /* Stop the update to the time */ | 79 | /* Stop the update to the time */ |
80 | m48t37_base->control = 0x40; | 80 | m48t37_base->control = 0x40; |
81 | 81 | ||
82 | year = BCD2BIN(m48t37_base->year); | 82 | year = bcd2bin(m48t37_base->year); |
83 | year += BCD2BIN(m48t37_base->century) * 100; | 83 | year += bcd2bin(m48t37_base->century) * 100; |
84 | 84 | ||
85 | month = BCD2BIN(m48t37_base->month); | 85 | month = bcd2bin(m48t37_base->month); |
86 | day = BCD2BIN(m48t37_base->date); | 86 | day = bcd2bin(m48t37_base->date); |
87 | hour = BCD2BIN(m48t37_base->hour); | 87 | hour = bcd2bin(m48t37_base->hour); |
88 | min = BCD2BIN(m48t37_base->min); | 88 | min = bcd2bin(m48t37_base->min); |
89 | sec = BCD2BIN(m48t37_base->sec); | 89 | sec = bcd2bin(m48t37_base->sec); |
90 | 90 | ||
91 | /* Start the update to the time again */ | 91 | /* Start the update to the time again */ |
92 | m48t37_base->control = 0x00; | 92 | m48t37_base->control = 0x00; |
93 | spin_unlock_irqrestore(&rtc_lock, flags); | 93 | spin_unlock_irqrestore(&rtc_lock, flags); |
94 | 94 | ||
95 | return mktime(year, month, day, hour, min, sec); | 95 | return mktime(year, month, day, hour, min, sec); |
96 | } | 96 | } |
97 | 97 | ||
98 | int rtc_mips_set_time(unsigned long tim) | 98 | int rtc_mips_set_time(unsigned long tim) |
99 | { | 99 | { |
100 | struct rtc_time tm; | 100 | struct rtc_time tm; |
101 | unsigned long flags; | 101 | unsigned long flags; |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Convert to a more useful format -- note months count from 0 | 104 | * Convert to a more useful format -- note months count from 0 |
105 | * and years from 1900 | 105 | * and years from 1900 |
106 | */ | 106 | */ |
107 | rtc_time_to_tm(tim, &tm); | 107 | rtc_time_to_tm(tim, &tm); |
108 | tm.tm_year += 1900; | 108 | tm.tm_year += 1900; |
109 | tm.tm_mon += 1; | 109 | tm.tm_mon += 1; |
110 | 110 | ||
111 | spin_lock_irqsave(&rtc_lock, flags); | 111 | spin_lock_irqsave(&rtc_lock, flags); |
112 | /* enable writing */ | 112 | /* enable writing */ |
113 | m48t37_base->control = 0x80; | 113 | m48t37_base->control = 0x80; |
114 | 114 | ||
115 | /* year */ | 115 | /* year */ |
116 | m48t37_base->year = BIN2BCD(tm.tm_year % 100); | 116 | m48t37_base->year = bin2bcd(tm.tm_year % 100); |
117 | m48t37_base->century = BIN2BCD(tm.tm_year / 100); | 117 | m48t37_base->century = bin2bcd(tm.tm_year / 100); |
118 | 118 | ||
119 | /* month */ | 119 | /* month */ |
120 | m48t37_base->month = BIN2BCD(tm.tm_mon); | 120 | m48t37_base->month = bin2bcd(tm.tm_mon); |
121 | 121 | ||
122 | /* day */ | 122 | /* day */ |
123 | m48t37_base->date = BIN2BCD(tm.tm_mday); | 123 | m48t37_base->date = bin2bcd(tm.tm_mday); |
124 | 124 | ||
125 | /* hour/min/sec */ | 125 | /* hour/min/sec */ |
126 | m48t37_base->hour = BIN2BCD(tm.tm_hour); | 126 | m48t37_base->hour = bin2bcd(tm.tm_hour); |
127 | m48t37_base->min = BIN2BCD(tm.tm_min); | 127 | m48t37_base->min = bin2bcd(tm.tm_min); |
128 | m48t37_base->sec = BIN2BCD(tm.tm_sec); | 128 | m48t37_base->sec = bin2bcd(tm.tm_sec); |
129 | 129 | ||
130 | /* day of week -- not really used, but let's keep it up-to-date */ | 130 | /* day of week -- not really used, but let's keep it up-to-date */ |
131 | m48t37_base->day = BIN2BCD(tm.tm_wday + 1); | 131 | m48t37_base->day = bin2bcd(tm.tm_wday + 1); |
132 | 132 | ||
133 | /* disable writing */ | 133 | /* disable writing */ |
134 | m48t37_base->control = 0x00; | 134 | m48t37_base->control = 0x00; |
135 | spin_unlock_irqrestore(&rtc_lock, flags); | 135 | spin_unlock_irqrestore(&rtc_lock, flags); |
136 | 136 | ||
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | void __init plat_time_init(void) | 140 | void __init plat_time_init(void) |
141 | { | 141 | { |
142 | mips_hpt_frequency = cpu_clock_freq / 2; | 142 | mips_hpt_frequency = cpu_clock_freq / 2; |
143 | mips_hpt_frequency = 33000000 * 3 * 5; | 143 | mips_hpt_frequency = 33000000 * 3 * 5; |
144 | } | 144 | } |
145 | 145 | ||
146 | unsigned long ocd_base; | 146 | unsigned long ocd_base; |
147 | 147 | ||
148 | EXPORT_SYMBOL(ocd_base); | 148 | EXPORT_SYMBOL(ocd_base); |
149 | 149 | ||
150 | /* | 150 | /* |
151 | * Common setup before any secondaries are started | 151 | * Common setup before any secondaries are started |
152 | */ | 152 | */ |
153 | 153 | ||
154 | #define TITAN_UART_CLK 3686400 | 154 | #define TITAN_UART_CLK 3686400 |
155 | #define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16) | 155 | #define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16) |
156 | #define TITAN_SERIAL_IRQ 4 | 156 | #define TITAN_SERIAL_IRQ 4 |
157 | #define TITAN_SERIAL_BASE 0xfd000008UL | 157 | #define TITAN_SERIAL_BASE 0xfd000008UL |
158 | 158 | ||
159 | static void __init py_map_ocd(void) | 159 | static void __init py_map_ocd(void) |
160 | { | 160 | { |
161 | ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE); | 161 | ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE); |
162 | if (!ocd_base) | 162 | if (!ocd_base) |
163 | panic("Mapping OCD failed - game over. Your score is 0."); | 163 | panic("Mapping OCD failed - game over. Your score is 0."); |
164 | 164 | ||
165 | /* Kludge for PMON bug ... */ | 165 | /* Kludge for PMON bug ... */ |
166 | OCD_WRITE(0x0710, 0x0ffff029); | 166 | OCD_WRITE(0x0710, 0x0ffff029); |
167 | } | 167 | } |
168 | 168 | ||
169 | static void __init py_uart_setup(void) | 169 | static void __init py_uart_setup(void) |
170 | { | 170 | { |
171 | #ifdef CONFIG_SERIAL_8250 | 171 | #ifdef CONFIG_SERIAL_8250 |
172 | struct uart_port up; | 172 | struct uart_port up; |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * Register to interrupt zero because we share the interrupt with | 175 | * Register to interrupt zero because we share the interrupt with |
176 | * the serial driver which we don't properly support yet. | 176 | * the serial driver which we don't properly support yet. |
177 | */ | 177 | */ |
178 | memset(&up, 0, sizeof(up)); | 178 | memset(&up, 0, sizeof(up)); |
179 | up.membase = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8); | 179 | up.membase = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8); |
180 | up.irq = TITAN_SERIAL_IRQ; | 180 | up.irq = TITAN_SERIAL_IRQ; |
181 | up.uartclk = TITAN_UART_CLK; | 181 | up.uartclk = TITAN_UART_CLK; |
182 | up.regshift = 0; | 182 | up.regshift = 0; |
183 | up.iotype = UPIO_MEM; | 183 | up.iotype = UPIO_MEM; |
184 | up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; | 184 | up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; |
185 | up.line = 0; | 185 | up.line = 0; |
186 | 186 | ||
187 | if (early_serial_setup(&up)) | 187 | if (early_serial_setup(&up)) |
188 | printk(KERN_ERR "Early serial init of port 0 failed\n"); | 188 | printk(KERN_ERR "Early serial init of port 0 failed\n"); |
189 | #endif /* CONFIG_SERIAL_8250 */ | 189 | #endif /* CONFIG_SERIAL_8250 */ |
190 | } | 190 | } |
191 | 191 | ||
192 | static void __init py_rtc_setup(void) | 192 | static void __init py_rtc_setup(void) |
193 | { | 193 | { |
194 | m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE); | 194 | m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE); |
195 | if (!m48t37_base) | 195 | if (!m48t37_base) |
196 | printk(KERN_ERR "Mapping the RTC failed\n"); | 196 | printk(KERN_ERR "Mapping the RTC failed\n"); |
197 | } | 197 | } |
198 | 198 | ||
199 | /* Not only time init but that's what the hook it's called through is named */ | 199 | /* Not only time init but that's what the hook it's called through is named */ |
200 | static void __init py_late_time_init(void) | 200 | static void __init py_late_time_init(void) |
201 | { | 201 | { |
202 | py_map_ocd(); | 202 | py_map_ocd(); |
203 | py_uart_setup(); | 203 | py_uart_setup(); |
204 | py_rtc_setup(); | 204 | py_rtc_setup(); |
205 | } | 205 | } |
206 | 206 | ||
207 | void __init plat_mem_setup(void) | 207 | void __init plat_mem_setup(void) |
208 | { | 208 | { |
209 | late_time_init = py_late_time_init; | 209 | late_time_init = py_late_time_init; |
210 | 210 | ||
211 | /* Add memory regions */ | 211 | /* Add memory regions */ |
212 | add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM); | 212 | add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM); |
213 | 213 | ||
214 | #if 0 /* XXX Crash ... */ | 214 | #if 0 /* XXX Crash ... */ |
215 | OCD_WRITE(RM9000x2_OCD_HTSC, | 215 | OCD_WRITE(RM9000x2_OCD_HTSC, |
216 | OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE); | 216 | OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE); |
217 | 217 | ||
218 | /* Set the BAR. Shifted mode */ | 218 | /* Set the BAR. Shifted mode */ |
219 | OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR); | 219 | OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR); |
220 | OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0); | 220 | OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0); |
221 | #endif | 221 | #endif |
222 | } | 222 | } |
223 | 223 |
arch/mips/sibyte/swarm/rtc_m41t81.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001 Broadcom Corporation | 2 | * Copyright (C) 2000, 2001 Broadcom Corporation |
3 | * | 3 | * |
4 | * Copyright (C) 2002 MontaVista Software Inc. | 4 | * Copyright (C) 2002 MontaVista Software Inc. |
5 | * Author: jsun@mvista.com or jsun@junsun.net | 5 | * Author: jsun@mvista.com or jsun@junsun.net |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 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 | 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 | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | #include <linux/bcd.h> | 13 | #include <linux/bcd.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/time.h> | 15 | #include <linux/time.h> |
16 | 16 | ||
17 | #include <asm/time.h> | 17 | #include <asm/time.h> |
18 | #include <asm/addrspace.h> | 18 | #include <asm/addrspace.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | 20 | ||
21 | #include <asm/sibyte/sb1250.h> | 21 | #include <asm/sibyte/sb1250.h> |
22 | #include <asm/sibyte/sb1250_regs.h> | 22 | #include <asm/sibyte/sb1250_regs.h> |
23 | #include <asm/sibyte/sb1250_smbus.h> | 23 | #include <asm/sibyte/sb1250_smbus.h> |
24 | 24 | ||
25 | 25 | ||
26 | /* M41T81 definitions */ | 26 | /* M41T81 definitions */ |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * Register bits | 29 | * Register bits |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #define M41T81REG_SC_ST 0x80 /* stop bit */ | 32 | #define M41T81REG_SC_ST 0x80 /* stop bit */ |
33 | #define M41T81REG_HR_CB 0x40 /* century bit */ | 33 | #define M41T81REG_HR_CB 0x40 /* century bit */ |
34 | #define M41T81REG_HR_CEB 0x80 /* century enable bit */ | 34 | #define M41T81REG_HR_CEB 0x80 /* century enable bit */ |
35 | #define M41T81REG_CTL_S 0x20 /* sign bit */ | 35 | #define M41T81REG_CTL_S 0x20 /* sign bit */ |
36 | #define M41T81REG_CTL_FT 0x40 /* frequency test bit */ | 36 | #define M41T81REG_CTL_FT 0x40 /* frequency test bit */ |
37 | #define M41T81REG_CTL_OUT 0x80 /* output level */ | 37 | #define M41T81REG_CTL_OUT 0x80 /* output level */ |
38 | #define M41T81REG_WD_RB0 0x01 /* watchdog resolution bit 0 */ | 38 | #define M41T81REG_WD_RB0 0x01 /* watchdog resolution bit 0 */ |
39 | #define M41T81REG_WD_RB1 0x02 /* watchdog resolution bit 1 */ | 39 | #define M41T81REG_WD_RB1 0x02 /* watchdog resolution bit 1 */ |
40 | #define M41T81REG_WD_BMB0 0x04 /* watchdog multiplier bit 0 */ | 40 | #define M41T81REG_WD_BMB0 0x04 /* watchdog multiplier bit 0 */ |
41 | #define M41T81REG_WD_BMB1 0x08 /* watchdog multiplier bit 1 */ | 41 | #define M41T81REG_WD_BMB1 0x08 /* watchdog multiplier bit 1 */ |
42 | #define M41T81REG_WD_BMB2 0x10 /* watchdog multiplier bit 2 */ | 42 | #define M41T81REG_WD_BMB2 0x10 /* watchdog multiplier bit 2 */ |
43 | #define M41T81REG_WD_BMB3 0x20 /* watchdog multiplier bit 3 */ | 43 | #define M41T81REG_WD_BMB3 0x20 /* watchdog multiplier bit 3 */ |
44 | #define M41T81REG_WD_BMB4 0x40 /* watchdog multiplier bit 4 */ | 44 | #define M41T81REG_WD_BMB4 0x40 /* watchdog multiplier bit 4 */ |
45 | #define M41T81REG_AMO_ABE 0x20 /* alarm in "battery back-up mode" enable bit */ | 45 | #define M41T81REG_AMO_ABE 0x20 /* alarm in "battery back-up mode" enable bit */ |
46 | #define M41T81REG_AMO_SQWE 0x40 /* square wave enable */ | 46 | #define M41T81REG_AMO_SQWE 0x40 /* square wave enable */ |
47 | #define M41T81REG_AMO_AFE 0x80 /* alarm flag enable flag */ | 47 | #define M41T81REG_AMO_AFE 0x80 /* alarm flag enable flag */ |
48 | #define M41T81REG_ADT_RPT5 0x40 /* alarm repeat mode bit 5 */ | 48 | #define M41T81REG_ADT_RPT5 0x40 /* alarm repeat mode bit 5 */ |
49 | #define M41T81REG_ADT_RPT4 0x80 /* alarm repeat mode bit 4 */ | 49 | #define M41T81REG_ADT_RPT4 0x80 /* alarm repeat mode bit 4 */ |
50 | #define M41T81REG_AHR_RPT3 0x80 /* alarm repeat mode bit 3 */ | 50 | #define M41T81REG_AHR_RPT3 0x80 /* alarm repeat mode bit 3 */ |
51 | #define M41T81REG_AHR_HT 0x40 /* halt update bit */ | 51 | #define M41T81REG_AHR_HT 0x40 /* halt update bit */ |
52 | #define M41T81REG_AMN_RPT2 0x80 /* alarm repeat mode bit 2 */ | 52 | #define M41T81REG_AMN_RPT2 0x80 /* alarm repeat mode bit 2 */ |
53 | #define M41T81REG_ASC_RPT1 0x80 /* alarm repeat mode bit 1 */ | 53 | #define M41T81REG_ASC_RPT1 0x80 /* alarm repeat mode bit 1 */ |
54 | #define M41T81REG_FLG_AF 0x40 /* alarm flag (read only) */ | 54 | #define M41T81REG_FLG_AF 0x40 /* alarm flag (read only) */ |
55 | #define M41T81REG_FLG_WDF 0x80 /* watchdog flag (read only) */ | 55 | #define M41T81REG_FLG_WDF 0x80 /* watchdog flag (read only) */ |
56 | #define M41T81REG_SQW_RS0 0x10 /* sqw frequency bit 0 */ | 56 | #define M41T81REG_SQW_RS0 0x10 /* sqw frequency bit 0 */ |
57 | #define M41T81REG_SQW_RS1 0x20 /* sqw frequency bit 1 */ | 57 | #define M41T81REG_SQW_RS1 0x20 /* sqw frequency bit 1 */ |
58 | #define M41T81REG_SQW_RS2 0x40 /* sqw frequency bit 2 */ | 58 | #define M41T81REG_SQW_RS2 0x40 /* sqw frequency bit 2 */ |
59 | #define M41T81REG_SQW_RS3 0x80 /* sqw frequency bit 3 */ | 59 | #define M41T81REG_SQW_RS3 0x80 /* sqw frequency bit 3 */ |
60 | 60 | ||
61 | 61 | ||
62 | /* | 62 | /* |
63 | * Register numbers | 63 | * Register numbers |
64 | */ | 64 | */ |
65 | 65 | ||
66 | #define M41T81REG_TSC 0x00 /* tenths/hundredths of second */ | 66 | #define M41T81REG_TSC 0x00 /* tenths/hundredths of second */ |
67 | #define M41T81REG_SC 0x01 /* seconds */ | 67 | #define M41T81REG_SC 0x01 /* seconds */ |
68 | #define M41T81REG_MN 0x02 /* minute */ | 68 | #define M41T81REG_MN 0x02 /* minute */ |
69 | #define M41T81REG_HR 0x03 /* hour/century */ | 69 | #define M41T81REG_HR 0x03 /* hour/century */ |
70 | #define M41T81REG_DY 0x04 /* day of week */ | 70 | #define M41T81REG_DY 0x04 /* day of week */ |
71 | #define M41T81REG_DT 0x05 /* date of month */ | 71 | #define M41T81REG_DT 0x05 /* date of month */ |
72 | #define M41T81REG_MO 0x06 /* month */ | 72 | #define M41T81REG_MO 0x06 /* month */ |
73 | #define M41T81REG_YR 0x07 /* year */ | 73 | #define M41T81REG_YR 0x07 /* year */ |
74 | #define M41T81REG_CTL 0x08 /* control */ | 74 | #define M41T81REG_CTL 0x08 /* control */ |
75 | #define M41T81REG_WD 0x09 /* watchdog */ | 75 | #define M41T81REG_WD 0x09 /* watchdog */ |
76 | #define M41T81REG_AMO 0x0A /* alarm: month */ | 76 | #define M41T81REG_AMO 0x0A /* alarm: month */ |
77 | #define M41T81REG_ADT 0x0B /* alarm: date */ | 77 | #define M41T81REG_ADT 0x0B /* alarm: date */ |
78 | #define M41T81REG_AHR 0x0C /* alarm: hour */ | 78 | #define M41T81REG_AHR 0x0C /* alarm: hour */ |
79 | #define M41T81REG_AMN 0x0D /* alarm: minute */ | 79 | #define M41T81REG_AMN 0x0D /* alarm: minute */ |
80 | #define M41T81REG_ASC 0x0E /* alarm: second */ | 80 | #define M41T81REG_ASC 0x0E /* alarm: second */ |
81 | #define M41T81REG_FLG 0x0F /* flags */ | 81 | #define M41T81REG_FLG 0x0F /* flags */ |
82 | #define M41T81REG_SQW 0x13 /* square wave register */ | 82 | #define M41T81REG_SQW 0x13 /* square wave register */ |
83 | 83 | ||
84 | #define M41T81_CCR_ADDRESS 0x68 | 84 | #define M41T81_CCR_ADDRESS 0x68 |
85 | 85 | ||
86 | #define SMB_CSR(reg) IOADDR(A_SMB_REGISTER(1, reg)) | 86 | #define SMB_CSR(reg) IOADDR(A_SMB_REGISTER(1, reg)) |
87 | 87 | ||
88 | static int m41t81_read(uint8_t addr) | 88 | static int m41t81_read(uint8_t addr) |
89 | { | 89 | { |
90 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 90 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
91 | ; | 91 | ; |
92 | 92 | ||
93 | __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD)); | 93 | __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD)); |
94 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE, | 94 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE, |
95 | SMB_CSR(R_SMB_START)); | 95 | SMB_CSR(R_SMB_START)); |
96 | 96 | ||
97 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 97 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
98 | ; | 98 | ; |
99 | 99 | ||
100 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, | 100 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, |
101 | SMB_CSR(R_SMB_START)); | 101 | SMB_CSR(R_SMB_START)); |
102 | 102 | ||
103 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 103 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
104 | ; | 104 | ; |
105 | 105 | ||
106 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { | 106 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { |
107 | /* Clear error bit by writing a 1 */ | 107 | /* Clear error bit by writing a 1 */ |
108 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); | 108 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); |
109 | return -1; | 109 | return -1; |
110 | } | 110 | } |
111 | 111 | ||
112 | return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff); | 112 | return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int m41t81_write(uint8_t addr, int b) | 115 | static int m41t81_write(uint8_t addr, int b) |
116 | { | 116 | { |
117 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 117 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
118 | ; | 118 | ; |
119 | 119 | ||
120 | __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD)); | 120 | __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD)); |
121 | __raw_writeq(b & 0xff, SMB_CSR(R_SMB_DATA)); | 121 | __raw_writeq(b & 0xff, SMB_CSR(R_SMB_DATA)); |
122 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE, | 122 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE, |
123 | SMB_CSR(R_SMB_START)); | 123 | SMB_CSR(R_SMB_START)); |
124 | 124 | ||
125 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 125 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
126 | ; | 126 | ; |
127 | 127 | ||
128 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { | 128 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { |
129 | /* Clear error bit by writing a 1 */ | 129 | /* Clear error bit by writing a 1 */ |
130 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); | 130 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); |
131 | return -1; | 131 | return -1; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* read the same byte again to make sure it is written */ | 134 | /* read the same byte again to make sure it is written */ |
135 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, | 135 | __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, |
136 | SMB_CSR(R_SMB_START)); | 136 | SMB_CSR(R_SMB_START)); |
137 | 137 | ||
138 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 138 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
139 | ; | 139 | ; |
140 | 140 | ||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | int m41t81_set_time(unsigned long t) | 144 | int m41t81_set_time(unsigned long t) |
145 | { | 145 | { |
146 | struct rtc_time tm; | 146 | struct rtc_time tm; |
147 | unsigned long flags; | 147 | unsigned long flags; |
148 | 148 | ||
149 | /* Note we don't care about the century */ | 149 | /* Note we don't care about the century */ |
150 | rtc_time_to_tm(t, &tm); | 150 | rtc_time_to_tm(t, &tm); |
151 | 151 | ||
152 | /* | 152 | /* |
153 | * Note the write order matters as it ensures the correctness. | 153 | * Note the write order matters as it ensures the correctness. |
154 | * When we write sec, 10th sec is clear. It is reasonable to | 154 | * When we write sec, 10th sec is clear. It is reasonable to |
155 | * believe we should finish writing min within a second. | 155 | * believe we should finish writing min within a second. |
156 | */ | 156 | */ |
157 | 157 | ||
158 | spin_lock_irqsave(&rtc_lock, flags); | 158 | spin_lock_irqsave(&rtc_lock, flags); |
159 | tm.tm_sec = BIN2BCD(tm.tm_sec); | 159 | tm.tm_sec = bin2bcd(tm.tm_sec); |
160 | m41t81_write(M41T81REG_SC, tm.tm_sec); | 160 | m41t81_write(M41T81REG_SC, tm.tm_sec); |
161 | 161 | ||
162 | tm.tm_min = BIN2BCD(tm.tm_min); | 162 | tm.tm_min = bin2bcd(tm.tm_min); |
163 | m41t81_write(M41T81REG_MN, tm.tm_min); | 163 | m41t81_write(M41T81REG_MN, tm.tm_min); |
164 | 164 | ||
165 | tm.tm_hour = BIN2BCD(tm.tm_hour); | 165 | tm.tm_hour = bin2bcd(tm.tm_hour); |
166 | tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0); | 166 | tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0); |
167 | m41t81_write(M41T81REG_HR, tm.tm_hour); | 167 | m41t81_write(M41T81REG_HR, tm.tm_hour); |
168 | 168 | ||
169 | /* tm_wday starts from 0 to 6 */ | 169 | /* tm_wday starts from 0 to 6 */ |
170 | if (tm.tm_wday == 0) tm.tm_wday = 7; | 170 | if (tm.tm_wday == 0) tm.tm_wday = 7; |
171 | tm.tm_wday = BIN2BCD(tm.tm_wday); | 171 | tm.tm_wday = bin2bcd(tm.tm_wday); |
172 | m41t81_write(M41T81REG_DY, tm.tm_wday); | 172 | m41t81_write(M41T81REG_DY, tm.tm_wday); |
173 | 173 | ||
174 | tm.tm_mday = BIN2BCD(tm.tm_mday); | 174 | tm.tm_mday = bin2bcd(tm.tm_mday); |
175 | m41t81_write(M41T81REG_DT, tm.tm_mday); | 175 | m41t81_write(M41T81REG_DT, tm.tm_mday); |
176 | 176 | ||
177 | /* tm_mon starts from 0, *ick* */ | 177 | /* tm_mon starts from 0, *ick* */ |
178 | tm.tm_mon ++; | 178 | tm.tm_mon ++; |
179 | tm.tm_mon = BIN2BCD(tm.tm_mon); | 179 | tm.tm_mon = bin2bcd(tm.tm_mon); |
180 | m41t81_write(M41T81REG_MO, tm.tm_mon); | 180 | m41t81_write(M41T81REG_MO, tm.tm_mon); |
181 | 181 | ||
182 | /* we don't do century, everything is beyond 2000 */ | 182 | /* we don't do century, everything is beyond 2000 */ |
183 | tm.tm_year %= 100; | 183 | tm.tm_year %= 100; |
184 | tm.tm_year = BIN2BCD(tm.tm_year); | 184 | tm.tm_year = bin2bcd(tm.tm_year); |
185 | m41t81_write(M41T81REG_YR, tm.tm_year); | 185 | m41t81_write(M41T81REG_YR, tm.tm_year); |
186 | spin_unlock_irqrestore(&rtc_lock, flags); | 186 | spin_unlock_irqrestore(&rtc_lock, flags); |
187 | 187 | ||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | unsigned long m41t81_get_time(void) | 191 | unsigned long m41t81_get_time(void) |
192 | { | 192 | { |
193 | unsigned int year, mon, day, hour, min, sec; | 193 | unsigned int year, mon, day, hour, min, sec; |
194 | unsigned long flags; | 194 | unsigned long flags; |
195 | 195 | ||
196 | /* | 196 | /* |
197 | * min is valid if two reads of sec are the same. | 197 | * min is valid if two reads of sec are the same. |
198 | */ | 198 | */ |
199 | for (;;) { | 199 | for (;;) { |
200 | spin_lock_irqsave(&rtc_lock, flags); | 200 | spin_lock_irqsave(&rtc_lock, flags); |
201 | sec = m41t81_read(M41T81REG_SC); | 201 | sec = m41t81_read(M41T81REG_SC); |
202 | min = m41t81_read(M41T81REG_MN); | 202 | min = m41t81_read(M41T81REG_MN); |
203 | if (sec == m41t81_read(M41T81REG_SC)) break; | 203 | if (sec == m41t81_read(M41T81REG_SC)) break; |
204 | spin_unlock_irqrestore(&rtc_lock, flags); | 204 | spin_unlock_irqrestore(&rtc_lock, flags); |
205 | } | 205 | } |
206 | hour = m41t81_read(M41T81REG_HR) & 0x3f; | 206 | hour = m41t81_read(M41T81REG_HR) & 0x3f; |
207 | day = m41t81_read(M41T81REG_DT); | 207 | day = m41t81_read(M41T81REG_DT); |
208 | mon = m41t81_read(M41T81REG_MO); | 208 | mon = m41t81_read(M41T81REG_MO); |
209 | year = m41t81_read(M41T81REG_YR); | 209 | year = m41t81_read(M41T81REG_YR); |
210 | spin_unlock_irqrestore(&rtc_lock, flags); | 210 | spin_unlock_irqrestore(&rtc_lock, flags); |
211 | 211 | ||
212 | sec = BCD2BIN(sec); | 212 | sec = bcd2bin(sec); |
213 | min = BCD2BIN(min); | 213 | min = bcd2bin(min); |
214 | hour = BCD2BIN(hour); | 214 | hour = bcd2bin(hour); |
215 | day = BCD2BIN(day); | 215 | day = bcd2bin(day); |
216 | mon = BCD2BIN(mon); | 216 | mon = bcd2bin(mon); |
217 | year = BCD2BIN(year); | 217 | year = bcd2bin(year); |
218 | 218 | ||
219 | year += 2000; | 219 | year += 2000; |
220 | 220 | ||
221 | return mktime(year, mon, day, hour, min, sec); | 221 | return mktime(year, mon, day, hour, min, sec); |
222 | } | 222 | } |
223 | 223 | ||
224 | int m41t81_probe(void) | 224 | int m41t81_probe(void) |
225 | { | 225 | { |
226 | unsigned int tmp; | 226 | unsigned int tmp; |
227 | 227 | ||
228 | /* enable chip if it is not enabled yet */ | 228 | /* enable chip if it is not enabled yet */ |
229 | tmp = m41t81_read(M41T81REG_SC); | 229 | tmp = m41t81_read(M41T81REG_SC); |
230 | m41t81_write(M41T81REG_SC, tmp & 0x7f); | 230 | m41t81_write(M41T81REG_SC, tmp & 0x7f); |
231 | 231 | ||
232 | return (m41t81_read(M41T81REG_SC) != -1); | 232 | return (m41t81_read(M41T81REG_SC) != -1); |
233 | } | 233 | } |
234 | 234 |
arch/mips/sibyte/swarm/rtc_xicor1241.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001 Broadcom Corporation | 2 | * Copyright (C) 2000, 2001 Broadcom Corporation |
3 | * | 3 | * |
4 | * Copyright (C) 2002 MontaVista Software Inc. | 4 | * Copyright (C) 2002 MontaVista Software Inc. |
5 | * Author: jsun@mvista.com or jsun@junsun.net | 5 | * Author: jsun@mvista.com or jsun@junsun.net |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 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 | 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 | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | */ | 11 | */ |
12 | #include <linux/bcd.h> | 12 | #include <linux/bcd.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/time.h> | 14 | #include <linux/time.h> |
15 | 15 | ||
16 | #include <asm/time.h> | 16 | #include <asm/time.h> |
17 | #include <asm/addrspace.h> | 17 | #include <asm/addrspace.h> |
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | 19 | ||
20 | #include <asm/sibyte/sb1250.h> | 20 | #include <asm/sibyte/sb1250.h> |
21 | #include <asm/sibyte/sb1250_regs.h> | 21 | #include <asm/sibyte/sb1250_regs.h> |
22 | #include <asm/sibyte/sb1250_smbus.h> | 22 | #include <asm/sibyte/sb1250_smbus.h> |
23 | 23 | ||
24 | 24 | ||
25 | /* Xicor 1241 definitions */ | 25 | /* Xicor 1241 definitions */ |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Register bits | 28 | * Register bits |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #define X1241REG_SR_BAT 0x80 /* currently on battery power */ | 31 | #define X1241REG_SR_BAT 0x80 /* currently on battery power */ |
32 | #define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */ | 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 */ | 33 | #define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */ |
34 | #define X1241REG_SR_RTCF 0x01 /* clock failed */ | 34 | #define X1241REG_SR_RTCF 0x01 /* clock failed */ |
35 | #define X1241REG_BL_BP2 0x80 /* block protect 2 */ | 35 | #define X1241REG_BL_BP2 0x80 /* block protect 2 */ |
36 | #define X1241REG_BL_BP1 0x40 /* block protect 1 */ | 36 | #define X1241REG_BL_BP1 0x40 /* block protect 1 */ |
37 | #define X1241REG_BL_BP0 0x20 /* block protect 0 */ | 37 | #define X1241REG_BL_BP0 0x20 /* block protect 0 */ |
38 | #define X1241REG_BL_WD1 0x10 | 38 | #define X1241REG_BL_WD1 0x10 |
39 | #define X1241REG_BL_WD0 0x08 | 39 | #define X1241REG_BL_WD0 0x08 |
40 | #define X1241REG_HR_MIL 0x80 /* military time format */ | 40 | #define X1241REG_HR_MIL 0x80 /* military time format */ |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Register numbers | 43 | * Register numbers |
44 | */ | 44 | */ |
45 | 45 | ||
46 | #define X1241REG_BL 0x10 /* block protect bits */ | 46 | #define X1241REG_BL 0x10 /* block protect bits */ |
47 | #define X1241REG_INT 0x11 /* */ | 47 | #define X1241REG_INT 0x11 /* */ |
48 | #define X1241REG_SC 0x30 /* Seconds */ | 48 | #define X1241REG_SC 0x30 /* Seconds */ |
49 | #define X1241REG_MN 0x31 /* Minutes */ | 49 | #define X1241REG_MN 0x31 /* Minutes */ |
50 | #define X1241REG_HR 0x32 /* Hours */ | 50 | #define X1241REG_HR 0x32 /* Hours */ |
51 | #define X1241REG_DT 0x33 /* Day of month */ | 51 | #define X1241REG_DT 0x33 /* Day of month */ |
52 | #define X1241REG_MO 0x34 /* Month */ | 52 | #define X1241REG_MO 0x34 /* Month */ |
53 | #define X1241REG_YR 0x35 /* Year */ | 53 | #define X1241REG_YR 0x35 /* Year */ |
54 | #define X1241REG_DW 0x36 /* Day of Week */ | 54 | #define X1241REG_DW 0x36 /* Day of Week */ |
55 | #define X1241REG_Y2K 0x37 /* Year 2K */ | 55 | #define X1241REG_Y2K 0x37 /* Year 2K */ |
56 | #define X1241REG_SR 0x3F /* Status register */ | 56 | #define X1241REG_SR 0x3F /* Status register */ |
57 | 57 | ||
58 | #define X1241_CCR_ADDRESS 0x6F | 58 | #define X1241_CCR_ADDRESS 0x6F |
59 | 59 | ||
60 | #define SMB_CSR(reg) IOADDR(A_SMB_REGISTER(1, reg)) | 60 | #define SMB_CSR(reg) IOADDR(A_SMB_REGISTER(1, reg)) |
61 | 61 | ||
62 | static int xicor_read(uint8_t addr) | 62 | static int xicor_read(uint8_t addr) |
63 | { | 63 | { |
64 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 64 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
65 | ; | 65 | ; |
66 | 66 | ||
67 | __raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); | 67 | __raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); |
68 | __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA)); | 68 | __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA)); |
69 | __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE, | 69 | __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE, |
70 | SMB_CSR(R_SMB_START)); | 70 | SMB_CSR(R_SMB_START)); |
71 | 71 | ||
72 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 72 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
73 | ; | 73 | ; |
74 | 74 | ||
75 | __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, | 75 | __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, |
76 | SMB_CSR(R_SMB_START)); | 76 | SMB_CSR(R_SMB_START)); |
77 | 77 | ||
78 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 78 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
79 | ; | 79 | ; |
80 | 80 | ||
81 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { | 81 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { |
82 | /* Clear error bit by writing a 1 */ | 82 | /* Clear error bit by writing a 1 */ |
83 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); | 83 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); |
84 | return -1; | 84 | return -1; |
85 | } | 85 | } |
86 | 86 | ||
87 | return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff); | 87 | return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff); |
88 | } | 88 | } |
89 | 89 | ||
90 | static int xicor_write(uint8_t addr, int b) | 90 | static int xicor_write(uint8_t addr, int b) |
91 | { | 91 | { |
92 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 92 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
93 | ; | 93 | ; |
94 | 94 | ||
95 | __raw_writeq(addr, SMB_CSR(R_SMB_CMD)); | 95 | __raw_writeq(addr, SMB_CSR(R_SMB_CMD)); |
96 | __raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); | 96 | __raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); |
97 | __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, | 97 | __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, |
98 | SMB_CSR(R_SMB_START)); | 98 | SMB_CSR(R_SMB_START)); |
99 | 99 | ||
100 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) | 100 | while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) |
101 | ; | 101 | ; |
102 | 102 | ||
103 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { | 103 | if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { |
104 | /* Clear error bit by writing a 1 */ | 104 | /* Clear error bit by writing a 1 */ |
105 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); | 105 | __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); |
106 | return -1; | 106 | return -1; |
107 | } else { | 107 | } else { |
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | int xicor_set_time(unsigned long t) | 112 | int xicor_set_time(unsigned long t) |
113 | { | 113 | { |
114 | struct rtc_time tm; | 114 | struct rtc_time tm; |
115 | int tmp; | 115 | int tmp; |
116 | unsigned long flags; | 116 | unsigned long flags; |
117 | 117 | ||
118 | rtc_time_to_tm(t, &tm); | 118 | rtc_time_to_tm(t, &tm); |
119 | tm.tm_year += 1900; | 119 | tm.tm_year += 1900; |
120 | 120 | ||
121 | spin_lock_irqsave(&rtc_lock, flags); | 121 | spin_lock_irqsave(&rtc_lock, flags); |
122 | /* unlock writes to the CCR */ | 122 | /* unlock writes to the CCR */ |
123 | xicor_write(X1241REG_SR, X1241REG_SR_WEL); | 123 | xicor_write(X1241REG_SR, X1241REG_SR_WEL); |
124 | xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); | 124 | xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); |
125 | 125 | ||
126 | /* trivial ones */ | 126 | /* trivial ones */ |
127 | tm.tm_sec = BIN2BCD(tm.tm_sec); | 127 | tm.tm_sec = bin2bcd(tm.tm_sec); |
128 | xicor_write(X1241REG_SC, tm.tm_sec); | 128 | xicor_write(X1241REG_SC, tm.tm_sec); |
129 | 129 | ||
130 | tm.tm_min = BIN2BCD(tm.tm_min); | 130 | tm.tm_min = bin2bcd(tm.tm_min); |
131 | xicor_write(X1241REG_MN, tm.tm_min); | 131 | xicor_write(X1241REG_MN, tm.tm_min); |
132 | 132 | ||
133 | tm.tm_mday = BIN2BCD(tm.tm_mday); | 133 | tm.tm_mday = bin2bcd(tm.tm_mday); |
134 | xicor_write(X1241REG_DT, tm.tm_mday); | 134 | xicor_write(X1241REG_DT, tm.tm_mday); |
135 | 135 | ||
136 | /* tm_mon starts from 0, *ick* */ | 136 | /* tm_mon starts from 0, *ick* */ |
137 | tm.tm_mon ++; | 137 | tm.tm_mon ++; |
138 | tm.tm_mon = BIN2BCD(tm.tm_mon); | 138 | tm.tm_mon = bin2bcd(tm.tm_mon); |
139 | xicor_write(X1241REG_MO, tm.tm_mon); | 139 | xicor_write(X1241REG_MO, tm.tm_mon); |
140 | 140 | ||
141 | /* year is split */ | 141 | /* year is split */ |
142 | tmp = tm.tm_year / 100; | 142 | tmp = tm.tm_year / 100; |
143 | tm.tm_year %= 100; | 143 | tm.tm_year %= 100; |
144 | xicor_write(X1241REG_YR, tm.tm_year); | 144 | xicor_write(X1241REG_YR, tm.tm_year); |
145 | xicor_write(X1241REG_Y2K, tmp); | 145 | xicor_write(X1241REG_Y2K, tmp); |
146 | 146 | ||
147 | /* hour is the most tricky one */ | 147 | /* hour is the most tricky one */ |
148 | tmp = xicor_read(X1241REG_HR); | 148 | tmp = xicor_read(X1241REG_HR); |
149 | if (tmp & X1241REG_HR_MIL) { | 149 | if (tmp & X1241REG_HR_MIL) { |
150 | /* 24 hour format */ | 150 | /* 24 hour format */ |
151 | tm.tm_hour = BIN2BCD(tm.tm_hour); | 151 | tm.tm_hour = bin2bcd(tm.tm_hour); |
152 | tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f); | 152 | tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f); |
153 | } else { | 153 | } else { |
154 | /* 12 hour format, with 0x2 for pm */ | 154 | /* 12 hour format, with 0x2 for pm */ |
155 | tmp = tmp & ~0x3f; | 155 | tmp = tmp & ~0x3f; |
156 | if (tm.tm_hour >= 12) { | 156 | if (tm.tm_hour >= 12) { |
157 | tmp |= 0x20; | 157 | tmp |= 0x20; |
158 | tm.tm_hour -= 12; | 158 | tm.tm_hour -= 12; |
159 | } | 159 | } |
160 | tm.tm_hour = BIN2BCD(tm.tm_hour); | 160 | tm.tm_hour = bin2bcd(tm.tm_hour); |
161 | tmp |= tm.tm_hour; | 161 | tmp |= tm.tm_hour; |
162 | } | 162 | } |
163 | xicor_write(X1241REG_HR, tmp); | 163 | xicor_write(X1241REG_HR, tmp); |
164 | 164 | ||
165 | xicor_write(X1241REG_SR, 0); | 165 | xicor_write(X1241REG_SR, 0); |
166 | spin_unlock_irqrestore(&rtc_lock, flags); | 166 | spin_unlock_irqrestore(&rtc_lock, flags); |
167 | 167 | ||
168 | return 0; | 168 | return 0; |
169 | } | 169 | } |
170 | 170 | ||
171 | unsigned long xicor_get_time(void) | 171 | unsigned long xicor_get_time(void) |
172 | { | 172 | { |
173 | unsigned int year, mon, day, hour, min, sec, y2k; | 173 | unsigned int year, mon, day, hour, min, sec, y2k; |
174 | unsigned long flags; | 174 | unsigned long flags; |
175 | 175 | ||
176 | spin_lock_irqsave(&rtc_lock, flags); | 176 | spin_lock_irqsave(&rtc_lock, flags); |
177 | sec = xicor_read(X1241REG_SC); | 177 | sec = xicor_read(X1241REG_SC); |
178 | min = xicor_read(X1241REG_MN); | 178 | min = xicor_read(X1241REG_MN); |
179 | hour = xicor_read(X1241REG_HR); | 179 | hour = xicor_read(X1241REG_HR); |
180 | 180 | ||
181 | if (hour & X1241REG_HR_MIL) { | 181 | if (hour & X1241REG_HR_MIL) { |
182 | hour &= 0x3f; | 182 | hour &= 0x3f; |
183 | } else { | 183 | } else { |
184 | if (hour & 0x20) | 184 | if (hour & 0x20) |
185 | hour = (hour & 0xf) + 0x12; | 185 | hour = (hour & 0xf) + 0x12; |
186 | } | 186 | } |
187 | 187 | ||
188 | day = xicor_read(X1241REG_DT); | 188 | day = xicor_read(X1241REG_DT); |
189 | mon = xicor_read(X1241REG_MO); | 189 | mon = xicor_read(X1241REG_MO); |
190 | year = xicor_read(X1241REG_YR); | 190 | year = xicor_read(X1241REG_YR); |
191 | y2k = xicor_read(X1241REG_Y2K); | 191 | y2k = xicor_read(X1241REG_Y2K); |
192 | spin_unlock_irqrestore(&rtc_lock, flags); | 192 | spin_unlock_irqrestore(&rtc_lock, flags); |
193 | 193 | ||
194 | sec = BCD2BIN(sec); | 194 | sec = bcd2bin(sec); |
195 | min = BCD2BIN(min); | 195 | min = bcd2bin(min); |
196 | hour = BCD2BIN(hour); | 196 | hour = bcd2bin(hour); |
197 | day = BCD2BIN(day); | 197 | day = bcd2bin(day); |
198 | mon = BCD2BIN(mon); | 198 | mon = bcd2bin(mon); |
199 | year = BCD2BIN(year); | 199 | year = bcd2bin(year); |
200 | y2k = BCD2BIN(y2k); | 200 | y2k = bcd2bin(y2k); |
201 | 201 | ||
202 | year += (y2k * 100); | 202 | year += (y2k * 100); |
203 | 203 | ||
204 | return mktime(year, mon, day, hour, min, sec); | 204 | return mktime(year, mon, day, hour, min, sec); |
205 | } | 205 | } |
206 | 206 | ||
207 | int xicor_probe(void) | 207 | int xicor_probe(void) |
208 | { | 208 | { |
209 | return (xicor_read(X1241REG_SC) != -1); | 209 | return (xicor_read(X1241REG_SC) != -1); |
210 | } | 210 | } |
211 | 211 |