rtc: isl12022: switch to using regmap API
authorRasmus Villemoes <linux@rasmusvillemoes.dk>
Wed, 21 Sep 2022 11:46:23 +0000 (13:46 +0200)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Wed, 12 Oct 2022 22:17:22 +0000 (00:17 +0200)
The regmap abstraction allows us to avoid the private i2c transfer
helpers, and also offers some nice utility functions such as the
regmap_update_bits family.

While at it, simplify the code even more by not keeping track of
->write_enabled: rtc_set_time is not a hot path, so one extra i2c read
doesn't hurt (regmap_update_bits elides the write when the bits are
already as desired).

Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Link: https://lore.kernel.org/r/20220921114624.3250848-9-linux@rasmusvillemoes.dk
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/rtc/Kconfig
drivers/rtc/rtc-isl12022.c

index b8de251..bb63edb 100644 (file)
@@ -423,6 +423,7 @@ config RTC_DRV_ISL1208
 
 config RTC_DRV_ISL12022
        tristate "Intersil ISL12022"
+       select REGMAP_I2C
        help
          If you say yes here you get support for the
          Intersil ISL12022 RTC chip.
index 6fb13a5..ca677c4 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 
 /* ISL register offsets */
 #define ISL12022_REG_SC                0x00
@@ -42,72 +43,21 @@ static struct i2c_driver isl12022_driver;
 
 struct isl12022 {
        struct rtc_device *rtc;
-
-       bool write_enabled;     /* true if write enable is set */
+       struct regmap *regmap;
 };
 
-
-static int isl12022_read_regs(struct i2c_client *client, uint8_t reg,
-                             uint8_t *data, size_t n)
-{
-       struct i2c_msg msgs[] = {
-               {
-                       .addr   = client->addr,
-                       .flags  = 0,
-                       .len    = 1,
-                       .buf    = data
-               },              /* setup read ptr */
-               {
-                       .addr   = client->addr,
-                       .flags  = I2C_M_RD,
-                       .len    = n,
-                       .buf    = data
-               }
-       };
-
-       int ret;
-
-       data[0] = reg;
-       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-       if (ret != ARRAY_SIZE(msgs)) {
-               dev_err(&client->dev, "%s: read error, ret=%d\n",
-                       __func__, ret);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-
-static int isl12022_write_reg(struct i2c_client *client,
-                             uint8_t reg, uint8_t val)
-{
-       uint8_t data[2] = { reg, val };
-       int err;
-
-       err = i2c_master_send(client, data, sizeof(data));
-       if (err != sizeof(data)) {
-               dev_err(&client->dev,
-                       "%s: err=%d addr=%02x, data=%02x\n",
-                       __func__, err, data[0], data[1]);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-
 /*
  * In the routines that deal directly with the isl12022 hardware, we use
  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
  */
 static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       struct i2c_client *client = to_i2c_client(dev);
+       struct isl12022 *isl12022 = dev_get_drvdata(dev);
+       struct regmap *regmap = isl12022->regmap;
        uint8_t buf[ISL12022_REG_INT + 1];
        int ret;
 
-       ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf));
+       ret = regmap_bulk_read(regmap, ISL12022_REG_SC, buf, sizeof(buf));
        if (ret)
                return ret;
 
@@ -148,33 +98,18 @@ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       struct i2c_client *client = to_i2c_client(dev);
        struct isl12022 *isl12022 = dev_get_drvdata(dev);
-       size_t i;
+       struct regmap *regmap = isl12022->regmap;
        int ret;
        uint8_t buf[ISL12022_REG_DW + 1];
 
        dev_dbg(dev, "%s: %ptR\n", __func__, tm);
 
-       if (!isl12022->write_enabled) {
-
-               ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1);
-               if (ret)
-                       return ret;
-
-               /* Check if WRTC (write rtc enable) is set factory default is
-                * 0 (not set) */
-               if (!(buf[0] & ISL12022_INT_WRTC)) {
-                       /* Set the write enable bit. */
-                       ret = isl12022_write_reg(client,
-                                                ISL12022_REG_INT,
-                                                buf[0] | ISL12022_INT_WRTC);
-                       if (ret)
-                               return ret;
-               }
-
-               isl12022->write_enabled = true;
-       }
+       /* Ensure the write enable bit is set. */
+       ret = regmap_update_bits(regmap, ISL12022_REG_INT,
+                                ISL12022_INT_WRTC, ISL12022_INT_WRTC);
+       if (ret)
+               return ret;
 
        /* hours, minutes and seconds */
        buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec);
@@ -191,15 +126,8 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
        buf[ISL12022_REG_DW] = tm->tm_wday & 0x07;
 
-       /* write register's data */
-       for (i = 0; i < ARRAY_SIZE(buf); i++) {
-               ret = isl12022_write_reg(client, ISL12022_REG_SC + i,
-                                        buf[ISL12022_REG_SC + i]);
-               if (ret)
-                       return -EIO;
-       }
-
-       return 0;
+       return regmap_bulk_write(isl12022->regmap, ISL12022_REG_SC,
+                                buf, sizeof(buf));
 }
 
 static const struct rtc_class_ops isl12022_rtc_ops = {
@@ -207,6 +135,12 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
        .set_time       = isl12022_rtc_set_time,
 };
 
+static const struct regmap_config regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .use_single_write = true,
+};
+
 static int isl12022_probe(struct i2c_client *client)
 {
        struct isl12022 *isl12022;
@@ -220,6 +154,12 @@ static int isl12022_probe(struct i2c_client *client)
                return -ENOMEM;
        dev_set_drvdata(&client->dev, isl12022);
 
+       isl12022->regmap = devm_regmap_init_i2c(client, &regmap_config);
+       if (IS_ERR(isl12022->regmap)) {
+               dev_err(&client->dev, "regmap allocation failed\n");
+               return PTR_ERR(isl12022->regmap);
+       }
+
        isl12022->rtc = devm_rtc_allocate_device(&client->dev);
        if (IS_ERR(isl12022->rtc))
                return PTR_ERR(isl12022->rtc);