2016-04-21 18:24:29

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 0/6] add support for Microcrystal RV-3049

The current patchset adds the support of the microcrystal RV-3049 (spi).
This RTC will use the same driver than RV-3029 by updating it to use regmap.
It also adds the alarm IRQ functionality.


Mylène Josserand (6):
rtc: rv3029: remove 'i2c' in functions names
rtc: rv3029: convert to use regmap
rtc: rv3029: Add support of RV3049
rtc: rv3049: Removes some checks and warnings
rtc: rv3029: enable AE_x bits on set_alarm
rtc: rv3029: add alarm IRQ

drivers/rtc/Kconfig | 37 +--
drivers/rtc/rtc-rv3029c2.c | 582 +++++++++++++++++++++++++++++----------------
2 files changed, 397 insertions(+), 222 deletions(-)

--
2.8.0.rc3


2016-04-21 18:24:32

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 1/6] rtc: rv3029: remove 'i2c' in functions names

To prepare the use of regmap to add the support of RV-3049, all the
'i2c' in functions's names are removed.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 132 ++++++++++++++++++++-------------------------
1 file changed, 57 insertions(+), 75 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index d0cbf08..091be48 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -116,9 +116,8 @@
#define RV3029_USR2_RAM_PAGE 0x3C
#define RV3029_USR2_SECTION_LEN 0x04

-static int
-rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
- unsigned len)
+static int rv3029_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
+ unsigned len)
{
int ret;

@@ -134,9 +133,8 @@ rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
return 0;
}

-static int
-rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
- unsigned len)
+static int rv3029_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+ unsigned len)
{
if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
@@ -145,28 +143,27 @@ rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
}

-static int
-rv3029_i2c_update_bits(struct i2c_client *client, u8 reg, u8 mask, u8 set)
+static int rv3029_update_bits(struct i2c_client *client, u8 reg, u8 mask,
+ u8 set)
{
u8 buf;
int ret;

- ret = rv3029_i2c_read_regs(client, reg, &buf, 1);
+ ret = rv3029_read_regs(client, reg, &buf, 1);
if (ret < 0)
return ret;
buf &= ~mask;
buf |= set & mask;
- ret = rv3029_i2c_write_regs(client, reg, &buf, 1);
+ ret = rv3029_write_regs(client, reg, &buf, 1);
if (ret < 0)
return ret;

return 0;
}

-static int
-rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf)
+static int rv3029_get_sr(struct i2c_client *client, u8 *buf)
{
- int ret = rv3029_i2c_read_regs(client, RV3029_STATUS, buf, 1);
+ int ret = rv3029_read_regs(client, RV3029_STATUS, buf, 1);

if (ret < 0)
return -EIO;
@@ -174,14 +171,13 @@ rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf)
return 0;
}

-static int
-rv3029_i2c_set_sr(struct i2c_client *client, u8 val)
+static int rv3029_set_sr(struct i2c_client *client, u8 val)
{
u8 buf[1];
int sr;

buf[0] = val;
- sr = rv3029_i2c_write_regs(client, RV3029_STATUS, buf, 1);
+ sr = rv3029_write_regs(client, RV3029_STATUS, buf, 1);
dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
if (sr < 0)
return -EIO;
@@ -194,7 +190,7 @@ static int rv3029_eeprom_busywait(struct i2c_client *client)
u8 sr;

for (i = 100; i > 0; i--) {
- ret = rv3029_i2c_get_sr(client, &sr);
+ ret = rv3029_get_sr(client, &sr);
if (ret < 0)
break;
if (!(sr & RV3029_STATUS_EEBUSY))
@@ -212,9 +208,9 @@ static int rv3029_eeprom_busywait(struct i2c_client *client)
static int rv3029_eeprom_exit(struct i2c_client *client)
{
/* Re-enable eeprom refresh */
- return rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
- RV3029_ONOFF_CTRL_EERE,
- RV3029_ONOFF_CTRL_EERE);
+ return rv3029_update_bits(client, RV3029_ONOFF_CTRL,
+ RV3029_ONOFF_CTRL_EERE,
+ RV3029_ONOFF_CTRL_EERE);
}

static int rv3029_eeprom_enter(struct i2c_client *client)
@@ -223,7 +219,7 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
u8 sr;

/* Check whether we are in the allowed voltage range. */
- ret = rv3029_i2c_get_sr(client, &sr);
+ ret = rv3029_get_sr(client, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
@@ -232,11 +228,11 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
*/
sr &= ~RV3029_STATUS_VLOW1;
sr &= ~RV3029_STATUS_VLOW2;
- ret = rv3029_i2c_set_sr(client, sr);
+ ret = rv3029_set_sr(client, sr);
if (ret < 0)
return ret;
usleep_range(1000, 10000);
- ret = rv3029_i2c_get_sr(client, &sr);
+ ret = rv3029_get_sr(client, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
@@ -247,8 +243,8 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
}

/* Disable eeprom refresh. */
- ret = rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
- RV3029_ONOFF_CTRL_EERE, 0);
+ ret = rv3029_update_bits(client, RV3029_ONOFF_CTRL,
+ RV3029_ONOFF_CTRL_EERE, 0);
if (ret < 0)
return ret;

@@ -269,7 +265,7 @@ static int rv3029_eeprom_read(struct i2c_client *client, u8 reg,
if (err < 0)
return err;

- ret = rv3029_i2c_read_regs(client, reg, buf, len);
+ ret = rv3029_read_regs(client, reg, buf, len);

err = rv3029_eeprom_exit(client);
if (err < 0)
@@ -290,11 +286,11 @@ static int rv3029_eeprom_write(struct i2c_client *client, u8 reg,
return err;

for (i = 0; i < len; i++, reg++) {
- ret = rv3029_i2c_read_regs(client, reg, &tmp, 1);
+ ret = rv3029_read_regs(client, reg, &tmp, 1);
if (ret < 0)
break;
if (tmp != buf[i]) {
- ret = rv3029_i2c_write_regs(client, reg, &buf[i], 1);
+ ret = rv3029_write_regs(client, reg, &buf[i], 1);
if (ret < 0)
break;
}
@@ -328,21 +324,20 @@ static int rv3029_eeprom_update_bits(struct i2c_client *client,
return 0;
}

-static int
-rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+static int rv3029_read_time(struct i2c_client *client, struct rtc_time *tm)
{
u8 buf[1];
int ret;
u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };

- ret = rv3029_i2c_get_sr(client, buf);
+ ret = rv3029_get_sr(client, buf);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_i2c_read_regs(client, RV3029_W_SEC, regs,
- RV3029_WATCH_SECTION_LEN);
+ ret = rv3029_read_regs(client, RV3029_W_SEC, regs,
+ RV3029_WATCH_SECTION_LEN);
if (ret < 0) {
dev_err(&client->dev, "%s: reading RTC section failed\n",
__func__);
@@ -375,24 +370,24 @@ rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)

static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- return rv3029_i2c_read_time(to_i2c_client(dev), tm);
+ return rv3029_read_time(to_i2c_client(dev), tm);
}

-static int
-rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+static int rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];

- ret = rv3029_i2c_get_sr(client, regs);
+ ret = rv3029_get_sr(client, regs);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_i2c_read_regs(client, RV3029_A_SC, regs,
- RV3029_ALARM_SECTION_LEN);
+ ret = rv3029_read_regs(client, RV3029_A_SC, regs,
+ RV3029_ALARM_SECTION_LEN);

if (ret < 0) {
dev_err(&client->dev, "%s: reading alarm section failed\n",
@@ -411,21 +406,14 @@ rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
return 0;
}

-static int
-rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-{
- return rv3029_i2c_read_alarm(to_i2c_client(dev), alarm);
-}
-
-static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client,
- int enable)
+static int rv3029_rtc_alarm_set_irq(struct i2c_client *client, int enable)
{
int ret;

/* enable/disable AIE irq */
- ret = rv3029_i2c_update_bits(client, RV3029_IRQ_CTRL,
- RV3029_IRQ_CTRL_AIE,
- (enable ? RV3029_IRQ_CTRL_AIE : 0));
+ ret = rv3029_update_bits(client, RV3029_IRQ_CTRL,
+ RV3029_IRQ_CTRL_AIE,
+ (enable ? RV3029_IRQ_CTRL_AIE : 0));
if (ret < 0) {
dev_err(&client->dev, "can't update INT reg\n");
return ret;
@@ -434,9 +422,9 @@ static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client,
return 0;
}

-static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
- struct rtc_wkalrm *alarm)
+static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];
@@ -449,7 +437,7 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
if (tm->tm_year < 100)
return -EINVAL;

- ret = rv3029_i2c_get_sr(client, regs);
+ ret = rv3029_get_sr(client, regs);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return -EIO;
@@ -462,28 +450,28 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

- ret = rv3029_i2c_write_regs(client, RV3029_A_SC, regs,
- RV3029_ALARM_SECTION_LEN);
+ ret = rv3029_write_regs(client, RV3029_A_SC, regs,
+ RV3029_ALARM_SECTION_LEN);
if (ret < 0)
return ret;

if (alarm->enabled) {
/* clear AF flag */
- ret = rv3029_i2c_update_bits(client, RV3029_IRQ_FLAGS,
- RV3029_IRQ_FLAGS_AF, 0);
+ ret = rv3029_update_bits(client, RV3029_IRQ_FLAGS,
+ RV3029_IRQ_FLAGS_AF, 0);
if (ret < 0) {
dev_err(&client->dev, "can't clear alarm flag\n");
return ret;
}
/* enable AIE irq */
- ret = rv3029_rtc_i2c_alarm_set_irq(client, 1);
+ ret = rv3029_rtc_alarm_set_irq(client, 1);
if (ret)
return ret;

dev_dbg(&client->dev, "alarm IRQ armed\n");
} else {
/* disable AIE irq */
- ret = rv3029_rtc_i2c_alarm_set_irq(client, 0);
+ ret = rv3029_rtc_alarm_set_irq(client, 0);
if (ret)
return ret;

@@ -493,13 +481,7 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
return 0;
}

-static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-{
- return rv3029_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
-}
-
-static int
-rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
+static int rv3029_set_time(struct i2c_client *client, struct rtc_time const *tm)
{
u8 regs[8];
int ret;
@@ -520,18 +502,18 @@ rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

- ret = rv3029_i2c_write_regs(client, RV3029_W_SEC, regs,
- RV3029_WATCH_SECTION_LEN);
+ ret = rv3029_write_regs(client, RV3029_W_SEC, regs,
+ RV3029_WATCH_SECTION_LEN);
if (ret < 0)
return ret;

- ret = rv3029_i2c_get_sr(client, regs);
+ ret = rv3029_get_sr(client, regs);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return ret;
}
/* clear PON bit */
- ret = rv3029_i2c_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
+ ret = rv3029_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return ret;
@@ -542,7 +524,7 @@ rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)

static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- return rv3029_i2c_set_time(to_i2c_client(dev), tm);
+ return rv3029_set_time(to_i2c_client(dev), tm);
}

static const struct rv3029_trickle_tab_elem {
@@ -646,7 +628,7 @@ static int rv3029_read_temp(struct i2c_client *client, int *temp_mC)
int ret;
u8 temp;

- ret = rv3029_i2c_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
+ ret = rv3029_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
if (ret < 0)
return ret;

@@ -743,8 +725,8 @@ static void rv3029_hwmon_register(struct i2c_client *client)
&client->dev, client->name, client, rv3029_hwmon_groups);
if (IS_ERR(hwmon_dev)) {
dev_warn(&client->dev,
- "unable to register hwmon device %ld\n",
- PTR_ERR(hwmon_dev));
+ "unable to register hwmon device %ld\n",
+ PTR_ERR(hwmon_dev));
}
}

@@ -780,7 +762,7 @@ static int rv3029_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
return -ENODEV;

- rc = rv3029_i2c_get_sr(client, buf);
+ rc = rv3029_get_sr(client, buf);
if (rc < 0) {
dev_err(&client->dev, "reading status failed\n");
return rc;
--
2.8.0.rc3

2016-04-21 18:24:43

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 2/6] rtc: rv3029: convert to use regmap

To add support of rv3049, the current driver is converted to use regmap.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 275 +++++++++++++++++++++++----------------------
1 file changed, 142 insertions(+), 133 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 091be48..96dd166 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -20,7 +20,7 @@
#include <linux/of.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-
+#include <linux/regmap.h>

/* Register map */
/* control section */
@@ -116,81 +116,84 @@
#define RV3029_USR2_RAM_PAGE 0x3C
#define RV3029_USR2_SECTION_LEN 0x04

-static int rv3029_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
+struct rv3029_data {
+ struct device *dev;
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+ int irq;
+};
+
+static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf,
unsigned len)
{
- int ret;
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);

if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

- ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
- if (ret < 0)
- return ret;
- if (ret < len)
- return -EIO;
- return 0;
+ return regmap_bulk_read(rv3029->regmap, reg, buf, len);
}

-static int rv3029_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[],
unsigned len)
{
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
+
if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

- return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
+ return regmap_bulk_write(rv3029->regmap, reg, buf, len);
}

