xref: /OK3568_Linux_fs/kernel/drivers/rtc/rtc-meson.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * RTC driver for the interal RTC block in the Amlogic Meson6, Meson8,
4*4882a593Smuzhiyun  * Meson8b and Meson8m2 SoCs.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * The RTC is split in to two parts, the AHB front end and a simple serial
7*4882a593Smuzhiyun  * connection to the actual registers. This driver manages both parts.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Copyright (c) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
10*4882a593Smuzhiyun  * Copyright (c) 2015 Ben Dooks <ben.dooks@codethink.co.uk> for Codethink Ltd
11*4882a593Smuzhiyun  * Based on origin by Carlo Caione <carlo@endlessm.com>
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/bitfield.h>
15*4882a593Smuzhiyun #include <linux/delay.h>
16*4882a593Smuzhiyun #include <linux/io.h>
17*4882a593Smuzhiyun #include <linux/kernel.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/nvmem-provider.h>
20*4882a593Smuzhiyun #include <linux/of.h>
21*4882a593Smuzhiyun #include <linux/platform_device.h>
22*4882a593Smuzhiyun #include <linux/regmap.h>
23*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
24*4882a593Smuzhiyun #include <linux/reset.h>
25*4882a593Smuzhiyun #include <linux/rtc.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* registers accessed from cpu bus */
28*4882a593Smuzhiyun #define RTC_ADDR0				0x00
29*4882a593Smuzhiyun 	#define RTC_ADDR0_LINE_SCLK		BIT(0)
30*4882a593Smuzhiyun 	#define RTC_ADDR0_LINE_SEN		BIT(1)
31*4882a593Smuzhiyun 	#define RTC_ADDR0_LINE_SDI		BIT(2)
32*4882a593Smuzhiyun 	#define RTC_ADDR0_START_SER		BIT(17)
33*4882a593Smuzhiyun 	#define RTC_ADDR0_WAIT_SER		BIT(22)
34*4882a593Smuzhiyun 	#define RTC_ADDR0_DATA			GENMASK(31, 24)
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define RTC_ADDR1				0x04
37*4882a593Smuzhiyun 	#define RTC_ADDR1_SDO			BIT(0)
38*4882a593Smuzhiyun 	#define RTC_ADDR1_S_READY		BIT(1)
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define RTC_ADDR2				0x08
41*4882a593Smuzhiyun #define RTC_ADDR3				0x0c
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define RTC_REG4				0x10
44*4882a593Smuzhiyun 	#define RTC_REG4_STATIC_VALUE		GENMASK(7, 0)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /* rtc registers accessed via rtc-serial interface */
47*4882a593Smuzhiyun #define RTC_COUNTER		(0)
48*4882a593Smuzhiyun #define RTC_SEC_ADJ		(2)
49*4882a593Smuzhiyun #define RTC_REGMEM_0		(4)
50*4882a593Smuzhiyun #define RTC_REGMEM_1		(5)
51*4882a593Smuzhiyun #define RTC_REGMEM_2		(6)
52*4882a593Smuzhiyun #define RTC_REGMEM_3		(7)
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define RTC_ADDR_BITS		(3)	/* number of address bits to send */
55*4882a593Smuzhiyun #define RTC_DATA_BITS		(32)	/* number of data bits to tx/rx */
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define MESON_STATIC_BIAS_CUR	(0x5 << 1)
58*4882a593Smuzhiyun #define MESON_STATIC_VOLTAGE	(0x3 << 11)
59*4882a593Smuzhiyun #define MESON_STATIC_DEFAULT    (MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE)
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct meson_rtc {
62*4882a593Smuzhiyun 	struct rtc_device	*rtc;		/* rtc device we created */
63*4882a593Smuzhiyun 	struct device		*dev;		/* device we bound from */
64*4882a593Smuzhiyun 	struct reset_control	*reset;		/* reset source */
65*4882a593Smuzhiyun 	struct regulator	*vdd;		/* voltage input */
66*4882a593Smuzhiyun 	struct regmap		*peripheral;	/* peripheral registers */
67*4882a593Smuzhiyun 	struct regmap		*serial;	/* serial registers */
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static const struct regmap_config meson_rtc_peripheral_regmap_config = {
71*4882a593Smuzhiyun 	.name		= "peripheral-registers",
72*4882a593Smuzhiyun 	.reg_bits	= 8,
73*4882a593Smuzhiyun 	.val_bits	= 32,
74*4882a593Smuzhiyun 	.reg_stride	= 4,
75*4882a593Smuzhiyun 	.max_register	= RTC_REG4,
76*4882a593Smuzhiyun 	.fast_io	= true,
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* RTC front-end serialiser controls */
80*4882a593Smuzhiyun 
meson_rtc_sclk_pulse(struct meson_rtc * rtc)81*4882a593Smuzhiyun static void meson_rtc_sclk_pulse(struct meson_rtc *rtc)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	udelay(5);
84*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SCLK, 0);
85*4882a593Smuzhiyun 	udelay(5);
86*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SCLK,
87*4882a593Smuzhiyun 			   RTC_ADDR0_LINE_SCLK);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
meson_rtc_send_bit(struct meson_rtc * rtc,unsigned int bit)90*4882a593Smuzhiyun static void meson_rtc_send_bit(struct meson_rtc *rtc, unsigned int bit)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SDI,
93*4882a593Smuzhiyun 			   bit ? RTC_ADDR0_LINE_SDI : 0);
94*4882a593Smuzhiyun 	meson_rtc_sclk_pulse(rtc);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
meson_rtc_send_bits(struct meson_rtc * rtc,u32 data,unsigned int nr)97*4882a593Smuzhiyun static void meson_rtc_send_bits(struct meson_rtc *rtc, u32 data,
98*4882a593Smuzhiyun 				unsigned int nr)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	u32 bit = 1 << (nr - 1);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	while (bit) {
103*4882a593Smuzhiyun 		meson_rtc_send_bit(rtc, data & bit);
104*4882a593Smuzhiyun 		bit >>= 1;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
meson_rtc_set_dir(struct meson_rtc * rtc,u32 mode)108*4882a593Smuzhiyun static void meson_rtc_set_dir(struct meson_rtc *rtc, u32 mode)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SEN, 0);
111*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SDI, 0);
112*4882a593Smuzhiyun 	meson_rtc_send_bit(rtc, mode);
113*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SDI, 0);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
meson_rtc_get_data(struct meson_rtc * rtc)116*4882a593Smuzhiyun static u32 meson_rtc_get_data(struct meson_rtc *rtc)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	u32 tmp, val = 0;
119*4882a593Smuzhiyun 	int bit;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	for (bit = 0; bit < RTC_DATA_BITS; bit++) {
122*4882a593Smuzhiyun 		meson_rtc_sclk_pulse(rtc);
123*4882a593Smuzhiyun 		val <<= 1;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 		regmap_read(rtc->peripheral, RTC_ADDR1, &tmp);
126*4882a593Smuzhiyun 		val |= tmp & RTC_ADDR1_SDO;
127*4882a593Smuzhiyun 	}
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return val;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
meson_rtc_get_bus(struct meson_rtc * rtc)132*4882a593Smuzhiyun static int meson_rtc_get_bus(struct meson_rtc *rtc)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	int ret, retries;
135*4882a593Smuzhiyun 	u32 val;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/* prepare bus for transfers, set all lines low */
138*4882a593Smuzhiyun 	val = RTC_ADDR0_LINE_SDI | RTC_ADDR0_LINE_SEN | RTC_ADDR0_LINE_SCLK;
139*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, val, 0);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	for (retries = 0; retries < 3; retries++) {
142*4882a593Smuzhiyun 		/* wait for the bus to be ready */
143*4882a593Smuzhiyun 		if (!regmap_read_poll_timeout(rtc->peripheral, RTC_ADDR1, val,
144*4882a593Smuzhiyun 					      val & RTC_ADDR1_S_READY, 10,
145*4882a593Smuzhiyun 					      10000))
146*4882a593Smuzhiyun 			return 0;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 		dev_warn(rtc->dev, "failed to get bus, resetting RTC\n");
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 		ret = reset_control_reset(rtc->reset);
151*4882a593Smuzhiyun 		if (ret)
152*4882a593Smuzhiyun 			return ret;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	dev_err(rtc->dev, "bus is not ready\n");
156*4882a593Smuzhiyun 	return -ETIMEDOUT;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
meson_rtc_serial_bus_reg_read(void * context,unsigned int reg,unsigned int * data)159*4882a593Smuzhiyun static int meson_rtc_serial_bus_reg_read(void *context, unsigned int reg,
160*4882a593Smuzhiyun 					 unsigned int *data)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	struct meson_rtc *rtc = context;
163*4882a593Smuzhiyun 	int ret;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	ret = meson_rtc_get_bus(rtc);
166*4882a593Smuzhiyun 	if (ret)
167*4882a593Smuzhiyun 		return ret;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SEN,
170*4882a593Smuzhiyun 			   RTC_ADDR0_LINE_SEN);
171*4882a593Smuzhiyun 	meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS);
172*4882a593Smuzhiyun 	meson_rtc_set_dir(rtc, 0);
173*4882a593Smuzhiyun 	*data = meson_rtc_get_data(rtc);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	return 0;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
meson_rtc_serial_bus_reg_write(void * context,unsigned int reg,unsigned int data)178*4882a593Smuzhiyun static int meson_rtc_serial_bus_reg_write(void *context, unsigned int reg,
179*4882a593Smuzhiyun 					  unsigned int data)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	struct meson_rtc *rtc = context;
182*4882a593Smuzhiyun 	int ret;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	ret = meson_rtc_get_bus(rtc);
185*4882a593Smuzhiyun 	if (ret)
186*4882a593Smuzhiyun 		return ret;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0, RTC_ADDR0_LINE_SEN,
189*4882a593Smuzhiyun 			   RTC_ADDR0_LINE_SEN);
190*4882a593Smuzhiyun 	meson_rtc_send_bits(rtc, data, RTC_DATA_BITS);
191*4882a593Smuzhiyun 	meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS);
192*4882a593Smuzhiyun 	meson_rtc_set_dir(rtc, 1);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	return 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static const struct regmap_bus meson_rtc_serial_bus = {
198*4882a593Smuzhiyun 	.reg_read	= meson_rtc_serial_bus_reg_read,
199*4882a593Smuzhiyun 	.reg_write	= meson_rtc_serial_bus_reg_write,
200*4882a593Smuzhiyun };
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun static const struct regmap_config meson_rtc_serial_regmap_config = {
203*4882a593Smuzhiyun 	.name		= "serial-registers",
204*4882a593Smuzhiyun 	.reg_bits	= 4,
205*4882a593Smuzhiyun 	.reg_stride	= 1,
206*4882a593Smuzhiyun 	.val_bits	= 32,
207*4882a593Smuzhiyun 	.max_register	= RTC_REGMEM_3,
208*4882a593Smuzhiyun 	.fast_io	= false,
209*4882a593Smuzhiyun };
210*4882a593Smuzhiyun 
meson_rtc_write_static(struct meson_rtc * rtc,u32 data)211*4882a593Smuzhiyun static int meson_rtc_write_static(struct meson_rtc *rtc, u32 data)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	u32 tmp;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	regmap_write(rtc->peripheral, RTC_REG4,
216*4882a593Smuzhiyun 		     FIELD_PREP(RTC_REG4_STATIC_VALUE, (data >> 8)));
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* write the static value and start the auto serializer */
219*4882a593Smuzhiyun 	tmp = FIELD_PREP(RTC_ADDR0_DATA, (data & 0xff)) | RTC_ADDR0_START_SER;
220*4882a593Smuzhiyun 	regmap_update_bits(rtc->peripheral, RTC_ADDR0,
221*4882a593Smuzhiyun 			   RTC_ADDR0_DATA | RTC_ADDR0_START_SER, tmp);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/* wait for the auto serializer to complete */
224*4882a593Smuzhiyun 	return regmap_read_poll_timeout(rtc->peripheral, RTC_REG4, tmp,
225*4882a593Smuzhiyun 					!(tmp & RTC_ADDR0_WAIT_SER), 10,
226*4882a593Smuzhiyun 					10000);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun /* RTC interface layer functions */
230*4882a593Smuzhiyun 
meson_rtc_gettime(struct device * dev,struct rtc_time * tm)231*4882a593Smuzhiyun static int meson_rtc_gettime(struct device *dev, struct rtc_time *tm)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	struct meson_rtc *rtc = dev_get_drvdata(dev);
234*4882a593Smuzhiyun 	u32 time;
235*4882a593Smuzhiyun 	int ret;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	ret = regmap_read(rtc->serial, RTC_COUNTER, &time);
238*4882a593Smuzhiyun 	if (!ret)
239*4882a593Smuzhiyun 		rtc_time64_to_tm(time, tm);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	return ret;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun 
meson_rtc_settime(struct device * dev,struct rtc_time * tm)244*4882a593Smuzhiyun static int meson_rtc_settime(struct device *dev, struct rtc_time *tm)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	struct meson_rtc *rtc = dev_get_drvdata(dev);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	return regmap_write(rtc->serial, RTC_COUNTER, rtc_tm_to_time64(tm));
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun static const struct rtc_class_ops meson_rtc_ops = {
252*4882a593Smuzhiyun 	.read_time	= meson_rtc_gettime,
253*4882a593Smuzhiyun 	.set_time	= meson_rtc_settime,
254*4882a593Smuzhiyun };
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun /* NVMEM interface layer functions */
257*4882a593Smuzhiyun 
meson_rtc_regmem_read(void * context,unsigned int offset,void * buf,size_t bytes)258*4882a593Smuzhiyun static int meson_rtc_regmem_read(void *context, unsigned int offset,
259*4882a593Smuzhiyun 				 void *buf, size_t bytes)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	struct meson_rtc *rtc = context;
262*4882a593Smuzhiyun 	unsigned int read_offset, read_size;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	read_offset = RTC_REGMEM_0 + (offset / 4);
265*4882a593Smuzhiyun 	read_size = bytes / 4;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return regmap_bulk_read(rtc->serial, read_offset, buf, read_size);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
meson_rtc_regmem_write(void * context,unsigned int offset,void * buf,size_t bytes)270*4882a593Smuzhiyun static int meson_rtc_regmem_write(void *context, unsigned int offset,
271*4882a593Smuzhiyun 				  void *buf, size_t bytes)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	struct meson_rtc *rtc = context;
274*4882a593Smuzhiyun 	unsigned int write_offset, write_size;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	write_offset = RTC_REGMEM_0 + (offset / 4);
277*4882a593Smuzhiyun 	write_size = bytes / 4;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	return regmap_bulk_write(rtc->serial, write_offset, buf, write_size);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
meson_rtc_probe(struct platform_device * pdev)282*4882a593Smuzhiyun static int meson_rtc_probe(struct platform_device *pdev)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun 	struct nvmem_config meson_rtc_nvmem_config = {
285*4882a593Smuzhiyun 		.name = "meson-rtc-regmem",
286*4882a593Smuzhiyun 		.type = NVMEM_TYPE_BATTERY_BACKED,
287*4882a593Smuzhiyun 		.word_size = 4,
288*4882a593Smuzhiyun 		.stride = 4,
289*4882a593Smuzhiyun 		.size = 4 * 4,
290*4882a593Smuzhiyun 		.reg_read = meson_rtc_regmem_read,
291*4882a593Smuzhiyun 		.reg_write = meson_rtc_regmem_write,
292*4882a593Smuzhiyun 	};
293*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
294*4882a593Smuzhiyun 	struct meson_rtc *rtc;
295*4882a593Smuzhiyun 	void __iomem *base;
296*4882a593Smuzhiyun 	int ret;
297*4882a593Smuzhiyun 	u32 tm;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	rtc = devm_kzalloc(dev, sizeof(struct meson_rtc), GFP_KERNEL);
300*4882a593Smuzhiyun 	if (!rtc)
301*4882a593Smuzhiyun 		return -ENOMEM;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	rtc->rtc = devm_rtc_allocate_device(dev);
304*4882a593Smuzhiyun 	if (IS_ERR(rtc->rtc))
305*4882a593Smuzhiyun 		return PTR_ERR(rtc->rtc);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	platform_set_drvdata(pdev, rtc);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	rtc->dev = dev;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	rtc->rtc->ops = &meson_rtc_ops;
312*4882a593Smuzhiyun 	rtc->rtc->range_max = U32_MAX;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	base = devm_platform_ioremap_resource(pdev, 0);
315*4882a593Smuzhiyun 	if (IS_ERR(base))
316*4882a593Smuzhiyun 		return PTR_ERR(base);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	rtc->peripheral = devm_regmap_init_mmio(dev, base,
319*4882a593Smuzhiyun 					&meson_rtc_peripheral_regmap_config);
320*4882a593Smuzhiyun 	if (IS_ERR(rtc->peripheral)) {
321*4882a593Smuzhiyun 		dev_err(dev, "failed to create peripheral regmap\n");
322*4882a593Smuzhiyun 		return PTR_ERR(rtc->peripheral);
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	rtc->reset = devm_reset_control_get(dev, NULL);
326*4882a593Smuzhiyun 	if (IS_ERR(rtc->reset)) {
327*4882a593Smuzhiyun 		dev_err(dev, "missing reset line\n");
328*4882a593Smuzhiyun 		return PTR_ERR(rtc->reset);
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	rtc->vdd = devm_regulator_get(dev, "vdd");
332*4882a593Smuzhiyun 	if (IS_ERR(rtc->vdd)) {
333*4882a593Smuzhiyun 		dev_err(dev, "failed to get the vdd-supply\n");
334*4882a593Smuzhiyun 		return PTR_ERR(rtc->vdd);
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	ret = regulator_enable(rtc->vdd);
338*4882a593Smuzhiyun 	if (ret) {
339*4882a593Smuzhiyun 		dev_err(dev, "failed to enable vdd-supply\n");
340*4882a593Smuzhiyun 		return ret;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	ret = meson_rtc_write_static(rtc, MESON_STATIC_DEFAULT);
344*4882a593Smuzhiyun 	if (ret) {
345*4882a593Smuzhiyun 		dev_err(dev, "failed to set static values\n");
346*4882a593Smuzhiyun 		goto out_disable_vdd;
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	rtc->serial = devm_regmap_init(dev, &meson_rtc_serial_bus, rtc,
350*4882a593Smuzhiyun 				       &meson_rtc_serial_regmap_config);
351*4882a593Smuzhiyun 	if (IS_ERR(rtc->serial)) {
352*4882a593Smuzhiyun 		dev_err(dev, "failed to create serial regmap\n");
353*4882a593Smuzhiyun 		ret = PTR_ERR(rtc->serial);
354*4882a593Smuzhiyun 		goto out_disable_vdd;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	/*
358*4882a593Smuzhiyun 	 * check if we can read RTC counter, if not then the RTC is probably
359*4882a593Smuzhiyun 	 * not functional. If it isn't probably best to not bind.
360*4882a593Smuzhiyun 	 */
361*4882a593Smuzhiyun 	ret = regmap_read(rtc->serial, RTC_COUNTER, &tm);
362*4882a593Smuzhiyun 	if (ret) {
363*4882a593Smuzhiyun 		dev_err(dev, "cannot read RTC counter, RTC not functional\n");
364*4882a593Smuzhiyun 		goto out_disable_vdd;
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	meson_rtc_nvmem_config.priv = rtc;
368*4882a593Smuzhiyun 	ret = rtc_nvmem_register(rtc->rtc, &meson_rtc_nvmem_config);
369*4882a593Smuzhiyun 	if (ret)
370*4882a593Smuzhiyun 		goto out_disable_vdd;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	ret = rtc_register_device(rtc->rtc);
373*4882a593Smuzhiyun 	if (ret)
374*4882a593Smuzhiyun 		goto out_disable_vdd;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	return 0;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun out_disable_vdd:
379*4882a593Smuzhiyun 	regulator_disable(rtc->vdd);
380*4882a593Smuzhiyun 	return ret;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun static const struct of_device_id meson_rtc_dt_match[] = {
384*4882a593Smuzhiyun 	{ .compatible = "amlogic,meson6-rtc", },
385*4882a593Smuzhiyun 	{ .compatible = "amlogic,meson8-rtc", },
386*4882a593Smuzhiyun 	{ .compatible = "amlogic,meson8b-rtc", },
387*4882a593Smuzhiyun 	{ .compatible = "amlogic,meson8m2-rtc", },
388*4882a593Smuzhiyun 	{ },
389*4882a593Smuzhiyun };
390*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, meson_rtc_dt_match);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static struct platform_driver meson_rtc_driver = {
393*4882a593Smuzhiyun 	.probe		= meson_rtc_probe,
394*4882a593Smuzhiyun 	.driver		= {
395*4882a593Smuzhiyun 		.name		= "meson-rtc",
396*4882a593Smuzhiyun 		.of_match_table	= of_match_ptr(meson_rtc_dt_match),
397*4882a593Smuzhiyun 	},
398*4882a593Smuzhiyun };
399*4882a593Smuzhiyun module_platform_driver(meson_rtc_driver);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun MODULE_DESCRIPTION("Amlogic Meson RTC Driver");
402*4882a593Smuzhiyun MODULE_AUTHOR("Ben Dooks <ben.doosk@codethink.co.uk>");
403*4882a593Smuzhiyun MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
404*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
405*4882a593Smuzhiyun MODULE_ALIAS("platform:meson-rtc");
406