alpha: fix RTC on marvel
Unlike other alphas, marvel doesn't have real PC-style CMOS clock hardware - RTC accesses are emulated via PAL calls. Unfortunately, for unknown reason these calls work only on CPU #0. So current implementation for arbitrary CPU makes CMOS_READ/WRITE to be executed on CPU #0 via IPI. However, for obvious reason this doesn't work with standard get/set_rtc_time() functions, where a bunch of CMOS accesses is done with disabled interrupts. Solved by making the IPI calls for entire get/set_rtc_time() functions, not for individual CMOS accesses. Which is also a lot more effective performance-wise. The patch is largely based on the code from Jay Estabrook. My changes: - tweak asm-generic/rtc.h by adding a couple of #defines to avoid a massive code duplication in arch/alpha/include/asm/rtc.h; - sys_marvel.c: fix get/set_rtc_time() return values (Jay's FIXMEs). NOTE: this fixes *only* LIB_RTC drivers. Legacy (CONFIG_RTC) driver wont't work on marvel. Actually I think that we should just disable CONFIG_RTC on alpha (maybe in 2.6.30?), like most other arches - AFAIK, all modern distributions use LIB_RTC anyway. Signed-off-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Richard Henderson <rth@twiddle.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
2f88d151cb
commit
5f7dc5d750
@ -658,16 +658,8 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
|
||||
rtc_access.data = bcd2bin(b);
|
||||
rtc_access.function = 0x48 + !write; /* GET/PUT_TOY */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (smp_processor_id() != boot_cpuid)
|
||||
smp_call_function_single(boot_cpuid,
|
||||
__marvel_access_rtc,
|
||||
&rtc_access, 1);
|
||||
else
|
||||
__marvel_access_rtc(&rtc_access);
|
||||
#else
|
||||
__marvel_access_rtc(&rtc_access);
|
||||
#endif
|
||||
|
||||
ret = bin2bcd(rtc_access.data);
|
||||
break;
|
||||
|
||||
|
@ -40,7 +40,10 @@
|
||||
#define CAT1(x,y) x##y
|
||||
#define CAT(x,y) CAT1(x,y)
|
||||
|
||||
#define DO_DEFAULT_RTC .rtc_port = 0x70
|
||||
#define DO_DEFAULT_RTC \
|
||||
.rtc_port = 0x70, \
|
||||
.rtc_get_time = common_get_rtc_time, \
|
||||
.rtc_set_time = common_set_rtc_time
|
||||
|
||||
#define DO_EV4_MMU \
|
||||
.max_asn = EV4_MAX_ASN, \
|
||||
|
@ -145,6 +145,8 @@ extern void smp_percpu_timer_interrupt(struct pt_regs *);
|
||||
extern irqreturn_t timer_interrupt(int irq, void *dev);
|
||||
extern void common_init_rtc(void);
|
||||
extern unsigned long est_cycle_freq;
|
||||
extern unsigned int common_get_rtc_time(struct rtc_time *time);
|
||||
extern int common_set_rtc_time(struct rtc_time *time);
|
||||
|
||||
/* smc37c93x.c */
|
||||
extern void SMC93x_Init(void);
|
||||
|
@ -261,6 +261,8 @@ struct alpha_machine_vector jensen_mv __initmv = {
|
||||
.machine_check = jensen_machine_check,
|
||||
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
|
||||
.rtc_port = 0x170,
|
||||
.rtc_get_time = common_get_rtc_time,
|
||||
.rtc_set_time = common_set_rtc_time,
|
||||
|
||||
.nr_irqs = 16,
|
||||
.device_interrupt = jensen_device_interrupt,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/vga.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "err_impl.h"
|
||||
@ -426,6 +427,57 @@ marvel_init_rtc(void)
|
||||
init_rtc_irq();
|
||||
}
|
||||
|
||||
struct marvel_rtc_time {
|
||||
struct rtc_time *time;
|
||||
int retval;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void
|
||||
smp_get_rtc_time(void *data)
|
||||
{
|
||||
struct marvel_rtc_time *mrt = data;
|
||||
mrt->retval = __get_rtc_time(mrt->time);
|
||||
}
|
||||
|
||||
static void
|
||||
smp_set_rtc_time(void *data)
|
||||
{
|
||||
struct marvel_rtc_time *mrt = data;
|
||||
mrt->retval = __set_rtc_time(mrt->time);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int
|
||||
marvel_get_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
struct marvel_rtc_time mrt;
|
||||
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
mrt.time = time;
|
||||
smp_call_function_single(boot_cpuid, smp_get_rtc_time, &mrt, 1);
|
||||
return mrt.retval;
|
||||
}
|
||||
#endif
|
||||
return __get_rtc_time(time);
|
||||
}
|
||||
|
||||
static int
|
||||
marvel_set_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
struct marvel_rtc_time mrt;
|
||||
|
||||
if (smp_processor_id() != boot_cpuid) {
|
||||
mrt.time = time;
|
||||
smp_call_function_single(boot_cpuid, smp_set_rtc_time, &mrt, 1);
|
||||
return mrt.retval;
|
||||
}
|
||||
#endif
|
||||
return __set_rtc_time(time);
|
||||
}
|
||||
|
||||
static void
|
||||
marvel_smp_callin(void)
|
||||
{
|
||||
@ -466,7 +518,9 @@ marvel_smp_callin(void)
|
||||
struct alpha_machine_vector marvel_ev7_mv __initmv = {
|
||||
.vector_name = "MARVEL/EV7",
|
||||
DO_EV7_MMU,
|
||||
DO_DEFAULT_RTC,
|
||||
.rtc_port = 0x70,
|
||||
.rtc_get_time = marvel_get_rtc_time,
|
||||
.rtc_set_time = marvel_set_rtc_time,
|
||||
DO_MARVEL_IO,
|
||||
.machine_check = marvel_machine_check,
|
||||
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/8253pit.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
#include <linux/mc146818rtc.h>
|
||||
#include <linux/time.h>
|
||||
@ -180,6 +181,15 @@ common_init_rtc(void)
|
||||
init_rtc_irq();
|
||||
}
|
||||
|
||||
unsigned int common_get_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
return __get_rtc_time(time);
|
||||
}
|
||||
|
||||
int common_set_rtc_time(struct rtc_time *time)
|
||||
{
|
||||
return __set_rtc_time(time);
|
||||
}
|
||||
|
||||
/* Validate a computed cycle counter result against the known bounds for
|
||||
the given processor core. There's too much brokenness in the way of
|
||||
|
Reference in New Issue
Block a user