-static int rv3029_update_bits(struct i2c_client *client, u8 reg, u8 mask,
- u8 set)
+static int rv3029_update_bits(struct device *dev, u8 reg, u8 mask, u8 set)
{
u8 buf;
int ret;

- ret = rv3029_read_regs(client, reg, &buf, 1);
+ ret = rv3029_read_regs(dev, reg, &buf, 1);
if (ret < 0)
return ret;
buf &= ~mask;
buf |= set & mask;
- ret = rv3029_write_regs(client, reg, &buf, 1);
+ ret = rv3029_write_regs(dev, reg, &buf, 1);
if (ret < 0)
return ret;

return 0;
}

-static int rv3029_get_sr(struct i2c_client *client, u8 *buf)
+static int rv3029_get_sr(struct device *dev, u8 *buf)
{
- int ret = rv3029_read_regs(client, RV3029_STATUS, buf, 1);
+ int ret = rv3029_read_regs(dev, RV3029_STATUS, buf, 1);

if (ret < 0)
return -EIO;
- dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
+ dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
return 0;
}

-static int rv3029_set_sr(struct i2c_client *client, u8 val)
+static int rv3029_set_sr(struct device *dev, u8 val)
{
u8 buf[1];
int sr;

buf[0] = val;
- sr = rv3029_write_regs(client, RV3029_STATUS, buf, 1);
- dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
+ sr = rv3029_write_regs(dev, RV3029_STATUS, buf, 1);
+ dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
if (sr < 0)
return -EIO;
return 0;
}

-static int rv3029_eeprom_busywait(struct i2c_client *client)
+static int rv3029_eeprom_busywait(struct device *dev)
{
int i, ret;
u8 sr;

for (i = 100; i > 0; i--) {
- ret = rv3029_get_sr(client, &sr);
+ ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
break;
if (!(sr & RV3029_STATUS_EEBUSY))
@@ -198,28 +201,28 @@ static int rv3029_eeprom_busywait(struct i2c_client *client)
usleep_range(1000, 10000);
}
if (i <= 0) {
- dev_err(&client->dev, "EEPROM busy wait timeout.\n");
+ dev_err(dev, "EEPROM busy wait timeout.\n");
return -ETIMEDOUT;
}

return ret;
}

-static int rv3029_eeprom_exit(struct i2c_client *client)
+static int rv3029_eeprom_exit(struct device *dev)
{
/* Re-enable eeprom refresh */
- return rv3029_update_bits(client, RV3029_ONOFF_CTRL,
+ return rv3029_update_bits(dev, RV3029_ONOFF_CTRL,
RV3029_ONOFF_CTRL_EERE,
RV3029_ONOFF_CTRL_EERE);
}

-static int rv3029_eeprom_enter(struct i2c_client *client)
+static int rv3029_eeprom_enter(struct device *dev)
{
int ret;
u8 sr;

/* Check whether we are in the allowed voltage range. */
- ret = rv3029_get_sr(client, &sr);
+ ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
@@ -228,119 +231,118 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
*/
sr &= ~RV3029_STATUS_VLOW1;
sr &= ~RV3029_STATUS_VLOW2;
- ret = rv3029_set_sr(client, sr);
+ ret = rv3029_set_sr(dev, sr);
if (ret < 0)
return ret;
usleep_range(1000, 10000);
- ret = rv3029_get_sr(client, &sr);
+ ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
- dev_err(&client->dev,
+ dev_err(dev,
"Supply voltage is too low to safely access the EEPROM.\n");
return -ENODEV;
}
}

/* Disable eeprom refresh. */
- ret = rv3029_update_bits(client, RV3029_ONOFF_CTRL,
- RV3029_ONOFF_CTRL_EERE, 0);
+ ret = rv3029_update_bits(dev, RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE,
+ 0);
if (ret < 0)
return ret;

/* Wait for any previous eeprom accesses to finish. */
- ret = rv3029_eeprom_busywait(client);
+ ret = rv3029_eeprom_busywait(dev);
if (ret < 0)
- rv3029_eeprom_exit(client);
+ rv3029_eeprom_exit(dev);

return ret;
}

-static int rv3029_eeprom_read(struct i2c_client *client, u8 reg,
+static int rv3029_eeprom_read(struct device *dev, u8 reg,
u8 buf[], size_t len)
{
int ret, err;

- err = rv3029_eeprom_enter(client);
+ err = rv3029_eeprom_enter(dev);
if (err < 0)
return err;

- ret = rv3029_read_regs(client, reg, buf, len);
+ ret = rv3029_read_regs(dev, reg, buf, len);

- err = rv3029_eeprom_exit(client);
+ err = rv3029_eeprom_exit(dev);
if (err < 0)
return err;

return ret;
}

-static int rv3029_eeprom_write(struct i2c_client *client, u8 reg,
+static int rv3029_eeprom_write(struct device *dev, u8 reg,
u8 const buf[], size_t len)
{
int ret, err;
size_t i;
u8 tmp;

- err = rv3029_eeprom_enter(client);
+ err = rv3029_eeprom_enter(dev);
if (err < 0)
return err;

for (i = 0; i < len; i++, reg++) {
- ret = rv3029_read_regs(client, reg, &tmp, 1);
+ ret = rv3029_read_regs(dev, reg, &tmp, 1);
if (ret < 0)
break;
if (tmp != buf[i]) {
- ret = rv3029_write_regs(client, reg, &buf[i], 1);
+ ret = rv3029_write_regs(dev, reg, &buf[i], 1);
if (ret < 0)
break;
}
- ret = rv3029_eeprom_busywait(client);
+ ret = rv3029_eeprom_busywait(dev);
if (ret < 0)
break;
}

- err = rv3029_eeprom_exit(client);
+ err = rv3029_eeprom_exit(dev);
if (err < 0)
return err;

return ret;
}

-static int rv3029_eeprom_update_bits(struct i2c_client *client,
+static int rv3029_eeprom_update_bits(struct device *dev,
u8 reg, u8 mask, u8 set)
{
u8 buf;
int ret;

- ret = rv3029_eeprom_read(client, reg, &buf, 1);
+ ret = rv3029_eeprom_read(dev, reg, &buf, 1);
if (ret < 0)
return ret;
buf &= ~mask;
buf |= set & mask;
- ret = rv3029_eeprom_write(client, reg, &buf, 1);
+ ret = rv3029_eeprom_write(dev, reg, &buf, 1);
if (ret < 0)
return ret;

return 0;
}

-static int rv3029_read_time(struct i2c_client *client, struct rtc_time *tm)
+static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
{
u8 buf[1];
int ret;
u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };

- ret = rv3029_get_sr(client, buf);
+ ret = rv3029_get_sr(dev, buf);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_read_regs(client, RV3029_W_SEC, regs,
+ ret = rv3029_read_regs(dev, RV3029_W_SEC, regs,
RV3029_WATCH_SECTION_LEN);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading RTC section failed\n",
- __func__);
+ dev_err(dev, "%s: reading RTC section failed\n", __func__);
return ret;
}

@@ -368,30 +370,23 @@ static int rv3029_read_time(struct i2c_client *client, struct rtc_time *tm)
return 0;
}

-static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return rv3029_read_time(to_i2c_client(dev), tm);
-}
-
-static int rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
- struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];

- ret = rv3029_get_sr(client, regs);
+ ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_read_regs(client, RV3029_A_SC, regs,
+ ret = rv3029_read_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);

if (ret < 0) {
- dev_err(&client->dev, "%s: reading alarm section failed\n",
- __func__);
+ dev_err(dev, "%s: reading alarm section failed\n", __func__);
return ret;
}

@@ -406,25 +401,23 @@ static int rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return 0;
}

-static int rv3029_rtc_alarm_set_irq(struct i2c_client *client, int enable)
+static int rv3029_rtc_alarm_set_irq(struct device *dev, int enable)
{
int ret;

/* enable/disable AIE irq */
- ret = rv3029_update_bits(client, RV3029_IRQ_CTRL,
- RV3029_IRQ_CTRL_AIE,
+ ret = rv3029_update_bits(dev, RV3029_IRQ_CTRL, RV3029_IRQ_CTRL_AIE,
(enable ? RV3029_IRQ_CTRL_AIE : 0));
if (ret < 0) {
- dev_err(&client->dev, "can't update INT reg\n");
+ dev_err(dev, "can't update INT reg\n");
return ret;
}

return 0;
}

-static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
- struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];
@@ -437,9 +430,9 @@ static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (tm->tm_year < 100)
return -EINVAL;

- ret = rv3029_get_sr(client, regs);
+ ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}
regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
@@ -450,38 +443,38 @@ static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

- ret = rv3029_write_regs(client, RV3029_A_SC, regs,
+ ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);
if (ret < 0)
return ret;

if (alarm->enabled) {
/* clear AF flag */
- ret = rv3029_update_bits(client, RV3029_IRQ_FLAGS,
+ ret = rv3029_update_bits(dev, RV3029_IRQ_FLAGS,
RV3029_IRQ_FLAGS_AF, 0);
if (ret < 0) {
- dev_err(&client->dev, "can't clear alarm flag\n");
+ dev_err(dev, "can't clear alarm flag\n");
return ret;
}
/* enable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(client, 1);
+ ret = rv3029_rtc_alarm_set_irq(dev, 1);
if (ret)
return ret;

- dev_dbg(&client->dev, "alarm IRQ armed\n");
+ dev_dbg(dev, "alarm IRQ armed\n");
} else {
/* disable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(client, 0);
+ ret = rv3029_rtc_alarm_set_irq(dev, 0);
if (ret)
return ret;

- dev_dbg(&client->dev, "alarm IRQ disabled\n");
+ dev_dbg(dev, "alarm IRQ disabled\n");
}

return 0;
}

-static int rv3029_set_time(struct i2c_client *client, struct rtc_time const *tm)
+static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
{
u8 regs[8];
int ret;
@@ -502,31 +495,25 @@ static int rv3029_set_time(struct i2c_client *client, struct rtc_time const *tm)
regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

- ret = rv3029_write_regs(client, RV3029_W_SEC, regs,
+ ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
RV3029_WATCH_SECTION_LEN);
if (ret < 0)
return ret;

- ret = rv3029_get_sr(client, regs);
+ ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return ret;
}
/* clear PON bit */
- ret = rv3029_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
+ ret = rv3029_set_sr(dev, (regs[0] & ~RV3029_STATUS_PON));
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return ret;
}

return 0;
}
-
-static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return rv3029_set_time(to_i2c_client(dev), tm);
-}
-
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
@@ -584,9 +571,9 @@ static const struct rv3029_trickle_tab_elem {
},
};

-static void rv3029_trickle_config(struct i2c_client *client)
+static void rv3029_trickle_config(struct device *dev)
{
- struct device_node *of_node = client->dev.of_node;
+ struct device_node *of_node = dev->of_node;
const struct rv3029_trickle_tab_elem *elem;
int i, err;
u32 ohms;
@@ -608,27 +595,26 @@ static void rv3029_trickle_config(struct i2c_client *client)
break;
}
trickle_set_bits = elem->conf;
- dev_info(&client->dev,
+ dev_info(dev,
"Trickle charger enabled at %d ohms resistance.\n",
elem->r);
}
- err = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+ err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_TRICKLE_MASK,
trickle_set_bits);
if (err < 0) {
- dev_err(&client->dev,
- "Failed to update trickle charger config\n");
+ dev_err(dev, "Failed to update trickle charger config\n");
}
}

#ifdef CONFIG_RTC_DRV_RV3029_HWMON

