Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
Linus Torvalds [Mon, 1 Mar 2010 17:15:15 +0000 (09:15 -0800)]
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (100 commits)
  ARM: Eliminate decompressor -Dstatic= PIC hack
  ARM: 5958/1: ARM: U300: fix inverted clk round rate
  ARM: 5956/1: misplaced parentheses
  ARM: 5955/1: ep93xx: move timer defines into core.c and document
  ARM: 5954/1: ep93xx: move gpio interrupt support to gpio.c
  ARM: 5953/1: ep93xx: fix broken build of clock.c
  ARM: 5952/1: ARM: MM: Add ARM_L1_CACHE_SHIFT_6 for handle inside each ARCH Kconfig
  ARM: 5949/1: NUC900 add gpio virtual memory map
  ARM: 5948/1: Enable timer0 to time4 clock support for nuc910
  ARM: 5940/2: ARM: MMCI: remove custom DBG macro and printk
  ARM: make_coherent(): fix problems with highpte, part 2
  MM: Pass a PTE pointer to update_mmu_cache() rather than the PTE itself
  ARM: 5945/1: ep93xx: include correct irq.h in core.c
  ARM: 5933/1: amba-pl011: support hardware flow control
  ARM: 5930/1: Add PKMAP area description to memory.txt.
  ARM: 5929/1: Add checks to detect overlap of memory regions.
  ARM: 5928/1: Change type of VMALLOC_END to unsigned long.
  ARM: 5927/1: Make delimiters of DMA area globally visibly.
  ARM: 5926/1: Add "Virtual kernel memory..." printout.
  ARM: 5920/1: OMAP4: Enable L2 Cache
  ...

Fix up trivial conflict in arch/arm/mach-mx25/clock.c

318 files changed:
Documentation/arm/memory.txt
Documentation/cachetlb.txt
arch/alpha/include/asm/pgtable.h
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/decompress.c [new file with mode: 0644]
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/misc.c
arch/arm/boot/compressed/vmlinux.lds.in
arch/arm/common/clkdev.c
arch/arm/common/dmabounce.c
arch/arm/common/vic.c
arch/arm/configs/at572d940hfek_defconfig [new file with mode: 0644]
arch/arm/configs/omap_4430sdp_defconfig
arch/arm/include/asm/atomic.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/clkdev.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/io.h
arch/arm/include/asm/mach/time.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/mmu.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/page.h
arch/arm/include/asm/perf_event.h [new file with mode: 0644]
arch/arm/include/asm/pgtable-nommu.h
arch/arm/include/asm/pmu.h [new file with mode: 0644]
arch/arm/include/asm/setup.h
arch/arm/include/asm/smp_plat.h
arch/arm/include/asm/spinlock.h
arch/arm/include/asm/system.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/tlbflush.h
arch/arm/kernel/Makefile
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/debug.S
arch/arm/kernel/leds.c [new file with mode: 0644]
arch/arm/kernel/perf_event.c [new file with mode: 0644]
arch/arm/kernel/pmu.c [new file with mode: 0644]
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-aaec2000/include/mach/debug-macro.S
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at572d940hf.c [new file with mode: 0644]
arch/arm/mach-at91/at572d940hf_devices.c [new file with mode: 0644]
arch/arm/mach-at91/board-at572d940hf_ek.c [new file with mode: 0644]
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/clock.h
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/at572d940hf.h [new file with mode: 0644]
arch/arm/mach-at91/include/mach/at572d940hf_matrix.h [new file with mode: 0644]
arch/arm/mach-at91/include/mach/at91_pmc.h
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-at91/include/mach/debug-macro.S
arch/arm/mach-at91/include/mach/hardware.h
arch/arm/mach-at91/include/mach/timex.h
arch/arm/mach-bcmring/core.c
arch/arm/mach-clps711x/include/mach/debug-macro.S
arch/arm/mach-davinci/include/mach/debug-macro.S
arch/arm/mach-davinci/include/mach/hardware.h
arch/arm/mach-davinci/io.c
arch/arm/mach-dove/include/mach/debug-macro.S
arch/arm/mach-dove/include/mach/vmalloc.h
arch/arm/mach-ebsa110/include/mach/debug-macro.S
arch/arm/mach-ep93xx/Kconfig
arch/arm/mach-ep93xx/Makefile
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/dma-m2p.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/gpio.c
arch/arm/mach-ep93xx/include/mach/debug-macro.S
arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
arch/arm/mach-ep93xx/include/mach/vmalloc.h
arch/arm/mach-ep93xx/simone.c [new file with mode: 0644]
arch/arm/mach-ep93xx/snappercl15.c [new file with mode: 0644]
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/include/mach/debug-macro.S
arch/arm/mach-gemini/include/mach/debug-macro.S
arch/arm/mach-gemini/include/mach/vmalloc.h
arch/arm/mach-h720x/include/mach/debug-macro.S
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/include/mach/debug-macro.S
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-iop13xx/include/mach/debug-macro.S
arch/arm/mach-iop13xx/io.c
arch/arm/mach-iop32x/include/mach/debug-macro.S
arch/arm/mach-iop32x/include/mach/vmalloc.h
arch/arm/mach-iop33x/include/mach/debug-macro.S
arch/arm/mach-iop33x/include/mach/vmalloc.h
arch/arm/mach-ixp2000/include/mach/debug-macro.S
arch/arm/mach-ixp2000/include/mach/vmalloc.h
arch/arm/mach-ixp23xx/include/mach/debug-macro.S
arch/arm/mach-ixp23xx/include/mach/vmalloc.h
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/include/mach/debug-macro.S
arch/arm/mach-ixp4xx/include/mach/vmalloc.h
arch/arm/mach-kirkwood/include/mach/debug-macro.S
arch/arm/mach-kirkwood/include/mach/vmalloc.h
arch/arm/mach-ks8695/include/mach/debug-macro.S
arch/arm/mach-l7200/include/mach/debug-macro.S
arch/arm/mach-lh7a40x/include/mach/debug-macro.S
arch/arm/mach-lh7a40x/include/mach/vmalloc.h
arch/arm/mach-loki/include/mach/debug-macro.S
arch/arm/mach-loki/include/mach/vmalloc.h
arch/arm/mach-mmp/clock.c
arch/arm/mach-mmp/clock.h
arch/arm/mach-mmp/include/mach/debug-macro.S
arch/arm/mach-mmp/include/mach/vmalloc.h
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-mmp/pxa910.c
arch/arm/mach-msm/include/mach/debug-macro.S
arch/arm/mach-msm/io.c
arch/arm/mach-mv78xx0/include/mach/debug-macro.S
arch/arm/mach-mv78xx0/include/mach/vmalloc.h
arch/arm/mach-mx1/clock.c
arch/arm/mach-mx2/clock_imx21.c
arch/arm/mach-mx2/clock_imx27.c
arch/arm/mach-mx25/clock.c
arch/arm/mach-mx3/clock-imx35.c
arch/arm/mach-mx3/clock.c
arch/arm/mach-mxc91231/clock.c
arch/arm/mach-netx/include/mach/debug-macro.S
arch/arm/mach-nomadik/include/mach/debug-macro.S
arch/arm/mach-nomadik/include/mach/vmalloc.h
arch/arm/mach-ns9xxx/include/mach/debug-macro.S
arch/arm/mach-ns9xxx/include/mach/vmalloc.h
arch/arm/mach-nuc93x/Kconfig [new file with mode: 0644]
arch/arm/mach-nuc93x/Makefile [new file with mode: 0644]
arch/arm/mach-nuc93x/Makefile.boot [new file with mode: 0644]
arch/arm/mach-nuc93x/clock.c [new file with mode: 0644]
arch/arm/mach-nuc93x/clock.h [new file with mode: 0644]
arch/arm/mach-nuc93x/cpu.c [new file with mode: 0644]
arch/arm/mach-nuc93x/cpu.h [new file with mode: 0644]
arch/arm/mach-nuc93x/dev.c [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/entry-macro.S [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/hardware.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/irqs.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/map.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/memory.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/regs-clock.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/regs-ebi.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/regs-irq.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/regs-serial.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/regs-timer.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/system.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-nuc93x/include/mach/vmalloc.h [new file with mode: 0644]
arch/arm/mach-nuc93x/irq.c [new file with mode: 0644]
arch/arm/mach-nuc93x/mach-nuc932evb.c [new file with mode: 0644]
arch/arm/mach-nuc93x/nuc932.c [new file with mode: 0644]
arch/arm/mach-nuc93x/nuc932.h [new file with mode: 0644]
arch/arm/mach-nuc93x/time.c [new file with mode: 0644]
arch/arm/mach-omap1/include/mach/debug-macro.S
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/include/mach/debug-macro.S
arch/arm/mach-orion5x/include/mach/debug-macro.S
arch/arm/mach-orion5x/include/mach/vmalloc.h
arch/arm/mach-pnx4008/clock.c
arch/arm/mach-pnx4008/clock.h
arch/arm/mach-pnx4008/i2c.c
arch/arm/mach-pnx4008/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-pnx4008/include/mach/debug-macro.S
arch/arm/mach-pnx4008/include/mach/timex.h
arch/arm/mach-pnx4008/pm.c
arch/arm/mach-pnx4008/time.c
arch/arm/mach-pnx4008/time.h [new file with mode: 0644]
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/include/mach/debug-macro.S
arch/arm/mach-pxa/include/mach/vmalloc.h
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa300.c
arch/arm/mach-pxa/pxa320.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-realview/core.c
arch/arm/mach-realview/include/mach/debug-macro.S
arch/arm/mach-realview/include/mach/vmalloc.h
arch/arm/mach-rpc/include/mach/debug-macro.S
arch/arm/mach-s3c2410/include/mach/debug-macro.S
arch/arm/mach-s3c24a0/include/mach/debug-macro.S
arch/arm/mach-s3c24a0/include/mach/vmalloc.h
arch/arm/mach-s3c6400/include/mach/debug-macro.S
arch/arm/mach-s5pc100/include/mach/debug-macro.S
arch/arm/mach-sa1100/include/mach/debug-macro.S
arch/arm/mach-sa1100/include/mach/vmalloc.h
arch/arm/mach-shark/include/mach/debug-macro.S
arch/arm/mach-u300/clock.c
arch/arm/mach-u300/core.c
arch/arm/mach-u300/gpio.c
arch/arm/mach-u300/include/mach/debug-macro.S
arch/arm/mach-u300/include/mach/dma_channels.h [new file with mode: 0644]
arch/arm/mach-u300/include/mach/vmalloc.h
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/cpu-u8500.c
arch/arm/mach-ux500/include/mach/debug-macro.S
arch/arm/mach-ux500/include/mach/vmalloc.h
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/include/mach/debug-macro.S
arch/arm/mach-w90x900/clock.c
arch/arm/mach-w90x900/clock.h
arch/arm/mach-w90x900/cpu.c
arch/arm/mach-w90x900/include/mach/vmalloc.h
arch/arm/mm/Kconfig
arch/arm/mm/alignment.c
arch/arm/mm/cache-fa.S
arch/arm/mm/cache-l2x0.c
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/context.c
arch/arm/mm/copypage-feroceon.c
arch/arm/mm/copypage-v3.c
arch/arm/mm/copypage-v4mc.c
arch/arm/mm/copypage-v4wb.c
arch/arm/mm/copypage-v4wt.c
arch/arm/mm/copypage-v6.c
arch/arm/mm/copypage-xsc3.c
arch/arm/mm/copypage-xscale.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault-armv.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/init.c
arch/arm/mm/ioremap.c
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-mohawk.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/oprofile/op_model_arm11_core.c
arch/arm/oprofile/op_model_arm11_core.h
arch/arm/oprofile/op_model_mpcore.c
arch/arm/oprofile/op_model_v6.c
arch/arm/oprofile/op_model_v7.c
arch/arm/oprofile/op_model_v7.h
arch/arm/oprofile/op_model_xscale.c
arch/arm/plat-iop/io.c
arch/arm/plat-mxc/include/mach/debug-macro.S
arch/arm/plat-mxc/include/mach/vmalloc.h
arch/arm/plat-nomadik/include/plat/i2c.h [new file with mode: 0644]
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/include/plat/omap44xx.h
arch/arm/plat-omap/io.c
arch/arm/plat-s3c/include/mach/vmalloc.h
arch/arm/plat-stmp3xxx/clock.c
arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
arch/arm/plat-stmp3xxx/include/mach/vmalloc.h
arch/arm/vfp/vfpmodule.c
arch/avr32/include/asm/pgtable.h
arch/avr32/mm/tlb.c
arch/cris/include/asm/pgtable.h
arch/frv/include/asm/pgtable.h
arch/ia64/include/asm/pgtable.h
arch/m32r/include/asm/tlbflush.h
arch/m32r/mm/fault-nommu.c
arch/m32r/mm/fault.c
arch/m68k/include/asm/pgtable_mm.h
arch/microblaze/include/asm/tlbflush.h
arch/mips/include/asm/pgtable.h
arch/mn10300/include/asm/pgtable.h
arch/mn10300/mm/mmu-context.c
arch/parisc/include/asm/pgtable.h
arch/parisc/kernel/cache.c
arch/powerpc/include/asm/pgtable.h
arch/powerpc/mm/mem.c
arch/s390/include/asm/pgtable.h
arch/score/include/asm/pgtable.h
arch/sh/include/asm/pgtable.h
arch/sh/mm/fault_32.c
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/mm/fault_32.c
arch/sparc/mm/init_64.c
arch/sparc/mm/nosun4c.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/um/include/asm/pgtable.h
arch/x86/include/asm/pgtable_32.h
arch/x86/include/asm/pgtable_64.h
arch/xtensa/include/asm/pgtable.h
arch/xtensa/mm/cache.c
drivers/i2c/busses/i2c-pnx.c
drivers/mmc/host/mmci.c
drivers/rtc/rtc-pl031.c
drivers/serial/amba-pl011.c
drivers/spi/amba-pl022.c
drivers/watchdog/pnx4008_wdt.c
include/linux/i2c-pnx.h
mm/hugetlb.c
mm/memory.c
mm/migrate.c

index 9d58c7c..eb0fae1 100644 (file)
@@ -59,7 +59,11 @@ PAGE_OFFSET  high_memory-1   Kernel direct-mapped RAM region.
                                This maps the platforms RAM, and typically
                                maps all platform RAM in a 1:1 relationship.
 
-TASK_SIZE      PAGE_OFFSET-1   Kernel module space
+PKMAP_BASE     PAGE_OFFSET-1   Permanent kernel mappings
+                               One way of mapping HIGHMEM pages into kernel
+                               space.
+
+MODULES_VADDR  MODULES_END-1   Kernel module space
                                Kernel modules inserted via insmod are
                                placed here using dynamic mappings.
 
index b231414..2b5f823 100644 (file)
@@ -88,12 +88,12 @@ changes occur:
        This is used primarily during fault processing.
 
 5) void update_mmu_cache(struct vm_area_struct *vma,
-                        unsigned long address, pte_t pte)
+                        unsigned long address, pte_t *ptep)
 
        At the end of every page fault, this routine is invoked to
        tell the architecture specific code that a translation
-       described by "pte" now exists at virtual address "address"
-       for address space "vma->vm_mm", in the software page tables.
+       now exists at virtual address "address" for address space
+       "vma->vm_mm", in the software page tables.
 
        A port may use this information in any way it so chooses.
        For example, it could use this event to pre-load TLB
index 3f0c59f..71a2432 100644 (file)
@@ -329,7 +329,7 @@ extern pgd_t swapper_pg_dir[1024];
  * tables contain all the necessary information.
  */
 extern inline void update_mmu_cache(struct vm_area_struct * vma,
-       unsigned long address, pte_t pte)
+       unsigned long address, pte_t *ptep)
 {
 }
 
index 184a6bd..3b18128 100644 (file)
@@ -12,6 +12,7 @@ config ARM
        select HAVE_IDE
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
+       select GENERIC_ATOMIC64 if (!CPU_32v6K)
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB
        select HAVE_KPROBES if (!XIP_KERNEL)
@@ -20,6 +21,8 @@ config ARM
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZO
+       select HAVE_PERF_EVENTS
+       select PERF_USE_VMALLOC
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -52,6 +55,9 @@ config HAVE_TCM
        bool
        select GENERIC_ALLOCATOR
 
+config HAVE_PROC_CPU
+       bool
+
 config NO_IOPORT
        bool
 
@@ -161,6 +167,11 @@ config ARCH_MTD_XIP
 config GENERIC_HARDIRQS_NO__DO_IRQ
        def_bool y
 
+config ARM_L1_CACHE_SHIFT_6
+       bool
+       help
+         Setting ARM L1 cache line size to 64 Bytes.
+
 if OPROFILE
 
 config OPROFILE_ARMV6
@@ -550,10 +561,20 @@ config ARCH_W90X900
          <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
                ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
 
+config ARCH_NUC93X
+       bool "Nuvoton NUC93X CPU"
+       select CPU_ARM926T
+       select HAVE_CLK
+       select COMMON_CLKDEV
+       help
+         Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
+         low-power and high performance MPEG-4/JPEG multimedia controller chip.
+
 config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
        select CPU_ARM926T
        select HAVE_CLK
+       select COMMON_CLKDEV
        help
          This enables support for Philips PNX4008 mobile platform.
 
@@ -638,6 +659,7 @@ config ARCH_S5PC1XX
        select GENERIC_GPIO
        select HAVE_CLK
        select CPU_V7
+       select ARM_L1_CACHE_SHIFT_6
        help
          Samsung S5PC1XX series based systems
 
@@ -785,6 +807,8 @@ source "arch/arm/plat-nomadik/Kconfig"
 
 source "arch/arm/mach-ns9xxx/Kconfig"
 
+source "arch/arm/mach-nuc93x/Kconfig"
+
 source "arch/arm/plat-omap/Kconfig"
 
 source "arch/arm/mach-omap1/Kconfig"
@@ -867,6 +891,11 @@ config XSCALE_PMU
        depends on CPU_XSCALE && !XSCALE_PMU_TIMER
        default y
 
+config CPU_HAS_PMU
+       depends on CPU_V6 || CPU_V7 || XSCALE_PMU
+       default y
+       bool
+
 if !MMU
 source "arch/arm/Kconfig-nommu"
 endif
@@ -921,6 +950,19 @@ config ARM_ERRATA_460075
          ACTLR register. Note that setting specific bits in the ACTLR register
          may not be available in non-secure mode.
 
