Blame view

drivers/rtc/rtc-snvs.c 10.4 KB
5874c7f16   Fabio Estevam   rtc: snvs: Switch...
1
2
3
  // SPDX-License-Identifier: GPL-2.0+
  //
  // Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
179a502f8   Shawn Guo   rtc: snvs: add Fr...
4
5
6
7
8
9
  
  #include <linux/init.h>
  #include <linux/io.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/of.h>
179a502f8   Shawn Guo   rtc: snvs: add Fr...
10
  #include <linux/platform_device.h>
e7afddb2b   Anson Huang   rtc: snvs: use de...
11
  #include <linux/pm_wakeirq.h>
179a502f8   Shawn Guo   rtc: snvs: add Fr...
12
  #include <linux/rtc.h>
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
13
  #include <linux/clk.h>
d482893b1   Frank Li   rtc: snvs: use sy...
14
15
16
17
  #include <linux/mfd/syscon.h>
  #include <linux/regmap.h>
  
  #define SNVS_LPREGISTER_OFFSET	0x34
179a502f8   Shawn Guo   rtc: snvs: add Fr...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  
  /* These register offsets are relative to LP (Low Power) range */
  #define SNVS_LPCR		0x04
  #define SNVS_LPSR		0x18
  #define SNVS_LPSRTCMR		0x1c
  #define SNVS_LPSRTCLR		0x20
  #define SNVS_LPTAR		0x24
  #define SNVS_LPPGDR		0x30
  
  #define SNVS_LPCR_SRTC_ENV	(1 << 0)
  #define SNVS_LPCR_LPTA_EN	(1 << 1)
  #define SNVS_LPCR_LPWUI_EN	(1 << 3)
  #define SNVS_LPSR_LPTA		(1 << 0)
  
  #define SNVS_LPPGDR_INIT	0x41736166
  #define CNTR_TO_SECS_SH		15
  
  struct snvs_rtc_data {
  	struct rtc_device *rtc;
d482893b1   Frank Li   rtc: snvs: use sy...
37
38
  	struct regmap *regmap;
  	int offset;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
39
  	int irq;
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
40
  	struct clk *clk;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
41
  };
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
42
43
44
45
46
47
48
49
50
51
52
53
54
  /* Read 64 bit timer register, which could be in inconsistent state */
  static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
  {
  	u32 msb, lsb;
  
  	regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
  	regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
  	return (u64)msb << 32 | lsb;
  }
  
  /* Read the secure real time counter, taking care to deal with the cases of the
   * counter updating while being read.
   */
d482893b1   Frank Li   rtc: snvs: use sy...
55
  static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
179a502f8   Shawn Guo   rtc: snvs: add Fr...
56
57
  {
  	u64 read1, read2;
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
58
  	unsigned int timeout = 100;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
59

cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
60
61
62
63
64
  	/* As expected, the registers might update between the read of the LSB
  	 * reg and the MSB reg.  It's also possible that one register might be
  	 * in partially modified state as well.
  	 */
  	read1 = rtc_read_lpsrt(data);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
65
  	do {
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
66
67
68
69
70
71
  		read2 = read1;
  		read1 = rtc_read_lpsrt(data);
  	} while (read1 != read2 && --timeout);
  	if (!timeout)
  		dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read
  ");
179a502f8   Shawn Guo   rtc: snvs: add Fr...
72
73
74
75
  
  	/* Convert 47-bit counter to 32-bit raw second count */
  	return (u32) (read1 >> CNTR_TO_SECS_SH);
  }
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
76
77
  /* Just read the lsb from the counter, dealing with inconsistent state */
  static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