-static int rv3029_read_temp(struct i2c_client *client, int *temp_mC)
+static int rv3029_read_temp(struct device *dev, int *temp_mC)
{
int ret;
u8 temp;

- ret = rv3029_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
+ ret = rv3029_read_regs(dev, RV3029_TEMP_PAGE, &temp, 1);
if (ret < 0)
return ret;

@@ -641,10 +627,9 @@ static ssize_t rv3029_hwmon_show_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = dev_get_drvdata(dev);
int ret, temp_mC;

- ret = rv3029_read_temp(client, &temp_mC);
+ ret = rv3029_read_temp(dev, &temp_mC);
if (ret < 0)
return ret;

@@ -656,7 +641,6 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = dev_get_drvdata(dev);
unsigned long interval_ms;
int ret;
u8 th_set_bits = 0;
@@ -670,7 +654,7 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
if (interval_ms >= 16000)
th_set_bits |= RV3029_EECTRL_THP;
}
- ret = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+ ret = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_EECTRL_THE | RV3029_EECTRL_THP,
th_set_bits);
if (ret < 0)
@@ -683,11 +667,10 @@ static ssize_t rv3029_hwmon_show_update_interval(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = dev_get_drvdata(dev);
int ret, interval_ms;
u8 eectrl;

- ret = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL,
+ ret = rv3029_eeprom_read(dev, RV3029_CONTROL_E2P_EECTRL,
&eectrl, 1);
if (ret < 0)
return ret;
@@ -717,32 +700,32 @@ static struct attribute *rv3029_hwmon_attrs[] = {
};
ATTRIBUTE_GROUPS(rv3029_hwmon);

-static void rv3029_hwmon_register(struct i2c_client *client)
+static void rv3029_hwmon_register(struct device *dev, const char *name)
{
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
struct device *hwmon_dev;

- hwmon_dev = devm_hwmon_device_register_with_groups(
- &client->dev, client->name, client, rv3029_hwmon_groups);
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, name, rv3029,
+ rv3029_hwmon_groups);
if (IS_ERR(hwmon_dev)) {
- dev_warn(&client->dev,
- "unable to register hwmon device %ld\n",
+ dev_warn(dev, "unable to register hwmon device %ld\n",
PTR_ERR(hwmon_dev));
}
}

#else /* CONFIG_RTC_DRV_RV3029_HWMON */

-static void rv3029_hwmon_register(struct i2c_client *client)
+static void rv3029_hwmon_register(struct device *dev, const char *name)
{
}

#endif /* CONFIG_RTC_DRV_RV3029_HWMON */

static const struct rtc_class_ops rv3029_rtc_ops = {
- .read_time = rv3029_rtc_read_time,
- .set_time = rv3029_rtc_set_time,
- .read_alarm = rv3029_rtc_read_alarm,
- .set_alarm = rv3029_rtc_set_alarm,
+ .read_time = rv3029_read_time,
+ .set_time = rv3029_set_time,
+ .read_alarm = rv3029_read_alarm,
+ .set_alarm = rv3029_set_alarm,
};

static struct i2c_device_id rv3029_id[] = {
@@ -752,41 +735,67 @@ static struct i2c_device_id rv3029_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rv3029_id);

-static int rv3029_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
+ const char *name)
{
- struct rtc_device *rtc;
+ struct rv3029_data *rv3029;
int rc = 0;
u8 buf[1];

- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
- return -ENODEV;
+ rv3029 = devm_kzalloc(dev, sizeof(*rv3029), GFP_KERNEL);
+ if (!rv3029)
+ return -ENOMEM;
+
+ rv3029->regmap = regmap;
+ rv3029->irq = irq;
+ rv3029->dev = dev;
+ dev_set_drvdata(dev, rv3029);

- rc = rv3029_get_sr(client, buf);
+ rc = rv3029_get_sr(dev, buf);
if (rc < 0) {
- dev_err(&client->dev, "reading status failed\n");
+ dev_err(dev, "reading status failed\n");
return rc;
}

- rv3029_trickle_config(client);
- rv3029_hwmon_register(client);
+ rv3029_trickle_config(dev);
+ rv3029_hwmon_register(dev, name);
+
+ rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
+ THIS_MODULE);

- rtc = devm_rtc_device_register(&client->dev, client->name,
- &rv3029_rtc_ops, THIS_MODULE);
+ return PTR_ERR_OR_ZERO(rv3029->rtc);
+}

- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+static int rv3029_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+ static const struct regmap_config config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ };
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
+ I2C_FUNC_SMBUS_BYTE)) {
+ dev_err(&client->dev, "Adapter does not support SMBUS_I2C_BLOCK or SMBUS_I2C_BYTE\n");
+ return -ENODEV;
+ }

- i2c_set_clientdata(client, rtc);
+ regmap = devm_regmap_init_i2c(client, &config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
+ __func__, PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }

- return 0;
+ return rv3029_probe(&client->dev, regmap, client->irq, client->name);
}

static struct i2c_driver rv3029_driver = {
.driver = {
.name = "rtc-rv3029c2",
},
- .probe = rv3029_probe,
+ .probe = rv3029_i2c_probe,
.id_table = rv3029_id,
};

--
2.8.0.rc3

2016-04-21 18:24:40

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 4/6] rtc: rv3029: Removes some checks and warnings

Removes some checks from checkpatch such as spaces around arithmetic
operations.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 66 ++++++++++++++++++++++------------------------
1 file changed, 32 insertions(+), 34 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 470cc1e..a849005 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -130,7 +130,7 @@ static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf,
struct rv3029_data *rv3029 = dev_get_drvdata(dev);

if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
- (reg + len > RV3029_USR1_RAM_PAGE + 8))
+ (reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

return regmap_bulk_read(rv3029->regmap, reg, buf, len);
@@ -142,7 +142,7 @@ static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[],
struct rv3029_data *rv3029 = dev_get_drvdata(dev);

if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
- (reg + len > RV3029_USR1_RAM_PAGE + 8))
+ (reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

return regmap_bulk_write(rv3029->regmap, reg, buf, len);
@@ -347,12 +347,12 @@ static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
return ret;
}

- tm->tm_sec = bcd2bin(regs[RV3029_W_SEC-RV3029_W_SEC]);
- tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES-RV3029_W_SEC]);
+ tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]);
+ tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]);

/* HR field has a more complex interpretation */
{
- const u8 _hr = regs[RV3029_W_HOURS-RV3029_W_SEC];
+ const u8 _hr = regs[RV3029_W_HOURS - RV3029_W_SEC];

if (_hr & RV3029_REG_HR_12_24) {
/* 12h format */
@@ -363,10 +363,10 @@ static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour = bcd2bin(_hr & 0x3f);
}

- tm->tm_mday = bcd2bin(regs[RV3029_W_DATE-RV3029_W_SEC]);
- tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS-RV3029_W_SEC]) - 1;
- tm->tm_year = bcd2bin(regs[RV3029_W_YEARS-RV3029_W_SEC]) + 100;
- tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS-RV3029_W_SEC]) - 1;
+ tm->tm_mday = bcd2bin(regs[RV3029_W_DATE - RV3029_W_SEC]);
+ tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS - RV3029_W_SEC]) - 1;
+ tm->tm_year = bcd2bin(regs[RV3029_W_YEARS - RV3029_W_SEC]) + 100;
+ tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS - RV3029_W_SEC]) - 1;

return 0;
}
@@ -391,13 +391,13 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ret;
}

- tm->tm_sec = bcd2bin(regs[RV3029_A_SC-RV3029_A_SC] & 0x7f);
- tm->tm_min = bcd2bin(regs[RV3029_A_MN-RV3029_A_SC] & 0x7f);
- tm->tm_hour = bcd2bin(regs[RV3029_A_HR-RV3029_A_SC] & 0x3f);
- tm->tm_mday = bcd2bin(regs[RV3029_A_DT-RV3029_A_SC] & 0x3f);
- tm->tm_mon = bcd2bin(regs[RV3029_A_MO-RV3029_A_SC] & 0x1f) - 1;
- tm->tm_year = bcd2bin(regs[RV3029_A_YR-RV3029_A_SC] & 0x7f) + 100;
- tm->tm_wday = bcd2bin(regs[RV3029_A_DW-RV3029_A_SC] & 0x07) - 1;
+ tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f);
+ tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f);
+ tm->tm_hour = bcd2bin(regs[RV3029_A_HR - RV3029_A_SC] & 0x3f);
+ tm->tm_mday = bcd2bin(regs[RV3029_A_DT - RV3029_A_SC] & 0x3f);
+ tm->tm_mon = bcd2bin(regs[RV3029_A_MO - RV3029_A_SC] & 0x1f) - 1;
+ tm->tm_year = bcd2bin(regs[RV3029_A_YR - RV3029_A_SC] & 0x7f) + 100;
+ tm->tm_wday = bcd2bin(regs[RV3029_A_DW - RV3029_A_SC] & 0x07) - 1;

return 0;
}
@@ -436,13 +436,13 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}
- regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
- regs[RV3029_A_MN-RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
- regs[RV3029_A_HR-RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
- regs[RV3029_A_DT-RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
- regs[RV3029_A_MO-RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
- regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
- regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
+ regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
+ regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
+ regs[RV3029_A_HR - RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
+ regs[RV3029_A_DT - RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
+ regs[RV3029_A_MO - RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
+ regs[RV3029_A_DW - RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
+ regs[RV3029_A_YR - RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);
@@ -488,13 +488,13 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
if (tm->tm_year < 100)
return -EINVAL;

- regs[RV3029_W_SEC-RV3029_W_SEC] = bin2bcd(tm->tm_sec);
- regs[RV3029_W_MINUTES-RV3029_W_SEC] = bin2bcd(tm->tm_min);
- regs[RV3029_W_HOURS-RV3029_W_SEC] = bin2bcd(tm->tm_hour);
- regs[RV3029_W_DATE-RV3029_W_SEC] = bin2bcd(tm->tm_mday);
- regs[RV3029_W_MONTHS-RV3029_W_SEC] = bin2bcd(tm->tm_mon+1);
- regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
- regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);
+ regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec);
+ regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min);
+ regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
+ regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday);
+ regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1);
+ regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7) + 1);
+ regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
RV3029_WATCH_SECTION_LEN);
@@ -515,6 +515,7 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)

return 0;
}
+
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
@@ -603,9 +604,8 @@ static void rv3029_trickle_config(struct device *dev)
err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_TRICKLE_MASK,
trickle_set_bits);
- if (err < 0) {
+ if (err < 0)
dev_err(dev, "Failed to update trickle charger config\n");
- }
}

#ifdef CONFIG_RTC_DRV_RV3029_HWMON
@@ -829,8 +829,6 @@ static void rv3029_unregister_driver(void)

static int rv3049_probe(struct spi_device *spi)
{
- int res;
- unsigned int tmp;
static const struct regmap_config config = {
.reg_bits = 8,
.val_bits = 8,
--
2.8.0.rc3

2016-04-21 18:24:50

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 6/6] rtc: rv3029: add alarm IRQ

Add the alarm IRQ functionality.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 114 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 93 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 42de1a3..152ca9d 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -329,6 +329,47 @@ static int rv3029_eeprom_update_bits(struct device *dev,
return 0;
}

+static irqreturn_t rv3029_handle_irq(int irq, void *dev_id)
+{
+ struct device *dev = dev_id;
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
+ struct mutex *lock = &rv3029->rtc->ops_lock;
+ unsigned long events = 0;
+ u8 flags, controls;
+ int ret;
+
+ mutex_lock(lock);
+
+ ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ if (ret) {
+ dev_warn(dev, "Read IRQ Control Register error %d\n", ret);
+ mutex_unlock(lock);
+ return IRQ_NONE;
+ }
+
+ ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
+ if (ret) {
+ dev_warn(dev, "Read IRQ Flags Register error %d\n", ret);
+ mutex_unlock(lock);
+ return IRQ_NONE;
+ }
+
+ if (flags & RV3029_IRQ_FLAGS_AF) {
+ flags &= ~RV3029_IRQ_FLAGS_AF;
+ controls &= ~RV3029_IRQ_CTRL_AIE;
+ events |= RTC_AF;
+ }
+
+ if (events) {
+ rtc_update_irq(rv3029->rtc, 1, events);
+ rv3029_write_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
+ rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ }
+ mutex_unlock(lock);
+
+ return IRQ_HANDLED;
+}
+
static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
{
u8 buf[1];
@@ -376,7 +417,7 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct rtc_time *const tm = &alarm->time;
int ret;
- u8 regs[8];
+ u8 regs[8], controls, flags;

ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
@@ -392,6 +433,17 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ret;
}

+ ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ if (ret) {
+ dev_err(dev, "Read IRQ Control Register error %d\n", ret);
+ return ret;
+ }
+ ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
+ if (ret < 0) {
+ dev_err(dev, "Read IRQ Flags Register error %d\n", ret);
+ return ret;
+ }
+
tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f);
tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f);
tm->tm_hour = bcd2bin(regs[RV3029_A_HR - RV3029_A_SC] & 0x3f);
@@ -400,16 +452,30 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
tm->tm_year = bcd2bin(regs[RV3029_A_YR - RV3029_A_SC] & 0x7f) + 100;
tm->tm_wday = bcd2bin(regs[RV3029_A_DW - RV3029_A_SC] & 0x07) - 1;

+ alarm->enabled = !!(controls & RV3029_IRQ_CTRL_AIE);
+ alarm->pending = (flags & RV3029_IRQ_FLAGS_AF) && alarm->enabled;
+
return 0;
}

