patch-2.4.22 linux-2.4.22/arch/sh/kernel/time.c
Next file: linux-2.4.22/arch/sh/kernel/traps.c
Previous file: linux-2.4.22/arch/sh/kernel/sys_sh.c
Back to the patch index
Back to the overall index
- Lines: 290
- Date:
2003-08-25 04:44:40.000000000 -0700
- Orig file:
linux-2.4.21/arch/sh/kernel/time.c
- Orig date:
2001-09-08 12:29:09.000000000 -0700
diff -urN linux-2.4.21/arch/sh/kernel/time.c linux-2.4.22/arch/sh/kernel/time.c
@@ -1,9 +1,10 @@
-/* $Id: time.c,v 1.30 2001/09/01 14:34:31 mrbrown Exp $
+/* $Id: time.c,v 1.1.1.1.2.6 2003/07/16 18:43:55 yoshii Exp $
*
* linux/arch/sh/kernel/time.c
*
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
*
* Some code taken from i386 version.
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
@@ -29,17 +30,36 @@
#include <asm/delay.h>
#include <asm/machvec.h>
#include <asm/rtc.h>
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
#include <linux/timex.h>
#include <linux/irq.h>
-#define TMU_TOCR_INIT 0x00
-#define TMU0_TCR_INIT 0x0020
-#define TMU_TSTR_INIT 1
+#define TMU_TOCR_INIT 0x00 /* Don't output RTC clock */
+
+#define TMU0_TCR_INIT 0x0020 /* Clock/4, rising edge; interrupt on */
+#define TMU0_TCR_CALIB 0x0000 /* Clock/4, rising edge; no interrupt */
+#define TMU0_TSTR_INIT 0x01 /* Bit to turn on TMU0 */
-#define TMU0_TCR_CALIB 0x0000
+#define TMU1_TCR_INIT 0x0000 /* Clock/4, rising edge; no interrupt */
+#define TMU1_TSTR_INIT 0x02 /* Bit to turn on TMU1 */
#if defined(__sh3__)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+#define TMU_TSTR 0xA412FE92 /* Byte access */
+
+#define TMU0_TCOR 0xA412FE94 /* Long access */
+#define TMU0_TCNT 0xA412FE98 /* Long access */
+#define TMU0_TCR 0xA412FE9C /* Word access */
+
+#define TMU1_TCOR 0xA412FEA0 /* Long access */
+#define TMU1_TCNT 0xA412FEA4 /* Long access */
+#define TMU1_TCR 0xA412FEA8 /* Word access */
+
+#define FRQCR 0xA415FF80
+#else
#define TMU_TOCR 0xfffffe90 /* Byte access */
#define TMU_TSTR 0xfffffe92 /* Byte access */
@@ -47,7 +67,12 @@
#define TMU0_TCNT 0xfffffe98 /* Long access */
#define TMU0_TCR 0xfffffe9c /* Word access */
+#define TMU1_TCOR 0xfffffea0 /* Long access */
+#define TMU1_TCNT 0xfffffea4 /* Long access */
+#define TMU1_TCR 0xfffffea8 /* Word access */
+
#define FRQCR 0xffffff80
+#endif
#elif defined(__SH4__)
#define TMU_TOCR 0xffd80000 /* Byte access */
#define TMU_TSTR 0xffd80004 /* Byte access */
@@ -56,6 +81,10 @@
#define TMU0_TCNT 0xffd8000c /* Long access */
#define TMU0_TCR 0xffd80010 /* Word access */
+#define TMU1_TCOR 0xffd80014 /* Long access */
+#define TMU1_TCNT 0xffd80018 /* Long access */
+#define TMU1_TCR 0xffd8001c /* Word access */
+
#define FRQCR 0xffc00000
/* Core Processor Version Register */
@@ -64,10 +93,10 @@
#define CCN_PVR_CHIP_MASK 0xff
#define CCN_PVR_CHIP_ST40STB1 0x4
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
#define CLOCKGEN_MEMCLKCR 0xbb040038
#define MEMCLKCR_RATIO_MASK 0x7
-#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
+#endif /* CONFIG_CPU_SUBTYPE_ST40 */
#endif /* __sh3__ or __SH4__ */
extern rwlock_t xtime_lock;
@@ -176,6 +205,27 @@
/* last time the RTC clock got updated */
static long last_rtc_update;
+static __inline__ void sh_do_profile (unsigned long pc)
+{
+ extern int _stext;
+
+ if (!prof_buffer)
+ return;
+
+ if(pc >= 0xa0000000UL && pc < 0xc0000000UL)
+ pc -= 0x20000000;
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+ /*
+ * Don't ignore out-of-bounds PC values silently,
+ * put them into the last histogram slot, so if
+ * present, they will show up as a sharp peak.
+ */
+ if (pc > prof_len-1)
+ pc = prof_len-1;
+ prof_buffer[pc]++;
+}
+
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
@@ -245,7 +295,9 @@
* have it count down at its natural rate.
*/
ctrl_outb(0, TMU_TSTR);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+#endif
ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
ctrl_outl(0xffffffff, TMU0_TCOR);
ctrl_outl(0xffffffff, TMU0_TCNT);
@@ -257,7 +309,7 @@
} while (tv1.tv_usec == tv2.tv_usec && tv1.tv_sec == tv2.tv_sec);
/* actually start the timer */
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+ ctrl_outb(TMU0_TSTR_INIT, TMU_TSTR);
do {
rtc_gettimeofday(&tv2);
@@ -283,27 +335,41 @@
return freq * factor;
}
+static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ;
+static int __init sh_pclk_setup(char *str)
+{
+ unsigned int freq;
+ if (get_option(&str, &freq))
+ sh_pclk_freq = freq;
+ return 1;
+}
+__setup("sh_pclk=", sh_pclk_setup);
+
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
void __init time_init(void)
{
unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
unsigned int memory_clock;
#endif
unsigned int timer_freq;
unsigned short frqcr, ifc, pfc, bfc;
unsigned long interval;
#if defined(__sh3__)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+ static int pfc_table[] = { 1, 2, 3, 4, 6 };
+#else
static int ifc_table[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
static int pfc_table[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
static int stc_table[] = { 1, 2, 4, 8, 3, 6, 1, 1 };
+#endif
#elif defined(__SH4__)
static int ifc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
#define bfc_table ifc_table /* Same */
static int pfc_table[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
struct frqcr_data {
unsigned short frqcr;
struct {
@@ -359,19 +425,33 @@
#endif
#endif
- rtc_gettimeofday(&xtime);
+ if(rtc_gettimeofday)
+ rtc_gettimeofday(&xtime);
+ else{
+ xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+ xtime.tv_usec = 0;
+ }
setup_irq(TIMER_IRQ, &irq0);
- timer_freq = get_timer_frequency();
-
- module_clock = timer_freq * 4;
+ if( sh_pclk_freq ){
+ module_clock = sh_pclk_freq;
+ }else{
+ timer_freq = get_timer_frequency();
+ module_clock = timer_freq * 4;
+ }
#if defined(__sh3__)
{
unsigned short tmp;
frqcr = ctrl_inw(FRQCR);
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+ bfc = ((frqcr & 0x0700) >> 8)+1;
+ ifc = ((frqcr & 0x0070) >> 4)+1;
+ tmp = frqcr & 0x0007;
+ pfc = pfc_table[tmp];
+#else
tmp = (frqcr & 0x8000) >> 13;
tmp |= (frqcr & 0x0030) >> 4;
bfc = stc_table[tmp];
@@ -381,10 +461,11 @@
tmp = (frqcr & 0x2000) >> 11;
tmp |= frqcr & 0x0003;
pfc = pfc_table[tmp];
+#endif
}
#elif defined(__SH4__)
{
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
unsigned long pvr;
/* This should probably be moved into the SH3 probing code, and then use the processor
@@ -438,14 +519,14 @@
master_clock = module_clock * pfc;
bus_clock = master_clock / bfc;
cpu_clock = master_clock / ifc;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
skip_calc:
#endif
printk("CPU clock: %d.%02dMHz\n",
(cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
printk("Bus clock: %d.%02dMHz\n",
(bus_clock/1000000), (bus_clock % 1000000)/10000);
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
printk("Memory clock: %d.%02dMHz\n",
(memory_clock/1000000), (memory_clock % 1000000)/10000);
#endif
@@ -458,16 +539,37 @@
current_cpu_data.cpu_clock = cpu_clock;
current_cpu_data.master_clock = master_clock;
current_cpu_data.bus_clock = bus_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
current_cpu_data.memory_clock = memory_clock;
#endif
current_cpu_data.module_clock = module_clock;
- /* Start TMU0 */
+ /* Stop all timers */
ctrl_outb(0, TMU_TSTR);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+#endif
+
+ /* Start TMU0 (jiffy interrupts) */
ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
ctrl_outl(interval, TMU0_TCOR);
ctrl_outl(interval, TMU0_TCNT);
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+ ctrl_outb(TMU0_TSTR_INIT, TMU_TSTR);
+
+#if defined(CONFIG_START_TMU1)
+ /* Start TMU1 (free-running) */
+ ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
+ ctrl_outl(0xffffffff, TMU1_TCOR);
+ ctrl_outl(0xffffffff, TMU1_TCNT);
+ ctrl_outb((ctrl_inb(TMU_TSTR) | TMU1_TSTR_INIT), TMU_TSTR);
+#endif
+
+#if defined(CONFIG_SH_KGDB)
+ /*
+ * Set up kgdb as requested. We do it here because the serial
+ * init uses the timer vars we just set up for figuring baud.
+ */
+ kgdb_init();
+#endif
+
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)