179a502f8   Shawn Guo   rtc: snvs: add Fr...
78
  {
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
79
80
81
82
83
84
85
86
87
88
89
90
  	u32 count1, count2;
  	unsigned int timeout = 100;
  
  	regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
  	do {
  		count2 = count1;
  		regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
  	} while (count1 != count2 && --timeout);
  	if (!timeout) {
  		dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read
  ");
  		return -ETIMEDOUT;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
91
  	}
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  
  	*lsb = count1;
  	return 0;
  }
  
  static int rtc_write_sync_lp(struct snvs_rtc_data *data)
  {
  	u32 count1, count2;
  	u32 elapsed;
  	unsigned int timeout = 1000;
  	int ret;
  
  	ret = rtc_read_lp_counter_lsb(data, &count1);
  	if (ret)
  		return ret;
  
  	/* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
  	do {
  		ret = rtc_read_lp_counter_lsb(data, &count2);
  		if (ret)
  			return ret;
  		elapsed = count2 - count1; /* wrap around _is_ handled! */
  	} while (elapsed < 3 && --timeout);
  	if (!timeout) {
  		dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change
  ");
  		return -ETIMEDOUT;
  	}
  	return 0;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
121
122
123
124
  }
  
  static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
  {
179a502f8   Shawn Guo   rtc: snvs: add Fr...
125
126
  	int timeout = 1000;
  	u32 lpcr;
d482893b1   Frank Li   rtc: snvs: use sy...
127
128
  	regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_SRTC_ENV,
  			   enable ? SNVS_LPCR_SRTC_ENV : 0);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
129
130
  
  	while (--timeout) {
d482893b1   Frank Li   rtc: snvs: use sy...
131
  		regmap_read(data->regmap, data->offset + SNVS_LPCR, &lpcr);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  
  		if (enable) {
  			if (lpcr & SNVS_LPCR_SRTC_ENV)
  				break;
  		} else {
  			if (!(lpcr & SNVS_LPCR_SRTC_ENV))
  				break;
  		}
  	}
  
  	if (!timeout)
  		return -ETIMEDOUT;
  
  	return 0;
  }
  
  static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
4b957bde5   Anson Huang   rtc: snvs: Add ne...
151
152
153
154
155
156
157
158
  	unsigned long time;
  	int ret;
  
  	if (data->clk) {
  		ret = clk_enable(data->clk);
  		if (ret)
  			return ret;
  	}
179a502f8   Shawn Guo   rtc: snvs: add Fr...
159

4b957bde5   Anson Huang   rtc: snvs: Add ne...
160
  	time = rtc_read_lp_counter(data);
c59a9fc72   Alexandre Belloni   rtc: snvs: switch...
161
  	rtc_time64_to_tm(time, tm);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
162

4b957bde5   Anson Huang   rtc: snvs: Add ne...
163
164
  	if (data->clk)
  		clk_disable(data->clk);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
165
166
167
168
169
170
  	return 0;
  }
  
  static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
c59a9fc72   Alexandre Belloni   rtc: snvs: switch...
171
  	unsigned long time = rtc_tm_to_time64(tm);
1485991c0   Bryan O'Donoghue   rtc: snvs: Fix us...
172
  	int ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
173

4b957bde5   Anson Huang   rtc: snvs: Add ne...
174
175
176
177
178
  	if (data->clk) {
  		ret = clk_enable(data->clk);
  		if (ret)
  			return ret;
  	}
179a502f8   Shawn Guo   rtc: snvs: add Fr...
179
  	/* Disable RTC first */
1485991c0   Bryan O'Donoghue   rtc: snvs: Fix us...
180
181
182
  	ret = snvs_rtc_enable(data, false);
  	if (ret)
  		return ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
183
184
  
  	/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
d482893b1   Frank Li   rtc: snvs: use sy...
185
186
  	regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
  	regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
179a502f8   Shawn Guo   rtc: snvs: add Fr...
187
188
  
  	/* Enable RTC again */
1485991c0   Bryan O'Donoghue   rtc: snvs: Fix us...
189
  	ret = snvs_rtc_enable(data, true);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
190

4b957bde5   Anson Huang   rtc: snvs: Add ne...
191
192
  	if (data->clk)
  		clk_disable(data->clk);
1485991c0   Bryan O'Donoghue   rtc: snvs: Fix us...
193
  	return ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
194
195
196
197
198
199
  }
  
  static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
  	u32 lptar, lpsr;
4b957bde5   Anson Huang   rtc: snvs: Add ne...
200
201
202
203
204
205
206
  	int ret;
  
  	if (data->clk) {
  		ret = clk_enable(data->clk);
  		if (ret)
  			return ret;
  	}