+config PL310_ERRATA_588369
+       bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
+       depends on CACHE_L2X0 && ARCH_OMAP4
+       help
+          The PL310 L2 cache controller implements three types of Clean &
+          Invalidate maintenance operations: by Physical Address
+          (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
+          They are architecturally defined to behave as the execution of a
+          clean operation followed immediately by an invalidate operation,
+          both performing to the same memory location. This functionality
+          is not correctly implemented in PL310 as clean lines are not
+          invalidated as a result of these operations. Note that this errata
+          uses Texas Instrument's secure monitor api.
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1171,6 +1213,14 @@ config HIGHPTE
        depends on HIGHMEM
        depends on !OUTER_CACHE
 
+config HW_PERF_EVENTS
+       bool "Enable hardware performance counter support for perf events"
+       depends on PERF_EVENTS && CPU_HAS_PMU && (CPU_V6 || CPU_V7)
+       default y
+       help
+         Enable hardware performance counter support for perf events. If
+         disabled, perf events will use software events only.
+
 source "mm/Kconfig"
 
 config LEDS
@@ -1230,6 +1280,7 @@ config ALIGNMENT_TRAP
        bool
        depends on CPU_CP15_MMU
        default y if !ARCH_EBSA110
+       select HAVE_PROC_CPU if PROC_FS
        help
          ARM processors cannot fetch/store information which is not
          naturally aligned on the bus, i.e., a 4 byte fetch must start at an
index 356d702..81f54ca 100644 (file)
@@ -171,6 +171,7 @@ machine-$(CONFIG_ARCH_U300)         := u300
 machine-$(CONFIG_ARCH_U8500)           := ux500
 machine-$(CONFIG_ARCH_VERSATILE)       := versatile
 machine-$(CONFIG_ARCH_W90X900)         := w90x900
+machine-$(CONFIG_ARCH_NUC93X)          := nuc93x
 machine-$(CONFIG_FOOTBRIDGE)           := footbridge
 
 # Platform directory name.  This list is sorted alphanumerically
index 2d4d88b..97c89e7 100644 (file)
@@ -5,7 +5,7 @@
 #
 
 HEAD   = head.o
-OBJS   = misc.o
+OBJS   = misc.o decompress.o
 FONTC  = $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
@@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o
 $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
        $(call cmd,shipped)
 
-# Don't allow any static data in misc.o, which
-# would otherwise mess up our GOT table
-CFLAGS_misc.o := -Dstatic=
-
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
                $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
        $(call if_changed,ld)
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
new file mode 100644 (file)
index 0000000..0da382f
--- /dev/null
@@ -0,0 +1,45 @@
+#define _LINUX_STRING_H_
+
+#include <linux/compiler.h>    /* for inline */
+#include <linux/types.h>       /* for size_t */
+#include <linux/stddef.h>      /* for NULL */
+#include <linux/linkage.h>
+#include <asm/string.h>
+
+extern unsigned long free_mem_ptr;
+extern unsigned long free_mem_end_ptr;
+extern void error(char *);
+
+#define STATIC static
+
+#define ARCH_HAS_DECOMP_WDOG
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZO
+#include "../../../../lib/decompress_unlzo.c"
+#endif
+
+void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
+{
+       decompress(input, len, NULL, NULL, output, NULL, error);
+}
index 4fddc50..99b75aa 100644 (file)
 #if defined(CONFIG_DEBUG_ICEDCC)
 
 #ifdef CONFIG_CPU_V6
-               .macro  loadsp, rb
+               .macro  loadsp, rb, tmp
                .endm
                .macro  writeb, ch, rb
                mcr     p14, 0, \ch, c0, c5, 0
                .endm
 #elif defined(CONFIG_CPU_V7)
-               .macro  loadsp, rb
+               .macro  loadsp, rb, tmp
                .endm
                .macro  writeb, ch, rb
 wait:          mrc     p14, 0, pc, c0, c1, 0
@@ -36,13 +36,13 @@ wait:               mrc     p14, 0, pc, c0, c1, 0
                mcr     p14, 0, \ch, c0, c5, 0
                .endm
 #elif defined(CONFIG_CPU_XSCALE)
-               .macro  loadsp, rb
+               .macro  loadsp, rb, tmp
                .endm
                .macro  writeb, ch, rb
                mcr     p14, 0, \ch, c8, c0, 0
                .endm
 #else
-               .macro  loadsp, rb
+               .macro  loadsp, rb, tmp
                .endm
                .macro  writeb, ch, rb
                mcr     p14, 0, \ch, c1, c0, 0
@@ -58,7 +58,7 @@ wait:         mrc     p14, 0, pc, c0, c1, 0
                .endm
 
 #if defined(CONFIG_ARCH_SA1100)
-               .macro  loadsp, rb
+               .macro  loadsp, rb, tmp
                mov     \rb, #0x80000000        @ physical base address
 #ifdef CONFIG_DEBUG_LL_SER3
                add     \rb, \rb, #0x00050000   @ Ser3
@@ -67,13 +67,13 @@ wait:               mrc     p14, 0, pc, c0, c1, 0
 #endif
                .endm
 #elif defined(CONFIG_ARCH_S3C2410)
-               .macro loadsp, rb
+               .macro loadsp, rb, tmp
                mov     \rb, #0x50000000
                add     \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
                .endm
 #else
-               .macro  loadsp, rb
-               addruart \rb
+               .macro  loadsp, rb, tmp
+               addruart \rb, \tmp
                .endm
 #endif
 #endif
@@ -1025,7 +1025,7 @@ phex:             adr     r3, phexbuf
                strb    r2, [r3, r1]
                b       1b
 
-puts:          loadsp  r3
+puts:          loadsp  r3, r1
 1:             ldrb    r2, [r0], #1
                teq     r2, #0
                moveq   pc, lr
@@ -1042,7 +1042,7 @@ puts:             loadsp  r3
 putc:
                mov     r2, r0
                mov     r0, #0
-               loadsp  r3
+               loadsp  r3, r1
                b       2b
 
 memdump:       mov     r12, r0
index 56a0d11..d32bc71 100644 (file)
@@ -23,8 +23,8 @@ unsigned int __machine_arch_type;
 #include <linux/compiler.h>    /* for inline */
 #include <linux/types.h>       /* for size_t */
 #include <linux/stddef.h>      /* for NULL */
-#include <asm/string.h>
 #include <linux/linkage.h>
+#include <asm/string.h>
 
 #include <asm/unaligned.h>
 
@@ -117,57 +117,7 @@ static void putstr(const char *ptr)
 
 #endif
 
-#define __ptr_t void *
-
-#define memzero(s,n) __memzero(s,n)
-
-/*
- * Optimised C version of memzero for the ARM.
- */
-void __memzero (__ptr_t s, size_t n)
-{
-       union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
-       int i;
-
-       u.vp = s;
-
-       for (i = n >> 5; i > 0; i--) {
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-       }
-
-       if (n & 1 << 4) {
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-       }
-
-       if (n & 1 << 3) {
-               *u.ulp++ = 0;
-               *u.ulp++ = 0;
-       }
-
-       if (n & 1 << 2)
-               *u.ulp++ = 0;
-
-       if (n & 1 << 1) {
-               *u.ucp++ = 0;
-               *u.ucp++ = 0;
-       }
-
-       if (n & 1)
-               *u.ucp++ = 0;
-}
-
-static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
-                           size_t __n)
+void *memcpy(void *__dest, __const void *__src, size_t __n)
 {
        int i = 0;
        unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
@@ -204,59 +154,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
 /*
  * gzip delarations
  */
-#define STATIC static
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-static void error(char *m);
-
 extern char input_data[];
 extern char input_data_end[];
 
-static unsigned char *output_data;
-static unsigned long output_ptr;
-
-static void error(char *m);
+unsigned char *output_data;
+unsigned long output_ptr;
 
-static void putstr(const char *);
-
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#ifdef STANDALONE_DEBUG
-#define NO_INFLATE_MALLOC
-#endif
-
-#define ARCH_HAS_DECOMP_WDOG
-
-#ifdef CONFIG_KERNEL_GZIP
-#include "../../../../lib/decompress_inflate.c"
-#endif
-
-#ifdef CONFIG_KERNEL_LZO
-#include "../../../../lib/decompress_unlzo.c"
-#endif
+unsigned long free_mem_ptr;
+unsigned long free_mem_end_ptr;
 
 #ifndef arch_error
 #define arch_error(x)
 #endif
 
-static void error(char *x)
+void error(char *x)
 {
        arch_error(x);
 
@@ -272,6 +183,8 @@ asmlinkage void __div0(void)
        error("Attempting division by 0!");
 }
 
+extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
+
 #ifndef STANDALONE_DEBUG
 
 unsigned long
@@ -292,8 +205,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
        output_ptr = get_unaligned_le32(tmp);
 
        putstr("Uncompressing Linux...");
-       decompress(input_data, input_data_end - input_data,
-                       NULL, NULL, output_data, NULL, error);
+       do_decompress(input_data, input_data_end - input_data,
+                       output_data, error);
        putstr(" done, booting the kernel.\n");
        return output_ptr;
 }
index a5924b9..7ca9ecf 100644 (file)
@@ -14,6 +14,13 @@ SECTIONS
   /DISCARD/ : {
     *(.ARM.exidx*)
     *(.ARM.extab*)
+    /*
+     * Discard any r/w data - this produces a link error if we have any,
+     * which is required for PIC decompression.  Local data generates
+     * GOTOFF relocations, which prevents it being relocated independently
+     * of the text/got segments.
+     */
+    *(.data)
   }
 
   . = TEXT_START;
@@ -40,7 +47,6 @@ SECTIONS
   .got                 : { *(.got) }
   _got_end = .;
   .got.plt             : { *(.got.plt) }
-  .data                        : { *(.data) }
   _edata = .;
 
   . = BSS_START;
index aae5bc0..446b696 100644 (file)
@@ -99,6 +99,16 @@ void clkdev_add(struct clk_lookup *cl)
 }
 EXPORT_SYMBOL(clkdev_add);
 
+void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
+{
+       mutex_lock(&clocks_mutex);
+       while (num--) {
+               list_add_tail(&cl->node, &clocks);
+               cl++;
+       }
+       mutex_unlock(&clocks_mutex);
+}
+
 #define MAX_DEV_ID     20
 #define MAX_CON_ID     16
 
index cc32c1e..cc0a932 100644 (file)
@@ -277,7 +277,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
                 * We don't need to sync the DMA buffer since
                 * it was allocated via the coherent allocators.
                 */
-               dma_cache_maint(ptr, size, dir);
+               __dma_single_cpu_to_dev(ptr, size, dir);
        }
 
        return dma_addr;
@@ -315,6 +315,8 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
                        __cpuc_flush_dcache_area(ptr, size);
                }
                free_safe_buffer(dev->archdata.dmabounce, buf);
+       } else {
+               __dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);
        }
 }
 
index f232941..1cf999a 100644 (file)
@@ -18,6 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/vic.h>
 
-static void vic_ack_irq(unsigned int irq)
-{
-       void __iomem *base = get_irq_chip_data(irq);
-       irq &= 31;
-       writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
-       /* moreover, clear the soft-triggered, in case it was the reason */
-       writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
-}
-
-static void vic_mask_irq(unsigned int irq)
-{
-       void __iomem *base = get_irq_chip_data(irq);
-       irq &= 31;
-       writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
-}
-
-static void vic_unmask_irq(unsigned int irq)
-{
-       void __iomem *base = get_irq_chip_data(irq);
-       irq &= 31;
-       writel(1 << irq, base + VIC_INT_ENABLE);
-}
-
-/**
- * vic_init2 - common initialisation code
- * @base: Base of the VIC.
- *
- * Common initialisation code for registeration
- * and resume.
-*/
-static void vic_init2(void __iomem *base)
-{
-       int i;
-
-       for (i = 0; i < 16; i++) {
-               void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
-               writel(VIC_VECT_CNTL_ENABLE | i, reg);
-       }
-
-       writel(32, base + VIC_PL190_DEF_VECT_ADDR);
-}
-
 #if defined(CONFIG_PM)
 /**
  * struct vic_device - VIC PM device
@@ -99,13 +58,34 @@ struct vic_device {
 /* we cannot allocate memory when VICs are initially registered */
 static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
 
+static int vic_id;
+
 static inline struct vic_device *to_vic(struct sys_device *sys)
 {
        return container_of(sys, struct vic_device, sysdev);
 }
+#endif /* CONFIG_PM */
 
-static int vic_id;
+/**
+ * vic_init2 - common initialisation code
+ * @base: Base of the VIC.
+ *
+ * Common initialisation code for registeration
+ * and resume.
+*/
+static void vic_init2(void __iomem *base)
+{
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
+               writel(VIC_VECT_CNTL_ENABLE | i, reg);
+       }
+
+       writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+}
 
+#if defined(CONFIG_PM)
 static int vic_class_resume(struct sys_device *dev)
 {
        struct vic_device *vic = to_vic(dev);
@@ -159,31 +139,6 @@ struct sysdev_class vic_class = {
 };
 
 /**
- * vic_pm_register - Register a VIC for later power management control
- * @base: The base address of the VIC.
- * @irq: The base IRQ for the VIC.
- * @resume_sources: bitmask of interrupts allowed for resume sources.
- *
- * Register the VIC with the system device tree so that it can be notified
- * of suspend and resume requests and ensure that the correct actions are
- * taken to re-instate the settings on resume.
- */
-static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
-{
-       struct vic_device *v;
-
-       if (vic_id >= ARRAY_SIZE(vic_devices))
-               printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
-       else {
-               v = &vic_devices[vic_id];
-               v->base = base;
-               v->resume_sources = resume_sources;
-               v->irq = irq;
-               vic_id++;
-       }
-}
-
-/**
  * vic_pm_init - initicall to register VIC pm
  *
  * This is called via late_initcall() to register
@@ -219,9 +174,60 @@ static int __init vic_pm_init(void)
 
        return 0;
 }
-
 late_initcall(vic_pm_init);
 
+/**
+ * vic_pm_register - Register a VIC for later power management control
+ * @base: The base address of the VIC.
+ * @irq: The base IRQ for the VIC.
+ * @resume_sources: bitmask of interrupts allowed for resume sources.
+ *
+ * Register the VIC with the system device tree so that it can be notified
+ * of suspend and resume requests and ensure that the correct actions are
+ * taken to re-instate the settings on resume.
+ */
+static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
+{
+       struct vic_device *v;
+
+       if (vic_id >= ARRAY_SIZE(vic_devices))
+               printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
+       else {
+               v = &vic_devices[vic_id];
+               v->base = base;
+               v->resume_sources = resume_sources;
+               v->irq = irq;
+               vic_id++;
+       }
+}
+#else
+static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
+#endif /* CONFIG_PM */
+
+static void vic_ack_irq(unsigned int irq)
+{
+       void __iomem *base = get_irq_chip_data(irq);
+       irq &= 31;
+       writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
+       /* moreover, clear the soft-triggered, in case it was the reason */
+       writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
+}
+
+static void vic_mask_irq(unsigned int irq)
+{
+       void __iomem *base = get_irq_chip_data(irq);
+       irq &= 31;
+       writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
+}
+
+static void vic_unmask_irq(unsigned int irq)
+{
+       void __iomem *base = get_irq_chip_data(irq);
+       irq &= 31;
+       writel(1 << irq, base + VIC_INT_ENABLE);
+}
+
+#if defined(CONFIG_PM)
 static struct vic_device *vic_from_irq(unsigned int irq)
 {
         struct vic_device *v = vic_devices;
@@ -255,10 +261,7 @@ static int vic_set_wake(unsigned int irq, unsigned int on)
 
        return 0;
 }
-
 #else
-static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
-
 #define vic_set_wake NULL
 #endif /* CONFIG_PM */
 
@@ -270,9 +273,62 @@ static struct irq_chip vic_chip = {
        .set_wake = vic_set_wake,
 };
 
-/* The PL190 cell from ARM has been modified by ST, so handle both here */
-static void vik_init_st(void __iomem *base, unsigned int irq_start,
-                        u32 vic_sources);
+/*
+ * The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
+ * The original cell has 32 interrupts, while the modified one has 64,
+ * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case
+ * the probe function is called twice, with base set to offset 000
+ *  and 020 within the page. We call this "second block".
+ */
+static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
+                               u32 vic_sources)
+{
+       unsigned int i;
+       int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
+
+       /* Disable all interrupts initially. */
+
+       writel(0, base + VIC_INT_SELECT);
+       writel(0, base + VIC_INT_ENABLE);
+       writel(~0, base + VIC_INT_ENABLE_CLEAR);
+       writel(0, base + VIC_IRQ_STATUS);
+       writel(0, base + VIC_ITCR);
+       writel(~0, base + VIC_INT_SOFT_CLEAR);
+
+       /*
+        * Make sure we clear all existing interrupts. The vector registers
+        * in this cell are after the second block of general registers,
+        * so we can address them using standard offsets, but only from
+        * the second base address, which is 0x20 in the page
+        */
+       if (vic_2nd_block) {
+               writel(0, base + VIC_PL190_VECT_ADDR);
+               for (i = 0; i < 19; i++) {
+                       unsigned int value;
+
+                       value = readl(base + VIC_PL190_VECT_ADDR);
+                       writel(value, base + VIC_PL190_VECT_ADDR);
+               }
+               /* ST has 16 vectors as well, but we don't enable them by now */
+               for (i = 0; i < 16; i++) {
+                       void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
+                       writel(0, reg);
+               }
+
+               writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+       }
+
+       for (i = 0; i < 32; i++) {
+               if (vic_sources & (1 << i)) {
+                       unsigned int irq = irq_start + i;
+
+                       set_irq_chip(irq, &vic_chip);
+                       set_irq_chip_data(irq, base);
+                       set_irq_handler(irq, handle_level_irq);
+                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+               }
+       }
+}
 
 /**
  * vic_init - initialise a vectored interrupt controller
@@ -299,7 +355,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
 
        switch(vendor) {
        case AMBA_VENDOR_ST:
-               vik_init_st(base, irq_start, vic_sources);
+               vic_init_st(base, irq_start, vic_sources);
                return;
        default:
                printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
@@ -343,60 +399,3 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
 
        vic_pm_register(base, irq_start, resume_sources);
 }
-
-/*
- * The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
- * The original cell has 32 interrupts, while the modified one has 64,
- * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case
- * the probe function is called twice, with base set to offset 000
- *  and 020 within the page. We call this "second block".
- */
-static void __init vik_init_st(void __iomem *base, unsigned int irq_start,
-                               u32 vic_sources)
-{
-       unsigned int i;
-       int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
-
-       /* Disable all interrupts initially. */
-
-       writel(0, base + VIC_INT_SELECT);
-       writel(0, base + VIC_INT_ENABLE);
-       writel(~0, base + VIC_INT_ENABLE_CLEAR);
-       writel(0, base + VIC_IRQ_STATUS);
-       writel(0, base + VIC_ITCR);
-       writel(~0, base + VIC_INT_SOFT_CLEAR);
-
-       /*
-        * Make sure we clear all existing interrupts. The vector registers
-        * in this cell are after the second block of general registers,
-        * so we can address them using standard offsets, but only from
-        * the second base address, which is 0x20 in the page
-        */
-       if (vic_2nd_block) {
-               writel(0, base + VIC_PL190_VECT_ADDR);
-               for (i = 0; i < 19; i++) {
-                       unsigned int value;
-
-                       value = readl(base + VIC_PL190_VECT_ADDR);
-                       writel(value, base + VIC_PL190_VECT_ADDR);
-               }
-               /* ST has 16 vectors as well, but we don't enable them by now */
-               for (i = 0; i < 16; i++) {
-                       void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
-                       writel(0, reg);
-               }
-
-               writel(32, base + VIC_PL190_DEF_VECT_ADDR);
-       }
-
-       for (i = 0; i < 32; i++) {
-               if (vic_sources & (1 << i)) {
-                       unsigned int irq = irq_start + i;
-
-                       set_irq_chip(irq, &vic_chip);
-                       set_irq_chip_data(irq, base);
-                       set_irq_handler(irq, handle_level_irq);
-                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-               }
-       }
-}
diff --git a/arch/arm/configs/at572d940hfek_defconfig b/arch/arm/configs/at572d940hfek_defconfig
new file mode 100644 (file)
index 0000000..76d724b
--- /dev/null
@@ -0,0 +1,1640 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc7
+# Fri Dec  5 10:58:47 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-AT572D940HF"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+# CONFIG_TASK_DELAY_ACCT is not set
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_AUDIT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+# CONFIG_USER_SCHED is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_CPUACCT=y
+# CONFIG_RESOURCE_COUNTERS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+# CONFIG_ARCH_AT91SAM9263 is not set
+# CONFIG_ARCH_AT91SAM9RL is not set
+# CONFIG_ARCH_AT91SAM9G20 is not set
+# CONFIG_ARCH_AT91CAP9 is not set
+# CONFIG_ARCH_AT91X40 is not set
+CONFIG_ARCH_AT572D940HF=y
+CONFIG_AT91_PMC_UNIT=y
+
+#
+# AT572D940HF Board Type
+#
+CONFIG_MACH_AT572D940HFEB=y
+
+#
+# AT91 Board Options
+#
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+# CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16 is not set
+CONFIG_NUM_SERIAL=3
+
+#
+# AT91 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_TIMER_HZ=100
+CONFIG_AT91_EARLY_DBGU=y
+# CONFIG_AT91_EARLY_USART0 is not set
+# CONFIG_AT91_EARLY_USART1 is not set
+# CONFIG_AT91_EARLY_USART2 is not set
+# CONFIG_AT91_EARLY_USART3 is not set
+# CONFIG_AT91_EARLY_USART4 is not set
+# CONFIG_AT91_EARLY_USART5 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="mem=48M console=ttyS0 initrd=0x21100000,3145728 root=/dev/ram0 rw ip=172.16.1.181"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_DEBUG_DEVICES=y
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=1
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+CONFIG_MTD_PLATRAM=m
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+# CONFIG_MTD_NAND_ATMEL is not set
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_TCB_CLKSRC=y
+CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
+CONFIG_ATMEL_SSC=m
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MACB=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+CONFIG_WLAN_PRE80211=y
+CONFIG_STRIP=m
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_USB_ZD1201=m
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_DM9601=m
+# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+# CONFIG_MOUSE_BCM5974 is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+CONFIG_SPECIALIX=m
+CONFIG_RIO=m
+# CONFIG_RIO_OLDPCI is not set
+CONFIG_STALDRV=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_ATMEL_PDC=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_TCG_TPM=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_DS1682=m
+# CONFIG_AT24 is not set
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_BITBANG=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_AT25=m
+CONFIG_SPI_SPIDEV=m
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_PCM_OSS_PLUGINS is not set
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+# CONFIG_SND_AT73C213 is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+CONFIG_USB_STORAGE_KARMA=y
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+CONFIG_USB_SERIAL_SPCP8X5=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=m
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_AT91=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=m
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+CONFIG_RTC_DRV_DS1305=y
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_AT91SAM9 is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+CONFIG_REISERFS_CHECK=y
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+# CONFIG_UBIFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 3de640a..c48d7b8 100644 (file)
@@ -242,10 +242,13 @@ CONFIG_CPU_CP15_MMU=y
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_BPREDICT_DISABLE is not set
 CONFIG_HAS_TLS_REG=y
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_L2X0=y
 CONFIG_ARM_L1_CACHE_SHIFT=5
 # CONFIG_ARM_ERRATA_430973 is not set
 # CONFIG_ARM_ERRATA_458693 is not set
 # CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_PL310_ERRATA_588369=y
 CONFIG_ARM_GIC=y
 
 #
