summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2016-02-04 13:44:14 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2016-02-04 13:44:14 +1100
commit01ae1d78d3d7977bbde8c54bdec1f851ce128e78 (patch)
tree4768fc1492e770384f1b2ab4067336d3ed5f15bd
parent666f1287119eb66a6258521aae80f78cab1ff52f (diff)
parent3afab204714143a94e42a99573c0ef8ef8d7062a (diff)
downloadlinux-01ae1d78d3d7977bbde8c54bdec1f851ce128e78.tar.gz
linux-01ae1d78d3d7977bbde8c54bdec1f851ce128e78.tar.xz
Merge remote-tracking branch 'rtc/rtc-next'
-rw-r--r--Documentation/devicetree/bindings/rtc/epson,rx6110.txt39
-rw-r--r--drivers/rtc/Kconfig30
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-ds1305.c4
-rw-r--r--drivers/rtc/rtc-ds1307.c117
-rw-r--r--drivers/rtc/rtc-max77686.c360
-rw-r--r--drivers/rtc/rtc-max77802.c502
-rw-r--r--drivers/rtc/rtc-pcf2123.c214
-rw-r--r--drivers/rtc/rtc-rx6110.c402
-rw-r--r--drivers/rtc/rtc-rx8025.c1
10 files changed, 991 insertions, 680 deletions
diff --git a/Documentation/devicetree/bindings/rtc/epson,rx6110.txt b/Documentation/devicetree/bindings/rtc/epson,rx6110.txt
new file mode 100644
index 000000000000..3dc313e01f77
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/epson,rx6110.txt
@@ -0,0 +1,39 @@
+Epson RX6110 Real Time Clock
+============================
+
+The Epson RX6110 can be used with SPI or I2C busses. The kind of
+bus depends on the SPISEL pin and can not be configured via software.
+
+I2C mode
+--------
+
+Required properties:
+ - compatible: should be: "epson,rx6110"
+ - reg : the I2C address of the device for I2C
+
+Example:
+
+ rtc: rtc@32 {
+ compatible = "epson,rx6110"
+ reg = <0x32>;
+ };
+
+SPI mode
+--------
+
+Required properties:
+ - compatible: should be: "epson,rx6110"
+ - reg: chip select number
+ - spi-cs-high: RX6110 needs chipselect high
+ - spi-cpha: RX6110 works with SPI shifted clock phase
+ - spi-cpol: RX6110 works with SPI inverse clock polarity
+
+Example:
+
+ rtc: rtc@3 {
+ compatible = "epson,rx6110"
+ reg = <3>
+ spi-cs-high;
+ spi-cpha;
+ spi-cpol;
+ };
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 376322f71fd5..ec6a25324525 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -212,6 +212,15 @@ config RTC_DRV_DS1307
This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
+config RTC_DRV_DS1307_HWMON
+ bool "HWMON support for rtc-ds1307"
+ depends on RTC_DRV_DS1307 && HWMON
+ depends on !(RTC_DRV_DS1307=y && HWMON=m)
+ default y
+ help
+ Say Y here if you want to expose temperature sensor data on
+ rtc-ds1307 (only DS3231)
+
config RTC_DRV_DS1374
tristate "Dallas/Maxim DS1374"
help
@@ -335,16 +344,6 @@ config RTC_DRV_RK808
This driver can also be built as a module. If so, the module
will be called rk808-rtc.
-config RTC_DRV_MAX77802
- tristate "Maxim 77802 RTC"
- depends on MFD_MAX77686
- help
- If you say yes here you will get support for the
- RTC of Maxim MAX77802 PMIC.
-
- This driver can also be built as a module. If so, the module
- will be called rtc-max77802.
-
config RTC_DRV_RS5C372
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help
@@ -744,6 +743,15 @@ config RTC_DRV_RX4581
This driver can also be built as a module. If so the module
will be called rtc-rx4581.
+config RTC_DRV_RX6110
+ tristate "Epson RX-6110"
+ select REGMAP_SPI
+ help
+ If you say yes here you will get support for the Epson RX-6610.
+
+ This driver can also be built as a module. If so the module
+ will be called rtc-rx6110.
+
config RTC_DRV_MCP795
tristate "Microchip MCP795"
help
@@ -1603,7 +1611,7 @@ config RTC_DRV_MOXART
config RTC_DRV_MT6397
tristate "Mediatek Real Time Clock driver"
- depends on MFD_MT6397 || COMPILE_TEST
+ depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
help
This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
MT6397 PMIC. You should enable MT6397 PMIC MFD before select
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 62d61b26ca7e..c8a21479deea 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
-obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o
obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
@@ -128,6 +127,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
+obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o
obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index f39691eea736..8e41c4613e51 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
struct spi_transfer x[2];
int status;
- spi = container_of(kobj, struct spi_device, dev.kobj);
+ spi = to_spi_device(kobj_to_dev(kobj));
addr = DS1305_NVRAM + off;
msg_init(&m, x, &addr, count, NULL, buf);
@@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
struct spi_transfer x[2];
int status;
- spi = container_of(kobj, struct spi_device, dev.kobj);
+ spi = to_spi_device(kobj_to_dev(kobj));
addr = (DS1305_WRITE | DS1305_NVRAM) + off;
msg_init(&m, x, &addr, count, buf, NULL);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index cf685f67b391..2462d5a53a53 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -19,6 +19,8 @@
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
@@ -842,6 +844,90 @@ out:
return;
}
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_RTC_DRV_DS1307_HWMON
+
+/*
+ * Temperature sensor support for ds3231 devices.
+ */
+
+#define DS3231_REG_TEMPERATURE 0x11
+
+/*
+ * A user-initiated temperature conversion is not started by this function,
+ * so the temperature is updated once every 64 seconds.
+ */
+static int ds3231_hwmon_read_temp(struct device *dev, s16 *mC)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ u8 temp_buf[2];
+ s16 temp;
+ int ret;
+
+ ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE,
+ sizeof(temp_buf), temp_buf);
+ if (ret < 0)
+ 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.
+ */
+ temp = (temp_buf[0] << 8) | temp_buf[1];
+ temp >>= 6;
+ *mC = temp * 250;
+
+ return 0;
+}
+
+static ssize_t ds3231_hwmon_show_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ s16 temp;
+
+ ret = ds3231_hwmon_read_temp(dev, &temp);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", temp);
+}
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp,
+ NULL, 0);
+
+static struct attribute *ds3231_hwmon_attrs[] = {
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(ds3231_hwmon);
+
+static void ds1307_hwmon_register(struct ds1307 *ds1307)
+{
+ struct device *dev;
+
+ if (ds1307->type != ds_3231)
+ return;
+
+ dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev,
+ ds1307->client->name,
+ ds1307, ds3231_hwmon_groups);
+ if (IS_ERR(dev)) {
+ dev_warn(&ds1307->client->dev,
+ "unable to register hwmon device %ld\n", PTR_ERR(dev));
+ }
+}
+
+#else
+
+static void ds1307_hwmon_register(struct ds1307 *ds1307)
+{
+}
+
+#endif
+
static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -851,6 +937,7 @@ static int ds1307_probe(struct i2c_client *client,
struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
+ bool ds1307_can_wakeup_device = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
irq_handler_t irq_handler = ds1307_irq;
@@ -898,6 +985,20 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->write_block_data = ds1307_write_block_data;
}
+#ifdef CONFIG_OF
+/*
+ * For devices with no IRQ directly connected to the SoC, the RTC chip
+ * can be forced as a wakeup source by stating that explicitly in
+ * the device's .dts file using the "wakeup-source" boolean property.
+ * If the "wakeup-source" property is set, don't request an IRQ.
+ * This will guarantee the 'wakealarm' sysfs entry is available on the device,
+ * if supported by the RTC.
+ */
+ if (of_property_read_bool(client->dev.of_node, "wakeup-source")) {
+ ds1307_can_wakeup_device = true;
+ }
+#endif
+
switch (ds1307->type) {
case ds_1337:
case ds_1339:
@@ -916,11 +1017,13 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
/*
- * Using IRQ? Disable the square wave and both alarms.
+ * Using IRQ or defined as wakeup-source?
+ * Disable the square wave and both alarms.
* For some variants, be sure alarms can trigger when we're
* running on Vbackup (BBSQI/BBSQW)
*/
- if (ds1307->client->irq > 0 && chip->alarm) {
+ if (chip->alarm && (ds1307->client->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);
@@ -1135,6 +1238,14 @@ read_rtc:
return PTR_ERR(ds1307->rtc);
}
+ if (ds1307_can_wakeup_device) {
+ /* Disable request for an IRQ */
+ want_irq = false;
+ dev_info(&client->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,
@@ -1182,6 +1293,8 @@ read_rtc:
}
}
+ ds1307_hwmon_register(ds1307);
+
return 0;
exit:
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 7184a0eda793..188593d37d44 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -1,5 +1,5 @@
/*
- * RTC driver for Maxim MAX77686
+ * RTC driver for Maxim MAX77686 and MAX77802
*
* Copyright (C) 2012 Samsung Electronics Co.Ltd
*
@@ -12,8 +12,6 @@
*
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/slab.h>
#include <linux/rtc.h>
#include <linux/delay.h>
@@ -41,7 +39,14 @@
#define ALARM_ENABLE_SHIFT 7
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
-#define MAX77686_RTC_UPDATE_DELAY 16
+#define REG_RTC_NONE 0xdeadbeef
+
+/*
+ * MAX77802 has separate register (RTCAE1) for alarm enable instead
+ * using 1 bit from registers RTC{SEC,MIN,HOUR,DAY,MONTH,YEAR,DATE}
+ * as in done in MAX77686.
+ */
+#define MAX77802_ALARM_ENABLE_VALUE 0x77
enum {
RTC_SEC = 0,
@@ -54,6 +59,19 @@ enum {
RTC_NR_TIME
};
+struct max77686_rtc_driver_data {
+ /* Minimum usecs needed for a RTC update */
+ unsigned long delay;
+ /* Mask used to read RTC registers value */
+ u8 mask;
+ /* Registers offset to I2C addresses map */
+ const unsigned int *map;
+ /* Has a separate alarm enable register? */
+ bool alarm_enable_reg;
+ /* Has a separate I2C regmap for the RTC? */
+ bool separate_i2c_addr;
+};
+
struct max77686_rtc_info {
struct device *dev;
struct max77686_dev *max77686;
@@ -63,6 +81,8 @@ struct max77686_rtc_info {
struct regmap *regmap;
+ const struct max77686_rtc_driver_data *drv_data;
+
int virq;
int rtc_24hr_mode;
};
@@ -72,12 +92,120 @@ enum MAX77686_RTC_OP {
MAX77686_RTC_READ,
};
+/* These are not registers but just offsets that are mapped to addresses */
+enum max77686_rtc_reg_offset {
+ REG_RTC_CONTROLM = 0,
+ REG_RTC_CONTROL,
+ REG_RTC_UPDATE0,
+ REG_WTSR_SMPL_CNTL,
+ REG_RTC_SEC,
+ REG_RTC_MIN,
+ REG_RTC_HOUR,
+ REG_RTC_WEEKDAY,
+ REG_RTC_MONTH,
+ REG_RTC_YEAR,
+ REG_RTC_DATE,
+ REG_ALARM1_SEC,
+ REG_ALARM1_MIN,
+ REG_ALARM1_HOUR,
+ REG_ALARM1_WEEKDAY,
+ REG_ALARM1_MONTH,
+ REG_ALARM1_YEAR,
+ REG_ALARM1_DATE,
+ REG_ALARM2_SEC,
+ REG_ALARM2_MIN,
+ REG_ALARM2_HOUR,
+ REG_ALARM2_WEEKDAY,
+ REG_ALARM2_MONTH,
+ REG_ALARM2_YEAR,
+ REG_ALARM2_DATE,
+ REG_RTC_AE1,
+ REG_RTC_END,
+};
+
+/* Maps RTC registers offset to the MAX77686 register addresses */
+static const unsigned int max77686_map[REG_RTC_END] = {
+ [REG_RTC_CONTROLM] = MAX77686_RTC_CONTROLM,
+ [REG_RTC_CONTROL] = MAX77686_RTC_CONTROL,
+ [REG_RTC_UPDATE0] = MAX77686_RTC_UPDATE0,
+ [REG_WTSR_SMPL_CNTL] = MAX77686_WTSR_SMPL_CNTL,
+ [REG_RTC_SEC] = MAX77686_RTC_SEC,
+ [REG_RTC_MIN] = MAX77686_RTC_MIN,
+ [REG_RTC_HOUR] = MAX77686_RTC_HOUR,
+ [REG_RTC_WEEKDAY] = MAX77686_RTC_WEEKDAY,
+ [REG_RTC_MONTH] = MAX77686_RTC_MONTH,
+ [REG_RTC_YEAR] = MAX77686_RTC_YEAR,
+ [REG_RTC_DATE] = MAX77686_RTC_DATE,
+ [REG_ALARM1_SEC] = MAX77686_ALARM1_SEC,
+ [REG_ALARM1_MIN] = MAX77686_ALARM1_MIN,
+ [REG_ALARM1_HOUR] = MAX77686_ALARM1_HOUR,
+ [REG_ALARM1_WEEKDAY] = MAX77686_ALARM1_WEEKDAY,
+ [REG_ALARM1_MONTH] = MAX77686_ALARM1_MONTH,
+ [REG_ALARM1_YEAR] = MAX77686_ALARM1_YEAR,
+ [REG_ALARM1_DATE] = MAX77686_ALARM1_DATE,
+ [REG_ALARM2_SEC] = MAX77686_ALARM2_SEC,
+ [REG_ALARM2_MIN] = MAX77686_ALARM2_MIN,
+ [REG_ALARM2_HOUR] = MAX77686_ALARM2_HOUR,
+ [REG_ALARM2_WEEKDAY] = MAX77686_ALARM2_WEEKDAY,
+ [REG_ALARM2_MONTH] = MAX77686_ALARM2_MONTH,
+ [REG_ALARM2_YEAR] = MAX77686_ALARM2_YEAR,
+ [REG_ALARM2_DATE] = MAX77686_ALARM2_DATE,
+ [REG_RTC_AE1] = REG_RTC_NONE,
+};
+
+static const struct max77686_rtc_driver_data max77686_drv_data = {
+ .delay = 16000,
+ .mask = 0x7f,
+ .map = max77686_map,
+ .alarm_enable_reg = false,
+ .separate_i2c_addr = true,
+};
+
+static const unsigned int max77802_map[REG_RTC_END] = {
+ [REG_RTC_CONTROLM] = MAX77802_RTC_CONTROLM,
+ [REG_RTC_CONTROL] = MAX77802_RTC_CONTROL,
+ [REG_RTC_UPDATE0] = MAX77802_RTC_UPDATE0,
+ [REG_WTSR_SMPL_CNTL] = MAX77802_WTSR_SMPL_CNTL,
+ [REG_RTC_SEC] = MAX77802_RTC_SEC,
+ [REG_RTC_MIN] = MAX77802_RTC_MIN,
+ [REG_RTC_HOUR] = MAX77802_RTC_HOUR,
+ [REG_RTC_WEEKDAY] = MAX77802_RTC_WEEKDAY,
+ [REG_RTC_MONTH] = MAX77802_RTC_MONTH,
+ [REG_RTC_YEAR] = MAX77802_RTC_YEAR,
+ [REG_RTC_DATE] = MAX77802_RTC_DATE,
+ [REG_ALARM1_SEC] = MAX77802_ALARM1_SEC,
+ [REG_ALARM1_MIN] = MAX77802_ALARM1_MIN,
+ [REG_ALARM1_HOUR] = MAX77802_ALARM1_HOUR,
+ [REG_ALARM1_WEEKDAY] = MAX77802_ALARM1_WEEKDAY,
+ [REG_ALARM1_MONTH] = MAX77802_ALARM1_MONTH,
+ [REG_ALARM1_YEAR] = MAX77802_ALARM1_YEAR,
+ [REG_ALARM1_DATE] = MAX77802_ALARM1_DATE,
+ [REG_ALARM2_SEC] = MAX77802_ALARM2_SEC,
+ [REG_ALARM2_MIN] = MAX77802_ALARM2_MIN,
+ [REG_ALARM2_HOUR] = MAX77802_ALARM2_HOUR,
+ [REG_ALARM2_WEEKDAY] = MAX77802_ALARM2_WEEKDAY,
+ [REG_ALARM2_MONTH] = MAX77802_ALARM2_MONTH,
+ [REG_ALARM2_YEAR] = MAX77802_ALARM2_YEAR,
+ [REG_ALARM2_DATE] = MAX77802_ALARM2_DATE,
+ [REG_RTC_AE1] = MAX77802_RTC_AE1,
+};
+
+static const struct max77686_rtc_driver_data max77802_drv_data = {
+ .delay = 200,
+ .mask = 0xff,
+ .map = max77802_map,
+ .alarm_enable_reg = true,
+ .separate_i2c_addr = false,
+};
+
static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
- int rtc_24hr_mode)
+ struct max77686_rtc_info *info)
{
- tm->tm_sec = data[RTC_SEC] & 0x7f;
- tm->tm_min = data[RTC_MIN] & 0x7f;
- if (rtc_24hr_mode)
+ u8 mask = info->drv_data->mask;
+
+ tm->tm_sec = data[RTC_SEC] & mask;
+ tm->tm_min = data[RTC_MIN] & mask;
+ if (info->rtc_24hr_mode)
tm->tm_hour = data[RTC_HOUR] & 0x1f;
else {
tm->tm_hour = data[RTC_HOUR] & 0x0f;
@@ -86,15 +214,23 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
}
/* Only a single bit is set in data[], so fls() would be equivalent */
- tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
+ tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1;
tm->tm_mday = data[RTC_DATE] & 0x1f;
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
- tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
+ tm->tm_year = data[RTC_YEAR] & mask;
tm->tm_yday = 0;
tm->tm_isdst = 0;
+
+ /*
+ * MAX77686 uses 1 bit from sec/min/hour/etc RTC registers and the
+ * year values are just 0..99 so add 100 to support up to 2099.
+ */
+ if (!info->drv_data->alarm_enable_reg)
+ tm->tm_year += 100;
}
-static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data,
+ struct max77686_rtc_info *info)
{
data[RTC_SEC] = tm->tm_sec;
data[RTC_MIN] = tm->tm_min;
@@ -102,13 +238,20 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
data[RTC_WEEKDAY] = 1 << tm->tm_wday;
data[RTC_DATE] = tm->tm_mday;
data[RTC_MONTH] = tm->tm_mon + 1;
+
+ if (info->drv_data->alarm_enable_reg) {
+ data[RTC_YEAR] = tm->tm_year;
+ return 0;
+ }
+
data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;
if (tm->tm_year < 100) {
- pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n",
+ dev_err(info->dev, "RTC cannot handle the year %d.\n",
1900 + tm->tm_year);
return -EINVAL;
}
+
return 0;
}
@@ -117,6 +260,7 @@ static int max77686_rtc_update(struct max77686_rtc_info *info,
{
int ret;
unsigned int data;
+ unsigned long delay = info->drv_data->delay;
if (op == MAX77686_RTC_WRITE)
data = 1 << RTC_UDR_SHIFT;
@@ -124,13 +268,14 @@ static int max77686_rtc_update(struct max77686_rtc_info *info,
data = 1 << RTC_RBUDR_SHIFT;
ret = regmap_update_bits(info->max77686->rtc_regmap,
- MAX77686_RTC_UPDATE0, data, data);
+ info->drv_data->map[REG_RTC_UPDATE0],
+ data, data);
if (ret < 0)
- dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
- __func__, ret, data);
+ dev_err(info->dev, "Fail to write update reg(ret=%d, data=0x%x)\n",
+ ret, data);
else {
- /* Minimum 16ms delay required before RTC update. */
- msleep(MAX77686_RTC_UPDATE_DELAY);
+ /* Minimum delay required before RTC update. */
+ usleep_range(delay, delay * 2);
}
return ret;
@@ -149,13 +294,14 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm)
goto out;
ret = regmap_bulk_read(info->max77686->rtc_regmap,
- MAX77686_RTC_SEC, data, RTC_NR_TIME);
+ info->drv_data->map[REG_RTC_SEC],
+ data, ARRAY_SIZE(data));
if (ret < 0) {
- dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret);
+ dev_err(info->dev, "Fail to read time reg(%d)\n", ret);
goto out;
}
- max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
+ max77686_rtc_data_to_tm(data, tm, info);
ret = rtc_valid_tm(tm);
@@ -170,17 +316,17 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm)
u8 data[RTC_NR_TIME];
int ret;
- ret = max77686_rtc_tm_to_data(tm, data);
+ ret = max77686_rtc_tm_to_data(tm, data, info);
if (ret < 0)
return ret;
mutex_lock(&info->lock);
ret = regmap_bulk_write(info->max77686->rtc_regmap,
- MAX77686_RTC_SEC, data, RTC_NR_TIME);
+ info->drv_data->map[REG_RTC_SEC],
+ data, ARRAY_SIZE(data));
if (ret < 0) {
- dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
- ret);
+ dev_err(info->dev, "Fail to write time reg(%d)\n", ret);
goto out;
}
@@ -196,6 +342,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct max77686_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
unsigned int val;
+ const unsigned int *map = info->drv_data->map;
int i, ret;
mutex_lock(&info->lock);
@@ -205,28 +352,47 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
goto out;
ret = regmap_bulk_read(info->max77686->rtc_regmap,
- MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
+ map[REG_ALARM1_SEC], data, ARRAY_SIZE(data));
if (ret < 0) {
- dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
- __func__, __LINE__, ret);
+ dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
goto out;
}
- max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
+ max77686_rtc_data_to_tm(data, &alrm->time, info);
alrm->enabled = 0;
- for (i = 0; i < RTC_NR_TIME; i++) {
- if (data[i] & ALARM_ENABLE_MASK) {
+
+ if (info->drv_data->alarm_enable_reg) {
+ if (map[REG_RTC_AE1] == REG_RTC_NONE) {
+ ret = -EINVAL;
+ dev_err(info->dev,
+ "alarm enable register not set(%d)\n", ret);
+ goto out;
+ }
+
+ ret = regmap_read(info->max77686->regmap,
+ map[REG_RTC_AE1], &val);
+ if (ret < 0) {
+ dev_err(info->dev,
+ "fail to read alarm enable(%d)\n", ret);
+ goto out;
+ }
+
+ if (val)
alrm->enabled = 1;
- break;
+ } else {
+ for (i = 0; i < ARRAY_SIZE(data); i++) {
+ if (data[i] & ALARM_ENABLE_MASK) {
+ alrm->enabled = 1;
+ break;
+ }
}
}
alrm->pending = 0;
ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val);
if (ret < 0) {
- dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
- __func__, __LINE__, ret);
+ dev_err(info->dev, "Fail to read status2 reg(%d)\n", ret);
goto out;
}
@@ -235,7 +401,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
out:
mutex_unlock(&info->lock);
- return 0;
+ return ret;
}
static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
@@ -243,6 +409,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
u8 data[RTC_NR_TIME];
int ret, i;
struct rtc_time tm;
+ const unsigned int *map = info->drv_data->map;
if (!mutex_is_locked(&info->lock))
dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
@@ -251,24 +418,36 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
if (ret < 0)
goto out;
- ret = regmap_bulk_read(info->max77686->rtc_regmap,
- MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
- __func__, ret);
- goto out;
- }
+ if (info->drv_data->alarm_enable_reg) {
+ if (map[REG_RTC_AE1] == REG_RTC_NONE) {
+ ret = -EINVAL;
+ dev_err(info->dev,
+ "alarm enable register not set(%d)\n", ret);
+ goto out;
+ }
- max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode);
+ ret = regmap_write(info->max77686->regmap, map[REG_RTC_AE1], 0);
+ } else {
+ ret = regmap_bulk_read(info->max77686->rtc_regmap,
+ map[REG_ALARM1_SEC], data,
+ ARRAY_SIZE(data));
+ if (ret < 0) {
+ dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
+ goto out;
+ }
- for (i = 0; i < RTC_NR_TIME; i++)
- data[i] &= ~ALARM_ENABLE_MASK;
+ max77686_rtc_data_to_tm(data, &tm, info);
+
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ data[i] &= ~ALARM_ENABLE_MASK;
+
+ ret = regmap_bulk_write(info->max77686->rtc_regmap,
+ map[REG_ALARM1_SEC], data,
+ ARRAY_SIZE(data));
+ }
- ret = regmap_bulk_write(info->max77686->rtc_regmap,
- MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
- dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
- __func__, ret);
+ dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
goto out;
}
@@ -282,6 +461,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info)
u8 data[RTC_NR_TIME];
int ret;
struct rtc_time tm;
+ const unsigned int *map = info->drv_data->map;
if (!mutex_is_locked(&info->lock))
dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
@@ -290,32 +470,38 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info)
if (ret < 0)
goto out;
- ret = regmap_bulk_read(info->max77686->rtc_regmap,
- MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
- __func__, ret);
- goto out;
- }
-
- max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode);
+ if (info->drv_data->alarm_enable_reg) {
+ ret = regmap_write(info->max77686->regmap, map[REG_RTC_AE1],
+ MAX77802_ALARM_ENABLE_VALUE);
+ } else {
+ ret = regmap_bulk_read(info->max77686->rtc_regmap,
+ map[REG_ALARM1_SEC], data,
+ ARRAY_SIZE(data));
+ if (ret < 0) {
+ dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
+ goto out;
+ }
- data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT);
- data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT);
- data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT);
- data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
- if (data[RTC_MONTH] & 0xf)
- data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT);
- if (data[RTC_YEAR] & 0x7f)
- data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT);
- if (data[RTC_DATE] & 0x1f)
- data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
+ max77686_rtc_data_to_tm(data, &tm, info);
+
+ data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT);
+ data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT);
+ data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT);
+ data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
+ if (data[RTC_MONTH] & 0xf)
+ data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT);
+ if (data[RTC_YEAR] & info->drv_data->mask)
+ data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT);
+ if (data[RTC_DATE] & 0x1f)
+ data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
+
+ ret = regmap_bulk_write(info->max77686->rtc_regmap,
+ map[REG_ALARM1_SEC], data,
+ ARRAY_SIZE(data));
+ }
- ret = regmap_bulk_write(info->max77686->rtc_regmap,
- MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
- dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
- __func__, ret);
+ dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
goto out;
}
@@ -330,7 +516,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 data[RTC_NR_TIME];
int ret;
- ret = max77686_rtc_tm_to_data(&alrm->time, data);
+ ret = max77686_rtc_tm_to_data(&alrm->time, data, info);
if (ret < 0)
return ret;
@@ -341,11 +527,11 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
goto out;
ret = regmap_bulk_write(info->max77686->rtc_regmap,
- MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
+ info->drv_data->map[REG_ALARM1_SEC],
+ data, ARRAY_SIZE(data));
if (ret < 0) {
- dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
- __func__, ret);
+ dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
goto out;
}
@@ -380,7 +566,7 @@ static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data)
{
struct max77686_rtc_info *info = data;
- dev_info(info->dev, "%s:irq(%d)\n", __func__, irq);
+ dev_dbg(info->dev, "RTC alarm IRQ: %d\n", irq);
rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
@@ -406,10 +592,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
info->rtc_24hr_mode = 1;
- ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2);
+ ret = regmap_bulk_write(info->max77686->rtc_regmap,
+ info->drv_data->map[REG_RTC_CONTROLM],
+ data, ARRAY_SIZE(data));
if (ret < 0) {
- dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
- __func__, ret);
+ dev_err(info->dev, "Fail to write controlm reg(%d)\n", ret);
return ret;
}
@@ -421,10 +608,9 @@ static int max77686_rtc_probe(struct platform_device *pdev)
{
struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent);
struct max77686_rtc_info *info;
+ const struct platform_device_id *id = platform_get_device_id(pdev);
int ret;
- dev_info(&pdev->dev, "%s\n", __func__);
-
info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info),
GFP_KERNEL);
if (!info)
@@ -434,6 +620,11 @@ static int max77686_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->max77686 = max77686;
info->rtc = max77686->rtc;
+ info->drv_data = (const struct max77686_rtc_driver_data *)
+ id->driver_data;
+
+ if (!info->drv_data->separate_i2c_addr)
+ info->max77686->rtc_regmap = info->max77686->regmap;
platform_set_drvdata(pdev, info);
@@ -446,7 +637,7 @@ static int max77686_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
- info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
+ info->rtc_dev = devm_rtc_device_register(&pdev->dev, id->name,
&max77686_rtc_ops, THIS_MODULE);
if (IS_ERR(info->rtc_dev)) {
@@ -459,7 +650,7 @@ static int max77686_rtc_probe(struct platform_device *pdev)
if (!max77686->rtc_irq_data) {
ret = -EINVAL;
- dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
+ dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
goto err_rtc;
}
@@ -508,7 +699,8 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
max77686_rtc_suspend, max77686_rtc_resume);
static const struct platform_device_id rtc_id[] = {
- { "max77686-rtc", 0 },
+ { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, },
+ { "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, },
{},
};
MODULE_DEVICE_TABLE(platform, rtc_id);
diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c
deleted file mode 100644
index 82ffcc5a5345..000000000000
--- a/drivers/rtc/rtc-max77802.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * RTC driver for Maxim MAX77802
- *
- * Copyright (C) 2013 Google, Inc
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- * based on rtc-max8997.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/rtc.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/max77686-private.h>
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-/* RTC Control Register */
-#define BCD_EN_SHIFT 0
-#define BCD_EN_MASK (1 << BCD_EN_SHIFT)
-#define MODEL24_SHIFT 1
-#define MODEL24_MASK (1 << MODEL24_SHIFT)
-/* RTC Update Register1 */
-#define RTC_UDR_SHIFT 0
-#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
-#define RTC_RBUDR_SHIFT 4
-#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
-/* RTC Hour register */
-#define HOUR_PM_SHIFT 6
-#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
-/* RTC Alarm Enable */
-#define ALARM_ENABLE_SHIFT 7
-#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
-
-/* For the RTCAE1 register, we write this value to enable the alarm */
-#define ALARM_ENABLE_VALUE 0x77
-
-#define MAX77802_RTC_UPDATE_DELAY_US 200
-
-enum {
- RTC_SEC = 0,
- RTC_MIN,
- RTC_HOUR,
- RTC_WEEKDAY,
- RTC_MONTH,
- RTC_YEAR,
- RTC_DATE,
- RTC_NR_TIME
-};
-
-struct max77802_rtc_info {
- struct device *dev;
- struct max77686_dev *max77802;
- struct i2c_client *rtc;
- struct rtc_device *rtc_dev;
- struct mutex lock;
-
- struct regmap *regmap;
-
- int virq;
- int rtc_24hr_mode;
-};
-
-enum MAX77802_RTC_OP {
- MAX77802_RTC_WRITE,
- MAX77802_RTC_READ,
-};
-
-static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
- int rtc_24hr_mode)
-{
- tm->tm_sec = data[RTC_SEC] & 0xff;
- tm->tm_min = data[RTC_MIN] & 0xff;
- if (rtc_24hr_mode)
- tm->tm_hour = data[RTC_HOUR] & 0x1f;
- else {
- tm->tm_hour = data[RTC_HOUR] & 0x0f;
- if (data[RTC_HOUR] & HOUR_PM_MASK)
- tm->tm_hour += 12;
- }
-
- /* Only a single bit is set in data[], so fls() would be equivalent */
- tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
- tm->tm_mday = data[RTC_DATE] & 0x1f;
- tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
-
- tm->tm_year = data[RTC_YEAR] & 0xff;
- tm->tm_yday = 0;
- tm->tm_isdst = 0;
-}
-
-static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
-{
- data[RTC_SEC] = tm->tm_sec;
- data[RTC_MIN] = tm->tm_min;
- data[RTC_HOUR] = tm->tm_hour;
- data[RTC_WEEKDAY] = 1 << tm->tm_wday;
- data[RTC_DATE] = tm->tm_mday;
- data[RTC_MONTH] = tm->tm_mon + 1;
- data[RTC_YEAR] = tm->tm_year;
-
- return 0;
-}
-
-static int max77802_rtc_update(struct max77802_rtc_info *info,
- enum MAX77802_RTC_OP op)
-{
- int ret;
- unsigned int data;
-
- if (op == MAX77802_RTC_WRITE)
- data = 1 << RTC_UDR_SHIFT;
- else
- data = 1 << RTC_RBUDR_SHIFT;
-
- ret = regmap_update_bits(info->max77802->regmap,
- MAX77802_RTC_UPDATE0, data, data);
- if (ret < 0)
- dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
- __func__, ret, data);
- else {
- /* Minimum delay required before RTC update. */
- usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
- MAX77802_RTC_UPDATE_DELAY_US * 2);
- }
-
- return ret;
-}
-
-static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
- u8 data[RTC_NR_TIME];
- int ret;
-
- mutex_lock(&info->lock);
-
- ret = max77802_rtc_update(info, MAX77802_RTC_READ);
- if (ret < 0)
- goto out;
-
- ret = regmap_bulk_read(info->max77802->regmap,
- MAX77802_RTC_SEC, data, RTC_NR_TIME);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
- ret);
- goto out;
- }
-
- max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
-
- ret = rtc_valid_tm(tm);
-
-out:
- mutex_unlock(&info->lock);
- return ret;
-}
-
-static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
- u8 data[RTC_NR_TIME];
- int ret;
-
- ret = max77802_rtc_tm_to_data(tm, data);
- if (ret < 0)
- return ret;
-
- mutex_lock(&info->lock);
-
- ret = regmap_bulk_write(info->max77802->regmap,
- MAX77802_RTC_SEC, data, RTC_NR_TIME);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
- ret);
- goto out;
- }
-
- ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-
-out:
- mutex_unlock(&info->lock);
- return ret;
-}
-
-static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
- u8 data[RTC_NR_TIME];
- unsigned int val;
- int ret;
-
- mutex_lock(&info->lock);
-
- ret = max77802_rtc_update(info, MAX77802_RTC_READ);
- if (ret < 0)
- goto out;
-
- ret = regmap_bulk_read(info->max77802->regmap,
- MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
- if (ret < 0) {
- dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
- __func__, __LINE__, ret);
- goto out;
- }
-
- max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
-
- alrm->enabled = 0;
- ret = regmap_read(info->max77802->regmap,
- MAX77802_RTC_AE1, &val);
- if (ret < 0) {
- dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
- __func__, __LINE__, ret);
- goto out;
- }
- if (val)
- alrm->enabled = 1;
-
- alrm->pending = 0;
- ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
- if (ret < 0) {
- dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
- __func__, __LINE__, ret);
- goto out;
- }
-
- if (val & (1 << 2)) /* RTCA1 */
- alrm->pending = 1;
-
-out:
- mutex_unlock(&info->lock);
- return 0;
-}
-
-static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
-{
- int ret;
-
- if (!mutex_is_locked(&info->lock))
- dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
-
- ret = max77802_rtc_update(info, MAX77802_RTC_READ);
- if (ret < 0)
- goto out;
-
- ret = regmap_write(info->max77802->regmap,
- MAX77802_RTC_AE1, 0);
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
- __func__, ret);
- goto out;
- }
-
- ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-out:
- return ret;
-}
-
-static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
-{
- int ret;
-
- if (!mutex_is_locked(&info->lock))
- dev_warn(info->dev, "%s: should have mutex locked\n",
- __func__);
-
- ret = max77802_rtc_update(info, MAX77802_RTC_READ);
- if (ret < 0)
- goto out;
-
- ret = regmap_write(info->max77802->regmap,
- MAX77802_RTC_AE1,
- ALARM_ENABLE_VALUE);
-
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
- __func__, ret);
- goto out;
- }
-
- ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-out:
- return ret;
-}
-
-static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
- u8 data[RTC_NR_TIME];
- int ret;
-
- ret = max77802_rtc_tm_to_data(&alrm->time, data);
- if (ret < 0)
- return ret;
-
- mutex_lock(&info->lock);
-
- ret = max77802_rtc_stop_alarm(info);
- if (ret < 0)
- goto out;
-
- ret = regmap_bulk_write(info->max77802->regmap,
- MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
-
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
- __func__, ret);
- goto out;
- }
-
- ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
- if (ret < 0)
- goto out;
-
- if (alrm->enabled)
- ret = max77802_rtc_start_alarm(info);
-out:
- mutex_unlock(&info->lock);
- return ret;
-}
-
-static int max77802_rtc_alarm_irq_enable(struct device *dev,
- unsigned int enabled)
-{
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
- int ret;
-
- mutex_lock(&info->lock);
- if (enabled)
- ret = max77802_rtc_start_alarm(info);
- else
- ret = max77802_rtc_stop_alarm(info);
- mutex_unlock(&info->lock);
-
- return ret;
-}
-
-static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
-{
- struct max77802_rtc_info *info = data;
-
- dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
-
- rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
-
- return IRQ_HANDLED;
-}
-
-static const struct rtc_class_ops max77802_rtc_ops = {
- .read_time = max77802_rtc_read_time,
- .set_time = max77802_rtc_set_time,
- .read_alarm = max77802_rtc_read_alarm,
- .set_alarm = max77802_rtc_set_alarm,
- .alarm_irq_enable = max77802_rtc_alarm_irq_enable,
-};
-
-static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
-{
- u8 data[2];
- int ret;
-
- max77802_rtc_update(info, MAX77802_RTC_READ);
-
- /* Set RTC control register : Binary mode, 24hour mdoe */
- data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
- data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
-
- info->rtc_24hr_mode = 1;
-
- ret = regmap_bulk_write(info->max77802->regmap,
- MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
- if (ret < 0) {
- dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
- __func__, ret);
- return ret;
- }
-
- ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
- return ret;
-}
-
-static int max77802_rtc_probe(struct platform_device *pdev)
-{
- struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
- struct max77802_rtc_info *info;
- int ret;
-
- dev_dbg(&pdev->dev, "%s\n", __func__);
-
- info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
- GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- mutex_init(&info->lock);
- info->dev = &pdev->dev;
- info->max77802 = max77802;
- info->rtc = max77802->i2c;
-
- platform_set_drvdata(pdev, info);
-
- ret = max77802_rtc_init_reg(info);
-
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
- return ret;
- }
-
- device_init_wakeup(&pdev->dev, 1);
-
- info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
- &max77802_rtc_ops, THIS_MODULE);
-
- if (IS_ERR(info->rtc_dev)) {
- ret = PTR_ERR(info->rtc_dev);
- dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
- if (ret == 0)
- ret = -EINVAL;
- return ret;
- }
-
- if (!max77802->rtc_irq_data) {
- dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
- return -EINVAL;
- }
-
- info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
- MAX77686_RTCIRQ_RTCA1);
-
- if (info->virq <= 0) {
- dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
- MAX77686_RTCIRQ_RTCA1);
- return -EINVAL;
- }
-
- ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
- max77802_rtc_alarm_irq, 0, "rtc-alarm1",
- info);
- if (ret < 0)
- dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
- info->virq, ret);
-
- return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int max77802_rtc_suspend(struct device *dev)
-{
- if (device_may_wakeup(dev)) {
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
-
- return enable_irq_wake(info->virq);
- }
-
- return 0;
-}
-
-static int max77802_rtc_resume(struct device *dev)
-{
- if (device_may_wakeup(dev)) {
- struct max77802_rtc_info *info = dev_get_drvdata(dev);
-
- return disable_irq_wake(info->virq);
- }
-
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
- max77802_rtc_suspend, max77802_rtc_resume);
-
-static const struct platform_device_id rtc_id[] = {
- { "max77802-rtc", 0 },
- {},
-};
-MODULE_DEVICE_TABLE(platform, rtc_id);
-
-static struct platform_driver max77802_rtc_driver = {
- .driver = {
- .name = "max77802-rtc",
- .pm = &max77802_rtc_pm_ops,
- },
- .probe = max77802_rtc_probe,
- .id_table = rtc_id,
-};
-
-module_platform_driver(max77802_rtc_driver);
-
-MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
-MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index ea8a31c91641..d9a44ad1239b 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -48,6 +48,7 @@
#define DRV_VERSION "0.6"
+/* REGISTERS */
#define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */
#define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */
#define PCF2123_REG_SC (0x02) /* datetime */
@@ -57,10 +58,53 @@
#define PCF2123_REG_DW (0x06)
#define PCF2123_REG_MO (0x07)
#define PCF2123_REG_YR (0x08)
+#define PCF2123_REG_ALRM_MN (0x09) /* Alarm Registers */
+#define PCF2123_REG_ALRM_HR (0x0a)
+#define PCF2123_REG_ALRM_DM (0x0b)
+#define PCF2123_REG_ALRM_DW (0x0c)
+#define PCF2123_REG_OFFSET (0x0d) /* Clock Rate Offset Register */
+#define PCF2123_REG_TMR_CLKOUT (0x0e) /* Timer Registers */
+#define PCF2123_REG_CTDWN_TMR (0x0f)
+
+/* PCF2123_REG_CTRL1 BITS */
+#define CTRL1_CLEAR (0) /* Clear */
+#define CTRL1_CORR_INT BIT(1) /* Correction irq enable */
+#define CTRL1_12_HOUR BIT(2) /* 12 hour time */
+#define CTRL1_SW_RESET (BIT(3) | BIT(4) | BIT(6)) /* Software reset */
+#define CTRL1_STOP BIT(5) /* Stop the clock */
+#define CTRL1_EXT_TEST BIT(7) /* External clock test mode */
+
+/* PCF2123_REG_CTRL2 BITS */
+#define CTRL2_TIE BIT(0) /* Countdown timer irq enable */
+#define CTRL2_AIE BIT(1) /* Alarm irq enable */
+#define CTRL2_TF BIT(2) /* Countdown timer flag */
+#define CTRL2_AF BIT(3) /* Alarm flag */
+#define CTRL2_TI_TP BIT(4) /* Irq pin generates pulse */
+#define CTRL2_MSF BIT(5) /* Minute or second irq flag */
+#define CTRL2_SI BIT(6) /* Second irq enable */
+#define CTRL2_MI BIT(7) /* Minute irq enable */
+
+/* PCF2123_REG_SC BITS */
+#define OSC_HAS_STOPPED BIT(7) /* Clock has been stopped */
+
+/* PCF2123_REG_ALRM_XX BITS */
+#define ALRM_ENABLE BIT(7) /* MN, HR, DM, or DW alarm enable */
+
+/* PCF2123_REG_TMR_CLKOUT BITS */
+#define CD_TMR_4096KHZ (0) /* 4096 KHz countdown timer */
+#define CD_TMR_64HZ (1) /* 64 Hz countdown timer */
+#define CD_TMR_1HZ (2) /* 1 Hz countdown timer */
+#define CD_TMR_60th_HZ (3) /* 60th Hz countdown timer */
+#define CD_TMR_TE BIT(3) /* Countdown timer enable */
+
+/* PCF2123_REG_OFFSET BITS */
+#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */
+#define OFFSET_COARSE BIT(7) /* Coarse mode offset */
+
+/* READ/WRITE ADDRESS BITS */
+#define PCF2123_WRITE BIT(4)
+#define PCF2123_READ (BIT(4) | BIT(7))
-#define PCF2123_SUBADDR (1 << 4)
-#define PCF2123_WRITE ((0 << 7) | PCF2123_SUBADDR)
-#define PCF2123_READ ((1 << 7) | PCF2123_SUBADDR)
static struct spi_driver pcf2123_driver;
@@ -84,12 +128,44 @@ static inline void pcf2123_delay_trec(void)
ndelay(30);
}
+static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+ reg |= PCF2123_READ;
+ ret = spi_write_then_read(spi, &reg, 1, rxbuf, size);
+ pcf2123_delay_trec();
+
+ return ret;
+}
+
+static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+ txbuf[0] |= PCF2123_WRITE;
+ ret = spi_write(spi, txbuf, size);
+ pcf2123_delay_trec();
+
+ return ret;
+}
+
+static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val)
+{
+ u8 txbuf[2];
+
+ txbuf[0] = reg;
+ txbuf[1] = val;
+ return pcf2123_write(dev, txbuf, sizeof(txbuf));
+}
+
static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
char *buffer)
{
- struct spi_device *spi = to_spi_device(dev);
struct pcf2123_sysfs_reg *r;
- u8 txbuf[1], rxbuf[1];
+ u8 rxbuf[1];
unsigned long reg;
int ret;
@@ -99,19 +175,16 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
- txbuf[0] = PCF2123_READ | reg;
- ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
+ ret = pcf2123_read(dev, reg, rxbuf, 1);
if (ret < 0)
return -EIO;
- pcf2123_delay_trec();
+
return sprintf(buffer, "0x%x\n", rxbuf[0]);
}
static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
const char *buffer, size_t count) {
- struct spi_device *spi = to_spi_device(dev);
struct pcf2123_sysfs_reg *r;
- u8 txbuf[2];
unsigned long reg;
unsigned long val;
@@ -127,27 +200,25 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
- txbuf[0] = PCF2123_WRITE | reg;
- txbuf[1] = val;
- ret = spi_write(spi, txbuf, sizeof(txbuf));
+ pcf2123_write_reg(dev, reg, val);
if (ret < 0)
return -EIO;
- pcf2123_delay_trec();
return count;
}
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- u8 txbuf[1], rxbuf[7];
+ u8 rxbuf[7];
int ret;
- txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
- ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
- rxbuf, sizeof(rxbuf));
+ ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf));
if (ret < 0)
return ret;
- pcf2123_delay_trec();
+
+ if (rxbuf[0] & OSC_HAS_STOPPED) {
+ dev_info(dev, "clock was stopped. Time is not valid\n");
+ return -EINVAL;
+ }
tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
@@ -170,7 +241,6 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
u8 txbuf[8];
int ret;
@@ -181,15 +251,12 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* Stop the counter first */
- txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
- txbuf[1] = 0x20;
- ret = spi_write(spi, txbuf, 2);
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
if (ret < 0)
return ret;
- pcf2123_delay_trec();
/* Set the new time */
- txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC;
+ txbuf[0] = PCF2123_REG_SC;
txbuf[1] = bin2bcd(tm->tm_sec & 0x7F);
txbuf[2] = bin2bcd(tm->tm_min & 0x7F);
txbuf[3] = bin2bcd(tm->tm_hour & 0x3F);
@@ -198,18 +265,48 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */
txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);
- ret = spi_write(spi, txbuf, sizeof(txbuf));
+ ret = pcf2123_write(dev, txbuf, sizeof(txbuf));
if (ret < 0)
return ret;
- pcf2123_delay_trec();
/* Start the counter */
- txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
- txbuf[1] = 0x00;
- ret = spi_write(spi, txbuf, 2);
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int pcf2123_reset(struct device *dev)
+{
+ int ret;
+ u8 rxbuf[2];
+
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
+ if (ret < 0)
+ return ret;
+
+ /* Stop the counter */
+ dev_dbg(dev, "stopping RTC\n");
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
+ if (ret < 0)
+ return ret;
+
+ /* See if the counter was actually stopped */
+ dev_dbg(dev, "checking for presence of RTC\n");
+ ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf));
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n",
+ rxbuf[0], rxbuf[1]);
+ if (!(rxbuf[0] & CTRL1_STOP))
+ return -ENODEV;
+
+ /* Start the counter */
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
if (ret < 0)
return ret;
- pcf2123_delay_trec();
return 0;
}
@@ -222,8 +319,8 @@ static const struct rtc_class_ops pcf2123_rtc_ops = {
static int pcf2123_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
+ struct rtc_time tm;
struct pcf2123_plat_data *pdata;
- u8 txbuf[2], rxbuf[2];
int ret, i;
pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data),
@@ -232,56 +329,19 @@ static int pcf2123_probe(struct spi_device *spi)
return -ENOMEM;
spi->dev.platform_data = pdata;
- /* Send a software reset command */
- txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
- txbuf[1] = 0x58;
- dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n",
- txbuf[0], txbuf[1]);
- ret = spi_write(spi, txbuf, 2 * sizeof(u8));
- if (ret < 0)
- goto kfree_exit;
- pcf2123_delay_trec();
-
- /* Stop the counter */
- txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
- txbuf[1] = 0x20;
- dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n",
- txbuf[0], txbuf[1]);
- ret = spi_write(spi, txbuf, 2 * sizeof(u8));
- if (ret < 0)
- goto kfree_exit;
- pcf2123_delay_trec();
-
- /* See if the counter was actually stopped */
- txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
- dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n",
- txbuf[0]);
- ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8),
- rxbuf, 2 * sizeof(u8));
- dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n",
- rxbuf[0], rxbuf[1]);
- if (ret < 0)
- goto kfree_exit;
- pcf2123_delay_trec();
-
- if (!(rxbuf[0] & 0x20)) {
- dev_err(&spi->dev, "chip not found\n");
- ret = -ENODEV;
- goto kfree_exit;
+ ret = pcf2123_rtc_read_time(&spi->dev, &tm);
+ if (ret < 0) {
+ ret = pcf2123_reset(&spi->dev);
+ if (ret < 0) {
+ dev_err(&spi->dev, "chip not found\n");
+ goto kfree_exit;
+ }
}
dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
dev_info(&spi->dev, "spiclk %u KHz.\n",
(spi->max_speed_hz + 500) / 1000);
- /* Start the counter */
- txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
- txbuf[1] = 0x00;
- ret = spi_write(spi, txbuf, sizeof(txbuf));
- if (ret < 0)
- goto kfree_exit;
- pcf2123_delay_trec();
-
/* Finalize the initialization */
rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name,
&pcf2123_rtc_ops, THIS_MODULE);
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
new file mode 100644
index 000000000000..bbad00b233bc
--- /dev/null
+++ b/drivers/rtc/rtc-rx6110.c
@@ -0,0 +1,402 @@
+/*
+ * Driver for the Epson RTC module RX-6110 SA
+ *
+ * Copyright(C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ * Copyright(C) SEIKO EPSON CORPORATION 2013. All rights reserved.
+ *
+ * This driver software is distributed as is, without any warranty of any kind,
+ * either express or implied as further specified in the GNU Public License.
+ * This software may be used and distributed according to the terms of the GNU
+ * Public License, version 2 as published by the Free Software Foundation.
+ * See the file COPYING in the main directory of this archive for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+
+/* RX-6110 Register definitions */
+#define RX6110_REG_SEC 0x10
+#define RX6110_REG_MIN 0x11
+#define RX6110_REG_HOUR 0x12
+#define RX6110_REG_WDAY 0x13
+#define RX6110_REG_MDAY 0x14
+#define RX6110_REG_MONTH 0x15
+#define RX6110_REG_YEAR 0x16
+#define RX6110_REG_RES1 0x17
+#define RX6110_REG_ALMIN 0x18
+#define RX6110_REG_ALHOUR 0x19
+#define RX6110_REG_ALWDAY 0x1A
+#define RX6110_REG_TCOUNT0 0x1B
+#define RX6110_REG_TCOUNT1 0x1C
+#define RX6110_REG_EXT 0x1D
+#define RX6110_REG_FLAG 0x1E
+#define RX6110_REG_CTRL 0x1F
+#define RX6110_REG_USER0 0x20
+#define RX6110_REG_USER1 0x21
+#define RX6110_REG_USER2 0x22
+#define RX6110_REG_USER3 0x23
+#define RX6110_REG_USER4 0x24
+#define RX6110_REG_USER5 0x25
+#define RX6110_REG_USER6 0x26
+#define RX6110_REG_USER7 0x27
+#define RX6110_REG_USER8 0x28
+#define RX6110_REG_USER9 0x29
+#define RX6110_REG_USERA 0x2A
+#define RX6110_REG_USERB 0x2B
+#define RX6110_REG_USERC 0x2C
+#define RX6110_REG_USERD 0x2D
+#define RX6110_REG_USERE 0x2E
+#define RX6110_REG_USERF 0x2F
+#define RX6110_REG_RES2 0x30
+#define RX6110_REG_RES3 0x31
+#define RX6110_REG_IRQ 0x32
+
+#define RX6110_BIT_ALARM_EN BIT(7)
+
+/* Extension Register (1Dh) bit positions */
+#define RX6110_BIT_EXT_TSEL0 BIT(0)
+#define RX6110_BIT_EXT_TSEL1 BIT(1)
+#define RX6110_BIT_EXT_TSEL2 BIT(2)
+#define RX6110_BIT_EXT_WADA BIT(3)
+#define RX6110_BIT_EXT_TE BIT(4)
+#define RX6110_BIT_EXT_USEL BIT(5)
+#define RX6110_BIT_EXT_FSEL0 BIT(6)
+#define RX6110_BIT_EXT_FSEL1 BIT(7)
+
+/* Flag Register (1Eh) bit positions */
+#define RX6110_BIT_FLAG_VLF BIT(1)
+#define RX6110_BIT_FLAG_AF BIT(3)
+#define RX6110_BIT_FLAG_TF BIT(4)
+#define RX6110_BIT_FLAG_UF BIT(5)
+
+/* Control Register (1Fh) bit positions */
+#define RX6110_BIT_CTRL_TBKE BIT(0)
+#define RX6110_BIT_CTRL_TBKON BIT(1)
+#define RX6110_BIT_CTRL_TSTP BIT(2)
+#define RX6110_BIT_CTRL_AIE BIT(3)
+#define RX6110_BIT_CTRL_TIE BIT(4)
+#define RX6110_BIT_CTRL_UIE BIT(5)
+#define RX6110_BIT_CTRL_STOP BIT(6)
+#define RX6110_BIT_CTRL_TEST BIT(7)
+
+enum {
+ RTC_SEC = 0,
+ RTC_MIN,
+ RTC_HOUR,
+ RTC_WDAY,
+ RTC_MDAY,
+ RTC_MONTH,
+ RTC_YEAR,
+ RTC_NR_TIME
+};
+
+#define RX6110_DRIVER_NAME "rx6110"
+
+struct rx6110_data {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+};
+
+/**
+ * rx6110_rtc_tm_to_data - convert rtc_time to native time encoding
+ *
+ * @tm: holds date and time
+ * @data: holds the encoding in rx6110 native form
+ */
+static int rx6110_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+ pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+ /*
+ * The year in the RTC is a value between 0 and 99.
+ * Assume that this represents the current century
+ * and disregard all other values.
+ */
+ if (tm->tm_year < 100 || tm->tm_year >= 200)
+ return -EINVAL;
+
+ data[RTC_SEC] = bin2bcd(tm->tm_sec);
+ data[RTC_MIN] = bin2bcd(tm->tm_min);
+ data[RTC_HOUR] = bin2bcd(tm->tm_hour);
+ data[RTC_WDAY] = BIT(bin2bcd(tm->tm_wday));
+ data[RTC_MDAY] = bin2bcd(tm->tm_mday);
+ data[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
+ data[RTC_YEAR] = bin2bcd(tm->tm_year % 100);
+
+ return 0;
+}
+
+/**
+ * rx6110_data_to_rtc_tm - convert native time encoding to rtc_time
+ *
+ * @data: holds the encoding in rx6110 native form
+ * @tm: holds date and time
+ */
+static int rx6110_data_to_rtc_tm(u8 *data, struct rtc_time *tm)
+{
+ tm->tm_sec = bcd2bin(data[RTC_SEC] & 0x7f);
+ tm->tm_min = bcd2bin(data[RTC_MIN] & 0x7f);
+ /* only 24-hour clock */
+ tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
+ tm->tm_wday = ffs(data[RTC_WDAY] & 0x7f);
+ tm->tm_mday = bcd2bin(data[RTC_MDAY] & 0x3f);
+ tm->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1f) - 1;
+ tm->tm_year = bcd2bin(data[RTC_YEAR]) + 100;
+
+ pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+ /*
+ * The year in the RTC is a value between 0 and 99.
+ * Assume that this represents the current century
+ * and disregard all other values.
+ */
+ if (tm->tm_year < 100 || tm->tm_year >= 200)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * rx6110_set_time - set the current time in the rx6110 registers
+ *
+ * @dev: the rtc device in use
+ * @tm: holds date and time
+ *
+ * BUG: The HW assumes every year that is a multiple of 4 to be a leap
+ * year. Next time this is wrong is 2100, which will not be a leap year
+ *
+ * Note: If STOP is not set/cleared, the clock will start when the seconds
+ * register is written
+ *
+ */
+static int rx6110_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rx6110_data *rx6110 = dev_get_drvdata(dev);
+ u8 data[RTC_NR_TIME];
+ int ret;
+
+ ret = rx6110_rtc_tm_to_data(tm, data);
+ if (ret < 0)
+ return ret;
+
+ /* set STOP bit before changing clock/calendar */
+ ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
+ RX6110_BIT_CTRL_STOP, RX6110_BIT_CTRL_STOP);
+ if (ret)
+ return ret;
+
+ ret = regmap_bulk_write(rx6110->regmap, RX6110_REG_SEC, data,
+ RTC_NR_TIME);
+ if (ret)
+ return ret;
+
+ /* The time in the RTC is valid. Be sure to have VLF cleared. */
+ ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
+ RX6110_BIT_FLAG_VLF, 0);
+ if (ret)
+ return ret;
+
+ /* clear STOP bit after changing clock/calendar */
+ ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
+ RX6110_BIT_CTRL_STOP, 0);
+
+ return ret;
+}
+
+/**
+ * rx6110_get_time - get the current time from the rx6110 registers
+ * @dev: the rtc device in use
+ * @tm: holds date and time
+ */
+static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rx6110_data *rx6110 = dev_get_drvdata(dev);
+ u8 data[RTC_NR_TIME];
+ int flags;
+ int ret;
+
+ ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
+ if (ret)
+ return -EINVAL;
+
+ /* check for VLF Flag (set at power-on) */
+ if ((flags & RX6110_BIT_FLAG_VLF)) {
+ dev_warn(dev, "Voltage low, data is invalid.\n");
+ return -EINVAL;
+ }
+
+ /* read registers to date */
+ ret = regmap_bulk_read(rx6110->regmap, RX6110_REG_SEC, data,
+ RTC_NR_TIME);
+ if (ret)
+ return ret;
+
+ ret = rx6110_data_to_rtc_tm(data, tm);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+ return rtc_valid_tm(tm);
+}
+
+static const struct reg_sequence rx6110_default_regs[] = {
+ { RX6110_REG_RES1, 0xB8 },
+ { RX6110_REG_RES2, 0x00 },
+ { RX6110_REG_RES3, 0x10 },
+ { RX6110_REG_IRQ, 0x00 },
+ { RX6110_REG_ALMIN, 0x00 },
+ { RX6110_REG_ALHOUR, 0x00 },
+ { RX6110_REG_ALWDAY, 0x00 },
+};
+
+/**
+ * rx6110_init - initialize the rx6110 registers
+ *
+ * @rx6110: pointer to the rx6110 struct in use
+ *
+ */
+static int rx6110_init(struct rx6110_data *rx6110)
+{
+ struct rtc_device *rtc = rx6110->rtc;
+ int flags;
+ int ret;
+
+ ret = regmap_update_bits(rx6110->regmap, RX6110_REG_EXT,
+ RX6110_BIT_EXT_TE, 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_register_patch(rx6110->regmap, rx6110_default_regs,
+ ARRAY_SIZE(rx6110_default_regs));
+ if (ret)
+ return ret;
+
+ ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
+ if (ret)
+ return ret;
+
+ /* check for VLF Flag (set at power-on) */
+ if ((flags & RX6110_BIT_FLAG_VLF))
+ dev_warn(&rtc->dev, "Voltage low, data loss detected.\n");
+
+ /* check for Alarm Flag */
+ if (flags & RX6110_BIT_FLAG_AF)
+ dev_warn(&rtc->dev, "An alarm may have been missed.\n");
+
+ /* check for Periodic Timer Flag */
+ if (flags & RX6110_BIT_FLAG_TF)
+ dev_warn(&rtc->dev, "Periodic timer was detected\n");
+
+ /* check for Update Timer Flag */
+ if (flags & RX6110_BIT_FLAG_UF)
+ dev_warn(&rtc->dev, "Update timer was detected\n");
+
+ /* clear all flags BUT VLF */
+ ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
+ RX6110_BIT_FLAG_AF |
+ RX6110_BIT_FLAG_UF |
+ RX6110_BIT_FLAG_TF,
+ 0);
+
+ return ret;
+}
+
+static struct rtc_class_ops rx6110_rtc_ops = {
+ .read_time = rx6110_get_time,
+ .set_time = rx6110_set_time,
+};
+
+static struct regmap_config regmap_spi_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RX6110_REG_IRQ,
+ .read_flag_mask = 0x80,
+};
+
+/**
+ * rx6110_probe - initialize rtc driver
+ * @spi: pointer to spi device
+ */
+static int rx6110_probe(struct spi_device *spi)
+{
+ struct rx6110_data *rx6110;
+ int err;
+
+ if ((spi->bits_per_word && spi->bits_per_word != 8) ||
+ (spi->max_speed_hz > 2000000) ||
+ (spi->mode != (SPI_CS_HIGH | SPI_CPOL | SPI_CPHA))) {
+ dev_warn(&spi->dev, "SPI settings: bits_per_word: %d, max_speed_hz: %d, mode: %xh\n",
+ spi->bits_per_word, spi->max_speed_hz, spi->mode);
+ dev_warn(&spi->dev, "driving device in an unsupported mode");
+ }
+
+ rx6110 = devm_kzalloc(&spi->dev, sizeof(*rx6110), GFP_KERNEL);
+ if (!rx6110)
+ return -ENOMEM;
+
+ rx6110->regmap = devm_regmap_init_spi(spi, &regmap_spi_config);
+ if (IS_ERR(rx6110->regmap)) {
+ dev_err(&spi->dev, "regmap init failed for rtc rx6110\n");
+ return PTR_ERR(rx6110->regmap);
+ }
+
+ spi_set_drvdata(spi, rx6110);
+
+ rx6110->rtc = devm_rtc_device_register(&spi->dev,
+ RX6110_DRIVER_NAME,
+ &rx6110_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rx6110->rtc))
+ return PTR_ERR(rx6110->rtc);
+
+ err = rx6110_init(rx6110);
+ if (err)
+ return err;
+
+ rx6110->rtc->max_user_freq = 1;
+
+ return 0;
+}
+
+static int rx6110_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static const struct spi_device_id rx6110_id[] = {
+ { "rx6110", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, rx6110_id);
+
+static struct spi_driver rx6110_driver = {
+ .driver = {
+ .name = RX6110_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = rx6110_probe,
+ .remove = rx6110_remove,
+ .id_table = rx6110_id,
+};
+
+module_spi_driver(rx6110_driver);
+
+MODULE_AUTHOR("Val Krutov <val.krutov@erd.epson.com>");
+MODULE_DESCRIPTION("RX-6110 SA RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index bd911bafb809..17341feadad1 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -65,7 +65,6 @@
static const struct i2c_device_id rx8025_id[] = {
{ "rx8025", 0 },
- { "rv8803", 1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx8025_id);