diff options
-rw-r--r-- | Documentation/devicetree/bindings/rtc/rtc-cmos.txt | 28 | ||||
-rw-r--r-- | arch/x86/kernel/rtc.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 45 | ||||
-rw-r--r-- | include/linux/of.h | 12 |
4 files changed, 88 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.txt b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt new file mode 100644 index 00000000000..7382989b305 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt | |||
@@ -0,0 +1,28 @@ | |||
1 | Motorola mc146818 compatible RTC | ||
2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
3 | |||
4 | Required properties: | ||
5 | - compatible : "motorola,mc146818" | ||
6 | - reg : should contain registers location and length. | ||
7 | |||
8 | Optional properties: | ||
9 | - interrupts : should contain interrupt. | ||
10 | - interrupt-parent : interrupt source phandle. | ||
11 | - ctrl-reg : Contains the initial value of the control register also | ||
12 | called "Register B". | ||
13 | - freq-reg : Contains the initial value of the frequency register also | ||
14 | called "Regsiter A". | ||
15 | |||
16 | "Register A" and "B" are usually initialized by the firmware (BIOS for | ||
17 | instance). If this is not done, it can be performed by the driver. | ||
18 | |||
19 | ISA Example: | ||
20 | |||
21 | rtc@70 { | ||
22 | compatible = "motorola,mc146818"; | ||
23 | interrupts = <8 3>; | ||
24 | interrupt-parent = <&ioapic1>; | ||
25 | ctrl-reg = <2>; | ||
26 | freq-reg = <0x26>; | ||
27 | reg = <1 0x70 2>; | ||
28 | }; | ||
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 6f39cab052d..3f2ad2640d8 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/acpi.h> | 6 | #include <linux/acpi.h> |
7 | #include <linux/bcd.h> | 7 | #include <linux/bcd.h> |
8 | #include <linux/pnp.h> | 8 | #include <linux/pnp.h> |
9 | #include <linux/of.h> | ||
9 | 10 | ||
10 | #include <asm/vsyscall.h> | 11 | #include <asm/vsyscall.h> |
11 | #include <asm/x86_init.h> | 12 | #include <asm/x86_init.h> |
@@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void) | |||
236 | } | 237 | } |
237 | } | 238 | } |
238 | #endif | 239 | #endif |
240 | if (of_have_populated_dt()) | ||
241 | return 0; | ||
239 | 242 | ||
240 | platform_device_register(&rtc_device); | 243 | platform_device_register(&rtc_device); |
241 | dev_info(&rtc_device.dev, | 244 | dev_info(&rtc_device.dev, |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index c7ff8df347e..159b95e4b42 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | #include <linux/log2.h> | 38 | #include <linux/log2.h> |
39 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
40 | #include <linux/of.h> | ||
41 | #include <linux/of_platform.h> | ||
40 | 42 | ||
41 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
42 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
@@ -1123,6 +1125,47 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1123 | 1125 | ||
1124 | #endif /* CONFIG_PNP */ | 1126 | #endif /* CONFIG_PNP */ |
1125 | 1127 | ||
1128 | #ifdef CONFIG_OF | ||
1129 | static const struct of_device_id of_cmos_match[] = { | ||
1130 | { | ||
1131 | .compatible = "motorola,mc146818", | ||
1132 | }, | ||
1133 | { }, | ||
1134 | }; | ||
1135 | MODULE_DEVICE_TABLE(of, of_cmos_match); | ||
1136 | |||
1137 | static __init void cmos_of_init(struct platform_device *pdev) | ||
1138 | { | ||
1139 | struct device_node *node = pdev->dev.of_node; | ||
1140 | struct rtc_time time; | ||
1141 | int ret; | ||
1142 | const __be32 *val; | ||
1143 | |||
1144 | if (!node) | ||
1145 | return; | ||
1146 | |||
1147 | val = of_get_property(node, "ctrl-reg", NULL); | ||
1148 | if (val) | ||
1149 | CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL); | ||
1150 | |||
1151 | val = of_get_property(node, "freq-reg", NULL); | ||
1152 | if (val) | ||
1153 | CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); | ||
1154 | |||
1155 | get_rtc_time(&time); | ||
1156 | ret = rtc_valid_tm(&time); | ||
1157 | if (ret) { | ||
1158 | struct rtc_time def_time = { | ||
1159 | .tm_year = 1, | ||
1160 | .tm_mday = 1, | ||
1161 | }; | ||
1162 | set_rtc_time(&def_time); | ||
1163 | } | ||
1164 | } | ||
1165 | #else | ||
1166 | static inline void cmos_of_init(struct platform_device *pdev) {} | ||
1167 | #define of_cmos_match NULL | ||
1168 | #endif | ||
1126 | /*----------------------------------------------------------------*/ | 1169 | /*----------------------------------------------------------------*/ |
1127 | 1170 | ||
1128 | /* Platform setup should have set up an RTC device, when PNP is | 1171 | /* Platform setup should have set up an RTC device, when PNP is |
@@ -1131,6 +1174,7 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1131 | 1174 | ||
1132 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1175 | static int __init cmos_platform_probe(struct platform_device *pdev) |
1133 | { | 1176 | { |
1177 | cmos_of_init(pdev); | ||
1134 | cmos_wake_setup(&pdev->dev); | 1178 | cmos_wake_setup(&pdev->dev); |
1135 | return cmos_do_probe(&pdev->dev, | 1179 | return cmos_do_probe(&pdev->dev, |
1136 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1180 | platform_get_resource(pdev, IORESOURCE_IO, 0), |
@@ -1162,6 +1206,7 @@ static struct platform_driver cmos_platform_driver = { | |||
1162 | #ifdef CONFIG_PM | 1206 | #ifdef CONFIG_PM |
1163 | .pm = &cmos_pm_ops, | 1207 | .pm = &cmos_pm_ops, |
1164 | #endif | 1208 | #endif |
1209 | .of_match_table = of_cmos_match, | ||
1165 | } | 1210 | } |
1166 | }; | 1211 | }; |
1167 | 1212 | ||
diff --git a/include/linux/of.h b/include/linux/of.h index d9dd664a6a9..266db1d0baa 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -70,6 +70,11 @@ extern struct device_node *allnodes; | |||
70 | extern struct device_node *of_chosen; | 70 | extern struct device_node *of_chosen; |
71 | extern rwlock_t devtree_lock; | 71 | extern rwlock_t devtree_lock; |
72 | 72 | ||
73 | static inline bool of_have_populated_dt(void) | ||
74 | { | ||
75 | return allnodes != NULL; | ||
76 | } | ||
77 | |||
73 | static inline bool of_node_is_root(const struct device_node *node) | 78 | static inline bool of_node_is_root(const struct device_node *node) |
74 | { | 79 | { |
75 | return node && (node->parent == NULL); | 80 | return node && (node->parent == NULL); |
@@ -222,5 +227,12 @@ extern void of_attach_node(struct device_node *); | |||
222 | extern void of_detach_node(struct device_node *); | 227 | extern void of_detach_node(struct device_node *); |
223 | #endif | 228 | #endif |
224 | 229 | ||
230 | #else | ||
231 | |||
232 | static inline bool of_have_populated_dt(void) | ||
233 | { | ||
234 | return false; | ||
235 | } | ||
236 | |||
225 | #endif /* CONFIG_OF */ | 237 | #endif /* CONFIG_OF */ |
226 | #endif /* _LINUX_OF_H */ | 238 | #endif /* _LINUX_OF_H */ |