Blame view

drivers/rtc/rtc-stmp3xxx.c 12.3 KB
838d2d916   Alexandre Belloni   rtc: stmp3xxx: co...
1
  // SPDX-License-Identifier: GPL-2.0+
df17f6317   dmitry pervushin   rtc: add Freescal...
2
3
4
5
6
7
8
9
  /*
   * 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...
10
   * Copyright 2011 Wolfram Sang, Pengutronix e.K.
df17f6317   dmitry pervushin   rtc: add Freescal...
11
   */
df17f6317   dmitry pervushin   rtc: add Freescal...
12
13
  #include <linux/kernel.h>
  #include <linux/module.h>
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
14
  #include <linux/io.h>
df17f6317   dmitry pervushin   rtc: add Freescal...
15
16
17
  #include <linux/init.h>
  #include <linux/platform_device.h>
  #include <linux/interrupt.h>
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
18
  #include <linux/delay.h>
df17f6317   dmitry pervushin   rtc: add Freescal...
19
  #include <linux/rtc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
dd8d20a3f   Marek Vasut   rtc: stmp3xxx: Ad...
21
  #include <linux/of_device.h>
c8a6046e1   Sachin Kamat   drivers/rtc: use ...
22
  #include <linux/of.h>
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
23
24
  #include <linux/stmp_device.h>
  #include <linux/stmp3xxx_rtc_wdt.h>
df17f6317   dmitry pervushin   rtc: add Freescal...
25

47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
26
27
28
29
  #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...
30
  #define STMP3XXX_RTC_CTRL_WATCHDOGEN		0x00000010
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
31
32
33
34
  
  #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...
35
36
  #define STMP3XXX_RTC_STAT_XTAL32000_PRESENT	0x10000000
  #define STMP3XXX_RTC_STAT_XTAL32768_PRESENT	0x08000000
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
37
38
39
40
  
  #define STMP3XXX_RTC_SECONDS			0x30
  
  #define STMP3XXX_RTC_ALARM			0x40
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
41
  #define STMP3XXX_RTC_WATCHDOG			0x50
47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
42
  #define STMP3XXX_RTC_PERSISTENT0		0x60
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
43
44
45
46
47
48
49
  #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...
50

1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
51
52
53
  #define STMP3XXX_RTC_PERSISTENT1		0x70
  /* missing bitmask in headers */
  #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER	0x80000000
df17f6317   dmitry pervushin   rtc: add Freescal...
54
55
  struct stmp3xxx_rtc_data {
  	struct rtc_device *rtc;
df17f6317   dmitry pervushin   rtc: add Freescal...
56
  	void __iomem *io;
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
57
  	int irq_alarm;
df17f6317   dmitry pervushin   rtc: add Freescal...
58
  };
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
59
60
61
62
63
64
65
66
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
  #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...
98
  	int rc = -1;
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
99
100
101
102
103
104
  	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...
105
  		rc = platform_device_add(wdt_pdev);
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
106
  	}
3497610a4   Sudip Mukherjee   rtc: stmp3xxx: pr...
107
108
109
110
111
  
  	if (rc)
  		dev_err(&rtc_pdev->dev,
  			"failed to register stmp3xxx_rtc_wdt
  ");
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
112
113
114
115
116
117
  }
  #else
  static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
  {
  }
  #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
118
  static int stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
df17f6317   dmitry pervushin   rtc: add Freescal...
119
  {
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
120
  	int timeout = 5000; /* 3ms according to i.MX28 Ref Manual */
df17f6317   dmitry pervushin   rtc: add Freescal...
121
  	/*
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
122
123
124
125
126
127
128
129
  	 * 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...
130
  	 */
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
131
132
133
134
135
136
137
138
  	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...
139
140
141
142
143
  }
  
  /* Time read/write */
  static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
  {
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
144
  	int ret;
df17f6317   dmitry pervushin   rtc: add Freescal...
145
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
146
147
148
  	ret = stmp3xxx_wait_time(rtc_data);
  	if (ret)
  		return ret;
a659a0818   Alexandre Belloni   rtc: stmp3xxx: sw...
149
  	rtc_time64_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
df17f6317   dmitry pervushin   rtc: add Freescal...
150
151
  	return 0;
  }
