Blame view

drivers/rtc/rtc-s3c.c 20 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1add6781c   Ben Dooks   [PATCH] RTC: clas...
2
3
  /* drivers/rtc/rtc-s3c.c
   *
e48add8c1   Atul Dahiya   rtc: rtc-s3c: Upd...
4
5
6
   * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   *		http://www.samsung.com/
   *
1add6781c   Ben Dooks   [PATCH] RTC: clas...
7
8
9
10
   * Copyright (c) 2004,2006 Simtec Electronics
   *	Ben Dooks, <ben@simtec.co.uk>
   *	http://armlinux.simtec.co.uk/
   *
1add6781c   Ben Dooks   [PATCH] RTC: clas...
11
12
13
14
15
16
17
18
19
20
21
22
   * S3C2410/S3C2440/S3C24XX Internal RTC Driver
  */
  
  #include <linux/module.h>
  #include <linux/fs.h>
  #include <linux/string.h>
  #include <linux/init.h>
  #include <linux/platform_device.h>
  #include <linux/interrupt.h>
  #include <linux/rtc.h>
  #include <linux/bcd.h>
  #include <linux/clk.h>
9974b6ea7   Robert P. J. Day   rtc-s3c: Use is_p...
23
  #include <linux/log2.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
39ce4084a   Thomas Abraham   rtc: rtc-s3c: Add...
25
  #include <linux/of.h>
64704c92f   Marek Szyprowski   rtc: s3c: Use gen...
26
  #include <linux/of_device.h>
dbd9acbef   Sachin Kamat   drivers/rtc/rtc-s...
27
28
  #include <linux/uaccess.h>
  #include <linux/io.h>
1add6781c   Ben Dooks   [PATCH] RTC: clas...
29

1add6781c   Ben Dooks   [PATCH] RTC: clas...
30
  #include <asm/irq.h>
b9d7c5d3f   Arnd Bergmann   rtc: s3c: make he...
31
  #include "rtc-s3c.h"
1add6781c   Ben Dooks   [PATCH] RTC: clas...
32

19be09f51   Chanwoo Choi   rtc: s3c: define ...
33
34
35
36
37
38
  struct s3c_rtc {
  	struct device *dev;
  	struct rtc_device *rtc;
  
  	void __iomem *base;
  	struct clk *rtc_clk;
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
39
  	struct clk *rtc_src_clk;
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
40
  	bool alarm_enabled;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
41

6b72086d8   Krzysztof Kozlowski   rtc: s3c: Do not ...
42
  	const struct s3c_rtc_data *data;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
43

19be09f51   Chanwoo Choi   rtc: s3c: define ...
44
45
  	int irq_alarm;
  	int irq_tick;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
46

19be09f51   Chanwoo Choi   rtc: s3c: define ...
47
  	spinlock_t pie_lock;
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
48
  	spinlock_t alarm_lock;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
49

fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
50
51
  	int ticnt_save;
  	int ticnt_en_save;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
52
53
  	bool wake_en;
  };
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
54
55
  struct s3c_rtc_data {
  	int max_user_freq;
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
56
  	bool needs_src_clk;
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
57
58
59
60
61
62
63
64
65
66
  
  	void (*irq_handler) (struct s3c_rtc *info, int mask);
  	void (*set_freq) (struct s3c_rtc *info, int freq);
  	void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq);
  	void (*select_tick_clk) (struct s3c_rtc *info);
  	void (*save_tick_cnt) (struct s3c_rtc *info);
  	void (*restore_tick_cnt) (struct s3c_rtc *info);
  	void (*enable) (struct s3c_rtc *info);
  	void (*disable) (struct s3c_rtc *info);
  };
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
67
  static int s3c_rtc_enable_clk(struct s3c_rtc *info)
88cee8fd7   Donggeun Kim   drivers/rtc/rtc-s...
68
  {
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
69
  	int ret;
88cee8fd7   Donggeun Kim   drivers/rtc/rtc-s...
70

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
71
72
73
  	ret = clk_enable(info->rtc_clk);
  	if (ret)
  		return ret;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
74

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
75
76
77
78
79
  	if (info->data->needs_src_clk) {
  		ret = clk_enable(info->rtc_src_clk);
  		if (ret) {
  			clk_disable(info->rtc_clk);
  			return ret;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
80
  		}
1fb1c35f5   Joonyoung Shim   rtc: s3c: fix dis...
81
  	}
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
82
  	return 0;
24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
83
84
85
86
  }
  
  static void s3c_rtc_disable_clk(struct s3c_rtc *info)
  {
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
87
88
89
  	if (info->data->needs_src_clk)
  		clk_disable(info->rtc_src_clk);
  	clk_disable(info->rtc_clk);
88cee8fd7   Donggeun Kim   drivers/rtc/rtc-s...
90
  }
1add6781c   Ben Dooks   [PATCH] RTC: clas...
91
  /* IRQ Handlers */
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
92
  static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
93
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
94
  	struct s3c_rtc *info = (struct s3c_rtc *)id;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
95

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
96
97
  	if (info->data->irq_handler)
  		info->data->irq_handler(info, S3C2410_INTP_TIC);
88cee8fd7   Donggeun Kim   drivers/rtc/rtc-s...
98

1add6781c   Ben Dooks   [PATCH] RTC: clas...
99
100
  	return IRQ_HANDLED;
  }
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
101
  static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
102
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
103
  	struct s3c_rtc *info = (struct s3c_rtc *)id;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
104

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
105
106
  	if (info->data->irq_handler)
  		info->data->irq_handler(info, S3C2410_INTP_ALM);
