Blame view

drivers/rtc/rtc-stmp3xxx.c 12.1 KB
df17f6317   dmitry pervushin   rtc: add Freescal...
1
2
3
4
5
6
7
8
  /*
   * Freescale STMP37XX/STMP378X Real Time Clock driver
   *
   * Copyright (c) 2007 Sigmatel, Inc.
   * Peter Hartley, <peter.hartley@sigmatel.com>
   *
   * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
   * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
9
   * Copyright 2011 Wolfram Sang, Pengutronix e.K.
df17f6317   dmitry pervushin   rtc: add Freescal...
10
11
12
13
14
15
16
17
18
19
20
21
   */
  
  /*
   * The code contained herein is licensed under the GNU General Public
   * License. You may obtain a copy of the GNU General Public License
   * Version 2 or later at the following locations:
   *
   * http://www.opensource.org/licenses/gpl-license.html
   * http://www.gnu.org/copyleft/gpl.html
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
22
  #include <linux/io.h>
df17f6317   dmitry pervushin   rtc: add Freescal...
23
24
25
  #include <linux/init.h>
  #include <linux/platform_device.h>
  #include <linux/interrupt.h>
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
26
  #include <linux/delay.h>
df17f6317   dmitry pervushin   rtc: add Freescal...
27
  #include <linux/rtc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
dd8d20a3f   Marek Vasut   rtc: stmp3xxx: Ad...
29
  #include <linux/of_device.h>
c8a6046e1   Sachin Kamat   drivers/rtc: use ...
30
  #include <linux/of.h>
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
31
32
  #include <linux/stmp_device.h>
  #include <linux/stmp3xxx_rtc_wdt.h>
df17f6317   dmitry pervushin   rtc: add Freescal...
33

47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
34
35
36
37
  #define STMP3XXX_RTC_CTRL			0x0
  #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN		0x00000001
  #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002
  #define STMP3XXX_RTC_CTRL_ALARM_IRQ		0x00000004
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
38
  #define STMP3XXX_RTC_CTRL_WATCHDOGEN		0x00000010
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
39
40
41
42
  
  #define STMP3XXX_RTC_STAT			0x10
  #define STMP3XXX_RTC_STAT_STALE_SHIFT		16
  #define STMP3XXX_RTC_STAT_RTC_PRESENT		0x80000000
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
43
44
  #define STMP3XXX_RTC_STAT_XTAL32000_PRESENT	0x10000000
  #define STMP3XXX_RTC_STAT_XTAL32768_PRESENT	0x08000000
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
45
46
47
48
  
  #define STMP3XXX_RTC_SECONDS			0x30
  
  #define STMP3XXX_RTC_ALARM			0x40
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
49
  #define STMP3XXX_RTC_WATCHDOG			0x50
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
50
  #define STMP3XXX_RTC_PERSISTENT0		0x60
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
51
52
53
54
55
56
57
  #define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
  #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
  #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN		(1 << 2)
  #define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP	(1 << 4)
  #define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP	(1 << 5)
  #define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
  #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
df17f6317   dmitry pervushin   rtc: add Freescal...
58

1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
59
60
61
  #define STMP3XXX_RTC_PERSISTENT1		0x70
  /* missing bitmask in headers */
  #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER	0x80000000
df17f6317   dmitry pervushin   rtc: add Freescal...
62
63
  struct stmp3xxx_rtc_data {
  	struct rtc_device *rtc;
df17f6317   dmitry pervushin   rtc: add Freescal...
64
  	void __iomem *io;
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
65
  	int irq_alarm;
df17f6317   dmitry pervushin   rtc: add Freescal...
66
  };
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
  /**
   * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC
   * @dev: the parent device of the watchdog (= the RTC)
   * @timeout: the desired value for the timeout register of the watchdog.
   *           0 disables the watchdog
   *
   * The watchdog needs one register and two bits which are in the RTC domain.
   * To handle the resource conflict, the RTC driver will create another
   * platform_device for the watchdog driver as a child of the RTC device.
   * The watchdog driver is passed the below accessor function via platform_data
   * to configure the watchdog. Locking is not needed because accessing SET/CLR
   * registers is atomic.
   */
  
  static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout)
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  
  	if (timeout) {
  		writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG);
  		writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
  		       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
  		writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER,
  		       rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET);
  	} else {
  		writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
  		       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
  		writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER,
  		       rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR);
  	}
  }
  
  static struct stmp3xxx_wdt_pdata wdt_pdata = {
  	.wdt_set_timeout = stmp3xxx_wdt_set_timeout,
  };
  
  static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
  {
3497610a4   Sudip Mukherjee   rtc: stmp3xxx: pr...
106
  	int rc = -1;
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
107
108
109
110
111
112
  	struct platform_device *wdt_pdev =
  		platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id);
  
  	if (wdt_pdev) {
  		wdt_pdev->dev.parent = &rtc_pdev->dev;
  		wdt_pdev->dev.platform_data = &wdt_pdata;
3497610a4   Sudip Mukherjee   rtc: stmp3xxx: pr...
113
  		rc = platform_device_add(wdt_pdev);
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
114
  	}