-static int rv3029_rtc_alarm_set_irq(struct device *dev, int enable)
+static int rv3029_alarm_irq_enable(struct device *dev, unsigned int enable)
{
int ret;
+ u8 controls;
+
+ ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ if (ret < 0) {
+ dev_warn(dev, "Read IRQ Control Register error %d\n", ret);
+ return ret;
+ }

/* enable/disable AIE irq */
- ret = rv3029_update_bits(dev, RV3029_IRQ_CTRL, RV3029_IRQ_CTRL_AIE,
- (enable ? RV3029_IRQ_CTRL_AIE : 0));
+ if (enable)
+ controls |= RV3029_IRQ_CTRL_AIE;
+ else
+ controls &= ~RV3029_IRQ_CTRL_AIE;
+
+ ret = rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
if (ret < 0) {
dev_err(dev, "can't update INT reg\n");
return ret;
@@ -459,26 +525,15 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ret;

if (alarm->enabled) {
- /* clear AF flag */
- ret = rv3029_update_bits(dev, RV3029_IRQ_FLAGS,
- RV3029_IRQ_FLAGS_AF, 0);
- if (ret < 0) {
- dev_err(dev, "can't clear alarm flag\n");
- return ret;
- }
/* enable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(dev, 1);
+ ret = rv3029_alarm_irq_enable(dev, 1);
if (ret)
return ret;
-
- dev_dbg(dev, "alarm IRQ armed\n");
} else {
/* disable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(dev, 0);
+ ret = rv3029_alarm_irq_enable(dev, 0);
if (ret)
return ret;
-
- dev_dbg(dev, "alarm IRQ disabled\n");
}

return 0;
@@ -731,11 +786,9 @@ static void rv3029_hwmon_register(struct device *dev, const char *name)

#endif /* CONFIG_RTC_DRV_RV3029_HWMON */

-static const struct rtc_class_ops rv3029_rtc_ops = {
+static struct rtc_class_ops rv3029_rtc_ops = {
.read_time = rv3029_read_time,
.set_time = rv3029_set_time,
- .read_alarm = rv3029_read_alarm,
- .set_alarm = rv3029_set_alarm,
};

static struct i2c_device_id rv3029_id[] = {
@@ -772,8 +825,27 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,

rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
THIS_MODULE);
+ if (IS_ERR(rv3029->rtc)) {
+ dev_err(dev, "unable to register the class device\n");
+ return PTR_ERR(rv3029->rtc);
+ }

- return PTR_ERR_OR_ZERO(rv3029->rtc);
+ if (rv3029->irq > 0) {
+ rc = devm_request_threaded_irq(dev, rv3029->irq,
+ NULL, rv3029_handle_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "rv3029", dev);
+ if (rc) {
+ dev_warn(dev, "unable to request IRQ, alarms disabled\n");
+ rv3029->irq = 0;
+ } else {
+ rv3029_rtc_ops.read_alarm = rv3029_read_alarm;
+ rv3029_rtc_ops.set_alarm = rv3029_set_alarm;
+ rv3029_rtc_ops.alarm_irq_enable = rv3029_alarm_irq_enable;
+ }
+ }
+
+ return 0;
}

#if IS_ENABLED(CONFIG_I2C)
--
2.8.0.rc3

2016-04-21 18:24:42

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 3/6] rtc: rv3029: Add support of RV3049

Add support of Microcrystal RV3049 RTC (SPI) using regmap on the
RV3029 (I2C) driver.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/Kconfig | 37 +++++++--------
drivers/rtc/rtc-rv3029c2.c | 110 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 126 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index f1e1f50..18639e0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -573,24 +573,6 @@ config RTC_DRV_EM3027
This driver can also be built as a module. If so, the module
will be called rtc-em3027.

-config RTC_DRV_RV3029C2
- tristate "Micro Crystal RV3029"
- help
- If you say yes here you get support for the Micro Crystal
- RV3029 RTC chips.
-
- This driver can also be built as a module. If so, the module
- will be called rtc-rv3029c2.
-
-config RTC_DRV_RV3029_HWMON
- bool "HWMON support for RV3029"
- depends on RTC_DRV_RV3029C2 && HWMON
- depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
- default y
- help
- Say Y here if you want to expose temperature sensor data on
- rtc-rv3029.
-
config RTC_DRV_RV8803
tristate "Micro Crystal RV8803"
help
@@ -786,6 +768,25 @@ config RTC_DRV_PCF2127
This driver can also be built as a module. If so, the module
will be called rtc-pcf2127.

+config RTC_DRV_RV3029C2
+ tristate "Micro Crystal RV3029/3049"
+ depends on RTC_I2C_AND_SPI
+ help
+ If you say yes here you get support for the Micro Crystal
+ RV3029 and RV3049 RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-rv3029c2.
+
+config RTC_DRV_RV3029_HWMON
+ bool "HWMON support for RV3029/3049"
+ depends on RTC_DRV_RV3029C2 && HWMON
+ depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
+ default y
+ help
+ Say Y here if you want to expose temperature sensor data on
+ rtc-rv3029.
+
comment "Platform RTC drivers"

# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 96dd166..470cc1e 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -1,5 +1,5 @@
/*
- * Micro Crystal RV-3029 rtc class driver
+ * Micro Crystal RV-3029 / RV-3049 rtc class driver
*
* Author: Gregory Hermant <[email protected]>
* Michael Buesch <[email protected]>
@@ -14,6 +14,7 @@

#include <linux/module.h>
#include <linux/i2c.h>
+#include <linux/spi/spi.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/delay.h>
@@ -766,6 +767,8 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
return PTR_ERR_OR_ZERO(rv3029->rtc);
}

+#if IS_ENABLED(CONFIG_I2C)
+
static int rv3029_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -799,9 +802,110 @@ static struct i2c_driver rv3029_driver = {
.id_table = rv3029_id,
};

-module_i2c_driver(rv3029_driver);
+static int rv3029_register_driver(void)
+{
+ return i2c_add_driver(&rv3029_driver);
+}
+
+static void rv3029_unregister_driver(void)
+{
+ i2c_del_driver(&rv3029_driver);
+}
+
+#else
+
+static int rv3029_register_driver(void)
+{
+ return 0;
+}
+
+static void rv3029_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static int rv3049_probe(struct spi_device *spi)
+{
+ int res;
+ unsigned int tmp;
+ static const struct regmap_config config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ };
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_spi(spi, &config);
+ if (IS_ERR(regmap)) {
+ dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
+ __func__, PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ return rv3029_probe(&spi->dev, regmap, spi->irq, "rv3049");
+}
+
+static struct spi_driver rv3049_driver = {
+ .driver = {
+ .name = "rv3049",
+ },
+ .probe = rv3049_probe,
+};
+
+static int rv3049_register_driver(void)
+{
+ return spi_register_driver(&rv3049_driver);
+}
+
+static void rv3049_unregister_driver(void)
+{
+ spi_unregister_driver(&rv3049_driver);
+}
+
+#else
+
+static int rv3049_register_driver(void)
+{
+ return 0;
+}
+
+static void rv3049_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init rv30x9_init(void)
+{
+ int ret;
+
+ ret = rv3029_register_driver();
+ if (ret) {
+ pr_err("Failed to register rv3029 driver: %d\n", ret);
+ return ret;
+ }
+
+ ret = rv3049_register_driver();
+ if (ret) {
+ pr_err("Failed to register rv3049 driver: %d\n", ret);
+ rv3029_unregister_driver();
+ }
+
+ return ret;
+}
+module_init(rv30x9_init)
+
+static void __exit rv30x9_exit(void)
+{
+ rv3049_unregister_driver();
+ rv3029_unregister_driver();
+}
+module_exit(rv30x9_exit)

MODULE_AUTHOR("Gregory Hermant <[email protected]>");
MODULE_AUTHOR("Michael Buesch <[email protected]>");
-MODULE_DESCRIPTION("Micro Crystal RV3029 RTC driver");
+MODULE_DESCRIPTION("Micro Crystal RV3029/RV3049 RTC driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:rv3049");
--
2.8.0.rc3

2016-04-21 18:25:40

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH 5/6] rtc: rv3029: enable AE_x bits on set_alarm

The RTC RV3029 handles different types of alarms : seconds, minutes, ...
These alarms can be enabled or disabled individually using an AE_x bit
which is the last bit (BIT(7)) on each alarm registers.

To prepare the alarm IRQ support, the current code enables all the alarm
types by setting each AE_x to 1.
It also fixes month and weekday errors : it was performing -1 instead
of +1.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index a849005..42de1a3 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -76,6 +76,7 @@
#define RV3029_A_DW 0x14
#define RV3029_A_MO 0x15
#define RV3029_A_YR 0x16
+#define RV3029_A_AE_X BIT(7)
#define RV3029_ALARM_SECTION_LEN 0x07

/* timer section */
@@ -436,14 +437,22 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}
- regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
- regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
- regs[RV3029_A_HR - RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
- regs[RV3029_A_DT - RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
- regs[RV3029_A_MO - RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
- regs[RV3029_A_DW - RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
- regs[RV3029_A_YR - RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

+ /* Activate all the alarms with AE_x bit */
+ regs[RV3029_A_SC - RV3029_A_SC] = (bin2bcd(tm->tm_sec)) | RV3029_A_AE_X;
+ regs[RV3029_A_MN - RV3029_A_SC] = (bin2bcd(tm->tm_min)) | RV3029_A_AE_X;
+ regs[RV3029_A_HR - RV3029_A_SC] = (bin2bcd(tm->tm_hour & 0x3f))
+ | RV3029_A_AE_X;
+ regs[RV3029_A_DT - RV3029_A_SC] = (bin2bcd(tm->tm_mday & 0x3f))
+ | RV3029_A_AE_X;
+ regs[RV3029_A_MO - RV3029_A_SC] = (bin2bcd((tm->tm_mon & 0x1f) + 1))
+ | RV3029_A_AE_X;
+ regs[RV3029_A_DW - RV3029_A_SC] = (bin2bcd((tm->tm_wday & 7) + 1))
+ | RV3029_A_AE_X;
+ regs[RV3029_A_YR - RV3029_A_SC] = (bin2bcd((tm->tm_year) - 100))
+ | RV3029_A_AE_X;
+
+ /* Write the alarm */
ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);
if (ret < 0)
--
2.8.0.rc3

2016-04-22 23:30:09

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 4/6] rtc: rv3029: Removes some checks and warnings

Hi,

On 21/04/2016 at 20:24:17 +0200, Myl?ne Josserand wrote :
> @@ -829,8 +829,6 @@ static void rv3029_unregister_driver(void)
>
> static int rv3049_probe(struct spi_device *spi)
> {
> - int res;
> - unsigned int tmp;

Well, you just introduced those variables in the previous patch.

> static const struct regmap_config config = {
> .reg_bits = 8,
> .val_bits = 8,
> --
> 2.8.0.rc3
>

--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

2016-04-22 23:31:58

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 4/6] rtc: rv3029: Removes some checks and warnings

On 23/04/2016 at 01:29:46 +0200, Alexandre Belloni wrote :
> Hi,
>
> On 21/04/2016 at 20:24:17 +0200, Myl?ne Josserand wrote :
> > @@ -829,8 +829,6 @@ static void rv3029_unregister_driver(void)
> >
> > static int rv3049_probe(struct spi_device *spi)
> > {
> > - int res;
> > - unsigned int tmp;
>
> Well, you just introduced those variables in the previous patch.
>

And I forgot to add that you still have a few checkpatch warnings to
remove while at it:

WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
#129: FILE: drivers/rtc/rtc-rv3029c2.c:129:
+ unsigned len)

WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
#141: FILE: drivers/rtc/rtc-rv3029c2.c:141:
+ unsigned len)


--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

2016-04-22 23:37:30

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 5/6] rtc: rv3029: enable AE_x bits on set_alarm

On 21/04/2016 at 20:24:18 +0200, Myl?ne Josserand wrote :
> The RTC RV3029 handles different types of alarms : seconds, minutes, ...
> These alarms can be enabled or disabled individually using an AE_x bit
> which is the last bit (BIT(7)) on each alarm registers.
>
> To prepare the alarm IRQ support, the current code enables all the alarm
> types by setting each AE_x to 1.
> It also fixes month and weekday errors : it was performing -1 instead
> of +1.
>
> Signed-off-by: Myl?ne Josserand <[email protected]>
> ---
> drivers/rtc/rtc-rv3029c2.c | 23 ++++++++++++++++-------
> 1 file changed, 16 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
> index a849005..42de1a3 100644
> --- a/drivers/rtc/rtc-rv3029c2.c
> +++ b/drivers/rtc/rtc-rv3029c2.c
> @@ -76,6 +76,7 @@
> #define RV3029_A_DW 0x14
> #define RV3029_A_MO 0x15
> #define RV3029_A_YR 0x16
> +#define RV3029_A_AE_X BIT(7)
> #define RV3029_ALARM_SECTION_LEN 0x07
>
> /* timer section */
> @@ -436,14 +437,22 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> dev_err(dev, "%s: reading SR failed\n", __func__);
> return -EIO;
> }
> - regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
> - regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
> - regs[RV3029_A_HR - RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
> - regs[RV3029_A_DT - RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
> - regs[RV3029_A_MO - RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
> - regs[RV3029_A_DW - RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
> - regs[RV3029_A_YR - RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
>
> + /* Activate all the alarms with AE_x bit */
> + regs[RV3029_A_SC - RV3029_A_SC] = (bin2bcd(tm->tm_sec)) | RV3029_A_AE_X;
> + regs[RV3029_A_MN - RV3029_A_SC] = (bin2bcd(tm->tm_min)) | RV3029_A_AE_X;
> + regs[RV3029_A_HR - RV3029_A_SC] = (bin2bcd(tm->tm_hour & 0x3f))
> + | RV3029_A_AE_X;
> + regs[RV3029_A_DT - RV3029_A_SC] = (bin2bcd(tm->tm_mday & 0x3f))
> + | RV3029_A_AE_X;
> + regs[RV3029_A_MO - RV3029_A_SC] = (bin2bcd((tm->tm_mon & 0x1f) + 1))
> + | RV3029_A_AE_X;
> + regs[RV3029_A_DW - RV3029_A_SC] = (bin2bcd((tm->tm_wday & 7) + 1))
> + | RV3029_A_AE_X;
> + regs[RV3029_A_YR - RV3029_A_SC] = (bin2bcd((tm->tm_year) - 100))
> + | RV3029_A_AE_X;
> +

Alarms probably never worked anyway because this still suffers form
another bug:
(bin2bcd(tm->tm_hour & 0x3f)) should be (bin2bcd(tm->tm_hour) & 0x3f),
and the same for the other members.

note that (bin2bcd((tm->tm_mon & 0x1f) + 1)) must be
(bin2bcd(tm->tm_mon + 1) & 0x1f)

etc...

> + /* Write the alarm */
> ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
> RV3029_ALARM_SECTION_LEN);
> if (ret < 0)
> --
> 2.8.0.rc3
>

--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

2016-04-22 23:49:08

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH 6/6] rtc: rv3029: add alarm IRQ

On 21/04/2016 at 20:24:19 +0200, Myl?ne Josserand wrote :
> @@ -731,11 +786,9 @@ static void rv3029_hwmon_register(struct device *dev, const char *name)
>
> #endif /* CONFIG_RTC_DRV_RV3029_HWMON */
>
> -static const struct rtc_class_ops rv3029_rtc_ops = {
> +static struct rtc_class_ops rv3029_rtc_ops = {
> .read_time = rv3029_read_time,
> .set_time = rv3029_set_time,
> - .read_alarm = rv3029_read_alarm,
> - .set_alarm = rv3029_set_alarm,
> };
>
> static struct i2c_device_id rv3029_id[] = {
> @@ -772,8 +825,27 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
>
> rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
> THIS_MODULE);
> + if (IS_ERR(rv3029->rtc)) {
> + dev_err(dev, "unable to register the class device\n");
> + return PTR_ERR(rv3029->rtc);
> + }
>
> - return PTR_ERR_OR_ZERO(rv3029->rtc);
> + if (rv3029->irq > 0) {
> + rc = devm_request_threaded_irq(dev, rv3029->irq,
> + NULL, rv3029_handle_irq,
> + IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> + "rv3029", dev);
> + if (rc) {
> + dev_warn(dev, "unable to request IRQ, alarms disabled\n");
> + rv3029->irq = 0;
> + } else {
> + rv3029_rtc_ops.read_alarm = rv3029_read_alarm;
> + rv3029_rtc_ops.set_alarm = rv3029_set_alarm;
> + rv3029_rtc_ops.alarm_irq_enable = rv3029_alarm_irq_enable;
> + }
> + }
> +

While this work, devm_rtc_device_register() needs to know whether the
alarms are enabled and will try to call .read_alarm(). That is not
completely an issue right now and as we discussed, I'm planning to send
a rework of the rtc core to overcome that issue.

--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

2016-04-28 22:01:52

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 0/6] add support for Microcrystal RV-3049

The current patchset adds the support of the microcrystal RV-3049 (spi).
This RTC will use the same driver than RV-3029 by updating it to use regmap.
It also adds the alarm IRQ functionality.

V2 :
- Add some checks removal from checkpatch
- Fix the alarm support with a wrong use of bit mask on bin2bcd

Mylène Josserand (6):
rtc: rv3029: remove 'i2c' in functions names
rtc: rv3029: convert to use regmap
rtc: rv3029: Add support of RV3049
rtc: rv3029: Removes some checks and warnings
rtc: rv3029: fix alarm support
rtc: rv3029: add alarm IRQ

drivers/rtc/Kconfig | 37 +--
drivers/rtc/rtc-rv3029c2.c | 582 +++++++++++++++++++++++++++++----------------
2 files changed, 397 insertions(+), 222 deletions(-)

--
2.8.0.rc3

2016-04-28 22:02:01

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 1/6] rtc: rv3029: remove 'i2c' in functions names

To prepare the use of regmap to add the support of RV-3049, all the
'i2c' in functions's names are removed.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 132 ++++++++++++++++++++-------------------------
1 file changed, 57 insertions(+), 75 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index d0cbf08..091be48 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -116,9 +116,8 @@
#define RV3029_USR2_RAM_PAGE 0x3C
#define RV3029_USR2_SECTION_LEN 0x04

-static int
-rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
- unsigned len)
+static int rv3029_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
+ unsigned len)
{
int ret;

@@ -134,9 +133,8 @@ rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
return 0;
}

-static int
-rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
- unsigned len)
+static int rv3029_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+ unsigned len)
{
if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
@@ -145,28 +143,27 @@ rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
}

