aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2017-06-02 14:26:49 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2017-06-02 14:26:49 +1000
commit1bc60b48157f140f72a98357b7f1f4eef12a887b (patch)
tree967934cca490351da7585579b8cc2d34b8105400
parent1c7f92e6a6adb3fafd1ba66e71e5f790169c7090 (diff)
parenta21512c1698d8106bcece0d24ff590dc92682678 (diff)
Merge remote-tracking branch 'rtc/rtc-next'
-rw-r--r--Documentation/rtc.txt44
-rw-r--r--drivers/rtc/interface.c9
-rw-r--r--drivers/rtc/rtc-ds1307.c604
-rw-r--r--drivers/rtc/rtc-m41t80.c251
-rw-r--r--drivers/rtc/rtc-opal.c10
5 files changed, 438 insertions, 480 deletions
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index ddc366026e00..47feb4414b7e 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -1,6 +1,6 @@
-
- Real Time Clock (RTC) Drivers for Linux
- =======================================
+=======================================
+Real Time Clock (RTC) Drivers for Linux
+=======================================
When Linux developers talk about a "Real Time Clock", they usually mean
something that tracks wall clock time and is battery backed so that it
@@ -32,8 +32,8 @@ only issue an alarm up to 24 hours in the future, other hardware may
be able to schedule one any time in the upcoming century.
- Old PC/AT-Compatible driver: /dev/rtc
- --------------------------------------
+Old PC/AT-Compatible driver: /dev/rtc
+--------------------------------------
All PCs (even Alpha machines) have a Real Time Clock built into them.
Usually they are built into the chipset of the computer, but some may
@@ -105,8 +105,8 @@ that will be using this driver. See the code at the end of this document.
(The original /dev/rtc driver was written by Paul Gortmaker.)
- New portable "RTC Class" drivers: /dev/rtcN
- --------------------------------------------
+New portable "RTC Class" drivers: /dev/rtcN
+--------------------------------------------
Because Linux supports many non-ACPI and non-PC platforms, some of which
have more than one RTC style clock, it needed a more portable solution
@@ -136,35 +136,37 @@ a high functionality RTC is integrated into the SOC. That system might read
the system clock from the discrete RTC, but use the integrated one for all
other tasks, because of its greater functionality.
-SYSFS INTERFACE
+SYSFS interface
---------------
The sysfs interface under /sys/class/rtc/rtcN provides access to various
rtc attributes without requiring the use of ioctls. All dates and times
are in the RTC's timezone, rather than in system time.
-date: RTC-provided date
-hctosys: 1 if the RTC provided the system time at boot via the
+================ ==============================================================
+date RTC-provided date
+hctosys 1 if the RTC provided the system time at boot via the
CONFIG_RTC_HCTOSYS kernel option, 0 otherwise
-max_user_freq: The maximum interrupt rate an unprivileged user may request
+max_user_freq The maximum interrupt rate an unprivileged user may request
from this RTC.
-name: The name of the RTC corresponding to this sysfs directory
-since_epoch: The number of seconds since the epoch according to the RTC
-time: RTC-provided time
-wakealarm: The time at which the clock will generate a system wakeup
+name The name of the RTC corresponding to this sysfs directory
+since_epoch The number of seconds since the epoch according to the RTC
+time RTC-provided time
+wakealarm The time at which the clock will generate a system wakeup
event. This is a one shot wakeup event, so must be reset
- after wake if a daily wakeup is required. Format is seconds since
- the epoch by default, or if there's a leading +, seconds in the
- future, or if there is a leading +=, seconds ahead of the current
- alarm.
-offset: The amount which the rtc clock has been adjusted in firmware.
+ after wake if a daily wakeup is required. Format is seconds
+ since the epoch by default, or if there's a leading +, seconds
+ in the future, or if there is a leading +=, seconds ahead of
+ the current alarm.
+offset The amount which the rtc clock has been adjusted in firmware.
Visible only if the driver supports clock offset adjustment.
The unit is parts per billion, i.e. The number of clock ticks
which are added to or removed from the rtc's base clock per
billion ticks. A positive value makes a day pass more slowly,
longer, and a negative value makes a day pass more quickly.
+================ ==============================================================
-IOCTL INTERFACE
+IOCTL interface
---------------
The ioctl() calls supported by /dev/rtc are also supported by the RTC class
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index fc0fa7577636..8cec9a02c0b8 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -227,6 +227,13 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
missing = year;
}
+ /* Can't proceed if alarm is still invalid after replacing
+ * missing fields.
+ */
+ err = rtc_valid_tm(&alarm->time);
+ if (err)
+ goto done;
+
/* with luck, no rollover is needed */
t_now = rtc_tm_to_time64(&now);
t_alm = rtc_tm_to_time64(&alarm->time);
@@ -278,9 +285,9 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
dev_warn(&rtc->dev, "alarm rollover not handled\n");
}
-done:
err = rtc_valid_tm(&alarm->time);
+done:
if (err) {
dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 77339b3d50a1..a264938500af 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -24,6 +24,7 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/clk-provider.h>
+#include <linux/regmap.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
@@ -120,12 +121,11 @@ struct ds1307 {
unsigned long flags;
#define HAS_NVRAM 0 /* bit 0 == sysfs file active */
#define HAS_ALARM 1 /* bit 1 == irq claimed */
- struct i2c_client *client;
+ struct device *dev;
+ struct regmap *regmap;
+ const char *name;
+ int irq;
struct rtc_device *rtc;
- s32 (*read_block_data)(const struct i2c_client *client, u8 command,
- u8 length, u8 *values);
- s32 (*write_block_data)(const struct i2c_client *client, u8 command,
- u8 length, const u8 *values);
#ifdef CONFIG_COMMON_CLK
struct clk_hw clks[2];
#endif
@@ -137,11 +137,11 @@ struct chip_desc {
u16 nvram_size;
u16 trickle_charger_reg;
u8 trickle_charger_setup;
- u8 (*do_trickle_setup)(struct i2c_client *, uint32_t, bool);
+ u8 (*do_trickle_setup)(struct ds1307 *, uint32_t,
+ bool);
};
-static u8 do_trickle_setup_ds1339(struct i2c_client *,
- uint32_t ohms, bool diode);
+static u8 do_trickle_setup_ds1339(struct ds1307 *, uint32_t ohms, bool diode);
static struct chip_desc chips[last_ds_type] = {
[ds_1307] = {
@@ -280,136 +280,6 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids);
#endif
-/*----------------------------------------------------------------------*/
-
-#define BLOCK_DATA_MAX_TRIES 10
-
-static s32 ds1307_read_block_data_once(const struct i2c_client *client,
- u8 command, u8 length, u8 *values)
-{
- s32 i, data;
-
- for (i = 0; i < length; i++) {
- data = i2c_smbus_read_byte_data(client, command + i);
- if (data < 0)
- return data;
- values[i] = data;
- }
- return i;
-}
-
-static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command,
- u8 length, u8 *values)
-{
- u8 oldvalues[255];
- s32 ret;
- int tries = 0;
-
- dev_dbg(&client->dev, "ds1307_read_block_data (length=%d)\n", length);
- ret = ds1307_read_block_data_once(client, command, length, values);
- if (ret < 0)
- return ret;
- do {
- if (++tries > BLOCK_DATA_MAX_TRIES) {
- dev_err(&client->dev,
- "ds1307_read_block_data failed\n");
- return -EIO;
- }
- memcpy(oldvalues, values, length);
- ret = ds1307_read_block_data_once(client, command, length,
- values);
- if (ret < 0)
- return ret;
- } while (memcmp(oldvalues, values, length));
- return length;
-}
-
-static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command,
- u8 length, const u8 *values)
-{
- u8 currvalues[255];
- int tries = 0;
-
- dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length);
- do {
- s32 i, ret;
-
- if (++tries > BLOCK_DATA_MAX_TRIES) {
- dev_err(&client->dev,
- "ds1307_write_block_data failed\n");
- return -EIO;
- }
- for (i = 0; i < length; i++) {
- ret = i2c_smbus_write_byte_data(client, command + i,
- values[i]);
- if (ret < 0)
- return ret;
- }
- ret = ds1307_read_block_data_once(client, command, length,
- currvalues);
- if (ret < 0)
- return ret;
- } while (memcmp(currvalues, values, length));
- return length;
-}
-
-/*----------------------------------------------------------------------*/
-
-/* These RTC devices are not designed to be connected to a SMbus adapter.
- SMbus limits block operations length to 32 bytes, whereas it's not
- limited on I2C buses. As a result, accesses may exceed 32 bytes;
- in that case, split them into smaller blocks */
-
-static s32 ds1307_native_smbus_write_block_data(const struct i2c_client *client,
- u8 command, u8 length, const u8 *values)
-{
- u8 suboffset = 0;
-
- if (length <= I2C_SMBUS_BLOCK_MAX) {
- s32 retval = i2c_smbus_write_i2c_block_data(client,
- command, length, values);
- if (retval < 0)
- return retval;
- return length;
- }
-
- while (suboffset < length) {
- s32 retval = i2c_smbus_write_i2c_block_data(client,
- command + suboffset,
- min(I2C_SMBUS_BLOCK_MAX, length - suboffset),
- values + suboffset);
- if (retval < 0)
- return retval;
-
- suboffset += I2C_SMBUS_BLOCK_MAX;
- }
- return length;
-}
-
-static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client,
- u8 command, u8 length, u8 *values)
-{
- u8 suboffset = 0;
-
- if (length <= I2C_SMBUS_BLOCK_MAX)
- return i2c_smbus_read_i2c_block_data(client,
- command, length, values);
-
- while (suboffset < length) {
- s32 retval = i2c_smbus_read_i2c_block_data(client,
- command + suboffset,
- min(I2C_SMBUS_BLOCK_MAX, length - suboffset),
- values + suboffset);
- if (retval < 0)
- return retval;
-
- suboffset += I2C_SMBUS_BLOCK_MAX;
- }
- return length;
-}
-
-/*----------------------------------------------------------------------*/
-
/*
* The ds1337 and ds1339 both have two alarms, but we only use the first
* one (with a "seconds" field). For ds1337 we expect nINTA is our alarm
@@ -417,26 +287,25 @@ static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client,
*/
static irqreturn_t ds1307_irq(int irq, void *dev_id)
{
- struct i2c_client *client = dev_id;
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = dev_id;
struct mutex *lock = &ds1307->rtc->ops_lock;
- int stat, control;
+ int stat, control, ret;
mutex_lock(lock);
- stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
- if (stat < 0)
+ ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &stat);
+ if (ret)
goto out;
if (stat & DS1337_BIT_A1I) {
stat &= ~DS1337_BIT_A1I;
- i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat);
+ regmap_write(ds1307->regmap, DS1337_REG_STATUS, stat);
- control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
- if (control < 0)
+ ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
+ if (ret)
goto out;
control &= ~DS1337_BIT_A1IE;
- i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
+ regmap_write(ds1307->regmap, DS1337_REG_CONTROL, control);
rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
}
@@ -452,14 +321,13 @@ out:
static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
- int tmp;
+ int tmp, ret;
/* read the RTC date and time registers all at once */
- tmp = ds1307->read_block_data(ds1307->client,
- ds1307->offset, 7, ds1307->regs);
- if (tmp != 7) {
- dev_err(dev, "%s error %d\n", "read", tmp);
- return -EIO;
+ ret = regmap_bulk_read(ds1307->regmap, ds1307->offset, ds1307->regs, 7);
+ if (ret) {
+ dev_err(dev, "%s error %d\n", "read", ret);
+ return ret;
}
dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs);
@@ -580,9 +448,8 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
dev_dbg(dev, "%s: %7ph\n", "write", buf);
- result = ds1307->write_block_data(ds1307->client,
- ds1307->offset, 7, buf);
- if (result < 0) {
+ result = regmap_bulk_write(ds1307->regmap, ds1307->offset, buf, 7);
+ if (result) {
dev_err(dev, "%s error %d\n", "write", result);
return result;
}
@@ -591,19 +458,18 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
int ret;
if (!test_bit(HAS_ALARM, &ds1307->flags))
return -EINVAL;
/* read all ALARM1, ALARM2, and status registers at once */
- ret = ds1307->read_block_data(client,
- DS1339_REG_ALARM1_SECS, 9, ds1307->regs);
- if (ret != 9) {
+ ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS,
+ ds1307->regs, 9);
+ if (ret) {
dev_err(dev, "%s error %d\n", "alarm read", ret);
- return -EIO;
+ return ret;
}
dev_dbg(dev, "%s: %4ph, %3ph, %2ph\n", "alarm read",
@@ -633,8 +499,7 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
unsigned char *buf = ds1307->regs;
u8 control, status;
int ret;
@@ -649,11 +514,10 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
t->enabled, t->pending);
/* read current status of both alarms and the chip */
- ret = ds1307->read_block_data(client,
- DS1339_REG_ALARM1_SECS, 9, buf);
- if (ret != 9) {
+ ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, buf, 9);
+ if (ret) {
dev_err(dev, "%s error %d\n", "alarm write", ret);
- return -EIO;
+ return ret;
}
control = ds1307->regs[7];
status = ds1307->regs[8];
@@ -676,9 +540,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE);
buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
- ret = ds1307->write_block_data(client,
- DS1339_REG_ALARM1_SECS, 9, buf);
- if (ret < 0) {
+ ret = regmap_bulk_write(ds1307->regmap, DS1339_REG_ALARM1_SECS, buf, 9);
+ if (ret) {
dev_err(dev, "can't set alarm time\n");
return ret;
}
@@ -687,7 +550,7 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
if (t->enabled) {
dev_dbg(dev, "alarm IRQ armed\n");
buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */
- i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, buf[7]);
+ regmap_write(ds1307->regmap, DS1337_REG_CONTROL, buf[7]);
}
return 0;
@@ -695,27 +558,22 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
- int ret;
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ int control, ret;
if (!test_bit(HAS_ALARM, &ds1307->flags))
return -ENOTTY;
- ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
- if (ret < 0)
+ ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
+ if (ret)
return ret;
if (enabled)
- ret |= DS1337_BIT_A1IE;
+ control |= DS1337_BIT_A1IE;
else
- ret &= ~DS1337_BIT_A1IE;
-
- ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, ret);
- if (ret < 0)
- return ret;
+ control &= ~DS1337_BIT_A1IE;
- return 0;
+ return regmap_write(ds1307->regmap, DS1337_REG_CONTROL, control);
}
static const struct rtc_class_ops ds13xx_rtc_ops = {
@@ -752,31 +610,30 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
{
- struct i2c_client *client = dev_id;
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = dev_id;
struct mutex *lock = &ds1307->rtc->ops_lock;
int reg, ret;
mutex_lock(lock);
/* Check and clear alarm 0 interrupt flag. */
- reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_ALARM0_CTRL);
- if (reg < 0)
+ ret = regmap_read(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, &reg);
+ if (ret)
goto out;
if (!(reg & MCP794XX_BIT_ALMX_IF))
goto out;
reg &= ~MCP794XX_BIT_ALMX_IF;
- ret = i2c_smbus_write_byte_data(client, MCP794XX_REG_ALARM0_CTRL, reg);
- if (ret < 0)
+ ret = regmap_write(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, reg);
+ if (ret)
goto out;
/* Disable alarm 0. */
- reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_CONTROL);
- if (reg < 0)
+ ret = regmap_read(ds1307->regmap, MCP794XX_REG_CONTROL, &reg);
+ if (ret)
goto out;
reg &= ~MCP794XX_BIT_ALM0_EN;
- ret = i2c_smbus_write_byte_data(client, MCP794XX_REG_CONTROL, reg);
- if (ret < 0)
+ ret = regmap_write(ds1307->regmap, MCP794XX_REG_CONTROL, reg);
+ if (ret)
goto out;
rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
@@ -789,8 +646,7 @@ out:
static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
u8 *regs = ds1307->regs;
int ret;
@@ -798,8 +654,8 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
return -EINVAL;
/* Read control and alarm 0 registers. */
- ret = ds1307->read_block_data(client, MCP794XX_REG_CONTROL, 10, regs);
- if (ret < 0)
+ ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10);
+ if (ret)
return ret;
t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN);
@@ -828,8 +684,7 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
unsigned char *regs = ds1307->regs;
int ret;
@@ -843,8 +698,8 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
t->enabled, t->pending);
/* Read control and alarm 0 registers. */
- ret = ds1307->read_block_data(client, MCP794XX_REG_CONTROL, 10, regs);
- if (ret < 0)
+ ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10);
+ if (ret)
return ret;
/* Set alarm 0, using 24-hour and day-of-month modes. */
@@ -862,35 +717,34 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
/* Disable interrupt. We will not enable until completely programmed */
regs[0] &= ~MCP794XX_BIT_ALM0_EN;
- ret = ds1307->write_block_data(client, MCP794XX_REG_CONTROL, 10, regs);
- if (ret < 0)
+ ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10);
+ if (ret)
return ret;
if (!t->enabled)
return 0;
regs[0] |= MCP794XX_BIT_ALM0_EN;
- return i2c_smbus_write_byte_data(client, MCP794XX_REG_CONTROL, regs[0]);
+ return regmap_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs[0]);
}
static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
- int reg;
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ int reg, ret;
if (!test_bit(HAS_ALARM, &ds1307->flags))
return -EINVAL;
- reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_CONTROL);
- if (reg < 0)
- return reg;
+ ret = regmap_read(ds1307->regmap, MCP794XX_REG_CONTROL, &reg);
+ if (ret)
+ return ret;
if (enabled)
reg |= MCP794XX_BIT_ALM0_EN;
else
reg &= ~MCP794XX_BIT_ALM0_EN;
- return i2c_smbus_write_byte_data(client, MCP794XX_REG_CONTROL, reg);
+ return regmap_write(ds1307->regmap, MCP794XX_REG_CONTROL, reg);
}
static const struct rtc_class_ops mcp794xx_rtc_ops = {
@@ -908,17 +762,15 @@ ds1307_nvram_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
- struct i2c_client *client;
struct ds1307 *ds1307;
int result;
- client = kobj_to_i2c_client(kobj);
- ds1307 = i2c_get_clientdata(client);
+ ds1307 = dev_get_drvdata(kobj_to_dev(kobj));
- result = ds1307->read_block_data(client, ds1307->nvram_offset + off,
- count, buf);
- if (result < 0)
- dev_err(&client->dev, "%s error %d\n", "nvram read", result);
+ result = regmap_bulk_read(ds1307->regmap, ds1307->nvram_offset + off,
+ buf, count);
+ if (result)
+ dev_err(ds1307->dev, "%s error %d\n", "nvram read", result);
return result;
}
@@ -927,17 +779,15 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
- struct i2c_client *client;
struct ds1307 *ds1307;
int result;
- client = kobj_to_i2c_client(kobj);
- ds1307 = i2c_get_clientdata(client);
+ ds1307 = dev_get_drvdata(kobj_to_dev(kobj));
- result = ds1307->write_block_data(client, ds1307->nvram_offset + off,
- count, buf);
- if (result < 0) {
- dev_err(&client->dev, "%s error %d\n", "nvram write", result);
+ result = regmap_bulk_write(ds1307->regmap, ds1307->nvram_offset + off,
+ buf, count);
+ if (result) {
+ dev_err(ds1307->dev, "%s error %d\n", "nvram write", result);
return result;
}
return count;
@@ -946,7 +796,7 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
/*----------------------------------------------------------------------*/
-static u8 do_trickle_setup_ds1339(struct i2c_client *client,
+static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307,
uint32_t ohms, bool diode)
{
u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
@@ -963,14 +813,14 @@ static u8 do_trickle_setup_ds1339(struct i2c_client *client,
setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
break;
default:
- dev_warn(&client->dev,
+ dev_warn(ds1307->dev,
"Unsupported ohm value %u in dt\n", ohms);
return 0;
}
return setup;
}
-static void ds1307_trickle_init(struct i2c_client *client,
+static void ds1307_trickle_init(struct ds1307 *ds1307,
struct chip_desc *chip)
{
uint32_t ohms = 0;
@@ -978,11 +828,12 @@ static void ds1307_trickle_init(struct i2c_client *client,
if (!chip->do_trickle_setup)
goto out;
- if (device_property_read_u32(&client->dev, "trickle-resistor-ohms", &ohms))
+ if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms",
+ &ohms))
goto out;
- if (device_property_read_bool(&client->dev, "trickle-diode-disable"))
+ if (device_property_read_bool(ds1307->dev, "trickle-diode-disable"))
diode = false;
- chip->trickle_charger_setup = chip->do_trickle_setup(client,
+ chip->trickle_charger_setup = chip->do_trickle_setup(ds1307,
ohms, diode);
out:
return;
@@ -1009,13 +860,10 @@ static int ds3231_hwmon_read_temp(struct device *dev, s32 *mC)
s16 temp;
int ret;
- ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE,
- sizeof(temp_buf), temp_buf);
- if (ret < 0)
+ ret = regmap_bulk_read(ds1307->regmap, DS3231_REG_TEMPERATURE,
+ temp_buf, sizeof(temp_buf));
+ if (ret)
return ret;
- if (ret != sizeof(temp_buf))
- return -EIO;
-
/*
* Temperature is represented as a 10-bit code with a resolution of
* 0.25 degree celsius and encoded in two's complement format.
@@ -1055,12 +903,11 @@ static void ds1307_hwmon_register(struct ds1307 *ds1307)
if (ds1307->type != ds_3231)
return;
- dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev,
- ds1307->client->name,
+ dev = devm_hwmon_device_register_with_groups(ds1307->dev, ds1307->name,
ds1307, ds3231_hwmon_groups);
if (IS_ERR(dev)) {
- dev_warn(&ds1307->client->dev,
- "unable to register hwmon device %ld\n", PTR_ERR(dev));
+ dev_warn(ds1307->dev, "unable to register hwmon device %ld\n",
+ PTR_ERR(dev));
}
}
@@ -1099,23 +946,20 @@ static int ds3231_clk_sqw_rates[] = {
static int ds1337_write_control(struct ds1307 *ds1307, u8 mask, u8 value)
{
- struct i2c_client *client = ds1307->client;
struct mutex *lock = &ds1307->rtc->ops_lock;
int control;
int ret;
mutex_lock(lock);
- control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
- if (control < 0) {
- ret = control;
+ ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
+ if (ret)
goto out;
- }
control &= ~mask;
control |= value;
- ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
+ ret = regmap_write(ds1307->regmap, DS1337_REG_CONTROL, control);
out:
mutex_unlock(lock);
@@ -1126,12 +970,12 @@ static unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
- int control;
+ int control, ret;
int rate_sel = 0;
- control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
- if (control < 0)
- return control;
+ ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
+ if (ret)
+ return ret;
if (control & DS1337_BIT_RS1)
rate_sel += 1;
if (control & DS1337_BIT_RS2)
@@ -1195,11 +1039,11 @@ static void ds3231_clk_sqw_unprepare(struct clk_hw *hw)
static int ds3231_clk_sqw_is_prepared(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
- int control;
+ int control, ret;
- control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
- if (control < 0)
- return control;
+ ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
+ if (ret)
+ return ret;
return !(control & DS1337_BIT_INTCN);
}
@@ -1221,25 +1065,22 @@ static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw,
static int ds3231_clk_32khz_control(struct ds1307 *ds1307, bool enable)
{
- struct i2c_client *client = ds1307->client;
struct mutex *lock = &ds1307->rtc->ops_lock;
int status;
int ret;
mutex_lock(lock);
- status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
- if (status < 0) {
- ret = status;
+ ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &status);
+ if (ret)
goto out;
- }
if (enable)
status |= DS3231_BIT_EN32KHZ;
else
status &= ~DS3231_BIT_EN32KHZ;
- ret = i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, status);
+ ret = regmap_write(ds1307->regmap, DS1337_REG_STATUS, status);
out:
mutex_unlock(lock);
@@ -1263,11 +1104,11 @@ static void ds3231_clk_32khz_unprepare(struct clk_hw *hw)
static int ds3231_clk_32khz_is_prepared(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
- int status;
+ int status, ret;
- status = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_STATUS);
- if (status < 0)
- return status;
+ ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &status);
+ if (ret)
+ return ret;
return !!(status & DS3231_BIT_EN32KHZ);
}
@@ -1292,18 +1133,17 @@ static struct clk_init_data ds3231_clks_init[] = {
static int ds3231_clks_register(struct ds1307 *ds1307)
{
- struct i2c_client *client = ds1307->client;
- struct device_node *node = client->dev.of_node;
+ struct device_node *node = ds1307->dev->of_node;
struct clk_onecell_data *onecell;
int i;
- onecell = devm_kzalloc(&client->dev, sizeof(*onecell), GFP_KERNEL);
+ onecell = devm_kzalloc(ds1307->dev, sizeof(*onecell), GFP_KERNEL);
if (!onecell)
return -ENOMEM;
onecell->clk_num = ARRAY_SIZE(ds3231_clks_init);
- onecell->clks = devm_kcalloc(&client->dev, onecell->clk_num,
- sizeof(onecell->clks[0]), GFP_KERNEL);
+ onecell->clks = devm_kcalloc(ds1307->dev, onecell->clk_num,
+ sizeof(onecell->clks[0]), GFP_KERNEL);
if (!onecell->clks)
return -ENOMEM;
@@ -1322,8 +1162,8 @@ static int ds3231_clks_register(struct ds1307 *ds1307)
&init.name);
ds1307->clks[i].init = &init;
- onecell->clks[i] = devm_clk_register(&client->dev,
- &ds1307->clks[i]);
+ onecell->clks[i] = devm_clk_register(ds1307->dev,
+ &ds1307->clks[i]);
if (IS_ERR(onecell->clks[i]))
return PTR_ERR(onecell->clks[i]);
}
@@ -1345,8 +1185,8 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
ret = ds3231_clks_register(ds1307);
if (ret) {
- dev_warn(&ds1307->client->dev,
- "unable to register clock device %d\n", ret);
+ dev_warn(ds1307->dev, "unable to register clock device %d\n",
+ ret);
}
}
@@ -1358,6 +1198,12 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
#endif /* CONFIG_COMMON_CLK */
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x12,
+};
+
static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1365,7 +1211,6 @@ static int ds1307_probe(struct i2c_client *client,
int err = -ENODEV;
int tmp, wday;
struct chip_desc *chip;
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
bool ds1307_can_wakeup_device = false;
unsigned char *buf;
@@ -1382,17 +1227,22 @@ static int ds1307_probe(struct i2c_client *client,
};
const struct rtc_class_ops *rtc_ops = &ds13xx_rtc_ops;
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)
- && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
- return -EIO;
-
ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
if (!ds1307)
return -ENOMEM;
- i2c_set_clientdata(client, ds1307);
+ dev_set_drvdata(&client->dev, ds1307);
+ ds1307->dev = &client->dev;
+ ds1307->name = client->name;
+ ds1307->irq = client->irq;
+
+ ds1307->regmap = devm_regmap_init_i2c(client, &regmap_config);
+ if (IS_ERR(ds1307->regmap)) {
+ dev_err(ds1307->dev, "regmap allocation failed\n");
+ return PTR_ERR(ds1307->regmap);
+ }
- ds1307->client = client;
+ i2c_set_clientdata(client, ds1307);
if (client->dev.of_node) {
ds1307->type = (enum ds_type)
@@ -1405,7 +1255,7 @@ static int ds1307_probe(struct i2c_client *client,
const struct acpi_device_id *acpi_id;
acpi_id = acpi_match_device(ACPI_PTR(ds1307_acpi_ids),
- &client->dev);
+ ds1307->dev);
if (!acpi_id)
return -ENODEV;
chip = &chips[acpi_id->driver_data];
@@ -1413,27 +1263,21 @@ static int ds1307_probe(struct i2c_client *client,
}
if (!pdata)
- ds1307_trickle_init(client, chip);
+ ds1307_trickle_init(ds1307, chip);
else if (pdata->trickle_charger_setup)
chip->trickle_charger_setup = pdata->trickle_charger_setup;
if (chip->trickle_charger_setup && chip->trickle_charger_reg) {
- dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n",
+ dev_dbg(ds1307->dev,
+ "writing trickle charger info 0x%x to 0x%x\n",
DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup,
chip->trickle_charger_reg);
- i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
+ regmap_write(ds1307->regmap, chip->trickle_charger_reg,
DS13XX_TRICKLE_CHARGER_MAGIC |
chip->trickle_charger_setup);
}
buf = ds1307->regs;
- if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
- ds1307->read_block_data = ds1307_native_smbus_read_block_data;
- ds1307->write_block_data = ds1307_native_smbus_write_block_data;
- } else {
- ds1307->read_block_data = ds1307_read_block_data;
- ds1307->write_block_data = ds1307_write_block_data;
- }
#ifdef CONFIG_OF
/*
@@ -1459,11 +1303,10 @@ static int ds1307_probe(struct i2c_client *client,
case ds_1339:
case ds_3231:
/* get registers that the "rtc" read below won't read... */
- tmp = ds1307->read_block_data(ds1307->client,
- DS1337_REG_CONTROL, 2, buf);
- if (tmp != 2) {
- dev_dbg(&client->dev, "read error %d\n", tmp);
- err = -EIO;
+ err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
+ buf, 2);
+ if (err) {
+ dev_dbg(ds1307->dev, "read error %d\n", err);
goto exit;
}
@@ -1477,8 +1320,8 @@ static int ds1307_probe(struct i2c_client *client,
* For some variants, be sure alarms can trigger when we're
* running on Vbackup (BBSQI/BBSQW)
*/
- if (chip->alarm && (ds1307->client->irq > 0 ||
- ds1307_can_wakeup_device)) {
+ if (chip->alarm && (ds1307->irq > 0 ||
+ ds1307_can_wakeup_device)) {
ds1307->regs[0] |= DS1337_BIT_INTCN
| bbsqi_bitpos[ds1307->type];
ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
@@ -1486,50 +1329,49 @@ static int ds1307_probe(struct i2c_client *client,
want_irq = true;
}
- i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
- ds1307->regs[0]);
+ regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
+ ds1307->regs[0]);
/* oscillator fault? clear flag, and warn */
if (ds1307->regs[1] & DS1337_BIT_OSF) {
- i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
- ds1307->regs[1] & ~DS1337_BIT_OSF);
- dev_warn(&client->dev, "SET TIME!\n");
+ regmap_write(ds1307->regmap, DS1337_REG_STATUS,
+ ds1307->regs[1] & ~DS1337_BIT_OSF);
+ dev_warn(ds1307->dev, "SET TIME!\n");
}
break;
case rx_8025:
- tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
- RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
- if (tmp != 2) {
- dev_dbg(&client->dev, "read error %d\n", tmp);
- err = -EIO;
+ err = regmap_bulk_read(ds1307->regmap,
+ RX8025_REG_CTRL1 << 4 | 0x08, buf, 2);
+ if (err) {
+ dev_dbg(ds1307->dev, "read error %d\n", err);
goto exit;
}
/* oscillator off? turn it on, so clock can tick. */
if (!(ds1307->regs[1] & RX8025_BIT_XST)) {
ds1307->regs[1] |= RX8025_BIT_XST;
- i2c_smbus_write_byte_data(client,
- RX8025_REG_CTRL2 << 4 | 0x08,
- ds1307->regs[1]);
- dev_warn(&client->dev,
+ regmap_write(ds1307->regmap,
+ RX8025_REG_CTRL2 << 4 | 0x08,
+ ds1307->regs[1]);
+ dev_warn(ds1307->dev,
"oscillator stop detected - SET TIME!\n");
}
if (ds1307->regs[1] & RX8025_BIT_PON) {
ds1307->regs[1] &= ~RX8025_BIT_PON;
- i2c_smbus_write_byte_data(client,
- RX8025_REG_CTRL2 << 4 | 0x08,
- ds1307->regs[1]);
- dev_warn(&client->dev, "power-on detected\n");
+ regmap_write(ds1307->regmap,
+ RX8025_REG_CTRL2 << 4 | 0x08,
+ ds1307->regs[1]);
+ dev_warn(ds1307->dev, "power-on detected\n");
}
if (ds1307->regs[1] & RX8025_BIT_VDET) {
ds1307->regs[1] &= ~RX8025_BIT_VDET;
- i2c_smbus_write_byte_data(client,
- RX8025_REG_CTRL2 << 4 | 0x08,
- ds1307->regs[1]);
- dev_warn(&client->dev, "voltage drop detected\n");
+ regmap_write(ds1307->regmap,
+ RX8025_REG_CTRL2 << 4 | 0x08,
+ ds1307->regs[1]);
+ dev_warn(ds1307->dev, "voltage drop detected\n");
}
/* make sure we are running in 24hour mode */
@@ -1537,16 +1379,15 @@ static int ds1307_probe(struct i2c_client *client,
u8 hour;
/* switch to 24 hour mode */
- i2c_smbus_write_byte_data(client,
- RX8025_REG_CTRL1 << 4 | 0x08,
- ds1307->regs[0] |
- RX8025_BIT_2412);
-
- tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
- RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
- if (tmp != 2) {
- dev_dbg(&client->dev, "read error %d\n", tmp);
- err = -EIO;
+ regmap_write(ds1307->regmap,
+ RX8025_REG_CTRL1 << 4 | 0x08,
+ ds1307->regs[0] | RX8025_BIT_2412);
+
+ err = regmap_bulk_read(ds1307->regmap,
+ RX8025_REG_CTRL1 << 4 | 0x08,
+ buf, 2);
+ if (err) {
+ dev_dbg(ds1307->dev, "read error %d\n", err);
goto exit;
}
@@ -1557,9 +1398,8 @@ static int ds1307_probe(struct i2c_client *client,
if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
hour += 12;
- i2c_smbus_write_byte_data(client,
- DS1307_REG_HOUR << 4 | 0x08,
- hour);
+ regmap_write(ds1307->regmap,
+ DS1307_REG_HOUR << 4 | 0x08, hour);
}
break;
case ds_1388:
@@ -1567,7 +1407,8 @@ static int ds1307_probe(struct i2c_client *client,
break;
case mcp794xx:
rtc_ops = &mcp794xx_rtc_ops;
- if (ds1307->client->irq > 0 && chip->alarm) {
+ if (chip->alarm && (ds1307->irq > 0 ||
+ ds1307_can_wakeup_device)) {
irq_handler = mcp794xx_irq;
want_irq = true;
}
@@ -1578,10 +1419,9 @@ static int ds1307_probe(struct i2c_client *client,
read_rtc:
/* read RTC registers */
- tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
- if (tmp != 8) {
- dev_dbg(&client->dev, "read error %d\n", tmp);
- err = -EIO;
+ err = regmap_bulk_read(ds1307->regmap, ds1307->offset, buf, 8);
+ if (err) {
+ dev_dbg(ds1307->dev, "read error %d\n", err);
goto exit;
}
@@ -1597,56 +1437,55 @@ read_rtc:
case m41t00:
/* clock halted? turn it on, so clock can tick. */
if (tmp & DS1307_BIT_CH) {
- i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
- dev_warn(&client->dev, "SET TIME!\n");
+ regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
+ dev_warn(ds1307->dev, "SET TIME!\n");
goto read_rtc;
}
break;
case ds_1338:
/* clock halted? turn it on, so clock can tick. */
if (tmp & DS1307_BIT_CH)
- i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+ regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
/* oscillator fault? clear flag, and warn */
if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
- i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
- ds1307->regs[DS1307_REG_CONTROL]
- & ~DS1338_BIT_OSF);
- dev_warn(&client->dev, "SET TIME!\n");
+ regmap_write(ds1307->regmap, DS1307_REG_CONTROL,
+ ds1307->regs[DS1307_REG_CONTROL] &
+ ~DS1338_BIT_OSF);
+ dev_warn(ds1307->dev, "SET TIME!\n");
goto read_rtc;
}
break;
case ds_1340:
/* clock halted? turn it on, so clock can tick. */
if (tmp & DS1340_BIT_nEOSC)
- i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+ regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
- tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG);
- if (tmp < 0) {
- dev_dbg(&client->dev, "read error %d\n", tmp);
- err = -EIO;
+ err = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp);
+ if (err) {
+ dev_dbg(ds1307->dev, "read error %d\n", err);
goto exit;
}
/* oscillator fault? clear flag, and warn */
if (tmp & DS1340_BIT_OSF) {
- i2c_smbus_write_byte_data(client, DS1340_REG_FLAG, 0);
- dev_warn(&client->dev, "SET TIME!\n");
+ regmap_write(ds1307->regmap, DS1340_REG_FLAG, 0);
+ dev_warn(ds1307->dev, "SET TIME!\n");
}
break;
case mcp794xx:
/* make sure that the backup battery is enabled */
if (!(ds1307->regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
- i2c_smbus_write_byte_data(client, DS1307_REG_WDAY,
- ds1307->regs[DS1307_REG_WDAY]
- | MCP794XX_BIT_VBATEN);
+ regmap_write(ds1307->regmap, DS1307_REG_WDAY,
+ ds1307->regs[DS1307_REG_WDAY] |
+ MCP794XX_BIT_VBATEN);
}
/* clock halted? turn it on, so clock can tick. */
if (!(tmp & MCP794XX_BIT_ST)) {
- i2c_smbus_write_byte_data(client, DS1307_REG_SECS,
- MCP794XX_BIT_ST);
- dev_warn(&client->dev, "SET TIME!\n");
+ regmap_write(ds1307->regmap, DS1307_REG_SECS,
+ MCP794XX_BIT_ST);
+ dev_warn(ds1307->dev, "SET TIME!\n");
goto read_rtc;
}
@@ -1680,16 +1519,15 @@ read_rtc:
tmp = 0;
if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
tmp += 12;
- i2c_smbus_write_byte_data(client,
- ds1307->offset + DS1307_REG_HOUR,
- bin2bcd(tmp));
+ regmap_write(ds1307->regmap, ds1307->offset + DS1307_REG_HOUR,
+ bin2bcd(tmp));
}
/*
* Some IPs have weekday reset value = 0x1 which might not correct
* hence compute the wday using the current date/month/year values
*/
- ds1307_get_time(&client->dev, &tm);
+ ds1307_get_time(ds1307->dev, &tm);
wday = tm.tm_wday;
timestamp = rtc_tm_to_time64(&tm);
rtc_time64_to_tm(timestamp, &tm);
@@ -1700,51 +1538,53 @@ read_rtc:
* timestamp
*/
if (wday != tm.tm_wday) {
- wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY);
+ regmap_read(ds1307->regmap, MCP794XX_REG_WEEKDAY, &wday);
wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK;
wday = wday | (tm.tm_wday + 1);
- i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday);
+ regmap_write(ds1307->regmap, MCP794XX_REG_WEEKDAY, wday);
}
if (want_irq) {
- device_set_wakeup_capable(&client->dev, true);
+ device_set_wakeup_capable(ds1307->dev, true);
set_bit(HAS_ALARM, &ds1307->flags);
}
- ds1307->rtc = devm_rtc_device_register(&client->dev, client->name,
+ ds1307->rtc = devm_rtc_device_register(ds1307->dev, ds1307->name,
rtc_ops, THIS_MODULE);
if (IS_ERR(ds1307->rtc)) {
return PTR_ERR(ds1307->rtc);
}
- if (ds1307_can_wakeup_device && ds1307->client->irq <= 0) {
+ if (ds1307_can_wakeup_device && ds1307->irq <= 0) {
/* Disable request for an IRQ */
want_irq = false;
- dev_info(&client->dev, "'wakeup-source' is set, request for an IRQ is disabled!\n");
+ dev_info(ds1307->dev,
+ "'wakeup-source' is set, request for an IRQ is disabled!\n");
/* We cannot support UIE mode if we do not have an IRQ line */
ds1307->rtc->uie_unsupported = 1;
}
if (want_irq) {
- err = devm_request_threaded_irq(&client->dev,
- client->irq, NULL, irq_handler,
+ err = devm_request_threaded_irq(ds1307->dev,
+ ds1307->irq, NULL, irq_handler,
IRQF_SHARED | IRQF_ONESHOT,
- ds1307->rtc->name, client);
+ ds1307->rtc->name, ds1307);
if (err) {
client->irq = 0;
- device_set_wakeup_capable(&client->dev, false);
+ device_set_wakeup_capable(ds1307->dev, false);
clear_bit(HAS_ALARM, &ds1307->flags);
- dev_err(&client->dev, "unable to request IRQ!\n");
+ dev_err(ds1307->dev, "unable to request IRQ!\n");
} else
- dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+ dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
}
if (chip->nvram_size) {
- ds1307->nvram = devm_kzalloc(&client->dev,
+ ds1307->nvram = devm_kzalloc(ds1307->dev,
sizeof(struct bin_attribute),
GFP_KERNEL);
if (!ds1307->nvram) {
- dev_err(&client->dev, "cannot allocate memory for nvram sysfs\n");
+ dev_err(ds1307->dev,
+ "cannot allocate memory for nvram sysfs\n");
} else {
ds1307->nvram->attr.name = "nvram";
@@ -1757,15 +1597,15 @@ read_rtc:
ds1307->nvram->size = chip->nvram_size;
ds1307->nvram_offset = chip->nvram_offset;
- err = sysfs_create_bin_file(&client->dev.kobj,
+ err = sysfs_create_bin_file(&ds1307->dev->kobj,
ds1307->nvram);
if (err) {
- dev_err(&client->dev,
+ dev_err(ds1307->dev,
"unable to create sysfs file: %s\n",
ds1307->nvram->attr.name);
} else {
set_bit(HAS_NVRAM, &ds1307->flags);
- dev_info(&client->dev, "%zu bytes nvram\n",
+ dev_info(ds1307->dev, "%zu bytes nvram\n",
ds1307->nvram->size);
}
}
@@ -1785,7 +1625,7 @@ static int ds1307_remove(struct i2c_client *client)
struct ds1307 *ds1307 = i2c_get_clientdata(client);
if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
- sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram);
+ sysfs_remove_bin_file(&ds1307->dev->kobj, ds1307->nvram);
return 0;
}
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 5ec4653022ff..8940e9e43ea0 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -16,6 +16,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bcd.h>
+#include <linux/clk-provider.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -53,6 +54,8 @@
#define M41T80_ALARM_REG_SIZE \
(M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
+#define M41T80_SQW_MAX_FREQ 32768
+
#define M41T80_SEC_ST BIT(7) /* ST: Stop Bit */
#define M41T80_ALMON_AFE BIT(7) /* AFE: AF Enable Bit */
#define M41T80_ALMON_SQWE BIT(6) /* SQWE: SQW Enable Bit */
@@ -147,7 +150,11 @@ MODULE_DEVICE_TABLE(of, m41t80_of_match);
struct m41t80_data {
unsigned long features;
+ struct i2c_client *client;
struct rtc_device *rtc;
+#ifdef CONFIG_COMMON_CLK
+ struct clk_hw sqw;
+#endif
};
static irqreturn_t m41t80_handle_irq(int irq, void *dev_id)
@@ -227,6 +234,7 @@ static int m41t80_get_datetime(struct i2c_client *client,
/* Sets the given date and time to the real time clock. */
static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
+ struct m41t80_data *clientdata = i2c_get_clientdata(client);
unsigned char buf[8];
int err, flags;
@@ -242,6 +250,17 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year - 100);
buf[M41T80_REG_WDAY] = tm->tm_wday;
+ /* If the square wave output is controlled in the weekday register */
+ if (clientdata->features & M41T80_FEATURE_SQ_ALT) {
+ int val;
+
+ val = i2c_smbus_read_byte_data(client, M41T80_REG_WDAY);
+ if (val < 0)
+ return val;
+
+ buf[M41T80_REG_WDAY] |= (val & 0xf0);
+ }
+
err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_SSEC,
sizeof(buf), buf);
if (err < 0) {
@@ -332,6 +351,9 @@ static int m41t80_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return err;
}
+ /* Keep SQWE bit value */
+ alarmvals[0] |= (ret & M41T80_ALMON_SQWE);
+
ret = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
if (ret < 0)
return ret;
@@ -431,103 +453,175 @@ static ssize_t flags_show(struct device *dev,
}
static DEVICE_ATTR_RO(flags);
-static ssize_t sqwfreq_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static struct attribute *attrs[] = {
+ &dev_attr_flags.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
+#ifdef CONFIG_COMMON_CLK
+#define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw)
+
+static unsigned long m41t80_sqw_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct m41t80_data *clientdata = i2c_get_clientdata(client);
- int val, reg_sqw;
+ struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw);
+ struct i2c_client *client = m41t80->client;
+ int reg_sqw = (m41t80->features & M41T80_FEATURE_SQ_ALT) ?
+ M41T80_REG_WDAY : M41T80_REG_SQW;
+ int ret = i2c_smbus_read_byte_data(client, reg_sqw);
+ unsigned long val = M41T80_SQW_MAX_FREQ;
- if (!(clientdata->features & M41T80_FEATURE_SQ))
- return -EINVAL;
+ if (ret < 0)
+ return 0;
- reg_sqw = M41T80_REG_SQW;
- if (clientdata->features & M41T80_FEATURE_SQ_ALT)
- reg_sqw = M41T80_REG_WDAY;
- val = i2c_smbus_read_byte_data(client, reg_sqw);
- if (val < 0)
- return val;
- val = (val >> 4) & 0xf;
- switch (val) {
- case 0:
- break;
- case 1:
- val = 32768;
- break;
- default:
- val = 32768 >> val;
- }
- return sprintf(buf, "%d\n", val);
+ ret >>= 4;
+ if (ret == 0)
+ val = 0;
+ else if (ret > 1)
+ val = val / (1 << ret);
+
+ return val;
}
-static ssize_t sqwfreq_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static long m41t80_sqw_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct m41t80_data *clientdata = i2c_get_clientdata(client);
- int almon, sqw, reg_sqw, rc;
- unsigned long val;
+ int i, freq = M41T80_SQW_MAX_FREQ;
- rc = kstrtoul(buf, 0, &val);
- if (rc < 0)
- return rc;
+ if (freq <= rate)
+ return freq;
- if (!(clientdata->features & M41T80_FEATURE_SQ))
- return -EINVAL;
+ for (i = 2; i <= ilog2(M41T80_SQW_MAX_FREQ); i++) {
+ freq /= 1 << i;
+ if (freq <= rate)
+ return freq;
+ }
- if (val) {
- if (!is_power_of_2(val))
+ return 0;
+}
+
+static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw);
+ struct i2c_client *client = m41t80->client;
+ int reg_sqw = (m41t80->features & M41T80_FEATURE_SQ_ALT) ?
+ M41T80_REG_WDAY : M41T80_REG_SQW;
+ int reg, ret, val = 0;
+
+ if (rate) {
+ if (!is_power_of_2(rate))
return -EINVAL;
- val = ilog2(val);
- if (val == 15)
+ val = ilog2(rate);
+ if (val == ilog2(M41T80_SQW_MAX_FREQ))
val = 1;
- else if (val < 14)
- val = 15 - val;
+ else if (val < (ilog2(M41T80_SQW_MAX_FREQ) - 1))
+ val = ilog2(M41T80_SQW_MAX_FREQ) - val;
else
return -EINVAL;
}
- /* disable SQW, set SQW frequency & re-enable */
- almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
- if (almon < 0)
- return almon;
- reg_sqw = M41T80_REG_SQW;
- if (clientdata->features & M41T80_FEATURE_SQ_ALT)
- reg_sqw = M41T80_REG_WDAY;
- sqw = i2c_smbus_read_byte_data(client, reg_sqw);
- if (sqw < 0)
- return sqw;
- sqw = (sqw & 0x0f) | (val << 4);
-
- rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
- almon & ~M41T80_ALMON_SQWE);
- if (rc < 0)
- return rc;
- if (val) {
- rc = i2c_smbus_write_byte_data(client, reg_sqw, sqw);
- if (rc < 0)
- return rc;
+ reg = i2c_smbus_read_byte_data(client, reg_sqw);
+ if (reg < 0)
+ return reg;
- rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
- almon | M41T80_ALMON_SQWE);
- if (rc < 0)
- return rc;
- }
- return count;
+ reg = (reg & 0x0f) | (val << 4);
+
+ ret = i2c_smbus_write_byte_data(client, reg_sqw, reg);
+ if (ret < 0)
+ return ret;
+
+ return -EINVAL;
}
-static DEVICE_ATTR_RW(sqwfreq);
-static struct attribute *attrs[] = {
- &dev_attr_flags.attr,
- &dev_attr_sqwfreq.attr,
- NULL,
-};
+static int m41t80_sqw_control(struct clk_hw *hw, bool enable)
+{
+ struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw);
+ struct i2c_client *client = m41t80->client;
+ int ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
-static struct attribute_group attr_group = {
- .attrs = attrs,
+ if (ret < 0)
+ return ret;
+
+ if (enable)
+ ret |= M41T80_ALMON_SQWE;
+ else
+ ret &= ~M41T80_ALMON_SQWE;
+
+ return i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, ret);
+}
+
+static int m41t80_sqw_prepare(struct clk_hw *hw)
+{
+ return m41t80_sqw_control(hw, 1);
+}
+
+static void m41t80_sqw_unprepare(struct clk_hw *hw)
+{
+ m41t80_sqw_control(hw, 0);
+}
+
+static int m41t80_sqw_is_prepared(struct clk_hw *hw)
+{
+ struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw);
+ struct i2c_client *client = m41t80->client;
+ int ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+
+ if (ret < 0)
+ return ret;
+
+ return !!(ret & M41T80_ALMON_SQWE);
+}
+
+static const struct clk_ops m41t80_sqw_ops = {
+ .prepare = m41t80_sqw_prepare,
+ .unprepare = m41t80_sqw_unprepare,
+ .is_prepared = m41t80_sqw_is_prepared,
+ .recalc_rate = m41t80_sqw_recalc_rate,
+ .round_rate = m41t80_sqw_round_rate,
+ .set_rate = m41t80_sqw_set_rate,
};
+static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
+{
+ struct i2c_client *client = m41t80->client;
+ struct device_node *node = client->dev.of_node;
+ struct clk *clk;
+ struct clk_init_data init;
+ int ret;
+
+ /* First disable the clock */
+ ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ ret = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ ret & ~(M41T80_ALMON_SQWE));
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ init.name = "m41t80-sqw";
+ init.ops = &m41t80_sqw_ops;
+ init.flags = 0;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ m41t80->sqw.init = &init;
+
+ /* optional override of the clockname */
+ of_property_read_string(node, "clock-output-names", &init.name);
+
+ /* register the clock */
+ clk = clk_register(&client->dev, &m41t80->sqw);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return clk;
+}
+#endif
+
#ifdef CONFIG_RTC_DRV_M41T80_WDT
/*
*****************************************************************************
@@ -845,6 +939,7 @@ static int m41t80_probe(struct i2c_client *client,
if (!m41t80_data)
return -ENOMEM;
+ m41t80_data->client = client;
if (client->dev.of_node)
m41t80_data->features = (unsigned long)
of_device_get_match_data(&client->dev);
@@ -937,6 +1032,10 @@ static int m41t80_probe(struct i2c_client *client,
}
}
#endif
+#ifdef CONFIG_COMMON_CLK
+ if (m41t80_data->features & M41T80_FEATURE_SQ)
+ m41t80_sqw_register_clk(m41t80_data);
+#endif
return 0;
}
diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c
index ea20f627dabe..2d84e2a28772 100644
--- a/drivers/rtc/rtc-opal.c
+++ b/drivers/rtc/rtc-opal.c
@@ -142,6 +142,16 @@ static int opal_get_tpo_time(struct device *dev, struct rtc_wkalrm *alarm)
y_m_d = be32_to_cpu(__y_m_d);
h_m_s_ms = ((u64)be32_to_cpu(__h_m) << 32);
+
+ /* check if no alarm is set */
+ if (y_m_d == 0 && h_m_s_ms == 0) {
+ pr_debug("No alarm is set\n");
+ rc = -ENOENT;
+ goto exit;
+ } else {
+ pr_debug("Alarm set to %x %llx\n", y_m_d, h_m_s_ms);
+ }
+
opal_to_tm(y_m_d, h_m_s_ms, &alarm->time);
exit: