Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f7dc5d7 authored by Ivan Kokshaysky's avatar Ivan Kokshaysky Committed by Linus Torvalds
Browse files

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: default avatarIvan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2f88d151
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ struct pci_dev;
struct pci_ops;
struct pci_controller;
struct _alpha_agp_info;
struct rtc_time;

struct alpha_machine_vector
{
@@ -94,6 +95,9 @@ struct alpha_machine_vector

	struct _alpha_agp_info *(*agp_info)(void);

	unsigned int (*rtc_get_time)(struct rtc_time *);
	int (*rtc_set_time)(struct rtc_time *);

	const char *vector_name;

	/* NUMA information */
+9 −3
Original line number Diff line number Diff line
#ifndef _ALPHA_RTC_H
#define _ALPHA_RTC_H

/*
 * Alpha uses the default access methods for the RTC.
 */
#if defined(CONFIG_ALPHA_GENERIC)
# define get_rtc_time		alpha_mv.rtc_get_time
# define set_rtc_time		alpha_mv.rtc_set_time
#else
# if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP)
#  define get_rtc_time		marvel_get_rtc_time
#  define set_rtc_time		marvel_set_rtc_time
# endif
#endif

#include <asm-generic/rtc.h>

+1 −9
Original line number Diff line number Diff line
@@ -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;

+4 −1
Original line number Diff line number Diff line
@@ -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,			\
+2 −0
Original line number Diff line number Diff line
@@ -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);
Loading