index d0daeab..e8ddec2 100644 (file)
@@ -235,6 +235,234 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()    smp_mb()
 #define smp_mb__after_atomic_inc()     smp_mb()
 
+#ifndef CONFIG_GENERIC_ATOMIC64
+typedef struct {
+       u64 __aligned(8) counter;
+} atomic64_t;
+
+#define ATOMIC64_INIT(i) { (i) }
+
+static inline u64 atomic64_read(atomic64_t *v)
+{
+       u64 result;
+
+       __asm__ __volatile__("@ atomic64_read\n"
+"      ldrexd  %0, %H0, [%1]"
+       : "=&r" (result)
+       : "r" (&v->counter)
+       );
+
+       return result;
+}
+
+static inline void atomic64_set(atomic64_t *v, u64 i)
+{
+       u64 tmp;
+
+       __asm__ __volatile__("@ atomic64_set\n"
+"1:    ldrexd  %0, %H0, [%1]\n"
+"      strexd  %0, %2, %H2, [%1]\n"
+"      teq     %0, #0\n"
+"      bne     1b"
+       : "=&r" (tmp)
+       : "r" (&v->counter), "r" (i)
+       : "cc");
+}
+
+static inline void atomic64_add(u64 i, atomic64_t *v)
+{
+       u64 result;
+       unsigned long tmp;
+
+       __asm__ __volatile__("@ atomic64_add\n"
+"1:    ldrexd  %0, %H0, [%2]\n"
+"      adds    %0, %0, %3\n"
+"      adc     %H0, %H0, %H3\n"
+"      strexd  %1, %0, %H0, [%2]\n"
+"      teq     %1, #0\n"
+"      bne     1b"
+       : "=&r" (result), "=&r" (tmp)
+       : "r" (&v->counter), "r" (i)
+       : "cc");
+}
+
+static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
+{
+       u64 result;
+       unsigned long tmp;
+
+       smp_mb();
+
+       __asm__ __volatile__("@ atomic64_add_return\n"
+"1:    ldrexd  %0, %H0, [%2]\n"
+"      adds    %0, %0, %3\n"
+"      adc     %H0, %H0, %H3\n"
+"      strexd  %1, %0, %H0, [%2]\n"
+"      teq     %1, #0\n"
+"      bne     1b"
+       : "=&r" (result), "=&r" (tmp)
+       : "r" (&v->counter), "r" (i)
+       : "cc");
+
+       smp_mb();
+
+       return result;
+}
+
+static inline void atomic64_sub(u64 i, atomic64_t *v)
+{
+       u64 result;
+       unsigned long tmp;
+
+       __asm__ __volatile__("@ atomic64_sub\n"
+"1:    ldrexd  %0, %H0, [%2]\n"
+"      subs    %0, %0, %3\n"
+"      sbc     %H0, %H0, %H3\n"
+"      strexd  %1, %0, %H0, [%2]\n"
+"      teq     %1, #0\n"
+"      bne     1b"
+       : "=&r" (result), "=&r" (tmp)
+       : "r" (&v->counter), "r" (i)
+       : "cc");
+}
+
+static inline u64 atomic64_sub_return(u64 i, atomic64_t *v)
+{
+       u64 result;
+       unsigned long tmp;
+
+       smp_mb();
+
+       __asm__ __volatile__("@ atomic64_sub_return\n"
+"1:    ldrexd  %0, %H0, [%2]\n"
+"      subs    %0, %0, %3\n"
+"      sbc     %H0, %H0, %H3\n"
+"      strexd  %1, %0, %H0, [%2]\n"
+"      teq     %1, #0\n"
+"      bne     1b"
+       : "=&r" (result), "=&r" (tmp)
+       : "r" (&v->counter), "r" (i)
+       : "cc");
+
+       smp_mb();
+
+       return result;
+}
+
+static inline u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old, u64 new)
+{
+       u64 oldval;
+       unsigned long res;
+
+       smp_mb();
+
+       do {
+               __asm__ __volatile__("@ atomic64_cmpxchg\n"
+               "ldrexd         %1, %H1, [%2]\n"
+               "mov            %0, #0\n"
+               "teq            %1, %3\n"
+               "teqeq          %H1, %H3\n"
+               "strexdeq       %0, %4, %H4, [%2]"
+               : "=&r" (res), "=&r" (oldval)
+               : "r" (&ptr->counter), "r" (old), "r" (new)
+               : "cc");
+       } while (res);
+
+       smp_mb();
+
+       return oldval;
+}
+
+static inline u64 atomic64_xchg(atomic64_t *ptr, u64 new)
+{
+       u64 result;
+       unsigned long tmp;
+
+       smp_mb();
+
+       __asm__ __volatile__("@ atomic64_xchg\n"
+"1:    ldrexd  %0, %H0, [%2]\n"
+"      strexd  %1, %3, %H3, [%2]\n"
+"      teq     %1, #0\n"
+"      bne     1b"
+       : "=&r" (result), "=&r" (tmp)
+       : "r" (&ptr->counter), "r" (new)
+       : "cc");
+
+       smp_mb();
+
+       return result;
+}
+
+static inline u64 atomic64_dec_if_positive(atomic64_t *v)
+{
+       u64 result;
+       unsigned long tmp;
+
+       smp_mb();
+
+       __asm__ __volatile__("@ atomic64_dec_if_positive\n"
+"1:    ldrexd  %0, %H0, [%2]\n"
+"      subs    %0, %0, #1\n"
+"      sbc     %H0, %H0, #0\n"
+"      teq     %H0, #0\n"
+"      bmi     2f\n"
+"      strexd  %1, %0, %H0, [%2]\n"
+"      teq     %1, #0\n"
+"      bne     1b\n"
+"2:"
+       : "=&r" (result), "=&r" (tmp)
+       : "r" (&v->counter)
+       : "cc");
+
+       smp_mb();
+
+       return result;
+}
+
+static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
+{
+       u64 val;
+       unsigned long tmp;
+       int ret = 1;
+
+       smp_mb();
+
+       __asm__ __volatile__("@ atomic64_add_unless\n"
+"1:    ldrexd  %0, %H0, [%3]\n"
+"      teq     %0, %4\n"
+"      teqeq   %H0, %H4\n"
+"      moveq   %1, #0\n"
+"      beq     2f\n"
+"      adds    %0, %0, %5\n"
+"      adc     %H0, %H0, %H5\n"
+"      strexd  %2, %0, %H0, [%3]\n"
+"      teq     %2, #0\n"
+"      bne     1b\n"
+"2:"
+       : "=&r" (val), "=&r" (ret), "=&r" (tmp)
+       : "r" (&v->counter), "r" (u), "r" (a)
+       : "cc");
+
+       if (ret)
+               smp_mb();
+
+       return ret;
+}
+
+#define atomic64_add_negative(a, v)    (atomic64_add_return((a), (v)) < 0)
+#define atomic64_inc(v)                        atomic64_add(1LL, (v))
+#define atomic64_inc_return(v)         atomic64_add_return(1LL, (v))
+#define atomic64_inc_and_test(v)       (atomic64_inc_return(v) == 0)
+#define atomic64_sub_and_test(a, v)    (atomic64_sub_return((a), (v)) == 0)
+#define atomic64_dec(v)                        atomic64_sub(1LL, (v))
+#define atomic64_dec_return(v)         atomic64_sub_return(1LL, (v))
+#define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
+#define atomic64_inc_not_zero(v)       atomic64_add_unless((v), 1LL, 0LL)
+
+#else /* !CONFIG_GENERIC_ATOMIC64 */
+#include <asm-generic/atomic64.h>
+#endif
 #include <asm-generic/atomic-long.h>
 #endif
 #endif
index 5fe4a2a..72da7e0 100644 (file)
  *     DMA Cache Coherency
  *     ===================
  *
- *     dma_inv_range(start, end)
- *
- *             Invalidate (discard) the specified virtual address range.
- *             May not write back any entries.  If 'start' or 'end'
- *             are not cache line aligned, those lines must be written
- *             back.
- *             - start  - virtual start address
- *             - end    - virtual end address
- *
- *     dma_clean_range(start, end)
- *
- *             Clean (write back) the specified virtual address range.
- *             - start  - virtual start address
- *             - end    - virtual end address
- *
  *     dma_flush_range(start, end)
  *
  *             Clean and invalidate the specified virtual address range.
@@ -228,8 +213,9 @@ struct cpu_cache_fns {
        void (*coherent_user_range)(unsigned long, unsigned long);
        void (*flush_kern_dcache_area)(void *, size_t);
 
-       void (*dma_inv_range)(const void *, const void *);
-       void (*dma_clean_range)(const void *, const void *);
+       void (*dma_map_area)(const void *, size_t, int);
+       void (*dma_unmap_area)(const void *, size_t, int);
+
        void (*dma_flush_range)(const void *, const void *);
 };
 
@@ -259,8 +245,8 @@ extern struct cpu_cache_fns cpu_cache;
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
-#define dmac_inv_range                 cpu_cache.dma_inv_range
-#define dmac_clean_range               cpu_cache.dma_clean_range
+#define dmac_map_area                  cpu_cache.dma_map_area
+#define dmac_unmap_area                cpu_cache.dma_unmap_area
 #define dmac_flush_range               cpu_cache.dma_flush_range
 
 #else
@@ -285,12 +271,12 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
-#define dmac_inv_range                 __glue(_CACHE,_dma_inv_range)
-#define dmac_clean_range               __glue(_CACHE,_dma_clean_range)
+#define dmac_map_area                  __glue(_CACHE,_dma_map_area)
+#define dmac_unmap_area                __glue(_CACHE,_dma_unmap_area)
 #define dmac_flush_range               __glue(_CACHE,_dma_flush_range)
 
-extern void dmac_inv_range(const void *, const void *);
-extern void dmac_clean_range(const void *, const void *);
+extern void dmac_map_area(const void *, size_t, int);
+extern void dmac_unmap_area(const void *, size_t, int);
 extern void dmac_flush_range(const void *, const void *);
 
 #endif
@@ -331,12 +317,8 @@ static inline void outer_flush_range(unsigned long start, unsigned long end)
  * processes address space.  Really, we want to allow our "user
  * space" model to handle this.
  */
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-       do {                                                    \
-               memcpy(dst, src, len);                          \
-               flush_ptrace_access(vma, page, vaddr, dst, len, 1);\
-       } while (0)
-
+extern void copy_to_user_page(struct vm_area_struct *, struct page *,
+       unsigned long, void *, const void *, unsigned long);
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
        do {                                                    \
                memcpy(dst, src, len);                          \
@@ -370,17 +352,6 @@ vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
        }
 }
 
-static inline void
-vivt_flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
-                        unsigned long uaddr, void *kaddr,
-                        unsigned long len, int write)
-{
-       if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
-               unsigned long addr = (unsigned long)kaddr;
-               __cpuc_coherent_kern_range(addr, addr + len);
-       }
-}
-
 #ifndef CONFIG_CPU_CACHE_VIPT
 #define flush_cache_mm(mm) \
                vivt_flush_cache_mm(mm)
@@ -388,15 +359,10 @@ vivt_flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
                vivt_flush_cache_range(vma,start,end)
 #define flush_cache_page(vma,addr,pfn) \
                vivt_flush_cache_page(vma,addr,pfn)
-#define flush_ptrace_access(vma,page,ua,ka,len,write) \
-               vivt_flush_ptrace_access(vma,page,ua,ka,len,write)
 #else
 extern void flush_cache_mm(struct mm_struct *mm);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
 extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
-extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
-                               unsigned long uaddr, void *kaddr,
-                               unsigned long len, int write);
 #endif
 
 #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
index b6ec7c6..7a0690d 100644 (file)
@@ -27,4 +27,7 @@ struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
 void clkdev_add(struct clk_lookup *cl);
 void clkdev_drop(struct clk_lookup *cl);
 
+void clkdev_add_table(struct clk_lookup *, size_t);
+int clk_add_alias(const char *, const char *, char *, struct device *);
+
 #endif
index a96300b..256ee1c 100644 (file)
@@ -57,18 +57,58 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
 #endif
 
 /*
- * DMA-consistent mapping functions.  These allocate/free a region of
- * uncached, unwrite-buffered mapped memory space for use with DMA
- * devices.  This is the "generic" version.  The PCI specific version
- * is in pci.h
+ * The DMA API is built upon the notion of "buffer ownership".  A buffer
+ * is either exclusively owned by the CPU (and therefore may be accessed
+ * by it) or exclusively owned by the DMA device.  These helper functions
+ * represent the transitions between these two ownership states.
  *
- * Note: Drivers should NOT use this function directly, as it will break
- * platforms with CONFIG_DMABOUNCE.
- * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
+ * Note, however, that on later ARMs, this notion does not work due to
+ * speculative prefetches.  We model our approach on the assumption that
+ * the CPU does do speculative prefetches, which means we clean caches
+ * before transfers and delay cache invalidation until transfer completion.
+ *
+ * Private support functions: these are not part of the API and are
+ * liable to change.  Drivers must not use these.
  */
-extern void dma_cache_maint(const void *kaddr, size_t size, int rw);
-extern void dma_cache_maint_page(struct page *page, unsigned long offset,
-                                size_t size, int rw);
+static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
+       enum dma_data_direction dir)
+{
+       extern void ___dma_single_cpu_to_dev(const void *, size_t,
+               enum dma_data_direction);
+
+       if (!arch_is_coherent())
+               ___dma_single_cpu_to_dev(kaddr, size, dir);
+}
+
+static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
+       enum dma_data_direction dir)
+{
+       extern void ___dma_single_dev_to_cpu(const void *, size_t,
+               enum dma_data_direction);
+
+       if (!arch_is_coherent())
+               ___dma_single_dev_to_cpu(kaddr, size, dir);
+}
+
+static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
+       size_t size, enum dma_data_direction dir)
+{
+       extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
+               size_t, enum dma_data_direction);
+
+       if (!arch_is_coherent())
+               ___dma_page_cpu_to_dev(page, off, size, dir);
+}
+
+static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
+       size_t size, enum dma_data_direction dir)
+{
+       extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
+               size_t, enum dma_data_direction);
+
+       if (!arch_is_coherent())
+               ___dma_page_dev_to_cpu(page, off, size, dir);
+}
 
 /*
  * Return whether the given device DMA address mask can be supported
@@ -304,8 +344,7 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
 {
        BUG_ON(!valid_dma_direction(dir));
 
-       if (!arch_is_coherent())
-               dma_cache_maint(cpu_addr, size, dir);
+       __dma_single_cpu_to_dev(cpu_addr, size, dir);
 
        return virt_to_dma(dev, cpu_addr);
 }
@@ -329,8 +368,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 {
        BUG_ON(!valid_dma_direction(dir));
 
-       if (!arch_is_coherent())
-               dma_cache_maint_page(page, offset, size, dir);
+       __dma_page_cpu_to_dev(page, offset, size, dir);
 
        return page_to_dma(dev, page) + offset;
 }
@@ -352,7 +390,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       /* nothing to do */
+       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
 }
 
 /**
@@ -372,7 +410,8 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
 static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       /* nothing to do */
+       __dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK,
+               size, dir);
 }
 #endif /* CONFIG_DMABOUNCE */
 
@@ -400,7 +439,10 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
 {
        BUG_ON(!valid_dma_direction(dir));
 
-       dmabounce_sync_for_cpu(dev, handle, offset, size, dir);
+       if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
+               return;
+
+       __dma_single_dev_to_cpu(dma_to_virt(dev, handle) + offset, size, dir);
 }
 
 static inline void dma_sync_single_range_for_device(struct device *dev,
@@ -412,8 +454,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
        if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
                return;
 
-       if (!arch_is_coherent())
-               dma_cache_maint(dma_to_virt(dev, handle) + offset, size, dir);
+       __dma_single_cpu_to_dev(dma_to_virt(dev, handle) + offset, size, dir);
 }
 
 static inline void dma_sync_single_for_cpu(struct device *dev,
index d2a59cf..c980156 100644 (file)
@@ -69,9 +69,16 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 /*
  * __arm_ioremap takes CPU physical address.
  * __arm_ioremap_pfn takes a Page Frame Number and an offset into that page
+ * The _caller variety takes a __builtin_return_address(0) value for
+ * /proc/vmalloc to use - and should only be used in non-inline functions.
  */
-extern void __iomem * __arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
-extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
+extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long,
+       size_t, unsigned int, void *);
+extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int,
+       void *);
+
+extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
+extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
 extern void __iounmap(volatile void __iomem *addr);
 
 /*
index b2cc1fc..8bffc3f 100644 (file)
@@ -46,12 +46,4 @@ struct sys_timer {
 extern struct sys_timer *system_timer;
 extern void timer_tick(void);
 
-/*
- * Kernel time keeping support.
- */
-struct timespec;
-extern int (*set_rtc)(void);
-extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
-extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
-
 #endif
index 5421d82..4312ee5 100644 (file)
  */
 #define IOREMAP_MAX_ORDER      24
 
+/*
+ * Size of DMA-consistent memory region.  Must be multiple of 2M,
+ * between 2MB and 14MB inclusive.
+ */
+#ifndef CONSISTENT_DMA_SIZE
+#define CONSISTENT_DMA_SIZE    SZ_2M
+#endif
+
+#define CONSISTENT_END         (0xffe00000UL)
+#define CONSISTENT_BASE                (CONSISTENT_END - CONSISTENT_DMA_SIZE)
+
 #else /* CONFIG_MMU */
 
 /*
 #endif
 
 #ifndef PHYS_OFFSET
-#define PHYS_OFFSET            (CONFIG_DRAM_BASE)
+#define PHYS_OFFSET            UL(CONFIG_DRAM_BASE)
 #endif
 
 #ifndef END_MEM
-#define END_MEM                (CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE)
+#define END_MEM                (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
 #endif
 
 #ifndef PAGE_OFFSET
 #endif /* !CONFIG_MMU */
 
 /*
- * Size of DMA-consistent memory region.  Must be multiple of 2M,
- * between 2MB and 14MB inclusive.
- */
-#ifndef CONSISTENT_DMA_SIZE
-#define CONSISTENT_DMA_SIZE SZ_2M
-#endif
-
-/*
  * Physical vs virtual RAM address space conversion.  These are
  * private definitions which should NOT be used outside memory.h
  * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
index b561584..68870c7 100644 (file)
@@ -6,6 +6,7 @@
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
        unsigned int id;
+       spinlock_t id_lock;
 #endif
        unsigned int kvm_seq;
 } mm_context_t;
index de6cefb..a0b3cac 100644 (file)
@@ -43,12 +43,23 @@ void __check_kvm_seq(struct mm_struct *mm);
 #define ASID_FIRST_VERSION     (1 << ASID_BITS)
 
 extern unsigned int cpu_last_asid;
+#ifdef CONFIG_SMP
+DECLARE_PER_CPU(struct mm_struct *, current_mm);
+#endif
 
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 void __new_context(struct mm_struct *mm);
 
 static inline void check_context(struct mm_struct *mm)
 {
+       /*
+        * This code is executed with interrupts enabled. Therefore,
+        * mm->context.id cannot be updated to the latest ASID version
+        * on a different CPU (and condition below not triggered)
+        * without first getting an IPI to reset the context. The
+        * alternative is to take a read_lock on mm->context.id_lock
+        * (after changing its type to rwlock_t).
+        */
        if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
                __new_context(mm);
 
@@ -108,6 +119,10 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
                __flush_icache_all();
 #endif
        if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
+#ifdef CONFIG_SMP
+               struct mm_struct **crt_mm = &per_cpu(current_mm, cpu);
+               *crt_mm = next;
+#endif
                check_context(next);
                cpu_switch_mm(next->pgd, next);
                if (cache_is_vivt())
index 3a32af4..a485ac3 100644 (file)
 #endif
 
 struct page;
+struct vm_area_struct;
 
 struct cpu_user_fns {
        void (*cpu_clear_user_highpage)(struct page *page, unsigned long vaddr);
        void (*cpu_copy_user_highpage)(struct page *to, struct page *from,
-                       unsigned long vaddr);
+                       unsigned long vaddr, struct vm_area_struct *vma);
 };
 
 #ifdef MULTI_USER
@@ -137,7 +138,7 @@ extern struct cpu_user_fns cpu_user;
 
 extern void __cpu_clear_user_highpage(struct page *page, unsigned long vaddr);
 extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