3497610a4   Sudip Mukherjee   rtc: stmp3xxx: pr...
115
116
117
118
119
  
  	if (rc)
  		dev_err(&rtc_pdev->dev,
  			"failed to register stmp3xxx_rtc_wdt
  ");
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
120
121
122
123
124
125
  }
  #else
  static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
  {
  }
  #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
126
  static int stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
df17f6317   dmitry pervushin   rtc: add Freescal...
127
  {
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
128
  	int timeout = 5000; /* 3ms according to i.MX28 Ref Manual */
df17f6317   dmitry pervushin   rtc: add Freescal...
129
  	/*
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
130
131
132
133
134
135
136
137
  	 * The i.MX28 Applications Processor Reference Manual, Rev. 1, 2010
  	 * states:
  	 * | The order in which registers are updated is
  	 * | Persistent 0, 1, 2, 3, 4, 5, Alarm, Seconds.
  	 * | (This list is in bitfield order, from LSB to MSB, as they would
  	 * | appear in the STALE_REGS and NEW_REGS bitfields of the HW_RTC_STAT
  	 * | register. For example, the Seconds register corresponds to
  	 * | STALE_REGS or NEW_REGS containing 0x80.)
df17f6317   dmitry pervushin   rtc: add Freescal...
138
  	 */
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
139
140
141
142
143
144
145
146
  	do {
  		if (!(readl(rtc_data->io + STMP3XXX_RTC_STAT) &
  				(0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)))
  			return 0;
  		udelay(1);
  	} while (--timeout > 0);
  	return (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
  		(0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)) ? -ETIME : 0;
df17f6317   dmitry pervushin   rtc: add Freescal...
147
148
149
150
151
  }
  
  /* Time read/write */
  static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
  {
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
152
  	int ret;
df17f6317   dmitry pervushin   rtc: add Freescal...
153
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
154
155
156
  	ret = stmp3xxx_wait_time(rtc_data);
  	if (ret)
  		return ret;
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
157
  	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
df17f6317   dmitry pervushin   rtc: add Freescal...
158
159
160
161
162
163
  	return 0;
  }
  
  static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
164
  	writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
165
  	return stmp3xxx_wait_time(rtc_data);
df17f6317   dmitry pervushin   rtc: add Freescal...
166
167
168
169
170
171
  }
  
  /* interrupt(s) handler */
  static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id);
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
172
  	u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL);
df17f6317   dmitry pervushin   rtc: add Freescal...
173

47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
174
  	if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
175
  		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
244178299   Harald Geyer   rtc: stmp3xxx: un...
176
  			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
177
178
  		rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
  		return IRQ_HANDLED;
df17f6317   dmitry pervushin   rtc: add Freescal...
179
  	}
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
180
  	return IRQ_NONE;
df17f6317   dmitry pervushin   rtc: add Freescal...
181
182
183
184
185
  }
  
  static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
df17f6317   dmitry pervushin   rtc: add Freescal...
186
187
  
  	if (enabled) {
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
188
189
  		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
190
191
  			rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
  				STMP_OFFSET_REG_SET);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
192
  		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
193
  			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
df17f6317   dmitry pervushin   rtc: add Freescal...
194
  	} else {
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
195
196
  		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
197
198
  			rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
  				STMP_OFFSET_REG_CLR);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
199
  		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
200
  			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
df17f6317   dmitry pervushin   rtc: add Freescal...
201
202
203
  	}
  	return 0;
  }
df17f6317   dmitry pervushin   rtc: add Freescal...
204
205
206
  static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
207
  	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
