]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge branches 'at91', 'davinci', 'imx', 'iop', 'ixp', 'ks8695', 'misc', 'pxa' and...
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Thu, 12 Jul 2007 20:30:18 +0000 (21:30 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 12 Jul 2007 20:30:18 +0000 (21:30 +0100)
81 files changed:
arch/arm/Kconfig
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-xscale.S
arch/arm/boot/compressed/head.S
arch/arm/common/sharpsl_pm.c
arch/arm/kernel/head-common.S
arch/arm/kernel/head.S
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-davinci/Makefile
arch/arm/mach-davinci/board-evm.c
arch/arm/mach-davinci/clock.c [new file with mode: 0644]
arch/arm/mach-davinci/clock.h [new file with mode: 0644]
arch/arm/mach-davinci/gpio.c [new file with mode: 0644]
arch/arm/mach-davinci/io.c
arch/arm/mach-davinci/mux.c [new file with mode: 0644]
arch/arm/mach-davinci/psc.c
arch/arm/mach-imx/generic.c
arch/arm/mach-imx/time.c
arch/arm/mach-iop13xx/tpmi.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/Makefile
arch/arm/mach-ixp4xx/gateway7001-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/gateway7001-setup.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/gtwx5715-pci.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/wg302v2-pci.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/wg302v2-setup.c [new file with mode: 0644]
arch/arm/mach-ks8695/Makefile
arch/arm/mach-ks8695/gpio.c [new file with mode: 0644]
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/devices.h [new file with mode: 0644]
arch/arm/mach-pxa/dma.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pm.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/time.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-sa1100/pm.c
arch/arm/mach-sa1100/time.c
arch/arm/mm/ioremap.c
drivers/mmc/host/pxamci.h
include/asm-arm/Kbuild
include/asm-arm/arch-at91/at91_dbgu.h
include/asm-arm/arch-at91/at91x40.h [new file with mode: 0644]
include/asm-arm/arch-at91/cpu.h
include/asm-arm/arch-at91/hardware.h
include/asm-arm/arch-at91/timex.h
include/asm-arm/arch-at91/uncompress.h
include/asm-arm/arch-davinci/clock.h [new file with mode: 0644]
include/asm-arm/arch-davinci/gpio.h [new file with mode: 0644]
include/asm-arm/arch-davinci/hardware.h
include/asm-arm/arch-davinci/mux.h [new file with mode: 0644]
include/asm-arm/arch-imx/gpio.h [new file with mode: 0644]
include/asm-arm/arch-imx/imx-regs.h
include/asm-arm/arch-ixp4xx/ixdp425.h
include/asm-arm/arch-ixp4xx/uncompress.h
include/asm-arm/arch-ks8695/gpio.h [new file with mode: 0644]
include/asm-arm/arch-pxa/dma.h
include/asm-arm/arch-pxa/entry-macro.S
include/asm-arm/arch-pxa/hardware.h
include/asm-arm/arch-pxa/irqs.h
include/asm-arm/arch-pxa/pm.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/elf.h
include/asm-arm/hwcap.h [new file with mode: 0644]
include/asm-arm/ptrace.h

index 50d9f3e4e0f1ad315eb9a04e1e3e9aa5299d6fa5..a0fa1ce9ad6cd97d531c0d99129d4b8a64f793dd 100644 (file)
@@ -241,6 +241,9 @@ config ARCH_H720X
 
 config ARCH_IMX
        bool "IMX"
+       select GENERIC_GPIO
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        help
          Support for Motorola's i.MX family of processors (MX1, MXL).
 
@@ -308,6 +311,7 @@ config ARCH_L7200
 
 config ARCH_KS8695
        bool "Micrel/Kendin KS8695"
+       select GENERIC_GPIO
        help
          Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
          System-on-Chip devices.
@@ -384,6 +388,7 @@ config ARCH_DAVINCI
        bool "TI DaVinci"
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select GENERIC_GPIO
        help
          Support for TI's DaVinci platform.
 
index aefee20cbf987abc7db39f5dc7084b0bed127b47..b15f927a5926187f90f0ba50da935c18a4a5061e 100644 (file)
@@ -1 +1,2 @@
 piggy.gz
+font.c
index adddc71316852f5001314faf10678f5fc4e3ef8d..a1f1691b67fe212f01c11a5e20f0f5fc78087fd3 100644 (file)
@@ -6,15 +6,13 @@
 
 HEAD   = head.o
 OBJS   = misc.o
-FONTC  = drivers/video/console/font_acorn_8x8.c
-
-FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+FONTC  = $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS           += ll_char_wr.o $(FONT)
+OBJS           += ll_char_wr.o font.o
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -73,7 +71,7 @@ endif
 
 SEDFLAGS       = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
+targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
                 head.o misc.o $(OBJS)
 EXTRA_CFLAGS  := -fpic
 EXTRA_AFLAGS  :=
@@ -105,7 +103,10 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE
 
 $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 
-CFLAGS_font_acorn_8x8.o := -Dstatic=
+CFLAGS_font.o := -Dstatic=
+
+$(obj)/font.c: $(FONTC)
+       $(call cmd,shipped)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
        @sed "$(SEDFLAGS)" < $< > $@
index 73c5d9e0201c47fd48b6a79194e3cb0413d5147f..236bbe5783123ceaaa3284bd7b1920007fb9f084 100644 (file)
@@ -41,11 +41,6 @@ __XScale_start:
                mov     r7, #MACH_TYPE_COTULLA_IDP
 #endif
 
-#ifdef  CONFIG_MACH_GTWX5715
-               mov     r7, #(MACH_TYPE_GTWX5715 & 0xff)
-               orr     r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
-#endif
-
 #ifdef CONFIG_ARCH_IXP2000
                mov     r1, #-1
                mov     r0, #0xd6000000
index 680ea6ed77b89c746715f0a38c42142f52a0b4b3..d7fb5ee1637e8f25e23edcd69b7acbeca019b539 100644 (file)
@@ -436,6 +436,28 @@ __armv4_mmu_cache_on:
                mcr     p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
                mov     pc, r12
 
+__armv7_mmu_cache_on:
+               mov     r12, lr
+               mrc     p15, 0, r11, c0, c1, 4  @ read ID_MMFR0
+               tst     r11, #0xf               @ VMSA
+               blne    __setup_mmu
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
+               tst     r11, #0xf               @ VMSA
+               mcrne   p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
+               mrc     p15, 0, r0, c1, c0, 0   @ read control reg
+               orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
+               orr     r0, r0, #0x003c         @ write buffer
+               orrne   r0, r0, #1              @ MMU enabled
+               movne   r1, #-1
+               mcrne   p15, 0, r3, c2, c0, 0   @ load page table pointer
+               mcrne   p15, 0, r1, c3, c0, 0   @ load domain access control
+               mcr     p15, 0, r0, c1, c0, 0   @ load control register
+               mrc     p15, 0, r0, c1, c0, 0   @ and read it back
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c5, 4   @ ISB
+               mov     pc, r12
+
 __arm6_mmu_cache_on:
                mov     r12, lr
                bl      __setup_mmu
@@ -622,11 +644,17 @@ proc_types:
                b       __armv4_mmu_cache_flush
 
                .word   0x0007b000              @ ARMv6
-               .word   0x0007f000
+               .word   0x000ff000
                b       __armv4_mmu_cache_on
                b       __armv4_mmu_cache_off
                b       __armv6_mmu_cache_flush
 
+               .word   0x000f0000              @ new CPU Id
+               .word   0x000f0000
+               b       __armv7_mmu_cache_on
+               b       __armv7_mmu_cache_off
+               b       __armv7_mmu_cache_flush
+
                .word   0                       @ unrecognised type
                .word   0
                mov     pc, lr
@@ -674,6 +702,16 @@ __armv4_mmu_cache_off:
                mcr     p15, 0, r0, c8, c7      @ invalidate whole TLB v4
                mov     pc, lr
 
+__armv7_mmu_cache_off:
+               mrc     p15, 0, r0, c1, c0
+               bic     r0, r0, #0x000d
+               mcr     p15, 0, r0, c1, c0      @ turn MMU and cache off
+               mov     r12, lr
+               bl      __armv7_mmu_cache_flush
+               mov     r0, #0
+               mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB
+               mov     pc, r12
+
 __arm6_mmu_cache_off:
                mov     r0, #0x00000030         @ ARM6 control reg.
                b       __armv3_mmu_cache_off
@@ -730,6 +768,59 @@ __armv6_mmu_cache_flush:
                mcr     p15, 0, r1, c7, c10, 4  @ drain WB
                mov     pc, lr
 
+__armv7_mmu_cache_flush:
+               mrc     p15, 0, r10, c0, c1, 5  @ read ID_MMFR1
+               tst     r10, #0xf << 16         @ hierarchical cache (ARMv7)
+               beq     hierarchical
+               mov     r10, #0
+               mcr     p15, 0, r10, c7, c14, 0 @ clean+invalidate D
+               b       iflush
+hierarchical:
+               stmfd   sp!, {r0-r5, r7, r9-r11}
+               mrc     p15, 1, r0, c0, c0, 1   @ read clidr
+               ands    r3, r0, #0x7000000      @ extract loc from clidr
+               mov     r3, r3, lsr #23         @ left align loc bit field
+               beq     finished                @ if loc is 0, then no need to clean
+               mov     r10, #0                 @ start clean at cache level 0
+loop1:
+               add     r2, r10, r10, lsr #1    @ work out 3x current cache level
+               mov     r1, r0, lsr r2          @ extract cache type bits from clidr
+               and     r1, r1, #7              @ mask of the bits for current cache only
+               cmp     r1, #2                  @ see what cache we have at this level
+               blt     skip                    @ skip if no cache, or just i-cache
+               mcr     p15, 2, r10, c0, c0, 0  @ select current cache level in cssr
+               mcr     p15, 0, r10, c7, c5, 4  @ isb to sych the new cssr&csidr
+               mrc     p15, 1, r1, c0, c0, 0   @ read the new csidr
+               and     r2, r1, #7              @ extract the length of the cache lines
+               add     r2, r2, #4              @ add 4 (line length offset)
+               ldr     r4, =0x3ff
+               ands    r4, r4, r1, lsr #3      @ find maximum number on the way size
+               .word   0xe16f5f14              @ clz r5, r4 - find bit position of way size increment
+               ldr     r7, =0x7fff
+               ands    r7, r7, r1, lsr #13     @ extract max number of the index size
+loop2:
+               mov     r9, r4                  @ create working copy of max way size
+loop3:
+               orr     r11, r10, r9, lsl r5    @ factor way and cache number into r11
+               orr     r11, r11, r7, lsl r2    @ factor index number into r11
+               mcr     p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+               subs    r9, r9, #1              @ decrement the way
+               bge     loop3
+               subs    r7, r7, #1              @ decrement the index
+               bge     loop2
+skip:
+               add     r10, r10, #2            @ increment cache number
+               cmp     r3, r10
+               bgt     loop1
+finished:
+               mov     r10, #0                 @ swith back to cache level 0
+               mcr     p15, 2, r10, c0, c0, 0  @ select current cache level in cssr
+               ldmfd   sp!, {r0-r5, r7, r9-r11}
+iflush:
+               mcr     p15, 0, r10, c7, c5, 0  @ invalidate I+BTB
+               mcr     p15, 0, r10, c7, c10, 4 @ drain WB
+               mov     pc, lr
+
 __armv4_mmu_cache_flush:
                mov     r2, #64*1024            @ default: 32K dcache size (*2)
                mov     r11, #32                @ default: 32 byte line size
index 3bf3a927ae22fbb4d09586ce0d55f88bb5f5dcd9..111a7fa5debee4ace5a39f1aa5c50b2ab3927683 100644 (file)
@@ -766,9 +766,7 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info)
 }
 
 static struct pm_ops sharpsl_pm_ops = {
-       .prepare        = pxa_pm_prepare,
        .enter          = corgi_pxa_pm_enter,
-       .finish         = pxa_pm_finish,
        .valid          = pm_valid_only_mem,
 };
 
index a52da0ddb43d01b26821c4e6c98f59bbe92d4f84..024a9cf469b47d6e841da0147e3c02355268ca81 100644 (file)
@@ -20,7 +20,8 @@ __switch_data:
        .long   _end                            @ r7
        .long   processor_id                    @ r4
        .long   __machine_arch_type             @ r5
-       .long   cr_alignment                    @ r6
+       .long   __atags_pointer                 @ r6
+       .long   cr_alignment                    @ r7
        .long   init_thread_union + THREAD_START_SP @ sp
 
 /*
@@ -29,6 +30,7 @@ __switch_data:
  *
  *  r0  = cp#15 control register
  *  r1  = machine ID
+ *  r2  = atags pointer
  *  r9  = processor ID
  */
        .type   __mmap_switched, %function
@@ -47,11 +49,12 @@ __mmap_switched:
        strcc   fp, [r6],#4
        bcc     1b
 
-       ldmia   r3, {r4, r5, r6, sp}
+       ldmia   r3, {r4, r5, r6, r7, sp}
        str     r9, [r4]                        @ Save processor ID
        str     r1, [r5]                        @ Save machine type
+       str     r2, [r6]                        @ Save atags pointer
        bic     r4, r0, #CR_A                   @ Clear 'A' bit