2f3478f65   Atul Dahiya   rtc: rtc-s3c: Upd...
107

1add6781c   Ben Dooks   [PATCH] RTC: clas...
108
109
110
111
  	return IRQ_HANDLED;
  }
  
  /* Update control registers */
2ec38a035   Axel Lin   drivers/rtc/rtc-s...
112
  static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
113
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
114
  	struct s3c_rtc *info = dev_get_drvdata(dev);
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
115
  	unsigned long flags;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
116
  	unsigned int tmp;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
117
  	int ret;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
118

19be09f51   Chanwoo Choi   rtc: s3c: define ...
119
120
  	dev_dbg(info->dev, "%s: aie=%d
  ", __func__, enabled);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
121

498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
122
123
124
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
125

19be09f51   Chanwoo Choi   rtc: s3c: define ...
126
  	tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
127

2ec38a035   Axel Lin   drivers/rtc/rtc-s...
128
  	if (enabled)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
129
  		tmp |= S3C2410_RTCALM_ALMEN;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
130
  	writeb(tmp, info->base + S3C2410_RTCALM);
2ec38a035   Axel Lin   drivers/rtc/rtc-s...
131

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
132
  	spin_lock_irqsave(&info->alarm_lock, flags);
88cee8fd7   Donggeun Kim   drivers/rtc/rtc-s...
133

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
134
  	if (info->alarm_enabled && !enabled)
1fb1c35f5   Joonyoung Shim   rtc: s3c: fix dis...
135
  		s3c_rtc_disable_clk(info);
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
136
137
  	else if (!info->alarm_enabled && enabled)
  		ret = s3c_rtc_enable_clk(info);
1fb1c35f5   Joonyoung Shim   rtc: s3c: fix dis...
138

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
139
140
141
142
143
144
  	info->alarm_enabled = enabled;
  	spin_unlock_irqrestore(&info->alarm_lock, flags);
  
  	s3c_rtc_disable_clk(info);
  
  	return ret;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
145
  }
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
146
  /* Set RTC frequency */
19be09f51   Chanwoo Choi   rtc: s3c: define ...
147
  static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
148
  {
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
149
  	int ret;
5d2a50371   Jonathan Cameron   rtc: move power o...
150
151
  	if (!is_power_of_2(freq))
  		return -EINVAL;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
152
153
154
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
155
  	spin_lock_irq(&info->pie_lock);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
156

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
157
158
  	if (info->data->set_freq)
  		info->data->set_freq(info, freq);
25c1a2466   Heiko Stuebner   rtc-s3c: add vari...
159

19be09f51   Chanwoo Choi   rtc: s3c: define ...
160
  	spin_unlock_irq(&info->pie_lock);
70c96dfac   Alim Akhtar   rtc: s3c: Add s3c...
161
  	s3c_rtc_disable_clk(info);
773be7ee9   Ben Dooks   rtc: rtc-s3c: upd...
162
163
  
  	return 0;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
164
165
166
  }
  
  /* Time read/write */
1add6781c   Ben Dooks   [PATCH] RTC: clas...
167
168
  static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
169
  	struct s3c_rtc *info = dev_get_drvdata(dev);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
170
  	unsigned int have_retried = 0;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
171
  	int ret;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
172

498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
173
174
175
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
176

fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
177
  retry_get_time:
19be09f51   Chanwoo Choi   rtc: s3c: define ...
178
179
180
181
182
183
  	rtc_tm->tm_min  = readb(info->base + S3C2410_RTCMIN);
  	rtc_tm->tm_hour = readb(info->base + S3C2410_RTCHOUR);
  	rtc_tm->tm_mday = readb(info->base + S3C2410_RTCDATE);
  	rtc_tm->tm_mon  = readb(info->base + S3C2410_RTCMON);
  	rtc_tm->tm_year = readb(info->base + S3C2410_RTCYEAR);
  	rtc_tm->tm_sec  = readb(info->base + S3C2410_RTCSEC);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
184

48fc7f7e7   Adam Buchbinder   Fix misspellings ...
185
  	/* the only way to work out whether the system was mid-update
1add6781c   Ben Dooks   [PATCH] RTC: clas...
186
187
188
189
190
191
192
193
  	 * when we read it is to check the second counter, and if it
  	 * is zero, then we re-try the entire read
  	 */
  
  	if (rtc_tm->tm_sec == 0 && !have_retried) {
  		have_retried = 1;
  		goto retry_get_time;
  	}
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
194
195
196
197
198
199
  	rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
  	rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
  	rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
  	rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
  	rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
  	rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
200

24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
201
  	s3c_rtc_disable_clk(info);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
202
203
  	rtc_tm->tm_year += 100;
  	rtc_tm->tm_mon -= 1;
9a1bacf42   Andy Shevchenko   rtc: s3c: Switch ...
204
205
  	dev_dbg(dev, "read time %ptR
  ", rtc_tm);
22652ba72   Alexandre Belloni   rtc: stop validat...
206
  	return 0;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
207
208
209
210
  }
  
  static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
211
  	struct s3c_rtc *info = dev_get_drvdata(dev);
641741e01   Ben Dooks   [PATCH] rtc-s3c.c...
212
  	int year = tm->tm_year - 100;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
213
  	int ret;
9a654518e   Ben Dooks   [PATCH] drivers/r...
214

