From be7d9c9161b9c76edeff15e79edc2f256568fe05 Mon Sep 17 00:00:00 2001 From: Daniel Palmer Date: Mon, 23 Aug 2021 19:16:12 +0200 Subject: rtc: Add support for the MSTAR MSC313 RTC This adds support for the RTC block on the Mstar MSC313e SoCs and newer. Signed-off-by: Daniel Palmer Co-developed-by: Romain Perier Signed-off-by: Romain Perier Reviewed-by: Nobuhiro Iwamatsu Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20210823171613.18941-3-romain.perier@gmail.com --- drivers/rtc/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/rtc/Kconfig') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e1bc5214494e..59dc1410a160 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1935,4 +1935,14 @@ config RTC_DRV_WILCO_EC This can also be built as a module. If so, the module will be named "rtc_wilco_ec". +config RTC_DRV_MSC313 + tristate "MStar MSC313 RTC" + depends on ARCH_MSTARV7 || COMPILE_TEST + help + If you say yes here you get support for the Mstar MSC313e On-Chip + Real Time Clock. + + This driver can also be built as a module, if so, the module + will be called "rtc-msc313". + endif # RTC_CLASS -- cgit v1.2.3 From 91f3849d956d58073ef55e01f2e8871dc30847a5 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 18 Oct 2021 17:36:46 +0200 Subject: rtc: pcf8523: switch to regmap Use regmap to access the RTC registers, this is a huge reduction in code lines and generated code. Values on ARMv7: text data bss dec hex 5180 132 0 5312 14c0 before 3900 132 0 4032 fc0 after Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211018153651.82069-1-alexandre.belloni@bootlin.com --- drivers/rtc/Kconfig | 1 + drivers/rtc/rtc-pcf8523.c | 303 +++++++++++++--------------------------------- 2 files changed, 85 insertions(+), 219 deletions(-) (limited to 'drivers/rtc/Kconfig') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 59dc1410a160..8dc92b4e042f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -441,6 +441,7 @@ config RTC_DRV_X1205 config RTC_DRV_PCF8523 tristate "NXP PCF8523" + select REGMAP_I2C help If you say yes here you get support for the NXP PCF8523 RTC chips. diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 09110b3ae25f..c5d31c525997 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -49,115 +50,45 @@ struct pcf8523 { struct rtc_device *rtc; - struct i2c_client *client; + struct regmap *regmap; }; -static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep) +static int pcf8523_load_capacitance(struct pcf8523 *pcf8523, struct device_node *node) { - struct i2c_msg msgs[2]; - u8 value = 0; - int err; - - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = sizeof(reg); - msgs[0].buf = ® - - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = sizeof(value); - msgs[1].buf = &value; - - err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (err < 0) - return err; - - *valuep = value; - - return 0; -} - -static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value) -{ - u8 buffer[2] = { reg, value }; - struct i2c_msg msg; - int err; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = sizeof(buffer); - msg.buf = buffer; - - err = i2c_transfer(client->adapter, &msg, 1); - if (err < 0) - return err; - - return 0; -} - -static int pcf8523_load_capacitance(struct i2c_client *client) -{ - u32 load; - u8 value; - int err; - - err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); - if (err < 0) - return err; + u32 load, value = 0; load = 12500; - of_property_read_u32(client->dev.of_node, "quartz-load-femtofarads", - &load); + of_property_read_u32(node, "quartz-load-femtofarads", &load); switch (load) { default: - dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500", + dev_warn(&pcf8523->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500", load); fallthrough; case 12500: value |= PCF8523_CONTROL1_CAP_SEL; break; case 7000: - value &= ~PCF8523_CONTROL1_CAP_SEL; break; } - err = pcf8523_write(client, PCF8523_REG_CONTROL1, value); - - return err; -} - -static int pcf8523_set_pm(struct i2c_client *client, u8 pm) -{ - u8 value; - int err; - - err = pcf8523_read(client, PCF8523_REG_CONTROL3, &value); - if (err < 0) - return err; - - value = (value & ~PCF8523_CONTROL3_PM_MASK) | pm; - - err = pcf8523_write(client, PCF8523_REG_CONTROL3, value); - if (err < 0) - return err; - - return 0; + return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1, + PCF8523_CONTROL1_CAP_SEL, value); } static irqreturn_t pcf8523_irq(int irq, void *dev_id) { - struct pcf8523 *pcf8523 = i2c_get_clientdata(dev_id); - u8 value; + struct pcf8523 *pcf8523 = dev_id; + u32 value; int err; - err = pcf8523_read(pcf8523->client, PCF8523_REG_CONTROL2, &value); + err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL2, &value); if (err < 0) return IRQ_HANDLED; if (value & PCF8523_CONTROL2_AF) { value &= ~PCF8523_CONTROL2_AF; - pcf8523_write(pcf8523->client, PCF8523_REG_CONTROL2, value); + regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL2, value); rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF); return IRQ_HANDLED; @@ -166,60 +97,14 @@ static irqreturn_t pcf8523_irq(int irq, void *dev_id) return IRQ_NONE; } -static int pcf8523_stop_rtc(struct i2c_client *client) -{ - u8 value; - int err; - - err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); - if (err < 0) - return err; - - value |= PCF8523_CONTROL1_STOP; - - err = pcf8523_write(client, PCF8523_REG_CONTROL1, value); - if (err < 0) - return err; - - return 0; -} - -static int pcf8523_start_rtc(struct i2c_client *client) -{ - u8 value; - int err; - - err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); - if (err < 0) - return err; - - value &= ~PCF8523_CONTROL1_STOP; - - err = pcf8523_write(client, PCF8523_REG_CONTROL1, value); - if (err < 0) - return err; - - return 0; -} - static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct i2c_client *client = to_i2c_client(dev); - u8 start = PCF8523_REG_SECONDS, regs[7]; - struct i2c_msg msgs[2]; + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); + u8 regs[7]; int err; - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = 1; - msgs[0].buf = &start; - - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = sizeof(regs); - msgs[1].buf = regs; - - err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + err = regmap_bulk_read(pcf8523->regmap, PCF8523_REG_SECONDS, regs, + sizeof(regs)); if (err < 0) return err; @@ -239,63 +124,50 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct i2c_client *client = to_i2c_client(dev); - struct i2c_msg msg; - u8 regs[8]; + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); + u8 regs[7]; int err; - err = pcf8523_stop_rtc(client); + err = regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1, + PCF8523_CONTROL1_STOP, PCF8523_CONTROL1_STOP); if (err < 0) return err; - regs[0] = PCF8523_REG_SECONDS; /* This will purposely overwrite PCF8523_SECONDS_OS */ - regs[1] = bin2bcd(tm->tm_sec); - regs[2] = bin2bcd(tm->tm_min); - regs[3] = bin2bcd(tm->tm_hour); - regs[4] = bin2bcd(tm->tm_mday); - regs[5] = tm->tm_wday; - regs[6] = bin2bcd(tm->tm_mon + 1); - regs[7] = bin2bcd(tm->tm_year - 100); - - msg.addr = client->addr; - msg.flags = 0; - msg.len = sizeof(regs); - msg.buf = regs; - - err = i2c_transfer(client->adapter, &msg, 1); + regs[0] = bin2bcd(tm->tm_sec); + regs[1] = bin2bcd(tm->tm_min); + regs[2] = bin2bcd(tm->tm_hour); + regs[3] = bin2bcd(tm->tm_mday); + regs[4] = tm->tm_wday; + regs[5] = bin2bcd(tm->tm_mon + 1); + regs[6] = bin2bcd(tm->tm_year - 100); + + err = regmap_bulk_write(pcf8523->regmap, PCF8523_REG_SECONDS, regs, + sizeof(regs)); if (err < 0) { /* * If the time cannot be set, restart the RTC anyway. Note * that errors are ignored if the RTC cannot be started so * that we have a chance to propagate the original error. */ - pcf8523_start_rtc(client); + regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1, + PCF8523_CONTROL1_STOP, 0); return err; } - return pcf8523_start_rtc(client); + return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1, + PCF8523_CONTROL1_STOP, 0); } static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) { - struct i2c_client *client = to_i2c_client(dev); - u8 start = PCF8523_REG_MINUTE_ALARM, regs[4]; - struct i2c_msg msgs[2]; - u8 value; + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); + u8 regs[4]; + u32 value; int err; - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = 1; - msgs[0].buf = &start; - - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = sizeof(regs); - msgs[1].buf = regs; - - err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + err = regmap_bulk_read(pcf8523->regmap, PCF8523_REG_MINUTE_ALARM, regs, + sizeof(regs)); if (err < 0) return err; @@ -305,12 +177,12 @@ static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) tm->time.tm_mday = bcd2bin(regs[2] & 0x3F); tm->time.tm_wday = bcd2bin(regs[3] & 0x7); - err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); + err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL1, &value); if (err < 0) return err; tm->enabled = !!(value & PCF8523_CONTROL1_AIE); - err = pcf8523_read(client, PCF8523_REG_CONTROL2, &value); + err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL2, &value); if (err < 0) return err; tm->pending = !!(value & PCF8523_CONTROL2_AF); @@ -320,30 +192,16 @@ static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) static int pcf8523_irq_enable(struct device *dev, unsigned int enabled) { - struct i2c_client *client = to_i2c_client(dev); - u8 value; - int err; + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); - err = pcf8523_read(client, PCF8523_REG_CONTROL1, &value); - if (err < 0) - return err; - - value &= PCF8523_CONTROL1_AIE; - - if (enabled) - value |= PCF8523_CONTROL1_AIE; - - err = pcf8523_write(client, PCF8523_REG_CONTROL1, value); - if (err < 0) - return err; - - return 0; + return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1, + PCF8523_CONTROL1_AIE, enabled ? + PCF8523_CONTROL1_AIE : 0); } static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) { - struct i2c_client *client = to_i2c_client(dev); - struct i2c_msg msg; + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); u8 regs[5]; int err; @@ -351,7 +209,7 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) if (err) return err; - err = pcf8523_write(client, PCF8523_REG_CONTROL2, 0); + err = regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL2, 0); if (err < 0) return err; @@ -363,16 +221,13 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) rtc_time64_to_tm(alarm_time, &tm->time); } - regs[0] = PCF8523_REG_MINUTE_ALARM; - regs[1] = bin2bcd(tm->time.tm_min); - regs[2] = bin2bcd(tm->time.tm_hour); - regs[3] = bin2bcd(tm->time.tm_mday); - regs[4] = ALARM_DIS; - msg.addr = client->addr; - msg.flags = 0; - msg.len = sizeof(regs); - msg.buf = regs; - err = i2c_transfer(client->adapter, &msg, 1); + regs[0] = bin2bcd(tm->time.tm_min); + regs[1] = bin2bcd(tm->time.tm_hour); + regs[2] = bin2bcd(tm->time.tm_mday); + regs[3] = ALARM_DIS; + + err = regmap_bulk_write(pcf8523->regmap, PCF8523_REG_MINUTE_ALARM, regs, + sizeof(regs)); if (err < 0) return err; @@ -386,21 +241,21 @@ static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { - struct i2c_client *client = to_i2c_client(dev); + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); unsigned int flags = 0; - u8 value; + u32 value; int ret; switch (cmd) { case RTC_VL_READ: - ret = pcf8523_read(client, PCF8523_REG_CONTROL3, &value); + ret = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value); if (ret < 0) return ret; if (value & PCF8523_CONTROL3_BLF) flags |= RTC_VL_BACKUP_LOW; - ret = pcf8523_read(client, PCF8523_REG_SECONDS, &value); + ret = regmap_read(pcf8523->regmap, PCF8523_REG_SECONDS, &value); if (ret < 0) return ret; @@ -419,12 +274,12 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, static int pcf8523_rtc_read_offset(struct device *dev, long *offset) { - struct i2c_client *client = to_i2c_client(dev); + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); int err; - u8 value; + u32 value; s8 val; - err = pcf8523_read(client, PCF8523_REG_OFFSET, &value); + err = regmap_read(pcf8523->regmap, PCF8523_REG_OFFSET, &value); if (err < 0) return err; @@ -437,9 +292,9 @@ static int pcf8523_rtc_read_offset(struct device *dev, long *offset) static int pcf8523_rtc_set_offset(struct device *dev, long offset) { - struct i2c_client *client = to_i2c_client(dev); + struct pcf8523 *pcf8523 = dev_get_drvdata(dev); long reg_m0, reg_m1; - u8 value; + u32 value; reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L); reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L); @@ -449,7 +304,7 @@ static int pcf8523_rtc_set_offset(struct device *dev, long offset) else value = (reg_m1 & 0x7f) | PCF8523_OFFSET_MODE; - return pcf8523_write(client, PCF8523_REG_OFFSET, value); + return regmap_write(pcf8523->regmap, PCF8523_REG_OFFSET, value); } static const struct rtc_class_ops pcf8523_rtc_ops = { @@ -463,6 +318,12 @@ static const struct rtc_class_ops pcf8523_rtc_ops = { .set_offset = pcf8523_rtc_set_offset, }; +static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x13, +}; + static int pcf8523_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -478,37 +339,41 @@ static int pcf8523_probe(struct i2c_client *client, if (!pcf8523) return -ENOMEM; + pcf8523->regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(pcf8523->regmap)) + return PTR_ERR(pcf8523->regmap); + i2c_set_clientdata(client, pcf8523); - pcf8523->client = client; - err = pcf8523_load_capacitance(client); + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + pcf8523->rtc = rtc; + + err = pcf8523_load_capacitance(pcf8523, client->dev.of_node); if (err < 0) dev_warn(&client->dev, "failed to set xtal load capacitance: %d", err); - err = pcf8523_set_pm(client, 0); + err = regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL3, + PCF8523_CONTROL3_PM_MASK, 0); if (err < 0) return err; - rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - pcf8523->rtc = rtc; rtc->ops = &pcf8523_rtc_ops; rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_max = RTC_TIMESTAMP_END_2099; rtc->uie_unsupported = 1; if (client->irq > 0) { - err = pcf8523_write(client, PCF8523_TMR_CLKOUT_CTRL, 0x38); + err = regmap_write(pcf8523->regmap, PCF8523_TMR_CLKOUT_CTRL, 0x38); if (err < 0) return err; err = devm_request_threaded_irq(&client->dev, client->irq, NULL, pcf8523_irq, IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, - dev_name(&rtc->dev), client); + dev_name(&rtc->dev), pcf8523); if (err) return err; -- cgit v1.2.3 From 005870f46cf6f98417ec48d129721e945dfb3a43 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 21 Oct 2021 22:22:56 +0300 Subject: rtc: tps80031: Remove driver Driver was upstreamed in 2013 and never got a user, remove it. Signed-off-by: Dmitry Osipenko Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211021192258.21968-2-digetx@gmail.com --- drivers/rtc/Kconfig | 8 -- drivers/rtc/Makefile | 1 - drivers/rtc/rtc-tps80031.c | 324 --------------------------------------------- 3 files changed, 333 deletions(-) delete mode 100644 drivers/rtc/rtc-tps80031.c (limited to 'drivers/rtc/Kconfig') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8dc92b4e042f..f4dfc65693a4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -583,14 +583,6 @@ config RTC_DRV_TPS65910 This driver can also be built as a module. If so, the module will be called rtc-tps65910. -config RTC_DRV_TPS80031 - tristate "TI TPS80031/TPS80032 RTC driver" - depends on MFD_TPS80031 - help - TI Power Management IC TPS80031 supports RTC functionality - along with alarm. This driver supports the RTC driver for - the TPS80031 RTC module. - config RTC_DRV_RC5T583 tristate "RICOH 5T583 RTC driver" depends on MFD_RC5T583 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e76308053b0f..678a8ef4abae 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -170,7 +170,6 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o -obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c deleted file mode 100644 index c77b8eab94a0..000000000000 --- a/drivers/rtc/rtc-tps80031.c +++ /dev/null @@ -1,324 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver - * - * RTC driver for TI TPS80031/TPS80032 Fully Integrated - * Power Management with Power Path and Battery Charger - * - * Copyright (c) 2012, NVIDIA Corporation. - * - * Author: Laxman Dewangan - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ENABLE_ALARM_INT 0x08 -#define ALARM_INT_STATUS 0x40 - -/** - * Setting bit to 1 in STOP_RTC will run the RTC and - * setting this bit to 0 will freeze RTC. - */ -#define STOP_RTC 0x1 - -/* Power on reset Values of RTC registers */ -#define TPS80031_RTC_POR_YEAR 0 -#define TPS80031_RTC_POR_MONTH 1 -#define TPS80031_RTC_POR_DAY 1 - -/* Numbers of registers for time and alarms */ -#define TPS80031_RTC_TIME_NUM_REGS 7 -#define TPS80031_RTC_ALARM_NUM_REGS 6 - -/** - * PMU RTC have only 2 nibbles to store year information, so using an - * offset of 100 to set the base year as 2000 for our driver. - */ -#define RTC_YEAR_OFFSET 100 - -struct tps80031_rtc { - struct rtc_device *rtc; - int irq; -}; - -static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - u8 buff[TPS80031_RTC_TIME_NUM_REGS]; - int ret; - - ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_SECONDS_REG, TPS80031_RTC_TIME_NUM_REGS, buff); - if (ret < 0) { - dev_err(dev, "reading RTC_SECONDS_REG failed, err = %d\n", ret); - return ret; - } - - tm->tm_sec = bcd2bin(buff[0]); - tm->tm_min = bcd2bin(buff[1]); - tm->tm_hour = bcd2bin(buff[2]); - tm->tm_mday = bcd2bin(buff[3]); - tm->tm_mon = bcd2bin(buff[4]) - 1; - tm->tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; - tm->tm_wday = bcd2bin(buff[6]); - return 0; -} - -static int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - u8 buff[7]; - int ret; - - buff[0] = bin2bcd(tm->tm_sec); - buff[1] = bin2bcd(tm->tm_min); - buff[2] = bin2bcd(tm->tm_hour); - buff[3] = bin2bcd(tm->tm_mday); - buff[4] = bin2bcd(tm->tm_mon + 1); - buff[5] = bin2bcd(tm->tm_year % RTC_YEAR_OFFSET); - buff[6] = bin2bcd(tm->tm_wday); - - /* Stop RTC while updating the RTC time registers */ - ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_CTRL_REG, STOP_RTC); - if (ret < 0) { - dev_err(dev->parent, "Stop RTC failed, err = %d\n", ret); - return ret; - } - - ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_SECONDS_REG, - TPS80031_RTC_TIME_NUM_REGS, buff); - if (ret < 0) { - dev_err(dev, "writing RTC_SECONDS_REG failed, err %d\n", ret); - return ret; - } - - ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_CTRL_REG, STOP_RTC); - if (ret < 0) - dev_err(dev->parent, "Start RTC failed, err = %d\n", ret); - return ret; -} - -static int tps80031_rtc_alarm_irq_enable(struct device *dev, - unsigned int enable) -{ - int ret; - - if (enable) - ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); - else - ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); - if (ret < 0) { - dev_err(dev, "Update on RTC_INT failed, err = %d\n", ret); - return ret; - } - return 0; -} - -static int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - u8 buff[TPS80031_RTC_ALARM_NUM_REGS]; - int ret; - - buff[0] = bin2bcd(alrm->time.tm_sec); - buff[1] = bin2bcd(alrm->time.tm_min); - buff[2] = bin2bcd(alrm->time.tm_hour); - buff[3] = bin2bcd(alrm->time.tm_mday); - buff[4] = bin2bcd(alrm->time.tm_mon + 1); - buff[5] = bin2bcd(alrm->time.tm_year % RTC_YEAR_OFFSET); - ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_ALARM_SECONDS_REG, - TPS80031_RTC_ALARM_NUM_REGS, buff); - if (ret < 0) { - dev_err(dev, "Writing RTC_ALARM failed, err %d\n", ret); - return ret; - } - return tps80031_rtc_alarm_irq_enable(dev, alrm->enabled); -} - -static int tps80031_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - u8 buff[6]; - int ret; - - ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_ALARM_SECONDS_REG, - TPS80031_RTC_ALARM_NUM_REGS, buff); - if (ret < 0) { - dev_err(dev->parent, - "reading RTC_ALARM failed, err = %d\n", ret); - return ret; - } - - alrm->time.tm_sec = bcd2bin(buff[0]); - alrm->time.tm_min = bcd2bin(buff[1]); - alrm->time.tm_hour = bcd2bin(buff[2]); - alrm->time.tm_mday = bcd2bin(buff[3]); - alrm->time.tm_mon = bcd2bin(buff[4]) - 1; - alrm->time.tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; - return 0; -} - -static int clear_alarm_int_status(struct device *dev, struct tps80031_rtc *rtc) -{ - int ret; - u8 buf; - - /** - * As per datasheet, A dummy read of this RTC_STATUS_REG register - * is necessary before each I2C read in order to update the status - * register value. - */ - ret = tps80031_read(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_STATUS_REG, &buf); - if (ret < 0) { - dev_err(dev, "reading RTC_STATUS failed. err = %d\n", ret); - return ret; - } - - /* clear Alarm status bits.*/ - ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_STATUS_REG, ALARM_INT_STATUS); - if (ret < 0) { - dev_err(dev, "clear Alarm INT failed, err = %d\n", ret); - return ret; - } - return 0; -} - -static irqreturn_t tps80031_rtc_irq(int irq, void *data) -{ - struct device *dev = data; - struct tps80031_rtc *rtc = dev_get_drvdata(dev); - int ret; - - ret = clear_alarm_int_status(dev, rtc); - if (ret < 0) - return ret; - - rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); - return IRQ_HANDLED; -} - -static const struct rtc_class_ops tps80031_rtc_ops = { - .read_time = tps80031_rtc_read_time, - .set_time = tps80031_rtc_set_time, - .set_alarm = tps80031_rtc_set_alarm, - .read_alarm = tps80031_rtc_read_alarm, - .alarm_irq_enable = tps80031_rtc_alarm_irq_enable, -}; - -static int tps80031_rtc_probe(struct platform_device *pdev) -{ - struct tps80031_rtc *rtc; - struct rtc_time tm; - int ret; - - rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); - if (!rtc) - return -ENOMEM; - - rtc->irq = platform_get_irq(pdev, 0); - platform_set_drvdata(pdev, rtc); - - /* Start RTC */ - ret = tps80031_set_bits(pdev->dev.parent, TPS80031_SLAVE_ID1, - TPS80031_RTC_CTRL_REG, STOP_RTC); - if (ret < 0) { - dev_err(&pdev->dev, "failed to start RTC. err = %d\n", ret); - return ret; - } - - /* If RTC have POR values, set time 01:01:2000 */ - tps80031_rtc_read_time(&pdev->dev, &tm); - if ((tm.tm_year == RTC_YEAR_OFFSET + TPS80031_RTC_POR_YEAR) && - (tm.tm_mon == (TPS80031_RTC_POR_MONTH - 1)) && - (tm.tm_mday == TPS80031_RTC_POR_DAY)) { - tm.tm_year = 2000; - tm.tm_mday = 1; - tm.tm_mon = 1; - ret = tps80031_rtc_set_time(&pdev->dev, &tm); - if (ret < 0) { - dev_err(&pdev->dev, - "RTC set time failed, err = %d\n", ret); - return ret; - } - } - - /* Clear alarm intretupt status if it is there */ - ret = clear_alarm_int_status(&pdev->dev, rtc); - if (ret < 0) { - dev_err(&pdev->dev, "Clear alarm int failed, err = %d\n", ret); - return ret; - } - - rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &tps80031_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc->rtc)) { - ret = PTR_ERR(rtc->rtc); - dev_err(&pdev->dev, "RTC registration failed, err %d\n", ret); - return ret; - } - - ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, - tps80031_rtc_irq, - IRQF_ONESHOT, - dev_name(&pdev->dev), rtc); - if (ret < 0) { - dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n", - rtc->irq, ret); - return ret; - } - device_set_wakeup_capable(&pdev->dev, 1); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int tps80031_rtc_suspend(struct device *dev) -{ - struct tps80031_rtc *rtc = dev_get_drvdata(dev); - - if (device_may_wakeup(dev)) - enable_irq_wake(rtc->irq); - return 0; -} - -static int tps80031_rtc_resume(struct device *dev) -{ - struct tps80031_rtc *rtc = dev_get_drvdata(dev); - - if (device_may_wakeup(dev)) - disable_irq_wake(rtc->irq); - return 0; -}; -#endif - -static SIMPLE_DEV_PM_OPS(tps80031_pm_ops, tps80031_rtc_suspend, - tps80031_rtc_resume); - -static struct platform_driver tps80031_rtc_driver = { - .driver = { - .name = "tps80031-rtc", - .pm = &tps80031_pm_ops, - }, - .probe = tps80031_rtc_probe, -}; - -module_platform_driver(tps80031_rtc_driver); - -MODULE_ALIAS("platform:tps80031-rtc"); -MODULE_DESCRIPTION("TI TPS80031/TPS80032 RTC driver"); -MODULE_AUTHOR("Laxman Dewangan "); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3