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