179a502f8   Shawn Guo   rtc: snvs: add Fr...
207

d482893b1   Frank Li   rtc: snvs: use sy...
208
  	regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
c59a9fc72   Alexandre Belloni   rtc: snvs: switch...
209
  	rtc_time64_to_tm(lptar, &alrm->time);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
210

d482893b1   Frank Li   rtc: snvs: use sy...
211
  	regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
212
  	alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
4b957bde5   Anson Huang   rtc: snvs: Add ne...
213
214
  	if (data->clk)
  		clk_disable(data->clk);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
215
216
217
218
219
220
  	return 0;
  }
  
  static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
4b957bde5   Anson Huang   rtc: snvs: Add ne...
221
222
223
224
225
226
227
  	int ret;
  
  	if (data->clk) {
  		ret = clk_enable(data->clk);
  		if (ret)
  			return ret;
  	}
179a502f8   Shawn Guo   rtc: snvs: add Fr...
228

d482893b1   Frank Li   rtc: snvs: use sy...
229
230
231
  	regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
  			   (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
  			   enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
232

4b957bde5   Anson Huang   rtc: snvs: Add ne...
233
234
235
236
237
238
  	ret = rtc_write_sync_lp(data);
  
  	if (data->clk)
  		clk_disable(data->clk);
  
  	return ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
239
240
241
242
243
  }
  
  static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
c59a9fc72   Alexandre Belloni   rtc: snvs: switch...
244
  	unsigned long time = rtc_tm_to_time64(&alrm->time);
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
245
  	int ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
246

4b957bde5   Anson Huang   rtc: snvs: Add ne...
247
248
249
250
251
  	if (data->clk) {
  		ret = clk_enable(data->clk);
  		if (ret)
  			return ret;
  	}
d482893b1   Frank Li   rtc: snvs: use sy...
252
  	regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
cd7f3a249   Trent Piepho   rtc: snvs: Add ti...
253
254
255
  	ret = rtc_write_sync_lp(data);
  	if (ret)
  		return ret;
d482893b1   Frank Li   rtc: snvs: use sy...
256
  	regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
257
258
  
  	/* Clear alarm interrupt status bit */
d482893b1   Frank Li   rtc: snvs: use sy...
259
  	regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
260

4b957bde5   Anson Huang   rtc: snvs: Add ne...
261
262
  	if (data->clk)
  		clk_disable(data->clk);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
  	return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
  }
  
  static const struct rtc_class_ops snvs_rtc_ops = {
  	.read_time = snvs_rtc_read_time,
  	.set_time = snvs_rtc_set_time,
  	.read_alarm = snvs_rtc_read_alarm,
  	.set_alarm = snvs_rtc_set_alarm,
  	.alarm_irq_enable = snvs_rtc_alarm_irq_enable,
  };
  
  static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
  {
  	struct device *dev = dev_id;
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
  	u32 lpsr;
  	u32 events = 0;
edb190cb1   Anson Huang   rtc: snvs: make s...
280
281
  	if (data->clk)
  		clk_enable(data->clk);
d482893b1   Frank Li   rtc: snvs: use sy...
282
  	regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
283
284
285
286
287
288
289
290
291
292
293
  
  	if (lpsr & SNVS_LPSR_LPTA) {
  		events |= (RTC_AF | RTC_IRQF);
  
  		/* RTC alarm should be one-shot */
  		snvs_rtc_alarm_irq_enable(dev, 0);
  
  		rtc_update_irq(data->rtc, 1, events);
  	}
  
  	/* clear interrupt status */
d482893b1   Frank Li   rtc: snvs: use sy...
294
  	regmap_write(data->regmap, data->offset + SNVS_LPSR, lpsr);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
295

edb190cb1   Anson Huang   rtc: snvs: make s...
296
297
  	if (data->clk)
  		clk_disable(data->clk);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
298
299
  	return events ? IRQ_HANDLED : IRQ_NONE;
  }
d482893b1   Frank Li   rtc: snvs: use sy...
300
301
302
303
304
  static const struct regmap_config snvs_rtc_config = {
  	.reg_bits = 32,
  	.val_bits = 32,
  	.reg_stride = 4,
  };
