From: Akhilesh Patil Date: Sat, 20 Sep 2025 15:02:16 +0000 (+0530) Subject: rtc: m41t93: migrate to regmap api for register access X-Git-Tag: v7.2-rc1~7^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d86e8682593c79d8599537707f49e201456a76de;p=thirdparty%2Fkernel%2Fstable.git rtc: m41t93: migrate to regmap api for register access Adapt driver to use regmap api with spi bus instead of direct spi subsystem calls to access device registers. Simplify and standardize the register interactions using more abstract and bus agnostic regmap api to reduce code duplication and improve maintainability. Define spi regmap config suitable for m41t93 spi bus protocol to achieve same transactions on spi bus. Tested on TI am62x sk board with m41t93 rtc chip connected over spi0. Validated set and get time using hwclock tool and verified spi bus transfers using logic analyzer. Signed-off-by: Akhilesh Patil Link: https://patch.msgid.link/180f9b6c3ee7c490fe3537c2d50a92cec359e4cd.1758379856.git.akhilesh@ee.iitb.ac.in Signed-off-by: Alexandre Belloni --- diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 4e803ff0ce491..61e761af56ade 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -12,6 +12,7 @@ #include #include #include +#include #define M41T93_REG_SSEC 0 #define M41T93_REG_ST_SEC 1 @@ -31,23 +32,17 @@ #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", @@ -56,31 +51,31 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm) 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); } } @@ -94,14 +89,13 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm) 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; @@ -113,32 +107,32 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm) 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]); @@ -167,26 +161,51 @@ static const struct rtc_class_ops m41t93_rtc_ops = { 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; }