9a1bacf42   Andy Shevchenko   rtc: s3c: Switch ...
215
216
  	dev_dbg(dev, "set time %ptR
  ", tm);
641741e01   Ben Dooks   [PATCH] rtc-s3c.c...
217
218
  
  	/* we get around y2k by simply not supporting it */
1add6781c   Ben Dooks   [PATCH] RTC: clas...
219

641741e01   Ben Dooks   [PATCH] rtc-s3c.c...
220
  	if (year < 0 || year >= 100) {
9a654518e   Ben Dooks   [PATCH] drivers/r...
221
222
  		dev_err(dev, "rtc only supports 100 years
  ");
1add6781c   Ben Dooks   [PATCH] RTC: clas...
223
  		return -EINVAL;
9a654518e   Ben Dooks   [PATCH] drivers/r...
224
  	}
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
225
226
227
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
228
229
230
231
232
233
234
  
  	writeb(bin2bcd(tm->tm_sec),  info->base + S3C2410_RTCSEC);
  	writeb(bin2bcd(tm->tm_min),  info->base + S3C2410_RTCMIN);
  	writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_RTCHOUR);
  	writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_RTCDATE);
  	writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON);
  	writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR);
24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
235
  	s3c_rtc_disable_clk(info);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
236
237
238
239
240
241
  
  	return 0;
  }
  
  static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
242
  	struct s3c_rtc *info = dev_get_drvdata(dev);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
243
244
  	struct rtc_time *alm_tm = &alrm->time;
  	unsigned int alm_en;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
245
  	int ret;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
246

498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
247
248
249
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
250

19be09f51   Chanwoo Choi   rtc: s3c: define ...
251
252
253
254
255
256
  	alm_tm->tm_sec  = readb(info->base + S3C2410_ALMSEC);
  	alm_tm->tm_min  = readb(info->base + S3C2410_ALMMIN);
  	alm_tm->tm_hour = readb(info->base + S3C2410_ALMHOUR);
  	alm_tm->tm_mon  = readb(info->base + S3C2410_ALMMON);
  	alm_tm->tm_mday = readb(info->base + S3C2410_ALMDATE);
  	alm_tm->tm_year = readb(info->base + S3C2410_ALMYEAR);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
257

19be09f51   Chanwoo Choi   rtc: s3c: define ...
258
  	alm_en = readb(info->base + S3C2410_RTCALM);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
259

24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
260
  	s3c_rtc_disable_clk(info);
a2db8dfce   David Brownell   [PATCH] rtc frame...
261
  	alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
9a1bacf42   Andy Shevchenko   rtc: s3c: Switch ...
262
263
  	dev_dbg(dev, "read alarm %d, %ptR
  ", alm_en, alm_tm);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
264

1add6781c   Ben Dooks   [PATCH] RTC: clas...
265
  	/* decode the alarm enable field */
1add6781c   Ben Dooks   [PATCH] RTC: clas...
266
  	if (alm_en & S3C2410_RTCALM_SECEN)
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
267
  		alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
268
269
  
  	if (alm_en & S3C2410_RTCALM_MINEN)
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
270
  		alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
271
272
  
  	if (alm_en & S3C2410_RTCALM_HOUREN)
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
273
  		alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
274
275
  
  	if (alm_en & S3C2410_RTCALM_DAYEN)
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
276
  		alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
277
278
  
  	if (alm_en & S3C2410_RTCALM_MONEN) {
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
279
  		alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
280
  		alm_tm->tm_mon -= 1;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
281
282
283
  	}
  
  	if (alm_en & S3C2410_RTCALM_YEAREN)
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
284
  		alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
285
286
287
288
289
290
  
  	return 0;
  }
  
  static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
291
  	struct s3c_rtc *info = dev_get_drvdata(dev);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
292
293
  	struct rtc_time *tm = &alrm->time;
  	unsigned int alrm_en;
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
294
  	int ret;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
295

9a1bacf42   Andy Shevchenko   rtc: s3c: Switch ...
296
297
  	dev_dbg(dev, "s3c_rtc_setalarm: %d, %ptR
  ", alrm->enabled, tm);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
298

498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
299
300
301
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
302

19be09f51   Chanwoo Choi   rtc: s3c: define ...
303
304
  	alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
  	writeb(0x00, info->base + S3C2410_RTCALM);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
305
306
307
  
  	if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
  		alrm_en |= S3C2410_RTCALM_SECEN;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
308
  		writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_ALMSEC);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
309
310
311
312
  	}
  
  	if (tm->tm_min < 60 && tm->tm_min >= 0) {
  		alrm_en |= S3C2410_RTCALM_MINEN;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
313
  		writeb(bin2bcd(tm->tm_min), info->base + S3C2410_ALMMIN);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
314
315
316
317
  	}
  
  	if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
  		alrm_en |= S3C2410_RTCALM_HOUREN;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
318
  		writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
319
  	}
fb4ac3c14   Krzysztof Kozlowski   rtc: s3c: Set yea...
320
321
322
323
324
325
326
327
328
  	if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
  		alrm_en |= S3C2410_RTCALM_MONEN;
  		writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
  	}
  
  	if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
  		alrm_en |= S3C2410_RTCALM_DAYEN;
  		writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE);
  	}
d4a48c2ad   Jingoo Han   drivers/rtc/rtc-s...
329
330
  	dev_dbg(dev, "setting S3C2410_RTCALM to %08x
  ", alrm_en);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
331

19be09f51   Chanwoo Choi   rtc: s3c: define ...
332
  	writeb(alrm_en, info->base + S3C2410_RTCALM);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
333

24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
334
  	s3c_rtc_setaie(dev, alrm->enabled);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
335

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
336
  	s3c_rtc_disable_clk(info);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
337
338
  	return 0;
  }
1add6781c   Ben Dooks   [PATCH] RTC: clas...
339
340
  static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
