uboot/drivers/rtc/ds1374.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001, 2002, 2003
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 * Keith Outwater, keith_outwater@mvis.com`
   6 * Steven Scholz, steven.scholz@imc-berlin.de
   7 */
   8
   9/*
  10 * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
  11 * DS1374 Real Time Clock (RTC).
  12 *
  13 * based on ds1337.c
  14 */
  15
  16#include <common.h>
  17#include <command.h>
  18#include <rtc.h>
  19#include <i2c.h>
  20
  21/*---------------------------------------------------------------------*/
  22#undef DEBUG_RTC
  23#define DEBUG_RTC
  24
  25#ifdef DEBUG_RTC
  26#define DEBUGR(fmt,args...) printf(fmt ,##args)
  27#else
  28#define DEBUGR(fmt,args...)
  29#endif
  30/*---------------------------------------------------------------------*/
  31
  32#ifndef CFG_SYS_I2C_RTC_ADDR
  33# define CFG_SYS_I2C_RTC_ADDR   0x68
  34#endif
  35
  36#if defined(CONFIG_RTC_DS1374) && (CONFIG_SYS_I2C_SPEED > 400000)
  37# error The DS1374 is specified up to 400kHz in fast mode!
  38#endif
  39
  40/*
  41 * RTC register addresses
  42 */
  43#define RTC_TOD_CNT_BYTE0_ADDR          0x00 /* TimeOfDay */
  44#define RTC_TOD_CNT_BYTE1_ADDR          0x01
  45#define RTC_TOD_CNT_BYTE2_ADDR          0x02
  46#define RTC_TOD_CNT_BYTE3_ADDR          0x03
  47
  48#define RTC_WD_ALM_CNT_BYTE0_ADDR       0x04
  49#define RTC_WD_ALM_CNT_BYTE1_ADDR       0x05
  50#define RTC_WD_ALM_CNT_BYTE2_ADDR       0x06
  51
  52#define RTC_CTL_ADDR                    0x07 /* RTC-CoNTrol-register */
  53#define RTC_SR_ADDR                     0x08 /* RTC-StatusRegister */
  54#define RTC_TCS_DS_ADDR                 0x09 /* RTC-TrickleChargeSelect DiodeSelect-register */
  55
  56#define RTC_CTL_BIT_AIE                 (1<<0) /* Bit 0 - Alarm Interrupt enable */
  57#define RTC_CTL_BIT_RS1                 (1<<1) /* Bit 1/2 - Rate Select square wave output */
  58#define RTC_CTL_BIT_RS2                 (1<<2) /* Bit 2/2 - Rate Select square wave output */
  59#define RTC_CTL_BIT_WDSTR               (1<<3) /* Bit 3 - Watchdog Reset Steering */
  60#define RTC_CTL_BIT_BBSQW               (1<<4) /* Bit 4 - Battery-Backed Square-Wave */
  61#define RTC_CTL_BIT_WD_ALM              (1<<5) /* Bit 5 - Watchdog/Alarm Counter Select */
  62#define RTC_CTL_BIT_WACE                (1<<6) /* Bit 6 - Watchdog/Alarm Counter Enable WACE*/
  63#define RTC_CTL_BIT_EN_OSC              (1<<7) /* Bit 7 - Enable Oscilator */
  64
  65#define RTC_SR_BIT_AF                   0x01 /* Bit 0 = Alarm Flag */
  66#define RTC_SR_BIT_OSF                  0x80 /* Bit 7 - Osc Stop Flag */
  67
  68const char RtcTodAddr[] = {
  69        RTC_TOD_CNT_BYTE0_ADDR,
  70        RTC_TOD_CNT_BYTE1_ADDR,
  71        RTC_TOD_CNT_BYTE2_ADDR,
  72        RTC_TOD_CNT_BYTE3_ADDR
  73};
  74
  75static uchar rtc_read (uchar reg);
  76static void rtc_write(uchar reg, uchar val, bool set);
  77static void rtc_write_raw (uchar reg, uchar val);
  78
  79/*
  80 * Get the current time from the RTC
  81 */
  82int rtc_get (struct rtc_time *tm){
  83        int rel = 0;
  84        unsigned long time1, time2;
  85        unsigned int limit;
  86        unsigned char tmp;
  87        unsigned int i;
  88
  89        /*
  90         * Since the reads are being performed one byte at a time,
  91         * there is a chance that a carry will occur during the read.
  92         * To detect this, 2 reads are performed and compared.
  93         */
  94        limit = 10;
  95        do {
  96                i = 4;
  97                time1 = 0;
  98                while (i--) {
  99                        tmp = rtc_read(RtcTodAddr[i]);
 100                        time1 = (time1 << 8) | (tmp & 0xff);
 101                }
 102
 103                i = 4;
 104                time2 = 0;
 105                while (i--) {
 106                        tmp = rtc_read(RtcTodAddr[i]);
 107                        time2 = (time2 << 8) | (tmp & 0xff);
 108                }
 109        } while ((time1 != time2) && limit--);
 110
 111        if (time1 != time2) {
 112                printf("can't get consistent time from rtc chip\n");
 113                rel = -1;
 114        }
 115
 116        DEBUGR ("Get RTC s since 1.1.1970: %ld\n", time1);
 117
 118        rtc_to_tm(time1, tm); /* To Gregorian Date */
 119
 120        if (rtc_read(RTC_SR_ADDR) & RTC_SR_BIT_OSF) {
 121                printf ("### Warning: RTC oscillator has stopped\n");
 122                rel = -1;
 123        }
 124
 125        DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 126                tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
 127                tm->tm_hour, tm->tm_min, tm->tm_sec);
 128
 129        return rel;
 130}
 131
 132/*
 133 * Set the RTC
 134 */
 135int rtc_set (struct rtc_time *tmp){
 136
 137        unsigned long time;
 138        unsigned i;
 139
 140        DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 141                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 142                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 143
 144        if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
 145                printf("WARNING: year should be between 1970 and 2069!\n");
 146
 147        time = rtc_mktime(tmp);
 148
 149        DEBUGR ("Set RTC s since 1.1.1970: %ld (0x%02lx)\n", time, time);
 150
 151        /* write to RTC_TOD_CNT_BYTEn_ADDR */
 152        for (i = 0; i <= 3; i++) {
 153                rtc_write_raw(RtcTodAddr[i], (unsigned char)(time & 0xff));
 154                time = time >> 8;
 155        }
 156
 157        /* Start clock */
 158        rtc_write(RTC_CTL_ADDR, RTC_CTL_BIT_EN_OSC, false);
 159
 160        return 0;
 161}
 162
 163/*
 164 * Reset the RTC. We setting the date back to 1970-01-01.
 165 * We also enable the oscillator output on the SQW/OUT pin and program
 166 * it for 32,768 Hz output. Note that according to the datasheet, turning
 167 * on the square wave output increases the current drain on the backup
 168 * battery to something between 480nA and 800nA.
 169 */
 170void rtc_reset (void){
 171
 172        /* clear status flags */
 173        rtc_write(RTC_SR_ADDR, (RTC_SR_BIT_AF|RTC_SR_BIT_OSF), false); /* clearing OSF and AF */
 174
 175        /* Initialise DS1374 oriented to MPC8349E-ADS */
 176        rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_EN_OSC
 177                                 |RTC_CTL_BIT_WACE
 178                                 |RTC_CTL_BIT_AIE), false);/* start osc, disable WACE, clear AIE
 179                                                              - set to 0 */
 180        rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_WD_ALM
 181                                |RTC_CTL_BIT_WDSTR
 182                                |RTC_CTL_BIT_RS1
 183                                |RTC_CTL_BIT_RS2
 184                                |RTC_CTL_BIT_BBSQW), true);/* disable WD/ALM, WDSTR set to INT-pin,
 185                                                              set BBSQW and SQW to 32k
 186                                                              - set to 1 */
 187        rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR, 0xAC, true);
 188        rtc_write(RTC_WD_ALM_CNT_BYTE1_ADDR, 0xDE, true);
 189        rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR, 0xAD, true);
 190}
 191
 192/*
 193 * Helper functions
 194 */
 195static uchar rtc_read (uchar reg)
 196{
 197        return (i2c_reg_read (CFG_SYS_I2C_RTC_ADDR, reg));
 198}
 199
 200static void rtc_write(uchar reg, uchar val, bool set)
 201{
 202        if (set == true) {
 203                val |= i2c_reg_read (CFG_SYS_I2C_RTC_ADDR, reg);
 204                i2c_reg_write (CFG_SYS_I2C_RTC_ADDR, reg, val);
 205        } else {
 206                val = i2c_reg_read (CFG_SYS_I2C_RTC_ADDR, reg) & ~val;
 207                i2c_reg_write (CFG_SYS_I2C_RTC_ADDR, reg, val);
 208        }
 209}
 210
 211static void rtc_write_raw (uchar reg, uchar val)
 212{
 213                i2c_reg_write (CFG_SYS_I2C_RTC_ADDR, reg, val);
 214}
 215