1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (C) 2011 3*4882a593Smuzhiyun * Jason Cooper <u-boot@lakedaemon.net> 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun /* 9*4882a593Smuzhiyun * Date & Time support for Marvell Integrated RTC 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <common.h> 13*4882a593Smuzhiyun #include <command.h> 14*4882a593Smuzhiyun #include <rtc.h> 15*4882a593Smuzhiyun #include <asm/io.h> 16*4882a593Smuzhiyun #include "mvrtc.h" 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun /* This RTC does not support century, so we assume 20 */ 19*4882a593Smuzhiyun #define CENTURY 20 20*4882a593Smuzhiyun rtc_get(struct rtc_time * t)21*4882a593Smuzhiyunint rtc_get(struct rtc_time *t) 22*4882a593Smuzhiyun { 23*4882a593Smuzhiyun u32 time; 24*4882a593Smuzhiyun u32 date; 25*4882a593Smuzhiyun struct mvrtc_registers *mvrtc_regs; 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun /* read the time register */ 30*4882a593Smuzhiyun time = readl(&mvrtc_regs->time); 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun /* read the date register */ 33*4882a593Smuzhiyun date = readl(&mvrtc_regs->date); 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun /* test for 12 hour clock (can't tell if it's am/pm) */ 36*4882a593Smuzhiyun if (time & MVRTC_HRFMT_MSK) { 37*4882a593Smuzhiyun printf("Error: RTC in 12 hour mode, can't determine AM/PM.\n"); 38*4882a593Smuzhiyun return -1; 39*4882a593Smuzhiyun } 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun /* time */ 42*4882a593Smuzhiyun t->tm_sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK); 43*4882a593Smuzhiyun t->tm_min = bcd2bin((time >> MVRTC_MIN_SFT) & MVRTC_MIN_MSK); 44*4882a593Smuzhiyun t->tm_hour = bcd2bin((time >> MVRTC_HOUR_SFT) & MVRTC_HOUR_MSK); 45*4882a593Smuzhiyun t->tm_wday = bcd2bin((time >> MVRTC_DAY_SFT) & MVRTC_DAY_MSK); 46*4882a593Smuzhiyun t->tm_wday--; 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun /* date */ 49*4882a593Smuzhiyun t->tm_mday = bcd2bin((date >> MVRTC_DATE_SFT) & MVRTC_DATE_MSK); 50*4882a593Smuzhiyun t->tm_mon = bcd2bin((date >> MVRTC_MON_SFT) & MVRTC_MON_MSK); 51*4882a593Smuzhiyun t->tm_year = bcd2bin((date >> MVRTC_YEAR_SFT) & MVRTC_YEAR_MSK); 52*4882a593Smuzhiyun t->tm_year += CENTURY * 100; 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun /* not supported in this RTC */ 55*4882a593Smuzhiyun t->tm_yday = 0; 56*4882a593Smuzhiyun t->tm_isdst = 0; 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun return 0; 59*4882a593Smuzhiyun } 60*4882a593Smuzhiyun rtc_set(struct rtc_time * t)61*4882a593Smuzhiyunint rtc_set(struct rtc_time *t) 62*4882a593Smuzhiyun { 63*4882a593Smuzhiyun u32 time = 0; /* sets hour format bit to zero, 24hr format. */ 64*4882a593Smuzhiyun u32 date = 0; 65*4882a593Smuzhiyun struct mvrtc_registers *mvrtc_regs; 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun /* check that this code isn't 80+ years old ;-) */ 70*4882a593Smuzhiyun if ((t->tm_year / 100) != CENTURY) 71*4882a593Smuzhiyun printf("Warning: Only century %d supported.\n", CENTURY); 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun /* time */ 74*4882a593Smuzhiyun time |= (bin2bcd(t->tm_sec) & MVRTC_SEC_MSK) << MVRTC_SEC_SFT; 75*4882a593Smuzhiyun time |= (bin2bcd(t->tm_min) & MVRTC_MIN_MSK) << MVRTC_MIN_SFT; 76*4882a593Smuzhiyun time |= (bin2bcd(t->tm_hour) & MVRTC_HOUR_MSK) << MVRTC_HOUR_SFT; 77*4882a593Smuzhiyun time |= (bin2bcd(t->tm_wday + 1) & MVRTC_DAY_MSK) << MVRTC_DAY_SFT; 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun /* date */ 80*4882a593Smuzhiyun date |= (bin2bcd(t->tm_mday) & MVRTC_DATE_MSK) << MVRTC_DATE_SFT; 81*4882a593Smuzhiyun date |= (bin2bcd(t->tm_mon) & MVRTC_MON_MSK) << MVRTC_MON_SFT; 82*4882a593Smuzhiyun date |= (bin2bcd(t->tm_year % 100) & MVRTC_YEAR_MSK) << MVRTC_YEAR_SFT; 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun /* write the time register */ 85*4882a593Smuzhiyun writel(time, &mvrtc_regs->time); 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* write the date register */ 88*4882a593Smuzhiyun writel(date, &mvrtc_regs->date); 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun return 0; 91*4882a593Smuzhiyun } 92*4882a593Smuzhiyun rtc_reset(void)93*4882a593Smuzhiyunvoid rtc_reset(void) 94*4882a593Smuzhiyun { 95*4882a593Smuzhiyun u32 time; 96*4882a593Smuzhiyun u32 sec; 97*4882a593Smuzhiyun struct mvrtc_registers *mvrtc_regs; 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun /* no init routine for this RTC needed, just check that it's working */ 102*4882a593Smuzhiyun time = readl(&mvrtc_regs->time); 103*4882a593Smuzhiyun sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK); 104*4882a593Smuzhiyun udelay(1000000); 105*4882a593Smuzhiyun time = readl(&mvrtc_regs->time); 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun if (sec == bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK)) 108*4882a593Smuzhiyun printf("Error: RTC did not increment.\n"); 109*4882a593Smuzhiyun } 110