-static int
-rv3029_i2c_update_bits(struct i2c_client *client, u8 reg, u8 mask, u8 set)
+static int rv3029_update_bits(struct i2c_client *client, u8 reg, u8 mask,
+ u8 set)
{
u8 buf;
int ret;

- ret = rv3029_i2c_read_regs(client, reg, &buf, 1);
+ ret = rv3029_read_regs(client, reg, &buf, 1);
if (ret < 0)
return ret;
buf &= ~mask;
buf |= set & mask;
- ret = rv3029_i2c_write_regs(client, reg, &buf, 1);
+ ret = rv3029_write_regs(client, reg, &buf, 1);
if (ret < 0)
return ret;

return 0;
}

-static int
-rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf)
+static int rv3029_get_sr(struct i2c_client *client, u8 *buf)
{
- int ret = rv3029_i2c_read_regs(client, RV3029_STATUS, buf, 1);
+ int ret = rv3029_read_regs(client, RV3029_STATUS, buf, 1);

if (ret < 0)
return -EIO;
@@ -174,14 +171,13 @@ rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf)
return 0;
}

-static int
-rv3029_i2c_set_sr(struct i2c_client *client, u8 val)
+static int rv3029_set_sr(struct i2c_client *client, u8 val)
{
u8 buf[1];
int sr;

buf[0] = val;
- sr = rv3029_i2c_write_regs(client, RV3029_STATUS, buf, 1);
+ sr = rv3029_write_regs(client, RV3029_STATUS, buf, 1);
dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
if (sr < 0)
return -EIO;
@@ -194,7 +190,7 @@ static int rv3029_eeprom_busywait(struct i2c_client *client)
u8 sr;

for (i = 100; i > 0; i--) {
- ret = rv3029_i2c_get_sr(client, &sr);
+ ret = rv3029_get_sr(client, &sr);
if (ret < 0)
break;
if (!(sr & RV3029_STATUS_EEBUSY))
@@ -212,9 +208,9 @@ static int rv3029_eeprom_busywait(struct i2c_client *client)
static int rv3029_eeprom_exit(struct i2c_client *client)
{
/* Re-enable eeprom refresh */
- return rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
- RV3029_ONOFF_CTRL_EERE,
- RV3029_ONOFF_CTRL_EERE);
+ return rv3029_update_bits(client, RV3029_ONOFF_CTRL,
+ RV3029_ONOFF_CTRL_EERE,
+ RV3029_ONOFF_CTRL_EERE);
}

static int rv3029_eeprom_enter(struct i2c_client *client)
@@ -223,7 +219,7 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
u8 sr;

/* Check whether we are in the allowed voltage range. */
- ret = rv3029_i2c_get_sr(client, &sr);
+ ret = rv3029_get_sr(client, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
@@ -232,11 +228,11 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
*/
sr &= ~RV3029_STATUS_VLOW1;
sr &= ~RV3029_STATUS_VLOW2;
- ret = rv3029_i2c_set_sr(client, sr);
+ ret = rv3029_set_sr(client, sr);
if (ret < 0)
return ret;
usleep_range(1000, 10000);
- ret = rv3029_i2c_get_sr(client, &sr);
+ ret = rv3029_get_sr(client, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
@@ -247,8 +243,8 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
}

/* Disable eeprom refresh. */
- ret = rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
- RV3029_ONOFF_CTRL_EERE, 0);
+ ret = rv3029_update_bits(client, RV3029_ONOFF_CTRL,
+ RV3029_ONOFF_CTRL_EERE, 0);
if (ret < 0)
return ret;

@@ -269,7 +265,7 @@ static int rv3029_eeprom_read(struct i2c_client *client, u8 reg,
if (err < 0)
return err;

- ret = rv3029_i2c_read_regs(client, reg, buf, len);
+ ret = rv3029_read_regs(client, reg, buf, len);

err = rv3029_eeprom_exit(client);
if (err < 0)
@@ -290,11 +286,11 @@ static int rv3029_eeprom_write(struct i2c_client *client, u8 reg,
return err;

for (i = 0; i < len; i++, reg++) {
- ret = rv3029_i2c_read_regs(client, reg, &tmp, 1);
+ ret = rv3029_read_regs(client, reg, &tmp, 1);
if (ret < 0)
break;
if (tmp != buf[i]) {
- ret = rv3029_i2c_write_regs(client, reg, &buf[i], 1);
+ ret = rv3029_write_regs(client, reg, &buf[i], 1);
if (ret < 0)
break;
}
@@ -328,21 +324,20 @@ static int rv3029_eeprom_update_bits(struct i2c_client *client,
return 0;
}

-static int
-rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+static int rv3029_read_time(struct i2c_client *client, struct rtc_time *tm)
{
u8 buf[1];
int ret;
u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };

- ret = rv3029_i2c_get_sr(client, buf);
+ ret = rv3029_get_sr(client, buf);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_i2c_read_regs(client, RV3029_W_SEC, regs,
- RV3029_WATCH_SECTION_LEN);
+ ret = rv3029_read_regs(client, RV3029_W_SEC, regs,
+ RV3029_WATCH_SECTION_LEN);
if (ret < 0) {
dev_err(&client->dev, "%s: reading RTC section failed\n",
__func__);
@@ -375,24 +370,24 @@ rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)

static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- return rv3029_i2c_read_time(to_i2c_client(dev), tm);
+ return rv3029_read_time(to_i2c_client(dev), tm);
}

-static int
-rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+static int rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];

- ret = rv3029_i2c_get_sr(client, regs);
+ ret = rv3029_get_sr(client, regs);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_i2c_read_regs(client, RV3029_A_SC, regs,
- RV3029_ALARM_SECTION_LEN);
+ ret = rv3029_read_regs(client, RV3029_A_SC, regs,
+ RV3029_ALARM_SECTION_LEN);

if (ret < 0) {
dev_err(&client->dev, "%s: reading alarm section failed\n",
@@ -411,21 +406,14 @@ rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
return 0;
}

-static int
-rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-{
- return rv3029_i2c_read_alarm(to_i2c_client(dev), alarm);
-}
-
-static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client,
- int enable)
+static int rv3029_rtc_alarm_set_irq(struct i2c_client *client, int enable)
{
int ret;

/* enable/disable AIE irq */
- ret = rv3029_i2c_update_bits(client, RV3029_IRQ_CTRL,
- RV3029_IRQ_CTRL_AIE,
- (enable ? RV3029_IRQ_CTRL_AIE : 0));
+ ret = rv3029_update_bits(client, RV3029_IRQ_CTRL,
+ RV3029_IRQ_CTRL_AIE,
+ (enable ? RV3029_IRQ_CTRL_AIE : 0));
if (ret < 0) {
dev_err(&client->dev, "can't update INT reg\n");
return ret;
@@ -434,9 +422,9 @@ static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client,
return 0;
}

-static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
- struct rtc_wkalrm *alarm)
+static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];
@@ -449,7 +437,7 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
if (tm->tm_year < 100)
return -EINVAL;

- ret = rv3029_i2c_get_sr(client, regs);
+ ret = rv3029_get_sr(client, regs);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return -EIO;
@@ -462,28 +450,28 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

- ret = rv3029_i2c_write_regs(client, RV3029_A_SC, regs,
- RV3029_ALARM_SECTION_LEN);
+ ret = rv3029_write_regs(client, RV3029_A_SC, regs,
+ RV3029_ALARM_SECTION_LEN);
if (ret < 0)
return ret;

if (alarm->enabled) {
/* clear AF flag */
- ret = rv3029_i2c_update_bits(client, RV3029_IRQ_FLAGS,
- RV3029_IRQ_FLAGS_AF, 0);
+ ret = rv3029_update_bits(client, RV3029_IRQ_FLAGS,
+ RV3029_IRQ_FLAGS_AF, 0);
if (ret < 0) {
dev_err(&client->dev, "can't clear alarm flag\n");
return ret;
}
/* enable AIE irq */
- ret = rv3029_rtc_i2c_alarm_set_irq(client, 1);
+ ret = rv3029_rtc_alarm_set_irq(client, 1);
if (ret)
return ret;

dev_dbg(&client->dev, "alarm IRQ armed\n");
} else {
/* disable AIE irq */
- ret = rv3029_rtc_i2c_alarm_set_irq(client, 0);
+ ret = rv3029_rtc_alarm_set_irq(client, 0);
if (ret)
return ret;

@@ -493,13 +481,7 @@ static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
return 0;
}

-static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-{
- return rv3029_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
-}
-
-static int
-rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
+static int rv3029_set_time(struct i2c_client *client, struct rtc_time const *tm)
{
u8 regs[8];
int ret;
@@ -520,18 +502,18 @@ rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

- ret = rv3029_i2c_write_regs(client, RV3029_W_SEC, regs,
- RV3029_WATCH_SECTION_LEN);
+ ret = rv3029_write_regs(client, RV3029_W_SEC, regs,
+ RV3029_WATCH_SECTION_LEN);
if (ret < 0)
return ret;

- ret = rv3029_i2c_get_sr(client, regs);
+ ret = rv3029_get_sr(client, regs);
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return ret;
}
/* clear PON bit */
- ret = rv3029_i2c_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
+ ret = rv3029_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
if (ret < 0) {
dev_err(&client->dev, "%s: reading SR failed\n", __func__);
return ret;
@@ -542,7 +524,7 @@ rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)

static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- return rv3029_i2c_set_time(to_i2c_client(dev), tm);
+ return rv3029_set_time(to_i2c_client(dev), tm);
}

