Пример #1
0
void __init time_init(void)
{
        unsigned int est_freq;

	printk("calculating r4koff... ");
	r4k_offset = cal_r4koff();
	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);

	//est_freq = 2*r4k_offset*HZ;
	est_freq = r4k_offset*HZ;
	est_freq += 5000;    /* round */
	est_freq -= est_freq%10000;
	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
	       (est_freq%1000000)*100/1000000);
 	set_au1x00_speed(est_freq);
 	set_au1x00_lcd_clock(); // program the LCD clock
	r4k_cur = (read_c0_count() + r4k_offset);

	write_c0_compare(r4k_cur);

	/* no RTC on the pb1000 */
	xtime.tv_sec = 0;
	xtime.tv_usec = 0;

#ifdef CONFIG_PM
	/*
	 * setup counter 0, since it keeps ticking after a
	 * 'wait' instruction has been executed. The CP0 timer and
	 * counter 1 do NOT continue running after 'wait'
	 *
	 * It's too early to call request_irq() here, so we handle
	 * counter 0 interrupt as a special irq and it doesn't show
	 * up under /proc/interrupts.
	 */
	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
	au_writel(0, SYS_TOYWRITE);
	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);

	au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
	au_writel(~0, SYS_WAKESRC);
	au_sync();
	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);

	/* setup match20 to interrupt once every 10ms */
	last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
	au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
	au_sync();
	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
	startup_match20_interrupt();
#endif

	//set_c0_status(ALLINTS);
	au_sync();
}
Пример #2
0
void __init plat_timer_setup(struct irqaction *irq)
{
    unsigned int est_freq;

    printk("calculating r4koff... ");
    r4k_offset = cal_r4koff();
    printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);

    //est_freq = 2*r4k_offset*HZ;
    est_freq = r4k_offset*HZ;
    est_freq += 5000;    /* round */
    est_freq -= est_freq%10000;
    printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
           (est_freq%1000000)*100/1000000);
    set_au1x00_speed(est_freq);
    set_au1x00_lcd_clock(); // program the LCD clock

    r4k_cur = (read_c0_count() + r4k_offset);
    write_c0_compare(r4k_cur);

#ifdef CONFIG_PM
    /*
     * setup counter 0, since it keeps ticking after a
     * 'wait' instruction has been executed. The CP0 timer and
     * counter 1 do NOT continue running after 'wait'
     *
     * It's too early to call request_irq() here, so we handle
     * counter 0 interrupt as a special irq and it doesn't show
     * up under /proc/interrupts.
     *
     * Check to ensure we really have a 32KHz oscillator before
     * we do this.
     */
    if (no_au1xxx_32khz) {
        unsigned int c0_status;

        printk("WARNING: no 32KHz clock found.\n");

        /* Ensure we get CPO_COUNTER interrupts.
        */
        c0_status = read_c0_status();
        c0_status |= IE_IRQ5;
        write_c0_status(c0_status);
    }
    else {
        while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
        au_writel(0, SYS_TOYWRITE);
        while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);

        au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
        au_writel(~0, SYS_WAKESRC);
        au_sync();
        while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);

        /* setup match20 to interrupt once every HZ */
        last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
        au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
        au_sync();
        while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
        startup_match20_interrupt(counter0_irq);

        /* We can use the real 'wait' instruction.
        */
        allow_au1k_wait = 1;
    }

#endif
}
Пример #3
0
static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
		      void *buffer, size_t * len)
{
	int retval = 0, i;
	unsigned long val, pll;
#define TMPBUFLEN 64
#define MAX_CPU_FREQ 396
	char buf[TMPBUFLEN], *p;
	unsigned long flags, intc0_mask, intc1_mask;
	unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,
	    old_refresh;
	unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;

	spin_lock_irqsave(&pm_lock, flags);
	if (!write) {
		*len = 0;
	} else {
		/* Parse the new frequency */
		if (*len > TMPBUFLEN - 1) {
			spin_unlock_irqrestore(&pm_lock, flags);
			return -EFAULT;
		}
		if (copy_from_user(buf, buffer, *len)) {
			spin_unlock_irqrestore(&pm_lock, flags);
			return -EFAULT;
		}
		buf[*len] = 0;
		p = buf;
		val = simple_strtoul(p, &p, 0);
		if (val > MAX_CPU_FREQ) {
			spin_unlock_irqrestore(&pm_lock, flags);
			return -EFAULT;
		}

		pll = val / 12;
		if ((pll > 33) || (pll < 7)) {	/* 396 MHz max, 84 MHz min */
			/* revisit this for higher speed cpus */
			spin_unlock_irqrestore(&pm_lock, flags);
			return -EFAULT;
		}

		old_baud_base = get_au1x00_uart_baud_base();
		old_cpu_freq = get_au1x00_speed();

		new_cpu_freq = pll * 12 * 1000000;
	        new_baud_base =  (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
		set_au1x00_speed(new_cpu_freq);
		set_au1x00_uart_baud_base(new_baud_base);

		old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
		new_refresh =
		    ((old_refresh * new_cpu_freq) /
		     old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);

		au_writel(pll, SYS_CPUPLL);
		au_sync_delay(1);
		au_writel(new_refresh, MEM_SDREFCFG);
		au_sync_delay(1);

		for (i = 0; i < 4; i++) {
			if (au_readl
			    (UART_BASE + UART_MOD_CNTRL +
			     i * 0x00100000) == 3) {
				old_clk =
				    au_readl(UART_BASE + UART_CLK +
					  i * 0x00100000);
				// baud_rate = baud_base/clk
				baud_rate = old_baud_base / old_clk;
				/* we won't get an exact baud rate and the error
				 * could be significant enough that our new
				 * calculation will result in a clock that will
				 * give us a baud rate that's too far off from
				 * what we really want.
				 */
				if (baud_rate > 100000)
					baud_rate = 115200;
				else if (baud_rate > 50000)
					baud_rate = 57600;
				else if (baud_rate > 30000)
					baud_rate = 38400;
				else if (baud_rate > 17000)
					baud_rate = 19200;
				else
					(baud_rate = 9600);
				// new_clk = new_baud_base/baud_rate
				new_clk = new_baud_base / baud_rate;
				au_writel(new_clk,
				       UART_BASE + UART_CLK +
				       i * 0x00100000);
				au_sync_delay(10);
			}
		}
	}


	/* We don't want _any_ interrupts other than
	 * match20. Otherwise our calibrate_delay()
	 * calculation will be off, potentially a lot.
	 */
	intc0_mask = save_local_and_disable(0);
	intc1_mask = save_local_and_disable(1);
	local_enable_irq(AU1000_TOY_MATCH2_INT);
	spin_unlock_irqrestore(&pm_lock, flags);
	calibrate_delay();
	restore_local_and_enable(0, intc0_mask);
	restore_local_and_enable(1, intc1_mask);
	return retval;
}