Skip to content

Commit

Permalink
[POWERPC] Implement {read,update}_persistent_clock
Browse files Browse the repository at this point in the history
With these functions implemented we cooperate better with the generic
timekeeping code.  This obsoletes the need for the timer sysdev as a bonus.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Tony Breeds authored and Paul Mackerras committed Oct 3, 2007
1 parent df174e3 commit aa3be5f
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 145 deletions.
3 changes: 3 additions & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ config MMU
bool
default y

config GENERIC_CMOS_UPDATE
def_bool y

config GENERIC_HARDIRQS
bool
default y
Expand Down
85 changes: 26 additions & 59 deletions arch/powerpc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,11 @@
#include <asm/iseries/hv_call_xm.h>
#endif

/* keep track of when we need to update the rtc */
time_t last_rtc_update;
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
#endif

/* The decrementer counts down by 128 every 128ns on a 601. */
#define DECREMENTER_COUNT_601 (1000000000 / HZ)

#define XSEC_PER_SEC (1024*1024)

#ifdef CONFIG_PPC64
Expand Down Expand Up @@ -348,39 +343,6 @@ void udelay(unsigned long usecs)
}
EXPORT_SYMBOL(udelay);

static __inline__ void timer_check_rtc(void)
{
/*
* update the rtc when needed, this should be performed on the
* right fraction of a second. Half or full second ?
* Full second works on mk48t59 clocks, others need testing.
* Note that this update is basically only used through
* the adjtimex system calls. Setting the HW clock in
* any other way is a /dev/rtc and userland business.
* This is still wrong by -0.5/+1.5 jiffies because of the
* timer interrupt resolution and possible delay, but here we
* hit a quantization limit which can only be solved by higher
* resolution timers and decoupling time management from timer
* interrupts. This is also wrong on the clocks
* which require being written at the half second boundary.
* We should have an rtc call that only sets the minutes and
* seconds like on Intel to avoid problems with non UTC clocks.
*/
if (ppc_md.set_rtc_time && ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ) {
struct rtc_time tm;
to_tm(xtime.tv_sec + 1 + timezone_offset, &tm);
tm.tm_year -= 1900;
tm.tm_mon -= 1;
if (ppc_md.set_rtc_time(&tm) == 0)
last_rtc_update = xtime.tv_sec + 1;
else
/* Try again one minute later */
last_rtc_update += 60;
}
}

/*
* This version of gettimeofday has microsecond resolution.
*/
Expand Down Expand Up @@ -689,7 +651,6 @@ void timer_interrupt(struct pt_regs * regs)
tb_last_jiffy = tb_next_jiffy;
do_timer(1);
timer_recalc_offset(tb_last_jiffy);
timer_check_rtc();
}
write_sequnlock(&xtime_lock);
}
Expand Down Expand Up @@ -801,11 +762,6 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, new_sec, new_nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);

/* In case of a large backwards jump in time with NTP, we want the
* clock to be updated as soon as the PLL is again in lock.
*/
last_rtc_update = new_sec - 658;

ntp_clear();

new_xsec = xtime.tv_nsec;
Expand Down Expand Up @@ -881,12 +837,35 @@ void __init generic_calibrate_decr(void)
#endif
}

unsigned long get_boot_time(void)
int update_persistent_clock(struct timespec now)
{
struct rtc_time tm;

if (!ppc_md.set_rtc_time)
return 0;

to_tm(now.tv_sec + 1 + timezone_offset, &tm);
tm.tm_year -= 1900;
tm.tm_mon -= 1;

return ppc_md.set_rtc_time(&tm);
}

unsigned long read_persistent_clock(void)
{
struct rtc_time tm;
static int first = 1;

/* XXX this is a litle fragile but will work okay in the short term */
if (first) {
first = 0;
if (ppc_md.time_init)
timezone_offset = ppc_md.time_init();

if (ppc_md.get_boot_time)
return ppc_md.get_boot_time();
/* get_boot_time() isn't guaranteed to be safe to call late */
if (ppc_md.get_boot_time)
return ppc_md.get_boot_time() -timezone_offset;
}
if (!ppc_md.get_rtc_time)
return 0;
ppc_md.get_rtc_time(&tm);
Expand All @@ -898,14 +877,10 @@ unsigned long get_boot_time(void)
void __init time_init(void)
{
unsigned long flags;
unsigned long tm = 0;
struct div_result res;
u64 scale, x;
unsigned shift;

if (ppc_md.time_init != NULL)
timezone_offset = ppc_md.time_init();

if (__USE_RTC()) {
/* 601 processor: dec counts down by 128 every 128ns */
ppc_tb_freq = 1000000000;
Expand Down Expand Up @@ -980,19 +955,14 @@ void __init time_init(void)
/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
boot_tb = get_tb_or_rtc();

tm = get_boot_time();

write_seqlock_irqsave(&xtime_lock, flags);

/* If platform provided a timezone (pmac), we correct the time */
if (timezone_offset) {
sys_tz.tz_minuteswest = -timezone_offset / 60;
sys_tz.tz_dsttime = 0;
tm -= timezone_offset;
}

xtime.tv_sec = tm;
xtime.tv_nsec = 0;
do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
Expand All @@ -1010,9 +980,6 @@ void __init time_init(void)

time_freq = 0;

last_rtc_update = xtime.tv_sec;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irqrestore(&xtime_lock, flags);

/* Not exact, but the timer interrupt takes care of this */
Expand Down
5 changes: 0 additions & 5 deletions arch/powerpc/sysdev/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
obj-$(CONFIG_AXON_RAM) += axonram.o

# contains only the suspend handler for time
ifeq ($(CONFIG_RTC_CLASS),)
obj-$(CONFIG_PM) += timer.o
endif

ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
Expand Down
81 changes: 0 additions & 81 deletions arch/powerpc/sysdev/timer.c

This file was deleted.

0 comments on commit aa3be5f

Please sign in to comment.