static const struct rv3029_trickle_tab_elem {
@@ -646,7 +628,7 @@ static int rv3029_read_temp(struct i2c_client *client, int *temp_mC)
int ret;
u8 temp;

- ret = rv3029_i2c_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
+ ret = rv3029_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
if (ret < 0)
return ret;

@@ -743,8 +725,8 @@ static void rv3029_hwmon_register(struct i2c_client *client)
&client->dev, client->name, client, rv3029_hwmon_groups);
if (IS_ERR(hwmon_dev)) {
dev_warn(&client->dev,
- "unable to register hwmon device %ld\n",
- PTR_ERR(hwmon_dev));
+ "unable to register hwmon device %ld\n",
+ PTR_ERR(hwmon_dev));
}
}

@@ -780,7 +762,7 @@ static int rv3029_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
return -ENODEV;

- rc = rv3029_i2c_get_sr(client, buf);
+ rc = rv3029_get_sr(client, buf);
if (rc < 0) {
dev_err(&client->dev, "reading status failed\n");
return rc;
--
2.8.0.rc3

2016-04-28 22:02:06

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 2/6] rtc: rv3029: convert to use regmap

To add support of rv3049, the current driver is converted to use regmap.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 275 +++++++++++++++++++++++----------------------
1 file changed, 142 insertions(+), 133 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 091be48..96dd166 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -20,7 +20,7 @@
#include <linux/of.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-
+#include <linux/regmap.h>

/* Register map */
/* control section */
@@ -116,81 +116,84 @@
#define RV3029_USR2_RAM_PAGE 0x3C
#define RV3029_USR2_SECTION_LEN 0x04

-static int rv3029_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
+struct rv3029_data {
+ struct device *dev;
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+ int irq;
+};
+
+static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf,
unsigned len)
{
- int ret;
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);

if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

- ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
- if (ret < 0)
- return ret;
- if (ret < len)
- return -EIO;
- return 0;
+ return regmap_bulk_read(rv3029->regmap, reg, buf, len);
}

-static int rv3029_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[],
unsigned len)
{
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
+
if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
(reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

- return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
+ return regmap_bulk_write(rv3029->regmap, reg, buf, len);
}

-static int rv3029_update_bits(struct i2c_client *client, u8 reg, u8 mask,
- u8 set)
+static int rv3029_update_bits(struct device *dev, u8 reg, u8 mask, u8 set)
{
u8 buf;
int ret;

- ret = rv3029_read_regs(client, reg, &buf, 1);
+ ret = rv3029_read_regs(dev, reg, &buf, 1);
if (ret < 0)
return ret;
buf &= ~mask;
buf |= set & mask;
- ret = rv3029_write_regs(client, reg, &buf, 1);
+ ret = rv3029_write_regs(dev, reg, &buf, 1);
if (ret < 0)
return ret;

return 0;
}

-static int rv3029_get_sr(struct i2c_client *client, u8 *buf)
+static int rv3029_get_sr(struct device *dev, u8 *buf)
{
- int ret = rv3029_read_regs(client, RV3029_STATUS, buf, 1);
+ int ret = rv3029_read_regs(dev, RV3029_STATUS, buf, 1);

if (ret < 0)
return -EIO;
- dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
+ dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
return 0;
}

-static int rv3029_set_sr(struct i2c_client *client, u8 val)
+static int rv3029_set_sr(struct device *dev, u8 val)
{
u8 buf[1];
int sr;

buf[0] = val;
- sr = rv3029_write_regs(client, RV3029_STATUS, buf, 1);
- dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
+ sr = rv3029_write_regs(dev, RV3029_STATUS, buf, 1);
+ dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
if (sr < 0)
return -EIO;
return 0;
}

-static int rv3029_eeprom_busywait(struct i2c_client *client)
+static int rv3029_eeprom_busywait(struct device *dev)
{
int i, ret;
u8 sr;

for (i = 100; i > 0; i--) {
- ret = rv3029_get_sr(client, &sr);
+ ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
break;
if (!(sr & RV3029_STATUS_EEBUSY))
@@ -198,28 +201,28 @@ static int rv3029_eeprom_busywait(struct i2c_client *client)
usleep_range(1000, 10000);
}
if (i <= 0) {
- dev_err(&client->dev, "EEPROM busy wait timeout.\n");
+ dev_err(dev, "EEPROM busy wait timeout.\n");
return -ETIMEDOUT;
}

return ret;
}

-static int rv3029_eeprom_exit(struct i2c_client *client)
+static int rv3029_eeprom_exit(struct device *dev)
{
/* Re-enable eeprom refresh */
- return rv3029_update_bits(client, RV3029_ONOFF_CTRL,
+ return rv3029_update_bits(dev, RV3029_ONOFF_CTRL,
RV3029_ONOFF_CTRL_EERE,
RV3029_ONOFF_CTRL_EERE);
}

-static int rv3029_eeprom_enter(struct i2c_client *client)
+static int rv3029_eeprom_enter(struct device *dev)
{
int ret;
u8 sr;

/* Check whether we are in the allowed voltage range. */
- ret = rv3029_get_sr(client, &sr);
+ ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
@@ -228,119 +231,118 @@ static int rv3029_eeprom_enter(struct i2c_client *client)
*/
sr &= ~RV3029_STATUS_VLOW1;
sr &= ~RV3029_STATUS_VLOW2;
- ret = rv3029_set_sr(client, sr);
+ ret = rv3029_set_sr(dev, sr);
if (ret < 0)
return ret;
usleep_range(1000, 10000);
- ret = rv3029_get_sr(client, &sr);
+ ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
- dev_err(&client->dev,
+ dev_err(dev,
"Supply voltage is too low to safely access the EEPROM.\n");
return -ENODEV;
}
}

/* Disable eeprom refresh. */
- ret = rv3029_update_bits(client, RV3029_ONOFF_CTRL,
- RV3029_ONOFF_CTRL_EERE, 0);
+ ret = rv3029_update_bits(dev, RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE,
+ 0);
if (ret < 0)
return ret;

/* Wait for any previous eeprom accesses to finish. */
- ret = rv3029_eeprom_busywait(client);
+ ret = rv3029_eeprom_busywait(dev);
if (ret < 0)
- rv3029_eeprom_exit(client);
+ rv3029_eeprom_exit(dev);

return ret;
}

-static int rv3029_eeprom_read(struct i2c_client *client, u8 reg,
+static int rv3029_eeprom_read(struct device *dev, u8 reg,
u8 buf[], size_t len)
{
int ret, err;

- err = rv3029_eeprom_enter(client);
+ err = rv3029_eeprom_enter(dev);
if (err < 0)
return err;

- ret = rv3029_read_regs(client, reg, buf, len);
+ ret = rv3029_read_regs(dev, reg, buf, len);

- err = rv3029_eeprom_exit(client);
+ err = rv3029_eeprom_exit(dev);
if (err < 0)
return err;

return ret;
}

-static int rv3029_eeprom_write(struct i2c_client *client, u8 reg,
+static int rv3029_eeprom_write(struct device *dev, u8 reg,
u8 const buf[], size_t len)
{
int ret, err;
size_t i;
u8 tmp;

- err = rv3029_eeprom_enter(client);
+ err = rv3029_eeprom_enter(dev);
if (err < 0)
return err;

for (i = 0; i < len; i++, reg++) {
- ret = rv3029_read_regs(client, reg, &tmp, 1);
+ ret = rv3029_read_regs(dev, reg, &tmp, 1);
if (ret < 0)
break;
if (tmp != buf[i]) {
- ret = rv3029_write_regs(client, reg, &buf[i], 1);
+ ret = rv3029_write_regs(dev, reg, &buf[i], 1);
if (ret < 0)
break;
}
- ret = rv3029_eeprom_busywait(client);
+ ret = rv3029_eeprom_busywait(dev);
if (ret < 0)
break;
}

- err = rv3029_eeprom_exit(client);
+ err = rv3029_eeprom_exit(dev);
if (err < 0)
return err;

return ret;
}

-static int rv3029_eeprom_update_bits(struct i2c_client *client,
+static int rv3029_eeprom_update_bits(struct device *dev,
u8 reg, u8 mask, u8 set)
{
u8 buf;
int ret;

- ret = rv3029_eeprom_read(client, reg, &buf, 1);
+ ret = rv3029_eeprom_read(dev, reg, &buf, 1);
if (ret < 0)
return ret;
buf &= ~mask;
buf |= set & mask;
- ret = rv3029_eeprom_write(client, reg, &buf, 1);
+ ret = rv3029_eeprom_write(dev, reg, &buf, 1);
if (ret < 0)
return ret;

return 0;
}

-static int rv3029_read_time(struct i2c_client *client, struct rtc_time *tm)
+static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
{
u8 buf[1];
int ret;
u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };

- ret = rv3029_get_sr(client, buf);
+ ret = rv3029_get_sr(dev, buf);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_read_regs(client, RV3029_W_SEC, regs,
+ ret = rv3029_read_regs(dev, RV3029_W_SEC, regs,
RV3029_WATCH_SECTION_LEN);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading RTC section failed\n",
- __func__);
+ dev_err(dev, "%s: reading RTC section failed\n", __func__);
return ret;
}

@@ -368,30 +370,23 @@ static int rv3029_read_time(struct i2c_client *client, struct rtc_time *tm)
return 0;
}

-static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return rv3029_read_time(to_i2c_client(dev), tm);
-}
-
-static int rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
- struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];

- ret = rv3029_get_sr(client, regs);
+ ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}

- ret = rv3029_read_regs(client, RV3029_A_SC, regs,
+ ret = rv3029_read_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);

if (ret < 0) {
- dev_err(&client->dev, "%s: reading alarm section failed\n",
- __func__);
+ dev_err(dev, "%s: reading alarm section failed\n", __func__);
return ret;
}

@@ -406,25 +401,23 @@ static int rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return 0;
}

-static int rv3029_rtc_alarm_set_irq(struct i2c_client *client, int enable)
+static int rv3029_rtc_alarm_set_irq(struct device *dev, int enable)
{
int ret;

/* enable/disable AIE irq */
- ret = rv3029_update_bits(client, RV3029_IRQ_CTRL,
- RV3029_IRQ_CTRL_AIE,
+ ret = rv3029_update_bits(dev, RV3029_IRQ_CTRL, RV3029_IRQ_CTRL_AIE,
(enable ? RV3029_IRQ_CTRL_AIE : 0));
if (ret < 0) {
- dev_err(&client->dev, "can't update INT reg\n");
+ dev_err(dev, "can't update INT reg\n");
return ret;
}

return 0;
}

-static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
- struct i2c_client *client = to_i2c_client(dev);
struct rtc_time *const tm = &alarm->time;
int ret;
u8 regs[8];
@@ -437,9 +430,9 @@ static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (tm->tm_year < 100)
return -EINVAL;

- ret = rv3029_get_sr(client, regs);
+ ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}
regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
@@ -450,38 +443,38 @@ static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

- ret = rv3029_write_regs(client, RV3029_A_SC, regs,
+ ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);
if (ret < 0)
return ret;

if (alarm->enabled) {
/* clear AF flag */
- ret = rv3029_update_bits(client, RV3029_IRQ_FLAGS,
+ ret = rv3029_update_bits(dev, RV3029_IRQ_FLAGS,
RV3029_IRQ_FLAGS_AF, 0);
if (ret < 0) {
- dev_err(&client->dev, "can't clear alarm flag\n");
+ dev_err(dev, "can't clear alarm flag\n");
return ret;
}
/* enable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(client, 1);
+ ret = rv3029_rtc_alarm_set_irq(dev, 1);
if (ret)
return ret;

- dev_dbg(&client->dev, "alarm IRQ armed\n");
+ dev_dbg(dev, "alarm IRQ armed\n");
} else {
/* disable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(client, 0);
+ ret = rv3029_rtc_alarm_set_irq(dev, 0);
if (ret)
return ret;

- dev_dbg(&client->dev, "alarm IRQ disabled\n");
+ dev_dbg(dev, "alarm IRQ disabled\n");
}

return 0;
}

-static int rv3029_set_time(struct i2c_client *client, struct rtc_time const *tm)
+static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
{
u8 regs[8];
int ret;
@@ -502,31 +495,25 @@ static int rv3029_set_time(struct i2c_client *client, struct rtc_time const *tm)
regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

- ret = rv3029_write_regs(client, RV3029_W_SEC, regs,
+ ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
RV3029_WATCH_SECTION_LEN);
if (ret < 0)
return ret;

- ret = rv3029_get_sr(client, regs);
+ ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return ret;
}
/* clear PON bit */
- ret = rv3029_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
+ ret = rv3029_set_sr(dev, (regs[0] & ~RV3029_STATUS_PON));
if (ret < 0) {
- dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ dev_err(dev, "%s: reading SR failed\n", __func__);
return ret;
}

return 0;
}
-
-static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return rv3029_set_time(to_i2c_client(dev), tm);
-}
-
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
@@ -584,9 +571,9 @@ static const struct rv3029_trickle_tab_elem {
},
};