341
  	struct s3c_rtc *info = dev_get_drvdata(dev);
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
342
  	int ret;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
343

498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
344
345
346
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
9f4123b78   Maurus Cuelenaere   s3c rtc driver: a...
347

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
348
349
  	if (info->data->enable_tick)
  		info->data->enable_tick(info, seq);
24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
350
  	s3c_rtc_disable_clk(info);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
351

1add6781c   Ben Dooks   [PATCH] RTC: clas...
352
353
  	return 0;
  }
ff8371ac9   David Brownell   [PATCH] constify ...
354
  static const struct rtc_class_ops s3c_rtcops = {
1add6781c   Ben Dooks   [PATCH] RTC: clas...
355
356
357
358
  	.read_time	= s3c_rtc_gettime,
  	.set_time	= s3c_rtc_settime,
  	.read_alarm	= s3c_rtc_getalarm,
  	.set_alarm	= s3c_rtc_setalarm,
e6eb524e6   Changhwan Youn   rtc: rtc-s3c: fix...
359
360
  	.proc		= s3c_rtc_proc,
  	.alarm_irq_enable = s3c_rtc_setaie,
1add6781c   Ben Dooks   [PATCH] RTC: clas...
361
  };
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
362
  static void s3c24xx_rtc_enable(struct s3c_rtc *info)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
