Commit fc4860c089a6b6603e1ae4f9c1f8bd1b3aadfc8b
1 parent
b18c68d891
Exists in
v2017.01-smarct4x
and in
37 other branches
x86: rtc: mc146818: Add helpers to read/write CMOS RAM
On x86 we use CMOS RAM to read and write some settings. Add basic support for this, including access to registers 128-255. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 2 changed files with 105 additions and 48 deletions Side-by-side Diff
drivers/rtc/mc146818.c
... | ... | @@ -27,9 +27,6 @@ |
27 | 27 | /* Set this to 1 to clear the CMOS RAM */ |
28 | 28 | #define CLEAR_CMOS 0 |
29 | 29 | |
30 | -static uchar rtc_read (uchar reg); | |
31 | -static void rtc_write (uchar reg, uchar val); | |
32 | - | |
33 | 30 | #define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 |
34 | 31 | #define RTC_SECONDS 0x00 |
35 | 32 | #define RTC_SECONDS_ALARM 0x01 |
36 | 33 | |
... | ... | @@ -60,24 +57,24 @@ |
60 | 57 | { |
61 | 58 | uchar sec, min, hour, mday, wday, mon, year; |
62 | 59 | /* here check if rtc can be accessed */ |
63 | - while((rtc_read(RTC_CONFIG_A)&0x80)==0x80); | |
64 | - sec = rtc_read (RTC_SECONDS); | |
65 | - min = rtc_read (RTC_MINUTES); | |
66 | - hour = rtc_read (RTC_HOURS); | |
67 | - mday = rtc_read (RTC_DATE_OF_MONTH); | |
68 | - wday = rtc_read (RTC_DAY_OF_WEEK); | |
69 | - mon = rtc_read (RTC_MONTH); | |
70 | - year = rtc_read (RTC_YEAR); | |
60 | + while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80); | |
61 | + sec = rtc_read8(RTC_SECONDS); | |
62 | + min = rtc_read8(RTC_MINUTES); | |
63 | + hour = rtc_read8(RTC_HOURS); | |
64 | + mday = rtc_read8(RTC_DATE_OF_MONTH); | |
65 | + wday = rtc_read8(RTC_DAY_OF_WEEK); | |
66 | + mon = rtc_read8(RTC_MONTH); | |
67 | + year = rtc_read8(RTC_YEAR); | |
71 | 68 | #ifdef RTC_DEBUG |
72 | 69 | printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " |
73 | 70 | "hr: %02x min: %02x sec: %02x\n", |
74 | 71 | year, mon, mday, wday, |
75 | 72 | hour, min, sec ); |
76 | 73 | printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", |
77 | - rtc_read (RTC_CONFIG_D) & 0x3F, | |
78 | - rtc_read (RTC_HOURS_ALARM), | |
79 | - rtc_read (RTC_MINUTES_ALARM), | |
80 | - rtc_read (RTC_SECONDS_ALARM) ); | |
74 | + rtc_read8(RTC_CONFIG_D) & 0x3F, | |
75 | + rtc_read8(RTC_HOURS_ALARM), | |
76 | + rtc_read8(RTC_MINUTES_ALARM), | |
77 | + rtc_read8(RTC_SECONDS_ALARM)); | |
81 | 78 | #endif |
82 | 79 | tmp->tm_sec = bcd2bin (sec & 0x7F); |
83 | 80 | tmp->tm_min = bcd2bin (min & 0x7F); |
84 | 81 | |
85 | 82 | |
86 | 83 | |
87 | 84 | |
88 | 85 | |
89 | 86 | |
90 | 87 | |
91 | 88 | |
92 | 89 | |
93 | 90 | |
94 | 91 | |
95 | 92 | |
96 | 93 | |
97 | 94 | |
98 | 95 | |
99 | 96 | |
100 | 97 | |
101 | 98 | |
102 | 99 | |
103 | 100 | |
... | ... | @@ -108,81 +105,109 @@ |
108 | 105 | tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, |
109 | 106 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); |
110 | 107 | #endif |
111 | - rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */ | |
108 | + rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ | |
112 | 109 | |
113 | - rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100)); | |
114 | - rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon)); | |
115 | - rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); | |
116 | - rtc_write (RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday)); | |
117 | - rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour)); | |
118 | - rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min )); | |
119 | - rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec )); | |
120 | - rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */ | |
110 | + rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100)); | |
111 | + rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon)); | |
112 | + rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); | |
113 | + rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday)); | |
114 | + rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour)); | |
115 | + rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min)); | |
116 | + rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec)); | |
117 | + rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */ | |
121 | 118 | |
122 | 119 | return 0; |
123 | 120 | } |
124 | 121 | |
125 | 122 | void rtc_reset (void) |
126 | 123 | { |
127 | - rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */ | |
128 | - rtc_write(RTC_CONFIG_A,0x20); /* Normal OP */ | |
129 | - rtc_write(RTC_CONFIG_B,0x00); | |
130 | - rtc_write(RTC_CONFIG_B,0x00); | |
131 | - rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */ | |
124 | + rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ | |
125 | + rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */ | |
126 | + rtc_write8(RTC_CONFIG_B, 0x00); | |
127 | + rtc_write8(RTC_CONFIG_B, 0x00); | |
128 | + rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */ | |
132 | 129 | } |
133 | 130 | |
134 | 131 | /* ------------------------------------------------------------------------- */ |
135 | 132 | |
136 | -#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR | |
137 | 133 | /* |
138 | 134 | * use direct memory access |
139 | 135 | */ |
140 | -static uchar rtc_read (uchar reg) | |
136 | +int rtc_read8(int reg) | |
141 | 137 | { |
138 | +#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR | |
142 | 139 | return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg); |
140 | +#else | |
141 | + int ofs = 0; | |
142 | + | |
143 | + if (reg >= 128) { | |
144 | + ofs = 2; | |
145 | + reg -= 128; | |
146 | + } | |
147 | + out8(RTC_PORT_MC146818 + ofs, reg); | |
148 | + | |
149 | + return in8(RTC_PORT_MC146818 + ofs + 1); | |
150 | +#endif | |
143 | 151 | } |
144 | 152 | |
145 | -static void rtc_write (uchar reg, uchar val) | |
153 | +void rtc_write8(int reg, uchar val) | |
146 | 154 | { |
155 | +#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR | |
147 | 156 | out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); |
148 | -} | |
149 | 157 | #else |
150 | -static uchar rtc_read (uchar reg) | |
158 | + int ofs = 0; | |
159 | + | |
160 | + if (reg >= 128) { | |
161 | + ofs = 2; | |
162 | + reg -= 128; | |
163 | + } | |
164 | + out8(RTC_PORT_MC146818 + ofs, reg); | |
165 | + out8(RTC_PORT_MC146818 + ofs + 1, val); | |
166 | +#endif | |
167 | +} | |
168 | + | |
169 | +u32 rtc_read32(int reg) | |
151 | 170 | { |
152 | - out8(RTC_PORT_MC146818,reg); | |
153 | - return in8(RTC_PORT_MC146818 + 1); | |
171 | + u32 value = 0; | |
172 | + int i; | |
173 | + | |
174 | + for (i = 0; i < sizeof(value); i++) | |
175 | + value |= rtc_read8(reg + i) << (i << 3); | |
176 | + | |
177 | + return value; | |
154 | 178 | } |
155 | 179 | |
156 | -static void rtc_write (uchar reg, uchar val) | |
180 | +void rtc_write32(int reg, u32 value) | |
157 | 181 | { |
158 | - out8(RTC_PORT_MC146818,reg); | |
159 | - out8(RTC_PORT_MC146818+1, val); | |
182 | + int i; | |
183 | + | |
184 | + for (i = 0; i < sizeof(value); i++) | |
185 | + rtc_write8(reg + i, (value >> (i << 3)) & 0xff); | |
160 | 186 | } |
161 | -#endif | |
162 | 187 | |
163 | 188 | void rtc_init(void) |
164 | 189 | { |
165 | 190 | #if CLEAR_CMOS |
166 | 191 | int i; |
167 | 192 | |
168 | - rtc_write(RTC_SECONDS_ALARM, 0); | |
169 | - rtc_write(RTC_MINUTES_ALARM, 0); | |
170 | - rtc_write(RTC_HOURS_ALARM, 0); | |
193 | + rtc_write8(RTC_SECONDS_ALARM, 0); | |
194 | + rtc_write8(RTC_MINUTES_ALARM, 0); | |
195 | + rtc_write8(RTC_HOURS_ALARM, 0); | |
171 | 196 | for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++) |
172 | - rtc_write(i, 0); | |
197 | + rtc_write8(i, 0); | |
173 | 198 | printf("RTC: zeroing CMOS RAM\n"); |
174 | 199 | #endif |
175 | 200 | |
176 | 201 | /* Setup the real time clock */ |
177 | - rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H); | |
202 | + rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H); | |
178 | 203 | /* Setup the frequency it operates at */ |
179 | - rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | | |
204 | + rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | | |
180 | 205 | RTC_CONFIG_A_RATE_1024HZ); |
181 | 206 | /* Ensure all reserved bits are 0 in register D */ |
182 | - rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); | |
207 | + rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); | |
183 | 208 | |
184 | 209 | /* Clear any pending interrupts */ |
185 | - rtc_read(RTC_CONFIG_C); | |
210 | + rtc_read8(RTC_CONFIG_C); | |
186 | 211 | } |
187 | 212 | #endif |
include/rtc.h
... | ... | @@ -51,6 +51,38 @@ |
51 | 51 | unsigned int, unsigned int, unsigned int); |
52 | 52 | |
53 | 53 | /** |
54 | + * rtc_read8() - Read an 8-bit register | |
55 | + * | |
56 | + * @reg: Register to read | |
57 | + * @return value read | |
58 | + */ | |
59 | +int rtc_read8(int reg); | |
60 | + | |
61 | +/** | |
62 | + * rtc_write8() - Write an 8-bit register | |
63 | + * | |
64 | + * @reg: Register to write | |
65 | + * @value: Value to write | |
66 | + */ | |
67 | +void rtc_write8(int reg, uchar val); | |
68 | + | |
69 | +/** | |
70 | + * rtc_read32() - Read a 32-bit value from the RTC | |
71 | + * | |
72 | + * @reg: Offset to start reading from | |
73 | + * @return value read | |
74 | + */ | |
75 | +u32 rtc_read32(int reg); | |
76 | + | |
77 | +/** | |
78 | + * rtc_write32() - Write a 32-bit value to the RTC | |
79 | + * | |
80 | + * @reg: Register to start writing to | |
81 | + * @value: Value to write | |
82 | + */ | |
83 | +void rtc_write32(int reg, u32 value); | |
84 | + | |
85 | +/** | |
54 | 86 | * rtc_init() - Set up the real time clock ready for use |
55 | 87 | */ |
56 | 88 | void rtc_init(void); |