-static void rv3029_trickle_config(struct i2c_client *client)
+static void rv3029_trickle_config(struct device *dev)
{
- struct device_node *of_node = client->dev.of_node;
+ struct device_node *of_node = dev->of_node;
const struct rv3029_trickle_tab_elem *elem;
int i, err;
u32 ohms;
@@ -608,27 +595,26 @@ static void rv3029_trickle_config(struct i2c_client *client)
break;
}
trickle_set_bits = elem->conf;
- dev_info(&client->dev,
+ dev_info(dev,
"Trickle charger enabled at %d ohms resistance.\n",
elem->r);
}
- err = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+ err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_TRICKLE_MASK,
trickle_set_bits);
if (err < 0) {
- dev_err(&client->dev,
- "Failed to update trickle charger config\n");
+ dev_err(dev, "Failed to update trickle charger config\n");
}
}

#ifdef CONFIG_RTC_DRV_RV3029_HWMON

-static int rv3029_read_temp(struct i2c_client *client, int *temp_mC)
+static int rv3029_read_temp(struct device *dev, int *temp_mC)
{
int ret;
u8 temp;

- ret = rv3029_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
+ ret = rv3029_read_regs(dev, RV3029_TEMP_PAGE, &temp, 1);
if (ret < 0)
return ret;

@@ -641,10 +627,9 @@ static ssize_t rv3029_hwmon_show_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = dev_get_drvdata(dev);
int ret, temp_mC;

- ret = rv3029_read_temp(client, &temp_mC);
+ ret = rv3029_read_temp(dev, &temp_mC);
if (ret < 0)
return ret;

@@ -656,7 +641,6 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = dev_get_drvdata(dev);
unsigned long interval_ms;
int ret;
u8 th_set_bits = 0;
@@ -670,7 +654,7 @@ static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
if (interval_ms >= 16000)
th_set_bits |= RV3029_EECTRL_THP;
}
- ret = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+ ret = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_EECTRL_THE | RV3029_EECTRL_THP,
th_set_bits);
if (ret < 0)
@@ -683,11 +667,10 @@ static ssize_t rv3029_hwmon_show_update_interval(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = dev_get_drvdata(dev);
int ret, interval_ms;
u8 eectrl;

- ret = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL,
+ ret = rv3029_eeprom_read(dev, RV3029_CONTROL_E2P_EECTRL,
&eectrl, 1);
if (ret < 0)
return ret;
@@ -717,32 +700,32 @@ static struct attribute *rv3029_hwmon_attrs[] = {
};
ATTRIBUTE_GROUPS(rv3029_hwmon);

-static void rv3029_hwmon_register(struct i2c_client *client)
+static void rv3029_hwmon_register(struct device *dev, const char *name)
{
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
struct device *hwmon_dev;

- hwmon_dev = devm_hwmon_device_register_with_groups(
- &client->dev, client->name, client, rv3029_hwmon_groups);
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, name, rv3029,
+ rv3029_hwmon_groups);
if (IS_ERR(hwmon_dev)) {
- dev_warn(&client->dev,
- "unable to register hwmon device %ld\n",
+ dev_warn(dev, "unable to register hwmon device %ld\n",
PTR_ERR(hwmon_dev));
}
}

#else /* CONFIG_RTC_DRV_RV3029_HWMON */

-static void rv3029_hwmon_register(struct i2c_client *client)
+static void rv3029_hwmon_register(struct device *dev, const char *name)
{
}

#endif /* CONFIG_RTC_DRV_RV3029_HWMON */

static const struct rtc_class_ops rv3029_rtc_ops = {
- .read_time = rv3029_rtc_read_time,
- .set_time = rv3029_rtc_set_time,
- .read_alarm = rv3029_rtc_read_alarm,
- .set_alarm = rv3029_rtc_set_alarm,
+ .read_time = rv3029_read_time,
+ .set_time = rv3029_set_time,
+ .read_alarm = rv3029_read_alarm,
+ .set_alarm = rv3029_set_alarm,
};

static struct i2c_device_id rv3029_id[] = {
@@ -752,41 +735,67 @@ static struct i2c_device_id rv3029_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rv3029_id);

-static int rv3029_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
+ const char *name)
{
- struct rtc_device *rtc;
+ struct rv3029_data *rv3029;
int rc = 0;
u8 buf[1];

- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
- return -ENODEV;
+ rv3029 = devm_kzalloc(dev, sizeof(*rv3029), GFP_KERNEL);
+ if (!rv3029)
+ return -ENOMEM;
+
+ rv3029->regmap = regmap;
+ rv3029->irq = irq;
+ rv3029->dev = dev;
+ dev_set_drvdata(dev, rv3029);

- rc = rv3029_get_sr(client, buf);
+ rc = rv3029_get_sr(dev, buf);
if (rc < 0) {
- dev_err(&client->dev, "reading status failed\n");
+ dev_err(dev, "reading status failed\n");
return rc;
}

- rv3029_trickle_config(client);
- rv3029_hwmon_register(client);
+ rv3029_trickle_config(dev);
+ rv3029_hwmon_register(dev, name);
+
+ rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
+ THIS_MODULE);

- rtc = devm_rtc_device_register(&client->dev, client->name,
- &rv3029_rtc_ops, THIS_MODULE);
+ return PTR_ERR_OR_ZERO(rv3029->rtc);
+}

- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+static int rv3029_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+ static const struct regmap_config config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ };
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
+ I2C_FUNC_SMBUS_BYTE)) {
+ dev_err(&client->dev, "Adapter does not support SMBUS_I2C_BLOCK or SMBUS_I2C_BYTE\n");
+ return -ENODEV;
+ }

- i2c_set_clientdata(client, rtc);
+ regmap = devm_regmap_init_i2c(client, &config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
+ __func__, PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }

- return 0;
+ return rv3029_probe(&client->dev, regmap, client->irq, client->name);
}

static struct i2c_driver rv3029_driver = {
.driver = {
.name = "rtc-rv3029c2",
},
- .probe = rv3029_probe,
+ .probe = rv3029_i2c_probe,
.id_table = rv3029_id,
};

--
2.8.0.rc3

2016-04-28 22:02:10

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 4/6] rtc: rv3029: Removes some checks and warnings

Removes some checks from checkpatch such as spaces around arithmetic
operations or prefer "unsigned int".

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 68 +++++++++++++++++++++++-----------------------
1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 1310646..cf8d465 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -125,24 +125,24 @@ struct rv3029_data {
};

static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf,
- unsigned len)
+ unsigned int len)
{
struct rv3029_data *rv3029 = dev_get_drvdata(dev);

if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
- (reg + len > RV3029_USR1_RAM_PAGE + 8))
+ (reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

return regmap_bulk_read(rv3029->regmap, reg, buf, len);
}

static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[],
- unsigned len)
+ unsigned int len)
{
struct rv3029_data *rv3029 = dev_get_drvdata(dev);

if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
- (reg + len > RV3029_USR1_RAM_PAGE + 8))
+ (reg + len > RV3029_USR1_RAM_PAGE + 8))
return -EINVAL;

return regmap_bulk_write(rv3029->regmap, reg, buf, len);
@@ -347,12 +347,12 @@ static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
return ret;
}

- tm->tm_sec = bcd2bin(regs[RV3029_W_SEC-RV3029_W_SEC]);
- tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES-RV3029_W_SEC]);
+ tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]);
+ tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]);

/* HR field has a more complex interpretation */
{
- const u8 _hr = regs[RV3029_W_HOURS-RV3029_W_SEC];
+ const u8 _hr = regs[RV3029_W_HOURS - RV3029_W_SEC];

if (_hr & RV3029_REG_HR_12_24) {
/* 12h format */
@@ -363,10 +363,10 @@ static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour = bcd2bin(_hr & 0x3f);
}

- tm->tm_mday = bcd2bin(regs[RV3029_W_DATE-RV3029_W_SEC]);
- tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS-RV3029_W_SEC]) - 1;
- tm->tm_year = bcd2bin(regs[RV3029_W_YEARS-RV3029_W_SEC]) + 100;
- tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS-RV3029_W_SEC]) - 1;
+ tm->tm_mday = bcd2bin(regs[RV3029_W_DATE - RV3029_W_SEC]);
+ tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS - RV3029_W_SEC]) - 1;
+ tm->tm_year = bcd2bin(regs[RV3029_W_YEARS - RV3029_W_SEC]) + 100;
+ tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS - RV3029_W_SEC]) - 1;

return 0;
}
@@ -391,13 +391,13 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ret;
}

- tm->tm_sec = bcd2bin(regs[RV3029_A_SC-RV3029_A_SC] & 0x7f);
- tm->tm_min = bcd2bin(regs[RV3029_A_MN-RV3029_A_SC] & 0x7f);
- tm->tm_hour = bcd2bin(regs[RV3029_A_HR-RV3029_A_SC] & 0x3f);
- tm->tm_mday = bcd2bin(regs[RV3029_A_DT-RV3029_A_SC] & 0x3f);
- tm->tm_mon = bcd2bin(regs[RV3029_A_MO-RV3029_A_SC] & 0x1f) - 1;
- tm->tm_year = bcd2bin(regs[RV3029_A_YR-RV3029_A_SC] & 0x7f) + 100;
- tm->tm_wday = bcd2bin(regs[RV3029_A_DW-RV3029_A_SC] & 0x07) - 1;
+ tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f);
+ tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f);
+ tm->tm_hour = bcd2bin(regs[RV3029_A_HR - RV3029_A_SC] & 0x3f);
+ tm->tm_mday = bcd2bin(regs[RV3029_A_DT - RV3029_A_SC] & 0x3f);
+ tm->tm_mon = bcd2bin(regs[RV3029_A_MO - RV3029_A_SC] & 0x1f) - 1;
+ tm->tm_year = bcd2bin(regs[RV3029_A_YR - RV3029_A_SC] & 0x7f) + 100;
+ tm->tm_wday = bcd2bin(regs[RV3029_A_DW - RV3029_A_SC] & 0x07) - 1;

return 0;
}
@@ -436,13 +436,13 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}
- regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
- regs[RV3029_A_MN-RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
- regs[RV3029_A_HR-RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
- regs[RV3029_A_DT-RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
- regs[RV3029_A_MO-RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
- regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
- regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
+ regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
+ regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
+ regs[RV3029_A_HR - RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
+ regs[RV3029_A_DT - RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
+ regs[RV3029_A_MO - RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
+ regs[RV3029_A_DW - RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
+ regs[RV3029_A_YR - RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);
@@ -488,13 +488,13 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
if (tm->tm_year < 100)
return -EINVAL;

- regs[RV3029_W_SEC-RV3029_W_SEC] = bin2bcd(tm->tm_sec);
- regs[RV3029_W_MINUTES-RV3029_W_SEC] = bin2bcd(tm->tm_min);
- regs[RV3029_W_HOURS-RV3029_W_SEC] = bin2bcd(tm->tm_hour);
- regs[RV3029_W_DATE-RV3029_W_SEC] = bin2bcd(tm->tm_mday);
- regs[RV3029_W_MONTHS-RV3029_W_SEC] = bin2bcd(tm->tm_mon+1);
- regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
- regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);
+ regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec);
+ regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min);
+ regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
+ regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday);
+ regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1);
+ regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7) + 1);
+ regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
RV3029_WATCH_SECTION_LEN);
@@ -515,6 +515,7 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)

return 0;
}
+
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
@@ -603,9 +604,8 @@ static void rv3029_trickle_config(struct device *dev)
err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_TRICKLE_MASK,
trickle_set_bits);
- if (err < 0) {
+ if (err < 0)
dev_err(dev, "Failed to update trickle charger config\n");
- }
}

#ifdef CONFIG_RTC_DRV_RV3029_HWMON
--
2.8.0.rc3

2016-04-28 22:02:30

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 6/6] rtc: rv3029: add alarm IRQ

Add the alarm IRQ functionality.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 114 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 93 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 916bbc2..c2ef64f 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -329,6 +329,47 @@ static int rv3029_eeprom_update_bits(struct device *dev,
return 0;
}

