aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2014-10-13 18:52:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 20:18:17 -0400
commitae05c95074e0ead8a8fda4aca066e10270086e3f (patch)
treef6596bb217bd96544c67108122c6b9b495d774b0 /drivers/rtc
parentd67288da51b782f54dd3ae1455b997131160fd41 (diff)
rtc: s3c: add s3c_rtc_data structure to use variant data instead of s3c_cpu_type
Add s3c_rtc_data structure to variant data according to SoC type. The s3c_rtc_data structure includes some functions to control RTC operation and specific data dependent on SoC type. Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-s3c.c461
1 files changed, 289 insertions, 172 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 4e95cca7615c..0d9089228bb0 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -32,17 +32,6 @@
32#include <asm/irq.h> 32#include <asm/irq.h>
33#include "rtc-s3c.h" 33#include "rtc-s3c.h"
34 34
35enum s3c_cpu_type {
36 TYPE_S3C2410,
37 TYPE_S3C2416,
38 TYPE_S3C2443,
39 TYPE_S3C64XX,
40};
41
42struct s3c_rtc_drv_data {
43 int cpu_type;
44};
45
46struct s3c_rtc { 35struct s3c_rtc {
47 struct device *dev; 36 struct device *dev;
48 struct rtc_device *rtc; 37 struct rtc_device *rtc;
@@ -51,7 +40,7 @@ struct s3c_rtc {
51 struct clk *rtc_clk; 40 struct clk *rtc_clk;
52 bool enabled; 41 bool enabled;
53 42
54 enum s3c_cpu_type cpu_type; 43 struct s3c_rtc_data *data;
55 44
56 int irq_alarm; 45 int irq_alarm;
57 int irq_tick; 46 int irq_tick;
@@ -63,6 +52,19 @@ struct s3c_rtc {
63 bool wake_en; 52 bool wake_en;
64}; 53};
65 54
55struct s3c_rtc_data {
56 int max_user_freq;
57
58 void (*irq_handler) (struct s3c_rtc *info, int mask);
59 void (*set_freq) (struct s3c_rtc *info, int freq);
60 void (*enable_tick) (struct s3c_rtc *info, struct seq_file *seq);
61 void (*select_tick_clk) (struct s3c_rtc *info);
62 void (*save_tick_cnt) (struct s3c_rtc *info);
63 void (*restore_tick_cnt) (struct s3c_rtc *info);
64 void (*enable) (struct s3c_rtc *info);
65 void (*disable) (struct s3c_rtc *info);
66};
67
66static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) 68static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable)
67{ 69{
68 unsigned long irq_flags; 70 unsigned long irq_flags;
@@ -83,34 +85,22 @@ static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable)
83} 85}
84 86
85/* IRQ Handlers */ 87/* IRQ Handlers */
86static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) 88static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
87{ 89{
88 struct s3c_rtc *info = (struct s3c_rtc *)id; 90 struct s3c_rtc *info = (struct s3c_rtc *)id;
89 91
90 clk_enable(info->rtc_clk); 92 if (info->data->irq_handler)
91 rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); 93 info->data->irq_handler(info, S3C2410_INTP_TIC);
92
93 if (info->cpu_type == TYPE_S3C64XX)
94 writeb(S3C2410_INTP_ALM, info->base + S3C2410_INTP);
95
96 clk_disable(info->rtc_clk);
97
98 s3c_rtc_alarm_clk_enable(info, false);
99 94
100 return IRQ_HANDLED; 95 return IRQ_HANDLED;
101} 96}
102 97
103static irqreturn_t s3c_rtc_tickirq(int irq, void *id) 98static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
104{ 99{
105 struct s3c_rtc *info = (struct s3c_rtc *)id; 100 struct s3c_rtc *info = (struct s3c_rtc *)id;
106 101
107 clk_enable(info->rtc_clk); 102 if (info->data->irq_handler)
108 rtc_update_irq(info->rtc, 1, RTC_PF | RTC_IRQF); 103 info->data->irq_handler(info, S3C2410_INTP_ALM);
109
110 if (info->cpu_type == TYPE_S3C64XX)
111 writeb(S3C2410_INTP_TIC, info->base + S3C2410_INTP);
112
113 clk_disable(info->rtc_clk);
114 104
115 return IRQ_HANDLED; 105 return IRQ_HANDLED;
116} 106}
@@ -137,36 +127,18 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
137 return 0; 127 return 0;
138} 128}
139 129
130/* Set RTC frequency */
140static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) 131static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
141{ 132{
142 unsigned int tmp = 0;
143 int val;
144
145 if (!is_power_of_2(freq)) 133 if (!is_power_of_2(freq))
146 return -EINVAL; 134 return -EINVAL;
147 135
148 clk_enable(info->rtc_clk); 136 clk_enable(info->rtc_clk);
149 spin_lock_irq(&info->pie_lock); 137 spin_lock_irq(&info->pie_lock);
150 138
151 if (info->cpu_type != TYPE_S3C64XX) { 139 if (info->data->set_freq)
152 tmp = readb(info->base + S3C2410_TICNT); 140 info->data->set_freq(info, freq);
153 tmp &= S3C2410_TICNT_ENABLE;
154 }
155
156 val = (info->rtc->max_user_freq / freq) - 1;
157
158 if (info->cpu_type == TYPE_S3C2416 || info->cpu_type == TYPE_S3C2443) {
159 tmp |= S3C2443_TICNT_PART(val);
160 writel(S3C2443_TICNT1_PART(val), info->base + S3C2443_TICNT1);
161 141
162 if (info->cpu_type == TYPE_S3C2416)
163 writel(S3C2416_TICNT2_PART(val),
164 info->base + S3C2416_TICNT2);
165 } else {
166 tmp |= val;
167 }
168
169 writel(tmp, info->base + S3C2410_TICNT);
170 spin_unlock_irq(&info->pie_lock); 142 spin_unlock_irq(&info->pie_lock);
171 clk_disable(info->rtc_clk); 143 clk_disable(info->rtc_clk);
172 144
@@ -174,7 +146,6 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
174} 146}
175 147
176/* Time read/write */ 148/* Time read/write */
177
178static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) 149static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
179{ 150{
180 struct s3c_rtc *info = dev_get_drvdata(dev); 151 struct s3c_rtc *info = dev_get_drvdata(dev);
@@ -355,19 +326,14 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
355static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) 326static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
356{ 327{
357 struct s3c_rtc *info = dev_get_drvdata(dev); 328 struct s3c_rtc *info = dev_get_drvdata(dev);
358 unsigned int ticnt;
359 329
360 clk_enable(info->rtc_clk); 330 clk_enable(info->rtc_clk);
361 if (info->cpu_type == TYPE_S3C64XX) {
362 ticnt = readw(info->base + S3C2410_RTCCON);
363 ticnt &= S3C64XX_RTCCON_TICEN;
364 } else {
365 ticnt = readb(info->base + S3C2410_TICNT);
366 ticnt &= S3C2410_TICNT_ENABLE;
367 }
368 331
369 seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); 332 if (info->data->enable_tick)
333 info->data->enable_tick(info, seq);
334
370 clk_disable(info->rtc_clk); 335 clk_disable(info->rtc_clk);
336
371 return 0; 337 return 0;
372} 338}
373 339
@@ -380,50 +346,69 @@ static const struct rtc_class_ops s3c_rtcops = {
380 .alarm_irq_enable = s3c_rtc_setaie, 346 .alarm_irq_enable = s3c_rtc_setaie,
381}; 347};
382 348
383static void s3c_rtc_enable(struct s3c_rtc *info, int en) 349static void s3c24xx_rtc_enable(struct s3c_rtc *info)
384{ 350{
385 unsigned int con, tmp; 351 unsigned int con, tmp;
386 352
387 clk_enable(info->rtc_clk); 353 clk_enable(info->rtc_clk);
388