From: Matteo Croce Date: Sat, 5 Jul 2008 14:49:07 +0000 (+0000) Subject: avr32: update to latest atmel sources X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=03b9d260c78073322d70322d3325f76ced5b53a6;p=openwrt%2Fstaging%2Fwigyori.git avr32: update to latest atmel sources SVN-Revision: 11665 --- diff --git a/target/linux/avr32/Makefile b/target/linux/avr32/Makefile index 5bb4928270..650d4936bf 100644 --- a/target/linux/avr32/Makefile +++ b/target/linux/avr32/Makefile @@ -10,7 +10,7 @@ ARCH:=avr32 BOARD:=avr32 BOARDNAME:=Atmel AVR32 FEATURES:=squashfs -LINUX_VERSION:=2.6.25.9 +LINUX_VERSION:=2.6.25.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/avr32/config-default b/target/linux/avr32/config-default index 3fbfb59e89..d26ad893fc 100644 --- a/target/linux/avr32/config-default +++ b/target/linux/avr32/config-default @@ -128,12 +128,14 @@ CONFIG_MTD_PHYSMAP_START=0x80000000 # CONFIG_NEED_NODE_MEMMAP_SIZE is not set # CONFIG_NMI_DEBUGGING is not set CONFIG_NO_HZ=y +CONFIG_NR_QUICK=2 # CONFIG_OWNERSHIP_TRACE is not set CONFIG_PERFORMANCE_COUNTERS=y CONFIG_PHYLIB=y CONFIG_PHYS_OFFSET=0x10000000 CONFIG_PLATFORM_AT32AP=y # CONFIG_QSEMI_PHY is not set +CONFIG_QUICKLIST=y # CONFIG_REALTEK_PHY is not set CONFIG_RTC_CLASS=m CONFIG_RTC_DRV_AT32AP700X=m diff --git a/target/linux/avr32/patches/100-git_sync.patch b/target/linux/avr32/patches/100-git_sync.patch index 9bab060196..f1e1cf733b 100644 --- a/target/linux/avr32/patches/100-git_sync.patch +++ b/target/linux/avr32/patches/100-git_sync.patch @@ -1,3 +1,105 @@ +--- a/Documentation/serial/driver ++++ b/Documentation/serial/driver +@@ -186,6 +186,17 @@ + Locking: port_sem taken. + Interrupts: caller dependent. + ++ flush_buffer(port) ++ Flush any write buffers, reset any DMA state and stop any ++ ongoing DMA transfers. ++ ++ This will be called whenever the port->info->xmit circular ++ buffer is cleared. ++ ++ Locking: port->lock taken. ++ Interrupts: locally disabled. ++ This call must not sleep ++ + set_termios(port,termios,oldtermios) + Change the port parameters, including word length, parity, stop + bits. Update read_status_mask and ignore_status_mask to indicate +--- a/arch/avr32/Kconfig ++++ b/arch/avr32/Kconfig +@@ -47,6 +47,9 @@ + config GENERIC_TIME + def_bool y + ++config GENERIC_CLOCKEVENTS ++ def_bool y ++ + config RWSEM_XCHGADD_ALGORITHM + def_bool n + +@@ -70,6 +73,8 @@ + + menu "System Type and features" + ++source "kernel/time/Kconfig" ++ + config SUBARCH_AVR32B + bool + config MMU +@@ -83,6 +88,7 @@ + select MMU + select PERFORMANCE_COUNTERS + select HAVE_GPIO_LIB ++ select GENERIC_ALLOCATOR + + # + # CPU types +@@ -117,6 +123,9 @@ + if BOARD_ATSTK1000 + source "arch/avr32/boards/atstk1000/Kconfig" + endif ++if BOARD_ATNGW100 ++source "arch/avr32/boards/atngw100/Kconfig" ++endif + + choice + prompt "Boot loader type" +@@ -142,6 +151,9 @@ + + source "kernel/Kconfig.preempt" + ++config QUICKLIST ++ def_bool y ++ + config HAVE_ARCH_BOOTMEM_NODE + def_bool n + +@@ -180,6 +192,10 @@ + be dumped to the console when a Non-Maskable Interrupt + happens. + ++config DW_DMAC ++ tristate "Synopsys DesignWare DMA Controller support" ++ default y if CPU_AT32AP7000 ++ + # FPU emulation goes here + + source "kernel/Kconfig.hz" +@@ -196,6 +212,11 @@ + + menu "Power management options" + ++config ARCH_SUSPEND_POSSIBLE ++ def_bool y ++ ++source "kernel/power/Kconfig" ++ + menu "CPU Frequency scaling" + + source "drivers/cpufreq/Kconfig" +--- a/arch/avr32/Makefile ++++ b/arch/avr32/Makefile +@@ -32,6 +32,7 @@ + core-y += arch/avr32/kernel/ + core-y += arch/avr32/mm/ + drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/ ++drivers-y += arch/avr32/drivers/ + libs-y += arch/avr32/lib/ + + archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap --- /dev/null +++ b/arch/avr32/boards/atngw100/Kconfig @@ -0,0 +1,12 @@ @@ -87,6 +189,87 @@ return 0; } +--- a/arch/avr32/boards/atstk1000/Kconfig ++++ b/arch/avr32/boards/atstk1000/Kconfig +@@ -18,6 +18,10 @@ + bool "ATSTK1004" + select CPU_AT32AP7002 + ++config BOARD_ATSTK1006 ++ bool "ATSTK1006" ++ select CPU_AT32AP7000 ++ + endchoice + + +@@ -102,4 +106,60 @@ + depends on !BOARD_ATSTK100X_SW1_CUSTOM && !BOARD_ATSTK100X_SW3_CUSTOM + default y + ++config BOARD_ATSTK100X_ENABLE_AC97 ++ bool "Use AC97C instead of ABDAC" ++ help ++ Select this if you want to use the built-in AC97 controller ++ instead of the built-in Audio Bitstream DAC. These share ++ the same I/O pins on the AP7000, so both can't be enabled ++ at the same time. ++ ++ Note that the STK1000 kit doesn't ship with an AC97 codec on ++ board, so say N unless you've got an expansion board with an ++ AC97 codec on it that you want to use. ++ ++config BOARD_ATSTK1000_CF_HACKS ++ bool "ATSTK1000 CompactFlash hacks" ++ depends on !BOARD_ATSTK100X_SW4_CUSTOM ++ help ++ Select this if you have re-routed the CompactFlash RESET and ++ CD signals to GPIOs on your STK1000. This is necessary for ++ reset and card detection to work properly, although some CF ++ cards may be able to cope without reset. ++ ++config BOARD_ATSTK1000_CF_RESET_PIN ++ hex "CompactFlash RESET pin" ++ default 0x30 ++ depends on BOARD_ATSTK1000_CF_HACKS ++ help ++ Select which GPIO pin to use for the CompactFlash RESET ++ signal. This is specified as a hexadecimal number and should ++ be defined as 0x20 * gpio_port + pin. ++ ++ The default is 0x30, which is pin 16 on PIOB, aka GPIO14. ++ ++config BOARD_ATSTK1000_CF_DETECT_PIN ++ hex "CompactFlash DETECT pin" ++ default 0x3e ++ depends on BOARD_ATSTK1000_CF_HACKS ++ help ++ Select which GPIO pin to use for the CompactFlash CD ++ signal. This is specified as a hexadecimal number and should ++ be defined as 0x20 * gpio_port + pin. ++ ++ The default is 0x3e, which is pin 30 on PIOB, aka GPIO15. ++ ++config BOARD_ATSTK100X_ENABLE_PSIF ++ bool "Enable PSIF peripheral (PS/2 support)" ++ default n ++ help ++ Select this if you want to use the PSIF peripheral to hook up PS/2 ++ devices to your STK1000. This will require a hardware modification to ++ work correctly, since PS/2 devices require 5 volt power and signals, ++ while the STK1000 only provides 3.3 volt. ++ ++ Say N if you have not modified the hardware to boost the voltage, say ++ Y if you have level convertion hardware or a PS/2 device capable of ++ operating on 3.3 volt. ++ + endif # stk 1000 +--- a/arch/avr32/boards/atstk1000/Makefile ++++ b/arch/avr32/boards/atstk1000/Makefile +@@ -2,3 +2,4 @@ + obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o + obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o + obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o ++obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -1,7 +1,7 @@ @@ -230,7 +413,7 @@ #endif at32_add_device_usba(0, NULL); +#ifdef CONFIG_BOARD_ATSTK100X_ENABLE_AC97 -+ at32_add_device_ac97c(0); ++ at32_add_device_ac97c(0, NULL); +#else + at32_add_device_abdac(0); +#endif @@ -290,7 +473,7 @@ #endif at32_add_device_usba(0, NULL); +#ifdef CONFIG_BOARD_ATSTK100X_ENABLE_AC97 -+ at32_add_device_ac97c(0); ++ at32_add_device_ac97c(0, NULL); +#else + at32_add_device_abdac(0); +#endif @@ -333,7 +516,7 @@ + fbmem_start, fbmem_size, 0); at32_add_device_usba(0, NULL); +#ifdef CONFIG_BOARD_ATSTK100X_ENABLE_AC97 -+ at32_add_device_ac97c(0); ++ at32_add_device_ac97c(0, NULL); +#else + at32_add_device_abdac(0); +#endif @@ -347,87 +530,6 @@ atstk1000_setup_j2_leds(); atstk1004_setup_extdac(); ---- a/arch/avr32/boards/atstk1000/Kconfig -+++ b/arch/avr32/boards/atstk1000/Kconfig -@@ -18,6 +18,10 @@ - bool "ATSTK1004" - select CPU_AT32AP7002 - -+config BOARD_ATSTK1006 -+ bool "ATSTK1006" -+ select CPU_AT32AP7000 -+ - endchoice - - -@@ -102,4 +106,60 @@ - depends on !BOARD_ATSTK100X_SW1_CUSTOM && !BOARD_ATSTK100X_SW3_CUSTOM - default y - -+config BOARD_ATSTK100X_ENABLE_AC97 -+ bool "Use AC97C instead of ABDAC" -+ help -+ Select this if you want to use the built-in AC97 controller -+ instead of the built-in Audio Bitstream DAC. These share -+ the same I/O pins on the AP7000, so both can't be enabled -+ at the same time. -+ -+ Note that the STK1000 kit doesn't ship with an AC97 codec on -+ board, so say N unless you've got an expansion board with an -+ AC97 codec on it that you want to use. -+ -+config BOARD_ATSTK1000_CF_HACKS -+ bool "ATSTK1000 CompactFlash hacks" -+ depends on !BOARD_ATSTK100X_SW4_CUSTOM -+ help -+ Select this if you have re-routed the CompactFlash RESET and -+ CD signals to GPIOs on your STK1000. This is necessary for -+ reset and card detection to work properly, although some CF -+ cards may be able to cope without reset. -+ -+config BOARD_ATSTK1000_CF_RESET_PIN -+ hex "CompactFlash RESET pin" -+ default 0x30 -+ depends on BOARD_ATSTK1000_CF_HACKS -+ help -+ Select which GPIO pin to use for the CompactFlash RESET -+ signal. This is specified as a hexadecimal number and should -+ be defined as 0x20 * gpio_port + pin. -+ -+ The default is 0x30, which is pin 16 on PIOB, aka GPIO14. -+ -+config BOARD_ATSTK1000_CF_DETECT_PIN -+ hex "CompactFlash DETECT pin" -+ default 0x3e -+ depends on BOARD_ATSTK1000_CF_HACKS -+ help -+ Select which GPIO pin to use for the CompactFlash CD -+ signal. This is specified as a hexadecimal number and should -+ be defined as 0x20 * gpio_port + pin. -+ -+ The default is 0x3e, which is pin 30 on PIOB, aka GPIO15. -+ -+config BOARD_ATSTK100X_ENABLE_PSIF -+ bool "Enable PSIF peripheral (PS/2 support)" -+ default n -+ help -+ Select this if you want to use the PSIF peripheral to hook up PS/2 -+ devices to your STK1000. This will require a hardware modification to -+ work correctly, since PS/2 devices require 5 volt power and signals, -+ while the STK1000 only provides 3.3 volt. -+ -+ Say N if you have not modified the hardware to boost the voltage, say -+ Y if you have level convertion hardware or a PS/2 device capable of -+ operating on 3.3 volt. -+ - endif # stk 1000 ---- a/arch/avr32/boards/atstk1000/Makefile -+++ b/arch/avr32/boards/atstk1000/Makefile -@@ -2,3 +2,4 @@ - obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o - obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o - obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o -+obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o --- a/arch/avr32/configs/atngw100_defconfig +++ b/arch/avr32/configs/atngw100_defconfig @@ -1,7 +1,7 @@ @@ -3542,6 +3644,10 @@ +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y --- /dev/null ++++ b/arch/avr32/drivers/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_DW_DMAC) += dw-dmac.o +--- /dev/null +++ b/arch/avr32/drivers/dw-dmac.c @@ -0,0 +1,761 @@ +/* @@ -4350,72 +4456,16 @@ +#define DW_DMAC_CHAN_DSR 0x050 + +#endif /* __AVR32_DW_DMAC_H__ */ ---- /dev/null -+++ b/arch/avr32/drivers/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_DW_DMAC) += dw-dmac.o ---- a/arch/avr32/Kconfig -+++ b/arch/avr32/Kconfig -@@ -47,6 +47,9 @@ - config GENERIC_TIME - def_bool y - -+config GENERIC_CLOCKEVENTS -+ def_bool y -+ - config RWSEM_XCHGADD_ALGORITHM - def_bool n - -@@ -70,6 +73,8 @@ - - menu "System Type and features" - -+source "kernel/time/Kconfig" -+ - config SUBARCH_AVR32B - bool - config MMU -@@ -83,6 +88,7 @@ - select MMU - select PERFORMANCE_COUNTERS - select HAVE_GPIO_LIB -+ select GENERIC_ALLOCATOR - - # - # CPU types -@@ -117,6 +123,9 @@ - if BOARD_ATSTK1000 - source "arch/avr32/boards/atstk1000/Kconfig" - endif -+if BOARD_ATNGW100 -+source "arch/avr32/boards/atngw100/Kconfig" -+endif - - choice - prompt "Boot loader type" -@@ -180,6 +189,10 @@ - be dumped to the console when a Non-Maskable Interrupt - happens. - -+config DW_DMAC -+ tristate "Synopsys DesignWare DMA Controller support" -+ default y if CPU_AT32AP7000 -+ - # FPU emulation goes here - - source "kernel/Kconfig.hz" -@@ -196,6 +209,11 @@ - - menu "Power management options" - -+config ARCH_SUSPEND_POSSIBLE -+ def_bool y -+ -+source "kernel/power/Kconfig" -+ - menu "CPU Frequency scaling" - - source "drivers/cpufreq/Kconfig" +--- a/arch/avr32/kernel/Makefile ++++ b/arch/avr32/kernel/Makefile +@@ -9,6 +9,7 @@ + obj-y += setup.o traps.o semaphore.o ocd.o ptrace.o + obj-y += signal.o sys_avr32.o process.o time.o + obj-y += init_task.o switch_to.o cpu.o ++obj-y += dma-controller.o + obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o + obj-$(CONFIG_KPROBES) += kprobes.o + obj-$(CONFIG_STACKTRACE) += stacktrace.o --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -29,7 +29,9 @@ @@ -4476,7 +4526,147 @@ +EXPORT_SYMBOL(find_dma_controller); --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S -@@ -741,26 +741,6 @@ +@@ -74,50 +74,41 @@ + .align 2 + bral do_dtlb_modified + +- /* +- * r0 : PGD/PT/PTE +- * r1 : Offending address +- * r2 : Scratch register +- * r3 : Cause (5, 12 or 13) +- */ + #define tlbmiss_save pushm r0-r3 + #define tlbmiss_restore popm r0-r3 + +- .section .tlbx.ex.text,"ax",@progbits ++ .org 0x50 + .global itlb_miss + itlb_miss: + tlbmiss_save + rjmp tlb_miss_common + +- .section .tlbr.ex.text,"ax",@progbits ++ .org 0x60 + dtlb_miss_read: + tlbmiss_save + rjmp tlb_miss_common + +- .section .tlbw.ex.text,"ax",@progbits ++ .org 0x70 + dtlb_miss_write: + tlbmiss_save + + .global tlb_miss_common ++ .align 2 + tlb_miss_common: + mfsr r0, SYSREG_TLBEAR + mfsr r1, SYSREG_PTBR + +- /* Is it the vmalloc space? */ +- bld r0, 31 +- brcs handle_vmalloc_miss +- +- /* First level lookup */ ++ /* ++ * First level lookup: The PGD contains virtual pointers to ++ * the second-level page tables, but they may be NULL if not ++ * present. ++ */ + pgtbl_lookup: + lsr r2, r0, PGDIR_SHIFT + ld.w r3, r1[r2 << 2] + bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT +- bld r3, _PAGE_BIT_PRESENT +- brcc page_table_not_present +- +- /* Translate to virtual address in P1. */ +- andl r3, 0xf000 +- sbr r3, 31 ++ cp.w r3, 0 ++ breq page_table_not_present + + /* Second level lookup */ + ld.w r2, r3[r1 << 2] +@@ -148,16 +139,55 @@ + tlbmiss_restore + rete + +-handle_vmalloc_miss: +- /* Simply do the lookup in init's page table */ ++ /* The slow path of the TLB miss handler */ ++ .align 2 ++page_table_not_present: ++ /* Do we need to synchronize with swapper_pg_dir? */ ++ bld r0, 31 ++ brcs sync_with_swapper_pg_dir ++ ++page_not_present: ++ tlbmiss_restore ++ sub sp, 4 ++ stmts --sp, r0-lr ++ rcall save_full_context_ex ++ mfsr r12, SYSREG_ECR ++ mov r11, sp ++ rcall do_page_fault ++ rjmp ret_from_exception ++ ++ .align 2 ++sync_with_swapper_pg_dir: ++ /* ++ * If swapper_pg_dir contains a non-NULL second-level page ++ * table pointer, copy it into the current PGD. If not, we ++ * must handle it as a full-blown page fault. ++ * ++ * Jumping back to pgtbl_lookup causes an unnecessary lookup, ++ * but it is guaranteed to be a cache hit, it won't happen ++ * very often, and we absolutely do not want to sacrifice any ++ * performance in the fast path in order to improve this. ++ */ + mov r1, lo(swapper_pg_dir) + orh r1, hi(swapper_pg_dir) ++ ld.w r3, r1[r2 << 2] ++ cp.w r3, 0 ++ breq page_not_present ++ mfsr r1, SYSREG_PTBR ++ st.w r1[r2 << 2], r3 + rjmp pgtbl_lookup + ++ /* ++ * We currently have two bytes left at this point until we ++ * crash into the system call handler... ++ * ++ * Don't worry, the assembler will let us know. ++ */ ++ + + /* --- System Call --- */ + +- .section .scall.text,"ax",@progbits ++ .org 0x100 + system_call: + #ifdef CONFIG_PREEMPT + mask_interrupts +@@ -266,18 +296,6 @@ + brcc syscall_exit_cont + rjmp enter_monitor_mode + +- /* The slow path of the TLB miss handler */ +-page_table_not_present: +-page_not_present: +- tlbmiss_restore +- sub sp, 4 +- stmts --sp, r0-lr +- rcall save_full_context_ex +- mfsr r12, SYSREG_ECR +- mov r11, sp +- rcall do_page_fault +- rjmp ret_from_exception +- + /* This function expects to find offending PC in SYSREG_RAR_EX */ + .type save_full_context_ex, @function + .align 2 +@@ -741,26 +759,6 @@ .section .irq.text,"ax",@progbits @@ -4503,16 +4693,6 @@ .global irq_level0 .global irq_level1 .global irq_level2 ---- a/arch/avr32/kernel/Makefile -+++ b/arch/avr32/kernel/Makefile -@@ -9,6 +9,7 @@ - obj-y += setup.o traps.o semaphore.o ocd.o ptrace.o - obj-y += signal.o sys_avr32.o process.o time.o - obj-y += init_task.o switch_to.o cpu.o -+obj-y += dma-controller.o - obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o - obj-$(CONFIG_KPROBES) += kprobes.o - obj-$(CONFIG_STACKTRACE) += stacktrace.o --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -18,11 +18,11 @@ @@ -4563,7 +4743,7 @@ --- a/arch/avr32/kernel/time.c +++ b/arch/avr32/kernel/time.c -@@ -1,16 +1,12 @@ +@@ -1,233 +1,147 @@ /* * Copyright (C) 2004-2007 Atmel Corporation * @@ -4577,13 +4757,25 @@ - #include -#include +-#include +-#include +#include - #include - #include ++#include #include -@@ -27,207 +23,133 @@ - #include - #include + #include +-#include +-#include +-#include +-#include +-#include +-#include ++#include ++#include + +-#include + #include +-#include +-#include -/* how many counter cycles in a jiffy? */ -static u32 cycles_per_jiffy; @@ -4629,20 +4821,20 @@ - * By default we provide the null RTC ops - */ -static unsigned long null_rtc_get_time(void) -+static irqreturn_t timer_interrupt(int irq, void *dev_id) - { +-{ - return mktime(2007, 1, 1, 0, 0, 0); -} - -static int null_rtc_set_time(unsigned long sec) --{ ++static irqreturn_t timer_interrupt(int irq, void *dev_id) + { - return 0; -} -+ struct clock_event_device *evdev = dev_id; - +- -static unsigned long (*rtc_get_time)(void) = null_rtc_get_time; -static int (*rtc_set_time)(unsigned long) = null_rtc_set_time; -- ++ struct clock_event_device *evdev = dev_id; + -static void avr32_timer_ack(void) -{ - u32 count; @@ -4873,6 +5065,34 @@ } - -device_initcall(init_timer_sysfs); +--- a/arch/avr32/kernel/vmlinux.lds.S ++++ b/arch/avr32/kernel/vmlinux.lds.S +@@ -68,14 +68,6 @@ + _evba = .; + _text = .; + *(.ex.text) +- . = 0x50; +- *(.tlbx.ex.text) +- . = 0x60; +- *(.tlbr.ex.text) +- . = 0x70; +- *(.tlbw.ex.text) +- . = 0x100; +- *(.scall.text) + *(.irq.text) + KPROBES_TEXT + TEXT_TEXT +@@ -107,6 +99,10 @@ + */ + *(.data.init_task) + ++ /* Then, the page-aligned data */ ++ . = ALIGN(PAGE_SIZE); ++ *(.data.page_aligned) ++ + /* Then, the cacheline aligned data */ + . = ALIGN(L1_CACHE_BYTES); + *(.data.cacheline_aligned) --- a/arch/avr32/lib/io-readsb.S +++ b/arch/avr32/lib/io-readsb.S @@ -41,7 +41,7 @@ @@ -4884,6 +5104,96 @@ sub r10, 1 st.b r11++, r8 brne 3b +--- a/arch/avr32/mach-at32ap/Kconfig ++++ b/arch/avr32/mach-at32ap/Kconfig +@@ -26,6 +26,13 @@ + + endchoice + ++config GPIO_DEV ++ bool "GPIO /dev interface" ++ select CONFIGFS_FS ++ default n ++ help ++ Say `Y' to enable a /dev interface to the GPIO pins. ++ + endmenu + + endif # PLATFORM_AT32AP +--- a/arch/avr32/mach-at32ap/Makefile ++++ b/arch/avr32/mach-at32ap/Makefile +@@ -1,4 +1,9 @@ +-obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o +-obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o +-obj-$(CONFIG_CPU_AT32AP700X) += time-tc.o ++obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o ++obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o + obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o ++obj-$(CONFIG_GPIO_DEV) += gpio-dev.o ++obj-$(CONFIG_PM) += pm.o ++ ++ifeq ($(CONFIG_PM_DEBUG),y) ++CFLAGS_pm.o += -DDEBUG ++endif +--- a/arch/avr32/mach-at32ap/at32ap.c ++++ /dev/null +@@ -1,56 +0,0 @@ +-/* +- * Copyright (C) 2006 Atmel Corporation +- * +- * 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 +-#include +-#include +-#include +- +-#include +- +-void __init setup_platform(void) +-{ +- at32_clock_init(); +- at32_portmux_init(); +-} +- +-static int __init pdc_probe(struct platform_device *pdev) +-{ +- struct clk *pclk, *hclk; +- +- pclk = clk_get(&pdev->dev, "pclk"); +- if (IS_ERR(pclk)) { +- dev_err(&pdev->dev, "no pclk defined\n"); +- return PTR_ERR(pclk); +- } +- hclk = clk_get(&pdev->dev, "hclk"); +- if (IS_ERR(hclk)) { +- dev_err(&pdev->dev, "no hclk defined\n"); +- clk_put(pclk); +- return PTR_ERR(hclk); +- } +- +- clk_enable(pclk); +- clk_enable(hclk); +- +- dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n"); +- return 0; +-} +- +-static struct platform_driver pdc_driver = { +- .probe = pdc_probe, +- .driver = { +- .name = "pdc", +- }, +-}; +- +-static int __init pdc_init(void) +-{ +- return platform_driver_register(&pdc_driver); +-} +-arch_initcall(pdc_init); --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -6,11 +6,13 @@ @@ -5149,8 +5459,7 @@ - .num_resources = ARRAY_SIZE(at32_systc0_resource), + .resource = at32_tcb0_resource, + .num_resources = ARRAY_SIZE(at32_tcb0_resource), - }; --DEV_CLK(pclk, at32_systc0, pbb, 3); ++}; +DEV_CLK(t0_clk, at32_tcb0, pbb, 3); + +static struct resource at32_tcb1_resource[] = { @@ -5162,7 +5471,8 @@ + .id = 1, + .resource = at32_tcb1_resource, + .num_resources = ARRAY_SIZE(at32_tcb1_resource), -+}; + }; +-DEV_CLK(pclk, at32_systc0, pbb, 3); +DEV_CLK(t0_clk, at32_tcb1, pbb, 4); /* -------------------------------------------------------------------- @@ -5259,7 +5569,27 @@ * USART * -------------------------------------------------------------------- */ -@@ -989,7 +1228,9 @@ +@@ -951,7 +1190,8 @@ + switch (id) { + case 0: + pdev = &atmel_spi0_device; +- select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ ++ /* pullup MISO so a level is always defined */ ++ select_peripheral(PA(0), PERIPH_A, AT32_GPIOF_PULLUP); + select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ + select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ + at32_spi_setup_slaves(0, b, n, spi0_pins); +@@ -959,7 +1199,8 @@ + + case 1: + pdev = &atmel_spi1_device; +- select_peripheral(PB(0), PERIPH_B, 0); /* MISO */ ++ /* pullup MISO so a level is always defined */ ++ select_peripheral(PB(0), PERIPH_B, AT32_GPIOF_PULLUP); + select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ + select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ + at32_spi_setup_slaves(1, b, n, spi1_pins); +@@ -989,7 +1230,9 @@ .index = 2, }; @@ -5270,7 +5600,7 @@ { struct platform_device *pdev; -@@ -1009,6 +1250,9 @@ +@@ -1009,6 +1252,9 @@ atmel_twi0_pclk.dev = &pdev->dev; @@ -5280,7 +5610,7 @@ platform_device_add(pdev); return pdev; -@@ -1032,7 +1276,8 @@ +@@ -1032,7 +1278,8 @@ .index = 9, }; @@ -5290,7 +5620,7 @@ { struct platform_device *pdev; -@@ -1041,11 +1286,15 @@ +@@ -1041,11 +1288,15 @@ pdev = platform_device_alloc("atmel_mci", id); if (!pdev) @@ -5308,7 +5638,7 @@ select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ -@@ -1054,12 +1303,19 @@ +@@ -1054,12 +1305,19 @@ select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ @@ -5329,7 +5659,7 @@ platform_device_put(pdev); return NULL; } -@@ -1097,7 +1353,8 @@ +@@ -1097,7 +1355,8 @@ struct platform_device *__init at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, @@ -5339,7 +5669,7 @@ { struct platform_device *pdev; struct atmel_lcdfb_info *info; -@@ -1124,37 +1381,77 @@ +@@ -1124,37 +1383,77 @@ switch (id) { case 0: pdev = &atmel_lcdfb0_device; @@ -5448,7 +5778,7 @@ clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); -@@ -1351,9 +1648,39 @@ +@@ -1351,9 +1650,39 @@ .index = 6, }; @@ -5488,7 +5818,7 @@ struct platform_device *pdev; if (id != 0) -@@ -1367,13 +1694,20 @@ +@@ -1367,13 +1696,20 @@ ARRAY_SIZE(usba0_resource))) goto out_free_pdev; @@ -5515,7 +5845,7 @@ usba0_pclk.dev = &pdev->dev; usba0_hclk.dev = &pdev->dev; -@@ -1526,6 +1860,58 @@ +@@ -1526,6 +1862,58 @@ #endif /* -------------------------------------------------------------------- @@ -5574,7 +5904,64 @@ * AC97C * -------------------------------------------------------------------- */ static struct resource atmel_ac97c0_resource[] __initdata = { -@@ -1683,6 +2069,7 @@ +@@ -1540,9 +1928,11 @@ + .index = 10, + }; + +-struct platform_device *__init at32_add_device_ac97c(unsigned int id) ++struct platform_device *__init ++at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) + { + struct platform_device *pdev; ++ struct ac97c_platform_data _data; + + if (id != 0) + return NULL; +@@ -1553,19 +1943,37 @@ + + if (platform_device_add_resources(pdev, atmel_ac97c0_resource, + ARRAY_SIZE(atmel_ac97c0_resource))) +- goto err_add_resources; ++ goto fail; + +- select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */ +- select_peripheral(PB(21), PERIPH_B, 0); /* SDO */ +- select_peripheral(PB(22), PERIPH_B, 0); /* SDI */ +- select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */ ++ if (!data) { ++ data = &_data; ++ memset(data, 0, sizeof(struct ac97c_platform_data)); ++ data->reset_pin = GPIO_PIN_NONE; ++ } ++ ++ data->dma_rx_periph_id = 3; ++ data->dma_tx_periph_id = 4; ++ data->dma_controller_id = 0; ++ ++ if (platform_device_add_data(pdev, data, ++ sizeof(struct ac97c_platform_data))) ++ goto fail; ++ ++ select_peripheral(PB(20), PERIPH_B, 0); /* SDO */ ++ select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */ ++ select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */ ++ select_peripheral(PB(23), PERIPH_B, 0); /* SDI */ ++ ++ /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ ++ if (data->reset_pin != GPIO_PIN_NONE) ++ at32_select_gpio(data->reset_pin, 0); + + atmel_ac97c0_pclk.dev = &pdev->dev; + + platform_device_add(pdev); + return pdev; + +-err_add_resources: ++fail: + platform_device_put(pdev); + return NULL; + } +@@ -1683,6 +2091,7 @@ &hmatrix_clk, &ebi_clk, &hramc_clk, @@ -5582,7 +5969,7 @@ &smc0_pclk, &smc0_mck, &pdc_hclk, -@@ -1694,7 +2081,10 @@ +@@ -1694,7 +2103,10 @@ &pio2_mck, &pio3_mck, &pio4_mck, @@ -5594,7 +5981,7 @@ &atmel_usart0_usart, &atmel_usart1_usart, &atmel_usart2_usart, -@@ -1730,16 +2120,7 @@ +@@ -1730,16 +2142,7 @@ }; unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); @@ -5612,7 +5999,7 @@ { u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; int i; -@@ -1794,4 +2175,36 @@ +@@ -1794,4 +2197,36 @@ pm_writel(HSB_MASK, hsb_mask); pm_writel(PBA_MASK, pba_mask); pm_writel(PBB_MASK, pbb_mask); @@ -5649,65 +6036,6 @@ + return -ENOMEM; } +core_initcall(sram_init); ---- a/arch/avr32/mach-at32ap/at32ap.c -+++ /dev/null -@@ -1,56 +0,0 @@ --/* -- * Copyright (C) 2006 Atmel Corporation -- * -- * 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 --#include --#include --#include -- --#include -- --void __init setup_platform(void) --{ -- at32_clock_init(); -- at32_portmux_init(); --} -- --static int __init pdc_probe(struct platform_device *pdev) --{ -- struct clk *pclk, *hclk; -- -- pclk = clk_get(&pdev->dev, "pclk"); -- if (IS_ERR(pclk)) { -- dev_err(&pdev->dev, "no pclk defined\n"); -- return PTR_ERR(pclk); -- } -- hclk = clk_get(&pdev->dev, "hclk"); -- if (IS_ERR(hclk)) { -- dev_err(&pdev->dev, "no hclk defined\n"); -- clk_put(pclk); -- return PTR_ERR(hclk); -- } -- -- clk_enable(pclk); -- clk_enable(hclk); -- -- dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n"); -- return 0; --} -- --static struct platform_driver pdc_driver = { -- .probe = pdc_probe, -- .driver = { -- .name = "pdc", -- }, --}; -- --static int __init pdc_init(void) --{ -- return platform_driver_register(&pdc_driver); --} --arch_initcall(pdc_init); --- a/arch/avr32/mach-at32ap/cpufreq.c +++ b/arch/avr32/mach-at32ap/cpufreq.c @@ -108,5 +108,4 @@ @@ -6409,37 +6737,6 @@ unsigned long intc_get_pending(unsigned int group) { return intc_readl(&intc0, INTREQ0 + 4 * group); ---- a/arch/avr32/mach-at32ap/Kconfig -+++ b/arch/avr32/mach-at32ap/Kconfig -@@ -26,6 +26,13 @@ - - endchoice - -+config GPIO_DEV -+ bool "GPIO /dev interface" -+ select CONFIGFS_FS -+ default n -+ help -+ Say `Y' to enable a /dev interface to the GPIO pins. -+ - endmenu - - endif # PLATFORM_AT32AP ---- a/arch/avr32/mach-at32ap/Makefile -+++ b/arch/avr32/mach-at32ap/Makefile -@@ -1,4 +1,9 @@ --obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o --obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o --obj-$(CONFIG_CPU_AT32AP700X) += time-tc.o -+obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o -+obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o - obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o -+obj-$(CONFIG_GPIO_DEV) += gpio-dev.o -+obj-$(CONFIG_PM) += pm.o -+ -+ifeq ($(CONFIG_PM_DEBUG),y) -+CFLAGS_pm.o += -DDEBUG -+endif --- /dev/null +++ b/arch/avr32/mach-at32ap/pdc.c @@ -0,0 +1,48 @@ @@ -6585,6 +6882,17 @@ if (!label) continue; +--- a/arch/avr32/mach-at32ap/pio.h ++++ b/arch/avr32/mach-at32ap/pio.h +@@ -57,7 +57,7 @@ + + /* Bitfields in IFDR */ + +-/* Bitfields in ISFR */ ++/* Bitfields in IFSR */ + + /* Bitfields in SODR */ + --- /dev/null +++ b/arch/avr32/mach-at32ap/pm-at32ap700x.S @@ -0,0 +1,174 @@ @@ -7310,16 +7618,6 @@ - - return IRQ_NONE; -} ---- a/arch/avr32/Makefile -+++ b/arch/avr32/Makefile -@@ -32,6 +32,7 @@ - core-y += arch/avr32/kernel/ - core-y += arch/avr32/mm/ - drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/ -+drivers-y += arch/avr32/drivers/ - libs-y += arch/avr32/lib/ - - archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c @@ -11,6 +11,7 @@ @@ -7330,23 +7628,384 @@ #include #include #include -@@ -28,15 +29,13 @@ - pgd_t swapper_pg_dir[PTRS_PER_PGD]; +@@ -23,20 +24,20 @@ + #include + #include + ++#define __page_aligned __attribute__((section(".data.page_aligned"))) ++ + DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); + +-pgd_t swapper_pg_dir[PTRS_PER_PGD]; ++pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned; struct page *empty_zero_page; +EXPORT_SYMBOL(empty_zero_page); /* - * Cache of MMU context last used. + * Cache of MMU context last used. + */ + unsigned long mmu_context_cache = NO_CONTEXT; + +-#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) +-#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) +- + void show_mem(void) + { + int total = 0, reserved = 0, cached = 0; +@@ -109,19 +110,9 @@ + zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0), + PAGE_SIZE); + +- { +- pgd_t *pg_dir; +- int i; +- +- pg_dir = swapper_pg_dir; +- sysreg_write(PTBR, (unsigned long)pg_dir); +- +- for (i = 0; i < PTRS_PER_PGD; i++) +- pgd_val(pg_dir[i]) = 0; +- +- enable_mmu(); +- printk ("CPU: Paging enabled\n"); +- } ++ sysreg_write(PTBR, (unsigned long)swapper_pg_dir); ++ enable_mmu(); ++ printk ("CPU: Paging enabled\n"); + + for_each_online_node(nid) { + pg_data_t *pgdat = NODE_DATA(nid); +--- a/arch/avr32/mm/tlb.c ++++ b/arch/avr32/mm/tlb.c +@@ -11,21 +11,21 @@ + + #include + +-#define _TLBEHI_I 0x100 ++/* TODO: Get the correct number from the CONFIG1 system register */ ++#define NR_TLB_ENTRIES 32 + +-void show_dtlb_entry(unsigned int index) ++static void show_dtlb_entry(unsigned int index) + { +- unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save; ++ u32 tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save; + unsigned long flags; + + local_irq_save(flags); + mmucr_save = sysreg_read(MMUCR); + tlbehi_save = sysreg_read(TLBEHI); +- mmucr = mmucr_save & 0x13; +- mmucr |= index << 14; ++ mmucr = SYSREG_BFINS(DRP, index, mmucr_save); + sysreg_write(MMUCR, mmucr); + +- asm volatile("tlbr" : : : "memory"); ++ __builtin_tlbr(); + cpu_sync_pipeline(); + + tlbehi = sysreg_read(TLBEHI); +@@ -33,15 +33,17 @@ + + printk("%2u: %c %c %02x %05x %05x %o %o %c %c %c %c\n", + index, +- (tlbehi & 0x200)?'1':'0', +- (tlbelo & 0x100)?'1':'0', +- (tlbehi & 0xff), +- (tlbehi >> 12), (tlbelo >> 12), +- (tlbelo >> 4) & 7, (tlbelo >> 2) & 3, +- (tlbelo & 0x200)?'1':'0', +- (tlbelo & 0x080)?'1':'0', +- (tlbelo & 0x001)?'1':'0', +- (tlbelo & 0x002)?'1':'0'); ++ SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0', ++ SYSREG_BFEXT(G, tlbelo) ? '1' : '0', ++ SYSREG_BFEXT(ASID, tlbehi), ++ SYSREG_BFEXT(VPN, tlbehi) >> 2, ++ SYSREG_BFEXT(PFN, tlbelo) >> 2, ++ SYSREG_BFEXT(AP, tlbelo), ++ SYSREG_BFEXT(SZ, tlbelo), ++ SYSREG_BFEXT(TLBELO_C, tlbelo) ? 'C' : ' ', ++ SYSREG_BFEXT(B, tlbelo) ? 'B' : ' ', ++ SYSREG_BFEXT(W, tlbelo) ? 'W' : ' ', ++ SYSREG_BFEXT(TLBELO_D, tlbelo) ? 'D' : ' '); + + sysreg_write(MMUCR, mmucr_save); + sysreg_write(TLBEHI, tlbehi_save); +@@ -54,29 +56,33 @@ + unsigned int i; + + printk("ID V G ASID VPN PFN AP SZ C B W D\n"); +- for (i = 0; i < 32; i++) ++ for (i = 0; i < NR_TLB_ENTRIES; i++) + show_dtlb_entry(i); + } + +-static unsigned long last_mmucr; +- +-static inline void set_replacement_pointer(unsigned shift) ++static void update_dtlb(unsigned long address, pte_t pte) + { +- unsigned long mmucr, mmucr_save; ++ u32 tlbehi; ++ u32 mmucr; + +- mmucr = mmucr_save = sysreg_read(MMUCR); ++ /* ++ * We're not changing the ASID here, so no need to flush the ++ * pipeline. ++ */ ++ tlbehi = sysreg_read(TLBEHI); ++ tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); ++ tlbehi |= address & MMU_VPN_MASK; ++ tlbehi |= SYSREG_BIT(TLBEHI_V); ++ sysreg_write(TLBEHI, tlbehi); + + /* Does this mapping already exist? */ +- __asm__ __volatile__( +- " tlbs\n" +- " mfsr %0, %1" +- : "=r"(mmucr) +- : "i"(SYSREG_MMUCR)); ++ __builtin_tlbs(); ++ mmucr = sysreg_read(MMUCR); + + if (mmucr & SYSREG_BIT(MMUCR_N)) { + /* Not found -- pick a not-recently-accessed entry */ +- unsigned long rp; +- unsigned long tlbar = sysreg_read(TLBARLO); ++ unsigned int rp; ++ u32 tlbar = sysreg_read(TLBARLO); + + rp = 32 - fls(tlbar); + if (rp == 32) { +@@ -84,30 +90,14 @@ + sysreg_write(TLBARLO, -1L); + } + +- mmucr &= 0x13; +- mmucr |= (rp << shift); +- ++ mmucr = SYSREG_BFINS(DRP, rp, mmucr); + sysreg_write(MMUCR, mmucr); + } + +- last_mmucr = mmucr; +-} +- +-static void update_dtlb(unsigned long address, pte_t pte, unsigned long asid) +-{ +- unsigned long vpn; +- +- vpn = (address & MMU_VPN_MASK) | _TLBEHI_VALID | asid; +- sysreg_write(TLBEHI, vpn); +- cpu_sync_pipeline(); +- +- set_replacement_pointer(14); +- + sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK); + + /* Let's go */ +- asm volatile("nop\n\ttlbw" : : : "memory"); +- cpu_sync_pipeline(); ++ __builtin_tlbw(); + } + + void update_mmu_cache(struct vm_area_struct *vma, +@@ -120,39 +110,40 @@ + return; + + local_irq_save(flags); +- update_dtlb(address, pte, get_asid()); ++ update_dtlb(address, pte); + local_irq_restore(flags); + } + +-void __flush_tlb_page(unsigned long asid, unsigned long page) ++static void __flush_tlb_page(unsigned long asid, unsigned long page) + { +- unsigned long mmucr, tlbehi; ++ u32 mmucr, tlbehi; + +- page |= asid; +- sysreg_write(TLBEHI, page); +- cpu_sync_pipeline(); +- asm volatile("tlbs"); ++ /* ++ * Caller is responsible for masking out non-PFN bits in page ++ * and changing the current ASID if necessary. This means that ++ * we don't need to flush the pipeline after writing TLBEHI. ++ */ ++ tlbehi = page | asid; ++ sysreg_write(TLBEHI, tlbehi); ++ ++ __builtin_tlbs(); + mmucr = sysreg_read(MMUCR); + + if (!(mmucr & SYSREG_BIT(MMUCR_N))) { +- unsigned long tlbarlo; +- unsigned long entry; ++ unsigned int entry; ++ u32 tlbarlo; + + /* Clear the "valid" bit */ +- tlbehi = sysreg_read(TLBEHI); +- tlbehi &= ~_TLBEHI_VALID; + sysreg_write(TLBEHI, tlbehi); +- cpu_sync_pipeline(); + + /* mark the entry as "not accessed" */ +- entry = (mmucr >> 14) & 0x3f; ++ entry = SYSREG_BFEXT(DRP, mmucr); + tlbarlo = sysreg_read(TLBARLO); +- tlbarlo |= (0x80000000 >> entry); ++ tlbarlo |= (0x80000000UL >> entry); + sysreg_write(TLBARLO, tlbarlo); + + /* update the entry with valid bit clear */ +- asm volatile("tlbw"); +- cpu_sync_pipeline(); ++ __builtin_tlbw(); + } + } + +@@ -190,17 +181,22 @@ + + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; ++ + if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */ + mm->context = NO_CONTEXT; + if (mm == current->mm) + activate_context(mm); + } else { +- unsigned long asid = mm->context & MMU_CONTEXT_ASID_MASK; +- unsigned long saved_asid = MMU_NO_ASID; ++ unsigned long asid; ++ unsigned long saved_asid; ++ ++ asid = mm->context & MMU_CONTEXT_ASID_MASK; ++ saved_asid = MMU_NO_ASID; + + start &= PAGE_MASK; + end += (PAGE_SIZE - 1); + end &= PAGE_MASK; ++ + if (mm != current->mm) { + saved_asid = get_asid(); + set_asid(asid); +@@ -218,33 +214,34 @@ + } + + /* +- * TODO: If this is only called for addresses > TASK_SIZE, we can probably +- * skip the ASID stuff and just use the Global bit... ++ * This function depends on the pages to be flushed having the G ++ * (global) bit set in their pte. This is true for all ++ * PAGE_KERNEL(_RO) pages. */ - unsigned long mmu_context_cache = NO_CONTEXT; + void flush_tlb_kernel_range(unsigned long start, unsigned long end) + { + unsigned long flags; + int size; --#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) --#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) -- - void show_mem(void) +- local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */ + flush_tlb_all(); + } else { +- unsigned long asid = init_mm.context & MMU_CONTEXT_ASID_MASK; +- unsigned long saved_asid = get_asid(); ++ unsigned long asid; ++ ++ local_irq_save(flags); ++ asid = get_asid(); + + start &= PAGE_MASK; + end += (PAGE_SIZE - 1); + end &= PAGE_MASK; +- set_asid(asid); ++ + while (start < end) { + __flush_tlb_page(asid, start); + start += PAGE_SIZE; + } +- set_asid(saved_asid); ++ local_irq_restore(flags); + } +- local_irq_restore(flags); + } + + void flush_tlb_mm(struct mm_struct *mm) +@@ -280,7 +277,7 @@ { - int total = 0, reserved = 0, cached = 0; + static unsigned long tlb_index; + +- if (*pos >= 32) ++ if (*pos >= NR_TLB_ENTRIES) + return NULL; + + tlb_index = 0; +@@ -291,7 +288,7 @@ + { + unsigned long *index = v; + +- if (*index >= 31) ++ if (*index >= NR_TLB_ENTRIES - 1) + return NULL; + + ++*pos; +@@ -313,16 +310,16 @@ + if (*index == 0) + seq_puts(tlb, "ID V G ASID VPN PFN AP SZ C B W D\n"); + +- BUG_ON(*index >= 32); ++ BUG_ON(*index >= NR_TLB_ENTRIES); + + local_irq_save(flags); + mmucr_save = sysreg_read(MMUCR); + tlbehi_save = sysreg_read(TLBEHI); +- mmucr = mmucr_save & 0x13; +- mmucr |= *index << 14; ++ mmucr = SYSREG_BFINS(DRP, *index, mmucr_save); + sysreg_write(MMUCR, mmucr); + +- asm volatile("tlbr" : : : "memory"); ++ /* TLBR might change the ASID */ ++ __builtin_tlbr(); + cpu_sync_pipeline(); + + tlbehi = sysreg_read(TLBEHI); +@@ -334,16 +331,18 @@ + local_irq_restore(flags); + + seq_printf(tlb, "%2lu: %c %c %02x %05x %05x %o %o %c %c %c %c\n", +- *index, +- (tlbehi & 0x200)?'1':'0', +- (tlbelo & 0x100)?'1':'0', +- (tlbehi & 0xff), +- (tlbehi >> 12), (tlbelo >> 12), +- (tlbelo >> 4) & 7, (tlbelo >> 2) & 3, +- (tlbelo & 0x200)?'1':'0', +- (tlbelo & 0x080)?'1':'0', +- (tlbelo & 0x001)?'1':'0', +- (tlbelo & 0x002)?'1':'0'); ++ *index, ++ SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0', ++ SYSREG_BFEXT(G, tlbelo) ? '1' : '0', ++ SYSREG_BFEXT(ASID, tlbehi), ++ SYSREG_BFEXT(VPN, tlbehi) >> 2, ++ SYSREG_BFEXT(PFN, tlbelo) >> 2, ++ SYSREG_BFEXT(AP, tlbelo), ++ SYSREG_BFEXT(SZ, tlbelo), ++ SYSREG_BFEXT(TLBELO_C, tlbelo) ? '1' : '0', ++ SYSREG_BFEXT(B, tlbelo) ? '1' : '0', ++ SYSREG_BFEXT(W, tlbelo) ? '1' : '0', ++ SYSREG_BFEXT(TLBELO_D, tlbelo) ? '1' : '0'); + + return 0; + } --- a/arch/avr32/oprofile/op_model_avr32.c +++ b/arch/avr32/oprofile/op_model_avr32.c @@ -16,7 +16,6 @@ @@ -7701,6 +8360,33 @@ + return 0; +} +arch_initcall(tcb_clksrc_init); +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -88,6 +88,14 @@ + to support combined I2C messages. Use the i2c-gpio driver + unless your system can cope with those limitations. + ++config I2C_ATMELTWI ++ tristate "Atmel Two-Wire Interface (TWI)" ++ depends on I2C && (ARCH_AT91 || PLATFORM_AT32AP) ++ help ++ Atmel on-chip TWI controller. Say Y if you have an AT32 or ++ AT91-based device and want to use its built-in TWI ++ functionality. ++ + config I2C_AU1550 + tristate "Au1550/Au1200 SMBus interface" + depends on SOC_AU1550 || SOC_AU1200 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -52,6 +52,7 @@ + obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o + obj-$(CONFIG_SCx200_ACB) += scx200_acb.o + obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o ++obj-$(CONFIG_I2C_ATMELTWI) += i2c-atmeltwi.o + + ifeq ($(CONFIG_I2C_DEBUG_BUS),y) + EXTRA_CFLAGS += -DDEBUG --- /dev/null +++ b/drivers/i2c/busses/i2c-atmeltwi.c @@ -0,0 +1,436 @@ @@ -8260,33 +8946,36 @@ + __raw_writel((value), (port)->regs + TWI_##reg) + +#endif /* __ATMELTWI_H__ */ ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -88,6 +88,14 @@ - to support combined I2C messages. Use the i2c-gpio driver - unless your system can cope with those limitations. +--- a/drivers/input/serio/Kconfig ++++ b/drivers/input/serio/Kconfig +@@ -88,6 +88,17 @@ + To compile this driver as a module, choose M here: the + module will be called rpckbd. -+config I2C_ATMELTWI -+ tristate "Atmel Two-Wire Interface (TWI)" -+ depends on I2C && (ARCH_AT91 || PLATFORM_AT32AP) ++config SERIO_AT32PSIF ++ tristate "AVR32 PSIF PS/2 keyboard and mouse controller" ++ depends on AVR32 ++ default n + help -+ Atmel on-chip TWI controller. Say Y if you have an AT32 or -+ AT91-based device and want to use its built-in TWI -+ functionality. ++ Say Y here if you want to use the PSIF peripheral on AVR32 devices ++ and connect a PS/2 keyboard and/or mouse to it. + - config I2C_AU1550 - tristate "Au1550/Au1200 SMBus interface" - depends on SOC_AU1550 || SOC_AU1200 ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -52,6 +52,7 @@ - obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o - obj-$(CONFIG_SCx200_ACB) += scx200_acb.o - obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o -+obj-$(CONFIG_I2C_ATMELTWI) += i2c-atmeltwi.o - - ifeq ($(CONFIG_I2C_DEBUG_BUS),y) - EXTRA_CFLAGS += -DDEBUG ++ To compile this driver as a module, choose M here: the module will ++ be called at32psif. ++ + config SERIO_AMBAKMI + tristate "AMBA KMI keyboard controller" + depends on ARM_AMBA +--- a/drivers/input/serio/Makefile ++++ b/drivers/input/serio/Makefile +@@ -12,6 +12,7 @@ + obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o + obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o + obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o ++obj-$(CONFIG_SERIO_AT32PSIF) += at32psif.o + obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o + obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o + obj-$(CONFIG_HP_SDC) += hp_sdc.o --- /dev/null +++ b/drivers/input/serio/at32psif.c @@ -0,0 +1,351 @@ @@ -8726,36 +9415,58 @@ + __raw_writel((value), (port)->regs + PSIF_##reg) + +#endif /* _AT32PSIF_H */ ---- a/drivers/input/serio/Kconfig -+++ b/drivers/input/serio/Kconfig -@@ -88,6 +88,17 @@ - To compile this driver as a module, choose M here: the - module will be called rpckbd. +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -22,6 +22,39 @@ + purposes including software controlled power-efficent backlights + on LCD displays, motor control, and waveform generation. -+config SERIO_AT32PSIF -+ tristate "AVR32 PSIF PS/2 keyboard and mouse controller" -+ depends on AVR32 -+ default n ++config ATMEL_TCLIB ++ bool "Atmel AT32/AT91 Timer/Counter Library" ++ depends on (AVR32 || ARCH_AT91) + help -+ Say Y here if you want to use the PSIF peripheral on AVR32 devices -+ and connect a PS/2 keyboard and/or mouse to it. ++ Select this if you want a library to allocate the Timer/Counter ++ blocks found on many Atmel processors. This facilitates using ++ these blocks by different drivers despite processor differences. + -+ To compile this driver as a module, choose M here: the module will -+ be called at32psif. ++config ATMEL_TCB_CLKSRC ++ bool "TC Block Clocksource" ++ depends on ATMEL_TCLIB && GENERIC_TIME ++ default y ++ help ++ Select this to get a high precision clocksource based on a ++ TC block with a 5+ MHz base clock rate. Two timer channels ++ are combined to make a single 32-bit timer. + - config SERIO_AMBAKMI - tristate "AMBA KMI keyboard controller" - depends on ARM_AMBA ---- a/drivers/input/serio/Makefile -+++ b/drivers/input/serio/Makefile -@@ -12,6 +12,7 @@ - obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o - obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o - obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o -+obj-$(CONFIG_SERIO_AT32PSIF) += at32psif.o - obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o - obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o - obj-$(CONFIG_HP_SDC) += hp_sdc.o ++ When GENERIC_CLOCKEVENTS is defined, the third timer channel ++ may be used as a clock event device supporting oneshot mode ++ (delays of up to two seconds) based on the 32 KiHz clock. ++ ++config ATMEL_TCB_CLKSRC_BLOCK ++ int ++ depends on ATMEL_TCB_CLKSRC ++ prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X ++ default 0 ++ range 0 1 ++ help ++ Some chips provide more than one TC block, so you have the ++ choice of which one to use for the clock framework. The other ++ TC can be used for other purposes, such as PWM generation and ++ interval timing. ++ + config IBM_ASM + tristate "Device driver for IBM RSA service processor" + depends on X86 && PCI && INPUT && EXPERIMENTAL +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -10,6 +10,7 @@ + obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o + obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o + obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o ++obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o + obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o + obj-$(CONFIG_LKDTM) += lkdtm.o + obj-$(CONFIG_TIFM_CORE) += tifm_core.o --- /dev/null +++ b/drivers/misc/atmel_tclib.c @@ -0,0 +1,161 @@ @@ -8920,61 +9631,38 @@ + return platform_driver_probe(&tc_driver, tc_probe); +} +arch_initcall(tc_init); ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -22,6 +22,39 @@ - purposes including software controlled power-efficent backlights - on LCD displays, motor control, and waveform generation. +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -91,6 +91,16 @@ -+config ATMEL_TCLIB -+ bool "Atmel AT32/AT91 Timer/Counter Library" -+ depends on (AVR32 || ARCH_AT91) -+ help -+ Select this if you want a library to allocate the Timer/Counter -+ blocks found on many Atmel processors. This facilitates using -+ these blocks by different drivers despite processor differences. -+ -+config ATMEL_TCB_CLKSRC -+ bool "TC Block Clocksource" -+ depends on ATMEL_TCLIB && GENERIC_TIME -+ default y + If unsure, say N. + ++config MMC_ATMELMCI ++ tristate "Atmel Multimedia Card Interface support" ++ depends on AVR32 && MMC + help -+ Select this to get a high precision clocksource based on a -+ TC block with a 5+ MHz base clock rate. Two timer channels -+ are combined to make a single 32-bit timer. -+ -+ When GENERIC_CLOCKEVENTS is defined, the third timer channel -+ may be used as a clock event device supporting oneshot mode -+ (delays of up to two seconds) based on the 32 KiHz clock. ++ This selects the Atmel Multimedia Card Interface. If you have ++ a AT91 (ARM) or AT32 (AVR32) platform with a Multimedia Card ++ slot, say Y or M here. + -+config ATMEL_TCB_CLKSRC_BLOCK -+ int -+ depends on ATMEL_TCB_CLKSRC -+ prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X -+ default 0 -+ range 0 1 -+ help -+ Some chips provide more than one TC block, so you have the -+ choice of which one to use for the clock framework. The other -+ TC can be used for other purposes, such as PWM generation and -+ interval timing. ++ If unsure, say N. + - config IBM_ASM - tristate "Device driver for IBM RSA service processor" - depends on X86 && PCI && INPUT && EXPERIMENTAL ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -10,6 +10,7 @@ - obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o - obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o - obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o -+obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o - obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o - obj-$(CONFIG_LKDTM) += lkdtm.o - obj-$(CONFIG_TIFM_CORE) += tifm_core.o + config MMC_IMX + tristate "Motorola i.MX Multimedia Card Interface support" + depends on ARCH_IMX +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -15,6 +15,7 @@ + obj-$(CONFIG_MMC_AU1X) += au1xmmc.o + obj-$(CONFIG_MMC_OMAP) += omap.o + obj-$(CONFIG_MMC_AT91) += at91_mci.o ++obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o + obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o + obj-$(CONFIG_MMC_SPI) += mmc_spi.o + --- /dev/null +++ b/drivers/mmc/host/atmel-mci.c -@@ -0,0 +1,1220 @@ +@@ -0,0 +1,1234 @@ +/* + * Atmel MultiMedia Card Interface driver + * @@ -9054,6 +9742,7 @@ + struct clk *mck; + struct platform_device *pdev; + ++ int pending_stop; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_root; + struct dentry *debugfs_regs; @@ -9843,6 +10532,12 @@ + data->bytes_xfered = data->blocks * data->blksz; + atmci_data_complete(host, data); + } ++ /* See if there is a pending STOP which can be sent */ ++ if (host->pending_stop && mci_cmd_is_complete(host)) { ++ host->pending_stop = 0; ++ if (mrq->stop && !mci_set_stop_sent_is_completed(host)) ++ send_stop_cmd(host->mmc, mrq->data, 0); ++ } +} + +static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status) @@ -9895,9 +10590,16 @@ + * drivers) or when interrupts are disabled for a long time. + */ + mci_set_dma_complete(host); -+ if (data->stop && mci_cmd_is_complete(host) -+ && !mci_set_stop_sent_is_completed(host)) -+ send_stop_cmd(host->mmc, data, 0); ++ ++ if (data->stop) { ++ if (!mci_cmd_is_complete(host)) { ++ /* Just remember a STOP must be sent */ ++ host->pending_stop = 1; ++ } else if (!mci_set_stop_sent_is_completed(host)) { ++ send_stop_cmd(host->mmc, data, 0); ++ host->pending_stop = 0; ++ } ++ } + + /* + * Regardless of what the documentation says, we have to wait @@ -10390,35 +11092,78 @@ + __raw_writel((value), (port)->regs + MCI_##reg) + +#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */ ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -91,6 +91,16 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -272,12 +272,54 @@ - If unsure, say N. + If you say "m", the module will be called "cs553x_nand.ko". -+config MMC_ATMELMCI -+ tristate "Atmel Multimedia Card Interface support" -+ depends on AVR32 && MMC +-config MTD_NAND_AT91 +- bool "Support for NAND Flash / SmartMedia on AT91" +- depends on ARCH_AT91 ++config MTD_NAND_ATMEL ++ bool "Support for NAND Flash / SmartMedia on AT91 and AVR32" ++ depends on ARCH_AT91 || AVR32 + help + Enables support for NAND Flash / Smart Media Card interface +- on Atmel AT91 processors. ++ on Atmel AT91 and AVR32 processors. ++choice ++ prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32" ++ depends on MTD_NAND_ATMEL ++ ++config MTD_NAND_ATMEL_ECC_HW ++ bool "Hardware ECC" ++ depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32 + help -+ This selects the Atmel Multimedia Card Interface. If you have -+ a AT91 (ARM) or AT32 (AVR32) platform with a Multimedia Card -+ slot, say Y or M here. ++ Use hardware ECC instead of software ECC when the chip ++ supports it. + -+ If unsure, say N. ++ The hardware ECC controller is capable of single bit error ++ correction and 2-bit random detection per page. + - config MMC_IMX - tristate "Motorola i.MX Multimedia Card Interface support" - depends on ARCH_IMX ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -15,6 +15,7 @@ - obj-$(CONFIG_MMC_AU1X) += au1xmmc.o - obj-$(CONFIG_MMC_OMAP) += omap.o - obj-$(CONFIG_MMC_AT91) += at91_mci.o -+obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o - obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o - obj-$(CONFIG_MMC_SPI) += mmc_spi.o ++ NB : hardware and software ECC schemes are incompatible. ++ If you switch from one to another, you'll have to erase your ++ mtd partition. ++ ++ If unsure, say Y ++ ++config MTD_NAND_ATMEL_ECC_SOFT ++ bool "Software ECC" ++ help ++ Use software ECC. ++ ++ NB : hardware and software ECC schemes are incompatible. ++ If you switch from one to another, you'll have to erase your ++ mtd partition. ++ ++config MTD_NAND_ATMEL_ECC_NONE ++ bool "No ECC (testing only, DANGEROUS)" ++ depends on DEBUG_KERNEL ++ help ++ No ECC will be used. ++ It's not a good idea and it should be reserved for testing ++ purpose only. ++ ++ If unsure, say N ++ ++ endchoice ++ ++endchoice + config MTD_NAND_CM_X270 + tristate "Support for NAND Flash on CM-X270 modules" +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -24,7 +24,7 @@ + obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o + obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o + obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o +-obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o ++obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o + obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o + obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o + obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o --- a/drivers/mtd/nand/at91_nand.c +++ /dev/null @@ -1,236 +0,0 @@ @@ -11357,78 +12102,6 @@ MODULE_AUTHOR(DRV_AUTHOR); MODULE_DESCRIPTION(DRV_DESC); +MODULE_ALIAS("platform:" DRV_NAME); ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -272,12 +272,54 @@ - - If you say "m", the module will be called "cs553x_nand.ko". - --config MTD_NAND_AT91 -- bool "Support for NAND Flash / SmartMedia on AT91" -- depends on ARCH_AT91 -+config MTD_NAND_ATMEL -+ bool "Support for NAND Flash / SmartMedia on AT91 and AVR32" -+ depends on ARCH_AT91 || AVR32 - help - Enables support for NAND Flash / Smart Media Card interface -- on Atmel AT91 processors. -+ on Atmel AT91 and AVR32 processors. -+choice -+ prompt "ECC management for NAND Flash / SmartMedia on AT91 / AVR32" -+ depends on MTD_NAND_ATMEL -+ -+config MTD_NAND_ATMEL_ECC_HW -+ bool "Hardware ECC" -+ depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 || AVR32 -+ help -+ Use hardware ECC instead of software ECC when the chip -+ supports it. -+ -+ The hardware ECC controller is capable of single bit error -+ correction and 2-bit random detection per page. -+ -+ NB : hardware and software ECC schemes are incompatible. -+ If you switch from one to another, you'll have to erase your -+ mtd partition. -+ -+ If unsure, say Y -+ -+config MTD_NAND_ATMEL_ECC_SOFT -+ bool "Software ECC" -+ help -+ Use software ECC. -+ -+ NB : hardware and software ECC schemes are incompatible. -+ If you switch from one to another, you'll have to erase your -+ mtd partition. -+ -+config MTD_NAND_ATMEL_ECC_NONE -+ bool "No ECC (testing only, DANGEROUS)" -+ depends on DEBUG_KERNEL -+ help -+ No ECC will be used. -+ It's not a good idea and it should be reserved for testing -+ purpose only. -+ -+ If unsure, say N -+ -+ endchoice -+ -+endchoice - - config MTD_NAND_CM_X270 - tristate "Support for NAND Flash on CM-X270 modules" ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -24,7 +24,7 @@ - obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o - obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o - obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o --obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o -+obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o - obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o - obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o - obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -317,3 +317,5 @@ @@ -11519,6 +12192,32 @@ ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style +--- a/drivers/pcmcia/Kconfig ++++ b/drivers/pcmcia/Kconfig +@@ -277,6 +277,13 @@ + Say Y here to support the CompactFlash controller on the + PA Semi Electra eval board. + ++config AT32_CF ++ tristate "AT32AP CompactFlash Controller" ++ depends on PCMCIA && AVR32 && PLATFORM_AT32AP ++ help ++ Say Y here to support the CompactFlash controller on AT32 chips. ++ Or choose M to compile the driver as a module named "at32_cf". ++ + config PCCARD_NONSTATIC + tristate + +--- a/drivers/pcmcia/Makefile ++++ b/drivers/pcmcia/Makefile +@@ -38,6 +38,7 @@ + obj-$(CONFIG_OMAP_CF) += omap_cf.o + obj-$(CONFIG_AT91_CF) += at91_cf.o + obj-$(CONFIG_ELECTRA_CF) += electra_cf.o ++obj-$(CONFIG_AT32_CF) += at32_cf.o + + sa11xx_core-y += soc_common.o sa11xx_base.o + pxa2xx_core-y += soc_common.o pxa2xx_base.o --- /dev/null +++ b/drivers/pcmcia/at32_cf.c @@ -0,0 +1,533 @@ @@ -12055,35 +12754,57 @@ +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Driver for SMC PCMCIA interface"); +MODULE_AUTHOR("Hans-Christian Egtvedt "); ---- a/drivers/pcmcia/Kconfig -+++ b/drivers/pcmcia/Kconfig -@@ -277,6 +277,13 @@ - Say Y here to support the CompactFlash controller on the - PA Semi Electra eval board. +--- a/drivers/rtc/rtc-at32ap700x.c ++++ b/drivers/rtc/rtc-at32ap700x.c +@@ -262,6 +262,7 @@ + } -+config AT32_CF -+ tristate "AT32AP CompactFlash Controller" -+ depends on PCMCIA && AVR32 && PLATFORM_AT32AP -+ help -+ Say Y here to support the CompactFlash controller on AT32 chips. -+ Or choose M to compile the driver as a module named "at32_cf". -+ - config PCCARD_NONSTATIC - tristate + platform_set_drvdata(pdev, rtc); ++ device_init_wakeup(&pdev->dev, 1); ---- a/drivers/pcmcia/Makefile -+++ b/drivers/pcmcia/Makefile -@@ -38,6 +38,7 @@ - obj-$(CONFIG_OMAP_CF) += omap_cf.o - obj-$(CONFIG_AT91_CF) += at91_cf.o - obj-$(CONFIG_ELECTRA_CF) += electra_cf.o -+obj-$(CONFIG_AT32_CF) += at32_cf.o + dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", + (unsigned long)rtc->regs, rtc->irq); +@@ -281,6 +282,8 @@ + { + struct rtc_at32ap700x *rtc = platform_get_drvdata(pdev); - sa11xx_core-y += soc_common.o sa11xx_base.o - pxa2xx_core-y += soc_common.o pxa2xx_base.o ++ device_init_wakeup(&pdev->dev, 0); ++ + free_irq(rtc->irq, rtc); + iounmap(rtc->regs); + rtc_device_unregister(rtc->rtc); --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c -@@ -1440,6 +1440,15 @@ +@@ -957,6 +957,20 @@ + } + + /* ++ * Flush any TX data submitted for DMA. Called when the TX circular ++ * buffer is reset. ++ */ ++static void atmel_flush_buffer(struct uart_port *port) ++{ ++ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); ++ ++ if (atmel_use_dma_tx(port)) { ++ UART_PUT_TCR(port, 0); ++ atmel_port->pdc_tx.ofs = 0; ++ } ++} ++ ++/* + * Power / Clock management. + */ + static void atmel_serial_pm(struct uart_port *port, unsigned int state, +@@ -1190,6 +1204,7 @@ + .break_ctl = atmel_break_ctl, + .startup = atmel_startup, + .shutdown = atmel_shutdown, ++ .flush_buffer = atmel_flush_buffer, + .set_termios = atmel_set_termios, + .type = atmel_type, + .release_port = atmel_release_port, +@@ -1440,6 +1455,15 @@ }; #ifdef CONFIG_PM @@ -12099,7 +12820,7 @@ static int atmel_serial_suspend(struct platform_device *pdev, pm_message_t state) { -@@ -1447,7 +1456,7 @@ +@@ -1447,7 +1471,7 @@ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); if (device_may_wakeup(&pdev->dev) @@ -12108,6 +12829,17 @@ enable_irq_wake(port->irq); else { uart_suspend_port(&atmel_uart, port); +--- a/drivers/serial/serial_core.c ++++ b/drivers/serial/serial_core.c +@@ -552,6 +552,8 @@ + + spin_lock_irqsave(&port->lock, flags); + uart_circ_clear(&state->info->xmit); ++ if (port->ops->flush_buffer) ++ port->ops->flush_buffer(port); + spin_unlock_irqrestore(&port->lock, flags); + tty_wakeup(tty); + } --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -51,9 +51,7 @@ @@ -12332,6 +13064,21 @@ /* report completed message */ atmel_spi_msg_done(master, as, msg, 0, xfer->cs_change); +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -118,10 +118,10 @@ + config USB_GADGET_ATMEL_USBA + boolean "Atmel USBA" + select USB_GADGET_DUALSPEED +- depends on AVR32 ++ depends on AVR32 || ARCH_AT91CAP9 + help + USBA is the integrated high-speed USB Device controller on +- the AT32AP700x processors from Atmel. ++ the AT32AP700x and AT91CAP9 processors from Atmel. + + config USB_ATMEL_USBA + tristate --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -18,6 +18,7 @@ @@ -12684,21 +13431,6 @@ /* Bitfields in FNUM */ #define USBA_MICRO_FRAME_NUM_OFFSET 0 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -118,10 +118,10 @@ - config USB_GADGET_ATMEL_USBA - boolean "Atmel USBA" - select USB_GADGET_DUALSPEED -- depends on AVR32 -+ depends on AVR32 || ARCH_AT91CAP9 - help - USBA is the integrated high-speed USB Device controller on -- the AT32AP700x processors from Atmel. -+ the AT32AP700x and AT91CAP9 processors from Atmel. - - config USB_ATMEL_USBA - tristate --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -38,7 +38,9 @@ @@ -12846,12 +13578,13 @@ struct platform_device * at32_add_device_usba(unsigned int id, struct usba_platform_data *data); -@@ -68,8 +73,17 @@ +@@ -68,9 +73,27 @@ struct platform_device * at32_add_device_ssc(unsigned int id, unsigned int flags); -struct platform_device *at32_add_device_twi(unsigned int id); -struct platform_device *at32_add_device_mci(unsigned int id); +-struct platform_device *at32_add_device_ac97c(unsigned int id); +struct i2c_board_info; +struct platform_device *at32_add_device_twi(unsigned int id, + struct i2c_board_info *b, @@ -12863,10 +13596,20 @@ +}; +struct platform_device * +at32_add_device_mci(unsigned int id, struct mci_platform_data *data); - struct platform_device *at32_add_device_ac97c(unsigned int id); ++ ++struct ac97c_platform_data { ++ unsigned short dma_rx_periph_id; ++ unsigned short dma_tx_periph_id; ++ unsigned short dma_controller_id; ++ int reset_pin; ++}; ++struct platform_device * ++at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data); ++ struct platform_device *at32_add_device_abdac(unsigned int id); -@@ -84,4 +98,20 @@ + struct cf_platform_data { +@@ -84,4 +107,20 @@ at32_add_device_cf(unsigned int id, unsigned int extint, struct cf_platform_data *data); @@ -13452,6 +14195,16 @@ #endif #endif /* __ASM_AVR32_IOCTLS_H */ +--- a/include/asm-avr32/mmu_context.h ++++ b/include/asm-avr32/mmu_context.h +@@ -13,7 +13,6 @@ + #define __ASM_AVR32_MMU_CONTEXT_H + + #include +-#include + #include + #include + --- a/include/asm-avr32/page.h +++ b/include/asm-avr32/page.h @@ -8,13 +8,11 @@ @@ -13480,6 +14233,185 @@ +#include + #endif /* __ASM_AVR32_PCI_H__ */ +--- a/include/asm-avr32/pgalloc.h ++++ b/include/asm-avr32/pgalloc.h +@@ -8,65 +8,79 @@ + #ifndef __ASM_AVR32_PGALLOC_H + #define __ASM_AVR32_PGALLOC_H + +-#include +-#include +-#include +-#include ++#include ++#include ++#include + +-#define pmd_populate_kernel(mm, pmd, pte) \ +- set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) ++#define QUICK_PGD 0 /* Preserve kernel mappings over free */ ++#define QUICK_PT 1 /* Zero on free */ + +-static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, ++static inline void pmd_populate_kernel(struct mm_struct *mm, ++ pmd_t *pmd, pte_t *pte) ++{ ++ set_pmd(pmd, __pmd((unsigned long)pte)); ++} ++ ++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, + pgtable_t pte) + { +- set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); ++ set_pmd(pmd, __pmd((unsigned long)page_address(pte))); + } + #define pmd_pgtable(pmd) pmd_page(pmd) + ++static inline void pgd_ctor(void *x) ++{ ++ pgd_t *pgd = x; ++ ++ memcpy(pgd + USER_PTRS_PER_PGD, ++ swapper_pg_dir + USER_PTRS_PER_PGD, ++ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); ++} ++ + /* + * Allocate and free page tables + */ +-static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm) ++static inline pgd_t *pgd_alloc(struct mm_struct *mm) + { +- return kcalloc(USER_PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL); ++ return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor); + } + + static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) + { +- kfree(pgd); ++ quicklist_free(QUICK_PGD, NULL, pgd); + } + + static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) + { +- pte_t *pte; +- +- pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); +- +- return pte; ++ return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL); + } + +-static inline struct page *pte_alloc_one(struct mm_struct *mm, ++static inline pgtable_t pte_alloc_one(struct mm_struct *mm, + unsigned long address) + { +- struct page *pte; ++ struct page *page; ++ void *pg; + +- pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); +- if (!pte) ++ pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL); ++ if (!pg) + return NULL; +- pgtable_page_ctor(pte); +- return pte; ++ ++ page = virt_to_page(pg); ++ pgtable_page_ctor(page); ++ ++ return page; + } + + static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) + { +- free_page((unsigned long)pte); ++ quicklist_free(QUICK_PT, NULL, pte); + } + + static inline void pte_free(struct mm_struct *mm, pgtable_t pte) + { + pgtable_page_dtor(pte); +- __free_page(pte); ++ quicklist_free_page(QUICK_PT, NULL, pte); + } + + #define __pte_free_tlb(tlb,pte) \ +@@ -75,6 +89,10 @@ + tlb_remove_page((tlb), pte); \ + } while (0) + +-#define check_pgt_cache() do { } while(0) ++static inline void check_pgt_cache(void) ++{ ++ quicklist_trim(QUICK_PGD, NULL, 25, 16); ++ quicklist_trim(QUICK_PT, NULL, 25, 16); ++} + + #endif /* __ASM_AVR32_PGALLOC_H */ +--- a/include/asm-avr32/pgtable.h ++++ b/include/asm-avr32/pgtable.h +@@ -129,13 +129,6 @@ + + #define _PAGE_FLAGS_CACHE_MASK (_PAGE_CACHABLE | _PAGE_BUFFER | _PAGE_WT) + +-/* TODO: Check for saneness */ +-/* User-mode page table flags (to be set in a pgd or pmd entry) */ +-#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_TYPE_SMALL | _PAGE_RW \ +- | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) +-/* Kernel-mode page table flags */ +-#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_TYPE_SMALL | _PAGE_RW \ +- | _PAGE_ACCESSED | _PAGE_DIRTY) + /* Flags that may be modified by software */ + #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY \ + | _PAGE_FLAGS_CACHE_MASK) +@@ -254,10 +247,14 @@ + } + + #define pmd_none(x) (!pmd_val(x)) +-#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) +-#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) +-#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) \ +- != _KERNPG_TABLE) ++#define pmd_present(x) (pmd_val(x)) ++ ++static inline void pmd_clear(pmd_t *pmdp) ++{ ++ set_pmd(pmdp, __pmd(0)); ++} ++ ++#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK) + + /* + * Permanent address of a page. We don't support highmem, so this is +@@ -295,19 +292,16 @@ + + #define page_pte(page) page_pte_prot(page, __pgprot(0)) + +-#define pmd_page_vaddr(pmd) \ +- ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) +- +-#define pmd_page(pmd) (phys_to_page(pmd_val(pmd))) ++#define pmd_page_vaddr(pmd) pmd_val(pmd) ++#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) + + /* to find an entry in a page-table-directory. */ +-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +-#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) +-#define pgd_offset_current(address) \ +- ((pgd_t *)__mfsr(SYSREG_PTBR) + pgd_index(address)) ++#define pgd_index(address) (((address) >> PGDIR_SHIFT) \ ++ & (PTRS_PER_PGD - 1)) ++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) + + /* to find an entry in a kernel page-table-directory */ +-#define pgd_offset_k(address) pgd_offset(&init_mm, address) ++#define pgd_offset_k(address) pgd_offset(&init_mm, address) + + /* Find an entry in the third-level page table.. */ + #define pte_index(address) \ --- /dev/null +++ b/include/asm-avr32/serial.h @@ -0,0 +1,13 @@ @@ -13506,6 +14438,16 @@ #define TIF_DEBUG 30 /* debugging enabled */ #define TIF_USERSPACE 31 /* true if FS sets userspace */ +--- a/include/asm-avr32/tlbflush.h ++++ b/include/asm-avr32/tlbflush.h +@@ -26,7 +26,6 @@ + extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); + extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); +-extern void __flush_tlb_page(unsigned long asid, unsigned long page); + + extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); + --- /dev/null +++ b/include/asm-avr32/xor.h @@ -0,0 +1,6 @@ @@ -13781,6 +14723,16 @@ extern int write_inode_now(struct inode *, int); extern int filemap_fdatawrite(struct address_space *); extern int filemap_flush(struct address_space *); +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -188,6 +188,7 @@ + void (*break_ctl)(struct uart_port *, int ctl); + int (*startup)(struct uart_port *); + void (*shutdown)(struct uart_port *); ++ void (*flush_buffer)(struct uart_port *); + void (*set_termios)(struct uart_port *, struct ktermios *new, + struct ktermios *old); + void (*pm)(struct uart_port *, unsigned int state, --- /dev/null +++ b/include/linux/usb/atmel_usba_udc.h @@ -0,0 +1,22 @@ @@ -13806,424 +14758,62 @@ +}; + +#endif /* __LINUX_USB_USBA_H */ ---- a/include/mtd/Kbuild -+++ b/include/mtd/Kbuild -@@ -3,5 +3,4 @@ - header-y += mtd-abi.h - header-y += mtd-user.h - header-y += nftl-user.h --header-y += ubi-header.h - header-y += ubi-user.h ---- a/include/mtd/ubi-header.h -+++ /dev/null -@@ -1,372 +0,0 @@ --/* -- * Copyright (c) International Business Machines Corp., 2006 -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -- * the GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- * -- * Authors: Artem Bityutskiy (Битюцкий Артём) -- * Thomas Gleixner -- * Frank Haverkamp -- * Oliver Lohmann -- * Andreas Arnez -- */ -- --/* -- * This file defines the layout of UBI headers and all the other UBI on-flash -- * data structures. May be included by user-space. -- */ -- --#ifndef __UBI_HEADER_H__ --#define __UBI_HEADER_H__ -- --#include -- --/* The version of UBI images supported by this implementation */ --#define UBI_VERSION 1 -- --/* The highest erase counter value supported by this implementation */ --#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF -- --/* The initial CRC32 value used when calculating CRC checksums */ --#define UBI_CRC32_INIT 0xFFFFFFFFU -- --/* Erase counter header magic number (ASCII "UBI#") */ --#define UBI_EC_HDR_MAGIC 0x55424923 --/* Volume identifier header magic number (ASCII "UBI!") */ --#define UBI_VID_HDR_MAGIC 0x55424921 -- --/* -- * Volume type constants used in the volume identifier header. -- * -- * @UBI_VID_DYNAMIC: dynamic volume -- * @UBI_VID_STATIC: static volume -- */ --enum { -- UBI_VID_DYNAMIC = 1, -- UBI_VID_STATIC = 2 --}; -- --/* -- * Volume flags used in the volume table record. -- * -- * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume -- * -- * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume -- * table. UBI automatically re-sizes the volume which has this flag and makes -- * the volume to be of largest possible size. This means that if after the -- * initialization UBI finds out that there are available physical eraseblocks -- * present on the device, it automatically appends all of them to the volume -- * (the physical eraseblocks reserved for bad eraseblocks handling and other -- * reserved physical eraseblocks are not taken). So, if there is a volume with -- * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical -- * eraseblocks will be zero after UBI is loaded, because all of them will be -- * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared -- * after the volume had been initialized. -- * -- * The auto-resize feature is useful for device production purposes. For -- * example, different NAND flash chips may have different amount of initial bad -- * eraseblocks, depending of particular chip instance. Manufacturers of NAND -- * chips usually guarantee that the amount of initial bad eraseblocks does not -- * exceed certain percent, e.g. 2%. When one creates an UBI image which will be -- * flashed to the end devices in production, he does not know the exact amount -- * of good physical eraseblocks the NAND chip on the device will have, but this -- * number is required to calculate the volume sized and put them to the volume -- * table of the UBI image. In this case, one of the volumes (e.g., the one -- * which will store the root file system) is marked as "auto-resizable", and -- * UBI will adjust its size on the first boot if needed. -- * -- * Note, first UBI reserves some amount of physical eraseblocks for bad -- * eraseblock handling, and then re-sizes the volume, not vice-versa. This -- * means that the pool of reserved physical eraseblocks will always be present. -- */ --enum { -- UBI_VTBL_AUTORESIZE_FLG = 0x01, --}; -- --/* -- * Compatibility constants used by internal volumes. -- * -- * @UBI_COMPAT_DELETE: delete this internal volume before anything is written -- * to the flash -- * @UBI_COMPAT_RO: attach this device in read-only mode -- * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its -- * physical eraseblocks, don't allow the wear-leveling unit to move them -- * @UBI_COMPAT_REJECT: reject this UBI image -- */ --enum { -- UBI_COMPAT_DELETE = 1, -- UBI_COMPAT_RO = 2, -- UBI_COMPAT_PRESERVE = 4, -- UBI_COMPAT_REJECT = 5 --}; -- --/* Sizes of UBI headers */ --#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr) --#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr) -- --/* Sizes of UBI headers without the ending CRC */ --#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(__be32)) --#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32)) -- --/** -- * struct ubi_ec_hdr - UBI erase counter header. -- * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) -- * @version: version of UBI implementation which is supposed to accept this -- * UBI image -- * @padding1: reserved for future, zeroes -- * @ec: the erase counter -- * @vid_hdr_offset: where the VID header starts -- * @data_offset: where the user data start -- * @padding2: reserved for future, zeroes -- * @hdr_crc: erase counter header CRC checksum -- * -- * The erase counter header takes 64 bytes and has a plenty of unused space for -- * future usage. The unused fields are zeroed. The @version field is used to -- * indicate the version of UBI implementation which is supposed to be able to -- * work with this UBI image. If @version is greater then the current UBI -- * version, the image is rejected. This may be useful in future if something -- * is changed radically. This field is duplicated in the volume identifier -- * header. -- * -- * The @vid_hdr_offset and @data_offset fields contain the offset of the the -- * volume identifier header and user data, relative to the beginning of the -- * physical eraseblock. These values have to be the same for all physical -- * eraseblocks. -- */ --struct ubi_ec_hdr { -- __be32 magic; -- __u8 version; -- __u8 padding1[3]; -- __be64 ec; /* Warning: the current limit is 31-bit anyway! */ -- __be32 vid_hdr_offset; -- __be32 data_offset; -- __u8 padding2[36]; -- __be32 hdr_crc; --} __attribute__ ((packed)); -- --/** -- * struct ubi_vid_hdr - on-flash UBI volume identifier header. -- * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) -- * @version: UBI implementation version which is supposed to accept this UBI -- * image (%UBI_VERSION) -- * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) -- * @copy_flag: if this logical eraseblock was copied from another physical -- * eraseblock (for wear-leveling reasons) -- * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, -- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) -- * @vol_id: ID of this volume -- * @lnum: logical eraseblock number -- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be -- * removed, kept only for not breaking older UBI users) -- * @data_size: how many bytes of data this logical eraseblock contains -- * @used_ebs: total number of used logical eraseblocks in this volume -- * @data_pad: how many bytes at the end of this physical eraseblock are not -- * used -- * @data_crc: CRC checksum of the data stored in this logical eraseblock -- * @padding1: reserved for future, zeroes -- * @sqnum: sequence number -- * @padding2: reserved for future, zeroes -- * @hdr_crc: volume identifier header CRC checksum -- * -- * The @sqnum is the value of the global sequence counter at the time when this -- * VID header was created. The global sequence counter is incremented each time -- * UBI writes a new VID header to the flash, i.e. when it maps a logical -- * eraseblock to a new physical eraseblock. The global sequence counter is an -- * unsigned 64-bit integer and we assume it never overflows. The @sqnum -- * (sequence number) is used to distinguish between older and newer versions of -- * logical eraseblocks. -- * -- * There are 2 situations when there may be more then one physical eraseblock -- * corresponding to the same logical eraseblock, i.e., having the same @vol_id -- * and @lnum values in the volume identifier header. Suppose we have a logical -- * eraseblock L and it is mapped to the physical eraseblock P. -- * -- * 1. Because UBI may erase physical eraseblocks asynchronously, the following -- * situation is possible: L is asynchronously erased, so P is scheduled for -- * erasure, then L is written to,i.e. mapped to another physical eraseblock P1, -- * so P1 is written to, then an unclean reboot happens. Result - there are 2 -- * physical eraseblocks P and P1 corresponding to the same logical eraseblock -- * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the -- * flash. -- * -- * 2. From time to time UBI moves logical eraseblocks to other physical -- * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P -- * to P1, and an unclean reboot happens before P is physically erased, there -- * are two physical eraseblocks P and P1 corresponding to L and UBI has to -- * select one of them when the flash is attached. The @sqnum field says which -- * PEB is the original (obviously P will have lower @sqnum) and the copy. But -- * it is not enough to select the physical eraseblock with the higher sequence -- * number, because the unclean reboot could have happen in the middle of the -- * copying process, so the data in P is corrupted. It is also not enough to -- * just select the physical eraseblock with lower sequence number, because the -- * data there may be old (consider a case if more data was added to P1 after -- * the copying). Moreover, the unclean reboot may happen when the erasure of P -- * was just started, so it result in unstable P, which is "mostly" OK, but -- * still has unstable bits. -- * -- * UBI uses the @copy_flag field to indicate that this logical eraseblock is a -- * copy. UBI also calculates data CRC when the data is moved and stores it at -- * the @data_crc field of the copy (P1). So when UBI needs to pick one physical -- * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is -- * examined. If it is cleared, the situation* is simple and the newer one is -- * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC -- * checksum is correct, this physical eraseblock is selected (P1). Otherwise -- * the older one (P) is selected. -- * -- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum -- * in the past. But it is not used anymore and we keep it in order to be able -- * to deal with old UBI images. It will be removed at some point. -- * -- * There are 2 sorts of volumes in UBI: user volumes and internal volumes. -- * Internal volumes are not seen from outside and are used for various internal -- * UBI purposes. In this implementation there is only one internal volume - the -- * layout volume. Internal volumes are the main mechanism of UBI extensions. -- * For example, in future one may introduce a journal internal volume. Internal -- * volumes have their own reserved range of IDs. -- * -- * The @compat field is only used for internal volumes and contains the "degree -- * of their compatibility". It is always zero for user volumes. This field -- * provides a mechanism to introduce UBI extensions and to be still compatible -- * with older UBI binaries. For example, if someone introduced a journal in -- * future, he would probably use %UBI_COMPAT_DELETE compatibility for the -- * journal volume. And in this case, older UBI binaries, which know nothing -- * about the journal volume, would just delete this volume and work perfectly -- * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image -- * - it just ignores the Ext3fs journal. -- * -- * The @data_crc field contains the CRC checksum of the contents of the logical -- * eraseblock if this is a static volume. In case of dynamic volumes, it does -- * not contain the CRC checksum as a rule. The only exception is when the -- * data of the physical eraseblock was moved by the wear-leveling unit, then -- * the wear-leveling unit calculates the data CRC and stores it in the -- * @data_crc field. And of course, the @copy_flag is %in this case. -- * -- * The @data_size field is used only for static volumes because UBI has to know -- * how many bytes of data are stored in this eraseblock. For dynamic volumes, -- * this field usually contains zero. The only exception is when the data of the -- * physical eraseblock was moved to another physical eraseblock for -- * wear-leveling reasons. In this case, UBI calculates CRC checksum of the -- * contents and uses both @data_crc and @data_size fields. In this case, the -- * @data_size field contains data size. -- * -- * The @used_ebs field is used only for static volumes and indicates how many -- * eraseblocks the data of the volume takes. For dynamic volumes this field is -- * not used and always contains zero. -- * -- * The @data_pad is calculated when volumes are created using the alignment -- * parameter. So, effectively, the @data_pad field reduces the size of logical -- * eraseblocks of this volume. This is very handy when one uses block-oriented -- * software (say, cramfs) on top of the UBI volume. -- */ --struct ubi_vid_hdr { -- __be32 magic; -- __u8 version; -- __u8 vol_type; -- __u8 copy_flag; -- __u8 compat; -- __be32 vol_id; -- __be32 lnum; -- __be32 leb_ver; /* obsolete, to be removed, don't use */ -- __be32 data_size; -- __be32 used_ebs; -- __be32 data_pad; -- __be32 data_crc; -- __u8 padding1[4]; -- __be64 sqnum; -- __u8 padding2[12]; -- __be32 hdr_crc; --} __attribute__ ((packed)); -- --/* Internal UBI volumes count */ --#define UBI_INT_VOL_COUNT 1 -- --/* -- * Starting ID of internal volumes. There is reserved room for 4096 internal -- * volumes. -- */ --#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) -- --/* The layout volume contains the volume table */ -- --#define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START --#define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC --#define UBI_LAYOUT_VOLUME_ALIGN 1 --#define UBI_LAYOUT_VOLUME_EBS 2 --#define UBI_LAYOUT_VOLUME_NAME "layout volume" --#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT -- --/* The maximum number of volumes per one UBI device */ --#define UBI_MAX_VOLUMES 128 -- --/* The maximum volume name length */ --#define UBI_VOL_NAME_MAX 127 -- --/* Size of the volume table record */ --#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record) -- --/* Size of the volume table record without the ending CRC */ --#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32)) -- --/** -- * struct ubi_vtbl_record - a record in the volume table. -- * @reserved_pebs: how many physical eraseblocks are reserved for this volume -- * @alignment: volume alignment -- * @data_pad: how many bytes are unused at the end of the each physical -- * eraseblock to satisfy the requested alignment -- * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) -- * @upd_marker: if volume update was started but not finished -- * @name_len: volume name length -- * @name: the volume name -- * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) -- * @padding: reserved, zeroes -- * @crc: a CRC32 checksum of the record -- * -- * The volume table records are stored in the volume table, which is stored in -- * the layout volume. The layout volume consists of 2 logical eraseblock, each -- * of which contains a copy of the volume table (i.e., the volume table is -- * duplicated). The volume table is an array of &struct ubi_vtbl_record -- * objects indexed by the volume ID. -- * -- * If the size of the logical eraseblock is large enough to fit -- * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES -- * records. Otherwise, it contains as many records as it can fit (i.e., size of -- * logical eraseblock divided by sizeof(struct ubi_vtbl_record)). -- * -- * The @upd_marker flag is used to implement volume update. It is set to %1 -- * before update and set to %0 after the update. So if the update operation was -- * interrupted, UBI knows that the volume is corrupted. -- * -- * The @alignment field is specified when the volume is created and cannot be -- * later changed. It may be useful, for example, when a block-oriented file -- * system works on top of UBI. The @data_pad field is calculated using the -- * logical eraseblock size and @alignment. The alignment must be multiple to the -- * minimal flash I/O unit. If @alignment is 1, all the available space of -- * the physical eraseblocks is used. -- * -- * Empty records contain all zeroes and the CRC checksum of those zeroes. -- */ --struct ubi_vtbl_record { -- __be32 reserved_pebs; -- __be32 alignment; -- __be32 data_pad; -- __u8 vol_type; -- __u8 upd_marker; -- __be16 name_len; -- __u8 name[UBI_VOL_NAME_MAX+1]; -- __u8 flags; -- __u8 padding[23]; -- __be32 crc; --} __attribute__ ((packed)); -- --#endif /* !__UBI_HEADER_H__ */ ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -126,8 +126,14 @@ - - static int __init rootwait_setup(char *str) - { -- if (*str) -+ if (*str && *str != '=') - return 0; +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -187,7 +187,7 @@ + config NR_QUICK + int + depends on QUICKLIST +- default "2" if SUPERH ++ default "2" if SUPERH || AVR32 + default "1" + + config VIRT_TO_BUS +--- a/sound/Kconfig ++++ b/sound/Kconfig +@@ -63,6 +63,8 @@ + + source "sound/arm/Kconfig" + ++source "sound/avr32/Kconfig" + -+ if (*str) -+ printk(KERN_WARNING -+ "WARNING: \"rootwait=1\" is deprecated, " -+ "use \"rootwait\" instead.\n"); + if SPI + source "sound/spi/Kconfig" + endif +--- a/sound/Makefile ++++ b/sound/Makefile +@@ -6,7 +6,7 @@ + obj-$(CONFIG_SOUND_PRIME) += oss/ + obj-$(CONFIG_DMASOUND) += oss/ + obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ +- sparc/ spi/ parisc/ pcmcia/ mips/ soc/ ++ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ avr32/ + obj-$(CONFIG_SND_AOA) += aoa/ + + # This one must be compilable even if sound is configured out +--- /dev/null ++++ b/sound/avr32/Kconfig +@@ -0,0 +1,11 @@ ++menu "AVR32 devices" ++ depends on SND != n && AVR32 + - root_wait = 1; - return 1; - } -@@ -347,7 +353,8 @@ - - if (saved_root_name[0]) { - root_device_name = saved_root_name; -- if (!strncmp(root_device_name, "mtd", 3)) { -+ if (!strncmp(root_device_name, "mtd", 3) || -+ !strncmp(root_device_name, "ubi", 3)) { - mount_block_root(root_device_name, root_mountflags); - goto out; - } ++config SND_ATMEL_AC97 ++ tristate "Atmel AC97 Controller Driver" ++ select SND_PCM ++ select SND_AC97_CODEC ++ help ++ ALSA sound driver for the Atmel AC97 controller. ++ ++endmenu --- /dev/null -+++ b/localversion-atmel -@@ -0,0 +1 @@ -+.atmel.1 ++++ b/sound/avr32/Makefile +@@ -0,0 +1,3 @@ ++snd-atmel-ac97-objs := ac97c.o ++ ++obj-$(CONFIG_SND_ATMEL_AC97) += snd-atmel-ac97.o --- /dev/null +++ b/sound/avr32/ac97c.c -@@ -0,0 +1,914 @@ +@@ -0,0 +1,951 @@ +/* + * Driver for the Atmel AC97 controller + * @@ -14236,6 +14826,7 @@ +#include +#include +#include ++#include +#include +#include +#include @@ -14243,7 +14834,6 @@ +#include +#include + -+#include +#include +#include +#include @@ -14251,6 +14841,7 @@ +#include +#include + ++#include +#include + +#include "ac97c.h" @@ -14263,6 +14854,7 @@ + struct dma_request_cyclic req_rx; + unsigned short rx_periph_id; + unsigned short tx_periph_id; ++ unsigned short controller; +}; + +struct atmel_ac97 { @@ -14277,6 +14869,7 @@ + struct snd_ac97_bus *ac97_bus; + int opened; + int period; ++ int reset_pin; + u64 cur_format; + unsigned int cur_rate; + struct clk *mck; @@ -14918,6 +15511,14 @@ + +static void snd_atmel_ac97_reset(struct atmel_ac97 *chip) +{ ++ /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ ++ if (chip->reset_pin >= 0) { ++ gpio_set_value(chip->reset_pin, 0); ++ /* AC97 v2.2 specifications says minimum 1 us. */ ++ udelay(5); ++ gpio_set_value(chip->reset_pin, 1); ++ } ++ + ac97c_writel(chip, MR, AC97C_MR_WRST); + mdelay(1); + ac97c_writel(chip, MR, AC97C_MR_ENA); @@ -14953,6 +15554,7 @@ + .read = snd_atmel_ac97_read, + }; + struct atmel_ac97 *chip = get_chip(card); ++ struct ac97c_platform_data *pdata; + struct resource *regs; + struct clk *mck; + int err; @@ -14961,6 +15563,26 @@ + if (!regs) + return -ENXIO; + ++ pdata = pdev->dev.platform_data; ++ if (!pdata) ++ return -ENXIO; ++ ++ chip->reset_pin = pdata->reset_pin; ++ ++ /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ ++ if (chip->reset_pin >= 0) { ++ if (gpio_request(chip->reset_pin, chip->card->shortname)) { ++ dev_dbg(&pdev->dev, "ac97: reset pin not available\n"); ++ chip->reset_pin = -1; ++ } else { ++ gpio_direction_output(chip->reset_pin, 1); ++ } ++ } ++ ++ chip->dma.rx_periph_id = pdata->dma_rx_periph_id; ++ chip->dma.tx_periph_id = pdata->dma_tx_periph_id; ++ chip->dma.controller = pdata->dma_controller_id; ++ + mck = clk_get(&pdev->dev, "pclk"); + if (IS_ERR(mck)) + return PTR_ERR(mck); @@ -14999,7 +15621,9 @@ + THIS_MODULE, sizeof(struct atmel_ac97)); + if (!card) + goto out; ++ + chip = get_chip(card); ++ chip->reset_pin = -1; + + err = snd_atmel_ac97_create(card, pdev); + if (err) @@ -15015,23 +15639,19 @@ + if (err) + goto out_free_card; + -+ /* TODO: Get this information from the platform device */ -+ chip->dma.req_tx.req.dmac = find_dma_controller(0); ++ chip->dma.req_tx.req.dmac = find_dma_controller(chip->dma.controller); + if (!chip->dma.req_tx.req.dmac) { + dev_dbg(&chip->pdev->dev, "DMA controller for TX missing\n"); + err = -ENODEV; + goto out_free_card; + } -+ chip->dma.req_rx.req.dmac = find_dma_controller(0); ++ chip->dma.req_rx.req.dmac = find_dma_controller(chip->dma.controller); + if (!chip->dma.req_rx.req.dmac) { + dev_dbg(&chip->pdev->dev, "DMA controller for RX missing\n"); + err = -ENODEV; + goto out_free_card; + } + -+ chip->dma.rx_periph_id = 3; -+ chip->dma.tx_periph_id = 4; -+ + ch = dma_alloc_channel(chip->dma.req_tx.req.dmac); + if (ch < 0) { + dev_dbg(&chip->pdev->dev, @@ -15073,6 +15693,9 @@ + return 0; + +out_free_card: ++ /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ ++ if (chip->reset_pin >= 0) ++ gpio_free(chip->reset_pin); + snd_card_free(card); +out: + return err; @@ -15092,7 +15715,7 @@ + +static int snd_atmel_ac97_resume(struct platform_device *pdev) +{ -+ struct snd_card *card = dev_get_drvdata(pdev); ++ struct snd_card *card = platform_get_drvdata(pdev); + struct atmel_ac97 *chip = card->private_data; + + clk_enable(chip->mck); @@ -15107,7 +15730,11 @@ +static int __devexit snd_atmel_ac97_remove(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); ++ struct atmel_ac97 *chip = get_chip(card); + ++ /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ ++ if (chip->reset_pin >= 0) ++ gpio_free(chip->reset_pin); + snd_card_free(card); + platform_set_drvdata(pdev, NULL); + return 0; @@ -15212,48 +15839,26 @@ +#define AC97C_CHANNEL_B 0x2 + +#endif /* __SOUND_AVR32_AC97C_H */ ---- /dev/null -+++ b/sound/avr32/Kconfig -@@ -0,0 +1,11 @@ -+menu "AVR32 devices" -+ depends on SND != n && AVR32 -+ -+config SND_ATMEL_AC97 -+ tristate "Atmel AC97 Controller Driver" -+ select SND_PCM -+ select SND_AC97_CODEC -+ help -+ ALSA sound driver for the Atmel AC97 controller. -+ -+endmenu ---- /dev/null -+++ b/sound/avr32/Makefile -@@ -0,0 +1,3 @@ -+snd-atmel-ac97-objs := ac97c.o +--- a/sound/oss/Kconfig ++++ b/sound/oss/Kconfig +@@ -654,3 +654,7 @@ + int "DAC channel" + default "1" + depends on SOUND_SH_DAC_AUDIO + -+obj-$(CONFIG_SND_ATMEL_AC97) += snd-atmel-ac97.o ---- a/sound/Kconfig -+++ b/sound/Kconfig -@@ -63,6 +63,8 @@ - - source "sound/arm/Kconfig" ++config SOUND_AT32_ABDAC ++ tristate "Atmel AT32 Audio Bitstream DAC (ABDAC) support" ++ depends on SOUND_PRIME && AVR32 +--- a/sound/oss/Makefile ++++ b/sound/oss/Makefile +@@ -9,6 +9,7 @@ -+source "sound/avr32/Kconfig" -+ - if SPI - source "sound/spi/Kconfig" - endif ---- a/sound/Makefile -+++ b/sound/Makefile -@@ -6,7 +6,7 @@ - obj-$(CONFIG_SOUND_PRIME) += oss/ - obj-$(CONFIG_DMASOUND) += oss/ - obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ -- sparc/ spi/ parisc/ pcmcia/ mips/ soc/ -+ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ avr32/ - obj-$(CONFIG_SND_AOA) += aoa/ + # Please leave it as is, cause the link order is significant ! - # This one must be compilable even if sound is configured out ++obj-$(CONFIG_SOUND_AT32_ABDAC) += at32_abdac.o + obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o + obj-$(CONFIG_SOUND_HAL2) += hal2.o + obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o --- /dev/null +++ b/sound/oss/at32_abdac.c @@ -0,0 +1,722 @@ @@ -16041,26 +16646,6 @@ + __raw_writel((value), (port)->regs + DAC_##reg) + +#endif /* __SOUND_OSS_AT32_ABDAC_H__ */ ---- a/sound/oss/Kconfig -+++ b/sound/oss/Kconfig -@@ -654,3 +654,7 @@ - int "DAC channel" - default "1" - depends on SOUND_SH_DAC_AUDIO -+ -+config SOUND_AT32_ABDAC -+ tristate "Atmel AT32 Audio Bitstream DAC (ABDAC) support" -+ depends on SOUND_PRIME && AVR32 ---- a/sound/oss/Makefile -+++ b/sound/oss/Makefile -@@ -9,6 +9,7 @@ - - # Please leave it as is, cause the link order is significant ! - -+obj-$(CONFIG_SOUND_AT32_ABDAC) += at32_abdac.o - obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o - obj-$(CONFIG_SOUND_HAL2) += hal2.o - obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -737,7 +737,7 @@ diff --git a/target/linux/avr32/patches/120-fast_sd_cards_fix.patch b/target/linux/avr32/patches/120-fast_sd_cards_fix.patch deleted file mode 100644 index 2d79b9de05..0000000000 --- a/target/linux/avr32/patches/120-fast_sd_cards_fix.patch +++ /dev/null @@ -1,43 +0,0 @@ ---- a/drivers/mmc/host/atmel-mci.c -+++ b/drivers/mmc/host/atmel-mci.c -@@ -77,6 +77,7 @@ struct atmel_mci { - struct clk *mck; - struct platform_device *pdev; - -+ int pending_stop; - #ifdef CONFIG_DEBUG_FS - struct dentry *debugfs_root; - struct dentry *debugfs_regs; -@@ -866,6 +867,12 @@ static void atmci_tasklet_func(unsigned long priv) - data->bytes_xfered = data->blocks * data->blksz; - atmci_data_complete(host, data); - } -+ /* See if there is a pending STOP which can be sent */ -+ if (host->pending_stop && mci_cmd_is_complete(host)) { -+ host->pending_stop = 0; -+ if (mrq->stop && !mci_set_stop_sent_is_completed(host)) -+ send_stop_cmd(host->mmc, mrq->data, 0); -+ } - } - - static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status) -@@ -918,9 +925,16 @@ static void atmci_xfer_complete(struct dma_request *_req) - * drivers) or when interrupts are disabled for a long time. - */ - mci_set_dma_complete(host); -- if (data->stop && mci_cmd_is_complete(host) -- && !mci_set_stop_sent_is_completed(host)) -- send_stop_cmd(host->mmc, data, 0); -+ -+ if (data->stop) { -+ if (!mci_cmd_is_complete(host)) { -+ /* Just remember a STOP must be sent */ -+ host->pending_stop = 1; -+ } else if (!mci_set_stop_sent_is_completed(host)) { -+ send_stop_cmd(host->mmc, data, 0); -+ host->pending_stop = 0; -+ } -+ } - - /* - * Regardless of what the documentation says, we have to wait