-                       unsigned long vaddr);
+                       unsigned long vaddr, struct vm_area_struct *vma);
 #endif
 
 #define clear_user_highpage(page,vaddr)                \
@@ -145,7 +146,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
 
 #define __HAVE_ARCH_COPY_USER_HIGHPAGE
 #define copy_user_highpage(to,from,vaddr,vma)  \
-       __cpu_copy_user_highpage(to, from, vaddr)
+       __cpu_copy_user_highpage(to, from, vaddr, vma)
 
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
new file mode 100644 (file)
index 0000000..49e3049
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  linux/arch/arm/include/asm/perf_event.h
+ *
+ *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ARM_PERF_EVENT_H__
+#define __ARM_PERF_EVENT_H__
+
+/*
+ * NOP: on *most* (read: all supported) ARM platforms, the performance
+ * counter interrupts are regular interrupts and not an NMI. This
+ * means that when we receive the interrupt we can call
+ * perf_event_do_pending() that handles all of the work with
+ * interrupts enabled.
+ */
+static inline void
+set_perf_event_pending(void)
+{
+}
+
+/* ARM performance counters start from 1 (in the cp15 accesses) so use the
+ * same indexes here for consistency. */
+#define PERF_EVENT_INDEX_OFFSET 1
+
+#endif /* __ARM_PERF_EVENT_H__ */
index b011f2e..013cfcd 100644 (file)
@@ -86,8 +86,8 @@ extern unsigned int kobjsize(const void *objp);
  * All 32bit addresses are effectively valid for vmalloc...
  * Sort of meaningless for non-VM targets.
  */
-#define        VMALLOC_START   0
-#define        VMALLOC_END     0xffffffff
+#define        VMALLOC_START   0UL
+#define        VMALLOC_END     0xffffffffUL
 
 #define FIRST_USER_ADDRESS      (0)
 
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
new file mode 100644 (file)
index 0000000..2829b9f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  linux/arch/arm/include/asm/pmu.h
+ *
+ *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ARM_PMU_H__
+#define __ARM_PMU_H__
+
+#ifdef CONFIG_CPU_HAS_PMU
+
+struct pmu_irqs {
+       const int   *irqs;
+       int         num_irqs;
+};
+
+/**
+ * reserve_pmu() - reserve the hardware performance counters
+ *
+ * Reserve the hardware performance counters in the system for exclusive use.
+ * The 'struct pmu_irqs' for the system is returned on success, ERR_PTR()
+ * encoded error on failure.
+ */
+extern const struct pmu_irqs *
+reserve_pmu(void);
+
+/**
+ * release_pmu() - Relinquish control of the performance counters
+ *
+ * Release the performance counters and allow someone else to use them.
+ * Callers must have disabled the counters and released IRQs before calling
+ * this. The 'struct pmu_irqs' returned from reserve_pmu() must be passed as
+ * a cookie.
+ */
+extern int
+release_pmu(const struct pmu_irqs *irqs);
+
+/**
+ * init_pmu() - Initialise the PMU.
+ *
+ * Initialise the system ready for PMU enabling. This should typically set the
+ * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do
+ * the actual hardware initialisation.
+ */
+extern int
+init_pmu(void);
+
+#else /* CONFIG_CPU_HAS_PMU */
+
+static inline const struct pmu_irqs *
+reserve_pmu(void)
+{
+       return ERR_PTR(-ENODEV);
+}
+
+static inline int
+release_pmu(const struct pmu_irqs *irqs)
+{
+       return -ENODEV;
+}
+
+static inline int
+init_pmu(void)
+{
+       return -ENODEV;
+}
+
+#endif /* CONFIG_CPU_HAS_PMU */
+
+#endif /* __ARM_PMU_H__ */
index 5ccce0a..f392fb4 100644 (file)
@@ -223,18 +223,6 @@ extern struct meminfo meminfo;
 #define bank_phys_end(bank)    ((bank)->start + (bank)->size)
 #define bank_phys_size(bank)   (bank)->size
 
-/*
- * Early command line parameters.
- */
-struct early_params {
-       const char *arg;
-       void (*fn)(char **p);
-};
-
-#define __early_param(name,fn)                                 \
-static struct early_params __early_##fn __used                 \
-__attribute__((__section__(".early_param.init"))) = { name, fn }
-
 #endif  /*  __KERNEL__  */
 
 #endif
index 59303e2..e621530 100644 (file)
@@ -13,4 +13,9 @@ static inline int tlb_ops_need_broadcast(void)
        return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
 }
 
+static inline int cache_ops_need_broadcast(void)
+{
+       return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
+}
+
 #endif
index c91c64c..17eb355 100644 (file)
@@ -5,6 +5,22 @@
 #error SMP not supported on pre-ARMv6 CPUs
 #endif
 
+static inline void dsb_sev(void)
+{
+#if __LINUX_ARM_ARCH__ >= 7
+       __asm__ __volatile__ (
+               "dsb\n"
+               "sev"
+       );
+#elif defined(CONFIG_CPU_32v6K)
+       __asm__ __volatile__ (
+               "mcr p15, 0, %0, c7, c10, 4\n"
+               "sev"
+               : : "r" (0)
+       );
+#endif
+}
+
 /*
  * ARMv6 Spin-locking.
  *
@@ -69,13 +85,11 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 
        __asm__ __volatile__(
 "      str     %1, [%0]\n"
-#ifdef CONFIG_CPU_32v6K
-"      mcr     p15, 0, %1, c7, c10, 4\n" /* DSB */
-"      sev"
-#endif
        :
        : "r" (&lock->lock), "r" (0)
        : "cc");
+
+       dsb_sev();
 }
 
 /*
@@ -132,13 +146,11 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
 
        __asm__ __volatile__(
        "str    %1, [%0]\n"
-#ifdef CONFIG_CPU_32v6K
-"      mcr     p15, 0, %1, c7, c10, 4\n" /* DSB */
-"      sev\n"
-#endif
        :
        : "r" (&rw->lock), "r" (0)
        : "cc");
+
+       dsb_sev();
 }
 
 /* write_can_lock - would write_trylock() succeed? */
@@ -188,14 +200,12 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 "      strex   %1, %0, [%2]\n"
 "      teq     %1, #0\n"
 "      bne     1b"
-#ifdef CONFIG_CPU_32v6K
-"\n    cmp     %0, #0\n"
-"      mcreq   p15, 0, %0, c7, c10, 4\n"
-"      seveq"
-#endif
        : "=&r" (tmp), "=&r" (tmp2)
        : "r" (&rw->lock)
        : "cc");
+
+       if (tmp == 0)
+               dsb_sev();
 }
 
 static inline int arch_read_trylock(arch_rwlock_t *rw)
index 058e7e9..ca88e6a 100644 (file)
@@ -73,8 +73,7 @@ extern unsigned int mem_fclk_21285;
 
 struct pt_regs;
 
-void die(const char *msg, struct pt_regs *regs, int err)
-               __attribute__((noreturn));
+void die(const char *msg, struct pt_regs *regs, int err);
 
 struct siginfo;
 void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
index 2dfb7d7..b74970e 100644 (file)
@@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
 extern void iwmmxt_task_release(struct thread_info *);
 extern void iwmmxt_task_switch(struct thread_info *);
 
-extern void vfp_sync_state(struct thread_info *thread);
+extern void vfp_sync_hwstate(struct thread_info *);
+extern void vfp_flush_hwstate(struct thread_info *);
 
 #endif
 
index c2f1605..e085e2c 100644 (file)
@@ -529,7 +529,8 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
  * cache entries for the kernels virtual memory range are written
  * back to the page.
  */
-extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
+extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+       pte_t *ptep);
 
 #endif
 
index dd00f74..26d302c 100644 (file)
@@ -17,6 +17,7 @@ obj-y         := compat.o elf.o entry-armv.o entry-common.o irq.o \
                   process.o ptrace.o return_address.o setup.o signal.o \
                   sys_arm.o stacktrace.o time.o traps.o
 
+obj-$(CONFIG_LEDS)             += leds.o
 obj-$(CONFIG_OC_ETM)           += etm.o
 
 obj-$(CONFIG_ISA_DMA_API)      += dma.o
@@ -46,6 +47,8 @@ obj-$(CONFIG_CPU_XSCALE)      += xscale-cp0.o
 obj-$(CONFIG_CPU_XSC3)         += xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)       += xscale-cp0.o
 obj-$(CONFIG_IWMMXT)           += iwmmxt.o
+obj-$(CONFIG_CPU_HAS_PMU)      += pmu.o
+obj-$(CONFIG_HW_PERF_EVENTS)   += perf_event.o
 AFLAGS_iwmmxt.o                        := -Wa,-mcpu=iwmmxt
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
index 4a88125..8835115 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
 #include <asm/mach/arch.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
@@ -112,5 +113,9 @@ int main(void)
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,  offsetof(struct processor, _prefetch_abort));
 #endif
+  BLANK();
+  DEFINE(DMA_BIDIRECTIONAL,    DMA_BIDIRECTIONAL);
+  DEFINE(DMA_TO_DEVICE,                DMA_TO_DEVICE);
+  DEFINE(DMA_FROM_DEVICE,      DMA_FROM_DEVICE);
   return 0; 
 }
index 5c91add..a38b487 100644 (file)
@@ -24,7 +24,7 @@
 
 #if defined(CONFIG_CPU_V6)
 
-               .macro  addruart, rx
+               .macro  addruart, rx, tmp
                .endm
 
                .macro  senduart, rd, rx
@@ -51,7 +51,7 @@
 
 #elif defined(CONFIG_CPU_V7)
 
-               .macro  addruart, rx
+               .macro  addruart, rx, tmp
                .endm
 
                .macro  senduart, rd, rx
@@ -71,7 +71,7 @@ wait:         mrc     p14, 0, pc, c0, c1, 0
 
 #elif defined(CONFIG_CPU_XSCALE)
 
-               .macro  addruart, rx
+               .macro  addruart, rx, tmp
                .endm
 
                .macro  senduart, rd, rx
@@ -98,7 +98,7 @@ wait:         mrc     p14, 0, pc, c0, c1, 0
 
 #else
 
-               .macro  addruart, rx
+               .macro  addruart, rx, tmp
                .endm
 
                .macro  senduart, rd, rx
@@ -164,7 +164,7 @@ ENDPROC(printhex2)
                .ltorg
 
 ENTRY(printascii)
-               addruart r3
+               addruart r3, r1
                b       2f
 1:             waituart r2, r3
                senduart r1, r3
@@ -180,7 +180,7 @@ ENTRY(printascii)
 ENDPROC(printascii)
 
 ENTRY(printch)
-               addruart r3
+               addruart r3, r1
                mov     r1, r0
                mov     r0, #0
                b       1b
diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c
new file mode 100644 (file)
index 0000000..31a316c
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * LED support code, ripped out of arch/arm/kernel/time.c
+ *
+ *  Copyright (C) 1994-2001 Russell King
+ *
+ * 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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/leds.h>
+
+static void dummy_leds_event(led_event_t evt)
+{
+}
+
+void (*leds_event)(led_event_t) = dummy_leds_event;
+
+struct leds_evt_name {
+       const char      name[8];
+       int             on;
+       int             off;
+};
+
+static const struct leds_evt_name evt_names[] = {
+       { "amber", led_amber_on, led_amber_off },
+       { "blue",  led_blue_on,  led_blue_off  },
+       { "green", led_green_on, led_green_off },
+       { "red",   led_red_on,   led_red_off   },
+};
+
+static ssize_t leds_store(struct sys_device *dev,
+                       struct sysdev_attribute *attr,
+                       const char *buf, size_t size)
+{
+       int ret = -EINVAL, len = strcspn(buf, " ");
+
+       if (len > 0 && buf[len] == '\0')
+               len--;
+
+       if (strncmp(buf, "claim", len) == 0) {
+               leds_event(led_claim);
+               ret = size;
+       } else if (strncmp(buf, "release", len) == 0) {
+               leds_event(led_release);
+               ret = size;
+       } else {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
+                       if (strlen(evt_names[i].name) != len ||
+                           strncmp(buf, evt_names[i].name, len) != 0)
+                               continue;
+                       if (strncmp(buf+len, " on", 3) == 0) {
+                               leds_event(evt_names[i].on);
+                               ret = size;
+                       } else if (strncmp(buf+len, " off", 4) == 0) {
+                               leds_event(evt_names[i].off);
+                               ret = size;
+                       }
+                       break;
+               }
+       }
+       return ret;
+}
+
+static SYSDEV_ATTR(event, 0200, NULL, leds_store);
+
+static int leds_suspend(struct sys_device *dev, pm_message_t state)
+{
+       leds_event(led_stop);
+       return 0;
+}
+
+static int leds_resume(struct sys_device *dev)
+{
+       leds_event(led_start);
+       return 0;
+}
+
+static int leds_shutdown(struct sys_device *dev)
+{
+       leds_event(led_halted);
+       return 0;
+}
+
+static struct sysdev_class leds_sysclass = {
+       .name           = "leds",
+       .shutdown       = leds_shutdown,
+       .suspend        = leds_suspend,
+       .resume         = leds_resume,
+};
+
+static struct sys_device leds_device = {
+       .id             = 0,
+       .cls            = &leds_sysclass,
+};
+
+static int __init leds_init(void)
+{
+       int ret;
+       ret = sysdev_class_register(&leds_sysclass);
+       if (ret == 0)
+               ret = sysdev_register(&leds_device);
+       if (ret == 0)
+               ret = sysdev_create_file(&leds_device, &attr_event);
+       return ret;
+}
+
+device_initcall(leds_init);
+
+EXPORT_SYMBOL(leds_event);
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
new file mode 100644 (file)
index 0000000..c54ceb3
--- /dev/null
@@ -0,0 +1,2276 @@
+#undef DEBUG
+
+/*
+ * ARM performance counter support.
+ *
+ * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
+ *
+ * ARMv7 support: Jean Pihet <jpihet@mvista.com>
+ * 2010 (c) MontaVista Software, LLC.
+ *
+ * This code is based on the sparc64 perf event code, which is in turn based
+ * on the x86 code. Callchain code is based on the ARM OProfile backtrace
+ * code.
+ */
+#define pr_fmt(fmt) "hw perfevents: " fmt
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+
+#include <asm/cputype.h>
+#include <asm/irq.h>
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
+#include <asm/stacktrace.h>
+
+static const struct pmu_irqs *pmu_irqs;
+
+/*
+ * Hardware lock to serialize accesses to PMU registers. Needed for the
+ * read/modify/write sequences.
+ */
+DEFINE_SPINLOCK(pmu_lock);
+
+/*
+ * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
+ * another platform that supports more, we need to increase this to be the
+ * largest of all platforms.
+ *
+ * ARMv7 supports up to 32 events:
+ *  cycle counter CCNT + 31 events counters CNT0..30.
+ *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
+ */
+#define ARMPMU_MAX_HWEVENTS            33
+
+/* The events for a given CPU. */
+struct cpu_hw_events {
+       /*
+        * The events that are active on the CPU for the given index. Index 0
+        * is reserved.
+        */
+       struct perf_event       *events[ARMPMU_MAX_HWEVENTS];
+
+       /*
+        * A 1 bit for an index indicates that the counter is being used for
+        * an event. A 0 means that the counter can be used.
+        */
+       unsigned long           used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
+
+       /*
+        * A 1 bit for an index indicates that the counter is actively being
+        * used.
+        */
+       unsigned long           active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
+};
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+struct arm_pmu {
+       char            *name;
+       irqreturn_t     (*handle_irq)(int irq_num, void *dev);
+       void            (*enable)(struct hw_perf_event *evt, int idx);
+       void            (*disable)(struct hw_perf_event *evt, int idx);
+       int             (*event_map)(int evt);
+       u64             (*raw_event)(u64);
+       int             (*get_event_idx)(struct cpu_hw_events *cpuc,
+                                        struct hw_perf_event *hwc);
+       u32             (*read_counter)(int idx);
+       void            (*write_counter)(int idx, u32 val);
+       void            (*start)(void);
+       void            (*stop)(void);
+       int             num_events;
+       u64             max_period;
+};
+
+/* Set at runtime when we know what CPU type we are. */
+static const struct arm_pmu *armpmu;
+
+#define HW_OP_UNSUPPORTED              0xFFFF
+
+#define C(_x) \
+       PERF_COUNT_HW_CACHE_##_x
+
+#define CACHE_OP_UNSUPPORTED           0xFFFF
+
+static unsigned armpmu_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                    [PERF_COUNT_HW_CACHE_OP_MAX]
+                                    [PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+static int
+armpmu_map_cache_event(u64 config)
+{
+       unsigned int cache_type, cache_op, cache_result, ret;
+
+       cache_type = (config >>  0) & 0xff;
+       if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+               return -EINVAL;
+
+       cache_op = (config >>  8) & 0xff;
+       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+               return -EINVAL;
+
+       cache_result = (config >> 16) & 0xff;
+       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+               return -EINVAL;
+
+       ret = (int)armpmu_perf_cache_map[cache_type][cache_op][cache_result];
+
+       if (ret == CACHE_OP_UNSUPPORTED)
+               return -ENOENT;
+
+       return ret;
+}
+
+static int
+armpmu_event_set_period(struct perf_event *event,
+                       struct hw_perf_event *hwc,
+                       int idx)
+{
+       s64 left = atomic64_read(&hwc->period_left);
+       s64 period = hwc->sample_period;
+       int ret = 0;
+
+       if (unlikely(left <= -period)) {
+               left = period;
+               atomic64_set(&hwc->period_left, left);
+               hwc->last_period = period;
+               ret = 1;
+       }
+
+       if (unlikely(left <= 0)) {
+               left += period;
+               atomic64_set(&hwc->period_left, left);
+               hwc->last_period = period;
+               ret = 1;
+       }
+
+       if (left > (s64)armpmu->max_period)
+               left = armpmu->max_period;
+
+       atomic64_set(&hwc->prev_count, (u64)-left);
+
+       armpmu->write_counter(idx, (u64)(-left) & 0xffffffff);
+
+       perf_event_update_userpage(event);
+
+       return ret;
+}
+
+static u64
+armpmu_event_update(struct perf_event *event,
+                   struct hw_perf_event *hwc,
+                   int idx)
+{
+       int shift = 64 - 32;
+       s64 prev_raw_count, new_raw_count;
+       s64 delta;
+
+again:
+       prev_raw_count = atomic64_read(&hwc->prev_count);
+       new_raw_count = armpmu->read_counter(idx);
+
+       if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                            new_raw_count) != prev_raw_count)
+               goto again;
+
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       atomic64_add(delta, &event->count);
+       atomic64_sub(delta, &hwc->period_left);
+
+       return new_raw_count;
+}
+
+static void
+armpmu_disable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       WARN_ON(idx < 0);
+
+       clear_bit(idx, cpuc->active_mask);
+       armpmu->disable(hwc, idx);
+
+       barrier();
+
+       armpmu_event_update(event, hwc, idx);
+       cpuc->events[idx] = NULL;
+       clear_bit(idx, cpuc->used_mask);
+
+       perf_event_update_userpage(event);
+}
+
+static void
+armpmu_read(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       /* Don't read disabled counters! */
+       if (hwc->idx < 0)
+               return;
+
+       armpmu_event_update(event, hwc, hwc->idx);
+}
+
+static void
+armpmu_unthrottle(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       /*
+        * Set the period again. Some counters can't be stopped, so when we
+        * were throttled we simply disabled the IRQ source and the counter
+        * may have been left counting. If we don't do this step then we may
+        * get an interrupt too soon or *way* too late if the overflow has
+        * happened since disabling.
+        */
+       armpmu_event_set_period(event, hwc, hwc->idx);
+       armpmu->enable(hwc, hwc->idx);
+}
+
+static int
+armpmu_enable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx;
+       int err = 0;
+
+       /* If we don't have a space for the counter then finish early. */
+       idx = armpmu->get_event_idx(cpuc, hwc);
+       if (idx < 0) {
+               err = idx;
+               goto out;
+       }
+
+       /*
+        * If there is an event in the counter we are going to use then make
+        * sure it is disabled.
+        */
+       event->hw.idx = idx;
+       armpmu->disable(hwc, idx);
+       cpuc->events[idx] = event;
+       set_bit(idx, cpuc->active_mask);
+
+       /* Set the period for the event. */
+       armpmu_event_set_period(event, hwc, idx);
+
+       /* Enable the event. */
+       armpmu->enable(hwc, idx);
+
+       /* Propagate our changes to the userspace mapping. */
+       perf_event_update_userpage(event);
+
+out:
+       return err;
+}
+
+static struct pmu pmu = {
+       .enable     = armpmu_enable,
+       .disable    = armpmu_disable,
+       .unthrottle = armpmu_unthrottle,
+       .read       = armpmu_read,
+};
+
+static int
+validate_event(struct cpu_hw_events *cpuc,
+              struct perf_event *event)
+{
+       struct hw_perf_event fake_event = event->hw;
+
+       if (event->pmu && event->pmu != &pmu)
+               return 0;
+
+       return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
+}
+
+static int
+validate_group(struct perf_event *event)
+{
+       struct perf_event *sibling, *leader = event->group_leader;
+       struct cpu_hw_events fake_pmu;
+
+       memset(&fake_pmu, 0, sizeof(fake_pmu));
+
+       if (!validate_event(&fake_pmu, leader))
+               return -ENOSPC;
+
+       list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+               if (!validate_event(&fake_pmu, sibling))
+                       return -ENOSPC;
+       }
+
+       if (!validate_event(&fake_pmu, event))
+               return -ENOSPC;
+
+       return 0;
+}
+
+static int
+armpmu_reserve_hardware(void)
+{
+       int i;
+       int err;
+
+       pmu_irqs = reserve_pmu();
+       if (IS_ERR(pmu_irqs)) {
+               pr_warning("unable to reserve pmu\n");
+               return PTR_ERR(pmu_irqs);
+       }
+
+       init_pmu();
+
+       if (pmu_irqs->num_irqs < 1) {
+               pr_err("no irqs for PMUs defined\n");
+               return -ENODEV;
+       }
+
+       for (i = 0; i < pmu_irqs->num_irqs; ++i) {
+               err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq,
+                                 IRQF_DISABLED, "armpmu", NULL);
+               if (err) {
+                       pr_warning("unable to request IRQ%d for ARM "
+                                  "perf counters\n", pmu_irqs->irqs[i]);
+                       break;
+               }
+       }
+
+       if (err) {
+               for (i = i - 1; i >= 0; --i)
+                       free_irq(pmu_irqs->irqs[i], NULL);
+               release_pmu(pmu_irqs);
+               pmu_irqs = NULL;
+       }
+
+       return err;
+}
+
+static void
+armpmu_release_hardware(void)
+{
+       int i;
+
+       for (i = pmu_irqs->num_irqs - 1; i >= 0; --i)
+               free_irq(pmu_irqs->irqs[i], NULL);
+       armpmu->stop();
+
+       release_pmu(pmu_irqs);
+       pmu_irqs = NULL;
+}
+
+static atomic_t active_events = ATOMIC_INIT(0);
+static DEFINE_MUTEX(pmu_reserve_mutex);
+
+static void
+hw_perf_event_destroy(struct perf_event *event)
+{
+       if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) {
+               armpmu_release_hardware();
+               mutex_unlock(&pmu_reserve_mutex);
+       }
+}
+
+static int
+__hw_perf_event_init(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       int mapping, err;
+
+       /* Decode the generic type into an ARM event identifier. */
+       if (PERF_TYPE_HARDWARE == event->attr.type) {
+               mapping = armpmu->event_map(event->attr.config);
+       } else if (PERF_TYPE_HW_CACHE == event->attr.type) {
+               mapping = armpmu_map_cache_event(event->attr.config);
+       } else if (PERF_TYPE_RAW == event->attr.type) {
+               mapping = armpmu->raw_event(event->attr.config);
+       } else {
+               pr_debug("event type %x not supported\n", event->attr.type);
+               return -EOPNOTSUPP;
+       }
+
+       if (mapping < 0) {
+               pr_debug("event %x:%llx not supported\n", event->attr.type,
+                        event->attr.config);
+               return mapping;
+       }
+
+       /*
+        * Check whether we need to exclude the counter from certain modes.
+        * The ARM performance counters are on all of the time so if someone
+        * has asked us for some excludes then we have to fail.
+        */
+       if (event->attr.exclude_kernel || event->attr.exclude_user ||
+           event->attr.exclude_hv || event->attr.exclude_idle) {
+               pr_debug("ARM performance counters do not support "
+                        "mode exclusion\n");
+               return -EPERM;
+       }
+
+       /*
+        * We don't assign an index until we actually place the event onto
+        * hardware. Use -1 to signify that we haven't decided where to put it
+        * yet. For SMP systems, each core has it's own PMU so we can't do any
+        * clever allocation or constraints checking at this point.
+        */
+       hwc->idx = -1;
+
+       /*
+        * Store the event encoding into the config_base field. config and
+        * event_base are unused as the only 2 things we need to know are
+        * the event mapping and the counter to use. The counter to use is
+        * also the indx and the config_base is the event type.
+        */
+       hwc->config_base            = (unsigned long)mapping;
+       hwc->config                 = 0;
+       hwc->event_base             = 0;
+
+       if (!hwc->sample_period) {
+               hwc->sample_period  = armpmu->max_period;
+               hwc->last_period    = hwc->sample_period;
+               atomic64_set(&hwc->period_left, hwc->sample_period);
+       }
+
+       err = 0;
+       if (event->group_leader != event) {
+               err = validate_group(event);
+               if (err)
+                       return -EINVAL;
+       }
+
+       return err;
+}
+
+const struct pmu *
+hw_perf_event_init(struct perf_event *event)
+{
+       int err = 0;
+
+       if (!armpmu)
+               return ERR_PTR(-ENODEV);
+
+       event->destroy = hw_perf_event_destroy;
+
+       if (!atomic_inc_not_zero(&active_events)) {
+               if (atomic_read(&active_events) > perf_max_events) {
+                       atomic_dec(&active_events);
+                       return ERR_PTR(-ENOSPC);
+               }
+
+               mutex_lock(&pmu_reserve_mutex);
+               if (atomic_read(&active_events) == 0) {
+                       err = armpmu_reserve_hardware();
+               }
+
+               if (!err)
+                       atomic_inc(&active_events);
+               mutex_unlock(&pmu_reserve_mutex);
+       }
+
+       if (err)
+               return ERR_PTR(err);
+
+       err = __hw_perf_event_init(event);
+       if (err)
+               hw_perf_event_destroy(event);
+
+       return err ? ERR_PTR(err) : &pmu;
+}
+
+void
+hw_perf_enable(void)
+{
+       /* Enable all of the perf events on hardware. */
+       int idx;
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+       if (!armpmu)
+               return;
+
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+
+               if (!event)
+                       continue;
+
+               armpmu->enable(&event->hw, idx);
+       }
+
+       armpmu->start();
+}
+
+void
+hw_perf_disable(void)
+{
+       if (armpmu)
+               armpmu->stop();
+}
+
+/*
+ * ARMv6 Performance counter handling code.
+ *
+ * ARMv6 has 2 configurable performance counters and a single cycle counter.
+ * They all share a single reset bit but can be written to zero so we can use
+ * that for a reset.
+ *
+ * The counters can't be individually enabled or disabled so when we remove
+ * one event and replace it with another we could get spurious counts from the
+ * wrong event. However, we can take advantage of the fact that the
+ * performance counters can export events to the event bus, and the event bus
+ * itself can be monitored. This requires that we *don't* export the events to
+ * the event bus. The procedure for disabling a configurable counter is:
+ *     - change the counter to count the ETMEXTOUT[0] signal (0x20). This
+ *       effectively stops the counter from counting.
+ *     - disable the counter's interrupt generation (each counter has it's
+ *       own interrupt enable bit).
+ * Once stopped, the counter value can be written as 0 to reset.
+ *
+ * To enable a counter:
+ *     - enable the counter's interrupt generation.
+ *     - set the new event type.
+ *
+ * Note: the dedicated cycle counter only counts cycles and can't be
+ * enabled/disabled independently of the others. When we want to disable the
+ * cycle counter, we have to just disable the interrupt reporting and start
+ * ignoring that counter. When re-enabling, we have to reset the value and
+ * enable the interrupt.
+ */
+
+enum armv6_perf_types {
+       ARMV6_PERFCTR_ICACHE_MISS           = 0x0,
+       ARMV6_PERFCTR_IBUF_STALL            = 0x1,
+       ARMV6_PERFCTR_DDEP_STALL            = 0x2,
+       ARMV6_PERFCTR_ITLB_MISS             = 0x3,
+       ARMV6_PERFCTR_DTLB_MISS             = 0x4,
+       ARMV6_PERFCTR_BR_EXEC               = 0x5,
+       ARMV6_PERFCTR_BR_MISPREDICT         = 0x6,
+       ARMV6_PERFCTR_INSTR_EXEC            = 0x7,
+       ARMV6_PERFCTR_DCACHE_HIT            = 0x9,
+       ARMV6_PERFCTR_DCACHE_ACCESS         = 0xA,
+       ARMV6_PERFCTR_DCACHE_MISS           = 0xB,
+       ARMV6_PERFCTR_DCACHE_WBACK          = 0xC,
+       ARMV6_PERFCTR_SW_PC_CHANGE          = 0xD,
+       ARMV6_PERFCTR_MAIN_TLB_MISS         = 0xF,
+       ARMV6_PERFCTR_EXPL_D_ACCESS         = 0x10,
+       ARMV6_PERFCTR_LSU_FULL_STALL        = 0x11,
+       ARMV6_PERFCTR_WBUF_DRAINED          = 0x12,
+       ARMV6_PERFCTR_CPU_CYCLES            = 0xFF,
+       ARMV6_PERFCTR_NOP                   = 0x20,
+};
+
+enum armv6_counters {
+       ARMV6_CYCLE_COUNTER = 1,
+       ARMV6_COUNTER0,
+       ARMV6_COUNTER1,
+};
+
+/*
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV6_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV6_PERFCTR_INSTR_EXEC,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV6_PERFCTR_BR_MISPREDICT,
+       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                         [PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV6_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DCACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV6_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DCACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * The ARM performance counters can count micro DTLB misses,
+                * micro ITLB misses and main TLB misses. There isn't an event
+                * for TLB misses, so use the micro misses here and if users
+                * want the main TLB misses they can use a raw counter.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+enum armv6mpcore_perf_types {
+       ARMV6MPCORE_PERFCTR_ICACHE_MISS     = 0x0,
+       ARMV6MPCORE_PERFCTR_IBUF_STALL      = 0x1,
+       ARMV6MPCORE_PERFCTR_DDEP_STALL      = 0x2,
+       ARMV6MPCORE_PERFCTR_ITLB_MISS       = 0x3,
+       ARMV6MPCORE_PERFCTR_DTLB_MISS       = 0x4,
+       ARMV6MPCORE_PERFCTR_BR_EXEC         = 0x5,
+       ARMV6MPCORE_PERFCTR_BR_NOTPREDICT   = 0x6,
+       ARMV6MPCORE_PERFCTR_BR_MISPREDICT   = 0x7,
+       ARMV6MPCORE_PERFCTR_INSTR_EXEC      = 0x8,
+       ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA,
+       ARMV6MPCORE_PERFCTR_DCACHE_RDMISS   = 0xB,
+       ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC,
+       ARMV6MPCORE_PERFCTR_DCACHE_WRMISS   = 0xD,
+       ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE,
+       ARMV6MPCORE_PERFCTR_SW_PC_CHANGE    = 0xF,
+       ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS   = 0x10,
+       ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11,
+       ARMV6MPCORE_PERFCTR_LSU_FULL_STALL  = 0x12,
+       ARMV6MPCORE_PERFCTR_WBUF_DRAINED    = 0x13,
+       ARMV6MPCORE_PERFCTR_CPU_CYCLES      = 0xFF,
+};
+
+/*
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV6MPCORE_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV6MPCORE_PERFCTR_INSTR_EXEC,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
+       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                       [PERF_COUNT_HW_CACHE_OP_MAX]
+                                       [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  =
+                               ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
+                       [C(RESULT_MISS)]    =
+                               ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  =
+                               ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
+                       [C(RESULT_MISS)]    =
+                               ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * The ARM performance counters can count micro DTLB misses,
+                * micro ITLB misses and main TLB misses. There isn't an event
+                * for TLB misses, so use the micro misses here and if users
+                * want the main TLB misses they can use a raw counter.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+static inline unsigned long
+armv6_pmcr_read(void)
+{
+       u32 val;
+       asm volatile("mrc   p15, 0, %0, c15, c12, 0" : "=r"(val));
+       return val;
+}
+
+static inline void
+armv6_pmcr_write(unsigned long val)
+{
+       asm volatile("mcr   p15, 0, %0, c15, c12, 0" : : "r"(val));
+}
+
+#define ARMV6_PMCR_ENABLE              (1 << 0)
+#define ARMV6_PMCR_CTR01_RESET         (1 << 1)
+#define ARMV6_PMCR_CCOUNT_RESET                (1 << 2)
+#define ARMV6_PMCR_CCOUNT_DIV          (1 << 3)
+#define ARMV6_PMCR_COUNT0_IEN          (1 << 4)
+#define ARMV6_PMCR_COUNT1_IEN          (1 << 5)
+#define ARMV6_PMCR_CCOUNT_IEN          (1 << 6)
+#define ARMV6_PMCR_COUNT0_OVERFLOW     (1 << 8)
+#define ARMV6_PMCR_COUNT1_OVERFLOW     (1 << 9)
+#define ARMV6_PMCR_CCOUNT_OVERFLOW     (1 << 10)
+#define ARMV6_PMCR_EVT_COUNT0_SHIFT    20
+#define ARMV6_PMCR_EVT_COUNT0_MASK     (0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
+#define ARMV6_PMCR_EVT_COUNT1_SHIFT    12
+#define ARMV6_PMCR_EVT_COUNT1_MASK     (0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
+
+#define ARMV6_PMCR_OVERFLOWED_MASK \
+       (ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \
+        ARMV6_PMCR_CCOUNT_OVERFLOW)
+
+static inline int
+armv6_pmcr_has_overflowed(unsigned long pmcr)
+{
+       return (pmcr & ARMV6_PMCR_OVERFLOWED_MASK);
+}
+
+static inline int
+armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
+                                 enum armv6_counters counter)
+{
+       int ret = 0;
+
+       if (ARMV6_CYCLE_COUNTER == counter)
+               ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW;
+       else if (ARMV6_COUNTER0 == counter)
+               ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW;
+       else if (ARMV6_COUNTER1 == counter)
+               ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW;
+       else
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+
+       return ret;
+}
+
+static inline u32
+armv6pmu_read_counter(int counter)
+{
+       unsigned long value = 0;
+
+       if (ARMV6_CYCLE_COUNTER == counter)
+               asm volatile("mrc   p15, 0, %0, c15, c12, 1" : "=r"(value));
+       else if (ARMV6_COUNTER0 == counter)
+               asm volatile("mrc   p15, 0, %0, c15, c12, 2" : "=r"(value));
+       else if (ARMV6_COUNTER1 == counter)
+               asm volatile("mrc   p15, 0, %0, c15, c12, 3" : "=r"(value));
+       else
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+
+       return value;
+}
+
+static inline void
+armv6pmu_write_counter(int counter,
+                      u32 value)
+{
+       if (ARMV6_CYCLE_COUNTER == counter)
+               asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
+       else if (ARMV6_COUNTER0 == counter)
+               asm volatile("mcr   p15, 0, %0, c15, c12, 2" : : "r"(value));
+       else if (ARMV6_COUNTER1 == counter)
+               asm volatile("mcr   p15, 0, %0, c15, c12, 3" : : "r"(value));
+       else
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+}
+
+void
+armv6pmu_enable_event(struct hw_perf_event *hwc,
+                     int idx)
+{
+       unsigned long val, mask, evt, flags;
+
+       if (ARMV6_CYCLE_COUNTER == idx) {
+               mask    = 0;
+               evt     = ARMV6_PMCR_CCOUNT_IEN;
+       } else if (ARMV6_COUNTER0 == idx) {
+               mask    = ARMV6_PMCR_EVT_COUNT0_MASK;
+               evt     = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) |
+                         ARMV6_PMCR_COUNT0_IEN;
+       } else if (ARMV6_COUNTER1 == idx) {
+               mask    = ARMV6_PMCR_EVT_COUNT1_MASK;
+               evt     = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) |
+                         ARMV6_PMCR_COUNT1_IEN;
+       } else {
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       /*
+        * Mask out the current event and set the counter to count the event
+        * that we're interested in.
+        */
+       spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~mask;
+       val |= evt;
+       armv6_pmcr_write(val);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static irqreturn_t
+armv6pmu_handle_irq(int irq_num,
+                   void *dev)
+{
+       unsigned long pmcr = armv6_pmcr_read();
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct pt_regs *regs;
+       int idx;
+
+       if (!armv6_pmcr_has_overflowed(pmcr))
+               return IRQ_NONE;
+
+       regs = get_irq_regs();
+
+       /*
+        * The interrupts are cleared by writing the overflow flags back to
+        * the control register. All of the other bits don't have any effect
+        * if they are rewritten, so write the whole value back.
+        */
+       armv6_pmcr_write(pmcr);
+
+       data.addr = 0;
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+               struct hw_perf_event *hwc;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               /*
+                * We have a single interrupt for all counters. Check that
+                * each counter has overflowed before we process it.
+                */
+               if (!armv6_pmcr_counter_has_overflowed(pmcr, idx))
+                       continue;
+
+               hwc = &event->hw;
+               armpmu_event_update(event, hwc, idx);
+               data.period = event->hw.last_period;
+               if (!armpmu_event_set_period(event, hwc, idx))
+                       continue;
+
+               if (perf_event_overflow(event, 0, &data, regs))
+                       armpmu->disable(hwc, idx);
+       }
+
+       /*
+        * Handle the pending perf events.
+        *
+        * Note: this call *must* be run with interrupts enabled. For
+        * platforms that can have the PMU interrupts raised as a PMI, this
+        * will not work.
+        */
+       perf_event_do_pending();
+
+       return IRQ_HANDLED;
+}
+
+static void
+armv6pmu_start(void)
+{
+       unsigned long flags, val;
+
+       spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val |= ARMV6_PMCR_ENABLE;
+       armv6_pmcr_write(val);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+void
+armv6pmu_stop(void)
+{
+       unsigned long flags, val;
+
+       spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~ARMV6_PMCR_ENABLE;
+       armv6_pmcr_write(val);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static inline int
+armv6pmu_event_map(int config)
+{
+       int mapping = armv6_perf_map[config];
+       if (HW_OP_UNSUPPORTED == mapping)
+               mapping = -EOPNOTSUPP;
+       return mapping;
+}
+
+static inline int
+armv6mpcore_pmu_event_map(int config)
+{
+       int mapping = armv6mpcore_perf_map[config];
+       if (HW_OP_UNSUPPORTED == mapping)
+               mapping = -EOPNOTSUPP;
+       return mapping;
+}
+
+static u64
+armv6pmu_raw_event(u64 config)
+{
+       return config & 0xff;
+}
+
+static int
+armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+                      struct hw_perf_event *event)
+{
+       /* Always place a cycle counter into the cycle counter. */
+       if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
+               if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
+                       return -EAGAIN;
+
+               return ARMV6_CYCLE_COUNTER;
+       } else {
+               /*
+                * For anything other than a cycle counter, try and use
+                * counter0 and counter1.
+                */
+               if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) {
+                       return ARMV6_COUNTER1;
+               }
+
+               if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) {
+                       return ARMV6_COUNTER0;
+               }
+
+               /* The counters are all in use. */
+               return -EAGAIN;
+       }
+}
+
+static void
+armv6pmu_disable_event(struct hw_perf_event *hwc,
+                      int idx)
+{
+       unsigned long val, mask, evt, flags;
+
+       if (ARMV6_CYCLE_COUNTER == idx) {
+               mask    = ARMV6_PMCR_CCOUNT_IEN;
+               evt     = 0;
+       } else if (ARMV6_COUNTER0 == idx) {
+               mask    = ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK;
+               evt     = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT;
+       } else if (ARMV6_COUNTER1 == idx) {
+               mask    = ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK;
+               evt     = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT;
+       } else {
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       /*
+        * Mask out the current event and set the counter to count the number
+        * of ETM bus signal assertion cycles. The external reporting should
+        * be disabled and so this should never increment.
+        */
+       spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~mask;
+       val |= evt;
+       armv6_pmcr_write(val);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
+                             int idx)
+{
+       unsigned long val, mask, flags, evt = 0;
+
+       if (ARMV6_CYCLE_COUNTER == idx) {
+               mask    = ARMV6_PMCR_CCOUNT_IEN;
+       } else if (ARMV6_COUNTER0 == idx) {
+               mask    = ARMV6_PMCR_COUNT0_IEN;
+       } else if (ARMV6_COUNTER1 == idx) {
+               mask    = ARMV6_PMCR_COUNT1_IEN;
+       } else {
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       /*
+        * Unlike UP ARMv6, we don't have a way of stopping the counters. We
+        * simply disable the interrupt reporting.
+        */
+       spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~mask;
+       val |= evt;
+       armv6_pmcr_write(val);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static const struct arm_pmu armv6pmu = {
+       .name                   = "v6",
+       .handle_irq             = armv6pmu_handle_irq,
+       .enable                 = armv6pmu_enable_event,
+       .disable                = armv6pmu_disable_event,
+       .event_map              = armv6pmu_event_map,
+       .raw_event              = armv6pmu_raw_event,
+       .read_counter           = armv6pmu_read_counter,
+       .write_counter          = armv6pmu_write_counter,
+       .get_event_idx          = armv6pmu_get_event_idx,
+       .start                  = armv6pmu_start,
+       .stop                   = armv6pmu_stop,
+       .num_events             = 3,
+       .max_period             = (1LLU << 32) - 1,
+};
+
+/*
+ * ARMv6mpcore is almost identical to single core ARMv6 with the exception
+ * that some of the events have different enumerations and that there is no
+ * *hack* to stop the programmable counters. To stop the counters we simply
+ * disable the interrupt reporting and update the event. When unthrottling we
+ * reset the period and enable the interrupt reporting.
+ */
+static const struct arm_pmu armv6mpcore_pmu = {
+       .name                   = "v6mpcore",
+       .handle_irq             = armv6pmu_handle_irq,
+       .enable                 = armv6pmu_enable_event,
+       .disable                = armv6mpcore_pmu_disable_event,
+       .event_map              = armv6mpcore_pmu_event_map,
+       .raw_event              = armv6pmu_raw_event,
+       .read_counter           = armv6pmu_read_counter,
+       .write_counter          = armv6pmu_write_counter,
+       .get_event_idx          = armv6pmu_get_event_idx,
+       .start                  = armv6pmu_start,
+       .stop                   = armv6pmu_stop,
+       .num_events             = 3,
+       .max_period             = (1LLU << 32) - 1,
+};
+
+/*
+ * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
+ *
+ * Copied from ARMv6 code, with the low level code inspired
+ *  by the ARMv7 Oprofile code.
+ *
+ * Cortex-A8 has up to 4 configurable performance counters and
+ *  a single cycle counter.
+ * Cortex-A9 has up to 31 configurable performance counters and
+ *  a single cycle counter.
+ *
+ * All counters can be enabled/disabled and IRQ masked separately. The cycle
+ *  counter and all 4 performance counters together can be reset separately.
+ */
+
+#define ARMV7_PMU_CORTEX_A8_NAME               "ARMv7 Cortex-A8"
+
+#define ARMV7_PMU_CORTEX_A9_NAME               "ARMv7 Cortex-A9"
+
+/* Common ARMv7 event types */
+enum armv7_perf_types {
+       ARMV7_PERFCTR_PMNC_SW_INCR              = 0x00,
+       ARMV7_PERFCTR_IFETCH_MISS               = 0x01,
+       ARMV7_PERFCTR_ITLB_MISS                 = 0x02,
+       ARMV7_PERFCTR_DCACHE_REFILL             = 0x03,
+       ARMV7_PERFCTR_DCACHE_ACCESS             = 0x04,
+       ARMV7_PERFCTR_DTLB_REFILL               = 0x05,
+       ARMV7_PERFCTR_DREAD                     = 0x06,
+       ARMV7_PERFCTR_DWRITE                    = 0x07,
+
+       ARMV7_PERFCTR_EXC_TAKEN                 = 0x09,
+       ARMV7_PERFCTR_EXC_EXECUTED              = 0x0A,
+       ARMV7_PERFCTR_CID_WRITE                 = 0x0B,
+       /* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
+        * It counts:
+        *  - all branch instructions,
+        *  - instructions that explicitly write the PC,
+        *  - exception generating instructions.
+        */
+       ARMV7_PERFCTR_PC_WRITE                  = 0x0C,
+       ARMV7_PERFCTR_PC_IMM_BRANCH             = 0x0D,
+       ARMV7_PERFCTR_UNALIGNED_ACCESS          = 0x0F,
+       ARMV7_PERFCTR_PC_BRANCH_MIS_PRED        = 0x10,
+       ARMV7_PERFCTR_CLOCK_CYCLES              = 0x11,
+
+       ARMV7_PERFCTR_PC_BRANCH_MIS_USED        = 0x12,
+
+       ARMV7_PERFCTR_CPU_CYCLES                = 0xFF
+};
+
+/* ARMv7 Cortex-A8 specific event types */
+enum armv7_a8_perf_types {
+       ARMV7_PERFCTR_INSTR_EXECUTED            = 0x08,
+
+       ARMV7_PERFCTR_PC_PROC_RETURN            = 0x0E,
+
+       ARMV7_PERFCTR_WRITE_BUFFER_FULL         = 0x40,
+       ARMV7_PERFCTR_L2_STORE_MERGED           = 0x41,
+       ARMV7_PERFCTR_L2_STORE_BUFF             = 0x42,
+       ARMV7_PERFCTR_L2_ACCESS                 = 0x43,
+       ARMV7_PERFCTR_L2_CACH_MISS              = 0x44,
+       ARMV7_PERFCTR_AXI_READ_CYCLES           = 0x45,
+       ARMV7_PERFCTR_AXI_WRITE_CYCLES          = 0x46,
+       ARMV7_PERFCTR_MEMORY_REPLAY             = 0x47,
+       ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY   = 0x48,
+       ARMV7_PERFCTR_L1_DATA_MISS              = 0x49,
+       ARMV7_PERFCTR_L1_INST_MISS              = 0x4A,
+       ARMV7_PERFCTR_L1_DATA_COLORING          = 0x4B,
+       ARMV7_PERFCTR_L1_NEON_DATA              = 0x4C,
+       ARMV7_PERFCTR_L1_NEON_CACH_DATA         = 0x4D,
+       ARMV7_PERFCTR_L2_NEON                   = 0x4E,
+       ARMV7_PERFCTR_L2_NEON_HIT               = 0x4F,
+       ARMV7_PERFCTR_L1_INST                   = 0x50,
+       ARMV7_PERFCTR_PC_RETURN_MIS_PRED        = 0x51,
+       ARMV7_PERFCTR_PC_BRANCH_FAILED          = 0x52,
+       ARMV7_PERFCTR_PC_BRANCH_TAKEN           = 0x53,
+       ARMV7_PERFCTR_PC_BRANCH_EXECUTED        = 0x54,
+       ARMV7_PERFCTR_OP_EXECUTED               = 0x55,
+       ARMV7_PERFCTR_CYCLES_INST_STALL         = 0x56,
+       ARMV7_PERFCTR_CYCLES_INST               = 0x57,
+       ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL    = 0x58,
+       ARMV7_PERFCTR_CYCLES_NEON_INST_STALL    = 0x59,
+       ARMV7_PERFCTR_NEON_CYCLES               = 0x5A,
+
+       ARMV7_PERFCTR_PMU0_EVENTS               = 0x70,
+       ARMV7_PERFCTR_PMU1_EVENTS               = 0x71,
+       ARMV7_PERFCTR_PMU_EVENTS                = 0x72,
+};
+
+/* ARMv7 Cortex-A9 specific event types */
+enum armv7_a9_perf_types {
+       ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC     = 0x40,
+       ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC     = 0x41,
+       ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC       = 0x42,
+
+       ARMV7_PERFCTR_COHERENT_LINE_MISS        = 0x50,
+       ARMV7_PERFCTR_COHERENT_LINE_HIT         = 0x51,
+
+       ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES   = 0x60,
+       ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES   = 0x61,
+       ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES = 0x62,
+       ARMV7_PERFCTR_STREX_EXECUTED_PASSED     = 0x63,
+       ARMV7_PERFCTR_STREX_EXECUTED_FAILED     = 0x64,
+       ARMV7_PERFCTR_DATA_EVICTION             = 0x65,
+       ARMV7_PERFCTR_ISSUE_STAGE_NO_INST       = 0x66,
+       ARMV7_PERFCTR_ISSUE_STAGE_EMPTY         = 0x67,
+       ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE  = 0x68,
+
+       ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS = 0x6E,
+
+       ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST   = 0x70,
+       ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST = 0x71,
+       ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST  = 0x72,
+       ARMV7_PERFCTR_FP_EXECUTED_INST          = 0x73,
+       ARMV7_PERFCTR_NEON_EXECUTED_INST        = 0x74,
+
+       ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES = 0x80,
+       ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES  = 0x81,
+       ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES        = 0x82,
+       ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES        = 0x83,
+       ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES  = 0x84,
+       ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES  = 0x85,
+       ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES      = 0x86,
+
+       ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES  = 0x8A,
+       ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES = 0x8B,
+
+       ARMV7_PERFCTR_ISB_INST                  = 0x90,
+       ARMV7_PERFCTR_DSB_INST                  = 0x91,
+       ARMV7_PERFCTR_DMB_INST                  = 0x92,
+       ARMV7_PERFCTR_EXT_INTERRUPTS            = 0x93,
+
+       ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED     = 0xA0,
+       ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED       = 0xA1,
+       ARMV7_PERFCTR_PLE_FIFO_FLUSH            = 0xA2,
+       ARMV7_PERFCTR_PLE_RQST_COMPLETED        = 0xA3,
+       ARMV7_PERFCTR_PLE_FIFO_OVERFLOW         = 0xA4,
+       ARMV7_PERFCTR_PLE_RQST_PROG             = 0xA5
+};
+
+/*
+ * Cortex-A8 HW events mapping
+ *
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV7_PERFCTR_INSTR_EXECUTED,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                         [PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * Only ITLB misses and DTLB refills are supported.
+                * If users want the DTLB refills misses a raw counter
+                * must be used.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+/*
+ * Cortex-A9 HW events mapping
+ */
+static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        =
+                                       ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
+       [PERF_COUNT_HW_CACHE_MISSES]        = ARMV7_PERFCTR_COHERENT_LINE_MISS,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                         [PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * Only ITLB misses and DTLB refills are supported.
+                * If users want the DTLB refills misses a raw counter
+                * must be used.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+/*
+ * Perf Events counters
+ */
+enum armv7_counters {
+       ARMV7_CYCLE_COUNTER             = 1,    /* Cycle counter */
+       ARMV7_COUNTER0                  = 2,    /* First event counter */
+};
+
+/*
+ * The cycle counter is ARMV7_CYCLE_COUNTER.
+ * The first event counter is ARMV7_COUNTER0.
+ * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
+ */
+#define        ARMV7_COUNTER_LAST      (ARMV7_COUNTER0 + armpmu->num_events - 1)
+
+/*
+ * ARMv7 low level PMNC access
+ */
+
+/*
+ * Per-CPU PMNC: config reg
+ */
+#define ARMV7_PMNC_E           (1 << 0) /* Enable all counters */
+#define ARMV7_PMNC_P           (1 << 1) /* Reset all counters */
+#define ARMV7_PMNC_C           (1 << 2) /* Cycle counter reset */
+#define ARMV7_PMNC_D           (1 << 3) /* CCNT counts every 64th cpu cycle */
+#define ARMV7_PMNC_X           (1 << 4) /* Export to ETM */
+#define ARMV7_PMNC_DP          (1 << 5) /* Disable CCNT if non-invasive debug*/
+#define        ARMV7_PMNC_N_SHIFT      11       /* Number of counters supported */
+#define        ARMV7_PMNC_N_MASK       0x1f
+#define        ARMV7_PMNC_MASK         0x3f     /* Mask for writable bits */
+
+/*
+ * Available counters
+ */
+#define ARMV7_CNT0             0       /* First event counter */
+#define ARMV7_CCNT             31      /* Cycle counter */
+
+/* Perf Event to low level counters mapping */
+#define ARMV7_EVENT_CNT_TO_CNTx        (ARMV7_COUNTER0 - ARMV7_CNT0)
+
+/*
+ * CNTENS: counters enable reg
+ */
+#define ARMV7_CNTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_CNTENS_C         (1 << ARMV7_CCNT)
+
+/*
+ * CNTENC: counters disable reg
+ */
+#define ARMV7_CNTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_CNTENC_C         (1 << ARMV7_CCNT)
+
+/*
+ * INTENS: counters overflow interrupt enable reg
+ */
+#define ARMV7_INTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_INTENS_C         (1 << ARMV7_CCNT)
+
+/*
+ * INTENC: counters overflow interrupt disable reg
+ */
+#define ARMV7_INTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_INTENC_C         (1 << ARMV7_CCNT)
+
+/*
+ * EVTSEL: Event selection reg
+ */
+#define        ARMV7_EVTSEL_MASK       0x7f            /* Mask for writable bits */
+
+/*
+ * SELECT: Counter selection reg
+ */
+#define        ARMV7_SELECT_MASK       0x1f            /* Mask for writable bits */
+
+/*
+ * FLAG: counters overflow flag status reg
+ */
+#define ARMV7_FLAG_P(idx)      (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_FLAG_C           (1 << ARMV7_CCNT)
+#define        ARMV7_FLAG_MASK         0xffffffff      /* Mask for writable bits */
+#define        ARMV7_OVERFLOWED_MASK   ARMV7_FLAG_MASK
+
+static inline unsigned long armv7_pmnc_read(void)
+{
+       u32 val;
+       asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
+       return val;
+}
+
+static inline void armv7_pmnc_write(unsigned long val)
+{
+       val &= ARMV7_PMNC_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
+}
+
+static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+{
+       return pmnc & ARMV7_OVERFLOWED_MASK;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
+                                       enum armv7_counters counter)
+{
+       int ret;
+
+       if (counter == ARMV7_CYCLE_COUNTER)
+               ret = pmnc & ARMV7_FLAG_C;
+       else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
+               ret = pmnc & ARMV7_FLAG_P(counter);
+       else
+               pr_err("CPU%u checking wrong counter %d overflow status\n",
+                       smp_processor_id(), counter);
+
+       return ret;
+}
+
+static inline int armv7_pmnc_select_counter(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
+               pr_err("CPU%u selecting wrong PMNC counter"
+                       " %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7pmu_read_counter(int idx)
+{
+       unsigned long value = 0;
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
+       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
+               if (armv7_pmnc_select_counter(idx) == idx)
+                       asm volatile("mrc p15, 0, %0, c9, c13, 2"
+                                    : "=r" (value));
+       } else
+               pr_err("CPU%u reading wrong counter %d\n",
+                       smp_processor_id(), idx);
+
+       return value;
+}
+
+static inline void armv7pmu_write_counter(int idx, u32 value)
+{
+       if (idx == ARMV7_CYCLE_COUNTER)
+               asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
+               if (armv7_pmnc_select_counter(idx) == idx)
+                       asm volatile("mcr p15, 0, %0, c9, c13, 2"
+                                    : : "r" (value));
+       } else
+               pr_err("CPU%u writing wrong counter %d\n",
+                       smp_processor_id(), idx);
+}
+
+static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+{
+       if (armv7_pmnc_select_counter(idx) == idx) {
+               val &= ARMV7_EVTSEL_MASK;
+               asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
+       }
+}
+
+static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u enabling wrong PMNC counter"
+                       " %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_CNTENS_C;
+       else
+               val = ARMV7_CNTENS_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+{
+       u32 val;
+
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u disabling wrong PMNC counter"
+                       " %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_CNTENC_C;
+       else
+               val = ARMV7_CNTENC_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u enabling wrong PMNC counter"
+                       " interrupt enable %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_INTENS_C;
+       else
+               val = ARMV7_INTENS_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u disabling wrong PMNC counter"
+                       " interrupt enable %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_INTENC_C;
+       else
+               val = ARMV7_INTENC_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_getreset_flags(void)
+{
+       u32 val;
+
+       /* Read */
+       asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
+
+       /* Write to clear flags */
+       val &= ARMV7_FLAG_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
+
+       return val;
+}
+
+#ifdef DEBUG
+static void armv7_pmnc_dump_regs(void)
+{
+       u32 val;
+       unsigned int cnt;
+
+       printk(KERN_INFO "PMNC registers dump:\n");
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
+       printk(KERN_INFO "PMNC  =0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
+       printk(KERN_INFO "CNTENS=0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
+       printk(KERN_INFO "INTENS=0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
+       printk(KERN_INFO "FLAGS =0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
+       printk(KERN_INFO "SELECT=0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
+       printk(KERN_INFO "CCNT  =0x%08x\n", val);
+
+       for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
+               armv7_pmnc_select_counter(cnt);
+               asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
+               printk(KERN_INFO "CNT[%d] count =0x%08x\n",
+                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+               asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
+               printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
+                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+       }
+}
+#endif
+
+void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long flags;
+
+       /*
+        * Enable counter and interrupt, and set the counter to count
+        * the event that we're interested in.
+        */
+       spin_lock_irqsave(&pmu_lock, flags);
+
+       /*
+        * Disable counter
+        */
+       armv7_pmnc_disable_counter(idx);
+
+       /*
+        * Set event (if destined for PMNx counters)
+        * We don't need to set the event if it's a cycle count
+        */
+       if (idx != ARMV7_CYCLE_COUNTER)
+               armv7_pmnc_write_evtsel(idx, hwc->config_base);
+
+       /*
+        * Enable interrupt for this counter
+        */
+       armv7_pmnc_enable_intens(idx);
+
+       /*
+        * Enable counter
+        */
+       armv7_pmnc_enable_counter(idx);
+
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long flags;
+
+       /*
+        * Disable counter and interrupt
+        */
+       spin_lock_irqsave(&pmu_lock, flags);
+
+       /*
+        * Disable counter
+        */
+       armv7_pmnc_disable_counter(idx);
+
+       /*
+        * Disable interrupt for this counter
+        */
+       armv7_pmnc_disable_intens(idx);
+
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
+{
+       unsigned long pmnc;
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct pt_regs *regs;
+       int idx;
+
+       /*
+        * Get and reset the IRQ flags
+        */
+       pmnc = armv7_pmnc_getreset_flags();
+
+       /*
+        * Did an overflow occur?
+        */
+       if (!armv7_pmnc_has_overflowed(pmnc))
+               return IRQ_NONE;
+
+       /*
+        * Handle the counter(s) overflow(s)
+        */
+       regs = get_irq_regs();
+
+       data.addr = 0;
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+               struct hw_perf_event *hwc;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               /*
+                * We have a single interrupt for all counters. Check that
+                * each counter has overflowed before we process it.
+                */
+               if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
+                       continue;
+
+               hwc = &event->hw;
+               armpmu_event_update(event, hwc, idx);
+               data.period = event->hw.last_period;
+               if (!armpmu_event_set_period(event, hwc, idx))
+                       continue;
+
+               if (perf_event_overflow(event, 0, &data, regs))
+                       armpmu->disable(hwc, idx);
+       }
+
+       /*
+        * Handle the pending perf events.
+        *
+        * Note: this call *must* be run with interrupts enabled. For
+        * platforms that can have the PMU interrupts raised as a PMI, this
+        * will not work.
+        */
+       perf_event_do_pending();
+
+       return IRQ_HANDLED;
+}
+
+static void armv7pmu_start(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu_lock, flags);
+       /* Enable all counters */
+       armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void armv7pmu_stop(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu_lock, flags);
+       /* Disable all counters */
+       armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static inline int armv7_a8_pmu_event_map(int config)
+{
+       int mapping = armv7_a8_perf_map[config];
+       if (HW_OP_UNSUPPORTED == mapping)
+               mapping = -EOPNOTSUPP;
+       return mapping;
+}
+
+static inline int armv7_a9_pmu_event_map(int config)
+{
+       int mapping = armv7_a9_perf_map[config];
+       if (HW_OP_UNSUPPORTED == mapping)
+               mapping = -EOPNOTSUPP;
+       return mapping;
+}
+
+static u64 armv7pmu_raw_event(u64 config)
+{
+       return config & 0xff;
+}
+
+static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+                                 struct hw_perf_event *event)
+{
+       int idx;
+
+       /* Always place a cycle counter into the cycle counter. */
+       if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
+               if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
+                       return -EAGAIN;
+
+               return ARMV7_CYCLE_COUNTER;
+       } else {
+               /*
+                * For anything other than a cycle counter, try and use
+                * the events counters
+                */
+               for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
+                       if (!test_and_set_bit(idx, cpuc->used_mask))
+                               return idx;
+               }
+
+               /* The counters are all in use. */
+               return -EAGAIN;
+       }
+}
+
+static struct arm_pmu armv7pmu = {
+       .handle_irq             = armv7pmu_handle_irq,
+       .enable                 = armv7pmu_enable_event,
+       .disable                = armv7pmu_disable_event,
+       .raw_event              = armv7pmu_raw_event,
+       .read_counter           = armv7pmu_read_counter,
+       .write_counter          = armv7pmu_write_counter,
+       .get_event_idx          = armv7pmu_get_event_idx,
+       .start                  = armv7pmu_start,
+       .stop                   = armv7pmu_stop,
+       .max_period             = (1LLU << 32) - 1,
+};
+
+static u32 __init armv7_reset_read_pmnc(void)
+{
+       u32 nb_cnt;
+
+       /* Initialize & Reset PMNC: C and P bits */
+       armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
+
+       /* Read the nb of CNTx counters supported from PMNC */
+       nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
+
+       /* Add the CPU cycles counter and return */
+       return nb_cnt + 1;
+}
+
+static int __init
+init_hw_perf_events(void)
+{
+       unsigned long cpuid = read_cpuid_id();
+       unsigned long implementor = (cpuid & 0xFF000000) >> 24;
+       unsigned long part_number = (cpuid & 0xFFF0);
+
+       /* We only support ARM CPUs implemented by ARM at the moment. */
+       if (0x41 == implementor) {
+               switch (part_number) {
+               case 0xB360:    /* ARM1136 */
+               case 0xB560:    /* ARM1156 */
+               case 0xB760:    /* ARM1176 */
+                       armpmu = &armv6pmu;
+                       memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
+                                       sizeof(armv6_perf_cache_map));
+                       perf_max_events = armv6pmu.num_events;
+                       break;
+               case 0xB020:    /* ARM11mpcore */
+                       armpmu = &armv6mpcore_pmu;
+                       memcpy(armpmu_perf_cache_map,
+                              armv6mpcore_perf_cache_map,
+                              sizeof(armv6mpcore_perf_cache_map));
+                       perf_max_events = armv6mpcore_pmu.num_events;
+                       break;
+               case 0xC080:    /* Cortex-A8 */
+                       armv7pmu.name = ARMV7_PMU_CORTEX_A8_NAME;
+                       memcpy(armpmu_perf_cache_map, armv7_a8_perf_cache_map,
+                               sizeof(armv7_a8_perf_cache_map));
+                       armv7pmu.event_map = armv7_a8_pmu_event_map;
+                       armpmu = &armv7pmu;
+
+                       /* Reset PMNC and read the nb of CNTx counters
+                           supported */
+                       armv7pmu.num_events = armv7_reset_read_pmnc();
+                       perf_max_events = armv7pmu.num_events;
+                       break;
+               case 0xC090:    /* Cortex-A9 */
+                       armv7pmu.name = ARMV7_PMU_CORTEX_A9_NAME;
+                       memcpy(armpmu_perf_cache_map, armv7_a9_perf_cache_map,
+                               sizeof(armv7_a9_perf_cache_map));
+                       armv7pmu.event_map = armv7_a9_pmu_event_map;
+                       armpmu = &armv7pmu;
+
+                       /* Reset PMNC and read the nb of CNTx counters
+                           supported */
+                       armv7pmu.num_events = armv7_reset_read_pmnc();
+                       perf_max_events = armv7pmu.num_events;
+                       break;
+               default:
+                       pr_info("no hardware support available\n");
+                       perf_max_events = -1;
+               }
+       }
+
+       if (armpmu)
+               pr_info("enabled with %s PMU driver, %d counters available\n",
+                       armpmu->name, armpmu->num_events);
+
+       return 0;
+}
+arch_initcall(init_hw_perf_events);
+
+/*
+ * Callchain handling code.
+ */
+static inline void
+callchain_store(struct perf_callchain_entry *entry,
+               u64 ip)
+{
+       if (entry->nr < PERF_MAX_STACK_DEPTH)
+               entry->ip[entry->nr++] = ip;
+}
+
+/*
+ * The registers we're interested in are at the end of the variable
+ * length saved register structure. The fp points at the end of this
+ * structure so the address of this struct is:
+ * (struct frame_tail *)(xxx->fp)-1
+ *
+ * This code has been adapted from the ARM OProfile support.
+ */
+struct frame_tail {
+       struct frame_tail   *fp;
+       unsigned long       sp;
+       unsigned long       lr;
+} __attribute__((packed));
+
+/*
+ * Get the return address for a single stackframe and return a pointer to the
+ * next frame tail.
+ */
+static struct frame_tail *
+user_backtrace(struct frame_tail *tail,
+              struct perf_callchain_entry *entry)
+{
+       struct frame_tail buftail;
+
+       /* Also check accessibility of one struct frame_tail beyond */
+       if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
+               return NULL;
+       if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
+               return NULL;
+
+       callchain_store(entry, buftail.lr);
+
+       /*
+        * Frame pointers should strictly progress back up the stack
+        * (towards higher addresses).
+        */
+       if (tail >= buftail.fp)
+               return NULL;
+
+       return buftail.fp - 1;
+}
+
+static void
+perf_callchain_user(struct pt_regs *regs,
+                   struct perf_callchain_entry *entry)
+{
+       struct frame_tail *tail;
+
+       callchain_store(entry, PERF_CONTEXT_USER);
+
+       if (!user_mode(regs))
+               regs = task_pt_regs(current);
+
+       tail = (struct frame_tail *)regs->ARM_fp - 1;
+
+       while (tail && !((unsigned long)tail & 0x3))
+               tail = user_backtrace(tail, entry);
+}
+
+/*
+ * Gets called by walk_stackframe() for every stackframe. This will be called
+ * whist unwinding the stackframe and is like a subroutine return so we use
+ * the PC.
+ */
+static int
+callchain_trace(struct stackframe *fr,
+               void *data)
+{
+       struct perf_callchain_entry *entry = data;
+       callchain_store(entry, fr->pc);
+       return 0;
+}
+
+static void
+perf_callchain_kernel(struct pt_regs *regs,
+                     struct perf_callchain_entry *entry)
+{
+       struct stackframe fr;
+
+       callchain_store(entry, PERF_CONTEXT_KERNEL);
+       fr.fp = regs->ARM_fp;
+       fr.sp = regs->ARM_sp;
+       fr.lr = regs->ARM_lr;
+       fr.pc = regs->ARM_pc;
+       walk_stackframe(&fr, callchain_trace, entry);
+}
+
+static void
+perf_do_callchain(struct pt_regs *regs,
+                 struct perf_callchain_entry *entry)
+{
+       int is_user;
+
+       if (!regs)
+               return;
+
+       is_user = user_mode(regs);
+
+       if (!current || !current->pid)
+               return;
+
+       if (is_user && current->state != TASK_RUNNING)
+               return;
+
+       if (!is_user)
+               perf_callchain_kernel(regs, entry);
+
+       if (current->mm)
+               perf_callchain_user(regs, entry);
+}
+
+static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
+
+struct perf_callchain_entry *
+perf_callchain(struct pt_regs *regs)
+{
+       struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
+
+       entry->nr = 0;
+       perf_do_callchain(regs, entry);
+       return entry;
+}
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
new file mode 100644 (file)
index 0000000..a124312
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  linux/arch/arm/kernel/pmu.c
+ *
+ *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
+ *
+ * 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 <linux/cpumask.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/pmu.h>
+
+/*
+ * Define the IRQs for the system. We could use something like a platform
+ * device but that seems fairly heavyweight for this. Also, the performance
+ * counters can't be removed or hotplugged.
+ *
+ * Ordering is important: init_pmu() will use the ordering to set the affinity
+ * to the corresponding core. e.g. the first interrupt will go to cpu 0, the
+ * second goes to cpu 1 etc.
+ */
+static const int irqs[] = {
+#if defined(CONFIG_ARCH_OMAP2)
+       3,
+#elif defined(CONFIG_ARCH_BCMRING)
+       IRQ_PMUIRQ,
+#elif defined(CONFIG_MACH_REALVIEW_EB)
+       IRQ_EB11MP_PMU_CPU0,
+       IRQ_EB11MP_PMU_CPU1,
+       IRQ_EB11MP_PMU_CPU2,
+       IRQ_EB11MP_PMU_CPU3,
+#elif defined(CONFIG_ARCH_OMAP3)
+       INT_34XX_BENCH_MPU_EMUL,
+#elif defined(CONFIG_ARCH_IOP32X)
+       IRQ_IOP32X_CORE_PMU,
+#elif defined(CONFIG_ARCH_IOP33X)
+       IRQ_IOP33X_CORE_PMU,
+#elif defined(CONFIG_ARCH_PXA)
+       IRQ_PMU,
+#endif
+};
+
+static const struct pmu_irqs pmu_irqs = {
+       .irqs       = irqs,
+       .num_irqs   = ARRAY_SIZE(irqs),
+};
+
+static volatile long pmu_lock;
+
+const struct pmu_irqs *
+reserve_pmu(void)
+{
+       return test_and_set_bit_lock(0, &pmu_lock) ? ERR_PTR(-EBUSY) :
+               &pmu_irqs;
+}
+EXPORT_SYMBOL_GPL(reserve_pmu);
+
+int
+release_pmu(const struct pmu_irqs *irqs)
+{
+       if (WARN_ON(irqs != &pmu_irqs))
+               return -EINVAL;
+       clear_bit_unlock(0, &pmu_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(release_pmu);
+
+static int
+set_irq_affinity(int irq,
+                unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+       int err = irq_set_affinity(irq, cpumask_of(cpu));
+       if (err)
+               pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+                          irq, cpu);
+       return err;
+#else
+       return 0;
+#endif
+}
+
+int
+init_pmu(void)
+{
+       int i, err = 0;
+
+       for (i = 0; i < pmu_irqs.num_irqs; ++i) {
+               err = set_irq_affinity(pmu_irqs.irqs[i], i);
+               if (err)
+                       break;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(init_pmu);
index a2ea385..08f899f 100644 (file)
@@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = {
        .fn             = break_trap,
 };
 
+static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
+{
+       unsigned int instr2;
+       void __user *pc;
+
+       /* Check the second half of the instruction.  */
+       pc = (void __user *)(instruction_pointer(regs) + 2);
+
+       if (processor_mode(regs) == SVC_MODE) {
+               instr2 = *(u16 *) pc;
+       } else {
+               get_user(instr2, (u16 __user *)pc);
+       }
+
+       if (instr2 == 0xa000) {
+               ptrace_break(current, regs);
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+static struct undef_hook thumb2_break_hook = {
+       .instr_mask     = 0xffff,
+       .instr_val      = 0xf7f0,
+       .cpsr_mask      = PSR_T_BIT,
+       .cpsr_val       = PSR_T_BIT,
+       .fn             = thumb2_break_trap,
+};
+
 static int __init ptrace_break_init(void)
 {
        register_undef_hook(&arm_break_hook);
        register_undef_hook(&thumb_break_hook);
+       register_undef_hook(&thumb2_break_hook);
        return 0;
 }
 
@@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
        union vfp_state *vfp = &thread->vfpstate;
        struct user_vfp __user *ufp = data;
 
-       vfp_sync_state(thread);
+       vfp_sync_hwstate(thread);
 
        /* copy the floating point registers */
        if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
@@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
        union vfp_state *vfp = &thread->vfpstate;
        struct user_vfp __user *ufp = data;
 
-       vfp_sync_state(thread);
+       vfp_sync_hwstate(thread);
 
        /* copy the floating point registers */
        if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
@@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
        if (get_user(vfp->hard.fpscr, &ufp->fpscr))
                return -EFAULT;
 
+       vfp_flush_hwstate(thread);
+
        return 0;
 }
 #endif
@@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        int ret;
 
        switch (request) {
-               /*
-                * read word at location "addr" in the child process.
-                */
-               case PTRACE_PEEKTEXT:
-               case PTRACE_PEEKDATA:
-                       ret = generic_ptrace_peekdata(child, addr, data);
-                       break;
-
                case PTRACE_PEEKUSR:
                        ret = ptrace_read_user(child, addr, (unsigned long __user *)data);
                        break;
 
-               /*
-                * write the word at location addr.
-                */
-               case PTRACE_POKETEXT:
-               case PTRACE_POKEDATA:
-                       ret = generic_ptrace_pokedata(child, addr, data);
-                       break;
-
                case PTRACE_POKEUSR:
                        ret = ptrace_write_user(child, addr, data);
                        break;
index 621acad..c91c77b 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/proc_fs.h>
 
 #include <asm/unified.h>
 #include <asm/cpu.h>
@@ -118,7 +119,7 @@ EXPORT_SYMBOL(elf_platform);
 
 static const char *cpu_name;
 static const char *machine_name;
-static char __initdata command_line[COMMAND_LINE_SIZE];
+static char __initdata cmd_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -418,10 +419,11 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
  * Pick out the memory size.  We look for mem=size@start,
  * where start and size are "size[KkMm]"
  */
-static void __init early_mem(char **p)
+static int __init early_mem(char *p)
 {
        static int usermem __initdata = 0;
        unsigned long size, start;
+       char *endp;
 
        /*
         * If the user specifies memory size, we
@@ -434,52 +436,15 @@ static void __init early_mem(char **p)
        }
 
        start = PHYS_OFFSET;
-       size  = memparse(*p, p);
-       if (**p == '@')
-               start = memparse(*p + 1, p);
+       size  = memparse(p, &endp);
+       if (*endp == '@')
+               start = memparse(endp + 1, NULL);
 
        arm_add_memory(start, size);
-}
-__early_param("mem=", early_mem);
 
-/*
- * Initial parsing of the command line.
- */
-static void __init parse_cmdline(char **cmdline_p, char *from)
-{
-       char c = ' ', *to = command_line;
-       int len = 0;
-
-       for (;;) {
-               if (c == ' ') {
-                       extern struct early_params __early_begin, __early_end;
-                       struct early_params *p;
-
-                       for (p = &__early_begin; p < &__early_end; p++) {
-                               int arglen = strlen(p->arg);
-
-                               if (memcmp(from, p->arg, arglen) == 0) {
-                                       if (to != command_line)
-                                               to -= 1;
-                                       from += arglen;
-                                       p->fn(&from);
-
-                                       while (*from != ' ' && *from != '\0')
-                                               from++;
-                                       break;
-                               }
-                       }
-               }
-               c = *from++;
-               if (!c)
-                       break;
-               if (COMMAND_LINE_SIZE <= ++len)
-                       break;
-               *to++ = c;
-       }
-       *to = '\0';
-       *cmdline_p = command_line;
+       return 0;
 }
+early_param("mem", early_mem);
 
 static void __init
 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
@@ -740,9 +705,15 @@ void __init setup_arch(char **cmdline_p)
        init_mm.end_data   = (unsigned long) _edata;
        init_mm.brk        = (unsigned long) _end;
 
-       memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
-       boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
-       parse_cmdline(cmdline_p, from);
+       /* parse_early_param needs a boot_command_line */
+       strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+
+       /* populate cmd_line too for later use, preserving boot_command_line */
+       strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+       *cmdline_p = cmd_line;
+
+       parse_early_param();
+
        paging_init(mdesc);
        request_standard_resources(&meminfo, mdesc);
 
@@ -783,9 +754,21 @@ static int __init topology_init(void)
 
        return 0;
 }
-
 subsys_initcall(topology_init);
 
+#ifdef CONFIG_HAVE_PROC_CPU
+static int __init proc_cpu_init(void)
+{
+       struct proc_dir_entry *res;
+
+       res = proc_mkdir("cpu", NULL);
+       if (!res)
+               return -ENOMEM;
+       return 0;
+}
+fs_initcall(proc_cpu_init);
+#endif
+
 static const char *hwcap_str[] = {
        "swp",
        "half",
index d38cdf2..2875380 100644 (file)
  *
  *  This file contains the ARM-specific time handling details:
  *  reading the RTC at bootup, etc...
- *
- *  1994-07-02  Alan Modra
- *              fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
- *  1998-12-20  Updated NTP code according to technical memorandum Jan '96
- *              "A Kernel Model for Precision Timekeeping" by Dave Mills
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -77,11 +72,6 @@ unsigned long profile_pc(struct pt_regs *regs)
 EXPORT_SYMBOL(profile_pc);
 #endif
 
-/*
- * hook for setting the RTC's idea of the current time.
- */
-int (*set_rtc)(void);
-
 #ifndef CONFIG_GENERIC_TIME
 static unsigned long dummy_gettimeoffset(void)
 {
@@ -89,140 +79,6 @@ static unsigned long dummy_gettimeoffset(void)
 }
 #endif
 
-static unsigned long next_rtc_update;
-
-/*
- * If we have an externally synchronized linux clock, then update
- * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be
- * called as close as possible to 500 ms before the new second
- * starts.
- */
-static inline void do_set_rtc(void)
-{
-       if (!ntp_synced() || set_rtc == NULL)
-               return;
-
-       if (next_rtc_update &&
-           time_before((unsigned long)xtime.tv_sec, next_rtc_update))
-               return;
-
-       if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
-           xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
-               return;
-
-       if (set_rtc())
-               /*
-                * rtc update failed.  Try again in 60s
-                */
-               next_rtc_update = xtime.tv_sec + 60;
-       else
-               next_rtc_update = xtime.tv_sec + 660;
-}
-
-#ifdef CONFIG_LEDS
-
-static void dummy_leds_event(led_event_t evt)
-{
-}
-
-void (*leds_event)(led_event_t) = dummy_leds_event;
-
-struct leds_evt_name {
-       const char      name[8];
-       int             on;
-       int             off;
-};
-
-static const struct leds_evt_name evt_names[] = {
-       { "amber", led_amber_on, led_amber_off },
-       { "blue",  led_blue_on,  led_blue_off  },
-       { "green", led_green_on, led_green_off },
-       { "red",   led_red_on,   led_red_off   },
-};
-
-static ssize_t leds_store(struct sys_device *dev,
-                       struct sysdev_attribute *attr,
-                       const char *buf, size_t size)
-{
-       int ret = -EINVAL, len = strcspn(buf, " ");
-
-       if (len > 0 && buf[len] == '\0')
-               len--;
-
-       if (strncmp(buf, "claim", len) == 0) {
-               leds_event(led_claim);
-               ret = size;
-       } else if (strncmp(buf, "release", len) == 0) {
-               leds_event(led_release);
-               ret = size;
-       } else {
-               int i;
-
-               for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
-                       if (strlen(evt_names[i].name) != len ||
-                           strncmp(buf, evt_names[i].name, len) != 0)
-                               continue;
-                       if (strncmp(buf+len, " on", 3) == 0) {
-                               leds_event(evt_names[i].on);
-                               ret = size;
-                       } else if (strncmp(buf+len, " off", 4) == 0) {
-                               leds_event(evt_names[i].off);
-                               ret = size;
-                       }
-                       break;
-               }
-       }
-       return ret;
-}
-
-static SYSDEV_ATTR(event, 0200, NULL, leds_store);
-
-static int leds_suspend(struct sys_device *dev, pm_message_t state)
-{
-       leds_event(led_stop);
-       return 0;
-}
-
-static int leds_resume(struct sys_device *dev)
-{
-       leds_event(led_start);
-       return 0;
-}
-
-static int leds_shutdown(struct sys_device *dev)
-{
-       leds_event(led_halted);
-       return 0;
-}
-
-static struct sysdev_class leds_sysclass = {
-       .name           = "leds",
-       .shutdown       = leds_shutdown,
-       .suspend        = leds_suspend,
-       .resume         = leds_resume,
-};
-
-static struct sys_device leds_device = {
-       .id             = 0,
-       .cls            = &leds_sysclass,
-};
-
-static int __init leds_init(void)
-{
-       int ret;
-       ret = sysdev_class_register(&leds_sysclass);
-       if (ret == 0)
-               ret = sysdev_register(&leds_device);
-       if (ret == 0)
-               ret = sysdev_create_file(&leds_device, &attr_event);
-       return ret;
-}
-
-device_initcall(leds_init);
-
-EXPORT_SYMBOL(leds_event);
-#endif
-
 #ifdef CONFIG_LEDS_TIMER
 static inline void do_leds(void)
 {
@@ -295,39 +151,6 @@ int do_settimeofday(struct timespec *tv)
 EXPORT_SYMBOL(do_settimeofday);
 #endif /* !CONFIG_GENERIC_TIME */
 
-/**
- * save_time_delta - Save the offset between system time and RTC time
- * @delta: pointer to timespec to store delta
- * @rtc: pointer to timespec for current RTC time
- *
- * Return a delta between the system time and the RTC time, such
- * that system time can be restored later with restore_time_delta()
- */
-void save_time_delta(struct timespec *delta, struct timespec *rtc)
-{
-       set_normalized_timespec(delta,
-                               xtime.tv_sec - rtc->tv_sec,
-                               xtime.tv_nsec - rtc->tv_nsec);
-}
-EXPORT_SYMBOL(save_time_delta);
-
-/**
- * restore_time_delta - Restore the current system time
- * @delta: delta returned by save_time_delta()
- * @rtc: pointer to timespec for current RTC time
- */
-void restore_time_delta(struct timespec *delta, struct timespec *rtc)
-{
-       struct timespec ts;
-
-       set_normalized_timespec(&ts,
-                               delta->tv_sec + rtc->tv_sec,
-                               delta->tv_nsec + rtc->tv_nsec);
-
-       do_settimeofday(&ts);
-}
-EXPORT_SYMBOL(restore_time_delta);
-
 #ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * Kernel system timer support.
@@ -336,7 +159,6 @@ void timer_tick(void)
 {
        profile_tick(CPU_PROFILING);
        do_leds();
-       do_set_rtc();
        write_seqlock(&xtime_lock);
        do_timer(1);
        write_sequnlock(&xtime_lock);
index 3f361a7..1621e53 100644 (file)
  *  'linux/arch/arm/lib/traps.S'.  Mostly a debugging aid, but will probably
  *  kill the offending process.
  */
-#include <linux/module.h>
 #include <linux/signal.h>
-#include <linux/spinlock.h>
 #include <linux/personality.h>
 #include <linux/kallsyms.h>
-#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
 #include <linux/hardirq.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/uaccess.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
 #define S_SMP ""
 #endif
 
-static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
+static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 {
        struct task_struct *tsk = thread->task;
        static int die_counter;
+       int ret;
 
        printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
               str, err, ++die_counter);
        sysfs_printk_last_file();
+
+       /* trap and error numbers are mostly meaningless on ARM */
+       ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
+       if (ret == NOTIFY_STOP)
+               return ret;
+
        print_modules();
        __show_regs(regs);
        printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
@@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
                dump_backtrace(regs, tsk);
                dump_instr(KERN_EMERG, regs);
        }
+
+       return ret;
 }
 
 DEFINE_SPINLOCK(die_lock);
@@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock);
 /*
  * This function is protected against re-entrancy.
  */
-NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
+void die(const char *str, struct pt_regs *regs, int err)
 {
        struct thread_info *thread = current_thread_info();
+       int ret;
 
        oops_enter();
 
        spin_lock_irq(&die_lock);
        console_verbose();
        bust_spinlocks(1);
-       __die(str, err, thread, regs);
+       ret = __die(str, err, thread, regs);
+
+       if (regs && kexec_should_crash(thread->task))
+               crash_kexec(regs);
+
        bust_spinlocks(0);
        add_taint(TAINT_DIE);
        spin_unlock_irq(&die_lock);
@@ -267,11 +283,10 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
 
        if (in_interrupt())
                panic("Fatal exception in interrupt");
-
        if (panic_on_oops)
                panic("Fatal exception");
-
-       do_exit(SIGSEGV);
+       if (ret != NOTIFY_STOP)
+               do_exit(SIGSEGV);
 }
 
 void arm_notify_die(const char *str, struct pt_regs *regs,
index 4957e13..b16c079 100644 (file)
@@ -43,10 +43,6 @@ SECTIONS
 
                INIT_SETUP(16)
 
-               __early_begin = .;
-                       *(.early_param.init)
-               __early_end = .;
-
                INIT_CALLS
                CON_INITCALL
                SECURITY_INITCALL
index 0b6351d..a9cac36 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include "hardware.h"
-               .macro  addruart,rx
+               .macro  addruart, rx, tmp
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
                moveq   \rx, #0x80000000                @ physical
index 0b2ee95..2db43a5 100644 (file)
@@ -89,6 +89,12 @@ config ARCH_AT91CAP9
        select GENERIC_CLOCKEVENTS
        select HAVE_FB_ATMEL
 
+config ARCH_AT572D940HF
+       bool "AT572D940HF"
+       select CPU_ARM926T
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+
 config ARCH_AT91X40
        bool "AT91x40"
 
@@ -390,6 +396,23 @@ endif
 
 # ----------------------------------------------------------
 
+if ARCH_AT572D940HF
+
+comment "AT572D940HF Board Type"
+
+config MACH_AT572D940HFEB
+       bool "AT572D940HF-EK"
+       depends on ARCH_AT572D940HF
+       select HAVE_AT91_DATAFLASH_CARD
+       select HAVE_NAND_ATMEL_BUSWIDTH_16
+       help
+         Select this if you are using Atmel's AT572D940HF-EK evaluation kit.
+         <http://www.atmel.com/products/diopsis/default.asp>
+
+endif
+
+# ----------------------------------------------------------
+
 if ARCH_AT91X40
 
 comment "AT91X40 Board Type"
index 709fbad..027dd57 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devi
 obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o  sam9_smc.o
  obj-$(CONFIG_ARCH_AT91SAM9G45)        += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91CAP9)    += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT572D940HF)  += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91X40)     += at91x40.o at91x40_time.o
 
 # AT91RM9200 board-specific support
@@ -69,6 +70,9 @@ obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o
 # AT91CAP9 board-specific support
 obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
 
+# AT572D940HF board-specific support
+obj-$(CONFIG_MACH_AT572D940HFEB) += board-at572d940hf_ek.o
+
 # AT91X40 board-specific support
 obj-$(CONFIG_MACH_AT91EB01)    += board-eb01.o
 
diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c
new file mode 100644 (file)
index 0000000..a6b9c68
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * arch/arm/mach-at91/at572d940hf.c
+ *
+ * Antonio R. Costa <costa.antonior@gmail.com>
+ * Copyright (C) 2008 Atmel
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * 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
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/at572d940hf.h>
+#include <mach/at91_pmc.h>
+#include <mach/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at572d940hf_io_desc[] __initdata = {
+       {
+               .virtual        = AT91_VA_BASE_SYS,
+               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_IO_VIRT_BASE - AT572D940HF_SRAM_SIZE,
+               .pfn            = __phys_to_pfn(AT572D940HF_SRAM_BASE),
+               .length         = AT572D940HF_SRAM_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+       .name           = "pioA_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_PIOA,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+       .name           = "pioB_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_PIOB,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+       .name           = "pioC_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_PIOC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+       .name           = "macb_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_EMAC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+       .name           = "usart0_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_US0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+       .name           = "usart1_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_US1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+       .name           = "usart2_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_US2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+       .name           = "mci_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_MCI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+       .name           = "udc_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_UDP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi0_clk = {
+       .name           = "twi0_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_TWI0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+       .name           = "spi0_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_SPI0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+       .name           = "spi1_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_SPI1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc0_clk = {
+       .name           = "ssc0_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_SSC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc1_clk = {
+       .name           = "ssc1_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_SSC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc2_clk = {
+       .name           = "ssc2_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_SSC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc0_clk = {
+       .name           = "tc0_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_TC0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+       .name           = "tc1_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_TC1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+       .name           = "tc2_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_TC2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+       .name           = "ohci_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_UHP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ssc3_clk = {
+       .name           = "ssc3_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_SSC3,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi1_clk = {
+       .name           = "twi1_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_TWI1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk can0_clk = {
+       .name           = "can0_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_CAN0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk can1_clk = {
+       .name           = "can1_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_CAN1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mAgicV_clk = {
+       .name           = "mAgicV_clk",
+       .pmc_mask       = 1 << AT572D940HF_ID_MSIRQ0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+
+
+static struct clk *periph_clocks[] __initdata = {
+       &pioA_clk,
+       &pioB_clk,
+       &pioC_clk,
+       &macb_clk,
+       &usart0_clk,
+       &usart1_clk,
+       &usart2_clk,
+       &mmc_clk,
+       &udc_clk,
+       &twi0_clk,
+       &spi0_clk,
+       &spi1_clk,
+       &ssc0_clk,
+       &ssc1_clk,
+       &ssc2_clk,
+       &tc0_clk,
+       &tc1_clk,
+       &tc2_clk,
+       &ohci_clk,
+       &ssc3_clk,
+       &twi1_clk,
+       &can0_clk,
+       &can1_clk,
+       &mAgicV_clk,
+       /* irq0 .. irq2 */
+};
+
+/*
+ * The five programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+       .name           = "pck0",
+       .pmc_mask       = AT91_PMC_PCK0,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 0,
+};
+static struct clk pck1 = {
+       .name           = "pck1",
+       .pmc_mask       = AT91_PMC_PCK1,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 1,
+};
+static struct clk pck2 = {
+       .name           = "pck2",
+       .pmc_mask       = AT91_PMC_PCK2,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 2,
+};
+static struct clk pck3 = {
+       .name           = "pck3",
+       .pmc_mask       = AT91_PMC_PCK3,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 3,
+};
+
+static struct clk mAgicV_mem_clk = {
+       .name           = "mAgicV_mem_clk",
+       .pmc_mask       = AT91_PMC_PCK4,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 4,
+};
+
+/* HClocks */
+static struct clk hck0 = {
+       .name           = "hck0",
+       .pmc_mask       = AT91_PMC_HCK0,
+       .type           = CLK_TYPE_SYSTEM,
+       .id             = 0,
+};
+static struct clk hck1 = {
+       .name           = "hck1",
+       .pmc_mask       = AT91_PMC_HCK1,
+       .type           = CLK_TYPE_SYSTEM,
+       .id             = 1,
+};
+
+static void __init at572d940hf_register_clocks(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+               clk_register(periph_clocks[i]);
+
+       clk_register(&pck0);
+       clk_register(&pck1);
+       clk_register(&pck2);
+       clk_register(&pck3);
+       clk_register(&mAgicV_mem_clk);
+
+       clk_register(&hck0);
+       clk_register(&hck1);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at572d940hf_gpio[] = {
+       {
+               .id             = AT572D940HF_ID_PIOA,
+               .offset         = AT91_PIOA,
+               .clock          = &pioA_clk,
+       }, {
+               .id             = AT572D940HF_ID_PIOB,
+               .offset         = AT91_PIOB,
+               .clock          = &pioB_clk,
+       }, {
+               .id             = AT572D940HF_ID_PIOC,
+               .offset         = AT91_PIOC,
+               .clock          = &pioC_clk,
+       }
+};
+
+static void at572d940hf_reset(void)
+{
+       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ *  AT572D940HF processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at572d940hf_initialize(unsigned long main_clock)
+{
+       /* Map peripherals */
+       iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc));
+
+       at91_arch_reset = at572d940hf_reset;
+       at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1)
+                       | (1 << AT572D940HF_ID_IRQ2);
+
+       /* Init clock subsystem */
+       at91_clock_init(main_clock);
+
+       /* Register the processor-specific clocks */
+       at572d940hf_register_clocks();
+
+       /* Register GPIO subsystem */
+       at91_gpio_init(at572d940hf_gpio, 3);
+}
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at572d940hf_default_irq_priority[NR_AIC_IRQS] __initdata = {
+       7,      /* Advanced Interrupt Controller */
+       7,      /* System Peripherals */
+       0,      /* Parallel IO Controller A */
+       0,      /* Parallel IO Controller B */
+       0,      /* Parallel IO Controller C */
+       3,      /* Ethernet */
+       6,      /* USART 0 */
+       6,      /* USART 1 */
+       6,      /* USART 2 */
+       0,      /* Multimedia Card Interface */
+       4,      /* USB Device Port */
+       0,      /* Two-Wire Interface 0 */
+       6,      /* Serial Peripheral Interface 0 */
+       6,      /* Serial Peripheral Interface 1 */
+       5,      /* Serial Synchronous Controller 0 */
+       5,      /* Serial Synchronous Controller 1 */
+       5,      /* Serial Synchronous Controller 2 */
+       0,      /* Timer Counter 0 */
+       0,      /* Timer Counter 1 */
+       0,      /* Timer Counter 2 */
+       3,      /* USB Host port */
+       3,      /* Serial Synchronous Controller 3 */
+       0,      /* Two-Wire Interface 1 */
+       0,      /* CAN Controller 0 */
+       0,      /* CAN Controller 1 */
+       0,      /* mAgicV HALT line */
+       0,      /* mAgicV SIRQ0 line */
+       0,      /* mAgicV exception line */
+       0,      /* mAgicV end of DMA line */
+       0,      /* Advanced Interrupt Controller */
+       0,      /* Advanced Interrupt Controller */
+       0,      /* Advanced Interrupt Controller */
+};
+
+void __init at572d940hf_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+       if (!priority)
+               priority = at572d940hf_default_irq_priority;
+
+       /* Initialize the AIC interrupt controller */
+       at91_aic_init(priority);
+
+       /* Enable GPIO interrupts */
+       at91_gpio_irq_setup();
+}
+
diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
new file mode 100644 (file)
index 0000000..0fc20a2
--- /dev/null
@@ -0,0 +1,970 @@
+/*
+ * arch/arm/mach-at91/at572d940hf_devices.c
+ *
+ * Copyright (C) 2008 Atmel Antonio R. Costa <costa.antonior@gmail.com>
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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
+ *
+ */
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/at572d940hf.h>
+#include <mach/at572d940hf_matrix.h>
+#include <mach/at91sam9_smc.h>
+
+#include "generic.h"
+#include "sam9_smc.h"
+
+
+/* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+       [0] = {
+               .start  = AT572D940HF_UHP_BASE,
+               .end    = AT572D940HF_UHP_BASE + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT572D940HF_ID_UHP,
+               .end    = AT572D940HF_ID_UHP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at572d940hf_usbh_device = {
+       .name           = "at91_ohci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &ohci_dmamask,
+                               .coherent_dma_mask      = DMA_BIT_MASK(32),
+                               .platform_data          = &usbh_data,
+       },
+       .resource       = usbh_resources,
+       .num_resources  = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+       if (!data)
+               return;
+
+       usbh_data = *data;
+       platform_device_register(&at572d940hf_usbh_device);
+
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+       [0] = {
+               .start  = AT572D940HF_BASE_UDP,
+               .end    = AT572D940HF_BASE_UDP + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT572D940HF_ID_UDP,
+               .end    = AT572D940HF_ID_UDP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at572d940hf_udc_device = {
+       .name           = "at91_udc",
+       .id             = -1,
+       .dev            = {
+                               .platform_data          = &udc_data,
+       },
+       .resource       = udc_resources,
+       .num_resources  = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+       if (!data)
+               return;
+
+       if (data->vbus_pin) {
+               at91_set_gpio_input(data->vbus_pin, 0);
+               at91_set_deglitch(data->vbus_pin, 1);
+       }
+
+       /* Pullup pin is handled internally */
+
+       udc_data = *data;
+       platform_device_register(&at572d940hf_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = DMA_BIT_MASK(32);
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+       [0] = {
+               .start  = AT572D940HF_BASE_EMAC,
+               .end    = AT572D940HF_BASE_EMAC + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT572D940HF_ID_EMAC,
+               .end    = AT572D940HF_ID_EMAC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at572d940hf_eth_device = {
+       .name           = "macb",
+       .id             = -1,
+       .dev            = {
+                       .dma_mask               = &eth_dmamask,
+                       .coherent_dma_mask      = DMA_BIT_MASK(32),
+                       .platform_data          = &eth_data,
+       },
+       .resource       = eth_resources,
+       .num_resources  = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+       if (!data)
+               return;
+
+       if (data->phy_irq_pin) {
+               at91_set_gpio_input(data->phy_irq_pin, 0);
+               at91_set_deglitch(data->phy_irq_pin, 1);
+       }
+
+       /* Only RMII is supported */
+       data->is_rmii = 1;
+
+       /* Pins used for RMII */
+       at91_set_A_periph(AT91_PIN_PA16, 0);    /* ETXCK_EREFCK */
+       at91_set_A_periph(AT91_PIN_PA17, 0);    /* ERXDV */
+       at91_set_A_periph(AT91_PIN_PA18, 0);    /* ERX0 */
+       at91_set_A_periph(AT91_PIN_PA19, 0);    /* ERX1 */
+       at91_set_A_periph(AT91_PIN_PA20, 0);    /* ERXER */
+       at91_set_A_periph(AT91_PIN_PA23, 0);    /* ETXEN */
+       at91_set_A_periph(AT91_PIN_PA21, 0);    /* ETX0 */
+       at91_set_A_periph(AT91_PIN_PA22, 0);    /* ETX1 */
+       at91_set_A_periph(AT91_PIN_PA13, 0);    /* EMDIO */
+       at91_set_A_periph(AT91_PIN_PA14, 0);    /* EMDC */
+
+       eth_data = *data;
+       platform_device_register(&at572d940hf_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = DMA_BIT_MASK(32);
+static struct at91_mmc_data mmc_data;
+
+static struct resource mmc_resources[] = {
+       [0] = {
+               .start  = AT572D940HF_BASE_MCI,
+               .end    = AT572D940HF_BASE_MCI + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT572D940HF_ID_MCI,
+               .end    = AT572D940HF_ID_MCI,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at572d940hf_mmc_device = {
+       .name           = "at91_mci",
+       .id             = -1,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = DMA_BIT_MASK(32),
+                               .platform_data          = &mmc_data,
+       },
+       .resource       = mmc_resources,
+       .num_resources  = ARRAY_SIZE(mmc_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+       if (!data)
+               return;
+
+       /* input/irq */
+       if (data->det_pin) {
+               at91_set_gpio_input(data->det_pin, 1);
+               at91_set_deglitch(data->det_pin, 1);
+       }
+       if (data->wp_pin)
+               at91_set_gpio_input(data->wp_pin, 1);
+       if (data->vcc_pin)
+               at91_set_gpio_output(data->vcc_pin, 0);
+
+       /* CLK */
+       at91_set_A_periph(AT91_PIN_PC22, 0);
+
+       /* CMD */
+       at91_set_A_periph(AT91_PIN_PC23, 1);
+
+       /* DAT0, maybe DAT1..DAT3 */
+       at91_set_A_periph(AT91_PIN_PC24, 1);
+       if (data->wire4) {
+               at91_set_A_periph(AT91_PIN_PC25, 1);
+               at91_set_A_periph(AT91_PIN_PC26, 1);
+               at91_set_A_periph(AT91_PIN_PC27, 1);
+       }
+
+       mmc_data = *data;
+       platform_device_register(&at572d940hf_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
+static struct atmel_nand_data nand_data;
+
+#define NAND_BASE      AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+       {
+               .start  = NAND_BASE,
+               .end    = NAND_BASE + SZ_256M - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device at572d940hf_nand_device = {
+       .name           = "atmel_nand",
+       .id             = -1,
+       .dev            = {
+                               .platform_data  = &nand_data,
+       },
+       .resource       = nand_resources,
+       .num_resources  = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct atmel_nand_data *data)
+{
+       unsigned long csa;
+
+       if (!data)
+               return;
+
+       csa = at91_sys_read(AT91_MATRIX_EBICSA);
+       at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
+
+       /* enable pin */
+       if (data->enable_pin)
+               at91_set_gpio_output(data->enable_pin, 1);
+
+       /* ready/busy pin */
+       if (data->rdy_pin)
+               at91_set_gpio_input(data->rdy_pin, 1);
+
+       /* card detect pin */
+       if (data->det_pin)
+               at91_set_gpio_input(data->det_pin, 1);
+
+       at91_set_A_periph(AT91_PIN_PB28, 0);            /* A[22] */
+       at91_set_B_periph(AT91_PIN_PA28, 0);            /* NANDOE */
+       at91_set_B_periph(AT91_PIN_PA29, 0);            /* NANDWE */
+
+       nand_data = *data;
+       platform_device_register(&at572d940hf_nand_device);
+}
+
+#else
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+/*
+ * Prefer the GPIO code since the TWI controller isn't robust
+ * (gets overruns and underruns under load) and can only issue
+ * repeated STARTs in one scenario (the driver doesn't yet handle them).
+ */
+
+#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
+
+static struct i2c_gpio_platform_data pdata = {
+       .sda_pin                = AT91_PIN_PC7,
+       .sda_is_open_drain      = 1,
+       .scl_pin                = AT91_PIN_PC8,
+       .scl_is_open_drain      = 1,
+       .udelay                 = 2,            /* ~100 kHz */
+};
+
+static struct platform_device at572d940hf_twi_device {
+       .name                   = "i2c-gpio",
+       .id                     = -1,
+       .dev.platform_data      = &pdata,
+};
+
+void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
+{
+       at91_set_GPIO_periph(AT91_PIN_PC7, 1);          /* TWD (SDA) */
+       at91_set_multi_drive(AT91_PIN_PC7, 1);
+
+       at91_set_GPIO_periph(AT91_PIN_PA8, 1);          /* TWCK (SCL) */
+       at91_set_multi_drive(AT91_PIN_PC8, 1);
+
+       i2c_register_board_info(0, devices, nr_devices);
+       platform_device_register(&at572d940hf_twi_device);
+}
+
+#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi0_resources[] = {
+       [0] = {
+               .start  = AT572D940HF_BASE_TWI0,
+               .end    = AT572D940HF_BASE_TWI0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT572D940HF_ID_TWI0,
+               .end    = AT572D940HF_ID_TWI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at572d940hf_twi0_device = {
+       .name           = "at91_i2c",
+       .id             = 0,
+       .resource       = twi0_resources,
+       .num_resources  = ARRAY_SIZE(twi0_resources),
+};
+
+static struct resource twi1_resources[] = {
+       [0] = {
+               .start  = AT572D940HF_BASE_TWI1,
+               .end    = AT572D940HF_BASE_TWI1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT572D940HF_ID_TWI1,
+               .end    = AT572D940HF_ID_TWI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at572d940hf_twi1_device = {
+       .name           = "at91_i2c",
+       .id             = 1,
+       .resource       = twi1_resources,
+       .num_resources  = ARRAY_SIZE(twi1_resources),
+};
+
+void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
+{
+       /* pins used for TWI0 interface */
+       at91_set_A_periph(AT91_PIN_PC7, 0);             /* TWD */