18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 2005 James Chapman (ds1337 core)
68c2ecf20Sopenharmony_ci *  Copyright (C) 2006 David Brownell
78c2ecf20Sopenharmony_ci *  Copyright (C) 2009 Matthias Fuchs (rx8025 support)
88c2ecf20Sopenharmony_ci *  Copyright (C) 2012 Bertrand Achard (nvram access fixes)
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/acpi.h>
128c2ecf20Sopenharmony_ci#include <linux/bcd.h>
138c2ecf20Sopenharmony_ci#include <linux/i2c.h>
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/of_device.h>
178c2ecf20Sopenharmony_ci#include <linux/rtc/ds1307.h>
188c2ecf20Sopenharmony_ci#include <linux/rtc.h>
198c2ecf20Sopenharmony_ci#include <linux/slab.h>
208c2ecf20Sopenharmony_ci#include <linux/string.h>
218c2ecf20Sopenharmony_ci#include <linux/hwmon.h>
228c2ecf20Sopenharmony_ci#include <linux/hwmon-sysfs.h>
238c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
248c2ecf20Sopenharmony_ci#include <linux/regmap.h>
258c2ecf20Sopenharmony_ci#include <linux/watchdog.h>
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/*
288c2ecf20Sopenharmony_ci * We can't determine type by probing, but if we expect pre-Linux code
298c2ecf20Sopenharmony_ci * to have set the chip up as a clock (turning on the oscillator and
308c2ecf20Sopenharmony_ci * setting the date and time), Linux can ignore the non-clock features.
318c2ecf20Sopenharmony_ci * That's a natural job for a factory or repair bench.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_cienum ds_type {
348c2ecf20Sopenharmony_ci	ds_1307,
358c2ecf20Sopenharmony_ci	ds_1308,
368c2ecf20Sopenharmony_ci	ds_1337,
378c2ecf20Sopenharmony_ci	ds_1338,
388c2ecf20Sopenharmony_ci	ds_1339,
398c2ecf20Sopenharmony_ci	ds_1340,
408c2ecf20Sopenharmony_ci	ds_1341,
418c2ecf20Sopenharmony_ci	ds_1388,
428c2ecf20Sopenharmony_ci	ds_3231,
438c2ecf20Sopenharmony_ci	m41t0,
448c2ecf20Sopenharmony_ci	m41t00,
458c2ecf20Sopenharmony_ci	m41t11,
468c2ecf20Sopenharmony_ci	mcp794xx,
478c2ecf20Sopenharmony_ci	rx_8025,
488c2ecf20Sopenharmony_ci	rx_8130,
498c2ecf20Sopenharmony_ci	last_ds_type /* always last */
508c2ecf20Sopenharmony_ci	/* rs5c372 too?  different address... */
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* RTC registers don't differ much, except for the century flag */
548c2ecf20Sopenharmony_ci#define DS1307_REG_SECS		0x00	/* 00-59 */
558c2ecf20Sopenharmony_ci#	define DS1307_BIT_CH		0x80
568c2ecf20Sopenharmony_ci#	define DS1340_BIT_nEOSC		0x80
578c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ST		0x80
588c2ecf20Sopenharmony_ci#define DS1307_REG_MIN		0x01	/* 00-59 */
598c2ecf20Sopenharmony_ci#	define M41T0_BIT_OF		0x80
608c2ecf20Sopenharmony_ci#define DS1307_REG_HOUR		0x02	/* 00-23, or 1-12{am,pm} */
618c2ecf20Sopenharmony_ci#	define DS1307_BIT_12HR		0x40	/* in REG_HOUR */
628c2ecf20Sopenharmony_ci#	define DS1307_BIT_PM		0x20	/* in REG_HOUR */
638c2ecf20Sopenharmony_ci#	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */
648c2ecf20Sopenharmony_ci#	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */
658c2ecf20Sopenharmony_ci#define DS1307_REG_WDAY		0x03	/* 01-07 */
668c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_VBATEN	0x08
678c2ecf20Sopenharmony_ci#define DS1307_REG_MDAY		0x04	/* 01-31 */
688c2ecf20Sopenharmony_ci#define DS1307_REG_MONTH	0x05	/* 01-12 */
698c2ecf20Sopenharmony_ci#	define DS1337_BIT_CENTURY	0x80	/* in REG_MONTH */
708c2ecf20Sopenharmony_ci#define DS1307_REG_YEAR		0x06	/* 00-99 */
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/*
738c2ecf20Sopenharmony_ci * Other registers (control, status, alarms, trickle charge, NVRAM, etc)
748c2ecf20Sopenharmony_ci * start at 7, and they differ a LOT. Only control and status matter for
758c2ecf20Sopenharmony_ci * basic RTC date and time functionality; be careful using them.
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_ci#define DS1307_REG_CONTROL	0x07		/* or ds1338 */
788c2ecf20Sopenharmony_ci#	define DS1307_BIT_OUT		0x80
798c2ecf20Sopenharmony_ci#	define DS1338_BIT_OSF		0x20
808c2ecf20Sopenharmony_ci#	define DS1307_BIT_SQWE		0x10
818c2ecf20Sopenharmony_ci#	define DS1307_BIT_RS1		0x02
828c2ecf20Sopenharmony_ci#	define DS1307_BIT_RS0		0x01
838c2ecf20Sopenharmony_ci#define DS1337_REG_CONTROL	0x0e
848c2ecf20Sopenharmony_ci#	define DS1337_BIT_nEOSC		0x80
858c2ecf20Sopenharmony_ci#	define DS1339_BIT_BBSQI		0x20
868c2ecf20Sopenharmony_ci#	define DS3231_BIT_BBSQW		0x40 /* same as BBSQI */
878c2ecf20Sopenharmony_ci#	define DS1337_BIT_RS2		0x10
888c2ecf20Sopenharmony_ci#	define DS1337_BIT_RS1		0x08
898c2ecf20Sopenharmony_ci#	define DS1337_BIT_INTCN		0x04
908c2ecf20Sopenharmony_ci#	define DS1337_BIT_A2IE		0x02
918c2ecf20Sopenharmony_ci#	define DS1337_BIT_A1IE		0x01
928c2ecf20Sopenharmony_ci#define DS1340_REG_CONTROL	0x07
938c2ecf20Sopenharmony_ci#	define DS1340_BIT_OUT		0x80
948c2ecf20Sopenharmony_ci#	define DS1340_BIT_FT		0x40
958c2ecf20Sopenharmony_ci#	define DS1340_BIT_CALIB_SIGN	0x20
968c2ecf20Sopenharmony_ci#	define DS1340_M_CALIBRATION	0x1f
978c2ecf20Sopenharmony_ci#define DS1340_REG_FLAG		0x09
988c2ecf20Sopenharmony_ci#	define DS1340_BIT_OSF		0x80
998c2ecf20Sopenharmony_ci#define DS1337_REG_STATUS	0x0f
1008c2ecf20Sopenharmony_ci#	define DS1337_BIT_OSF		0x80
1018c2ecf20Sopenharmony_ci#	define DS3231_BIT_EN32KHZ	0x08
1028c2ecf20Sopenharmony_ci#	define DS1337_BIT_A2I		0x02
1038c2ecf20Sopenharmony_ci#	define DS1337_BIT_A1I		0x01
1048c2ecf20Sopenharmony_ci#define DS1339_REG_ALARM1_SECS	0x07
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci#define DS13XX_TRICKLE_CHARGER_MAGIC	0xa0
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#define RX8025_REG_CTRL1	0x0e
1098c2ecf20Sopenharmony_ci#	define RX8025_BIT_2412		0x20
1108c2ecf20Sopenharmony_ci#define RX8025_REG_CTRL2	0x0f
1118c2ecf20Sopenharmony_ci#	define RX8025_BIT_PON		0x10
1128c2ecf20Sopenharmony_ci#	define RX8025_BIT_VDET		0x40
1138c2ecf20Sopenharmony_ci#	define RX8025_BIT_XST		0x20
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci#define RX8130_REG_ALARM_MIN		0x17
1168c2ecf20Sopenharmony_ci#define RX8130_REG_ALARM_HOUR		0x18
1178c2ecf20Sopenharmony_ci#define RX8130_REG_ALARM_WEEK_OR_DAY	0x19
1188c2ecf20Sopenharmony_ci#define RX8130_REG_EXTENSION		0x1c
1198c2ecf20Sopenharmony_ci#define RX8130_REG_EXTENSION_WADA	BIT(3)
1208c2ecf20Sopenharmony_ci#define RX8130_REG_FLAG			0x1d
1218c2ecf20Sopenharmony_ci#define RX8130_REG_FLAG_VLF		BIT(1)
1228c2ecf20Sopenharmony_ci#define RX8130_REG_FLAG_AF		BIT(3)
1238c2ecf20Sopenharmony_ci#define RX8130_REG_CONTROL0		0x1e
1248c2ecf20Sopenharmony_ci#define RX8130_REG_CONTROL0_AIE		BIT(3)
1258c2ecf20Sopenharmony_ci#define RX8130_REG_CONTROL1		0x1f
1268c2ecf20Sopenharmony_ci#define RX8130_REG_CONTROL1_INIEN	BIT(4)
1278c2ecf20Sopenharmony_ci#define RX8130_REG_CONTROL1_CHGEN	BIT(5)
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci#define MCP794XX_REG_CONTROL		0x07
1308c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALM0_EN	0x10
1318c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALM1_EN	0x20
1328c2ecf20Sopenharmony_ci#define MCP794XX_REG_ALARM0_BASE	0x0a
1338c2ecf20Sopenharmony_ci#define MCP794XX_REG_ALARM0_CTRL	0x0d
1348c2ecf20Sopenharmony_ci#define MCP794XX_REG_ALARM1_BASE	0x11
1358c2ecf20Sopenharmony_ci#define MCP794XX_REG_ALARM1_CTRL	0x14
1368c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALMX_IF	BIT(3)
1378c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALMX_C0	BIT(4)
1388c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALMX_C1	BIT(5)
1398c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALMX_C2	BIT(6)
1408c2ecf20Sopenharmony_ci#	define MCP794XX_BIT_ALMX_POL	BIT(7)
1418c2ecf20Sopenharmony_ci#	define MCP794XX_MSK_ALMX_MATCH	(MCP794XX_BIT_ALMX_C0 | \
1428c2ecf20Sopenharmony_ci					 MCP794XX_BIT_ALMX_C1 | \
1438c2ecf20Sopenharmony_ci					 MCP794XX_BIT_ALMX_C2)
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci#define M41TXX_REG_CONTROL	0x07
1468c2ecf20Sopenharmony_ci#	define M41TXX_BIT_OUT		BIT(7)
1478c2ecf20Sopenharmony_ci#	define M41TXX_BIT_FT		BIT(6)
1488c2ecf20Sopenharmony_ci#	define M41TXX_BIT_CALIB_SIGN	BIT(5)
1498c2ecf20Sopenharmony_ci#	define M41TXX_M_CALIBRATION	GENMASK(4, 0)
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#define DS1388_REG_WDOG_HUN_SECS	0x08
1528c2ecf20Sopenharmony_ci#define DS1388_REG_WDOG_SECS		0x09
1538c2ecf20Sopenharmony_ci#define DS1388_REG_FLAG			0x0b
1548c2ecf20Sopenharmony_ci#	define DS1388_BIT_WF		BIT(6)
1558c2ecf20Sopenharmony_ci#	define DS1388_BIT_OSF		BIT(7)
1568c2ecf20Sopenharmony_ci#define DS1388_REG_CONTROL		0x0c
1578c2ecf20Sopenharmony_ci#	define DS1388_BIT_RST		BIT(0)
1588c2ecf20Sopenharmony_ci#	define DS1388_BIT_WDE		BIT(1)
1598c2ecf20Sopenharmony_ci#	define DS1388_BIT_nEOSC		BIT(7)
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci/* negative offset step is -2.034ppm */
1628c2ecf20Sopenharmony_ci#define M41TXX_NEG_OFFSET_STEP_PPB	2034
1638c2ecf20Sopenharmony_ci/* positive offset step is +4.068ppm */
1648c2ecf20Sopenharmony_ci#define M41TXX_POS_OFFSET_STEP_PPB	4068
1658c2ecf20Sopenharmony_ci/* Min and max values supported with 'offset' interface by M41TXX */
1668c2ecf20Sopenharmony_ci#define M41TXX_MIN_OFFSET	((-31) * M41TXX_NEG_OFFSET_STEP_PPB)
1678c2ecf20Sopenharmony_ci#define M41TXX_MAX_OFFSET	((31) * M41TXX_POS_OFFSET_STEP_PPB)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistruct ds1307 {
1708c2ecf20Sopenharmony_ci	enum ds_type		type;
1718c2ecf20Sopenharmony_ci	unsigned long		flags;
1728c2ecf20Sopenharmony_ci#define HAS_NVRAM	0		/* bit 0 == sysfs file active */
1738c2ecf20Sopenharmony_ci#define HAS_ALARM	1		/* bit 1 == irq claimed */
1748c2ecf20Sopenharmony_ci	struct device		*dev;
1758c2ecf20Sopenharmony_ci	struct regmap		*regmap;
1768c2ecf20Sopenharmony_ci	const char		*name;
1778c2ecf20Sopenharmony_ci	struct rtc_device	*rtc;
1788c2ecf20Sopenharmony_ci#ifdef CONFIG_COMMON_CLK
1798c2ecf20Sopenharmony_ci	struct clk_hw		clks[2];
1808c2ecf20Sopenharmony_ci#endif
1818c2ecf20Sopenharmony_ci};
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistruct chip_desc {
1848c2ecf20Sopenharmony_ci	unsigned		alarm:1;
1858c2ecf20Sopenharmony_ci	u16			nvram_offset;
1868c2ecf20Sopenharmony_ci	u16			nvram_size;
1878c2ecf20Sopenharmony_ci	u8			offset; /* register's offset */
1888c2ecf20Sopenharmony_ci	u8			century_reg;
1898c2ecf20Sopenharmony_ci	u8			century_enable_bit;
1908c2ecf20Sopenharmony_ci	u8			century_bit;
1918c2ecf20Sopenharmony_ci	u8			bbsqi_bit;
1928c2ecf20Sopenharmony_ci	irq_handler_t		irq_handler;
1938c2ecf20Sopenharmony_ci	const struct rtc_class_ops *rtc_ops;
1948c2ecf20Sopenharmony_ci	u16			trickle_charger_reg;
1958c2ecf20Sopenharmony_ci	u8			(*do_trickle_setup)(struct ds1307 *, u32,
1968c2ecf20Sopenharmony_ci						    bool);
1978c2ecf20Sopenharmony_ci	/* Does the RTC require trickle-resistor-ohms to select the value of
1988c2ecf20Sopenharmony_ci	 * the resistor between Vcc and Vbackup?
1998c2ecf20Sopenharmony_ci	 */
2008c2ecf20Sopenharmony_ci	bool			requires_trickle_resistor;
2018c2ecf20Sopenharmony_ci	/* Some RTC's batteries and supercaps were charged by default, others
2028c2ecf20Sopenharmony_ci	 * allow charging but were not configured previously to do so.
2038c2ecf20Sopenharmony_ci	 * Remember this behavior to stay backwards compatible.
2048c2ecf20Sopenharmony_ci	 */
2058c2ecf20Sopenharmony_ci	bool			charge_default;
2068c2ecf20Sopenharmony_ci};
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic const struct chip_desc chips[last_ds_type];
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic int ds1307_get_time(struct device *dev, struct rtc_time *t)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct ds1307	*ds1307 = dev_get_drvdata(dev);
2138c2ecf20Sopenharmony_ci	int		tmp, ret;
2148c2ecf20Sopenharmony_ci	const struct chip_desc *chip = &chips[ds1307->type];
2158c2ecf20Sopenharmony_ci	u8 regs[7];
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if (ds1307->type == rx_8130) {
2188c2ecf20Sopenharmony_ci		unsigned int regflag;
2198c2ecf20Sopenharmony_ci		ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, &regflag);
2208c2ecf20Sopenharmony_ci		if (ret) {
2218c2ecf20Sopenharmony_ci			dev_err(dev, "%s error %d\n", "read", ret);
2228c2ecf20Sopenharmony_ci			return ret;
2238c2ecf20Sopenharmony_ci		}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci		if (regflag & RX8130_REG_FLAG_VLF) {
2268c2ecf20Sopenharmony_ci			dev_warn_once(dev, "oscillator failed, set time!\n");
2278c2ecf20Sopenharmony_ci			return -EINVAL;
2288c2ecf20Sopenharmony_ci		}
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* read the RTC date and time registers all at once */
2328c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2338c2ecf20Sopenharmony_ci			       sizeof(regs));
2348c2ecf20Sopenharmony_ci	if (ret) {
2358c2ecf20Sopenharmony_ci		dev_err(dev, "%s error %d\n", "read", ret);
2368c2ecf20Sopenharmony_ci		return ret;
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: %7ph\n", "read", regs);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	/* if oscillator fail bit is set, no data can be trusted */
2428c2ecf20Sopenharmony_ci	if (ds1307->type == m41t0 &&
2438c2ecf20Sopenharmony_ci	    regs[DS1307_REG_MIN] & M41T0_BIT_OF) {
2448c2ecf20Sopenharmony_ci		dev_warn_once(dev, "oscillator failed, set time!\n");
2458c2ecf20Sopenharmony_ci		return -EINVAL;
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	tmp = regs[DS1307_REG_SECS];
2498c2ecf20Sopenharmony_ci	switch (ds1307->type) {
2508c2ecf20Sopenharmony_ci	case ds_1307:
2518c2ecf20Sopenharmony_ci	case m41t0:
2528c2ecf20Sopenharmony_ci	case m41t00:
2538c2ecf20Sopenharmony_ci	case m41t11:
2548c2ecf20Sopenharmony_ci		if (tmp & DS1307_BIT_CH)
2558c2ecf20Sopenharmony_ci			return -EINVAL;
2568c2ecf20Sopenharmony_ci		break;
2578c2ecf20Sopenharmony_ci	case ds_1308:
2588c2ecf20Sopenharmony_ci	case ds_1338:
2598c2ecf20Sopenharmony_ci		if (tmp & DS1307_BIT_CH)
2608c2ecf20Sopenharmony_ci			return -EINVAL;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci		ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &tmp);
2638c2ecf20Sopenharmony_ci		if (ret)
2648c2ecf20Sopenharmony_ci			return ret;
2658c2ecf20Sopenharmony_ci		if (tmp & DS1338_BIT_OSF)
2668c2ecf20Sopenharmony_ci			return -EINVAL;
2678c2ecf20Sopenharmony_ci		break;
2688c2ecf20Sopenharmony_ci	case ds_1340:
2698c2ecf20Sopenharmony_ci		if (tmp & DS1340_BIT_nEOSC)
2708c2ecf20Sopenharmony_ci			return -EINVAL;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		ret = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp);
2738c2ecf20Sopenharmony_ci		if (ret)
2748c2ecf20Sopenharmony_ci			return ret;
2758c2ecf20Sopenharmony_ci		if (tmp & DS1340_BIT_OSF)
2768c2ecf20Sopenharmony_ci			return -EINVAL;
2778c2ecf20Sopenharmony_ci		break;
2788c2ecf20Sopenharmony_ci	case ds_1388:
2798c2ecf20Sopenharmony_ci		ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp);
2808c2ecf20Sopenharmony_ci		if (ret)
2818c2ecf20Sopenharmony_ci			return ret;
2828c2ecf20Sopenharmony_ci		if (tmp & DS1388_BIT_OSF)
2838c2ecf20Sopenharmony_ci			return -EINVAL;
2848c2ecf20Sopenharmony_ci		break;
2858c2ecf20Sopenharmony_ci	case mcp794xx:
2868c2ecf20Sopenharmony_ci		if (!(tmp & MCP794XX_BIT_ST))
2878c2ecf20Sopenharmony_ci			return -EINVAL;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci		break;
2908c2ecf20Sopenharmony_ci	default:
2918c2ecf20Sopenharmony_ci		break;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f);
2958c2ecf20Sopenharmony_ci	t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f);
2968c2ecf20Sopenharmony_ci	tmp = regs[DS1307_REG_HOUR] & 0x3f;
2978c2ecf20Sopenharmony_ci	t->tm_hour = bcd2bin(tmp);
2988c2ecf20Sopenharmony_ci	/* rx8130 is bit position, not BCD */
2998c2ecf20Sopenharmony_ci	if (ds1307->type == rx_8130)
3008c2ecf20Sopenharmony_ci		t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f);
3018c2ecf20Sopenharmony_ci	else
3028c2ecf20Sopenharmony_ci		t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
3038c2ecf20Sopenharmony_ci	t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f);
3048c2ecf20Sopenharmony_ci	tmp = regs[DS1307_REG_MONTH] & 0x1f;
3058c2ecf20Sopenharmony_ci	t->tm_mon = bcd2bin(tmp) - 1;
3068c2ecf20Sopenharmony_ci	t->tm_year = bcd2bin(regs[DS1307_REG_YEAR]) + 100;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	if (regs[chip->century_reg] & chip->century_bit &&
3098c2ecf20Sopenharmony_ci	    IS_ENABLED(CONFIG_RTC_DRV_DS1307_CENTURY))
3108c2ecf20Sopenharmony_ci		t->tm_year += 100;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s secs=%d, mins=%d, "
3138c2ecf20Sopenharmony_ci		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
3148c2ecf20Sopenharmony_ci		"read", t->tm_sec, t->tm_min,
3158c2ecf20Sopenharmony_ci		t->tm_hour, t->tm_mday,
3168c2ecf20Sopenharmony_ci		t->tm_mon, t->tm_year, t->tm_wday);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	return 0;
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic int ds1307_set_time(struct device *dev, struct rtc_time *t)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct ds1307	*ds1307 = dev_get_drvdata(dev);
3248c2ecf20Sopenharmony_ci	const struct chip_desc *chip = &chips[ds1307->type];
3258c2ecf20Sopenharmony_ci	int		result;
3268c2ecf20Sopenharmony_ci	int		tmp;
3278c2ecf20Sopenharmony_ci	u8		regs[7];
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s secs=%d, mins=%d, "
3308c2ecf20Sopenharmony_ci		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
3318c2ecf20Sopenharmony_ci		"write", t->tm_sec, t->tm_min,
3328c2ecf20Sopenharmony_ci		t->tm_hour, t->tm_mday,
3338c2ecf20Sopenharmony_ci		t->tm_mon, t->tm_year, t->tm_wday);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	if (t->tm_year < 100)
3368c2ecf20Sopenharmony_ci		return -EINVAL;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci#ifdef CONFIG_RTC_DRV_DS1307_CENTURY
3398c2ecf20Sopenharmony_ci	if (t->tm_year > (chip->century_bit ? 299 : 199))
3408c2ecf20Sopenharmony_ci		return -EINVAL;
3418c2ecf20Sopenharmony_ci#else
3428c2ecf20Sopenharmony_ci	if (t->tm_year > 199)
3438c2ecf20Sopenharmony_ci		return -EINVAL;
3448c2ecf20Sopenharmony_ci#endif
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
3478c2ecf20Sopenharmony_ci	regs[DS1307_REG_MIN] = bin2bcd(t->tm_min);
3488c2ecf20Sopenharmony_ci	regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
3498c2ecf20Sopenharmony_ci	/* rx8130 is bit position, not BCD */
3508c2ecf20Sopenharmony_ci	if (ds1307->type == rx_8130)
3518c2ecf20Sopenharmony_ci		regs[DS1307_REG_WDAY] = 1 << t->tm_wday;
3528c2ecf20Sopenharmony_ci	else
3538c2ecf20Sopenharmony_ci		regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
3548c2ecf20Sopenharmony_ci	regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);
3558c2ecf20Sopenharmony_ci	regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	/* assume 20YY not 19YY */
3588c2ecf20Sopenharmony_ci	tmp = t->tm_year - 100;
3598c2ecf20Sopenharmony_ci	regs[DS1307_REG_YEAR] = bin2bcd(tmp);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	if (chip->century_enable_bit)
3628c2ecf20Sopenharmony_ci		regs[chip->century_reg] |= chip->century_enable_bit;
3638c2ecf20Sopenharmony_ci	if (t->tm_year > 199 && chip->century_bit)
3648c2ecf20Sopenharmony_ci		regs[chip->century_reg] |= chip->century_bit;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	switch (ds1307->type) {
3678c2ecf20Sopenharmony_ci	case ds_1308:
3688c2ecf20Sopenharmony_ci	case ds_1338:
3698c2ecf20Sopenharmony_ci		regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
3708c2ecf20Sopenharmony_ci				   DS1338_BIT_OSF, 0);
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	case ds_1340:
3738c2ecf20Sopenharmony_ci		regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
3748c2ecf20Sopenharmony_ci				   DS1340_BIT_OSF, 0);
3758c2ecf20Sopenharmony_ci		break;
3768c2ecf20Sopenharmony_ci	case ds_1388:
3778c2ecf20Sopenharmony_ci		regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,
3788c2ecf20Sopenharmony_ci				   DS1388_BIT_OSF, 0);
3798c2ecf20Sopenharmony_ci		break;
3808c2ecf20Sopenharmony_ci	case mcp794xx:
3818c2ecf20Sopenharmony_ci		/*
3828c2ecf20Sopenharmony_ci		 * these bits were cleared when preparing the date/time
3838c2ecf20Sopenharmony_ci		 * values and need to be set again before writing the
3848c2ecf20Sopenharmony_ci		 * regsfer out to the device.
3858c2ecf20Sopenharmony_ci		 */
3868c2ecf20Sopenharmony_ci		regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST;
3878c2ecf20Sopenharmony_ci		regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN;
3888c2ecf20Sopenharmony_ci		break;
3898c2ecf20Sopenharmony_ci	default:
3908c2ecf20Sopenharmony_ci		break;
3918c2ecf20Sopenharmony_ci	}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: %7ph\n", "write", regs);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	result = regmap_bulk_write(ds1307->regmap, chip->offset, regs,
3968c2ecf20Sopenharmony_ci				   sizeof(regs));
3978c2ecf20Sopenharmony_ci	if (result) {
3988c2ecf20Sopenharmony_ci		dev_err(dev, "%s error %d\n", "write", result);
3998c2ecf20Sopenharmony_ci		return result;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (ds1307->type == rx_8130) {
4038c2ecf20Sopenharmony_ci		/* clear Voltage Loss Flag as data is available now */
4048c2ecf20Sopenharmony_ci		result = regmap_write(ds1307->regmap, RX8130_REG_FLAG,
4058c2ecf20Sopenharmony_ci				      ~(u8)RX8130_REG_FLAG_VLF);
4068c2ecf20Sopenharmony_ci		if (result) {
4078c2ecf20Sopenharmony_ci			dev_err(dev, "%s error %d\n", "write", result);
4088c2ecf20Sopenharmony_ci			return result;
4098c2ecf20Sopenharmony_ci		}
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return 0;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	struct ds1307		*ds1307 = dev_get_drvdata(dev);
4188c2ecf20Sopenharmony_ci	int			ret;
4198c2ecf20Sopenharmony_ci	u8			regs[9];
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
4228c2ecf20Sopenharmony_ci		return -EINVAL;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/* read all ALARM1, ALARM2, and status registers at once */
4258c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS,
4268c2ecf20Sopenharmony_ci			       regs, sizeof(regs));
4278c2ecf20Sopenharmony_ci	if (ret) {
4288c2ecf20Sopenharmony_ci		dev_err(dev, "%s error %d\n", "alarm read", ret);
4298c2ecf20Sopenharmony_ci		return ret;
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: %4ph, %3ph, %2ph\n", "alarm read",
4338c2ecf20Sopenharmony_ci		&regs[0], &regs[4], &regs[7]);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	/*
4368c2ecf20Sopenharmony_ci	 * report alarm time (ALARM1); assume 24 hour and day-of-month modes,
4378c2ecf20Sopenharmony_ci	 * and that all four fields are checked matches
4388c2ecf20Sopenharmony_ci	 */
4398c2ecf20Sopenharmony_ci	t->time.tm_sec = bcd2bin(regs[0] & 0x7f);
4408c2ecf20Sopenharmony_ci	t->time.tm_min = bcd2bin(regs[1] & 0x7f);
4418c2ecf20Sopenharmony_ci	t->time.tm_hour = bcd2bin(regs[2] & 0x3f);
4428c2ecf20Sopenharmony_ci	t->time.tm_mday = bcd2bin(regs[3] & 0x3f);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/* ... and status */
4458c2ecf20Sopenharmony_ci	t->enabled = !!(regs[7] & DS1337_BIT_A1IE);
4468c2ecf20Sopenharmony_ci	t->pending = !!(regs[8] & DS1337_BIT_A1I);
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s secs=%d, mins=%d, "
4498c2ecf20Sopenharmony_ci		"hours=%d, mday=%d, enabled=%d, pending=%d\n",
4508c2ecf20Sopenharmony_ci		"alarm read", t->time.tm_sec, t->time.tm_min,
4518c2ecf20Sopenharmony_ci		t->time.tm_hour, t->time.tm_mday,
4528c2ecf20Sopenharmony_ci		t->enabled, t->pending);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return 0;
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	struct ds1307		*ds1307 = dev_get_drvdata(dev);
4608c2ecf20Sopenharmony_ci	unsigned char		regs[9];
4618c2ecf20Sopenharmony_ci	u8			control, status;
4628c2ecf20Sopenharmony_ci	int			ret;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
4658c2ecf20Sopenharmony_ci		return -EINVAL;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s secs=%d, mins=%d, "
4688c2ecf20Sopenharmony_ci		"hours=%d, mday=%d, enabled=%d, pending=%d\n",
4698c2ecf20Sopenharmony_ci		"alarm set", t->time.tm_sec, t->time.tm_min,
4708c2ecf20Sopenharmony_ci		t->time.tm_hour, t->time.tm_mday,
4718c2ecf20Sopenharmony_ci		t->enabled, t->pending);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	/* read current status of both alarms and the chip */
4748c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, regs,
4758c2ecf20Sopenharmony_ci			       sizeof(regs));
4768c2ecf20Sopenharmony_ci	if (ret) {
4778c2ecf20Sopenharmony_ci		dev_err(dev, "%s error %d\n", "alarm write", ret);
4788c2ecf20Sopenharmony_ci		return ret;
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci	control = regs[7];
4818c2ecf20Sopenharmony_ci	status = regs[8];
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: %4ph, %3ph, %02x %02x\n", "alarm set (old status)",
4848c2ecf20Sopenharmony_ci		&regs[0], &regs[4], control, status);
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	/* set ALARM1, using 24 hour and day-of-month modes */
4878c2ecf20Sopenharmony_ci	regs[0] = bin2bcd(t->time.tm_sec);
4888c2ecf20Sopenharmony_ci	regs[1] = bin2bcd(t->time.tm_min);
4898c2ecf20Sopenharmony_ci	regs[2] = bin2bcd(t->time.tm_hour);
4908c2ecf20Sopenharmony_ci	regs[3] = bin2bcd(t->time.tm_mday);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	/* set ALARM2 to non-garbage */
4938c2ecf20Sopenharmony_ci	regs[4] = 0;
4948c2ecf20Sopenharmony_ci	regs[5] = 0;
4958c2ecf20Sopenharmony_ci	regs[6] = 0;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	/* disable alarms */
4988c2ecf20Sopenharmony_ci	regs[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE);
4998c2ecf20Sopenharmony_ci	regs[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(ds1307->regmap, DS1339_REG_ALARM1_SECS, regs,
5028c2ecf20Sopenharmony_ci				sizeof(regs));
5038c2ecf20Sopenharmony_ci	if (ret) {
5048c2ecf20Sopenharmony_ci		dev_err(dev, "can't set alarm time\n");
5058c2ecf20Sopenharmony_ci		return ret;
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* optionally enable ALARM1 */
5098c2ecf20Sopenharmony_ci	if (t->enabled) {
5108c2ecf20Sopenharmony_ci		dev_dbg(dev, "alarm IRQ armed\n");
5118c2ecf20Sopenharmony_ci		regs[7] |= DS1337_BIT_A1IE;	/* only ALARM1 is used */
5128c2ecf20Sopenharmony_ci		regmap_write(ds1307->regmap, DS1337_REG_CONTROL, regs[7]);
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	return 0;
5168c2ecf20Sopenharmony_ci}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_cistatic int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	struct ds1307		*ds1307 = dev_get_drvdata(dev);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
5238c2ecf20Sopenharmony_ci		return -ENOTTY;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	return regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL,
5268c2ecf20Sopenharmony_ci				  DS1337_BIT_A1IE,
5278c2ecf20Sopenharmony_ci				  enabled ? DS1337_BIT_A1IE : 0);
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
5338c2ecf20Sopenharmony_ci		DS1307_TRICKLE_CHARGER_NO_DIODE;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	switch (ohms) {
5388c2ecf20Sopenharmony_ci	case 250:
5398c2ecf20Sopenharmony_ci		setup |= DS1307_TRICKLE_CHARGER_250_OHM;
5408c2ecf20Sopenharmony_ci		break;
5418c2ecf20Sopenharmony_ci	case 2000:
5428c2ecf20Sopenharmony_ci		setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
5438c2ecf20Sopenharmony_ci		break;
5448c2ecf20Sopenharmony_ci	case 4000:
5458c2ecf20Sopenharmony_ci		setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
5468c2ecf20Sopenharmony_ci		break;
5478c2ecf20Sopenharmony_ci	default:
5488c2ecf20Sopenharmony_ci		dev_warn(ds1307->dev,
5498c2ecf20Sopenharmony_ci			 "Unsupported ohm value %u in dt\n", ohms);
5508c2ecf20Sopenharmony_ci		return 0;
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci	return setup;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
5568c2ecf20Sopenharmony_ci{
5578c2ecf20Sopenharmony_ci	/* make sure that the backup battery is enabled */
5588c2ecf20Sopenharmony_ci	u8 setup = RX8130_REG_CONTROL1_INIEN;
5598c2ecf20Sopenharmony_ci	if (diode)
5608c2ecf20Sopenharmony_ci		setup |= RX8130_REG_CONTROL1_CHGEN;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	return setup;
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_cistatic irqreturn_t rx8130_irq(int irq, void *dev_id)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	struct ds1307           *ds1307 = dev_id;
5688c2ecf20Sopenharmony_ci	struct mutex            *lock = &ds1307->rtc->ops_lock;
5698c2ecf20Sopenharmony_ci	u8 ctl[3];
5708c2ecf20Sopenharmony_ci	int ret;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	mutex_lock(lock);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/* Read control registers. */
5758c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
5768c2ecf20Sopenharmony_ci			       sizeof(ctl));
5778c2ecf20Sopenharmony_ci	if (ret < 0)
5788c2ecf20Sopenharmony_ci		goto out;
5798c2ecf20Sopenharmony_ci	if (!(ctl[1] & RX8130_REG_FLAG_AF))
5808c2ecf20Sopenharmony_ci		goto out;
5818c2ecf20Sopenharmony_ci	ctl[1] &= ~RX8130_REG_FLAG_AF;
5828c2ecf20Sopenharmony_ci	ctl[2] &= ~RX8130_REG_CONTROL0_AIE;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
5858c2ecf20Sopenharmony_ci				sizeof(ctl));
5868c2ecf20Sopenharmony_ci	if (ret < 0)
5878c2ecf20Sopenharmony_ci		goto out;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ciout:
5928c2ecf20Sopenharmony_ci	mutex_unlock(lock);
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
6008c2ecf20Sopenharmony_ci	u8 ald[3], ctl[3];
6018c2ecf20Sopenharmony_ci	int ret;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
6048c2ecf20Sopenharmony_ci		return -EINVAL;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	/* Read alarm registers. */
6078c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald,
6088c2ecf20Sopenharmony_ci			       sizeof(ald));
6098c2ecf20Sopenharmony_ci	if (ret < 0)
6108c2ecf20Sopenharmony_ci		return ret;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* Read control registers. */
6138c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
6148c2ecf20Sopenharmony_ci			       sizeof(ctl));
6158c2ecf20Sopenharmony_ci	if (ret < 0)
6168c2ecf20Sopenharmony_ci		return ret;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	t->enabled = !!(ctl[2] & RX8130_REG_CONTROL0_AIE);
6198c2ecf20Sopenharmony_ci	t->pending = !!(ctl[1] & RX8130_REG_FLAG_AF);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	/* Report alarm 0 time assuming 24-hour and day-of-month modes. */
6228c2ecf20Sopenharmony_ci	t->time.tm_sec = -1;
6238c2ecf20Sopenharmony_ci	t->time.tm_min = bcd2bin(ald[0] & 0x7f);
6248c2ecf20Sopenharmony_ci	t->time.tm_hour = bcd2bin(ald[1] & 0x7f);
6258c2ecf20Sopenharmony_ci	t->time.tm_wday = -1;
6268c2ecf20Sopenharmony_ci	t->time.tm_mday = bcd2bin(ald[2] & 0x7f);
6278c2ecf20Sopenharmony_ci	t->time.tm_mon = -1;
6288c2ecf20Sopenharmony_ci	t->time.tm_year = -1;
6298c2ecf20Sopenharmony_ci	t->time.tm_yday = -1;
6308c2ecf20Sopenharmony_ci	t->time.tm_isdst = -1;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d enabled=%d\n",
6338c2ecf20Sopenharmony_ci		__func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
6348c2ecf20Sopenharmony_ci		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled);
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	return 0;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
6428c2ecf20Sopenharmony_ci	u8 ald[3], ctl[3];
6438c2ecf20Sopenharmony_ci	int ret;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
6468c2ecf20Sopenharmony_ci		return -EINVAL;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
6498c2ecf20Sopenharmony_ci		"enabled=%d pending=%d\n", __func__,
6508c2ecf20Sopenharmony_ci		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
6518c2ecf20Sopenharmony_ci		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
6528c2ecf20Sopenharmony_ci		t->enabled, t->pending);
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	/* Read control registers. */
6558c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
6568c2ecf20Sopenharmony_ci			       sizeof(ctl));
6578c2ecf20Sopenharmony_ci	if (ret < 0)
6588c2ecf20Sopenharmony_ci		return ret;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	ctl[0] &= RX8130_REG_EXTENSION_WADA;
6618c2ecf20Sopenharmony_ci	ctl[1] &= ~RX8130_REG_FLAG_AF;
6628c2ecf20Sopenharmony_ci	ctl[2] &= ~RX8130_REG_CONTROL0_AIE;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl,
6658c2ecf20Sopenharmony_ci				sizeof(ctl));
6668c2ecf20Sopenharmony_ci	if (ret < 0)
6678c2ecf20Sopenharmony_ci		return ret;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	/* Hardware alarm precision is 1 minute! */
6708c2ecf20Sopenharmony_ci	ald[0] = bin2bcd(t->time.tm_min);
6718c2ecf20Sopenharmony_ci	ald[1] = bin2bcd(t->time.tm_hour);
6728c2ecf20Sopenharmony_ci	ald[2] = bin2bcd(t->time.tm_mday);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald,
6758c2ecf20Sopenharmony_ci				sizeof(ald));
6768c2ecf20Sopenharmony_ci	if (ret < 0)
6778c2ecf20Sopenharmony_ci		return ret;
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	if (!t->enabled)
6808c2ecf20Sopenharmony_ci		return 0;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	ctl[2] |= RX8130_REG_CONTROL0_AIE;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, ctl[2]);
6858c2ecf20Sopenharmony_ci}
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_cistatic int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)
6888c2ecf20Sopenharmony_ci{
6898c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
6908c2ecf20Sopenharmony_ci	int ret, reg;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
6938c2ecf20Sopenharmony_ci		return -EINVAL;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	ret = regmap_read(ds1307->regmap, RX8130_REG_CONTROL0, &reg);
6968c2ecf20Sopenharmony_ci	if (ret < 0)
6978c2ecf20Sopenharmony_ci		return ret;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	if (enabled)
7008c2ecf20Sopenharmony_ci		reg |= RX8130_REG_CONTROL0_AIE;
7018c2ecf20Sopenharmony_ci	else
7028c2ecf20Sopenharmony_ci		reg &= ~RX8130_REG_CONTROL0_AIE;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg);
7058c2ecf20Sopenharmony_ci}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_cistatic irqreturn_t mcp794xx_irq(int irq, void *dev_id)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	struct ds1307           *ds1307 = dev_id;
7108c2ecf20Sopenharmony_ci	struct mutex            *lock = &ds1307->rtc->ops_lock;
7118c2ecf20Sopenharmony_ci	int reg, ret;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	mutex_lock(lock);
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	/* Check and clear alarm 0 interrupt flag. */
7168c2ecf20Sopenharmony_ci	ret = regmap_read(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, &reg);
7178c2ecf20Sopenharmony_ci	if (ret)
7188c2ecf20Sopenharmony_ci		goto out;
7198c2ecf20Sopenharmony_ci	if (!(reg & MCP794XX_BIT_ALMX_IF))
7208c2ecf20Sopenharmony_ci		goto out;
7218c2ecf20Sopenharmony_ci	reg &= ~MCP794XX_BIT_ALMX_IF;
7228c2ecf20Sopenharmony_ci	ret = regmap_write(ds1307->regmap, MCP794XX_REG_ALARM0_CTRL, reg);
7238c2ecf20Sopenharmony_ci	if (ret)
7248c2ecf20Sopenharmony_ci		goto out;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	/* Disable alarm 0. */
7278c2ecf20Sopenharmony_ci	ret = regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,
7288c2ecf20Sopenharmony_ci				 MCP794XX_BIT_ALM0_EN, 0);
7298c2ecf20Sopenharmony_ci	if (ret)
7308c2ecf20Sopenharmony_ci		goto out;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ciout:
7358c2ecf20Sopenharmony_ci	mutex_unlock(lock);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_cistatic int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
7418c2ecf20Sopenharmony_ci{
7428c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
7438c2ecf20Sopenharmony_ci	u8 regs[10];
7448c2ecf20Sopenharmony_ci	int ret;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
7478c2ecf20Sopenharmony_ci		return -EINVAL;
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	/* Read control and alarm 0 registers. */
7508c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
7518c2ecf20Sopenharmony_ci			       sizeof(regs));
7528c2ecf20Sopenharmony_ci	if (ret)
7538c2ecf20Sopenharmony_ci		return ret;
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN);
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	/* Report alarm 0 time assuming 24-hour and day-of-month modes. */
7588c2ecf20Sopenharmony_ci	t->time.tm_sec = bcd2bin(regs[3] & 0x7f);
7598c2ecf20Sopenharmony_ci	t->time.tm_min = bcd2bin(regs[4] & 0x7f);
7608c2ecf20Sopenharmony_ci	t->time.tm_hour = bcd2bin(regs[5] & 0x3f);
7618c2ecf20Sopenharmony_ci	t->time.tm_wday = bcd2bin(regs[6] & 0x7) - 1;
7628c2ecf20Sopenharmony_ci	t->time.tm_mday = bcd2bin(regs[7] & 0x3f);
7638c2ecf20Sopenharmony_ci	t->time.tm_mon = bcd2bin(regs[8] & 0x1f) - 1;
7648c2ecf20Sopenharmony_ci	t->time.tm_year = -1;
7658c2ecf20Sopenharmony_ci	t->time.tm_yday = -1;
7668c2ecf20Sopenharmony_ci	t->time.tm_isdst = -1;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
7698c2ecf20Sopenharmony_ci		"enabled=%d polarity=%d irq=%d match=%lu\n", __func__,
7708c2ecf20Sopenharmony_ci		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
7718c2ecf20Sopenharmony_ci		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled,
7728c2ecf20Sopenharmony_ci		!!(regs[6] & MCP794XX_BIT_ALMX_POL),
7738c2ecf20Sopenharmony_ci		!!(regs[6] & MCP794XX_BIT_ALMX_IF),
7748c2ecf20Sopenharmony_ci		(regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	return 0;
7778c2ecf20Sopenharmony_ci}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci/*
7808c2ecf20Sopenharmony_ci * We may have a random RTC weekday, therefore calculate alarm weekday based
7818c2ecf20Sopenharmony_ci * on current weekday we read from the RTC timekeeping regs
7828c2ecf20Sopenharmony_ci */
7838c2ecf20Sopenharmony_cistatic int mcp794xx_alm_weekday(struct device *dev, struct rtc_time *tm_alarm)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	struct rtc_time tm_now;
7868c2ecf20Sopenharmony_ci	int days_now, days_alarm, ret;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	ret = ds1307_get_time(dev, &tm_now);
7898c2ecf20Sopenharmony_ci	if (ret)
7908c2ecf20Sopenharmony_ci		return ret;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	days_now = div_s64(rtc_tm_to_time64(&tm_now), 24 * 60 * 60);
7938c2ecf20Sopenharmony_ci	days_alarm = div_s64(rtc_tm_to_time64(tm_alarm), 24 * 60 * 60);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	return (tm_now.tm_wday + days_alarm - days_now) % 7 + 1;
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
7998c2ecf20Sopenharmony_ci{
8008c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
8018c2ecf20Sopenharmony_ci	unsigned char regs[10];
8028c2ecf20Sopenharmony_ci	int wday, ret;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
8058c2ecf20Sopenharmony_ci		return -EINVAL;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	wday = mcp794xx_alm_weekday(dev, &t->time);
8088c2ecf20Sopenharmony_ci	if (wday < 0)
8098c2ecf20Sopenharmony_ci		return wday;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
8128c2ecf20Sopenharmony_ci		"enabled=%d pending=%d\n", __func__,
8138c2ecf20Sopenharmony_ci		t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
8148c2ecf20Sopenharmony_ci		t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
8158c2ecf20Sopenharmony_ci		t->enabled, t->pending);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	/* Read control and alarm 0 registers. */
8188c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
8198c2ecf20Sopenharmony_ci			       sizeof(regs));
8208c2ecf20Sopenharmony_ci	if (ret)
8218c2ecf20Sopenharmony_ci		return ret;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	/* Set alarm 0, using 24-hour and day-of-month modes. */
8248c2ecf20Sopenharmony_ci	regs[3] = bin2bcd(t->time.tm_sec);
8258c2ecf20Sopenharmony_ci	regs[4] = bin2bcd(t->time.tm_min);
8268c2ecf20Sopenharmony_ci	regs[5] = bin2bcd(t->time.tm_hour);
8278c2ecf20Sopenharmony_ci	regs[6] = wday;
8288c2ecf20Sopenharmony_ci	regs[7] = bin2bcd(t->time.tm_mday);
8298c2ecf20Sopenharmony_ci	regs[8] = bin2bcd(t->time.tm_mon + 1);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/* Clear the alarm 0 interrupt flag. */
8328c2ecf20Sopenharmony_ci	regs[6] &= ~MCP794XX_BIT_ALMX_IF;
8338c2ecf20Sopenharmony_ci	/* Set alarm match: second, minute, hour, day, date, month. */
8348c2ecf20Sopenharmony_ci	regs[6] |= MCP794XX_MSK_ALMX_MATCH;
8358c2ecf20Sopenharmony_ci	/* Disable interrupt. We will not enable until completely programmed */
8368c2ecf20Sopenharmony_ci	regs[0] &= ~MCP794XX_BIT_ALM0_EN;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs,
8398c2ecf20Sopenharmony_ci				sizeof(regs));
8408c2ecf20Sopenharmony_ci	if (ret)
8418c2ecf20Sopenharmony_ci		return ret;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	if (!t->enabled)
8448c2ecf20Sopenharmony_ci		return 0;
8458c2ecf20Sopenharmony_ci	regs[0] |= MCP794XX_BIT_ALM0_EN;
8468c2ecf20Sopenharmony_ci	return regmap_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs[0]);
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistatic int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	if (!test_bit(HAS_ALARM, &ds1307->flags))
8548c2ecf20Sopenharmony_ci		return -EINVAL;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	return regmap_update_bits(ds1307->regmap, MCP794XX_REG_CONTROL,
8578c2ecf20Sopenharmony_ci				  MCP794XX_BIT_ALM0_EN,
8588c2ecf20Sopenharmony_ci				  enabled ? MCP794XX_BIT_ALM0_EN : 0);
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_cistatic int m41txx_rtc_read_offset(struct device *dev, long *offset)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
8648c2ecf20Sopenharmony_ci	unsigned int ctrl_reg;
8658c2ecf20Sopenharmony_ci	u8 val;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	val = ctrl_reg & M41TXX_M_CALIBRATION;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	/* check if positive */
8728c2ecf20Sopenharmony_ci	if (ctrl_reg & M41TXX_BIT_CALIB_SIGN)
8738c2ecf20Sopenharmony_ci		*offset = (val * M41TXX_POS_OFFSET_STEP_PPB);
8748c2ecf20Sopenharmony_ci	else
8758c2ecf20Sopenharmony_ci		*offset = -(val * M41TXX_NEG_OFFSET_STEP_PPB);
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	return 0;
8788c2ecf20Sopenharmony_ci}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_cistatic int m41txx_rtc_set_offset(struct device *dev, long offset)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
8838c2ecf20Sopenharmony_ci	unsigned int ctrl_reg;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	if ((offset < M41TXX_MIN_OFFSET) || (offset > M41TXX_MAX_OFFSET))
8868c2ecf20Sopenharmony_ci		return -ERANGE;
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	if (offset >= 0) {
8898c2ecf20Sopenharmony_ci		ctrl_reg = DIV_ROUND_CLOSEST(offset,
8908c2ecf20Sopenharmony_ci					     M41TXX_POS_OFFSET_STEP_PPB);
8918c2ecf20Sopenharmony_ci		ctrl_reg |= M41TXX_BIT_CALIB_SIGN;
8928c2ecf20Sopenharmony_ci	} else {
8938c2ecf20Sopenharmony_ci		ctrl_reg = DIV_ROUND_CLOSEST(abs(offset),
8948c2ecf20Sopenharmony_ci					     M41TXX_NEG_OFFSET_STEP_PPB);
8958c2ecf20Sopenharmony_ci	}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	return regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL,
8988c2ecf20Sopenharmony_ci				  M41TXX_M_CALIBRATION | M41TXX_BIT_CALIB_SIGN,
8998c2ecf20Sopenharmony_ci				  ctrl_reg);
9008c2ecf20Sopenharmony_ci}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci#ifdef CONFIG_WATCHDOG_CORE
9038c2ecf20Sopenharmony_cistatic int ds1388_wdt_start(struct watchdog_device *wdt_dev)
9048c2ecf20Sopenharmony_ci{
9058c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
9068c2ecf20Sopenharmony_ci	u8 regs[2];
9078c2ecf20Sopenharmony_ci	int ret;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	ret = regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,
9108c2ecf20Sopenharmony_ci				 DS1388_BIT_WF, 0);
9118c2ecf20Sopenharmony_ci	if (ret)
9128c2ecf20Sopenharmony_ci		return ret;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	ret = regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL,
9158c2ecf20Sopenharmony_ci				 DS1388_BIT_WDE | DS1388_BIT_RST, 0);
9168c2ecf20Sopenharmony_ci	if (ret)
9178c2ecf20Sopenharmony_ci		return ret;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	/*
9208c2ecf20Sopenharmony_ci	 * watchdog timeouts are measured in seconds. So ignore hundredths of
9218c2ecf20Sopenharmony_ci	 * seconds field.
9228c2ecf20Sopenharmony_ci	 */
9238c2ecf20Sopenharmony_ci	regs[0] = 0;
9248c2ecf20Sopenharmony_ci	regs[1] = bin2bcd(wdt_dev->timeout);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs,
9278c2ecf20Sopenharmony_ci				sizeof(regs));
9288c2ecf20Sopenharmony_ci	if (ret)
9298c2ecf20Sopenharmony_ci		return ret;
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL,
9328c2ecf20Sopenharmony_ci				  DS1388_BIT_WDE | DS1388_BIT_RST,
9338c2ecf20Sopenharmony_ci				  DS1388_BIT_WDE | DS1388_BIT_RST);
9348c2ecf20Sopenharmony_ci}
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_cistatic int ds1388_wdt_stop(struct watchdog_device *wdt_dev)
9378c2ecf20Sopenharmony_ci{
9388c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	return regmap_update_bits(ds1307->regmap, DS1388_REG_CONTROL,
9418c2ecf20Sopenharmony_ci				  DS1388_BIT_WDE | DS1388_BIT_RST, 0);
9428c2ecf20Sopenharmony_ci}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_cistatic int ds1388_wdt_ping(struct watchdog_device *wdt_dev)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
9478c2ecf20Sopenharmony_ci	u8 regs[2];
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	return regmap_bulk_read(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs,
9508c2ecf20Sopenharmony_ci				sizeof(regs));
9518c2ecf20Sopenharmony_ci}
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_cistatic int ds1388_wdt_set_timeout(struct watchdog_device *wdt_dev,
9548c2ecf20Sopenharmony_ci				  unsigned int val)
9558c2ecf20Sopenharmony_ci{
9568c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = watchdog_get_drvdata(wdt_dev);
9578c2ecf20Sopenharmony_ci	u8 regs[2];
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	wdt_dev->timeout = val;
9608c2ecf20Sopenharmony_ci	regs[0] = 0;
9618c2ecf20Sopenharmony_ci	regs[1] = bin2bcd(wdt_dev->timeout);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	return regmap_bulk_write(ds1307->regmap, DS1388_REG_WDOG_HUN_SECS, regs,
9648c2ecf20Sopenharmony_ci				 sizeof(regs));
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci#endif
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_cistatic const struct rtc_class_ops rx8130_rtc_ops = {
9698c2ecf20Sopenharmony_ci	.read_time      = ds1307_get_time,
9708c2ecf20Sopenharmony_ci	.set_time       = ds1307_set_time,
9718c2ecf20Sopenharmony_ci	.read_alarm     = rx8130_read_alarm,
9728c2ecf20Sopenharmony_ci	.set_alarm      = rx8130_set_alarm,
9738c2ecf20Sopenharmony_ci	.alarm_irq_enable = rx8130_alarm_irq_enable,
9748c2ecf20Sopenharmony_ci};
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_cistatic const struct rtc_class_ops mcp794xx_rtc_ops = {
9778c2ecf20Sopenharmony_ci	.read_time      = ds1307_get_time,
9788c2ecf20Sopenharmony_ci	.set_time       = ds1307_set_time,
9798c2ecf20Sopenharmony_ci	.read_alarm     = mcp794xx_read_alarm,
9808c2ecf20Sopenharmony_ci	.set_alarm      = mcp794xx_set_alarm,
9818c2ecf20Sopenharmony_ci	.alarm_irq_enable = mcp794xx_alarm_irq_enable,
9828c2ecf20Sopenharmony_ci};
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistatic const struct rtc_class_ops m41txx_rtc_ops = {
9858c2ecf20Sopenharmony_ci	.read_time      = ds1307_get_time,
9868c2ecf20Sopenharmony_ci	.set_time       = ds1307_set_time,
9878c2ecf20Sopenharmony_ci	.read_alarm	= ds1337_read_alarm,
9888c2ecf20Sopenharmony_ci	.set_alarm	= ds1337_set_alarm,
9898c2ecf20Sopenharmony_ci	.alarm_irq_enable = ds1307_alarm_irq_enable,
9908c2ecf20Sopenharmony_ci	.read_offset	= m41txx_rtc_read_offset,
9918c2ecf20Sopenharmony_ci	.set_offset	= m41txx_rtc_set_offset,
9928c2ecf20Sopenharmony_ci};
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_cistatic const struct chip_desc chips[last_ds_type] = {
9958c2ecf20Sopenharmony_ci	[ds_1307] = {
9968c2ecf20Sopenharmony_ci		.nvram_offset	= 8,
9978c2ecf20Sopenharmony_ci		.nvram_size	= 56,
9988c2ecf20Sopenharmony_ci	},
9998c2ecf20Sopenharmony_ci	[ds_1308] = {
10008c2ecf20Sopenharmony_ci		.nvram_offset	= 8,
10018c2ecf20Sopenharmony_ci		.nvram_size	= 56,
10028c2ecf20Sopenharmony_ci	},
10038c2ecf20Sopenharmony_ci	[ds_1337] = {
10048c2ecf20Sopenharmony_ci		.alarm		= 1,
10058c2ecf20Sopenharmony_ci		.century_reg	= DS1307_REG_MONTH,
10068c2ecf20Sopenharmony_ci		.century_bit	= DS1337_BIT_CENTURY,
10078c2ecf20Sopenharmony_ci	},
10088c2ecf20Sopenharmony_ci	[ds_1338] = {
10098c2ecf20Sopenharmony_ci		.nvram_offset	= 8,
10108c2ecf20Sopenharmony_ci		.nvram_size	= 56,
10118c2ecf20Sopenharmony_ci	},
10128c2ecf20Sopenharmony_ci	[ds_1339] = {
10138c2ecf20Sopenharmony_ci		.alarm		= 1,
10148c2ecf20Sopenharmony_ci		.century_reg	= DS1307_REG_MONTH,
10158c2ecf20Sopenharmony_ci		.century_bit	= DS1337_BIT_CENTURY,
10168c2ecf20Sopenharmony_ci		.bbsqi_bit	= DS1339_BIT_BBSQI,
10178c2ecf20Sopenharmony_ci		.trickle_charger_reg = 0x10,
10188c2ecf20Sopenharmony_ci		.do_trickle_setup = &do_trickle_setup_ds1339,
10198c2ecf20Sopenharmony_ci		.requires_trickle_resistor = true,
10208c2ecf20Sopenharmony_ci		.charge_default = true,
10218c2ecf20Sopenharmony_ci	},
10228c2ecf20Sopenharmony_ci	[ds_1340] = {
10238c2ecf20Sopenharmony_ci		.century_reg	= DS1307_REG_HOUR,
10248c2ecf20Sopenharmony_ci		.century_enable_bit = DS1340_BIT_CENTURY_EN,
10258c2ecf20Sopenharmony_ci		.century_bit	= DS1340_BIT_CENTURY,
10268c2ecf20Sopenharmony_ci		.do_trickle_setup = &do_trickle_setup_ds1339,
10278c2ecf20Sopenharmony_ci		.trickle_charger_reg = 0x08,
10288c2ecf20Sopenharmony_ci		.requires_trickle_resistor = true,
10298c2ecf20Sopenharmony_ci		.charge_default = true,
10308c2ecf20Sopenharmony_ci	},
10318c2ecf20Sopenharmony_ci	[ds_1341] = {
10328c2ecf20Sopenharmony_ci		.century_reg	= DS1307_REG_MONTH,
10338c2ecf20Sopenharmony_ci		.century_bit	= DS1337_BIT_CENTURY,
10348c2ecf20Sopenharmony_ci	},
10358c2ecf20Sopenharmony_ci	[ds_1388] = {
10368c2ecf20Sopenharmony_ci		.offset		= 1,
10378c2ecf20Sopenharmony_ci		.trickle_charger_reg = 0x0a,
10388c2ecf20Sopenharmony_ci	},
10398c2ecf20Sopenharmony_ci	[ds_3231] = {
10408c2ecf20Sopenharmony_ci		.alarm		= 1,
10418c2ecf20Sopenharmony_ci		.century_reg	= DS1307_REG_MONTH,
10428c2ecf20Sopenharmony_ci		.century_bit	= DS1337_BIT_CENTURY,
10438c2ecf20Sopenharmony_ci		.bbsqi_bit	= DS3231_BIT_BBSQW,
10448c2ecf20Sopenharmony_ci	},
10458c2ecf20Sopenharmony_ci	[rx_8130] = {
10468c2ecf20Sopenharmony_ci		.alarm		= 1,
10478c2ecf20Sopenharmony_ci		/* this is battery backed SRAM */
10488c2ecf20Sopenharmony_ci		.nvram_offset	= 0x20,
10498c2ecf20Sopenharmony_ci		.nvram_size	= 4,	/* 32bit (4 word x 8 bit) */
10508c2ecf20Sopenharmony_ci		.offset		= 0x10,
10518c2ecf20Sopenharmony_ci		.irq_handler = rx8130_irq,
10528c2ecf20Sopenharmony_ci		.rtc_ops = &rx8130_rtc_ops,
10538c2ecf20Sopenharmony_ci		.trickle_charger_reg = RX8130_REG_CONTROL1,
10548c2ecf20Sopenharmony_ci		.do_trickle_setup = &do_trickle_setup_rx8130,
10558c2ecf20Sopenharmony_ci	},
10568c2ecf20Sopenharmony_ci	[m41t0] = {
10578c2ecf20Sopenharmony_ci		.rtc_ops	= &m41txx_rtc_ops,
10588c2ecf20Sopenharmony_ci	},
10598c2ecf20Sopenharmony_ci	[m41t00] = {
10608c2ecf20Sopenharmony_ci		.rtc_ops	= &m41txx_rtc_ops,
10618c2ecf20Sopenharmony_ci	},
10628c2ecf20Sopenharmony_ci	[m41t11] = {
10638c2ecf20Sopenharmony_ci		/* this is battery backed SRAM */
10648c2ecf20Sopenharmony_ci		.nvram_offset	= 8,
10658c2ecf20Sopenharmony_ci		.nvram_size	= 56,
10668c2ecf20Sopenharmony_ci		.rtc_ops	= &m41txx_rtc_ops,
10678c2ecf20Sopenharmony_ci	},
10688c2ecf20Sopenharmony_ci	[mcp794xx] = {
10698c2ecf20Sopenharmony_ci		.alarm		= 1,
10708c2ecf20Sopenharmony_ci		/* this is battery backed SRAM */
10718c2ecf20Sopenharmony_ci		.nvram_offset	= 0x20,
10728c2ecf20Sopenharmony_ci		.nvram_size	= 0x40,
10738c2ecf20Sopenharmony_ci		.irq_handler = mcp794xx_irq,
10748c2ecf20Sopenharmony_ci		.rtc_ops = &mcp794xx_rtc_ops,
10758c2ecf20Sopenharmony_ci	},
10768c2ecf20Sopenharmony_ci};
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_cistatic const struct i2c_device_id ds1307_id[] = {
10798c2ecf20Sopenharmony_ci	{ "ds1307", ds_1307 },
10808c2ecf20Sopenharmony_ci	{ "ds1308", ds_1308 },
10818c2ecf20Sopenharmony_ci	{ "ds1337", ds_1337 },
10828c2ecf20Sopenharmony_ci	{ "ds1338", ds_1338 },
10838c2ecf20Sopenharmony_ci	{ "ds1339", ds_1339 },
10848c2ecf20Sopenharmony_ci	{ "ds1388", ds_1388 },
10858c2ecf20Sopenharmony_ci	{ "ds1340", ds_1340 },
10868c2ecf20Sopenharmony_ci	{ "ds1341", ds_1341 },
10878c2ecf20Sopenharmony_ci	{ "ds3231", ds_3231 },
10888c2ecf20Sopenharmony_ci	{ "m41t0", m41t0 },
10898c2ecf20Sopenharmony_ci	{ "m41t00", m41t00 },
10908c2ecf20Sopenharmony_ci	{ "m41t11", m41t11 },
10918c2ecf20Sopenharmony_ci	{ "mcp7940x", mcp794xx },
10928c2ecf20Sopenharmony_ci	{ "mcp7941x", mcp794xx },
10938c2ecf20Sopenharmony_ci	{ "pt7c4338", ds_1307 },
10948c2ecf20Sopenharmony_ci	{ "rx8025", rx_8025 },
10958c2ecf20Sopenharmony_ci	{ "isl12057", ds_1337 },
10968c2ecf20Sopenharmony_ci	{ "rx8130", rx_8130 },
10978c2ecf20Sopenharmony_ci	{ }
10988c2ecf20Sopenharmony_ci};
10998c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ds1307_id);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
11028c2ecf20Sopenharmony_cistatic const struct of_device_id ds1307_of_match[] = {
11038c2ecf20Sopenharmony_ci	{
11048c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1307",
11058c2ecf20Sopenharmony_ci		.data = (void *)ds_1307
11068c2ecf20Sopenharmony_ci	},
11078c2ecf20Sopenharmony_ci	{
11088c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1308",
11098c2ecf20Sopenharmony_ci		.data = (void *)ds_1308
11108c2ecf20Sopenharmony_ci	},
11118c2ecf20Sopenharmony_ci	{
11128c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1337",
11138c2ecf20Sopenharmony_ci		.data = (void *)ds_1337
11148c2ecf20Sopenharmony_ci	},
11158c2ecf20Sopenharmony_ci	{
11168c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1338",
11178c2ecf20Sopenharmony_ci		.data = (void *)ds_1338
11188c2ecf20Sopenharmony_ci	},
11198c2ecf20Sopenharmony_ci	{
11208c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1339",
11218c2ecf20Sopenharmony_ci		.data = (void *)ds_1339
11228c2ecf20Sopenharmony_ci	},
11238c2ecf20Sopenharmony_ci	{
11248c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1388",
11258c2ecf20Sopenharmony_ci		.data = (void *)ds_1388
11268c2ecf20Sopenharmony_ci	},
11278c2ecf20Sopenharmony_ci	{
11288c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1340",
11298c2ecf20Sopenharmony_ci		.data = (void *)ds_1340
11308c2ecf20Sopenharmony_ci	},
11318c2ecf20Sopenharmony_ci	{
11328c2ecf20Sopenharmony_ci		.compatible = "dallas,ds1341",
11338c2ecf20Sopenharmony_ci		.data = (void *)ds_1341
11348c2ecf20Sopenharmony_ci	},
11358c2ecf20Sopenharmony_ci	{
11368c2ecf20Sopenharmony_ci		.compatible = "maxim,ds3231",
11378c2ecf20Sopenharmony_ci		.data = (void *)ds_3231
11388c2ecf20Sopenharmony_ci	},
11398c2ecf20Sopenharmony_ci	{
11408c2ecf20Sopenharmony_ci		.compatible = "st,m41t0",
11418c2ecf20Sopenharmony_ci		.data = (void *)m41t0
11428c2ecf20Sopenharmony_ci	},
11438c2ecf20Sopenharmony_ci	{
11448c2ecf20Sopenharmony_ci		.compatible = "st,m41t00",
11458c2ecf20Sopenharmony_ci		.data = (void *)m41t00
11468c2ecf20Sopenharmony_ci	},
11478c2ecf20Sopenharmony_ci	{
11488c2ecf20Sopenharmony_ci		.compatible = "st,m41t11",
11498c2ecf20Sopenharmony_ci		.data = (void *)m41t11
11508c2ecf20Sopenharmony_ci	},
11518c2ecf20Sopenharmony_ci	{
11528c2ecf20Sopenharmony_ci		.compatible = "microchip,mcp7940x",
11538c2ecf20Sopenharmony_ci		.data = (void *)mcp794xx
11548c2ecf20Sopenharmony_ci	},
11558c2ecf20Sopenharmony_ci	{
11568c2ecf20Sopenharmony_ci		.compatible = "microchip,mcp7941x",
11578c2ecf20Sopenharmony_ci		.data = (void *)mcp794xx
11588c2ecf20Sopenharmony_ci	},
11598c2ecf20Sopenharmony_ci	{
11608c2ecf20Sopenharmony_ci		.compatible = "pericom,pt7c4338",
11618c2ecf20Sopenharmony_ci		.data = (void *)ds_1307
11628c2ecf20Sopenharmony_ci	},
11638c2ecf20Sopenharmony_ci	{
11648c2ecf20Sopenharmony_ci		.compatible = "epson,rx8025",
11658c2ecf20Sopenharmony_ci		.data = (void *)rx_8025
11668c2ecf20Sopenharmony_ci	},
11678c2ecf20Sopenharmony_ci	{
11688c2ecf20Sopenharmony_ci		.compatible = "isil,isl12057",
11698c2ecf20Sopenharmony_ci		.data = (void *)ds_1337
11708c2ecf20Sopenharmony_ci	},
11718c2ecf20Sopenharmony_ci	{
11728c2ecf20Sopenharmony_ci		.compatible = "epson,rx8130",
11738c2ecf20Sopenharmony_ci		.data = (void *)rx_8130
11748c2ecf20Sopenharmony_ci	},
11758c2ecf20Sopenharmony_ci	{ }
11768c2ecf20Sopenharmony_ci};
11778c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, ds1307_of_match);
11788c2ecf20Sopenharmony_ci#endif
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
11818c2ecf20Sopenharmony_cistatic const struct acpi_device_id ds1307_acpi_ids[] = {
11828c2ecf20Sopenharmony_ci	{ .id = "DS1307", .driver_data = ds_1307 },
11838c2ecf20Sopenharmony_ci	{ .id = "DS1308", .driver_data = ds_1308 },
11848c2ecf20Sopenharmony_ci	{ .id = "DS1337", .driver_data = ds_1337 },
11858c2ecf20Sopenharmony_ci	{ .id = "DS1338", .driver_data = ds_1338 },
11868c2ecf20Sopenharmony_ci	{ .id = "DS1339", .driver_data = ds_1339 },
11878c2ecf20Sopenharmony_ci	{ .id = "DS1388", .driver_data = ds_1388 },
11888c2ecf20Sopenharmony_ci	{ .id = "DS1340", .driver_data = ds_1340 },
11898c2ecf20Sopenharmony_ci	{ .id = "DS1341", .driver_data = ds_1341 },
11908c2ecf20Sopenharmony_ci	{ .id = "DS3231", .driver_data = ds_3231 },
11918c2ecf20Sopenharmony_ci	{ .id = "M41T0", .driver_data = m41t0 },
11928c2ecf20Sopenharmony_ci	{ .id = "M41T00", .driver_data = m41t00 },
11938c2ecf20Sopenharmony_ci	{ .id = "M41T11", .driver_data = m41t11 },
11948c2ecf20Sopenharmony_ci	{ .id = "MCP7940X", .driver_data = mcp794xx },
11958c2ecf20Sopenharmony_ci	{ .id = "MCP7941X", .driver_data = mcp794xx },
11968c2ecf20Sopenharmony_ci	{ .id = "PT7C4338", .driver_data = ds_1307 },
11978c2ecf20Sopenharmony_ci	{ .id = "RX8025", .driver_data = rx_8025 },
11988c2ecf20Sopenharmony_ci	{ .id = "ISL12057", .driver_data = ds_1337 },
11998c2ecf20Sopenharmony_ci	{ .id = "RX8130", .driver_data = rx_8130 },
12008c2ecf20Sopenharmony_ci	{ }
12018c2ecf20Sopenharmony_ci};
12028c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids);
12038c2ecf20Sopenharmony_ci#endif
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci/*
12068c2ecf20Sopenharmony_ci * The ds1337 and ds1339 both have two alarms, but we only use the first
12078c2ecf20Sopenharmony_ci * one (with a "seconds" field).  For ds1337 we expect nINTA is our alarm
12088c2ecf20Sopenharmony_ci * signal; ds1339 chips have only one alarm signal.
12098c2ecf20Sopenharmony_ci */
12108c2ecf20Sopenharmony_cistatic irqreturn_t ds1307_irq(int irq, void *dev_id)
12118c2ecf20Sopenharmony_ci{
12128c2ecf20Sopenharmony_ci	struct ds1307		*ds1307 = dev_id;
12138c2ecf20Sopenharmony_ci	struct mutex		*lock = &ds1307->rtc->ops_lock;
12148c2ecf20Sopenharmony_ci	int			stat, ret;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	mutex_lock(lock);
12178c2ecf20Sopenharmony_ci	ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &stat);
12188c2ecf20Sopenharmony_ci	if (ret)
12198c2ecf20Sopenharmony_ci		goto out;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	if (stat & DS1337_BIT_A1I) {
12228c2ecf20Sopenharmony_ci		stat &= ~DS1337_BIT_A1I;
12238c2ecf20Sopenharmony_ci		regmap_write(ds1307->regmap, DS1337_REG_STATUS, stat);
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci		ret = regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL,
12268c2ecf20Sopenharmony_ci					 DS1337_BIT_A1IE, 0);
12278c2ecf20Sopenharmony_ci		if (ret)
12288c2ecf20Sopenharmony_ci			goto out;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci		rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
12318c2ecf20Sopenharmony_ci	}
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ciout:
12348c2ecf20Sopenharmony_ci	mutex_unlock(lock);
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
12378c2ecf20Sopenharmony_ci}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci/*----------------------------------------------------------------------*/
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_cistatic const struct rtc_class_ops ds13xx_rtc_ops = {
12428c2ecf20Sopenharmony_ci	.read_time	= ds1307_get_time,
12438c2ecf20Sopenharmony_ci	.set_time	= ds1307_set_time,
12448c2ecf20Sopenharmony_ci	.read_alarm	= ds1337_read_alarm,
12458c2ecf20Sopenharmony_ci	.set_alarm	= ds1337_set_alarm,
12468c2ecf20Sopenharmony_ci	.alarm_irq_enable = ds1307_alarm_irq_enable,
12478c2ecf20Sopenharmony_ci};
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_cistatic ssize_t frequency_test_store(struct device *dev,
12508c2ecf20Sopenharmony_ci				    struct device_attribute *attr,
12518c2ecf20Sopenharmony_ci				    const char *buf, size_t count)
12528c2ecf20Sopenharmony_ci{
12538c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev->parent);
12548c2ecf20Sopenharmony_ci	bool freq_test_en;
12558c2ecf20Sopenharmony_ci	int ret;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	ret = kstrtobool(buf, &freq_test_en);
12588c2ecf20Sopenharmony_ci	if (ret) {
12598c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to store RTC Frequency Test attribute\n");
12608c2ecf20Sopenharmony_ci		return ret;
12618c2ecf20Sopenharmony_ci	}
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	regmap_update_bits(ds1307->regmap, M41TXX_REG_CONTROL, M41TXX_BIT_FT,
12648c2ecf20Sopenharmony_ci			   freq_test_en ? M41TXX_BIT_FT : 0);
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	return count;
12678c2ecf20Sopenharmony_ci}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_cistatic ssize_t frequency_test_show(struct device *dev,
12708c2ecf20Sopenharmony_ci				   struct device_attribute *attr,
12718c2ecf20Sopenharmony_ci				   char *buf)
12728c2ecf20Sopenharmony_ci{
12738c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev->parent);
12748c2ecf20Sopenharmony_ci	unsigned int ctrl_reg;
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci	regmap_read(ds1307->regmap, M41TXX_REG_CONTROL, &ctrl_reg);
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, (ctrl_reg & M41TXX_BIT_FT) ? "on\n" :
12798c2ecf20Sopenharmony_ci			"off\n");
12808c2ecf20Sopenharmony_ci}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(frequency_test);
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_cistatic struct attribute *rtc_freq_test_attrs[] = {
12858c2ecf20Sopenharmony_ci	&dev_attr_frequency_test.attr,
12868c2ecf20Sopenharmony_ci	NULL,
12878c2ecf20Sopenharmony_ci};
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_cistatic const struct attribute_group rtc_freq_test_attr_group = {
12908c2ecf20Sopenharmony_ci	.attrs		= rtc_freq_test_attrs,
12918c2ecf20Sopenharmony_ci};
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_cistatic int ds1307_add_frequency_test(struct ds1307 *ds1307)
12948c2ecf20Sopenharmony_ci{
12958c2ecf20Sopenharmony_ci	int err;
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	switch (ds1307->type) {
12988c2ecf20Sopenharmony_ci	case m41t0:
12998c2ecf20Sopenharmony_ci	case m41t00:
13008c2ecf20Sopenharmony_ci	case m41t11:
13018c2ecf20Sopenharmony_ci		err = rtc_add_group(ds1307->rtc, &rtc_freq_test_attr_group);
13028c2ecf20Sopenharmony_ci		if (err)
13038c2ecf20Sopenharmony_ci			return err;
13048c2ecf20Sopenharmony_ci		break;
13058c2ecf20Sopenharmony_ci	default:
13068c2ecf20Sopenharmony_ci		break;
13078c2ecf20Sopenharmony_ci	}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	return 0;
13108c2ecf20Sopenharmony_ci}
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci/*----------------------------------------------------------------------*/
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_cistatic int ds1307_nvram_read(void *priv, unsigned int offset, void *val,
13158c2ecf20Sopenharmony_ci			     size_t bytes)
13168c2ecf20Sopenharmony_ci{
13178c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = priv;
13188c2ecf20Sopenharmony_ci	const struct chip_desc *chip = &chips[ds1307->type];
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	return regmap_bulk_read(ds1307->regmap, chip->nvram_offset + offset,
13218c2ecf20Sopenharmony_ci				val, bytes);
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
13258c2ecf20Sopenharmony_ci			      size_t bytes)
13268c2ecf20Sopenharmony_ci{
13278c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = priv;
13288c2ecf20Sopenharmony_ci	const struct chip_desc *chip = &chips[ds1307->type];
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	return regmap_bulk_write(ds1307->regmap, chip->nvram_offset + offset,
13318c2ecf20Sopenharmony_ci				 val, bytes);
13328c2ecf20Sopenharmony_ci}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci/*----------------------------------------------------------------------*/
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_cistatic u8 ds1307_trickle_init(struct ds1307 *ds1307,
13378c2ecf20Sopenharmony_ci			      const struct chip_desc *chip)
13388c2ecf20Sopenharmony_ci{
13398c2ecf20Sopenharmony_ci	u32 ohms, chargeable;
13408c2ecf20Sopenharmony_ci	bool diode = chip->charge_default;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	if (!chip->do_trickle_setup)
13438c2ecf20Sopenharmony_ci		return 0;
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms",
13468c2ecf20Sopenharmony_ci				     &ohms) && chip->requires_trickle_resistor)
13478c2ecf20Sopenharmony_ci		return 0;
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	/* aux-voltage-chargeable takes precedence over the deprecated
13508c2ecf20Sopenharmony_ci	 * trickle-diode-disable
13518c2ecf20Sopenharmony_ci	 */
13528c2ecf20Sopenharmony_ci	if (!device_property_read_u32(ds1307->dev, "aux-voltage-chargeable",
13538c2ecf20Sopenharmony_ci				     &chargeable)) {
13548c2ecf20Sopenharmony_ci		switch (chargeable) {
13558c2ecf20Sopenharmony_ci		case 0:
13568c2ecf20Sopenharmony_ci			diode = false;
13578c2ecf20Sopenharmony_ci			break;
13588c2ecf20Sopenharmony_ci		case 1:
13598c2ecf20Sopenharmony_ci			diode = true;
13608c2ecf20Sopenharmony_ci			break;
13618c2ecf20Sopenharmony_ci		default:
13628c2ecf20Sopenharmony_ci			dev_warn(ds1307->dev,
13638c2ecf20Sopenharmony_ci				 "unsupported aux-voltage-chargeable value\n");
13648c2ecf20Sopenharmony_ci			break;
13658c2ecf20Sopenharmony_ci		}
13668c2ecf20Sopenharmony_ci	} else if (device_property_read_bool(ds1307->dev,
13678c2ecf20Sopenharmony_ci					     "trickle-diode-disable")) {
13688c2ecf20Sopenharmony_ci		diode = false;
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	return chip->do_trickle_setup(ds1307, ohms, diode);
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci/*----------------------------------------------------------------------*/
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci#if IS_REACHABLE(CONFIG_HWMON)
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci/*
13798c2ecf20Sopenharmony_ci * Temperature sensor support for ds3231 devices.
13808c2ecf20Sopenharmony_ci */
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci#define DS3231_REG_TEMPERATURE	0x11
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci/*
13858c2ecf20Sopenharmony_ci * A user-initiated temperature conversion is not started by this function,
13868c2ecf20Sopenharmony_ci * so the temperature is updated once every 64 seconds.
13878c2ecf20Sopenharmony_ci */
13888c2ecf20Sopenharmony_cistatic int ds3231_hwmon_read_temp(struct device *dev, s32 *mC)
13898c2ecf20Sopenharmony_ci{
13908c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = dev_get_drvdata(dev);
13918c2ecf20Sopenharmony_ci	u8 temp_buf[2];
13928c2ecf20Sopenharmony_ci	s16 temp;
13938c2ecf20Sopenharmony_ci	int ret;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	ret = regmap_bulk_read(ds1307->regmap, DS3231_REG_TEMPERATURE,
13968c2ecf20Sopenharmony_ci			       temp_buf, sizeof(temp_buf));
13978c2ecf20Sopenharmony_ci	if (ret)
13988c2ecf20Sopenharmony_ci		return ret;
13998c2ecf20Sopenharmony_ci	/*
14008c2ecf20Sopenharmony_ci	 * Temperature is represented as a 10-bit code with a resolution of
14018c2ecf20Sopenharmony_ci	 * 0.25 degree celsius and encoded in two's complement format.
14028c2ecf20Sopenharmony_ci	 */
14038c2ecf20Sopenharmony_ci	temp = (temp_buf[0] << 8) | temp_buf[1];
14048c2ecf20Sopenharmony_ci	temp >>= 6;
14058c2ecf20Sopenharmony_ci	*mC = temp * 250;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	return 0;
14088c2ecf20Sopenharmony_ci}
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_cistatic ssize_t ds3231_hwmon_show_temp(struct device *dev,
14118c2ecf20Sopenharmony_ci				      struct device_attribute *attr, char *buf)
14128c2ecf20Sopenharmony_ci{
14138c2ecf20Sopenharmony_ci	int ret;
14148c2ecf20Sopenharmony_ci	s32 temp;
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	ret = ds3231_hwmon_read_temp(dev, &temp);
14178c2ecf20Sopenharmony_ci	if (ret)
14188c2ecf20Sopenharmony_ci		return ret;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", temp);
14218c2ecf20Sopenharmony_ci}
14228c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_input, 0444, ds3231_hwmon_show_temp,
14238c2ecf20Sopenharmony_ci			  NULL, 0);
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_cistatic struct attribute *ds3231_hwmon_attrs[] = {
14268c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_input.dev_attr.attr,
14278c2ecf20Sopenharmony_ci	NULL,
14288c2ecf20Sopenharmony_ci};
14298c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(ds3231_hwmon);
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_cistatic void ds1307_hwmon_register(struct ds1307 *ds1307)
14328c2ecf20Sopenharmony_ci{
14338c2ecf20Sopenharmony_ci	struct device *dev;
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	if (ds1307->type != ds_3231)
14368c2ecf20Sopenharmony_ci		return;
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	dev = devm_hwmon_device_register_with_groups(ds1307->dev, ds1307->name,
14398c2ecf20Sopenharmony_ci						     ds1307,
14408c2ecf20Sopenharmony_ci						     ds3231_hwmon_groups);
14418c2ecf20Sopenharmony_ci	if (IS_ERR(dev)) {
14428c2ecf20Sopenharmony_ci		dev_warn(ds1307->dev, "unable to register hwmon device %ld\n",
14438c2ecf20Sopenharmony_ci			 PTR_ERR(dev));
14448c2ecf20Sopenharmony_ci	}
14458c2ecf20Sopenharmony_ci}
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_ci#else
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_cistatic void ds1307_hwmon_register(struct ds1307 *ds1307)
14508c2ecf20Sopenharmony_ci{
14518c2ecf20Sopenharmony_ci}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci#endif /* CONFIG_RTC_DRV_DS1307_HWMON */
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci/*----------------------------------------------------------------------*/
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci/*
14588c2ecf20Sopenharmony_ci * Square-wave output support for DS3231
14598c2ecf20Sopenharmony_ci * Datasheet: https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
14608c2ecf20Sopenharmony_ci */
14618c2ecf20Sopenharmony_ci#ifdef CONFIG_COMMON_CLK
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_cienum {
14648c2ecf20Sopenharmony_ci	DS3231_CLK_SQW = 0,
14658c2ecf20Sopenharmony_ci	DS3231_CLK_32KHZ,
14668c2ecf20Sopenharmony_ci};
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci#define clk_sqw_to_ds1307(clk)	\
14698c2ecf20Sopenharmony_ci	container_of(clk, struct ds1307, clks[DS3231_CLK_SQW])
14708c2ecf20Sopenharmony_ci#define clk_32khz_to_ds1307(clk)	\
14718c2ecf20Sopenharmony_ci	container_of(clk, struct ds1307, clks[DS3231_CLK_32KHZ])
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic int ds3231_clk_sqw_rates[] = {
14748c2ecf20Sopenharmony_ci	1,
14758c2ecf20Sopenharmony_ci	1024,
14768c2ecf20Sopenharmony_ci	4096,
14778c2ecf20Sopenharmony_ci	8192,
14788c2ecf20Sopenharmony_ci};
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_cistatic int ds1337_write_control(struct ds1307 *ds1307, u8 mask, u8 value)
14818c2ecf20Sopenharmony_ci{
14828c2ecf20Sopenharmony_ci	struct mutex *lock = &ds1307->rtc->ops_lock;
14838c2ecf20Sopenharmony_ci	int ret;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	mutex_lock(lock);
14868c2ecf20Sopenharmony_ci	ret = regmap_update_bits(ds1307->regmap, DS1337_REG_CONTROL,
14878c2ecf20Sopenharmony_ci				 mask, value);
14888c2ecf20Sopenharmony_ci	mutex_unlock(lock);
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	return ret;
14918c2ecf20Sopenharmony_ci}
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_cistatic unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw,
14948c2ecf20Sopenharmony_ci						unsigned long parent_rate)
14958c2ecf20Sopenharmony_ci{
14968c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
14978c2ecf20Sopenharmony_ci	int control, ret;
14988c2ecf20Sopenharmony_ci	int rate_sel = 0;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
15018c2ecf20Sopenharmony_ci	if (ret)
15028c2ecf20Sopenharmony_ci		return ret;
15038c2ecf20Sopenharmony_ci	if (control & DS1337_BIT_RS1)
15048c2ecf20Sopenharmony_ci		rate_sel += 1;
15058c2ecf20Sopenharmony_ci	if (control & DS1337_BIT_RS2)
15068c2ecf20Sopenharmony_ci		rate_sel += 2;
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	return ds3231_clk_sqw_rates[rate_sel];
15098c2ecf20Sopenharmony_ci}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_cistatic long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate,
15128c2ecf20Sopenharmony_ci				      unsigned long *prate)
15138c2ecf20Sopenharmony_ci{
15148c2ecf20Sopenharmony_ci	int i;
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	for (i = ARRAY_SIZE(ds3231_clk_sqw_rates) - 1; i >= 0; i--) {
15178c2ecf20Sopenharmony_ci		if (ds3231_clk_sqw_rates[i] <= rate)
15188c2ecf20Sopenharmony_ci			return ds3231_clk_sqw_rates[i];
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	return 0;
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_cistatic int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
15258c2ecf20Sopenharmony_ci				   unsigned long parent_rate)
15268c2ecf20Sopenharmony_ci{
15278c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
15288c2ecf20Sopenharmony_ci	int control = 0;
15298c2ecf20Sopenharmony_ci	int rate_sel;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	for (rate_sel = 0; rate_sel < ARRAY_SIZE(ds3231_clk_sqw_rates);
15328c2ecf20Sopenharmony_ci			rate_sel++) {
15338c2ecf20Sopenharmony_ci		if (ds3231_clk_sqw_rates[rate_sel] == rate)
15348c2ecf20Sopenharmony_ci			break;
15358c2ecf20Sopenharmony_ci	}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	if (rate_sel == ARRAY_SIZE(ds3231_clk_sqw_rates))
15388c2ecf20Sopenharmony_ci		return -EINVAL;
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	if (rate_sel & 1)
15418c2ecf20Sopenharmony_ci		control |= DS1337_BIT_RS1;
15428c2ecf20Sopenharmony_ci	if (rate_sel & 2)
15438c2ecf20Sopenharmony_ci		control |= DS1337_BIT_RS2;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	return ds1337_write_control(ds1307, DS1337_BIT_RS1 | DS1337_BIT_RS2,
15468c2ecf20Sopenharmony_ci				control);
15478c2ecf20Sopenharmony_ci}
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_cistatic int ds3231_clk_sqw_prepare(struct clk_hw *hw)
15508c2ecf20Sopenharmony_ci{
15518c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	return ds1337_write_control(ds1307, DS1337_BIT_INTCN, 0);
15548c2ecf20Sopenharmony_ci}
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_cistatic void ds3231_clk_sqw_unprepare(struct clk_hw *hw)
15578c2ecf20Sopenharmony_ci{
15588c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	ds1337_write_control(ds1307, DS1337_BIT_INTCN, DS1337_BIT_INTCN);
15618c2ecf20Sopenharmony_ci}
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_cistatic int ds3231_clk_sqw_is_prepared(struct clk_hw *hw)
15648c2ecf20Sopenharmony_ci{
15658c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
15668c2ecf20Sopenharmony_ci	int control, ret;
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	ret = regmap_read(ds1307->regmap, DS1337_REG_CONTROL, &control);
15698c2ecf20Sopenharmony_ci	if (ret)
15708c2ecf20Sopenharmony_ci		return ret;
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci	return !(control & DS1337_BIT_INTCN);
15738c2ecf20Sopenharmony_ci}
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_cistatic const struct clk_ops ds3231_clk_sqw_ops = {
15768c2ecf20Sopenharmony_ci	.prepare = ds3231_clk_sqw_prepare,
15778c2ecf20Sopenharmony_ci	.unprepare = ds3231_clk_sqw_unprepare,
15788c2ecf20Sopenharmony_ci	.is_prepared = ds3231_clk_sqw_is_prepared,
15798c2ecf20Sopenharmony_ci	.recalc_rate = ds3231_clk_sqw_recalc_rate,
15808c2ecf20Sopenharmony_ci	.round_rate = ds3231_clk_sqw_round_rate,
15818c2ecf20Sopenharmony_ci	.set_rate = ds3231_clk_sqw_set_rate,
15828c2ecf20Sopenharmony_ci};
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_cistatic unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw,
15858c2ecf20Sopenharmony_ci						  unsigned long parent_rate)
15868c2ecf20Sopenharmony_ci{
15878c2ecf20Sopenharmony_ci	return 32768;
15888c2ecf20Sopenharmony_ci}
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_cistatic int ds3231_clk_32khz_control(struct ds1307 *ds1307, bool enable)
15918c2ecf20Sopenharmony_ci{
15928c2ecf20Sopenharmony_ci	struct mutex *lock = &ds1307->rtc->ops_lock;
15938c2ecf20Sopenharmony_ci	int ret;
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	mutex_lock(lock);
15968c2ecf20Sopenharmony_ci	ret = regmap_update_bits(ds1307->regmap, DS1337_REG_STATUS,
15978c2ecf20Sopenharmony_ci				 DS3231_BIT_EN32KHZ,
15988c2ecf20Sopenharmony_ci				 enable ? DS3231_BIT_EN32KHZ : 0);
15998c2ecf20Sopenharmony_ci	mutex_unlock(lock);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	return ret;
16028c2ecf20Sopenharmony_ci}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_cistatic int ds3231_clk_32khz_prepare(struct clk_hw *hw)
16058c2ecf20Sopenharmony_ci{
16068c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	return ds3231_clk_32khz_control(ds1307, true);
16098c2ecf20Sopenharmony_ci}
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_cistatic void ds3231_clk_32khz_unprepare(struct clk_hw *hw)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	ds3231_clk_32khz_control(ds1307, false);
16168c2ecf20Sopenharmony_ci}
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_cistatic int ds3231_clk_32khz_is_prepared(struct clk_hw *hw)
16198c2ecf20Sopenharmony_ci{
16208c2ecf20Sopenharmony_ci	struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
16218c2ecf20Sopenharmony_ci	int status, ret;
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci	ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &status);
16248c2ecf20Sopenharmony_ci	if (ret)
16258c2ecf20Sopenharmony_ci		return ret;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	return !!(status & DS3231_BIT_EN32KHZ);
16288c2ecf20Sopenharmony_ci}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_cistatic const struct clk_ops ds3231_clk_32khz_ops = {
16318c2ecf20Sopenharmony_ci	.prepare = ds3231_clk_32khz_prepare,
16328c2ecf20Sopenharmony_ci	.unprepare = ds3231_clk_32khz_unprepare,
16338c2ecf20Sopenharmony_ci	.is_prepared = ds3231_clk_32khz_is_prepared,
16348c2ecf20Sopenharmony_ci	.recalc_rate = ds3231_clk_32khz_recalc_rate,
16358c2ecf20Sopenharmony_ci};
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_cistatic struct clk_init_data ds3231_clks_init[] = {
16388c2ecf20Sopenharmony_ci	[DS3231_CLK_SQW] = {
16398c2ecf20Sopenharmony_ci		.name = "ds3231_clk_sqw",
16408c2ecf20Sopenharmony_ci		.ops = &ds3231_clk_sqw_ops,
16418c2ecf20Sopenharmony_ci	},
16428c2ecf20Sopenharmony_ci	[DS3231_CLK_32KHZ] = {
16438c2ecf20Sopenharmony_ci		.name = "ds3231_clk_32khz",
16448c2ecf20Sopenharmony_ci		.ops = &ds3231_clk_32khz_ops,
16458c2ecf20Sopenharmony_ci	},
16468c2ecf20Sopenharmony_ci};
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_cistatic int ds3231_clks_register(struct ds1307 *ds1307)
16498c2ecf20Sopenharmony_ci{
16508c2ecf20Sopenharmony_ci	struct device_node *node = ds1307->dev->of_node;
16518c2ecf20Sopenharmony_ci	struct clk_onecell_data	*onecell;
16528c2ecf20Sopenharmony_ci	int i;
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	onecell = devm_kzalloc(ds1307->dev, sizeof(*onecell), GFP_KERNEL);
16558c2ecf20Sopenharmony_ci	if (!onecell)
16568c2ecf20Sopenharmony_ci		return -ENOMEM;
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	onecell->clk_num = ARRAY_SIZE(ds3231_clks_init);
16598c2ecf20Sopenharmony_ci	onecell->clks = devm_kcalloc(ds1307->dev, onecell->clk_num,
16608c2ecf20Sopenharmony_ci				     sizeof(onecell->clks[0]), GFP_KERNEL);
16618c2ecf20Sopenharmony_ci	if (!onecell->clks)
16628c2ecf20Sopenharmony_ci		return -ENOMEM;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ds3231_clks_init); i++) {
16658c2ecf20Sopenharmony_ci		struct clk_init_data init = ds3231_clks_init[i];
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci		/*
16688c2ecf20Sopenharmony_ci		 * Interrupt signal due to alarm conditions and square-wave
16698c2ecf20Sopenharmony_ci		 * output share same pin, so don't initialize both.
16708c2ecf20Sopenharmony_ci		 */
16718c2ecf20Sopenharmony_ci		if (i == DS3231_CLK_SQW && test_bit(HAS_ALARM, &ds1307->flags))
16728c2ecf20Sopenharmony_ci			continue;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci		/* optional override of the clockname */
16758c2ecf20Sopenharmony_ci		of_property_read_string_index(node, "clock-output-names", i,
16768c2ecf20Sopenharmony_ci					      &init.name);
16778c2ecf20Sopenharmony_ci		ds1307->clks[i].init = &init;
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci		onecell->clks[i] = devm_clk_register(ds1307->dev,
16808c2ecf20Sopenharmony_ci						     &ds1307->clks[i]);
16818c2ecf20Sopenharmony_ci		if (IS_ERR(onecell->clks[i]))
16828c2ecf20Sopenharmony_ci			return PTR_ERR(onecell->clks[i]);
16838c2ecf20Sopenharmony_ci	}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	if (!node)
16868c2ecf20Sopenharmony_ci		return 0;
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	of_clk_add_provider(node, of_clk_src_onecell_get, onecell);
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	return 0;
16918c2ecf20Sopenharmony_ci}
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_cistatic void ds1307_clks_register(struct ds1307 *ds1307)
16948c2ecf20Sopenharmony_ci{
16958c2ecf20Sopenharmony_ci	int ret;
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	if (ds1307->type != ds_3231)
16988c2ecf20Sopenharmony_ci		return;
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci	ret = ds3231_clks_register(ds1307);
17018c2ecf20Sopenharmony_ci	if (ret) {
17028c2ecf20Sopenharmony_ci		dev_warn(ds1307->dev, "unable to register clock device %d\n",
17038c2ecf20Sopenharmony_ci			 ret);
17048c2ecf20Sopenharmony_ci	}
17058c2ecf20Sopenharmony_ci}
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci#else
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_cistatic void ds1307_clks_register(struct ds1307 *ds1307)
17108c2ecf20Sopenharmony_ci{
17118c2ecf20Sopenharmony_ci}
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci#endif /* CONFIG_COMMON_CLK */
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci#ifdef CONFIG_WATCHDOG_CORE
17168c2ecf20Sopenharmony_cistatic const struct watchdog_info ds1388_wdt_info = {
17178c2ecf20Sopenharmony_ci	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
17188c2ecf20Sopenharmony_ci	.identity = "DS1388 watchdog",
17198c2ecf20Sopenharmony_ci};
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_cistatic const struct watchdog_ops ds1388_wdt_ops = {
17228c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
17238c2ecf20Sopenharmony_ci	.start = ds1388_wdt_start,
17248c2ecf20Sopenharmony_ci	.stop = ds1388_wdt_stop,
17258c2ecf20Sopenharmony_ci	.ping = ds1388_wdt_ping,
17268c2ecf20Sopenharmony_ci	.set_timeout = ds1388_wdt_set_timeout,
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci};
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_cistatic void ds1307_wdt_register(struct ds1307 *ds1307)
17318c2ecf20Sopenharmony_ci{
17328c2ecf20Sopenharmony_ci	struct watchdog_device	*wdt;
17338c2ecf20Sopenharmony_ci	int err;
17348c2ecf20Sopenharmony_ci	int val;
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	if (ds1307->type != ds_1388)
17378c2ecf20Sopenharmony_ci		return;
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	wdt = devm_kzalloc(ds1307->dev, sizeof(*wdt), GFP_KERNEL);
17408c2ecf20Sopenharmony_ci	if (!wdt)
17418c2ecf20Sopenharmony_ci		return;
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci	err = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &val);
17448c2ecf20Sopenharmony_ci	if (!err && val & DS1388_BIT_WF)
17458c2ecf20Sopenharmony_ci		wdt->bootstatus = WDIOF_CARDRESET;
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci	wdt->info = &ds1388_wdt_info;
17488c2ecf20Sopenharmony_ci	wdt->ops = &ds1388_wdt_ops;
17498c2ecf20Sopenharmony_ci	wdt->timeout = 99;
17508c2ecf20Sopenharmony_ci	wdt->max_timeout = 99;
17518c2ecf20Sopenharmony_ci	wdt->min_timeout = 1;
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	watchdog_init_timeout(wdt, 0, ds1307->dev);
17548c2ecf20Sopenharmony_ci	watchdog_set_drvdata(wdt, ds1307);
17558c2ecf20Sopenharmony_ci	devm_watchdog_register_device(ds1307->dev, wdt);
17568c2ecf20Sopenharmony_ci}
17578c2ecf20Sopenharmony_ci#else
17588c2ecf20Sopenharmony_cistatic void ds1307_wdt_register(struct ds1307 *ds1307)
17598c2ecf20Sopenharmony_ci{
17608c2ecf20Sopenharmony_ci}
17618c2ecf20Sopenharmony_ci#endif /* CONFIG_WATCHDOG_CORE */
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_cistatic const struct regmap_config regmap_config = {
17648c2ecf20Sopenharmony_ci	.reg_bits = 8,
17658c2ecf20Sopenharmony_ci	.val_bits = 8,
17668c2ecf20Sopenharmony_ci};
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_cistatic int ds1307_probe(struct i2c_client *client,
17698c2ecf20Sopenharmony_ci			const struct i2c_device_id *id)
17708c2ecf20Sopenharmony_ci{
17718c2ecf20Sopenharmony_ci	struct ds1307		*ds1307;
17728c2ecf20Sopenharmony_ci	int			err = -ENODEV;
17738c2ecf20Sopenharmony_ci	int			tmp;
17748c2ecf20Sopenharmony_ci	const struct chip_desc	*chip;
17758c2ecf20Sopenharmony_ci	bool			want_irq;
17768c2ecf20Sopenharmony_ci	bool			ds1307_can_wakeup_device = false;
17778c2ecf20Sopenharmony_ci	unsigned char		regs[8];
17788c2ecf20Sopenharmony_ci	struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
17798c2ecf20Sopenharmony_ci	u8			trickle_charger_setup = 0;
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
17828c2ecf20Sopenharmony_ci	if (!ds1307)
17838c2ecf20Sopenharmony_ci		return -ENOMEM;
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	dev_set_drvdata(&client->dev, ds1307);
17868c2ecf20Sopenharmony_ci	ds1307->dev = &client->dev;
17878c2ecf20Sopenharmony_ci	ds1307->name = client->name;
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci	ds1307->regmap = devm_regmap_init_i2c(client, &regmap_config);
17908c2ecf20Sopenharmony_ci	if (IS_ERR(ds1307->regmap)) {
17918c2ecf20Sopenharmony_ci		dev_err(ds1307->dev, "regmap allocation failed\n");
17928c2ecf20Sopenharmony_ci		return PTR_ERR(ds1307->regmap);
17938c2ecf20Sopenharmony_ci	}
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, ds1307);
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	if (client->dev.of_node) {
17988c2ecf20Sopenharmony_ci		ds1307->type = (enum ds_type)
17998c2ecf20Sopenharmony_ci			of_device_get_match_data(&client->dev);
18008c2ecf20Sopenharmony_ci		chip = &chips[ds1307->type];
18018c2ecf20Sopenharmony_ci	} else if (id) {
18028c2ecf20Sopenharmony_ci		chip = &chips[id->driver_data];
18038c2ecf20Sopenharmony_ci		ds1307->type = id->driver_data;
18048c2ecf20Sopenharmony_ci	} else {
18058c2ecf20Sopenharmony_ci		const struct acpi_device_id *acpi_id;
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci		acpi_id = acpi_match_device(ACPI_PTR(ds1307_acpi_ids),
18088c2ecf20Sopenharmony_ci					    ds1307->dev);
18098c2ecf20Sopenharmony_ci		if (!acpi_id)
18108c2ecf20Sopenharmony_ci			return -ENODEV;
18118c2ecf20Sopenharmony_ci		chip = &chips[acpi_id->driver_data];
18128c2ecf20Sopenharmony_ci		ds1307->type = acpi_id->driver_data;
18138c2ecf20Sopenharmony_ci	}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	want_irq = client->irq > 0 && chip->alarm;
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci	if (!pdata)
18188c2ecf20Sopenharmony_ci		trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
18198c2ecf20Sopenharmony_ci	else if (pdata->trickle_charger_setup)
18208c2ecf20Sopenharmony_ci		trickle_charger_setup = pdata->trickle_charger_setup;
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	if (trickle_charger_setup && chip->trickle_charger_reg) {
18238c2ecf20Sopenharmony_ci		dev_dbg(ds1307->dev,
18248c2ecf20Sopenharmony_ci			"writing trickle charger info 0x%x to 0x%x\n",
18258c2ecf20Sopenharmony_ci			trickle_charger_setup, chip->trickle_charger_reg);
18268c2ecf20Sopenharmony_ci		regmap_write(ds1307->regmap, chip->trickle_charger_reg,
18278c2ecf20Sopenharmony_ci			     trickle_charger_setup);
18288c2ecf20Sopenharmony_ci	}
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
18318c2ecf20Sopenharmony_ci/*
18328c2ecf20Sopenharmony_ci * For devices with no IRQ directly connected to the SoC, the RTC chip
18338c2ecf20Sopenharmony_ci * can be forced as a wakeup source by stating that explicitly in
18348c2ecf20Sopenharmony_ci * the device's .dts file using the "wakeup-source" boolean property.
18358c2ecf20Sopenharmony_ci * If the "wakeup-source" property is set, don't request an IRQ.
18368c2ecf20Sopenharmony_ci * This will guarantee the 'wakealarm' sysfs entry is available on the device,
18378c2ecf20Sopenharmony_ci * if supported by the RTC.
18388c2ecf20Sopenharmony_ci */
18398c2ecf20Sopenharmony_ci	if (chip->alarm && of_property_read_bool(client->dev.of_node,
18408c2ecf20Sopenharmony_ci						 "wakeup-source"))
18418c2ecf20Sopenharmony_ci		ds1307_can_wakeup_device = true;
18428c2ecf20Sopenharmony_ci#endif
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci	switch (ds1307->type) {
18458c2ecf20Sopenharmony_ci	case ds_1337:
18468c2ecf20Sopenharmony_ci	case ds_1339:
18478c2ecf20Sopenharmony_ci	case ds_1341:
18488c2ecf20Sopenharmony_ci	case ds_3231:
18498c2ecf20Sopenharmony_ci		/* get registers that the "rtc" read below won't read... */
18508c2ecf20Sopenharmony_ci		err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
18518c2ecf20Sopenharmony_ci				       regs, 2);
18528c2ecf20Sopenharmony_ci		if (err) {
18538c2ecf20Sopenharmony_ci			dev_dbg(ds1307->dev, "read error %d\n", err);
18548c2ecf20Sopenharmony_ci			goto exit;
18558c2ecf20Sopenharmony_ci		}
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci		/* oscillator off?  turn it on, so clock can tick. */
18588c2ecf20Sopenharmony_ci		if (regs[0] & DS1337_BIT_nEOSC)
18598c2ecf20Sopenharmony_ci			regs[0] &= ~DS1337_BIT_nEOSC;
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci		/*
18628c2ecf20Sopenharmony_ci		 * Using IRQ or defined as wakeup-source?
18638c2ecf20Sopenharmony_ci		 * Disable the square wave and both alarms.
18648c2ecf20Sopenharmony_ci		 * For some variants, be sure alarms can trigger when we're
18658c2ecf20Sopenharmony_ci		 * running on Vbackup (BBSQI/BBSQW)
18668c2ecf20Sopenharmony_ci		 */
18678c2ecf20Sopenharmony_ci		if (want_irq || ds1307_can_wakeup_device) {
18688c2ecf20Sopenharmony_ci			regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
18698c2ecf20Sopenharmony_ci			regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
18708c2ecf20Sopenharmony_ci		}
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci		regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
18738c2ecf20Sopenharmony_ci			     regs[0]);
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci		/* oscillator fault?  clear flag, and warn */
18768c2ecf20Sopenharmony_ci		if (regs[1] & DS1337_BIT_OSF) {
18778c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap, DS1337_REG_STATUS,
18788c2ecf20Sopenharmony_ci				     regs[1] & ~DS1337_BIT_OSF);
18798c2ecf20Sopenharmony_ci			dev_warn(ds1307->dev, "SET TIME!\n");
18808c2ecf20Sopenharmony_ci		}
18818c2ecf20Sopenharmony_ci		break;
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	case rx_8025:
18848c2ecf20Sopenharmony_ci		err = regmap_bulk_read(ds1307->regmap,
18858c2ecf20Sopenharmony_ci				       RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
18868c2ecf20Sopenharmony_ci		if (err) {
18878c2ecf20Sopenharmony_ci			dev_dbg(ds1307->dev, "read error %d\n", err);
18888c2ecf20Sopenharmony_ci			goto exit;
18898c2ecf20Sopenharmony_ci		}
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci		/* oscillator off?  turn it on, so clock can tick. */
18928c2ecf20Sopenharmony_ci		if (!(regs[1] & RX8025_BIT_XST)) {
18938c2ecf20Sopenharmony_ci			regs[1] |= RX8025_BIT_XST;
18948c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap,
18958c2ecf20Sopenharmony_ci				     RX8025_REG_CTRL2 << 4 | 0x08,
18968c2ecf20Sopenharmony_ci				     regs[1]);
18978c2ecf20Sopenharmony_ci			dev_warn(ds1307->dev,
18988c2ecf20Sopenharmony_ci				 "oscillator stop detected - SET TIME!\n");
18998c2ecf20Sopenharmony_ci		}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci		if (regs[1] & RX8025_BIT_PON) {
19028c2ecf20Sopenharmony_ci			regs[1] &= ~RX8025_BIT_PON;
19038c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap,
19048c2ecf20Sopenharmony_ci				     RX8025_REG_CTRL2 << 4 | 0x08,
19058c2ecf20Sopenharmony_ci				     regs[1]);
19068c2ecf20Sopenharmony_ci			dev_warn(ds1307->dev, "power-on detected\n");
19078c2ecf20Sopenharmony_ci		}
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci		if (regs[1] & RX8025_BIT_VDET) {
19108c2ecf20Sopenharmony_ci			regs[1] &= ~RX8025_BIT_VDET;
19118c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap,
19128c2ecf20Sopenharmony_ci				     RX8025_REG_CTRL2 << 4 | 0x08,
19138c2ecf20Sopenharmony_ci				     regs[1]);
19148c2ecf20Sopenharmony_ci			dev_warn(ds1307->dev, "voltage drop detected\n");
19158c2ecf20Sopenharmony_ci		}
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci		/* make sure we are running in 24hour mode */
19188c2ecf20Sopenharmony_ci		if (!(regs[0] & RX8025_BIT_2412)) {
19198c2ecf20Sopenharmony_ci			u8 hour;
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci			/* switch to 24 hour mode */
19228c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap,
19238c2ecf20Sopenharmony_ci				     RX8025_REG_CTRL1 << 4 | 0x08,
19248c2ecf20Sopenharmony_ci				     regs[0] | RX8025_BIT_2412);
19258c2ecf20Sopenharmony_ci
19268c2ecf20Sopenharmony_ci			err = regmap_bulk_read(ds1307->regmap,
19278c2ecf20Sopenharmony_ci					       RX8025_REG_CTRL1 << 4 | 0x08,
19288c2ecf20Sopenharmony_ci					       regs, 2);
19298c2ecf20Sopenharmony_ci			if (err) {
19308c2ecf20Sopenharmony_ci				dev_dbg(ds1307->dev, "read error %d\n", err);
19318c2ecf20Sopenharmony_ci				goto exit;
19328c2ecf20Sopenharmony_ci			}
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci			/* correct hour */
19358c2ecf20Sopenharmony_ci			hour = bcd2bin(regs[DS1307_REG_HOUR]);
19368c2ecf20Sopenharmony_ci			if (hour == 12)
19378c2ecf20Sopenharmony_ci				hour = 0;
19388c2ecf20Sopenharmony_ci			if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
19398c2ecf20Sopenharmony_ci				hour += 12;
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap,
19428c2ecf20Sopenharmony_ci				     DS1307_REG_HOUR << 4 | 0x08, hour);
19438c2ecf20Sopenharmony_ci		}
19448c2ecf20Sopenharmony_ci		break;
19458c2ecf20Sopenharmony_ci	case ds_1388:
19468c2ecf20Sopenharmony_ci		err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
19478c2ecf20Sopenharmony_ci		if (err) {
19488c2ecf20Sopenharmony_ci			dev_dbg(ds1307->dev, "read error %d\n", err);
19498c2ecf20Sopenharmony_ci			goto exit;
19508c2ecf20Sopenharmony_ci		}
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci		/* oscillator off?  turn it on, so clock can tick. */
19538c2ecf20Sopenharmony_ci		if (tmp & DS1388_BIT_nEOSC) {
19548c2ecf20Sopenharmony_ci			tmp &= ~DS1388_BIT_nEOSC;
19558c2ecf20Sopenharmony_ci			regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
19568c2ecf20Sopenharmony_ci		}
19578c2ecf20Sopenharmony_ci		break;
19588c2ecf20Sopenharmony_ci	default:
19598c2ecf20Sopenharmony_ci		break;
19608c2ecf20Sopenharmony_ci	}
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci	/* read RTC registers */
19638c2ecf20Sopenharmony_ci	err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
19648c2ecf20Sopenharmony_ci			       sizeof(regs));
19658c2ecf20Sopenharmony_ci	if (err) {
19668c2ecf20Sopenharmony_ci		dev_dbg(ds1307->dev, "read error %d\n", err);
19678c2ecf20Sopenharmony_ci		goto exit;
19688c2ecf20Sopenharmony_ci	}
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	if (ds1307->type == mcp794xx &&
19718c2ecf20Sopenharmony_ci	    !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
19728c2ecf20Sopenharmony_ci		regmap_write(ds1307->regmap, DS1307_REG_WDAY,
19738c2ecf20Sopenharmony_ci			     regs[DS1307_REG_WDAY] |
19748c2ecf20Sopenharmony_ci			     MCP794XX_BIT_VBATEN);
19758c2ecf20Sopenharmony_ci	}
19768c2ecf20Sopenharmony_ci
19778c2ecf20Sopenharmony_ci	tmp = regs[DS1307_REG_HOUR];
19788c2ecf20Sopenharmony_ci	switch (ds1307->type) {
19798c2ecf20Sopenharmony_ci	case ds_1340:
19808c2ecf20Sopenharmony_ci	case m41t0:
19818c2ecf20Sopenharmony_ci	case m41t00:
19828c2ecf20Sopenharmony_ci	case m41t11:
19838c2ecf20Sopenharmony_ci		/*
19848c2ecf20Sopenharmony_ci		 * NOTE: ignores century bits; fix before deploying
19858c2ecf20Sopenharmony_ci		 * systems that will run through year 2100.
19868c2ecf20Sopenharmony_ci		 */
19878c2ecf20Sopenharmony_ci		break;
19888c2ecf20Sopenharmony_ci	case rx_8025:
19898c2ecf20Sopenharmony_ci		break;
19908c2ecf20Sopenharmony_ci	default:
19918c2ecf20Sopenharmony_ci		if (!(tmp & DS1307_BIT_12HR))
19928c2ecf20Sopenharmony_ci			break;
19938c2ecf20Sopenharmony_ci
19948c2ecf20Sopenharmony_ci		/*
19958c2ecf20Sopenharmony_ci		 * Be sure we're in 24 hour mode.  Multi-master systems
19968c2ecf20Sopenharmony_ci		 * take note...
19978c2ecf20Sopenharmony_ci		 */
19988c2ecf20Sopenharmony_ci		tmp = bcd2bin(tmp & 0x1f);
19998c2ecf20Sopenharmony_ci		if (tmp == 12)
20008c2ecf20Sopenharmony_ci			tmp = 0;
20018c2ecf20Sopenharmony_ci		if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
20028c2ecf20Sopenharmony_ci			tmp += 12;
20038c2ecf20Sopenharmony_ci		regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
20048c2ecf20Sopenharmony_ci			     bin2bcd(tmp));
20058c2ecf20Sopenharmony_ci	}
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	if (want_irq || ds1307_can_wakeup_device) {
20088c2ecf20Sopenharmony_ci		device_set_wakeup_capable(ds1307->dev, true);
20098c2ecf20Sopenharmony_ci		set_bit(HAS_ALARM, &ds1307->flags);
20108c2ecf20Sopenharmony_ci	}
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
20138c2ecf20Sopenharmony_ci	if (IS_ERR(ds1307->rtc))
20148c2ecf20Sopenharmony_ci		return PTR_ERR(ds1307->rtc);
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	if (ds1307_can_wakeup_device && !want_irq) {
20178c2ecf20Sopenharmony_ci		dev_info(ds1307->dev,
20188c2ecf20Sopenharmony_ci			 "'wakeup-source' is set, request for an IRQ is disabled!\n");
20198c2ecf20Sopenharmony_ci		/* We cannot support UIE mode if we do not have an IRQ line */
20208c2ecf20Sopenharmony_ci		ds1307->rtc->uie_unsupported = 1;
20218c2ecf20Sopenharmony_ci	}
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_ci	if (want_irq) {
20248c2ecf20Sopenharmony_ci		err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
20258c2ecf20Sopenharmony_ci						chip->irq_handler ?: ds1307_irq,
20268c2ecf20Sopenharmony_ci						IRQF_SHARED | IRQF_ONESHOT,
20278c2ecf20Sopenharmony_ci						ds1307->name, ds1307);
20288c2ecf20Sopenharmony_ci		if (err) {
20298c2ecf20Sopenharmony_ci			client->irq = 0;
20308c2ecf20Sopenharmony_ci			device_set_wakeup_capable(ds1307->dev, false);
20318c2ecf20Sopenharmony_ci			clear_bit(HAS_ALARM, &ds1307->flags);
20328c2ecf20Sopenharmony_ci			dev_err(ds1307->dev, "unable to request IRQ!\n");
20338c2ecf20Sopenharmony_ci		} else {
20348c2ecf20Sopenharmony_ci			dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
20358c2ecf20Sopenharmony_ci		}
20368c2ecf20Sopenharmony_ci	}
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_ci	ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
20398c2ecf20Sopenharmony_ci	err = ds1307_add_frequency_test(ds1307);
20408c2ecf20Sopenharmony_ci	if (err)
20418c2ecf20Sopenharmony_ci		return err;
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci	err = rtc_register_device(ds1307->rtc);
20448c2ecf20Sopenharmony_ci	if (err)
20458c2ecf20Sopenharmony_ci		return err;
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci	if (chip->nvram_size) {
20488c2ecf20Sopenharmony_ci		struct nvmem_config nvmem_cfg = {
20498c2ecf20Sopenharmony_ci			.name = "ds1307_nvram",
20508c2ecf20Sopenharmony_ci			.word_size = 1,
20518c2ecf20Sopenharmony_ci			.stride = 1,
20528c2ecf20Sopenharmony_ci			.size = chip->nvram_size,
20538c2ecf20Sopenharmony_ci			.reg_read = ds1307_nvram_read,
20548c2ecf20Sopenharmony_ci			.reg_write = ds1307_nvram_write,
20558c2ecf20Sopenharmony_ci			.priv = ds1307,
20568c2ecf20Sopenharmony_ci		};
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci		ds1307->rtc->nvram_old_abi = true;
20598c2ecf20Sopenharmony_ci		rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
20608c2ecf20Sopenharmony_ci	}
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	ds1307_hwmon_register(ds1307);
20638c2ecf20Sopenharmony_ci	ds1307_clks_register(ds1307);
20648c2ecf20Sopenharmony_ci	ds1307_wdt_register(ds1307);
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci	return 0;
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ciexit:
20698c2ecf20Sopenharmony_ci	return err;
20708c2ecf20Sopenharmony_ci}
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_cistatic struct i2c_driver ds1307_driver = {
20738c2ecf20Sopenharmony_ci	.driver = {
20748c2ecf20Sopenharmony_ci		.name	= "rtc-ds1307",
20758c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(ds1307_of_match),
20768c2ecf20Sopenharmony_ci		.acpi_match_table = ACPI_PTR(ds1307_acpi_ids),
20778c2ecf20Sopenharmony_ci	},
20788c2ecf20Sopenharmony_ci	.probe		= ds1307_probe,
20798c2ecf20Sopenharmony_ci	.id_table	= ds1307_id,
20808c2ecf20Sopenharmony_ci};
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_cimodule_i2c_driver(ds1307_driver);
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("RTC driver for DS1307 and similar chips");
20858c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
2086