622eb9b48   Alexandre Belloni   rtc: stmp3xxx: us...
152
  static int stmp3xxx_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
df17f6317   dmitry pervushin   rtc: add Freescal...
153
154
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
622eb9b48   Alexandre Belloni   rtc: stmp3xxx: us...
155
  	writel(rtc_tm_to_time64(rtc_tm), rtc_data->io + STMP3XXX_RTC_SECONDS);
28a0c8831   Lothar Waßmann   drivers/rtc/rtc-s...
156
  	return stmp3xxx_wait_time(rtc_data);
df17f6317   dmitry pervushin   rtc: add Freescal...
157
158
159
160
161
162
  }
  
  /* 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...
163
  	u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL);
df17f6317   dmitry pervushin   rtc: add Freescal...
164

47eac337c   Wolfram Sang   rtc: stmp3xxx: Re...
165
  	if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
166
  		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
244178299   Harald Geyer   rtc: stmp3xxx: un...
167
  			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
168
169
  		rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
  		return IRQ_HANDLED;
df17f6317   dmitry pervushin   rtc: add Freescal...
170
  	}
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
171
  	return IRQ_NONE;
df17f6317   dmitry pervushin   rtc: add Freescal...
172
173
174
175
176
  }
  
  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...
177
178
  
  	if (enabled) {
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
179
180
  		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
181
182
  			rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
  				STMP_OFFSET_REG_SET);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
183
  		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
184
  			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
df17f6317   dmitry pervushin   rtc: add Freescal...
185
  	} else {
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
186
187
  		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
  				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
188
189
  			rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
  				STMP_OFFSET_REG_CLR);
b5167159d   Wolfram Sang   rtc: stmp3xxx: Ge...
190
  		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
191
  			rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
df17f6317   dmitry pervushin   rtc: add Freescal...
192
193
194
  	}
  	return 0;
  }
df17f6317   dmitry pervushin   rtc: add Freescal...
195
196
197
  static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
  {
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
a659a0818   Alexandre Belloni   rtc: stmp3xxx: sw...
198
  	rtc_time64_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
df17f6317   dmitry pervushin   rtc: add Freescal...
199
200
201
202
203
  	return 0;
  }
  
  static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
  {
df17f6317   dmitry pervushin   rtc: add Freescal...
204
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
a659a0818   Alexandre Belloni   rtc: stmp3xxx: sw...
205
  	writel(rtc_tm_to_time64(&alm->time), rtc_data->io + STMP3XXX_RTC_ALARM);
7e794cb7e   Wolfram Sang   rtc: stmp3xxx: Re...
206
207
  
  	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
df17f6317   dmitry pervushin   rtc: add Freescal...
208
209
  	return 0;
  }
34c7b3ac4   Julia Lawall   rtc: constify rtc...
210
  static const struct rtc_class_ops stmp3xxx_rtc_ops = {
df17f6317   dmitry pervushin   rtc: add Freescal...
211
212
  	.alarm_irq_enable =
  			  stmp3xxx_alarm_irq_enable,
df17f6317   dmitry pervushin   rtc: add Freescal...
213
  	.read_time	= stmp3xxx_rtc_gettime,
622eb9b48   Alexandre Belloni   rtc: stmp3xxx: us...
214
  	.set_time	= stmp3xxx_rtc_settime,
df17f6317   dmitry pervushin   rtc: add Freescal...
215
216
217
218
219
220
221
222
223
224
  	.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...
225
  	writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
244178299   Harald Geyer   rtc: stmp3xxx: un...
226
  		rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
df17f6317   dmitry pervushin   rtc: add Freescal...
227
228
229
230
231
232
233
234
  
  	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...
235
236
237
  	u32 rtc_stat;
  	u32 pers0_set, pers0_clr;
  	u32 crystalfreq = 0;
df17f6317   dmitry pervushin   rtc: add Freescal...
238
  	int err;
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
239
  	rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL);
df17f6317   dmitry pervushin   rtc: add Freescal...
240
241
242
243
244
245
246
  	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...
247
  		return -ENXIO;
df17f6317   dmitry pervushin   rtc: add Freescal...
248
  	}
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
249
  	rtc_data->io = devm_ioremap(&pdev->dev, r->start, resource_size(r));
df17f6317   dmitry pervushin   rtc: add Freescal...
250
251
252
  	if (!rtc_data->io) {
  		dev_err(&pdev->dev, "ioremap failed
  ");
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
253
  		return -EIO;
df17f6317   dmitry pervushin   rtc: add Freescal...
254
255
256
  	}
  
  	rtc_data->irq_alarm = platform_get_irq(pdev, 0);
df17f6317   dmitry pervushin   rtc: add Freescal...
257

7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
258
259
  	rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT);
  	if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) {
df17f6317   dmitry pervushin   rtc: add Freescal...
260
261
  		dev_err(&pdev->dev, "no device onboard
  ");
87a814208   Jingoo Han   rtc: rtc-stmp3xxx...
262
  		return -ENODEV;
df17f6317   dmitry pervushin   rtc: add Freescal...
263
  	}
a91d2bab3   Wolfram Sang   rtc: stmp3xxx: In...
264
  	platform_set_drvdata(pdev, rtc_data);
dff700fa8   Uwe Kleine-König   rtc: stmp3xxx: Do...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  	/*
  	 * Resetting the rtc stops the watchdog timer that is potentially
  	 * running. So (assuming it is running on purpose) don't reset if the
  	 * watchdog is enabled.
  	 */
  	if (readl(rtc_data->io + STMP3XXX_RTC_CTRL) &
  	    STMP3XXX_RTC_CTRL_WATCHDOGEN) {
  		dev_info(&pdev->dev,
  			 "Watchdog is running, skip resetting rtc
  ");
  	} else {
  		err = stmp_reset_block(rtc_data->io);
  		if (err) {
  			dev_err(&pdev->dev, "stmp_reset_block failed: %d
  ",
  				err);
  			return err;
  		}
4e80b1880   Fabio Estevam   drivers/rtc/rtc-s...
283
  	}
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
  	/*
  	 * 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
  ");
df561f668   Gustavo A. R. Silva   treewide: Use fal...
320
  		fallthrough;
7f48b21bd   Uwe Kleine-König   rtc: stmp3xxx: us...
321
322
323
324
325
326
  	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

0d823abd7   Alexandre Belloni   rtc: stmp3xxx: se...
339
  	rtc_data->rtc = devm_rtc_allocate_device(&pdev->dev);
dfd2a1780   Jingoo Han   rtc: rtc-stmp3xxx...
340
341
  	if (IS_ERR(rtc_data->rtc))
  		return PTR_ERR(rtc_data->rtc);
df17f6317   dmitry pervushin   rtc: add Freescal...
342

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

0d823abd7   Alexandre Belloni   rtc: stmp3xxx: se...
352
353
354
355
356
357
  	rtc_data->rtc->ops = &stmp3xxx_rtc_ops;
  	rtc_data->rtc->range_max = U32_MAX;
  
  	err = rtc_register_device(rtc_data->rtc);
  	if (err)
  		return err;
1a71fb84f   Wolfram Sang   rtc: stmp3xxx: ad...
358
  	stmp3xxx_wdt_register(pdev);
df17f6317   dmitry pervushin   rtc: add Freescal...
359
  	return 0;
df17f6317   dmitry pervushin   rtc: add Freescal...
360
  }
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
361
362
  #ifdef CONFIG_PM_SLEEP
  static int stmp3xxx_rtc_suspend(struct device *dev)
df17f6317   dmitry pervushin   rtc: add Freescal...
363
364
365
  {
  	return 0;
  }
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
366
  static int stmp3xxx_rtc_resume(struct device *dev)
df17f6317   dmitry pervushin   rtc: add Freescal...
367
  {
ef69a7f06   Jingoo Han   rtc: rtc-stmp3xxx...
368
  	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
df17f6317   dmitry pervushin   rtc: add Freescal...
369

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