]>
Commit | Line | Data |
---|---|---|
c7260d15 RM |
1 | /* |
2 | * (C) Copyright 2010 | |
3 | * Reinhard Meyer, reinhard.meyer@emk-elektronik.de | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
c7260d15 RM |
6 | */ |
7 | ||
8 | /* | |
9 | * Date & Time support for the internal Real-time Timer | |
10 | * of AT91SAM9260 and compatibles. | |
11 | * Compatible with the LinuX rtc driver workaround: | |
12 | * The RTT cannot be written to, but only reset. | |
13 | * The actual time is the sum of RTT and one of | |
14 | * the four GPBR registers. | |
15 | * | |
16 | * The at91sam9260 has 4 GPBR (0-3). | |
17 | * For their typical use see at91_gpbr.h ! | |
18 | * | |
19 | * make sure u-boot and kernel use the same GPBR ! | |
20 | */ | |
21 | ||
22 | #include <common.h> | |
23 | #include <command.h> | |
24 | #include <rtc.h> | |
86592f60 | 25 | #include <asm/io.h> |
1221ce45 | 26 | #include <linux/errno.h> |
c7260d15 | 27 | #include <asm/arch/hardware.h> |
c7260d15 RM |
28 | #include <asm/arch/at91_rtt.h> |
29 | #include <asm/arch/at91_gpbr.h> | |
30 | ||
31 | #if defined(CONFIG_CMD_DATE) | |
32 | ||
33 | int rtc_get (struct rtc_time *tmp) | |
34 | { | |
372f2783 RM |
35 | at91_rtt_t *rtt = (at91_rtt_t *) ATMEL_BASE_RTT; |
36 | at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR; | |
c7260d15 RM |
37 | ulong tim; |
38 | ulong tim2; | |
39 | ulong off; | |
40 | ||
41 | do { | |
42 | tim = readl(&rtt->vr); | |
43 | tim2 = readl(&rtt->vr); | |
44 | } while (tim!=tim2); | |
45 | off = readl(&gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); | |
46 | /* off==0 means time is invalid, but we ignore that */ | |
9f9276c3 | 47 | rtc_to_tm(tim+off, tmp); |
c7260d15 RM |
48 | return 0; |
49 | } | |
50 | ||
51 | int rtc_set (struct rtc_time *tmp) | |
52 | { | |
372f2783 RM |
53 | at91_rtt_t *rtt = (at91_rtt_t *) ATMEL_BASE_RTT; |
54 | at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR; | |
c7260d15 RM |
55 | ulong tim; |
56 | ||
71420983 | 57 | tim = rtc_mktime(tmp); |
c7260d15 RM |
58 | |
59 | /* clear alarm, set prescaler to 32768, clear counter */ | |
60 | writel(32768+AT91_RTT_RTTRST, &rtt->mr); | |
61 | writel(~0, &rtt->ar); | |
62 | writel(tim, &gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); | |
63 | /* wait for counter clear to happen, takes less than a 1/32768th second */ | |
64 | while (readl(&rtt->vr) != 0) | |
65 | ; | |
66 | return 0; | |
67 | } | |
68 | ||
69 | void rtc_reset (void) | |
70 | { | |
372f2783 RM |
71 | at91_rtt_t *rtt = (at91_rtt_t *) ATMEL_BASE_RTT; |
72 | at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR; | |
c7260d15 RM |
73 | |
74 | /* clear alarm, set prescaler to 32768, clear counter */ | |
75 | writel(32768+AT91_RTT_RTTRST, &rtt->mr); | |
76 | writel(~0, &rtt->ar); | |
77 | writel(0, &gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); | |
78 | /* wait for counter clear to happen, takes less than a 1/32768th second */ | |
79 | while (readl(&rtt->vr) != 0) | |
80 | ; | |
81 | } | |
82 | ||
83 | #endif |