df17f6317   dmitry pervushin   rtc: add Freescal...
208
209
210
211
212
213
214
215
216
  	return 0;
  }
  
  static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
  {
  	unsigned long t;
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
  
  	rtc_tm_to_time(&alm->time, &t);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
217
  	writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
218
219
  
  	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
df17f6317   dmitry pervushin   rtc: add Freescal...
220
221
222
223
224
225
  	return 0;
  }
  
  static struct rtc_class_ops stmp3xxx_rtc_ops = {
  	.alarm_irq_enable =
  			  stmp3xxx_alarm_irq_enable,
df17f6317   dmitry pervushin   rtc: add Freescal...
226
227
228
229
230
231
232
233
234
235
236
237
  	.read_time	= stmp3xxx_rtc_gettime,
  	.set_mmss	= stmp3xxx_rtc_set_mmss,
  	.read_alarm	= stmp3xxx_rtc_read_alarm,
  	.set_alarm	= stmp3xxx_rtc_set_alarm,
  };
  
  static int stmp3xxx_rtc_remove(struct platform_device *pdev)
  {
  	struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(pdev);
  
  	if (!rtc_data)
  		return 0;
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
238
  	writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
239
  		rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
df17f6317   dmitry pervushin   rtc: add Freescal...
240
241
242
243
244
245
246
247
  
  	return 0;
  }
  
  static int stmp3xxx_rtc_probe(struct platform_device *pdev)
  {
  	struct stmp3xxx_rtc_data *rtc_data;
  	struct resource *r;
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
248
249
250
  	u32 rtc_stat;
  	u32 pers0_set, pers0_clr;
  	u32 crystalfreq = 0;
df17f6317   dmitry pervushin   rtc: add Freescal...
251
  	int err;
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
252
  	rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL);
df17f6317   dmitry pervushin   rtc: add Freescal...
253
254
255
256
257
258
259
  	if (!rtc_data)
  		return -ENOMEM;
  
  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!r) {
  		dev_err(&pdev->dev, "failed to get resource
  ");
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
260
  		return -ENXIO;
df17f6317   dmitry pervushin   rtc: add Freescal...
261
  	}
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
262
  	rtc_data->io = devm_ioremap(&pdev->dev, r->start, resource_size(r));
df17f6317   dmitry pervushin   rtc: add Freescal...
263
264
265
  	if (!rtc_data->io) {
  		dev_err(&pdev->dev, "ioremap failed
  ");
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
266
  		return -EIO;
df17f6317   dmitry pervushin   rtc: add Freescal...
267
268
269
  	}
  
  	rtc_data->irq_alarm = platform_get_irq(pdev, 0);
df17f6317   dmitry pervushin   rtc: add Freescal...
270

7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
271
272
  	rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT);
  	if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) {
df17f6317   dmitry pervushin   rtc: add Freescal...
273
274
  		dev_err(&pdev->dev, "no device onboard
  ");
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
275
  		return -ENODEV;
df17f6317   dmitry pervushin   rtc: add Freescal...
276
  	}
a91d2bab3   Wolfram Sang   rtc: stmp3xxx: In...
277
  	platform_set_drvdata(pdev, rtc_data);
4e80b1880   Fabio Estevam   drivers/rtc/rtc-s...
278
279
280
281
282
283
  	err = stmp_reset_block(rtc_data->io);
  	if (err) {
  		dev_err(&pdev->dev, "stmp_reset_block failed: %d
  ", err);
  		return err;
  	}
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  	/*
  	 * Obviously the rtc needs a clock input to be able to run.
  	 * This clock can be provided by an external 32k crystal. If that one is
  	 * missing XTAL must not be disabled in suspend which consumes a
  	 * lot of power. Normally the presence and exact frequency (supported
  	 * are 32000 Hz and 32768 Hz) is detectable from fuses, but as reality
  	 * proves these fuses are not blown correctly on all machines, so the
  	 * frequency can be overridden in the device tree.
  	 */
  	if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32000_PRESENT)
  		crystalfreq = 32000;
  	else if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32768_PRESENT)
  		crystalfreq = 32768;
  
  	of_property_read_u32(pdev->dev.of_node, "stmp,crystal-freq",
  			     &crystalfreq);
  
  	switch (crystalfreq) {
  	case 32000:
  		/* keep 32kHz crystal running in low-power mode */
  		pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ |
  			STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
  			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
  		pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP;
  		break;
  	case 32768:
  		/* keep 32.768kHz crystal running in low-power mode */
  		pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
  			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
  		pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP |
  			STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ;
  		break;
  	default:
  		dev_warn(&pdev->dev,
  			 "invalid crystal-freq specified in device-tree. Assuming no crystal
  ");
  		/* fall-through */
  	case 0:
  		/* keep XTAL on in low-power mode */
  		pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP;
  		pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
  			STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
  	}
244178299   Harald Geyer   rtc: stmp3xxx: un...
327
328
  	writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
  			STMP_OFFSET_REG_SET);
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
329

