18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * An I2C driver for the Philips PCF8563 RTC
48c2ecf20Sopenharmony_ci * Copyright 2005-06 Tower Technologies
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Author: Alessandro Zummo <a.zummo@towertech.it>
78c2ecf20Sopenharmony_ci * Maintainers: http://www.nslu2-linux.org/
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * based on the other drivers in this same directory.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
158c2ecf20Sopenharmony_ci#include <linux/i2c.h>
168c2ecf20Sopenharmony_ci#include <linux/bcd.h>
178c2ecf20Sopenharmony_ci#include <linux/rtc.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/of.h>
218c2ecf20Sopenharmony_ci#include <linux/err.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define PCF8563_REG_ST1		0x00 /* status */
248c2ecf20Sopenharmony_ci#define PCF8563_REG_ST2		0x01
258c2ecf20Sopenharmony_ci#define PCF8563_BIT_AIE		BIT(1)
268c2ecf20Sopenharmony_ci#define PCF8563_BIT_AF		BIT(3)
278c2ecf20Sopenharmony_ci#define PCF8563_BITS_ST2_N	(7 << 5)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define PCF8563_REG_SC		0x02 /* datetime */
308c2ecf20Sopenharmony_ci#define PCF8563_REG_MN		0x03
318c2ecf20Sopenharmony_ci#define PCF8563_REG_HR		0x04
328c2ecf20Sopenharmony_ci#define PCF8563_REG_DM		0x05
338c2ecf20Sopenharmony_ci#define PCF8563_REG_DW		0x06
348c2ecf20Sopenharmony_ci#define PCF8563_REG_MO		0x07
358c2ecf20Sopenharmony_ci#define PCF8563_REG_YR		0x08
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define PCF8563_REG_AMN		0x09 /* alarm */
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO		0x0D /* clock out */
408c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO_FE		0x80 /* clock out enabled */
418c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO_F_MASK		0x03 /* frequenc mask */
428c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO_F_32768HZ	0x00
438c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO_F_1024HZ	0x01
448c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO_F_32HZ		0x02
458c2ecf20Sopenharmony_ci#define PCF8563_REG_CLKO_F_1HZ		0x03
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define PCF8563_REG_TMRC	0x0E /* timer control */
488c2ecf20Sopenharmony_ci#define PCF8563_TMRC_ENABLE	BIT(7)
498c2ecf20Sopenharmony_ci#define PCF8563_TMRC_4096	0
508c2ecf20Sopenharmony_ci#define PCF8563_TMRC_64		1
518c2ecf20Sopenharmony_ci#define PCF8563_TMRC_1		2
528c2ecf20Sopenharmony_ci#define PCF8563_TMRC_1_60	3
538c2ecf20Sopenharmony_ci#define PCF8563_TMRC_MASK	3
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define PCF8563_REG_TMR		0x0F /* timer */
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define PCF8563_SC_LV		0x80 /* low voltage */
588c2ecf20Sopenharmony_ci#define PCF8563_MO_C		0x80 /* century */
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic struct i2c_driver pcf8563_driver;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistruct pcf8563 {
638c2ecf20Sopenharmony_ci	struct rtc_device *rtc;
648c2ecf20Sopenharmony_ci	/*
658c2ecf20Sopenharmony_ci	 * The meaning of MO_C bit varies by the chip type.
668c2ecf20Sopenharmony_ci	 * From PCF8563 datasheet: this bit is toggled when the years
678c2ecf20Sopenharmony_ci	 * register overflows from 99 to 00
688c2ecf20Sopenharmony_ci	 *   0 indicates the century is 20xx
698c2ecf20Sopenharmony_ci	 *   1 indicates the century is 19xx
708c2ecf20Sopenharmony_ci	 * From RTC8564 datasheet: this bit indicates change of
718c2ecf20Sopenharmony_ci	 * century. When the year digit data overflows from 99 to 00,
728c2ecf20Sopenharmony_ci	 * this bit is set. By presetting it to 0 while still in the
738c2ecf20Sopenharmony_ci	 * 20th century, it will be set in year 2000, ...
748c2ecf20Sopenharmony_ci	 * There seems no reliable way to know how the system use this
758c2ecf20Sopenharmony_ci	 * bit.  So let's do it heuristically, assuming we are live in
768c2ecf20Sopenharmony_ci	 * 1970...2069.
778c2ecf20Sopenharmony_ci	 */
788c2ecf20Sopenharmony_ci	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	struct i2c_client *client;
818c2ecf20Sopenharmony_ci#ifdef CONFIG_COMMON_CLK
828c2ecf20Sopenharmony_ci	struct clk_hw		clkout_hw;
838c2ecf20Sopenharmony_ci#endif
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
878c2ecf20Sopenharmony_ci				   unsigned char length, unsigned char *buf)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	struct i2c_msg msgs[] = {
908c2ecf20Sopenharmony_ci		{/* setup read ptr */
918c2ecf20Sopenharmony_ci			.addr = client->addr,
928c2ecf20Sopenharmony_ci			.len = 1,
938c2ecf20Sopenharmony_ci			.buf = &reg,
948c2ecf20Sopenharmony_ci		},
958c2ecf20Sopenharmony_ci		{
968c2ecf20Sopenharmony_ci			.addr = client->addr,
978c2ecf20Sopenharmony_ci			.flags = I2C_M_RD,
988c2ecf20Sopenharmony_ci			.len = length,
998c2ecf20Sopenharmony_ci			.buf = buf
1008c2ecf20Sopenharmony_ci		},
1018c2ecf20Sopenharmony_ci	};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
1048c2ecf20Sopenharmony_ci		dev_err(&client->dev, "%s: read error\n", __func__);
1058c2ecf20Sopenharmony_ci		return -EIO;
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	return 0;
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic int pcf8563_write_block_data(struct i2c_client *client,
1128c2ecf20Sopenharmony_ci				   unsigned char reg, unsigned char length,
1138c2ecf20Sopenharmony_ci				   unsigned char *buf)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	int i, err;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	for (i = 0; i < length; i++) {
1188c2ecf20Sopenharmony_ci		unsigned char data[2] = { reg + i, buf[i] };
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci		err = i2c_master_send(client, data, sizeof(data));
1218c2ecf20Sopenharmony_ci		if (err != sizeof(data)) {
1228c2ecf20Sopenharmony_ci			dev_err(&client->dev,
1238c2ecf20Sopenharmony_ci				"%s: err=%d addr=%02x, data=%02x\n",
1248c2ecf20Sopenharmony_ci				__func__, err, data[0], data[1]);
1258c2ecf20Sopenharmony_ci			return -EIO;
1268c2ecf20Sopenharmony_ci		}
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	return 0;
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	unsigned char buf;
1358c2ecf20Sopenharmony_ci	int err;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
1388c2ecf20Sopenharmony_ci	if (err < 0)
1398c2ecf20Sopenharmony_ci		return err;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	if (on)
1428c2ecf20Sopenharmony_ci		buf |= PCF8563_BIT_AIE;
1438c2ecf20Sopenharmony_ci	else
1448c2ecf20Sopenharmony_ci		buf &= ~PCF8563_BIT_AIE;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	buf &= ~(PCF8563_BIT_AF | PCF8563_BITS_ST2_N);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
1498c2ecf20Sopenharmony_ci	if (err < 0) {
1508c2ecf20Sopenharmony_ci		dev_err(&client->dev, "%s: write error\n", __func__);
1518c2ecf20Sopenharmony_ci		return -EIO;
1528c2ecf20Sopenharmony_ci	}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return 0;
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
1588c2ecf20Sopenharmony_ci				  unsigned char *pen)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	unsigned char buf;
1618c2ecf20Sopenharmony_ci	int err;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
1648c2ecf20Sopenharmony_ci	if (err)
1658c2ecf20Sopenharmony_ci		return err;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (en)
1688c2ecf20Sopenharmony_ci		*en = !!(buf & PCF8563_BIT_AIE);
1698c2ecf20Sopenharmony_ci	if (pen)
1708c2ecf20Sopenharmony_ci		*pen = !!(buf & PCF8563_BIT_AF);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	return 0;
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic irqreturn_t pcf8563_irq(int irq, void *dev_id)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id);
1788c2ecf20Sopenharmony_ci	int err;
1798c2ecf20Sopenharmony_ci	char pending;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
1828c2ecf20Sopenharmony_ci	if (err)
1838c2ecf20Sopenharmony_ci		return IRQ_NONE;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (pending) {
1868c2ecf20Sopenharmony_ci		rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
1878c2ecf20Sopenharmony_ci		pcf8563_set_alarm_mode(pcf8563->client, 1);
1888c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1898c2ecf20Sopenharmony_ci	}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	return IRQ_NONE;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/*
1958c2ecf20Sopenharmony_ci * In the routines that deal directly with the pcf8563 hardware, we use
1968c2ecf20Sopenharmony_ci * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
1978c2ecf20Sopenharmony_ci */
1988c2ecf20Sopenharmony_cistatic int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
2018c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
2028c2ecf20Sopenharmony_ci	unsigned char buf[9];
2038c2ecf20Sopenharmony_ci	int err;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf);
2068c2ecf20Sopenharmony_ci	if (err)
2078c2ecf20Sopenharmony_ci		return err;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
2108c2ecf20Sopenharmony_ci		dev_err(&client->dev,
2118c2ecf20Sopenharmony_ci			"low voltage detected, date/time is not reliable.\n");
2128c2ecf20Sopenharmony_ci		return -EINVAL;
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	dev_dbg(&client->dev,
2168c2ecf20Sopenharmony_ci		"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
2178c2ecf20Sopenharmony_ci		"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
2188c2ecf20Sopenharmony_ci		__func__,
2198c2ecf20Sopenharmony_ci		buf[0], buf[1], buf[2], buf[3],
2208c2ecf20Sopenharmony_ci		buf[4], buf[5], buf[6], buf[7],
2218c2ecf20Sopenharmony_ci		buf[8]);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
2258c2ecf20Sopenharmony_ci	tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
2268c2ecf20Sopenharmony_ci	tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
2278c2ecf20Sopenharmony_ci	tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
2288c2ecf20Sopenharmony_ci	tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
2298c2ecf20Sopenharmony_ci	tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
2308c2ecf20Sopenharmony_ci	tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]) + 100;
2318c2ecf20Sopenharmony_ci	/* detect the polarity heuristically. see note above. */
2328c2ecf20Sopenharmony_ci	pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
2338c2ecf20Sopenharmony_ci		(tm->tm_year >= 100) : (tm->tm_year < 100);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
2368c2ecf20Sopenharmony_ci		"mday=%d, mon=%d, year=%d, wday=%d\n",
2378c2ecf20Sopenharmony_ci		__func__,
2388c2ecf20Sopenharmony_ci		tm->tm_sec, tm->tm_min, tm->tm_hour,
2398c2ecf20Sopenharmony_ci		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	return 0;
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistatic int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
2478c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
2488c2ecf20Sopenharmony_ci	unsigned char buf[9];
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
2518c2ecf20Sopenharmony_ci		"mday=%d, mon=%d, year=%d, wday=%d\n",
2528c2ecf20Sopenharmony_ci		__func__,
2538c2ecf20Sopenharmony_ci		tm->tm_sec, tm->tm_min, tm->tm_hour,
2548c2ecf20Sopenharmony_ci		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	/* hours, minutes and seconds */
2578c2ecf20Sopenharmony_ci	buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
2588c2ecf20Sopenharmony_ci	buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
2598c2ecf20Sopenharmony_ci	buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	/* month, 1 - 12 */
2648c2ecf20Sopenharmony_ci	buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* year and century */
2678c2ecf20Sopenharmony_ci	buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year - 100);
2688c2ecf20Sopenharmony_ci	if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
2698c2ecf20Sopenharmony_ci		buf[PCF8563_REG_MO] |= PCF8563_MO_C;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	return pcf8563_write_block_data(client, PCF8563_REG_SC,
2748c2ecf20Sopenharmony_ci				9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
2808c2ecf20Sopenharmony_ci	int ret;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	switch (cmd) {
2838c2ecf20Sopenharmony_ci	case RTC_VL_READ:
2848c2ecf20Sopenharmony_ci		ret = i2c_smbus_read_byte_data(client, PCF8563_REG_SC);
2858c2ecf20Sopenharmony_ci		if (ret < 0)
2868c2ecf20Sopenharmony_ci			return ret;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		return put_user(ret & PCF8563_SC_LV ? RTC_VL_DATA_INVALID : 0,
2898c2ecf20Sopenharmony_ci				(unsigned int __user *)arg);
2908c2ecf20Sopenharmony_ci	default:
2918c2ecf20Sopenharmony_ci		return -ENOIOCTLCMD;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
2988c2ecf20Sopenharmony_ci	unsigned char buf[4];
2998c2ecf20Sopenharmony_ci	int err;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf);
3028c2ecf20Sopenharmony_ci	if (err)
3038c2ecf20Sopenharmony_ci		return err;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	dev_dbg(&client->dev,
3068c2ecf20Sopenharmony_ci		"%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
3078c2ecf20Sopenharmony_ci		__func__, buf[0], buf[1], buf[2], buf[3]);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	tm->time.tm_sec = 0;
3108c2ecf20Sopenharmony_ci	tm->time.tm_min = bcd2bin(buf[0] & 0x7F);
3118c2ecf20Sopenharmony_ci	tm->time.tm_hour = bcd2bin(buf[1] & 0x3F);
3128c2ecf20Sopenharmony_ci	tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
3138c2ecf20Sopenharmony_ci	tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
3168c2ecf20Sopenharmony_ci	if (err < 0)
3178c2ecf20Sopenharmony_ci		return err;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
3208c2ecf20Sopenharmony_ci		" enabled=%d, pending=%d\n", __func__, tm->time.tm_min,
3218c2ecf20Sopenharmony_ci		tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday,
3228c2ecf20Sopenharmony_ci		tm->enabled, tm->pending);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	return 0;
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_cistatic int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
3308c2ecf20Sopenharmony_ci	unsigned char buf[4];
3318c2ecf20Sopenharmony_ci	int err;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	/* The alarm has no seconds, round up to nearest minute */
3348c2ecf20Sopenharmony_ci	if (tm->time.tm_sec) {
3358c2ecf20Sopenharmony_ci		time64_t alarm_time = rtc_tm_to_time64(&tm->time);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci		alarm_time += 60 - tm->time.tm_sec;
3388c2ecf20Sopenharmony_ci		rtc_time64_to_tm(alarm_time, &tm->time);
3398c2ecf20Sopenharmony_ci	}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d "
3428c2ecf20Sopenharmony_ci		"enabled=%d pending=%d\n", __func__,
3438c2ecf20Sopenharmony_ci		tm->time.tm_min, tm->time.tm_hour, tm->time.tm_wday,
3448c2ecf20Sopenharmony_ci		tm->time.tm_mday, tm->enabled, tm->pending);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	buf[0] = bin2bcd(tm->time.tm_min);
3478c2ecf20Sopenharmony_ci	buf[1] = bin2bcd(tm->time.tm_hour);
3488c2ecf20Sopenharmony_ci	buf[2] = bin2bcd(tm->time.tm_mday);
3498c2ecf20Sopenharmony_ci	buf[3] = tm->time.tm_wday & 0x07;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf);
3528c2ecf20Sopenharmony_ci	if (err)
3538c2ecf20Sopenharmony_ci		return err;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	return pcf8563_set_alarm_mode(client, !!tm->enabled);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: en=%d\n", __func__, enabled);
3618c2ecf20Sopenharmony_ci	return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
3628c2ecf20Sopenharmony_ci}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci#ifdef CONFIG_COMMON_CLK
3658c2ecf20Sopenharmony_ci/*
3668c2ecf20Sopenharmony_ci * Handling of the clkout
3678c2ecf20Sopenharmony_ci */
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci#define clkout_hw_to_pcf8563(_hw) container_of(_hw, struct pcf8563, clkout_hw)
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic const int clkout_rates[] = {
3728c2ecf20Sopenharmony_ci	32768,
3738c2ecf20Sopenharmony_ci	1024,
3748c2ecf20Sopenharmony_ci	32,
3758c2ecf20Sopenharmony_ci	1,
3768c2ecf20Sopenharmony_ci};
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
3798c2ecf20Sopenharmony_ci						unsigned long parent_rate)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
3828c2ecf20Sopenharmony_ci	struct i2c_client *client = pcf8563->client;
3838c2ecf20Sopenharmony_ci	unsigned char buf;
3848c2ecf20Sopenharmony_ci	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	if (ret < 0)
3878c2ecf20Sopenharmony_ci		return 0;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	buf &= PCF8563_REG_CLKO_F_MASK;
3908c2ecf20Sopenharmony_ci	return clkout_rates[buf];
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
3948c2ecf20Sopenharmony_ci				      unsigned long *prate)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	int i;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
3998c2ecf20Sopenharmony_ci		if (clkout_rates[i] <= rate)
4008c2ecf20Sopenharmony_ci			return clkout_rates[i];
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	return 0;
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
4068c2ecf20Sopenharmony_ci				   unsigned long parent_rate)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
4098c2ecf20Sopenharmony_ci	struct i2c_client *client = pcf8563->client;
4108c2ecf20Sopenharmony_ci	unsigned char buf;
4118c2ecf20Sopenharmony_ci	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
4128c2ecf20Sopenharmony_ci	int i;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	if (ret < 0)
4158c2ecf20Sopenharmony_ci		return ret;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
4188c2ecf20Sopenharmony_ci		if (clkout_rates[i] == rate) {
4198c2ecf20Sopenharmony_ci			buf &= ~PCF8563_REG_CLKO_F_MASK;
4208c2ecf20Sopenharmony_ci			buf |= i;
4218c2ecf20Sopenharmony_ci			ret = pcf8563_write_block_data(client,
4228c2ecf20Sopenharmony_ci						       PCF8563_REG_CLKO, 1,
4238c2ecf20Sopenharmony_ci						       &buf);
4248c2ecf20Sopenharmony_ci			return ret;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	return -EINVAL;
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_cistatic int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
4338c2ecf20Sopenharmony_ci	struct i2c_client *client = pcf8563->client;
4348c2ecf20Sopenharmony_ci	unsigned char buf;
4358c2ecf20Sopenharmony_ci	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	if (ret < 0)
4388c2ecf20Sopenharmony_ci		return ret;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	if (enable)
4418c2ecf20Sopenharmony_ci		buf |= PCF8563_REG_CLKO_FE;
4428c2ecf20Sopenharmony_ci	else
4438c2ecf20Sopenharmony_ci		buf &= ~PCF8563_REG_CLKO_FE;
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
4468c2ecf20Sopenharmony_ci	return ret;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic int pcf8563_clkout_prepare(struct clk_hw *hw)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	return pcf8563_clkout_control(hw, 1);
4528c2ecf20Sopenharmony_ci}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_cistatic void pcf8563_clkout_unprepare(struct clk_hw *hw)
4558c2ecf20Sopenharmony_ci{
4568c2ecf20Sopenharmony_ci	pcf8563_clkout_control(hw, 0);
4578c2ecf20Sopenharmony_ci}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_cistatic int pcf8563_clkout_is_prepared(struct clk_hw *hw)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
4628c2ecf20Sopenharmony_ci	struct i2c_client *client = pcf8563->client;
4638c2ecf20Sopenharmony_ci	unsigned char buf;
4648c2ecf20Sopenharmony_ci	int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	if (ret < 0)
4678c2ecf20Sopenharmony_ci		return ret;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	return !!(buf & PCF8563_REG_CLKO_FE);
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cistatic const struct clk_ops pcf8563_clkout_ops = {
4738c2ecf20Sopenharmony_ci	.prepare = pcf8563_clkout_prepare,
4748c2ecf20Sopenharmony_ci	.unprepare = pcf8563_clkout_unprepare,
4758c2ecf20Sopenharmony_ci	.is_prepared = pcf8563_clkout_is_prepared,
4768c2ecf20Sopenharmony_ci	.recalc_rate = pcf8563_clkout_recalc_rate,
4778c2ecf20Sopenharmony_ci	.round_rate = pcf8563_clkout_round_rate,
4788c2ecf20Sopenharmony_ci	.set_rate = pcf8563_clkout_set_rate,
4798c2ecf20Sopenharmony_ci};
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	struct i2c_client *client = pcf8563->client;
4848c2ecf20Sopenharmony_ci	struct device_node *node = client->dev.of_node;
4858c2ecf20Sopenharmony_ci	struct clk *clk;
4868c2ecf20Sopenharmony_ci	struct clk_init_data init;
4878c2ecf20Sopenharmony_ci	int ret;
4888c2ecf20Sopenharmony_ci	unsigned char buf;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	/* disable the clkout output */
4918c2ecf20Sopenharmony_ci	buf = 0;
4928c2ecf20Sopenharmony_ci	ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
4938c2ecf20Sopenharmony_ci	if (ret < 0)
4948c2ecf20Sopenharmony_ci		return ERR_PTR(ret);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	init.name = "pcf8563-clkout";
4978c2ecf20Sopenharmony_ci	init.ops = &pcf8563_clkout_ops;
4988c2ecf20Sopenharmony_ci	init.flags = 0;
4998c2ecf20Sopenharmony_ci	init.parent_names = NULL;
5008c2ecf20Sopenharmony_ci	init.num_parents = 0;
5018c2ecf20Sopenharmony_ci	pcf8563->clkout_hw.init = &init;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	/* optional override of the clockname */
5048c2ecf20Sopenharmony_ci	of_property_read_string(node, "clock-output-names", &init.name);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* register the clock */
5078c2ecf20Sopenharmony_ci	clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	if (!IS_ERR(clk))
5108c2ecf20Sopenharmony_ci		of_clk_add_provider(node, of_clk_src_simple_get, clk);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	return clk;
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci#endif
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic const struct rtc_class_ops pcf8563_rtc_ops = {
5178c2ecf20Sopenharmony_ci	.ioctl		= pcf8563_rtc_ioctl,
5188c2ecf20Sopenharmony_ci	.read_time	= pcf8563_rtc_read_time,
5198c2ecf20Sopenharmony_ci	.set_time	= pcf8563_rtc_set_time,
5208c2ecf20Sopenharmony_ci	.read_alarm	= pcf8563_rtc_read_alarm,
5218c2ecf20Sopenharmony_ci	.set_alarm	= pcf8563_rtc_set_alarm,
5228c2ecf20Sopenharmony_ci	.alarm_irq_enable = pcf8563_irq_enable,
5238c2ecf20Sopenharmony_ci};
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_cistatic int pcf8563_probe(struct i2c_client *client,
5268c2ecf20Sopenharmony_ci				const struct i2c_device_id *id)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	struct pcf8563 *pcf8563;
5298c2ecf20Sopenharmony_ci	int err;
5308c2ecf20Sopenharmony_ci	unsigned char buf;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s\n", __func__);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
5358c2ecf20Sopenharmony_ci		return -ENODEV;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	pcf8563 = devm_kzalloc(&client->dev, sizeof(struct pcf8563),
5388c2ecf20Sopenharmony_ci				GFP_KERNEL);
5398c2ecf20Sopenharmony_ci	if (!pcf8563)
5408c2ecf20Sopenharmony_ci		return -ENOMEM;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, pcf8563);
5438c2ecf20Sopenharmony_ci	pcf8563->client = client;
5448c2ecf20Sopenharmony_ci	device_set_wakeup_capable(&client->dev, 1);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	/* Set timer to lowest frequency to save power (ref Haoyu datasheet) */
5478c2ecf20Sopenharmony_ci	buf = PCF8563_TMRC_1_60;
5488c2ecf20Sopenharmony_ci	err = pcf8563_write_block_data(client, PCF8563_REG_TMRC, 1, &buf);
5498c2ecf20Sopenharmony_ci	if (err < 0) {
5508c2ecf20Sopenharmony_ci		dev_err(&client->dev, "%s: write error\n", __func__);
5518c2ecf20Sopenharmony_ci		return err;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	/* Clear flags and disable interrupts */
5558c2ecf20Sopenharmony_ci	buf = 0;
5568c2ecf20Sopenharmony_ci	err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
5578c2ecf20Sopenharmony_ci	if (err < 0) {
5588c2ecf20Sopenharmony_ci		dev_err(&client->dev, "%s: write error\n", __func__);
5598c2ecf20Sopenharmony_ci		return err;
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	pcf8563->rtc = devm_rtc_allocate_device(&client->dev);
5638c2ecf20Sopenharmony_ci	if (IS_ERR(pcf8563->rtc))
5648c2ecf20Sopenharmony_ci		return PTR_ERR(pcf8563->rtc);
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	pcf8563->rtc->ops = &pcf8563_rtc_ops;
5678c2ecf20Sopenharmony_ci	/* the pcf8563 alarm only supports a minute accuracy */
5688c2ecf20Sopenharmony_ci	pcf8563->rtc->uie_unsupported = 1;
5698c2ecf20Sopenharmony_ci	pcf8563->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
5708c2ecf20Sopenharmony_ci	pcf8563->rtc->range_max = RTC_TIMESTAMP_END_2099;
5718c2ecf20Sopenharmony_ci	pcf8563->rtc->set_start_time = true;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	if (client->irq > 0) {
5748c2ecf20Sopenharmony_ci		err = devm_request_threaded_irq(&client->dev, client->irq,
5758c2ecf20Sopenharmony_ci				NULL, pcf8563_irq,
5768c2ecf20Sopenharmony_ci				IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW,
5778c2ecf20Sopenharmony_ci				pcf8563_driver.driver.name, client);
5788c2ecf20Sopenharmony_ci		if (err) {
5798c2ecf20Sopenharmony_ci			dev_err(&client->dev, "unable to request IRQ %d\n",
5808c2ecf20Sopenharmony_ci								client->irq);
5818c2ecf20Sopenharmony_ci			return err;
5828c2ecf20Sopenharmony_ci		}
5838c2ecf20Sopenharmony_ci	}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	err = rtc_register_device(pcf8563->rtc);
5868c2ecf20Sopenharmony_ci	if (err)
5878c2ecf20Sopenharmony_ci		return err;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci#ifdef CONFIG_COMMON_CLK
5908c2ecf20Sopenharmony_ci	/* register clk in common clk framework */
5918c2ecf20Sopenharmony_ci	pcf8563_clkout_register_clk(pcf8563);
5928c2ecf20Sopenharmony_ci#endif
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	return 0;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic const struct i2c_device_id pcf8563_id[] = {
5988c2ecf20Sopenharmony_ci	{ "pcf8563", 0 },
5998c2ecf20Sopenharmony_ci	{ "rtc8564", 0 },
6008c2ecf20Sopenharmony_ci	{ }
6018c2ecf20Sopenharmony_ci};
6028c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pcf8563_id);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
6058c2ecf20Sopenharmony_cistatic const struct of_device_id pcf8563_of_match[] = {
6068c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pcf8563" },
6078c2ecf20Sopenharmony_ci	{ .compatible = "epson,rtc8564" },
6088c2ecf20Sopenharmony_ci	{ .compatible = "microcrystal,rv8564" },
6098c2ecf20Sopenharmony_ci	{}
6108c2ecf20Sopenharmony_ci};
6118c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pcf8563_of_match);
6128c2ecf20Sopenharmony_ci#endif
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic struct i2c_driver pcf8563_driver = {
6158c2ecf20Sopenharmony_ci	.driver		= {
6168c2ecf20Sopenharmony_ci		.name	= "rtc-pcf8563",
6178c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(pcf8563_of_match),
6188c2ecf20Sopenharmony_ci	},
6198c2ecf20Sopenharmony_ci	.probe		= pcf8563_probe,
6208c2ecf20Sopenharmony_ci	.id_table	= pcf8563_id,
6218c2ecf20Sopenharmony_ci};
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cimodule_i2c_driver(pcf8563_driver);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ciMODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
6268c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
6278c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
628