diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index aa1d400d721a..6783c2e5512d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -740,7 +740,7 @@ config XIP_PHYS_ADDR endmenu -if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP) +if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX ) menu "CPU Frequency scaling" @@ -767,6 +767,15 @@ config CPU_FREQ_INTEGRATOR If in doubt, say Y. +config CPU_FREQ_IMX + tristate "CPUfreq driver for i.MX CPUs" + depends on ARCH_IMX && CPU_FREQ + default n + help + This enables the CPUfreq driver for i.MX CPUs. + + If in doubt, say N. + endmenu endif @@ -945,6 +954,8 @@ source "drivers/video/Kconfig" source "sound/Kconfig" +source "drivers/hid/Kconfig" + source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 3173924a9b60..e8f74363328c 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -331,6 +331,19 @@ CALL(sys_mbind) /* 320 */ CALL(sys_get_mempolicy) CALL(sys_set_mempolicy) + CALL(sys_openat) + CALL(sys_mkdirat) + CALL(sys_mknodat) +/* 325 */ CALL(sys_fchownat) + CALL(sys_futimesat) + CALL(sys_fstatat64) + CALL(sys_unlinkat) + CALL(sys_renameat) +/* 330 */ CALL(sys_linkat) + CALL(sys_symlinkat) + CALL(sys_readlinkat) + CALL(sys_fchmodat) + CALL(sys_faccessat) #ifndef syscalls_counted .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls #define syscalls_counted diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index bda0748ffb00..d994561816a1 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -22,30 +22,31 @@ #include #include -#define KERNEL_RAM_ADDR (PAGE_OFFSET + TEXT_OFFSET) +#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) +#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) /* * swapper_pg_dir is the virtual address of the initial page table. - * We place the page tables 16K below KERNEL_RAM_ADDR. Therefore, we must - * make sure that KERNEL_RAM_ADDR is correctly set. Currently, we expect + * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must + * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect * the least significant 16 bits to be 0x8000, but we could probably - * relax this restriction to KERNEL_RAM_ADDR >= PAGE_OFFSET + 0x4000. + * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. */ -#if (KERNEL_RAM_ADDR & 0xffff) != 0x8000 -#error KERNEL_RAM_ADDR must start at 0xXXXX8000 +#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 +#error KERNEL_RAM_VADDR must start at 0xXXXX8000 #endif .globl swapper_pg_dir - .equ swapper_pg_dir, KERNEL_RAM_ADDR - 0x4000 + .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 .macro pgtbl, rd - ldr \rd, =(__virt_to_phys(KERNEL_RAM_ADDR - 0x4000)) + ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) .endm #ifdef CONFIG_XIP_KERNEL #define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) #else -#define TEXTADDR KERNEL_RAM_ADDR +#define TEXTADDR KERNEL_RAM_VADDR #endif /* diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 238dd9b6db84..cf2bd4242803 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -354,9 +354,6 @@ static void __init setup_processor(void) #ifndef CONFIG_ARM_THUMB elf_hwcap &= ~HWCAP_THUMB; #endif -#ifndef CONFIG_VFP - elf_hwcap &= ~HWCAP_VFP; -#endif cpu_proc_init(); } diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91rm9200/at91sam9260_devices.c index a6c596dc4516..f42d3a40ec3c 100644 --- a/arch/arm/mach-at91rm9200/at91sam9260_devices.c +++ b/arch/arm/mach-at91rm9200/at91sam9260_devices.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "generic.h" diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91rm9200/board-sam9260ek.c index ffca9bdec37b..da5d58ac870b 100644 --- a/arch/arm/mach-at91rm9200/board-sam9260ek.c +++ b/arch/arm/mach-at91rm9200/board-sam9260ek.c @@ -119,6 +119,7 @@ static struct spi_board_info ek_spi_devices[] = { * MACB Ethernet device */ static struct __initdata eth_platform_data ek_macb_data = { + .phy_irq_pin = AT91_PIN_PA7, .is_rmii = 1, }; diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 0b27d79f2efd..02272aa36e90 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -9,6 +9,8 @@ obj-y += irq.o time.o dma.o generic.o +obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o + # Specific board support obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c new file mode 100644 index 000000000000..ac5f99895660 --- /dev/null +++ b/arch/arm/mach-imx/cpufreq.c @@ -0,0 +1,287 @@ +/* + * cpu.c: clock scaling for the iMX + * + * Copyright (C) 2000 2001, The Delft University of Technology + * Copyright (c) 2004 Sascha Hauer + * Copyright (C) 2006 Inky Lung + * Copyright (C) 2006 Pavel Pisa, PiKRON + * + * Based on SA1100 version written by: + * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version + * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl): + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include + +#include + +#include "generic.h" + +#ifndef __val2mfld +#define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask)) +#endif +#ifndef __mfld2val +#define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1))) +#endif + +#define CR_920T_CLOCK_MODE 0xC0000000 +#define CR_920T_FASTBUS_MODE 0x00000000 +#define CR_920T_ASYNC_MODE 0xC0000000 + +static u32 mpctl0_at_boot; + +static void imx_set_async_mode(void) +{ + adjust_cr(CR_920T_CLOCK_MODE, CR_920T_ASYNC_MODE); +} + +static void imx_set_fastbus_mode(void) +{ + adjust_cr(CR_920T_CLOCK_MODE, CR_920T_FASTBUS_MODE); +} + +static void imx_set_mpctl0(u32 mpctl0) +{ + unsigned long flags; + + if (mpctl0 == 0) { + local_irq_save(flags); + CSCR &= ~CSCR_MPEN; + local_irq_restore(flags); + return; + } + + local_irq_save(flags); + MPCTL0 = mpctl0; + CSCR |= CSCR_MPEN; + local_irq_restore(flags); +} + +/** + * imx_compute_mpctl - compute new PLL parameters + * @new_mpctl: pointer to location assigned by new PLL control register value + * @cur_mpctl: current PLL control register parameters + * @freq: required frequency in Hz + * @relation: is one of %CPUFREQ_RELATION_L (supremum) + * and %CPUFREQ_RELATION_H (infimum) + */ +long imx_compute_mpctl(u32 *new_mpctl, u32 cur_mpctl, unsigned long freq, int relation) +{ + u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512); + u32 mfi; + u32 mfn; + u32 mfd; + u32 pd; + unsigned long long ll; + long l; + long quot; + + /* Fdppl=2*Fref*(MFI+MFN/(MFD+1))/(PD+1) */ + /* PD=<0,15>, MFD=<1,1023>, MFI=<5,15> MFN=<0,1022> */ + + if (cur_mpctl) { + mfd = ((cur_mpctl >> 16) & 0x3ff) + 1; + pd = ((cur_mpctl >> 26) & 0xf) + 1; + } else { + pd=2; mfd=313; + } + + /* pd=2; mfd=313; mfi=8; mfn=183; */ + /* (MFI+MFN/(MFD)) = Fdppl / (2*Fref) * (PD); */ + + quot = (f_ref + (1 << 9)) >> 10; + l = (freq * pd + quot) / (2 * quot); + mfi = l >> 10; + mfn = ((l & ((1 << 10) - 1)) * mfd + (1 << 9)) >> 10; + + mfd -= 1; + pd -= 1; + + *new_mpctl = ((mfi & 0xf) << 10) | (mfn & 0x3ff) | ((mfd & 0x3ff) << 16) + | ((pd & 0xf) << 26); + + ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) ); + quot = (pd+1) * (1<<16); + ll += quot / 2; + do_div(ll, quot); + freq = ll; + + pr_debug(KERN_DEBUG "imx: new PLL parameters pd=%d mfd=%d mfi=%d mfn=%d, freq=%ld\n", + pd, mfd, mfi, mfn, freq); + + return freq; +} + + +static int imx_verify_speed(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); + + return 0; +} + +static unsigned int imx_get_speed(unsigned int cpu) +{ + unsigned int freq; + unsigned int cr; + unsigned int cscr; + unsigned int bclk_div; + + if (cpu) + return 0; + + cscr = CSCR; + bclk_div = __mfld2val(CSCR_BCLK_DIV, cscr) + 1; + cr = get_cr(); + + if((cr & CR_920T_CLOCK_MODE) == CR_920T_FASTBUS_MODE) { + freq = imx_get_system_clk(); + freq = (freq + bclk_div/2) / bclk_div; + } else { + freq = imx_get_mcu_clk(); + if (cscr & CSCR_MPU_PRESC) + freq /= 2; + } + + freq = (freq + 500) / 1000; + + return freq; +} + +static int imx_set_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + u32 mpctl0 = 0; + u32 cscr; + unsigned long flags; + long freq; + long sysclk; + unsigned int bclk_div = 1; + + freq = target_freq * 1000; + + pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n", + freq, mpctl0_at_boot); + + sysclk = imx_get_system_clk(); + + if (freq > sysclk + 1000000) { + freq = imx_compute_mpctl(&mpctl0, mpctl0_at_boot, freq, relation); + if (freq < 0) { + printk(KERN_WARNING "imx: target frequency %ld Hz cannot be set\n", freq); + return -EINVAL; + } + } else { + if(freq + 1000 < sysclk) { + if (relation == CPUFREQ_RELATION_L) + bclk_div = (sysclk - 1000) / freq; + else + bclk_div = (sysclk + freq + 1000) / freq; + + if(bclk_div > 16) + bclk_div = 16; + } + freq = (sysclk + bclk_div / 2) / bclk_div; + } + + freqs.old = imx_get_speed(0); + freqs.new = (freq + 500) / 1000; + freqs.cpu = 0; + freqs.flags = 0; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + local_irq_save(flags); + + imx_set_fastbus_mode(); + + imx_set_mpctl0(mpctl0); + + cscr = CSCR; + cscr &= ~CSCR_BCLK_DIV; + cscr |= __val2mfld(CSCR_BCLK_DIV, bclk_div - 1); + CSCR = cscr; + + if(mpctl0) { + CSCR |= CSCR_MPLL_RESTART; + + /* Wait until MPLL is stablized */ + while( CSCR & CSCR_MPLL_RESTART ); + + imx_set_async_mode(); + } + + local_irq_restore(flags); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + pr_debug(KERN_INFO "imx: set frequency %ld Hz, running from %s\n", + freq, mpctl0? "MPLL": "SPLL"); + + return 0; +} + +static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy) +{ + printk(KERN_INFO "i.MX cpu freq change driver v1.0\n"); + + if (policy->cpu != 0) + return -EINVAL; + + policy->cur = policy->min = policy->max = imx_get_speed(0); + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.min_freq = 8000; + policy->cpuinfo.max_freq = 200000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + return 0; +} + +static struct cpufreq_driver imx_driver = { + .flags = CPUFREQ_STICKY, + .verify = imx_verify_speed, + .target = imx_set_target, + .get = imx_get_speed, + .init = imx_cpufreq_driver_init, + .name = "imx", +}; + +static int __init imx_cpufreq_init(void) +{ + + mpctl0_at_boot = 0; + + if((CSCR & CSCR_MPEN) && + ((get_cr() & CR_920T_CLOCK_MODE) != CR_920T_FASTBUS_MODE)) + mpctl0_at_boot = MPCTL0; + + return cpufreq_register_driver(&imx_driver); +} + +arch_initcall(imx_cpufreq_init); + diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 0993336c0b55..5773b55ef4a6 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -19,21 +19,14 @@ #include #include +#include +#include #include #include #include #include -/* - * Returns number of us since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - */ -static unsigned long netx_gettimeoffset(void) -{ - return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100; -} - /* * IRQ handler for the timer */ @@ -43,6 +36,7 @@ netx_timer_interrupt(int irq, void *dev_id) write_seqlock(&xtime_lock); timer_tick(); + write_sequnlock(&xtime_lock); /* acknowledge interrupt */ @@ -51,13 +45,26 @@ netx_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - static struct irqaction netx_timer_irq = { .name = "NetX Timer Tick", .flags = IRQF_DISABLED | IRQF_TIMER, .handler = netx_timer_interrupt, }; +cycle_t netx_get_cycles(void) +{ + return readl(NETX_GPIO_COUNTER_CURRENT(1)); +} + +static struct clocksource clocksource_netx = { + .name = "netx_timer", + .rating = 200, + .read = netx_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .is_continuous = 1, +}; + /* * Set up timer interrupt */ @@ -80,9 +87,20 @@ static void __init netx_timer_init(void) NETX_GPIO_COUNTER_CTRL(0)); setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); + + /* Setup timer one for clocksource */ + writel(0, NETX_GPIO_COUNTER_CTRL(1)); + writel(0, NETX_GPIO_COUNTER_CURRENT(1)); + writel(0xFFFFFFFF, NETX_GPIO_COUNTER_MAX(1)); + + writel(NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(1)); + + clocksource_netx.mult = + clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift); + clocksource_register(&clocksource_netx); } struct sys_timer netx_timer = { - .init = netx_timer_init, - .offset = netx_gettimeoffset, + .init = netx_timer_init, }; diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index b91466861029..3775b8f38429 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -48,27 +49,6 @@ static int pxa_set_rtc(void) return 0; } -/* IRQs are disabled before entering here from do_gettimeofday() */ -static unsigned long pxa_gettimeoffset (void) -{ - long ticks_to_match, elapsed, usec; - - /* Get ticks before next timer match */ - ticks_to_match = OSMR0 - OSCR; - - /* We need elapsed ticks since last match */ - elapsed = LATCH - ticks_to_match; - - /* don't get fooled by the workaround in pxa_timer_interrupt() */ - if (elapsed <= 0) - return 0; - - /* Now convert them to usec */ - usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH; - - return usec; -} - #ifdef CONFIG_NO_IDLE_HZ static unsigned long initial_match; static int match_posponed; @@ -121,6 +101,20 @@ static struct irqaction pxa_timer_irq = { .handler = pxa_timer_interrupt, }; +cycle_t pxa_get_cycles(void) +{ + return OSCR; +} + +static struct clocksource clocksource_pxa = { + .name = "pxa_timer", + .rating = 200, + .read = pxa_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .is_continuous = 1, +}; + static void __init pxa_timer_init(void) { struct timespec tv; @@ -139,6 +133,14 @@ static void __init pxa_timer_init(void) OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ OSMR0 = OSCR + LATCH; /* set initial match */ local_irq_restore(flags); + + /* on PXA OSCR runs continiously and is not written to, so we can use it + * as clock source directly. + */ + clocksource_pxa.mult = + clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_pxa.shift); + clocksource_register(&clocksource_pxa); + } #ifdef CONFIG_NO_IDLE_HZ @@ -211,7 +213,6 @@ struct sys_timer pxa_timer = { .init = pxa_timer_init, .suspend = pxa_timer_suspend, .resume = pxa_timer_resume, - .offset = pxa_gettimeoffset, #ifdef CONFIG_NO_IDLE_HZ .dyn_tick = &pxa_dyn_tick, #endif diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index c1827d021ba8..119c64b7223f 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -393,10 +393,6 @@ static struct pxafb_mach_info sharp_lcd = { .pxafb_backlight_power = board_backlight_power, }; -static void __init trizeps4_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) -{ -} - static void __init trizeps4_init(void) { platform_add_devices(trizeps4_devices, ARRAY_SIZE(trizeps4_devices)); @@ -469,7 +465,6 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = TRIZEPS4_SDRAM_BASE + 0x100, - .fixup = trizeps4_fixup, .init_machine = trizeps4_init, .map_io = trizeps4_map_io, .init_irq = pxa_init_irq, diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index 17f5a43acdb7..54ecdaa373d6 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -1,5 +1,15 @@ /* * linux/arch/arm/mach-sa1100/jornada720.c + * + * HP Jornada720 init code + * + * Copyright (C) 2006 Filip Zyzniewski + * Copyright (C) 2005 Michael Gernoth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * */ #include @@ -10,13 +20,13 @@ #include #include #include +#include