#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#define M41T93_REG_SSEC 0
#define M41T93_REG_ST_SEC 1
#define M41T93_FLAG_BL (1 << 4)
#define M41T93_FLAG_HT (1 << 6)
-static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
-{
- u8 buf[2];
-
- /* MSB must be '1' to write */
- buf[0] = addr | 0x80;
- buf[1] = data;
-
- return spi_write(spi, buf, sizeof(buf));
-}
+struct m41t93_data {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+};
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- int tmp;
- u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
- u8 * const data = &buf[1]; /* ptr to first data byte */
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int tmp, ret;
+ u8 buf[8] = {0}; /* 8 data bytes */
+ u8 * const data = &buf[0]; /* ptr to first data byte */
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
tm->tm_mon, tm->tm_year, tm->tm_wday);
if (tm->tm_year < 100) {
- dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n");
+ dev_warn(dev, "unsupported date (before 2000-01-01).\n");
return -EINVAL;
}
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_OF) {
- dev_warn(&spi->dev, "OF bit is set, resetting.\n");
- m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
+ dev_warn(dev, "OF bit is set, resetting.\n");
+ regmap_write(m41t93->regmap, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0) {
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0) {
+ return ret;
} else if (tmp & M41T93_FLAG_OF) {
/* OF cannot be immediately reset: oscillator has to be
* restarted. */
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
- dev_warn(&spi->dev,
+ dev_warn(dev,
"OF bit is still set, kickstarting clock.\n");
- m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
+ regmap_write(m41t93->regmap, M41T93_REG_ST_SEC, reset_osc);
reset_osc &= ~M41T93_FLAG_ST;
- m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
+ regmap_write(m41t93->regmap, M41T93_REG_ST_SEC, reset_osc);
}
}
data[M41T93_REG_MON] = bin2bcd(tm->tm_mon + 1);
data[M41T93_REG_YEAR] = bin2bcd(tm->tm_year % 100);
- return spi_write(spi, buf, sizeof(buf));
+ return regmap_bulk_write(m41t93->regmap, M41T93_REG_SSEC, buf, sizeof(buf));
}
static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- const u8 start_addr = 0;
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
u8 buf[8];
int century_after_1900;
int tmp;
case after poweron. Time is valid after resetting HT bit.
2. oscillator fail bit (OF) is set: time is invalid.
*/
- tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_ALM_HOUR_HT, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_HT) {
- dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n");
- m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT,
- tmp & ~M41T93_FLAG_HT);
+ dev_dbg(dev, "HT bit is set, reenable clock update.\n");
+ regmap_write(m41t93->regmap, M41T93_REG_ALM_HOUR_HT,
+ tmp & ~M41T93_FLAG_HT);
}
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_OF) {
ret = -EINVAL;
- dev_warn(&spi->dev, "OF bit is set, write time to restart.\n");
+ dev_warn(dev, "OF bit is set, write time to restart.\n");
}
if (tmp & M41T93_FLAG_BL)
- dev_warn(&spi->dev, "BL bit is set, replace battery.\n");
+ dev_warn(dev, "BL bit is set, replace battery.\n");
/* read actual time/date */
- tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf));
- if (tmp < 0)
- return tmp;
+ ret = regmap_bulk_read(m41t93->regmap, M41T93_REG_SSEC, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
tm->tm_sec = bcd2bin(buf[M41T93_REG_ST_SEC]);
tm->tm_min = bcd2bin(buf[M41T93_REG_MIN]);
static struct spi_driver m41t93_driver;
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = 0x00,
+ .write_flag_mask = 0x80,
+ .zero_flag_mask = true,
+};
+
static int m41t93_probe(struct spi_device *spi)
{
- struct rtc_device *rtc;
- int res;
+ int res, ret;
+ struct m41t93_data *m41t93;
spi->bits_per_word = 8;
spi_setup(spi);
- res = spi_w8r8(spi, M41T93_REG_WDAY);
+ m41t93 = devm_kzalloc(&spi->dev, sizeof(struct m41t93_data), GFP_KERNEL);
+
+ if (!m41t93)
+ return -ENOMEM;
+
+ /* Set up regmap to access device registers*/
+ m41t93->regmap = devm_regmap_init_spi(spi, ®map_config);
+ if (IS_ERR(m41t93->regmap)) {
+ dev_err(&spi->dev, "regmap init failure\n");
+ return PTR_ERR(m41t93->regmap);
+ }
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_WDAY, &res);
+ if (ret < 0) {
+ dev_err(&spi->dev, "IO error\n");
+ return -EIO;
+ }
+
if (res < 0 || (res & 0xf8) != 0) {
dev_err(&spi->dev, "not found 0x%x.\n", res);
return -ENODEV;
}
- rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
- &m41t93_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+ spi_set_drvdata(spi, m41t93);
- spi_set_drvdata(spi, rtc);
+ m41t93->rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
+ &m41t93_rtc_ops, THIS_MODULE);
+ if (IS_ERR(m41t93->rtc))
+ return PTR_ERR(m41t93->rtc);
return 0;
}