diff options
| author | Chanwoo Choi <cw00.choi@samsung.com> | 2014-10-13 18:52:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 20:18:17 -0400 |
| commit | ae05c95074e0ead8a8fda4aca066e10270086e3f (patch) | |
| tree | f6596bb217bd96544c67108122c6b9b495d774b0 /drivers/rtc | |
| parent | d67288da51b782f54dd3ae1455b997131160fd41 (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.c | 461 |
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 | ||
| 35 | enum s3c_cpu_type { | ||
| 36 | TYPE_S3C2410, | ||
| 37 | TYPE_S3C2416, | ||
| 38 | TYPE_S3C2443, | ||
| 39 | TYPE_S3C64XX, | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct s3c_rtc_drv_data { | ||
| 43 | int cpu_type; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct s3c_rtc { | 35 | struct 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 | ||
| 55 | struct 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 | |||
| 66 | static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) | 68 | static 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 */ |
| 86 | static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | 88 | static 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 | ||
| 103 | static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | 98 | static 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 */ | ||
| 140 | static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) | 131 | static 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 | |||
| 178 | static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | 149 | static 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) | |||
| 355 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | 326 | static 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 | ||
| 383 | static void s3c_rtc_enable(struct s3c_rtc *info, int en) | 349 | static 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 | |||
