Blame view

drivers/rtc/rtc-jz4740.c 9.83 KB
86836d641   Alexandre Belloni   rtc: jz4740: conv...
1
  // SPDX-License-Identifier: GPL-2.0+
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
2
3
  /*
   *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
d0f744c8c   Paul Cercueil   drivers/rtc/rtc-j...
4
   *  Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net>
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
5
   *	 JZ4740 SoC RTC driver
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
6
   */
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
7
  #include <linux/clk.h>
c08ac4894   Jingoo Han   rtc: rtc-jz4740: ...
8
  #include <linux/io.h>
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
9
  #include <linux/kernel.h>
586655d27   Alexandre Belloni   rtc: jz4740: make...
10
  #include <linux/module.h>
c05229a89   Paul Cercueil   rtc: jz4740: Add ...
11
  #include <linux/of_device.h>
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
12
  #include <linux/platform_device.h>
3b2dc19ff   Alexandre Belloni   rtc: jz4740: use ...
13
  #include <linux/pm_wakeirq.h>
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
14
  #include <linux/reboot.h>
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
15
16
17
18
19
20
21
22
23
  #include <linux/rtc.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  
  #define JZ_REG_RTC_CTRL		0x00
  #define JZ_REG_RTC_SEC		0x04
  #define JZ_REG_RTC_SEC_ALARM	0x08
  #define JZ_REG_RTC_REGULATOR	0x0C
  #define JZ_REG_RTC_HIBERNATE	0x20
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
24
25
  #define JZ_REG_RTC_WAKEUP_FILTER	0x24
  #define JZ_REG_RTC_RESET_COUNTER	0x28
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
26
  #define JZ_REG_RTC_SCRATCHPAD	0x34
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
27
28
29
  /* The following are present on the jz4780 */
  #define JZ_REG_RTC_WENR	0x3C
  #define JZ_RTC_WENR_WEN	BIT(31)
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
30
31
32
33
34
35
36
  #define JZ_RTC_CTRL_WRDY	BIT(7)
  #define JZ_RTC_CTRL_1HZ		BIT(6)
  #define JZ_RTC_CTRL_1HZ_IRQ	BIT(5)
  #define JZ_RTC_CTRL_AF		BIT(4)
  #define JZ_RTC_CTRL_AF_IRQ	BIT(3)
  #define JZ_RTC_CTRL_AE		BIT(2)
  #define JZ_RTC_CTRL_ENABLE	BIT(0)
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
37
38
  /* Magic value to enable writes on jz4780 */
  #define JZ_RTC_WENR_MAGIC	0xA55A
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
39
40
  #define JZ_RTC_WAKEUP_FILTER_MASK	0x0000FFE0
  #define JZ_RTC_RESET_COUNTER_MASK	0x00000FE0
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
41
42
  enum jz4740_rtc_type {
  	ID_JZ4740,
584074852   Paul Cercueil   rtc: jz4740: Add ...
43
  	ID_JZ4760,
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
44
45
  	ID_JZ4780,
  };
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
46
  struct jz4740_rtc {
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
47
  	void __iomem *base;
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
48
  	enum jz4740_rtc_type type;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
49
50
  
  	struct rtc_device *rtc;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
51
52
53
  
  	spinlock_t lock;
  };
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
54
  static struct device *dev_for_power_off;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
