uboot/drivers/rtc/ds1307.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 * DS1307 and DS1338/9 Real Time Clock (RTC).
  12 *
  13 * based on ds1337.c
  14 */
  15
  16#include <common.h>
  17#include <command.h>
  18#include <dm.h>
  19#include <log.h>
  20#include <rtc.h>
  21#include <i2c.h>
  22
  23enum ds_type {
  24        ds_1307,
  25        ds_1337,
  26        ds_1339,
  27        ds_1340,
  28        m41t11,
  29        mcp794xx,
  30};
  31
  32/*
  33 * RTC register addresses
  34 */
  35#define RTC_SEC_REG_ADDR        0x00
  36#define RTC_MIN_REG_ADDR        0x01
  37#define RTC_HR_REG_ADDR         0x02
  38#define RTC_DAY_REG_ADDR        0x03
  39#define RTC_DATE_REG_ADDR       0x04
  40#define RTC_MON_REG_ADDR        0x05
  41#define RTC_YR_REG_ADDR         0x06
  42#define RTC_CTL_REG_ADDR        0x07
  43
  44#define DS1337_CTL_REG_ADDR     0x0e
  45#define DS1337_STAT_REG_ADDR    0x0f
  46#define DS1340_STAT_REG_ADDR    0x09
  47
  48#define RTC_STAT_BIT_OSF        0x80
  49
  50#define RTC_SEC_BIT_CH          0x80    /* Clock Halt (in Register 0)   */
  51
  52/* DS1307-specific bits */
  53#define RTC_CTL_BIT_RS0         0x01    /* Rate select 0                */
  54#define RTC_CTL_BIT_RS1         0x02    /* Rate select 1                */
  55#define RTC_CTL_BIT_SQWE        0x10    /* Square Wave Enable           */
  56#define RTC_CTL_BIT_OUT         0x80    /* Output Control               */
  57
  58/* DS1337-specific bits */
  59#define DS1337_CTL_BIT_RS1      0x08    /* Rate select 1                */
  60#define DS1337_CTL_BIT_RS2      0x10    /* Rate select 2                */
  61#define DS1337_CTL_BIT_EOSC     0x80    /* Enable Oscillator            */
  62
  63/* DS1340-specific bits */
  64#define DS1340_SEC_BIT_EOSC     0x80    /* Enable Oscillator            */
  65#define DS1340_CTL_BIT_OUT      0x80    /* Output Control               */
  66
  67/* MCP7941X-specific bits */
  68#define MCP7941X_BIT_ST         0x80
  69#define MCP7941X_BIT_VBATEN     0x08
  70
  71#ifndef CONFIG_DM_RTC
  72
  73/*---------------------------------------------------------------------*/
  74#undef DEBUG_RTC
  75
  76#ifdef DEBUG_RTC
  77#define DEBUGR(fmt, args...) printf(fmt, ##args)
  78#else
  79#define DEBUGR(fmt, args...)
  80#endif
  81/*---------------------------------------------------------------------*/
  82
  83#ifndef CFG_SYS_I2C_RTC_ADDR
  84# define CFG_SYS_I2C_RTC_ADDR   0x68
  85#endif
  86
  87#if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000)
  88# error The DS1307 is specified only up to 100kHz!
  89#endif
  90
  91static uchar rtc_read (uchar reg);
  92static void rtc_write (uchar reg, uchar val);
  93
  94/*
  95 * Get the current time from the RTC
  96 */
  97int rtc_get (struct rtc_time *tmp)
  98{
  99        int rel = 0;
 100        uchar sec, min, hour, mday, wday, mon, year;
 101
 102#ifdef CONFIG_RTC_MCP79411
 103read_rtc:
 104#endif
 105        sec = rtc_read (RTC_SEC_REG_ADDR);
 106        min = rtc_read (RTC_MIN_REG_ADDR);
 107        hour = rtc_read (RTC_HR_REG_ADDR);
 108        wday = rtc_read (RTC_DAY_REG_ADDR);
 109        mday = rtc_read (RTC_DATE_REG_ADDR);
 110        mon = rtc_read (RTC_MON_REG_ADDR);
 111        year = rtc_read (RTC_YR_REG_ADDR);
 112
 113        DEBUGR ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
 114                "hr: %02x min: %02x sec: %02x\n",
 115                year, mon, mday, wday, hour, min, sec);
 116
 117#ifdef CONFIG_RTC_DS1307
 118        if (sec & RTC_SEC_BIT_CH) {
 119                printf ("### Warning: RTC oscillator has stopped\n");
 120                /* clear the CH flag */
 121                rtc_write (RTC_SEC_REG_ADDR,
 122                           rtc_read (RTC_SEC_REG_ADDR) & ~RTC_SEC_BIT_CH);
 123                rel = -1;
 124        }
 125#endif
 126
 127#ifdef CONFIG_RTC_MCP79411
 128        /* make sure that the backup battery is enabled */
 129        if (!(wday & MCP7941X_BIT_VBATEN)) {
 130                rtc_write(RTC_DAY_REG_ADDR,
 131                          wday | MCP7941X_BIT_VBATEN);
 132        }
 133
 134        /* clock halted?  turn it on, so clock can tick. */
 135        if (!(sec & MCP7941X_BIT_ST)) {
 136                rtc_write(RTC_SEC_REG_ADDR, MCP7941X_BIT_ST);
 137                printf("Started RTC\n");
 138                goto read_rtc;
 139        }
 140#endif
 141
 142
 143        tmp->tm_sec  = bcd2bin (sec & 0x7F);
 144        tmp->tm_min  = bcd2bin (min & 0x7F);
 145        tmp->tm_hour = bcd2bin (hour & 0x3F);
 146        tmp->tm_mday = bcd2bin (mday & 0x3F);
 147        tmp->tm_mon  = bcd2bin (mon & 0x1F);
 148        tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
 149        tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
 150        tmp->tm_yday = 0;
 151        tmp->tm_isdst= 0;
 152
 153        DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 154                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 155                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 156
 157        return rel;
 158}
 159
 160
 161/*
 162 * Set the RTC
 163 */
 164int rtc_set (struct rtc_time *tmp)
 165{
 166        DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 167                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 168                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 169
 170        if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
 171                printf("WARNING: year should be between 1970 and 2069!\n");
 172
 173        rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
 174        rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon));
 175#ifdef CONFIG_RTC_MCP79411
 176        rtc_write (RTC_DAY_REG_ADDR,
 177                   bin2bcd (tmp->tm_wday + 1) | MCP7941X_BIT_VBATEN);
 178#else
 179        rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
 180#endif
 181        rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
 182        rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
 183        rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
 184#ifdef CONFIG_RTC_MCP79411
 185        rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec) | MCP7941X_BIT_ST);
 186#else
 187        rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
 188#endif
 189
 190        return 0;
 191}
 192
 193
 194/*
 195 * Reset the RTC. We setting the date back to 1970-01-01.
 196 * We also enable the oscillator output on the SQW/OUT pin and program
 197 * it for 32,768 Hz output. Note that according to the datasheet, turning
 198 * on the square wave output increases the current drain on the backup
 199 * battery to something between 480nA and 800nA.
 200 */
 201void rtc_reset (void)
 202{
 203        rtc_write (RTC_SEC_REG_ADDR, 0x00);     /* clearing Clock Halt  */
 204        rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS0);
 205}
 206
 207
 208/*
 209 * Helper functions
 210 */
 211
 212static
 213uchar rtc_read (uchar reg)
 214{
 215        return (i2c_reg_read (CFG_SYS_I2C_RTC_ADDR, reg));
 216}
 217
 218
 219static void rtc_write (uchar reg, uchar val)
 220{
 221        i2c_reg_write (CFG_SYS_I2C_RTC_ADDR, reg, val);
 222}
 223
 224#endif /* !CONFIG_DM_RTC */
 225
 226#ifdef CONFIG_DM_RTC
 227static int ds1307_rtc_set(struct udevice *dev, const struct rtc_time *tm)
 228{
 229        int ret;
 230        uchar buf[7];
 231        enum ds_type type = dev_get_driver_data(dev);
 232
 233        debug("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 234              tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
 235              tm->tm_hour, tm->tm_min, tm->tm_sec);
 236
 237        if (tm->tm_year < 1970 || tm->tm_year > 2069)
 238                printf("WARNING: year should be between 1970 and 2069!\n");
 239
 240        buf[RTC_YR_REG_ADDR] = bin2bcd(tm->tm_year % 100);
 241        buf[RTC_MON_REG_ADDR] = bin2bcd(tm->tm_mon);
 242        buf[RTC_DAY_REG_ADDR] = bin2bcd(tm->tm_wday + 1);
 243        buf[RTC_DATE_REG_ADDR] = bin2bcd(tm->tm_mday);
 244        buf[RTC_HR_REG_ADDR] = bin2bcd(tm->tm_hour);
 245        buf[RTC_MIN_REG_ADDR] = bin2bcd(tm->tm_min);
 246        buf[RTC_SEC_REG_ADDR] = bin2bcd(tm->tm_sec);
 247
 248        if (type == mcp794xx) {
 249                buf[RTC_DAY_REG_ADDR] |= MCP7941X_BIT_VBATEN;
 250                buf[RTC_SEC_REG_ADDR] |= MCP7941X_BIT_ST;
 251        }
 252
 253        ret = dm_i2c_write(dev, 0, buf, sizeof(buf));
 254        if (ret < 0)
 255                return ret;
 256
 257        if (type == ds_1337) {
 258                /* Ensure oscillator is enabled */
 259                dm_i2c_reg_write(dev, DS1337_CTL_REG_ADDR, 0);
 260        }
 261
 262        return 0;
 263}
 264
 265static int ds1307_rtc_get(struct udevice *dev, struct rtc_time *tm)
 266{
 267        int ret;
 268        uchar buf[7];
 269        enum ds_type type = dev_get_driver_data(dev);
 270
 271        ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
 272        if (ret < 0)
 273                return ret;
 274
 275        if (type == ds_1337 || type == ds_1340) {
 276                uint reg = (type == ds_1337) ? DS1337_STAT_REG_ADDR :
 277                                               DS1340_STAT_REG_ADDR;
 278                int status = dm_i2c_reg_read(dev, reg);
 279
 280                if (status >= 0 && (status & RTC_STAT_BIT_OSF)) {
 281                        printf("### Warning: RTC oscillator has stopped\n");
 282                        /* clear the OSF flag */
 283                        dm_i2c_reg_write(dev, reg, status & ~RTC_STAT_BIT_OSF);
 284                }
 285        }
 286
 287        tm->tm_sec  = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F);
 288        tm->tm_min  = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F);
 289        tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x3F);
 290        tm->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F);
 291        tm->tm_mon  = bcd2bin(buf[RTC_MON_REG_ADDR] & 0x1F);
 292        tm->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR]) +
 293                              (bcd2bin(buf[RTC_YR_REG_ADDR]) >= 70 ?
 294                               1900 : 2000);
 295        tm->tm_wday = bcd2bin((buf[RTC_DAY_REG_ADDR] - 1) & 0x07);
 296        tm->tm_yday = 0;
 297        tm->tm_isdst = 0;
 298
 299        debug("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 300              tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
 301              tm->tm_hour, tm->tm_min, tm->tm_sec);
 302
 303        return 0;
 304}
 305
 306static int ds1307_rtc_reset(struct udevice *dev)
 307{
 308        int ret;
 309        enum ds_type type = dev_get_driver_data(dev);
 310
 311        /*
 312         * reset clock/oscillator in the seconds register:
 313         * on DS1307 bit 7 enables Clock Halt (CH),
 314         * on DS1340 bit 7 disables the oscillator (not EOSC)
 315         * on MCP794xx bit 7 enables Start Oscillator (ST)
 316         */
 317        ret = dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, 0x00);
 318        if (ret < 0)
 319                return ret;
 320
 321        if (type == ds_1307) {
 322                /* Write control register in order to enable square-wave
 323                 * output (SQWE) and set a default rate of 32.768kHz (RS1|RS0).
 324                 */
 325                ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR,
 326                                       RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 |
 327                                       RTC_CTL_BIT_RS0);
 328        } else if (type == ds_1337) {
 329                /* Write control register in order to enable oscillator output
 330                 * (not EOSC) and set a default rate of 32.768kHz (RS2|RS1).
 331                 */
 332                ret = dm_i2c_reg_write(dev, DS1337_CTL_REG_ADDR,
 333                                       DS1337_CTL_BIT_RS2 | DS1337_CTL_BIT_RS1);
 334        } else if (type == ds_1340 || type == mcp794xx || type == m41t11) {
 335                /* Reset clock calibration, frequency test and output level. */
 336                ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, 0x00);
 337        }
 338
 339        return ret;
 340}
 341
 342static int ds1307_probe(struct udevice *dev)
 343{
 344        i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
 345                           DM_I2C_CHIP_WR_ADDRESS);
 346
 347        return 0;
 348}
 349
 350static const struct rtc_ops ds1307_rtc_ops = {
 351        .get = ds1307_rtc_get,
 352        .set = ds1307_rtc_set,
 353        .reset = ds1307_rtc_reset,
 354};
 355
 356static const struct udevice_id ds1307_rtc_ids[] = {
 357        { .compatible = "dallas,ds1307", .data = ds_1307 },
 358        { .compatible = "dallas,ds1337", .data = ds_1337 },
 359        { .compatible = "dallas,ds1339", .data = ds_1339 },
 360        { .compatible = "dallas,ds1340", .data = ds_1340 },
 361        { .compatible = "microchip,mcp7940x", .data = mcp794xx },
 362        { .compatible = "microchip,mcp7941x", .data = mcp794xx },
 363        { .compatible = "st,m41t11", .data = m41t11 },
 364        { }
 365};
 366
 367U_BOOT_DRIVER(rtc_ds1307) = {
 368        .name   = "rtc-ds1307",
 369        .id     = UCLASS_RTC,
 370        .probe  = ds1307_probe,
 371        .of_match = ds1307_rtc_ids,
 372        .ops    = &ds1307_rtc_ops,
 373};
 374#endif /* CONFIG_DM_RTC */
 375