1 /* 2 * 3 * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com> 4 * Copied and modified Carsten Langgaard's time.c 5 * 6 * Carsten Langgaard, carstenl@mips.com 7 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. 8 * 9 * ######################################################################## 10 * 11 * This program is free software; you can distribute it and/or modify it 12 * under the terms of the GNU General Public License (Version 2) as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope it will be useful, but WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 * for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 23 * 24 * ######################################################################## 25 * 26 * Setting up the clock on the MIPS boards. 27 * 28 * We provide the clock interrupt processing and the timer offset compute 29 * functions. If CONFIG_PM is selected, we also ensure the 32KHz timer is 30 * available. -- Dan 31 */ 32 33 #include <linux/types.h> 34 #include <linux/init.h> 35 #include <linux/spinlock.h> 36 37 #include <asm/mipsregs.h> 38 #include <asm/time.h> 39 #include <asm/mach-au1x00/au1000.h> 40 41 static int no_au1xxx_32khz; 42 extern int allow_au1k_wait; /* default off for CP0 Counter */ 43 44 #ifdef CONFIG_PM 45 #if HZ < 100 || HZ > 1000 46 #error "unsupported HZ value! Must be in [100,1000]" 47 #endif 48 #define MATCH20_INC (328 * 100 / HZ) /* magic number 328 is for HZ=100... */ 49 static unsigned long last_pc0, last_match20; 50 #endif 51 52 static DEFINE_SPINLOCK(time_lock); 53 54 unsigned long wtimer; 55 56 #ifdef CONFIG_PM 57 static irqreturn_t counter0_irq(int irq, void *dev_id) 58 { 59 unsigned long pc0; 60 int time_elapsed; 61 static int jiffie_drift; 62 63 if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { 64 /* should never happen! */ 65 printk(KERN_WARNING "counter 0 w status error\n"); 66 return IRQ_NONE; 67 } 68 69 pc0 = au_readl(SYS_TOYREAD); 70 if (pc0 < last_match20) 71 /* counter overflowed */ 72 time_elapsed = (0xffffffff - last_match20) + pc0; 73 else 74 time_elapsed = pc0 - last_match20; 75 76 while (time_elapsed > 0) { 77 do_timer(1); 78 #ifndef CONFIG_SMP 79 update_process_times(user_mode(get_irq_regs())); 80 #endif 81 time_elapsed -= MATCH20_INC; 82 last_match20 += MATCH20_INC; 83 jiffie_drift++; 84 } 85 86 last_pc0 = pc0; 87 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); 88 au_sync(); 89 90 /* 91 * Our counter ticks at 10.009765625 ms/tick, we we're running 92 * almost 10 uS too slow per tick. 93 */ 94 95 if (jiffie_drift >= 999) { 96 jiffie_drift -= 999; 97 do_timer(1); /* increment jiffies by one */ 98 #ifndef CONFIG_SMP 99 update_process_times(user_mode(get_irq_regs())); 100 #endif 101 } 102 103 return IRQ_HANDLED; 104 } 105 106 struct irqaction counter0_action = { 107 .handler = counter0_irq, 108 .flags = IRQF_DISABLED, 109 .name = "alchemy-toy", 110 .dev_id = NULL, 111 }; 112 113 /* When we wakeup from sleep, we have to "catch up" on all of the 114 * timer ticks we have missed. 115 */ 116 void wakeup_counter0_adjust(void) 117 { 118 unsigned long pc0; 119 int time_elapsed; 120 121 pc0 = au_readl(SYS_TOYREAD); 122 if (pc0 < last_match20) 123 /* counter overflowed */ 124 time_elapsed = (0xffffffff - last_match20) + pc0; 125 else 126 time_elapsed = pc0 - last_match20; 127 128 while (time_elapsed > 0) { 129 time_elapsed -= MATCH20_INC; 130 last_match20 += MATCH20_INC; 131 } 132 133 last_pc0 = pc0; 134 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); 135 au_sync(); 136 137 } 138 139 /* This is just for debugging to set the timer for a sleep delay. */ 140 void wakeup_counter0_set(int ticks) 141 { 142 unsigned long pc0; 143 144 pc0 = au_readl(SYS_TOYREAD); 145 last_pc0 = pc0; 146 au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2); 147 au_sync(); 148 } 149 #endif 150 151 /* 152 * I haven't found anyone that doesn't use a 12 MHz source clock, 153 * but just in case..... 154 */ 155 #define AU1000_SRC_CLK 12000000 156 157 /* 158 * We read the real processor speed from the PLL. This is important 159 * because it is more accurate than computing it from the 32 KHz 160 * counter, if it exists. If we don't have an accurate processor 161 * speed, all of the peripherals that derive their clocks based on 162 * this advertised speed will introduce error and sometimes not work 163 * properly. This function is futher convoluted to still allow configurations 164 * to do that in case they have really, really old silicon with a 165 * write-only PLL register, that we need the 32 KHz when power management 166 * "wait" is enabled, and we need to detect if the 32 KHz isn't present 167 * but requested......got it? :-) -- Dan 168 */ 169 unsigned long calc_clock(void) 170 { 171 unsigned long cpu_speed; 172 unsigned long flags; 173 unsigned long counter; 174 175 spin_lock_irqsave(&time_lock, flags); 176 177 /* Power management cares if we don't have a 32 KHz counter. */ 178 no_au1xxx_32khz = 0; 179 counter = au_readl(SYS_COUNTER_CNTRL); 180 if (counter & SYS_CNTRL_E0) { 181 int trim_divide = 16; 182 183 au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL); 184 185 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); 186 /* RTC now ticks at 32.768/16 kHz */ 187 au_writel(trim_divide - 1, SYS_RTCTRIM); 188 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); 189 190 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); 191 au_writel(0, SYS_TOYWRITE); 192 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); 193 } else 194 no_au1xxx_32khz = 1; 195 196 /* 197 * On early Au1000, sys_cpupll was write-only. Since these 198 * silicon versions of Au1000 are not sold by AMD, we don't bend 199 * over backwards trying to determine the frequency. 200 */ 201 if (cur_cpu_spec[0]->cpu_pll_wo) 202 #ifdef CONFIG_SOC_AU1000_FREQUENCY 203 cpu_speed = CONFIG_SOC_AU1000_FREQUENCY; 204 #else 205 cpu_speed = 396000000; 206 #endif 207 else 208 cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; 209 /* On Alchemy CPU:counter ratio is 1:1 */ 210 mips_hpt_frequency = cpu_speed; 211 /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */ 212 set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL) 213 & 0x03) + 2) * 16)); 214 spin_unlock_irqrestore(&time_lock, flags); 215 return cpu_speed; 216 } 217 218 void __init plat_time_init(void) 219 { 220 unsigned int est_freq = calc_clock(); 221 222 est_freq += 5000; /* round */ 223 est_freq -= est_freq%10000; 224 printk(KERN_INFO "CPU frequency %u.%02u MHz\n", 225 est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000); 226 set_au1x00_speed(est_freq); 227 set_au1x00_lcd_clock(); /* program the LCD clock */ 228 229 #ifdef CONFIG_PM 230 /* 231 * setup counter 0, since it keeps ticking after a 232 * 'wait' instruction has been executed. The CP0 timer and 233 * counter 1 do NOT continue running after 'wait' 234 * 235 * It's too early to call request_irq() here, so we handle 236 * counter 0 interrupt as a special irq and it doesn't show 237 * up under /proc/interrupts. 238 * 239 * Check to ensure we really have a 32 KHz oscillator before 240 * we do this. 241 */ 242 if (no_au1xxx_32khz) 243 printk(KERN_WARNING "WARNING: no 32KHz clock found.\n"); 244 else { 245 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); 246 au_writel(0, SYS_TOYWRITE); 247 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); 248 249 au_writel(au_readl(SYS_WAKEMSK) | (1 << 8), SYS_WAKEMSK); 250 au_writel(~0, SYS_WAKESRC); 251 au_sync(); 252 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); 253 254 /* Setup match20 to interrupt once every HZ */ 255 last_pc0 = last_match20 = au_readl(SYS_TOYREAD); 256 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); 257 au_sync(); 258 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); 259 setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action); 260 261 /* We can use the real 'wait' instruction. */ 262 allow_au1k_wait = 1; 263 } 264 265 #endif 266 } 267