aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/platform/mrst/vrtc.c46
-rw-r--r--drivers/rtc/Kconfig12
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-mrst.c578
4 files changed, 637 insertions, 0 deletions
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
index 4944bd521d2c..4d3f770456f7 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -20,6 +20,7 @@
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/sfi.h> 22#include <linux/sfi.h>
23#include <linux/platform_device.h>
23 24
24#include <asm/mrst.h> 25#include <asm/mrst.h>
25#include <asm/mrst-vrtc.h> 26#include <asm/mrst-vrtc.h>
@@ -118,3 +119,48 @@ void __init mrst_rtc_init(void)
118 x86_platform.get_wallclock = vrtc_get_time; 119 x86_platform.get_wallclock = vrtc_get_time;
119 x86_platform.set_wallclock = vrtc_set_mmss; 120 x86_platform.set_wallclock = vrtc_set_mmss;
120} 121}
122
123/*
124 * The Moorestown platform has a memory mapped virtual RTC device that emulates
125 * the programming interface of the RTC.
126 */
127
128static struct resource vrtc_resources[] = {
129 [0] = {
130 .flags = IORESOURCE_MEM,
131 },
132 [1] = {
133 .flags = IORESOURCE_IRQ,
134 }
135};
136
137static struct platform_device vrtc_device = {
138 .name = "rtc_mrst",
139 .id = -1,
140 .resource = vrtc_resources,
141 .num_resources = ARRAY_SIZE(vrtc_resources),
142};
143
144/* Register the RTC device if appropriate */
145static int __init mrst_device_create(void)
146{
147 /* No Moorestown, no device */
148 if (!mrst_identify_cpu())
149 return -ENODEV;
150 /* No timer, no device */
151 if (!sfi_mrtc_num)
152 return -ENODEV;
153
154 /* iomem resource */
155 vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr;
156 vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr +
157 MRST_VRTC_MAP_SZ;
158 /* irq resource */
159 vrtc_resources[1].start = sfi_mrtc_array[0].irq;
160 vrtc_resources[1].end = sfi_mrtc_array[0].irq;
161
162 platform_device_register(&vrtc_device);
163 return 0;
164}
165
166module_init(mrst_device_create);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2883428d5ac8..4941cade319f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -463,6 +463,18 @@ config RTC_DRV_CMOS
463 This driver can also be built as a module. If so, the module 463 This driver can also be built as a module. If so, the module
464 will be called rtc-cmos. 464 will be called rtc-cmos.
465 465
466config RTC_DRV_VRTC
467 tristate "Virtual RTC for Moorestown platforms"
468 depends on X86_MRST
469 default y if X86_MRST
470
471 help
472 Say "yes" here to get direct support for the real time clock
473 found on Moorestown platforms. The VRTC is a emulated RTC that
474 derives its clock source from a real RTC in the PMIC. The MC146818
475 style programming interface is mostly conserved, but any
476 updates are done via IPC calls to the system controller FW.
477
466config RTC_DRV_DS1216 478config RTC_DRV_DS1216
467 tristate "Dallas DS1216" 479 tristate "Dallas DS1216"
468 depends on SNI_RM 480 depends on SNI_RM
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 4c2832df4697..2afdaf3ff986 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
30obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o 30obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
31obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o 31obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o
32obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o 32obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
33obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
33obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o 34obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
34obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o 35obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
35obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o 36obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
new file mode 100644
index 000000000000..67b6be2b874d
--- /dev/null
+++ b/drivers/rtc/rtc-mrst.c
@@ -0,0 +1,578 @@
1/*
2 * rtc-mrst.c: Driver for Moorestown virtual RTC
3 *
4 * (C) Copyright 2009 Intel Corporation
5 * Author: Jacob Pan (jacob.jun.pan@intel.com)
6 * Feng Tang (feng.tang@intel.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; version 2
11 * of the License.
12 *
13 * Note:
14 * VRTC is emulated by system controller firmware, the real HW
15 * RTC is located in the PMIC device. SCU FW shadows PMIC RTC
16 * in a memory mapped IO space that is visible to the host IA
17 * processor.
18 *
19 * This driver is based upon drivers/rtc/rtc-cmos.c
20 */
21
22/*
23 * Note:
24 * * vRTC only supports binary mode and 24H mode
25 * * vRTC only support PIE and AIE, no UIE, and its PIE only happens
26 * at 23:59:59pm everyday, no support for adjustable frequency
27 * * Alarm function is also limited to hr/min/sec.
28 */
29
30#include <linux/mod_devicetable.h>
31#include <linux/platform_device.h>
32#include <linux/interrupt.h>
33#include <linux/spinlock.h>
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/init.h>
37#include <linux/sfi.h>
38
39#include <asm-generic/rtc.h>
40#include <asm/intel_scu_ipc.h>
41#include <asm/mrst.h>
42#include <asm/mrst-vrtc.h>
43
44struct mrst_rtc {
45 struct rtc_device *rtc;
46 struct device *dev;
47 int irq;
48 struct resource *iomem;
49
50 u8 enabled_wake;
51 u8 suspend_ctrl;
52};
53
54static const char driver_name[] = "rtc_mrst";
55
56#define RTC_IRQMASK (RTC_PF | RTC_AF)
57
58static inline int is_intr(u8 rtc_intr)
59{
60 if (!(rtc_intr & RTC_IRQF))
61 return 0;
62 return rtc_intr & RTC_IRQMASK;
63}
64
65/*
66 * rtc_time's year contains the increment over 1900, but vRTC's YEAR
67 * register can't be programmed to value larger than 0x64, so vRTC
68 * driver chose to use 1960 (1970 is UNIX time start point) as the base,
69 * and does the translation at read/write time
70 */
71static int mrst_read_time(struct device *dev, struct rtc_time *time)
72{
73 unsigned long flags;
74
75 if (rtc_is_updating())
76 mdelay(20);
77
78 spin_lock_irqsave(&rtc_lock, flags);
79 time->tm_sec = vrtc_cmos_read(RTC_SECONDS);
80 time->tm_min = vrtc_cmos_read(RTC_MINUTES);
81 time->tm_hour = vrtc_cmos_read(RTC_HOURS);
82 time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
83 time->tm_mon = vrtc_cmos_read(RTC_MONTH);
84 time->tm_year = vrtc_cmos_read(RTC_YEAR);
85 spin_unlock_irqrestore(&rtc_lock, flags);
86
87 /* Adjust for the 1960/1900 */
88 time->tm_year += 60;
89 time->tm_mon--;
90 return RTC_24H;
91}
92
93static int mrst_set_time(struct device *dev, struct rtc_time *time)
94{
95 int ret;
96 unsigned long flags;
97 unsigned char mon, day, hrs, min, sec;
98 unsigned int yrs;
99
100 yrs = time->tm_year;
101 mon = time->tm_mon + 1; /* tm_mon starts at zero */
102 day = time->tm_mday;
103 hrs = time->tm_hour;