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 static uchar rtc_read (uchar reg); 31 static void rtc_write (uchar reg, uchar val); 32 33 #define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 34 #define RTC_SECONDS 0x00 35 #define RTC_SECONDS_ALARM 0x01 36 #define RTC_MINUTES 0x02 37 #define RTC_MINUTES_ALARM 0x03 38 #define RTC_HOURS 0x04 39 #define RTC_HOURS_ALARM 0x05 40 #define RTC_DAY_OF_WEEK 0x06 41 #define RTC_DATE_OF_MONTH 0x07 42 #define RTC_MONTH 0x08 43 #define RTC_YEAR 0x09 44 #define RTC_CONFIG_A 0x0A 45 #define RTC_CONFIG_B 0x0B 46 #define RTC_CONFIG_C 0x0C 47 #define RTC_CONFIG_D 0x0D 48 #define RTC_REG_SIZE 0x80 49 50 #define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) 51 #define RTC_CONFIG_A_RATE_1024HZ 6 52 53 #define RTC_CONFIG_B_24H (1 << 1) 54 55 #define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80 56 57 /* ------------------------------------------------------------------------- */ 58 59 int rtc_get (struct rtc_time *tmp) 60 { 61 uchar sec, min, hour, mday, wday, mon, year; 62 /* 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); 71 #ifdef RTC_DEBUG 72 printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " 73 "hr: %02x min: %02x sec: %02x\n", 74 year, mon, mday, wday, 75 hour, min, sec ); 76 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) ); 81 #endif 82 tmp->tm_sec = bcd2bin (sec & 0x7F); 83 tmp->tm_min = bcd2bin (min & 0x7F); 84 tmp->tm_hour = bcd2bin (hour & 0x3F); 85 tmp->tm_mday = bcd2bin (mday & 0x3F); 86 tmp->tm_mon = bcd2bin (mon & 0x1F); 87 tmp->tm_year = bcd2bin (year); 88 tmp->tm_wday = bcd2bin (wday & 0x07); 89 if(tmp->tm_year<70) 90 tmp->tm_year+=2000; 91 else 92 tmp->tm_year+=1900; 93 tmp->tm_yday = 0; 94 tmp->tm_isdst= 0; 95 #ifdef RTC_DEBUG 96 printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 97 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 98 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 99 #endif 100 101 return 0; 102 } 103 104 int rtc_set (struct rtc_time *tmp) 105 { 106 #ifdef RTC_DEBUG 107 printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 108 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 109 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 110 #endif 111 rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */ 112 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 */ 121 122 return 0; 123 } 124 125 void rtc_reset (void) 126 { 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 */ 132 } 133 134 /* ------------------------------------------------------------------------- */ 135 136 #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR 137 /* 138 * use direct memory access 139 */ 140 static uchar rtc_read (uchar reg) 141 { 142 return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg); 143 } 144 145 static void rtc_write (uchar reg, uchar val) 146 { 147 out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); 148 } 149 #else 150 static uchar rtc_read (uchar reg) 151 { 152 out8(RTC_PORT_MC146818,reg); 153 return in8(RTC_PORT_MC146818 + 1); 154 } 155 156 static void rtc_write (uchar reg, uchar val) 157 { 158 out8(RTC_PORT_MC146818,reg); 159 out8(RTC_PORT_MC146818+1, val); 160 } 161 #endif 162 163 void rtc_init(void) 164 { 165 #if CLEAR_CMOS 166 int i; 167 168 rtc_write(RTC_SECONDS_ALARM, 0); 169 rtc_write(RTC_MINUTES_ALARM, 0); 170 rtc_write(RTC_HOURS_ALARM, 0); 171 for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++) 172 rtc_write(i, 0); 173 printf("RTC: zeroing CMOS RAM\n"); 174 #endif 175 176 /* Setup the real time clock */ 177 rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H); 178 /* Setup the frequency it operates at */ 179 rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | 180 RTC_CONFIG_A_RATE_1024HZ); 181 /* Ensure all reserved bits are 0 in register D */ 182 rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); 183 184 /* Clear any pending interrupts */ 185 rtc_read(RTC_CONFIG_C); 186 } 187 #endif 188