1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * RTC client/driver for the Maxim/Dallas DS3232/DS3234 Real-Time Clock
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2009-2011 Freescale Semiconductor.
6*4882a593Smuzhiyun * Author: Jack Lan <jack.lan@freescale.com>
7*4882a593Smuzhiyun * Copyright (C) 2008 MIMOMax Wireless Ltd.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/interrupt.h>
15*4882a593Smuzhiyun #include <linux/i2c.h>
16*4882a593Smuzhiyun #include <linux/spi/spi.h>
17*4882a593Smuzhiyun #include <linux/rtc.h>
18*4882a593Smuzhiyun #include <linux/bcd.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun #include <linux/regmap.h>
21*4882a593Smuzhiyun #include <linux/hwmon.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define DS3232_REG_SECONDS 0x00
24*4882a593Smuzhiyun #define DS3232_REG_MINUTES 0x01
25*4882a593Smuzhiyun #define DS3232_REG_HOURS 0x02
26*4882a593Smuzhiyun #define DS3232_REG_AMPM 0x02
27*4882a593Smuzhiyun #define DS3232_REG_DAY 0x03
28*4882a593Smuzhiyun #define DS3232_REG_DATE 0x04
29*4882a593Smuzhiyun #define DS3232_REG_MONTH 0x05
30*4882a593Smuzhiyun #define DS3232_REG_CENTURY 0x05
31*4882a593Smuzhiyun #define DS3232_REG_YEAR 0x06
32*4882a593Smuzhiyun #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */
33*4882a593Smuzhiyun #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */
34*4882a593Smuzhiyun #define DS3232_REG_CR 0x0E /* Control register */
35*4882a593Smuzhiyun # define DS3232_REG_CR_nEOSC 0x80
36*4882a593Smuzhiyun # define DS3232_REG_CR_INTCN 0x04
37*4882a593Smuzhiyun # define DS3232_REG_CR_A2IE 0x02
38*4882a593Smuzhiyun # define DS3232_REG_CR_A1IE 0x01
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define DS3232_REG_SR 0x0F /* control/status register */
41*4882a593Smuzhiyun # define DS3232_REG_SR_OSF 0x80
42*4882a593Smuzhiyun # define DS3232_REG_SR_BSY 0x04
43*4882a593Smuzhiyun # define DS3232_REG_SR_A2F 0x02
44*4882a593Smuzhiyun # define DS3232_REG_SR_A1F 0x01
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define DS3232_REG_TEMPERATURE 0x11
47*4882a593Smuzhiyun #define DS3232_REG_SRAM_START 0x14
48*4882a593Smuzhiyun #define DS3232_REG_SRAM_END 0xFF
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define DS3232_REG_SRAM_SIZE 236
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun struct ds3232 {
53*4882a593Smuzhiyun struct device *dev;
54*4882a593Smuzhiyun struct regmap *regmap;
55*4882a593Smuzhiyun int irq;
56*4882a593Smuzhiyun struct rtc_device *rtc;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun bool suspended;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
ds3232_check_rtc_status(struct device * dev)61*4882a593Smuzhiyun static int ds3232_check_rtc_status(struct device *dev)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
64*4882a593Smuzhiyun int ret = 0;
65*4882a593Smuzhiyun int control, stat;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
68*4882a593Smuzhiyun if (ret)
69*4882a593Smuzhiyun return ret;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if (stat & DS3232_REG_SR_OSF)
72*4882a593Smuzhiyun dev_warn(dev,
73*4882a593Smuzhiyun "oscillator discontinuity flagged, "
74*4882a593Smuzhiyun "time unreliable\n");
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
79*4882a593Smuzhiyun if (ret)
80*4882a593Smuzhiyun return ret;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* If the alarm is pending, clear it before requesting
83*4882a593Smuzhiyun * the interrupt, so an interrupt event isn't reported
84*4882a593Smuzhiyun * before everything is initialized.
85*4882a593Smuzhiyun */
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
88*4882a593Smuzhiyun if (ret)
89*4882a593Smuzhiyun return ret;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
92*4882a593Smuzhiyun control |= DS3232_REG_CR_INTCN;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return regmap_write(ds3232->regmap, DS3232_REG_CR, control);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
ds3232_read_time(struct device * dev,struct rtc_time * time)97*4882a593Smuzhiyun static int ds3232_read_time(struct device *dev, struct rtc_time *time)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
100*4882a593Smuzhiyun int ret;
101*4882a593Smuzhiyun u8 buf[7];
102*4882a593Smuzhiyun unsigned int year, month, day, hour, minute, second;
103*4882a593Smuzhiyun unsigned int week, twelve_hr, am_pm;
104*4882a593Smuzhiyun unsigned int century, add_century = 0;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
107*4882a593Smuzhiyun if (ret)
108*4882a593Smuzhiyun return ret;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun second = buf[0];
111*4882a593Smuzhiyun minute = buf[1];
112*4882a593Smuzhiyun hour = buf[2];
113*4882a593Smuzhiyun week = buf[3];
114*4882a593Smuzhiyun day = buf[4];
115*4882a593Smuzhiyun month = buf[5];
116*4882a593Smuzhiyun year = buf[6];
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* Extract additional information for AM/PM and century */
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun twelve_hr = hour & 0x40;
121*4882a593Smuzhiyun am_pm = hour & 0x20;
122*4882a593Smuzhiyun century = month & 0x80;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* Write to rtc_time structure */
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun time->tm_sec = bcd2bin(second);
127*4882a593Smuzhiyun time->tm_min = bcd2bin(minute);
128*4882a593Smuzhiyun if (twelve_hr) {
129*4882a593Smuzhiyun /* Convert to 24 hr */
130*4882a593Smuzhiyun if (am_pm)
131*4882a593Smuzhiyun time->tm_hour = bcd2bin(hour & 0x1F) + 12;
132*4882a593Smuzhiyun else
133*4882a593Smuzhiyun time->tm_hour = bcd2bin(hour & 0x1F);
134*4882a593Smuzhiyun } else {
135*4882a593Smuzhiyun time->tm_hour = bcd2bin(hour);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
139*4882a593Smuzhiyun time->tm_wday = bcd2bin(week) - 1;
140*4882a593Smuzhiyun time->tm_mday = bcd2bin(day);
141*4882a593Smuzhiyun /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
142*4882a593Smuzhiyun time->tm_mon = bcd2bin(month & 0x7F) - 1;
143*4882a593Smuzhiyun if (century)
144*4882a593Smuzhiyun add_century = 100;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun time->tm_year = bcd2bin(year) + add_century;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun return 0;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
ds3232_set_time(struct device * dev,struct rtc_time * time)151*4882a593Smuzhiyun static int ds3232_set_time(struct device *dev, struct rtc_time *time)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
154*4882a593Smuzhiyun u8 buf[7];
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /* Extract time from rtc_time and load into ds3232*/
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun buf[0] = bin2bcd(time->tm_sec);
159*4882a593Smuzhiyun buf[1] = bin2bcd(time->tm_min);
160*4882a593Smuzhiyun buf[2] = bin2bcd(time->tm_hour);
161*4882a593Smuzhiyun /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
162*4882a593Smuzhiyun buf[3] = bin2bcd(time->tm_wday + 1);
163*4882a593Smuzhiyun buf[4] = bin2bcd(time->tm_mday); /* Date */
164*4882a593Smuzhiyun /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
165*4882a593Smuzhiyun buf[5] = bin2bcd(time->tm_mon + 1);
166*4882a593Smuzhiyun if (time->tm_year >= 100) {
167*4882a593Smuzhiyun buf[5] |= 0x80;
168*4882a593Smuzhiyun buf[6] = bin2bcd(time->tm_year - 100);
169*4882a593Smuzhiyun } else {
170*4882a593Smuzhiyun buf[6] = bin2bcd(time->tm_year);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /*
177*4882a593Smuzhiyun * DS3232 has two alarm, we only use alarm1
178*4882a593Smuzhiyun * According to linux specification, only support one-shot alarm
179*4882a593Smuzhiyun * no periodic alarm mode
180*4882a593Smuzhiyun */
ds3232_read_alarm(struct device * dev,struct rtc_wkalrm * alarm)181*4882a593Smuzhiyun static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
184*4882a593Smuzhiyun int control, stat;
185*4882a593Smuzhiyun int ret;
186*4882a593Smuzhiyun u8 buf[4];
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
189*4882a593Smuzhiyun if (ret)
190*4882a593Smuzhiyun goto out;
191*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
192*4882a593Smuzhiyun if (ret)
193*4882a593Smuzhiyun goto out;
194*4882a593Smuzhiyun ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
195*4882a593Smuzhiyun if (ret)
196*4882a593Smuzhiyun goto out;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
199*4882a593Smuzhiyun alarm->time.tm_min = bcd2bin(buf[1] & 0x7F);
200*4882a593Smuzhiyun alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F);
201*4882a593Smuzhiyun alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun alarm->enabled = !!(control & DS3232_REG_CR_A1IE);
204*4882a593Smuzhiyun alarm->pending = !!(stat & DS3232_REG_SR_A1F);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun ret = 0;
207*4882a593Smuzhiyun out:
208*4882a593Smuzhiyun return ret;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /*
212*4882a593Smuzhiyun * linux rtc-module does not support wday alarm
213*4882a593Smuzhiyun * and only 24h time mode supported indeed
214*4882a593Smuzhiyun */
ds3232_set_alarm(struct device * dev,struct rtc_wkalrm * alarm)215*4882a593Smuzhiyun static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
218*4882a593Smuzhiyun int control, stat;
219*4882a593Smuzhiyun int ret;
220*4882a593Smuzhiyun u8 buf[4];
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (ds3232->irq <= 0)
223*4882a593Smuzhiyun return -EINVAL;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun buf[0] = bin2bcd(alarm->time.tm_sec);
226*4882a593Smuzhiyun buf[1] = bin2bcd(alarm->time.tm_min);
227*4882a593Smuzhiyun buf[2] = bin2bcd(alarm->time.tm_hour);
228*4882a593Smuzhiyun buf[3] = bin2bcd(alarm->time.tm_mday);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* clear alarm interrupt enable bit */
231*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
232*4882a593Smuzhiyun if (ret)
233*4882a593Smuzhiyun goto out;
234*4882a593Smuzhiyun control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
235*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
236*4882a593Smuzhiyun if (ret)
237*4882a593Smuzhiyun goto out;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /* clear any pending alarm flag */
240*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
241*4882a593Smuzhiyun if (ret)
242*4882a593Smuzhiyun goto out;
243*4882a593Smuzhiyun stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
244*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
245*4882a593Smuzhiyun if (ret)
246*4882a593Smuzhiyun goto out;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun ret = regmap_bulk_write(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
249*4882a593Smuzhiyun if (ret)
250*4882a593Smuzhiyun goto out;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (alarm->enabled) {
253*4882a593Smuzhiyun control |= DS3232_REG_CR_A1IE;
254*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun out:
257*4882a593Smuzhiyun return ret;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
ds3232_update_alarm(struct device * dev,unsigned int enabled)260*4882a593Smuzhiyun static int ds3232_update_alarm(struct device *dev, unsigned int enabled)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
263*4882a593Smuzhiyun int control;
264*4882a593Smuzhiyun int ret;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
267*4882a593Smuzhiyun if (ret)
268*4882a593Smuzhiyun return ret;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun if (enabled)
271*4882a593Smuzhiyun /* enable alarm1 interrupt */
272*4882a593Smuzhiyun control |= DS3232_REG_CR_A1IE;
273*4882a593Smuzhiyun else
274*4882a593Smuzhiyun /* disable alarm1 interrupt */
275*4882a593Smuzhiyun control &= ~(DS3232_REG_CR_A1IE);
276*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun return ret;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /*
282*4882a593Smuzhiyun * Temperature sensor support for ds3232/ds3234 devices.
283*4882a593Smuzhiyun * A user-initiated temperature conversion is not started by this function,
284*4882a593Smuzhiyun * so the temperature is updated once every 64 seconds.
285*4882a593Smuzhiyun */
ds3232_hwmon_read_temp(struct device * dev,long int * mC)286*4882a593Smuzhiyun static int ds3232_hwmon_read_temp(struct device *dev, long int *mC)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
289*4882a593Smuzhiyun u8 temp_buf[2];
290*4882a593Smuzhiyun s16 temp;
291*4882a593Smuzhiyun int ret;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_TEMPERATURE, temp_buf,
294*4882a593Smuzhiyun sizeof(temp_buf));
295*4882a593Smuzhiyun if (ret < 0)
296*4882a593Smuzhiyun return ret;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /*
299*4882a593Smuzhiyun * Temperature is represented as a 10-bit code with a resolution of
300*4882a593Smuzhiyun * 0.25 degree celsius and encoded in two's complement format.
301*4882a593Smuzhiyun */
302*4882a593Smuzhiyun temp = (temp_buf[0] << 8) | temp_buf[1];
303*4882a593Smuzhiyun temp >>= 6;
304*4882a593Smuzhiyun *mC = temp * 250;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return 0;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
ds3232_hwmon_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)309*4882a593Smuzhiyun static umode_t ds3232_hwmon_is_visible(const void *data,
310*4882a593Smuzhiyun enum hwmon_sensor_types type,
311*4882a593Smuzhiyun u32 attr, int channel)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun if (type != hwmon_temp)
314*4882a593Smuzhiyun return 0;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun switch (attr) {
317*4882a593Smuzhiyun case hwmon_temp_input:
318*4882a593Smuzhiyun return 0444;
319*4882a593Smuzhiyun default:
320*4882a593Smuzhiyun return 0;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
ds3232_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * temp)324*4882a593Smuzhiyun static int ds3232_hwmon_read(struct device *dev,
325*4882a593Smuzhiyun enum hwmon_sensor_types type,
326*4882a593Smuzhiyun u32 attr, int channel, long *temp)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun int err;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun switch (attr) {
331*4882a593Smuzhiyun case hwmon_temp_input:
332*4882a593Smuzhiyun err = ds3232_hwmon_read_temp(dev, temp);
333*4882a593Smuzhiyun break;
334*4882a593Smuzhiyun default:
335*4882a593Smuzhiyun err = -EOPNOTSUPP;
336*4882a593Smuzhiyun break;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun return err;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun static u32 ds3232_hwmon_chip_config[] = {
343*4882a593Smuzhiyun HWMON_C_REGISTER_TZ,
344*4882a593Smuzhiyun 0
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun static const struct hwmon_channel_info ds3232_hwmon_chip = {
348*4882a593Smuzhiyun .type = hwmon_chip,
349*4882a593Smuzhiyun .config = ds3232_hwmon_chip_config,
350*4882a593Smuzhiyun };
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun static u32 ds3232_hwmon_temp_config[] = {
353*4882a593Smuzhiyun HWMON_T_INPUT,
354*4882a593Smuzhiyun 0
355*4882a593Smuzhiyun };
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun static const struct hwmon_channel_info ds3232_hwmon_temp = {
358*4882a593Smuzhiyun .type = hwmon_temp,
359*4882a593Smuzhiyun .config = ds3232_hwmon_temp_config,
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun static const struct hwmon_channel_info *ds3232_hwmon_info[] = {
363*4882a593Smuzhiyun &ds3232_hwmon_chip,
364*4882a593Smuzhiyun &ds3232_hwmon_temp,
365*4882a593Smuzhiyun NULL
366*4882a593Smuzhiyun };
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun static const struct hwmon_ops ds3232_hwmon_hwmon_ops = {
369*4882a593Smuzhiyun .is_visible = ds3232_hwmon_is_visible,
370*4882a593Smuzhiyun .read = ds3232_hwmon_read,
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun static const struct hwmon_chip_info ds3232_hwmon_chip_info = {
374*4882a593Smuzhiyun .ops = &ds3232_hwmon_hwmon_ops,
375*4882a593Smuzhiyun .info = ds3232_hwmon_info,
376*4882a593Smuzhiyun };
377*4882a593Smuzhiyun
ds3232_hwmon_register(struct device * dev,const char * name)378*4882a593Smuzhiyun static void ds3232_hwmon_register(struct device *dev, const char *name)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
381*4882a593Smuzhiyun struct device *hwmon_dev;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (!IS_ENABLED(CONFIG_RTC_DRV_DS3232_HWMON))
384*4882a593Smuzhiyun return;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun hwmon_dev = devm_hwmon_device_register_with_info(dev, name, ds3232,
387*4882a593Smuzhiyun &ds3232_hwmon_chip_info,
388*4882a593Smuzhiyun NULL);
389*4882a593Smuzhiyun if (IS_ERR(hwmon_dev)) {
390*4882a593Smuzhiyun dev_err(dev, "unable to register hwmon device %ld\n",
391*4882a593Smuzhiyun PTR_ERR(hwmon_dev));
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
ds3232_alarm_irq_enable(struct device * dev,unsigned int enabled)395*4882a593Smuzhiyun static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun if (ds3232->irq <= 0)
400*4882a593Smuzhiyun return -EINVAL;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun return ds3232_update_alarm(dev, enabled);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
ds3232_irq(int irq,void * dev_id)405*4882a593Smuzhiyun static irqreturn_t ds3232_irq(int irq, void *dev_id)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun struct device *dev = dev_id;
408*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
409*4882a593Smuzhiyun struct mutex *lock = &ds3232->rtc->ops_lock;
410*4882a593Smuzhiyun int ret;
411*4882a593Smuzhiyun int stat, control;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun mutex_lock(lock);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
416*4882a593Smuzhiyun if (ret)
417*4882a593Smuzhiyun goto unlock;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun if (stat & DS3232_REG_SR_A1F) {
420*4882a593Smuzhiyun ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
421*4882a593Smuzhiyun if (ret) {
422*4882a593Smuzhiyun dev_warn(ds3232->dev,
423*4882a593Smuzhiyun "Read Control Register error %d\n", ret);
424*4882a593Smuzhiyun } else {
425*4882a593Smuzhiyun /* disable alarm1 interrupt */
426*4882a593Smuzhiyun control &= ~(DS3232_REG_CR_A1IE);
427*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
428*4882a593Smuzhiyun control);
429*4882a593Smuzhiyun if (ret) {
430*4882a593Smuzhiyun dev_warn(ds3232->dev,
431*4882a593Smuzhiyun "Write Control Register error %d\n",
432*4882a593Smuzhiyun ret);
433*4882a593Smuzhiyun goto unlock;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /* clear the alarm pend flag */
437*4882a593Smuzhiyun stat &= ~DS3232_REG_SR_A1F;
438*4882a593Smuzhiyun ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
439*4882a593Smuzhiyun if (ret) {
440*4882a593Smuzhiyun dev_warn(ds3232->dev,
441*4882a593Smuzhiyun "Write Status Register error %d\n",
442*4882a593Smuzhiyun ret);
443*4882a593Smuzhiyun goto unlock;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun unlock:
451*4882a593Smuzhiyun mutex_unlock(lock);
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun return IRQ_HANDLED;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun static const struct rtc_class_ops ds3232_rtc_ops = {
457*4882a593Smuzhiyun .read_time = ds3232_read_time,
458*4882a593Smuzhiyun .set_time = ds3232_set_time,
459*4882a593Smuzhiyun .read_alarm = ds3232_read_alarm,
460*4882a593Smuzhiyun .set_alarm = ds3232_set_alarm,
461*4882a593Smuzhiyun .alarm_irq_enable = ds3232_alarm_irq_enable,
462*4882a593Smuzhiyun };
463*4882a593Smuzhiyun
ds3232_nvmem_read(void * priv,unsigned int offset,void * val,size_t bytes)464*4882a593Smuzhiyun static int ds3232_nvmem_read(void *priv, unsigned int offset, void *val,
465*4882a593Smuzhiyun size_t bytes)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun struct regmap *ds3232_regmap = (struct regmap *)priv;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun return regmap_bulk_read(ds3232_regmap, DS3232_REG_SRAM_START + offset,
470*4882a593Smuzhiyun val, bytes);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
ds3232_nvmem_write(void * priv,unsigned int offset,void * val,size_t bytes)473*4882a593Smuzhiyun static int ds3232_nvmem_write(void *priv, unsigned int offset, void *val,
474*4882a593Smuzhiyun size_t bytes)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun struct regmap *ds3232_regmap = (struct regmap *)priv;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun return regmap_bulk_write(ds3232_regmap, DS3232_REG_SRAM_START + offset,
479*4882a593Smuzhiyun val, bytes);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
ds3232_probe(struct device * dev,struct regmap * regmap,int irq,const char * name)482*4882a593Smuzhiyun static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
483*4882a593Smuzhiyun const char *name)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun struct ds3232 *ds3232;
486*4882a593Smuzhiyun int ret;
487*4882a593Smuzhiyun struct nvmem_config nvmem_cfg = {
488*4882a593Smuzhiyun .name = "ds3232_sram",
489*4882a593Smuzhiyun .stride = 1,
490*4882a593Smuzhiyun .size = DS3232_REG_SRAM_SIZE,
491*4882a593Smuzhiyun .word_size = 1,
492*4882a593Smuzhiyun .reg_read = ds3232_nvmem_read,
493*4882a593Smuzhiyun .reg_write = ds3232_nvmem_write,
494*4882a593Smuzhiyun .priv = regmap,
495*4882a593Smuzhiyun .type = NVMEM_TYPE_BATTERY_BACKED
496*4882a593Smuzhiyun };
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
499*4882a593Smuzhiyun if (!ds3232)
500*4882a593Smuzhiyun return -ENOMEM;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun ds3232->regmap = regmap;
503*4882a593Smuzhiyun ds3232->irq = irq;
504*4882a593Smuzhiyun ds3232->dev = dev;
505*4882a593Smuzhiyun dev_set_drvdata(dev, ds3232);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun ret = ds3232_check_rtc_status(dev);
508*4882a593Smuzhiyun if (ret)
509*4882a593Smuzhiyun return ret;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun if (ds3232->irq > 0)
512*4882a593Smuzhiyun device_init_wakeup(dev, 1);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun ds3232_hwmon_register(dev, name);
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops,
517*4882a593Smuzhiyun THIS_MODULE);
518*4882a593Smuzhiyun if (IS_ERR(ds3232->rtc))
519*4882a593Smuzhiyun return PTR_ERR(ds3232->rtc);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun ret = rtc_nvmem_register(ds3232->rtc, &nvmem_cfg);
522*4882a593Smuzhiyun if(ret)
523*4882a593Smuzhiyun return ret;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun if (ds3232->irq > 0) {
526*4882a593Smuzhiyun ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
527*4882a593Smuzhiyun ds3232_irq,
528*4882a593Smuzhiyun IRQF_SHARED | IRQF_ONESHOT,
529*4882a593Smuzhiyun name, dev);
530*4882a593Smuzhiyun if (ret) {
531*4882a593Smuzhiyun device_set_wakeup_capable(dev, 0);
532*4882a593Smuzhiyun ds3232->irq = 0;
533*4882a593Smuzhiyun dev_err(dev, "unable to request IRQ\n");
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun return 0;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
ds3232_suspend(struct device * dev)541*4882a593Smuzhiyun static int ds3232_suspend(struct device *dev)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun if (device_may_wakeup(dev)) {
546*4882a593Smuzhiyun if (enable_irq_wake(ds3232->irq))
547*4882a593Smuzhiyun dev_warn_once(dev, "Cannot set wakeup source\n");
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
ds3232_resume(struct device * dev)553*4882a593Smuzhiyun static int ds3232_resume(struct device *dev)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun struct ds3232 *ds3232 = dev_get_drvdata(dev);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (device_may_wakeup(dev))
558*4882a593Smuzhiyun disable_irq_wake(ds3232->irq);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun return 0;
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun #endif
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun static const struct dev_pm_ops ds3232_pm_ops = {
565*4882a593Smuzhiyun SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
566*4882a593Smuzhiyun };
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_I2C)
569*4882a593Smuzhiyun
ds3232_i2c_probe(struct i2c_client * client,const struct i2c_device_id * id)570*4882a593Smuzhiyun static int ds3232_i2c_probe(struct i2c_client *client,
571*4882a593Smuzhiyun const struct i2c_device_id *id)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun struct regmap *regmap;
574*4882a593Smuzhiyun static const struct regmap_config config = {
575*4882a593Smuzhiyun .reg_bits = 8,
576*4882a593Smuzhiyun .val_bits = 8,
577*4882a593Smuzhiyun .max_register = DS3232_REG_SRAM_END,
578*4882a593Smuzhiyun };
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun regmap = devm_regmap_init_i2c(client, &config);
581*4882a593Smuzhiyun if (IS_ERR(regmap)) {
582*4882a593Smuzhiyun dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
583*4882a593Smuzhiyun __func__, PTR_ERR(regmap));
584*4882a593Smuzhiyun return PTR_ERR(regmap);
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun return ds3232_probe(&client->dev, regmap, client->irq, client->name);
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun static const struct i2c_device_id ds3232_id[] = {
591*4882a593Smuzhiyun { "ds3232", 0 },
592*4882a593Smuzhiyun { }
593*4882a593Smuzhiyun };
594*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, ds3232_id);
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun static const struct of_device_id ds3232_of_match[] = {
597*4882a593Smuzhiyun { .compatible = "dallas,ds3232" },
598*4882a593Smuzhiyun { }
599*4882a593Smuzhiyun };
600*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ds3232_of_match);
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun static struct i2c_driver ds3232_driver = {
603*4882a593Smuzhiyun .driver = {
604*4882a593Smuzhiyun .name = "rtc-ds3232",
605*4882a593Smuzhiyun .of_match_table = of_match_ptr(ds3232_of_match),
606*4882a593Smuzhiyun .pm = &ds3232_pm_ops,
607*4882a593Smuzhiyun },
608*4882a593Smuzhiyun .probe = ds3232_i2c_probe,
609*4882a593Smuzhiyun .id_table = ds3232_id,
610*4882a593Smuzhiyun };
611*4882a593Smuzhiyun
ds3232_register_driver(void)612*4882a593Smuzhiyun static int ds3232_register_driver(void)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun return i2c_add_driver(&ds3232_driver);
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
ds3232_unregister_driver(void)617*4882a593Smuzhiyun static void ds3232_unregister_driver(void)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun i2c_del_driver(&ds3232_driver);
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun #else
623*4882a593Smuzhiyun
ds3232_register_driver(void)624*4882a593Smuzhiyun static int ds3232_register_driver(void)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun return 0;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
ds3232_unregister_driver(void)629*4882a593Smuzhiyun static void ds3232_unregister_driver(void)
630*4882a593Smuzhiyun {
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun #endif
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SPI_MASTER)
636*4882a593Smuzhiyun
ds3234_probe(struct spi_device * spi)637*4882a593Smuzhiyun static int ds3234_probe(struct spi_device *spi)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun int res;
640*4882a593Smuzhiyun unsigned int tmp;
641*4882a593Smuzhiyun static const struct regmap_config config = {
642*4882a593Smuzhiyun .reg_bits = 8,
643*4882a593Smuzhiyun .val_bits = 8,
644*4882a593Smuzhiyun .max_register = DS3232_REG_SRAM_END,
645*4882a593Smuzhiyun .write_flag_mask = 0x80,
646*4882a593Smuzhiyun };
647*4882a593Smuzhiyun struct regmap *regmap;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun regmap = devm_regmap_init_spi(spi, &config);
650*4882a593Smuzhiyun if (IS_ERR(regmap)) {
651*4882a593Smuzhiyun dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
652*4882a593Smuzhiyun __func__, PTR_ERR(regmap));
653*4882a593Smuzhiyun return PTR_ERR(regmap);
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun spi->mode = SPI_MODE_3;
657*4882a593Smuzhiyun spi->bits_per_word = 8;
658*4882a593Smuzhiyun spi_setup(spi);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun res = regmap_read(regmap, DS3232_REG_SECONDS, &tmp);
661*4882a593Smuzhiyun if (res)
662*4882a593Smuzhiyun return res;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /* Control settings
665*4882a593Smuzhiyun *
666*4882a593Smuzhiyun * CONTROL_REG
667*4882a593Smuzhiyun * BIT 7 6 5 4 3 2 1 0
668*4882a593Smuzhiyun * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE
669*4882a593Smuzhiyun *
670*4882a593Smuzhiyun * 0 0 0 1 1 1 0 0
671*4882a593Smuzhiyun *
672*4882a593Smuzhiyun * CONTROL_STAT_REG
673*4882a593Smuzhiyun * BIT 7 6 5 4 3 2 1 0
674*4882a593Smuzhiyun * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F
675*4882a593Smuzhiyun *
676*4882a593Smuzhiyun * 1 0 0 0 1 0 0 0
677*4882a593Smuzhiyun */
678*4882a593Smuzhiyun res = regmap_read(regmap, DS3232_REG_CR, &tmp);
679*4882a593Smuzhiyun if (res)
680*4882a593Smuzhiyun return res;
681*4882a593Smuzhiyun res = regmap_write(regmap, DS3232_REG_CR, tmp & 0x1c);
682*4882a593Smuzhiyun if (res)
683*4882a593Smuzhiyun return res;
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun res = regmap_read(regmap, DS3232_REG_SR, &tmp);
686*4882a593Smuzhiyun if (res)
687*4882a593Smuzhiyun return res;
688*4882a593Smuzhiyun res = regmap_write(regmap, DS3232_REG_SR, tmp & 0x88);
689*4882a593Smuzhiyun if (res)
690*4882a593Smuzhiyun return res;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun /* Print our settings */
693*4882a593Smuzhiyun res = regmap_read(regmap, DS3232_REG_CR, &tmp);
694*4882a593Smuzhiyun if (res)
695*4882a593Smuzhiyun return res;
696*4882a593Smuzhiyun dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun res = regmap_read(regmap, DS3232_REG_SR, &tmp);
699*4882a593Smuzhiyun if (res)
700*4882a593Smuzhiyun return res;
701*4882a593Smuzhiyun dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234");
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun static struct spi_driver ds3234_driver = {
707*4882a593Smuzhiyun .driver = {
708*4882a593Smuzhiyun .name = "ds3234",
709*4882a593Smuzhiyun },
710*4882a593Smuzhiyun .probe = ds3234_probe,
711*4882a593Smuzhiyun };
712*4882a593Smuzhiyun
ds3234_register_driver(void)713*4882a593Smuzhiyun static int ds3234_register_driver(void)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun return spi_register_driver(&ds3234_driver);
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun
ds3234_unregister_driver(void)718*4882a593Smuzhiyun static void ds3234_unregister_driver(void)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun spi_unregister_driver(&ds3234_driver);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun #else
724*4882a593Smuzhiyun
ds3234_register_driver(void)725*4882a593Smuzhiyun static int ds3234_register_driver(void)
726*4882a593Smuzhiyun {
727*4882a593Smuzhiyun return 0;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
ds3234_unregister_driver(void)730*4882a593Smuzhiyun static void ds3234_unregister_driver(void)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun #endif
735*4882a593Smuzhiyun
ds323x_init(void)736*4882a593Smuzhiyun static int __init ds323x_init(void)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun int ret;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun ret = ds3232_register_driver();
741*4882a593Smuzhiyun if (ret) {
742*4882a593Smuzhiyun pr_err("Failed to register ds3232 driver: %d\n", ret);
743*4882a593Smuzhiyun return ret;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun ret = ds3234_register_driver();
747*4882a593Smuzhiyun if (ret) {
748*4882a593Smuzhiyun pr_err("Failed to register ds3234 driver: %d\n", ret);
749*4882a593Smuzhiyun ds3232_unregister_driver();
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun return ret;
753*4882a593Smuzhiyun }
module_init(ds323x_init)754*4882a593Smuzhiyun module_init(ds323x_init)
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun static void __exit ds323x_exit(void)
757*4882a593Smuzhiyun {
758*4882a593Smuzhiyun ds3234_unregister_driver();
759*4882a593Smuzhiyun ds3232_unregister_driver();
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun module_exit(ds323x_exit)
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
764*4882a593Smuzhiyun MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
765*4882a593Smuzhiyun MODULE_DESCRIPTION("Maxim/Dallas DS3232/DS3234 RTC Driver");
766*4882a593Smuzhiyun MODULE_LICENSE("GPL");
767*4882a593Smuzhiyun MODULE_ALIAS("spi:ds3234");
768