rtc-s3c: add variants for S3C2443 and S3C2416

Especially the TICNT registers are different from the two rtc
types that currently exists.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
This commit is contained in:
Heiko Stuebner 2011-12-24 10:52:19 +09:00 коммит произвёл Kukjin Kim
Родитель d2524caac3
Коммит 25c1a24660
2 изменённых файлов: 53 добавлений и 4 удалений

Просмотреть файл

@ -22,11 +22,28 @@
#define S3C2410_RTCCON_RTCEN (1 << 0) #define S3C2410_RTCCON_RTCEN (1 << 0)
#define S3C2410_RTCCON_CNTSEL (1 << 2) #define S3C2410_RTCCON_CNTSEL (1 << 2)
#define S3C2410_RTCCON_CLKRST (1 << 3) #define S3C2410_RTCCON_CLKRST (1 << 3)
#define S3C2443_RTCCON_TICSEL (1 << 4)
#define S3C64XX_RTCCON_TICEN (1 << 8) #define S3C64XX_RTCCON_TICEN (1 << 8)
#define S3C2410_TICNT S3C2410_RTCREG(0x44) #define S3C2410_TICNT S3C2410_RTCREG(0x44)
#define S3C2410_TICNT_ENABLE (1 << 7) #define S3C2410_TICNT_ENABLE (1 << 7)
/* S3C2443: tick count is 15 bit wide
* TICNT[6:0] contains upper 7 bits
* TICNT1[7:0] contains lower 8 bits
*/
#define S3C2443_TICNT_PART(x) ((x & 0x7f00) >> 8)
#define S3C2443_TICNT1 S3C2410_RTCREG(0x4C)
#define S3C2443_TICNT1_PART(x) (x & 0xff)
/* S3C2416: tick count is 32 bit wide
* TICNT[6:0] contains bits [14:8]
* TICNT1[7:0] contains lower 8 bits
* TICNT2[16:0] contains upper 17 bits
*/
#define S3C2416_TICNT2 S3C2410_RTCREG(0x48)
#define S3C2416_TICNT2_PART(x) ((x & 0xffff8000) >> 15)
#define S3C2410_RTCALM S3C2410_RTCREG(0x50) #define S3C2410_RTCALM S3C2410_RTCREG(0x50)
#define S3C2410_RTCALM_ALMEN (1 << 6) #define S3C2410_RTCALM_ALMEN (1 << 6)
#define S3C2410_RTCALM_YEAREN (1 << 5) #define S3C2410_RTCALM_YEAREN (1 << 5)

Просмотреть файл

@ -35,6 +35,8 @@
enum s3c_cpu_type { enum s3c_cpu_type {
TYPE_S3C2410, TYPE_S3C2410,
TYPE_S3C2416,
TYPE_S3C2443,
TYPE_S3C64XX, TYPE_S3C64XX,
}; };
@ -132,6 +134,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct rtc_device *rtc_dev = platform_get_drvdata(pdev); struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
unsigned int tmp = 0; unsigned int tmp = 0;
int val;
if (!is_power_of_2(freq)) if (!is_power_of_2(freq))
return -EINVAL; return -EINVAL;
@ -139,12 +142,22 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
clk_enable(rtc_clk); clk_enable(rtc_clk);
spin_lock_irq(&s3c_rtc_pie_lock); spin_lock_irq(&s3c_rtc_pie_lock);
if (s3c_rtc_cpu_type == TYPE_S3C2410) { if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
tmp = readb(s3c_rtc_base + S3C2410_TICNT); tmp = readb(s3c_rtc_base + S3C2410_TICNT);
tmp &= S3C2410_TICNT_ENABLE; tmp &= S3C2410_TICNT_ENABLE;
} }
tmp |= (rtc_dev->max_user_freq / freq)-1; val = (rtc_dev->max_user_freq / freq) - 1;
if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
tmp |= S3C2443_TICNT_PART(val);
writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1);
if (s3c_rtc_cpu_type == TYPE_S3C2416)
writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2);
} else {
tmp |= val;
}
writel(tmp, s3c_rtc_base + S3C2410_TICNT); writel(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock); spin_unlock_irq(&s3c_rtc_pie_lock);
@ -371,7 +384,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
tmp &= ~S3C2410_RTCCON_RTCEN; tmp &= ~S3C2410_RTCCON_RTCEN;
writew(tmp, base + S3C2410_RTCCON); writew(tmp, base + S3C2410_RTCCON);
if (s3c_rtc_cpu_type == TYPE_S3C2410) { if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
tmp = readb(base + S3C2410_TICNT); tmp = readb(base + S3C2410_TICNT);
tmp &= ~S3C2410_TICNT_ENABLE; tmp &= ~S3C2410_TICNT_ENABLE;
writeb(tmp, base + S3C2410_TICNT); writeb(tmp, base + S3C2410_TICNT);
@ -448,6 +461,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
struct rtc_time rtc_tm; struct rtc_time rtc_tm;
struct resource *res; struct resource *res;
int ret; int ret;
int tmp;
pr_debug("%s: probe=%p\n", __func__, pdev); pr_debug("%s: probe=%p\n", __func__, pdev);
@ -541,11 +555,17 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
} }
if (s3c_rtc_cpu_type == TYPE_S3C64XX) if (s3c_rtc_cpu_type != TYPE_S3C2410)
rtc->max_user_freq = 32768; rtc->max_user_freq = 32768;
else else
rtc->max_user_freq = 128; rtc->max_user_freq = 128;
if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
tmp |= S3C2443_RTCCON_TICSEL;
writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
}
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
s3c_rtc_setfreq(&pdev->dev, 1); s3c_rtc_setfreq(&pdev->dev, 1);
@ -649,6 +669,12 @@ static const struct of_device_id s3c_rtc_dt_match[] = {
{ {
.compatible = "samsung,s3c2410-rtc" .compatible = "samsung,s3c2410-rtc"
.data = TYPE_S3C2410, .data = TYPE_S3C2410,
}, {
.compatible = "samsung,s3c2416-rtc"
.data = TYPE_S3C2416,
}, {
.compatible = "samsung,s3c2443-rtc"
.data = TYPE_S3C2443,
}, { }, {
.compatible = "samsung,s3c6410-rtc" .compatible = "samsung,s3c6410-rtc"
.data = TYPE_S3C64XX, .data = TYPE_S3C64XX,
@ -664,6 +690,12 @@ static struct platform_device_id s3c_rtc_driver_ids[] = {
{ {
.name = "s3c2410-rtc", .name = "s3c2410-rtc",
.driver_data = TYPE_S3C2410, .driver_data = TYPE_S3C2410,
}, {
.name = "s3c2416-rtc",
.driver_data = TYPE_S3C2416,
}, {
.name = "s3c2443-rtc",
.driver_data = TYPE_S3C2443,
}, { }, {
.name = "s3c64xx-rtc", .name = "s3c64xx-rtc",
.driver_data = TYPE_S3C64XX, .driver_data = TYPE_S3C64XX,