xref: /openbmc/linux/drivers/rtc/rtc-pcf85063.c (revision 060f35a317ef09101b128f399dce7ed13d019461)
1de311aa8SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0
2796b7abbSSøren Andersen /*
3796b7abbSSøren Andersen  * An I2C driver for the PCF85063 RTC
4796b7abbSSøren Andersen  * Copyright 2014 Rose Technology
5796b7abbSSøren Andersen  *
6796b7abbSSøren Andersen  * Author: Søren Andersen <san@rosetechnology.dk>
7796b7abbSSøren Andersen  * Maintainers: http://www.nslu2-linux.org/
85b3a3adeSAlexandre Belloni  *
95b3a3adeSAlexandre Belloni  * Copyright (C) 2019 Micro Crystal AG
105b3a3adeSAlexandre Belloni  * Author: Alexandre Belloni <alexandre.belloni@bootlin.com>
11796b7abbSSøren Andersen  */
128c229ab6SMichael McCormick #include <linux/clk-provider.h>
13796b7abbSSøren Andersen #include <linux/i2c.h>
14796b7abbSSøren Andersen #include <linux/bcd.h>
15796b7abbSSøren Andersen #include <linux/rtc.h>
16796b7abbSSøren Andersen #include <linux/module.h>
1748144c28SRob Herring #include <linux/of.h>
1805cb3a56SAlexandre Belloni #include <linux/pm_wakeirq.h>
19e89b60d0SAlexandre Belloni #include <linux/regmap.h>
20796b7abbSSøren Andersen 
210d981f81SChris DeBruin /*
220d981f81SChris DeBruin  * Information for this driver was pulled from the following datasheets.
230d981f81SChris DeBruin  *
24663bff17SFabio Estevam  *  https://www.nxp.com/docs/en/data-sheet/PCF85063A.pdf
25663bff17SFabio Estevam  *  https://www.nxp.com/docs/en/data-sheet/PCF85063TP.pdf
260d981f81SChris DeBruin  *
2798c25b80SFabio Estevam  *  PCF85063A -- Rev. 7 — 30 March 2018
280d981f81SChris DeBruin  *  PCF85063TP -- Rev. 4 — 6 May 2015
295b3a3adeSAlexandre Belloni  *
305b3a3adeSAlexandre Belloni  *  https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-8263-C7_App-Manual.pdf
315b3a3adeSAlexandre Belloni  *  RV8263 -- Rev. 1.0 — January 2019
320d981f81SChris DeBruin  */
330d981f81SChris DeBruin 
34796b7abbSSøren Andersen #define PCF85063_REG_CTRL1		0x00 /* status */
35bbb43838SSam Ravnborg #define PCF85063_REG_CTRL1_CAP_SEL	BIT(0)
3631d4d33eSJuergen Borleis #define PCF85063_REG_CTRL1_STOP		BIT(5)
379f08c9edSPhil Elwell #define PCF85063_REG_CTRL1_EXT_TEST	BIT(7)
38796b7abbSSøren Andersen 
3905cb3a56SAlexandre Belloni #define PCF85063_REG_CTRL2		0x01
4005cb3a56SAlexandre Belloni #define PCF85063_CTRL2_AF		BIT(6)
4105cb3a56SAlexandre Belloni #define PCF85063_CTRL2_AIE		BIT(7)
4205cb3a56SAlexandre Belloni 
4385370d3dSAlexandre Belloni #define PCF85063_REG_OFFSET		0x02
4485370d3dSAlexandre Belloni #define PCF85063_OFFSET_SIGN_BIT	6	/* 2's complement sign bit */
4585370d3dSAlexandre Belloni #define PCF85063_OFFSET_MODE		BIT(7)
4685370d3dSAlexandre Belloni #define PCF85063_OFFSET_STEP0		4340
4785370d3dSAlexandre Belloni #define PCF85063_OFFSET_STEP1		4069
4885370d3dSAlexandre Belloni 
498c229ab6SMichael McCormick #define PCF85063_REG_CLKO_F_MASK	0x07 /* frequency mask */
508c229ab6SMichael McCormick #define PCF85063_REG_CLKO_F_32768HZ	0x00
518c229ab6SMichael McCormick #define PCF85063_REG_CLKO_F_OFF		0x07
528c229ab6SMichael McCormick 
53fadfd092SAlexandre Belloni #define PCF85063_REG_RAM		0x03
54fadfd092SAlexandre Belloni 
55796b7abbSSøren Andersen #define PCF85063_REG_SC			0x04 /* datetime */
566cc4c8b1SJuergen Borleis #define PCF85063_REG_SC_OS		0x80
57796b7abbSSøren Andersen 
5805cb3a56SAlexandre Belloni #define PCF85063_REG_ALM_S		0x0b
5905cb3a56SAlexandre Belloni #define PCF85063_AEN			BIT(7)
6005cb3a56SAlexandre Belloni 
610e2e8777SAlexandre Belloni struct pcf85063_config {
620e2e8777SAlexandre Belloni 	struct regmap_config regmap;
6305cb3a56SAlexandre Belloni 	unsigned has_alarms:1;
645b3a3adeSAlexandre Belloni 	unsigned force_cap_7000:1;
650e2e8777SAlexandre Belloni };
660e2e8777SAlexandre Belloni 
67e89b60d0SAlexandre Belloni struct pcf85063 {
68e89b60d0SAlexandre Belloni 	struct rtc_device	*rtc;
69e89b60d0SAlexandre Belloni 	struct regmap		*regmap;
708c229ab6SMichael McCormick #ifdef CONFIG_COMMON_CLK
718c229ab6SMichael McCormick 	struct clk_hw		clkout_hw;
728c229ab6SMichael McCormick #endif
73e89b60d0SAlexandre Belloni };
740d981f81SChris DeBruin 
pcf85063_rtc_read_time(struct device * dev,struct rtc_time * tm)75965271dfSAlexandre Belloni static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
76796b7abbSSøren Andersen {
77e89b60d0SAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
787b576848SJuergen Borleis 	int rc;
797b576848SJuergen Borleis 	u8 regs[7];
80796b7abbSSøren Andersen 
817b576848SJuergen Borleis 	/*
827b576848SJuergen Borleis 	 * while reading, the time/date registers are blocked and not updated
837b576848SJuergen Borleis 	 * anymore until the access is finished. To not lose a second
847b576848SJuergen Borleis 	 * event, the access must be finished within one second. So, read all
857b576848SJuergen Borleis 	 * time/date registers in one turn.
867b576848SJuergen Borleis 	 */
87e89b60d0SAlexandre Belloni 	rc = regmap_bulk_read(pcf85063->regmap, PCF85063_REG_SC, regs,
88e89b60d0SAlexandre Belloni 			      sizeof(regs));
89e89b60d0SAlexandre Belloni 	if (rc)
90e89b60d0SAlexandre Belloni 		return rc;
91796b7abbSSøren Andersen 
926cc4c8b1SJuergen Borleis 	/* if the clock has lost its power it makes no sense to use its time */
936cc4c8b1SJuergen Borleis 	if (regs[0] & PCF85063_REG_SC_OS) {
94e89b60d0SAlexandre Belloni 		dev_warn(&pcf85063->rtc->dev, "Power loss detected, invalid time\n");
956cc4c8b1SJuergen Borleis 		return -EINVAL;
966cc4c8b1SJuergen Borleis 	}
976cc4c8b1SJuergen Borleis 
987b576848SJuergen Borleis 	tm->tm_sec = bcd2bin(regs[0] & 0x7F);
997b576848SJuergen Borleis 	tm->tm_min = bcd2bin(regs[1] & 0x7F);
1007b576848SJuergen Borleis 	tm->tm_hour = bcd2bin(regs[2] & 0x3F); /* rtc hr 0-23 */
1017b576848SJuergen Borleis 	tm->tm_mday = bcd2bin(regs[3] & 0x3F);
1027b576848SJuergen Borleis 	tm->tm_wday = regs[4] & 0x07;
1037b576848SJuergen Borleis 	tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
1047b576848SJuergen Borleis 	tm->tm_year = bcd2bin(regs[6]);
105c421ce72SAlexandre Belloni 	tm->tm_year += 100;
106796b7abbSSøren Andersen 
1070a6b8886SAlexandre Belloni 	return 0;
108796b7abbSSøren Andersen }
109796b7abbSSøren Andersen 
pcf85063_rtc_set_time(struct device * dev,struct rtc_time * tm)110965271dfSAlexandre Belloni static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
111796b7abbSSøren Andersen {
112e89b60d0SAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
11331d4d33eSJuergen Borleis 	int rc;
1140d981f81SChris DeBruin 	u8 regs[7];
115796b7abbSSøren Andersen 
11631d4d33eSJuergen Borleis 	/*
11731d4d33eSJuergen Borleis 	 * to accurately set the time, reset the divider chain and keep it in
11831d4d33eSJuergen Borleis 	 * reset state until all time/date registers are written
11931d4d33eSJuergen Borleis 	 */
120e89b60d0SAlexandre Belloni 	rc = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
1219f08c9edSPhil Elwell 				PCF85063_REG_CTRL1_EXT_TEST |
122e89b60d0SAlexandre Belloni 				PCF85063_REG_CTRL1_STOP,
123e89b60d0SAlexandre Belloni 				PCF85063_REG_CTRL1_STOP);
124e89b60d0SAlexandre Belloni 	if (rc)
12531d4d33eSJuergen Borleis 		return rc;
126796b7abbSSøren Andersen 
127796b7abbSSøren Andersen 	/* hours, minutes and seconds */
12831d4d33eSJuergen Borleis 	regs[0] = bin2bcd(tm->tm_sec) & 0x7F; /* clear OS flag */
129796b7abbSSøren Andersen 
13031d4d33eSJuergen Borleis 	regs[1] = bin2bcd(tm->tm_min);
13131d4d33eSJuergen Borleis 	regs[2] = bin2bcd(tm->tm_hour);
132796b7abbSSøren Andersen 
133796b7abbSSøren Andersen 	/* Day of month, 1 - 31 */
13431d4d33eSJuergen Borleis 	regs[3] = bin2bcd(tm->tm_mday);
135796b7abbSSøren Andersen 
136796b7abbSSøren Andersen 	/* Day, 0 - 6 */
13731d4d33eSJuergen Borleis 	regs[4] = tm->tm_wday & 0x07;
138796b7abbSSøren Andersen 
139796b7abbSSøren Andersen 	/* month, 1 - 12 */
14031d4d33eSJuergen Borleis 	regs[5] = bin2bcd(tm->tm_mon + 1);
141796b7abbSSøren Andersen 
142796b7abbSSøren Andersen 	/* year and century */
143c421ce72SAlexandre Belloni 	regs[6] = bin2bcd(tm->tm_year - 100);
144796b7abbSSøren Andersen 
14531d4d33eSJuergen Borleis 	/* write all registers at once */
146e89b60d0SAlexandre Belloni 	rc = regmap_bulk_write(pcf85063->regmap, PCF85063_REG_SC,
147e89b60d0SAlexandre Belloni 			       regs, sizeof(regs));
148e89b60d0SAlexandre Belloni 	if (rc)
14931d4d33eSJuergen Borleis 		return rc;
150796b7abbSSøren Andersen 
1510d981f81SChris DeBruin 	/*
1520d981f81SChris DeBruin 	 * Write the control register as a separate action since the size of
1530d981f81SChris DeBruin 	 * the register space is different between the PCF85063TP and
1540d981f81SChris DeBruin 	 * PCF85063A devices.  The rollover point can not be used.
1550d981f81SChris DeBruin 	 */
156e89b60d0SAlexandre Belloni 	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
157e89b60d0SAlexandre Belloni 				  PCF85063_REG_CTRL1_STOP, 0);
158796b7abbSSøren Andersen }
159796b7abbSSøren Andersen 
pcf85063_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)16005cb3a56SAlexandre Belloni static int pcf85063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
16105cb3a56SAlexandre Belloni {
16205cb3a56SAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
16305cb3a56SAlexandre Belloni 	u8 buf[4];
16405cb3a56SAlexandre Belloni 	unsigned int val;
16505cb3a56SAlexandre Belloni 	int ret;
16605cb3a56SAlexandre Belloni 
16705cb3a56SAlexandre Belloni 	ret = regmap_bulk_read(pcf85063->regmap, PCF85063_REG_ALM_S,
16805cb3a56SAlexandre Belloni 			       buf, sizeof(buf));
16905cb3a56SAlexandre Belloni 	if (ret)
17005cb3a56SAlexandre Belloni 		return ret;
17105cb3a56SAlexandre Belloni 
172a6ceee26SAlexander Stein 	alrm->time.tm_sec = bcd2bin(buf[0] & 0x7f);
173a6ceee26SAlexander Stein 	alrm->time.tm_min = bcd2bin(buf[1] & 0x7f);
174a6ceee26SAlexander Stein 	alrm->time.tm_hour = bcd2bin(buf[2] & 0x3f);
175a6ceee26SAlexander Stein 	alrm->time.tm_mday = bcd2bin(buf[3] & 0x3f);
17605cb3a56SAlexandre Belloni 
17705cb3a56SAlexandre Belloni 	ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val);
17805cb3a56SAlexandre Belloni 	if (ret)
17905cb3a56SAlexandre Belloni 		return ret;
18005cb3a56SAlexandre Belloni 
18105cb3a56SAlexandre Belloni 	alrm->enabled =  !!(val & PCF85063_CTRL2_AIE);
18205cb3a56SAlexandre Belloni 
18305cb3a56SAlexandre Belloni 	return 0;
18405cb3a56SAlexandre Belloni }
18505cb3a56SAlexandre Belloni 
pcf85063_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)18605cb3a56SAlexandre Belloni static int pcf85063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
18705cb3a56SAlexandre Belloni {
18805cb3a56SAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
18905cb3a56SAlexandre Belloni 	u8 buf[5];
19005cb3a56SAlexandre Belloni 	int ret;
19105cb3a56SAlexandre Belloni 
19205cb3a56SAlexandre Belloni 	buf[0] = bin2bcd(alrm->time.tm_sec);
19305cb3a56SAlexandre Belloni 	buf[1] = bin2bcd(alrm->time.tm_min);
19405cb3a56SAlexandre Belloni 	buf[2] = bin2bcd(alrm->time.tm_hour);
19505cb3a56SAlexandre Belloni 	buf[3] = bin2bcd(alrm->time.tm_mday);
19605cb3a56SAlexandre Belloni 	buf[4] = PCF85063_AEN; /* Do not match on week day */
19705cb3a56SAlexandre Belloni 
19805cb3a56SAlexandre Belloni 	ret = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
19905cb3a56SAlexandre Belloni 				 PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF, 0);
20005cb3a56SAlexandre Belloni 	if (ret)
20105cb3a56SAlexandre Belloni 		return ret;
20205cb3a56SAlexandre Belloni 
20305cb3a56SAlexandre Belloni 	ret = regmap_bulk_write(pcf85063->regmap, PCF85063_REG_ALM_S,
20405cb3a56SAlexandre Belloni 				buf, sizeof(buf));
20505cb3a56SAlexandre Belloni 	if (ret)
20605cb3a56SAlexandre Belloni 		return ret;
20705cb3a56SAlexandre Belloni 
20805cb3a56SAlexandre Belloni 	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
20905cb3a56SAlexandre Belloni 				  PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF,
21005cb3a56SAlexandre Belloni 				  alrm->enabled ? PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF : PCF85063_CTRL2_AF);
21105cb3a56SAlexandre Belloni }
21205cb3a56SAlexandre Belloni 
pcf85063_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)21305cb3a56SAlexandre Belloni static int pcf85063_rtc_alarm_irq_enable(struct device *dev,
21405cb3a56SAlexandre Belloni 					 unsigned int enabled)
21505cb3a56SAlexandre Belloni {
21605cb3a56SAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
21705cb3a56SAlexandre Belloni 
21805cb3a56SAlexandre Belloni 	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
21905cb3a56SAlexandre Belloni 				  PCF85063_CTRL2_AIE,
22005cb3a56SAlexandre Belloni 				  enabled ? PCF85063_CTRL2_AIE : 0);
22105cb3a56SAlexandre Belloni }
22205cb3a56SAlexandre Belloni 
pcf85063_rtc_handle_irq(int irq,void * dev_id)22305cb3a56SAlexandre Belloni static irqreturn_t pcf85063_rtc_handle_irq(int irq, void *dev_id)
22405cb3a56SAlexandre Belloni {
22505cb3a56SAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_id;
22605cb3a56SAlexandre Belloni 	unsigned int val;
22705cb3a56SAlexandre Belloni 	int err;
22805cb3a56SAlexandre Belloni 
22905cb3a56SAlexandre Belloni 	err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val);
23005cb3a56SAlexandre Belloni 	if (err)
23105cb3a56SAlexandre Belloni 		return IRQ_NONE;
23205cb3a56SAlexandre Belloni 
23305cb3a56SAlexandre Belloni 	if (val & PCF85063_CTRL2_AF) {
23405cb3a56SAlexandre Belloni 		rtc_update_irq(pcf85063->rtc, 1, RTC_IRQF | RTC_AF);
23505cb3a56SAlexandre Belloni 		regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
23605cb3a56SAlexandre Belloni 				   PCF85063_CTRL2_AIE | PCF85063_CTRL2_AF,
23705cb3a56SAlexandre Belloni 				   0);
23805cb3a56SAlexandre Belloni 		return IRQ_HANDLED;
23905cb3a56SAlexandre Belloni 	}
24005cb3a56SAlexandre Belloni 
24105cb3a56SAlexandre Belloni 	return IRQ_NONE;
24205cb3a56SAlexandre Belloni }
24305cb3a56SAlexandre Belloni 
pcf85063_read_offset(struct device * dev,long * offset)24485370d3dSAlexandre Belloni static int pcf85063_read_offset(struct device *dev, long *offset)
24585370d3dSAlexandre Belloni {
24685370d3dSAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
24785370d3dSAlexandre Belloni 	long val;
24885370d3dSAlexandre Belloni 	u32 reg;
24985370d3dSAlexandre Belloni 	int ret;
25085370d3dSAlexandre Belloni 
25185370d3dSAlexandre Belloni 	ret = regmap_read(pcf85063->regmap, PCF85063_REG_OFFSET, &reg);
25285370d3dSAlexandre Belloni 	if (ret < 0)
25385370d3dSAlexandre Belloni 		return ret;
25485370d3dSAlexandre Belloni 
25585370d3dSAlexandre Belloni 	val = sign_extend32(reg & ~PCF85063_OFFSET_MODE,
25685370d3dSAlexandre Belloni 			    PCF85063_OFFSET_SIGN_BIT);
25785370d3dSAlexandre Belloni 
25885370d3dSAlexandre Belloni 	if (reg & PCF85063_OFFSET_MODE)
25985370d3dSAlexandre Belloni 		*offset = val * PCF85063_OFFSET_STEP1;
26085370d3dSAlexandre Belloni 	else
26185370d3dSAlexandre Belloni 		*offset = val * PCF85063_OFFSET_STEP0;
26285370d3dSAlexandre Belloni 
26385370d3dSAlexandre Belloni 	return 0;
26485370d3dSAlexandre Belloni }
26585370d3dSAlexandre Belloni 
pcf85063_set_offset(struct device * dev,long offset)26685370d3dSAlexandre Belloni static int pcf85063_set_offset(struct device *dev, long offset)
26785370d3dSAlexandre Belloni {
26885370d3dSAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
26985370d3dSAlexandre Belloni 	s8 mode0, mode1, reg;
27085370d3dSAlexandre Belloni 	unsigned int error0, error1;
27185370d3dSAlexandre Belloni 
27285370d3dSAlexandre Belloni 	if (offset > PCF85063_OFFSET_STEP0 * 63)
27385370d3dSAlexandre Belloni 		return -ERANGE;
27485370d3dSAlexandre Belloni 	if (offset < PCF85063_OFFSET_STEP0 * -64)
27585370d3dSAlexandre Belloni 		return -ERANGE;
27685370d3dSAlexandre Belloni 
27785370d3dSAlexandre Belloni 	mode0 = DIV_ROUND_CLOSEST(offset, PCF85063_OFFSET_STEP0);
27885370d3dSAlexandre Belloni 	mode1 = DIV_ROUND_CLOSEST(offset, PCF85063_OFFSET_STEP1);
27985370d3dSAlexandre Belloni 
28085370d3dSAlexandre Belloni 	error0 = abs(offset - (mode0 * PCF85063_OFFSET_STEP0));
28185370d3dSAlexandre Belloni 	error1 = abs(offset - (mode1 * PCF85063_OFFSET_STEP1));
28285370d3dSAlexandre Belloni 	if (mode1 > 63 || mode1 < -64 || error0 < error1)
28385370d3dSAlexandre Belloni 		reg = mode0 & ~PCF85063_OFFSET_MODE;
28485370d3dSAlexandre Belloni 	else
28585370d3dSAlexandre Belloni 		reg = mode1 | PCF85063_OFFSET_MODE;
28685370d3dSAlexandre Belloni 
28785370d3dSAlexandre Belloni 	return regmap_write(pcf85063->regmap, PCF85063_REG_OFFSET, reg);
28885370d3dSAlexandre Belloni }
28985370d3dSAlexandre Belloni 
pcf85063_ioctl(struct device * dev,unsigned int cmd,unsigned long arg)29027ff836dSAlexandre Belloni static int pcf85063_ioctl(struct device *dev, unsigned int cmd,
29127ff836dSAlexandre Belloni 			  unsigned long arg)
29227ff836dSAlexandre Belloni {
29327ff836dSAlexandre Belloni 	struct pcf85063 *pcf85063 = dev_get_drvdata(dev);
29427ff836dSAlexandre Belloni 	int status, ret = 0;
29527ff836dSAlexandre Belloni 
29627ff836dSAlexandre Belloni 	switch (cmd) {
29727ff836dSAlexandre Belloni 	case RTC_VL_READ:
29827ff836dSAlexandre Belloni 		ret = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &status);
29927ff836dSAlexandre Belloni 		if (ret < 0)
30027ff836dSAlexandre Belloni 			return ret;
30127ff836dSAlexandre Belloni 
30272e4ee63SAlexandre Belloni 		status = (status & PCF85063_REG_SC_OS) ? RTC_VL_DATA_INVALID : 0;
30327ff836dSAlexandre Belloni 
304f86dc5bdSAlexandre Belloni 		return put_user(status, (unsigned int __user *)arg);
30527ff836dSAlexandre Belloni 
30627ff836dSAlexandre Belloni 	default:
30727ff836dSAlexandre Belloni 		return -ENOIOCTLCMD;
30827ff836dSAlexandre Belloni 	}
30927ff836dSAlexandre Belloni }
31027ff836dSAlexandre Belloni 
311796b7abbSSøren Andersen static const struct rtc_class_ops pcf85063_rtc_ops = {
312796b7abbSSøren Andersen 	.read_time	= pcf85063_rtc_read_time,
31385370d3dSAlexandre Belloni 	.set_time	= pcf85063_rtc_set_time,
31485370d3dSAlexandre Belloni 	.read_offset	= pcf85063_read_offset,
31585370d3dSAlexandre Belloni 	.set_offset	= pcf85063_set_offset,
31605cb3a56SAlexandre Belloni 	.read_alarm	= pcf85063_rtc_read_alarm,
31705cb3a56SAlexandre Belloni 	.set_alarm	= pcf85063_rtc_set_alarm,
31805cb3a56SAlexandre Belloni 	.alarm_irq_enable = pcf85063_rtc_alarm_irq_enable,
31927ff836dSAlexandre Belloni 	.ioctl		= pcf85063_ioctl,
32005cb3a56SAlexandre Belloni };
32105cb3a56SAlexandre Belloni 
pcf85063_nvmem_read(void * priv,unsigned int offset,void * val,size_t bytes)322fadfd092SAlexandre Belloni static int pcf85063_nvmem_read(void *priv, unsigned int offset,
323fadfd092SAlexandre Belloni 			       void *val, size_t bytes)
324fadfd092SAlexandre Belloni {
325*9adefa7bSOleksij Rempel 	unsigned int tmp;
326*9adefa7bSOleksij Rempel 	int ret;
327*9adefa7bSOleksij Rempel 
328*9adefa7bSOleksij Rempel 	ret = regmap_read(priv, PCF85063_REG_RAM, &tmp);
329*9adefa7bSOleksij Rempel 	if (ret < 0)
330*9adefa7bSOleksij Rempel 		return ret;
331*9adefa7bSOleksij Rempel 
332*9adefa7bSOleksij Rempel 	*(u8 *)val = tmp;
333*9adefa7bSOleksij Rempel 
334*9adefa7bSOleksij Rempel 	return 0;
335fadfd092SAlexandre Belloni }
336fadfd092SAlexandre Belloni 
pcf85063_nvmem_write(void * priv,unsigned int offset,void * val,size_t bytes)337fadfd092SAlexandre Belloni static int pcf85063_nvmem_write(void *priv, unsigned int offset,
338fadfd092SAlexandre Belloni 				void *val, size_t bytes)
339fadfd092SAlexandre Belloni {
340fadfd092SAlexandre Belloni 	return regmap_write(priv, PCF85063_REG_RAM, *(u8 *)val);
341fadfd092SAlexandre Belloni }
342fadfd092SAlexandre Belloni 
pcf85063_load_capacitance(struct pcf85063 * pcf85063,const struct device_node * np,unsigned int force_cap)343e89b60d0SAlexandre Belloni static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
3445b3a3adeSAlexandre Belloni 				     const struct device_node *np,
3455b3a3adeSAlexandre Belloni 				     unsigned int force_cap)
346bbb43838SSam Ravnborg {
347e89b60d0SAlexandre Belloni 	u32 load = 7000;
348e89b60d0SAlexandre Belloni 	u8 reg = 0;
349bbb43838SSam Ravnborg 
3505b3a3adeSAlexandre Belloni 	if (force_cap)
3515b3a3adeSAlexandre Belloni 		load = force_cap;
3525b3a3adeSAlexandre Belloni 	else
353e89b60d0SAlexandre Belloni 		of_property_read_u32(np, "quartz-load-femtofarads", &load);
3545b3a3adeSAlexandre Belloni 
355bbb43838SSam Ravnborg 	switch (load) {
356bbb43838SSam Ravnborg 	default:
357e89b60d0SAlexandre Belloni 		dev_warn(&pcf85063->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",
358bbb43838SSam Ravnborg 			 load);
359df561f66SGustavo A. R. Silva 		fallthrough;
360bbb43838SSam Ravnborg 	case 7000:
361bbb43838SSam Ravnborg 		break;
362bbb43838SSam Ravnborg 	case 12500:
363e89b60d0SAlexandre Belloni 		reg = PCF85063_REG_CTRL1_CAP_SEL;
364bbb43838SSam Ravnborg 		break;
365bbb43838SSam Ravnborg 	}
366bbb43838SSam Ravnborg 
367e89b60d0SAlexandre Belloni 	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
368e89b60d0SAlexandre Belloni 				  PCF85063_REG_CTRL1_CAP_SEL, reg);
369bbb43838SSam Ravnborg }
370bbb43838SSam Ravnborg 
3718c229ab6SMichael McCormick #ifdef CONFIG_COMMON_CLK
3728c229ab6SMichael McCormick /*
3738c229ab6SMichael McCormick  * Handling of the clkout
3748c229ab6SMichael McCormick  */
3758c229ab6SMichael McCormick 
3768c229ab6SMichael McCormick #define clkout_hw_to_pcf85063(_hw) container_of(_hw, struct pcf85063, clkout_hw)
3778c229ab6SMichael McCormick 
3788c229ab6SMichael McCormick static int clkout_rates[] = {
3798c229ab6SMichael McCormick 	32768,
3808c229ab6SMichael McCormick 	16384,
3818c229ab6SMichael McCormick 	8192,
3828c229ab6SMichael McCormick 	4096,
3838c229ab6SMichael McCormick 	2048,
3848c229ab6SMichael McCormick 	1024,
3858c229ab6SMichael McCormick 	1,
3868c229ab6SMichael McCormick 	0
3878c229ab6SMichael McCormick };
3888c229ab6SMichael McCormick 
pcf85063_clkout_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)3898c229ab6SMichael McCormick static unsigned long pcf85063_clkout_recalc_rate(struct clk_hw *hw,
3908c229ab6SMichael McCormick 						 unsigned long parent_rate)
3918c229ab6SMichael McCormick {
3928c229ab6SMichael McCormick 	struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
3938c229ab6SMichael McCormick 	unsigned int buf;
3948c229ab6SMichael McCormick 	int ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf);
3958c229ab6SMichael McCormick 
3968c229ab6SMichael McCormick 	if (ret < 0)
3978c229ab6SMichael McCormick 		return 0;
3988c229ab6SMichael McCormick 
3998c229ab6SMichael McCormick 	buf &= PCF85063_REG_CLKO_F_MASK;
4008c229ab6SMichael McCormick 	return clkout_rates[buf];
4018c229ab6SMichael McCormick }
4028c229ab6SMichael McCormick 
pcf85063_clkout_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)4038c229ab6SMichael McCormick static long pcf85063_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
4048c229ab6SMichael McCormick 				       unsigned long *prate)
4058c229ab6SMichael McCormick {
4068c229ab6SMichael McCormick 	int i;
4078c229ab6SMichael McCormick 
4088c229ab6SMichael McCormick 	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
4098c229ab6SMichael McCormick 		if (clkout_rates[i] <= rate)
4108c229ab6SMichael McCormick 			return clkout_rates[i];
4118c229ab6SMichael McCormick 
4128c229ab6SMichael McCormick 	return 0;
4138c229ab6SMichael McCormick }
4148c229ab6SMichael McCormick 
pcf85063_clkout_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)4158c229ab6SMichael McCormick static int pcf85063_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
4168c229ab6SMichael McCormick 				    unsigned long parent_rate)
4178c229ab6SMichael McCormick {
4188c229ab6SMichael McCormick 	struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
4198c229ab6SMichael McCormick 	int i;
4208c229ab6SMichael McCormick 
4218c229ab6SMichael McCormick 	for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
4228c229ab6SMichael McCormick 		if (clkout_rates[i] == rate)
4238c229ab6SMichael McCormick 			return regmap_update_bits(pcf85063->regmap,
4248c229ab6SMichael McCormick 				PCF85063_REG_CTRL2,
4258c229ab6SMichael McCormick 				PCF85063_REG_CLKO_F_MASK, i);
4268c229ab6SMichael McCormick 
4278c229ab6SMichael McCormick 	return -EINVAL;
4288c229ab6SMichael McCormick }
4298c229ab6SMichael McCormick 
pcf85063_clkout_control(struct clk_hw * hw,bool enable)4308c229ab6SMichael McCormick static int pcf85063_clkout_control(struct clk_hw *hw, bool enable)
4318c229ab6SMichael McCormick {
4328c229ab6SMichael McCormick 	struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
4338c229ab6SMichael McCormick 	unsigned int buf;
4348c229ab6SMichael McCormick 	int ret;
4358c229ab6SMichael McCormick 
436c2d12e85SAlexandre Belloni 	ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf);
4378c229ab6SMichael McCormick 	if (ret < 0)
4388c229ab6SMichael McCormick 		return ret;
4398c229ab6SMichael McCormick 	buf &= PCF85063_REG_CLKO_F_MASK;
4408c229ab6SMichael McCormick 
4418c229ab6SMichael McCormick 	if (enable) {
4428c229ab6SMichael McCormick 		if (buf == PCF85063_REG_CLKO_F_OFF)
4438c229ab6SMichael McCormick 			buf = PCF85063_REG_CLKO_F_32768HZ;
4448c229ab6SMichael McCormick 		else
4458c229ab6SMichael McCormick 			return 0;
4468c229ab6SMichael McCormick 	} else {
4478c229ab6SMichael McCormick 		if (buf != PCF85063_REG_CLKO_F_OFF)
4488c229ab6SMichael McCormick 			buf = PCF85063_REG_CLKO_F_OFF;
4498c229ab6SMichael McCormick 		else
4508c229ab6SMichael McCormick 			return 0;
4518c229ab6SMichael McCormick 	}
4528c229ab6SMichael McCormick 
4538c229ab6SMichael McCormick 	return regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL2,
4548c229ab6SMichael McCormick 					PCF85063_REG_CLKO_F_MASK, buf);
4558c229ab6SMichael McCormick }
4568c229ab6SMichael McCormick 
pcf85063_clkout_prepare(struct clk_hw * hw)4578c229ab6SMichael McCormick static int pcf85063_clkout_prepare(struct clk_hw *hw)
4588c229ab6SMichael McCormick {
4598c229ab6SMichael McCormick 	return pcf85063_clkout_control(hw, 1);
4608c229ab6SMichael McCormick }
4618c229ab6SMichael McCormick 
pcf85063_clkout_unprepare(struct clk_hw * hw)4628c229ab6SMichael McCormick static void pcf85063_clkout_unprepare(struct clk_hw *hw)
4638c229ab6SMichael McCormick {
4648c229ab6SMichael McCormick 	pcf85063_clkout_control(hw, 0);
4658c229ab6SMichael McCormick }
4668c229ab6SMichael McCormick 
pcf85063_clkout_is_prepared(struct clk_hw * hw)4678c229ab6SMichael McCormick static int pcf85063_clkout_is_prepared(struct clk_hw *hw)
4688c229ab6SMichael McCormick {
4698c229ab6SMichael McCormick 	struct pcf85063 *pcf85063 = clkout_hw_to_pcf85063(hw);
4708c229ab6SMichael McCormick 	unsigned int buf;
4718c229ab6SMichael McCormick 	int ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf);
4728c229ab6SMichael McCormick 
4738c229ab6SMichael McCormick 	if (ret < 0)
4748c229ab6SMichael McCormick 		return 0;
4758c229ab6SMichael McCormick 
4768c229ab6SMichael McCormick 	return (buf & PCF85063_REG_CLKO_F_MASK) != PCF85063_REG_CLKO_F_OFF;
4778c229ab6SMichael McCormick }
4788c229ab6SMichael McCormick 
4798c229ab6SMichael McCormick static const struct clk_ops pcf85063_clkout_ops = {
4808c229ab6SMichael McCormick 	.prepare = pcf85063_clkout_prepare,
4818c229ab6SMichael McCormick 	.unprepare = pcf85063_clkout_unprepare,
4828c229ab6SMichael McCormick 	.is_prepared = pcf85063_clkout_is_prepared,
4838c229ab6SMichael McCormick 	.recalc_rate = pcf85063_clkout_recalc_rate,
4848c229ab6SMichael McCormick 	.round_rate = pcf85063_clkout_round_rate,
4858c229ab6SMichael McCormick 	.set_rate = pcf85063_clkout_set_rate,
4868c229ab6SMichael McCormick };
4878c229ab6SMichael McCormick 
pcf85063_clkout_register_clk(struct pcf85063 * pcf85063)4888c229ab6SMichael McCormick static struct clk *pcf85063_clkout_register_clk(struct pcf85063 *pcf85063)
4898c229ab6SMichael McCormick {
4908c229ab6SMichael McCormick 	struct clk *clk;
4918c229ab6SMichael McCormick 	struct clk_init_data init;
49203531606SFrancois Gervais 	struct device_node *node = pcf85063->rtc->dev.parent->of_node;
4934c8a7b80SAlexander Stein 	struct device_node *fixed_clock;
4944c8a7b80SAlexander Stein 
4954c8a7b80SAlexander Stein 	fixed_clock = of_get_child_by_name(node, "clock");
4964c8a7b80SAlexander Stein 	if (fixed_clock) {
4974c8a7b80SAlexander Stein 		/*
4984c8a7b80SAlexander Stein 		 * skip registering square wave clock when a fixed
4994c8a7b80SAlexander Stein 		 * clock has been registered. The fixed clock is
5004c8a7b80SAlexander Stein 		 * registered automatically when being referenced.
5014c8a7b80SAlexander Stein 		 */
5024c8a7b80SAlexander Stein 		of_node_put(fixed_clock);
5034c8a7b80SAlexander Stein 		return NULL;
5044c8a7b80SAlexander Stein 	}
5058c229ab6SMichael McCormick 
5068c229ab6SMichael McCormick 	init.name = "pcf85063-clkout";
5078c229ab6SMichael McCormick 	init.ops = &pcf85063_clkout_ops;
5088c229ab6SMichael McCormick 	init.flags = 0;
5098c229ab6SMichael McCormick 	init.parent_names = NULL;
5108c229ab6SMichael McCormick 	init.num_parents = 0;
5118c229ab6SMichael McCormick 	pcf85063->clkout_hw.init = &init;
5128c229ab6SMichael McCormick 
5138c229ab6SMichael McCormick 	/* optional override of the clockname */
51403531606SFrancois Gervais 	of_property_read_string(node, "clock-output-names", &init.name);
5158c229ab6SMichael McCormick 
5168c229ab6SMichael McCormick 	/* register the clock */
5178c229ab6SMichael McCormick 	clk = devm_clk_register(&pcf85063->rtc->dev, &pcf85063->clkout_hw);
5188c229ab6SMichael McCormick 
5198c229ab6SMichael McCormick 	if (!IS_ERR(clk))
52003531606SFrancois Gervais 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
5218c229ab6SMichael McCormick 
5228c229ab6SMichael McCormick 	return clk;
5238c229ab6SMichael McCormick }
5248c229ab6SMichael McCormick #endif
5258c229ab6SMichael McCormick 
5265789837cSBiju Das static const struct pcf85063_config config_pcf85063 = {
5275789837cSBiju Das 	.regmap = {
5285789837cSBiju Das 		.reg_bits = 8,
5295789837cSBiju Das 		.val_bits = 8,
5305789837cSBiju Das 		.max_register = 0x0a,
5315789837cSBiju Das 	},
5321c1b3098SMarc Ferland };
5331c1b3098SMarc Ferland 
5345789837cSBiju Das static const struct pcf85063_config config_pcf85063tp = {
5350e2e8777SAlexandre Belloni 	.regmap = {
5360e2e8777SAlexandre Belloni 		.reg_bits = 8,
5370e2e8777SAlexandre Belloni 		.val_bits = 8,
5380e2e8777SAlexandre Belloni 		.max_register = 0x0a,
5390e2e8777SAlexandre Belloni 	},
5405789837cSBiju Das };
5415789837cSBiju Das 
5425789837cSBiju Das static const struct pcf85063_config config_pcf85063a = {
5431c1b3098SMarc Ferland 	.regmap = {
5441c1b3098SMarc Ferland 		.reg_bits = 8,
5451c1b3098SMarc Ferland 		.val_bits = 8,
5461c1b3098SMarc Ferland 		.max_register = 0x11,
5471c1b3098SMarc Ferland 	},
5481c1b3098SMarc Ferland 	.has_alarms = 1,
5495789837cSBiju Das };
5505789837cSBiju Das 
5515789837cSBiju Das static const struct pcf85063_config config_rv8263 = {
5521c1b3098SMarc Ferland 	.regmap = {
5531c1b3098SMarc Ferland 		.reg_bits = 8,
5541c1b3098SMarc Ferland 		.val_bits = 8,
5551c1b3098SMarc Ferland 		.max_register = 0x11,
5561c1b3098SMarc Ferland 	},
5571c1b3098SMarc Ferland 	.has_alarms = 1,
5581c1b3098SMarc Ferland 	.force_cap_7000 = 1,
559e89b60d0SAlexandre Belloni };
560e89b60d0SAlexandre Belloni 
pcf85063_probe(struct i2c_client * client)5610f21700aSAlexandre Belloni static int pcf85063_probe(struct i2c_client *client)
562796b7abbSSøren Andersen {
563e89b60d0SAlexandre Belloni 	struct pcf85063 *pcf85063;
564e89b60d0SAlexandre Belloni 	unsigned int tmp;
565c18b4c52SMirza Krak 	int err;
5661c1b3098SMarc Ferland 	const struct pcf85063_config *config;
567fadfd092SAlexandre Belloni 	struct nvmem_config nvmem_cfg = {
568fadfd092SAlexandre Belloni 		.name = "pcf85063_nvram",
569fadfd092SAlexandre Belloni 		.reg_read = pcf85063_nvmem_read,
570fadfd092SAlexandre Belloni 		.reg_write = pcf85063_nvmem_write,
571fadfd092SAlexandre Belloni 		.type = NVMEM_TYPE_BATTERY_BACKED,
572fadfd092SAlexandre Belloni 		.size = 1,
573fadfd092SAlexandre Belloni 	};
574796b7abbSSøren Andersen 
575796b7abbSSøren Andersen 	dev_dbg(&client->dev, "%s\n", __func__);
576796b7abbSSøren Andersen 
577e89b60d0SAlexandre Belloni 	pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063),
578e89b60d0SAlexandre Belloni 				GFP_KERNEL);
579e89b60d0SAlexandre Belloni 	if (!pcf85063)
580e89b60d0SAlexandre Belloni 		return -ENOMEM;
581e89b60d0SAlexandre Belloni 
58268c624f8SBiju Das 	config = i2c_get_match_data(client);
5831c1b3098SMarc Ferland 	if (!config)
5841c1b3098SMarc Ferland 		return -ENODEV;
5850e2e8777SAlexandre Belloni 
5860e2e8777SAlexandre Belloni 	pcf85063->regmap = devm_regmap_init_i2c(client, &config->regmap);
587e89b60d0SAlexandre Belloni 	if (IS_ERR(pcf85063->regmap))
588e89b60d0SAlexandre Belloni 		return PTR_ERR(pcf85063->regmap);
589e89b60d0SAlexandre Belloni 
590e89b60d0SAlexandre Belloni 	i2c_set_clientdata(client, pcf85063);
591e89b60d0SAlexandre Belloni 
592e89b60d0SAlexandre Belloni 	err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL1, &tmp);
593e89b60d0SAlexandre Belloni 	if (err) {
594c18b4c52SMirza Krak 		dev_err(&client->dev, "RTC chip is not present\n");
595c18b4c52SMirza Krak 		return err;
596c18b4c52SMirza Krak 	}
597c18b4c52SMirza Krak 
598e89b60d0SAlexandre Belloni 	pcf85063->rtc = devm_rtc_allocate_device(&client->dev);
599e89b60d0SAlexandre Belloni 	if (IS_ERR(pcf85063->rtc))
600e89b60d0SAlexandre Belloni 		return PTR_ERR(pcf85063->rtc);
601e89b60d0SAlexandre Belloni 
6025b3a3adeSAlexandre Belloni 	err = pcf85063_load_capacitance(pcf85063, client->dev.of_node,
6035b3a3adeSAlexandre Belloni 					config->force_cap_7000 ? 7000 : 0);
604bbb43838SSam Ravnborg 	if (err < 0)
605bbb43838SSam Ravnborg 		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
606bbb43838SSam Ravnborg 			 err);
607bbb43838SSam Ravnborg 
608e89b60d0SAlexandre Belloni 	pcf85063->rtc->ops = &pcf85063_rtc_ops;
609e89b60d0SAlexandre Belloni 	pcf85063->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
610e89b60d0SAlexandre Belloni 	pcf85063->rtc->range_max = RTC_TIMESTAMP_END_2099;
611a9f2d5bbSAlexandre Belloni 	set_bit(RTC_FEATURE_ALARM_RES_2S, pcf85063->rtc->features);
61211316c24SAlexandre Belloni 	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, pcf85063->rtc->features);
613d4eaffe2SAlexandre Belloni 	clear_bit(RTC_FEATURE_ALARM, pcf85063->rtc->features);
61405cb3a56SAlexandre Belloni 
61505cb3a56SAlexandre Belloni 	if (config->has_alarms && client->irq > 0) {
6167e815272SAlexandre Belloni 		unsigned long irqflags = IRQF_TRIGGER_LOW;
6177e815272SAlexandre Belloni 
6187e815272SAlexandre Belloni 		if (dev_fwnode(&client->dev))
6197e815272SAlexandre Belloni 			irqflags = 0;
6207e815272SAlexandre Belloni 
62105cb3a56SAlexandre Belloni 		err = devm_request_threaded_irq(&client->dev, client->irq,
62205cb3a56SAlexandre Belloni 						NULL, pcf85063_rtc_handle_irq,
6237e815272SAlexandre Belloni 						irqflags | IRQF_ONESHOT,
62405cb3a56SAlexandre Belloni 						"pcf85063", pcf85063);
62505cb3a56SAlexandre Belloni 		if (err) {
62605cb3a56SAlexandre Belloni 			dev_warn(&pcf85063->rtc->dev,
62705cb3a56SAlexandre Belloni 				 "unable to request IRQ, alarms disabled\n");
62805cb3a56SAlexandre Belloni 		} else {
629d4eaffe2SAlexandre Belloni 			set_bit(RTC_FEATURE_ALARM, pcf85063->rtc->features);
63005cb3a56SAlexandre Belloni 			device_init_wakeup(&client->dev, true);
63105cb3a56SAlexandre Belloni 			err = dev_pm_set_wake_irq(&client->dev, client->irq);
63205cb3a56SAlexandre Belloni 			if (err)
63305cb3a56SAlexandre Belloni 				dev_err(&pcf85063->rtc->dev,
63405cb3a56SAlexandre Belloni 					"failed to enable irq wake\n");
63505cb3a56SAlexandre Belloni 		}
63605cb3a56SAlexandre Belloni 	}
637796b7abbSSøren Andersen 
638fadfd092SAlexandre Belloni 	nvmem_cfg.priv = pcf85063->regmap;
6393a905c2dSBartosz Golaszewski 	devm_rtc_nvmem_register(pcf85063->rtc, &nvmem_cfg);
640fadfd092SAlexandre Belloni 
6418c229ab6SMichael McCormick #ifdef CONFIG_COMMON_CLK
6428c229ab6SMichael McCormick 	/* register clk in common clk framework */
6438c229ab6SMichael McCormick 	pcf85063_clkout_register_clk(pcf85063);
6448c229ab6SMichael McCormick #endif
6458c229ab6SMichael McCormick 
646fdcfd854SBartosz Golaszewski 	return devm_rtc_register_device(pcf85063->rtc);
647796b7abbSSøren Andersen }
648796b7abbSSøren Andersen 
6491c1b3098SMarc Ferland static const struct i2c_device_id pcf85063_ids[] = {
6505789837cSBiju Das 	{ "pca85073a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
6515789837cSBiju Das 	{ "pcf85063", .driver_data = (kernel_ulong_t)&config_pcf85063 },
6525789837cSBiju Das 	{ "pcf85063tp", .driver_data = (kernel_ulong_t)&config_pcf85063tp },
6535789837cSBiju Das 	{ "pcf85063a", .driver_data = (kernel_ulong_t)&config_pcf85063a },
6545789837cSBiju Das 	{ "rv8263", .driver_data = (kernel_ulong_t)&config_rv8263 },
6551c1b3098SMarc Ferland 	{}
6561c1b3098SMarc Ferland };
6571c1b3098SMarc Ferland MODULE_DEVICE_TABLE(i2c, pcf85063_ids);
6581c1b3098SMarc Ferland 
659796b7abbSSøren Andersen #ifdef CONFIG_OF
660796b7abbSSøren Andersen static const struct of_device_id pcf85063_of_match[] = {
6615789837cSBiju Das 	{ .compatible = "nxp,pca85073a", .data = &config_pcf85063a },
6625789837cSBiju Das 	{ .compatible = "nxp,pcf85063", .data = &config_pcf85063 },
6635789837cSBiju Das 	{ .compatible = "nxp,pcf85063tp", .data = &config_pcf85063tp },
6645789837cSBiju Das 	{ .compatible = "nxp,pcf85063a", .data = &config_pcf85063a },
6655789837cSBiju Das 	{ .compatible = "microcrystal,rv8263", .data = &config_rv8263 },
666796b7abbSSøren Andersen 	{}
667796b7abbSSøren Andersen };
668796b7abbSSøren Andersen MODULE_DEVICE_TABLE(of, pcf85063_of_match);
669796b7abbSSøren Andersen #endif
670796b7abbSSøren Andersen 
671796b7abbSSøren Andersen static struct i2c_driver pcf85063_driver = {
672796b7abbSSøren Andersen 	.driver		= {
673796b7abbSSøren Andersen 		.name	= "rtc-pcf85063",
674796b7abbSSøren Andersen 		.of_match_table = of_match_ptr(pcf85063_of_match),
675796b7abbSSøren Andersen 	},
67631b0cecbSUwe Kleine-König 	.probe		= pcf85063_probe,
6771c1b3098SMarc Ferland 	.id_table	= pcf85063_ids,
678796b7abbSSøren Andersen };
679796b7abbSSøren Andersen 
680796b7abbSSøren Andersen module_i2c_driver(pcf85063_driver);
681796b7abbSSøren Andersen 
682796b7abbSSøren Andersen MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>");
683796b7abbSSøren Andersen MODULE_DESCRIPTION("PCF85063 RTC driver");
684796b7abbSSøren Andersen MODULE_LICENSE("GPL");
685