From: M. R. B. <mr...@su...> - 2001-09-01 07:12:03
|
Here's preliminary support for the Dreamcast AICA RTC registers - it adds the appropiate calls to the machvec which allows the timer frequency and RTC query stuff to work as intended. I'll be writing mc146818rtc stuff in a bit. M. R. 2000-08-31 M. R. Brown <mr...@0x...> * arch/sh/kernel/Makefile: Add dependency for rtc-aica.o for CONFIG_SH_DREAMCAST. * arch/sh/kernel/mach_dc.c: Add prototypes and pointers for the AICA RTC routines to the machvec. * arch/sh/kernel/time.c (time_init): Remove checks for MACH_DREAMCAST as we can just use the RTC routines defined in the machvec. * arch/sh/kernel/rtc-aica.c: New file. Index: Makefile =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/Makefile,v retrieving revision 1.30 diff -u -r1.30 Makefile --- Makefile 2001/08/24 12:38:19 1.30 +++ Makefile 2001/09/01 06:08:03 @@ -74,7 +74,7 @@ obj-$(CONFIG_HD64465) += setup_hd64465.o io_hd64465.o hd64465_gpio.o obj-$(CONFIG_SH_DMIDA) += mach_dmida.o obj-$(CONFIG_SH_EC3104) += setup_ec3104.o io_ec3104.o mach_ec3104.o -obj-$(CONFIG_SH_DREAMCAST) += mach_dc.o setup_dc.o io_dc.o +obj-$(CONFIG_SH_DREAMCAST) += mach_dc.o setup_dc.o io_dc.o rtc-aica.o ifeq ($(CONFIG_SH_GENERIC),y) obj-y += $(machine-specific-objs) Index: mach_dc.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/mach_dc.c,v retrieving revision 1.4 diff -u -r1.4 mach_dc.c --- mach_dc.c 2001/05/24 05:09:16 1.4 +++ mach_dc.c 2001/09/01 06:08:03 @@ -1,10 +1,11 @@ /* - * $Id: mach_dc.c,v 1.4 2001/05/24 05:09:16 mrbrown Exp $ + * $Id: mach_dc.c,v 1.2 2001/09/01 04:45:08 mrbrown Exp $ * SEGA Dreamcast machine vector */ #include <linux/config.h> #include <linux/init.h> +#include <linux/time.h> #include <asm/machvec.h> #include <asm/machvec_init.h> @@ -16,6 +17,10 @@ void __init setup_dreamcast(void); void __init dreamcast_pcibios_init(void); +/* Custom Dreamcast RTC routines */ +void aica_rtc_gettimeofday(struct timeval *tv); +int aica_rtc_settimeofday(const struct timeval *tv); + /* * The Machine Vector */ @@ -59,6 +64,9 @@ mv_init_arch: setup_dreamcast, mv_isa_port2addr: dreamcast_isa_port2addr, mv_irq_demux: systemasic_irq_demux, + + mv_rtc_gettimeofday: aica_rtc_gettimeofday, + mv_rtc_settimeofday: aica_rtc_settimeofday, mv_hw_dreamcast: 1, }; Index: time.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/time.c,v retrieving revision 1.29 diff -u -r1.29 time.c --- time.c 2001/07/23 10:43:42 1.29 +++ time.c 2001/09/01 06:08:03 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.29 2001/07/23 10:43:42 gniibe Exp $ +/* $Id: time.c,v 1.2 2001/09/01 04:45:48 mrbrown Exp $ * * linux/arch/sh/kernel/time.c * @@ -359,17 +359,11 @@ #endif #endif - if (MACH_DREAMCAST) - xtime.tv_sec = xtime.tv_usec = 0; - else - rtc_gettimeofday(&xtime); + rtc_gettimeofday(&xtime); setup_irq(TIMER_IRQ, &irq0); - if (MACH_DREAMCAST) - timer_freq = 50*1000*1000/4; - else - timer_freq = get_timer_frequency(); + timer_freq = get_timer_frequency(); module_clock = timer_freq * 4; =================================================================== /* arch/sh/kernel/rtc-aica.c * * Dreamcast AICA RTC routines. * * Copyright (c) 2001 M. R. Brown <mr...@0x...> * * Released under the terms of the GNU GPL v2.0. * */ #include <linux/time.h> #include <asm/io.h> /* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in seconds to get the standard Unix Epoch when getting the time, and add 20 years when setting the time. */ #define TWENTY_YEARS ((20 * 365LU + 5) * 86400) /* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit registers.*/ #define AICA_RTC_SECS_H 0xa0710000 #define AICA_RTC_SECS_L 0xa0710004 /** * aica_rtc_gettimeofday - Get the time from the AICA RTC * @tv: pointer to resulting timeval * * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch. */ void aica_rtc_gettimeofday(struct timeval *tv) { unsigned long val1, val2; do { val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); } while (val1 != val2); tv->tv_sec = val1 - TWENTY_YEARS; /* Can't get microseconds with just a seconds counter. */ tv->tv_usec = 0; } /** * aica_rtc_settimeofday - Set the AICA RTC to the current time * @tv: contains the timeval to set * * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter. */ int aica_rtc_settimeofday(const struct timeval *tv) { unsigned long val1, val2; unsigned long secs = tv->tv_sec + TWENTY_YEARS; do { ctrl_outl((secs & 0xffff0000) >> 16, AICA_RTC_SECS_H); ctrl_outl((secs & 0xffff), AICA_RTC_SECS_L); val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); } while (val1 != val2); return 0; } |