1/* 2 * Copyright 2006, Broadcom Corporation 3 * All Rights Reserved. 4 * 5 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 6 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 7 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 8 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 9 * 10 * $Id: time.c,v 1.1.1.1 2008/10/15 03:26:06 james26_jang Exp $ 11 */ 12#include <linux/config.h> 13#include <linux/init.h> 14#include <linux/kernel.h> 15#include <linux/sched.h> 16#include <linux/serial_reg.h> 17#include <linux/interrupt.h> 18#include <asm/addrspace.h> 19#include <asm/io.h> 20#include <asm/time.h> 21 22#include <typedefs.h> 23#include <osl.h> 24#include <bcmutils.h> 25#include <bcmnvram.h> 26#include <sbconfig.h> 27#include <sbextif.h> 28#include <sbchipc.h> 29#include <sbutils.h> 30#include <hndmips.h> 31#include <mipsinc.h> 32#include <hndcpu.h> 33#include <bcmdevs.h> 34 35/* Global SB handle */ 36extern void *bcm947xx_sbh; 37extern spinlock_t bcm947xx_sbh_lock; 38 39/* Convenience */ 40#define sbh bcm947xx_sbh 41#define sbh_lock bcm947xx_sbh_lock 42 43extern int panic_timeout; 44static int watchdog = 0; 45static u8 *mcr = NULL; 46 47void __init 48bcm947xx_time_init(void) 49{ 50 unsigned int hz; 51 extifregs_t *eir; 52 53 /* 54 * Use deterministic values for initial counter interrupt 55 * so that calibrate delay avoids encountering a counter wrap. 56 */ 57 write_c0_count(0); 58 write_c0_compare(0xffff); 59 60 if (!(hz = sb_cpu_clock(sbh))) 61 hz = 100000000; 62 63 printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh), sb_chiprev(sbh), 64 (hz + 500000) / 1000000); 65 66 /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ 67 mips_counter_frequency = hz / 2; 68 69 /* Set watchdog interval in ms */ 70 watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0); 71 72 /* Please set the watchdog to 3 sec if it is less than 3 but not equal to 0 */ 73 if (watchdog > 0) { 74 if (watchdog < 3000) 75 watchdog = 3000; 76 } 77 78 /* Set panic timeout in seconds */ 79 panic_timeout = watchdog / 1000; 80 81 /* Setup blink */ 82 if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { 83 sbconfig_t *sb = (sbconfig_t *)((unsigned int) eir + SBCONFIGOFF); 84 unsigned long base = EXTIF_CFGIF_BASE(sb_base(readl(&sb->sbadmatch1))); 85 mcr = (u8 *) ioremap_nocache(base + UART_MCR, 1); 86 } 87} 88 89#ifdef CONFIG_HND_BMIPS3300_PROF 90extern bool hndprofiling; 91#ifdef CONFIG_MIPS64 92typedef u_int64_t sbprof_pc; 93#else 94typedef u_int32_t sbprof_pc; 95#endif 96extern void sbprof_cpu_intr(sbprof_pc restartpc); 97#endif /* CONFIG_HND_BMIPS3300_PROF */ 98 99static void 100bcm947xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 101{ 102#ifdef CONFIG_HND_BMIPS3300_PROF 103 /* 104 * Are there any ExcCode or other mean(s) to determine what has caused 105 * the timer interrupt? For now simply stop the normal timer proc if 106 * count register is less than compare register. 107 */ 108 if (hndprofiling) { 109 sbprof_cpu_intr(regs->cp0_epc + 110 ((regs->cp0_cause >> (CAUSEB_BD - 2)) & 4)); 111 if (read_c0_count() < read_c0_compare()) 112 return; 113 } 114#endif /* CONFIG_HND_BMIPS3300_PROF */ 115 116 /* Generic MIPS timer code */ 117 timer_interrupt(irq, dev_id, regs); 118 119 /* Set the watchdog timer to reset after the specified number of ms */ 120 if (watchdog > 0) { 121 if (sb_chip(sbh) == BCM5354_CHIP_ID) 122 sb_watchdog(sbh, WATCHDOG_CLOCK_5354 / 1000 * watchdog); 123 else 124 sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog); 125 } 126 127#ifdef CONFIG_HWSIM 128 (*((int *)0xa0000f1c))++; 129#else 130 /* Blink one of the LEDs in the external UART */ 131 if (mcr && !(jiffies % (HZ/2))) 132 writeb(readb(mcr) ^ UART_MCR_OUT2, mcr); 133#endif 134} 135 136static struct irqaction bcm947xx_timer_irqaction = { 137 bcm947xx_timer_interrupt, 138 SA_INTERRUPT, 139 0, 140 "timer", 141 NULL, 142 NULL 143}; 144 145void __init 146bcm947xx_timer_setup(struct irqaction *irq) 147{ 148 /* Enable the timer interrupt */ 149 setup_irq(7, &bcm947xx_timer_irqaction); 150} 151 152#define CFE_UPDATE 1 // added by Chen-I for mac/regulation update 153 154#ifdef CFE_UPDATE 155void bcm947xx_watchdog_disable(void) 156{ 157 watchdog=0; 158 sb_watchdog(sbh, 0); 159} 160#endif 161 162