55
56
57
58
59
60
61
62
  static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
  {
  	return readl(rtc->base + reg);
  }
  
  static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
  {
  	uint32_t ctrl;
695e38d88   Mathieu Malaterre   rtc: jz4740: fix ...
63
  	int timeout = 10000;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
64
65
66
67
68
69
70
  
  	do {
  		ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
  	} while (!(ctrl & JZ_RTC_CTRL_WRDY) && --timeout);
  
  	return timeout ? 0 : -EIO;
  }
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
71
72
73
  static inline int jz4780_rtc_enable_write(struct jz4740_rtc *rtc)
  {
  	uint32_t ctrl;
695e38d88   Mathieu Malaterre   rtc: jz4740: fix ...
74
  	int ret, timeout = 10000;
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
75
76
77
78
79
80
81
82
83
84
85
86
87
  
  	ret = jz4740_rtc_wait_write_ready(rtc);
  	if (ret != 0)
  		return ret;
  
  	writel(JZ_RTC_WENR_MAGIC, rtc->base + JZ_REG_RTC_WENR);
  
  	do {
  		ctrl = readl(rtc->base + JZ_REG_RTC_WENR);
  	} while (!(ctrl & JZ_RTC_WENR_WEN) && --timeout);
  
  	return timeout ? 0 : -EIO;
  }
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
88
89
90
  static inline int jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
  	uint32_t val)
  {
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
91
  	int ret = 0;
584074852   Paul Cercueil   rtc: jz4740: Add ...
92
  	if (rtc->type >= ID_JZ4760)
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
93
94
95
  		ret = jz4780_rtc_enable_write(rtc);
  	if (ret == 0)
  		ret = jz4740_rtc_wait_write_ready(rtc);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
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
121
122
123
124
125
126
127
128
129
130
131
132
  	if (ret == 0)
  		writel(val, rtc->base + reg);
  
  	return ret;
  }
  
  static int jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask,
  	bool set)
  {
  	int ret;
  	unsigned long flags;
  	uint32_t ctrl;
  
  	spin_lock_irqsave(&rtc->lock, flags);
  
  	ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
  
  	/* Don't clear interrupt flags by accident */
  	ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF;
  
  	if (set)
  		ctrl |= mask;
  	else
  		ctrl &= ~mask;
  
  	ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl);
  
  	spin_unlock_irqrestore(&rtc->lock, flags);
  
  	return ret;
  }
  
  static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
  {
  	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
  	uint32_t secs, secs2;
  	int timeout = 5;
7fe8fcee0   Alexandre Belloni   rtc: jz4740: rewo...
133
134
  	if (jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD) != 0x12345678)
  		return -EINVAL;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  	/* If the seconds register is read while it is updated, it can contain a
  	 * bogus value. This can be avoided by making sure that two consecutive
  	 * reads have the same value.
  	 */
  	secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
  	secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
  
  	while (secs != secs2 && --timeout) {
  		secs = secs2;
  		secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
  	}
  
  	if (timeout == 0)
  		return -EIO;
be8dce96f   Alexandre Belloni   rtc: jz4740: swit...
149
  	rtc_time64_to_tm(secs, time);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
150

ab62670e5   Alexandre Belloni   rtc: stop validat...
151
  	return 0;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
152
  }
e72746e79   Alexandre Belloni   rtc: jz4740: use ...
153
  static int jz4740_rtc_set_time(struct device *dev, struct rtc_time *time)
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
154
155
  {
  	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
7fe8fcee0   Alexandre Belloni   rtc: jz4740: rewo...
156
157
158
159
160
  	int ret;
  
  	ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, rtc_tm_to_time64(time));
  	if (ret)
  		return ret;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
161

7fe8fcee0   Alexandre Belloni   rtc: jz4740: rewo...
162
  	return jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  }
  
  static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
  	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
  	uint32_t secs;
  	uint32_t ctrl;
  
  	secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
  
  	ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
  
  	alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE);
  	alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF);
be8dce96f   Alexandre Belloni   rtc: jz4740: swit...
177
  	rtc_time64_to_tm(secs, &alrm->time);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
178

d10dcc95f   Alexandre Belloni   rtc: jz4740: remo...
179
  	return 0;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
180
181
182
183
184
185
  }
  
  static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
  	int ret;
  	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
be8dce96f   Alexandre Belloni   rtc: jz4740: swit...
186
  	uint32_t secs = lower_32_bits(rtc_tm_to_time64(&alrm->time));
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
187
188
189
  
  	ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs);
  	if (!ret)
d0f744c8c   Paul Cercueil   drivers/rtc/rtc-j...
190
191
  		ret = jz4740_rtc_ctrl_set_bits(rtc,
  			JZ_RTC_CTRL_AE | JZ_RTC_CTRL_AF_IRQ, alrm->enabled);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
192
193
194
  
  	return ret;
  }
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
195
196
197
198
199
  static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
  {
  	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
  	return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable);
  }
34c7b3ac4   Julia Lawall   rtc: constify rtc...
200
  static const struct rtc_class_ops jz4740_rtc_ops = {
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
201
  	.read_time	= jz4740_rtc_read_time,
e72746e79   Alexandre Belloni   rtc: jz4740: use ...
202
  	.set_time	= jz4740_rtc_set_time,
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
203
204
  	.read_alarm	= jz4740_rtc_read_alarm,
  	.set_alarm	= jz4740_rtc_set_alarm,
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  	.alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
  };
  
  static irqreturn_t jz4740_rtc_irq(int irq, void *data)
  {
  	struct jz4740_rtc *rtc = data;
  	uint32_t ctrl;
  	unsigned long events = 0;
  
  	ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
  
  	if (ctrl & JZ_RTC_CTRL_1HZ)
  		events |= (RTC_UF | RTC_IRQF);
  
  	if (ctrl & JZ_RTC_CTRL_AF)
  		events |= (RTC_AF | RTC_IRQF);
  
  	rtc_update_irq(rtc->rtc, 1, events);
  
  	jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, false);
  
  	return IRQ_HANDLED;
  }
819c21785   Alexandre Belloni   rtc: jz4740: remo...
228
  static void jz4740_rtc_poweroff(struct device *dev)
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
229
230
231
232
  {
  	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
  	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1);
  }
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
233

f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
234
235
  static void jz4740_rtc_power_off(void)
  {
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
236
  	jz4740_rtc_poweroff(dev_for_power_off);
586655d27   Alexandre Belloni   rtc: jz4740: make...
237
  	kernel_halt();
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
238
  }
796be8b59   Paul Cercueil   rtc: ingenic: Ena...
239
240
241
242
  static void jz4740_rtc_clk_disable(void *data)
  {
  	clk_disable_unprepare(data);
  }
c05229a89   Paul Cercueil   rtc: jz4740: Add ...
243
244
  static const struct of_device_id jz4740_rtc_of_match[] = {
  	{ .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 },
584074852   Paul Cercueil   rtc: jz4740: Add ...
245
  	{ .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 },
c05229a89   Paul Cercueil   rtc: jz4740: Add ...
246
247
248
  	{ .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 },
  	{},
  };
586655d27   Alexandre Belloni   rtc: jz4740: make...
249
  MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match);
c05229a89   Paul Cercueil   rtc: jz4740: Add ...
250

fe0557f4d   Paul Cercueil   rtc: ingenic: Set...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  static void jz4740_rtc_set_wakeup_params(struct jz4740_rtc *rtc,
  					 struct device_node *np,
  					 unsigned long rate)
  {
  	unsigned long wakeup_ticks, reset_ticks;
  	unsigned int min_wakeup_pin_assert_time = 60; /* Default: 60ms */
  	unsigned int reset_pin_assert_time = 100; /* Default: 100ms */
  
  	of_property_read_u32(np, "ingenic,reset-pin-assert-time-ms",
  			     &reset_pin_assert_time);
  	of_property_read_u32(np, "ingenic,min-wakeup-pin-assert-time-ms",
  			     &min_wakeup_pin_assert_time);
  
  	/*
  	 * Set minimum wakeup pin assertion time: 100 ms.
  	 * Range is 0 to 2 sec if RTC is clocked at 32 kHz.
  	 */
  	wakeup_ticks = (min_wakeup_pin_assert_time * rate) / 1000;
  	if (wakeup_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
  		wakeup_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
  	else
  		wakeup_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
  	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_WAKEUP_FILTER, wakeup_ticks);
  
  	/*
  	 * Set reset pin low-level assertion time after wakeup: 60 ms.
  	 * Range is 0 to 125 ms if RTC is clocked at 32 kHz.
  	 */
  	reset_ticks = (reset_pin_assert_time * rate) / 1000;
  	if (reset_ticks < JZ_RTC_RESET_COUNTER_MASK)
  		reset_ticks &= JZ_RTC_RESET_COUNTER_MASK;
  	else
  		reset_ticks = JZ_RTC_RESET_COUNTER_MASK;
  	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_RESET_COUNTER, reset_ticks);
  }