b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
330
  	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
331
  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
332
  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr,
244178299   Harald Geyer   rtc: stmp3xxx: un...
333
  		rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
a91d2bab3   Wolfram Sang   rtc: stmp3xxx: In...
334

7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
335
336
  	writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
  			STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
337
  		rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
338

87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
339
  	rtc_data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
df17f6317   dmitry pervushin   rtc: add Freescal...
340
  				&stmp3xxx_rtc_ops, THIS_MODULE);
dfd2a1780   Jingoo Han   rtc: rtc-stmp3xxx...
341
342
  	if (IS_ERR(rtc_data->rtc))
  		return PTR_ERR(rtc_data->rtc);
df17f6317   dmitry pervushin   rtc: add Freescal...
343

87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
344
345
  	err = devm_request_irq(&pdev->dev, rtc_data->irq_alarm,
  			stmp3xxx_rtc_interrupt, 0, "RTC alarm", &pdev->dev);
df17f6317   dmitry pervushin   rtc: add Freescal...
346
347
348
349
  	if (err) {
  		dev_err(&pdev->dev, "Cannot claim IRQ%d
  ",
  			rtc_data->irq_alarm);
dfd2a1780   Jingoo Han   rtc: rtc-stmp3xxx...
350
  		return err;
df17f6317   dmitry pervushin   rtc: add Freescal...
351
  	}
df17f6317   dmitry pervushin   rtc: add Freescal...
352

1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
353
  	stmp3xxx_wdt_register(pdev);
df17f6317   dmitry pervushin   rtc: add Freescal...
354
  	return 0;
df17f6317   dmitry pervushin   rtc: add Freescal...
355
  }
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
356
357
  #ifdef CONFIG_PM_SLEEP
  static int stmp3xxx_rtc_suspend(struct device *dev)
df17f6317   dmitry pervushin   rtc: add Freescal...
358
359
360
  {
  	return 0;
  }
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
361
  static int stmp3xxx_rtc_resume(struct device *dev)
df17f6317   dmitry pervushin   rtc: add Freescal...
362
  {
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
363
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
df17f6317   dmitry pervushin   rtc: add Freescal...
364

36d1da1d1   Shawn Guo   rtc: stmp3xxx: us...
365
  	stmp_reset_block(rtc_data->io);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
366
  	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
367
368
  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
  			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
244178299   Harald Geyer   rtc: stmp3xxx: un...
369
  		rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
df17f6317   dmitry pervushin   rtc: add Freescal...
370
371
  	return 0;
  }
df17f6317   dmitry pervushin   rtc: add Freescal...
372
  #endif
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
373
374
  static SIMPLE_DEV_PM_OPS(stmp3xxx_rtc_pm_ops, stmp3xxx_rtc_suspend,
  			stmp3xxx_rtc_resume);
dd8d20a3f   Marek Vasut   rtc: stmp3xxx: Ad...
375
376
377
378
379
  static const struct of_device_id rtc_dt_ids[] = {
  	{ .compatible = "fsl,stmp3xxx-rtc", },
  	{ /* sentinel */ }
  };
  MODULE_DEVICE_TABLE(of, rtc_dt_ids);
df17f6317   dmitry pervushin   rtc: add Freescal...
380
381
382
  static struct platform_driver stmp3xxx_rtcdrv = {
  	.probe		= stmp3xxx_rtc_probe,
  	.remove		= stmp3xxx_rtc_remove,
df17f6317   dmitry pervushin   rtc: add Freescal...
383
384
  	.driver		= {
  		.name	= "stmp3xxx-rtc",
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
385
  		.pm	= &stmp3xxx_rtc_pm_ops,
462a465be   Sachin Kamat   drivers/rtc/rtc-s...
386
  		.of_match_table = rtc_dt_ids,
df17f6317   dmitry pervushin   rtc: add Freescal...
387
388
  	},
  };
0c4eae665   Axel Lin   rtc: convert driv...
389
  module_platform_driver(stmp3xxx_rtcdrv);
df17f6317   dmitry pervushin   rtc: add Freescal...
390
391
  
  MODULE_DESCRIPTION("STMP3xxx RTC Driver");
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
392
393
  MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
  		"Wolfram Sang <w.sang@pengutronix.de>");
df17f6317   dmitry pervushin   rtc: add Freescal...
394
  MODULE_LICENSE("GPL");