1 /* 2 * (C) Copyright 2001 3 * Denis Peter MPL AG Switzerland. d.peter@mpl.ch 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 /* 9 * Date & Time support for the MC146818 (PIXX4) RTC 10 */ 11 12 /*#define DEBUG*/ 13 14 #include <common.h> 15 #include <command.h> 16 #include <rtc.h> 17 #include <version.h> 18 19 #if defined(__I386__) || defined(CONFIG_MALTA) 20 #include <asm/io.h> 21 #define in8(p) inb(p) 22 #define out8(p, v) outb(v, p) 23 #endif 24 25 #if defined(CONFIG_CMD_DATE) 26 27 /* Set this to 1 to clear the CMOS RAM */ 28 #define CLEAR_CMOS 0 29 30 #define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 31 #define RTC_SECONDS 0x00 32 #define RTC_SECONDS_ALARM 0x01 33 #define RTC_MINUTES 0x02 34 #define RTC_MINUTES_ALARM 0x03 35 #define RTC_HOURS 0x04 36 #define RTC_HOURS_ALARM 0x05 37 #define RTC_DAY_OF_WEEK 0x06 38 #define RTC_DATE_OF_MONTH 0x07 39 #define RTC_MONTH 0x08 40 #define RTC_YEAR 0x09 41 #define RTC_CONFIG_A 0x0A 42 #define RTC_CONFIG_B 0x0B 43 #define RTC_CONFIG_C 0x0C 44 #define RTC_CONFIG_D 0x0D 45 #define RTC_REG_SIZE 0x80 46 47 #define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) 48 #define RTC_CONFIG_A_RATE_1024HZ 6 49 50 #define RTC_CONFIG_B_24H (1 << 1) 51 52 #define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80 53 54 /* ------------------------------------------------------------------------- */ 55 56 int rtc_get (struct rtc_time *tmp) 57 { 58 uchar sec, min, hour, mday, wday, mon, year; 59 /* here check if rtc can be accessed */ 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); 68 #ifdef RTC_DEBUG 69 printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " 70 "hr: %02x min: %02x sec: %02x\n", 71 year, mon, mday, wday, 72 hour, min, sec ); 73 printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", 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)); 78 #endif 79 tmp->tm_sec = bcd2bin (sec & 0x7F); 80 tmp->tm_min = bcd2bin (min & 0x7F); 81 tmp->tm_hour = bcd2bin (hour & 0x3F); 82 tmp->tm_mday = bcd2bin (mday & 0x3F); 83 tmp->tm_mon = bcd2bin (mon & 0x1F); 84 tmp->tm_year = bcd2bin (year); 85 tmp->tm_wday = bcd2bin (wday & 0x07); 86 if(tmp->tm_year<70) 87 tmp->tm_year+=2000; 88 else 89 tmp->tm_year+=1900; 90 tmp->tm_yday = 0; 91 tmp->tm_isdst= 0; 92 #ifdef RTC_DEBUG 93 printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 94 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 95 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 96 #endif 97 98 return 0; 99 } 100 101 int rtc_set (struct rtc_time *tmp) 102 { 103 #ifdef RTC_DEBUG 104 printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 105 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 106 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 107 #endif 108 rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ 109 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 */ 118 119 return 0; 120 } 121 122 void rtc_reset (void) 123 { 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 */ 129 } 130 131 /* ------------------------------------------------------------------------- */ 132 133 /* 134 * use direct memory access 135 */ 136 int rtc_read8(int reg) 137 { 138 #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR 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 151 } 152 153 void rtc_write8(int reg, uchar val) 154 { 155 #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR 156 out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); 157 #else 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) 170 { 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; 178 } 179 180 void rtc_write32(int reg, u32 value) 181 { 182 int i; 183 184 for (i = 0; i < sizeof(value); i++) 185 rtc_write8(reg + i, (value >> (i << 3)) & 0xff); 186 } 187 188 void rtc_init(void) 189 { 190 #if CLEAR_CMOS 191 int i; 192 193 rtc_write8(RTC_SECONDS_ALARM, 0); 194 rtc_write8(RTC_MINUTES_ALARM, 0); 195 rtc_write8(RTC_HOURS_ALARM, 0); 196 for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++) 197 rtc_write8(i, 0); 198 printf("RTC: zeroing CMOS RAM\n"); 199 #endif 200 201 /* Setup the real time clock */ 202 rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H); 203 /* Setup the frequency it operates at */ 204 rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | 205 RTC_CONFIG_A_RATE_1024HZ); 206 /* Ensure all reserved bits are 0 in register D */ 207 rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); 208 209 /* Clear any pending interrupts */ 210 rtc_read8(RTC_CONFIG_C); 211 } 212 #endif 213