1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2012 Avionic Design GmbH
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/bcd.h>
7*4882a593Smuzhiyun #include <linux/i2c.h>
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/rtc.h>
10*4882a593Smuzhiyun #include <linux/of.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define DRIVER_NAME "rtc-pcf8523"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define REG_CONTROL1 0x00
15*4882a593Smuzhiyun #define REG_CONTROL1_CAP_SEL (1 << 7)
16*4882a593Smuzhiyun #define REG_CONTROL1_STOP (1 << 5)
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #define REG_CONTROL3 0x02
19*4882a593Smuzhiyun #define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */
20*4882a593Smuzhiyun #define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */
21*4882a593Smuzhiyun #define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */
22*4882a593Smuzhiyun #define REG_CONTROL3_PM_MASK 0xe0
23*4882a593Smuzhiyun #define REG_CONTROL3_BLF (1 << 2) /* battery low bit, read-only */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define REG_SECONDS 0x03
26*4882a593Smuzhiyun #define REG_SECONDS_OS (1 << 7)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define REG_MINUTES 0x04
29*4882a593Smuzhiyun #define REG_HOURS 0x05
30*4882a593Smuzhiyun #define REG_DAYS 0x06
31*4882a593Smuzhiyun #define REG_WEEKDAYS 0x07
32*4882a593Smuzhiyun #define REG_MONTHS 0x08
33*4882a593Smuzhiyun #define REG_YEARS 0x09
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define REG_OFFSET 0x0e
36*4882a593Smuzhiyun #define REG_OFFSET_MODE BIT(7)
37*4882a593Smuzhiyun
pcf8523_read(struct i2c_client * client,u8 reg,u8 * valuep)38*4882a593Smuzhiyun static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun struct i2c_msg msgs[2];
41*4882a593Smuzhiyun u8 value = 0;
42*4882a593Smuzhiyun int err;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun msgs[0].addr = client->addr;
45*4882a593Smuzhiyun msgs[0].flags = 0;
46*4882a593Smuzhiyun msgs[0].len = sizeof(reg);
47*4882a593Smuzhiyun msgs[0].buf = ®
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun msgs[1].addr = client->addr;
50*4882a593Smuzhiyun msgs[1].flags = I2C_M_RD;
51*4882a593Smuzhiyun msgs[1].len = sizeof(value);
52*4882a593Smuzhiyun msgs[1].buf = &value;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
55*4882a593Smuzhiyun if (err < 0)
56*4882a593Smuzhiyun return err;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun *valuep = value;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun return 0;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
pcf8523_write(struct i2c_client * client,u8 reg,u8 value)63*4882a593Smuzhiyun static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun u8 buffer[2] = { reg, value };
66*4882a593Smuzhiyun struct i2c_msg msg;
67*4882a593Smuzhiyun int err;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun msg.addr = client->addr;
70*4882a593Smuzhiyun msg.flags = 0;
71*4882a593Smuzhiyun msg.len = sizeof(buffer);
72*4882a593Smuzhiyun msg.buf = buffer;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun err = i2c_transfer(client->adapter, &msg, 1);
75*4882a593Smuzhiyun if (err < 0)
76*4882a593Smuzhiyun return err;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun return 0;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
pcf8523_voltage_low(struct i2c_client * client)81*4882a593Smuzhiyun static int pcf8523_voltage_low(struct i2c_client *client)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun u8 value;
84*4882a593Smuzhiyun int err;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun err = pcf8523_read(client, REG_CONTROL3, &value);
87*4882a593Smuzhiyun if (err < 0)
88*4882a593Smuzhiyun return err;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun return !!(value & REG_CONTROL3_BLF);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
pcf8523_load_capacitance(struct i2c_client * client)93*4882a593Smuzhiyun static int pcf8523_load_capacitance(struct i2c_client *client)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun u32 load;
96*4882a593Smuzhiyun u8 value;
97*4882a593Smuzhiyun int err;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun err = pcf8523_read(client, REG_CONTROL1, &value);
100*4882a593Smuzhiyun if (err < 0)
101*4882a593Smuzhiyun return err;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun load = 12500;
104*4882a593Smuzhiyun of_property_read_u32(client->dev.of_node, "quartz-load-femtofarads",
105*4882a593Smuzhiyun &load);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun switch (load) {
108*4882a593Smuzhiyun default:
109*4882a593Smuzhiyun dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500",
110*4882a593Smuzhiyun load);
111*4882a593Smuzhiyun fallthrough;
112*4882a593Smuzhiyun case 12500:
113*4882a593Smuzhiyun value |= REG_CONTROL1_CAP_SEL;
114*4882a593Smuzhiyun break;
115*4882a593Smuzhiyun case 7000:
116*4882a593Smuzhiyun value &= ~REG_CONTROL1_CAP_SEL;
117*4882a593Smuzhiyun break;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun err = pcf8523_write(client, REG_CONTROL1, value);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return err;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
pcf8523_set_pm(struct i2c_client * client,u8 pm)125*4882a593Smuzhiyun static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun u8 value;
128*4882a593Smuzhiyun int err;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun err = pcf8523_read(client, REG_CONTROL3, &value);
131*4882a593Smuzhiyun if (err < 0)
132*4882a593Smuzhiyun return err;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun value = (value & ~REG_CONTROL3_PM_MASK) | pm;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun err = pcf8523_write(client, REG_CONTROL3, value);
137*4882a593Smuzhiyun if (err < 0)
138*4882a593Smuzhiyun return err;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
pcf8523_stop_rtc(struct i2c_client * client)143*4882a593Smuzhiyun static int pcf8523_stop_rtc(struct i2c_client *client)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun u8 value;
146*4882a593Smuzhiyun int err;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun err = pcf8523_read(client, REG_CONTROL1, &value);
149*4882a593Smuzhiyun if (err < 0)
150*4882a593Smuzhiyun return err;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun value |= REG_CONTROL1_STOP;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun err = pcf8523_write(client, REG_CONTROL1, value);
155*4882a593Smuzhiyun if (err < 0)
156*4882a593Smuzhiyun return err;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun return 0;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
pcf8523_start_rtc(struct i2c_client * client)161*4882a593Smuzhiyun static int pcf8523_start_rtc(struct i2c_client *client)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun u8 value;
164*4882a593Smuzhiyun int err;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun err = pcf8523_read(client, REG_CONTROL1, &value);
167*4882a593Smuzhiyun if (err < 0)
168*4882a593Smuzhiyun return err;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun value &= ~REG_CONTROL1_STOP;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun err = pcf8523_write(client, REG_CONTROL1, value);
173*4882a593Smuzhiyun if (err < 0)
174*4882a593Smuzhiyun return err;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
pcf8523_rtc_read_time(struct device * dev,struct rtc_time * tm)179*4882a593Smuzhiyun static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
182*4882a593Smuzhiyun u8 start = REG_SECONDS, regs[7];
183*4882a593Smuzhiyun struct i2c_msg msgs[2];
184*4882a593Smuzhiyun int err;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun err = pcf8523_voltage_low(client);
187*4882a593Smuzhiyun if (err < 0) {
188*4882a593Smuzhiyun return err;
189*4882a593Smuzhiyun } else if (err > 0) {
190*4882a593Smuzhiyun dev_err(dev, "low voltage detected, time is unreliable\n");
191*4882a593Smuzhiyun return -EINVAL;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun msgs[0].addr = client->addr;
195*4882a593Smuzhiyun msgs[0].flags = 0;
196*4882a593Smuzhiyun msgs[0].len = 1;
197*4882a593Smuzhiyun msgs[0].buf = &start;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun msgs[1].addr = client->addr;
200*4882a593Smuzhiyun msgs[1].flags = I2C_M_RD;
201*4882a593Smuzhiyun msgs[1].len = sizeof(regs);
202*4882a593Smuzhiyun msgs[1].buf = regs;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
205*4882a593Smuzhiyun if (err < 0)
206*4882a593Smuzhiyun return err;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (regs[0] & REG_SECONDS_OS)
209*4882a593Smuzhiyun return -EINVAL;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun tm->tm_sec = bcd2bin(regs[0] & 0x7f);
212*4882a593Smuzhiyun tm->tm_min = bcd2bin(regs[1] & 0x7f);
213*4882a593Smuzhiyun tm->tm_hour = bcd2bin(regs[2] & 0x3f);
214*4882a593Smuzhiyun tm->tm_mday = bcd2bin(regs[3] & 0x3f);
215*4882a593Smuzhiyun tm->tm_wday = regs[4] & 0x7;
216*4882a593Smuzhiyun tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
217*4882a593Smuzhiyun tm->tm_year = bcd2bin(regs[6]) + 100;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
pcf8523_rtc_set_time(struct device * dev,struct rtc_time * tm)222*4882a593Smuzhiyun static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
225*4882a593Smuzhiyun struct i2c_msg msg;
226*4882a593Smuzhiyun u8 regs[8];
227*4882a593Smuzhiyun int err;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun /*
230*4882a593Smuzhiyun * The hardware can only store values between 0 and 99 in it's YEAR
231*4882a593Smuzhiyun * register (with 99 overflowing to 0 on increment).
232*4882a593Smuzhiyun * After 2100-02-28 we could start interpreting the year to be in the
233*4882a593Smuzhiyun * interval [2100, 2199], but there is no path to switch in a smooth way
234*4882a593Smuzhiyun * because the chip handles YEAR=0x00 (and the out-of-spec
235*4882a593Smuzhiyun * YEAR=0xa0) as a leap year, but 2100 isn't.
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun if (tm->tm_year < 100 || tm->tm_year >= 200)
238*4882a593Smuzhiyun return -EINVAL;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun err = pcf8523_stop_rtc(client);
241*4882a593Smuzhiyun if (err < 0)
242*4882a593Smuzhiyun return err;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun regs[0] = REG_SECONDS;
245*4882a593Smuzhiyun /* This will purposely overwrite REG_SECONDS_OS */
246*4882a593Smuzhiyun regs[1] = bin2bcd(tm->tm_sec);
247*4882a593Smuzhiyun regs[2] = bin2bcd(tm->tm_min);
248*4882a593Smuzhiyun regs[3] = bin2bcd(tm->tm_hour);
249*4882a593Smuzhiyun regs[4] = bin2bcd(tm->tm_mday);
250*4882a593Smuzhiyun regs[5] = tm->tm_wday;
251*4882a593Smuzhiyun regs[6] = bin2bcd(tm->tm_mon + 1);
252*4882a593Smuzhiyun regs[7] = bin2bcd(tm->tm_year - 100);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun msg.addr = client->addr;
255*4882a593Smuzhiyun msg.flags = 0;
256*4882a593Smuzhiyun msg.len = sizeof(regs);
257*4882a593Smuzhiyun msg.buf = regs;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun err = i2c_transfer(client->adapter, &msg, 1);
260*4882a593Smuzhiyun if (err < 0) {
261*4882a593Smuzhiyun /*
262*4882a593Smuzhiyun * If the time cannot be set, restart the RTC anyway. Note
263*4882a593Smuzhiyun * that errors are ignored if the RTC cannot be started so
264*4882a593Smuzhiyun * that we have a chance to propagate the original error.
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun pcf8523_start_rtc(client);
267*4882a593Smuzhiyun return err;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun return pcf8523_start_rtc(client);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun #ifdef CONFIG_RTC_INTF_DEV
pcf8523_rtc_ioctl(struct device * dev,unsigned int cmd,unsigned long arg)274*4882a593Smuzhiyun static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
275*4882a593Smuzhiyun unsigned long arg)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
278*4882a593Smuzhiyun int ret;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun switch (cmd) {
281*4882a593Smuzhiyun case RTC_VL_READ:
282*4882a593Smuzhiyun ret = pcf8523_voltage_low(client);
283*4882a593Smuzhiyun if (ret < 0)
284*4882a593Smuzhiyun return ret;
285*4882a593Smuzhiyun if (ret)
286*4882a593Smuzhiyun ret = RTC_VL_BACKUP_LOW;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun return put_user(ret, (unsigned int __user *)arg);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun default:
291*4882a593Smuzhiyun return -ENOIOCTLCMD;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun #else
295*4882a593Smuzhiyun #define pcf8523_rtc_ioctl NULL
296*4882a593Smuzhiyun #endif
297*4882a593Smuzhiyun
pcf8523_rtc_read_offset(struct device * dev,long * offset)298*4882a593Smuzhiyun static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
301*4882a593Smuzhiyun int err;
302*4882a593Smuzhiyun u8 value;
303*4882a593Smuzhiyun s8 val;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun err = pcf8523_read(client, REG_OFFSET, &value);
306*4882a593Smuzhiyun if (err < 0)
307*4882a593Smuzhiyun return err;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun /* sign extend the 7-bit offset value */
310*4882a593Smuzhiyun val = value << 1;
311*4882a593Smuzhiyun *offset = (value & REG_OFFSET_MODE ? 4069 : 4340) * (val >> 1);
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
pcf8523_rtc_set_offset(struct device * dev,long offset)316*4882a593Smuzhiyun static int pcf8523_rtc_set_offset(struct device *dev, long offset)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
319*4882a593Smuzhiyun long reg_m0, reg_m1;
320*4882a593Smuzhiyun u8 value;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L);
323*4882a593Smuzhiyun reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset))
326*4882a593Smuzhiyun value = reg_m0 & 0x7f;
327*4882a593Smuzhiyun else
328*4882a593Smuzhiyun value = (reg_m1 & 0x7f) | REG_OFFSET_MODE;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun return pcf8523_write(client, REG_OFFSET, value);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun static const struct rtc_class_ops pcf8523_rtc_ops = {
334*4882a593Smuzhiyun .read_time = pcf8523_rtc_read_time,
335*4882a593Smuzhiyun .set_time = pcf8523_rtc_set_time,
336*4882a593Smuzhiyun .ioctl = pcf8523_rtc_ioctl,
337*4882a593Smuzhiyun .read_offset = pcf8523_rtc_read_offset,
338*4882a593Smuzhiyun .set_offset = pcf8523_rtc_set_offset,
339*4882a593Smuzhiyun };
340*4882a593Smuzhiyun
pcf8523_probe(struct i2c_client * client,const struct i2c_device_id * id)341*4882a593Smuzhiyun static int pcf8523_probe(struct i2c_client *client,
342*4882a593Smuzhiyun const struct i2c_device_id *id)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun struct rtc_device *rtc;
345*4882a593Smuzhiyun int err;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
348*4882a593Smuzhiyun return -ENODEV;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun err = pcf8523_load_capacitance(client);
351*4882a593Smuzhiyun if (err < 0)
352*4882a593Smuzhiyun dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
353*4882a593Smuzhiyun err);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun err = pcf8523_set_pm(client, 0);
356*4882a593Smuzhiyun if (err < 0)
357*4882a593Smuzhiyun return err;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun rtc = devm_rtc_device_register(&client->dev, DRIVER_NAME,
360*4882a593Smuzhiyun &pcf8523_rtc_ops, THIS_MODULE);
361*4882a593Smuzhiyun if (IS_ERR(rtc))
362*4882a593Smuzhiyun return PTR_ERR(rtc);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun static const struct i2c_device_id pcf8523_id[] = {
368*4882a593Smuzhiyun { "pcf8523", 0 },
369*4882a593Smuzhiyun { }
370*4882a593Smuzhiyun };
371*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, pcf8523_id);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun #ifdef CONFIG_OF
374*4882a593Smuzhiyun static const struct of_device_id pcf8523_of_match[] = {
375*4882a593Smuzhiyun { .compatible = "nxp,pcf8523" },
376*4882a593Smuzhiyun { .compatible = "microcrystal,rv8523" },
377*4882a593Smuzhiyun { }
378*4882a593Smuzhiyun };
379*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, pcf8523_of_match);
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun static struct i2c_driver pcf8523_driver = {
383*4882a593Smuzhiyun .driver = {
384*4882a593Smuzhiyun .name = DRIVER_NAME,
385*4882a593Smuzhiyun .of_match_table = of_match_ptr(pcf8523_of_match),
386*4882a593Smuzhiyun },
387*4882a593Smuzhiyun .probe = pcf8523_probe,
388*4882a593Smuzhiyun .id_table = pcf8523_id,
389*4882a593Smuzhiyun };
390*4882a593Smuzhiyun module_i2c_driver(pcf8523_driver);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
393*4882a593Smuzhiyun MODULE_DESCRIPTION("NXP PCF8523 RTC driver");
394*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
395