Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 234912
b: refs/heads/master
c: 695884f
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner committed Feb 22, 2011
1 parent 72ea904 commit 7d44db3
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 71 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 04bea68b2f0eeebb089ecc67b618795925268b4a
refs/heads/master: 695884fb8acd9857e0e7120ccb2150e30f4b8fef
2 changes: 2 additions & 0 deletions trunk/arch/x86/include/asm/x86_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ struct x86_init_paging {
* boot cpu
* @tsc_pre_init: platform function called before TSC init
* @timer_init: initialize the platform timer (default PIT/HPET)
* @wallclock_init: init the wallclock device
*/
struct x86_init_timers {
void (*setup_percpu_clockev)(void);
void (*tsc_pre_init)(void);
void (*timer_init)(void);
void (*wallclock_init)(void);
};

/**
Expand Down
60 changes: 4 additions & 56 deletions trunk/arch/x86/kernel/apb_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta,
return 0;
}

/*
* APB timer clock is not in sync with pclk on Langwell, which translates to
* unreliable read value caused by sampling error. the error does not add up
* overtime and only happens when sampling a 0 as a 1 by mistake. so the time
* would go backwards. the following code is trying to prevent time traveling
* backwards. little bit paranoid.
*/
static cycle_t apbt_read_clocksource(struct clocksource *cs)
{
unsigned long t0, t1, t2;
static unsigned long last_read;

bad_count:
t1 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
t2 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
if (unlikely(t1 < t2)) {
pr_debug("APBT: read current count error %lx:%lx:%lx\n",
t1, t2, t2 - t1);
goto bad_count;
}
/*
* check against cached last read, makes sure time does not go back.
* it could be a normal rollover but we will do tripple check anyway
*/
if (unlikely(t2 > last_read)) {
/* check if we have a normal rollover */
unsigned long raw_intr_status =
apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
/*
* cs timer interrupt is masked but raw intr bit is set if
* rollover occurs. then we read EOI reg to clear it.
*/
if (raw_intr_status & (1 << phy_cs_timer_id)) {
apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
goto out;
}
pr_debug("APB CS going back %lx:%lx:%lx ",
t2, last_read, t2 - last_read);
bad_count_x3:
pr_debug("triple check enforced\n");
t0 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
udelay(1);
t1 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
udelay(1);
t2 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
if ((t2 > t1) || (t1 > t0)) {
printk(KERN_ERR "Error: APB CS tripple check failed\n");
goto bad_count_x3;
}
}
out:
last_read = t2;
return (cycle_t)~t2;
unsigned long current_count;

current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
return (cycle_t)~current_count;
}

static int apbt_clocksource_register(void)
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,8 @@ void __init setup_arch(char **cmdline_p)
#endif
x86_init.oem.banner();

x86_init.timers.wallclock_init();

mcheck_init();

local_irq_save(flags);
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/x86_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = {
.setup_percpu_clockev = setup_boot_APIC_clock,
.tsc_pre_init = x86_init_noop,
.timer_init = hpet_time_init,
.wallclock_init = x86_init_noop,
},

.iommu = {
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/pci/ce4100.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
static int ce4100_conf_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
int i, retval = 1;
int i;

if (bus == 1) {
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/x86/platform/mrst/mrst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;

Expand Down
16 changes: 4 additions & 12 deletions trunk/arch/x86/platform/mrst/vrtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +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;
}
Expand Down
13 changes: 12 additions & 1 deletion trunk/drivers/rtc/rtc-mrst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down

0 comments on commit 7d44db3

Please sign in to comment.