363
  {
d67288da5   Chanwoo Choi   rtc: s3c: remove ...
364
  	unsigned int con, tmp;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
365

d67288da5   Chanwoo Choi   rtc: s3c: remove ...
366
  	con = readw(info->base + S3C2410_RTCCON);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
367
368
369
370
  	/* re-enable the device, and check it is ok */
  	if ((con & S3C2410_RTCCON_RTCEN) == 0) {
  		dev_info(info->dev, "rtc disabled, re-enabling
  ");
1add6781c   Ben Dooks   [PATCH] RTC: clas...
371

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
372
  		tmp = readw(info->base + S3C2410_RTCCON);
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
373
  		writew(tmp | S3C2410_RTCCON_RTCEN, info->base + S3C2410_RTCCON);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
374
  	}
1add6781c   Ben Dooks   [PATCH] RTC: clas...
375

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
376
377
378
  	if (con & S3C2410_RTCCON_CNTSEL) {
  		dev_info(info->dev, "removing RTCCON_CNTSEL
  ");
1add6781c   Ben Dooks   [PATCH] RTC: clas...
379

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
380
381
  		tmp = readw(info->base + S3C2410_RTCCON);
  		writew(tmp & ~S3C2410_RTCCON_CNTSEL,
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
382
  		       info->base + S3C2410_RTCCON);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
383
  	}
1add6781c   Ben Dooks   [PATCH] RTC: clas...
384

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
385
386
387
  	if (con & S3C2410_RTCCON_CLKRST) {
  		dev_info(info->dev, "removing RTCCON_CLKRST
  ");
1add6781c   Ben Dooks   [PATCH] RTC: clas...
388

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
389
390
  		tmp = readw(info->base + S3C2410_RTCCON);
  		writew(tmp & ~S3C2410_RTCCON_CLKRST,
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
391
  		       info->base + S3C2410_RTCCON);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
392
  	}
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
393
394
395
396
397
  }
  
  static void s3c24xx_rtc_disable(struct s3c_rtc *info)
  {
  	unsigned int con;
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
398
399
400
401
402
403
404
  	con = readw(info->base + S3C2410_RTCCON);
  	con &= ~S3C2410_RTCCON_RTCEN;
  	writew(con, info->base + S3C2410_RTCCON);
  
  	con = readb(info->base + S3C2410_TICNT);
  	con &= ~S3C2410_TICNT_ENABLE;
  	writeb(con, info->base + S3C2410_TICNT);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
405
406
407
408
409
  }
  
  static void s3c6410_rtc_disable(struct s3c_rtc *info)
  {
  	unsigned int con;
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
410
411
412
413
  	con = readw(info->base + S3C2410_RTCCON);
  	con &= ~S3C64XX_RTCCON_TICEN;
  	con &= ~S3C2410_RTCCON_RTCEN;
  	writew(con, info->base + S3C2410_RTCCON);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
414
  }
19be09f51   Chanwoo Choi   rtc: s3c: define ...
415
  static int s3c_rtc_remove(struct platform_device *pdev)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
416
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
417
418
419
  	struct s3c_rtc *info = platform_get_drvdata(pdev);
  
  	s3c_rtc_setaie(info->dev, 0);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
420

7f23a9366   Joonyoung Shim   rtc: s3c: add mis...
421
422
  	if (info->data->needs_src_clk)
  		clk_unprepare(info->rtc_src_clk);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
423
  	clk_unprepare(info->rtc_clk);
e48add8c1   Atul Dahiya   rtc: rtc-s3c: Upd...
424

1add6781c   Ben Dooks   [PATCH] RTC: clas...
425
426
  	return 0;
  }
5a167f454   Greg Kroah-Hartman   Drivers: rtc: rem...
427
  static int s3c_rtc_probe(struct platform_device *pdev)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
428
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
429
  	struct s3c_rtc *info = NULL;
e1df962e6   Changhwan Youn   rtc: rtc-s3c: fix...
430
  	struct rtc_time rtc_tm;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
431
432
  	struct resource *res;
  	int ret;
19be09f51   Chanwoo Choi   rtc: s3c: define ...
433
434
435
  	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  	if (!info)
  		return -ENOMEM;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
436
437
  
  	/* find the IRQs */
19be09f51   Chanwoo Choi   rtc: s3c: define ...
438
439
  	info->irq_tick = platform_get_irq(pdev, 1);
  	if (info->irq_tick < 0) {
1add6781c   Ben Dooks   [PATCH] RTC: clas...
440
441
  		dev_err(&pdev->dev, "no irq for rtc tick
  ");
19be09f51   Chanwoo Choi   rtc: s3c: define ...
442
  		return info->irq_tick;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
443
  	}
19be09f51   Chanwoo Choi   rtc: s3c: define ...
444
  	info->dev = &pdev->dev;
64704c92f   Marek Szyprowski   rtc: s3c: Use gen...
445
  	info->data = of_device_get_match_data(&pdev->dev);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
446
447
448
449
450
  	if (!info->data) {
  		dev_err(&pdev->dev, "failed getting s3c_rtc_data
  ");
  		return -EINVAL;
  	}
19be09f51   Chanwoo Choi   rtc: s3c: define ...
451
  	spin_lock_init(&info->pie_lock);
5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
452
  	spin_lock_init(&info->alarm_lock);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
453
454
455
456
457
  
  	platform_set_drvdata(pdev, info);
  
  	info->irq_alarm = platform_get_irq(pdev, 0);
  	if (info->irq_alarm < 0) {
1add6781c   Ben Dooks   [PATCH] RTC: clas...
458
459
  		dev_err(&pdev->dev, "no irq for alarm
  ");
19be09f51   Chanwoo Choi   rtc: s3c: define ...
460
  		return info->irq_alarm;
1add6781c   Ben Dooks   [PATCH] RTC: clas...
461
  	}
d4a48c2ad   Jingoo Han   drivers/rtc/rtc-s...
462
463
  	dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d
  ",
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
464
  		info->irq_tick, info->irq_alarm);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
465
466
  
  	/* get the memory region */
1add6781c   Ben Dooks   [PATCH] RTC: clas...
467
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
468
469
470
  	info->base = devm_ioremap_resource(&pdev->dev, res);
  	if (IS_ERR(info->base))
  		return PTR_ERR(info->base);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
471

19be09f51   Chanwoo Choi   rtc: s3c: define ...
472
473
  	info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
  	if (IS_ERR(info->rtc_clk)) {
ae6e00b4c   Javier Martinez Canillas   rtc: s3c: Don't p...
474
475
476
477
478
479
480
481
  		ret = PTR_ERR(info->rtc_clk);
  		if (ret != -EPROBE_DEFER)
  			dev_err(&pdev->dev, "failed to find rtc clock
  ");
  		else
  			dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk
  ");
  		return ret;
e48add8c1   Atul Dahiya   rtc: rtc-s3c: Upd...
482
  	}
9903f68af   Krzysztof Kozlowski   rtc: s3c: Handle ...
483
484
485
  	ret = clk_prepare_enable(info->rtc_clk);
  	if (ret)
  		return ret;
e48add8c1   Atul Dahiya   rtc: rtc-s3c: Upd...
486

eaf3a6590   Marek Szyprowski   drivers/rtc/rtc-s...
487
488
489
  	if (info->data->needs_src_clk) {
  		info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
  		if (IS_ERR(info->rtc_src_clk)) {
ae6e00b4c   Javier Martinez Canillas   rtc: s3c: Don't p...
490
491
492
493
494
495
496
497
498
  			ret = PTR_ERR(info->rtc_src_clk);
  			if (ret != -EPROBE_DEFER)
  				dev_err(&pdev->dev,
  					"failed to find rtc source clock
  ");
  			else
  				dev_dbg(&pdev->dev,
  					"probe deferred due to missing rtc src clk
  ");
8768e7b3e   Krzysztof Kozlowski   rtc: s3c: Jump to...
499
  			goto err_src_clk;
eaf3a6590   Marek Szyprowski   drivers/rtc/rtc-s...
500
  		}
9903f68af   Krzysztof Kozlowski   rtc: s3c: Handle ...
501
502
503
  		ret = clk_prepare_enable(info->rtc_src_clk);
  		if (ret)
  			goto err_src_clk;
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
504
  	}
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
505

1add6781c   Ben Dooks   [PATCH] RTC: clas...
506
  	/* check to see if everything is setup correctly */
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
507
508
  	if (info->data->enable)
  		info->data->enable(info);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
509

d4a48c2ad   Jingoo Han   drivers/rtc/rtc-s...
510
511
  	dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x
  ",
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
512
  		readw(info->base + S3C2410_RTCCON));
1add6781c   Ben Dooks   [PATCH] RTC: clas...
513

51b7616e3   Yauhen Kharuzhy   rtc S3C: add devi...
514
  	device_init_wakeup(&pdev->dev, 1);
202fe4c27   Krzysztof Kozlowski   drivers/rtc/rtc-s...
515
  	/* Check RTC Time */
492da68c8   Krzysztof Kozlowski   drivers/rtc/rtc-s...
516
  	if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) {
202fe4c27   Krzysztof Kozlowski   drivers/rtc/rtc-s...
517
518
519
520
521
522
523
524
525
526
527
528
  		rtc_tm.tm_year	= 100;
  		rtc_tm.tm_mon	= 0;
  		rtc_tm.tm_mday	= 1;
  		rtc_tm.tm_hour	= 0;
  		rtc_tm.tm_min	= 0;
  		rtc_tm.tm_sec	= 0;
  
  		s3c_rtc_settime(&pdev->dev, &rtc_tm);
  
  		dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it
  ");
  	}
1add6781c   Ben Dooks   [PATCH] RTC: clas...
529
  	/* register RTC and exit */
19be09f51   Chanwoo Choi   rtc: s3c: define ...
530
  	info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops,
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
531
  					     THIS_MODULE);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
532
  	if (IS_ERR(info->rtc)) {
1add6781c   Ben Dooks   [PATCH] RTC: clas...
533
534
  		dev_err(&pdev->dev, "cannot attach rtc
  ");
19be09f51   Chanwoo Choi   rtc: s3c: define ...
535
  		ret = PTR_ERR(info->rtc);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
536
537
  		goto err_nortc;
  	}
19be09f51   Chanwoo Choi   rtc: s3c: define ...
538
  	ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
539
  			       0, "s3c2410-rtc alarm", info);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
540
541
542
543
544
  	if (ret) {
  		dev_err(&pdev->dev, "IRQ%d error %d
  ", info->irq_alarm, ret);
  		goto err_nortc;
  	}
eaa6e4dd4   Maurus Cuelenaere   rtc: s3c: initial...
545

19be09f51   Chanwoo Choi   rtc: s3c: define ...
546
  	ret = devm_request_irq(&pdev->dev, info->irq_tick, s3c_rtc_tickirq,
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
547
  			       0, "s3c2410-rtc tick", info);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
548
549
550
551
552
  	if (ret) {
  		dev_err(&pdev->dev, "IRQ%d error %d
  ", info->irq_tick, ret);
  		goto err_nortc;
  	}
051fe54e9   Taekgyun Ko   rtc: rtc-s3c: Add...
553

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
554
555
  	if (info->data->select_tick_clk)
  		info->data->select_tick_clk(info);
62d176018   MyungJoo Ham   drivers/rtc/rtc-s...
556

19be09f51   Chanwoo Choi   rtc: s3c: define ...
557
  	s3c_rtc_setfreq(info, 1);
62d176018   MyungJoo Ham   drivers/rtc/rtc-s...
558

5a5b614ba   Marek Szyprowski   rtc: s3c: Rewrite...
559
  	s3c_rtc_disable_clk(info);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
560
  	return 0;
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
561
  err_nortc:
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
562
563
  	if (info->data->disable)
  		info->data->disable(info);
24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
564
565
566
  
  	if (info->data->needs_src_clk)
  		clk_disable_unprepare(info->rtc_src_clk);
8768e7b3e   Krzysztof Kozlowski   rtc: s3c: Jump to...
567
  err_src_clk:
19be09f51   Chanwoo Choi   rtc: s3c: define ...
568
  	clk_disable_unprepare(info->rtc_clk);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
569

1add6781c   Ben Dooks   [PATCH] RTC: clas...
570
571
  	return ret;
  }
32e445aab   Jingoo Han   drivers/rtc/rtc-s...
572
  #ifdef CONFIG_PM_SLEEP
1add6781c   Ben Dooks   [PATCH] RTC: clas...
573

32e445aab   Jingoo Han   drivers/rtc/rtc-s...
574
  static int s3c_rtc_suspend(struct device *dev)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
575
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
576
  	struct s3c_rtc *info = dev_get_drvdata(dev);
498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
577
  	int ret;
32e445aab   Jingoo Han   drivers/rtc/rtc-s...
578

498bcf313   Krzysztof Kozlowski   rtc: s3c: Handle ...
579
580
581
  	ret = s3c_rtc_enable_clk(info);
  	if (ret)
  		return ret;
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
582

1add6781c   Ben Dooks   [PATCH] RTC: clas...
583
  	/* save TICNT for anyone using periodic interrupts */
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
584
585
586
587
588
  	if (info->data->save_tick_cnt)
  		info->data->save_tick_cnt(info);
  
  	if (info->data->disable)
  		info->data->disable(info);
f501ed524   Vladimir Zapolskiy   rtc: s3c: balance...
589

19be09f51   Chanwoo Choi   rtc: s3c: define ...
590
591
592
  	if (device_may_wakeup(dev) && !info->wake_en) {
  		if (enable_irq_wake(info->irq_alarm) == 0)
  			info->wake_en = true;
52cd4e5c6   Ben Dooks   drivers/rtc/rtc-s...
593
  		else
32e445aab   Jingoo Han   drivers/rtc/rtc-s...
594
595
  			dev_err(dev, "enable_irq_wake failed
  ");
52cd4e5c6   Ben Dooks   drivers/rtc/rtc-s...
596
  	}
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
597

1add6781c   Ben Dooks   [PATCH] RTC: clas...
598
599
  	return 0;
  }
32e445aab   Jingoo Han   drivers/rtc/rtc-s...
600
  static int s3c_rtc_resume(struct device *dev)
1add6781c   Ben Dooks   [PATCH] RTC: clas...
601
  {
19be09f51   Chanwoo Choi   rtc: s3c: define ...
602
  	struct s3c_rtc *info = dev_get_drvdata(dev);
9f4123b78   Maurus Cuelenaere   s3c rtc driver: a...
603

ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
604
605
606
607
608
  	if (info->data->enable)
  		info->data->enable(info);
  
  	if (info->data->restore_tick_cnt)
  		info->data->restore_tick_cnt(info);
f501ed524   Vladimir Zapolskiy   rtc: s3c: balance...
609

24e145549   Chanwoo Choi   drivers/rtc/rtc-s...
610
  	s3c_rtc_disable_clk(info);
19be09f51   Chanwoo Choi   rtc: s3c: define ...
611
612
613
  	if (device_may_wakeup(dev) && info->wake_en) {
  		disable_irq_wake(info->irq_alarm);
  		info->wake_en = false;
52cd4e5c6   Ben Dooks   drivers/rtc/rtc-s...
614
  	}
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
615

1add6781c   Ben Dooks   [PATCH] RTC: clas...
616
617
  	return 0;
  }
1add6781c   Ben Dooks   [PATCH] RTC: clas...
618
  #endif
32e445aab   Jingoo Han   drivers/rtc/rtc-s...
619
  static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
620
621
  static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask)
  {
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
622
  	rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
623
624
625
626
  }
  
  static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask)
  {
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
627
628
  	rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF);
  	writeb(mask, info->base + S3C2410_INTP);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  }
  
  static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq)
  {
  	unsigned int tmp = 0;
  	int val;
  
  	tmp = readb(info->base + S3C2410_TICNT);
  	tmp &= S3C2410_TICNT_ENABLE;
  
  	val = (info->rtc->max_user_freq / freq) - 1;
  	tmp |= val;
  
  	writel(tmp, info->base + S3C2410_TICNT);
  }
  
  static void s3c2416_rtc_setfreq(struct s3c_rtc *info, int freq)
  {
  	unsigned int tmp = 0;
  	int val;
  
  	tmp = readb(info->base + S3C2410_TICNT);
  	tmp &= S3C2410_TICNT_ENABLE;
  
  	val = (info->rtc->max_user_freq / freq) - 1;
  
  	tmp |= S3C2443_TICNT_PART(val);
  	writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
  
  	writel(S3C2416_TICNT2_PART(val), info->base + S3C2416_TICNT2);
  
  	writel(tmp, info->base + S3C2410_TICNT);
  }
  
  static void s3c2443_rtc_setfreq(struct s3c_rtc *info, int freq)
  {
  	unsigned int tmp = 0;
  	int val;
  
  	tmp = readb(info->base + S3C2410_TICNT);
  	tmp &= S3C2410_TICNT_ENABLE;
  
  	val = (info->rtc->max_user_freq / freq) - 1;
  
  	tmp |= S3C2443_TICNT_PART(val);
  	writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
  
  	writel(tmp, info->base + S3C2410_TICNT);
  }
  
  static void s3c6410_rtc_setfreq(struct s3c_rtc *info, int freq)
  {
  	int val;
  
  	val = (info->rtc->max_user_freq / freq) - 1;
  	writel(val, info->base + S3C2410_TICNT);
  }
  
  static void s3c24xx_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
  {
  	unsigned int ticnt;
  
  	ticnt = readb(info->base + S3C2410_TICNT);
  	ticnt &= S3C2410_TICNT_ENABLE;
  
  	seq_printf(seq, "periodic_IRQ\t: %s
  ", ticnt  ? "yes" : "no");
  }
  
  static void s3c2416_rtc_select_tick_clk(struct s3c_rtc *info)
  {
  	unsigned int con;
  
  	con = readw(info->base + S3C2410_RTCCON);
  	con |= S3C2443_RTCCON_TICSEL;
  	writew(con, info->base + S3C2410_RTCCON);
  }
  
  static void s3c6410_rtc_enable_tick(struct s3c_rtc *info, struct seq_file *seq)
  {
  	unsigned int ticnt;
  
  	ticnt = readw(info->base + S3C2410_RTCCON);
  	ticnt &= S3C64XX_RTCCON_TICEN;
  
  	seq_printf(seq, "periodic_IRQ\t: %s
  ", ticnt  ? "yes" : "no");
  }
  
  static void s3c24xx_rtc_save_tick_cnt(struct s3c_rtc *info)
  {
  	info->ticnt_save = readb(info->base + S3C2410_TICNT);
  }
  
  static void s3c24xx_rtc_restore_tick_cnt(struct s3c_rtc *info)
  {
  	writeb(info->ticnt_save, info->base + S3C2410_TICNT);
  }
  
  static void s3c6410_rtc_save_tick_cnt(struct s3c_rtc *info)
  {
  	info->ticnt_en_save = readw(info->base + S3C2410_RTCCON);
  	info->ticnt_en_save &= S3C64XX_RTCCON_TICEN;
  	info->ticnt_save = readl(info->base + S3C2410_TICNT);
  }
  
  static void s3c6410_rtc_restore_tick_cnt(struct s3c_rtc *info)
  {
  	unsigned int con;
  
  	writel(info->ticnt_save, info->base + S3C2410_TICNT);
  	if (info->ticnt_en_save) {
  		con = readw(info->base + S3C2410_RTCCON);
fc1afe605   Krzysztof Kozlowski   rtc: s3c: Minor w...
742
  		writew(con | info->ticnt_en_save, info->base + S3C2410_RTCCON);
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
  	}
  }
  
  static struct s3c_rtc_data const s3c2410_rtc_data = {
  	.max_user_freq		= 128,
  	.irq_handler		= s3c24xx_rtc_irq,
  	.set_freq		= s3c2410_rtc_setfreq,
  	.enable_tick		= s3c24xx_rtc_enable_tick,
  	.save_tick_cnt		= s3c24xx_rtc_save_tick_cnt,
  	.restore_tick_cnt	= s3c24xx_rtc_restore_tick_cnt,
  	.enable			= s3c24xx_rtc_enable,
  	.disable		= s3c24xx_rtc_disable,
  };
  
  static struct s3c_rtc_data const s3c2416_rtc_data = {
  	.max_user_freq		= 32768,
  	.irq_handler		= s3c24xx_rtc_irq,
  	.set_freq		= s3c2416_rtc_setfreq,
  	.enable_tick		= s3c24xx_rtc_enable_tick,
  	.select_tick_clk	= s3c2416_rtc_select_tick_clk,
  	.save_tick_cnt		= s3c24xx_rtc_save_tick_cnt,
  	.restore_tick_cnt	= s3c24xx_rtc_restore_tick_cnt,
  	.enable			= s3c24xx_rtc_enable,
  	.disable		= s3c24xx_rtc_disable,
  };
  
  static struct s3c_rtc_data const s3c2443_rtc_data = {
  	.max_user_freq		= 32768,
  	.irq_handler		= s3c24xx_rtc_irq,
  	.set_freq		= s3c2443_rtc_setfreq,
  	.enable_tick		= s3c24xx_rtc_enable_tick,
  	.select_tick_clk	= s3c2416_rtc_select_tick_clk,
  	.save_tick_cnt		= s3c24xx_rtc_save_tick_cnt,
  	.restore_tick_cnt	= s3c24xx_rtc_restore_tick_cnt,
  	.enable			= s3c24xx_rtc_enable,
  	.disable		= s3c24xx_rtc_disable,
  };
  
  static struct s3c_rtc_data const s3c6410_rtc_data = {
  	.max_user_freq		= 32768,
8792f7772   Javier Martinez Canillas   drivers/rtc/rtc-s...
783
  	.needs_src_clk		= true,
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
784
785
786
787
788
789
790
  	.irq_handler		= s3c6410_rtc_irq,
  	.set_freq		= s3c6410_rtc_setfreq,
  	.enable_tick		= s3c6410_rtc_enable_tick,
  	.save_tick_cnt		= s3c6410_rtc_save_tick_cnt,
  	.restore_tick_cnt	= s3c6410_rtc_restore_tick_cnt,
  	.enable			= s3c24xx_rtc_enable,
  	.disable		= s3c6410_rtc_disable,
c3cba9281   Tushar Behera   drivers/rtc/rtc-s...
791
  };
39ce4084a   Thomas Abraham   rtc: rtc-s3c: Add...
792
  static const struct of_device_id s3c_rtc_dt_match[] = {
d2524caac   Heiko Stuebner   rtc-s3c: make roo...
793
  	{
cd1e6f9e5   Tushar Behera   drivers/rtc/rtc-s...
794
  		.compatible = "samsung,s3c2410-rtc",
21df6fed0   Krzysztof Kozlowski   rtc: s3c: Drop un...
795
  		.data = &s3c2410_rtc_data,
d2524caac   Heiko Stuebner   rtc-s3c: make roo...
796
  	}, {
cd1e6f9e5   Tushar Behera   drivers/rtc/rtc-s...
797
  		.compatible = "samsung,s3c2416-rtc",
21df6fed0   Krzysztof Kozlowski   rtc: s3c: Drop un...
798
  		.data = &s3c2416_rtc_data,
25c1a2466   Heiko Stuebner   rtc-s3c: add vari...
799
  	}, {
cd1e6f9e5   Tushar Behera   drivers/rtc/rtc-s...
800
  		.compatible = "samsung,s3c2443-rtc",
21df6fed0   Krzysztof Kozlowski   rtc: s3c: Drop un...
801
  		.data = &s3c2443_rtc_data,
25c1a2466   Heiko Stuebner   rtc-s3c: add vari...
802
  	}, {
cd1e6f9e5   Tushar Behera   drivers/rtc/rtc-s...
803
  		.compatible = "samsung,s3c6410-rtc",
21df6fed0   Krzysztof Kozlowski   rtc: s3c: Drop un...
804
  		.data = &s3c6410_rtc_data,
df9e26d09   Chanwoo Choi   rtc: s3c: add sup...
805
806
  	}, {
  		.compatible = "samsung,exynos3250-rtc",
21df6fed0   Krzysztof Kozlowski   rtc: s3c: Drop un...
807
  		.data = &s3c6410_rtc_data,
d2524caac   Heiko Stuebner   rtc-s3c: make roo...
808
  	},
ae05c9507   Chanwoo Choi   rtc: s3c: add s3c...
809
  	{ /* sentinel */ },
39ce4084a   Thomas Abraham   rtc: rtc-s3c: Add...
810
811
  };
  MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
9f4123b78   Maurus Cuelenaere   s3c rtc driver: a...
812
813
  
  static struct platform_driver s3c_rtc_driver = {
1add6781c   Ben Dooks   [PATCH] RTC: clas...
814
  	.probe		= s3c_rtc_probe,
5a167f454   Greg Kroah-Hartman   Drivers: rtc: rem...
815
  	.remove		= s3c_rtc_remove,
1add6781c   Ben Dooks   [PATCH] RTC: clas...
816
  	.driver		= {
9f4123b78   Maurus Cuelenaere   s3c rtc driver: a...
817
  		.name	= "s3c-rtc",
32e445aab   Jingoo Han   drivers/rtc/rtc-s...
818
  		.pm	= &s3c_rtc_pm_ops,
04a373fdc   Sachin Kamat   drivers/rtc/rtc-s...
819
  		.of_match_table	= of_match_ptr(s3c_rtc_dt_match),
1add6781c   Ben Dooks   [PATCH] RTC: clas...
820
821
  	},
  };
0c4eae665   Axel Lin   rtc: convert driv...
822
  module_platform_driver(s3c_rtc_driver);
1add6781c   Ben Dooks   [PATCH] RTC: clas...
823
824
825
826
  
  MODULE_DESCRIPTION("Samsung S3C RTC Driver");
  MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
  MODULE_LICENSE("GPL");
ad28a07bc   Kay Sievers   rtc: fix platform...
827
  MODULE_ALIAS("platform:s3c2410-rtc");