1*b608b957SJason Cooper /* 2*b608b957SJason Cooper * Copyright (C) 2011 3*b608b957SJason Cooper * Jason Cooper <u-boot@lakedaemon.net> 4*b608b957SJason Cooper * 5*b608b957SJason Cooper * See file CREDITS for list of people who contributed to this 6*b608b957SJason Cooper * project. 7*b608b957SJason Cooper * 8*b608b957SJason Cooper * This program is free software; you can redistribute it and/or 9*b608b957SJason Cooper * modify it under the terms of the GNU General Public License as 10*b608b957SJason Cooper * published by the Free Software Foundation; either version 2 of 11*b608b957SJason Cooper * the License, or (at your option) any later version. 12*b608b957SJason Cooper * 13*b608b957SJason Cooper * This program is distributed in the hope that it will be useful, 14*b608b957SJason Cooper * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*b608b957SJason Cooper * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*b608b957SJason Cooper * GNU General Public License for more details. 17*b608b957SJason Cooper * 18*b608b957SJason Cooper * You should have received a copy of the GNU General Public License 19*b608b957SJason Cooper * along with this program; if not, write to the Free Software 20*b608b957SJason Cooper * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*b608b957SJason Cooper * MA 02111-1307 USA 22*b608b957SJason Cooper */ 23*b608b957SJason Cooper 24*b608b957SJason Cooper /* 25*b608b957SJason Cooper * Date & Time support for Marvell Integrated RTC 26*b608b957SJason Cooper */ 27*b608b957SJason Cooper 28*b608b957SJason Cooper #include <common.h> 29*b608b957SJason Cooper #include <command.h> 30*b608b957SJason Cooper #include <rtc.h> 31*b608b957SJason Cooper #include "mvrtc.h" 32*b608b957SJason Cooper 33*b608b957SJason Cooper /* This RTC does not support century, so we assume 20 */ 34*b608b957SJason Cooper #define CENTURY 20 35*b608b957SJason Cooper 36*b608b957SJason Cooper int rtc_get(struct rtc_time *t) 37*b608b957SJason Cooper { 38*b608b957SJason Cooper u32 time; 39*b608b957SJason Cooper u32 date; 40*b608b957SJason Cooper struct mvrtc_registers *mvrtc_regs; 41*b608b957SJason Cooper 42*b608b957SJason Cooper mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; 43*b608b957SJason Cooper 44*b608b957SJason Cooper /* read the time register */ 45*b608b957SJason Cooper time = readl(&mvrtc_regs->time); 46*b608b957SJason Cooper 47*b608b957SJason Cooper /* read the date register */ 48*b608b957SJason Cooper date = readl(&mvrtc_regs->date); 49*b608b957SJason Cooper 50*b608b957SJason Cooper /* test for 12 hour clock (can't tell if it's am/pm) */ 51*b608b957SJason Cooper if (time & MVRTC_HRFMT_MSK) { 52*b608b957SJason Cooper printf("Error: RTC in 12 hour mode, can't determine AM/PM.\n"); 53*b608b957SJason Cooper return -1; 54*b608b957SJason Cooper } 55*b608b957SJason Cooper 56*b608b957SJason Cooper /* time */ 57*b608b957SJason Cooper t->tm_sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK); 58*b608b957SJason Cooper t->tm_min = bcd2bin((time >> MVRTC_MIN_SFT) & MVRTC_MIN_MSK); 59*b608b957SJason Cooper t->tm_hour = bcd2bin((time >> MVRTC_HOUR_SFT) & MVRTC_HOUR_MSK); 60*b608b957SJason Cooper t->tm_wday = bcd2bin((time >> MVRTC_DAY_SFT) & MVRTC_DAY_MSK); 61*b608b957SJason Cooper t->tm_wday--; 62*b608b957SJason Cooper 63*b608b957SJason Cooper /* date */ 64*b608b957SJason Cooper t->tm_mday = bcd2bin((date >> MVRTC_DATE_SFT) & MVRTC_DATE_MSK); 65*b608b957SJason Cooper t->tm_mon = bcd2bin((date >> MVRTC_MON_SFT) & MVRTC_MON_MSK); 66*b608b957SJason Cooper t->tm_year = bcd2bin((date >> MVRTC_YEAR_SFT) & MVRTC_YEAR_MSK); 67*b608b957SJason Cooper t->tm_year += CENTURY * 100; 68*b608b957SJason Cooper 69*b608b957SJason Cooper /* not supported in this RTC */ 70*b608b957SJason Cooper t->tm_yday = 0; 71*b608b957SJason Cooper t->tm_isdst = 0; 72*b608b957SJason Cooper 73*b608b957SJason Cooper return 0; 74*b608b957SJason Cooper } 75*b608b957SJason Cooper 76*b608b957SJason Cooper int rtc_set(struct rtc_time *t) 77*b608b957SJason Cooper { 78*b608b957SJason Cooper u32 time = 0; /* sets hour format bit to zero, 24hr format. */ 79*b608b957SJason Cooper u32 date = 0; 80*b608b957SJason Cooper struct mvrtc_registers *mvrtc_regs; 81*b608b957SJason Cooper 82*b608b957SJason Cooper mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; 83*b608b957SJason Cooper 84*b608b957SJason Cooper /* check that this code isn't 80+ years old ;-) */ 85*b608b957SJason Cooper if ((t->tm_year / 100) != CENTURY) 86*b608b957SJason Cooper printf("Warning: Only century %d supported.\n", CENTURY); 87*b608b957SJason Cooper 88*b608b957SJason Cooper /* time */ 89*b608b957SJason Cooper time |= (bin2bcd(t->tm_sec) & MVRTC_SEC_MSK) << MVRTC_SEC_SFT; 90*b608b957SJason Cooper time |= (bin2bcd(t->tm_min) & MVRTC_MIN_MSK) << MVRTC_MIN_SFT; 91*b608b957SJason Cooper time |= (bin2bcd(t->tm_hour) & MVRTC_HOUR_MSK) << MVRTC_HOUR_SFT; 92*b608b957SJason Cooper time |= (bin2bcd(t->tm_wday + 1) & MVRTC_DAY_MSK) << MVRTC_DAY_SFT; 93*b608b957SJason Cooper 94*b608b957SJason Cooper /* date */ 95*b608b957SJason Cooper date |= (bin2bcd(t->tm_mday) & MVRTC_DATE_MSK) << MVRTC_DATE_SFT; 96*b608b957SJason Cooper date |= (bin2bcd(t->tm_mon) & MVRTC_MON_MSK) << MVRTC_MON_SFT; 97*b608b957SJason Cooper date |= (bin2bcd(t->tm_year % 100) & MVRTC_YEAR_MSK) << MVRTC_YEAR_SFT; 98*b608b957SJason Cooper 99*b608b957SJason Cooper /* write the time register */ 100*b608b957SJason Cooper writel(time, &mvrtc_regs->time); 101*b608b957SJason Cooper 102*b608b957SJason Cooper /* write the date register */ 103*b608b957SJason Cooper writel(date, &mvrtc_regs->date); 104*b608b957SJason Cooper 105*b608b957SJason Cooper return 0; 106*b608b957SJason Cooper } 107*b608b957SJason Cooper 108*b608b957SJason Cooper void rtc_reset(void) 109*b608b957SJason Cooper { 110*b608b957SJason Cooper u32 time; 111*b608b957SJason Cooper u32 sec; 112*b608b957SJason Cooper struct mvrtc_registers *mvrtc_regs; 113*b608b957SJason Cooper 114*b608b957SJason Cooper mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; 115*b608b957SJason Cooper 116*b608b957SJason Cooper /* no init routine for this RTC needed, just check that it's working */ 117*b608b957SJason Cooper time = readl(&mvrtc_regs->time); 118*b608b957SJason Cooper sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK); 119*b608b957SJason Cooper udelay(1000000); 120*b608b957SJason Cooper time = readl(&mvrtc_regs->time); 121*b608b957SJason Cooper 122*b608b957SJason Cooper if (sec == bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK)) 123*b608b957SJason Cooper printf("Error: RTC did not increment.\n"); 124*b608b957SJason Cooper } 125