summaryrefslogtreecommitdiffstats
path: root/rtc/bf5xx_rtc.c
blob: 85bbb56e3960cb51e9e98fe5301399ab1ad2e369 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * (C) Copyright 2001
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 * Real Time Clock interface of ADI21535 (Blackfin) for uCLinux
 *
 * Copyright (C) 2003 Motorola Corporation.  All rights reserved.
 * 				Richard Xiao (A2590C@email.mot.com)
 *
 * Copyright (C) 1996 Paul Gortmaker
 *
 *
 *	Based on other minimal char device drivers, like Alan's
 *	watchdog, Ted's random, etc. etc.
 *
 *	1.07	Paul Gortmaker.
 *	1.08	Miquel van Smoorenburg: disallow certain things on the
 *		DEC Alpha as the CMOS clock is also used for other things.
 *	1.09	Nikita Schmidt: epoch support and some Alpha cleanup.
 *	1.09a	Pete Zaitcev: Sun SPARC
 *	1.09b	Jeff Garzik: Modularize, init cleanup
 *	1.09c	Jeff Garzik: SMP cleanup
 *	1.10    Paul Barton-Davis: add support for async I/O
 *	1.10a	Andrea Arcangeli: Alpha updates
 *	1.10b	Andrew Morton: SMP lock fix
 *	1.10c	Cesar Barros: SMP locking fixes and cleanup
 *	1.10d	Paul Gortmaker: delete paranoia check in rtc_exit
 *	1.10e   LG Soft India: Register access is different in BF533.
 */

#include <common.h>
#include <command.h>
#include <rtc.h>

#if defined(CONFIG_RTC_BFIN) && (CONFIG_COMMANDS & CFG_CMD_DATE)

#include <asm/blackfin.h>
#include <asm/arch/bf5xx_rtc.h>

void rtc_reset(void)
{
	return;			/* nothing to do */
}

/* Wait for pending writes to complete */
void wait_for_complete(void)
{
	while (!(*(volatile unsigned short *)RTC_ISTAT & 0x8000)) {
		printf("");
	}
	*(volatile unsigned short *)RTC_ISTAT = 0x8000;
}

/* Enable the RTC prescaler enable register */
void rtc_init()
{
	*(volatile unsigned short *)RTC_PREN = 0x1;
	wait_for_complete();
}

/* Set the time. Get the time_in_secs which is the number of seconds since Jan 1970 and set the RTC registers
 * based on this value.
 */
void rtc_set(struct rtc_time *tmp)
{
	unsigned long n_days_1970 = 0;
	unsigned long n_secs_rem = 0;
	unsigned long n_hrs = 0;
	unsigned long n_mins = 0;
	unsigned long n_secs = 0;
	unsigned long time_in_secs;

	if (tmp == NULL) {
		printf("Error setting the date/time \n");
		return;
	}

	time_in_secs =
	    mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour,
		   tmp->tm_min, tmp->tm_sec);

	/* Compute no. of days since 1970 */
	n_days_1970 = (unsigned long)(time_in_secs / (NUM_SECS_IN_DAY));

	/* From the remining secs, compute the hrs(0-23), mins(0-59) and secs(0-59) */
	n_secs_rem = (unsigned long)(time_in_secs % (NUM_SECS_IN_DAY));
	n_hrs = n_secs_rem / (NUM_SECS_IN_HOUR);
	n_secs_rem = n_secs_rem % (NUM_SECS_IN_HOUR);
	n_mins = n_secs_rem / (NUM_SECS_IN_MIN);
	n_secs = n_secs_rem % (NUM_SECS_IN_MIN);

	/* Store the new time in the RTC_STAT register */
	*(volatile unsigned long *)RTC_STAT =
	    ((n_days_1970 << DAY_BITS_OFF) | (n_hrs << HOUR_BITS_OFF) |
	     (n_mins << MIN_BITS_OFF) | (n_secs << SEC_BITS_OFF));

	wait_for_complete();
}

/* Read the time from the RTC_STAT. time_in_seconds is seconds since Jan 1970 */
void rtc_get(struct rtc_time *tmp)
{
	unsigned long cur_rtc_stat = 0;
	unsigned long time_in_sec;
	unsigned long tm_sec = 0, tm_min = 0, tm_hour = 0, tm_day = 0;

	if (tmp == NULL) {
		printf("Error getting the date/time \n");
		return;
	}

	/* Read the RTC_STAT register */
	cur_rtc_stat = *(volatile unsigned long *)RTC_STAT;

	/* Get the secs (0-59), mins (0-59), hrs (0-23) and the days since Jan 1970 */
	tm_sec = (cur_rtc_stat >> SEC_BITS_OFF) & 0x3f;
	tm_min = (cur_rtc_stat >> MIN_BITS_OFF) & 0x3f;
	tm_hour = (cur_rtc_stat >> HOUR_BITS_OFF) & 0x1f;
	tm_day = (cur_rtc_stat >> DAY_BITS_OFF) & 0x7fff;

	/* Calculate the total number of seconds since Jan 1970 */
	time_in_sec = (tm_sec) +
	    MIN_TO_SECS(tm_min) + HRS_TO_SECS(tm_hour) + DAYS_TO_SECS(tm_day);
	to_tm(time_in_sec, tmp);
}
#endif				/* CONFIG_RTC_BFIN && CFG_CMD_DATE */