aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-02-13 01:01:37 -0500
committerArnd Bergmann <arnd@arndb.de>2012-02-13 01:01:37 -0500
commit7dae8c5209147ad06d424928a5f1ec45caa87691 (patch)
tree9d62ca389dde613cf6eba66710eb06d513f202a5
parentac819a86a76dc29d18306f5c998c38af1ebb58cd (diff)
parentb2994d318dc78c9a4a43605629f00217335ada28 (diff)
Merge branch 'v3.4-next/devel-samsung-rtc' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/drivers
* 'v3.4-next/devel-samsung-rtc' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: S3C2443/S3C2416: add s3c_rtc_setname and rename rtc devices rtc-s3c: add variants for S3C2443 and S3C2416 rtc-s3c: make room for more variants in devicetree block ARM: SAMSUNG: cleanup of rtc register definitions
-rw-r--r--arch/arm/mach-s3c2416/s3c2416.c2
-rw-r--r--arch/arm/mach-s3c2443/s3c2443.c2
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-rtc.h81
-rw-r--r--arch/arm/plat-samsung/include/plat/rtc-core.h27
-rw-r--r--drivers/rtc/rtc-s3c.c71
5 files changed, 131 insertions, 52 deletions
diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c
index 08bb0355159d..0e9a71c90ed7 100644
--- a/arch/arm/mach-s3c2416/s3c2416.c
+++ b/arch/arm/mach-s3c2416/s3c2416.c
@@ -59,6 +59,7 @@
59#include <plat/fb-core.h> 59#include <plat/fb-core.h>
60#include <plat/nand-core.h> 60#include <plat/nand-core.h>
61#include <plat/adc-core.h> 61#include <plat/adc-core.h>
62#include <plat/rtc-core.h>
62 63
63static struct map_desc s3c2416_iodesc[] __initdata = { 64static struct map_desc s3c2416_iodesc[] __initdata = {
64 IODESC_ENT(WATCHDOG), 65 IODESC_ENT(WATCHDOG),
@@ -98,6 +99,7 @@ int __init s3c2416_init(void)
98 s3c_fb_setname("s3c2443-fb"); 99 s3c_fb_setname("s3c2443-fb");
99 100
100 s3c_adc_setname("s3c2416-adc"); 101 s3c_adc_setname("s3c2416-adc");
102 s3c_rtc_setname("s3c2416-rtc");
101 103
102#ifdef CONFIG_PM 104#ifdef CONFIG_PM
103 register_syscore_ops(&s3c2416_pm_syscore_ops); 105 register_syscore_ops(&s3c2416_pm_syscore_ops);
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
index b9deaeb0dfff..b7778a9dafaf 100644
--- a/arch/arm/mach-s3c2443/s3c2443.c
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -41,6 +41,7 @@
41#include <plat/fb-core.h> 41#include <plat/fb-core.h>
42#include <plat/nand-core.h> 42#include <plat/nand-core.h>
43#include <plat/adc-core.h> 43#include <plat/adc-core.h>
44#include <plat/rtc-core.h>
44 45
45static struct map_desc s3c2443_iodesc[] __initdata = { 46static struct map_desc s3c2443_iodesc[] __initdata = {
46 IODESC_ENT(WATCHDOG), 47 IODESC_ENT(WATCHDOG),
@@ -73,6 +74,7 @@ int __init s3c2443_init(void)
73 s3c_fb_setname("s3c2443-fb"); 74 s3c_fb_setname("s3c2443-fb");
74 75
75 s3c_adc_setname("s3c2443-adc"); 76 s3c_adc_setname("s3c2443-adc");
77 s3c_rtc_setname("s3c2443-rtc");
76 78
77 /* change WDT IRQ number */ 79 /* change WDT IRQ number */
78 s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT; 80 s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;
diff --git a/arch/arm/plat-samsung/include/plat/regs-rtc.h b/arch/arm/plat-samsung/include/plat/regs-rtc.h
index 30b7cc14cef5..0f8263e93eea 100644
--- a/arch/arm/plat-samsung/include/plat/regs-rtc.h
+++ b/arch/arm/plat-samsung/include/plat/regs-rtc.h
@@ -18,51 +18,54 @@
18#define S3C2410_INTP_ALM (1 << 1) 18#define S3C2410_INTP_ALM (1 << 1)
19#define S3C2410_INTP_TIC (1 << 0) 19#define S3C2410_INTP_TIC (1 << 0)
20 20
21#define S3C2410_RTCCON S3C2410_RTCREG(0x40) 21#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
22#define S3C2410_RTCCON_RTCEN (1<<0) 22#define S3C2410_RTCCON_RTCEN (1 << 0)
23#define S3C2410_RTCCON_CLKSEL (1<<1) 23#define S3C2410_RTCCON_CNTSEL (1 << 2)
24#define S3C2410_RTCCON_CNTSEL (1<<2) 24#define S3C2410_RTCCON_CLKRST (1 << 3)
25#define S3C2410_RTCCON_CLKRST (1<<3) 25#define S3C2443_RTCCON_TICSEL (1 << 4)
26#define S3C64XX_RTCCON_TICEN (1<<8) 26#define S3C64XX_RTCCON_TICEN (1 << 8)
27 27
28#define S3C64XX_RTCCON_TICMSK (0xF<<7) 28#define S3C2410_TICNT S3C2410_RTCREG(0x44)
29#define S3C64XX_RTCCON_TICSHT (7) 29#define S3C2410_TICNT_ENABLE (1 << 7)
30 30
31#define S3C2410_TICNT S3C2410_RTCREG(0x44) 31/* S3C2443: tick count is 15 bit wide
32#define S3C2410_TICNT_ENABLE (1<<7) 32 * TICNT[6:0] contains upper 7 bits
33 * TICNT1[7:0] contains lower 8 bits
34 */
35#define S3C2443_TICNT_PART(x) ((x & 0x7f00) >> 8)
36#define S3C2443_TICNT1 S3C2410_RTCREG(0x4C)
37#define S3C2443_TICNT1_PART(x) (x & 0xff)
33 38
34#define S3C2410_RTCALM S3C2410_RTCREG(0x50) 39/* S3C2416: tick count is 32 bit wide
35#define S3C2410_RTCALM_ALMEN (1<<6) 40 * TICNT[6:0] contains bits [14:8]
36#define S3C2410_RTCALM_YEAREN (1<<5) 41 * TICNT1[7:0] contains lower 8 bits
37#define S3C2410_RTCALM_MONEN (1<<4) 42 * TICNT2[16:0] contains upper 17 bits
38#define S3C2410_RTCALM_DAYEN (1<<3) 43 */
39#define S3C2410_RTCALM_HOUREN (1<<2) 44#define S3C2416_TICNT2 S3C2410_RTCREG(0x48)
40#define S3C2410_RTCALM_MINEN (1<<1) 45#define S3C2416_TICNT2_PART(x) ((x & 0xffff8000) >> 15)
41#define S3C2410_RTCALM_SECEN (1<<0)
42 46
43#define S3C2410_RTCALM_ALL \ 47#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
44 S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\ 48#define S3C2410_RTCALM_ALMEN (1 << 6)
45 S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\ 49#define S3C2410_RTCALM_YEAREN (1 << 5)
46 S3C2410_RTCALM_SECEN 50#define S3C2410_RTCALM_MONEN (1 << 4)
51#define S3C2410_RTCALM_DAYEN (1 << 3)
52#define S3C2410_RTCALM_HOUREN (1 << 2)
53#define S3C2410_RTCALM_MINEN (1 << 1)
54#define S3C2410_RTCALM_SECEN (1 << 0)
47 55
56#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
57#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
58#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
48 59
49#define S3C2410_ALMSEC S3C2410_RTCREG(0x54) 60#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
50#define S3C2410_ALMMIN S3C2410_RTCREG(0x58) 61#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
51#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c) 62#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
52
53#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
54#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
55#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
56
57#define S3C2410_RTCRST S3C2410_RTCREG(0x6c)
58
59#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
60#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
61#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
62#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
63#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
64#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
65#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
66 63
64#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
65#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
66#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
67#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
68#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
69#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
67 70
68#endif /* __ASM_ARCH_REGS_RTC_H */ 71#endif /* __ASM_ARCH_REGS_RTC_H */
diff --git a/arch/arm/plat-samsung/include/plat/rtc-core.h b/arch/arm/plat-samsung/include/plat/rtc-core.h
new file mode 100644
index 000000000000..21d8594d37ca
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/rtc-core.h
@@ -0,0 +1,27 @@
1/* linux/arch/arm/plat-samsung/include/plat/rtc-core.h
2 *
3 * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
4 *
5 * Samsung RTC Controller core functions
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#ifndef __ASM_PLAT_RTC_CORE_H
13#define __ASM_PLAT_RTC_CORE_H __FILE__
14
15/* These functions are only for use with the core support code, such as
16 * the cpu specific initialisation code
17 */
18
19/* re-define device name depending on support. */
20static inline void s3c_rtc_setname(char *name)
21{
22#if defined(CONFIG_SAMSUNG_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
23 s3c_device_rtc.name = name;
24#endif
25}
26
27#endif /* __ASM_PLAT_RTC_CORE_H */
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index aef40bd2957b..78951866f8ab 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -35,6 +35,8 @@
35 35
36enum s3c_cpu_type { 36enum s3c_cpu_type {
37 TYPE_S3C2410, 37 TYPE_S3C2410,
38 TYPE_S3C2416,
39 TYPE_S3C2443,
38 TYPE_S3C64XX, 40 TYPE_S3C64XX,
39}; 41};
40 42
@@ -132,6 +134,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
132 struct platform_device *pdev = to_platform_device(dev); 134 struct platform_device *pdev = to_platform_device(dev);
133 struct rtc_device *rtc_dev = platform_get_drvdata(pdev); 135 struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
134 unsigned int tmp = 0; 136 unsigned int tmp = 0;
137 int val;
135 138
136 if (!is_power_of_2(freq)) 139 if (!is_power_of_2(freq))
137 return -EINVAL; 140 return -EINVAL;
@@ -139,12 +142,22 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
139 clk_enable(rtc_clk); 142 clk_enable(rtc_clk);
140 spin_lock_irq(&s3c_rtc_pie_lock); 143 spin_lock_irq(&s3c_rtc_pie_lock);
141 144
142 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 145 if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
143 tmp = readb(s3c_rtc_base + S3C2410_TICNT); 146 tmp = readb(s3c_rtc_base + S3C2410_TICNT);
144 tmp &= S3C2410_TICNT_ENABLE; 147 tmp &= S3C2410_TICNT_ENABLE;
145 } 148 }
146 149
147 tmp |= (rtc_dev->max_user_freq / freq)-1; 150 val = (rtc_dev->max_user_freq / freq) - 1;
151
152 if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
153 tmp |= S3C2443_TICNT_PART(val);
154 writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1);
155
156 if (s3c_rtc_cpu_type == TYPE_S3C2416)
157 writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2);
158 } else {
159 tmp |= val;
160 }
148 161
149 writel(tmp, s3c_rtc_base + S3C2410_TICNT); 162 writel(tmp, s3c_rtc_base + S3C2410_TICNT);
150 spin_unlock_irq(&s3c_rtc_pie_lock); 163 spin_unlock_irq(&s3c_rtc_pie_lock);
@@ -371,7 +384,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
371 tmp &= ~S3C2410_RTCCON_RTCEN; 384 tmp &= ~S3C2410_RTCCON_RTCEN;
372 writew(tmp, base + S3C2410_RTCCON); 385 writew(tmp, base + S3C2410_RTCCON);
373 386
374 if (s3c_rtc_cpu_type == TYPE_S3C2410) { 387 if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
375 tmp = readb(base + S3C2410_TICNT); 388 tmp = readb(base + S3C2410_TICNT);
376 tmp &= ~S3C2410_TICNT_ENABLE; 389 tmp &= ~S3C2410_TICNT_ENABLE;
377 writeb(tmp, base + S3C2410_TICNT); 390 writeb(tmp, base + S3C2410_TICNT);
@@ -428,12 +441,27 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
428 return 0; 441 return 0;
429} 442}
430 443
444static const struct of_device_id s3c_rtc_dt_match[];
445
446static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
447{
448#ifdef CONFIG_OF
449 if (pdev->dev.of_node) {
450 const struct of_device_id *match;
451 match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
452 return match->data;
453 }
454#endif
455 return platform_get_device_id(pdev)->driver_data;
456}
457
431static int __devinit s3c_rtc_probe(struct platform_device *pdev) 458static int __devinit s3c_rtc_probe(struct platform_device *pdev)
432{ 459{
433 struct rtc_device *rtc; 460 struct rtc_device *rtc;
434 struct rtc_time rtc_tm; 461 struct rtc_time rtc_tm;
435 struct resource *res; 462 struct resource *res;
436 int ret; 463 int ret;
464 int tmp;
437 465
438 pr_debug("%s: probe=%p\n", __func__, pdev); 466 pr_debug("%s: probe=%p\n", __func__, pdev);
439 467
@@ -508,13 +536,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
508 goto err_nortc; 536 goto err_nortc;
509 } 537 }
510 538
511#ifdef CONFIG_OF 539 s3c_rtc_cpu_type = s3c_rtc_get_driver_data(pdev);
512 if (pdev->dev.of_node)
513 s3c_rtc_cpu_type = of_device_is_compatible(pdev->dev.of_node,
514 "samsung,s3c6410-rtc") ? TYPE_S3C64XX : TYPE_S3C2410;
515 else
516#endif
517 s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
518 540
519 /* Check RTC Time */ 541 /* Check RTC Time */
520 542
@@ -533,11 +555,17 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
533 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); 555 dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
534 } 556 }
535 557
536 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 558 if (s3c_rtc_cpu_type != TYPE_S3C2410)
537 rtc->max_user_freq = 32768; 559 rtc->max_user_freq = 32768;
538 else 560 else
539 rtc->max_user_freq = 128; 561 rtc->max_user_freq = 128;
540 562
563 if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
564 tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
565 tmp |= S3C2443_RTCCON_TICSEL;
566 writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
567 }
568
541 platform_set_drvdata(pdev, rtc); 569 platform_set_drvdata(pdev, rtc);
542 570
543 s3c_rtc_setfreq(&pdev->dev, 1); 571 s3c_rtc_setfreq(&pdev->dev, 1);
@@ -638,8 +666,19 @@ static int s3c_rtc_resume(struct platform_device *pdev)
638 666
639#ifdef CONFIG_OF 667#ifdef CONFIG_OF
640static const struct of_device_id s3c_rtc_dt_match[] = { 668static const struct of_device_id s3c_rtc_dt_match[] = {
641 { .compatible = "samsung,s3c2410-rtc" }, 669 {
642 { .compatible = "samsung,s3c6410-rtc" }, 670 .compatible = "samsung,s3c2410-rtc"
671 .data = TYPE_S3C2410,
672 }, {
673 .compatible = "samsung,s3c2416-rtc"
674 .data = TYPE_S3C2416,
675 }, {
676 .compatible = "samsung,s3c2443-rtc"
677 .data = TYPE_S3C2443,
678 }, {
679 .compatible = "samsung,s3c6410-rtc"
680 .data = TYPE_S3C64XX,
681 },
643 {}, 682 {},
644}; 683};
645MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); 684MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
@@ -652,6 +691,12 @@ static struct platform_device_id s3c_rtc_driver_ids[] = {
652 .name = "s3c2410-rtc", 691 .name = "s3c2410-rtc",
653 .driver_data = TYPE_S3C2410, 692 .driver_data = TYPE_S3C2410,
654 }, { 693 }, {
694 .name = "s3c2416-rtc",
695 .driver_data = TYPE_S3C2416,
696 }, {
697 .name = "s3c2443-rtc",
698 .driver_data = TYPE_S3C2443,
699 }, {
655 .name = "s3c64xx-rtc", 700 .name = "s3c64xx-rtc",
656 .driver_data = TYPE_S3C64XX, 701 .driver_data = TYPE_S3C64XX,
657 }, 702 },