+static irqreturn_t rv3029_handle_irq(int irq, void *dev_id)
+{
+ struct device *dev = dev_id;
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
+ struct mutex *lock = &rv3029->rtc->ops_lock;
+ unsigned long events = 0;
+ u8 flags, controls;
+ int ret;
+
+ mutex_lock(lock);
+
+ ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ if (ret) {
+ dev_warn(dev, "Read IRQ Control Register error %d\n", ret);
+ mutex_unlock(lock);
+ return IRQ_NONE;
+ }
+
+ ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
+ if (ret) {
+ dev_warn(dev, "Read IRQ Flags Register error %d\n", ret);
+ mutex_unlock(lock);
+ return IRQ_NONE;
+ }
+
+ if (flags & RV3029_IRQ_FLAGS_AF) {
+ flags &= ~RV3029_IRQ_FLAGS_AF;
+ controls &= ~RV3029_IRQ_CTRL_AIE;
+ events |= RTC_AF;
+ }
+
+ if (events) {
+ rtc_update_irq(rv3029->rtc, 1, events);
+ rv3029_write_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
+ rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ }
+ mutex_unlock(lock);
+
+ return IRQ_HANDLED;
+}
+
static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
{
u8 buf[1];
@@ -376,7 +417,7 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct rtc_time *const tm = &alarm->time;
int ret;
- u8 regs[8];
+ u8 regs[8], controls, flags;

ret = rv3029_get_sr(dev, regs);
if (ret < 0) {
@@ -392,6 +433,17 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ret;
}

+ ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ if (ret) {
+ dev_err(dev, "Read IRQ Control Register error %d\n", ret);
+ return ret;
+ }
+ ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
+ if (ret < 0) {
+ dev_err(dev, "Read IRQ Flags Register error %d\n", ret);
+ return ret;
+ }
+
tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f);
tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f);
tm->tm_hour = bcd2bin(regs[RV3029_A_HR - RV3029_A_SC] & 0x3f);
@@ -400,16 +452,30 @@ static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
tm->tm_year = bcd2bin(regs[RV3029_A_YR - RV3029_A_SC] & 0x7f) + 100;
tm->tm_wday = bcd2bin(regs[RV3029_A_DW - RV3029_A_SC] & 0x07) - 1;

+ alarm->enabled = !!(controls & RV3029_IRQ_CTRL_AIE);
+ alarm->pending = (flags & RV3029_IRQ_FLAGS_AF) && alarm->enabled;
+
return 0;
}

-static int rv3029_rtc_alarm_set_irq(struct device *dev, int enable)
+static int rv3029_alarm_irq_enable(struct device *dev, unsigned int enable)
{
int ret;
+ u8 controls;
+
+ ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
+ if (ret < 0) {
+ dev_warn(dev, "Read IRQ Control Register error %d\n", ret);
+ return ret;
+ }

/* enable/disable AIE irq */
- ret = rv3029_update_bits(dev, RV3029_IRQ_CTRL, RV3029_IRQ_CTRL_AIE,
- (enable ? RV3029_IRQ_CTRL_AIE : 0));
+ if (enable)
+ controls |= RV3029_IRQ_CTRL_AIE;
+ else
+ controls &= ~RV3029_IRQ_CTRL_AIE;
+
+ ret = rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
if (ret < 0) {
dev_err(dev, "can't update INT reg\n");
return ret;
@@ -459,26 +525,15 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ret;

if (alarm->enabled) {
- /* clear AF flag */
- ret = rv3029_update_bits(dev, RV3029_IRQ_FLAGS,
- RV3029_IRQ_FLAGS_AF, 0);
- if (ret < 0) {
- dev_err(dev, "can't clear alarm flag\n");
- return ret;
- }
/* enable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(dev, 1);
+ ret = rv3029_alarm_irq_enable(dev, 1);
if (ret)
return ret;
-
- dev_dbg(dev, "alarm IRQ armed\n");
} else {
/* disable AIE irq */
- ret = rv3029_rtc_alarm_set_irq(dev, 0);
+ ret = rv3029_alarm_irq_enable(dev, 0);
if (ret)
return ret;
-
- dev_dbg(dev, "alarm IRQ disabled\n");
}

return 0;
@@ -731,11 +786,9 @@ static void rv3029_hwmon_register(struct device *dev, const char *name)

#endif /* CONFIG_RTC_DRV_RV3029_HWMON */

-static const struct rtc_class_ops rv3029_rtc_ops = {
+static struct rtc_class_ops rv3029_rtc_ops = {
.read_time = rv3029_read_time,
.set_time = rv3029_set_time,
- .read_alarm = rv3029_read_alarm,
- .set_alarm = rv3029_set_alarm,
};

static struct i2c_device_id rv3029_id[] = {
@@ -772,8 +825,27 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,

rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
THIS_MODULE);
+ if (IS_ERR(rv3029->rtc)) {
+ dev_err(dev, "unable to register the class device\n");
+ return PTR_ERR(rv3029->rtc);
+ }

- return PTR_ERR_OR_ZERO(rv3029->rtc);
+ if (rv3029->irq > 0) {
+ rc = devm_request_threaded_irq(dev, rv3029->irq,
+ NULL, rv3029_handle_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "rv3029", dev);
+ if (rc) {
+ dev_warn(dev, "unable to request IRQ, alarms disabled\n");
+ rv3029->irq = 0;
+ } else {
+ rv3029_rtc_ops.read_alarm = rv3029_read_alarm;
+ rv3029_rtc_ops.set_alarm = rv3029_set_alarm;
+ rv3029_rtc_ops.alarm_irq_enable = rv3029_alarm_irq_enable;
+ }
+ }
+
+ return 0;
}

#if IS_ENABLED(CONFIG_I2C)
--
2.8.0.rc3

2016-04-28 22:02:12

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 5/6] rtc: rv3029: fix alarm support

The RTC RV3029 handles different types of alarms : seconds, minutes, ...
These alarms can be enabled or disabled individually using an AE_x bit
which is the last bit (BIT(7)) on each alarm registers.

To prepare the alarm IRQ support, the current code enables all the alarm
types by setting each AE_x to 1.
It also fixes others alarms issues :
- month and weekday errors : it was performing -1 instead of +1.
- wrong use of bit mask with bin2bcd

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/rtc-rv3029c2.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index cf8d465..916bbc2 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -76,6 +76,7 @@
#define RV3029_A_DW 0x14
#define RV3029_A_MO 0x15
#define RV3029_A_YR 0x16
+#define RV3029_A_AE_X BIT(7)
#define RV3029_ALARM_SECTION_LEN 0x07

/* timer section */
@@ -436,14 +437,22 @@ static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
dev_err(dev, "%s: reading SR failed\n", __func__);
return -EIO;
}
- regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
- regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
- regs[RV3029_A_HR - RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
- regs[RV3029_A_DT - RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
- regs[RV3029_A_MO - RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
- regs[RV3029_A_DW - RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
- regs[RV3029_A_YR - RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);

+ /* Activate all the alarms with AE_x bit */
+ regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec) | RV3029_A_AE_X;
+ regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min) | RV3029_A_AE_X;
+ regs[RV3029_A_HR - RV3029_A_SC] = (bin2bcd(tm->tm_hour) & 0x3f)
+ | RV3029_A_AE_X;
+ regs[RV3029_A_DT - RV3029_A_SC] = (bin2bcd(tm->tm_mday) & 0x3f)
+ | RV3029_A_AE_X;
+ regs[RV3029_A_MO - RV3029_A_SC] = (bin2bcd(tm->tm_mon + 1) & 0x1f)
+ | RV3029_A_AE_X;
+ regs[RV3029_A_DW - RV3029_A_SC] = (bin2bcd(tm->tm_wday + 1) & 0x7)
+ | RV3029_A_AE_X;
+ regs[RV3029_A_YR - RV3029_A_SC] = (bin2bcd(tm->tm_year - 100))
+ | RV3029_A_AE_X;
+
+ /* Write the alarm */
ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
RV3029_ALARM_SECTION_LEN);
if (ret < 0)
@@ -493,7 +502,7 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday);
regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1);
- regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7) + 1);
+ regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd(tm->tm_wday + 1) & 0x7;
regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);

ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
--
2.8.0.rc3

2016-04-28 22:02:59

by Mylène Josserand

[permalink] [raw]
Subject: [PATCH V2 3/6] rtc: rv3029: Add support of RV3049

Add support of Microcrystal RV3049 RTC (SPI) using regmap on the
RV3029 (I2C) driver.

Signed-off-by: Mylène Josserand <[email protected]>
---
drivers/rtc/Kconfig | 37 ++++++++--------
drivers/rtc/rtc-rv3029c2.c | 108 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 124 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index f1e1f50..18639e0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -573,24 +573,6 @@ config RTC_DRV_EM3027
This driver can also be built as a module. If so, the module
will be called rtc-em3027.

-config RTC_DRV_RV3029C2
- tristate "Micro Crystal RV3029"
- help
- If you say yes here you get support for the Micro Crystal
- RV3029 RTC chips.
-
- This driver can also be built as a module. If so, the module
- will be called rtc-rv3029c2.
-
-config RTC_DRV_RV3029_HWMON
- bool "HWMON support for RV3029"
- depends on RTC_DRV_RV3029C2 && HWMON
- depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
- default y
- help
- Say Y here if you want to expose temperature sensor data on
- rtc-rv3029.
-
config RTC_DRV_RV8803
tristate "Micro Crystal RV8803"
help
@@ -786,6 +768,25 @@ config RTC_DRV_PCF2127
This driver can also be built as a module. If so, the module
will be called rtc-pcf2127.

+config RTC_DRV_RV3029C2
+ tristate "Micro Crystal RV3029/3049"
+ depends on RTC_I2C_AND_SPI
+ help
+ If you say yes here you get support for the Micro Crystal
+ RV3029 and RV3049 RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-rv3029c2.
+
+config RTC_DRV_RV3029_HWMON
+ bool "HWMON support for RV3029/3049"
+ depends on RTC_DRV_RV3029C2 && HWMON
+ depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
+ default y
+ help
+ Say Y here if you want to expose temperature sensor data on
+ rtc-rv3029.
+
comment "Platform RTC drivers"

# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 96dd166..1310646 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -1,5 +1,5 @@
/*
- * Micro Crystal RV-3029 rtc class driver
+ * Micro Crystal RV-3029 / RV-3049 rtc class driver
*
* Author: Gregory Hermant <[email protected]>
* Michael Buesch <[email protected]>
@@ -14,6 +14,7 @@

#include <linux/module.h>
#include <linux/i2c.h>
+#include <linux/spi/spi.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/delay.h>
@@ -766,6 +767,8 @@ static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
return PTR_ERR_OR_ZERO(rv3029->rtc);
}

+#if IS_ENABLED(CONFIG_I2C)
+
static int rv3029_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -799,9 +802,108 @@ static struct i2c_driver rv3029_driver = {
.id_table = rv3029_id,
};

-module_i2c_driver(rv3029_driver);
+static int rv3029_register_driver(void)
+{
+ return i2c_add_driver(&rv3029_driver);
+}
+
+static void rv3029_unregister_driver(void)
+{
+ i2c_del_driver(&rv3029_driver);
+}
+
+#else
+
+static int rv3029_register_driver(void)
+{
+ return 0;
+}
+
+static void rv3029_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static int rv3049_probe(struct spi_device *spi)
+{
+ static const struct regmap_config config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ };
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_spi(spi, &config);
+ if (IS_ERR(regmap)) {
+ dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
+ __func__, PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ return rv3029_probe(&spi->dev, regmap, spi->irq, "rv3049");
+}
+
+static struct spi_driver rv3049_driver = {
+ .driver = {
+ .name = "rv3049",
+ },
+ .probe = rv3049_probe,
+};
+
+static int rv3049_register_driver(void)
+{
+ return spi_register_driver(&rv3049_driver);
+}
+
+static void rv3049_unregister_driver(void)
+{
+ spi_unregister_driver(&rv3049_driver);
+}
+
+#else
+
+static int rv3049_register_driver(void)
+{
+ return 0;
+}
+
+static void rv3049_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init rv30x9_init(void)
+{
+ int ret;
+
+ ret = rv3029_register_driver();
+ if (ret) {
+ pr_err("Failed to register rv3029 driver: %d\n", ret);
+ return ret;
+ }
+
+ ret = rv3049_register_driver();
+ if (ret) {
+ pr_err("Failed to register rv3049 driver: %d\n", ret);
+ rv3029_unregister_driver();
+ }
+
+ return ret;
+}
+module_init(rv30x9_init)
+
+static void __exit rv30x9_exit(void)
+{
+ rv3049_unregister_driver();
+ rv3029_unregister_driver();
+}
+module_exit(rv30x9_exit)

MODULE_AUTHOR("Gregory Hermant <[email protected]>");
MODULE_AUTHOR("Michael Buesch <[email protected]>");
-MODULE_DESCRIPTION("Micro Crystal RV3029 RTC driver");
+MODULE_DESCRIPTION("Micro Crystal RV3029/RV3049 RTC driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:rv3049");
--
2.8.0.rc3