5a167f454   Greg Kroah-Hartman   Drivers: rtc: rem...
286
  static int jz4740_rtc_probe(struct platform_device *pdev)
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
287
  {
c61293f14   Paul Cercueil   rtc: ingenic: Use...
288
289
  	struct device *dev = &pdev->dev;
  	struct device_node *np = dev->of_node;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
290
  	struct jz4740_rtc *rtc;
fe0557f4d   Paul Cercueil   rtc: ingenic: Set...
291
  	unsigned long rate;
77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
292
293
  	struct clk *clk;
  	int ret, irq;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
294

c61293f14   Paul Cercueil   rtc: ingenic: Use...
295
  	rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
296
297
  	if (!rtc)
  		return -ENOMEM;
24e1f2c93   Paul Cercueil   rtc: ingenic: Onl...
298
  	rtc->type = (enum jz4740_rtc_type)device_get_match_data(dev);
cd563200c   Paul Cercueil   rtc: jz4740: Add ...
299

77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
300
301
  	irq = platform_get_irq(pdev, 0);
  	if (irq < 0)
15eeadd80   Paul Cercueil   rtc: ingenic: Fix...
302
  		return irq;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
303

09ef18bcd   YueHaibing   rtc: use devm_pla...
304
  	rtc->base = devm_platform_ioremap_resource(pdev, 0);
3b6aa907f   Jingoo Han   rtc: rtc-jz4740: ...
305
306
  	if (IS_ERR(rtc->base))
  		return PTR_ERR(rtc->base);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
307

77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
308
309
  	clk = devm_clk_get(dev, "rtc");
  	if (IS_ERR(clk)) {
c61293f14   Paul Cercueil   rtc: ingenic: Use...
310
311
  		dev_err(dev, "Failed to get RTC clock
  ");
77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
312
  		return PTR_ERR(clk);
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
313
  	}
77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
314
  	ret = clk_prepare_enable(clk);
796be8b59   Paul Cercueil   rtc: ingenic: Ena...
315
316
317
318
319
  	if (ret) {
  		dev_err(dev, "Failed to enable clock
  ");
  		return ret;
  	}
77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
320
  	ret = devm_add_action_or_reset(dev, jz4740_rtc_clk_disable, clk);
796be8b59   Paul Cercueil   rtc: ingenic: Ena...
321
322
323
324
325
  	if (ret) {
  		dev_err(dev, "Failed to register devm action
  ");
  		return ret;
  	}
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
326
327
328
  	spin_lock_init(&rtc->lock);
  
  	platform_set_drvdata(pdev, rtc);
c61293f14   Paul Cercueil   rtc: ingenic: Use...
329
  	device_init_wakeup(dev, 1);
d0f744c8c   Paul Cercueil   drivers/rtc/rtc-j...
330

77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
331
  	ret = dev_pm_set_wake_irq(dev, irq);
3b2dc19ff   Alexandre Belloni   rtc: jz4740: use ...
332
  	if (ret) {
c61293f14   Paul Cercueil   rtc: ingenic: Use...
333
334
  		dev_err(dev, "Failed to set wake irq: %d
  ", ret);
3b2dc19ff   Alexandre Belloni   rtc: jz4740: use ...
335
336
  		return ret;
  	}
c61293f14   Paul Cercueil   rtc: ingenic: Use...
337
  	rtc->rtc = devm_rtc_allocate_device(dev);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
338
339
  	if (IS_ERR(rtc->rtc)) {
  		ret = PTR_ERR(rtc->rtc);
c61293f14   Paul Cercueil   rtc: ingenic: Use...
340
341
  		dev_err(dev, "Failed to allocate rtc device: %d
  ", ret);
a7ab6bed2   Alexandre Belloni   rtc: jz4740: set ...
342
343
344
345
346
  		return ret;
  	}
  
  	rtc->rtc->ops = &jz4740_rtc_ops;
  	rtc->rtc->range_max = U32_MAX;
77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
347
  	rate = clk_get_rate(clk);
fe0557f4d   Paul Cercueil   rtc: ingenic: Set...
348
  	jz4740_rtc_set_wakeup_params(rtc, np, rate);
378252b6e   Paul Cercueil   rtc: ingenic: Res...
349
350
  	/* Each 1 Hz pulse should happen after (rate) ticks */
  	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_REGULATOR, rate - 1);
a7ab6bed2   Alexandre Belloni   rtc: jz4740: set ...
351
  	ret = rtc_register_device(rtc->rtc);
44c638ce4   Alexandre Belloni   rtc: remove super...
352
  	if (ret)
c08ac4894   Jingoo Han   rtc: rtc-jz4740: ...
353
  		return ret;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
354

77d8f3c12   Paul Cercueil   rtc: ingenic: Rem...
355
  	ret = devm_request_irq(dev, irq, jz4740_rtc_irq, 0,
c61293f14   Paul Cercueil   rtc: ingenic: Use...
356
  			       pdev->name, rtc);
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
357
  	if (ret) {
c61293f14   Paul Cercueil   rtc: ingenic: Use...
358
359
  		dev_err(dev, "Failed to request rtc irq: %d
  ", ret);
c08ac4894   Jingoo Han   rtc: rtc-jz4740: ...
360
  		return ret;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
361
  	}
24e1f2c93   Paul Cercueil   rtc: ingenic: Onl...
362
  	if (of_device_is_system_power_controller(np)) {
fe0557f4d   Paul Cercueil   rtc: ingenic: Set...
363
364
365
  		dev_for_power_off = dev;
  
  		if (!pm_power_off)
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
366
  			pm_power_off = jz4740_rtc_power_off;
fe0557f4d   Paul Cercueil   rtc: ingenic: Set...
367
  		else
c61293f14   Paul Cercueil   rtc: ingenic: Use...
368
369
  			dev_warn(dev, "Poweroff handler already present!
  ");
f9eb69d1a   Paul Cercueil   rtc: jz4740: Add ...
370
  	}
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
371
  	return 0;
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
372
  }
681d0378a   Axel Lin   drivers/rtc/rtc-j...
373
  static struct platform_driver jz4740_rtc_driver = {
d0f744c8c   Paul Cercueil   drivers/rtc/rtc-j...
374
  	.probe	 = jz4740_rtc_probe,
d0f744c8c   Paul Cercueil   drivers/rtc/rtc-j...
375
376
  	.driver	 = {
  		.name  = "jz4740-rtc",
24e1f2c93   Paul Cercueil   rtc: ingenic: Onl...
377
  		.of_match_table = jz4740_rtc_of_match,
3bf0eea89   Lars-Peter Clausen   RTC: Add JZ4740 R...
378
379
  	},
  };
586655d27   Alexandre Belloni   rtc: jz4740: make...
380
381
382
383
384
385
386
  module_platform_driver(jz4740_rtc_driver);
  
  MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC
  ");
  MODULE_ALIAS("platform:jz4740-rtc");