-       stmia   r6, {r0, r4}                    @ Save control register values
+       stmia   r7, {r0, r4}                    @ Save control register values
        b       start_kernel
 
 /*
@@ -215,3 +218,34 @@ ENTRY(lookup_machine_type)
        bl      __lookup_machine_type
        mov     r0, r5
        ldmfd   sp!, {r4 - r6, pc}
+
+/* Determine validity of the r2 atags pointer.  The heuristic requires
+ * that the pointer be aligned, in the first 16k of physical RAM and
+ * that the ATAG_CORE marker is first and present.  Future revisions
+ * of this function may be more lenient with the physical address and
+ * may also be able to move the ATAGS block if necessary.
+ *
+ * r8  = machinfo
+ *
+ * Returns:
+ *  r2 either valid atags pointer, or zero
+ *  r5, r6 corrupted
+ */
+
+       .type   __vet_atags, %function
+__vet_atags:
+       tst     r2, #0x3                        @ aligned?
+       bne     1f
+
+       ldr     r5, [r2, #0]                    @ is first tag ATAG_CORE?
+       subs    r5, r5, #ATAG_CORE_SIZE
+       bne     1f
+       ldr     r5, [r2, #4]
+       ldr     r6, =ATAG_CORE
+       cmp     r5, r6
+       bne     1f
+
+       mov     pc, lr                          @ atag pointer is ok
+
+1:     mov     r2, #0
+       mov     pc, lr
index 41f98b4ba2ee256d5998a514dd20bcf250bad577..7898cbc9861a9d484d655079c66b3f1e76dccd0b 100644 (file)
 #define KERNEL_RAM_VADDR       (PAGE_OFFSET + TEXT_OFFSET)
 #define KERNEL_RAM_PADDR       (PHYS_OFFSET + TEXT_OFFSET)
 
+#define ATAG_CORE 0x54410001
+#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
+
+
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -61,7 +65,7 @@
  *
  * This is normally called from the decompressor code.  The requirements
  * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
- * r1 = machine nr.
+ * r1 = machine nr, r2 = atags pointer.
  *
  * This code is mostly position independent, so if you link the kernel at
  * 0xc0008000, you call this at __pa(0xc0008000).
@@ -85,6 +89,7 @@ ENTRY(stext)
        bl      __lookup_machine_type           @ r5=machinfo
        movs    r8, r5                          @ invalid machine (r5=0)?
        beq     __error_a                       @ yes, error 'a'
+       bl      __vet_atags
        bl      __create_page_tables
 
        /*
index 842361777d4e63782a96535c6c50cfbf3faedd19..93b7f8e22dcc1b3b69aa424c60d0a91bed19f772 100644 (file)
@@ -44,6 +44,10 @@ static const char *processor_modes[] = {
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
+static const char *isa_modes[] = {
+  "ARM" , "Thumb" , "Jazelle", "ThumbEE"
+};
+
 extern void setup_mm_for_reboot(char mode);
 
 static volatile int hlt_counter;
@@ -230,11 +234,11 @@ void __show_regs(struct pt_regs *regs)
        buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
        buf[4] = '\0';
 
-       printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s%s  Segment %s\n",
+       printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
                buf, interrupts_enabled(regs) ? "n" : "ff",
                fast_interrupts_enabled(regs) ? "n" : "ff",
                processor_modes[processor_mode(regs)],
-               thumb_mode(regs) ? " (T)" : "",
+               isa_modes[isa_mode(regs)],
                get_fs() == get_ds() ? "kernel" : "user");
 #ifdef CONFIG_CPU_CP15
        {
index 650eac1bc0a6f2b5d3e10d382012c8e4850f56f0..5be2e987b8435b047bf168128364e3736eda30f4 100644 (file)
@@ -63,6 +63,8 @@ unsigned int processor_id;
 unsigned int __machine_arch_type;
 EXPORT_SYMBOL(__machine_arch_type);
 
+unsigned int __atags_pointer __initdata;
+
 unsigned int system_rev;
 EXPORT_SYMBOL(system_rev);
 
@@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p)
        if (mdesc->soft_reboot)
                reboot_setup("s");
 
-       if (mdesc->boot_params)
+       if (__atags_pointer)
+               tags = phys_to_virt(__atags_pointer);
+       else if (mdesc->boot_params)
                tags = phys_to_virt(mdesc->boot_params);
 
        /*
index 26ca8ab3f62a7dc3df8f620178cf2695614ce44e..42e172cb0f49bfe2d0e40d9382d574234f712f3e 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/dm9000.h>
+#include <linux/fb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -271,6 +276,127 @@ static struct spi_board_info ek_spi_devices[] = {
 };
 
 
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+       {
+               .name           = "TX09D50VM1CCA @ 60",
+               .refresh        = 60,
+               .xres           = 240,          .yres           = 320,
+               .pixclock       = KHZ2PICOS(4965),
+
+               .left_margin    = 1,            .right_margin   = 33,
+               .upper_margin   = 1,            .lower_margin   = 0,
+               .hsync_len      = 5,            .vsync_len      = 1,
+
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+       .manufacturer   = "HIT",
+       .monitor        = "TX09D50VM1CCA",
+
+       .modedb         = at91_tft_vga_modes,
+       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
+       .hfmin          = 15000,
+       .hfmax          = 64000,
+       .vfmin          = 50,
+       .vfmax          = 150,
+};
+
+#define AT91SAM9261_DEFAULT_LCDCON2    (ATMEL_LCDC_MEMOR_LITTLE \
+                                       | ATMEL_LCDC_DISTYPE_TFT    \
+                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+       if (on)
+               at91_set_gpio_value(AT91_PIN_PA12, 0);  /* power up */
+       else
+               at91_set_gpio_value(AT91_PIN_PA12, 1);  /* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+       .default_bpp                    = 16,
+       .default_dmacon                 = ATMEL_LCDC_DMAEN,
+       .default_lcdcon2                = AT91SAM9261_DEFAULT_LCDCON2,
+       .default_monspecs               = &at91fb_default_monspecs,
+       .atmel_lcdfb_power_control      = at91_lcdc_power_control,
+       .guard_time                     = 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+       {
+               .gpio           = AT91_PIN_PA27,
+               .keycode        = BTN_0,
+               .desc           = "Button 0",
+               .active_low     = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA26,
+               .keycode        = BTN_1,
+               .desc           = "Button 1",
+               .active_low     = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA25,
+               .keycode        = BTN_2,
+               .desc           = "Button 2",
+               .active_low     = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA24,
+               .keycode        = BTN_3,
+               .desc           = "Button 3",
+               .active_low     = 1,
+       }
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+       .buttons        = ek_buttons,
+       .nbuttons       = ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .num_resources  = 0,
+       .dev            = {
+               .platform_data  = &ek_button_data,
+       }
+};
+
+static void __init ek_add_device_buttons(void)
+{
+       at91_set_gpio_input(AT91_PIN_PB27, 0);  /* btn0 */
+       at91_set_deglitch(AT91_PIN_PB27, 1);
+       at91_set_gpio_input(AT91_PIN_PB26, 0);  /* btn1 */
+       at91_set_deglitch(AT91_PIN_PB26, 1);
+       at91_set_gpio_input(AT91_PIN_PB25, 0);  /* btn2 */
+       at91_set_deglitch(AT91_PIN_PB25, 1);
+       at91_set_gpio_input(AT91_PIN_PB24, 0);  /* btn3 */
+       at91_set_deglitch(AT91_PIN_PB24, 1);
+
+       platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
 static void __init ek_board_init(void)
 {
        /* Serial */
@@ -296,6 +422,10 @@ static void __init ek_board_init(void)
        /* MMC */
        at91_add_device_mmc(0, &ek_mmc_data);
 #endif
+       /* LCD Controller */
+       at91_add_device_lcdc(&ek_lcdc_data);
+       /* Push Buttons */
+       ek_add_device_buttons();
 }
 
 MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
index c164c8e58ae6a037cdfbbf4b9b5a9842b9b094e2..2a1cc73390b79cd88943d7718c3fd3454d3c65fa 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/fb.h>
+
+#include <video/atmel_lcdc.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -201,6 +204,65 @@ static struct at91_nand_data __initdata ek_nand_data = {
 };
 
 
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+       {
+               .name           = "TX09D50VM1CCA @ 60",
+               .refresh        = 60,
+               .xres           = 240,          .yres           = 320,
+               .pixclock       = KHZ2PICOS(4965),
+
+               .left_margin    = 1,            .right_margin   = 33,
+               .upper_margin   = 1,            .lower_margin   = 0,
+               .hsync_len      = 5,            .vsync_len      = 1,
+
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+       .manufacturer   = "HIT",
+       .monitor        = "TX09D70VM1CCA",
+
+       .modedb         = at91_tft_vga_modes,
+       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
+       .hfmin          = 15000,
+       .hfmax          = 64000,
+       .vfmin          = 50,
+       .vfmax          = 150,
+};
+
+#define AT91SAM9263_DEFAULT_LCDCON2    (ATMEL_LCDC_MEMOR_LITTLE \
+                                       | ATMEL_LCDC_DISTYPE_TFT    \
+                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+       if (on)
+               at91_set_gpio_value(AT91_PIN_PD12, 0);  /* power up */
+       else
+               at91_set_gpio_value(AT91_PIN_PD12, 1);  /* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+       .default_bpp                    = 16,
+       .default_dmacon                 = ATMEL_LCDC_DMAEN,
+       .default_lcdcon2                = AT91SAM9263_DEFAULT_LCDCON2,
+       .default_monspecs               = &at91fb_default_monspecs,
+       .atmel_lcdfb_power_control      = at91_lcdc_power_control,
+       .guard_time                     = 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
 /*
  * AC97
  */
@@ -230,6 +292,8 @@ static void __init ek_board_init(void)
        at91_add_device_nand(&ek_nand_data);
        /* I2C */
        at91_add_device_i2c();
+       /* LCD Controller */
+       at91_add_device_lcdc(&ek_lcdc_data);
        /* AC97 */
        at91_add_device_ac97(&ek_ac97_data);
 }
index a8f88cd299056ae1b52a673b2dd1b69b11de5ca0..99ac2e55774dcdf1c9b316ec9972a5d267765f89 100644 (file)
@@ -4,7 +4,8 @@
 #
 
 # Common objects
-obj-y                  := time.o irq.o serial.o io.o id.o psc.o
+obj-y                  := time.o irq.o clock.o serial.o io.o id.o psc.o \
+                          gpio.o mux.o
 
 # Board specific
 obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
index 633c12e43044528084b2275daf69143a1a0967b5..9e4024c4965f09a0ff24f71dc81df925bb93ed37 100644 (file)
@@ -32,6 +32,7 @@
 void __init davinci_psc_init(void);
 void __init davinci_irq_init(void);
 void __init davinci_map_common_io(void);
+void __init davinci_init_common_hw(void);
 
 /* NOR Flash base address set to CS0 by default */
 #define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@ static __init void davinci_evm_init(void)
 
 static __init void davinci_evm_irq_init(void)
 {
+       davinci_init_common_hw();
        davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644 (file)
index 0000000..139ceaa
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * TI DaVinci clock config file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/psc.h>
+#include "clock.h"
+
+/* PLL/Reset register offsets */
+#define PLLM           0x110
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
+
+static unsigned int commonrate;
+static unsigned int armrate;
+static unsigned int fixedrate = 27000000;      /* 27 MHZ */
+
+extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
+
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *p, *clk = ERR_PTR(-ENOENT);
+       int idno;
+
+       if (dev == NULL || dev->bus != &platform_bus_type)
+               idno = -1;
+       else
+               idno = to_platform_device(dev)->id;
+
+       mutex_lock(&clocks_mutex);
+
+       list_for_each_entry(p, &clocks, node) {
+               if (p->id == idno &&
+                   strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       goto found;
+               }
+       }
+
+       list_for_each_entry(p, &clocks, node) {
+               if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+
+found:
+       mutex_unlock(&clocks_mutex);
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       if (clk && !IS_ERR(clk))
+               module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+static int __clk_enable(struct clk *clk)
+{
+       if (clk->flags & ALWAYS_ENABLED)
+               return 0;
+
+       davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
+       return 0;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+       if (clk->usecount)
+               return;
+
+       davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+}
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       if (clk->usecount++ == 0) {
+               spin_lock_irqsave(&clockfw_lock, flags);
+               ret = __clk_enable(clk);
+               spin_unlock_irqrestore(&clockfw_lock, flags);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (clk == NULL || IS_ERR(clk))
+               return;
+
+       if (clk->usecount > 0 && !(--clk->usecount)) {
+               spin_lock_irqsave(&clockfw_lock, flags);
+               __clk_disable(clk);
+               spin_unlock_irqrestore(&clockfw_lock, flags);
+       }
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       /* changing the clk rate is not supported */
+       return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       mutex_lock(&clocks_mutex);
+       list_add(&clk->node, &clocks);
+       mutex_unlock(&clocks_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+       if (clk == NULL || IS_ERR(clk))
+               return;
+
+       mutex_lock(&clocks_mutex);
+       list_del(&clk->node);
+       mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static struct clk davinci_clks[] = {
+       {
+               .name = "ARMCLK",
+               .rate = &armrate,
+               .lpsc = -1,
+               .flags = ALWAYS_ENABLED,
+       },
+       {
+               .name = "UART",
+               .rate = &fixedrate,
+               .lpsc = DAVINCI_LPSC_UART0,
+       },
+       {
+               .name = "EMACCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+       },
+       {
+               .name = "I2CCLK",
+               .rate = &fixedrate,
+               .lpsc = DAVINCI_LPSC_I2C,
+       },
+       {
+               .name = "IDECLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_ATA,
+       },
+       {
+               .name = "McBSPCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_McBSP,
+       },
+       {
+               .name = "MMCSDCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_MMC_SD,
+       },
+       {
+               .name = "SPICLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_SPI,
+       },
+       {
+               .name = "gpio",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_GPIO,
+       },
+       {
+               .name = "AEMIFCLK",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_AEMIF,
+               .usecount = 1,
+       }
+};
+
+int __init davinci_clk_init(void)
+{
+       struct clk *clkp;
+       int count = 0;
+       u32 pll_mult;
+
+       pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
+       commonrate = ((pll_mult + 1) * 27000000) / 6;
+       armrate = ((pll_mult + 1) * 27000000) / 2;
+
+       for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
+            count++, clkp++) {
+               clk_register(clkp);
+
+               /* Turn on clocks that have been enabled in the
+                * table above */
+               if (clkp->usecount)
+                       clk_enable(clkp);
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return NULL;
+}
+
+static void davinci_ck_stop(struct seq_file *m, void *v)
+{
+}
+
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+       struct clk *cp;
+
+       list_for_each_entry(cp, &clocks, node)
+               seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+
+       return 0;
+}
+
+static struct seq_operations davinci_ck_op = {
+       .start  = davinci_ck_start,
+       .next   = davinci_ck_next,
+       .stop   = davinci_ck_stop,
+       .show   = davinci_ck_show
+};
+
+static int davinci_ck_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &davinci_ck_op);
+}
+
+static struct file_operations proc_davinci_ck_operations = {
+       .open           = davinci_ck_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init davinci_ck_proc_init(void)
+{
+       struct proc_dir_entry *entry;
+
+       entry = create_proc_entry("davinci_clocks", 0, NULL);
+       if (entry)
+               entry->proc_fops = &proc_davinci_ck_operations;
+       return 0;
+
+}
+__initcall(davinci_ck_proc_init);
+#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644 (file)
index 0000000..ed47079
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * TI DaVinci clock definitions
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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 __ARCH_ARM_DAVINCI_CLOCK_H
+#define __ARCH_ARM_DAVINCI_CLOCK_H
+
+struct clk {
+       struct list_head        node;
+       struct module           *owner;
+       const char              *name;
+       unsigned int            *rate;
+       int                     id;
+       __s8                    usecount;
+       __u8                    flags;
+       __u8                    lpsc;
+};
+
+/* Clock flags */
+#define RATE_CKCTL             1
+#define RATE_FIXED             2
+#define RATE_PROPAGATES                4
+#define VIRTUAL_CLOCK          8
+#define ALWAYS_ENABLED         16
+#define ENABLE_REG_32BIT       32
+
+#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644 (file)
index 0000000..9c67886
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
+
+int gpio_request(unsigned gpio, const char *tag)
+{
+       if (gpio >= DAVINCI_N_GPIO)
+               return -EINVAL;
+
+       if (test_and_set_bit(gpio, gpio_in_use))
+               return -EBUSY;
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+       if (gpio >= DAVINCI_N_GPIO)
+               return;
+
+       clear_bit(gpio, gpio_in_use);
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* create a non-inlined version */
+static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
+{
+       return __gpio_to_controller(gpio);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+void __gpio_set(unsigned gpio, int value)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+       __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
+}
+EXPORT_SYMBOL(__gpio_set);
+
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+int __gpio_get(unsigned gpio)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+       return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+EXPORT_SYMBOL(__gpio_get);
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * board setup code *MUST* set PINMUX0 and PINMUX1 as
+ * needed, and enable the GPIO clock.
+ */
+
+int gpio_direction_input(unsigned gpio)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       u32 temp;
+       u32 mask;
+
+       if (!g)
+               return -EINVAL;
+
+       spin_lock(&gpio_lock);
+       mask = __gpio_mask(gpio);
+       temp = __raw_readl(&g->dir);
+       temp |= mask;
+       __raw_writel(temp, &g->dir);
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       struct gpio_controller *__iomem g = gpio2controller(gpio);
+       u32 temp;
+       u32 mask;
+
+       if (!g)
+               return -EINVAL;
+
+       spin_lock(&gpio_lock);
+       mask = __gpio_mask(gpio);
+       temp = __raw_readl(&g->dir);
+       temp &= ~mask;
+       __raw_writel(mask, value ? &g->set_data : &g->clr_data);
+       __raw_writel(temp, &g->dir);
+       spin_unlock(&gpio_lock);
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * We expect irqs will normally be set up as input pins, but they can also be
+ * used as output pins ... which is convenient for testing.
+ *
+ * NOTE:  GPIO0..GPIO7 also have direct INTC hookups, which work in addition
+ * to their GPIOBNK0 irq (but with a bit less overhead).  But we don't have
+ * a good way to hook those up ...
+ *
+ * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+static void gpio_irq_disable(unsigned irq)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+       __raw_writel(mask, &g->clr_falling);
+       __raw_writel(mask, &g->clr_rising);
+}
+
+static void gpio_irq_enable(unsigned irq)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+       if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+               __raw_writel(mask, &g->set_falling);
+       if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+               __raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(unsigned irq, unsigned trigger)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+       if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+               return -EINVAL;
+
+       irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+       irq_desc[irq].status |= trigger;
+
+       __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+                    ? &g->set_falling : &g->clr_falling);
+       __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+                    ? &g->set_rising : &g->clr_rising);
+       return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+       .name           = "GPIO",
+       .enable         = gpio_irq_enable,
+       .disable        = gpio_irq_disable,
+       .set_type       = gpio_irq_type,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+       u32 mask = 0xffff;
+
+       /* we only care about one bank */
+       if (irq & 1)
+               mask <<= 16;
+
+       /* temporarily mask (level sensitive) parent IRQ */
+       desc->chip->ack(irq);
+       while (1) {
+               u32             status;
+               struct irq_desc *gpio;
+               int             n;
+               int             res;
+
+               /* ack any irqs */
+               status = __raw_readl(&g->intstat) & mask;
+               if (!status)
+                       break;
+               __raw_writel(status, &g->intstat);
+               if (irq & 1)
+                       status >>= 16;
+
+               /* now demux them to the right lowlevel handler */
+               n = (int)get_irq_data(irq);
+               gpio = &irq_desc[n];
+               while (status) {
+                       res = ffs(status);
+                       n += res;
+                       gpio += res;
+                       desc_handle_irq(n - 1, gpio - 1);
+                       status >>= res;
+               }
+       }
+       desc->chip->unmask(irq);
+       /* now it may re-trigger */
+}
+
+/*
+ * NOTE:  for suspend/resume, probably best to make a sysdev (and class)
+ * with its suspend/resume calls hooking into the results of the set_wake()
+ * calls ... so if no gpios are wakeup events the clock can be disabled,
+ * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
+ * can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+       unsigned        gpio, irq, bank;
+       struct clk      *clk;
+
+       clk = clk_get(NULL, "gpio");
+       if (IS_ERR(clk)) {
+               printk(KERN_ERR "Error %ld getting gpio clock?\n",
+                      PTR_ERR(clk));
+               return 0;
+       }
+
+       clk_enable(clk);
+
+       for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
+            gpio < DAVINCI_N_GPIO; bank++) {
+               struct gpio_controller  *__iomem g = gpio2controller(gpio);
+               unsigned                i;
+
+               __raw_writel(~0, &g->clr_falling);
+               __raw_writel(~0, &g->clr_rising);
+
+               /* set up all irqs in this bank */
+               set_irq_chained_handler(bank, gpio_irq_handler);
+               set_irq_chip_data(bank, g);
+               set_irq_data(bank, (void *)irq);
+
+               for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
+                    i++, irq++, gpio++) {
+                       set_irq_chip(irq, &gpio_irqchip);
+                       set_irq_chip_data(irq, g);
+                       set_irq_handler(irq, handle_simple_irq);
+                       set_irq_flags(irq, IRQF_VALID);
+               }
+       }
+
+       /* BINTEN -- per-bank interrupt enable. genirq would also let these
+        * bits be set/cleared dynamically.
+        */
+       __raw_writel(0x1f, (void *__iomem)
+                    IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+
+       printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+       return 0;
+}
+
+arch_initcall(davinci_gpio_irq_setup);
index 87fae6fb6ecf9b5d5447dce953a99aa42ab7c9d8..47787ff84a6ad19f9fd9ab455e9cc4d1762bdbfd 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/memory.h>
 
 #include <asm/mach/map.h>
