Commit 8d8bb7ce authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Torvalds

[PATCH] M68k generic RTC driver updates

M68k generic RTC driver updates:
  - Revive help text for CONFIG_GEN_RTC
  - Re-add lost config option for CONFIG_GEN_RTC_X
  - Re-add lost mach_get_ss()
  - Export mach_[gs]et_rtc_pll()
  - Add implementation of mach_get_ss() and mach_[gs]et_rtc_pll() for Q40/Q60
  - Add missing include
  - Add implementation of get_rtc_ss()
parent e465fe96
...@@ -1720,6 +1720,31 @@ config GEN_RTC ...@@ -1720,6 +1720,31 @@ config GEN_RTC
tristate "Generic /dev/rtc emulation" if !SUN3 tristate "Generic /dev/rtc emulation" if !SUN3
depends on !ATARI depends on !ATARI
default y if SUN3 default y if SUN3
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
will get access to the real time clock (or hardware clock) built
into your computer.
It reports status information via the file /proc/driver/rtc and its
behaviour is set by various ioctls on /dev/rtc. If you enable the
"extended RTC operation" below it will also provide an emulation
for RTC_UIE which is required by some programs and may improve
precision in some cases.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module is called genrtc.o. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>. To load the
module automatically add 'alias char-major-10-135 genrtc' to your
/etc/modules.conf
config GEN_RTC_X
bool "Extended RTC operation"
depends on GEN_RTC
help
Provides an emulation for RTC_UIE which is required by some programs
and may improve precision of the generic RTC support in some cases.
config UNIX98_PTYS config UNIX98_PTYS
bool "Unix98 PTY support" bool "Unix98 PTY support"
......
...@@ -50,6 +50,9 @@ EXPORT_SYMBOL(kernel_set_cachemode); ...@@ -50,6 +50,9 @@ EXPORT_SYMBOL(kernel_set_cachemode);
#endif /* !CONFIG_SUN3 */ #endif /* !CONFIG_SUN3 */
EXPORT_SYMBOL(m68k_debug_device); EXPORT_SYMBOL(m68k_debug_device);
EXPORT_SYMBOL(mach_hwclk); EXPORT_SYMBOL(mach_hwclk);
EXPORT_SYMBOL(mach_get_ss);
EXPORT_SYMBOL(mach_get_rtc_pll);
EXPORT_SYMBOL(mach_set_rtc_pll);
EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strnlen);
......
...@@ -82,6 +82,7 @@ void (*mach_process_int) (int, struct pt_regs *) = NULL; ...@@ -82,6 +82,7 @@ void (*mach_process_int) (int, struct pt_regs *) = NULL;
unsigned long (*mach_gettimeoffset) (void); unsigned long (*mach_gettimeoffset) (void);
int (*mach_hwclk) (int, struct rtc_time*) = NULL; int (*mach_hwclk) (int, struct rtc_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL; int (*mach_set_clock_mmss) (unsigned long) = NULL;
unsigned int (*mach_get_ss)(void) = NULL;
int (*mach_get_rtc_pll)(struct rtc_pll_info *) = NULL; int (*mach_get_rtc_pll)(struct rtc_pll_info *) = NULL;
int (*mach_set_rtc_pll)(struct rtc_pll_info *) = NULL; int (*mach_set_rtc_pll)(struct rtc_pll_info *) = NULL;
void (*mach_reset)( void ); void (*mach_reset)( void );
......
...@@ -53,7 +53,10 @@ extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *)); ...@@ -53,7 +53,10 @@ extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *));
extern unsigned long q40_gettimeoffset (void); extern unsigned long q40_gettimeoffset (void);
extern int q40_hwclk (int, struct rtc_time *); extern int q40_hwclk (int, struct rtc_time *);
extern unsigned int q40_get_ss (void);
extern int q40_set_clock_mmss (unsigned long); extern int q40_set_clock_mmss (unsigned long);
static int q40_get_rtc_pll(struct rtc_pll_info *pll);
static int q40_set_rtc_pll(struct rtc_pll_info *pll);
extern void q40_reset (void); extern void q40_reset (void);
void q40_halt(void); void q40_halt(void);
extern void q40_waitbut(void); extern void q40_waitbut(void);
...@@ -170,6 +173,9 @@ void __init config_q40(void) ...@@ -170,6 +173,9 @@ void __init config_q40(void)
mach_init_IRQ = q40_init_IRQ; mach_init_IRQ = q40_init_IRQ;
mach_gettimeoffset = q40_gettimeoffset; mach_gettimeoffset = q40_gettimeoffset;
mach_hwclk = q40_hwclk; mach_hwclk = q40_hwclk;
mach_get_ss = q40_get_ss;
mach_get_rtc_pll = q40_get_rtc_pll;
mach_set_rtc_pll = q40_set_rtc_pll;
mach_set_clock_mmss = q40_set_clock_mmss; mach_set_clock_mmss = q40_set_clock_mmss;
mach_reset = q40_reset; mach_reset = q40_reset;
...@@ -290,6 +296,11 @@ int q40_hwclk(int op, struct rtc_time *t) ...@@ -290,6 +296,11 @@ int q40_hwclk(int op, struct rtc_time *t)
return 0; return 0;
} }
unsigned int q40_get_ss()
{
return bcd2bin(Q40_RTC_SECS);
}
/* /*
* Set the minutes and seconds from seconds value 'nowtime'. Fail if * Set the minutes and seconds from seconds value 'nowtime'. Fail if
* clock is out by > 30 minutes. Logic lifted from atari code. * clock is out by > 30 minutes. Logic lifted from atari code.
...@@ -321,3 +332,36 @@ int q40_set_clock_mmss (unsigned long nowtime) ...@@ -321,3 +332,36 @@ int q40_set_clock_mmss (unsigned long nowtime)
return retval; return retval;
} }
/* get and set PLL calibration of RTC clock */
#define Q40_RTC_PLL_MASK ((1<<5)-1)
#define Q40_RTC_PLL_SIGN (1<<5)
static int q40_get_rtc_pll(struct rtc_pll_info *pll)
{
int tmp=Q40_RTC_CTRL;
pll->pll_value = tmp & Q40_RTC_PLL_MASK;
if (tmp & Q40_RTC_PLL_SIGN)
pll->pll_value = -pll->pll_value;
pll->pll_max=31;
pll->pll_min=-31;
pll->pll_posmult=512;
pll->pll_negmult=256;
pll->pll_clock=125829120;
return 0;
}
static int q40_set_rtc_pll(struct rtc_pll_info *pll)
{
if (!pll->pll_ctrl){
/* the docs are a bit unclear so I am doublesetting */
/* RTC_WRITE here ... */
int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) |
Q40_RTC_WRITE;
Q40_RTC_CTRL |= Q40_RTC_WRITE;
Q40_RTC_CTRL = tmp;
Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
return 0;
} else
return -EINVAL;
}
...@@ -23,6 +23,7 @@ extern void (*mach_process_int) (int irq, struct pt_regs *fp); ...@@ -23,6 +23,7 @@ extern void (*mach_process_int) (int irq, struct pt_regs *fp);
/* machine dependent timer functions */ /* machine dependent timer functions */
extern unsigned long (*mach_gettimeoffset)(void); extern unsigned long (*mach_gettimeoffset)(void);
extern int (*mach_hwclk)(int, struct rtc_time*); extern int (*mach_hwclk)(int, struct rtc_time*);
extern unsigned int (*mach_get_ss)(void);
extern int (*mach_get_rtc_pll)(struct rtc_pll_info *); extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
extern int (*mach_set_rtc_pll)(struct rtc_pll_info *); extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
extern int (*mach_set_clock_mmss)(unsigned long); extern int (*mach_set_clock_mmss)(unsigned long);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/rtc.h>
#include <asm/machdep.h> #include <asm/machdep.h>
/* a few implementation details for the emulation : */ /* a few implementation details for the emulation : */
...@@ -45,6 +46,18 @@ static inline int set_rtc_time(struct rtc_time *time) ...@@ -45,6 +46,18 @@ static inline int set_rtc_time(struct rtc_time *time)
return mach_hwclk(1, time); return mach_hwclk(1, time);
} }
static inline unsigned int get_rtc_ss(void)
{
if (mach_get_ss)
return mach_get_ss();
else{
struct rtc_time h;
get_rtc_time(&h);
return h.tm_sec;
}
}
static inline int get_rtc_pll(struct rtc_pll_info *pll) static inline int get_rtc_pll(struct rtc_pll_info *pll)
{ {
if (mach_get_rtc_pll) if (mach_get_rtc_pll)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment