xref: /OK3568_Linux_fs/kernel/drivers/rtc/rtc-ds3232.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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