+#include <asm/arch/clock.h>
 
 extern void davinci_check_revision(void);
 
@@ -49,3 +50,8 @@ void __init davinci_map_common_io(void)
         */
        davinci_check_revision();
 }
+
+void __init davinci_init_common_hw(void)
+{
+       davinci_clk_init();
+}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644 (file)
index 0000000..92d26bd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * DaVinci pin multiplexing configurations
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+
+#include <asm/arch/mux.h>
+
+/* System control register offsets */
+#define PINMUX0         0x00
+#define PINMUX1         0x04
+
+static DEFINE_SPINLOCK(mux_lock);
+
+void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+{
+       u32 pinmux, muxreg = PINMUX0;
+
+       if (mux >= DAVINCI_MUX_LEVEL2) {
+               muxreg = PINMUX1;
+               mux -= DAVINCI_MUX_LEVEL2;
+       }
+
+       spin_lock(&mux_lock);
+       pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+       if (enable)
+               pinmux |= (1 << mux);
+       else
+               pinmux &= ~(1 << mux);
+       davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+       spin_unlock(&mux_lock);
+}
index e1b0050283a681f78b2061d594be2a91c7be30bb..1334416559ad264cf3fd3f69ed68a8333cb56303 100644 (file)
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/psc.h>
+#include <asm/arch/mux.h>
 
-#define PTCMD       __REG(0x01C41120)
-#define PDSTAT      __REG(0x01C41200)
-#define PDCTL1      __REG(0x01C41304)
-#define EPCPR       __REG(0x01C41070)
-#define PTSTAT      __REG(0x01C41128)
+/* PSC register offsets */
+#define EPCPR          0x070
+#define PTCMD          0x120
+#define PTSTAT         0x128
+#define PDSTAT         0x200
+#define PDCTL1         0x304
+#define MDSTAT         0x800
+#define MDCTL          0xA00
 
-#define MDSTAT      IO_ADDRESS(0x01C41800)
-#define MDCTL       IO_ADDRESS(0x01C41A00)
-
-#define PINMUX0             __REG(0x01c40000)
-#define PINMUX1             __REG(0x01c40004)
-#define VDD3P3V_PWDN __REG(0x01C40048)
+/* System control register offsets */
+#define VDD3P3V_PWDN   0x48
 
 static void davinci_psc_mux(unsigned int id)
 {
        switch (id) {
        case DAVINCI_LPSC_ATA:
-               PINMUX0 |= (1 << 17) | (1 << 16);
+               davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
+               davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
                break;
        case DAVINCI_LPSC_MMC_SD:
                /* VDD power manupulations are done in U-Boot for CPMAC
                 * so applies to MMC as well
                 */
                /*Set up the pull regiter for MMC */
-               VDD3P3V_PWDN = 0x0;
-               PINMUX1 &= (~(1 << 9));
+               davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
+               davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
                break;
        case DAVINCI_LPSC_I2C:
-               PINMUX1 |= (1 << 7);
+               davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
                break;
        case DAVINCI_LPSC_McBSP:
-               PINMUX1 |= (1 << 10);
+               davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
                break;
        default:
                break;
@@ -67,33 +68,59 @@ static void davinci_psc_mux(unsigned int id)
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
 {
-       volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
-       volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
+       u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
 
        if (id < 0)
                return;
 
+       mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
        if (enable)
-               *mdctl |= 0x00000003;   /* Enable Module */
+               mdctl |= 0x00000003;    /* Enable Module */
        else
-               *mdctl &= 0xFFFFFFF2;   /* Disable Module */
+               mdctl &= 0xFFFFFFF2;    /* Disable Module */
+       davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
+
+       pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+       if ((pdstat & 0x00000001) == 0) {
+               pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+               pdctl1 |= 0x1;
+               davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+               ptcmd = 1 << domain;
+               davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
 
-       if ((PDSTAT & 0x00000001) == 0) {
-               PDCTL1 |= 0x1;
-               PTCMD = (1 << domain);
-               while ((((EPCPR >> domain) & 1) == 0));
+               do {
+                       epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                             EPCPR);
+               } while ((((epcpr >> domain) & 1) == 0));
 
-               PDCTL1 |= 0x100;
-               while (!(((PTSTAT >> domain) & 1) == 0));
+               pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+               pdctl1 |= 0x100;
+               davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+               do {
+                       ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                              PTSTAT);
+               } while (!(((ptstat >> domain) & 1) == 0));
        } else {
-               PTCMD = (1 << domain);
-               while (!(((PTSTAT >> domain) & 1) == 0));
+               ptcmd = 1 << domain;
+               davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+               do {
+                       ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                              PTSTAT);
+               } while (!(((ptstat >> domain) & 1) == 0));
        }
 
        if (enable)
-               while (!((*mdstat & 0x0000001F) == 0x3));
+               mdstat_mask = 0x3;
        else
-               while (!((*mdstat & 0x0000001F) == 0x2));
+               mdstat_mask = 0x2;
+
+       do {
+               mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+                                      MDSTAT + 4 * id);
+       } while (!((mdstat & 0x0000001F) == mdstat_mask));
 
        if (enable)
                davinci_psc_mux(id);
index 1c474cf709ca9b4a4241a112fceba2c1560244ea..a58b678006dff1ce50ef7ccaa86ffc1cc0b9fe1a 100644 (file)
 #include <linux/module.h>
 #include <linux/string.h>
 
+#include <asm/errno.h>
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode)
 
 EXPORT_SYMBOL(imx_gpio_mode);
 
+int imx_gpio_request(unsigned gpio, const char *label)
+{
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
+                       gpio, label ? label : "?");
+               return -EINVAL;
+
+       if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+               printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
+                       gpio, label ? label : "?");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
+{
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               return;
+
+       clear_bit(gpio, imx_gpio_alloc_map);
+}
+
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
+{
+       imx_gpio_mode(gpio| GPIO_IN);
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
+{
+       imx_gpio_set_value(gpio, value);
+       imx_gpio_mode(gpio| GPIO_OUT);
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                               int alloc_mode, const char *label)
+{
+       const int *p = pin_list;
+       int i;
+       unsigned gpio;
+       unsigned mode;
+
+       for (i = 0; i < count; i++) {
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+               if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+                       goto setup_error;
+
+               if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+                       imx_gpio_free(gpio);
+               else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+                       if (imx_gpio_request(gpio, label))
+                               if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+                                       goto setup_error;
+
+               if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+                                   IMX_GPIO_ALLOC_MODE_RELEASE)))
+                       imx_gpio_mode(gpio | mode);
+
+               p++;
+       }
+       return 0;
+
+setup_error:
+       if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+                        IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+               return -EINVAL;
+
+       while (p != pin_list) {
+               p--;
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               imx_gpio_free(gpio);
+       }
+
+       return -EINVAL;
+}
+
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
+{
+       imx_gpio_set_value_inline(gpio, value);
+}
+
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
+{
+       return IRQ_GPIOA(0) + gpio;
+}
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+       if (irq < IRQ_GPIOA(0))
+               return -EINVAL;
+       return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
+
 /*
  *  get the system pll clock in Hz
  *
index 6960a9d042175d824d080c38cb8e35b21148ef69..010f6fa984a65e7f05262fa5ec70edda8ee8b34b 100644 (file)
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2000-2001 Deep Blue Solutions
  *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
  *
  * 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
@@ -15,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -25,7 +27,8 @@
 /* Use timer 1 as system timer */
 #define TIMER_BASE IMX_TIM1_BASE
 
-static unsigned long evt_diff;
+static struct clock_event_device clockevent_imx;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
 /*
  * IRQ handler for the timer
@@ -33,25 +36,20 @@ static unsigned long evt_diff;
 static irqreturn_t
 imx_timer_interrupt(int irq, void *dev_id)
 {
+       struct clock_event_device *evt = &clockevent_imx;
        uint32_t tstat;
+       irqreturn_t ret = IRQ_NONE;
 
        /* clear the interrupt */
        tstat = IMX_TSTAT(TIMER_BASE);
        IMX_TSTAT(TIMER_BASE) = 0;
 
        if (tstat & TSTAT_COMP) {
-               do {
-
-                       write_seqlock(&xtime_lock);
-                       timer_tick();
-                       write_sequnlock(&xtime_lock);
-                       IMX_TCMP(TIMER_BASE) += evt_diff;
-
-               } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
-                                       - IMX_TCN(TIMER_BASE)) < 0));
+               evt->event_handler(evt);
+               ret = IRQ_HANDLED;
        }
 
-       return IRQ_HANDLED;
+       return ret;
 }
 
 static struct irqaction imx_timer_irq = {
@@ -70,10 +68,8 @@ static void __init imx_timer_hardware_init(void)
         */
        IMX_TCTL(TIMER_BASE) = 0;
        IMX_TPRER(TIMER_BASE) = 0;
-       IMX_TCMP(TIMER_BASE) = LATCH - 1;
 
-       IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
-       evt_diff = LATCH;
+       IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
 }
 
 cycle_t imx_get_cycles(void)
@@ -99,11 +95,108 @@ static int __init imx_clocksource_init(void)
        return 0;
 }
 
+static int imx_set_next_event(unsigned long evt,
+                                 struct clock_event_device *unused)
+{
+       unsigned long tcmp;
+
+       tcmp = IMX_TCN(TIMER_BASE) + evt;
+       IMX_TCMP(TIMER_BASE) = tcmp;
+
+       return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
+}
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[]={
+       [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+       [CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+       [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+       [CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /*DEBUG*/
+
+static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+       unsigned long flags;
+
+       /*
+        * The timer interrupt generation is disabled at least
+        * for enough time to call imx_set_next_event()
+        */
+       local_irq_save(flags);
+       /* Disable interrupt in GPT module */
+       IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
+       if (mode != clockevent_mode) {
+               /* Set event time into far-far future */
+               IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
+               /* Clear pending interrupt */
+               IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
+       }
+
+#ifdef DEBUG
+       printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
+               clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
+#endif /*DEBUG*/
+
+       /* Remember timer mode */
+       clockevent_mode = mode;
+       local_irq_restore(flags);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /*
+                * Do not put overhead of interrupt enable/disable into
+                * imx_set_next_event(), the core has about 4 minutes
+                * to call imx_set_next_event() or shutdown clock after
+                * mode switching
+                */
+               local_irq_save(flags);
+               IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
+               local_irq_restore(flags);
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+               /* Left event sources disabled, no more interrupts appears */
+               break;
+       }
+}
+
+static struct clock_event_device clockevent_imx = {
+       .name           = "imx_timer1",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .set_mode       = imx_set_mode,
+       .set_next_event = imx_set_next_event,
+       .rating         = 200,
+};
+
+static int __init imx_clockevent_init(void)
+{
+       clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC,
+                                       clockevent_imx.shift);
+       clockevent_imx.max_delta_ns =
+               clockevent_delta2ns(0xfffffffe, &clockevent_imx);
+       clockevent_imx.min_delta_ns =
+               clockevent_delta2ns(0xf, &clockevent_imx);
+
+       clockevent_imx.cpumask = cpumask_of_cpu(0);
+
+       clockevents_register_device(&clockevent_imx);
+
+       return 0;
+}
+
+
 static void __init imx_timer_init(void)
 {
        imx_timer_hardware_init();
        imx_clocksource_init();
 
+       imx_clockevent_init();
+
        /*
         * Make irqs happen for the system timer
         */
index d3dc278213da10892934032db9f75c241182a918..2476347ea62f13b5119a28e1fd6f185d76a8ad8f 100644 (file)
 #define IOP13XX_TPMI_MMR(dev)  IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
 #define IOP13XX_TPMI_MEM(dev)  IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
 #define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
+#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
 #define IOP13XX_TPMI_MMR_SIZE      (SZ_4K - 1)
 #define IOP13XX_TPMI_MEM_SIZE      (255)
 #define IOP13XX_TPMI_MEM_CTRL      (SZ_1K - 1)
 #define IOP13XX_TPMI_RESOURCE_MMR  0
 #define IOP13XX_TPMI_RESOURCE_MEM  1
 #define IOP13XX_TPMI_RESOURCE_CTRL 2
-#define IOP13XX_TPMI_RESOURCE_IRQ  3
+#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
+#define IOP13XX_TPMI_RESOURCE_IRQ  4
 
 static struct resource iop13xx_tpmi_0_resources[] = {
        [IOP13XX_TPMI_RESOURCE_MMR] = {
@@ -53,6 +55,11 @@ static struct resource iop13xx_tpmi_0_resources[] = {
                .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(0),
+               .end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI0_OUT,
                .end = IRQ_IOP13XX_TPMI0_OUT,
@@ -76,6 +83,11 @@ static struct resource iop13xx_tpmi_1_resources[] = {
                .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(1),
+               .end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI1_OUT,
                .end = IRQ_IOP13XX_TPMI1_OUT,
@@ -99,6 +111,11 @@ static struct resource iop13xx_tpmi_2_resources[] = {
                .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(2),
+               .end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI2_OUT,
                .end = IRQ_IOP13XX_TPMI2_OUT,
@@ -122,6 +139,11 @@ static struct resource iop13xx_tpmi_3_resources[] = {
                .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
                .flags = IORESOURCE_MEM,
        },
+       [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+               .start = IOP13XX_TPMI_IOP_CTRL(3),
+               .end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
+               .flags = IORESOURCE_MEM,
+       },
        [IOP13XX_TPMI_RESOURCE_IRQ] = {
                .start = IRQ_IOP13XX_TPMI3_OUT,
                .end = IRQ_IOP13XX_TPMI3_OUT,
@@ -133,7 +155,7 @@ u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
 static struct platform_device iop13xx_tpmi_0_device = {
        .name = "iop-tpmi",
        .id = 0,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
        .resource = iop13xx_tpmi_0_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
@@ -144,7 +166,7 @@ static struct platform_device iop13xx_tpmi_0_device = {
 static struct platform_device iop13xx_tpmi_1_device = {
        .name = "iop-tpmi",
        .id = 1,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
        .resource = iop13xx_tpmi_1_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
@@ -155,7 +177,7 @@ static struct platform_device iop13xx_tpmi_1_device = {
 static struct platform_device iop13xx_tpmi_2_device = {
        .name = "iop-tpmi",
        .id = 2,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
        .resource = iop13xx_tpmi_2_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
@@ -166,7 +188,7 @@ static struct platform_device iop13xx_tpmi_2_device = {
 static struct platform_device iop13xx_tpmi_3_device = {
        .name = "iop-tpmi",
        .id = 3,
-       .num_resources = 4,
+       .num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
        .resource = iop13xx_tpmi_3_resources,
        .dev = {
                .dma_mask          = &iop13xx_tpmi_mask,
index 060909870b505b582ee4a2ee684cdd9ddd311e67..61b2dfcb89d623dd401cd8226ec2d66bbf939690 100644 (file)
@@ -41,6 +41,22 @@ config ARCH_ADI_COYOTE
          Engineering Coyote Gateway Reference Platform. For more
          information on this platform, see <file:Documentation/arm/IXP4xx>.
 
+config MACH_GATEWAY7001
+       bool "Gateway 7001"
+       select PCI
+       help
+         Say 'Y' here if you want your kernel to support Gateway's
+         7001 Access Point. For more information on this platform,
+         see http://openwrt.org
+
+config MACH_WG302V2
+       bool "Netgear WG302 v2 / WAG302 v2"
+       select PCI
+       help
+         Say 'Y' here if you want your kernel to support Netgear's
+         WG302 v2 or WAG302 v2 Access Points. For more information
+         on this platform, see http://openwrt.org
+
 config ARCH_IXDP425
        bool "IXDP425"
        help
index 3b87c47e06cf893d6a74aa9fc161afdac6e426bf..77e00ade558589297aaa425558958a66a61fbffb 100644 (file)
@@ -13,6 +13,8 @@ obj-pci-$(CONFIG_MACH_GTWX5715)               += gtwx5715-pci.o
 obj-pci-$(CONFIG_MACH_NSLU2)           += nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)         += nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)         += dsmg600-pci.o
+obj-pci-$(CONFIG_MACH_GATEWAY7001)     += gateway7001-pci.o
+obj-pci-$(CONFIG_MACH_WG302V2)         += wg302v2-pci.o
 
 obj-y  += common.o
 
@@ -24,5 +26,7 @@ obj-$(CONFIG_MACH_GTWX5715)   += gtwx5715-setup.o
 obj-$(CONFIG_MACH_NSLU2)       += nslu2-setup.o nslu2-power.o
 obj-$(CONFIG_MACH_NAS100D)     += nas100d-setup.o nas100d-power.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
+obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
+obj-$(CONFIG_MACH_WG302V2)     += wg302v2-setup.o
 
 obj-$(CONFIG_PCI)              += $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
new file mode 100644 (file)
index 0000000..6abf568
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/gateway7001-pci.c
+ *
+ * PCI setup routines for Gateway 7001
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *     Copyright (C) 2002 Jungo Software Technologies.
+ *     Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init gateway7001_pci_preinit(void)
+{
+       set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (slot == 1)
+               return IRQ_IXP4XX_GPIO11;
+       else if (slot == 2)
+               return IRQ_IXP4XX_GPIO10;
+       else return -1;
+}
+
+struct hw_pci gateway7001_pci __initdata = {
+       .nr_controllers = 1,
+       .preinit =        gateway7001_pci_preinit,
+       .swizzle =        pci_std_swizzle,
+       .setup =          ixp4xx_setup,
+       .scan =           ixp4xx_scan_bus,
+       .map_irq =        gateway7001_map_irq,
+};
+
+int __init gateway7001_pci_init(void)
+{
+       if (machine_is_gateway7001())
+               pci_common_init(&gateway7001_pci);
+       return 0;
+}
+
+subsys_initcall(gateway7001_pci_init);
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
new file mode 100644 (file)
index 0000000..3787683
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ixp4xx/gateway7001-setup.c
+ *
+ * Board setup for the Gateway 7001 board
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <Kaloz@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data gateway7001_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+};
+
+static struct resource gateway7001_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device gateway7001_flash = {
+       .name           = "IXP4XX-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &gateway7001_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &gateway7001_flash_resource,
+};
+
+static struct resource gateway7001_uart_resource = {
+       .start  = IXP4XX_UART2_BASE_PHYS,
+       .end    = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port gateway7001_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { },
+};
+
+static struct platform_device gateway7001_uart = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = gateway7001_uart_data,
+       },
+       .num_resources  = 1,
+       .resource       = &gateway7001_uart_resource,
+};
+
+static struct platform_device *gateway7001_devices[] __initdata = {
+       &gateway7001_flash,
+       &gateway7001_uart
+};
+
+static void __init gateway7001_init(void)
+{
+       ixp4xx_sys_init();
+
+       gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+       gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+       *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+       *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+       platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices));
+}
+
+#ifdef CONFIG_MACH_GATEWAY7001
+MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
+       /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = gateway7001_init,
+MACHINE_END
+#endif
index a66484b63d36b12b0dccd06770b3b3a9d2931a7a..0d5a42455820322c804d046233e7563826d66106 100644 (file)
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
+
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/arch/gtwx5715.h>
 #include <asm/mach/pci.h>
 
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
-
 /*
  * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
  * Slot 0 isn't actually populated with a card connector but
index ec4f07950ec62745b300ae45e12c965434510048..d5008d8fc9a5af2eb24b85ff804410e4469f2ece 100644 (file)
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -24,6 +28,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
+#include <asm/delay.h>
 
 static struct flash_platform_data ixdp425_flash_data = {
        .map_name       = "cfi_probe",
@@ -44,6 +49,77 @@ static struct platform_device ixdp425_flash = {
        .resource       = &ixdp425_flash_resource,
 };
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ixdp425_partitions[] = {
+       {
+               .name   = "ixp400 NAND FS 0",
+               .offset = 0,
+               .size   = SZ_8M
+       }, {
+               .name   = "ixp400 NAND FS 1",
+               .offset = MTDPART_OFS_APPEND,
+               .size   = MTDPART_SIZ_FULL
+       },
+};
+#endif
+
+static void
+ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *this = mtd->priv;
+       int offset = (int)this->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               if (ctrl & NAND_NCE) {
+                       gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW);
+                       udelay(5);
+               } else
+                       gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH);
+
+               offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
+               offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
+               this->priv = (void *)offset;
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, this->IO_ADDR_W + offset);
+}
+
+static struct platform_nand_data ixdp425_flash_nand_data = {
+       .chip = {
+               .chip_delay             = 30,
+               .options                = NAND_NO_AUTOINCR,
+#ifdef CONFIG_MTD_PARTITIONS
+               .part_probe_types       = part_probes,
+               .partitions             = ixdp425_partitions,
+               .nr_partitions          = ARRAY_SIZE(ixdp425_partitions),
+#endif
+       },
+       .ctrl = {
+               .cmd_ctrl               = ixdp425_flash_nand_cmd_ctrl
+       }
+};
+
+static struct resource ixdp425_flash_nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash_nand = {
+       .name           = "gen_nand",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &ixdp425_flash_nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &ixdp425_flash_nand_resource,
+};
+#endif /* CONFIG_MTD_NAND_PLATFORM */
+
 static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = {
        .sda_pin        = IXDP425_SDA_PIN,
        .scl_pin        = IXDP425_SCL_PIN,
@@ -104,6 +180,10 @@ static struct platform_device ixdp425_uart = {
 static struct platform_device *ixdp425_devices[] __initdata = {
        &ixdp425_i2c_controller,
        &ixdp425_flash,
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+       &ixdp425_flash_nand,
+#endif
        &ixdp425_uart
 };
 
@@ -115,6 +195,22 @@ static void __init ixdp425_init(void)
        ixdp425_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+       ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
+       ixdp425_flash_nand_resource.end   = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
+
+       gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT);
+
+       /* Configure expansion bus for NAND Flash */
+       *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
+                         IXP4XX_EXP_BUS_STROBE_T(1) |  /* extend by 1 clock */
+                         IXP4XX_EXP_BUS_CYCLES(0) |    /* Intel cycles */
+                         IXP4XX_EXP_BUS_SIZE(0) |      /* 512bytes addr space*/
+                         IXP4XX_EXP_BUS_WR_EN |
+                         IXP4XX_EXP_BUS_BYTE_EN;       /* 8 bit data bus */
+#endif
+
        if (cpu_is_ixp43x()) {
                ixdp425_uart.num_resources = 1;
                ixdp425_uart_data[1].flags = 0;
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
new file mode 100644 (file)
index 0000000..6588f2c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/wg302v2-pci.c
+ *
+ * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *     Copyright (C) 2002 Jungo Software Technologies.
+ *     Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init wg302v2_pci_preinit(void)
+{
+       set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
+       set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
+
+       ixp4xx_pci_preinit();
+}
+
+static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (slot == 1)
+               return IRQ_IXP4XX_GPIO8;
+       else if (slot == 2)
+               return IRQ_IXP4XX_GPIO9;
+       else return -1;
+}
+
+struct hw_pci wg302v2_pci __initdata = {
+       .nr_controllers = 1,
+       .preinit =        wg302v2_pci_preinit,
+       .swizzle =        pci_std_swizzle,
+       .setup =          ixp4xx_setup,
+       .scan =           ixp4xx_scan_bus,
+       .map_irq =        wg302v2_map_irq,
+};
+
+int __init wg302v2_pci_init(void)
+{
+       if (machine_is_wg302v2())
+               pci_common_init(&wg302v2_pci);
+       return 0;
+}
+
+subsys_initcall(wg302v2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
new file mode 100644 (file)
index 0000000..f7e09ad
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-ixp4xx/wg302-setup.c
+ *
+ * Board setup for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <kaloz@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data wg302v2_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+};
+
+static struct resource wg302v2_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device wg302v2_flash = {
+       .name           = "IXP4XX-Flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &wg302v2_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &wg302v2_flash_resource,
+};
+
+static struct resource wg302v2_uart_resource = {
+       .start  = IXP4XX_UART2_BASE_PHYS,
+       .end    = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port wg302v2_uart_data[] = {
+       {
+               .mapbase        = IXP4XX_UART2_BASE_PHYS,
+               .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+               .irq            = IRQ_IXP4XX_UART2,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = IXP4XX_UART_XTAL,
+       },
+       { },
+};
+
+static struct platform_device wg302v2_uart = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev                    = {
+               .platform_data  = wg302v2_uart_data,
+       },
+       .num_resources  = 1,
+       .resource       = &wg302v2_uart_resource,
+};
+
+static struct platform_device *wg302v2_devices[] __initdata = {
+       &wg302v2_flash,
+       &wg302v2_uart,
+};
+
+static void __init wg302v2_init(void)
+{
+       ixp4xx_sys_init();
+
+       wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+       wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+       *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+       *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+       platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
+}
+
+#ifdef CONFIG_MACH_WG302V2
+MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
+       /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+       .phys_io        = IXP4XX_PERIPHERAL_BASE_PHYS,
+       .io_pg_offst    = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+       .map_io         = ixp4xx_map_io,
+       .init_irq       = ixp4xx_init_irq,
+       .timer          = &ixp4xx_timer,
+       .boot_params    = 0x0100,
+       .init_machine   = wg302v2_init,
+MACHINE_END
+#endif
index 56b7d337333a6fa43412c2b627ce18d35049625e..2a07a281fa8ae927f9957575f4c448a81bad8815 100644 (file)
@@ -3,7 +3,7 @@
 # Makefile for KS8695 architecture support
 #
 
-obj-y                          := cpu.o irq.o time.o devices.o
+obj-y                          := cpu.o irq.o time.o gpio.o devices.o
 obj-m                          :=
 obj-n                          :=
 obj-                           :=
diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
new file mode 100644 (file)
index 0000000..b1aa3cb
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * arch/arm/mach-ks8695/gpio.c
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * 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.
+ *
+ * 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/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/gpio.h>
+
+/*
+ * Configure a GPIO line for either GPIO function, or its internal
+ * function (Interrupt, Timer, etc).
+ */
+static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
+{
+       unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_5)        /* only GPIO 0..5 have internal functions */
+               return;
+
+       local_irq_save(flags);
+
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+       if (gpio)                       /* GPIO: set bit to 0 */
+               x &= ~enable[pin];
+       else                            /* Internal function: set bit to 1 */
+               x |= enable[pin];
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
+
+       local_irq_restore(flags);
+}
+
+
+static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       /* set pin as input */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+       x &= ~IOPM_(pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+       local_irq_restore(flags);
+
+       /* Set IRQ triggering type */
+       set_irq_type(gpio_irq[pin], type);
+
+       /* enable interrupt mode */
+       ks8695_gpio_mode(pin, 0);
+
+       return 0;
+}
+EXPORT_SYMBOL(ks8695_gpio_interrupt);
+
+
+
+/* .... Generic GPIO interface .............................................. */
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_15)
+               return -EINVAL;
+
+       /* set pin to GPIO mode */
+       ks8695_gpio_mode(pin, 1);
+
+       local_irq_save(flags);
+
+       /* set pin as input */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+       x &= ~IOPM_(pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_15)
+               return -EINVAL;
+
+       /* set pin to GPIO mode */
+       ks8695_gpio_mode(pin, 1);
+
+       local_irq_save(flags);
+
+       /* set line state */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+       if (state)
+               x |= (1 << pin);
+       else
+               x &= ~(1 << pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+       /* set pin as output */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+       x |= IOPM_(pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state)
+{
+       unsigned long x, flags;
+
+       if (pin > KS8695_GPIO_15)
+               return;
+
+       local_irq_save(flags);
+
+       /* set output line state */
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+       if (state)
+               x |= (1 << pin);
+       else
+               x &= ~(1 << pin);
+       __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin)
+{
+       unsigned long x;
+
+       if (pin > KS8695_GPIO_15)
+               return -EINVAL;
+
+       x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+       return (x & (1 << pin)) != 0;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin)
+{
+       if (pin > KS8695_GPIO_3)        /* only GPIO 0..3 can generate IRQ */
+               return -EINVAL;
+
+       return gpio_irq[pin];
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq)
+{
+       if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
+               return -EINVAL;
+
+       return (irq - KS8695_IRQ_EXTERN0);
+}
+EXPORT_SYMBOL(irq_to_gpio);
index 8f7c90a0593bce2ccf20669b1268703e8c4f4003..34a31caa6f9d6a83cbc379014fdbe8b88ccd7395 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/hardware.h>
-#include <asm/semaphore.h>
 
 struct clk {
        struct list_head        node;
@@ -25,21 +24,21 @@ struct clk {
 };
 
 static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_for_each_entry(p, &clocks, node) {
                if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
                        clk = p;
                        break;
                }
        }
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
 
        return clk;
 }
@@ -101,18 +100,18 @@ static struct clk clk_gpio27 = {
 
 int clk_register(struct clk *clk)
 {
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_add(&clk->node, &clocks);
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
        return 0;
 }
 EXPORT_SYMBOL(clk_register);
 
 void clk_unregister(struct clk *clk)
 {
-       down(&clocks_sem);
+       mutex_lock(&clocks_mutex);
        list_del(&clk->node);
-       up(&clocks_sem);
+       mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
 
index a1a900d16665fc8f58d6431306d1d4df0011dbee..aab27297b3c60da5937852e50a05cd70a27da5b8 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 
@@ -368,7 +369,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -380,7 +381,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -392,7 +393,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_corgi,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
new file mode 100644 (file)
index 0000000..9a6faff
--- /dev/null
@@ -0,0 +1,11 @@
+extern struct platform_device pxamci_device;
+extern struct platform_device pxaudc_device;
+extern struct platform_device pxafb_device;
+extern struct platform_device ffuart_device;
+extern struct platform_device btuart_device;
+extern struct platform_device stuart_device;
+extern struct platform_device hwuart_device;
+extern struct platform_device pxai2c_device;
+extern struct platform_device pxai2s_device;
+extern struct platform_device pxaficp_device;
+extern struct platform_device pxartc_device;
index 4440babe7b97595dabe3330082ffd8aad9b6d674..93c4f31f127faa053dcd555f5fe7aa66fb5aee34 100644 (file)
 
 #include <asm/arch/pxa-regs.h>
 
-static struct dma_channel {
+struct dma_channel {
        char *name;
+       pxa_dma_prio prio;
        void (*irq_handler)(int, void *);
        void *data;
-} dma_channels[PXA_DMA_CHANNELS];
+};
 
+static struct dma_channel *dma_channels;
+static int num_dma_channels;
 
 int pxa_request_dma (char *name, pxa_dma_prio prio,
                         void (*irq_handler)(int, void *),
@@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
 
        do {
                /* try grabbing a DMA channel with the requested priority */
-               pxa_for_each_dma_prio (i, prio) {
-                       if (!dma_channels[i].name) {
+               for (i = 0; i < num_dma_channels; i++) {
+                       if ((dma_channels[i].prio == prio) &&
+                           !dma_channels[i].name) {
                                found = 1;
                                break;
                        }
@@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
        int i, dint = DINT;
 
-       for (i = 0; i < PXA_DMA_CHANNELS; i++) {
+       for (i = 0; i < num_dma_channels; i++) {
                if (dint & (1 << i)) {
                        struct dma_channel *channel = &dma_channels[i];
                        if (channel->name && channel->irq_handler) {
@@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __init pxa_dma_init (void)
+int __init pxa_init_dma(int num_ch)
 {
-       int ret;
+       int i, ret;
 
-       ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
-       if (ret)
+       dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
+       if (dma_channels == NULL)
+               return -ENOMEM;
+
+       ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
+       if (ret) {
                printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-       return ret;
-}
+               kfree(dma_channels);
+               return ret;
+       }
 
-arch_initcall(pxa_dma_init);
+       /* dma channel priorities on pxa2xx processors:
+        * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH
+        * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM
+        * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW
+        */
+       for (i = 0; i < num_ch; i++)
+               dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
+
+       num_dma_channels = num_ch;
+       return 0;
+}
 
 EXPORT_SYMBOL(pxa_request_dma);
 EXPORT_SYMBOL(pxa_free_dma);
-
index 64b08b744f9f3fd12bcd06169e949b09881b39b8..296539b6359ca43af779f59e5fa078351c14195b 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
+#include "devices.h"
 #include "generic.h"
 
 /*
@@ -242,7 +243,7 @@ static struct resource pxamci_resources[] = {
 
 static u64 pxamci_dmamask = 0xffffffffUL;
 
-static struct platform_device pxamci_device = {
+struct platform_device pxamci_device = {
        .name           = "pxa2xx-mci",
        .id             = -1,
        .dev            = {
@@ -281,7 +282,7 @@ static struct resource pxa2xx_udc_resources[] = {
 
 static u64 udc_dma_mask = ~(u32)0;
 
-static struct platform_device udc_device = {
+struct platform_device pxaudc_device = {
        .name           = "pxa2xx-udc",
        .id             = -1,
        .resource       = pxa2xx_udc_resources,
@@ -307,7 +308,7 @@ static struct resource pxafb_resources[] = {
 
 static u64 fb_dma_mask = ~(u64)0;
 
-static struct platform_device pxafb_device = {
+struct platform_device pxafb_device = {
        .name           = "pxa2xx-fb",
        .id             = -1,
        .dev            = {
@@ -328,24 +329,24 @@ void __init set_pxa_fb_parent(struct device *parent_dev)
        pxafb_device.dev.parent = parent_dev;
 }
 
-static struct platform_device ffuart_device = {
+struct platform_device ffuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 0,
 };
-static struct platform_device btuart_device = {
+struct platform_device btuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 1,
 };
-static struct platform_device stuart_device = {
+struct platform_device stuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 2,
 };
-static struct platform_device hwuart_device = {
+struct platform_device hwuart_device = {
        .name           = "pxa2xx-uart",
        .id             = 3,
 };
 
-static struct resource i2c_resources[] = {
+static struct resource pxai2c_resources[] = {
        {
                .start  = 0x40301680,
                .end    = 0x403016a3,
@@ -357,40 +358,19 @@ static struct resource i2c_resources[] = {
        },
 };
 
-static struct platform_device i2c_device = {
+struct platform_device pxai2c_device = {
        .name           = "pxa2xx-i2c",
        .id             = 0,
-       .resource       = i2c_resources,
-       .num_resources  = ARRAY_SIZE(i2c_resources),
+       .resource       = pxai2c_resources,
+       .num_resources  = ARRAY_SIZE(pxai2c_resources),
 };
 
-#ifdef CONFIG_PXA27x
-static struct resource i2c_power_resources[] = {
-       {
-               .start  = 0x40f00180,
-               .end    = 0x40f001a3,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_PWRI2C,
-               .end    = IRQ_PWRI2C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device i2c_power_device = {
-       .name           = "pxa2xx-i2c",
-       .id             = 1,
-       .resource       = i2c_power_resources,
-       .num_resources  = ARRAY_SIZE(i2c_resources),
-};
-#endif
-
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
-       i2c_device.dev.platform_data = info;
+       pxai2c_device.dev.platform_data = info;
 }
 
-static struct resource i2s_resources[] = {
+static struct resource pxai2s_resources[] = {
        {
                .start  = 0x40400000,
                .end    = 0x40400083,
@@ -402,16 +382,16 @@ static struct resource i2s_resources[] = {
        },
 };
 
-static struct platform_device i2s_device = {
+struct platform_device pxai2s_device = {
        .name           = "pxa2xx-i2s",
        .id             = -1,
-       .resource       = i2s_resources,
-       .num_resources  = ARRAY_SIZE(i2s_resources),
+       .resource       = pxai2s_resources,
+       .num_resources  = ARRAY_SIZE(pxai2s_resources),
 };
 
 static u64 pxaficp_dmamask = ~(u32)0;
 
-static struct platform_device pxaficp_device = {
+struct platform_device pxaficp_device = {
        .name           = "pxa2xx-ir",
        .id             = -1,
        .dev            = {
@@ -425,42 +405,7 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
        pxaficp_device.dev.platform_data = info;
 }
 
-static struct platform_device pxartc_device = {
+struct platform_device pxartc_device = {
        .name           = "sa1100-rtc",
        .id             = -1,
 };
-
-static struct platform_device *devices[] __initdata = {
-       &pxamci_device,
-       &udc_device,
-       &pxafb_device,
-       &ffuart_device,
-       &btuart_device,
-       &stuart_device,
-       &pxaficp_device,
-       &i2c_device,
-#ifdef CONFIG_PXA27x
-       &i2c_power_device,
-#endif
-       &i2s_device,
-       &pxartc_device,
-};
-
-static int __init pxa_init(void)
-{
-       int cpuid, ret;
-
-       ret = platform_add_devices(devices, ARRAY_SIZE(devices));
-       if (ret)
-               return ret;
-
-       /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-       cpuid = read_cpuid(CPUID_ID);
-       if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
-           ((cpuid >> 4) & 0xfff) == 0x290)
-               ret = platform_device_register(&hwuart_device);
-
-       return ret;
-}
-
-subsys_initcall(pxa_init);
index e54a8dd63c17df1a5b2d12bb0fe2de306390ee18..91ab2ad8b34b78020da69be0bc71c5597c529ab4 100644 (file)
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
+extern void __init pxa_init_irq_low(void);
+extern void __init pxa_init_irq_high(void);
+extern void __init pxa_init_irq_gpio(int gpio_nr);
+extern void __init pxa25x_init_irq(void);
+extern void __init pxa27x_init_irq(void);
 extern void __init pxa_map_io(void);
-extern void __init pxa_init_irq(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
index 64df44043a654f88826edd7e2e65470d41bdf455..465108da285103be616ecfd8f13f9f5d302bcb63 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* TODO:
  * - add pxa2xx_audio_ops_t device structure
@@ -152,7 +153,7 @@ static void __init idp_init(void)
 static void __init idp_init_irq(void)
 {
 
-       pxa_init_irq();
+       pxa25x_init_irq();
 
        set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 }
index 4619d5fe606c2bad027ee2bf023f6c045d3ab882..4b867b0789d54c8a9e463e08fbce0cf1f239db61 100644 (file)
 
 static void pxa_mask_low_irq(unsigned int irq)
 {
-       ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+       ICMR &= ~(1 << irq);
 }
 
 static void pxa_unmask_low_irq(unsigned int irq)
 {
-       ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+       ICMR |= (1 << irq);
 }
 
 static int pxa_set_wake(unsigned int irq, unsigned int on)
@@ -67,7 +67,27 @@ static struct irq_chip pxa_internal_chip_low = {
        .set_wake       = pxa_set_wake,
 };
 
-#if PXA_INTERNAL_IRQS > 32
+void __init pxa_init_irq_low(void)
+{
+       int irq;
+
+       /* disable all IRQs */
+       ICMR = 0;
+
+       /* all IRQs are IRQ, not FIQ */
+       ICLR = 0;
+
+       /* only unmasked interrupts kick us out of idle */
+       ICCR = 1;
+
+       for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+               set_irq_chip(irq, &pxa_internal_chip_low);
+               set_irq_handler(irq, handle_level_irq);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+}
+
+#ifdef CONFIG_PXA27x
 
 /*
  * This is for the second set of internal IRQs as found on the PXA27x.
@@ -75,12 +95,12 @@ static struct irq_chip pxa_internal_chip_low = {
 
 static void pxa_mask_high_irq(unsigned int irq)
 {
-       ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+       ICMR2 &= ~(1 << (irq - 32));
 }
 
 static void pxa_unmask_high_irq(unsigned int irq)
 {
-       ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+       ICMR2 |= (1 << (irq - 32));
 }
 
 static struct irq_chip pxa_internal_chip_high = {
@@ -90,6 +110,19 @@ static struct irq_chip pxa_internal_chip_high = {
        .unmask         = pxa_unmask_high_irq,
 };
 
+void __init pxa_init_irq_high(void)
+{
+       int irq;
+
+       ICMR2 = 0;
+       ICLR2 = 0;
+
+       for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+               set_irq_chip(irq, &pxa_internal_chip_high);
+               set_irq_handler(irq, handle_level_irq);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+}
 #endif
 
 /* Note that if an input/irq line ever gets changed to an output during
@@ -217,7 +250,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
        do {
                loop = 0;
 
-               mask = GEDR0 & ~3;
+               mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
                if (mask) {
                        GEDR0 = mask;
                        irq = IRQ_GPIO(2);
@@ -233,7 +266,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        loop = 1;
                }
 
-               mask = GEDR1;
+               mask = GEDR1 & GPIO_IRQ_mask[1];
                if (mask) {
                        GEDR1 = mask;
                        irq = IRQ_GPIO(32);
@@ -248,7 +281,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        loop = 1;
                }
 
-               mask = GEDR2;
+               mask = GEDR2 & GPIO_IRQ_mask[2];
                if (mask) {
                        GEDR2 = mask;
                        irq = IRQ_GPIO(64);
@@ -263,8 +296,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        loop = 1;
                }
 
-#if PXA_LAST_GPIO >= 96
-               mask = GEDR3;
+               mask = GEDR3 & GPIO_IRQ_mask[3];
                if (mask) {
                        GEDR3 = mask;
                        irq = IRQ_GPIO(96);
@@ -278,7 +310,6 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
                        } while (mask);
                        loop = 1;
                }
-#endif
        } while (loop);
 }
 
@@ -314,64 +345,27 @@ static struct irq_chip pxa_muxed_gpio_chip = {
        .set_wake       = pxa_set_gpio_wake,
 };
 
-
-void __init pxa_init_irq(void)
+void __init pxa_init_irq_gpio(int gpio_nr)
 {
-       int irq;
-
-       /* disable all IRQs */
-       ICMR = 0;
-
-       /* all IRQs are IRQ, not FIQ */
-       ICLR = 0;
+       int irq, i;
 
        /* clear all GPIO edge detects */
-       GFER0 = 0;
-       GFER1 = 0;
-       GFER2 = 0;
-       GRER0 = 0;
-       GRER1 = 0;
-       GRER2 = 0;
-       GEDR0 = GEDR0;
-       GEDR1 = GEDR1;
-       GEDR2 = GEDR2;
-
-#ifdef CONFIG_PXA27x
-       /* And similarly for the extra regs on the PXA27x */
-       ICMR2 = 0;
-       ICLR2 = 0;
-       GFER3 = 0;
-       GRER3 = 0;
-       GEDR3 = GEDR3;
-#endif
-
-       /* only unmasked interrupts kick us out of idle */
-       ICCR = 1;
+       for (i = 0; i < gpio_nr; i += 32) {
+               GFER(i) = 0;
+               GRER(i) = 0;
+               GEDR(i) = GEDR(i);
+       }
 
        /* GPIO 0 and 1 must have their mask bit always set */
        GPIO_IRQ_mask[0] = 3;
 
-       for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-               set_irq_chip(irq, &pxa_internal_chip_low);
-               set_irq_handler(irq, handle_level_irq);
-               set_irq_flags(irq, IRQF_VALID);
-       }
-
-#if PXA_INTERNAL_IRQS > 32
-       for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
-               set_irq_chip(irq, &pxa_internal_chip_high);
-               set_irq_handler(irq, handle_level_irq);
-               set_irq_flags(irq, IRQF_VALID);
-       }
-#endif
-
        for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
                set_irq_chip(irq, &pxa_low_gpio_chip);
                set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
-       for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
+       for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) {
                set_irq_chip(irq, &pxa_muxed_gpio_chip);
                set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
index e3097664ffe136e9cdb2f1386ca5174797030f3a..26116440a7c927648d7b8a3e493bdf042cab3beb 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned int lpd270_irq_enabled;
@@ -97,7 +98,7 @@ static void __init lpd270_init_irq(void)
 {
        int irq;
 
-       pxa_init_irq();
+       pxa27x_init_irq();
 
        __raw_writew(0, LPD270_INT_MASK);
        __raw_writew(0, LPD270_INT_STATUS);
index 6377b2e29ff07df44eca47f01fd8e283baa8717f..e70048fd00a53e28f08667a4331aad4c0258ea28 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/arch/mmc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 #define LUB_MISC_WR            __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
@@ -103,7 +104,7 @@ static void __init lubbock_init_irq(void)
 {
        int irq;
 
-       pxa_init_irq();
+       pxa25x_init_irq();
 
        /* setup extra lubbock irqs */
        for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
index ed99a81b98f3e563905caba6db9283cd876ab2d9..b02c79c7e6a3c7d7bf972d0d200eae6e680bee63 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 static unsigned long mainstone_irq_enabled;
@@ -89,7 +90,7 @@ static void __init mainstone_init_irq(void)
 {
        int irq;
 
-       pxa_init_irq();
+       pxa27x_init_irq();
 
        /* setup extra Mainstone irqs */
        for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
index 6bf15ae73848efc667689d28661944e00a84d167..e66dbc26add1f1f8291e4461b3b2f9a000e86d3c 100644 (file)
@@ -77,7 +77,6 @@ int pxa_pm_enter(suspend_state_t state)
 {
        unsigned long sleep_save[SLEEP_SAVE_SIZE];
        unsigned long checksum = 0;
-       struct timespec delta, rtc;
        int i;
        extern void pxa_cpu_pm_enter(suspend_state_t state);
 
@@ -87,11 +86,6 @@ int pxa_pm_enter(suspend_state_t state)
                iwmmxt_task_disable(NULL);
 #endif
 
-       /* preserve current time */
-       rtc.tv_sec = RCNR;
-       rtc.tv_nsec = 0;
-       save_time_delta(&delta, &rtc);
-
        SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
        SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
        SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
@@ -183,10 +177,6 @@ int pxa_pm_enter(suspend_state_t state)
 
        RESTORE(PSTR);
 
-       /* restore current time */
-       rtc.tv_sec = RCNR;
-       restore_time_delta(&delta, &rtc);
-
 #ifdef DEBUG
        printk(KERN_DEBUG "*** made it back from resume\n");
 #endif
@@ -200,40 +190,3 @@ unsigned long sleep_phys_sp(void *sp)
 {
        return virt_to_phys(sp);
 }
-
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-int pxa_pm_prepare(suspend_state_t state)
-{
-       extern int pxa_cpu_pm_prepare(suspend_state_t state);
-
-       return pxa_cpu_pm_prepare(state);
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_prepare);
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-int pxa_pm_finish(suspend_state_t state)
-{
-       return 0;
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_finish);
-
-static struct pm_ops pxa_pm_ops = {
-       .prepare        = pxa_pm_prepare,
-       .enter          = pxa_pm_enter,
-       .finish         = pxa_pm_finish,
-       .valid          = pm_valid_only_mem,
-};
-
-static int __init pxa_pm_init(void)
-{
-       pm_set_ops(&pxa_pm_ops);
-       return 0;
-}
-
-device_initcall(pxa_pm_init);
index 34fb80b37023090147e43c1870591f6a829f6758..655668d4d0e9936a0eb925fa1b8d292ecde31a0f 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 static struct resource poodle_scoop_resources[] = {
@@ -412,7 +413,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_poodle,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = poodle_init,
 MACHINE_END
index c1f21739bf714a435dc7b3df21c3fc2c488e152b..f36ca448338e380ff76cef2764193a7d83e4949c 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /*
  * Various clock factors driven by the CCCR register.
@@ -105,18 +110,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_MEM:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
        extern void pxa_cpu_suspend(unsigned int);
@@ -133,4 +126,49 @@ void pxa_cpu_pm_enter(suspend_state_t state)
        }
 }
 
+static struct pm_ops pxa25x_pm_ops = {
+       .enter          = pxa_pm_enter,
+       .valid          = pm_valid_only_mem,
+};
+#endif
+
+void __init pxa25x_init_irq(void)
+{
+       pxa_init_irq_low();
+       pxa_init_irq_gpio(85);
+}
+
+static struct platform_device *pxa25x_devices[] __initdata = {
+       &pxamci_device,
+       &pxaudc_device,
+       &pxafb_device,
+       &ffuart_device,
+       &btuart_device,
+       &stuart_device,
+       &pxai2c_device,
+       &pxai2s_device,
+       &pxaficp_device,
+       &pxartc_device,
+};
+
+static int __init pxa25x_init(void)
+{
+       int ret = 0;
+
+       if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
+               if ((ret = pxa_init_dma(16)))
+                       return ret;
+#ifdef CONFIG_PM
+               pm_set_ops(&pxa25x_pm_ops);
 #endif
+               ret = platform_add_devices(pxa25x_devices,
+                                          ARRAY_SIZE(pxa25x_devices));
+       }
+       /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+       if (cpu_is_pxa25x())
+               ret = platform_device_register(&hwuart_device);
+
+       return ret;
+}
+
+subsys_initcall(pxa25x_init);
index 1939acc3f9f7f6cdbd21e9d4fbc07ed55230686a..aa5bb02c897bd331c59ce29b1bcbc10c2be83e81 100644 (file)
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/arch/irqs.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/ohci.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /* Crystal clock: 13MHz */
 #define BASE_CLK       13000000
@@ -122,17 +126,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
 
 #ifdef CONFIG_PM
 
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_MEM:
-       case PM_SUSPEND_STANDBY:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
 void pxa_cpu_pm_enter(suspend_state_t state)
 {
        extern void pxa_cpu_standby(void);
@@ -162,6 +155,15 @@ void pxa_cpu_pm_enter(suspend_state_t state)
        }
 }
 
+static int pxa27x_pm_valid(suspend_state_t state)
+{
+       return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
+}
+
+static struct pm_ops pxa27x_pm_ops = {
+       .enter          = pxa_pm_enter,
+       .valid          = pxa27x_pm_valid,
+};
 #endif
 
 /*
@@ -183,7 +185,7 @@ static struct resource pxa27x_ohci_resources[] = {
        },
 };
 
-static struct platform_device ohci_device = {
+static struct platform_device pxaohci_device = {
        .name           = "pxa27x-ohci",
        .id             = -1,
        .dev            = {
@@ -196,16 +198,62 @@ static struct platform_device ohci_device = {
 
 void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
 {
-       ohci_device.dev.platform_data = info;
+       pxaohci_device.dev.platform_data = info;
 }
 
+static struct resource i2c_power_resources[] = {
+       {
+               .start  = 0x40f00180,
+               .end    = 0x40f001a3,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_PWRI2C,
+               .end    = IRQ_PWRI2C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device pxai2c_power_device = {
+       .name           = "pxa2xx-i2c",
+       .id             = 1,
+       .resource       = i2c_power_resources,
+       .num_resources  = ARRAY_SIZE(i2c_power_resources),
+};
+
 static struct platform_device *devices[] __initdata = {
-       &ohci_device,
+       &pxamci_device,
+       &pxaudc_device,
+       &pxafb_device,
+       &ffuart_device,
+       &btuart_device,
+       &stuart_device,
+       &pxai2c_device,
+       &pxai2c_power_device,
+       &pxai2s_device,
+       &pxaficp_device,
+       &pxartc_device,
+       &pxaohci_device,
 };
 
+void __init pxa27x_init_irq(void)
+{
+       pxa_init_irq_low();
+       pxa_init_irq_high();
+       pxa_init_irq_gpio(128);
+}
+
 static int __init pxa27x_init(void)
 {
-       return platform_add_devices(devices, ARRAY_SIZE(devices));
+       int ret = 0;
+       if (cpu_is_pxa27x()) {
+               if ((ret = pxa_init_dma(32)))
+                       return ret;
+#ifdef CONFIG_PM
+               pm_set_ops(&pxa27x_pm_ops);
+#endif
+               ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+       }
+       return ret;
 }
 
 subsys_initcall(pxa27x_init);
index 3cbac63bed3c0b952db4c2af7149da2f6926c07d..bae47e145de83e01eefaf1b6fd2b05a0265f6f7a 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "devices.h"
 #include "sharpsl.h"
 
 /*
@@ -560,7 +561,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_spitz,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -572,7 +573,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_spitz,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -584,7 +585,7 @@ MACHINE_START(AKITA, "SHARP Akita")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_spitz,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .init_machine   = akita_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 5248abe334d23f6966ea63f2c0a8462f69878261..6f91fd2d061ab0b9dc5062d5db3c551e03f6198e 100644 (file)
 #include <asm/arch/pxa-regs.h>
 
 
-static inline unsigned long pxa_get_rtc_time(void)
-{
-       return RCNR;
-}
-
 static int pxa_set_rtc(void)
 {
        unsigned long current_time = xtime.tv_sec;
@@ -122,10 +117,6 @@ static void __init pxa_timer_init(void)
 
        set_rtc = pxa_set_rtc;
 
-       tv.tv_nsec = 0;
-       tv.tv_sec = pxa_get_rtc_time();
-       do_settimeofday(&tv);
-
        OIER = 0;               /* disable any timer interrupts */
        OSSR = 0xf;             /* clear status on all timers */
        setup_irq(IRQ_OST0, &pxa_timer_irq);
index 72738771fb57cbf05495fa784f80c50215c52f92..240fd042083da10e6639f36c2b33dec5c2b8f895 100644 (file)
@@ -42,7 +42,7 @@
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /*
  * SCOOP Device
@@ -332,7 +332,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .fixup          = fixup_tosa,
        .map_io         = pxa_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa25x_init_irq,
        .init_machine   = tosa_init,
        .timer          = &pxa_timer,
 MACHINE_END
index 28c79bd0a3a0da9c7fd741c24534e3cf62fc7e4c..e4ba43bdf85d9756123e13bd105b1024ef42a240 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/arch/ohci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 /********************************************************************************************
  * ONBOARD FLASH
@@ -503,7 +504,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
-       .init_irq       = pxa_init_irq,
+       .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
 
index d674cf3431567c88bdf5181ef99a7ab17c04fb36..01a37d3c0727de0c631dcbcd5e9c5378433c2946 100644 (file)
@@ -57,12 +57,7 @@ enum {       SLEEP_SAVE_SP = 0,
 static int sa11x0_pm_enter(suspend_state_t state)
 {
        unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
-       struct timespec delta, rtc;
 
-       /* preserve current time */
-       rtc.tv_sec = RCNR;
-       rtc.tv_nsec = 0;
-       save_time_delta(&delta, &rtc);
        gpio = GPLR;
 
        /* save vital registers */
@@ -119,10 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
         */
        PSSR = PSSR_PH;
 
-       /* restore current time */
-       rtc.tv_sec = RCNR;
-       restore_time_delta(&delta, &rtc);
-
        return 0;
 }
 
index 29cb0c1604ab896c719c86be3b147cbf1b1a737d..fdf7b016e7adeadfa5652ae9779803209eba3d91 100644 (file)
 #define RTC_DEF_DIVIDER                (32768 - 1)
 #define RTC_DEF_TRIM            0
 
-static unsigned long __init sa1100_get_rtc_time(void)
-{
-       /*
-        * According to the manual we should be able to let RTTR be zero
-        * and then a default divisor for a 32.768KHz clock is used.
-        * Apparently this doesn't work, at least for my SA1110 rev 5.
-        * If the clock divider is uninitialized then reset it to the
-        * default value to get the 1Hz clock.
-        */
-       if (RTTR == 0) {
-               RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-               printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
-               /* The current RTC value probably doesn't make sense either */
-               RCNR = 0;
-               return 0;
-       }
-       return RCNR;
-}
-
 static int sa1100_set_rtc(void)
 {
        unsigned long current_time = xtime.tv_sec;
@@ -117,15 +98,10 @@ static struct irqaction sa1100_timer_irq = {
 
 static void __init sa1100_timer_init(void)
 {
-       struct timespec tv;
        unsigned long flags;
 
        set_rtc = sa1100_set_rtc;
 
-       tv.tv_nsec = 0;
-       tv.tv_sec = sa1100_get_rtc_time();
-       do_settimeofday(&tv);
-
        OIER = 0;               /* disable any timer interrupts */
        OSSR = 0xf;             /* clear status on all timers */
        setup_irq(IRQ_OST0, &sa1100_timer_irq);
index f3ade18862aaa8fd8e63488bc3eee36253c4e0f7..75952779ce1991f68114dcbeef6a188c4c47d027 100644 (file)
@@ -280,7 +280,10 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
        if (!type)
                return NULL;
 
-       size = PAGE_ALIGN(size);
+       /*
+        * Page align the mapping size, taking account of any offset.
+        */
+       size = PAGE_ALIGN(offset + size);
 
        area = get_vm_area(size, VM_IOREMAP);
        if (!area)
@@ -325,11 +328,6 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
        if (!size || last_addr < phys_addr)
                return NULL;
 
-       /*
-        * Page align the mapping size
-        */
-       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
        return __arm_ioremap_pfn(pfn, offset, size, mtype);
 }
 EXPORT_SYMBOL(__arm_ioremap);
index 1b163220df2bad67727bf242ab982333dd6b5e54..df17c281278a68d272a21756b1be5eb1f1d9c82f 100644 (file)
@@ -1,25 +1,3 @@
-#undef MMC_STRPCL
-#undef MMC_STAT
-#undef MMC_CLKRT
-#undef MMC_SPI
-#undef MMC_CMDAT
-#undef MMC_RESTO
-#undef MMC_RDTO
-#undef MMC_BLKLEN
-#undef MMC_NOB
-#undef MMC_PRTBUF
-#undef MMC_I_MASK
-#undef END_CMD_RES
-#undef PRG_DONE
-#undef DATA_TRAN_DONE
-#undef MMC_I_REG
-#undef MMC_CMD
-#undef MMC_ARGH
-#undef MMC_ARGL
-#undef MMC_RES
-#undef MMC_RXFIFO
-#undef MMC_TXFIFO
-
 #define MMC_STRPCL     0x0000
 #define STOP_CLOCK             (1 << 0)
 #define START_CLOCK            (2 << 0)
index c68e1680da0173d5754d1a1df4944120a5239e58..73237bd130a28b16f35709fa432c2457f8c0191c 100644 (file)
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+unifdef-y += hwcap.h
index b0369e176f7bbd95a3fa333498a77a43b5f136dc..8019ffd0ad3b61a23ee920a3b6b79e2009b16ec6 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef AT91_DBGU_H
 #define AT91_DBGU_H
 
+#ifdef AT91_DBGU
 #define AT91_DBGU_CR           (AT91_DBGU + 0x00)      /* Control Register */
 #define AT91_DBGU_MR           (AT91_DBGU + 0x04)      /* Mode Register */
 #define AT91_DBGU_IER          (AT91_DBGU + 0x08)      /* Interrupt Enable Register */
 
 #define AT91_DBGU_CIDR         (AT91_DBGU + 0x40)      /* Chip ID Register */
 #define AT91_DBGU_EXID         (AT91_DBGU + 0x44)      /* Chip ID Extension Register */
+#define AT91_DBGU_FNR          (AT91_DBGU + 0x48)      /* Force NTRST Register [SAM9 only] */
+#define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
+
+#endif /* AT91_DBGU */
+
+/*
+ * Some AT91 parts that don't have full DEBUG units still support the ID
+ * and extensions register.
+ */
 #define                AT91_CIDR_VERSION       (0x1f << 0)             /* Version of the Device */
 #define                AT91_CIDR_EPROC         (7    << 5)             /* Embedded Processor */
 #define                AT91_CIDR_NVPSIZ        (0xf  << 8)             /* Nonvolatile Program Memory Size */
@@ -53,7 +63,4 @@
 #define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
 #define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
 
-#define AT91_DBGU_FNR          (AT91_DBGU + 0x48)      /* Force NTRST Register [SAM9 only] */
-#define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
-
 #endif
diff --git a/include/asm-arm/arch-at91/at91x40.h b/include/asm-arm/arch-at91/at91x40.h
new file mode 100644 (file)
index 0000000..612203e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-at91/at91x40.h
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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.
+ */
+
+#ifndef AT91X40_H
+#define AT91X40_H
+
+/*
+ *     IRQ list.
+ */
+#define AT91_ID_FIQ            0       /* FIQ */
+#define AT91_ID_SYS            1       /* System Peripheral */
+#define AT91X40_ID_USART0      2       /* USART port 0 */
+#define AT91X40_ID_USART1      3       /* USART port 1 */
+#define AT91X40_ID_TC0         4       /* Timer/Counter 0 */
+#define AT91X40_ID_TC1         5       /* Timer/Counter 1*/
+#define AT91X40_ID_TC2         6       /* Timer/Counter 2*/
+#define AT91X40_ID_WD          7       /* Watchdog? */
+#define AT91X40_ID_PIOA                8       /* Parallel IO Controller A */
+
+#define AT91X40_ID_IRQ0                16      /* External IRQ 0 */
+#define AT91X40_ID_IRQ1                17      /* External IRQ 1 */
+#define AT91X40_ID_IRQ2                18      /* External IRQ 2 */
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_BASE_SYS  0xffc00000
+
+#define AT91_EBI       (0xffe00000 - AT91_BASE_SYS)    /* External Bus Interface */
+#define AT91_SF                (0xfff00000 - AT91_BASE_SYS)    /* Special Function */
+#define AT91_USART1    (0xfffcc000 - AT91_BASE_SYS)    /* USART 1 */
+#define AT91_USART0    (0xfffd0000 - AT91_BASE_SYS)    /* USART 0 */
+#define AT91_TC                (0xfffe0000 - AT91_BASE_SYS)    /* Timer Counter */
+#define AT91_PIOA      (0xffff0000 - AT91_BASE_SYS)    /* PIO Controller A */
+#define AT91_PS                (0xffff4000 - AT91_BASE_SYS)    /* Power Save */
+#define AT91_WD                (0xffff8000 - AT91_BASE_SYS)    /* Watchdog Timer */
+#define AT91_AIC       (0xfffff000 - AT91_BASE_SYS)    /* Advanced Interrupt Controller */
+
+/*
+ * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
+ * But it does have a chip identify register and extension ID, so define at
+ * least these here.
+ */
+#define AT91_DBGU_CIDR (AT91_SF + 0)   /* CIDR in PS segment */
+#define AT91_DBGU_EXID (AT91_SF + 4)   /* EXID in PS segment */
+
+#endif /* AT91X40_H */
index ef93c30a9c5fd17fd642c35be4c5f51c9ecdb98b..080cbb401a874efd1e7e2e6b056e4f2ddd73287a 100644 (file)
 
 #define ARCH_ID_AT91SAM9RL64   0x019b03a0
 
+#define ARCH_ID_AT91M40800     0x14080044
+#define ARCH_ID_AT91R40807     0x44080746
+#define ARCH_ID_AT91M40807     0x14080745
+#define ARCH_ID_AT91R40008     0x44000840
+
 static inline unsigned long at91_cpu_identify(void)
 {
        return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
index 46835e945aea0b875a9e5f252155c0d27355f381..8f1cdd38a96986fe31f9ce47a34fac0a236ca053 100644 (file)
 #include <asm/arch/at91sam9263.h>
 #elif defined(CONFIG_ARCH_AT91SAM9RL)
 #include <asm/arch/at91sam9rl.h>
+#elif defined(CONFIG_ARCH_AT91X40)
+#include <asm/arch/at91x40.h>
 #else
 #error "Unsupported AT91 processor"
 #endif
 
 
+#ifdef CONFIG_MMU
 /*
  * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
  * to 0xFEF78000 .. 0xFF000000.  (544Kb)
  */
 #define AT91_IO_PHYS_BASE      0xFFF78000
-#define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 #define AT91_IO_VIRT_BASE      (0xFF000000 - AT91_IO_SIZE)
+#else
+/*
+ * Identity mapping for the non MMU case.
+ */
+#define AT91_IO_PHYS_BASE      AT91_BASE_SYS
+#define AT91_IO_VIRT_BASE      AT91_IO_PHYS_BASE
+#endif
+
+#define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
 
  /* Convert a physical IO address to virtual IO address */
 #define AT91_IO_P2V(x)         ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
 #define AT91_CHIPSELECT_7      0x80000000
 
 /* SDRAM */
+#ifdef CONFIG_DRAM_BASE
+#define AT91_SDRAM_BASE                CONFIG_DRAM_BASE
+#else
 #define AT91_SDRAM_BASE                AT91_CHIPSELECT_1
+#endif
 
 /* Clocks */
 #define AT91_SLOW_CLOCK                32768           /* slow clock */
index 2df1ee12dfb797a1a70adc3a7cb4f5015eeea8b3..a310698fb4da9eb04e32b3772dd1f52a75732a8e 100644 (file)
 #define AT91SAM9_MASTER_CLOCK  100000000
 #define CLOCK_TICK_RATE                (AT91SAM9_MASTER_CLOCK/16)
 
+#elif defined(CONFIG_ARCH_AT91X40)
+
+#define AT91X40_MASTER_CLOCK   40000000
+#define CLOCK_TICK_RATE                (AT91X40_MASTER_CLOCK)
+
 #endif
 
 #endif
index 30ac587b3b41d415eeb4d11739488ec33d649314..272a7e0dc6cf928c11a4328741a03e5302441c8e 100644 (file)
  */
 static void putc(int c)
 {
+#ifdef AT91_DBGU
        void __iomem *sys = (void __iomem *) AT91_BASE_SYS;     /* physical address */
 
        while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
                barrier();
        __raw_writel(c, sys + AT91_DBGU_THR);
+#endif
 }
 
 static inline void flush(void)
 {
+#ifdef AT91_DBGU
        void __iomem *sys = (void __iomem *) AT91_BASE_SYS;     /* physical address */
 
        /* wait for transmission to complete */
        while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
                barrier();
+#endif
 }
 
 #define arch_decomp_setup()
diff --git a/include/asm-arm/arch-davinci/clock.h b/include/asm-arm/arch-davinci/clock.h
new file mode 100644 (file)
index 0000000..cc168b7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-davinci/clock.h
+ *
+ * Clock control driver for DaVinci - header file
+ *
+ * Authors: Vladimir Barinov <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
+#define __ASM_ARCH_DAVINCI_CLOCK_H
+
+struct clk;
+
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+extern int davinci_clk_init(void);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
new file mode 100644 (file)
index 0000000..ea24a0e
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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.
+ */
+
+#ifndef        __DAVINCI_GPIO_H
+#define        __DAVINCI_GPIO_H
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation, and maybe
+ * for later updates, code should write GPIO(N) or:
+ *  - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
+ *  - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
+ *
+ * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
+ * for now, that's != GPIO(N)
+ */
+#define        GPIO(X)         (X)             /* 0 <= X <= 70 */
+#define        GPIOV18(X)      (X)             /* 1.8V i/o; 0 <= X <= 53 */
+#define        GPIOV33(X)      ((X)+54)        /* 3.3V i/o; 0 <= X <= 17 */
+
+struct gpio_controller {
+       u32     dir;
+       u32     out_data;
+       u32     set_data;
+       u32     clr_data;
+       u32     in_data;
+       u32     set_rising;
+       u32     clr_rising;
+       u32     set_falling;
+       u32     clr_falling;
+       u32     intstat;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct gpio_controller *__iomem
+__gpio_to_controller(unsigned gpio)
+{
+       void *__iomem ptr;
+
+       if (gpio < 32)
+               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+       else if (gpio < 64)
+               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+       else if (gpio < DAVINCI_N_GPIO)
+               ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+       else
+               ptr = NULL;
+       return ptr;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+       return 1 << (gpio % 32);
+}
+
+/* The get/set/clear functions will inline when called with constant
+ * parameters, for low-overhead bitbanging.  Illegal constant parameters
+ * cause link-time errors.
+ *
+ * Otherwise, calls with variable parameters use outlined functions.
+ */
+extern int __error_inval_gpio(void);
+
+extern void __gpio_set(unsigned gpio, int value);
+extern int __gpio_get(unsigned gpio);
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       if (__builtin_constant_p(value)) {
+               struct gpio_controller  *__iomem g;
+               u32                     mask;
+
+               if (gpio >= DAVINCI_N_GPIO)
+                       __error_inval_gpio();
+
+               g = __gpio_to_controller(gpio);
+               mask = __gpio_mask(gpio);
+               if (value)
+                       __raw_writel(mask, &g->set_data);
+               else
+                       __raw_writel(mask, &g->clr_data);
+               return;
+       }
+
+       __gpio_set(gpio, value);
+}
+
+/* Returns zero or nonzero; works for gpios configured as inputs OR
+ * as outputs.
+ *
+ * NOTE: changes in reported values are synchronized to the GPIO clock.
+ * This is most easily seen after calling gpio_set_value() and then immediatly
+ * gpio_get_value(), where the gpio_get_value() would return the old value
+ * until the GPIO clock ticks and the new value gets latched.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+       struct gpio_controller *__iomem g;
+
+       if (!__builtin_constant_p(gpio))
+               return __gpio_get(gpio);
+
+       if (gpio >= DAVINCI_N_GPIO)
+               return __error_inval_gpio();
+
+       g = __gpio_to_controller(gpio);
+       return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+
+/* powerup default direction is IN */
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+
+#include <asm-generic/gpio.h>  /* cansleep wrappers */
+
+extern int gpio_request(unsigned gpio, const char *tag);
+extern void gpio_free(unsigned gpio);
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return DAVINCI_N_AINTC_IRQ + gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return irq - DAVINCI_N_AINTC_IRQ;
+}
+
+#endif                         /* __DAVINCI_GPIO_H */
index 60362d80229e66f6a12c69ec4e2455096763b15c..a2e8969afaca913c263dbb98f419dab6c3fa3799 100644 (file)
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+/*
+ * Base register addresses
+ */
+#define DAVINCI_DMA_3PCC_BASE                  (0x01C00000)
+#define DAVINCI_DMA_3PTC0_BASE                 (0x01C10000)
+#define DAVINCI_DMA_3PTC1_BASE                 (0x01C10400)
+#define DAVINCI_I2C_BASE                       (0x01C21000)
+#define DAVINCI_PWM0_BASE                      (0x01C22000)
+#define DAVINCI_PWM1_BASE                      (0x01C22400)
+#define DAVINCI_PWM2_BASE                      (0x01C22800)
+#define DAVINCI_SYSTEM_MODULE_BASE             (0x01C40000)
+#define DAVINCI_PLL_CNTRL0_BASE                        (0x01C40800)
+#define DAVINCI_PLL_CNTRL1_BASE                        (0x01C40C00)
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE           (0x01C41000)
+#define DAVINCI_SYSTEM_DFT_BASE                        (0x01C42000)
+#define DAVINCI_IEEE1394_BASE                  (0x01C60000)
+#define DAVINCI_USB_OTG_BASE                   (0x01C64000)
+#define DAVINCI_CFC_ATA_BASE                   (0x01C66000)
+#define DAVINCI_SPI_BASE                       (0x01C66800)
+#define DAVINCI_GPIO_BASE                      (0x01C67000)
+#define DAVINCI_UHPI_BASE                      (0x01C67800)
+#define DAVINCI_VPSS_REGS_BASE                 (0x01C70000)
+#define DAVINCI_EMAC_CNTRL_REGS_BASE           (0x01C80000)
+#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE   (0x01C81000)
+#define DAVINCI_EMAC_WRAPPER_RAM_BASE          (0x01C82000)
+#define DAVINCI_MDIO_CNTRL_REGS_BASE           (0x01C84000)
+#define DAVINCI_IMCOP_BASE                     (0x01CC0000)
+#define DAVINCI_ASYNC_EMIF_CNTRL_BASE          (0x01E00000)
+#define DAVINCI_VLYNQ_BASE                     (0x01E01000)
+#define DAVINCI_MCBSP_BASE                     (0x01E02000)
+#define DAVINCI_MMC_SD_BASE                    (0x01E10000)
+#define DAVINCI_MS_BASE                                (0x01E20000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE       (0x02000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE       (0x04000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE       (0x06000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE       (0x08000000)
+#define DAVINCI_VLYNQ_REMOTE_BASE              (0x0C000000)
+
 #endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-davinci/mux.h b/include/asm-arm/arch-davinci/mux.h
new file mode 100644 (file)
index 0000000..c24b678
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * DaVinci pin multiplexing defines
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_MUX_H
+#define __ASM_ARCH_MUX_H
+
+#define DAVINCI_MUX_AEAW0      0
+#define DAVINCI_MUX_AEAW1      1
+#define DAVINCI_MUX_AEAW2      2
+#define DAVINCI_MUX_AEAW3      3
+#define DAVINCI_MUX_AEAW4      4
+#define DAVINCI_MUX_AECS4      10
+#define DAVINCI_MUX_AECS5      11
+#define DAVINCI_MUX_VLYNQWD0   12
+#define DAVINCI_MUX_VLYNQWD1   13
+#define DAVINCI_MUX_VLSCREN    14
+#define DAVINCI_MUX_VLYNQEN    15
+#define DAVINCI_MUX_HDIREN     16
+#define DAVINCI_MUX_ATAEN      17
+#define DAVINCI_MUX_RGB666     22
+#define DAVINCI_MUX_RGB888     23
+#define DAVINCI_MUX_LOEEN      24
+#define DAVINCI_MUX_LFLDEN     25
+#define DAVINCI_MUX_CWEN       26
+#define DAVINCI_MUX_CFLDEN     27
+#define DAVINCI_MUX_HPIEN      29
+#define DAVINCI_MUX_1394EN     30
+#define DAVINCI_MUX_EMACEN     31
+
+#define DAVINCI_MUX_LEVEL2     32
+#define DAVINCI_MUX_UART0      (DAVINCI_MUX_LEVEL2 + 0)
+#define DAVINCI_MUX_UART1      (DAVINCI_MUX_LEVEL2 + 1)
+#define DAVINCI_MUX_UART2      (DAVINCI_MUX_LEVEL2 + 2)
+#define DAVINCI_MUX_U2FLO      (DAVINCI_MUX_LEVEL2 + 3)
+#define DAVINCI_MUX_PWM0       (DAVINCI_MUX_LEVEL2 + 4)
+#define DAVINCI_MUX_PWM1       (DAVINCI_MUX_LEVEL2 + 5)
+#define DAVINCI_MUX_PWM2       (DAVINCI_MUX_LEVEL2 + 6)
+#define DAVINCI_MUX_I2C                (DAVINCI_MUX_LEVEL2 + 7)
+#define DAVINCI_MUX_SPI                (DAVINCI_MUX_LEVEL2 + 8)
+#define DAVINCI_MUX_MSTK       (DAVINCI_MUX_LEVEL2 + 9)
+#define DAVINCI_MUX_ASP                (DAVINCI_MUX_LEVEL2 + 10)
+#define DAVINCI_MUX_CLK0       (DAVINCI_MUX_LEVEL2 + 16)
+#define DAVINCI_MUX_CLK1       (DAVINCI_MUX_LEVEL2 + 17)
+#define DAVINCI_MUX_TIMIN      (DAVINCI_MUX_LEVEL2 + 18)
+
+extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
+
+#endif /* __ASM_ARCH_MUX_H */
diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h
new file mode 100644 (file)
index 0000000..4860232
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef _IMX_GPIO_H
+
+#include <asm/arch/imx-regs.h>
+
+#define IMX_GPIO_ALLOC_MODE_NORMAL     0
+#define IMX_GPIO_ALLOC_MODE_NO_ALLOC   1
+#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC  2
+#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY 4
+#define IMX_GPIO_ALLOC_MODE_RELEASE    8
+
+extern int imx_gpio_request(unsigned gpio, const char *label);
+
+extern void imx_gpio_free(unsigned gpio);
+
+extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                                       int alloc_mode, const char *label);
+
+extern int imx_gpio_direction_input(unsigned gpio);
+
+extern int imx_gpio_direction_output(unsigned gpio, int value);
+
+extern void __imx_gpio_set_value(unsigned gpio, int value);
+
+static inline int imx_gpio_get_value(unsigned gpio)
+{
+       return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
+}
+
+static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
+{
+       unsigned long flags;
+
+       raw_local_irq_save(flags);
+       if(value)
+               DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
+       else
+               DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
+       raw_local_irq_restore(flags);
+}
+
+static inline void imx_gpio_set_value(unsigned gpio, int value)
+{
+       if(__builtin_constant_p(gpio))
+               imx_gpio_set_value_inline(gpio, value);
+       else
+               __imx_gpio_set_value(gpio, value);
+}
+
+extern int imx_gpio_to_irq(unsigned gpio);
+
+extern int imx_irq_to_gpio(unsigned irq);
+
+/*-------------------------------------------------------------------------*/
+
+/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
+ * to allow future extension of GPIO logic.
+ */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+       return imx_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+       imx_gpio_free(gpio);
+}
+
+static inline  int gpio_direction_input(unsigned gpio)
+{
+       return imx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+       return imx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+       return imx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       imx_gpio_set_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>          /* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return imx_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return imx_irq_to_gpio(irq);
+}
+
+
+#endif
index 30de404c61f5ef71e1243e0dada38cbed8e277c9..fb9de27338796ab23d480cc250b86c55c27d8ed6 100644 (file)
@@ -77,6 +77,8 @@
 #define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
 #define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
 
+#define GPIO_PORT_MAX  3
+
 #define GPIO_PIN_MASK 0x1f
 #define GPIO_PORT_MASK (0x3 << 5)
 
index 3d3820d7ba09f71847bb9256aac2c6a7bb71b1ea..e0791af3bfead32bd7483965281dc68b353d9c47 100644 (file)
@@ -32,4 +32,8 @@
 #define        IXDP425_PCI_INTC_PIN    9
 #define        IXDP425_PCI_INTD_PIN    8
 
+/* NAND Flash pins */
+#define        IXDP425_NAND_NCE_PIN    12
 
+#define        IXDP425_NAND_CMD_BYTE   0x01
+#define        IXDP425_NAND_ADDR_BYTE  0x02
index 09ae6c91be60b075c3e972b383841515a9506900..f7a35b78823ff0227c44c6e4d9cc4d6052408ddd 100644 (file)
@@ -38,9 +38,10 @@ static void flush(void)
 static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 {
        /*
-        * Coyote and gtwx5715 only have UART2 connected
+        * Some boards are using UART2 as console
         */
-       if (machine_is_adi_coyote() || machine_is_gtwx5715())
+       if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
+                        machine_is_gateway7001() || machine_is_wg302v2())
                uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
        else
                uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/include/asm-arm/arch-ks8695/gpio.h b/include/asm-arm/arch-ks8695/gpio.h
new file mode 100644 (file)
index 0000000..65ceea2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * include/asm-arm/arch-ks8695/gpio.h
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * 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 __ASM_ARCH_GPIO_H_
+#define __ASM_ARCH_GPIO_H_
+
+#define KS8695_GPIO_0          0
+#define KS8695_GPIO_1          1
+#define KS8695_GPIO_2          2
+#define KS8695_GPIO_3          3
+#define KS8695_GPIO_4          4
+#define KS8695_GPIO_5          5
+#define KS8695_GPIO_6          6
+#define KS8695_GPIO_7          7
+#define KS8695_GPIO_8          8
+#define KS8695_GPIO_9          9
+#define KS8695_GPIO_10         10
+#define KS8695_GPIO_11         11
+#define KS8695_GPIO_12         12
+#define KS8695_GPIO_13         13
+#define KS8695_GPIO_14         14
+#define KS8695_GPIO_15         15
+
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin);
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state);
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin);
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin);
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq);
+
+
+#include <asm-generic/gpio.h>
+
+static inline int gpio_request(unsigned int pin, const char *label)
+{
+       return 0;
+}
+
+static inline void gpio_free(unsigned int pin)
+{
+}
+
+#endif
index bed042d71d68dd7154e5cf5ed0c4035230858706..3280ee2ddfa591cbbbe42e1336c7b89f4627e2aa 100644 (file)
@@ -30,30 +30,12 @@ typedef enum {
        DMA_PRIO_LOW = 2
 } pxa_dma_prio;
 
-#if defined(CONFIG_PXA27x)
-
-#define PXA_DMA_CHANNELS       32
-
-#define pxa_for_each_dma_prio(ch, prio)                                        \
-for (                                                                  \
-       ch = prio * 4;                                                  \
-       ch != (4 << prio) + 16;                                         \
-       ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1)       \
-)
-
-#elif defined(CONFIG_PXA25x)
-
-#define PXA_DMA_CHANNELS       16
-
-#define pxa_for_each_dma_prio(ch, prio)                                        \
-       for (ch = prio * 4; ch != (4 << prio); ch++)
-
-#endif
-
 /*
  * DMA registration
  */
 
+int __init pxa_init_dma(int num_ch);
+
 int pxa_request_dma (char *name,
                         pxa_dma_prio prio,
                         void (*irq_handler)(int, void *),
index 1d5fbb9b379a03652b3c8347ef1adaed15bce146..b7e730851461d635f38eff192b9ab6011053f98f 100644 (file)
                .endm
 
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifdef CONFIG_PXA27x
-               mrc     p6, 0, \irqstat, c0, c0, 0              @ ICIP
-               mrc     p6, 0, \irqnr, c1, c0, 0                @ ICMR
-#else
+               mrc     p15, 0, \tmp, c0, c0, 0         @ CPUID
+               mov     \tmp, \tmp, lsr #13
+               and     \tmp, \tmp, #0x7                @ Core G
+               cmp     \tmp, #1
+               bhi     1004f
+
                mov     \base, #io_p2v(0x40000000)      @ IIR Ctl = 0x40d00000
                add     \base, \base, #0x00d00000
                ldr     \irqstat, [\base, #0]           @ ICIP
                ldr     \irqnr, [\base, #4]             @ ICMR
-#endif
+               b       1002f
+
+1004:
+               mrc     p6, 0, \irqstat, c6, c0, 0      @ ICIP2
+               mrc     p6, 0, \irqnr, c7, c0, 0        @ ICMR2
+               ands    \irqstat, \irqstat, \irqnr
+               beq     1003f
+               rsb     \irqstat, \irqnr, #0
+               and     \irqstat, \irqstat, \irqnr
+               clz     \irqnr, \irqstat
+               rsb     \irqnr, \irqnr, #31
+               add     \irqnr, \irqnr, #32
+               b       1001f
+1003:
+               mrc     p6, 0, \irqstat, c0, c0, 0      @ ICIP
+               mrc     p6, 0, \irqnr, c1, c0, 0        @ ICMR
+1002:
                ands    \irqnr, \irqstat, \irqnr
                beq     1001f
                rsb     \irqstat, \irqnr, #0
                and     \irqstat, \irqstat, \irqnr
                clz     \irqnr, \irqstat
-               rsb     \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
+               rsb     \irqnr, \irqnr, #31
 1001:
                .endm
index e2bdc2fbede1efdd52e1a393601edb3c2f5f4e91..386121746417093c90d6807bda3cc90d3d2c7e91 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+#define __cpu_is_pxa21x(id)                            \
+       ({                                              \
+               unsigned int _id = (id) >> 4 & 0xf3f;   \
+               _id == 0x212;                           \
+       })
+
+#define __cpu_is_pxa25x(id)                            \
+       ({                                              \
+               unsigned int _id = (id) >> 4 & 0xfff;   \
+               _id == 0x2d0 || _id == 0x290;           \
+       })
+
+#define __cpu_is_pxa27x(id)                            \
+       ({                                              \
+               unsigned int _id = (id) >> 4 & 0xfff;   \
+               _id == 0x411;                           \
+       })
+
+#define cpu_is_pxa21x()                                        \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+               __cpu_is_pxa21x(id);                    \
+       })
+
+#define cpu_is_pxa25x()                                        \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+               __cpu_is_pxa25x(id);                    \
+       })
+
+#define cpu_is_pxa27x()                                        \
+       ({                                              \
+               unsigned int id = read_cpuid(CPUID_ID); \
+               __cpu_is_pxa27x(id);                    \
+       })
+
 /*
  * Handy routine to set GPIO alternate functions
  */
index 67ed43674c635a66a3a947accb3a757810fdd260..a07fe0f928cd1f4fdea379338ba18d5d4f0675ae 100644 (file)
  */
 
 
-#ifdef CONFIG_PXA27x
-#define PXA_IRQ_SKIP   0
-#else
-#define PXA_IRQ_SKIP   7
-#endif
-
-#define PXA_IRQ(x)     ((x) - PXA_IRQ_SKIP)
+#define PXA_IRQ(x)     (x)
 
+#ifdef CONFIG_PXA27x
 #define IRQ_SSP3       PXA_IRQ(0)      /* SSP3 service request */
 #define IRQ_MSL                PXA_IRQ(1)      /* MSL Interface interrupt */
 #define IRQ_USBH2      PXA_IRQ(2)      /* USB Host interrupt 1 (OHCI) */
@@ -26,6 +21,8 @@
 #define IRQ_KEYPAD     PXA_IRQ(4)      /* Key pad controller */
 #define IRQ_MEMSTK     PXA_IRQ(5)      /* Memory Stick interrupt */
 #define IRQ_PWRI2C     PXA_IRQ(6)      /* Power I2C interrupt */
+#endif
+
 #define IRQ_HWUART     PXA_IRQ(7)      /* HWUART Transmit/Receive/Error (PXA26x) */
 #define IRQ_OST_4_11   PXA_IRQ(7)      /* OS timer 4-11 matches (PXA27x) */
 #define        IRQ_GPIO0       PXA_IRQ(8)      /* GPIO0 Edge Detect */
 #ifdef CONFIG_PXA27x
 #define IRQ_TPM                PXA_IRQ(32)     /* TPM interrupt */
 #define IRQ_CAMERA     PXA_IRQ(33)     /* Camera Interface */
-
-#define PXA_INTERNAL_IRQS 34
-#else
-#define PXA_INTERNAL_IRQS 32
 #endif
 
-#define GPIO_2_x_TO_IRQ(x)     \
-                       PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define PXA_GPIO_IRQ_BASE      (64)
+#define PXA_GPIO_IRQ_NUM       (128)
+
+#define GPIO_2_x_TO_IRQ(x)     (PXA_GPIO_IRQ_BASE + (x))
 #define IRQ_GPIO(x)    (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
 
-#define IRQ_TO_GPIO_2_x(i)     \
-                       ((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO_2_x(i)     ((i) - PXA_GPIO_IRQ_BASE)
 #define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
 
 #if defined(CONFIG_PXA25x)
@@ -84,7 +78,7 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.
  */
-#define IRQ_BOARD_START                (IRQ_GPIO(PXA_LAST_GPIO) + 1)
+#define IRQ_BOARD_START                (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
 #define IRQ_BOARD_END          (IRQ_BOARD_START + 16)
 
 #define IRQ_SA1111_START       (IRQ_BOARD_END)
index 7a8a1cdf430ddaaf80d1bf9939b5975fa49d9e7b..52243a62c4e76de36fbe21f8aa10d4846684e283 100644 (file)
@@ -9,4 +9,3 @@
 
 extern int pxa_pm_prepare(suspend_state_t state);
 extern int pxa_pm_enter(suspend_state_t state);
-extern int pxa_pm_finish(suspend_state_t state);
index dbcc9298b0c89b7cc5880fd3d9a420fe4d89f3fc..e68b593d69da28638390fa3d89b55425fc032ea9 100644 (file)
 #define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL))
 
 /*
- * MultiMediaCard (MMC) controller
+ * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h
  */
 
-#define MMC_STRPCL     __REG(0x41100000)  /* Control to start and stop MMC clock */
-#define MMC_STAT       __REG(0x41100004)  /* MMC Status Register (read only) */
-#define MMC_CLKRT      __REG(0x41100008)  /* MMC clock rate */
-#define MMC_SPI                __REG(0x4110000c)  /* SPI mode control bits */
-#define MMC_CMDAT      __REG(0x41100010)  /* Command/response/data sequence control */
-#define MMC_RESTO      __REG(0x41100014)  /* Expected response time out */
-#define MMC_RDTO       __REG(0x41100018)  /* Expected data read time out */
-#define MMC_BLKLEN     __REG(0x4110001c)  /* Block length of data transaction */
-#define MMC_NOB                __REG(0x41100020)  /* Number of blocks, for block mode */
-#define MMC_PRTBUF     __REG(0x41100024)  /* Partial MMC_TXFIFO FIFO written */
-#define MMC_I_MASK     __REG(0x41100028)  /* Interrupt Mask */
-#define MMC_I_REG      __REG(0x4110002c)  /* Interrupt Register (read only) */
-#define MMC_CMD                __REG(0x41100030)  /* Index of current command */
-#define MMC_ARGH       __REG(0x41100034)  /* MSW part of the current command argument */
-#define MMC_ARGL       __REG(0x41100038)  /* LSW part of the current command argument */
-#define MMC_RES                __REG(0x4110003c)  /* Response FIFO (read only) */
-#define MMC_RXFIFO     __REG(0x41100040)  /* Receive FIFO (read only) */
-#define MMC_TXFIFO     __REG(0x41100044)  /* Transmit FIFO (write only) */
-
-
 /*
  * Core Clock
  */
index 3679a8a8922ee97778818e9fe75e7dd6ba4cf195..d7a777f05088d6332a3a723a7308f3c82070a7cd 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <asm/ptrace.h>
 #include <asm/user.h>
+#include <asm/hwcap.h>
 
 typedef unsigned long elf_greg_t;
 typedef unsigned long elf_freg_t[3];
@@ -39,30 +40,8 @@ typedef struct user_fp elf_fpregset_t;
 #endif
 #define ELF_ARCH       EM_ARM
 
-/*
- * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
- */
-#define HWCAP_SWP      1
-#define HWCAP_HALF     2
-#define HWCAP_THUMB    4
-#define HWCAP_26BIT    8       /* Play it safe */
-#define HWCAP_FAST_MULT        16
-#define HWCAP_FPA      32
-#define HWCAP_VFP      64
-#define HWCAP_EDSP     128
-#define HWCAP_JAVA     256
-#define HWCAP_IWMMXT   512
-#define HWCAP_CRUNCH   1024
-
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
-/*
- * This yields a mask that user programs can use to figure out what
- * instruction set this cpu supports.
- */
-#define ELF_HWCAP      (elf_hwcap)
-extern unsigned int elf_hwcap;
-
 /*
  * This yields a string that ld.so will use to load implementation
  * specific libraries for optimization.  This is more specific in
diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
new file mode 100644 (file)
index 0000000..01a1391
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASMARM_HWCAP_H
+#define __ASMARM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_SWP      1
+#define HWCAP_HALF     2
+#define HWCAP_THUMB    4
+#define HWCAP_26BIT    8       /* Play it safe */
+#define HWCAP_FAST_MULT        16
+#define HWCAP_FPA      32
+#define HWCAP_VFP      64
+#define HWCAP_EDSP     128
+#define HWCAP_JAVA     256
+#define HWCAP_IWMMXT   512
+#define HWCAP_CRUNCH   1024
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP      (elf_hwcap)
+extern unsigned int elf_hwcap;
+#endif
+
+#endif
index ee3d93c281d809900cd13086932755a368f18e40..7aaa206cb54ef22e8a45d92822b31bc8bda18782 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
+#include <asm/hwcap.h>
+
 #define PTRACE_GETREGS         12
 #define PTRACE_SETREGS         13
 #define PTRACE_GETFPREGS       14
@@ -45,6 +47,7 @@
 #define PSR_T_BIT      0x00000020
 #define PSR_F_BIT      0x00000040
 #define PSR_I_BIT      0x00000080
+#define PSR_A_BIT      0x00000100
 #define PSR_J_BIT      0x01000000
 #define PSR_Q_BIT      0x08000000
 #define PSR_V_BIT      0x10000000
@@ -103,6 +106,10 @@ struct pt_regs {
 #define thumb_mode(regs) (0)
 #endif
 
+#define isa_mode(regs) \
+       ((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
+        (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+
 #define processor_mode(regs) \
        ((regs)->ARM_cpsr & MODE_MASK)
 
@@ -117,14 +124,17 @@ struct pt_regs {
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
-       if (user_mode(regs) &&
-           (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
+       if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
+               regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
                return 1;
+       }
 
        /*
         * Force CPSR to something logical...
         */
-       regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
+       regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT;
+       if (!(elf_hwcap & HWCAP_26BIT))
+               regs->ARM_cpsr |= USR_MODE;
 
        return 0;
 }