linux/drivers/rtc/rtc-m41t93.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *
   4 * Driver for ST M41T93 SPI RTC
   5 *
   6 * (c) 2010 Nikolaus Voss, Weinmann Medical GmbH
   7 */
   8
   9#include <linux/bcd.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <linux/rtc.h>
  14#include <linux/spi/spi.h>
  15
  16#define M41T93_REG_SSEC                 0
  17#define M41T93_REG_ST_SEC               1
  18#define M41T93_REG_MIN                  2
  19#define M41T93_REG_CENT_HOUR            3
  20#define M41T93_REG_WDAY                 4
  21#define M41T93_REG_DAY                  5
  22#define M41T93_REG_MON                  6
  23#define M41T93_REG_YEAR                 7
  24
  25
  26#define M41T93_REG_ALM_HOUR_HT          0xc
  27#define M41T93_REG_FLAGS                0xf
  28
  29#define M41T93_FLAG_ST                  (1 << 7)
  30#define M41T93_FLAG_OF                  (1 << 2)
  31#define M41T93_FLAG_BL                  (1 << 4)
  32#define M41T93_FLAG_HT                  (1 << 6)
  33
  34static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
  35{
  36        u8 buf[2];
  37
  38        /* MSB must be '1' to write */
  39        buf[0] = addr | 0x80;
  40        buf[1] = data;
  41
  42        return spi_write(spi, buf, sizeof(buf));
  43}
  44
  45static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
  46{
  47        struct spi_device *spi = to_spi_device(dev);
  48        int tmp;
  49        u8 buf[9] = {0x80};        /* write cmd + 8 data bytes */
  50        u8 * const data = &buf[1]; /* ptr to first data byte */
  51
  52        dev_dbg(dev, "%s secs=%d, mins=%d, "
  53                "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
  54                "write", tm->tm_sec, tm->tm_min,
  55                tm->tm_hour, tm->tm_mday,
  56                tm->tm_mon, tm->tm_year, tm->tm_wday);
  57
  58        if (tm->tm_year < 100) {
  59                dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n");
  60                return -EINVAL;
  61        }
  62
  63        tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
  64        if (tmp < 0)
  65                return tmp;
  66
  67        if (tmp & M41T93_FLAG_OF) {
  68                dev_warn(&spi->dev, "OF bit is set, resetting.\n");
  69                m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
  70
  71                tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
  72                if (tmp < 0) {
  73                        return tmp;
  74                } else if (tmp & M41T93_FLAG_OF) {
  75                        /* OF cannot be immediately reset: oscillator has to be
  76                         * restarted. */
  77                        u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
  78
  79                        dev_warn(&spi->dev,
  80                                 "OF bit is still set, kickstarting clock.\n");
  81                        m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
  82                        reset_osc &= ~M41T93_FLAG_ST;
  83                        m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
  84                }
  85        }
  86
  87        data[M41T93_REG_SSEC]           = 0;
  88        data[M41T93_REG_ST_SEC]         = bin2bcd(tm->tm_sec);
  89        data[M41T93_REG_MIN]            = bin2bcd(tm->tm_min);
  90        data[M41T93_REG_CENT_HOUR]      = bin2bcd(tm->tm_hour) |
  91                                                ((tm->tm_year/100-1) << 6);
  92        data[M41T93_REG_DAY]            = bin2bcd(tm->tm_mday);
  93        data[M41T93_REG_WDAY]           = bin2bcd(tm->tm_wday + 1);
  94        data[M41T93_REG_MON]            = bin2bcd(tm->tm_mon + 1);
  95        data[M41T93_REG_YEAR]           = bin2bcd(tm->tm_year % 100);
  96
  97        return spi_write(spi, buf, sizeof(buf));
  98}
  99
 100
 101static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
 102{
 103        struct spi_device *spi = to_spi_device(dev);
 104        const u8 start_addr = 0;
 105        u8 buf[8];
 106        int century_after_1900;
 107        int tmp;
 108        int ret = 0;
 109
 110        /* Check status of clock. Two states must be considered:
 111           1. halt bit (HT) is set: the clock is running but update of readout
 112              registers has been disabled due to power failure. This is normal
 113              case after poweron. Time is valid after resetting HT bit.
 114           2. oscillator fail bit (OF) is set: time is invalid.
 115        */
 116        tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
 117        if (tmp < 0)
 118                return tmp;
 119
 120        if (tmp & M41T93_FLAG_HT) {
 121                dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n");
 122                m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT,
 123                               tmp & ~M41T93_FLAG_HT);
 124        }
 125
 126        tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
 127        if (tmp < 0)
 128                return tmp;
 129
 130        if (tmp & M41T93_FLAG_OF) {
 131                ret = -EINVAL;
 132                dev_warn(&spi->dev, "OF bit is set, write time to restart.\n");
 133        }
 134
 135        if (tmp & M41T93_FLAG_BL)
 136                dev_warn(&spi->dev, "BL bit is set, replace battery.\n");
 137
 138        /* read actual time/date */
 139        tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf));
 140        if (tmp < 0)
 141                return tmp;
 142
 143        tm->tm_sec      = bcd2bin(buf[M41T93_REG_ST_SEC]);
 144        tm->tm_min      = bcd2bin(buf[M41T93_REG_MIN]);
 145        tm->tm_hour     = bcd2bin(buf[M41T93_REG_CENT_HOUR] & 0x3f);
 146        tm->tm_mday     = bcd2bin(buf[M41T93_REG_DAY]);
 147        tm->tm_mon      = bcd2bin(buf[M41T93_REG_MON]) - 1;
 148        tm->tm_wday     = bcd2bin(buf[M41T93_REG_WDAY] & 0x0f) - 1;
 149
 150        century_after_1900 = (buf[M41T93_REG_CENT_HOUR] >> 6) + 1;
 151        tm->tm_year = bcd2bin(buf[M41T93_REG_YEAR]) + century_after_1900 * 100;
 152
 153        dev_dbg(dev, "%s secs=%d, mins=%d, "
 154                "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
 155                "read", tm->tm_sec, tm->tm_min,
 156                tm->tm_hour, tm->tm_mday,
 157                tm->tm_mon, tm->tm_year, tm->tm_wday);
 158
 159        return ret;
 160}
 161
 162
 163static const struct rtc_class_ops m41t93_rtc_ops = {
 164        .read_time      = m41t93_get_time,
 165        .set_time       = m41t93_set_time,
 166};
 167
 168static struct spi_driver m41t93_driver;
 169
 170static int m41t93_probe(struct spi_device *spi)
 171{
 172        struct rtc_device *rtc;
 173        int res;
 174
 175        spi->bits_per_word = 8;
 176        spi_setup(spi);
 177
 178        res = spi_w8r8(spi, M41T93_REG_WDAY);
 179        if (res < 0 || (res & 0xf8) != 0) {
 180                dev_err(&spi->dev, "not found 0x%x.\n", res);
 181                return -ENODEV;
 182        }
 183
 184        rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
 185                                        &m41t93_rtc_ops, THIS_MODULE);
 186        if (IS_ERR(rtc))
 187                return PTR_ERR(rtc);
 188
 189        spi_set_drvdata(spi, rtc);
 190
 191        return 0;
 192}
 193
 194static struct spi_driver m41t93_driver = {
 195        .driver = {
 196                .name   = "rtc-m41t93",
 197        },
 198        .probe  = m41t93_probe,
 199};
 200
 201module_spi_driver(m41t93_driver);
 202
 203MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
 204MODULE_DESCRIPTION("Driver for ST M41T93 SPI RTC");
 205MODULE_LICENSE("GPL");
 206MODULE_ALIAS("spi:rtc-m41t93");
 207