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