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