Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: cmos: Add OF bindings

This allows to load the OF driver based informations from the device
tree. Systems without BIOS may need to perform some initialization.
PowerPC creates a PNP device from the OF information and performs this
kind of initialization in their private PCI quirk. This looks more
generic.

This patch also avoids registering the platform RTC driver on X86 if
we have a device tree blob. Otherwise we would setup the device based
on the hardcoded information in arch/x86 rather than the device tree
based one.

[ tglx: Changed "int of_have_populated_dt()" to bool as recommended by
Grant ]

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Cc: sodaville@linutronix.de
Cc: devicetree-discuss@lists.ozlabs.org
Cc: rtc-linux@googlegroups.com
Cc: Alessandro Zummo <a.zummo@towertech.it>
LKML-Reference: <1298405266-1624-12-git-send-email-bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Sebastian Andrzej Siewior and committed by
Thomas Gleixner
3bcbaf6e 1fa4163b

+88
+28
Documentation/devicetree/bindings/rtc/rtc-cmos.txt
··· 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 + };
+3
arch/x86/kernel/rtc.c
··· 6 6 #include <linux/acpi.h> 7 7 #include <linux/bcd.h> 8 8 #include <linux/pnp.h> 9 + #include <linux/of.h> 9 10 10 11 #include <asm/vsyscall.h> 11 12 #include <asm/x86_init.h> ··· 237 236 } 238 237 } 239 238 #endif 239 + if (of_have_populated_dt()) 240 + return 0; 240 241 241 242 platform_device_register(&rtc_device); 242 243 dev_info(&rtc_device.dev,
+45
drivers/rtc/rtc-cmos.c
··· 37 37 #include <linux/mod_devicetable.h> 38 38 #include <linux/log2.h> 39 39 #include <linux/pm.h> 40 + #include <linux/of.h> 41 + #include <linux/of_platform.h> 40 42 41 43 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ 42 44 #include <asm-generic/rtc.h> ··· 1125 1123 1126 1124 #endif /* CONFIG_PNP */ 1127 1125 1126 + #ifdef CONFIG_OF 1127 + static const struct of_device_id of_cmos_match[] = { 1128 + { 1129 + .compatible = "motorola,mc146818", 1130 + }, 1131 + { }, 1132 + }; 1133 + MODULE_DEVICE_TABLE(of, of_cmos_match); 1134 + 1135 + static __init void cmos_of_init(struct platform_device *pdev) 1136 + { 1137 + struct device_node *node = pdev->dev.of_node; 1138 + struct rtc_time time; 1139 + int ret; 1140 + const __be32 *val; 1141 + 1142 + if (!node) 1143 + return; 1144 + 1145 + val = of_get_property(node, "ctrl-reg", NULL); 1146 + if (val) 1147 + CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL); 1148 + 1149 + val = of_get_property(node, "freq-reg", NULL); 1150 + if (val) 1151 + CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT); 1152 + 1153 + get_rtc_time(&time); 1154 + ret = rtc_valid_tm(&time); 1155 + if (ret) { 1156 + struct rtc_time def_time = { 1157 + .tm_year = 1, 1158 + .tm_mday = 1, 1159 + }; 1160 + set_rtc_time(&def_time); 1161 + } 1162 + } 1163 + #else 1164 + static inline void cmos_of_init(struct platform_device *pdev) {} 1165 + #define of_cmos_match NULL 1166 + #endif 1128 1167 /*----------------------------------------------------------------*/ 1129 1168 1130 1169 /* Platform setup should have set up an RTC device, when PNP is ··· 1174 1131 1175 1132 static int __init cmos_platform_probe(struct platform_device *pdev) 1176 1133 { 1134 + cmos_of_init(pdev); 1177 1135 cmos_wake_setup(&pdev->dev); 1178 1136 return cmos_do_probe(&pdev->dev, 1179 1137 platform_get_resource(pdev, IORESOURCE_IO, 0), ··· 1206 1162 #ifdef CONFIG_PM 1207 1163 .pm = &cmos_pm_ops, 1208 1164 #endif 1165 + .of_match_table = of_cmos_match, 1209 1166 } 1210 1167 }; 1211 1168
+12
include/linux/of.h
··· 70 70 extern struct device_node *of_chosen; 71 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 78 static inline bool of_node_is_root(const struct device_node *node) 74 79 { 75 80 return node && (node->parent == NULL); ··· 226 221 extern void of_attach_node(struct device_node *); 227 222 extern void of_detach_node(struct device_node *); 228 223 #endif 224 + 225 + #else 226 + 227 + static inline bool of_have_populated_dt(void) 228 + { 229 + return false; 230 + } 229 231 230 232 #endif /* CONFIG_OF */ 231 233 #endif /* _LINUX_OF_H */