7863bd076   Anson Huang   rtc: snvs: Use de...
305
306
307
308
309
  static void snvs_rtc_action(void *data)
  {
  	if (data)
  		clk_disable_unprepare(data);
  }
5a167f454   Greg Kroah-Hartman   Drivers: rtc: rem...
310
  static int snvs_rtc_probe(struct platform_device *pdev)
179a502f8   Shawn Guo   rtc: snvs: add Fr...
311
312
  {
  	struct snvs_rtc_data *data;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
313
  	int ret;
d482893b1   Frank Li   rtc: snvs: use sy...
314
  	void __iomem *mmio;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
315
316
317
318
  
  	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  	if (!data)
  		return -ENOMEM;
6fd4fe9b4   Anson Huang   rtc: snvs: fix po...
319
320
321
  	data->rtc = devm_rtc_allocate_device(&pdev->dev);
  	if (IS_ERR(data->rtc))
  		return PTR_ERR(data->rtc);
d482893b1   Frank Li   rtc: snvs: use sy...
322
323
324
325
326
  	data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
  
  	if (IS_ERR(data->regmap)) {
  		dev_warn(&pdev->dev, "snvs rtc: you use old dts file, please update it
  ");
d482893b1   Frank Li   rtc: snvs: use sy...
327

0c46b07ce   Anson Huang   rtc: snvs: use de...
328
  		mmio = devm_platform_ioremap_resource(pdev, 0);
d482893b1   Frank Li   rtc: snvs: use sy...
329
330
331
332
333
334
335
336
  		if (IS_ERR(mmio))
  			return PTR_ERR(mmio);
  
  		data->regmap = devm_regmap_init_mmio(&pdev->dev, mmio, &snvs_rtc_config);
  	} else {
  		data->offset = SNVS_LPREGISTER_OFFSET;
  		of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
  	}
758929005   Pan Bian   rtc: snvs: fix an...
337
  	if (IS_ERR(data->regmap)) {
d482893b1   Frank Li   rtc: snvs: use sy...
338
339
340
341
  		dev_err(&pdev->dev, "Can't find snvs syscon
  ");
  		return -ENODEV;
  	}
179a502f8   Shawn Guo   rtc: snvs: add Fr...
342
343
344
345
  
  	data->irq = platform_get_irq(pdev, 0);
  	if (data->irq < 0)
  		return data->irq;
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
346
347
348
349
350
351
352
353
354
355
356
357
  	data->clk = devm_clk_get(&pdev->dev, "snvs-rtc");
  	if (IS_ERR(data->clk)) {
  		data->clk = NULL;
  	} else {
  		ret = clk_prepare_enable(data->clk);
  		if (ret) {
  			dev_err(&pdev->dev,
  				"Could not prepare or enable the snvs clock
  ");
  			return ret;
  		}
  	}
7863bd076   Anson Huang   rtc: snvs: Use de...
358
359
360
  	ret = devm_add_action_or_reset(&pdev->dev, snvs_rtc_action, data->clk);
  	if (ret)
  		return ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
361
  	platform_set_drvdata(pdev, data);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
362
  	/* Initialize glitch detect */
d482893b1   Frank Li   rtc: snvs: use sy...
363
  	regmap_write(data->regmap, data->offset + SNVS_LPPGDR, SNVS_LPPGDR_INIT);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
364
365
  
  	/* Clear interrupt status */
d482893b1   Frank Li   rtc: snvs: use sy...
366
  	regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
367
368
  
  	/* Enable RTC */
1485991c0   Bryan O'Donoghue   rtc: snvs: Fix us...
369
370
371
372
  	ret = snvs_rtc_enable(data, true);
  	if (ret) {
  		dev_err(&pdev->dev, "failed to enable rtc %d
  ", ret);
7863bd076   Anson Huang   rtc: snvs: Use de...
373
  		return ret;
1485991c0   Bryan O'Donoghue   rtc: snvs: Fix us...
374
  	}
179a502f8   Shawn Guo   rtc: snvs: add Fr...
375
376
  
  	device_init_wakeup(&pdev->dev, true);
e7afddb2b   Anson Huang   rtc: snvs: use de...
377
378
379
380
  	ret = dev_pm_set_wake_irq(&pdev->dev, data->irq);
  	if (ret)
  		dev_err(&pdev->dev, "failed to enable irq wake
  ");
179a502f8   Shawn Guo   rtc: snvs: add Fr...
381
382
383
384
385
386
387
  
  	ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler,
  			       IRQF_SHARED, "rtc alarm", &pdev->dev);
  	if (ret) {
  		dev_err(&pdev->dev, "failed to request irq %d: %d
  ",
  			data->irq, ret);
7863bd076   Anson Huang   rtc: snvs: Use de...
388
  		return ret;
179a502f8   Shawn Guo   rtc: snvs: add Fr...
389
  	}
6fd4fe9b4   Anson Huang   rtc: snvs: fix po...
390
  	data->rtc->ops = &snvs_rtc_ops;
79610340c   Alexandre Belloni   rtc: snvs: set range
391
  	data->rtc->range_max = U32_MAX;
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
392

7863bd076   Anson Huang   rtc: snvs: Use de...
393
  	return rtc_register_device(data->rtc);
179a502f8   Shawn Guo   rtc: snvs: add Fr...
394
  }
dacb6a403   Anson Huang   rtc: snvs: Use __...
395
  static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev)
119434f44   Stefan Agner   rtc: snvs: fix wa...
396
397
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
398
  	if (data->clk)
20af67700   Anson Huang   rtc: snvs: Make S...
399
  		clk_disable(data->clk);
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
400

179a502f8   Shawn Guo   rtc: snvs: add Fr...
401
402
  	return 0;
  }
dacb6a403   Anson Huang   rtc: snvs: Use __...
403
  static int __maybe_unused snvs_rtc_resume_noirq(struct device *dev)
119434f44   Stefan Agner   rtc: snvs: fix wa...
404
405
406
407
  {
  	struct snvs_rtc_data *data = dev_get_drvdata(dev);
  
  	if (data->clk)
20af67700   Anson Huang   rtc: snvs: Make S...
408
  		return clk_enable(data->clk);
7f8993995   Sanchayan Maity   drivers/rtc/rtc-s...
409

179a502f8   Shawn Guo   rtc: snvs: add Fr...
410
411
  	return 0;
  }
179a502f8   Shawn Guo   rtc: snvs: add Fr...
412

7654e9d4f   Sanchayan Maity   drivers/rtc/rtc-s...
413
  static const struct dev_pm_ops snvs_rtc_pm_ops = {
dacb6a403   Anson Huang   rtc: snvs: Use __...
414
  	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(snvs_rtc_suspend_noirq, snvs_rtc_resume_noirq)
7654e9d4f   Sanchayan Maity   drivers/rtc/rtc-s...
415
  };
179a502f8   Shawn Guo   rtc: snvs: add Fr...
416

5a167f454   Greg Kroah-Hartman   Drivers: rtc: rem...
417
  static const struct of_device_id snvs_dt_ids[] = {
179a502f8   Shawn Guo   rtc: snvs: add Fr...
418
419
420
421
422
423
424
425
  	{ .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
  	{ /* sentinel */ }
  };
  MODULE_DEVICE_TABLE(of, snvs_dt_ids);
  
  static struct platform_driver snvs_rtc_driver = {
  	.driver = {
  		.name	= "snvs_rtc",
dacb6a403   Anson Huang   rtc: snvs: Use __...
426
  		.pm	= &snvs_rtc_pm_ops,
c39b3717b   Sachin Kamat   drivers/rtc/rtc-s...
427
  		.of_match_table = snvs_dt_ids,
179a502f8   Shawn Guo   rtc: snvs: add Fr...
428
429
  	},
  	.probe		= snvs_rtc_probe,
179a502f8   Shawn Guo   rtc: snvs: add Fr...
430
431
432
433
434
435
  };
  module_platform_driver(snvs_rtc_driver);
  
  MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  MODULE_DESCRIPTION("Freescale SNVS RTC Driver");
  MODULE_LICENSE("GPL");