diff options
Diffstat (limited to 'drivers/rtc/rtc-ds1307.c')
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 1632 |
1 files changed, 971 insertions, 661 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 4fac49e55d47..7205c59ff729 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. * @@ -5,18 +6,15 @@ * Copyright (C) 2006 David Brownell * Copyright (C) 2009 Matthias Fuchs (rx8025 support) * Copyright (C) 2012 Bertrand Achard (nvram access fixes) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ -#include <linux/acpi.h> #include <linux/bcd.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/kstrtox.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/property.h> #include <linux/rtc/ds1307.h> #include <linux/rtc.h> #include <linux/slab.h> @@ -25,6 +23,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/clk-provider.h> #include <linux/regmap.h> +#include <linux/watchdog.h> /* * We can't determine type by probing, but if we expect pre-Linux code @@ -33,16 +32,19 @@ * That's a natural job for a factory or repair bench. */ enum ds_type { + unknown_ds_type, /* always first and 0 */ ds_1307, ds_1308, ds_1337, ds_1338, ds_1339, ds_1340, + ds_1341, ds_1388, ds_3231, m41t0, m41t00, + m41t11, mcp794xx, rx_8025, rx_8130, @@ -50,7 +52,6 @@ enum ds_type { /* rs5c372 too? different address... */ }; - /* RTC registers don't differ much, except for the century flag */ #define DS1307_REG_SECS 0x00 /* 00-59 */ # define DS1307_BIT_CH 0x80 @@ -64,6 +65,7 @@ enum ds_type { # define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ # define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ #define DS1307_REG_WDAY 0x03 /* 01-07 */ +# define MCP794XX_BIT_OSCRUN BIT(5) # define MCP794XX_BIT_VBATEN 0x08 #define DS1307_REG_MDAY 0x04 /* 01-31 */ #define DS1307_REG_MONTH 0x05 /* 01-12 */ @@ -113,20 +115,65 @@ enum ds_type { # define RX8025_BIT_VDET 0x40 # define RX8025_BIT_XST 0x20 +#define RX8130_REG_ALARM_MIN 0x17 +#define RX8130_REG_ALARM_HOUR 0x18 +#define RX8130_REG_ALARM_WEEK_OR_DAY 0x19 +#define RX8130_REG_EXTENSION 0x1c +#define RX8130_REG_EXTENSION_WADA BIT(3) +#define RX8130_REG_FLAG 0x1d +#define RX8130_REG_FLAG_VLF BIT(1) +#define RX8130_REG_FLAG_AF BIT(3) +#define RX8130_REG_CONTROL0 0x1e +#define RX8130_REG_CONTROL0_AIE BIT(3) +#define RX8130_REG_CONTROL1 0x1f +#define RX8130_REG_CONTROL1_INIEN BIT(4) +#define RX8130_REG_CONTROL1_CHGEN BIT(5) + +#define MCP794XX_REG_CONTROL 0x07 +# define MCP794XX_BIT_ALM0_EN 0x10 +# define MCP794XX_BIT_ALM1_EN 0x20 +#define MCP794XX_REG_ALARM0_BASE 0x0a +#define MCP794XX_REG_ALARM0_CTRL 0x0d +#define MCP794XX_REG_ALARM1_BASE 0x11 +#define MCP794XX_REG_ALARM1_CTRL 0x14 +# define MCP794XX_BIT_ALMX_IF BIT(3) +# define MCP794XX_BIT_ALMX_C0 BIT(4) +# define MCP794XX_BIT_ALMX_C1 BIT(5) +# define MCP794XX_BIT_ALMX_C2 BIT(6) +# define MCP794XX_BIT_ALMX_POL BIT(7) +# define MCP794XX_MSK_ALMX_MATCH (MCP794XX_BIT_ALMX_C0 | \ + MCP794XX_BIT_ALMX_C1 | \ + MCP794XX_BIT_ALMX_C2) + +#define M41TXX_REG_CONTROL 0x07 +# define M41TXX_BIT_OUT BIT(7) +# define M41TXX_BIT_FT BIT(6) +# define M41TXX_BIT_CALIB_SIGN BIT(5) +# define M41TXX_M_CALIBRATION GENMASK(4, 0) + +#define DS1388_REG_WDOG_HUN_SECS 0x08 +#define DS1388_REG_WDOG_SECS 0x09 +#define DS1388_REG_FLAG 0x0b +# define DS1388_BIT_WF BIT(6) +# define DS1388_BIT_OSF BIT(7) +#define DS1388_REG_CONTROL 0x0c +# define DS1388_BIT_RST BIT(0) +# define DS1388_BIT_WDE BIT(1) +# define DS1388_BIT_nEOSC BIT(7) + +/* negative offset step is -2.034ppm */ +#define M41TXX_NEG_OFFSET_STEP_PPB 2034 +/* positive offset step is +4.068ppm */ +#define M41TXX_POS_OFFSET_STEP_PPB 4068 +/* Min and max values supported with 'offset' interface by M41TXX */ +#define M41TXX_MIN_OFFSET ((-31) * M41TXX_NEG_OFFSET_STEP_PPB) +#define M41TXX_MAX_OFFSET ((31) * M41TXX_POS_OFFSET_STEP_PPB) struct ds1307 { - u8 offset; /* register's offset */ - u8 regs[11]; - u16 nvram_offset; - struct nvmem_config nvmem_cfg; enum ds_type type; - unsigned long flags; -#define HAS_NVRAM 0 /* bit 0 == sysfs file active */ -#define HAS_ALARM 1 /* bit 1 == irq claimed */ struct device *dev; struct regmap *regmap; const char *name; - int irq; struct rtc_device *rtc; #ifdef CONFIG_COMMON_CLK struct clk_hw clks[2]; @@ -137,249 +184,139 @@ struct chip_desc { unsigned alarm:1; u16 nvram_offset; u16 nvram_size; + u8 offset; /* register's offset */ u8 century_reg; u8 century_enable_bit; u8 century_bit; + u8 bbsqi_bit; + irq_handler_t irq_handler; + const struct rtc_class_ops *rtc_ops; u16 trickle_charger_reg; - u8 trickle_charger_setup; - u8 (*do_trickle_setup)(struct ds1307 *, uint32_t, + u8 (*do_trickle_setup)(struct ds1307 *, u32, bool); + /* Does the RTC require trickle-resistor-ohms to select the value of + * the resistor between Vcc and Vbackup? + */ + bool requires_trickle_resistor; + /* Some RTC's batteries and supercaps were charged by default, others + * allow charging but were not configured previously to do so. + * Remember this behavior to stay backwards compatible. + */ + bool charge_default; }; -static u8 do_trickle_setup_ds1339(struct ds1307 *, uint32_t ohms, bool diode); - -static struct chip_desc chips[last_ds_type] = { - [ds_1307] = { - .nvram_offset = 8, - .nvram_size = 56, - }, - [ds_1308] = { - .nvram_offset = 8, - .nvram_size = 56, - }, - [ds_1337] = { - .alarm = 1, - .century_reg = DS1307_REG_MONTH, - .century_bit = DS1337_BIT_CENTURY, - }, - [ds_1338] = { - .nvram_offset = 8, - .nvram_size = 56, - }, - [ds_1339] = { - .alarm = 1, - .century_reg = DS1307_REG_MONTH, - .century_bit = DS1337_BIT_CENTURY, - .trickle_charger_reg = 0x10, - .do_trickle_setup = &do_trickle_setup_ds1339, - }, - [ds_1340] = { - .century_reg = DS1307_REG_HOUR, - .century_enable_bit = DS1340_BIT_CENTURY_EN, - .century_bit = DS1340_BIT_CENTURY, - .trickle_charger_reg = 0x08, - }, - [ds_1388] = { - .trickle_charger_reg = 0x0a, - }, - [ds_3231] = { - .alarm = 1, - .century_reg = DS1307_REG_MONTH, - .century_bit = DS1337_BIT_CENTURY, - }, - [rx_8130] = { - .alarm = 1, - /* this is battery backed SRAM */ - .nvram_offset = 0x20, - .nvram_size = 4, /* 32bit (4 word x 8 bit) */ - }, - [mcp794xx] = { - .alarm = 1, - /* this is battery backed SRAM */ - .nvram_offset = 0x20, - .nvram_size = 0x40, - }, -}; - -static const struct i2c_device_id ds1307_id[] = { - { "ds1307", ds_1307 }, - { "ds1308", ds_1308 }, - { "ds1337", ds_1337 }, - { "ds1338", ds_1338 }, - { "ds1339", ds_1339 }, - { "ds1388", ds_1388 }, - { "ds1340", ds_1340 }, - { "ds3231", ds_3231 }, - { "m41t0", m41t0 }, - { "m41t00", m41t00 }, - { "mcp7940x", mcp794xx }, - { "mcp7941x", mcp794xx }, - { "pt7c4338", ds_1307 }, - { "rx8025", rx_8025 }, - { "isl12057", ds_1337 }, - { "rx8130", rx_8130 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ds1307_id); - -#ifdef CONFIG_OF -static const struct of_device_id ds1307_of_match[] = { - { - .compatible = "dallas,ds1307", - .data = (void *)ds_1307 - }, - { - .compatible = "dallas,ds1308", - .data = (void *)ds_1308 - }, - { - .compatible = "dallas,ds1337", - .data = (void *)ds_1337 - }, - { - .compatible = "dallas,ds1338", - .data = (void *)ds_1338 - }, - { - .compatible = "dallas,ds1339", - .data = (void *)ds_1339 - }, - { - .compatible = "dallas,ds1388", - .data = (void *)ds_1388 - }, - { - .compatible = "dallas,ds1340", - .data = (void *)ds_1340 - }, - { - .compatible = "maxim,ds3231", - .data = (void *)ds_3231 - }, - { - .compatible = "st,m41t0", - .data = (void *)m41t00 - }, - { - .compatible = "st,m41t00", - .data = (void *)m41t00 - }, - { - .compatible = "microchip,mcp7940x", - .data = (void *)mcp794xx - }, - { - .compatible = "microchip,mcp7941x", - .data = (void *)mcp794xx - }, - { - .compatible = "pericom,pt7c4338", - .data = (void *)ds_1307 - }, - { - .compatible = "epson,rx8025", - .data = (void *)rx_8025 - }, - { - .compatible = "isil,isl12057", - .data = (void *)ds_1337 - }, - { } -}; -MODULE_DEVICE_TABLE(of, ds1307_of_match); -#endif - -#ifdef CONFIG_ACPI -static const struct acpi_device_id ds1307_acpi_ids[] = { - { .id = "DS1307", .driver_data = ds_1307 }, - { .id = "DS1308", .driver_data = ds_1308 }, - { .id = "DS1337", .driver_data = ds_1337 }, - { .id = "DS1338", .driver_data = ds_1338 }, - { .id = "DS1339", .driver_data = ds_1339 }, - { .id = "DS1388", .driver_data = ds_1388 }, - { .id = "DS1340", .driver_data = ds_1340 }, - { .id = "DS3231", .driver_data = ds_3231 }, - { .id = "M41T0", .driver_data = m41t0 }, - { .id = "M41T00", .driver_data = m41t00 }, - { .id = "MCP7940X", .driver_data = mcp794xx }, - { .id = "MCP7941X", .driver_data = mcp794xx }, - { .id = "PT7C4338", .driver_data = ds_1307 }, - { .id = "RX8025", .driver_data = rx_8025 }, - { .id = "ISL12057", .driver_data = ds_1337 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids); -#endif - -/* - * 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 - * signal; ds1339 chips have only one alarm signal. - */ -static irqreturn_t ds1307_irq(int irq, void *dev_id) -{ - struct ds1307 *ds1307 = dev_id; - struct mutex *lock = &ds1307->rtc->ops_lock; - int stat, ret; - - mutex_lock(lock); - ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &stat); - if (ret) - goto out; - - if (stat & DS1337_BIT_A1I) { - stat &= ~DS1337_BIT_A1I; - regmap_write(ds1307->regmap, DS1337_REG_STATUS, stat); - - ret = regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL, - DS1337_BIT_A1IE, 0); - if (ret) - goto out; - - rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); - } - -out: - mutex_unlock(lock); - - return IRQ_HANDLED; -} - -/*----------------------------------------------------------------------*/ +static const struct chip_desc chips[last_ds_type]; static int ds1307_get_time(struct device *dev, struct rtc_time *t) { struct ds1307 *ds1307 = dev_get_drvdata(dev); int tmp, ret; const struct chip_desc *chip = &chips[ds1307->type]; + u8 regs[7]; + + if (ds1307->type == rx_8130) { + unsigned int regflag; + ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, ®flag); + if (ret) { + dev_err(dev, "%s error %d\n", "read", ret); + return ret; + } + + if (regflag & RX8130_REG_FLAG_VLF) { + dev_warn_once(dev, "oscillator failed, set time!\n"); + return -EINVAL; + } + } /* read the RTC date and time registers all at once */ - ret = regmap_bulk_read(ds1307->regmap, ds1307->offset, ds1307->regs, 7); + ret = regmap_bulk_read(ds1307->regmap, chip->offset, regs, + sizeof(regs)); if (ret) { dev_err(dev, "%s error %d\n", "read", ret); return ret; } - dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs); + dev_dbg(dev, "%s: %7ph\n", "read", regs); /* if oscillator fail bit is set, no data can be trusted */ if (ds1307->type == m41t0 && - ds1307->regs[DS1307_REG_MIN] & M41T0_BIT_OF) { + regs[DS1307_REG_MIN] & M41T0_BIT_OF) { + dev_warn_once(dev, "oscillator failed, set time!\n"); + return -EINVAL; + } else if (ds1307->type == mcp794xx && + !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_OSCRUN)) { dev_warn_once(dev, "oscillator failed, set time!\n"); return -EINVAL; } - t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f); - t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); - tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f; + tmp = regs[DS1307_REG_SECS]; + switch (ds1307->type) { + case ds_1307: + case m41t0: + case m41t00: + case m41t11: + if (tmp & DS1307_BIT_CH) + return -EINVAL; + break; + case ds_1308: + case ds_1338: + if (tmp & DS1307_BIT_CH) + return -EINVAL; + + ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &tmp); + if (ret) + return ret; + if (tmp & DS1338_BIT_OSF) + return -EINVAL; + break; + case ds_1340: + if (tmp & DS1340_BIT_nEOSC) + return -EINVAL; + + ret = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp); + if (ret) + return ret; + if (tmp & DS1340_BIT_OSF) + return -EINVAL; + break; + case ds_1341: + ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &tmp); + if (ret) + return ret; + if (tmp & DS1337_BIT_OSF) + return -EINVAL; + break; + case ds_1388: + ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp); + if (ret) + return ret; + if (tmp & DS1388_BIT_OSF) + return -EINVAL; + break; + case mcp794xx: + if (!(tmp & MCP794XX_BIT_ST)) + return -EINVAL; + + break; + default: + break; + } + + t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f); + t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f); + tmp = regs[DS1307_REG_HOUR] & 0x3f; t->tm_hour = bcd2bin(tmp); - t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1; - t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f); - tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f; + /* rx8130 is bit position, not BCD */ + if (ds1307->type == rx_8130) + t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f); + else + t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; + t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f); + tmp = regs[DS1307_REG_MONTH] & 0x1f; t->tm_mon = bcd2bin(tmp) - 1; - t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100; + t->tm_year = bcd2bin(regs[DS1307_REG_YEAR]) + 100; - if (ds1307->regs[chip->century_reg] & chip->century_bit && + if (regs[chip->century_reg] & chip->century_bit && IS_ENABLED(CONFIG_RTC_DRV_DS1307_CENTURY)) t->tm_year += 100; @@ -389,8 +326,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) t->tm_hour, t->tm_mday, t->tm_mon, t->tm_year, t->tm_wday); - /* initial clock setting can be undefined */ - return rtc_valid_tm(t); + return 0; } static int ds1307_set_time(struct device *dev, struct rtc_time *t) @@ -399,7 +335,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) const struct chip_desc *chip = &chips[ds1307->type]; int result; int tmp; - u8 *buf = ds1307->regs; + u8 regs[7]; dev_dbg(dev, "%s secs=%d, mins=%d, " "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", @@ -418,39 +354,76 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) return -EINVAL; #endif - buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec); - buf[DS1307_REG_MIN] = bin2bcd(t->tm_min); - buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); - buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); - buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); - buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); + regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec); + regs[DS1307_REG_MIN] = bin2bcd(t->tm_min); + regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); + /* rx8130 is bit position, not BCD */ + if (ds1307->type == rx_8130) + regs[DS1307_REG_WDAY] = 1 << t->tm_wday; + else + regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); + regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); + regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); /* assume 20YY not 19YY */ - tmp = t->tm_year - 100; - buf[DS1307_REG_YEAR] = bin2bcd(tmp); + tmp = t->tm_year % 100; + regs[DS1307_REG_YEAR] = bin2bcd(tmp); if (chip->century_enable_bit) - buf[chip->century_reg] |= chip->century_enable_bit; + regs[chip->century_reg] |= chip->century_enable_bit; if (t->tm_year > 199 && chip->century_bit) - buf[chip->century_reg] |= chip->century_bit; + regs[chip->century_reg] |= chip->century_bit; - if (ds1307->type == mcp794xx) { + switch (ds1307->type) { + case ds_1308: + case ds_1338: + regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL, + DS1338_BIT_OSF, 0); + break; + case ds_1340: + regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG, + DS1340_BIT_OSF, 0); + break; + case ds_1341: + regmap_update_bits(ds1307->regmap, DS1337_REG_STATUS, + DS1337_BIT_OSF, 0); + break; + case ds_1388: + regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG, + DS1388_BIT_OSF, 0); + break; + case mcp794xx: /* * these bits were cleared when preparing the date/time * values and need to be set again before writing the - * buffer out to the device. + * regsfer out to the device. */ - buf[DS1307_REG_SECS] |= MCP794XX_BIT_ST; - buf[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN; + regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST; + regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN; + break; + default: + break; } - dev_dbg(dev, "%s: %7ph\n", "write", buf); + dev_dbg(dev, "%s: %7ph\n", "write", regs); - result = regmap_bulk_write(ds1307->regmap, ds1307->offset, buf, 7); + result = regmap_bulk_write(ds1307->regmap, chip->offset, regs, + sizeof(regs)); if (result) { dev_err(dev, "%s error %d\n", "write", result); return result; } + + if (ds1307->type == rx_8130) { + /* clear Voltage Loss Flag as data is available now */ + result = regmap_write(ds1307->regmap, RX8130_REG_FLAG, + ~(u8)RX8130_REG_FLAG_VLF); + if (result) { + dev_err(dev, "%s error %d\n", "write", result); + return result; + } + } + return 0; } @@ -458,33 +431,31 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) { struct ds1307 *ds1307 = dev_get_drvdata(dev); int ret; - - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; + u8 regs[9]; /* read all ALARM1, ALARM2, and status registers at once */ ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, - ds1307->regs, 9); + regs, sizeof(regs)); if (ret) { dev_err(dev, "%s error %d\n", "alarm read", ret); return ret; } dev_dbg(dev, "%s: %4ph, %3ph, %2ph\n", "alarm read", - &ds1307->regs[0], &ds1307->regs[4], &ds1307->regs[7]); + ®s[0], ®s[4], ®s[7]); /* * report alarm time (ALARM1); assume 24 hour and day-of-month modes, * and that all four fields are checked matches */ - t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f); - t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); - t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); - t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); + t->time.tm_sec = bcd2bin(regs[0] & 0x7f); + t->time.tm_min = bcd2bin(regs[1] & 0x7f); + t->time.tm_hour = bcd2bin(regs[2] & 0x3f); + t->time.tm_mday = bcd2bin(regs[3] & 0x3f); /* ... and status */ - t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); - t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I); + t->enabled = !!(regs[7] & DS1337_BIT_A1IE); + t->pending = !!(regs[8] & DS1337_BIT_A1I); dev_dbg(dev, "%s secs=%d, mins=%d, " "hours=%d, mday=%d, enabled=%d, pending=%d\n", @@ -498,13 +469,10 @@ 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 ds1307 *ds1307 = dev_get_drvdata(dev); - unsigned char *buf = ds1307->regs; + unsigned char regs[9]; u8 control, status; int ret; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; - dev_dbg(dev, "%s secs=%d, mins=%d, " "hours=%d, mday=%d, enabled=%d, pending=%d\n", "alarm set", t->time.tm_sec, t->time.tm_min, @@ -512,33 +480,35 @@ 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 = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, buf, 9); + ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, regs, + sizeof(regs)); if (ret) { dev_err(dev, "%s error %d\n", "alarm write", ret); return ret; } - control = ds1307->regs[7]; - status = ds1307->regs[8]; + control = regs[7]; + status = regs[8]; dev_dbg(dev, "%s: %4ph, %3ph, %02x %02x\n", "alarm set (old status)", - &ds1307->regs[0], &ds1307->regs[4], control, status); + ®s[0], ®s[4], control, status); /* set ALARM1, using 24 hour and day-of-month modes */ - buf[0] = bin2bcd(t->time.tm_sec); - buf[1] = bin2bcd(t->time.tm_min); - buf[2] = bin2bcd(t->time.tm_hour); - buf[3] = bin2bcd(t->time.tm_mday); + regs[0] = bin2bcd(t->time.tm_sec); + regs[1] = bin2bcd(t->time.tm_min); + regs[2] = bin2bcd(t->time.tm_hour); + regs[3] = bin2bcd(t->time.tm_mday); /* set ALARM2 to non-garbage */ - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; + regs[4] = 0; + regs[5] = 0; + regs[6] = 0; /* disable alarms */ - buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); - buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); + regs[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); + regs[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); - ret = regmap_bulk_write(ds1307->regmap, DS1339_REG_ALARM1_SECS, buf, 9); + ret = regmap_bulk_write(ds1307->regmap, DS1339_REG_ALARM1_SECS, regs, + sizeof(regs)); if (ret) { dev_err(dev, "can't set alarm time\n"); return ret; @@ -547,8 +517,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) /* optionally enable ALARM1 */ if (t->enabled) { dev_dbg(dev, "alarm IRQ armed\n"); - buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ - regmap_write(ds1307->regmap, DS1337_REG_CONTROL, buf[7]); + regs[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ + regmap_write(ds1307->regmap, DS1337_REG_CONTROL, regs[7]); } return 0; @@ -558,49 +528,57 @@ static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct ds1307 *ds1307 = dev_get_drvdata(dev); - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -ENOTTY; - return regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL, DS1337_BIT_A1IE, enabled ? DS1337_BIT_A1IE : 0); } -static const struct rtc_class_ops ds13xx_rtc_ops = { - .read_time = ds1307_get_time, - .set_time = ds1307_set_time, - .read_alarm = ds1337_read_alarm, - .set_alarm = ds1337_set_alarm, - .alarm_irq_enable = ds1307_alarm_irq_enable, -}; +static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode) +{ + u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE : + DS1307_TRICKLE_CHARGER_NO_DIODE; -/*----------------------------------------------------------------------*/ + setup |= DS13XX_TRICKLE_CHARGER_MAGIC; -/* - * Alarm support for rx8130 devices. - */ + switch (ohms) { + case 250: + setup |= DS1307_TRICKLE_CHARGER_250_OHM; + break; + case 2000: + setup |= DS1307_TRICKLE_CHARGER_2K_OHM; + break; + case 4000: + setup |= DS1307_TRICKLE_CHARGER_4K_OHM; + break; + default: + dev_warn(ds1307->dev, + "Unsupported ohm value %u in dt\n", ohms); + return 0; + } + return setup; +} -#define RX8130_REG_ALARM_MIN 0x07 -#define RX8130_REG_ALARM_HOUR 0x08 -#define RX8130_REG_ALARM_WEEK_OR_DAY 0x09 -#define RX8130_REG_EXTENSION 0x0c -#define RX8130_REG_EXTENSION_WADA (1 << 3) -#define RX8130_REG_FLAG 0x0d -#define RX8130_REG_FLAG_AF (1 << 3) -#define RX8130_REG_CONTROL0 0x0e -#define RX8130_REG_CONTROL0_AIE (1 << 3) +static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode) +{ + /* make sure that the backup battery is enabled */ + u8 setup = RX8130_REG_CONTROL1_INIEN; + if (diode) + setup |= RX8130_REG_CONTROL1_CHGEN; + + return setup; +} static irqreturn_t rx8130_irq(int irq, void *dev_id) { struct ds1307 *ds1307 = dev_id; - struct mutex *lock = &ds1307->rtc->ops_lock; u8 ctl[3]; int ret; - mutex_lock(lock); + rtc_lock(ds1307->rtc); /* Read control registers. */ - ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, + sizeof(ctl)); if (ret < 0) goto out; if (!(ctl[1] & RX8130_REG_FLAG_AF)) @@ -608,14 +586,15 @@ static irqreturn_t rx8130_irq(int irq, void *dev_id) ctl[1] &= ~RX8130_REG_FLAG_AF; ctl[2] &= ~RX8130_REG_CONTROL0_AIE; - ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); + ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, + sizeof(ctl)); if (ret < 0) goto out; rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); out: - mutex_unlock(lock); + rtc_unlock(ds1307->rtc); return IRQ_HANDLED; } @@ -626,16 +605,15 @@ static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t) u8 ald[3], ctl[3]; int ret; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; - /* Read alarm registers. */ - ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, 3); + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, + sizeof(ald)); if (ret < 0) return ret; /* Read control registers. */ - ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, + sizeof(ctl)); if (ret < 0) return ret; @@ -666,9 +644,6 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) u8 ald[3], ctl[3]; int ret; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; - dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " "enabled=%d pending=%d\n", __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour, @@ -676,15 +651,17 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) t->enabled, t->pending); /* Read control registers. */ - ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); + ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, + sizeof(ctl)); if (ret < 0) return ret; - ctl[0] &= ~RX8130_REG_EXTENSION_WADA; - ctl[1] |= RX8130_REG_FLAG_AF; + ctl[0] &= RX8130_REG_EXTENSION_WADA; + ctl[1] &= ~RX8130_REG_FLAG_AF; ctl[2] &= ~RX8130_REG_CONTROL0_AIE; - ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); + ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, + sizeof(ctl)); if (ret < 0) return ret; @@ -693,7 +670,8 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) ald[1] = bin2bcd(t->time.tm_hour); ald[2] = bin2bcd(t->time.tm_mday); - ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, 3); + ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, + sizeof(ald)); if (ret < 0) return ret; @@ -702,7 +680,7 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) ctl[2] |= RX8130_REG_CONTROL0_AIE; - return regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); + return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, ctl[2]); } static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) @@ -710,9 +688,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) struct ds1307 *ds1307 = dev_get_drvdata(dev); int ret, reg; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; - ret = regmap_read(ds1307->regmap, RX8130_REG_CONTROL0, ®); if (ret < 0) return ret; @@ -725,38 +700,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg); } -static const struct rtc_class_ops rx8130_rtc_ops = { - .read_time = ds1307_get_time, - .set_time = ds1307_set_time, - .read_alarm = rx8130_read_alarm, - .set_alarm = rx8130_set_alarm, - .alarm_irq_enable = rx8130_alarm_irq_enable, -}; - -/*----------------------------------------------------------------------*/ - -/* - * Alarm support for mcp794xx devices. - */ - -#define MCP794XX_REG_WEEKDAY 0x3 -#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7 -#define MCP794XX_REG_CONTROL 0x07 -# define MCP794XX_BIT_ALM0_EN 0x10 -# define MCP794XX_BIT_ALM1_EN 0x20 -#define MCP794XX_REG_ALARM0_BASE 0x0a -#define MCP794XX_REG_ALARM0_CTRL 0x0d -#define MCP794XX_REG_ALARM1_BASE 0x11 -#define MCP794XX_REG_ALARM1_CTRL 0x14 -# define MCP794XX_BIT_ALMX_IF (1 << 3) -# define MCP794XX_BIT_ALMX_C0 (1 << 4) -# define MCP794XX_BIT_ALMX_C1 (1 << 5) -# define MCP794XX_BIT_ALMX_C2 (1 << 6) -# define MCP794XX_BIT_ALMX_POL (1 << 7) -# define MCP794XX_MSK_ALMX_MATCH (MCP794XX_BIT_ALMX_C0 | \ - MCP794XX_BIT_ALMX_C1 | \ - MCP794XX_BIT_ALMX_C2) - static irqreturn_t mcp794xx_irq(int irq, void *dev_id) { struct ds1307 *ds1307 = dev_id; @@ -793,49 +736,67 @@ out: static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) { struct ds1307 *ds1307 = dev_get_drvdata(dev); - u8 *regs = ds1307->regs; + u8 regs[10]; int ret; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; - /* Read control and alarm 0 registers. */ - ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10); + ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, + sizeof(regs)); if (ret) return ret; t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN); /* Report alarm 0 time assuming 24-hour and day-of-month modes. */ - t->time.tm_sec = bcd2bin(ds1307->regs[3] & 0x7f); - t->time.tm_min = bcd2bin(ds1307->regs[4] & 0x7f); - t->time.tm_hour = bcd2bin(ds1307->regs[5] & 0x3f); - t->time.tm_wday = bcd2bin(ds1307->regs[6] & 0x7) - 1; - t->time.tm_mday = bcd2bin(ds1307->regs[7] & 0x3f); - t->time.tm_mon = bcd2bin(ds1307->regs[8] & 0x1f) - 1; + t->time.tm_sec = bcd2bin(regs[3] & 0x7f); + t->time.tm_min = bcd2bin(regs[4] & 0x7f); + t->time.tm_hour = bcd2bin(regs[5] & 0x3f); + t->time.tm_wday = bcd2bin(regs[6] & 0x7) - 1; + t->time.tm_mday = bcd2bin(regs[7] & 0x3f); + t->time.tm_mon = bcd2bin(regs[8] & 0x1f) - 1; t->time.tm_year = -1; t->time.tm_yday = -1; t->time.tm_isdst = -1; dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " - "enabled=%d polarity=%d irq=%d match=%d\n", __func__, + "enabled=%d polarity=%d irq=%d match=%lu\n", __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour, t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled, - !!(ds1307->regs[6] & MCP794XX_BIT_ALMX_POL), - !!(ds1307->regs[6] & MCP794XX_BIT_ALMX_IF), - (ds1307->regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4); + !!(regs[6] & MCP794XX_BIT_ALMX_POL), + !!(regs[6] & MCP794XX_BIT_ALMX_IF), + (regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4); return 0; } +/* + * We may have a random RTC weekday, therefore calculate alarm weekday based + * on current weekday we read from the RTC timekeeping regs + */ +static int mcp794xx_alm_weekday(struct device *dev, struct rtc_time *tm_alarm) +{ + struct rtc_time tm_now; + int days_now, days_alarm, ret; + + ret = ds1307_get_time(dev, &tm_now); + if (ret) + return ret; + + days_now = div_s64(rtc_tm_to_time64(&tm_now), 24 * 60 * 60); + days_alarm = div_s64(rtc_tm_to_time64(tm_alarm), 24 * 60 * 60); + + return (tm_now.tm_wday + days_alarm - days_now) % 7 + 1; +} + static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) { struct ds1307 *ds1307 = dev_get_drvdata(dev); - unsigned char *regs = ds1307->regs; - int ret; + unsigned char regs[10]; + int wday, ret; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; + wday = mcp794xx_alm_weekday(dev, &t->time); + if (wday < 0) + return wday; dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " "enabled=%d pending=%d\n", __func__, @@ -844,7 +805,8 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) t->enabled, t->pending); /* Read control and alarm 0 registers. */ - ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10); + ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, + sizeof(regs)); if (ret) return ret; @@ -852,7 +814,7 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) regs[3] = bin2bcd(t->time.tm_sec); regs[4] = bin2bcd(t->time.tm_min); regs[5] = bin2bcd(t->time.tm_hour); - regs[6] = bin2bcd(t->time.tm_wday + 1); + regs[6] = wday; regs[7] = bin2bcd(t->time.tm_mday); regs[8] = bin2bcd(t->time.tm_mon + 1); @@ -863,7 +825,8 @@ 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 = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10); + ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs, + sizeof(regs)); if (ret) return ret; @@ -877,30 +840,443 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct ds1307 *ds1307 = dev_get_drvdata(dev); - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -EINVAL; - return regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL, MCP794XX_BIT_ALM0_EN, enabled ? MCP794XX_BIT_ALM0_EN : 0); } +static int m41txx_rtc_read_offset(struct device *dev, long *offset) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + u8 val; + + regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg); + + val = ctrl_reg & M41TXX_M_CALIBRATION; + + /* check if positive */ + if (ctrl_reg & M41TXX_BIT_CALIB_SIGN) + *offset = (val * M41TXX_POS_OFFSET_STEP_PPB); + else + *offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB); + + return 0; +} + +static int m41txx_rtc_set_offset(struct device *dev, long offset) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + unsigned int ctrl_reg; + + if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET)) + return -ERANGE; + + if (offset >= 0) { + ctrl_reg = DIV_ROUND_CLOSEST(offset, + M41TXX_POS_OFFSET_STEP_PPB); + ctrl_reg |= M41TXX_BIT_CALIB_SIGN; + } else { + ctrl_reg = DIV_ROUND_CLOSEST(abs(offset), + M41TXX_NEG_OFFSET_STEP_PPB); + } + + return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, + M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN, + ctrl_reg); +} + +#ifdef CONFIG_WATCHDOG_CORE +static int ds1388_wdt_start(struct watchdog_device *wdt_dev) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + u8 regs[2]; + int ret; + + ret = regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG, + DS1388_BIT_WF, 0); + if (ret) + return ret; + + ret = regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL, + DS1388_BIT_WDE | DS1388_BIT_RST, 0); + if (ret) + return ret; + + /* + * watchdog timeouts are measured in seconds. So ignore hundredths of + * seconds field. + */ + regs[0] = 0; + regs[1] = bin2bcd(wdt_dev->timeout); + + ret = regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs, + sizeof(regs)); + if (ret) + return ret; + + return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL, + DS1388_BIT_WDE | DS1388_BIT_RST, + DS1388_BIT_WDE | DS1388_BIT_RST); +} + +static int ds1388_wdt_stop(struct watchdog_device *wdt_dev) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + + return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL, + DS1388_BIT_WDE | DS1388_BIT_RST, 0); +} + +static int ds1388_wdt_ping(struct watchdog_device *wdt_dev) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + u8 regs[2]; + + return regmap_bulk_read(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs, + sizeof(regs)); +} + +static int ds1388_wdt_set_timeout(struct watchdog_device *wdt_dev, + unsigned int val) +{ + struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev); + u8 regs[2]; + + wdt_dev->timeout = val; + regs[0] = 0; + regs[1] = bin2bcd(wdt_dev->timeout); + + return regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs, + sizeof(regs)); +} +#endif + +static const struct rtc_class_ops rx8130_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, + .read_alarm = rx8130_read_alarm, + .set_alarm = rx8130_set_alarm, + .alarm_irq_enable = rx8130_alarm_irq_enable, +}; + static const struct rtc_class_ops mcp794xx_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, + .read_alarm = mcp794xx_read_alarm, + .set_alarm = mcp794xx_set_alarm, + .alarm_irq_enable = mcp794xx_alarm_irq_enable, +}; + +static const struct rtc_class_ops m41txx_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, + .read_alarm = ds1337_read_alarm, + .set_alarm = ds1337_set_alarm, + .alarm_irq_enable = ds1307_alarm_irq_enable, + .read_offset = m41txx_rtc_read_offset, + .set_offset = m41txx_rtc_set_offset, +}; + +static const struct chip_desc chips[last_ds_type] = { + [ds_1307] = { + .nvram_offset = 8, + .nvram_size = 56, + }, + [ds_1308] = { + .nvram_offset = 8, + .nvram_size = 56, + }, + [ds_1337] = { + .alarm = 1, + .century_reg = DS1307_REG_MONTH, + .century_bit = DS1337_BIT_CENTURY, + }, + [ds_1338] = { + .nvram_offset = 8, + .nvram_size = 56, + }, + [ds_1339] = { + .alarm = 1, + .century_reg = DS1307_REG_MONTH, + .century_bit = DS1337_BIT_CENTURY, + .bbsqi_bit = DS1339_BIT_BBSQI, + .trickle_charger_reg = 0x10, + .do_trickle_setup = &do_trickle_setup_ds1339, + .requires_trickle_resistor = true, + .charge_default = true, + }, + [ds_1340] = { + .century_reg = DS1307_REG_HOUR, + .century_enable_bit = DS1340_BIT_CENTURY_EN, + .century_bit = DS1340_BIT_CENTURY, + .do_trickle_setup = &do_trickle_setup_ds1339, + .trickle_charger_reg = 0x08, + .requires_trickle_resistor = true, + .charge_default = true, + }, + [ds_1341] = { + .century_reg = DS1307_REG_MONTH, + .century_bit = DS1337_BIT_CENTURY, + }, + [ds_1388] = { + .offset = 1, + .trickle_charger_reg = 0x0a, + }, + [ds_3231] = { + .alarm = 1, + .century_reg = DS1307_REG_MONTH, + .century_bit = DS1337_BIT_CENTURY, + .bbsqi_bit = DS3231_BIT_BBSQW, + }, + [rx_8130] = { + .alarm = 1, + /* this is battery backed SRAM */ + .nvram_offset = 0x20, + .nvram_size = 4, /* 32bit (4 word x 8 bit) */ + .offset = 0x10, + .irq_handler = rx8130_irq, + .rtc_ops = &rx8130_rtc_ops, + .trickle_charger_reg = RX8130_REG_CONTROL1, + .do_trickle_setup = &do_trickle_setup_rx8130, + }, + [m41t0] = { + .rtc_ops = &m41txx_rtc_ops, + }, + [m41t00] = { + .rtc_ops = &m41txx_rtc_ops, + }, + [m41t11] = { + /* this is battery backed SRAM */ + .nvram_offset = 8, + .nvram_size = 56, + .rtc_ops = &m41txx_rtc_ops, + }, + [mcp794xx] = { + .alarm = 1, + /* this is battery backed SRAM */ + .nvram_offset = 0x20, + .nvram_size = 0x40, + .irq_handler = mcp794xx_irq, + .rtc_ops = &mcp794xx_rtc_ops, + }, +}; + +static const struct i2c_device_id ds1307_id[] = { + { "ds1307", ds_1307 }, + { "ds1308", ds_1308 }, + { "ds1337", ds_1337 }, + { "ds1338", ds_1338 }, + { "ds1339", ds_1339 }, + { "ds1388", ds_1388 }, + { "ds1340", ds_1340 }, + { "ds1341", ds_1341 }, + { "ds3231", ds_3231 }, + { "m41t0", m41t0 }, + { "m41t00", m41t00 }, + { "m41t11", m41t11 }, + { "mcp7940x", mcp794xx }, + { "mcp7941x", mcp794xx }, + { "pt7c4338", ds_1307 }, + { "rx8025", rx_8025 }, + { "isl12057", ds_1337 }, + { "rx8130", rx_8130 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds1307_id); + +static const struct of_device_id ds1307_of_match[] = { + { + .compatible = "dallas,ds1307", + .data = (void *)ds_1307 + }, + { + .compatible = "dallas,ds1308", + .data = (void *)ds_1308 + }, + { + .compatible = "dallas,ds1337", + .data = (void *)ds_1337 + }, + { + .compatible = "dallas,ds1338", + .data = (void *)ds_1338 + }, + { + .compatible = "dallas,ds1339", + .data = (void *)ds_1339 + }, + { + .compatible = "dallas,ds1388", + .data = (void *)ds_1388 + }, + { + .compatible = "dallas,ds1340", + .data = (void *)ds_1340 + }, + { + .compatible = "dallas,ds1341", + .data = (void *)ds_1341 + }, + { + .compatible = "maxim,ds3231", + .data = (void *)ds_3231 + }, + { + .compatible = "st,m41t0", + .data = (void *)m41t0 + }, + { + .compatible = "st,m41t00", + .data = (void *)m41t00 + }, + { + .compatible = "st,m41t11", + .data = (void *)m41t11 + }, + { + .compatible = "microchip,mcp7940x", + .data = (void *)mcp794xx + }, + { + .compatible = "microchip,mcp7941x", + .data = (void *)mcp794xx + }, + { + .compatible = "pericom,pt7c4338", + .data = (void *)ds_1307 + }, + { + .compatible = "epson,rx8025", + .data = (void *)rx_8025 + }, + { + .compatible = "isil,isl12057", + .data = (void *)ds_1337 + }, + { + .compatible = "epson,rx8130", + .data = (void *)rx_8130 + }, + { } +}; +MODULE_DEVICE_TABLE(of, ds1307_of_match); + +/* + * 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 + * signal; ds1339 chips have only one alarm signal. + */ +static irqreturn_t ds1307_irq(int irq, void *dev_id) +{ + struct ds1307 *ds1307 = dev_id; + struct mutex *lock = &ds1307->rtc->ops_lock; + int stat, ret; + + mutex_lock(lock); + ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &stat); + if (ret) + goto out; + + if (stat & DS1337_BIT_A1I) { + stat &= ~DS1337_BIT_A1I; + regmap_write(ds1307->regmap, DS1337_REG_STATUS, stat); + + ret = regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL, + DS1337_BIT_A1IE, 0); + if (ret) + goto out; + + rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); + } + +out: + mutex_unlock(lock); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------*/ + +static const struct rtc_class_ops ds13xx_rtc_ops = { .read_time = ds1307_get_time, .set_time = ds1307_set_time, - .read_alarm = mcp794xx_read_alarm, - .set_alarm = mcp794xx_set_alarm, - .alarm_irq_enable = mcp794xx_alarm_irq_enable, + .read_alarm = ds1337_read_alarm, + .set_alarm = ds1337_set_alarm, + .alarm_irq_enable = ds1307_alarm_irq_enable, }; +static ssize_t frequency_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev->parent); + bool freq_test_en; + int ret; + + ret = kstrtobool(buf, &freq_test_en); + if (ret) { + dev_err(dev, "Failed to store RTC Frequency Test attribute\n"); + return ret; + } + + regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, M41TXX_BIT_FT, + freq_test_en ? M41TXX_BIT_FT : 0); + + return count; +} + +static ssize_t frequency_test_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev->parent); + unsigned int ctrl_reg; + + regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg); + + return sysfs_emit(buf, (ctrl_reg & M41TXX_BIT_FT) ? "on\n" : "off\n"); +} + +static DEVICE_ATTR_RW(frequency_test); + +static struct attribute *rtc_freq_test_attrs[] = { + &dev_attr_frequency_test.attr, + NULL, +}; + +static const struct attribute_group rtc_freq_test_attr_group = { + .attrs = rtc_freq_test_attrs, +}; + +static int ds1307_add_frequency_test(struct ds1307 *ds1307) +{ + int err; + + switch (ds1307->type) { + case m41t0: + case m41t00: + case m41t11: + err = rtc_add_group(ds1307->rtc, &rtc_freq_test_attr_group); + if (err) + return err; + break; + default: + break; + } + + return 0; +} + /*----------------------------------------------------------------------*/ static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes) { struct ds1307 *ds1307 = priv; + const struct chip_desc *chip = &chips[ds1307->type]; - return regmap_bulk_read(ds1307->regmap, ds1307->nvram_offset + offset, + return regmap_bulk_read(ds1307->regmap, chip->nvram_offset + offset, val, bytes); } @@ -908,59 +1284,55 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val, size_t bytes) { struct ds1307 *ds1307 = priv; + const struct chip_desc *chip = &chips[ds1307->type]; - return regmap_bulk_write(ds1307->regmap, ds1307->nvram_offset + offset, + return regmap_bulk_write(ds1307->regmap, chip->nvram_offset + offset, val, bytes); } /*----------------------------------------------------------------------*/ -static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, - uint32_t ohms, bool diode) +static u8 ds1307_trickle_init(struct ds1307 *ds1307, + const struct chip_desc *chip) { - u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE : - DS1307_TRICKLE_CHARGER_NO_DIODE; + u32 ohms, chargeable; + bool diode = chip->charge_default; - switch (ohms) { - case 250: - setup |= DS1307_TRICKLE_CHARGER_250_OHM; - break; - case 2000: - setup |= DS1307_TRICKLE_CHARGER_2K_OHM; - break; - case 4000: - setup |= DS1307_TRICKLE_CHARGER_4K_OHM; - break; - default: - dev_warn(ds1307->dev, - "Unsupported ohm value %u in dt\n", ohms); + if (!chip->do_trickle_setup) return 0; - } - return setup; -} - -static void ds1307_trickle_init(struct ds1307 *ds1307, - struct chip_desc *chip) -{ - uint32_t ohms = 0; - bool diode = true; - if (!chip->do_trickle_setup) - goto out; if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms", - &ohms)) - goto out; - if (device_property_read_bool(ds1307->dev, "trickle-diode-disable")) + &ohms) && chip->requires_trickle_resistor) + return 0; + + /* aux-voltage-chargeable takes precedence over the deprecated + * trickle-diode-disable + */ + if (!device_property_read_u32(ds1307->dev, "aux-voltage-chargeable", + &chargeable)) { + switch (chargeable) { + case 0: + diode = false; + break; + case 1: + diode = true; + break; + default: + dev_warn(ds1307->dev, + "unsupported aux-voltage-chargeable value\n"); + break; + } + } else if (device_property_read_bool(ds1307->dev, + "trickle-diode-disable")) { diode = false; - chip->trickle_charger_setup = chip->do_trickle_setup(ds1307, - ohms, diode); -out: - return; + } + + return chip->do_trickle_setup(ds1307, ohms, diode); } /*----------------------------------------------------------------------*/ -#ifdef CONFIG_RTC_DRV_DS1307_HWMON +#if IS_REACHABLE(CONFIG_HWMON) /* * Temperature sensor support for ds3231 devices. @@ -995,7 +1367,7 @@ static int ds3231_hwmon_read_temp(struct device *dev, s32 *mC) } static ssize_t ds3231_hwmon_show_temp(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { int ret; s32 temp; @@ -1006,8 +1378,8 @@ static ssize_t ds3231_hwmon_show_temp(struct device *dev, return sprintf(buf, "%d\n", temp); } -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp, - NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_input, 0444, ds3231_hwmon_show_temp, + NULL, 0); static struct attribute *ds3231_hwmon_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -1023,7 +1395,8 @@ static void ds1307_hwmon_register(struct ds1307 *ds1307) return; dev = devm_hwmon_device_register_with_groups(ds1307->dev, ds1307->name, - ds1307, ds3231_hwmon_groups); + ds1307, + ds3231_hwmon_groups); if (IS_ERR(dev)) { dev_warn(ds1307->dev, "unable to register hwmon device %ld\n", PTR_ERR(dev)); @@ -1094,21 +1467,26 @@ static unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw, return ds3231_clk_sqw_rates[rate_sel]; } -static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int ds3231_clk_sqw_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { int i; for (i = ARRAY_SIZE(ds3231_clk_sqw_rates) - 1; i >= 0; i--) { - if (ds3231_clk_sqw_rates[i] <= rate) - return ds3231_clk_sqw_rates[i]; + if (ds3231_clk_sqw_rates[i] <= req->rate) { + req->rate = ds3231_clk_sqw_rates[i]; + + return 0; + } } + req->rate = ds3231_clk_sqw_rates[ARRAY_SIZE(ds3231_clk_sqw_rates) - 1]; + return 0; } static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) + unsigned long parent_rate) { struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw); int control = 0; @@ -1163,12 +1541,12 @@ static const struct clk_ops ds3231_clk_sqw_ops = { .unprepare = ds3231_clk_sqw_unprepare, .is_prepared = ds3231_clk_sqw_is_prepared, .recalc_rate = ds3231_clk_sqw_recalc_rate, - .round_rate = ds3231_clk_sqw_round_rate, + .determine_rate = ds3231_clk_sqw_determine_rate, .set_rate = ds3231_clk_sqw_set_rate, }; static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) + unsigned long parent_rate) { return 32768; } @@ -1220,13 +1598,16 @@ static const struct clk_ops ds3231_clk_32khz_ops = { .recalc_rate = ds3231_clk_32khz_recalc_rate, }; +static const char *ds3231_clks_names[] = { + [DS3231_CLK_SQW] = "ds3231_clk_sqw", + [DS3231_CLK_32KHZ] = "ds3231_clk_32khz", +}; + static struct clk_init_data ds3231_clks_init[] = { [DS3231_CLK_SQW] = { - .name = "ds3231_clk_sqw", .ops = &ds3231_clk_sqw_ops, }, [DS3231_CLK_32KHZ] = { - .name = "ds3231_clk_32khz", .ops = &ds3231_clk_32khz_ops, }, }; @@ -1247,6 +1628,11 @@ static int ds3231_clks_register(struct ds1307 *ds1307) if (!onecell->clks) return -ENOMEM; + /* optional override of the clockname */ + device_property_read_string_array(ds1307->dev, "clock-output-names", + ds3231_clks_names, + ARRAY_SIZE(ds3231_clks_names)); + for (i = 0; i < ARRAY_SIZE(ds3231_clks_init); i++) { struct clk_init_data init = ds3231_clks_init[i]; @@ -1254,12 +1640,10 @@ static int ds3231_clks_register(struct ds1307 *ds1307) * Interrupt signal due to alarm conditions and square-wave * output share same pin, so don't initialize both. */ - if (i == DS3231_CLK_SQW && test_bit(HAS_ALARM, &ds1307->flags)) + if (i == DS3231_CLK_SQW && test_bit(RTC_FEATURE_ALARM, ds1307->rtc->features)) continue; - /* optional override of the clockname */ - of_property_read_string_index(node, "clock-output-names", i, - &init.name); + init.name = ds3231_clks_names[i]; ds1307->clks[i].init = &init; onecell->clks[i] = devm_clk_register(ds1307->dev, @@ -1268,10 +1652,8 @@ static int ds3231_clks_register(struct ds1307 *ds1307) return PTR_ERR(onecell->clks[i]); } - if (!node) - return 0; - - of_clk_add_provider(node, of_clk_src_onecell_get, onecell); + if (node) + of_clk_add_provider(node, of_clk_src_onecell_get, onecell); return 0; } @@ -1298,34 +1680,72 @@ static void ds1307_clks_register(struct ds1307 *ds1307) #endif /* CONFIG_COMMON_CLK */ +#ifdef CONFIG_WATCHDOG_CORE +static const struct watchdog_info ds1388_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "DS1388 watchdog", +}; + +static const struct watchdog_ops ds1388_wdt_ops = { + .owner = THIS_MODULE, + .start = ds1388_wdt_start, + .stop = ds1388_wdt_stop, + .ping = ds1388_wdt_ping, + .set_timeout = ds1388_wdt_set_timeout, + +}; + +static void ds1307_wdt_register(struct ds1307 *ds1307) +{ + struct watchdog_device *wdt; + int err; + int val; + + if (ds1307->type != ds_1388) + return; + + wdt = devm_kzalloc(ds1307->dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) + return; + + err = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &val); + if (!err && val & DS1388_BIT_WF) + wdt->bootstatus = WDIOF_CARDRESET; + + wdt->info = &ds1388_wdt_info; + wdt->ops = &ds1388_wdt_ops; + wdt->timeout = 99; + wdt->max_timeout = 99; + wdt->min_timeout = 1; + + watchdog_init_timeout(wdt, 0, ds1307->dev); + watchdog_set_drvdata(wdt, ds1307); + devm_watchdog_register_device(ds1307->dev, wdt); +} +#else +static void ds1307_wdt_register(struct ds1307 *ds1307) +{ +} +#endif /* CONFIG_WATCHDOG_CORE */ + 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) +static int ds1307_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct ds1307 *ds1307; + const void *match; int err = -ENODEV; - int tmp, wday; - struct chip_desc *chip; - bool want_irq = false; + int tmp; + const struct chip_desc *chip; + bool want_irq; bool ds1307_can_wakeup_device = false; - unsigned char *buf; + unsigned char regs[8]; struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); - struct rtc_time tm; - unsigned long timestamp; - - irq_handler_t irq_handler = ds1307_irq; - - static const int bbsqi_bitpos[] = { - [ds_1337] = 0, - [ds_1339] = DS1339_BIT_BBSQI, - [ds_3231] = DS3231_BIT_BBSQW, - }; - const struct rtc_class_ops *rtc_ops = &ds13xx_rtc_ops; + u8 trickle_charger_setup = 0; ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL); if (!ds1307) @@ -1334,7 +1754,6 @@ static int ds1307_probe(struct i2c_client *client, 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, ®map_config); if (IS_ERR(ds1307->regmap)) { @@ -1344,42 +1763,32 @@ static int ds1307_probe(struct i2c_client *client, i2c_set_clientdata(client, ds1307); - if (client->dev.of_node) { - ds1307->type = (enum ds_type) - of_device_get_match_data(&client->dev); + match = device_get_match_data(&client->dev); + if (match) { + ds1307->type = (uintptr_t)match; chip = &chips[ds1307->type]; } else if (id) { chip = &chips[id->driver_data]; ds1307->type = id->driver_data; } else { - const struct acpi_device_id *acpi_id; - - acpi_id = acpi_match_device(ACPI_PTR(ds1307_acpi_ids), - ds1307->dev); - if (!acpi_id) - return -ENODEV; - chip = &chips[acpi_id->driver_data]; - ds1307->type = acpi_id->driver_data; + return -ENODEV; } + want_irq = client->irq > 0 && chip->alarm; + if (!pdata) - ds1307_trickle_init(ds1307, chip); + trickle_charger_setup = ds1307_trickle_init(ds1307, chip); else if (pdata->trickle_charger_setup) - chip->trickle_charger_setup = pdata->trickle_charger_setup; + trickle_charger_setup = pdata->trickle_charger_setup; - if (chip->trickle_charger_setup && chip->trickle_charger_reg) { + if (trickle_charger_setup && chip->trickle_charger_reg) { 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); + trickle_charger_setup, chip->trickle_charger_reg); regmap_write(ds1307->regmap, chip->trickle_charger_reg, - DS13XX_TRICKLE_CHARGER_MAGIC | - chip->trickle_charger_setup); + trickle_charger_setup); } - buf = ds1307->regs; - -#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 @@ -1388,31 +1797,25 @@ static int ds1307_probe(struct i2c_client *client, * 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; - } - /* Intersil ISL12057 DT backward compatibility */ - if (of_property_read_bool(client->dev.of_node, - "isil,irq2-can-wakeup-machine")) { + if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source")) ds1307_can_wakeup_device = true; - } -#endif switch (ds1307->type) { case ds_1337: case ds_1339: + case ds_1341: case ds_3231: /* get registers that the "rtc" read below won't read... */ err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL, - buf, 2); + regs, 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[0] & DS1337_BIT_nEOSC) - ds1307->regs[0] &= ~DS1337_BIT_nEOSC; + if (regs[0] & DS1337_BIT_nEOSC) + regs[0] &= ~DS1337_BIT_nEOSC; /* * Using IRQ or defined as wakeup-source? @@ -1420,194 +1823,118 @@ 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->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); - - want_irq = true; - } + if (want_irq || ds1307_can_wakeup_device) + regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit; regmap_write(ds1307->regmap, DS1337_REG_CONTROL, - ds1307->regs[0]); + regs[0]); - /* oscillator fault? clear flag, and warn */ - if (ds1307->regs[1] & DS1337_BIT_OSF) { - regmap_write(ds1307->regmap, DS1337_REG_STATUS, - ds1307->regs[1] & ~DS1337_BIT_OSF); + /* oscillator fault? warn */ + if (regs[1] & DS1337_BIT_OSF) { dev_warn(ds1307->dev, "SET TIME!\n"); } break; case rx_8025: err = regmap_bulk_read(ds1307->regmap, - RX8025_REG_CTRL1 << 4 | 0x08, buf, 2); + RX8025_REG_CTRL1 << 4 | 0x08, regs, 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; + if (!(regs[1] & RX8025_BIT_XST)) { + regs[1] |= RX8025_BIT_XST; regmap_write(ds1307->regmap, RX8025_REG_CTRL2 << 4 | 0x08, - ds1307->regs[1]); + 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; + if (regs[1] & RX8025_BIT_PON) { + regs[1] &= ~RX8025_BIT_PON; regmap_write(ds1307->regmap, RX8025_REG_CTRL2 << 4 | 0x08, - ds1307->regs[1]); + regs[1]); dev_warn(ds1307->dev, "power-on detected\n"); } - if (ds1307->regs[1] & RX8025_BIT_VDET) { - ds1307->regs[1] &= ~RX8025_BIT_VDET; + if (regs[1] & RX8025_BIT_VDET) { + regs[1] &= ~RX8025_BIT_VDET; regmap_write(ds1307->regmap, RX8025_REG_CTRL2 << 4 | 0x08, - ds1307->regs[1]); + regs[1]); dev_warn(ds1307->dev, "voltage drop detected\n"); } /* make sure we are running in 24hour mode */ - if (!(ds1307->regs[0] & RX8025_BIT_2412)) { + if (!(regs[0] & RX8025_BIT_2412)) { u8 hour; /* switch to 24 hour mode */ regmap_write(ds1307->regmap, RX8025_REG_CTRL1 << 4 | 0x08, - ds1307->regs[0] | RX8025_BIT_2412); + regs[0] | RX8025_BIT_2412); err = regmap_bulk_read(ds1307->regmap, RX8025_REG_CTRL1 << 4 | 0x08, - buf, 2); + regs, 2); if (err) { dev_dbg(ds1307->dev, "read error %d\n", err); goto exit; } /* correct hour */ - hour = bcd2bin(ds1307->regs[DS1307_REG_HOUR]); + hour = bcd2bin(regs[DS1307_REG_HOUR]); if (hour == 12) hour = 0; - if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) + if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM) hour += 12; regmap_write(ds1307->regmap, DS1307_REG_HOUR << 4 | 0x08, hour); } break; - case rx_8130: - ds1307->offset = 0x10; /* Seconds starts at 0x10 */ - rtc_ops = &rx8130_rtc_ops; - if (chip->alarm && ds1307->irq > 0) { - irq_handler = rx8130_irq; - want_irq = true; - } - break; case ds_1388: - ds1307->offset = 1; /* Seconds starts at 1 */ - break; - case mcp794xx: - rtc_ops = &mcp794xx_rtc_ops; - if (chip->alarm && (ds1307->irq > 0 || - ds1307_can_wakeup_device)) { - irq_handler = mcp794xx_irq; - want_irq = true; + err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp); + if (err) { + dev_dbg(ds1307->dev, "read error %d\n", err); + goto exit; + } + + /* oscillator off? turn it on, so clock can tick. */ + if (tmp & DS1388_BIT_nEOSC) { + tmp &= ~DS1388_BIT_nEOSC; + regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp); } break; default: break; } -read_rtc: /* read RTC registers */ - err = regmap_bulk_read(ds1307->regmap, ds1307->offset, buf, 8); + err = regmap_bulk_read(ds1307->regmap, chip->offset, regs, + sizeof(regs)); if (err) { dev_dbg(ds1307->dev, "read error %d\n", err); goto exit; } - /* - * minimal sanity checking; some chips (like DS1340) don't - * specify the extra bits as must-be-zero, but there are - * still a few values that are clearly out-of-range. - */ - tmp = ds1307->regs[DS1307_REG_SECS]; - switch (ds1307->type) { - case ds_1307: - case m41t0: - case m41t00: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1307_BIT_CH) { - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - break; - case ds_1308: - case ds_1338: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1307_BIT_CH) - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - - /* oscillator fault? clear flag, and warn */ - if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) { - 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) - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - - 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) { - 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)) { - 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)) { - regmap_write(ds1307->regmap, DS1307_REG_SECS, - MCP794XX_BIT_ST); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - - break; - default: - break; + if (ds1307->type == mcp794xx && + !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { + regmap_write(ds1307->regmap, DS1307_REG_WDAY, + regs[DS1307_REG_WDAY] | + MCP794XX_BIT_VBATEN); } - tmp = ds1307->regs[DS1307_REG_HOUR]; + tmp = regs[DS1307_REG_HOUR]; switch (ds1307->type) { case ds_1340: case m41t0: case m41t00: + case m41t11: /* * NOTE: ignores century bits; fix before deploying * systems that will run through year 2100. @@ -1626,85 +1953,69 @@ read_rtc: tmp = bcd2bin(tmp & 0x1f); if (tmp == 12) tmp = 0; - if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) + if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM) tmp += 12; - regmap_write(ds1307->regmap, ds1307->offset + DS1307_REG_HOUR, + regmap_write(ds1307->regmap, chip->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(ds1307->dev, &tm); - wday = tm.tm_wday; - timestamp = rtc_tm_to_time64(&tm); - rtc_time64_to_tm(timestamp, &tm); - - /* - * Check if reset wday is different from the computed wday - * If different then set the wday which we computed using - * timestamp - */ - if (wday != tm.tm_wday) - regmap_update_bits(ds1307->regmap, MCP794XX_REG_WEEKDAY, - MCP794XX_REG_WEEKDAY_WDAY_MASK, - tm.tm_wday + 1); - - if (want_irq) { - device_set_wakeup_capable(ds1307->dev, true); - set_bit(HAS_ALARM, &ds1307->flags); - } - ds1307->rtc = devm_rtc_allocate_device(ds1307->dev); - if (IS_ERR(ds1307->rtc)) { + if (IS_ERR(ds1307->rtc)) return PTR_ERR(ds1307->rtc); - } - if (ds1307_can_wakeup_device && ds1307->irq <= 0) { - /* Disable request for an IRQ */ - want_irq = false; + if (want_irq || ds1307_can_wakeup_device) + device_set_wakeup_capable(ds1307->dev, true); + else + clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features); + + if (ds1307_can_wakeup_device && !want_irq) { 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; + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features); } if (want_irq) { - err = devm_request_threaded_irq(ds1307->dev, - ds1307->irq, NULL, irq_handler, + err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL, + chip->irq_handler ?: ds1307_irq, IRQF_SHARED | IRQF_ONESHOT, ds1307->name, ds1307); if (err) { client->irq = 0; device_set_wakeup_capable(ds1307->dev, false); - clear_bit(HAS_ALARM, &ds1307->flags); + clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features); dev_err(ds1307->dev, "unable to request IRQ!\n"); - } else + } else { dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq); + } } - if (chip->nvram_size) { - ds1307->nvmem_cfg.name = "ds1307_nvram"; - ds1307->nvmem_cfg.word_size = 1; - ds1307->nvmem_cfg.stride = 1; - ds1307->nvmem_cfg.size = chip->nvram_size; - ds1307->nvmem_cfg.reg_read = ds1307_nvram_read; - ds1307->nvmem_cfg.reg_write = ds1307_nvram_write; - ds1307->nvmem_cfg.priv = ds1307; - ds1307->nvram_offset = chip->nvram_offset; - - ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg; - ds1307->rtc->nvram_old_abi = true; - } + ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; + err = ds1307_add_frequency_test(ds1307); + if (err) + return err; - ds1307->rtc->ops = rtc_ops; - err = rtc_register_device(ds1307->rtc); + err = devm_rtc_register_device(ds1307->rtc); if (err) return err; + if (chip->nvram_size) { + struct nvmem_config nvmem_cfg = { + .name = "ds1307_nvram", + .word_size = 1, + .stride = 1, + .size = chip->nvram_size, + .reg_read = ds1307_nvram_read, + .reg_write = ds1307_nvram_write, + .priv = ds1307, + }; + + devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg); + } + ds1307_hwmon_register(ds1307); ds1307_clks_register(ds1307); + ds1307_wdt_register(ds1307); return 0; @@ -1715,8 +2026,7 @@ exit: static struct i2c_driver ds1307_driver = { .driver = { .name = "rtc-ds1307", - .of_match_table = of_match_ptr(ds1307_of_match), - .acpi_match_table = ACPI_PTR(ds1307_acpi_ids), + .of_match_table = ds1307_of_match, }, .probe = ds1307_probe, .id_table = ds1307_id, |
