Blame view

bootloader/u-boot_2015_04/drivers/rtc/mpc5xxx.c 3.76 KB
6b13f685e   김민수   BSP 최초 추가
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
  /*
   * (C) Copyright 2004
   * Reinhard Meyer, EMK Elektronik GmbH
   * r.meyer@emk-elektronik.de
   * www.emk-elektronik.de
   *
   * SPDX-License-Identifier:	GPL-2.0+
   */
  
  /*****************************************************************************
   * Date & Time support for internal RTC of MPC52xx
   *****************************************************************************/
  /*#define	DEBUG*/
  
  #include <common.h>
  #include <command.h>
  #include <rtc.h>
  
  #if defined(CONFIG_CMD_DATE)
  
  /*****************************************************************************
   * this structure should be defined in mpc5200.h ...
   *****************************************************************************/
  typedef struct rtc5200 {
  	volatile ulong	tsr;	/* MBAR+0x800: time set register */
  	volatile ulong	dsr;	/* MBAR+0x804: data set register */
  	volatile ulong	nysr;	/* MBAR+0x808: new year and stopwatch register */
  	volatile ulong	aier;	/* MBAR+0x80C: alarm and interrupt enable register */
  	volatile ulong	ctr;	/* MBAR+0x810: current time register */
  	volatile ulong	cdr;	/* MBAR+0x814: current data register */
  	volatile ulong	asir;	/* MBAR+0x818: alarm and stopwatch interrupt register */
  	volatile ulong	piber;	/* MBAR+0x81C: periodic interrupt and bus error register */
  	volatile ulong	trdr;	/* MBAR+0x820: test register/divides register */
  } RTC5200;
  
  #define	RTC_SET		0x02000000
  #define	RTC_PAUSE	0x01000000
  
  /*****************************************************************************
   * get time
   *****************************************************************************/
  int rtc_get (struct rtc_time *tmp)
  {
  	RTC5200	*rtc = (RTC5200 *) (CONFIG_SYS_MBAR+0x800);
  	ulong time, date, time2;
  
  	/* read twice to avoid getting a funny time when the second is just changing */
  	do {
  		time = rtc->ctr;
  		date = rtc->cdr;
  		time2 = rtc->ctr;
  	} while (time != time2);
  
  	tmp->tm_year	= date & 0xfff;
  	tmp->tm_mon		= (date >> 24) & 0xf;
  	tmp->tm_mday	= (date >> 16) & 0x1f;
  	tmp->tm_wday	= (date >> 21) & 7;
  	/* sunday is 7 in 5200 but 0 in rtc_time */
  	if (tmp->tm_wday == 7)
  		tmp->tm_wday = 0;
  	tmp->tm_hour	= (time >> 16) & 0x1f;
  	tmp->tm_min		= (time >> 8) & 0x3f;
  	tmp->tm_sec		= time & 0x3f;
  
  	debug ( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d
  ",
  		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
  		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  
  	return 0;
  }
  
  /*****************************************************************************
   * set time
   *****************************************************************************/
  int rtc_set (struct rtc_time *tmp)
  {
  	RTC5200	*rtc = (RTC5200 *) (CONFIG_SYS_MBAR+0x800);
  	ulong time, date, year;
  
  	debug ( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d
  ",
  		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
  		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  
  	time = (tmp->tm_hour << 16) | (tmp->tm_min << 8) | tmp->tm_sec;
  	date = (tmp->tm_mon << 16) | tmp->tm_mday;
  	if (tmp->tm_wday == 0)
  		date |= (7 << 8);
  	else
  		date |= (tmp->tm_wday << 8);
  	year = tmp->tm_year;
  
  	/* mask unwanted bits that might show up when rtc_time is corrupt */
  	time &= 0x001f3f3f;
  	date &= 0x001f071f;
  	year &= 0x00000fff;
  
  	/* pause and set the RTC */
  	rtc->nysr = year;
  	rtc->dsr = date | RTC_PAUSE;
  	udelay (1000);
  	rtc->dsr = date | RTC_PAUSE | RTC_SET;
  	udelay (1000);
  	rtc->dsr = date | RTC_PAUSE;
  	udelay (1000);
  	rtc->dsr = date;
  	udelay (1000);
  
  	rtc->tsr = time | RTC_PAUSE;
  	udelay (1000);
  	rtc->tsr = time | RTC_PAUSE | RTC_SET;
  	udelay (1000);
  	rtc->tsr = time | RTC_PAUSE;
  	udelay (1000);
  	rtc->tsr = time;
  	udelay (1000);
  
  	return 0;
  }
  
  /*****************************************************************************
   * reset rtc circuit
   *****************************************************************************/
  void rtc_reset (void)
  {
  	return;	/* nothing to do */
  }
  
  #endif