uboot/drivers/rtc/ds3231.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2006
   4 * Markus Klotzbuecher, mk@denx.de
   5 */
   6
   7/*
   8 * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
   9 * Extremly Accurate DS3231 Real Time Clock (RTC).
  10 *
  11 * copied from ds1337.c
  12 */
  13
  14#include <common.h>
  15#include <command.h>
  16#include <rtc.h>
  17#include <i2c.h>
  18
  19#if defined(CONFIG_CMD_DATE)
  20
  21/*
  22 * RTC register addresses
  23 */
  24#define RTC_SEC_REG_ADDR        0x0
  25#define RTC_MIN_REG_ADDR        0x1
  26#define RTC_HR_REG_ADDR         0x2
  27#define RTC_DAY_REG_ADDR        0x3
  28#define RTC_DATE_REG_ADDR       0x4
  29#define RTC_MON_REG_ADDR        0x5
  30#define RTC_YR_REG_ADDR         0x6
  31#define RTC_CTL_REG_ADDR        0x0e
  32#define RTC_STAT_REG_ADDR       0x0f
  33
  34
  35/*
  36 * RTC control register bits
  37 */
  38#define RTC_CTL_BIT_A1IE        0x1     /* Alarm 1 interrupt enable     */
  39#define RTC_CTL_BIT_A2IE        0x2     /* Alarm 2 interrupt enable     */
  40#define RTC_CTL_BIT_INTCN       0x4     /* Interrupt control            */
  41#define RTC_CTL_BIT_RS1         0x8     /* Rate select 1                */
  42#define RTC_CTL_BIT_RS2         0x10    /* Rate select 2                */
  43#define RTC_CTL_BIT_DOSC        0x80    /* Disable Oscillator           */
  44
  45/*
  46 * RTC status register bits
  47 */
  48#define RTC_STAT_BIT_A1F        0x1     /* Alarm 1 flag                 */
  49#define RTC_STAT_BIT_A2F        0x2     /* Alarm 2 flag                 */
  50#define RTC_STAT_BIT_OSF        0x80    /* Oscillator stop flag         */
  51#define RTC_STAT_BIT_BB32KHZ    0x40    /* Battery backed 32KHz Output  */
  52#define RTC_STAT_BIT_EN32KHZ    0x8     /* Enable 32KHz Output  */
  53
  54
  55static uchar rtc_read (uchar reg);
  56static void rtc_write (uchar reg, uchar val);
  57
  58
  59/*
  60 * Get the current time from the RTC
  61 */
  62int rtc_get (struct rtc_time *tmp)
  63{
  64        int rel = 0;
  65        uchar sec, min, hour, mday, wday, mon_cent, year, control, status;
  66
  67        control = rtc_read (RTC_CTL_REG_ADDR);
  68        status = rtc_read (RTC_STAT_REG_ADDR);
  69        sec = rtc_read (RTC_SEC_REG_ADDR);
  70        min = rtc_read (RTC_MIN_REG_ADDR);
  71        hour = rtc_read (RTC_HR_REG_ADDR);
  72        wday = rtc_read (RTC_DAY_REG_ADDR);
  73        mday = rtc_read (RTC_DATE_REG_ADDR);
  74        mon_cent = rtc_read (RTC_MON_REG_ADDR);
  75        year = rtc_read (RTC_YR_REG_ADDR);
  76
  77        debug("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
  78                "hr: %02x min: %02x sec: %02x control: %02x status: %02x\n",
  79                year, mon_cent, mday, wday, hour, min, sec, control, status);
  80
  81        if (status & RTC_STAT_BIT_OSF) {
  82                printf ("### Warning: RTC oscillator has stopped\n");
  83                /* clear the OSF flag */
  84                rtc_write (RTC_STAT_REG_ADDR,
  85                           rtc_read (RTC_STAT_REG_ADDR) & ~RTC_STAT_BIT_OSF);
  86                rel = -1;
  87        }
  88
  89        tmp->tm_sec  = bcd2bin (sec & 0x7F);
  90        tmp->tm_min  = bcd2bin (min & 0x7F);
  91        tmp->tm_hour = bcd2bin (hour & 0x3F);
  92        tmp->tm_mday = bcd2bin (mday & 0x3F);
  93        tmp->tm_mon  = bcd2bin (mon_cent & 0x1F);
  94        tmp->tm_year = bcd2bin (year) + ((mon_cent & 0x80) ? 2000 : 1900);
  95        tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
  96        tmp->tm_yday = 0;
  97        tmp->tm_isdst= 0;
  98
  99        debug("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 100                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 101                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 102
 103        return rel;
 104}
 105
 106
 107/*
 108 * Set the RTC
 109 */
 110int rtc_set (struct rtc_time *tmp)
 111{
 112        uchar century;
 113
 114        debug("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 115                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 116                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 117
 118        rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
 119
 120        century = (tmp->tm_year >= 2000) ? 0x80 : 0;
 121        rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon) | century);
 122
 123        rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
 124        rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
 125        rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
 126        rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
 127        rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
 128
 129        return 0;
 130}
 131
 132
 133/*
 134 * Reset the RTC.  We also enable the oscillator output on the
 135 * SQW/INTB* pin and program it for 32,768 Hz output. Note that
 136 * according to the datasheet, turning on the square wave output
 137 * increases the current drain on the backup battery from about
 138 * 600 nA to 2uA.
 139 */
 140void rtc_reset (void)
 141{
 142        rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS2);
 143}
 144
 145/*
 146 * Enable 32KHz output
 147 */
 148void rtc_enable_32khz_output(void)
 149{
 150        rtc_write(RTC_STAT_REG_ADDR,
 151                  RTC_STAT_BIT_BB32KHZ | RTC_STAT_BIT_EN32KHZ);
 152}
 153
 154/*
 155 * Helper functions
 156 */
 157
 158static
 159uchar rtc_read (uchar reg)
 160{
 161        return (i2c_reg_read (CONFIG_SYS_I2C_RTC_ADDR, reg));
 162}
 163
 164
 165static void rtc_write (uchar reg, uchar val)
 166{
 167        i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 168}
 169
 170#endif
 171