Skip to contentSkip to conversation

x86/platform: add a wallclock_init func to x86_platforms ops

PATCH In review Alan Cox 3 participants 4 messages Jan 25, 2011 – Jan 27, 2011 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore

Alan Cox

author
#0 lore raw

PATCH 1/2 x86/platform: add a wallclock_init func to x86_platforms ops

From: Feng Tang <[email protected]>

Some wall clock devices use MMIO based HW register, this new function will give them a chance to do some initialization work before their get/set_time service get called.

---

 arch/x86/include/asm/x86_init.h |    2 ++
 arch/x86/kernel/setup.c         |    2 ++
 arch/x86/kernel/x86_init.c      |    2 ++
 3 files changed, 6 insertions(+), 0 deletions(-)
arch/x86/include/asm/x86_init.h +2 -0
index 64642ad..f7fa2e7 100644
@@ -138,6 +138,7 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:		calibrate TSC
+ * @wallclock_init:		init the wallclock device
  * @get_wallclock:		get time from HW clock like RTC etc.
  * @set_wallclock:		set time back to HW clock
  * @is_untracked_pat_range	exclude from PAT logic
@@ -146,6 +147,7 @@ struct x86_cpuinit_ops {
  */
 struct x86_platform_ops {
 	unsigned long (*calibrate_tsc)(void);
+	void (*wallclock_init)(void);
 	unsigned long (*get_wallclock)(void);
 	int (*set_wallclock)(unsigned long nowtime);
 	void (*iommu_shutdown)(void);
arch/x86/kernel/setup.c +2 -0
index d3cfe26..c204fd5 100644
@@ -1066,6 +1066,8 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	x86_init.oem.banner();
 
+	x86_platform.wallclock_init();
+
 	mcheck_init();
 
 	local_irq_save(flags);
arch/x86/kernel/x86_init.c +2 -0
index ceb2911..fc3f0e6 100644
@@ -27,6 +27,7 @@ void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
+void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -92,6 +93,7 @@ static int default_i8042_detect(void) { return 1; };
 
 struct x86_platform_ops x86_platform = {
 	.calibrate_tsc			= native_calibrate_tsc,
+	.wallclock_init			= wallclock_init_noop,
 	.get_wallclock			= mach_get_cmos_time,
 	.set_wallclock			= mach_set_rtc_mmss,
 	.iommu_shutdown			= iommu_shutdown_noop,
author
#1 lore raw

PATCH 2/2 mrst/vrtc: avoid using CMOS RTC ops

From: Jacob Pan <[email protected]>

If we don't assign Moorestown specific wallclock init and ops function the rtc/persisent clock code will use CMOS RTC for access, this will crash Moorestown as the ioports are not present.
Also in the vrtc driver, we should avoid using CMOS access to check UIP status.

---

 arch/x86/platform/mrst/mrst.c |    2 ++
 drivers/rtc/rtc-mrst.c        |   13 ++++++++++++-
 2 files changed, 14 insertions(+), 1 deletions(-)
arch/x86/platform/mrst/mrst.c +2 -0
index ea6529e..dea829c 100644
@@ -31,6 +31,7 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
 #include <asm/io.h>
 #include <asm/i8259.h>
 #include <asm/intel_scu_ipc.h>
@@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void)
 
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
 	x86_platform.i8042_detect = mrst_i8042_detect;
+	x86_platform.wallclock_init = mrst_rtc_init;
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
drivers/rtc/rtc-mrst.c +12 -1
index bcd0cf6..28e02e7 100644
@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr)
 	return rtc_intr & RTC_IRQMASK;
 }
 
+static inline unsigned char vrtc_is_updating(void)
+{
+	unsigned char uip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return uip;
+}
+
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
@@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
 {
 	unsigned long flags;
 
-	if (rtc_is_updating())
+	if (vrtc_is_updating())
 		mdelay(20);
 
 	spin_lock_irqsave(&rtc_lock, flags);

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw

Re: [PATCH 2/2] mrst/vrtc: avoid using CMOS RTC ops

Quoted 15 lines

From: Alan Cox <[email protected]>
Date: 2011/1/25
Subject: [PATCH 2/2] mrst/vrtc: avoid using CMOS RTC ops
To: [email protected], [email protected]

From: Jacob Pan <[email protected]>

If we don't assign Moorestown specific wallclock init and ops function the rtc/persisent clock code will use CMOS RTC for access, this will crash Moorestown as the ioports are not present.
Also in the vrtc driver, we should avoid using CMOS access to check UIP status.

Quoted 3 lines

---

Hi,

Here is the updated version, following the change of moving the wallclock_init() to x86_init.timers.

Thanks,
Feng
-----------------

Quoted 1 line

From f1b25a39a11a34036db625c8fb4e5a6a0acfa56d Mon Sep 17 00:00:00 2001

From: Feng Tang <[email protected]>
Date: Thu, 27 Jan 2011 09:39:08 +0800
Subject: [PATCH] mrst/vrtc: avoid using cmos rtc ops

If we don't assign Moorestown specific wallclock init and ops function the rtc/persisent clock code will use cmos rtc for access, this will crash Moorestown in that the ioports are not present.

Also in vrtc driver, should avoid using cmos access to check UIP status.

[[email protected]: use set_fixmap_offset_nocache() to simplify code]
---
 arch/x86/platform/mrst/mrst.c |    2 ++
 arch/x86/platform/mrst/vrtc.c |   15 ++++-----------
 drivers/rtc/rtc-mrst.c        |   13 ++++++++++++-
 3 files changed, 18 insertions(+), 12 deletions(-)
arch/x86/platform/mrst/mrst.c +2 -0
index ea6529e..5c0207b 100644
@@ -31,6 +31,7 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
 #include <asm/io.h>
 #include <asm/i8259.h>
 #include <asm/intel_scu_ipc.h>
@@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void)
 
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
 	x86_platform.i8042_detect = mrst_i8042_detect;
+	x86_init.timers.wallclock_init = mrst_rtc_init;
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
arch/x86/platform/mrst/vrtc.c +4 -11
index 32cd7ed..f6f34c5 100644
@@ -100,21 +100,14 @@ int vrtc_set_mmss(unsigned long nowtime)
 
 void __init mrst_rtc_init(void)
 {
-	unsigned long rtc_paddr;
-	void __iomem *virt_base;
+	unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr;
 
 	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
-	if (!sfi_mrtc_num)
+	if (!sfi_mrtc_num || !vrtc_paddr)
 		return;
 
-	rtc_paddr = sfi_mrtc_array[0].phys_addr;
-
-	/* vRTC's register address may not be page aligned */
-	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
-
-	virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
-	virt_base += rtc_paddr & ~PAGE_MASK;
-	vrtc_virt_base = virt_base;
+	vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
+								vrtc_paddr);
 
 	x86_platform.get_wallclock = vrtc_get_time;
 	x86_platform.set_wallclock = vrtc_set_mmss;
drivers/rtc/rtc-mrst.c +12 -1
index bcd0cf6..28e02e7 100644
@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr)
 	return rtc_intr & RTC_IRQMASK;
 }
 
+static inline unsigned char vrtc_is_updating(void)
+{
+	unsigned char uip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return uip;
+}
+
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
@@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
 {
 	unsigned long flags;
 
-	if (rtc_is_updating())
+	if (vrtc_is_updating())
 		mdelay(20);
 
 	spin_lock_irqsave(&rtc_lock, flags);
Signature · 1 line
1.7.0.4
#4 lore raw
In reply to Alan Cox
Quoted 22 lines · Alan Cox

From: Feng Tang <[email protected]>

Some wall clock devices use MMIO based HW register, this new function will give them a chance to do some initialization work before their get/set_time service get called.

---

 arch/x86/include/asm/x86_init.h |    2 ++
 arch/x86/kernel/setup.c         |    2 ++
 arch/x86/kernel/x86_init.c      |    2 ++
 3 files changed, 6 insertions(+), 0 deletions(-)
arch/x86/include/asm/x86_init.h +0 -0
index 64642ad..f7fa2e7 100644

arch/x86/include/asm/x86_init.h struct x86_cpuinit_ops { · line 141

Quoted 4 lines
arch/x86/include/asm/x86_init.h +1 -0
@@ -138,6 +138,7 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:		calibrate TSC
+ * @wallclock_init:		init the wallclock device

That's a one time called init function, so it should go into x86_init_ops.

Thanks,

tglx