diff options
author | Ulf Samuelsson <ulf.samuelsson@atmel.com> | 2009-01-29 09:32:45 +0000 |
---|---|---|
committer | Ulf Samuelsson <ulf.samuelsson@atmel.com> | 2009-01-29 09:32:45 +0000 |
commit | b47232e86922d3f18167ac42b47ef3b89e9c2c1a (patch) | |
tree | 8cd931b452946dfd50ac5f2f9fa601f5c8fc787f | |
parent | d459b1bc3d53dac0e1a3ee68893724a2878fad05 (diff) |
Add AVR32 support for linux-2.6.28.2
6 files changed, 16954 insertions, 49 deletions
diff --git a/target/device/Atmel/arch-avr32/Config.in.linux.patches b/target/device/Atmel/arch-avr32/Config.in.linux.patches index a8bcdbf1b..0b5f2cc96 100644 --- a/target/device/Atmel/arch-avr32/Config.in.linux.patches +++ b/target/device/Atmel/arch-avr32/Config.in.linux.patches @@ -3,70 +3,28 @@ choice depends on BR2_KERNEL_ARCH_PATCH_ENABLED depends on BR2_avr32 default BR2_ARCH_AVR32_2_6_27_6 if BR2_LINUX_2_6_27_6 - default BR2_ARCH_AVR32_2_6_25_10 if BR2_LINUX_2_6_25 - default BR2_ARCH_AVR32_2_6_24 if BR2_LINUX_2_6_24 - default BR2_ARCH_AVR32_2_6_23 if BR2_LINUX_2_6_23 - default BR2_ARCH_AVR32_2_6_22_10 if BR2_LINUX_2_6_22 || BR2_LINUX_2_6_22_10 - default BR2_ARCH_AVR32_2_6_22_1 if BR2_LINUX_2_6_22_1 - default BR2_ARCH_AVR32_2_6_21_5 if BR2_LINUX_2_6_21 || BR2_LINUX_2_6_21_5 - default BR2_ARCH_AVR32_2_6_20_4 if BR2_LINUX_2_6_20 || BR2_LINUX_2_6_20_4 - default BR2_ARCH_AVR32_2_6_24 + default BR2_ARCH_AVR32_2_6_28_2 help Select a patch to add to the Linux kernel +config BR2_ARCH_AVR32_2_6_28_2 + bool "2.6.28.2" + help + Apply the avr32 linux-2.6.28.2 patches + config BR2_ARCH_AVR32_2_6_27_6 bool "2.6.27.6" help Apply the avr32 linux-2.6.27.6 patches -config BR2_ARCH_AVR32_2_6_25_10 - bool "2.6.25.10" - help - Apply the avr32 linux-2.6.25.10 patches - -config BR2_ARCH_AVR32_2_6_24 - bool "2.6.24" - help - Apply the avr32 linux-2.6.24 patches - -config BR2_ARCH_AVR32_2_6_23 - bool "2.6.23" - help - Apply the avr32 linux-2.6.23 patches - -config BR2_ARCH_AVR32_2_6_22_10 - bool "2.6.22.10" - help - Apply the avr32 linux-2.6.22.10 patches - -config BR2_ARCH_AVR32_2_6_22_1 - bool "2.6.22.1" - help - Apply the avr32 linux-2.6.22.1 patches - -config BR2_ARCH_AVR32_2_6_21_5 - bool "2.6.21.5" - help - Apply the avr32 linux-2.6.21.5 patches - -config BR2_ARCH_AVR32_2_6_20_4 - bool "2.6.20.4" - help - Apply the avr32 linux-2.6.20.4 patches - endchoice config BR2_KERNEL_ARCH_PATCH_VERSION string depends on BR2_KERNEL_ARCH_PATCH_ENABLED depends on BR2_avr32 + default "2.6.28.2" if BR2_ARCH_AVR32_2_6_28_2 default "2.6.27.6" if BR2_ARCH_AVR32_2_6_27_6 - default "2.6.25.10" if BR2_ARCH_AVR32_2_6_25_10 - default "2.6.24" if BR2_ARCH_AVR32_2_6_24 - default "2.6.22.10" if BR2_ARCH_AVR32_2_6_22_10 - default "2.6.22.1" if BR2_ARCH_AVR32_2_6_22_1 - default "2.6.21.5" if BR2_ARCH_AVR32_2_6_21_5 - default "2.6.20.4" if BR2_ARCH_AVR32_2_6_20_4 config BR2_KERNEL_ARCH_PATCH_DIR string diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-100-avr32-atmel.1.patch b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-100-avr32-atmel.1.patch new file mode 100644 index 000000000..6512f77ef --- /dev/null +++ b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-100-avr32-atmel.1.patch @@ -0,0 +1,16813 @@ +diff -urN linux-2.6.28.2-0rig//arch/arm/mach-at91/include/mach/cpu.h linux-2.6.28.2/arch/arm/mach-at91/include/mach/cpu.h +--- linux-2.6.28.2-0rig//arch/arm/mach-at91/include/mach/cpu.h 2009-01-29 08:39:33.000000000 +0100 ++++ linux-2.6.28.2/arch/arm/mach-at91/include/mach/cpu.h 2009-01-29 08:52:44.000000000 +0100 +@@ -99,5 +99,6 @@ + * definitions may reduce clutter in common drivers. + */ + #define cpu_is_at32ap7000() (0) ++#define cpu_is_at32ap7200() (0) + + #endif +diff -urN linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/atstk1005.c linux-2.6.28.2/arch/avr32/boards/atstk1000/atstk1005.c +--- linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/atstk1005.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/boards/atstk1000/atstk1005.c 2009-01-29 08:52:48.000000000 +0100 +@@ -0,0 +1,225 @@ ++/* ++ * ATSTK1005 daughterboard-specific init code ++ * ++ * Copyright (C) 2005-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 <linux/device.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/list.h> ++#include <linux/string.h> ++#include <linux/mtd/partitions.h> ++#include <linux/spi/spi.h> ++ ++#include <asm/atmel-mci.h> ++#include <asm/setup.h> ++ ++#include <mach/at32ap720x.h> ++#include <mach/board.h> ++#include <mach/init.h> ++#include <mach/portmux.h> ++#include <mach/smc.h> ++ ++#include "atstk1000.h" ++ ++/* Oscillator frequencies. These are board specific */ ++unsigned long at32_board_osc_rates[4] = { ++ [0] = 20000000, /* 20 MHz on osc0 */ ++ [1] = 0, /* Nothing on osc1 */ ++ [2] = 12000000, /* 12 MHz on osc2 */ ++ [3] = 32768, /* 32.768 kHz on RTC osc */ ++}; ++ ++struct eth_addr { ++ u8 addr[6]; ++}; ++ ++static struct eth_addr __initdata hw_addr; ++static struct eth_platform_data __initdata eth_data; ++ ++static struct mci_platform_data mci_data __initdata = { ++ .slot[0] = { ++ .detect_pin = GPIO_PIN_NONE, ++ .wp_pin = GPIO_PIN_NONE, ++ .bus_width = 4, ++ }, ++ .slot[1] = { ++ .detect_pin = GPIO_PIN_PA(30), ++ .wp_pin = GPIO_PIN_PA(31), ++ .bus_width = 8, ++ }, ++}; ++ ++static struct spi_board_info spi0_board_info[] __initdata = { ++ { ++ /* AT45DB642D: 8MB DataFlash */ ++ .modalias = "mtd_dataflash", ++ .max_speed_hz = 8000000, ++ .chip_select = 0, ++ .mode = SPI_MODE_0, ++ }, { ++ /* QVGA display */ ++ .modalias = "ltv350qv", ++ .max_speed_hz = 8000000, ++ .chip_select = 2, ++ .mode = SPI_MODE_3, ++ }, ++}; ++ ++static struct smc_timing nand_timing __initdata = { ++ .ncs_read_setup = 0, ++ .nrd_setup = 10, ++ .ncs_write_setup = 0, ++ .nwe_setup = 10, ++ ++ .ncs_read_pulse = 30, ++ .nrd_pulse = 15, ++ .ncs_write_pulse = 30, ++ .nwe_pulse = 15, ++ ++ .read_cycle = 30, ++ .write_cycle = 30, ++ ++ .ncs_read_recover = 0, ++ .nrd_recover = 15, ++ .ncs_write_recover = 0, ++ .nwe_recover = 50, ++}; ++ ++static struct smc_config nand_config __initdata = { ++ .bus_width = 1, ++ .nrd_controlled = 1, ++ .nwe_controlled = 1, ++ .nwait_mode = 0, ++ .byte_write = 0, ++ .tdf_cycles = 3, ++ .tdf_mode = 0, ++}; ++ ++static struct mtd_partition nand_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 131072, ++ }, { ++ .name = "kernel", ++ .offset = 262144, ++ .size = 2097152, ++ }, { ++ .name = "user", ++ .offset = 2359296, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++/* Isn't this rather more complicated than necessary? */ ++static struct mtd_partition *nand_part_info(int size, int *num_partitions) ++{ ++ *num_partitions = ARRAY_SIZE(nand_partitions); ++ return nand_partitions; ++} ++ ++static struct atmel_nand_data nand_data __initdata = { ++ .cle = 21, ++ .ale = 22, ++ .rdy_pin = GPIO_PIN_PE(31), ++ .enable_pin = GPIO_PIN_PF(2), ++ .det_pin = GPIO_PIN_NONE, ++ .partition_info = nand_part_info, ++}; ++ ++ ++/* ++ * Grab ethernet address and PHY address provided by the boot loader. ++ */ ++static int __init parse_tag_ethernet(struct tag *tag) ++{ ++ struct tag_ethernet *etag = &tag->u.ethernet; ++ ++ if (etag->mac_index == 0) { ++ eth_data.phy_mask = ~(1U << etag->mii_phy_addr); ++ memcpy(&hw_addr.addr, etag->hw_address, sizeof(hw_addr.addr)); ++ } ++ ++ return 0; ++} ++__tagtable(ATAG_ETHERNET, parse_tag_ethernet); ++ ++/* ++ * We need to get rid of this crap and pass the mac address to the ++ * driver explicitly. ++ */ ++#include <linux/clk.h> ++#include <linux/etherdevice.h> ++#include <linux/io.h> ++#include <linux/ioport.h> ++#include <linux/platform_device.h> ++static void __init set_hw_addr(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ const u8 *addr; ++ void __iomem *regs; ++ struct clk *pclk; ++ ++ if (!res) ++ return; ++ if (pdev->id != 0) ++ return; ++ ++ addr = hw_addr.addr; ++ if (!is_valid_ether_addr(addr)) ++ return; ++ ++ /* ++ * Since this is board-specific code, we'll cheat and use the ++ * physical address directly as we happen to know that it's ++ * the same as the virtual address. ++ */ ++ regs = (void __iomem __force *)res->start; ++ pclk = clk_get(&pdev->dev, "pclk"); ++ if (!pclk) ++ return; ++ ++ clk_enable(pclk); ++ __raw_writel((addr[3] << 24) | (addr[2] << 16) ++ | (addr[1] << 8) | addr[0], regs + 0x98); ++ __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); ++ clk_disable(pclk); ++ clk_put(pclk); ++} ++ ++void __init setup_board(void) ++{ ++ at32_map_usart(4, 0); /* USART4: /dev/ttyS0, DB9 */ ++ at32_setup_serial_console(0); ++} ++ ++static int __init atstk1005_init(void) ++{ ++ struct platform_device *lcdc_pdev; ++ ++ at32_add_device_usart(0); ++ ++ set_hw_addr(at32_add_device_eth(0, ð_data)); ++ lcdc_pdev = at32_add_device_lcdc(0, &atstk1000_lcdc_data, ++ fbmem_start, fbmem_size, 0); ++ at32_add_device_mpop(0, lcdc_pdev, fbmem_start, fbmem_size); ++ at32_add_device_mci(0, &mci_data); ++ at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); ++ ++ /* NAND Flash */ ++ smc_set_timing(&nand_config, &nand_timing); ++ smc_set_configuration(3, &nand_config); ++ at32_add_device_nand(0, &nand_data); ++ ++ /* USB OHCI/EHCI host */ ++ at32_add_device_ohci(0); ++ at32_add_device_ehci(0); ++ ++ return 0; ++} ++postcore_initcall(atstk1005_init); +diff -urN linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/Kconfig linux-2.6.28.2/arch/avr32/boards/atstk1000/Kconfig +--- linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/Kconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/boards/atstk1000/Kconfig 2009-01-29 08:52:48.000000000 +0100 +@@ -18,6 +18,10 @@ + bool "ATSTK1004" + select CPU_AT32AP7002 + ++config BOARD_ATSTK1005 ++ bool "ATSTK1005" ++ select CPU_AT32AP7200 ++ + config BOARD_ATSTK1006 + bool "ATSTK1006" + select CPU_AT32AP7000 +diff -urN linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/Makefile linux-2.6.28.2/arch/avr32/boards/atstk1000/Makefile +--- linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/Makefile 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/boards/atstk1000/Makefile 2009-01-29 08:52:48.000000000 +0100 +@@ -2,4 +2,5 @@ + obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o + obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o + obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o ++obj-$(CONFIG_BOARD_ATSTK1005) += atstk1005.o + obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o +diff -urN linux-2.6.28.2-0rig//arch/avr32/configs/atngw100_defconfig linux-2.6.28.2/arch/avr32/configs/atngw100_defconfig +--- linux-2.6.28.2-0rig//arch/avr32/configs/atngw100_defconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/configs/atngw100_defconfig 2009-01-29 08:52:48.000000000 +0100 +@@ -1,7 +1,7 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.27-rc1 +-# Tue Aug 5 16:00:47 2008 ++# Linux kernel version: 2.6.27.4 ++# Thu Nov 13 14:33:33 2008 + # + CONFIG_AVR32=y + CONFIG_GENERIC_GPIO=y +@@ -130,11 +130,15 @@ + CONFIG_SUBARCH_AVR32B=y + CONFIG_MMU=y + CONFIG_PERFORMANCE_COUNTERS=y ++CONFIG_PORTMUX_PIO=y + CONFIG_PLATFORM_AT32AP=y + CONFIG_CPU_AT32AP700X=y + CONFIG_CPU_AT32AP7000=y + # CONFIG_BOARD_ATSTK1000 is not set + CONFIG_BOARD_ATNGW100=y ++# CONFIG_BOARD_FAVR_32 is not set ++# CONFIG_BOARD_MIMC200 is not set ++# CONFIG_BOARD_ATNGW100_EVKLCD10X is not set + CONFIG_LOADER_U_BOOT=y + + # +@@ -177,7 +181,7 @@ + # CONFIG_HZ_300 is not set + # CONFIG_HZ_1000 is not set + CONFIG_HZ=250 +-# CONFIG_SCHED_HRTICK is not set ++CONFIG_SCHED_HRTICK=y + CONFIG_CMDLINE="" + + # +@@ -615,6 +619,7 @@ + CONFIG_I2C=m + CONFIG_I2C_BOARDINFO=y + CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_HELPER_AUTO=y + CONFIG_I2C_ALGOBIT=m + + # +@@ -664,6 +669,7 @@ + # + # SPI Master Controller Drivers + # ++CONFIG_SPI_ATMEL_HAVE_PDC=y + CONFIG_SPI_ATMEL=y + # CONFIG_SPI_BITBANG is not set + +@@ -706,7 +712,7 @@ + # Watchdog Device Drivers + # + # CONFIG_SOFT_WATCHDOG is not set +-CONFIG_AT32AP700X_WDT=y ++CONFIG_AT32_WDT=y + + # + # Sonics Silicon Backplane +@@ -720,6 +726,7 @@ + # CONFIG_MFD_CORE is not set + # CONFIG_MFD_SM501 is not set + # CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set + + # + # Multimedia devices +@@ -751,11 +758,14 @@ + # CONFIG_DISPLAY_SUPPORT is not set + # CONFIG_SOUND is not set + CONFIG_USB_SUPPORT=y +-# CONFIG_USB_ARCH_HAS_HCD is not set +-# CONFIG_USB_ARCH_HAS_OHCI is not set +-# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++# CONFIG_USB is not set + # CONFIG_USB_OTG_WHITELIST is not set + # CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MUSB_HDRC is not set ++# CONFIG_USB_GADGET_MUSB_HDRC is not set + + # + # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +@@ -806,6 +816,7 @@ + # + # CONFIG_MMC_SDHCI is not set + CONFIG_MMC_ATMELMCI=y ++# CONFIG_MMC_ATMELMCI_DMA is not set + CONFIG_MMC_SPI=m + # CONFIG_MEMSTICK is not set + CONFIG_NEW_LEDS=y +@@ -880,11 +891,13 @@ + # on-CPU RTC drivers + # + CONFIG_RTC_DRV_AT32AP700X=y ++# CONFIG_RTC_DRV_AVR32_AST is not set + CONFIG_DMADEVICES=y + + # + # DMA Devices + # ++# CONFIG_ATMEL_PDCA is not set + CONFIG_DW_DMAC=y + CONFIG_DMA_ENGINE=y + +@@ -898,13 +911,13 @@ + # + # File systems + # +-CONFIG_EXT2_FS=m ++CONFIG_EXT2_FS=y + # CONFIG_EXT2_FS_XATTR is not set + # CONFIG_EXT2_FS_XIP is not set +-CONFIG_EXT3_FS=m ++CONFIG_EXT3_FS=y + # CONFIG_EXT3_FS_XATTR is not set + # CONFIG_EXT4DEV_FS is not set +-CONFIG_JBD=m ++CONFIG_JBD=y + # CONFIG_REISERFS_FS is not set + # CONFIG_JFS_FS is not set + # CONFIG_FS_POSIX_ACL is not set +@@ -944,7 +957,7 @@ + CONFIG_TMPFS=y + # CONFIG_TMPFS_POSIX_ACL is not set + # CONFIG_HUGETLB_PAGE is not set +-CONFIG_CONFIGFS_FS=m ++CONFIG_CONFIGFS_FS=y + + # + # Miscellaneous filesystems +diff -urN linux-2.6.28.2-0rig//arch/avr32/configs/atstk1002_defconfig linux-2.6.28.2/arch/avr32/configs/atstk1002_defconfig +--- linux-2.6.28.2-0rig//arch/avr32/configs/atstk1002_defconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/configs/atstk1002_defconfig 2009-01-29 08:52:49.000000000 +0100 +@@ -1,7 +1,7 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.27-rc1 +-# Mon Aug 4 16:02:27 2008 ++# Linux kernel version: 2.6.27.4 ++# Wed Nov 12 10:28:45 2008 + # + CONFIG_AVR32=y + CONFIG_GENERIC_GPIO=y +@@ -129,20 +129,24 @@ + CONFIG_SUBARCH_AVR32B=y + CONFIG_MMU=y + CONFIG_PERFORMANCE_COUNTERS=y ++CONFIG_PORTMUX_PIO=y + CONFIG_PLATFORM_AT32AP=y + CONFIG_CPU_AT32AP700X=y + CONFIG_CPU_AT32AP7000=y + CONFIG_BOARD_ATSTK1000=y + # CONFIG_BOARD_ATNGW100 is not set ++# CONFIG_BOARD_FAVR_32 is not set ++# CONFIG_BOARD_MIMC200 is not set + CONFIG_BOARD_ATSTK1002=y + # CONFIG_BOARD_ATSTK1003 is not set + # CONFIG_BOARD_ATSTK1004 is not set ++# CONFIG_BOARD_ATSTK1005 is not set + # CONFIG_BOARD_ATSTK1006 is not set + # CONFIG_BOARD_ATSTK100X_CUSTOM is not set + # CONFIG_BOARD_ATSTK100X_SPI1 is not set +-# CONFIG_BOARD_ATSTK1000_J2_LED is not set ++CONFIG_BOARD_ATSTK1000_J2_LED=y + # CONFIG_BOARD_ATSTK1000_J2_LED8 is not set +-# CONFIG_BOARD_ATSTK1000_J2_RGB is not set ++CONFIG_BOARD_ATSTK1000_J2_RGB=y + CONFIG_BOARD_ATSTK1000_EXTDAC=y + CONFIG_LOADER_U_BOOT=y + +@@ -186,7 +190,7 @@ + # CONFIG_HZ_300 is not set + # CONFIG_HZ_1000 is not set + CONFIG_HZ=250 +-# CONFIG_SCHED_HRTICK is not set ++CONFIG_SCHED_HRTICK=y + CONFIG_CMDLINE="" + + # +@@ -360,7 +364,8 @@ + # + CONFIG_MTD_CHAR=y + CONFIG_MTD_BLKDEVS=y +-CONFIG_MTD_BLOCK=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set + # CONFIG_FTL is not set + # CONFIG_NFTL is not set + # CONFIG_INFTL is not set +@@ -421,12 +426,23 @@ + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOC2001PLUS is not set + # CONFIG_MTD_NAND is not set ++# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set ++# CONFIG_MTD_NAND_ATMEL_ECC_SOFT is not set ++# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set + # CONFIG_MTD_ONENAND is not set + + # + # UBI - Unsorted block images + # +-# CONFIG_MTD_UBI is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++ ++# ++# UBI debugging options ++# ++# CONFIG_MTD_UBI_DEBUG is not set + # CONFIG_PARPORT is not set + CONFIG_BLK_DEV=y + # CONFIG_BLK_DEV_COW_COMMON is not set +@@ -502,7 +518,7 @@ + # CONFIG_BONDING is not set + # CONFIG_MACVLAN is not set + # CONFIG_EQUALIZER is not set +-CONFIG_TUN=m ++# CONFIG_TUN is not set + # CONFIG_VETH is not set + CONFIG_PHYLIB=y + +@@ -561,7 +577,7 @@ + # + # Input device support + # +-CONFIG_INPUT=m ++CONFIG_INPUT=y + # CONFIG_INPUT_FF_MEMLESS is not set + CONFIG_INPUT_POLLDEV=m + +@@ -590,6 +606,8 @@ + CONFIG_INPUT_MOUSE=y + # CONFIG_MOUSE_PS2 is not set + # CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set + # CONFIG_MOUSE_VSXXXAA is not set + CONFIG_MOUSE_GPIO=m + # CONFIG_INPUT_JOYSTICK is not set +@@ -606,8 +624,12 @@ + # + # Character devices + # +-# CONFIG_VT is not set +-# CONFIG_DEVKMEM is not set ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y + # CONFIG_SERIAL_NONSTANDARD is not set + + # +@@ -634,6 +656,7 @@ + CONFIG_I2C=m + CONFIG_I2C_BOARDINFO=y + CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_HELPER_AUTO=y + CONFIG_I2C_ALGOBIT=m + + # +@@ -663,7 +686,7 @@ + # Miscellaneous I2C Chip support + # + # CONFIG_DS1682 is not set +-CONFIG_AT24=m ++# CONFIG_AT24 is not set + # CONFIG_SENSORS_EEPROM is not set + # CONFIG_SENSORS_PCF8574 is not set + # CONFIG_PCF8575 is not set +@@ -683,6 +706,7 @@ + # + # SPI Master Controller Drivers + # ++CONFIG_SPI_ATMEL_HAVE_PDC=y + CONFIG_SPI_ATMEL=y + # CONFIG_SPI_BITBANG is not set + +@@ -725,7 +749,7 @@ + # Watchdog Device Drivers + # + # CONFIG_SOFT_WATCHDOG is not set +-CONFIG_AT32AP700X_WDT=y ++CONFIG_AT32_WDT=y + + # + # Sonics Silicon Backplane +@@ -739,6 +763,7 @@ + # CONFIG_MFD_CORE is not set + # CONFIG_MFD_SM501 is not set + # CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set + + # + # Multimedia devices +@@ -784,6 +809,7 @@ + # + # CONFIG_FB_S1D13XXX is not set + CONFIG_FB_ATMEL=y ++# CONFIG_FB_ATMEL_MPOP is not set + # CONFIG_FB_VIRTUAL is not set + CONFIG_BACKLIGHT_LCD_SUPPORT=y + CONFIG_LCD_CLASS_DEVICE=y +@@ -797,6 +823,12 @@ + # Display device support + # + # CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set + # CONFIG_LOGO is not set + CONFIG_SOUND=m + CONFIG_SND=m +@@ -820,11 +852,14 @@ + # CONFIG_SOUND_PRIME is not set + # CONFIG_HID_SUPPORT is not set + CONFIG_USB_SUPPORT=y +-# CONFIG_USB_ARCH_HAS_HCD is not set +-# CONFIG_USB_ARCH_HAS_OHCI is not set +-# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++# CONFIG_USB is not set + # CONFIG_USB_OTG_WHITELIST is not set + # CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MUSB_HDRC is not set ++# CONFIG_USB_GADGET_MUSB_HDRC is not set + + # + # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +@@ -876,6 +911,7 @@ + # + # CONFIG_MMC_SDHCI is not set + CONFIG_MMC_ATMELMCI=y ++# CONFIG_MMC_ATMELMCI_DMA is not set + CONFIG_MMC_SPI=m + # CONFIG_MEMSTICK is not set + CONFIG_NEW_LEDS=y +@@ -952,11 +988,13 @@ + # on-CPU RTC drivers + # + CONFIG_RTC_DRV_AT32AP700X=y ++# CONFIG_RTC_DRV_AVR32_AST is not set + CONFIG_DMADEVICES=y + + # + # DMA Devices + # ++# CONFIG_ATMEL_PDCA is not set + CONFIG_DW_DMAC=y + CONFIG_DMA_ENGINE=y + +@@ -1017,7 +1055,7 @@ + CONFIG_TMPFS=y + # CONFIG_TMPFS_POSIX_ACL is not set + # CONFIG_HUGETLB_PAGE is not set +-# CONFIG_CONFIGFS_FS is not set ++CONFIG_CONFIGFS_FS=y + + # + # Miscellaneous filesystems +@@ -1031,7 +1069,8 @@ + # CONFIG_EFS_FS is not set + CONFIG_JFFS2_FS=y + CONFIG_JFFS2_FS_DEBUG=0 +-# CONFIG_JFFS2_FS_WRITEBUFFER is not set ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set + # CONFIG_JFFS2_SUMMARY is not set + # CONFIG_JFFS2_FS_XATTR is not set + # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +@@ -1039,6 +1078,12 @@ + # CONFIG_JFFS2_LZO is not set + CONFIG_JFFS2_RTIME=y + # CONFIG_JFFS2_RUBIN is not set ++CONFIG_UBIFS_FS=y ++CONFIG_UBIFS_FS_XATTR=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_FS_DEBUG is not set + # CONFIG_CRAMFS is not set + # CONFIG_VXFS_FS is not set + CONFIG_MINIX_FS=m +@@ -1173,7 +1218,7 @@ + # + # Crypto core or helper + # +-CONFIG_CRYPTO_ALGAPI=m ++CONFIG_CRYPTO_ALGAPI=y + CONFIG_CRYPTO_AEAD=m + CONFIG_CRYPTO_BLKCIPHER=m + CONFIG_CRYPTO_HASH=m +@@ -1247,8 +1292,8 @@ + # + # Compression + # +-CONFIG_CRYPTO_DEFLATE=m +-# CONFIG_CRYPTO_LZO is not set ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZO=y + # CONFIG_CRYPTO_HW is not set + + # +@@ -1258,7 +1303,7 @@ + # CONFIG_GENERIC_FIND_FIRST_BIT is not set + # CONFIG_GENERIC_FIND_NEXT_BIT is not set + CONFIG_CRC_CCITT=m +-# CONFIG_CRC16 is not set ++CONFIG_CRC16=y + CONFIG_CRC_T10DIF=m + CONFIG_CRC_ITU_T=m + CONFIG_CRC32=y +@@ -1266,6 +1311,8 @@ + # CONFIG_LIBCRC32C is not set + CONFIG_ZLIB_INFLATE=y + CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y + CONFIG_GENERIC_ALLOCATOR=y + CONFIG_PLIST=y + CONFIG_HAS_IOMEM=y +diff -urN linux-2.6.28.2-0rig//arch/avr32/configs/atstk1003_defconfig linux-2.6.28.2/arch/avr32/configs/atstk1003_defconfig +--- linux-2.6.28.2-0rig//arch/avr32/configs/atstk1003_defconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/configs/atstk1003_defconfig 2009-01-29 08:52:49.000000000 +0100 +@@ -1,7 +1,7 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.27-rc1 +-# Tue Aug 5 15:34:44 2008 ++# Linux kernel version: 2.6.27.4 ++# Wed Nov 12 10:33:33 2008 + # + CONFIG_AVR32=y + CONFIG_GENERIC_GPIO=y +@@ -34,12 +34,9 @@ + CONFIG_SYSVIPC=y + CONFIG_SYSVIPC_SYSCTL=y + CONFIG_POSIX_MQUEUE=y +-CONFIG_BSD_PROCESS_ACCT=y +-CONFIG_BSD_PROCESS_ACCT_V3=y +-CONFIG_TASKSTATS=y +-CONFIG_TASK_DELAY_ACCT=y +-# CONFIG_TASK_XACCT is not set +-CONFIG_AUDIT=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set + # CONFIG_IKCONFIG is not set + CONFIG_LOG_BUF_SHIFT=14 + # CONFIG_CGROUPS is not set +@@ -71,7 +68,7 @@ + CONFIG_EVENTFD=y + CONFIG_SHMEM=y + CONFIG_VM_EVENT_COUNTERS=y +-# CONFIG_SLUB_DEBUG is not set ++CONFIG_SLUB_DEBUG=y + # CONFIG_SLAB is not set + CONFIG_SLUB=y + # CONFIG_SLOB is not set +@@ -90,6 +87,7 @@ + CONFIG_HAVE_CLK=y + CONFIG_PROC_PAGE_MONITOR=y + # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set ++CONFIG_SLABINFO=y + CONFIG_RT_MUTEXES=y + # CONFIG_TINY_SHMEM is not set + CONFIG_BASE_SMALL=1 +@@ -131,20 +129,24 @@ + CONFIG_SUBARCH_AVR32B=y + CONFIG_MMU=y + CONFIG_PERFORMANCE_COUNTERS=y ++CONFIG_PORTMUX_PIO=y + CONFIG_PLATFORM_AT32AP=y + CONFIG_CPU_AT32AP700X=y + CONFIG_CPU_AT32AP7001=y + CONFIG_BOARD_ATSTK1000=y + # CONFIG_BOARD_ATNGW100 is not set ++# CONFIG_BOARD_FAVR_32 is not set ++# CONFIG_BOARD_MIMC200 is not set + # CONFIG_BOARD_ATSTK1002 is not set + CONFIG_BOARD_ATSTK1003=y + # CONFIG_BOARD_ATSTK1004 is not set ++# CONFIG_BOARD_ATSTK1005 is not set + # CONFIG_BOARD_ATSTK1006 is not set + # CONFIG_BOARD_ATSTK100X_CUSTOM is not set + # CONFIG_BOARD_ATSTK100X_SPI1 is not set +-# CONFIG_BOARD_ATSTK1000_J2_LED is not set ++CONFIG_BOARD_ATSTK1000_J2_LED=y + # CONFIG_BOARD_ATSTK1000_J2_LED8 is not set +-# CONFIG_BOARD_ATSTK1000_J2_RGB is not set ++CONFIG_BOARD_ATSTK1000_J2_RGB=y + CONFIG_BOARD_ATSTK1000_EXTDAC=y + CONFIG_LOADER_U_BOOT=y + +@@ -188,7 +190,7 @@ + # CONFIG_HZ_300 is not set + # CONFIG_HZ_1000 is not set + CONFIG_HZ=250 +-# CONFIG_SCHED_HRTICK is not set ++CONFIG_SCHED_HRTICK=y + CONFIG_CMDLINE="" + + # +@@ -239,40 +241,71 @@ + CONFIG_PACKET=y + CONFIG_PACKET_MMAP=y + CONFIG_UNIX=y +-# CONFIG_NET_KEY is not set ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=m ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_XFRM_IPCOMP=m ++CONFIG_NET_KEY=m ++# CONFIG_NET_KEY_MIGRATE is not set + CONFIG_INET=y + # CONFIG_IP_MULTICAST is not set + # CONFIG_IP_ADVANCED_ROUTER is not set + CONFIG_IP_FIB_HASH=y +-# CONFIG_IP_PNP is not set +-# CONFIG_NET_IPIP is not set +-# CONFIG_NET_IPGRE is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_IP_PNP_BOOTP is not set ++# CONFIG_IP_PNP_RARP is not set ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE=m + # CONFIG_ARPD is not set + # CONFIG_SYN_COOKIES is not set +-# CONFIG_INET_AH is not set +-# CONFIG_INET_ESP is not set ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m + # CONFIG_INET_IPCOMP is not set + # CONFIG_INET_XFRM_TUNNEL is not set +-# CONFIG_INET_TUNNEL is not set +-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +-# CONFIG_INET_XFRM_MODE_TUNNEL is not set +-# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m + # CONFIG_INET_LRO is not set +-# CONFIG_INET_DIAG is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y + # CONFIG_TCP_CONG_ADVANCED is not set + CONFIG_TCP_CONG_CUBIC=y + CONFIG_DEFAULT_TCP_CONG="cubic" + # CONFIG_TCP_MD5SIG is not set +-# CONFIG_IPV6 is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++# CONFIG_IPV6_MIP6 is not set ++CONFIG_INET6_XFRM_TUNNEL=m ++CONFIG_INET6_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPV6_TUNNEL=m ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set + # CONFIG_NETWORK_SECMARK is not set + # CONFIG_NETFILTER is not set + # CONFIG_IP_DCCP is not set + # CONFIG_IP_SCTP is not set + # CONFIG_TIPC is not set + # CONFIG_ATM is not set +-# CONFIG_BRIDGE is not set ++CONFIG_STP=m ++CONFIG_BRIDGE=m + # CONFIG_VLAN_8021Q is not set + # CONFIG_DECNET is not set ++CONFIG_LLC=m + # CONFIG_LLC2 is not set + # CONFIG_IPX is not set + # CONFIG_ATALK is not set +@@ -331,7 +364,8 @@ + # + CONFIG_MTD_CHAR=y + CONFIG_MTD_BLKDEVS=y +-CONFIG_MTD_BLOCK=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set + # CONFIG_FTL is not set + # CONFIG_NFTL is not set + # CONFIG_INFTL is not set +@@ -397,7 +431,15 @@ + # + # UBI - Unsorted block images + # +-# CONFIG_MTD_UBI is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++ ++# ++# UBI debugging options ++# ++# CONFIG_MTD_UBI_DEBUG is not set + # CONFIG_PARPORT is not set + CONFIG_BLK_DEV=y + # CONFIG_BLK_DEV_COW_COMMON is not set +@@ -458,9 +500,7 @@ + # CONFIG_SCSI_ISCSI_ATTRS is not set + # CONFIG_SCSI_SAS_LIBSAS is not set + # CONFIG_SCSI_SRP_ATTRS is not set +-CONFIG_SCSI_LOWLEVEL=y +-# CONFIG_ISCSI_TCP is not set +-# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_LOWLEVEL is not set + # CONFIG_SCSI_DH is not set + CONFIG_ATA=m + # CONFIG_ATA_NONSTANDARD is not set +@@ -477,7 +517,32 @@ + # CONFIG_EQUALIZER is not set + # CONFIG_TUN is not set + # CONFIG_VETH is not set +-# CONFIG_NET_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++CONFIG_NET_ETHERNET=y ++# CONFIG_MII is not set ++CONFIG_MACB=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_B44 is not set + # CONFIG_NETDEV_1000 is not set + # CONFIG_NETDEV_10000 is not set + +@@ -509,7 +574,7 @@ + # + # Input device support + # +-CONFIG_INPUT=m ++CONFIG_INPUT=y + # CONFIG_INPUT_FF_MEMLESS is not set + CONFIG_INPUT_POLLDEV=m + +@@ -521,7 +586,7 @@ + CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 + CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 + # CONFIG_INPUT_JOYDEV is not set +-# CONFIG_INPUT_EVDEV is not set ++CONFIG_INPUT_EVDEV=m + # CONFIG_INPUT_EVBUG is not set + + # +@@ -538,6 +603,8 @@ + CONFIG_INPUT_MOUSE=y + # CONFIG_MOUSE_PS2 is not set + # CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set + # CONFIG_MOUSE_VSXXXAA is not set + CONFIG_MOUSE_GPIO=m + # CONFIG_INPUT_JOYSTICK is not set +@@ -555,7 +622,7 @@ + # Character devices + # + # CONFIG_VT is not set +-# CONFIG_DEVKMEM is not set ++CONFIG_DEVKMEM=y + # CONFIG_SERIAL_NONSTANDARD is not set + + # +@@ -582,6 +649,7 @@ + CONFIG_I2C=m + CONFIG_I2C_BOARDINFO=y + CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_HELPER_AUTO=y + CONFIG_I2C_ALGOBIT=m + + # +@@ -611,7 +679,7 @@ + # Miscellaneous I2C Chip support + # + # CONFIG_DS1682 is not set +-CONFIG_AT24=m ++# CONFIG_AT24 is not set + # CONFIG_SENSORS_EEPROM is not set + # CONFIG_SENSORS_PCF8574 is not set + # CONFIG_PCF8575 is not set +@@ -631,6 +699,7 @@ + # + # SPI Master Controller Drivers + # ++CONFIG_SPI_ATMEL_HAVE_PDC=y + CONFIG_SPI_ATMEL=y + # CONFIG_SPI_BITBANG is not set + +@@ -673,7 +742,7 @@ + # Watchdog Device Drivers + # + # CONFIG_SOFT_WATCHDOG is not set +-CONFIG_AT32AP700X_WDT=y ++CONFIG_AT32_WDT=y + + # + # Sonics Silicon Backplane +@@ -687,6 +756,7 @@ + # CONFIG_MFD_CORE is not set + # CONFIG_MFD_SM501 is not set + # CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set + + # + # Multimedia devices +@@ -726,8 +796,8 @@ + CONFIG_SND_PCM_OSS=m + CONFIG_SND_PCM_OSS_PLUGINS=y + # CONFIG_SND_DYNAMIC_MINORS is not set +-CONFIG_SND_SUPPORT_OLD_API=y +-CONFIG_SND_VERBOSE_PROCFS=y ++# CONFIG_SND_SUPPORT_OLD_API is not set ++# CONFIG_SND_VERBOSE_PROCFS is not set + # CONFIG_SND_VERBOSE_PRINTK is not set + # CONFIG_SND_DEBUG is not set + # CONFIG_SND_DRIVERS is not set +@@ -738,11 +808,14 @@ + # CONFIG_SOUND_PRIME is not set + # CONFIG_HID_SUPPORT is not set + CONFIG_USB_SUPPORT=y +-# CONFIG_USB_ARCH_HAS_HCD is not set +-# CONFIG_USB_ARCH_HAS_OHCI is not set +-# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++# CONFIG_USB is not set + # CONFIG_USB_OTG_WHITELIST is not set + # CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MUSB_HDRC is not set ++# CONFIG_USB_GADGET_MUSB_HDRC is not set + + # + # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +@@ -750,7 +823,7 @@ + CONFIG_USB_GADGET=y + # CONFIG_USB_GADGET_DEBUG is not set + # CONFIG_USB_GADGET_DEBUG_FILES is not set +-CONFIG_USB_GADGET_DEBUG_FS=y ++# CONFIG_USB_GADGET_DEBUG_FS is not set + CONFIG_USB_GADGET_SELECTED=y + # CONFIG_USB_GADGET_AMD5536UDC is not set + CONFIG_USB_GADGET_ATMEL_USBA=y +@@ -787,33 +860,34 @@ + CONFIG_MMC_BLOCK=y + CONFIG_MMC_BLOCK_BOUNCE=y + # CONFIG_SDIO_UART is not set +-CONFIG_MMC_TEST=m ++# CONFIG_MMC_TEST is not set + + # + # MMC/SD Host Controller Drivers + # + # CONFIG_MMC_SDHCI is not set + CONFIG_MMC_ATMELMCI=y ++# CONFIG_MMC_ATMELMCI_DMA is not set + CONFIG_MMC_SPI=m + # CONFIG_MEMSTICK is not set + CONFIG_NEW_LEDS=y +-CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_CLASS=m + + # + # LED drivers + # + CONFIG_LEDS_ATMEL_PWM=m + # CONFIG_LEDS_PCA9532 is not set +-CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_GPIO=m + # CONFIG_LEDS_PCA955X is not set + + # + # LED Triggers + # + CONFIG_LEDS_TRIGGERS=y +-CONFIG_LEDS_TRIGGER_TIMER=y +-CONFIG_LEDS_TRIGGER_HEARTBEAT=y +-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TIMER=m ++CONFIG_LEDS_TRIGGER_HEARTBEAT=m ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + # CONFIG_ACCESSIBILITY is not set + CONFIG_RTC_LIB=y + CONFIG_RTC_CLASS=y +@@ -870,11 +944,13 @@ + # on-CPU RTC drivers + # + CONFIG_RTC_DRV_AT32AP700X=y ++# CONFIG_RTC_DRV_AVR32_AST is not set + CONFIG_DMADEVICES=y + + # + # DMA Devices + # ++# CONFIG_ATMEL_PDCA is not set + CONFIG_DW_DMAC=y + CONFIG_DMA_ENGINE=y + +@@ -888,13 +964,13 @@ + # + # File systems + # +-CONFIG_EXT2_FS=m ++CONFIG_EXT2_FS=y + # CONFIG_EXT2_FS_XATTR is not set + # CONFIG_EXT2_FS_XIP is not set +-CONFIG_EXT3_FS=m ++CONFIG_EXT3_FS=y + # CONFIG_EXT3_FS_XATTR is not set + # CONFIG_EXT4DEV_FS is not set +-CONFIG_JBD=m ++CONFIG_JBD=y + # CONFIG_JBD_DEBUG is not set + # CONFIG_REISERFS_FS is not set + # CONFIG_JFS_FS is not set +@@ -935,7 +1011,7 @@ + CONFIG_TMPFS=y + # CONFIG_TMPFS_POSIX_ACL is not set + # CONFIG_HUGETLB_PAGE is not set +-CONFIG_CONFIGFS_FS=m ++CONFIG_CONFIGFS_FS=y + + # + # Miscellaneous filesystems +@@ -958,16 +1034,39 @@ + # CONFIG_JFFS2_LZO is not set + CONFIG_JFFS2_RTIME=y + # CONFIG_JFFS2_RUBIN is not set ++CONFIG_UBIFS_FS=y ++CONFIG_UBIFS_FS_XATTR=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_FS_DEBUG is not set + # CONFIG_CRAMFS is not set + # CONFIG_VXFS_FS is not set +-# CONFIG_MINIX_FS is not set ++CONFIG_MINIX_FS=m + # CONFIG_OMFS_FS is not set + # CONFIG_HPFS_FS is not set + # CONFIG_QNX4FS_FS is not set + # CONFIG_ROMFS_FS is not set + # CONFIG_SYSV_FS is not set + # CONFIG_UFS_FS is not set +-# CONFIG_NETWORK_FILESYSTEMS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set + + # + # Partition Types +@@ -1036,6 +1135,8 @@ + # CONFIG_SCHEDSTATS is not set + # CONFIG_TIMER_STATS is not set + # CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set + # CONFIG_DEBUG_RT_MUTEXES is not set + # CONFIG_RT_MUTEX_TESTER is not set + # CONFIG_DEBUG_SPINLOCK is not set +@@ -1068,7 +1169,88 @@ + # CONFIG_KEYS is not set + # CONFIG_SECURITY is not set + # CONFIG_SECURITY_FILE_CAPABILITIES is not set +-# CONFIG_CRYPTO is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_HASH=m ++CONFIG_CRYPTO_MANAGER=m ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=m ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=m ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=m ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=m ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZO=y ++# CONFIG_CRYPTO_HW is not set + + # + # Library routines +@@ -1077,15 +1259,16 @@ + # CONFIG_GENERIC_FIND_FIRST_BIT is not set + # CONFIG_GENERIC_FIND_NEXT_BIT is not set + CONFIG_CRC_CCITT=m +-# CONFIG_CRC16 is not set ++CONFIG_CRC16=y + CONFIG_CRC_T10DIF=m + CONFIG_CRC_ITU_T=m + CONFIG_CRC32=y + CONFIG_CRC7=m + # CONFIG_LIBCRC32C is not set +-CONFIG_AUDIT_GENERIC=y + CONFIG_ZLIB_INFLATE=y + CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y + CONFIG_GENERIC_ALLOCATOR=y + CONFIG_PLIST=y + CONFIG_HAS_IOMEM=y +diff -urN linux-2.6.28.2-0rig//arch/avr32/configs/atstk1004_defconfig linux-2.6.28.2/arch/avr32/configs/atstk1004_defconfig +--- linux-2.6.28.2-0rig//arch/avr32/configs/atstk1004_defconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/configs/atstk1004_defconfig 2009-01-29 08:52:49.000000000 +0100 +@@ -1,7 +1,7 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.27-rc1 +-# Tue Aug 5 15:38:56 2008 ++# Linux kernel version: 2.6.27.4 ++# Wed Nov 12 10:35:14 2008 + # + CONFIG_AVR32=y + CONFIG_GENERIC_GPIO=y +@@ -30,8 +30,10 @@ + CONFIG_INIT_ENV_ARG_LIMIT=32 + CONFIG_LOCALVERSION="" + # CONFIG_LOCALVERSION_AUTO is not set +-# CONFIG_SYSVIPC is not set +-# CONFIG_POSIX_MQUEUE is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y + # CONFIG_BSD_PROCESS_ACCT is not set + # CONFIG_TASKSTATS is not set + # CONFIG_AUDIT is not set +@@ -41,14 +43,16 @@ + # CONFIG_GROUP_SCHED is not set + CONFIG_SYSFS_DEPRECATED=y + CONFIG_SYSFS_DEPRECATED_V2=y +-# CONFIG_RELAY is not set ++CONFIG_RELAY=y + # CONFIG_NAMESPACES is not set +-# CONFIG_BLK_DEV_INITRD is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" + CONFIG_CC_OPTIMIZE_FOR_SIZE=y + CONFIG_SYSCTL=y + CONFIG_EMBEDDED=y + # CONFIG_SYSCTL_SYSCALL is not set + CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set + # CONFIG_KALLSYMS_EXTRA_PASS is not set + CONFIG_HOTPLUG=y + CONFIG_PRINTK=y +@@ -56,19 +60,23 @@ + CONFIG_ELF_CORE=y + # CONFIG_COMPAT_BRK is not set + # CONFIG_BASE_FULL is not set +-# CONFIG_FUTEX is not set +-# CONFIG_EPOLL is not set +-# CONFIG_SIGNALFD is not set +-# CONFIG_TIMERFD is not set +-# CONFIG_EVENTFD is not set ++CONFIG_FUTEX=y ++CONFIG_ANON_INODES=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y + CONFIG_SHMEM=y + CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y + # CONFIG_SLAB is not set +-# CONFIG_SLUB is not set +-CONFIG_SLOB=y +-# CONFIG_PROFILING is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++CONFIG_PROFILING=y + # CONFIG_MARKERS is not set ++CONFIG_OPROFILE=m + CONFIG_HAVE_OPROFILE=y ++CONFIG_KPROBES=y + # CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set + # CONFIG_HAVE_IOREMAP_PROT is not set + CONFIG_HAVE_KPROBES=y +@@ -77,36 +85,68 @@ + # CONFIG_HAVE_DMA_ATTRS is not set + # CONFIG_USE_GENERIC_SMP_HELPERS is not set + CONFIG_HAVE_CLK=y +-# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_PROC_PAGE_MONITOR=y + # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y + # CONFIG_TINY_SHMEM is not set + CONFIG_BASE_SMALL=1 +-# CONFIG_MODULES is not set +-# CONFIG_BLOCK is not set ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_AS is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" + CONFIG_CLASSIC_RCU=y + + # + # System Type and features + # +-# CONFIG_TICK_ONESHOT is not set +-# CONFIG_NO_HZ is not set +-# CONFIG_HIGH_RES_TIMERS is not set ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y + CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + CONFIG_SUBARCH_AVR32B=y + CONFIG_MMU=y + CONFIG_PERFORMANCE_COUNTERS=y ++CONFIG_PORTMUX_PIO=y + CONFIG_PLATFORM_AT32AP=y + CONFIG_CPU_AT32AP700X=y + CONFIG_CPU_AT32AP7002=y + CONFIG_BOARD_ATSTK1000=y + # CONFIG_BOARD_ATNGW100 is not set ++# CONFIG_BOARD_FAVR_32 is not set ++# CONFIG_BOARD_MIMC200 is not set + # CONFIG_BOARD_ATSTK1002 is not set + # CONFIG_BOARD_ATSTK1003 is not set + CONFIG_BOARD_ATSTK1004=y ++# CONFIG_BOARD_ATSTK1005 is not set + # CONFIG_BOARD_ATSTK1006 is not set + # CONFIG_BOARD_ATSTK100X_CUSTOM is not set + # CONFIG_BOARD_ATSTK100X_SPI1 is not set +-# CONFIG_BOARD_ATSTK1000_J2_LED is not set ++CONFIG_BOARD_ATSTK1000_J2_LED=y ++# CONFIG_BOARD_ATSTK1000_J2_LED8 is not set ++CONFIG_BOARD_ATSTK1000_J2_RGB=y + CONFIG_BOARD_ATSTK1000_EXTDAC=y + CONFIG_LOADER_U_BOOT=y + +@@ -144,25 +184,43 @@ + CONFIG_NR_QUICK=2 + CONFIG_VIRT_TO_BUS=y + # CONFIG_OWNERSHIP_TRACE is not set +-# CONFIG_NMI_DEBUGGING is not set ++CONFIG_NMI_DEBUGGING=y + # CONFIG_HZ_100 is not set + CONFIG_HZ_250=y + # CONFIG_HZ_300 is not set + # CONFIG_HZ_1000 is not set + CONFIG_HZ=250 +-# CONFIG_SCHED_HRTICK is not set ++CONFIG_SCHED_HRTICK=y + CONFIG_CMDLINE="" + + # + # Power management options + # +-# CONFIG_PM is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_SLEEP=y ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y + CONFIG_ARCH_SUSPEND_POSSIBLE=y + + # + # CPU Frequency scaling + # +-# CONFIG_CPU_FREQ is not set ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_TABLE=y ++# CONFIG_CPU_FREQ_DEBUG is not set ++# CONFIG_CPU_FREQ_STAT is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_AT32AP=y + + # + # Bus options +@@ -183,40 +241,71 @@ + CONFIG_PACKET=y + CONFIG_PACKET_MMAP=y + CONFIG_UNIX=y +-# CONFIG_NET_KEY is not set ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=m ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_XFRM_IPCOMP=m ++CONFIG_NET_KEY=m ++# CONFIG_NET_KEY_MIGRATE is not set + CONFIG_INET=y + # CONFIG_IP_MULTICAST is not set + # CONFIG_IP_ADVANCED_ROUTER is not set + CONFIG_IP_FIB_HASH=y +-# CONFIG_IP_PNP is not set +-# CONFIG_NET_IPIP is not set +-# CONFIG_NET_IPGRE is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_IP_PNP_BOOTP is not set ++# CONFIG_IP_PNP_RARP is not set ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE=m + # CONFIG_ARPD is not set + # CONFIG_SYN_COOKIES is not set +-# CONFIG_INET_AH is not set +-# CONFIG_INET_ESP is not set ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m + # CONFIG_INET_IPCOMP is not set + # CONFIG_INET_XFRM_TUNNEL is not set +-# CONFIG_INET_TUNNEL is not set +-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +-# CONFIG_INET_XFRM_MODE_TUNNEL is not set +-# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m + # CONFIG_INET_LRO is not set +-# CONFIG_INET_DIAG is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y + # CONFIG_TCP_CONG_ADVANCED is not set + CONFIG_TCP_CONG_CUBIC=y + CONFIG_DEFAULT_TCP_CONG="cubic" + # CONFIG_TCP_MD5SIG is not set +-# CONFIG_IPV6 is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++# CONFIG_IPV6_MIP6 is not set ++CONFIG_INET6_XFRM_TUNNEL=m ++CONFIG_INET6_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPV6_TUNNEL=m ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set + # CONFIG_NETWORK_SECMARK is not set + # CONFIG_NETFILTER is not set + # CONFIG_IP_DCCP is not set + # CONFIG_IP_SCTP is not set + # CONFIG_TIPC is not set + # CONFIG_ATM is not set +-# CONFIG_BRIDGE is not set ++CONFIG_STP=m ++CONFIG_BRIDGE=m + # CONFIG_VLAN_8021Q is not set + # CONFIG_DECNET is not set ++CONFIG_LLC=m + # CONFIG_LLC2 is not set + # CONFIG_IPX is not set + # CONFIG_ATALK is not set +@@ -230,6 +319,7 @@ + # Network testing + # + # CONFIG_NET_PKTGEN is not set ++# CONFIG_NET_TCPPROBE is not set + # CONFIG_HAMRADIO is not set + # CONFIG_CAN is not set + # CONFIG_IRDA is not set +@@ -257,6 +347,8 @@ + CONFIG_STANDALONE=y + # CONFIG_PREVENT_FIRMWARE_BUILD is not set + # CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set + # CONFIG_SYS_HYPERVISOR is not set + # CONFIG_CONNECTOR is not set + CONFIG_MTD=y +@@ -271,6 +363,14 @@ + # User Modules And Translation Layers + # + CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set + # CONFIG_MTD_OOPS is not set + + # +@@ -311,11 +411,13 @@ + # + # Self-contained MTD device drivers + # +-# CONFIG_MTD_DATAFLASH is not set +-# CONFIG_MTD_M25P80 is not set ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_M25P80=m ++CONFIG_M25PXX_USE_FAST_READ=y + # CONFIG_MTD_SLRAM is not set + # CONFIG_MTD_PHRAM is not set + # CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set + + # + # Disk-On-Chip Device Drivers +@@ -329,24 +431,186 @@ + # + # UBI - Unsorted block images + # +-# CONFIG_MTD_UBI is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++ ++# ++# UBI debugging options ++# ++# CONFIG_MTD_UBI_DEBUG is not set + # CONFIG_PARPORT is not set +-# CONFIG_MISC_DEVICES is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=m ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=m ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_MISC_DEVICES=y ++CONFIG_ATMEL_PWM=m ++CONFIG_ATMEL_TCLIB=y ++CONFIG_ATMEL_TCB_CLKSRC=y ++CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 ++# CONFIG_EEPROM_93CX6 is not set ++CONFIG_ATMEL_SSC=m ++# CONFIG_ENCLOSURE_SERVICES is not set + # CONFIG_HAVE_IDE is not set + + # + # SCSI device support + # +-# CONFIG_SCSI_DMA is not set ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=m ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_TGT is not set + # CONFIG_SCSI_NETLINK is not set +-# CONFIG_NETDEVICES is not set ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=m ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=m ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++CONFIG_ATA=m ++# CONFIG_ATA_NONSTANDARD is not set ++# CONFIG_SATA_PMP is not set ++CONFIG_ATA_SFF=y ++# CONFIG_SATA_MV is not set ++CONFIG_PATA_AT32=m ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++CONFIG_NET_ETHERNET=y ++# CONFIG_MII is not set ++CONFIG_MACB=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_B44 is not set ++# CONFIG_NETDEV_1000 is not set ++# CONFIG_NETDEV_10000 is not set ++ ++# ++# Wireless LAN ++# ++# CONFIG_WLAN_PRE80211 is not set ++# CONFIG_WLAN_80211 is not set ++# CONFIG_IWLWIFI_LEDS is not set ++# CONFIG_WAN is not set ++CONFIG_PPP=m ++# CONFIG_PPP_MULTILINK is not set ++# CONFIG_PPP_FILTER is not set ++CONFIG_PPP_ASYNC=m ++# CONFIG_PPP_SYNC_TTY is not set ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_BSDCOMP=m ++# CONFIG_PPP_MPPE is not set ++# CONFIG_PPPOE is not set ++# CONFIG_PPPOL2TP is not set ++# CONFIG_SLIP is not set ++CONFIG_SLHC=m ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set + # CONFIG_ISDN is not set + # CONFIG_PHONE is not set + + # + # Input device support + # +-# CONFIG_INPUT is not set ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++CONFIG_INPUT_POLLDEV=m ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=m ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=m ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++CONFIG_KEYBOARD_GPIO=m ++CONFIG_INPUT_MOUSE=y ++# CONFIG_MOUSE_PS2 is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++CONFIG_MOUSE_GPIO=m ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set + + # + # Hardware I/O ports +@@ -357,8 +621,12 @@ + # + # Character devices + # +-# CONFIG_VT is not set +-# CONFIG_DEVKMEM is not set ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y + # CONFIG_SERIAL_NONSTANDARD is not set + + # +@@ -371,7 +639,7 @@ + # + CONFIG_SERIAL_ATMEL=y + CONFIG_SERIAL_ATMEL_CONSOLE=y +-# CONFIG_SERIAL_ATMEL_PDC is not set ++CONFIG_SERIAL_ATMEL_PDC=y + # CONFIG_SERIAL_ATMEL_TTYAT is not set + CONFIG_SERIAL_CORE=y + CONFIG_SERIAL_CORE_CONSOLE=y +@@ -380,14 +648,62 @@ + # CONFIG_IPMI_HANDLER is not set + # CONFIG_HW_RANDOM is not set + # CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set + # CONFIG_TCG_TPM is not set +-# CONFIG_I2C is not set ++CONFIG_I2C=m ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_HELPER_AUTO=y ++CONFIG_I2C_ALGOBIT=m ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++CONFIG_I2C_GPIO=m ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_SIMTEC is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_STUB is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_DS1682 is not set ++# CONFIG_AT24 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_PCF8575 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CHIP is not set + CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set + CONFIG_SPI_MASTER=y + + # + # SPI Master Controller Drivers + # ++CONFIG_SPI_ATMEL_HAVE_PDC=y + CONFIG_SPI_ATMEL=y + # CONFIG_SPI_BITBANG is not set + +@@ -395,15 +711,19 @@ + # SPI Protocol Masters + # + # CONFIG_SPI_AT25 is not set +-# CONFIG_SPI_SPIDEV is not set ++CONFIG_SPI_SPIDEV=m + # CONFIG_SPI_TLE62X0 is not set + CONFIG_ARCH_REQUIRE_GPIOLIB=y + CONFIG_GPIOLIB=y +-# CONFIG_GPIO_SYSFS is not set ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y + + # + # I2C GPIO expanders: + # ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set + + # + # PCI GPIO expanders: +@@ -426,7 +746,7 @@ + # Watchdog Device Drivers + # + # CONFIG_SOFT_WATCHDOG is not set +-CONFIG_AT32AP700X_WDT=y ++CONFIG_AT32_WDT=y + + # + # Sonics Silicon Backplane +@@ -440,6 +760,7 @@ + # CONFIG_MFD_CORE is not set + # CONFIG_MFD_SM501 is not set + # CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set + + # + # Multimedia devices +@@ -485,6 +806,7 @@ + # + # CONFIG_FB_S1D13XXX is not set + CONFIG_FB_ATMEL=y ++# CONFIG_FB_ATMEL_MPOP is not set + # CONFIG_FB_VIRTUAL is not set + CONFIG_BACKLIGHT_LCD_SUPPORT=y + CONFIG_LCD_CLASS_DEVICE=y +@@ -498,20 +820,51 @@ + # Display device support + # + # CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set + # CONFIG_LOGO is not set +-# CONFIG_SOUND is not set ++CONFIG_SOUND=m ++CONFIG_SND=m ++CONFIG_SND_TIMER=m ++CONFIG_SND_PCM=m ++# CONFIG_SND_SEQUENCER is not set ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_PCM_OSS_PLUGINS=y ++# CONFIG_SND_DYNAMIC_MINORS is not set ++# CONFIG_SND_SUPPORT_OLD_API is not set ++# CONFIG_SND_VERBOSE_PROCFS is not set ++# CONFIG_SND_VERBOSE_PRINTK is not set ++# CONFIG_SND_DEBUG is not set ++# CONFIG_SND_DRIVERS is not set ++CONFIG_SND_SPI=y ++CONFIG_SND_AT73C213=m ++CONFIG_SND_AT73C213_TARGET_BITRATE=48000 ++# CONFIG_SND_SOC is not set ++# CONFIG_SOUND_PRIME is not set ++# CONFIG_HID_SUPPORT is not set + CONFIG_USB_SUPPORT=y +-# CONFIG_USB_ARCH_HAS_HCD is not set +-# CONFIG_USB_ARCH_HAS_OHCI is not set +-# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++# CONFIG_USB is not set + # CONFIG_USB_OTG_WHITELIST is not set + # CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MUSB_HDRC is not set ++# CONFIG_USB_GADGET_MUSB_HDRC is not set + + # + # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' + # + CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set + # CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set + CONFIG_USB_GADGET_SELECTED=y + # CONFIG_USB_GADGET_AMD5536UDC is not set + CONFIG_USB_GADGET_ATMEL_USBA=y +@@ -528,18 +881,54 @@ + # CONFIG_USB_GADGET_AT91 is not set + # CONFIG_USB_GADGET_DUMMY_HCD is not set + CONFIG_USB_GADGET_DUALSPEED=y +-# CONFIG_USB_ZERO is not set +-CONFIG_USB_ETH=y +-# CONFIG_USB_ETH_RNDIS is not set +-# CONFIG_USB_GADGETFS is not set +-# CONFIG_USB_FILE_STORAGE is not set +-# CONFIG_USB_G_SERIAL is not set ++CONFIG_USB_ZERO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FILE_STORAGE=m ++# CONFIG_USB_FILE_STORAGE_TEST is not set ++CONFIG_USB_G_SERIAL=m + # CONFIG_USB_MIDI_GADGET is not set + # CONFIG_USB_G_PRINTER is not set +-# CONFIG_USB_CDC_COMPOSITE is not set +-# CONFIG_MMC is not set ++CONFIG_USB_CDC_COMPOSITE=m ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_UNSAFE_RESUME is not set ++ ++# ++# MMC/SD Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD Host Controller Drivers ++# ++# CONFIG_MMC_SDHCI is not set ++CONFIG_MMC_ATMELMCI=y ++# CONFIG_MMC_ATMELMCI_DMA is not set ++CONFIG_MMC_SPI=m + # CONFIG_MEMSTICK is not set +-# CONFIG_NEW_LEDS is not set ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=m ++ ++# ++# LED drivers ++# ++CONFIG_LEDS_ATMEL_PWM=m ++# CONFIG_LEDS_PCA9532 is not set ++CONFIG_LEDS_GPIO=m ++# CONFIG_LEDS_PCA955X is not set ++ ++# ++# LED Triggers ++# ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=m ++CONFIG_LEDS_TRIGGER_HEARTBEAT=m ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + # CONFIG_ACCESSIBILITY is not set + CONFIG_RTC_LIB=y + CONFIG_RTC_CLASS=y +@@ -551,12 +940,28 @@ + # RTC interfaces + # + CONFIG_RTC_INTF_SYSFS=y +-# CONFIG_RTC_INTF_PROC is not set ++CONFIG_RTC_INTF_PROC=y + CONFIG_RTC_INTF_DEV=y + # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + # CONFIG_RTC_DRV_TEST is not set + + # ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++ ++# + # SPI RTC drivers + # + # CONFIG_RTC_DRV_M41T94 is not set +@@ -580,18 +985,62 @@ + # on-CPU RTC drivers + # + CONFIG_RTC_DRV_AT32AP700X=y +-# CONFIG_DMADEVICES is not set ++# CONFIG_RTC_DRV_AVR32_AST is not set ++CONFIG_DMADEVICES=y ++ ++# ++# DMA Devices ++# ++# CONFIG_ATMEL_PDCA is not set ++CONFIG_DW_DMAC=y ++CONFIG_DMA_ENGINE=y ++ ++# ++# DMA Clients ++# ++# CONFIG_NET_DMA is not set ++CONFIG_DMATEST=m + # CONFIG_UIO is not set + + # + # File systems + # ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_FS_XATTR is not set ++# CONFIG_EXT4DEV_FS is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set + # CONFIG_DNOTIFY is not set +-# CONFIG_INOTIFY is not set ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y + # CONFIG_QUOTA is not set + # CONFIG_AUTOFS_FS is not set + # CONFIG_AUTOFS4_FS is not set +-# CONFIG_FUSE_FS is not set ++CONFIG_FUSE_FS=m ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=m ++CONFIG_MSDOS_FS=m ++CONFIG_VFAT_FS=m ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set + + # + # Pseudo filesystems +@@ -603,14 +1052,22 @@ + CONFIG_TMPFS=y + # CONFIG_TMPFS_POSIX_ACL is not set + # CONFIG_HUGETLB_PAGE is not set +-# CONFIG_CONFIGFS_FS is not set ++CONFIG_CONFIGFS_FS=y + + # + # Miscellaneous filesystems + # ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set + CONFIG_JFFS2_FS=y + CONFIG_JFFS2_FS_DEBUG=0 +-# CONFIG_JFFS2_FS_WRITEBUFFER is not set ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set + # CONFIG_JFFS2_SUMMARY is not set + # CONFIG_JFFS2_FS_XATTR is not set + # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +@@ -618,8 +1075,85 @@ + # CONFIG_JFFS2_LZO is not set + CONFIG_JFFS2_RTIME=y + # CONFIG_JFFS2_RUBIN is not set +-# CONFIG_NETWORK_FILESYSTEMS is not set +-# CONFIG_NLS is not set ++CONFIG_UBIFS_FS=y ++CONFIG_UBIFS_FS_XATTR=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_FS_DEBUG is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++CONFIG_MINIX_FS=m ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++CONFIG_NLS=m ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=m ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++# CONFIG_NLS_ASCII is not set ++CONFIG_NLS_ISO8859_1=m ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=m + # CONFIG_DLM is not set + + # +@@ -631,11 +1165,43 @@ + CONFIG_FRAME_WARN=1024 + CONFIG_MAGIC_SYSRQ=y + # CONFIG_UNUSED_SYMBOLS is not set +-# CONFIG_DEBUG_FS is not set ++CONFIG_DEBUG_FS=y + # CONFIG_HEADERS_CHECK is not set +-# CONFIG_DEBUG_KERNEL is not set +-# CONFIG_DEBUG_BUGVERBOSE is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++CONFIG_DETECT_SOFTLOCKUP=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set + # CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_SG is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_KPROBES_SANITY_TEST is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_LKDTM is not set ++# CONFIG_FAULT_INJECTION is not set + # CONFIG_SAMPLES is not set + + # +@@ -644,7 +1210,88 @@ + # CONFIG_KEYS is not set + # CONFIG_SECURITY is not set + # CONFIG_SECURITY_FILE_CAPABILITIES is not set +-# CONFIG_CRYPTO is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_HASH=m ++CONFIG_CRYPTO_MANAGER=m ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=m ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=m ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=m ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=m ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZO=y ++# CONFIG_CRYPTO_HW is not set + + # + # Library routines +@@ -652,16 +1299,19 @@ + CONFIG_BITREVERSE=y + # CONFIG_GENERIC_FIND_FIRST_BIT is not set + # CONFIG_GENERIC_FIND_NEXT_BIT is not set +-# CONFIG_CRC_CCITT is not set +-# CONFIG_CRC16 is not set +-# CONFIG_CRC_T10DIF is not set +-# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC_CCITT=m ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=m ++CONFIG_CRC_ITU_T=m + CONFIG_CRC32=y +-# CONFIG_CRC7 is not set ++CONFIG_CRC7=m + # CONFIG_LIBCRC32C is not set + CONFIG_ZLIB_INFLATE=y + CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y + CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_PLIST=y + CONFIG_HAS_IOMEM=y + CONFIG_HAS_IOPORT=y + CONFIG_HAS_DMA=y +diff -urN linux-2.6.28.2-0rig//arch/avr32/configs/atstk1005_defconfig linux-2.6.28.2/arch/avr32/configs/atstk1005_defconfig +--- linux-2.6.28.2-0rig//arch/avr32/configs/atstk1005_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/configs/atstk1005_defconfig 2009-01-29 08:52:49.000000000 +0100 +@@ -0,0 +1,1505 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.27.4 ++# Fri Nov 7 10:22:27 2008 ++# ++CONFIG_AVR32=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_TIME=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_CGROUPS is not set ++# CONFIG_GROUP_SCHED is not set ++CONFIG_SYSFS_DEPRECATED=y ++CONFIG_SYSFS_DEPRECATED_V2=y ++CONFIG_RELAY=y ++# CONFIG_NAMESPACES is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_EMBEDDED=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_BASE_FULL is not set ++CONFIG_FUTEX=y ++CONFIG_ANON_INODES=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++CONFIG_PROFILING=y ++# CONFIG_MARKERS is not set ++CONFIG_OPROFILE=m ++CONFIG_HAVE_OPROFILE=y ++CONFIG_KPROBES=y ++# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set ++# CONFIG_HAVE_IOREMAP_PROT is not set ++CONFIG_HAVE_KPROBES=y ++# CONFIG_HAVE_KRETPROBES is not set ++# CONFIG_HAVE_ARCH_TRACEHOOK is not set ++# CONFIG_HAVE_DMA_ATTRS is not set ++# CONFIG_USE_GENERIC_SMP_HELPERS is not set ++CONFIG_HAVE_CLK=y ++CONFIG_PROC_PAGE_MONITOR=y ++# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=1 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_AS is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++CONFIG_CLASSIC_RCU=y ++ ++# ++# System Type and features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_SUBARCH_AVR32B=y ++CONFIG_MMU=y ++CONFIG_PERFORMANCE_COUNTERS=y ++CONFIG_PORTMUX_GPIO_V2=y ++CONFIG_TIMER_AST=y ++CONFIG_PLATFORM_AT32AP=y ++CONFIG_CPU_AT32AP720X=y ++CONFIG_CPU_AT32AP7200=y ++CONFIG_BOARD_ATSTK1000=y ++# CONFIG_BOARD_ATNGW100 is not set ++# CONFIG_BOARD_FAVR_32 is not set ++# CONFIG_BOARD_MIMC200 is not set ++# CONFIG_BOARD_ATSTK1002 is not set ++# CONFIG_BOARD_ATSTK1003 is not set ++# CONFIG_BOARD_ATSTK1004 is not set ++CONFIG_BOARD_ATSTK1005=y ++# CONFIG_BOARD_ATSTK1006 is not set ++# CONFIG_BOARD_ATSTK100X_CUSTOM is not set ++# CONFIG_BOARD_ATSTK100X_SPI1 is not set ++CONFIG_BOARD_ATSTK1000_J2_LED=y ++# CONFIG_BOARD_ATSTK1000_J2_LED8 is not set ++CONFIG_BOARD_ATSTK1000_J2_RGB=y ++CONFIG_BOARD_ATSTK1000_EXTDAC=y ++CONFIG_LOADER_U_BOOT=y ++ ++# ++# Atmel AVR32 AP options ++# ++CONFIG_LOAD_ADDRESS=0x10000000 ++CONFIG_ENTRY_ADDRESS=0x90000000 ++CONFIG_PHYS_OFFSET=0x10000000 ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_QUICKLIST=y ++# CONFIG_HAVE_ARCH_BOOTMEM_NODE is not set ++# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set ++# CONFIG_NEED_NODE_MEMMAP_SIZE is not set ++CONFIG_ARCH_FLATMEM_ENABLE=y ++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set ++# CONFIG_ARCH_SPARSEMEM_ENABLE is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++# CONFIG_SPARSEMEM_STATIC is not set ++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_RESOURCES_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_NR_QUICK=2 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_OWNERSHIP_TRACE is not set ++CONFIG_NMI_DEBUGGING=y ++# CONFIG_HZ_100 is not set ++CONFIG_HZ_250=y ++# CONFIG_HZ_300 is not set ++# CONFIG_HZ_1000 is not set ++CONFIG_HZ=250 ++CONFIG_SCHED_HRTICK=y ++CONFIG_CMDLINE="" ++ ++# ++# Power management options ++# ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_SLEEP=y ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_TABLE=y ++# CONFIG_CPU_FREQ_DEBUG is not set ++# CONFIG_CPU_FREQ_STAT is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_AT32AP=y ++ ++# ++# Bus options ++# ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Executable file formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_MISC is not set ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=m ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_XFRM_IPCOMP=m ++CONFIG_NET_KEY=m ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_IP_PNP_BOOTP is not set ++# CONFIG_IP_PNP_RARP is not set ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE=m ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++# CONFIG_IPV6_MIP6 is not set ++CONFIG_INET6_XFRM_TUNNEL=m ++CONFIG_INET6_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPV6_TUNNEL=m ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++CONFIG_STP=m ++CONFIG_BRIDGE=m ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++CONFIG_LLC=m ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_SCHED is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_NET_TCPPROBE is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++ ++# ++# Wireless ++# ++# CONFIG_CFG80211 is not set ++# CONFIG_WIRELESS_EXT is not set ++# CONFIG_MAC80211 is not set ++# CONFIG_IEEE80211 is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++# CONFIG_MTD_CONCAT is not set ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++# CONFIG_MTD_CFI_ADV_OPTIONS is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_CFI_INTELEXT is not set ++CONFIG_MTD_CFI_AMDSTD=y ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x8000000 ++CONFIG_MTD_PHYSMAP_LEN=0x0 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_M25P80=m ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++CONFIG_MTD_NAND_ECC_SMC=y ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++CONFIG_MTD_NAND_ATMEL=y ++CONFIG_MTD_NAND_ATMEL_ECC_HW=y ++# CONFIG_MTD_NAND_ATMEL_ECC_SOFT is not set ++# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_ALAUDA is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# UBI - Unsorted block images ++# ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=1 ++# CONFIG_MTD_UBI_GLUEBI is not set ++ ++# ++# UBI debugging options ++# ++# CONFIG_MTD_UBI_DEBUG is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=m ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++CONFIG_BLK_DEV_NBD=m ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=m ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_MISC_DEVICES=y ++CONFIG_ATMEL_PWM=m ++# CONFIG_ATMEL_TCLIB is not set ++# CONFIG_EEPROM_93CX6 is not set ++CONFIG_ATMEL_SSC=m ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HAVE_IDE is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=m ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_TGT is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=m ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=m ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++CONFIG_ATA=m ++# CONFIG_ATA_NONSTANDARD is not set ++# CONFIG_SATA_PMP is not set ++CONFIG_ATA_SFF=y ++# CONFIG_SATA_MV is not set ++CONFIG_PATA_AT32=m ++# CONFIG_PATA_PLATFORM is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=m ++CONFIG_MACB=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_B44 is not set ++# CONFIG_NETDEV_1000 is not set ++# CONFIG_NETDEV_10000 is not set ++ ++# ++# Wireless LAN ++# ++# CONFIG_WLAN_PRE80211 is not set ++# CONFIG_WLAN_80211 is not set ++# CONFIG_IWLWIFI_LEDS is not set ++ ++# ++# USB Network Adapters ++# ++CONFIG_USB_CATC=m ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++CONFIG_USB_USBNET=m ++# CONFIG_USB_NET_AX8817X is not set ++CONFIG_USB_NET_CDCETHER=m ++# CONFIG_USB_NET_DM9601 is not set ++# CONFIG_USB_NET_GL620A is not set ++# CONFIG_USB_NET_NET1080 is not set ++# CONFIG_USB_NET_PLUSB is not set ++# CONFIG_USB_NET_MCS7830 is not set ++# CONFIG_USB_NET_RNDIS_HOST is not set ++CONFIG_USB_NET_CDC_SUBSET=m ++# CONFIG_USB_ALI_M5632 is not set ++# CONFIG_USB_AN2720 is not set ++CONFIG_USB_BELKIN=y ++CONFIG_USB_ARMLINUX=y ++# CONFIG_USB_EPSON2888 is not set ++# CONFIG_USB_KC2190 is not set ++# CONFIG_USB_NET_ZAURUS is not set ++# CONFIG_WAN is not set ++CONFIG_PPP=m ++# CONFIG_PPP_MULTILINK is not set ++# CONFIG_PPP_FILTER is not set ++CONFIG_PPP_ASYNC=m ++# CONFIG_PPP_SYNC_TTY is not set ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_BSDCOMP=m ++# CONFIG_PPP_MPPE is not set ++# CONFIG_PPPOE is not set ++# CONFIG_PPPOL2TP is not set ++# CONFIG_SLIP is not set ++CONFIG_SLHC=m ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_ISDN is not set ++# CONFIG_PHONE is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++CONFIG_INPUT_POLLDEV=m ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=m ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=m ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++CONFIG_KEYBOARD_GPIO=m ++CONFIG_INPUT_MOUSE=y ++# CONFIG_MOUSE_PS2 is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++CONFIG_MOUSE_GPIO=m ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++CONFIG_SERIAL_ATMEL=y ++CONFIG_SERIAL_ATMEL_CONSOLE=y ++CONFIG_SERIAL_ATMEL_PDC=y ++# CONFIG_SERIAL_ATMEL_TTYAT is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_HW_RANDOM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_I2C=m ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_HELPER_AUTO=y ++CONFIG_I2C_ALGOBIT=m ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++CONFIG_I2C_GPIO=m ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_SIMTEC is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++CONFIG_I2C_TINY_USB=m ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_STUB is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_DS1682 is not set ++# CONFIG_AT24 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_PCF8575 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CHIP is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++CONFIG_SPI_ATMEL=y ++# CONFIG_SPI_BITBANG is not set ++ ++# ++# SPI Protocol Masters ++# ++# CONFIG_SPI_AT25 is not set ++CONFIG_SPI_SPIDEV=m ++# CONFIG_SPI_TLE62X0 is not set ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_THERMAL_HWMON is not set ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_AT32_WDT=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++ ++# ++# Sonics Silicon Backplane ++# ++CONFIG_SSB_POSSIBLE=y ++# CONFIG_SSB is not set ++ ++# ++# Multifunction device drivers ++# ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set ++ ++# ++# Multimedia devices ++# ++ ++# ++# Multimedia core support ++# ++# CONFIG_VIDEO_DEV is not set ++# CONFIG_DVB_CORE is not set ++# CONFIG_VIDEO_MEDIA is not set ++ ++# ++# Multimedia drivers ++# ++# CONFIG_DAB is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_FB_DDC is not set ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_S1D13XXX is not set ++CONFIG_FB_ATMEL=y ++# CONFIG_FB_ATMEL_MPOP is not set ++# CONFIG_FB_VIRTUAL is not set ++CONFIG_BACKLIGHT_LCD_SUPPORT=y ++CONFIG_LCD_CLASS_DEVICE=y ++CONFIG_LCD_LTV350QV=y ++# CONFIG_LCD_ILI9320 is not set ++# CONFIG_LCD_VGG2432A4 is not set ++# CONFIG_LCD_PLATFORM is not set ++# CONFIG_BACKLIGHT_CLASS_DEVICE is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++CONFIG_SOUND=m ++CONFIG_SND=m ++CONFIG_SND_TIMER=m ++CONFIG_SND_PCM=m ++CONFIG_SND_HWDEP=m ++CONFIG_SND_RAWMIDI=m ++# CONFIG_SND_SEQUENCER is not set ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_PCM_OSS_PLUGINS=y ++# CONFIG_SND_DYNAMIC_MINORS is not set ++# CONFIG_SND_SUPPORT_OLD_API is not set ++# CONFIG_SND_VERBOSE_PROCFS is not set ++# CONFIG_SND_VERBOSE_PRINTK is not set ++# CONFIG_SND_DEBUG is not set ++# CONFIG_SND_DRIVERS is not set ++CONFIG_SND_SPI=y ++CONFIG_SND_AT73C213=m ++CONFIG_SND_AT73C213_TARGET_BITRATE=48000 ++CONFIG_SND_USB=y ++CONFIG_SND_USB_AUDIO=m ++# CONFIG_SND_USB_CAIAQ is not set ++# CONFIG_SND_SOC is not set ++# CONFIG_SOUND_PRIME is not set ++CONFIG_HID_SUPPORT=y ++CONFIG_HID=y ++# CONFIG_HID_DEBUG is not set ++# CONFIG_HIDRAW is not set ++ ++# ++# USB Input Devices ++# ++CONFIG_USB_HID=y ++# CONFIG_USB_HIDINPUT_POWERBOOK is not set ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_DEVICE_CLASS is not set ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_SUSPEND=y ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++CONFIG_USB_MON=y ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++# CONFIG_USB_EHCI_TT_NEWSCHED is not set ++CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y ++CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y ++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y ++# CONFIG_USB_OHCI_LITTLE_ENDIAN is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_MUSB_HDRC is not set ++# CONFIG_USB_GADGET_MUSB_HDRC is not set ++ ++# ++# USB Device Class drivers ++# ++CONFIG_USB_ACM=m ++CONFIG_USB_PRINTER=m ++CONFIG_USB_WDM=m ++ ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' ++# ++ ++# ++# may also be needed; see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=m ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++CONFIG_USB_SERIAL=m ++# CONFIG_USB_EZUSB is not set ++CONFIG_USB_SERIAL_GENERIC=y ++# CONFIG_USB_SERIAL_AIRCABLE is not set ++# CONFIG_USB_SERIAL_ARK3116 is not set ++# CONFIG_USB_SERIAL_BELKIN is not set ++# CONFIG_USB_SERIAL_CH341 is not set ++# CONFIG_USB_SERIAL_WHITEHEAT is not set ++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set ++# CONFIG_USB_SERIAL_CP2101 is not set ++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set ++# CONFIG_USB_SERIAL_EMPEG is not set ++# CONFIG_USB_SERIAL_FTDI_SIO is not set ++# CONFIG_USB_SERIAL_FUNSOFT is not set ++# CONFIG_USB_SERIAL_VISOR is not set ++# CONFIG_USB_SERIAL_IPAQ is not set ++# CONFIG_USB_SERIAL_IR is not set ++# CONFIG_USB_SERIAL_EDGEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set ++# CONFIG_USB_SERIAL_GARMIN is not set ++# CONFIG_USB_SERIAL_IPW is not set ++# CONFIG_USB_SERIAL_IUU is not set ++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set ++# CONFIG_USB_SERIAL_KEYSPAN is not set ++# CONFIG_USB_SERIAL_KLSI is not set ++# CONFIG_USB_SERIAL_KOBIL_SCT is not set ++# CONFIG_USB_SERIAL_MCT_U232 is not set ++# CONFIG_USB_SERIAL_MOS7720 is not set ++# CONFIG_USB_SERIAL_MOS7840 is not set ++# CONFIG_USB_SERIAL_MOTOROLA is not set ++# CONFIG_USB_SERIAL_NAVMAN is not set ++CONFIG_USB_SERIAL_PL2303=m ++# CONFIG_USB_SERIAL_OTI6858 is not set ++# CONFIG_USB_SERIAL_SPCP8X5 is not set ++# CONFIG_USB_SERIAL_HP4X is not set ++# CONFIG_USB_SERIAL_SAFE is not set ++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set ++# CONFIG_USB_SERIAL_TI is not set ++# CONFIG_USB_SERIAL_CYBERJACK is not set ++# CONFIG_USB_SERIAL_XIRCOM is not set ++# CONFIG_USB_SERIAL_OPTION is not set ++# CONFIG_USB_SERIAL_OMNINET is not set ++# CONFIG_USB_SERIAL_DEBUG is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGET is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_SISUSBVGA is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++CONFIG_USB_TEST=m ++# CONFIG_USB_ISIGHTFW is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_SELECTED=y ++# CONFIG_USB_GADGET_AMD5536UDC is not set ++CONFIG_USB_GADGET_ATMEL_USBA=y ++CONFIG_USB_ATMEL_USBA=y ++# CONFIG_USB_GADGET_FSL_USB2 is not set ++# CONFIG_USB_GADGET_NET2280 is not set ++# CONFIG_USB_GADGET_PXA25X is not set ++# CONFIG_USB_GADGET_M66592 is not set ++# CONFIG_USB_GADGET_PXA27X is not set ++# CONFIG_USB_GADGET_GOKU is not set ++# CONFIG_USB_GADGET_LH7A40X is not set ++# CONFIG_USB_GADGET_OMAP is not set ++# CONFIG_USB_GADGET_S3C2410 is not set ++# CONFIG_USB_GADGET_AT91 is not set ++# CONFIG_USB_GADGET_DUMMY_HCD is not set ++CONFIG_USB_GADGET_DUALSPEED=y ++CONFIG_USB_ZERO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FILE_STORAGE=m ++# CONFIG_USB_FILE_STORAGE_TEST is not set ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_MIDI_GADGET is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_UNSAFE_RESUME is not set ++ ++# ++# MMC/SD Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_SDIO_UART is not set ++CONFIG_MMC_TEST=m ++ ++# ++# MMC/SD Host Controller Drivers ++# ++# CONFIG_MMC_SDHCI is not set ++CONFIG_MMC_ATMELMCI=y ++# CONFIG_MMC_ATMELMCI_DMA is not set ++CONFIG_MMC_SPI=m ++# CONFIG_MEMSTICK is not set ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=m ++ ++# ++# LED drivers ++# ++CONFIG_LEDS_ATMEL_PWM=m ++# CONFIG_LEDS_PCA9532 is not set ++CONFIG_LEDS_GPIO=m ++# CONFIG_LEDS_PCA955X is not set ++ ++# ++# LED Triggers ++# ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=m ++CONFIG_LEDS_TRIGGER_HEARTBEAT=m ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=m ++# CONFIG_ACCESSIBILITY is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_AT32AP700X is not set ++CONFIG_RTC_DRV_AVR32_AST=y ++CONFIG_DMADEVICES=y ++ ++# ++# DMA Devices ++# ++CONFIG_ATMEL_PDCA=y ++CONFIG_DW_DMAC=y ++CONFIG_DMA_ENGINE=y ++ ++# ++# DMA Clients ++# ++# CONFIG_NET_DMA is not set ++CONFIG_DMATEST=m ++# CONFIG_UIO is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_FS_XATTR is not set ++# CONFIG_EXT4DEV_FS is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_DNOTIFY is not set ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_FS is not set ++CONFIG_FUSE_FS=m ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=m ++CONFIG_MSDOS_FS=m ++CONFIG_VFAT_FS=m ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_KCORE=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=y ++ ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++CONFIG_UBIFS_FS=y ++CONFIG_UBIFS_FS_XATTR=y ++CONFIG_UBIFS_FS_ADVANCED_COMPR=y ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_FS_DEBUG is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++CONFIG_MINIX_FS=m ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++CONFIG_NLS=m ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=m ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++# CONFIG_NLS_ASCII is not set ++CONFIG_NLS_ISO8859_1=m ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=m ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++CONFIG_DETECT_SOFTLOCKUP=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_SG is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_KPROBES_SANITY_TEST is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_LKDTM is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_SAMPLES is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITY_FILE_CAPABILITIES is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_HASH=m ++CONFIG_CRYPTO_MANAGER=m ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=m ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=m ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=m ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=m ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZO=y ++# CONFIG_CRYPTO_HW is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_GENERIC_FIND_FIRST_BIT is not set ++# CONFIG_GENERIC_FIND_NEXT_BIT is not set ++CONFIG_CRC_CCITT=m ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=m ++CONFIG_CRC32=y ++CONFIG_CRC7=m ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y +diff -urN linux-2.6.28.2-0rig//arch/avr32/configs/atstk1006_defconfig linux-2.6.28.2/arch/avr32/configs/atstk1006_defconfig +--- linux-2.6.28.2-0rig//arch/avr32/configs/atstk1006_defconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/configs/atstk1006_defconfig 2009-01-29 09:11:15.000000000 +0100 +@@ -124,6 +124,7 @@ + CONFIG_SUBARCH_AVR32B=y + CONFIG_MMU=y + CONFIG_PERFORMANCE_COUNTERS=y ++CONFIG_PORTMUX_PIO=y + CONFIG_PLATFORM_AT32AP=y + CONFIG_CPU_AT32AP700X=y + CONFIG_CPU_AT32AP7000=y +@@ -137,9 +138,9 @@ + CONFIG_BOARD_ATSTK1006=y + # CONFIG_BOARD_ATSTK100X_CUSTOM is not set + # CONFIG_BOARD_ATSTK100X_SPI1 is not set +-# CONFIG_BOARD_ATSTK1000_J2_LED is not set ++CONFIG_BOARD_ATSTK1000_J2_LED=y + # CONFIG_BOARD_ATSTK1000_J2_LED8 is not set +-# CONFIG_BOARD_ATSTK1000_J2_RGB is not set ++CONFIG_BOARD_ATSTK1000_J2_RGB=y + CONFIG_BOARD_ATSTK1000_EXTDAC=y + CONFIG_LOADER_U_BOOT=y + +@@ -355,7 +356,8 @@ + CONFIG_MTD_CHAR=y + CONFIG_HAVE_MTD_OTP=y + CONFIG_MTD_BLKDEVS=y +-CONFIG_MTD_BLOCK=y ++# CONFIG_MTD_BLOCK is not set ++# CONFIG_MTD_BLOCK_RO is not set + # CONFIG_FTL is not set + # CONFIG_NFTL is not set + # CONFIG_INFTL is not set +@@ -419,7 +421,7 @@ + # CONFIG_MTD_DOC2001PLUS is not set + CONFIG_MTD_NAND=y + # CONFIG_MTD_NAND_VERIFY_WRITE is not set +-# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND_ECC_SMC=y + # CONFIG_MTD_NAND_MUSEUM_IDS is not set + CONFIG_MTD_NAND_IDS=y + # CONFIG_MTD_NAND_DISKONCHIP is not set +@@ -519,7 +521,7 @@ + # CONFIG_BONDING is not set + # CONFIG_MACVLAN is not set + # CONFIG_EQUALIZER is not set +-CONFIG_TUN=m ++# CONFIG_TUN is not set + # CONFIG_VETH is not set + CONFIG_PHYLIB=y + +@@ -581,7 +583,7 @@ + # + # Input device support + # +-CONFIG_INPUT=m ++CONFIG_INPUT=y + # CONFIG_INPUT_FF_MEMLESS is not set + CONFIG_INPUT_POLLDEV=m + +@@ -610,6 +612,8 @@ + CONFIG_INPUT_MOUSE=y + # CONFIG_MOUSE_PS2 is not set + # CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set + # CONFIG_MOUSE_VSXXXAA is not set + CONFIG_MOUSE_GPIO=m + # CONFIG_INPUT_JOYSTICK is not set +@@ -626,8 +630,12 @@ + # + # Character devices + # +-# CONFIG_VT is not set +-# CONFIG_DEVKMEM is not set ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y + # CONFIG_SERIAL_NONSTANDARD is not set + + # +@@ -704,6 +712,7 @@ + # + # SPI Master Controller Drivers + # ++CONFIG_SPI_ATMEL_HAVE_PDC=y + CONFIG_SPI_ATMEL=y + # CONFIG_SPI_BITBANG is not set + +@@ -752,6 +761,7 @@ + # CONFIG_SOFT_WATCHDOG is not set + CONFIG_AT32AP700X_WDT=y + CONFIG_SSB_POSSIBLE=y ++CONFIG_AT32_WDT=y + + # + # Sonics Silicon Backplane +@@ -814,6 +824,7 @@ + # + # CONFIG_FB_S1D13XXX is not set + CONFIG_FB_ATMEL=y ++# CONFIG_FB_ATMEL_MPOP is not set + # CONFIG_FB_VIRTUAL is not set + # CONFIG_FB_METRONOME is not set + # CONFIG_FB_MB862XX is not set +@@ -830,6 +841,12 @@ + # Display device support + # + # CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set + # CONFIG_LOGO is not set + CONFIG_SOUND=m + CONFIG_SOUND_OSS_CORE=y +@@ -846,11 +863,7 @@ + # CONFIG_SND_VERBOSE_PROCFS is not set + # CONFIG_SND_VERBOSE_PRINTK is not set + # CONFIG_SND_DEBUG is not set +-CONFIG_SND_DRIVERS=y +-# CONFIG_SND_DUMMY is not set +-# CONFIG_SND_MTPAV is not set +-# CONFIG_SND_SERIAL_U16550 is not set +-# CONFIG_SND_MPU401 is not set ++# CONFIG_SND_DRIVERS is not set + CONFIG_SND_SPI=y + CONFIG_SND_AT73C213=m + CONFIG_SND_AT73C213_TARGET_BITRATE=48000 +@@ -858,9 +871,9 @@ + # CONFIG_SOUND_PRIME is not set + # CONFIG_HID_SUPPORT is not set + CONFIG_USB_SUPPORT=y +-# CONFIG_USB_ARCH_HAS_HCD is not set +-# CONFIG_USB_ARCH_HAS_OHCI is not set +-# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y + # CONFIG_USB_OTG_WHITELIST is not set + # CONFIG_USB_OTG_BLACKLIST_HUB is not set + # CONFIG_USB_MUSB_HDRC is not set +@@ -900,7 +913,7 @@ + CONFIG_USB_G_SERIAL=m + # CONFIG_USB_MIDI_GADGET is not set + # CONFIG_USB_G_PRINTER is not set +-# CONFIG_USB_CDC_COMPOSITE is not set ++CONFIG_USB_CDC_COMPOSITE=m + CONFIG_MMC=y + # CONFIG_MMC_DEBUG is not set + # CONFIG_MMC_UNSAFE_RESUME is not set +@@ -1002,11 +1015,13 @@ + # on-CPU RTC drivers + # + CONFIG_RTC_DRV_AT32AP700X=y ++# CONFIG_RTC_DRV_AVR32_AST is not set + CONFIG_DMADEVICES=y + + # + # DMA Devices + # ++# CONFIG_ATMEL_PDCA is not set + CONFIG_DW_DMAC=y + CONFIG_DMA_ENGINE=y + +@@ -1022,17 +1037,17 @@ + # + # File systems + # +-CONFIG_EXT2_FS=m ++CONFIG_EXT2_FS=y + # CONFIG_EXT2_FS_XATTR is not set + # CONFIG_EXT2_FS_XIP is not set +-CONFIG_EXT3_FS=m ++CONFIG_EXT3_FS=y + # CONFIG_EXT3_FS_XATTR is not set +-CONFIG_EXT4_FS=m +-CONFIG_EXT4DEV_COMPAT=y ++# CONFIG_EXT4_FS is not set ++# CONFIG_EXT4DEV_COMPAT=y + # CONFIG_EXT4_FS_XATTR is not set +-CONFIG_JBD=m ++CONFIG_JBD=y + # CONFIG_JBD_DEBUG is not set +-CONFIG_JBD2=m ++# CONFIG_JBD2 is not set + # CONFIG_JBD2_DEBUG is not set + # CONFIG_REISERFS_FS is not set + # CONFIG_JFS_FS is not set +@@ -1075,7 +1090,7 @@ + CONFIG_TMPFS=y + # CONFIG_TMPFS_POSIX_ACL is not set + # CONFIG_HUGETLB_PAGE is not set +-# CONFIG_CONFIGFS_FS is not set ++CONFIG_CONFIGFS_FS=y + + # + # Miscellaneous filesystems +diff -urN linux-2.6.28.2-0rig//arch/avr32/include/asm/ast_regs.h linux-2.6.28.2/arch/avr32/include/asm/ast_regs.h +--- linux-2.6.28.2-0rig//arch/avr32/include/asm/ast_regs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/include/asm/ast_regs.h 2009-01-29 08:52:49.000000000 +0100 +@@ -0,0 +1,88 @@ ++/* ++ * Register definitions for the Asynchronous Timer (AST) ++ * ++ * Copyright (C) 2008 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. ++ */ ++#ifndef __AST_REGS_H__ ++#define __AST_REGS_H__ ++ ++/* Control Register */ ++#define AST_CR 0x0000 ++# define AST_CR_EN_BIT 0 /* Enable */ ++# define AST_CR_PCLR_BIT 1 /* Prescaler Clear */ ++# define AST_CR_CA0_BIT 8 /* Clear on Alarm */ ++# define AST_CR_CA1_BIT 9 ++# define AST_CR_PSEL_START 16 /* Prescale Select */ ++# define AST_CR_PSEL_SIZE 4 ++ ++/* Counter Value */ ++#define AST_CV 0x0004 ++ ++/* Status, Status Clear, Interrupt Enable/Disable/Mask, Wake Enable */ ++#define AST_SR 0x0008 ++#define AST_SCR 0x000c ++#define AST_IER 0x0010 ++#define AST_IDR 0x0014 ++#define AST_IMR 0x0018 ++#define AST_WER 0x001c ++# define AST_OVF_BIT 0 /* Overflow */ ++# define AST_ALARM0_BIT 8 /* Alarm event */ ++# define AST_ALARM1_BIT 9 ++# define AST_PER0_BIT 16 /* Periodic event */ ++# define AST_PER1_BIT 17 ++# define AST_BUSY_BIT 24 /* AST busy */ ++# define AST_READY_BIT 25 /* BUSY 1 -> 0 event */ ++# define AST_CLK_BUSY_BIT 28 /* CLOCK busy */ ++# define AST_CLK_READY_BIT 29 /* CKL_BUSY 1 -> 0 event */ ++ ++/* Alarm registers */ ++#define AST_AR0 0x0020 ++#define AST_AR1 0x0024 ++ ++/* Periodic Interval registers */ ++#define AST_PIR0 0x0030 ++#define AST_PIR1 0x0034 ++# define AST_PIRx_INSEL_START 0 /* Interval select */ ++# define AST_PIRx_INSEL_SIZE 4 ++ ++/* Clock Select register */ ++#define AST_CLOCK 0x0040 ++# define AST_CLOCK_CEN_BIT 0 /* Clock Enable */ ++# define AST_CLOCK_CSSEL_START 8 /* Clock Source */ ++# define AST_CLOCK_CSSEL_SIZE 2 ++# define AST_CLOCK_SLOW 0 /* RC oscillator */ ++# define AST_CLOCK_OSC32 1 /* 32 kHz oscillator */ ++# define AST_CLOCK_PB 2 /* Peripheral Bus clock */ ++# define AST_CLOCK_GC 3 /* Generic clock */ ++ ++/* Version register */ ++#define AST_VERSION 0x00fc ++ ++/* Bit manipulation macros */ ++#define AST_BIT(name) \ ++ (1 << AST_##name##_BIT) ++#define AST_BF(name,value) \ ++ (((value) & ((1 << AST_##name##_SIZE) - 1)) \ ++ << AST_##name##_START) ++#define AST_BFEXT(name,value) \ ++ (((value) >> AST_##name##_START) \ ++ & ((1 << AST_##name##_SIZE) - 1)) ++#define AST_BFINS(name,value,old) \ ++ (((old) & ~(((1 << AST_##name##_SIZE) - 1) \ ++ << AST_##name##_START)) \ ++ | AST_BF(name,value)) ++ ++/* Register access macros */ ++#define ast_readl(base, reg) \ ++ __raw_readl(base + AST_##reg) ++#define ast_writel(base, reg, value) \ ++ __raw_writel(value, base + AST_##reg) ++ ++struct platform_device; ++void ast_time_init(struct platform_device *pdev, unsigned int clksel); ++ ++#endif /* __AST_REGS_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/Kconfig linux-2.6.28.2/arch/avr32/Kconfig +--- linux-2.6.28.2-0rig//arch/avr32/Kconfig 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/Kconfig 2009-01-29 08:52:44.000000000 +0100 +@@ -85,6 +85,18 @@ + config PERFORMANCE_COUNTERS + bool + ++# The old "PIO" portmux/GPIO module used on AT32AP700x ++config PORTMUX_PIO ++ bool ++ ++# The new "GPIO" portmux/GPIO module, version 2 ++config PORTMUX_GPIO_V2 ++ bool ++ ++# Asynchronous Timer clocksource/clockevent driver ++config TIMER_AST ++ bool ++ + config PLATFORM_AT32AP + bool + select SUBARCH_AVR32B +@@ -101,6 +113,7 @@ + config CPU_AT32AP700X + bool + select PLATFORM_AT32AP ++ select PORTMUX_PIO + config CPU_AT32AP7000 + bool + select CPU_AT32AP700X +@@ -111,6 +124,16 @@ + bool + select CPU_AT32AP700X + ++# AP7200 derivatives ++config CPU_AT32AP720X ++ bool ++ select PLATFORM_AT32AP ++ select TIMER_AST ++ select PORTMUX_GPIO_V2 ++config CPU_AT32AP7200 ++ bool ++ select CPU_AT32AP720X ++ + choice + prompt "AVR32 board type" + default BOARD_ATSTK1000 +@@ -148,14 +171,17 @@ + config LOAD_ADDRESS + hex + default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP700X=y ++ default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP720X=y + + config ENTRY_ADDRESS + hex + default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP700X=y ++ default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP720X=y + + config PHYS_OFFSET + hex + default 0x10000000 if CPU_AT32AP700X=y ++ default 0x10000000 if CPU_AT32AP720X=y + + source "kernel/Kconfig.preempt" + +diff -urN linux-2.6.28.2-0rig//arch/avr32/kernel/cpu.c linux-2.6.28.2/arch/avr32/kernel/cpu.c +--- linux-2.6.28.2-0rig//arch/avr32/kernel/cpu.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/kernel/cpu.c 2009-01-29 08:52:49.000000000 +0100 +@@ -208,6 +208,7 @@ + + static const struct chip_id_map chip_names[] = { + { .mid = 0x1f, .pn = 0x1e82, .name = "AT32AP700x" }, ++ { .mid = 0x1f, .pn = 0x1e83, .name = "AT32AP720x" }, + }; + #define NR_CHIP_NAMES ARRAY_SIZE(chip_names) + +diff -urN linux-2.6.28.2-0rig//arch/avr32/kernel/entry-avr32b.S linux-2.6.28.2/arch/avr32/kernel/entry-avr32b.S +--- linux-2.6.28.2-0rig//arch/avr32/kernel/entry-avr32b.S 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/kernel/entry-avr32b.S 2009-01-29 08:52:49.000000000 +0100 +@@ -112,7 +112,9 @@ + + /* Second level lookup */ + ld.w r2, r3[r1 << 2] ++#ifdef CONFIG_CPU_AT32AP700X + mfsr r0, SYSREG_TLBARLO ++#endif + bld r2, _PAGE_BIT_PRESENT + brcc page_not_present + +@@ -124,6 +126,8 @@ + andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff + mtsr SYSREG_TLBELO, r2 + ++ /* Later CPUs do this algorithm in hardware */ ++#ifdef CONFIG_CPU_AT32AP700X + /* Figure out which entry we want to replace */ + mfsr r1, SYSREG_MMUCR + clz r2, r0 +@@ -134,6 +138,7 @@ + + 1: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE + mtsr SYSREG_MMUCR, r1 ++#endif /* CONFIG_CPU_AT32AP700X */ + tlbw + + tlbmiss_restore +@@ -751,8 +756,10 @@ + + lddsp r4, sp[REG_SR] + bfextu r4, r4, SYSREG_M0_OFFSET, 3 ++#ifdef CONFIG_CPU_AT32AP700X + cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET + breq 2f ++#endif + cp.w r4, MODE_USER >> SYSREG_M0_OFFSET + #ifdef CONFIG_PREEMPT + brne 3f +@@ -786,6 +793,7 @@ + rete + #endif + ++#ifdef CONFIG_CPU_AT32AP700X + 2: get_thread_info r0 + ld.w r1, r0[TI_flags] + bld r1, TIF_CPU_GOING_TO_SLEEP +@@ -796,6 +804,7 @@ + #endif + sub r1, pc, . - cpu_idle_skip_sleep + stdsp sp[REG_PC], r1 ++#endif + #ifdef CONFIG_PREEMPT + 3: get_thread_info r0 + ld.w r2, r0[TI_preempt_count] +diff -urN linux-2.6.28.2-0rig//arch/avr32/kernel/time.c linux-2.6.28.2/arch/avr32/kernel/time.c +--- linux-2.6.28.2-0rig//arch/avr32/kernel/time.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/kernel/time.c 2009-01-29 08:52:49.000000000 +0100 +@@ -15,6 +15,8 @@ + + #include <asm/sysreg.h> + ++#include <mach/cpu.h> ++#include <mach/init.h> + #include <mach/pm.h> + + +@@ -116,6 +118,9 @@ + unsigned long counter_hz; + int ret; + ++ /* Make sure we don't get any interrupts until we ask for it. */ ++ sysreg_write(COMPARE, 0); ++ + xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0); + xtime.tv_nsec = 0; + +@@ -130,12 +135,16 @@ + if (ret) + pr_debug("timer: could not register clocksource: %d\n", ret); + ++ if (!cpu_has_working_compare()) { ++ platform_time_init(); ++ return; ++ } ++ + /* setup COMPARE clockevent */ + comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift); + comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator); + comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1; + +- sysreg_write(COMPARE, 0); + timer_irqaction.dev_id = &comparator; + + ret = setup_irq(0, &timer_irqaction); +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/at32ap700x.c linux-2.6.28.2/arch/avr32/mach-at32ap/at32ap700x.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/at32ap700x.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/at32ap700x.c 2009-01-29 08:52:49.000000000 +0100 +@@ -23,6 +23,7 @@ + #include <mach/at32ap700x.h> + #include <mach/board.h> + #include <mach/hmatrix.h> ++#include <mach/pm.h> + #include <mach/portmux.h> + #include <mach/sram.h> + +@@ -30,7 +31,7 @@ + + #include "clock.h" + #include "pio.h" +-#include "pm.h" ++#include "pm-v1.h" + + + #define PBMEM(base) \ +@@ -996,6 +997,7 @@ + void __init at32_map_usart(unsigned int hw_id, unsigned int line) + { + struct platform_device *pdev; ++ u32 pin_mask; + + switch (hw_id) { + case 0: +@@ -1155,6 +1157,7 @@ + static struct resource atmel_spi0_resource[] = { + PBMEM(0xffe00000), + IRQ(3), ++ { 0 }, /* SRAM buffer, if available */ + }; + DEFINE_DEV(atmel_spi, 0); + DEV_CLK(spi_clk, atmel_spi0, pba, 0); +@@ -1162,6 +1165,7 @@ + static struct resource atmel_spi1_resource[] = { + PBMEM(0xffe00400), + IRQ(4), ++ { 0 }, /* SRAM buffer, if available */ + }; + DEFINE_DEV(atmel_spi, 1); + DEV_CLK(spi_clk, atmel_spi1, pba, 1); +@@ -1191,6 +1195,8 @@ + struct platform_device *__init + at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) + { ++ unsigned long sram_buf; ++ + /* + * Manage the chipselects as GPIOs, normally using the same pins + * the SPI controller expects; but boards can use other pins. +@@ -1231,6 +1237,13 @@ + return NULL; + } + ++ sram_buf = sram_alloc(4096); ++ if (sram_buf) { ++ pdev->resource[2].start = sram_buf; ++ pdev->resource[2].end = sram_buf + 4096 - 1; ++ pdev->resource[2].flags = IORESOURCE_MEM; ++ } ++ + spi_register_board_info(b, n); + platform_device_register(pdev); + return pdev; +@@ -1738,6 +1751,7 @@ + struct usba_ep_data ep[7]; + } usba_data; + struct platform_device *pdev; ++ u32 pin_mask; + + if (id != 0) + return NULL; +@@ -1940,6 +1954,7 @@ + at32_add_device_nand(unsigned int id, struct atmel_nand_data *data) + { + struct platform_device *pdev; ++ u32 pin_mask; + + if (id != 0 || !data) + return NULL; +@@ -2272,6 +2287,11 @@ + at32_init_pio(&pio4_device); + } + ++unsigned long at32_get_reset_cause(void) ++{ ++ return pm_readl(RCAUSE); ++} ++ + struct gen_pool *sram_pool; + + static int __init sram_init(void) +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/at32ap720x.c linux-2.6.28.2/arch/avr32/mach-at32ap/at32ap720x.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/at32ap720x.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/at32ap720x.c 2009-01-29 08:52:49.000000000 +0100 +@@ -0,0 +1,2303 @@ ++/* ++ * Copyright (C) 2008 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 <linux/atmel_pdca.h> ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/dw_dmac.h> ++#include <linux/errno.h> ++#include <linux/fb.h> ++#include <linux/gpio.h> ++#include <linux/io.h> ++#include <linux/ioport.h> ++#include <linux/kernel.h> ++#include <linux/platform_device.h> ++#include <linux/pm.h> ++#include <linux/spinlock.h> ++#include <linux/spi/atmel_spi.h> ++#include <linux/spi/spi.h> ++#include <video/atmel_lcdc.h> ++#include <video/atmel_mpop.h> ++ ++#include <asm/ast_regs.h> ++#include <asm/atmel-mci.h> ++ ++#include <mach/at32ap720x.h> ++#include <mach/board.h> ++#include <mach/hmatrix.h> ++#include <mach/init.h> ++#include <mach/pm.h> ++#include <mach/portmux.h> ++#include <mach/sram.h> ++ ++#include "clock.h" ++#include "gpio-v2.h" ++#include "pm-v3.h" ++#include "sdc.h" ++ ++#define PBMEM(base) \ ++ { \ ++ .start = base, \ ++ .end = base + 0x3ff, \ ++ .flags = IORESOURCE_MEM, \ ++ } ++#define IRQ(num) \ ++ { \ ++ .start = num, \ ++ .end = num, \ ++ .flags = IORESOURCE_IRQ, \ ++ } ++ ++#define select_peripheral(port, pin_mask, periph, flags) \ ++ at32_select_periph(GPIO_##port##_BASE, pin_mask, \ ++ GPIO_##periph, flags) ++ ++#define DEV_CLK(_name, devname, bus, _index) \ ++static struct clk devname##_##_name = { \ ++ .name = #_name, \ ++ .dev = &devname##_device.dev, \ ++ .parent = &bus##_clk, \ ++ .mode = bus##_clk_mode, \ ++ .get_rate = bus##_clk_get_rate, \ ++ .index = _index, \ ++} ++ ++static DEFINE_SPINLOCK(pm_lock); ++ ++static unsigned long rcosc_get_rate(struct clk *clk) ++{ ++ return 32768; ++} ++ ++static unsigned long osc_get_rate(struct clk *clk) ++{ ++ return at32_board_osc_rates[clk->index]; ++} ++ ++static void osc32_mode(struct clk *clk, int enabled) ++{ ++ /* We never disable the 32 kHz oscillator */ ++ if (!enabled) ++ return; ++ ++ /* If it's already running, we're done. */ ++ if (pm_readl(POSCSR) & PM_BIT(POSCSR_OSC32RDY)) ++ return; ++ ++ /* Enable it, unless someone did it for us already */ ++ if (!(sdc_readl(OSCCTRL32) & SDC_BIT(OSCCTRL32_OSC32EN))) { ++ u32 value; ++ ++ value = SDC_BF(OSCCTRL32_STARTUP, 5) ++ | SDC_BF(OSCCTRL32_MODE, 0xd) ++ | SDC_BIT(OSCCTRL32_OSC32EN); ++ ++ sdc_writel(OSCCTRL32, value | SDC_BF(OSCCTRL32_KEY, 0x55)); ++ sdc_writel(OSCCTRL32, value | SDC_BF(OSCCTRL32_KEY, 0xaa)); ++ } ++ ++ pr_info("Waiting for 32 kHz crystal oscillator to start...\n"); ++ ++ while (!(pm_readl(POSCSR) & PM_BIT(POSCSR_OSC32RDY))) ++ cpu_relax(); ++} ++ ++static void oscn_mode(struct clk *clk, int enabled) ++{ ++ unsigned int i = clk->index; ++ u32 mcctrl; ++ ++ BUG_ON(i > 2); ++ ++ /* Let's keep oscillators running for now... */ ++ if (!enabled) ++ goto out; ++ ++ /* If it's already running, we're done */ ++ if (pm_readl(POSCSR) & (PM_BIT(POSCSR_OSC0RDY) << i)) ++ goto out; ++ ++ /* Enable it, unless someone did it for us already */ ++ mcctrl = pm_readl(MCCTRL); ++ if (!(mcctrl & (PM_BIT(MCCTRL_OSC0EN) << i))) { ++ /* TODO: Make OSC startup parameters configurable */ ++ pm_writel(OSCCTRL[i], PM_BF(OSCCTRLx_STARTUP, 5) ++ | PM_BF(OSCCTRLx_MODE, 0xa)); ++ pm_writel(MCCTRL, mcctrl | (PM_BIT(MCCTRL_OSC0EN) << i)); ++ } ++ ++ pr_debug("clk %s: waiting for clock to become ready...\n", clk->name); ++ pr_debug("clk %s: MCCTRL=%08x OSCCTRL%u=%08x\n", clk->name, ++ pm_readl(MCCTRL), i, pm_readl(OSCCTRL[i])); ++ ++ while (!(pm_readl(POSCSR) & (PM_BIT(POSCSR_OSC0RDY) << i))) ++ cpu_relax(); ++ ++out: ++ pr_debug("clk %s: running\n", clk->name); ++} ++ ++static struct clk rcosc = { ++ .name = "rcosc", ++ .get_rate = rcosc_get_rate, ++ .users = 1, ++}; ++static struct clk osc0 = { ++ .name = "osc0", ++ .get_rate = osc_get_rate, ++ .mode = oscn_mode, ++ .users = 1, ++ .index = 0, ++}; ++static struct clk osc1 = { ++ .name = "osc1", ++ .get_rate = osc_get_rate, ++ .mode = oscn_mode, ++ .index = 1, ++}; ++static struct clk osc2 = { ++ .name = "osc2", ++ .get_rate = osc_get_rate, ++ .mode = oscn_mode, ++ .index = 2, ++}; ++static struct clk osc32 = { ++ .name = "osc32k", ++ .get_rate = osc_get_rate, ++ .mode = osc32_mode, ++ .index = 3, ++}; ++ ++static void pll_mode(struct clk *clk, int enabled) ++{ ++ unsigned long timeout; ++ unsigned int index = clk->index; ++ u32 status; ++ u32 ctrl; ++ ++ ctrl = pm_readl(PLL[index]); ++ ++ if (enabled) { ++ if (PM_BFEXT(PLLx_PLLMUL, ctrl) <= 1) { ++ pr_debug("clk %s: failed to enable, rate not set\n", ++ clk->name); ++ return; ++ } ++ ++ ctrl |= PM_BIT(PLLx_PLLEN); ++ pm_writel(PLL[index], ctrl); ++ ++ pr_debug("clk %s: waiting for lock...\n", clk->name); ++ for (timeout = 10000; timeout; timeout--) { ++ status = pm_readl(POSCSR); ++ if (status & (PM_BIT(POSCSR_LOCK0) << index)) ++ break; ++ udelay(10); ++ } ++ ++ if (!(status & (PM_BIT(POSCSR_LOCK0) << index))) ++ pr_err("clk %s: timeout waiting for lock\n", ++ clk->name); ++ else ++ pr_debug("clk %s: running\n", clk->name); ++ } else { ++ ctrl &= ~PM_BIT(PLLx_PLLEN); ++ pm_writel(PLL[index], ctrl); ++ pr_debug("clk %s: stopped\n", clk->name); ++ } ++} ++ ++ ++static unsigned long pll_get_rate(struct clk *clk) ++{ ++ unsigned long rate; ++ unsigned int div; ++ unsigned int mul; ++ u32 ctrl; ++ ++ ctrl = pm_readl(PLL[clk->index]); ++ ++ div = PM_BFEXT(PLLx_PLLDIV, ctrl); ++ mul = PM_BFEXT(PLLx_PLLMUL, ctrl); ++ ++ rate = clk->parent->get_rate(clk->parent); ++ if (div != 0) ++ rate = (rate + div / 2) / div; ++ else ++ rate = rate * 2; ++ rate *= mul; ++ ++ if (ctrl & PM_BF(PLLx_PLLOPT, 4)) ++ rate = (rate + 1) / 2; ++ ++ return rate; ++} ++ ++static long pll_set_rate(struct clk *clk, unsigned long rate, int apply) ++{ ++ unsigned long mul_best_fit = 0; ++ unsigned long div; ++ unsigned long div_min; ++ unsigned long div_max; ++ unsigned long div_best_fit = 0; ++ unsigned long base; ++ unsigned long fvco; ++ unsigned long actual = 0; ++ unsigned long rate_error_prev = ~0UL; ++ u32 ctrl; ++ ++ /* Rate must be between 25 MHz and 400 Mhz. */ ++ if (rate < 25000000UL || rate > 400000000UL) ++ return -EINVAL; ++ ++ base = clk->parent->get_rate(clk->parent); ++ ++ /* PLL input frequency must be between 10 MHz and 200 MHz. */ ++ div_min = DIV_ROUND_UP(base, 200000000UL); ++ div_max = base / 10000000UL; ++ ++ if (div_max < div_min) ++ return -EINVAL; ++ ++ for (div = div_min; div <= div_max; div++) { ++ unsigned long mul; ++ unsigned long pll_in; ++ unsigned long rate_error; ++ ++ pll_in = (base + div / 2) / div; ++ mul = (rate + pll_in / 2) / pll_in; ++ ++ if (mul < 1) ++ continue; ++ ++ actual = pll_in * mul; ++ rate_error = abs(actual - rate); ++ ++ if (rate_error < rate_error_prev) { ++ mul_best_fit = mul; ++ div_best_fit = div; ++ rate_error_prev = rate_error; ++ } ++ ++ if (rate_error == 0) ++ break; ++ } ++ ++ if (div_best_fit == 0) ++ return -EINVAL; ++ ++ ctrl = 0; ++ fvco = actual; ++ ++ /* ++ * MUL=1 is not allowed. So we must double it and set the ++ * divide-by-two bit. ++ */ ++ if (mul_best_fit == 1) { ++ ctrl |= PM_BF(PLLx_PLLOPT, 4); ++ mul_best_fit *= 2; ++ fvco = actual * 2; ++ } ++ ++ if (fvco > 200000000) ++ ctrl |= PM_BF(PLLx_PLLOPT, 3); ++ else if (fvco > 100000000) ++ ctrl |= PM_BF(PLLx_PLLOPT, 2); ++ else if (fvco > 50000000) ++ ctrl |= PM_BF(PLLx_PLLOPT, 1); ++ ++ ctrl |= PM_BF(PLLx_PLLCOUNT, 31); ++ ctrl |= PM_BF(PLLx_PLLMUL, mul_best_fit); ++ ctrl |= PM_BF(PLLx_PLLDIV, div_best_fit); ++ ctrl |= PM_BF(PLLx_PLLOSC, clk->parent->index); ++ ++ if (apply) { ++ if (actual != rate) ++ return -EINVAL; ++ if (clk->users > 0) ++ return -EBUSY; ++ pr_debug(KERN_INFO "clk %s: new rate %lu (actual rate %lu)\n", ++ clk->name, rate, actual); ++ pm_writel(PLL[clk->index], ctrl); ++ } ++ ++ return actual; ++} ++ ++static int pll_set_parent(struct clk *clk, struct clk *parent) ++{ ++ unsigned int index = clk->index; ++ u32 ctrl; ++ ++ if (clk->users > 0) ++ return -EBUSY; ++ ++ ctrl = pm_readl(PLL[index]); ++ BUG_ON(ctrl & PM_BIT(PLLx_PLLEN)); ++ ++ ctrl = PM_BFINS(PLLx_PLLOSC, parent->index, ctrl); ++ pm_writel(PLL[index], ctrl); ++ ++ clk->parent = parent; ++ ++ return 0; ++} ++ ++static struct clk pll0 = { ++ .name = "pll0", ++ .mode = pll_mode, ++ .get_rate = pll_get_rate, ++ .set_rate = pll_set_rate, ++ .set_parent = pll_set_parent, ++ .users = 1, ++ .index = 0, ++}; ++static struct clk pll1 = { ++ .name = "pll1", ++ .mode = pll_mode, ++ .get_rate = pll_get_rate, ++ .set_rate = pll_set_rate, ++ .set_parent = pll_set_parent, ++ .users = 0, ++ .index = 1, ++}; ++static struct clk pll2 = { ++ .name = "pll2", ++ .mode = pll_mode, ++ .get_rate = pll_get_rate, ++ .set_rate = pll_set_rate, ++ .set_parent = pll_set_parent, ++ .users = 0, ++ .index = 2, ++}; ++ ++/* ++ * The main clock can be either rcosc, osc0 or pll0. The boot loader ++ * may have chosen one for us, so we don't really know which one until ++ * we have a look at the PM registers. ++ */ ++static struct clk *main_clock; ++ ++/* ++ * Synchronous clocks are generated from the main clock. The clocks ++ * must satisfy the constraint ++ * fCPU >= fHSB >= fPB ++ * i.e. each clock must not be faster than its parent. ++ */ ++static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) ++{ ++ return main_clock->get_rate(main_clock) >> shift; ++}; ++ ++static void cpu_clk_mode(struct clk *clk, int enabled) ++{ ++ unsigned long flags; ++ u32 mask; ++ ++ spin_lock_irqsave(&pm_lock, flags); ++ ++ while (!(pm_readl(POSCSR) & PM_BIT(POSCSR_MSKRDY))) ++ cpu_relax(); ++ ++ mask = pm_readl(CPUMASK); ++ if (enabled) ++ mask |= 1 << clk->index; ++ else ++ mask &= ~(1 << clk->index); ++ pm_writel(CPUMASK, mask); ++ spin_unlock_irqrestore(&pm_lock, flags); ++} ++ ++static unsigned long cpu_clk_get_rate(struct clk *clk) ++{ ++ unsigned long cksel, shift = 0; ++ ++ cksel = pm_readl(CKSEL); ++ if (cksel & PM_BIT(CKSEL_CPUDIV)) ++ shift = PM_BFEXT(CKSEL_CPUSEL, cksel) + 1; ++ ++ return bus_clk_get_rate(clk, shift); ++} ++ ++static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply) ++{ ++ u32 control; ++ unsigned long parent_rate, child_div, actual_rate, div; ++ ++ parent_rate = clk->parent->get_rate(clk->parent); ++ control = pm_readl(CKSEL); ++ ++ if (control & PM_BIT(CKSEL_HSBDIV)) ++ child_div = 1 << (PM_BFEXT(CKSEL_HSBSEL, control) + 1); ++ else ++ child_div = 1; ++ ++ if (rate > 3 * (parent_rate / 4) || child_div == 1) { ++ actual_rate = parent_rate; ++ control &= ~PM_BIT(CKSEL_CPUDIV); ++ } else { ++ unsigned int cpusel; ++ div = (parent_rate + rate / 2) / rate; ++ if (div > child_div) ++ div = child_div; ++ cpusel = (div > 1) ? (fls(div) - 2) : 0; ++ control = PM_BIT(CKSEL_CPUDIV) ++ | PM_BFINS(CKSEL_CPUSEL, cpusel, control); ++ actual_rate = parent_rate / (1 << (cpusel + 1)); ++ } ++ ++ pr_debug("clk %s: new rate %lu (actual rate %lu)\n", ++ clk->name, rate, actual_rate); ++ ++ if (apply) { ++ while (!(pm_readl(POSCSR) & PM_BIT(POSCSR_CKRDY))) ++ cpu_relax(); ++ ++ pm_writel(CKSEL, control); ++ } ++ ++ return actual_rate; ++} ++ ++static void hsb_clk_mode(struct clk *clk, int enabled) ++{ ++ unsigned long flags; ++ u32 mask; ++ ++ spin_lock_irqsave(&pm_lock, flags); ++ ++ while (!(pm_readl(POSCSR) & PM_BIT(POSCSR_MSKRDY))) ++ cpu_relax(); ++ ++ mask = pm_readl(HSBMASK); ++ if (enabled) ++ mask |= 1 << clk->index; ++ else ++ mask &= ~(1 << clk->index); ++ pm_writel(HSBMASK, mask); ++ spin_unlock_irqrestore(&pm_lock, flags); ++} ++ ++static unsigned long hsb_clk_get_rate(struct clk *clk) ++{ ++ unsigned long cksel, shift = 0; ++ ++ cksel = pm_readl(CKSEL); ++ if (cksel & PM_BIT(CKSEL_HSBDIV)) ++ shift = PM_BFEXT(CKSEL_HSBSEL, cksel) + 1; ++ ++ return bus_clk_get_rate(clk, shift); ++} ++ ++static void pba_clk_mode(struct clk *clk, int enabled) ++{ ++ unsigned long flags; ++ u32 mask; ++ ++ spin_lock_irqsave(&pm_lock, flags); ++ ++ while (!(pm_readl(POSCSR) & PM_BIT(POSCSR_MSKRDY))) ++ cpu_relax(); ++ ++ mask = pm_readl(PBAMASK); ++ if (enabled) ++ mask |= 1 << clk->index; ++ else ++ mask &= ~(1 << clk->index); ++ pm_writel(PBAMASK, mask); ++ spin_unlock_irqrestore(&pm_lock, flags); ++} ++ ++static unsigned long pba_clk_get_rate(struct clk *clk) ++{ ++ unsigned long cksel, shift = 0; ++ ++ cksel = pm_readl(CKSEL); ++ if (cksel & PM_BIT(CKSEL_PBADIV)) ++ shift = PM_BFEXT(CKSEL_PBASEL, cksel) + 1; ++ ++ return bus_clk_get_rate(clk, shift); ++} ++ ++static void pbb_clk_mode(struct clk *clk, int enabled) ++{ ++ unsigned long flags; ++ u32 mask; ++ ++ spin_lock_irqsave(&pm_lock, flags); ++ ++ while (!(pm_readl(POSCSR) & PM_BIT(POSCSR_MSKRDY))) ++ cpu_relax(); ++ ++ mask = pm_readl(PBBMASK); ++ if (enabled) ++ mask |= 1 << clk->index; ++ else ++ mask &= ~(1 << clk->index); ++ pm_writel(PBBMASK, mask); ++ spin_unlock_irqrestore(&pm_lock, flags); ++} ++ ++static unsigned long pbb_clk_get_rate(struct clk *clk) ++{ ++ unsigned long cksel, shift = 0; ++ ++ cksel = pm_readl(CKSEL); ++ if (cksel & PM_BIT(CKSEL_PBBDIV)) ++ shift = PM_BFEXT(CKSEL_PBBSEL, cksel) + 1; ++ ++ return bus_clk_get_rate(clk, shift); ++} ++ ++static struct clk cpu_clk = { ++ .name = "cpu", ++ .get_rate = cpu_clk_get_rate, ++ .set_rate = cpu_clk_set_rate, ++ .users = 1, ++}; ++static struct clk hsb_clk = { ++ .name = "hsb", ++ .parent = &cpu_clk, ++ .get_rate = hsb_clk_get_rate, ++}; ++static struct clk pba_clk = { ++ .name = "pba", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = pba_clk_get_rate, ++ .users = 1, ++ .index = 1, ++}; ++static struct clk pbb_clk = { ++ .name = "pbb", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .users = 1, ++ .index = 2, ++}; ++static struct clk pbc_clk = { ++ .name = "pbc", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 3, ++}; ++ ++/* -------------------------------------------------------------------- ++ * Generic Clocks ++ * -------------------------------------------------------------------- */ ++ ++/* Mapping from GCCTRL:OSCSEL values to parent clocks */ ++static struct clk *const genclk_parent[] = { ++ &rcosc, ++ &osc32, ++ &osc0, ++ &osc1, ++ &osc2, ++ &pll0, ++ &pll1, ++ &pll2, ++ &cpu_clk, ++ &hsb_clk, ++ &pba_clk, ++ &pbb_clk, ++}; ++ ++#define NR_GENERIC_CLOCKS 8 ++ ++static void genclk_mode(struct clk *clk, int enabled) ++{ ++ u32 control; ++ ++ control = pm_readl(GCCTRL[clk->index]); ++ if (enabled) ++ control |= PM_BIT(GCCTRL_CEN); ++ else ++ control &= PM_BIT(GCCTRL_CEN); ++ pm_writel(GCCTRL[clk->index], control); ++} ++ ++static unsigned long genclk_get_rate(struct clk *clk) ++{ ++ u32 control; ++ unsigned long div = 1; ++ ++ control = pm_readl(GCCTRL[clk->index]); ++ if (control & PM_BIT(GCCTRL_DIVEN)) ++ div = 2 * (PM_BFEXT(GCCTRL_DIV, control) + 1); ++ ++ return clk->parent->get_rate(clk->parent) / div; ++} ++ ++static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) ++{ ++ unsigned long parent_rate; ++ unsigned long actual_rate; ++ unsigned long div; ++ u32 control; ++ ++ parent_rate = clk->parent->get_rate(clk->parent); ++ control = pm_readl(GCCTRL[clk->index]); ++ ++ if (rate > 3 * parent_rate / 4) { ++ actual_rate = parent_rate; ++ control &= ~PM_BIT(GCCTRL_DIVEN); ++ } else { ++ div = (parent_rate + rate) / (2 * rate) - 1; ++ control = PM_BFINS(GCCTRL_DIV, div, control) ++ | PM_BIT(GCCTRL_DIVEN); ++ actual_rate = parent_rate / (2 * (div + 1)); ++ } ++ ++ pr_debug("clk %s: new rate %lu (actual rate %lu)\n", ++ clk->name, rate, actual_rate); ++ ++ if (apply) ++ pm_writel(GCCTRL[clk->index], control); ++ ++ return actual_rate; ++} ++ ++static int genclk_set_parent(struct clk *clk, struct clk *parent) ++{ ++ unsigned int i; ++ u32 control; ++ ++ pr_debug("clk %s: new parent %s (was %s)\n", ++ clk->name, parent->name, ++ clk->parent ? clk->parent->name : "<none>"); ++ ++ control = pm_readl(GCCTRL[clk->index]); ++ ++ for (i = 0; i < ARRAY_SIZE(genclk_parent); i++) { ++ if (parent == genclk_parent[i]) { ++ control = PM_BFINS(GCCTRL_OSCSEL, i, control); ++ break; ++ } ++ } ++ ++ if (i >= ARRAY_SIZE(genclk_parent)) ++ return -EINVAL; ++ ++ pm_writel(GCCTRL[clk->index], control); ++ clk->parent = parent; ++ ++ return 0; ++} ++ ++#define DEFINE_GCLK(_name, i) \ ++ static struct clk _name = { \ ++ .name = #_name, \ ++ .mode = genclk_mode, \ ++ .get_rate = genclk_get_rate, \ ++ .set_rate = genclk_set_rate, \ ++ .set_parent = genclk_set_parent, \ ++ .index = i, \ ++ } ++ ++DEFINE_GCLK(gclk0, 0); ++DEFINE_GCLK(gclk1, 1); ++DEFINE_GCLK(gclk2, 2); ++DEFINE_GCLK(gclk3, 3); ++DEFINE_GCLK(gclk4, 4); ++DEFINE_GCLK(gclk5, 5); ++ ++static void __init genclk_init_parent(struct clk *clk) ++{ ++ unsigned int parent; ++ u32 control; ++ ++ BUG_ON(clk->index > NR_GENERIC_CLOCKS); ++ ++ control = pm_readl(GCCTRL[clk->index]); ++ parent = PM_BFEXT(GCCTRL_OSCSEL, control); ++ if (parent >= ARRAY_SIZE(genclk_parent)) { ++ /* Current parent is invalid. Reset to a sane value */ ++ parent = 0; ++ control = PM_BF(GCCTRL_OSCSEL, parent); ++ } ++ ++ clk->parent = genclk_parent[parent]; ++} ++ ++ ++/* -------------------------------------------------------------------- ++ * System peripherals ++ * -------------------------------------------------------------------- */ ++static struct dw_dma_platform_data dw_dmac0_data = { ++ .nr_channels = 4, ++}; ++static struct pdca_pdata pdca_data = { ++ .nr_channels = 20, ++}; ++ ++static struct resource intc_resource[] = { ++ PBMEM(0xffd00000), ++}; ++static struct resource pm_resource[] = { ++ PBMEM(0xffd00400), ++ IRQ(10), ++}; ++static struct resource sdc_resource[] = { ++ PBMEM(0xffd00800), ++ IRQ(45), ++}; ++static struct resource ast0_resource[] = { ++ PBMEM(0xffd00c00), ++ IRQ(11), ++}; ++static struct resource ast1_resource[] = { ++ PBMEM(0xffd01000), ++ IRQ(12), ++}; ++static struct resource wdt_resource[] = { ++ PBMEM(0xffd01400), ++}; ++static struct resource gpio_resource[] = { ++ PBMEM(0xffd02000), ++ { ++ .start = 16, ++ .end = 19, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static struct resource pdca_resource[] = { ++ { ++ .start = 0xffe00000, ++ .end = 0xffe01fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ IRQ(1), ++}; ++static struct resource smc_resource[] = { ++ PBMEM(0xffe04400), ++}; ++static struct resource dw_dmac0_resource[] = { ++ { ++ .start = 0xff100000, ++ .end = 0xff1003ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ IRQ(5), ++}; ++ ++struct platform_device at32_intc0_device = { ++ .name = "intc", ++ .resource = intc_resource, ++ .num_resources = ARRAY_SIZE(intc_resource), ++}; ++static struct platform_device pm_device = { ++ .name = "pm", ++ .resource = pm_resource, ++ .num_resources = ARRAY_SIZE(pm_resource), ++}; ++static struct platform_device sdc_device = { ++ .name = "sdc", ++ .resource = sdc_resource, ++ .num_resources = ARRAY_SIZE(sdc_resource), ++}; ++static struct platform_device ast0_device = { ++ .name = "rtc-ast", ++ .id = 0, ++ .resource = ast0_resource, ++ .num_resources = ARRAY_SIZE(ast0_resource), ++}; ++static struct platform_device ast1_device = { ++ .name = "timer-ast", ++ .id = 1, ++ .resource = ast1_resource, ++ .num_resources = ARRAY_SIZE(ast1_resource), ++}; ++static struct platform_device wdt_device = { ++ .name = "at32_wdt", ++ .id = 0, ++ .resource = wdt_resource, ++ .num_resources = ARRAY_SIZE(wdt_resource), ++}; ++static struct platform_device gpio_device = { ++ .name = "gpio", ++ .id = 0, ++ .resource = gpio_resource, ++ .num_resources = ARRAY_SIZE(gpio_resource), ++}; ++static struct platform_device pdca_device = { ++ .dev.platform_data = &pdca_data, ++ .name = "atmel_pdca", ++ .id = 0, ++ .resource = pdca_resource, ++ .num_resources = ARRAY_SIZE(pdca_resource), ++}; ++static struct platform_device smc_device = { ++ .name = "smc", ++ .id = 0, ++ .resource = smc_resource, ++ .num_resources = ARRAY_SIZE(smc_resource), ++}; ++static struct platform_device dw_dmac0_device = { ++ .dev.platform_data = &dw_dmac0_data, ++ .name = "dw_dmac", ++ .id = 0, ++ .resource = dw_dmac0_resource, ++ .num_resources = ARRAY_SIZE(dw_dmac0_resource), ++}; ++ ++DEV_CLK(pclk, at32_intc0, pba, 0); ++DEV_CLK(pclk, pm, pba, 1); ++DEV_CLK(pclk, sdc, pba, 2); ++DEV_CLK(pclk, ast0, pba, 3); ++DEV_CLK(pclk, ast1, pba, 4); ++DEV_CLK(pclk, wdt, pba, 5); ++DEV_CLK(pclk, gpio, pba, 8); ++DEV_CLK(hclk, pdca, hsb, 9); ++DEV_CLK(pclk, pdca, pbb, 0); ++DEV_CLK(pclk, smc, pbb, 5); ++DEV_CLK(hclk, dw_dmac0, hsb, 10); ++ ++static struct clk ebi_hclk = { ++ .name = "ebi_hclk", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = hsb_clk_get_rate, ++ .users = 1, ++}; ++static struct clk hramc_clk = { ++ .name = "hramc", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = hsb_clk_get_rate, ++ .users = 1, ++ .index = 4, ++}; ++static struct clk sdramc_clk = { ++ .name = "sdramc_clk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .users = 1, ++ .index = 6, ++}; ++ ++static int __init system_device_init(void) ++{ ++ platform_device_register(&at32_intc0_device); ++ platform_device_register(&pm_device); ++ platform_device_register(&sdc_device); ++ platform_device_register(&ast0_device); ++ platform_device_register(&ast1_device); ++ platform_device_register(&wdt_device); ++ platform_device_register(&gpio_device); ++ platform_device_register(&pdca_device); ++ platform_device_register(&smc_device); ++ platform_device_register(&dw_dmac0_device); ++ ++ return 0; ++} ++core_initcall(system_device_init); ++ ++/* -------------------------------------------------------------------- ++ * HMATRIX ++ * -------------------------------------------------------------------- */ ++ ++struct clk at32_hmatrix_clk = { ++ .name = "hmatrix_clk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 8, ++ .users = 0, ++}; ++ ++/* -------------------------------------------------------------------- ++ * USART ++ * -------------------------------------------------------------------- */ ++ ++static struct atmel_uart_data atmel_usart0_data = { ++ .use_dma_tx = 0, ++ .use_dma_rx = 0, ++}; ++static struct resource atmel_usart0_resource[] = { ++ PBMEM(0xffd03000), ++ IRQ(24), ++}; ++static struct platform_device atmel_usart0_device = { ++ .name = "atmel_usart", ++ .id = 0, ++ .dev = { ++ .platform_data = &atmel_usart0_data, ++ }, ++ .resource = atmel_usart0_resource, ++ .num_resources = ARRAY_SIZE(atmel_usart0_resource), ++}; ++DEV_CLK(usart, atmel_usart0, pba, 9); ++ ++static struct atmel_uart_data atmel_usart1_data = { ++ .use_dma_tx = 0, ++ .use_dma_rx = 0, ++}; ++static struct resource atmel_usart1_resource[] = { ++ PBMEM(0xffd03400), ++ IRQ(25), ++}; ++static struct platform_device atmel_usart1_device = { ++ .name = "atmel_usart", ++ .id = 1, ++ .dev = { ++ .platform_data = &atmel_usart1_data, ++ }, ++ .resource = atmel_usart1_resource, ++ .num_resources = ARRAY_SIZE(atmel_usart1_resource), ++}; ++DEV_CLK(usart, atmel_usart1, pba, 10); ++ ++static struct atmel_uart_data atmel_usart2_data = { ++ .use_dma_tx = 0, ++ .use_dma_rx = 0, ++}; ++static struct resource atmel_usart2_resource[] = { ++ PBMEM(0xffd03800), ++ IRQ(26), ++}; ++static struct platform_device atmel_usart2_device = { ++ .name = "atmel_usart", ++ .id = 2, ++ .dev = { ++ .platform_data = &atmel_usart2_data, ++ }, ++ .resource = atmel_usart2_resource, ++ .num_resources = ARRAY_SIZE(atmel_usart2_resource), ++}; ++DEV_CLK(usart, atmel_usart2, pba, 11); ++ ++static struct atmel_uart_data atmel_usart3_data = { ++ .use_dma_tx = 0, ++ .use_dma_rx = 0, ++}; ++static struct resource atmel_usart3_resource[] = { ++ PBMEM(0xffd03c00), ++ IRQ(27), ++}; ++static struct platform_device atmel_usart3_device = { ++ .name = "atmel_usart", ++ .id = 3, ++ .dev = { ++ .platform_data = &atmel_usart3_data, ++ }, ++ .resource = atmel_usart3_resource, ++ .num_resources = ARRAY_SIZE(atmel_usart3_resource), ++}; ++DEV_CLK(usart, atmel_usart3, pba, 12); ++ ++static struct atmel_uart_data atmel_usart4_data = { ++ .use_dma_tx = 0, ++ .use_dma_rx = 0, ++}; ++static struct resource atmel_usart4_resource[] = { ++ PBMEM(0xffd04000), ++ IRQ(28), ++}; ++static struct platform_device atmel_usart4_device = { ++ .name = "atmel_usart", ++ .id = 4, ++ .dev = { ++ .platform_data = &atmel_usart4_data, ++ }, ++ .resource = atmel_usart4_resource, ++ .num_resources = ARRAY_SIZE(atmel_usart4_resource), ++}; ++DEV_CLK(usart, atmel_usart4, pba, 13); ++ ++static struct atmel_uart_data atmel_usart5_data = { ++ .use_dma_tx = 0, ++ .use_dma_rx = 0, ++}; ++static struct resource atmel_usart5_resource[] = { ++ PBMEM(0xffd04400), ++ IRQ(29), ++}; ++static struct platform_device atmel_usart5_device = { ++ .name = "atmel_usart", ++ .id = 5, ++ .dev = { ++ .platform_data = &atmel_usart5_data, ++ }, ++ .resource = atmel_usart5_resource, ++ .num_resources = ARRAY_SIZE(atmel_usart5_resource), ++}; ++DEV_CLK(usart, atmel_usart5, pba, 14); ++ ++static void __init configure_usart0_pins(void) ++{ ++ /* RXD | TXD */ ++ select_peripheral(PB, (1 << 14) | (1 << 15), PERIPH_B, 0); ++} ++ ++static void __init configure_usart1_pins(void) ++{ ++ /* TXD | RXD */ ++ select_peripheral(PA, (1 << 8) | (1 << 9), PERIPH_A, 0); ++} ++ ++static void __init configure_usart2_pins(void) ++{ ++ /* TXD | RXD */ ++ select_peripheral(PA, (1 << 16) | (1 << 17), PERIPH_A, 0); ++} ++ ++static void __init configure_usart3_pins(void) ++{ ++ /* RXD | TXD */ ++ select_peripheral(PC, (1 << 10) | (1 << 11), PERIPH_A, 0); ++} ++ ++static void __init configure_usart4_pins(void) ++{ ++ /* TXD | RXD */ ++ select_peripheral(PA, (1 << 14) | (1 << 15), PERIPH_A, 0); ++} ++ ++static void __init configure_usart5_pins(void) ++{ ++ /* RXD | TXD */ ++ select_peripheral(PA, (1 << 22) | (1 << 23), PERIPH_A, 0); ++} ++ ++static struct platform_device *__initdata at32_usarts[6]; ++ ++void __init at32_map_usart(unsigned int hw_id, unsigned int line) ++{ ++ struct platform_device *pdev; ++ ++ switch (hw_id) { ++ case 0: ++ pdev = &atmel_usart0_device; ++ configure_usart0_pins(); ++ break; ++ case 1: ++ pdev = &atmel_usart1_device; ++ configure_usart1_pins(); ++ break; ++ case 2: ++ pdev = &atmel_usart2_device; ++ configure_usart2_pins(); ++ break; ++ case 3: ++ pdev = &atmel_usart3_device; ++ configure_usart3_pins(); ++ break; ++ case 4: ++ pdev = &atmel_usart4_device; ++ configure_usart4_pins(); ++ break; ++ case 5: ++ pdev = &atmel_usart5_device; ++ configure_usart5_pins(); ++ break; ++ default: ++ return; ++ } ++ ++ if (PXSEG(pdev->resource[0].start) == P4SEG) { ++ /* Addresses in the P4 segment are permanently mapped 1:1 */ ++ struct atmel_uart_data *data = pdev->dev.platform_data; ++ data->regs = (void __iomem __force *)pdev->resource[0].start; ++ } ++ ++ pdev->id = line; ++ at32_usarts[line] = pdev; ++} ++ ++struct platform_device *__init at32_add_device_usart(unsigned int id) ++{ ++ platform_device_register(at32_usarts[id]); ++ return at32_usarts[id]; ++} ++ ++struct platform_device *atmel_default_console_device; ++ ++void __init at32_setup_serial_console(unsigned int usart_id) ++{ ++ atmel_default_console_device = at32_usarts[usart_id]; ++} ++ ++/* -------------------------------------------------------------------- ++ * Ethernet ++ * -------------------------------------------------------------------- */ ++ ++static u64 macb0_dma_mask = DMA_32BIT_MASK; ++static struct resource macb0_resource[] __initdata = { ++ PBMEM(0xffe04000), ++ IRQ(8), ++}; ++static struct clk macb0_hclk = { ++ .name = "hclk", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = hsb_clk_get_rate, ++ .index = 8, ++}; ++static struct clk macb0_pclk = { ++ .name = "pclk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 4, ++}; ++ ++struct platform_device *__init ++at32_add_device_eth(unsigned int id, struct eth_platform_data *data) ++{ ++ struct platform_device *pdev; ++ u32 pin_mask_a; ++ u32 pin_mask_c; ++ ++ if (id != 0 || !data) ++ return NULL; ++ ++ pdev = platform_device_alloc("macb", id); ++ if (!pdev) ++ return NULL; ++ ++ if (platform_device_add_resources(pdev, macb0_resource, ++ ARRAY_SIZE(macb0_resource))) ++ goto out_free_pdev; ++ ++ if (platform_device_add_data(pdev, data, ++ sizeof(struct eth_platform_data))) ++ goto out_free_pdev; ++ ++ pin_mask_a = (1 << 4); /* RXDV */ ++ pin_mask_c = (1 << 10); /* MDC */ ++ pin_mask_c |= (1 << 11); /* MDIO */ ++ pin_mask_c |= (1 << 12); /* TXCK */ ++ pin_mask_c |= (1 << 14); /* RXD0 */ ++ pin_mask_c |= (1 << 15); /* RXD1 */ ++ pin_mask_c |= (1 << 16); /* RXER */ ++ pin_mask_c |= (1 << 18); /* TXEN */ ++ pin_mask_c |= (1 << 19); /* TXD0 */ ++ pin_mask_c |= (1 << 20); /* TXD1 */ ++ ++ if (!data->is_rmii) { ++ pin_mask_a |= (1<<0); /* COL */ ++ pin_mask_a |= (1<<1); /* RXD2 */ ++ pin_mask_a |= (1<<2); /* RXD3 */ ++ pin_mask_a |= (1<<3); /* RXCK */ ++ pin_mask_a |= (1<<5); /* TXER */ ++ pin_mask_a |= (1<<6); /* TXD2 */ ++ pin_mask_a |= (1<<7); /* TXD3 */ ++ pin_mask_c |= (1<<13); /* CRS */ ++ pin_mask_c |= (1<<17); /* SPD */ ++ } ++ ++ select_peripheral(PA, pin_mask_a, PERIPH_B, 0); ++ select_peripheral(PC, pin_mask_c, PERIPH_C, 0); ++ ++ pdev->dev.dma_mask = &macb0_dma_mask; ++ pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; ++ ++ macb0_hclk.dev = &pdev->dev; ++ macb0_pclk.dev = &pdev->dev; ++ ++ platform_device_add(pdev); ++ ++ return pdev; ++ ++out_free_pdev: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* -------------------------------------------------------------------- ++ * SPI ++ * -------------------------------------------------------------------- */ ++static struct resource atmel_spi_resource[][2] __initdata = { ++ { ++ PBMEM(0xffe05400), ++ IRQ(36), ++ }, { ++ PBMEM(0xffe05800), ++ IRQ(37), ++ }, { ++ PBMEM(0xffe05c00), ++ IRQ(38), ++ }, { ++ PBMEM(0xffe06000), ++ IRQ(39), ++ } ++}; ++static struct clk atmel_spi_clk[] = { ++ { ++ .name = "spi_clk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 9, ++ }, { ++ .name = "spi_clk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 10, ++ }, { ++ .name = "spi_clk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 11, ++ }, { ++ .name = "spi_clk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 12, ++ } ++}; ++static int __initdata atmel_spi_pins[][4] = { ++ { ++ /* SPI0 */ ++ GPIO_PIN_PB(3), GPIO_PIN_PB(4), ++ GPIO_PIN_PB(5), GPIO_PIN_PB(6), ++ }, { ++ /* SPI1 */ ++ GPIO_PIN_PB(4), -1, -1, -1, ++ }, { ++ /* SPI2 */ ++ GPIO_PIN_PA(28), -1, -1, -1, ++ }, { ++ /* SPI3 */ ++ GPIO_PIN_PA(27), GPIO_PIN_PA(20), ++ GPIO_PIN_PA(29), GPIO_PIN_PA(30), ++ } ++}; ++ ++ ++static void __init at32_spi_setup_dw_dma(unsigned int id, ++ struct atmel_spi_pdata *pdata) ++{ ++ struct dw_dma_slave *rx_dws; ++ struct dw_dma_slave *tx_dws; ++ ++ if (pdata->rx_dma_slave) ++ rx_dws = kmemdup(to_dw_dma_slave(pdata->rx_dma_slave), ++ sizeof(struct dw_dma_slave), GFP_KERNEL); ++ else ++ rx_dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); ++ if (pdata->tx_dma_slave) ++ tx_dws = kmemdup(to_dw_dma_slave(pdata->tx_dma_slave), ++ sizeof(struct dw_dma_slave), GFP_KERNEL); ++ else ++ tx_dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); ++ ++ rx_dws->slave.dma_dev = tx_dws->slave.dma_dev = &dw_dmac0_device.dev; ++ rx_dws->slave.reg_width = tx_dws->slave.reg_width ++ = DMA_SLAVE_WIDTH_8BIT; ++ ++ rx_dws->cfg_hi = DWC_CFGH_SRC_PER(2); ++ tx_dws->cfg_hi = DWC_CFGH_DST_PER(3); ++ rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL ++ | DWC_CFGL_HS_SRC_POL); ++ tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL ++ | DWC_CFGL_HS_SRC_POL); ++ ++ pdata->rx_dma_slave = &rx_dws->slave; ++ pdata->tx_dma_slave = &tx_dws->slave; ++} ++ ++static void __init at32_spi_setup_pdca(unsigned int id, ++ struct atmel_spi_pdata *pdata) ++{ ++ struct pdca_slave *rx_pslave; ++ struct pdca_slave *tx_pslave; ++ ++ if (pdata->rx_dma_slave) ++ rx_pslave = kmemdup(dma_to_pdca_slave(pdata->rx_dma_slave), ++ sizeof(struct pdca_slave), GFP_KERNEL); ++ else ++ rx_pslave = kzalloc(sizeof(struct pdca_slave), GFP_KERNEL); ++ if (pdata->tx_dma_slave) ++ tx_pslave = kmemdup(dma_to_pdca_slave(pdata->tx_dma_slave), ++ sizeof(struct pdca_slave), GFP_KERNEL); ++ else ++ tx_pslave = kzalloc(sizeof(struct pdca_slave), GFP_KERNEL); ++ ++ rx_pslave->slave.dma_dev = &pdca_device.dev; ++ tx_pslave->slave.dma_dev = &pdca_device.dev; ++ rx_pslave->slave.reg_width = DMA_SLAVE_WIDTH_8BIT; ++ tx_pslave->slave.reg_width = DMA_SLAVE_WIDTH_8BIT; ++ ++ rx_pslave->tx_periph_id = -1; ++ tx_pslave->rx_periph_id = -1; ++ ++ switch (id) { ++ case 1: ++ rx_pslave->rx_periph_id = 6; ++ tx_pslave->tx_periph_id = 17; ++ break; ++ case 2: ++ rx_pslave->rx_periph_id = 7; ++ tx_pslave->tx_periph_id = 18; ++ break; ++ case 3: ++ rx_pslave->rx_periph_id = 8; ++ tx_pslave->tx_periph_id = 19; ++ break; ++ } ++ ++ pdata->rx_dma_slave = &rx_pslave->slave; ++ pdata->tx_dma_slave = &tx_pslave->slave; ++} ++ ++static void __init ++at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, ++ unsigned int n, const int *pins) ++{ ++ unsigned int mode; ++ unsigned int cs; ++ int pin; ++ ++ for (; n; n--, b++) { ++ b->bus_num = bus_num; ++ cs = b->chip_select; ++ if (cs >= 4 || !gpio_is_valid(pins[cs])) ++ continue; ++ ++ pin = (int)b->controller_data; ++ if (!pin || !gpio_is_valid(pin)) { ++ pin = pins[cs]; ++ b->controller_data = (void *)pin; ++ } ++ ++ mode = AT32_GPIOF_OUTPUT; ++ if (!(b->mode & SPI_CS_HIGH)) ++ mode |= AT32_GPIOF_HIGH; ++ at32_select_gpio(pin, mode); ++ } ++} ++ ++struct platform_device *__init at32_add_device_spi(unsigned int id, ++ struct spi_board_info *b, unsigned int n) ++{ ++ struct atmel_spi_pdata pdata; ++ struct platform_device *pdev; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(atmel_spi_resource) ++ != ARRAY_SIZE(atmel_spi_clk)); ++ ++ if (id >= ARRAY_SIZE(atmel_spi_resource)) ++ return NULL; ++ ++ pdev = platform_device_alloc("atmel_spi", id); ++ if (!pdev) ++ goto fail; ++ ++ if (platform_device_add_resources(pdev, atmel_spi_resource[id], ++ ARRAY_SIZE(atmel_spi_resource[id]))) ++ goto fail; ++ ++ memset(&pdata, 0, sizeof(struct atmel_spi_pdata)); ++ ++ if (id == 0) ++ at32_spi_setup_dw_dma(id, &pdata); ++ else ++ at32_spi_setup_pdca(id, &pdata); ++ pdata.rx_dma_slave->dev = pdata.tx_dma_slave->dev = &pdev->dev; ++ ++ if (platform_device_add_data(pdev, &pdata, ++ sizeof(struct atmel_spi_pdata))) ++ goto fail; ++ ++ switch (id) { ++ case 0: ++ /* pullup MISO so a level is always defined */ ++ select_peripheral(PB, (1 << 1), PERIPH_A, AT32_GPIOF_PULLUP); ++ /* MOSI | SCK */ ++ select_peripheral(PB, (1 << 0) | (1 << 2), PERIPH_A, 0); ++ ++ at32_spi_setup_slaves(0, b, n, atmel_spi_pins[0]); ++ break; ++ ++ case 1: ++ /* pullup MISO so a level is always defined */ ++ select_peripheral(PB, (1 << 7), PERIPH_B, AT32_GPIOF_PULLUP); ++ /* MOSI | SCK */ ++ select_peripheral(PB, (1 << 6) | (1 << 5), PERIPH_B, 0); ++ ++ at32_spi_setup_slaves(1, b, n, atmel_spi_pins[1]); ++ break; ++ ++ case 2: ++ /* pullup MISO so a level is always defined */ ++ select_peripheral(PA, (1 << 30), PERIPH_B, AT32_GPIOF_PULLUP); ++ /* MOSI | SCK */ ++ select_peripheral(PA, (1 << 31) || (1 << 29), PERIPH_B, 0); ++ ++ at32_spi_setup_slaves(2, b, n, atmel_spi_pins[2]); ++ break; ++ ++ case 3: ++ /* pullup MISO so a level is always defined */ ++ select_peripheral(PA, (1 << 25), PERIPH_A, AT32_GPIOF_PULLUP); ++ /* MOSI | SCK */ ++ select_peripheral(PA, (1 << 24) | (1 << 26), PERIPH_A, 0); ++ ++ at32_spi_setup_slaves(3, b, n, atmel_spi_pins[3]); ++ break; ++ ++ default: ++ goto fail; ++ } ++ ++ atmel_spi_clk[id].dev = &pdev->dev; ++ spi_register_board_info(b, n); ++ platform_device_add(pdev); ++ ++ return pdev; ++ ++fail: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* -------------------------------------------------------------------- ++ * MMC ++ * -------------------------------------------------------------------- */ ++static struct resource atmel_mci0_resource[] __initdata = { ++ PBMEM(0xfff00000), ++ IRQ(43), ++}; ++/* MCI is on the PBC bus, but it is controlled by the PBBMASK register */ ++static struct clk atmel_mci0_pclk = { ++ .name = "mci_clk", ++ .parent = &pbc_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 16, ++}; ++ ++struct platform_device *__init ++at32_add_device_mci(unsigned int id, struct mci_platform_data *data) ++{ ++ struct platform_device *pdev; ++ struct dw_dma_slave *dws; ++ u32 pin_mask_1 = 0; ++ u32 pin_mask_2 = 0; ++ ++ if (id != 0) ++ return NULL; ++ ++ /* Must have at least one usable slot */ ++ if (!data->slot[0].bus_width && !data->slot[1].bus_width) ++ return NULL; ++ ++ pdev = platform_device_alloc("atmel_mci", id); ++ if (!pdev) ++ goto fail; ++ ++ if (platform_device_add_resources(pdev, atmel_mci0_resource, ++ ARRAY_SIZE(atmel_mci0_resource))) ++ goto fail; ++ ++ if (data->dma_slave) ++ dws = kmemdup(to_dw_dma_slave(data->dma_slave), ++ sizeof(struct dw_dma_slave), GFP_KERNEL); ++ else ++ dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); ++ ++ dws->slave.dev = &pdev->dev; ++ dws->slave.dma_dev = &dw_dmac0_device.dev; ++ dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT; ++ dws->cfg_hi = (DWC_CFGH_SRC_PER(0) ++ | DWC_CFGH_DST_PER(1)); ++ dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL ++ | DWC_CFGL_HS_SRC_POL); ++ ++ data->dma_slave = &dws->slave; ++ ++ if (platform_device_add_data(pdev, data, ++ sizeof(struct mci_platform_data))) ++ goto fail; ++ ++ switch (data->slot[0].bus_width) { ++ case 8: ++ pin_mask_1 |= (1 << 20); /* DATA4 */ ++ pin_mask_1 |= (1 << 21); /* DATA5 */ ++ pin_mask_1 |= (1 << 22); /* DATA6 */ ++ pin_mask_1 |= (1 << 23); /* DATA7 */ ++ /* fall through */ ++ case 4: ++ pin_mask_2 |= (1 << 19); /* DATA1 */ ++ pin_mask_2 |= (1 << 20); /* DATA2 */ ++ pin_mask_2 |= (1 << 21); /* DATA3 */ ++ /* fall through */ ++ case 1: ++ pin_mask_2 |= (1 << 18); /* DATA0 */ ++ pin_mask_2 |= (1 << 17); /* CMD */ ++ ++ select_peripheral(PA, pin_mask_1, PERIPH_D, AT32_GPIOF_PULLUP); ++ select_peripheral(PB, pin_mask_2, PERIPH_A, AT32_GPIOF_PULLUP); ++ select_peripheral(PB, (1 << 16), PERIPH_A, 0); /* CLK */ ++ ++ if (gpio_is_valid(data->slot[0].detect_pin)) ++ at32_select_gpio(data->slot[0].detect_pin, 0); ++ if (gpio_is_valid(data->slot[0].wp_pin)) ++ at32_select_gpio(data->slot[0].wp_pin, 0); ++ ++ break; ++ case 0: ++ /* Slot is unused */ ++ break; ++ default: ++ goto fail; ++ } ++ ++ pin_mask_1 = 0; ++ ++ switch (data->slot[1].bus_width) { ++ case 8: ++ pin_mask_1 |= (1 << 9); /* DATA7 */ ++ pin_mask_1 |= (1 << 8); /* DATA6 */ ++ pin_mask_1 |= (1 << 7); /* DATA5 */ ++ pin_mask_1 |= (1 << 6); /* DATA4 */ ++ /* fall through */ ++ case 4: ++ pin_mask_1 |= (1 << 5); /* DATA3 */ ++ pin_mask_1 |= (1 << 4); /* DATA2 */ ++ pin_mask_1 |= (1 << 3); /* DATA1 */ ++ /* fall through */ ++ case 1: ++ pin_mask_1 |= (1 << 2); /* DATA0 */ ++ pin_mask_1 |= (1 << 1); /* CMD */ ++ ++ select_peripheral(PC, pin_mask_1, PERIPH_A, AT32_GPIOF_PULLUP); ++ select_peripheral(PC, (1 << 0), PERIPH_A, 0); /* CLK */ ++ ++ if (gpio_is_valid(data->slot[1].detect_pin)) ++ at32_select_gpio(data->slot[1].detect_pin, 0); ++ if (gpio_is_valid(data->slot[1].wp_pin)) ++ at32_select_gpio(data->slot[1].wp_pin, 0); ++ ++ break; ++ case 0: ++ /* Slot is unused */ ++ break; ++ default: ++ goto fail; ++ } ++ ++ atmel_mci0_pclk.dev = &pdev->dev; ++ ++ platform_device_add(pdev); ++ return pdev; ++ ++fail: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* -------------------------------------------------------------------- ++ * LCDC ++ * -------------------------------------------------------------------- */ ++static u64 atmel_lcdfb0_dma_mask = DMA_32BIT_MASK; ++static struct resource atmel_lcdfb0_resource[] __initdata = { ++ { ++ .start = 0xff000000, ++ .end = 0xff000fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ IRQ(3), ++ { ++ /* Placeholder for pre-allocated fb memory */ ++ .start = 0x00000000, ++ .end = 0x00000000, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct clk atmel_lcdfb0_hck1 = { ++ .name = "hck1", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = hsb_clk_get_rate, ++ .index = 7, ++}; ++static struct clk atmel_lcdfb0_pixclk = { ++ .name = "lcdc_clk", ++ .mode = genclk_mode, ++ .get_rate = genclk_get_rate, ++ .set_rate = genclk_set_rate, ++ .set_parent = genclk_set_parent, ++ .index = 6, ++}; ++ ++struct platform_device *__init ++at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, ++ unsigned long fbmem_start, unsigned long fbmem_len, ++ u64 pin_mask) ++{ ++ struct { ++ struct atmel_lcdfb_info info; ++ struct fb_monspecs monspecs; ++ struct fb_videomode modedb[0]; ++ } *all_data; ++ struct platform_device *pdev; ++ unsigned int data_size; ++ unsigned int modedb_size; ++ unsigned int num_resources; ++ int ret; ++ ++ if (id > 0 || !data) ++ return NULL; ++ ++ pdev = platform_device_alloc("atmel_lcdfb", id); ++ if (!pdev) ++ return NULL; ++ ++ num_resources = ARRAY_SIZE(atmel_lcdfb0_resource); ++ if (fbmem_len) { ++ atmel_lcdfb0_resource[num_resources - 1].start = fbmem_start; ++ atmel_lcdfb0_resource[num_resources - 1].end ++ = fbmem_start + fbmem_len - 1; ++ } else { ++ num_resources--; ++ } ++ ++ if (platform_device_add_resources(pdev, atmel_lcdfb0_resource, ++ num_resources)) ++ goto error; ++ ++ /* ++ * Allocate all data -- info struct, monspecs and modedb -- in ++ * a single chunk. ++ */ ++ modedb_size = data->default_monspecs->modedb_len ++ * sizeof(struct fb_videomode); ++ data_size = sizeof(*all_data) + modedb_size; ++ all_data = kmalloc(data_size, GFP_KERNEL); ++ if (!all_data) ++ goto error; ++ ++ memcpy(&all_data->info, data, sizeof(struct atmel_lcdfb_info)); ++ memcpy(&all_data->monspecs, data->default_monspecs, ++ sizeof(struct fb_monspecs)); ++ memcpy(&all_data->modedb, data->default_monspecs->modedb, modedb_size); ++ ++ ret = platform_device_add_data(pdev, all_data, data_size); ++ kfree(all_data); ++ if (ret) ++ goto error; ++ ++ /* ++ * Update internal pointers to use memory allocated by ++ * platform_device_add_data(). ++ */ ++ all_data = pdev->dev.platform_data; ++ all_data->info.default_monspecs = &all_data->monspecs; ++ all_data->monspecs.modedb = all_data->modedb; ++ ++ select_peripheral(PD, 0x7fffffff, PERIPH_A, 0); ++ ++ pdev->dev.dma_mask = &atmel_lcdfb0_dma_mask; ++ pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; ++ ++ atmel_lcdfb0_hck1.dev = &pdev->dev; ++ atmel_lcdfb0_pixclk.dev = &pdev->dev; ++ ++ clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); ++ clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); ++ ++ platform_device_add(pdev); ++ return pdev; ++ ++error: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* -------------------------------------------------------------------- ++ * Media Post-Processor (MPOP) ++ * -------------------------------------------------------------------- */ ++ ++static u64 atmel_mpopfb0_dma_mask = DMA_32BIT_MASK; ++static struct resource atmel_mpopfb0_resource[] = { ++ { ++ /* Configuration interface */ ++ .start = 0xffe02000, ++ .end = 0xffe02fff, ++ .flags = IORESOURCE_MEM, ++ }, { ++ /* Data interface (output) */ ++ .start = 0xf0000000, ++ .end = 0xf0ffffff, ++ .flags = IORESOURCE_MEM, ++ }, ++ IRQ(4), ++ { ++ /* Placeholder for pre-allocated fb memory */ ++ .start = 0x00000000, ++ .end = 0x00000000, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct clk atmel_mpopfb0_hclk = { ++ .name = "hclk", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = hsb_clk_get_rate, ++ .index = 12, ++}; ++static struct clk atmel_mpopfb0_pclk = { ++ .name = "pclk", ++ .parent = &pbb_clk, ++ .mode = pbb_clk_mode, ++ .get_rate = pbb_clk_get_rate, ++ .index = 2, ++}; ++ ++struct platform_device *__init at32_add_device_mpop(unsigned int id, ++ struct platform_device *lcdc_pdev, ++ unsigned long fbmem_start, unsigned long fbmem_len) ++{ ++ struct platform_device *pdev; ++ struct atmel_mpopfb_info info; ++ unsigned int num_resources; ++ ++ if (id != 0) ++ return NULL; ++ ++ pdev = platform_device_alloc("atmel_mpopfb", id); ++ if (!pdev) ++ return NULL; ++ ++ num_resources = ARRAY_SIZE(atmel_mpopfb0_resource); ++ if (fbmem_len) { ++ atmel_mpopfb0_resource[num_resources - 1].start = fbmem_start; ++ atmel_mpopfb0_resource[num_resources - 1].end ++ = fbmem_start + fbmem_len - 1; ++ } else { ++ num_resources--; ++ } ++ if (platform_device_add_resources(pdev, atmel_mpopfb0_resource, ++ num_resources)) ++ goto error; ++ ++ info.lcdc_pdev = lcdc_pdev; ++ if (platform_device_add_data(pdev, &info, sizeof(info))) ++ goto error; ++ ++ pdev->dev.dma_mask = &atmel_mpopfb0_dma_mask; ++ pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; ++ ++ atmel_mpopfb0_hclk.dev = &pdev->dev; ++ atmel_mpopfb0_pclk.dev = &pdev->dev; ++ ++ platform_device_add(pdev); ++ return pdev; ++ ++error: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* ------------------------------------------------------------------- ++ * USB Host (OHCI/EHCI) ++ * ------------------------------------------------------------------- */ ++ ++static u64 usbh_dma_mask = DMA_32BIT_MASK; ++ ++static unsigned long parent_clk_get_rate(struct clk *clk) ++{ ++ return clk->parent->get_rate(clk->parent); ++} ++ ++static void parent_clk_mode(struct clk *clk, int enabled) ++{ ++ /* Parent clk enabled by clk core */ ++} ++ ++/* ++ * The UTMI clock is an internally controlled PLL. It is hardwired to ++ * OSC2 and will run at 30 MHz or 60 MHz depending on the internal ++ * UTMI <-> host controller data bus width. ++ * ++ * We can turn it on and off through the Power Manager. That's all. ++ */ ++static void utmi_clk_mode(struct clk *clk, int enabled) ++{ ++ u32 ppcr = pm_readl(PPCR); ++ ++ if (enabled) ++ /* Clear UTMI suspend signal */ ++ ppcr |= PM_BIT(PPCR_UTMI_CTRL); ++ else ++ /* Set UTMI suspend signal */ ++ ppcr &= ~PM_BIT(PPCR_UTMI_CTRL); ++ ++ pm_writel(PPCR, ppcr | PM_BF(PPCR_KEY, 0x55)); ++ pm_writel(PPCR, ppcr | PM_BF(PPCR_KEY, 0xaa)); ++ ++ if (enabled) ++ /* PLL startup time is 2.5 ms */ ++ udelay(2500); ++} ++ ++static unsigned long utmi_clk_get_rate(struct clk *clk) ++{ ++ /* ++ * Not sure about this, but I think the UTMI interface on ++ * AP7200 is 16 bits wide, which means 30 MHz PHY clock. ++ */ ++ return 30000000; ++} ++ ++static struct clk usbh_utmi_clk = { ++ .name = "usbh_utmi_clk", ++ .parent = &osc2, ++ .mode = utmi_clk_mode, ++ .get_rate = utmi_clk_get_rate, ++}; ++ ++static struct clk usbh_hclk = { ++ .name = "usbh_hclk", ++ .parent = &hsb_clk, ++ .mode = hsb_clk_mode, ++ .get_rate = hsb_clk_get_rate, ++ .index = 6, ++}; ++ ++/* ++ * UTMI and HSB clocks are shared between OHCI and EHCI. These wrappers ++ * make sure both can use the clocks as if they had their own. ++ */ ++static struct clk ohci_utmi_clk = { ++ .name = "utmi_clk", ++ .parent = &usbh_utmi_clk, ++ .mode = parent_clk_mode, ++ .get_rate = parent_clk_get_rate, ++}; ++static struct clk ohci_hclk = { ++ .name = "hclk", ++ .parent = &usbh_hclk, ++ .mode = parent_clk_mode, ++ .get_rate = parent_clk_get_rate, ++}; ++ ++static struct clk ehci_utmi_clk = { ++ .name = "utmi_clk", ++ .parent = &usbh_utmi_clk, ++ .mode = parent_clk_mode, ++ .get_rate = parent_clk_get_rate, ++}; ++static struct clk ehci_hclk = { ++ .name = "hclk", ++ .parent = &usbh_hclk, ++ .mode = parent_clk_mode, ++ .get_rate = parent_clk_get_rate, ++}; ++ ++/* ++ * The USBH needs both a 48 MHz and a 12 MHz clock, and the 12 MHz ++ * must be generated by dividing the 48 MHz clock. There's only one ++ * generic clock hooked up to the USBH which we must use to generate ++ * both. ++ * ++ * This can be done because GCLK0 generates an additional "divided ++ * clock", which is the normal clock output further divided by four ++ * (this is hardcoded, but not surprisingly, exactly what we need.) ++ * ++ * So we generate the clocks as follows: ++ * OSC2 (12 MHz) -> PLL2 (48 MHz) --> GCLK0 undivided (48 MHz) ++ * |-> GCLK0 divided (12 MHz) ++ * ++ * This clock is only used by the OHCI part of the controller, not the ++ * EHCI part. ++ */ ++static struct clk ohci_gclk = { ++ .name = "ohci_clk", ++ .parent = &gclk0, ++ .mode = parent_clk_mode, ++ .get_rate = parent_clk_get_rate, ++}; ++ ++static struct resource usbh_ohci_resource[] __initdata = { ++ { ++ .start = 0xff400000, ++ .end = 0xff400400, ++ .flags = IORESOURCE_MEM, ++ }, ++ IRQ(7), ++}; ++ ++static struct resource usbh_ehci_resource[] __initdata = { ++ { ++ .start = 0xff300000, ++ .end = 0xff300400, ++ .flags = IORESOURCE_MEM, ++ }, ++ IRQ(7), ++}; ++ ++static void __init usbh_setup_pins(void) ++{ ++ static bool already_done __initdata; ++ ++ if (!already_done) { ++ already_done = true; ++ /* OC_EN_N | OC_FLAG_N */ ++ select_peripheral(PA, (1 << 18) | (1 << 19), PERIPH_D, 0); ++ } ++} ++ ++struct platform_device *__init at32_add_device_ohci(unsigned int id) ++{ ++ struct platform_device *pdev; ++ ++ if (id != 0) ++ return NULL; ++ ++ pdev = platform_device_alloc("ohci", id); ++ if (!pdev) ++ goto error; ++ ++ if (platform_device_add_resources(pdev, usbh_ohci_resource, ++ ARRAY_SIZE(usbh_ohci_resource))) ++ goto error; ++ ++ pdev->dev.dma_mask = &usbh_dma_mask; ++ pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; ++ ++ clk_set_parent(&pll2, &osc2); ++ if (clk_round_rate(&pll2, 48000000) != 48000000) { ++ pr_debug("USBH OHCI: Cannot generate 48 MHz clock\n"); ++ goto error; ++ } ++ clk_set_rate(&pll2, 48000000); ++ ++ clk_set_parent(&gclk0, &pll2); ++ clk_set_rate(&gclk0, 48000000); ++ ++ ohci_utmi_clk.dev = &pdev->dev; ++ ohci_hclk.dev = &pdev->dev; ++ ohci_gclk.dev = &pdev->dev; ++ ++ usbh_setup_pins(); ++ ++ platform_device_add(pdev); ++ return pdev; ++ ++error: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++struct platform_device *__init at32_add_device_ehci(unsigned int id) ++{ ++ struct platform_device *pdev; ++ ++ if (id != 0) ++ return NULL; ++ ++ pdev = platform_device_alloc("ehci", id); ++ if (!pdev) ++ goto error; ++ ++ if (platform_device_add_resources(pdev, usbh_ehci_resource, ++ ARRAY_SIZE(usbh_ehci_resource))) ++ goto error; ++ ++ pdev->dev.dma_mask = &usbh_dma_mask; ++ pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; ++ ++ ehci_utmi_clk.dev = &pdev->dev; ++ ehci_hclk.dev = &pdev->dev; ++ ++ usbh_setup_pins(); ++ ++ platform_device_add(pdev); ++ return pdev; ++ ++error: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* ------------------------------------------------------------------- ++ * NAND Flash / SmartMedia ++ * ------------------------------------------------------------------- */ ++static struct resource smc_cs3_resource[] __initdata = { ++ { ++ .start = 0x24000000, ++ .end = 0x27ffffff, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = 0xffe04c00, ++ .end = 0xffe04fff, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct platform_device *__init ++at32_add_device_nand(unsigned int id, struct atmel_nand_data *data) ++{ ++ struct platform_device *pdev; ++ ++ if (id != 0 || !data) ++ return NULL; ++ ++ pdev = platform_device_alloc("atmel_nand", id); ++ if (!pdev) ++ goto error; ++ ++ if (platform_device_add_resources(pdev, smc_cs3_resource, ++ ARRAY_SIZE(smc_cs3_resource))) ++ goto error; ++ ++ if (platform_device_add_data(pdev, data, ++ sizeof(struct atmel_nand_data))) ++ goto error; ++ ++ hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_NAND_ENABLE); ++ ++ /* NANDOE | NANDWE */ ++ select_peripheral(PF, (1 << 0) | (1 << 1), PERIPH_A, 0); ++ ++ if (gpio_is_valid(data->enable_pin)) ++ at32_select_gpio(data->enable_pin, ++ AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); ++ if (gpio_is_valid(data->det_pin)) ++ at32_select_gpio(data->det_pin, 0); ++ if (gpio_is_valid(data->rdy_pin)) ++ at32_select_gpio(data->rdy_pin, 0); ++ ++ platform_device_add(pdev); ++ return pdev; ++ ++error: ++ platform_device_put(pdev); ++ return NULL; ++} ++ ++/* ------------------------------------------------------------------- ++ * Clock list ++ * ------------------------------------------------------------------- */ ++static __initdata struct clk *init_clocks[] = { ++ &rcosc, ++ &osc0, ++ &osc1, ++ &osc2, ++ &osc32, ++ &pll0, ++ &pll1, ++ &pll2, ++ &cpu_clk, ++ &hsb_clk, ++ &pba_clk, ++ &pbb_clk, ++ &pbc_clk, ++ &gclk0, ++ &gclk1, ++ &gclk2, ++ &gclk3, ++ &gclk4, ++ &gclk5, ++ &at32_intc0_pclk, ++ &pm_pclk, ++ &sdc_pclk, ++ &ast0_pclk, ++ &ast1_pclk, ++ &wdt_pclk, ++ &gpio_pclk, ++ &pdca_hclk, ++ &pdca_pclk, ++ &ebi_hclk, ++ &hramc_clk, ++ &smc_pclk, ++ &sdramc_clk, ++ &dw_dmac0_hclk, ++ &atmel_usart0_usart, ++ &atmel_usart1_usart, ++ &atmel_usart2_usart, ++ &atmel_usart3_usart, ++ &atmel_usart4_usart, ++ &atmel_usart5_usart, ++ &atmel_spi_clk[0], ++ &atmel_spi_clk[1], ++ &atmel_spi_clk[2], ++ &atmel_spi_clk[3], ++ &macb0_hclk, ++ &macb0_pclk, ++ &atmel_mci0_pclk, ++ &atmel_lcdfb0_hck1, ++ &atmel_lcdfb0_pixclk, ++ &atmel_mpopfb0_hclk, ++ &atmel_mpopfb0_pclk, ++ &usbh_utmi_clk, ++ &usbh_hclk, ++ &ohci_utmi_clk, ++ &ohci_hclk, ++ &ohci_gclk, ++ &ehci_utmi_clk, ++ &ehci_hclk, ++}; ++ ++static void pll_init_parent(struct clk *pll) ++{ ++ u32 ctrl; ++ ++ ctrl = pm_readl(PLL[pll->index]); ++ switch (PM_BFEXT(PLLx_PLLOSC, ctrl)) { ++ case 0: ++ pll->parent = &osc0; ++ break; ++ case 1: ++ pll->parent = &osc1; ++ break; ++ case 2: ++ pll->parent = &osc2; ++ break; ++ } ++} ++ ++static void ap7200_power_off(void) ++{ ++ /* ++ * Clear all wakeup events so that we don't wake up ++ * immediately after we shut down. ++ */ ++ sdc_writel(ECR, ~0UL); ++ sdc_readl(STATUS); ++ asm volatile("sleep %0; sub pc, -2" ++ :: "i"(CPU_SLEEP_SHUTDOWN) ++ : "memory"); ++} ++ ++void __init setup_platform(void) ++{ ++ unsigned int i; ++ u32 cpu_mask; ++ u32 hsb_mask; ++ u32 pba_mask; ++ u32 pbb_mask; ++ ++ switch (PM_BFEXT(MCCTRL_MCSEL, pm_readl(MCCTRL))) { ++ case 0: ++ main_clock = &rcosc; ++ break; ++ case 1: ++ main_clock = &osc0; ++ break; ++ case 2: ++ main_clock = &pll0; ++ break; ++ } ++ ++ cpu_clk.parent = main_clock; ++ ++ pll_init_parent(&pll0); ++ pll_init_parent(&pll1); ++ pll_init_parent(&pll2); ++ ++ genclk_init_parent(&gclk0); ++ genclk_init_parent(&gclk1); ++ genclk_init_parent(&gclk2); ++ genclk_init_parent(&gclk3); ++ genclk_init_parent(&gclk4); ++ genclk_init_parent(&gclk5); ++ genclk_init_parent(&atmel_lcdfb0_pixclk); ++ ++ /* ++ * Turn on all clocks that have at least one user already, and ++ * turn off everything else. We only do this for module ++ * clocks, and even though it isn't particularly pretty to ++ * check the address of the mode function, it should do the ++ * trick... ++ */ ++ cpu_mask = 0x10003; ++ hsb_mask = pba_mask = pbb_mask = 0; ++ ++ /* Make sure we don't disable the power manager or the SDRAM */ ++ pm_pclk.users = 1; ++ pm_pclk.parent->users = 1; ++ ebi_hclk.users = 1; ++ ++ /* Can't recursively call clk_enable() from any of the clk ops */ ++ sdc_pclk.users = 1; ++ ++ for (i = 0; i < ARRAY_SIZE(init_clocks); i++) { ++ struct clk *clk = init_clocks[i]; ++ ++ /* first, register clock */ ++ at32_clk_register(clk); ++ ++ if (clk->users == 0) ++ continue; ++ ++ if (clk->mode == &cpu_clk_mode) ++ cpu_mask |= 1 << clk->index; ++ else if (clk->mode == &hsb_clk_mode) ++ hsb_mask |= 1 << clk->index; ++ else if (clk->mode == &pba_clk_mode) ++ pba_mask |= 1 << clk->index; ++ else if (clk->mode == &pbb_clk_mode) ++ pbb_mask |= 1 << clk->index; ++ } ++ ++ pm_writel(CPUMASK, cpu_mask); ++ pm_writel(HSBMASK, hsb_mask); ++ pm_writel(PBAMASK, pba_mask); ++ pm_writel(PBBMASK, pbb_mask); ++ ++ at32_gpio_init(&gpio_device); ++ ++ /* Enter shutdown mode when powering off. This happens very ++ * early, so board code may still override this. */ ++ pm_power_off = ap7200_power_off; ++ ++ /* Enable WAKE pin */ ++ sdc_writel(CTRL, SDC_BIT(CTRL_PIN_EN) | SDC_BIT(CTRL_AST_EN) ++ | SDC_BIT(CTRL_OCD_EN) | SDC_BIT(CTRL_JTAG_EN) ++ | SDC_BF(CTRL_KEY, 0x55)); ++ sdc_writel(CTRL, SDC_BIT(CTRL_PIN_EN) | SDC_BIT(CTRL_AST_EN) ++ | SDC_BIT(CTRL_OCD_EN) | SDC_BIT(CTRL_JTAG_EN) ++ | SDC_BF(CTRL_KEY, 0xaa)); ++} ++ ++void __init platform_time_init(void) ++{ ++ ast_time_init(&ast1_device, AST_CLOCK_PB); ++} ++ ++unsigned long at32_get_reset_cause(void) ++{ ++ return pm_readl(RCAUSE); ++} ++ ++struct gen_pool *sram_pool; ++ ++static int __init sram_init(void) ++{ ++ struct gen_pool *pool; ++ ++ /* 1KiB granularity */ ++ pool = gen_pool_create(10, -1); ++ if (!pool) ++ goto fail; ++ ++ if (gen_pool_add(pool, 0x08000000, 0x10000, -1)) ++ goto err_pool_add; ++ ++ sram_pool = pool; ++ return 0; ++ ++err_pool_add: ++ gen_pool_destroy(pool); ++fail: ++ pr_err("Failed to create SRAM pool\n"); ++ return -ENOMEM; ++} ++core_initcall(sram_init); +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/extint.c linux-2.6.28.2/arch/avr32/mach-at32ap/extint.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/extint.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/extint.c 2009-01-29 08:52:49.000000000 +0100 +@@ -17,6 +17,8 @@ + + #include <asm/io.h> + ++#include <mach/cpu.h> ++ + /* EIC register offsets */ + #define EIC_IER 0x0000 + #define EIC_IDR 0x0004 +@@ -26,24 +28,18 @@ + #define EIC_MODE 0x0014 + #define EIC_EDGE 0x0018 + #define EIC_LEVEL 0x001c +-#define EIC_NMIC 0x0024 + +-/* Bitfields in NMIC */ +-#define EIC_NMIC_ENABLE (1 << 0) ++/* This is only valid on v1 (AP700x) */ ++#define EIC_NMIC 0x0024 ++# define EIC_NMIC_ENABLE (1 << 0) + +-/* Bit manipulation macros */ +-#define EIC_BIT(name) \ +- (1 << EIC_##name##_OFFSET) +-#define EIC_BF(name,value) \ +- (((value) & ((1 << EIC_##name##_SIZE) - 1)) \ +- << EIC_##name##_OFFSET) +-#define EIC_BFEXT(name,value) \ +- (((value) >> EIC_##name##_OFFSET) \ +- & ((1 << EIC_##name##_SIZE) - 1)) +-#define EIC_BFINS(name,value,old) \ +- (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \ +- << EIC_##name##_OFFSET)) \ +- | EIC_BF(name,value)) ++/* These are only valid on v3 (AP720x) */ ++#define EIC_FILTER 0x0020 ++#define EIC_TEST 0x0024 ++#define EIC_ASYNC 0x0028 ++#define EIC_EN 0x0030 ++#define EIC_DIS 0x0034 ++#define EIC_CTRL 0x0038 + + /* Register access macros */ + #define eic_readl(port,reg) \ +@@ -60,36 +56,68 @@ + static struct eic *nmi_eic; + static bool nmi_enabled; + ++static inline int eic_version(struct eic *eic) ++{ ++ if (cpu_is_at32ap7000()) ++ return 1; ++ if (cpu_is_at32ap7200()) ++ return 3; ++ ++ BUG(); ++} ++ ++static inline int eic_irq_bitmask(struct eic *eic, unsigned int irq) ++{ ++ irq -= eic->first_irq; ++ ++ if (eic_version(eic) > 2) ++ irq++; ++ return 1 << irq; ++} ++ + static void eic_ack_irq(unsigned int irq) + { + struct eic *eic = get_irq_chip_data(irq); +- eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); ++ eic_writel(eic, ICR, eic_irq_bitmask(eic, irq)); + } + + static void eic_mask_irq(unsigned int irq) + { + struct eic *eic = get_irq_chip_data(irq); +- eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); ++ eic_writel(eic, IDR, eic_irq_bitmask(eic, irq)); + } + + static void eic_mask_ack_irq(unsigned int irq) + { + struct eic *eic = get_irq_chip_data(irq); +- eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); +- eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); ++ eic_writel(eic, ICR, eic_irq_bitmask(eic, irq)); ++ eic_writel(eic, IDR, eic_irq_bitmask(eic, irq)); + } + + static void eic_unmask_irq(unsigned int irq) + { + struct eic *eic = get_irq_chip_data(irq); +- eic_writel(eic, IER, 1 << (irq - eic->first_irq)); ++ eic_writel(eic, IER, eic_irq_bitmask(eic, irq)); ++} ++ ++/* The following two hooks are only used on v2+ controllers */ ++static void eic_enable_irq(unsigned int irq) ++{ ++ struct eic *eic = get_irq_chip_data(irq); ++ eic_writel(eic, EN, eic_irq_bitmask(eic, irq)); ++} ++ ++static void eic_disable_irq(unsigned int irq) ++{ ++ struct eic *eic = get_irq_chip_data(irq); ++ eic_writel(eic, DIS, eic_irq_bitmask(eic, irq)); + } + + static int eic_set_irq_type(unsigned int irq, unsigned int flow_type) + { + struct eic *eic = get_irq_chip_data(irq); + struct irq_desc *desc; +- unsigned int i = irq - eic->first_irq; ++ unsigned int irq_bitmask = eic_irq_bitmask(eic, irq); + u32 mode, edge, level; + int ret = 0; + +@@ -105,20 +133,20 @@ + + switch (flow_type) { + case IRQ_TYPE_LEVEL_LOW: +- mode |= 1 << i; +- level &= ~(1 << i); ++ mode |= irq_bitmask; ++ level &= ~irq_bitmask; + break; + case IRQ_TYPE_LEVEL_HIGH: +- mode |= 1 << i; +- level |= 1 << i; ++ mode |= irq_bitmask; ++ level |= irq_bitmask; + break; + case IRQ_TYPE_EDGE_RISING: +- mode &= ~(1 << i); +- edge |= 1 << i; ++ mode &= ~irq_bitmask; ++ edge |= irq_bitmask; + break; + case IRQ_TYPE_EDGE_FALLING: +- mode &= ~(1 << i); +- edge &= ~(1 << i); ++ mode &= ~irq_bitmask; ++ edge &= ~irq_bitmask; + break; + default: + ret = -EINVAL; +@@ -160,6 +188,11 @@ + status = eic_readl(eic, ISR); + pending = status & eic_readl(eic, IMR); + ++ if (eic_version(eic) > 1) { ++ status >>= 1; ++ pending >>= 1; ++ } ++ + while (pending) { + i = fls(pending) - 1; + pending &= ~(1 << i); +@@ -172,16 +205,34 @@ + { + nmi_enabled = true; + +- if (nmi_eic) +- eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); ++ if (nmi_eic) { ++ if (eic_version(nmi_eic) > 2) { ++ eic_writel(nmi_eic, EN, 1 << 0); ++ eic_writel(nmi_eic, IER, 1 << 0); ++ } else if (eic_version(nmi_eic) > 1) { ++ eic_writel(nmi_eic, EN, 1 << 8); ++ eic_writel(nmi_eic, IER, 1 << 8); ++ } else { ++ eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); ++ } ++ } + + return 0; + } + + void nmi_disable(void) + { +- if (nmi_eic) +- eic_writel(nmi_eic, NMIC, 0); ++ if (nmi_eic) { ++ if (eic_version(nmi_eic) > 2) { ++ eic_writel(nmi_eic, IDR, 1 << 0); ++ eic_writel(nmi_eic, DIS, 1 << 0); ++ } else if (eic_version(nmi_eic) > 1) { ++ eic_writel(nmi_eic, IDR, 1 << 8); ++ eic_writel(nmi_eic, DIS, 1 << 8); ++ } else { ++ eic_writel(nmi_eic, NMIC, 0); ++ } ++ } + + nmi_enabled = false; + } +@@ -230,6 +281,15 @@ + eic_writel(eic, EDGE, 0UL); + eic_writel(eic, LEVEL, 0UL); + ++ /* ++ * v2+ controllers have an extra enable/disable/mask set of ++ * registers. ++ */ ++ if (eic_version(eic) >= 2) { ++ eic_chip.enable = eic_enable_irq; ++ eic_chip.disable = eic_disable_irq; ++ } ++ + eic->chip = &eic_chip; + + for (i = 0; i < nr_of_irqs; i++) { +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/gpio-v2.c linux-2.6.28.2/arch/avr32/mach-at32ap/gpio-v2.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/gpio-v2.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/gpio-v2.c 2009-01-29 08:52:49.000000000 +0100 +@@ -0,0 +1,534 @@ ++/* ++ * Atmel GPIO Port Multiplexer support ++ * ++ * Copyright (C) 2004-2008 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 <linux/clk.h> ++#include <linux/debugfs.h> ++#include <linux/fs.h> ++#include <linux/gpio.h> ++#include <linux/io.h> ++#include <linux/irq.h> ++#include <linux/platform_device.h> ++ ++#include <mach/portmux.h> ++#include <mach/chip.h> ++ ++#include "gpio-v2.h" ++ ++/* ++ * One chip corresponds with one bank of I/O registers. They're really ++ * all on the same controller. ++ */ ++struct atmel_gpio_chip { ++ void __iomem *regs; ++ u32 pinmux_mask; ++ struct gpio_chip chip; ++ char name[8]; ++ unsigned int bank; ++ int irq; ++}; ++ ++/* ...which means we only have one clock and one platform device */ ++static struct clk *gpio_clk; ++static struct atmel_gpio_chip gpio_dev[NR_GPIO_BANKS]; ++ ++/* Pin multiplexing API */ ++static DEFINE_SPINLOCK(gpio_lock); ++ ++static struct atmel_gpio_chip *to_atmel_gpio_chip(struct gpio_chip *chip) ++{ ++ return container_of(chip, struct atmel_gpio_chip, chip); ++} ++ ++static struct atmel_gpio_chip *pin_to_chip(unsigned int gpio) ++{ ++ struct atmel_gpio_chip *chip; ++ unsigned int index; ++ ++ index = gpio >> 5; ++ if (index >= NR_GPIO_BANKS) ++ return NULL; ++ chip = &gpio_dev[index]; ++ if (!chip->regs) ++ return NULL; ++ ++ return chip; ++} ++ ++/* Pin multiplexing API */ ++ ++void __init at32_select_periph(unsigned int port, u32 pin_mask, ++ unsigned int periph, unsigned long flags) ++{ ++ struct atmel_gpio_chip *chip; ++ ++ chip = pin_to_chip(port); ++ if (unlikely(!chip)) { ++ printk("GPIO: invalid port %u\n", port); ++ goto fail; ++ } ++ ++ /* Test if any of the requested pins is already muxed */ ++ spin_lock(&gpio_lock); ++ if (unlikely(gpiochip_is_requested(&chip->chip, port) ++ || unlikely(pin_mask & chip->pinmux_mask))) { ++ printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n", ++ chip->name, pin_mask, chip->pinmux_mask & pin_mask); ++ spin_unlock(&gpio_lock); ++ goto fail; ++ } ++ ++ switch (periph) { ++ case GPIO_PERIPH_A: ++ gpio_writel(chip, PMR0C, pin_mask); ++ gpio_writel(chip, PMR1C, pin_mask); ++ break; ++ case GPIO_PERIPH_B: ++ gpio_writel(chip, PMR0S, pin_mask); ++ gpio_writel(chip, PMR1C, pin_mask); ++ break; ++ case GPIO_PERIPH_C: ++ gpio_writel(chip, PMR0C, pin_mask); ++ gpio_writel(chip, PMR1S, pin_mask); ++ break; ++ case GPIO_PERIPH_D: ++ gpio_writel(chip, PMR0S, pin_mask); ++ gpio_writel(chip, PMR1S, pin_mask); ++ break; ++ default: ++ printk("%s: unknown function for pin mask %u\n", ++ chip->name, pin_mask); ++ goto fail; ++ } ++ ++ gpio_writel(chip, PUERS, pin_mask); ++ ++ gpio_writel(chip, GPERC, pin_mask); ++ if (!(flags & AT32_GPIOF_PULLUP)) ++ gpio_writel(chip, PUERC, pin_mask); ++ ++ spin_unlock(&gpio_lock); ++ ++ return; ++ ++fail: ++ dump_stack(); ++} ++ ++void __init at32_select_gpio(unsigned int pin, unsigned long flags) ++{ ++ struct atmel_gpio_chip *chip; ++ unsigned int pin_index = pin & 0x1f; ++ u32 mask = 1 << pin_index; ++ ++ chip = pin_to_chip(pin); ++ if (unlikely(!chip)) { ++ printk("GPIO: invalid pin %u\n", pin); ++ goto fail; ++ } ++ ++ if (unlikely(test_and_set_bit(pin_index, &chip->pinmux_mask))) { ++ printk("%s: pin %u is busy\n", chip->name, pin_index); ++ goto fail; ++ } ++ ++ if (flags & AT32_GPIOF_PULLUP) ++ gpio_writel(chip, PUERS, mask); ++ else ++ gpio_writel(chip, PUERC, mask); ++ if (flags & AT32_GPIOF_MULTIDRV) ++ gpio_writel(chip, ODMERS, mask); ++ else ++ gpio_writel(chip, ODMERC, mask); ++ if (flags & AT32_GPIOF_DEGLITCH) ++ gpio_writel(chip, GFERS, mask); ++ else ++ gpio_writel(chip, GFERC, mask); ++ ++ if (flags & AT32_GPIOF_OUTPUT) { ++ if (flags & AT32_GPIOF_HIGH) ++ gpio_writel(chip, OVRS, mask); ++ else ++ gpio_writel(chip, OVRC, mask); ++ gpio_writel(chip, ODERS, mask); ++ } else { ++ gpio_writel(chip, ODERC, mask); ++ } ++ ++ gpio_writel(chip, GPERS, mask); ++ ++ return; ++ ++fail: ++ dump_stack(); ++} ++ ++/* Reserve a pin, preventing anyone else from changing its configuration. */ ++void __init at32_reserve_pin(unsigned int port, u32 pin_mask) ++{ ++ struct atmel_gpio_chip *chip; ++ ++ chip = pin_to_chip(port); ++ if (unlikely(!chip)) { ++ printk("GPIO: invalid port %u\n", port); ++ goto fail; ++ } ++ ++ /* Test if any of the requested pins is already muxed */ ++ spin_lock(&gpio_lock); ++ if (unlikely(pin_mask & chip->pinmux_mask)) { ++ printk(KERN_WARNING "%s: pin(s) busy (req. 0x%x, busy 0x%x)\n", ++ chip->name, pin_mask, chip->pinmux_mask & pin_mask); ++ spin_unlock(&gpio_lock); ++ goto fail; ++ } ++ ++ /* Reserve pins */ ++ chip->pinmux_mask |= pin_mask; ++ spin_unlock(&gpio_lock); ++ return; ++ ++fail: ++ dump_stack(); ++} ++ ++/*--------------------------------------------------------------------------*/ ++ ++/* GPIO API */ ++ ++static int get_pin_state(struct gpio_chip *chip, unsigned int offset) ++{ ++ struct atmel_gpio_chip *gpio = to_atmel_gpio_chip(chip); ++ ++ return (gpio_readl(gpio, PVR) >> offset) & 1; ++} ++ ++static void set_pin_state(struct gpio_chip *chip, unsigned int offset, int high) ++{ ++ struct atmel_gpio_chip *gpio = to_atmel_gpio_chip(chip); ++ u32 mask = 1 << offset; ++ ++ if (high) ++ gpio_writel(gpio, OVRS, mask); ++ else ++ gpio_writel(gpio, OVRC, mask); ++} ++ ++static int direction_input(struct gpio_chip *chip, unsigned int offset) ++{ ++ struct atmel_gpio_chip *gpio = to_atmel_gpio_chip(chip); ++ u32 mask = 1 << offset; ++ ++ if (!(gpio_readl(gpio, GPER) & mask)) ++ return -EINVAL; ++ ++ gpio_writel(gpio, ODERC, mask); ++ return 0; ++} ++ ++static int direction_output(struct gpio_chip *chip, unsigned int offset, ++ int high) ++{ ++ struct atmel_gpio_chip *gpio = to_atmel_gpio_chip(chip); ++ u32 mask = 1 << offset; ++ ++ if (!(gpio_readl(gpio, GPER) & mask)) ++ return -EINVAL; ++ ++ set_pin_state(chip, offset, high); ++ gpio_writel(gpio, ODERS, mask); ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++ ++/* GPIO IRQ support */ ++ ++static void gpio_irq_mask(unsigned irq) ++{ ++ unsigned int pin = irq_to_gpio(irq); ++ struct atmel_gpio_chip *chip = &gpio_dev[pin >> 5]; ++ ++ gpio_writel(chip, IERC, 1 << (pin & 0x1f)); ++} ++ ++static void gpio_irq_unmask(unsigned irq) ++{ ++ unsigned int pin = irq_to_gpio(irq); ++ struct atmel_gpio_chip *chip = &gpio_dev[pin >> 5]; ++ ++ gpio_writel(chip, IERS, 1 << (pin & 0x1f)); ++} ++ ++static int gpio_irq_type(unsigned irq, unsigned type) ++{ ++ unsigned int pin = irq_to_gpio(irq); ++ struct atmel_gpio_chip *chip = &gpio_dev[pin >> 5]; ++ u32 mask = 1 << (pin & 0x1f); ++ ++ switch (type) { ++ case IRQ_TYPE_EDGE_FALLING: ++ gpio_writel(chip, IMR0C, mask); ++ gpio_writel(chip, IMR1S, mask); ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ gpio_writel(chip, IMR0S, mask); ++ gpio_writel(chip, IMR1C, mask); ++ break; ++ case IRQ_TYPE_NONE: ++ /* fall through */ ++ case IRQ_TYPE_EDGE_BOTH: ++ gpio_writel(chip, IMR0C, mask); ++ gpio_writel(chip, IMR1C, mask); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static struct irq_chip gpio_irqchip = { ++ .name = "gpio", ++ .mask = gpio_irq_mask, ++ .unmask = gpio_irq_unmask, ++ .set_type = gpio_irq_type, ++}; ++ ++static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) ++{ ++ struct atmel_gpio_chip *chip = get_irq_chip_data(irq); ++ unsigned int gpio_irq; ++ ++ gpio_irq = (unsigned int) get_irq_data(irq); ++ for (;;) { ++ u32 ifr; ++ struct irq_desc *d; ++ ++ /* ack pending GPIO interrupts */ ++ ifr = gpio_readl(chip, IFR); ++ if (!ifr) ++ break; ++ do { ++ int pin; ++ ++ pin = ffs(ifr) - 1; ++ ifr &= ~(1 << pin); ++ gpio_writel(chip, IFRC, (1 << pin)); ++ ++ pin += gpio_irq; ++ d = &irq_desc[pin]; ++ ++ d->handle_irq(pin, d); ++ } while (ifr); ++ } ++} ++ ++static void __init ++gpio_irq_setup(struct atmel_gpio_chip *chip, int irq, int gpio_irq) ++{ ++ unsigned i; ++ ++ set_irq_chip_data(irq, chip); ++ set_irq_data(irq, (void *) gpio_irq); ++ ++ for (i = 0; i < 32; i++, gpio_irq++) { ++ set_irq_chip_data(gpio_irq, chip); ++ set_irq_chip_and_handler(gpio_irq, &gpio_irqchip, ++ handle_simple_irq); ++ } ++ ++ set_irq_chained_handler(irq, gpio_irq_handler); ++} ++ ++/*--------------------------------------------------------------------------*/ ++ ++#ifdef CONFIG_DEBUG_FS ++ ++#include <linux/seq_file.h> ++ ++/* ++ * This shows more info than the generic gpio dump code: ++ * pullups, deglitching, open drain drive. ++ */ ++static void gpio_bank_show(struct seq_file *s, struct gpio_chip *chip) ++{ ++ struct atmel_gpio_chip *gpio = to_atmel_gpio_chip(chip); ++ u32 oder, ovr, puer, pder, gfer, odmer, ier, imr0, imr1; ++ unsigned int i; ++ u32 mask; ++ ++ oder = gpio_readl(gpio, ODER); ++ ovr = gpio_readl(gpio, OVR); ++ puer = gpio_readl(gpio, PUER); ++ pder = gpio_readl(gpio, PDER); ++ gfer = gpio_readl(gpio, GFER); ++ odmer = gpio_readl(gpio, ODMER); ++ ier = gpio_readl(gpio, IER); ++ imr0 = gpio_readl(gpio, IMR0); ++ imr1 = gpio_readl(gpio, IMR1); ++ ++ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) { ++ const char *label; ++ ++ label = gpiochip_is_requested(chip, i); ++ if (!label) ++ continue; ++ ++ seq_printf(s, " gpio-%-3d ", chip->base + i); ++ gpio_decode_pin(s, gpio->bank, i); ++ seq_printf(s, " (%-12s) %s %s", label, ++ (oder & mask) ? "out" : "in", ++ (ovr & mask) ? "hi" : "lo"); ++ if ((puer & mask) && !(pder & mask)) ++ seq_printf(s, " pull-up"); ++ else if (!(puer & mask) && (pder & mask)) ++ seq_printf(s, " pull-down"); ++ else if ((puer & mask) && (pder & mask)) ++ seq_printf(s, " buskeeper"); ++ if (gfer & mask) ++ seq_printf(s, " deglitch"); ++ if (odmer & mask) ++ seq_printf(s, " open-drain"); ++ if ((gpio->irq >= 0) && (ier & mask)) { ++ seq_printf(s, " irq-%d edge-", ++ gpio_to_irq(chip->base + i)); ++ if (!(imr0 & mask) && !(imr1 & mask)) ++ seq_printf(s, "both"); ++ else if ((imr0 & mask) && !(imr1 & mask)) ++ seq_printf(s, "rising"); ++ else if (!(imr0 & mask) && (imr1 & mask)) ++ seq_printf(s, "falling"); ++ else ++ seq_printf(s, "INVALID"); ++ } ++ seq_printf(s, "\n"); ++ } ++} ++ ++#else ++#define gpio_bank_show NULL ++#endif ++ ++static int __init gpio_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ struct resource *irqs; ++ int irq = -1; ++ unsigned int i; ++ ++ BUG_ON(pdev->id >= 1); ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_err(&pdev->dev, "no mmio resource defined\n"); ++ return -ENXIO; ++ } ++ irqs = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (irqs) ++ irq = irqs->start; ++ ++ for (i = 0; i < NR_GPIO_BANKS; i++) { ++ unsigned int gpio_irq_base; ++ struct atmel_gpio_chip *chip; ++ ++ chip = &gpio_dev[i]; ++ BUG_ON(!chip->regs); ++ ++ chip->chip.label = chip->name; ++ chip->chip.base = i * 32; ++ chip->chip.ngpio = 32; ++ ++ chip->chip.direction_input = direction_input; ++ chip->chip.get = get_pin_state; ++ chip->chip.direction_output = direction_output; ++ chip->chip.set = set_pin_state; ++ chip->chip.dbg_show = gpio_bank_show; ++ ++ gpiochip_add(&chip->chip); ++ ++ gpio_irq_base = GPIO_IRQ_BASE + (i * 32); ++ if (irqs && irq <= irqs->end) { ++ gpio_irq_setup(chip, irq, gpio_irq_base); ++ chip->irq = irq; ++ irq++; ++ } else { ++ chip->irq = -1; ++ } ++ ++ platform_set_drvdata(pdev, chip); ++ ++ printk(KERN_DEBUG "%s: base 0x%p", chip->name, chip->regs); ++ if (chip->irq >= 0) ++ printk(" irq %d chains %d..%d", irq, ++ gpio_irq_base, gpio_irq_base + 31); ++ printk("\n"); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_driver = { ++ .probe = gpio_probe, ++ .driver = { ++ .name = "gpio", ++ }, ++}; ++ ++static int __init gpio_init(void) ++{ ++ return platform_driver_register(&gpio_driver); ++} ++postcore_initcall(gpio_init); ++ ++void __init at32_gpio_init(struct platform_device *pdev) ++{ ++ int i; ++ struct clk *clk; ++ struct resource *regs; ++ void __iomem *iomem_base; ++ struct atmel_gpio_chip *chip; ++ ++ if (pdev->id > 0) { ++ dev_err(&pdev->dev, "only one GPIO controller supported\n"); ++ return; ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_err(&pdev->dev, "no mmio resource defined\n"); ++ return; ++ } ++ ++ clk = clk_get(&pdev->dev, "pclk"); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "no mck clock defined\n"); ++ return; ++ } ++ clk_enable(clk); ++ ++ gpio_clk = clk; ++ ++ /* ++ * We may get called too early for ioremap() to work. But we ++ * know that the GPIO registers are permanently mapped 1:1 ++ */ ++ iomem_base = (void __iomem __force *)regs->start; ++ ++ for (i = 0; i < NR_GPIO_BANKS; i++) { ++ chip = &gpio_dev[i]; ++ snprintf(chip->name, sizeof(chip->name), "gpio%d", i); ++ chip->regs = iomem_base + (i * 0x200); ++ chip->bank = i; ++ ++ /* start with irqs disabled and acked */ ++ gpio_writel(chip, IERC, ~0UL); ++ gpio_writel(chip, IFRC, ~0UL); ++ } ++} +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/gpio-v2.h linux-2.6.28.2/arch/avr32/mach-at32ap/gpio-v2.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/gpio-v2.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/gpio-v2.h 2009-01-29 08:52:49.000000000 +0100 +@@ -0,0 +1,116 @@ ++/* ++ * Copyright (C) 2008 Atmel Corporation ++ * ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * 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 ++ */ ++#ifndef __GPIO_REGS_H__ ++#define __GPIO_REGS_H__ ++ ++/* Register offsets */ ++struct gpio_regs { ++ u32 GPER; ++ u32 GPERS; ++ u32 GPERC; ++ u32 GPERT; ++ u32 PMR0; ++ u32 PMR0S; ++ u32 PMR0C; ++ u32 PMR0T; ++ u32 PMR1; ++ u32 PMR1S; ++ u32 PMR1C; ++ u32 PMR1T; ++ u32 __reserved0[4]; ++ u32 ODER; ++ u32 ODERS; ++ u32 ODERC; ++ u32 ODERT; ++ u32 OVR; ++ u32 OVRS; ++ u32 OVRC; ++ u32 OVRT; ++ u32 PVR; ++ u32 __reserved_PVRS; ++ u32 __reserved_PVRC; ++ u32 __reserved_PVRT; ++ u32 PUER; ++ u32 PUERS; ++ u32 PUERC; ++ u32 PUERT; ++ u32 PDER; ++ u32 PDERS; ++ u32 PDERC; ++ u32 PDERT; ++ u32 IER; ++ u32 IERS; ++ u32 IERC; ++ u32 IERT; ++ u32 IMR0; ++ u32 IMR0S; ++ u32 IMR0C; ++ u32 IMR0T; ++ u32 IMR1; ++ u32 IMR1S; ++ u32 IMR1C; ++ u32 IMR1T; ++ u32 GFER; ++ u32 GFERS; ++ u32 GFERC; ++ u32 GFERT; ++ u32 IFR; ++ u32 __reserved_IFRS; ++ u32 IFRC; ++ u32 __reserved_IFRT; ++ u32 ODMER; ++ u32 ODMERS; ++ u32 ODMERC; ++ u32 ODMERT; ++ u32 __reserved1[4]; ++ u32 ODCR0; ++ u32 ODCR0S; ++ u32 ODCR0C; ++ u32 ODCR0T; ++ u32 ODCR1; ++ u32 ODCR1S; ++ u32 ODCR1C; ++ u32 ODCR1T; ++ u32 __reserved2[4]; ++ u32 OSRR0; ++ u32 OSRR0S; ++ u32 OSRR0C; ++ u32 OSRR0T; ++ u32 __reserved3[8]; ++ u32 STER; ++ u32 STERS; ++ u32 STERC; ++ u32 STERT; ++ u32 __reserved4[35]; ++ u32 VERSION; ++}; ++ ++/* Register access macros */ ++#define __gpio_regs(bank) ((struct gpio_regs __iomem *)(bank)->regs) ++#define gpio_readl(bank, reg) \ ++ __raw_readl(&__gpio_regs(bank)->reg) ++#define gpio_writel(bank, reg, value) \ ++ __raw_writel(value, &__gpio_regs(bank)->reg) ++ ++void at32_gpio_init(struct platform_device *pdev); ++ ++#endif /* __GPIO_REGS_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/hmatrix.c linux-2.6.28.2/arch/avr32/mach-at32ap/hmatrix.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/hmatrix.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/hmatrix.c 2009-01-29 08:52:49.000000000 +0100 +@@ -54,6 +54,81 @@ + } + + /** ++ * hmatrix_set_default_master - set default master on a given slave ++ * @slave: HSB slave interface ID ++ * @master: HSB master interface ID ++ */ ++void hmatrix_set_default_master(unsigned int slave, unsigned int master) ++{ ++ u32 value; ++ unsigned int reg; ++ ++ WARN_ON(slave > HMATRIX_MAX_SLAVE ++ || master > HMATRIX_MASTER_LAST); ++ ++ reg = HMATRIX_SCFG(slave); ++ ++ clk_enable(&at32_hmatrix_clk); ++ value = __hmatrix_read_reg(reg); ++ value &= ~(HMATRIX_SCFG_FIXED_DEFMSTR(HMATRIX_MAX_SLAVE) ++ | HMATRIX_SCFG_DEFMSTR_MASK); ++ ++ switch (master) { ++ case HMATRIX_MASTER_NONE: ++ value |= HMATRIX_SCFG_DEFMSTR_NONE; ++ break; ++ case HMATRIX_MASTER_LAST: ++ value |= HMATRIX_SCFG_DEFMSTR_LAST; ++ break; ++ default: ++ value |= HMATRIX_SCFG_DEFMSTR_FIXED; ++ value |= HMATRIX_SCFG_FIXED_DEFMSTR(master); ++ break; ++ } ++ ++ __hmatrix_write_reg(reg, value); ++ __hmatrix_read_reg(reg); ++ clk_disable(&at32_hmatrix_clk); ++} ++ ++/** ++ * hmatrix_set_priority - set the priority of a master on a given slave ++ * @slave: HSB slave interface ID ++ * @master: HSB master interface ID ++ * @priority: Priority of @master when competing for access to @slave. ++ * ++ * Note that this is currently broken -- we need some way to enable ++ * fixed-priority arbitration, and that happens to be broken on AP7000 ++ * rev C. ++ */ ++void hmatrix_set_priority(unsigned int slave, unsigned int master, ++ unsigned int priority) ++{ ++ u32 value; ++ unsigned int reg; ++ ++ WARN_ON(slave > HMATRIX_MAX_SLAVE ++ || master > HMATRIX_MAX_MASTER ++ || priority > HMATRIX_MAX_PRIO); ++ ++ clk_enable(&at32_hmatrix_clk); ++ if (master < 8) { ++ reg = HMATRIX_PRAS(slave); ++ value = __hmatrix_read_reg(reg); ++ value &= ~HMATRIX_PRAS_PRIO(master, HMATRIX_MAX_PRIO); ++ value |= HMATRIX_PRAS_PRIO(master, priority); ++ } else { ++ reg = HMATRIX_PRBS(slave); ++ value = __hmatrix_read_reg(reg); ++ value &= ~HMATRIX_PRBS_PRIO(master, HMATRIX_MAX_PRIO); ++ value |= HMATRIX_PRBS_PRIO(master, priority); ++ } ++ __hmatrix_write_reg(reg, value); ++ __hmatrix_read_reg(reg); ++ clk_disable(&at32_hmatrix_clk); ++} ++ ++/** + * hmatrix_sfr_set_bits - set bits in a slave's Special Function Register + * @slave_id: operate on the SFR belonging to this slave + * @mask: mask of bits to be set in the SFR +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/hsmc.c linux-2.6.28.2/arch/avr32/mach-at32ap/hsmc.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/hsmc.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/hsmc.c 2009-01-29 08:52:49.000000000 +0100 +@@ -229,10 +229,8 @@ + if (IS_ERR(pclk)) + return PTR_ERR(pclk); + mck = clk_get(&pdev->dev, "mck"); +- if (IS_ERR(mck)) { +- ret = PTR_ERR(mck); +- goto out_put_pclk; +- } ++ if (IS_ERR(mck)) ++ mck = pclk; + + ret = -ENOMEM; + hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL); +@@ -260,8 +258,8 @@ + clk_disable(pclk); + kfree(hsmc); + out_put_clocks: +- clk_put(mck); +-out_put_pclk: ++ if (mck != pclk) ++ clk_put(mck); + clk_put(pclk); + hsmc = NULL; + return ret; +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/at32ap700x.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/at32ap700x.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/at32ap700x.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/at32ap700x.h 2009-01-29 08:52:49.000000000 +0100 +@@ -211,4 +211,135 @@ + + #define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA) + ++/* Bitmask for all EBI data (D16..D31) pins on port E */ ++#define ATMEL_EBI_PE_DATA_ALL (0x0000FFFF) ++ ++/* LCDC on port C */ ++#define ATMEL_LCDC_PC_CC (1ULL << 19) ++#define ATMEL_LCDC_PC_HSYNC (1ULL << 20) ++#define ATMEL_LCDC_PC_PCLK (1ULL << 21) ++#define ATMEL_LCDC_PC_VSYNC (1ULL << 22) ++#define ATMEL_LCDC_PC_DVAL (1ULL << 23) ++#define ATMEL_LCDC_PC_MODE (1ULL << 24) ++#define ATMEL_LCDC_PC_PWR (1ULL << 25) ++#define ATMEL_LCDC_PC_DATA0 (1ULL << 26) ++#define ATMEL_LCDC_PC_DATA1 (1ULL << 27) ++#define ATMEL_LCDC_PC_DATA2 (1ULL << 28) ++#define ATMEL_LCDC_PC_DATA3 (1ULL << 29) ++#define ATMEL_LCDC_PC_DATA4 (1ULL << 30) ++#define ATMEL_LCDC_PC_DATA5 (1ULL << 31) ++ ++/* LCDC on port D */ ++#define ATMEL_LCDC_PD_DATA6 (1ULL << 0) ++#define ATMEL_LCDC_PD_DATA7 (1ULL << 1) ++#define ATMEL_LCDC_PD_DATA8 (1ULL << 2) ++#define ATMEL_LCDC_PD_DATA9 (1ULL << 3) ++#define ATMEL_LCDC_PD_DATA10 (1ULL << 4) ++#define ATMEL_LCDC_PD_DATA11 (1ULL << 5) ++#define ATMEL_LCDC_PD_DATA12 (1ULL << 6) ++#define ATMEL_LCDC_PD_DATA13 (1ULL << 7) ++#define ATMEL_LCDC_PD_DATA14 (1ULL << 8) ++#define ATMEL_LCDC_PD_DATA15 (1ULL << 9) ++#define ATMEL_LCDC_PD_DATA16 (1ULL << 10) ++#define ATMEL_LCDC_PD_DATA17 (1ULL << 11) ++#define ATMEL_LCDC_PD_DATA18 (1ULL << 12) ++#define ATMEL_LCDC_PD_DATA19 (1ULL << 13) ++#define ATMEL_LCDC_PD_DATA20 (1ULL << 14) ++#define ATMEL_LCDC_PD_DATA21 (1ULL << 15) ++#define ATMEL_LCDC_PD_DATA22 (1ULL << 16) ++#define ATMEL_LCDC_PD_DATA23 (1ULL << 17) ++ ++/* LCDC on port E */ ++#define ATMEL_LCDC_PE_CC (1ULL << (32 + 0)) ++#define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1)) ++#define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2)) ++#define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3)) ++#define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4)) ++#define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5)) ++#define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6)) ++#define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7)) ++#define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8)) ++#define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9)) ++#define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10)) ++#define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11)) ++#define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12)) ++#define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13)) ++#define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14)) ++#define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15)) ++#define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16)) ++#define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17)) ++#define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18)) ++ ++ ++#define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN) ++ ++ ++#define ATMEL_LCDC_PRI_24B_DATA ( \ ++ ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ ++ ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ ++ ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ ++ ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ ++ ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ ++ ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ ++ ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \ ++ ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ ++ ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \ ++ ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \ ++ ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \ ++ ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) ++ ++#define ATMEL_LCDC_ALT_24B_DATA ( \ ++ ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ ++ ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ ++ ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ ++ ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ ++ ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ ++ ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ ++ ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \ ++ ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ ++ ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \ ++ ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \ ++ ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \ ++ ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) ++ ++#define ATMEL_LCDC_PRI_15B_DATA ( \ ++ ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ ++ ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ ++ ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ ++ ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ ++ ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ ++ ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA16) | \ ++ ATMEL_LCDC(PD, DATA17) | ATMEL_LCDC(PD, DATA18) | \ ++ ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20)) ++ ++#define ATMEL_LCDC_ALT_15B_DATA ( \ ++ ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ ++ ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ ++ ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ ++ ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ ++ ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ ++ ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PE, DATA16) | \ ++ ATMEL_LCDC(PE, DATA17) | ATMEL_LCDC(PE, DATA18) | \ ++ ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20)) ++ ++#define ATMEL_LCDC_PRI_CONTROL ( \ ++ ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \ ++ ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR)) ++ ++#define ATMEL_LCDC_ALT_CONTROL ( \ ++ ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \ ++ ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR)) ++ ++#define ATMEL_LCDC_CONTROL ( \ ++ ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \ ++ ATMEL_LCDC(PC, PCLK)) ++ ++#define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA) ++ ++#define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA) ++ ++#define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA) ++ ++#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA) ++ + #endif /* __ASM_ARCH_AT32AP700X_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/at32ap720x.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/at32ap720x.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/at32ap720x.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/at32ap720x.h 2009-01-29 08:52:49.000000000 +0100 +@@ -0,0 +1,105 @@ ++/* ++ * Pin definitions for AT32AP7200 ++ * ++ * Copyright (C) 2007 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. ++ */ ++#ifndef __ASM_ARCH_AT32AP7200_H__ ++#define __ASM_ARCH_AT32AP7200_H__ ++ ++#define GPIO_PERIPH_A 0x00 ++#define GPIO_PERIPH_B 0x01 ++#define GPIO_PERIPH_C 0x02 ++#define GPIO_PERIPH_D 0x03 ++ ++#define NR_GPIO_BANKS 8 ++ ++/* ++ * Pin numbers identifying specific GPIO pins on the chip. They can ++ * also be converted to IRQ numbers by passing them through ++ * gpio_to_irq(). ++ */ ++#define GPIO_BASE (0) ++ ++#define GPIO_PA_BASE (GPIO_BASE + 0 * 32) ++#define GPIO_PB_BASE (GPIO_BASE + 1 * 32) ++#define GPIO_PC_BASE (GPIO_BASE + 2 * 32) ++#define GPIO_PD_BASE (GPIO_BASE + 3 * 32) ++#define GPIO_PE_BASE (GPIO_BASE + 4 * 32) ++#define GPIO_PF_BASE (GPIO_BASE + 5 * 32) ++#define GPIO_PX_BASE (GPIO_BASE + 6 * 32) ++ ++#define GPIO_PIN_PA(N) (GPIO_PA_BASE + (N)) ++#define GPIO_PIN_PB(N) (GPIO_PB_BASE + (N)) ++#define GPIO_PIN_PC(N) (GPIO_PC_BASE + (N)) ++#define GPIO_PIN_PD(N) (GPIO_PD_BASE + (N)) ++#define GPIO_PIN_PE(N) (GPIO_PE_BASE + (N)) ++#define GPIO_PIN_PF(N) (GPIO_PF_BASE + (N)) ++#define GPIO_PIN_PX(N) (GPIO_PX_BASE + (N)) ++ ++#define gpio_decode_pin(s, bank, offset) \ ++ do { \ ++ switch (bank) { \ ++ case 7: \ ++ offset += 32; \ ++ /* fall through */ \ ++ case 6: \ ++ seq_printf(s, "PX%-2u", offset); \ ++ break; \ ++ default: \ ++ seq_printf(s, "P%c%-2u", bank + 'A', offset); \ ++ break; \ ++ } \ ++ } while (0) ++ ++/* HSB master IDs */ ++#define HMATRIX_MASTER_CPU_ICACHE 0 ++#define HMATRIX_MASTER_CPU_DCACHE 1 ++#define HMATRIX_MASTER_PDCA 2 ++#define HMATRIX_MASTER_LCDC 4 ++#define HMATRIX_MASTER_MPOP_IBI 5 ++#define HMATRIX_MASTER_MPOP_OBI 6 ++#define HMATRIX_MASTER_MPOP_OM 7 ++#define HMATRIX_MASTER_DMACA_M0 8 ++#define HMATRIX_MASTER_DMACA_M1 9 ++#define HMATRIX_MASTER_USBB 10 ++#define HMATRIX_MASTER_USBH_EHCI 11 ++#define HMATRIX_MASTER_USBH_OHCI 12 ++#define HMATRIX_MASTER_MACB 13 ++ ++/* HSB slave IDs */ ++#define HMATRIX_SLAVE_BOOTROM 0 ++#define HMATRIX_SLAVE_PBA 1 ++#define HMATRIX_SLAVE_PBB 2 ++#define HMATRIX_SLAVE_PBC 3 ++#define HMATRIX_SLAVE_SRAM0 4 ++#define HMATRIX_SLAVE_SRAM1 5 ++#define HMATRIX_SLAVE_EBI 6 ++#define HMATRIX_SLAVE_LCDC 7 ++#define HMATRIX_SLAVE_MPOP 8 ++#define HMATRIX_SLAVE_DMACA 9 ++#define HMATRIX_SLAVE_USBB 10 ++#define HMATRIX_SLAVE_EHCI 11 ++#define HMATRIX_SLAVE_OHCI 12 ++ ++/* Bits in HMATRIX SFR6 (EBI) */ ++#define HMATRIX_EBI_SDRAM_ENABLE (1 << 1) ++#define HMATRIX_EBI_NAND_ENABLE (1 << 3) ++#define HMATRIX_EBI_CF0_ENABLE (1 << 4) ++#define HMATRIX_EBI_CF1_ENABLE (1 << 5) ++ ++/* ++ * Base addresses of controllers that may be accessed early by ++ * platform code. ++ */ ++#define GPIO_HW_BASE 0xffd02000 ++#define INTC_BASE 0xffd00000 ++#define PM_BASE 0xffd00400 ++#define SDC_BASE 0xffd00800 ++#define SDRAMC_BASE 0xffe04800 ++#define HMATRIX_BASE 0xffe05000 ++ ++#endif /* __ASM_ARCH_AT32AP7200_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/chip.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/chip.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/chip.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/chip.h 2009-01-29 08:52:49.000000000 +0100 +@@ -12,6 +12,8 @@ + + #if defined(CONFIG_CPU_AT32AP700X) + # include <mach/at32ap700x.h> ++#elif defined(CONFIG_CPU_AT32AP720X) ++# include <mach/at32ap720x.h> + #else + # error Unknown chip type selected + #endif +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/cpu.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/cpu.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/cpu.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/cpu.h 2009-01-29 08:52:49.000000000 +0100 +@@ -20,6 +20,19 @@ + # define cpu_is_at32ap7000() (0) + #endif + ++#ifdef CONFIG_CPU_AT32AP720X ++# define cpu_is_at32ap7200() (1) ++#else ++# define cpu_is_at32ap7200() (0) ++#endif ++ ++/* ++ * Unfortunately, only AP700x has a non-broken COUNT/COMPARE ++ * implementation. Other chips need to use different timers. The good ++ * news is that these timers are usually better anyway. ++ */ ++#define cpu_has_working_compare() (cpu_is_at32ap7000()) ++ + /* + * Since this is AVR32, we will never run on any AT91 CPU. But these + * definitions may reduce clutter in common drivers. +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/hmatrix.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/hmatrix.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/hmatrix.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/hmatrix.h 2009-01-29 08:52:49.000000000 +0100 +@@ -15,6 +15,9 @@ + void hmatrix_write_reg(unsigned long offset, u32 value); + u32 hmatrix_read_reg(unsigned long offset); + ++void hmatrix_set_default_master(unsigned int slave, unsigned int master); ++void hmatrix_set_priority(unsigned int slave, unsigned int master, ++ unsigned int priority); + void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask); + void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask); + +@@ -33,6 +36,7 @@ + # define HMATRIX_SCFG_DEFMSTR_NONE ( 0 << 16) /* No default master */ + # define HMATRIX_SCFG_DEFMSTR_LAST ( 1 << 16) /* Last def master */ + # define HMATRIX_SCFG_DEFMSTR_FIXED ( 2 << 16) /* Fixed def master */ ++# define HMATRIX_SCFG_DEFMSTR_MASK ( 3 << 16) + # define HMATRIX_SCFG_FIXED_DEFMSTR(m) ((m) << 18) /* Fixed master ID */ + # define HMATRIX_SCFG_ARBT_ROUND_ROBIN ( 0 << 24) /* RR arbitration */ + # define HMATRIX_SCFG_ARBT_FIXED_PRIO ( 1 << 24) /* Fixed priority */ +@@ -52,4 +56,12 @@ + /* Special Function Register. Bit definitions are chip-specific */ + #define HMATRIX_SFR(s) (0x0110 + 4 * (s)) + ++#define HMATRIX_MAX_SLAVE 15 ++#define HMATRIX_MAX_MASTER 15 ++#define HMATRIX_MAX_PRIO 15 ++ ++/* Special master IDs for use with hmatrix_set_default_master() */ ++#define HMATRIX_MASTER_NONE 16 /* No default master */ ++#define HMATRIX_MASTER_LAST 17 /* Last master stays connected */ ++ + #endif /* __HMATRIX_H */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/init.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/init.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/init.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/init.h 2009-01-29 08:52:49.000000000 +0100 +@@ -15,4 +15,10 @@ + + void at32_setup_serial_console(unsigned int usart_id); + ++/* ++ * Called from time_init() when a broken COUNT/COMPARE implementation ++ * is detected. ++ */ ++void platform_time_init(void); ++ + #endif /* __ASM_AVR32_AT32AP_INIT_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/irq.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/irq.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/irq.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/irq.h 2009-01-29 08:52:49.000000000 +0100 +@@ -6,7 +6,7 @@ + #define AT32_EXTINT(n) (EIM_IRQ_BASE + (n)) + + #define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS) +-#define NR_GPIO_CTLR (5 /*internal*/ + 1 /*external*/) ++#define NR_GPIO_CTLR (8 /*internal*/ + 1 /*external*/) + #define NR_GPIO_IRQS (NR_GPIO_CTLR * 32) + + #define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS) +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/pm.h linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/pm.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/include/mach/pm.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/include/mach/pm.h 2009-01-29 08:52:49.000000000 +0100 +@@ -11,13 +11,17 @@ + #define __ASM_AVR32_ARCH_PM_H + + /* Possible arguments to the "sleep" instruction */ +-#define CPU_SLEEP_IDLE 0 +-#define CPU_SLEEP_FROZEN 1 +-#define CPU_SLEEP_STANDBY 2 +-#define CPU_SLEEP_STOP 3 +-#define CPU_SLEEP_STATIC 5 ++#define CPU_SLEEP_IDLE 0x00 ++#define CPU_SLEEP_FROZEN 0x01 ++#define CPU_SLEEP_STANDBY 0x02 ++#define CPU_SLEEP_STOP 0x03 ++#define CPU_SLEEP_DEEPSTOP 0x04 /* Not valid on AP700x */ ++#define CPU_SLEEP_STATIC 0x05 ++#define CPU_SLEEP_SHUTDOWN 0x06 /* Not valid on AP700x */ ++#define CPU_SLEEP_UNMASK_IRQ 0x80 /* Not valid on AP700x */ + + #ifndef __ASSEMBLY__ ++#if defined(CONFIG_CPU_AT32AP700X) + extern void cpu_enter_idle(void); + extern void cpu_enter_standby(unsigned long sdramc_base); + +@@ -37,15 +41,57 @@ + { + /* + * If we're using the COUNT and COMPARE registers for +- * timekeeping, we can't use the IDLE state. ++ * timekeeping on AP7000, we can't use the IDLE state. + */ + if (disable_idle_sleep) + cpu_relax(); + else + cpu_enter_idle(); + } ++#else ++static inline void cpu_disable_idle_sleep(void) ++{ ++ ++} ++ ++static inline void cpu_enable_idle_sleep(void) ++{ ++ ++} ++ ++static inline void cpu_enter_idle(void) ++{ ++ /* Enable interrupts and sleep */ ++ asm volatile("sleep %0" ++ : ++ : "i"(CPU_SLEEP_IDLE | CPU_SLEEP_UNMASK_IRQ) ++ : "memory"); ++} ++ ++static inline void cpu_idle_sleep(void) ++{ ++ local_irq_disable(); ++ if (!test_thread_flag(TIF_NEED_RESCHED)) ++ cpu_enter_idle(); ++ local_irq_enable(); ++} ++#endif + + void intc_set_suspend_handler(unsigned long offset); ++ ++extern unsigned long at32_get_reset_cause(void); ++ + #endif + ++#define AT32_RCAUSE_POR (1 << 0) /* Power-On Reset */ ++#define AT32_RCAUSE_BOD (1 << 1) /* Brown-Out Detected */ ++#define AT32_RCAUSE_EXT (1 << 2) /* External Reset */ ++#define AT32_RCAUSE_WDT (1 << 3) /* Watchdog Timeout */ ++#define AT32_RCAUSE_JTAG (1 << 4) /* JTAG Reset */ ++#define AT32_RCAUSE_NTAE (1 << 5) /* NanoTrace Access Error */ ++#define AT32_RCAUSE_SLEEP (1 << 6) /* Shutdown or Static mode */ ++#define AT32_RCAUSE_CPUERR (1 << 7) /* CPU Error */ ++#define AT32_RCAUSE_OCDRST (1 << 8) /* OCD Reset */ ++#define AT32_RCAUSE_JTAGHARD (1 << 9) /* JTAG Hard Reset */ ++ + #endif /* __ASM_AVR32_ARCH_PM_H */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/Makefile linux-2.6.28.2/arch/avr32/mach-at32ap/Makefile +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/Makefile 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/Makefile 2009-01-29 08:52:49.000000000 +0100 +@@ -1,9 +1,14 @@ +-obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o ++obj-y += pdc.o clock.o intc.o extint.o hsmc.o + obj-y += hmatrix.o +-obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o ++obj-$(CONFIG_PORTMUX_PIO) += pio.o ++obj-$(CONFIG_PORTMUX_GPIO_V2) += gpio-v2.o ++obj-$(CONFIG_TIMER_AST) += timer-ast.o + obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o + obj-$(CONFIG_PM) += pm.o + ++obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o ++obj-$(CONFIG_CPU_AT32AP720X) += at32ap720x.o pm-at32ap720x.o ++ + ifeq ($(CONFIG_PM_DEBUG),y) + CFLAGS_pm.o += -DDEBUG + endif +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-at32ap700x.S linux-2.6.28.2/arch/avr32/mach-at32ap/pm-at32ap700x.S +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-at32ap700x.S 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/pm-at32ap700x.S 2009-01-29 08:52:50.000000000 +0100 +@@ -12,12 +12,9 @@ + #include <asm/thread_info.h> + #include <mach/pm.h> + +-#include "pm.h" ++#include "pm-v1.h" + #include "sdramc.h" + +-/* Same as 0xfff00000 but fits in a 21 bit signed immediate */ +-#define PM_BASE -0x100000 +- + .section .bss, "wa", @nobits + .global disable_idle_sleep + .type disable_idle_sleep, @object +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-at32ap720x.S linux-2.6.28.2/arch/avr32/mach-at32ap/pm-at32ap720x.S +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-at32ap720x.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/pm-at32ap720x.S 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,110 @@ ++/* ++ * Low-level Power Management code. ++ * ++ * Copyright (C) 2008 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 <asm/asm.h> ++#include <asm/asm-offsets.h> ++#include <asm/thread_info.h> ++#include <mach/pm.h> ++ ++#include "pm-v3.h" ++#include "sdramc.h" ++ ++#ifdef CONFIG_PM ++ .section .init.text, "ax", @progbits ++ ++ .global pm_exception ++ .type pm_exception, @function ++pm_exception: ++ /* ++ * Exceptions are masked when we switch to this handler, so ++ * we'll only get "unrecoverable" exceptions (offset 0.) ++ */ ++ sub r12, pc, . - .Lpanic_msg ++ lddpc pc, .Lpanic_addr ++ ++ .align 2 ++.Lpanic_addr: ++ .long panic ++.Lpanic_msg: ++ .asciz "Unrecoverable exception during suspend\n" ++ .size pm_exception, . - pm_exception ++ ++ .global pm_irq0 ++ .type pm_irq0, @function ++pm_irq0: ++ /* Disable interrupts and return after the sleep instruction */ ++ mfsr r9, SYSREG_RSR_INT0 ++ mtsr SYSREG_RAR_INT0, r8 ++ sbr r9, SYSREG_GM_OFFSET ++ mtsr SYSREG_RSR_INT0, r9 ++ rete ++ ++ /* ++ * void cpu_enter_standby(unsigned long sdramc_base) ++ * ++ * Enter PM_SUSPEND_STANDBY mode. At this point, all drivers ++ * are suspended and interrupts are disabled. Interrupts ++ * marked as 'wakeup' event sources may still come along and ++ * get us out of here. ++ * ++ * The SDRAM will be put into self-refresh mode (which does ++ * not require a clock from the CPU), and the CPU will be put ++ * into "frozen" mode (HSB bus stopped). The SDRAM controller ++ * will automatically bring the SDRAM into normal mode on the ++ * first access, and the power manager will automatically ++ * start the HSB and CPU clocks upon a wakeup event. ++ */ ++ .global pm_standby ++ .type pm_standby, @function ++pm_standby: ++ /* ++ * interrupts are already masked at this point, and EVBA ++ * points to pm_exception above. ++ */ ++ ld.w r10, r12[SDRAMC_LPR] ++ sub r8, pc, . - 1f /* return address for irq handler */ ++ mov r11, SDRAMC_LPR_LPCB_SELF_RFR ++ bfins r10, r11, 0, 2 /* LPCB <- self Refresh */ ++ sync 0 /* flush write buffer */ ++ st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ ++ ld.w r11, r12[SDRAMC_LPR] ++ sleep CPU_SLEEP_FROZEN | CPU_SLEEP_UNMASK_IRQ ++1: mask_interrupts ++ retal r12 ++ .size pm_standby, . - pm_standby ++ ++ .global pm_suspend_to_ram ++ .type pm_suspend_to_ram, @function ++pm_suspend_to_ram: ++ /* ++ * interrupts are already masked at this point, and EVBA ++ * points to pm_exception above. ++ */ ++ mov r11, 0 ++ cache r11[2], 8 /* clean all dcache lines */ ++ sync 0 /* flush write buffer */ ++ ld.w r10, r12[SDRAMC_LPR] ++ sub r8, pc, . - 1f /* return address for irq handler */ ++ mov r11, SDRAMC_LPR_LPCB_SELF_RFR ++ bfins r10, r11, 0, 2 /* LPCB <- self refresh */ ++ st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ ++ ld.w r11, r12[SDRAMC_LPR] ++ ++ sleep CPU_SLEEP_STOP | CPU_SLEEP_UNMASK_IRQ ++1: mask_interrupts ++ ++ retal r12 ++ .size pm_suspend_to_ram, . - pm_suspend_to_ram ++ ++ .global pm_sram_end ++ .type pm_sram_end, @function ++pm_sram_end: ++ .size pm_sram_end, 0 ++ ++#endif /* CONFIG_PM */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm.h linux-2.6.28.2/arch/avr32/mach-at32ap/pm.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm.h 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/pm.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,112 +0,0 @@ +-/* +- * Register definitions for the Power Manager (PM) +- */ +-#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__ +-#define __ARCH_AVR32_MACH_AT32AP_PM_H__ +- +-/* PM register offsets */ +-#define PM_MCCTRL 0x0000 +-#define PM_CKSEL 0x0004 +-#define PM_CPU_MASK 0x0008 +-#define PM_HSB_MASK 0x000c +-#define PM_PBA_MASK 0x0010 +-#define PM_PBB_MASK 0x0014 +-#define PM_PLL0 0x0020 +-#define PM_PLL1 0x0024 +-#define PM_IER 0x0040 +-#define PM_IDR 0x0044 +-#define PM_IMR 0x0048 +-#define PM_ISR 0x004c +-#define PM_ICR 0x0050 +-#define PM_GCCTRL(x) (0x0060 + 4 * (x)) +-#define PM_RCAUSE 0x00c0 +- +-/* Bitfields in CKSEL */ +-#define PM_CPUSEL_OFFSET 0 +-#define PM_CPUSEL_SIZE 3 +-#define PM_CPUDIV_OFFSET 7 +-#define PM_CPUDIV_SIZE 1 +-#define PM_HSBSEL_OFFSET 8 +-#define PM_HSBSEL_SIZE 3 +-#define PM_HSBDIV_OFFSET 15 +-#define PM_HSBDIV_SIZE 1 +-#define PM_PBASEL_OFFSET 16 +-#define PM_PBASEL_SIZE 3 +-#define PM_PBADIV_OFFSET 23 +-#define PM_PBADIV_SIZE 1 +-#define PM_PBBSEL_OFFSET 24 +-#define PM_PBBSEL_SIZE 3 +-#define PM_PBBDIV_OFFSET 31 +-#define PM_PBBDIV_SIZE 1 +- +-/* Bitfields in PLL0 */ +-#define PM_PLLEN_OFFSET 0 +-#define PM_PLLEN_SIZE 1 +-#define PM_PLLOSC_OFFSET 1 +-#define PM_PLLOSC_SIZE 1 +-#define PM_PLLOPT_OFFSET 2 +-#define PM_PLLOPT_SIZE 3 +-#define PM_PLLDIV_OFFSET 8 +-#define PM_PLLDIV_SIZE 8 +-#define PM_PLLMUL_OFFSET 16 +-#define PM_PLLMUL_SIZE 8 +-#define PM_PLLCOUNT_OFFSET 24 +-#define PM_PLLCOUNT_SIZE 6 +-#define PM_PLLTEST_OFFSET 31 +-#define PM_PLLTEST_SIZE 1 +- +-/* Bitfields in ICR */ +-#define PM_LOCK0_OFFSET 0 +-#define PM_LOCK0_SIZE 1 +-#define PM_LOCK1_OFFSET 1 +-#define PM_LOCK1_SIZE 1 +-#define PM_WAKE_OFFSET 2 +-#define PM_WAKE_SIZE 1 +-#define PM_CKRDY_OFFSET 5 +-#define PM_CKRDY_SIZE 1 +-#define PM_MSKRDY_OFFSET 6 +-#define PM_MSKRDY_SIZE 1 +- +-/* Bitfields in GCCTRL0 */ +-#define PM_OSCSEL_OFFSET 0 +-#define PM_OSCSEL_SIZE 1 +-#define PM_PLLSEL_OFFSET 1 +-#define PM_PLLSEL_SIZE 1 +-#define PM_CEN_OFFSET 2 +-#define PM_CEN_SIZE 1 +-#define PM_DIVEN_OFFSET 4 +-#define PM_DIVEN_SIZE 1 +-#define PM_DIV_OFFSET 8 +-#define PM_DIV_SIZE 8 +- +-/* Bitfields in RCAUSE */ +-#define PM_POR_OFFSET 0 +-#define PM_POR_SIZE 1 +-#define PM_EXT_OFFSET 2 +-#define PM_EXT_SIZE 1 +-#define PM_WDT_OFFSET 3 +-#define PM_WDT_SIZE 1 +-#define PM_NTAE_OFFSET 4 +-#define PM_NTAE_SIZE 1 +- +-/* Bit manipulation macros */ +-#define PM_BIT(name) \ +- (1 << PM_##name##_OFFSET) +-#define PM_BF(name,value) \ +- (((value) & ((1 << PM_##name##_SIZE) - 1)) \ +- << PM_##name##_OFFSET) +-#define PM_BFEXT(name,value) \ +- (((value) >> PM_##name##_OFFSET) \ +- & ((1 << PM_##name##_SIZE) - 1)) +-#define PM_BFINS(name,value,old)\ +- (((old) & ~(((1 << PM_##name##_SIZE) - 1) \ +- << PM_##name##_OFFSET)) \ +- | PM_BF(name,value)) +- +-/* Register access macros */ +-#define pm_readl(reg) \ +- __raw_readl((void __iomem __force *)PM_BASE + PM_##reg) +-#define pm_writel(reg,value) \ +- __raw_writel((value), (void __iomem __force *)PM_BASE + PM_##reg) +- +-#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-v1.h linux-2.6.28.2/arch/avr32/mach-at32ap/pm-v1.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-v1.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/pm-v1.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,112 @@ ++/* ++ * Register definitions for the Power Manager (PM) ++ */ ++#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__ ++#define __ARCH_AVR32_MACH_AT32AP_PM_H__ ++ ++/* PM register offsets */ ++#define PM_MCCTRL 0x0000 ++#define PM_CKSEL 0x0004 ++#define PM_CPU_MASK 0x0008 ++#define PM_HSB_MASK 0x000c ++#define PM_PBA_MASK 0x0010 ++#define PM_PBB_MASK 0x0014 ++#define PM_PLL0 0x0020 ++#define PM_PLL1 0x0024 ++#define PM_IER 0x0040 ++#define PM_IDR 0x0044 ++#define PM_IMR 0x0048 ++#define PM_ISR 0x004c ++#define PM_ICR 0x0050 ++#define PM_GCCTRL(x) (0x0060 + 4 * (x)) ++#define PM_RCAUSE 0x00c0 ++ ++/* Bitfields in CKSEL */ ++#define PM_CPUSEL_OFFSET 0 ++#define PM_CPUSEL_SIZE 3 ++#define PM_CPUDIV_OFFSET 7 ++#define PM_CPUDIV_SIZE 1 ++#define PM_HSBSEL_OFFSET 8 ++#define PM_HSBSEL_SIZE 3 ++#define PM_HSBDIV_OFFSET 15 ++#define PM_HSBDIV_SIZE 1 ++#define PM_PBASEL_OFFSET 16 ++#define PM_PBASEL_SIZE 3 ++#define PM_PBADIV_OFFSET 23 ++#define PM_PBADIV_SIZE 1 ++#define PM_PBBSEL_OFFSET 24 ++#define PM_PBBSEL_SIZE 3 ++#define PM_PBBDIV_OFFSET 31 ++#define PM_PBBDIV_SIZE 1 ++ ++/* Bitfields in PLL0 */ ++#define PM_PLLEN_OFFSET 0 ++#define PM_PLLEN_SIZE 1 ++#define PM_PLLOSC_OFFSET 1 ++#define PM_PLLOSC_SIZE 1 ++#define PM_PLLOPT_OFFSET 2 ++#define PM_PLLOPT_SIZE 3 ++#define PM_PLLDIV_OFFSET 8 ++#define PM_PLLDIV_SIZE 8 ++#define PM_PLLMUL_OFFSET 16 ++#define PM_PLLMUL_SIZE 8 ++#define PM_PLLCOUNT_OFFSET 24 ++#define PM_PLLCOUNT_SIZE 6 ++#define PM_PLLTEST_OFFSET 31 ++#define PM_PLLTEST_SIZE 1 ++ ++/* Bitfields in ICR */ ++#define PM_LOCK0_OFFSET 0 ++#define PM_LOCK0_SIZE 1 ++#define PM_LOCK1_OFFSET 1 ++#define PM_LOCK1_SIZE 1 ++#define PM_WAKE_OFFSET 2 ++#define PM_WAKE_SIZE 1 ++#define PM_CKRDY_OFFSET 5 ++#define PM_CKRDY_SIZE 1 ++#define PM_MSKRDY_OFFSET 6 ++#define PM_MSKRDY_SIZE 1 ++ ++/* Bitfields in GCCTRL0 */ ++#define PM_OSCSEL_OFFSET 0 ++#define PM_OSCSEL_SIZE 1 ++#define PM_PLLSEL_OFFSET 1 ++#define PM_PLLSEL_SIZE 1 ++#define PM_CEN_OFFSET 2 ++#define PM_CEN_SIZE 1 ++#define PM_DIVEN_OFFSET 4 ++#define PM_DIVEN_SIZE 1 ++#define PM_DIV_OFFSET 8 ++#define PM_DIV_SIZE 8 ++ ++/* Bitfields in RCAUSE */ ++#define PM_POR_OFFSET 0 ++#define PM_POR_SIZE 1 ++#define PM_EXT_OFFSET 2 ++#define PM_EXT_SIZE 1 ++#define PM_WDT_OFFSET 3 ++#define PM_WDT_SIZE 1 ++#define PM_NTAE_OFFSET 4 ++#define PM_NTAE_SIZE 1 ++ ++/* Bit manipulation macros */ ++#define PM_BIT(name) \ ++ (1 << PM_##name##_OFFSET) ++#define PM_BF(name,value) \ ++ (((value) & ((1 << PM_##name##_SIZE) - 1)) \ ++ << PM_##name##_OFFSET) ++#define PM_BFEXT(name,value) \ ++ (((value) >> PM_##name##_OFFSET) \ ++ & ((1 << PM_##name##_SIZE) - 1)) ++#define PM_BFINS(name,value,old)\ ++ (((old) & ~(((1 << PM_##name##_SIZE) - 1) \ ++ << PM_##name##_OFFSET)) \ ++ | PM_BF(name,value)) ++ ++/* Register access macros */ ++#define pm_readl(reg) \ ++ __raw_readl((void __iomem __force *)PM_BASE + PM_##reg) ++#define pm_writel(reg,value) \ ++ __raw_writel((value), (void __iomem __force *)PM_BASE + PM_##reg) ++ ++#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-v3.h linux-2.6.28.2/arch/avr32/mach-at32ap/pm-v3.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/pm-v3.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/pm-v3.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,283 @@ ++/* ++ * Copyright (C) 2008 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. ++ */ ++#ifndef __PM_V3_H__ ++#define __PM_V3_H__ ++ ++#include <mach/chip.h> ++ ++/* PM Register offsets */ ++#ifndef __ASSEMBLY__ ++struct pm_regs { ++ u32 MCCTRL; /* Main Clock Control */ ++ u32 CKSEL; /* Clock Select */ ++ u32 CPUMASK; /* CPU Clock Mask */ ++ u32 HSBMASK; /* HSB Clock Mask */ ++ u32 PBAMASK; /* PBA Clock Mask */ ++ u32 PBBMASK; /* PBB Clock Mask */ ++ u32 PBADIVMASK; /* Divided PBA Clock Mask */ ++ u32 PBBDIVMASK; /* Divided PBB Clock Mask */ ++ u32 __reserved1[8]; ++ u32 PLL[3]; /* PLL Control */ ++ u32 __reserved2[13]; ++ u32 OSCCTRL[3]; /* Oscillator Control */ ++ u32 __reserved3[5]; ++ u32 OSCCTRL32; /* 32 kHz Oscillator Control */ ++ u32 __reserved4[7]; ++ u32 IER; /* Interrupt Enable */ ++ u32 IDR; /* Interrupt Disable */ ++ u32 IMR; /* Interrupt Mask */ ++ u32 ISR; /* Interrupt Status */ ++ u32 ICR; /* Interrupt Clear */ ++ u32 POSCSR; /* Power and Oscillator Status */ ++ u32 __reserved5[10]; ++ u32 GCCTRL[8]; /* Generic Clock Control */ ++ u32 __reserved6[8]; ++ u32 RCCR; /* RC Oscillator Calibration */ ++ u32 BGCR; /* Bandgap Calibration */ ++ u32 VREGCR; /* Buck Regulator Calibration */ ++ u32 BOD; /* BOD Level */ ++ u32 PPCR; /* Peripheral Power Control */ ++ u32 __reserved7[11]; ++ u32 RCAUSE; /* Reset Cause */ ++ u32 WCAUSE; /* Wake Cause */ ++ u32 AWEN; /* Asynchronous Wake Enable */ ++ u32 __reserved8[14]; ++ u32 GPLP; /* General Purpose Low-Power */ ++}; ++#endif ++ ++/* Assembly-friendly register offsets; same as above */ ++#define PM_MCCTRL 0x0000 ++#define PM_CKSEL 0x0004 ++#define PM_CPUMASK 0x0008 ++#define PM_HSBMASK 0x000c ++#define PM_PBAMASK 0x0010 ++#define PM_PBBMASK 0x0014 ++#define PM_PBADIVMASK 0x0018 ++#define PM_PBBDIVMASK 0x001c ++#define PM_PLL0 0x0040 ++#define PM_PLL1 0x0044 ++#define PM_PLL2 0x0048 ++#define PM_OSCCTRL0 0x0080 ++#define PM_OSCCTRL1 0x0084 ++#define PM_OSCCTRL2 0x0088 ++#define PM_OSCCTRL32 0x00a0 ++#define PM_IER 0x00c0 ++#define PM_IDR 0x00c4 ++#define PM_IMR 0x00c8 ++#define PM_ISR 0x00cc ++#define PM_ICR 0x00d0 ++#define PM_POSCSR 0x00d4 ++#define PM_GCCTRL 0x0100 ++#define PM_RCCR 0x0140 ++#define PM_BGCR 0x0144 ++#define PM_VREGCR 0x0148 ++#define PM_BOD 0x014c ++#define PM_PPCR 0x0150 ++#define PM_RC_RCAUSE 0x0180 ++#define PM_WCAUSE 0x0184 ++#define PM_AWEN 0x0188 ++#define PM_GPLP 0x01c0 ++ ++/* Bits in MCCTRL */ ++#define PM_MCCTRL_MCSEL_START 0 ++#define PM_MCCTRL_MCSEL_SIZE 2 ++#define PM_MCCTRL_OSC0EN_BIT 2 ++#define PM_MCCTRL_OSC1EN_BIT 3 ++#define PM_MCCTRL_OSC2EN_BIT 4 ++#define PM_MCCTRL_CRIPEL_BIT 24 ++ ++/* Bits in CKSEL */ ++#define PM_CKSEL_CPUSEL_START 0 ++#define PM_CKSEL_CPUSEL_SIZE 3 ++#define PM_CKSEL_CPUDIV_BIT 7 ++#define PM_CKSEL_HSBSEL_START 8 ++#define PM_CKSEL_HSBSEL_SIZE 3 ++#define PM_CKSEL_HSBDIV_BIT 15 ++#define PM_CKSEL_PBASEL_START 16 ++#define PM_CKSEL_PBASEL_SIZE 3 ++#define PM_CKSEL_PBADIV_BIT 23 ++#define PM_CKSEL_PBBSEL_START 24 ++#define PM_CKSEL_PBBSEL_SIZE 3 ++#define PM_CKSEL_PBBDIV_BIT 31 ++ ++/* Bits in CPUMASK */ ++#define PM_CPUMASK_SYSTIMER_BIT 16 ++ ++/* Bits in PLLx */ ++#define PM_PLLx_PLLEN_BIT 0 ++#define PM_PLLx_PLLOSC_START 1 ++#define PM_PLLx_PLLOSC_SIZE 2 ++#define PM_PLLx_PLLOPT_START 3 ++#define PM_PLLx_PLLOPT_SIZE 3 ++#define PM_PLLx_PLLBPL_BIT 7 ++#define PM_PLLx_PLLDIV_START 8 ++#define PM_PLLx_PLLDIV_SIZE 6 ++#define PM_PLLx_PLLMUL_START 16 ++#define PM_PLLx_PLLMUL_SIZE 6 ++#define PM_PLLx_PLLCOUNT_START 24 ++#define PM_PLLx_PLLCOUNT_SIZE 6 ++#define PM_PLLx_PLLIOTESTEN_BIT 30 ++#define PM_PLLx_PLLTEST_BIT 31 ++ ++/* Bits in OSCCTRLx */ ++#define PM_OSCCTRLx_MODE_START 0 ++#define PM_OSCCTRLx_MODE_SIZE 4 ++#define PM_OSCCTRLx_STARTUP_START 8 ++#define PM_OSCCTRLx_STARTUP_SIZE 3 ++ ++/* Bits in OSCCTRL32 */ ++#define PM_OSCCTRL32_OSC32EN_BIT 0 ++#define PM_OSCCTRL32_MODE_START 8 ++#define PM_OSCCTRL32_MODE_SIZE 3 ++#define PM_OSCCTRL32_STARTUP_START 16 ++#define PM_OSCCTRL32_STARTUP_SIZE 3 ++ ++/* Bits in IER/IDR/IMR/ISR/ICR */ ++#define PM_ISR_OSC0RDY_BIT 0 ++#define PM_ISR_OSC1RDY_BIT 1 ++#define PM_ISR_OSC2RDY_BIT 2 ++#define PM_ISR_OSC32RDY_BIT 7 ++#define PM_ISR_LOCK0_BIT 8 ++#define PM_ISR_LOCK1_BIT 9 ++#define PM_ISR_LOCK2_BIT 10 ++#define PM_ISR_LOCK0LOST_BIT 16 ++#define PM_ISR_LOCK1LOST_BIT 17 ++#define PM_ISR_LOCK2LOST_BIT 18 ++#define PM_ISR_CKRDY_BIT 24 ++#define PM_ISR_MSKRDY_BIT 25 ++#define PM_ISR_WAKE_BIT 26 ++#define PM_ISR_BODDET_BIT 27 ++#define PM_ISR_PERRDY_BIT 28 ++ ++/* Bits in POSCSR */ ++#define PM_POSCSR_OSC0RDY_BIT 0 ++#define PM_POSCSR_OSC1RDY_BIT 1 ++#define PM_POSCSR_OSC32RDY_BIT 7 ++#define PM_POSCSR_LOCK0_BIT 8 ++#define PM_POSCSR_LOCK1_BIT 9 ++#define PM_POSCSR_LOCK0LOST_BIT 16 ++#define PM_POSCSR_LOCK1LOST_BIT 17 ++#define PM_POSCSR_CKRDY_BIT 24 ++#define PM_POSCSR_MSKRDY_BIT 25 ++#define PM_POSCSR_WAKE_BIT 26 ++#define PM_POSCSR_BODDET_BIT 27 ++#define PM_POSCSR_PERRDY_BIT 28 ++ ++/* Bits in GCCTRL */ ++#define PM_GCCTRL_CEN_BIT 0 ++#define PM_GCCTRL_DIVEN_BIT 1 ++#define PM_GCCTRL_OSCSEL_START 8 ++#define PM_GCCTRL_OSCSEL_SIZE 4 ++#define PM_GCCTRL_DIV_START 16 ++#define PM_GCCTRL_DIV_SIZE 8 ++ ++/* Bits in RCCR */ ++#define PM_RCCR_CALIB_START 0 ++#define PM_RCCR_CALIB_SIZE 10 ++#define PM_RCCR_FCD_BIT 16 ++#define PM_RCCR_KEY_START 24 ++#define PM_RCCR_KEY_SIZE 8 ++ ++/* Bits in BGCR */ ++#define PM_BGCR_CALIB_START 0 ++#define PM_BGCR_CALIB_SIZE 3 ++#define PM_BGCR_FCD_BIT 16 ++#define PM_BGCR_KEY_START 24 ++#define PM_BGCR_KEY_SIZE 8 ++ ++/* Bits in VREGCR */ ++#define PM_VREGCR_CALIB_START 0 ++#define PM_VREGCR_CALIB_SIZE 3 ++#define PM_VREGCR_FCD_BIT 16 ++#define PM_VREGCR_KEY_START 24 ++#define PM_VREGCR_KEY_SIZE 8 ++ ++/* Bits in BOD */ ++#define PM_BOD_LEVEL_START 0 ++#define PM_BOD_LEVEL_SIZE 6 ++#define PM_BOD_HYST_BIT 6 ++#define PM_BOD_CTRL_START 8 ++#define PM_BOD_CTRL_SIZE 2 ++#define PM_BOD_FCD_BIT 16 ++#define PM_BOD_KEY_START 24 ++#define PM_BOD_KEY_SIZE 8 ++ ++/* Bits in PPCR */ ++#define PM_PPCR_EBI_VOLT_BIT 0 ++#define PM_PPCR_UTMI_CTRL_BIT 1 ++#define PM_PPCR_KEY_START 24 ++#define PM_PPCR_KEY_SIZE 8 ++ ++/* Bits in RC_RCAUSE */ ++#define PM_RC_RCAUSE_POR_BIT 0 ++#define PM_RC_RCAUSE_BOD_BIT 1 ++#define PM_RC_RCAUSE_EXT_BIT 2 ++#define PM_RC_RCAUSE_WDT_BIT 3 ++#define PM_RC_RCAUSE_JTAG_BIT 4 ++#define PM_RC_RCAUSE_NTAE_BIT 5 ++#define PM_RC_RCAUSE_SLEEP_BIT 6 ++#define PM_RC_RCAUSE_CPUERR_BIT 7 ++#define PM_RC_RCAUSE_OCDRST_BIT 8 ++#define PM_RC_RCAUSE_JTAGHARD_BIT 9 ++ ++/* Bits in WCAUSE */ ++#define PM_WCAUSE_PERIPH0_BIT 0 ++#define PM_WCAUSE_PERIPH1_BIT 1 ++#define PM_WCAUSE_EIC_BIT 16 ++#define PM_WCAUSE_RTC_BIT 17 ++ ++/* Constants for MCCTRL:MCSEL */ ++#define PM_MCSEL_SLOW 0 ++#define PM_MCSEL_OSC0 1 ++#define PM_MCSEL_PLL0 2 ++ ++/* Constants for OSCCTRLx:MODE */ ++#define PM_MODE_EXT_CLOCK 0 ++#define PM_MODE_CRYSTAL_ACG 1 ++#define PM_MODE_CRYSTAL_G0 4 ++#define PM_MODE_CRYSTAL_G1 5 ++#define PM_MODE_CRYSTAL_G2 6 ++#define PM_MODE_CRYSTAL_G3 7 ++ ++/* Constants for GCCTRL:OSCSEL */ ++#define PM_OSCSEL_SLOW 0 ++#define PM_OSCSEL_CLK32 1 ++#define PM_OSCSEL_OSC0 2 ++#define PM_OSCSEL_OSC1 3 ++#define PM_OSCSEL_PLL0 4 ++#define PM_OSCSEL_PLL1 5 ++ ++/* Constants for BOD:CTRL */ ++#define PM_CTRL_OFF1 0 ++#define PM_CTRL_ENABLED 1 ++#define PM_CTRL_ENABLED_NORESET 2 ++#define PM_CTRL_OFF2 3 ++ ++/* Bit manipulation macros */ ++#define PM_BIT(name) \ ++ (1 << PM_##name##_BIT) ++#define PM_BF(name,value) \ ++ (((value) & ((1 << PM_##name##_SIZE) - 1)) \ ++ << PM_##name##_START) ++#define PM_BFEXT(name,value) \ ++ (((value) >> PM_##name##_START) \ ++ & ((1 << PM_##name##_SIZE) - 1)) ++#define PM_BFINS(name,value,old) \ ++ (((old) & ~(((1 << PM_##name##_SIZE) - 1) \ ++ << PM_##name##_START)) \ ++ | PM_BF(name,value)) ++ ++/* Register access macros */ ++#define __pm_regs ((struct pm_regs __iomem __force *)PM_BASE) ++#define pm_readl(reg) \ ++ __raw_readl(&__pm_regs->reg) ++#define pm_writel(reg, value) \ ++ __raw_writel(value, &__pm_regs->reg) ++ ++#endif /* __PM_V3_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/sdc.h linux-2.6.28.2/arch/avr32/mach-at32ap/sdc.h +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/sdc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/sdc.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,103 @@ ++/* SDC */ ++ ++/* Register offsets */ ++#define SDC_CTRL 0x0000 ++#define SDC_ASYNC 0x0004 ++#define SDC_SYNC 0x0008 ++#define SDC_FILTERDUR 0x000c ++#define SDC_OSCCTRL32 0x0010 ++#define SDC_STATUS 0x0014 ++#define SDC_ECR 0x0018 ++#define SDC_IER 0x001c ++#define SDC_IDR 0x0020 ++#define SDC_IMR 0x0024 ++#define SDC_GPLP 0x0040 ++ ++/* Bits in CTRL */ ++#define SDC_CTRL_PIN_EN_BIT 0 ++#define SDC_CTRL_AST_EN_BIT 8 ++#define SDC_CTRL_WDT_EN_BIT 9 ++#define SDC_CTRL_OCD_EN_BIT 10 ++#define SDC_CTRL_JTAG_EN_BIT 11 ++#define SDC_CTRL_CORE_POR_TEST_BIT 23 ++#define SDC_CTRL_KEY_START 24 ++#define SDC_CTRL_KEY_SIZE 8 ++ ++/* Bits in ASYNC */ ++#define SDC_ASYNC_MODE_BIT 4 ++#define SDC_ASYNC_POL_BIT 8 ++#define SDC_ASYNC_KEY_START 24 ++#define SDC_ASYNC_KEY_SIZE 8 ++ ++/* Bits in SYNC */ ++#define SDC_SYNC_EN_BIT 0 ++#define SDC_SYNC_MODE_BIT 4 ++#define SDC_SYNC_POL_BIT 8 ++#define SDC_SYNC_FILTER_BIT 12 ++#define SDC_SYNC_KEY_START 24 ++#define SDC_SYNC_KEY_SIZE 8 ++ ++/* Bits in FILTERDUR */ ++#define SDC_FILTERDUR_Duration_START 0 ++#define SDC_FILTERDUR_Duration_SIZE 16 ++#define SDC_FILTERDUR_KEY_START 24 ++#define SDC_FILTERDUR_KEY_SIZE 8 ++ ++/* Bits in OSCCTRL32 */ ++#define SDC_OSCCTRL32_OSC32EN_BIT 0 ++#define SDC_OSCCTRL32_MODE_START 8 ++#define SDC_OSCCTRL32_MODE_SIZE 4 ++#define SDC_OSCCTRL32_STARTUP_START 16 ++#define SDC_OSCCTRL32_STARTUP_SIZE 3 ++#define SDC_OSCCTRL32_KEY_START 24 ++#define SDC_OSCCTRL32_KEY_SIZE 8 ++ ++/* Bits in STATUS */ ++#define SDC_STATUS_PIN_EVENT_BIT 0 ++#define SDC_STATUS_AST_EVENT_BIT 8 ++#define SDC_STATUS_WDT_EVENT_BIT 9 ++#define SDC_STATUS_OCD_EVENT_BIT 10 ++#define SDC_STATUS_JTAG_EVENT_BIT 11 ++#define SDC_STATUS_PIN_BIT 16 ++#define SDC_STATUS_BUSY_BIT 24 ++#define SDC_STATUS_SWTCH_BIT 30 ++#define SDC_STATUS_VBAT_BIT 31 ++ ++/* Bits in ECR */ ++#define SDC_ECR_PIN_EVENT_BIT 0 ++#define SDC_ECR_AST_EVENT_BIT 8 ++#define SDC_ECR_WDT_EVENT_BIT 9 ++#define SDC_ECR_OCD_EVENT_BIT 10 ++#define SDC_ECR_JTAG_EVENT_BIT 11 ++ ++/* Bits in IER */ ++#define SDC_IER_PIN_EVENT_BIT 0 ++#define SDC_IER_READY_BIT 24 ++ ++/* Bits in IDR */ ++#define SDC_IDR_PIN_EVENT_BIT 0 ++#define SDC_IDR_READY_BIT 24 ++ ++/* Bits in IMR */ ++#define SDC_IMR_PIN_EVENT_BIT 0 ++#define SDC_IMR_READY_BIT 24 ++ ++/* Bit manipulation macros */ ++#define SDC_BIT(name) \ ++ (1 << SDC_##name##_BIT) ++#define SDC_BF(name,value) \ ++ (((value) & ((1 << SDC_##name##_SIZE) - 1)) \ ++ << SDC_##name##_START) ++#define SDC_BFEXT(name,value) \ ++ (((value) >> SDC_##name##_START) \ ++ & ((1 << SDC_##name##_SIZE) - 1)) ++#define SDC_BFINS(name,value,old) \ ++ (((old) & ~(((1 << SDC_##name##_SIZE) - 1) \ ++ << SDC_##name##_START)) \ ++ | SDC_BF(name,value)) ++ ++/* Register access macros */ ++#define sdc_readl(reg) \ ++ __raw_readl((void __iomem __force *)(SDC_BASE + SDC_##reg)) ++#define sdc_writel(reg, value) \ ++ __raw_writel(value, (void __iomem __force *)(SDC_BASE + SDC_##reg)) +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/timer-ast.c linux-2.6.28.2/arch/avr32/mach-at32ap/timer-ast.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/timer-ast.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/timer-ast.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,191 @@ ++/* ++ * Asynchronous Timer (AST) used as clocksource / clockevent ++ * ++ * Copyright (C) 2008 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 <linux/clk.h> ++#include <linux/clockchips.h> ++#include <linux/clocksource.h> ++#include <linux/interrupt.h> ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/irq.h> ++#include <linux/platform_device.h> ++ ++#include <asm/ast_regs.h> ++ ++static void __iomem *ast_regs; ++ ++static inline void ast_wait_ready(void) ++{ ++ while (ast_readl(ast_regs, SR) & AST_BIT(BUSY)) ++ cpu_relax(); ++} ++ ++static cycle_t read_ast_counter(void) ++{ ++ return ast_readl(ast_regs, CV); ++} ++ ++static struct clocksource ast_clksrc = { ++ .name = "ast", ++ .rating = 400, ++ .read = read_ast_counter, ++ .mask = CLOCKSOURCE_MASK(32), ++ .shift = 16, ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++ ++static irqreturn_t ast_clkevt_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *clkevt = dev_id; ++ ++ /* ++ * We make sure delta is always long enough so that the BUSY ++ * bit is never set at this point. ++ */ ++ ast_writel(ast_regs, SCR, AST_BIT(ALARM0)); ++ clkevt->event_handler(clkevt); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction ast_clkevt_irqaction = { ++ .handler = ast_clkevt_interrupt, ++ .flags = IRQF_TIMER | IRQF_DISABLED, ++ .name = "timer-ast", ++}; ++ ++static int ast_next_event(unsigned long delta, ++ struct clock_event_device *clkevt) ++{ ++ ast_wait_ready(); ++ ast_writel(ast_regs, AR0, ast_readl(ast_regs, CV) + delta); ++ ++ return 0; ++} ++ ++static void ast_mode(enum clock_event_mode mode, ++ struct clock_event_device *evdev) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ case CLOCK_EVT_MODE_RESUME: ++ /* Make sure we don't trigger an alarm before we get ++ * around to reprogramming it. ++ */ ++ ast_wait_ready(); ++ ast_writel(ast_regs, AR0, ast_readl(ast_regs, CV) - 1); ++ ast_wait_ready(); ++ ast_writel(ast_regs, SCR, AST_BIT(ALARM0)); ++ ast_wait_ready(); ++ ast_writel(ast_regs, IER, AST_BIT(ALARM0)); ++ break; ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ ast_writel(ast_regs, IDR, AST_BIT(ALARM0)); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static struct clock_event_device ast_clkevt = { ++ .name = "ast", ++ .features = CLOCK_EVT_FEAT_ONESHOT, ++ .shift = 16, ++ .rating = 400, ++ .cpumask = CPU_MASK_CPU0, ++ .set_next_event = ast_next_event, ++ .set_mode = ast_mode, ++}; ++ ++void __init ast_time_init(struct platform_device *pdev, unsigned int clksel) ++{ ++ struct clk *clk, *pclk; ++ struct resource *regs; ++ unsigned long ast_hz; ++ int irq; ++ int ret; ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ pr_debug("AST: No MMIO resource\n"); ++ return; ++ } ++ ++ pclk = clk_get(&pdev->dev, "pclk"); ++ if (!pclk) { ++ pr_debug("AST: No peripheral clock (pclk)\n"); ++ return; ++ } ++ clk_enable(pclk); ++ ++ /* Too early for ioremap() */ ++ ast_regs = (void __iomem __force *)regs->start; ++ ++ switch (clksel) { ++ case AST_CLOCK_SLOW: ++ clk = clk_get(NULL, "rcosc"); ++ break; ++ case AST_CLOCK_OSC32: ++ clk = clk_get(NULL, "osc32"); ++ break; ++ case AST_CLOCK_PB: ++ clk = pclk; ++ break; ++ case AST_CLOCK_GC: ++ clk = clk_get(&pdev->dev, "gclk"); ++ break; ++ default: ++ clk = NULL; ++ break; ++ } ++ ++ if (!clk) { ++ pr_debug("AST: clock %u invalid, using pb clock\n", clksel); ++ clk = pclk; ++ } ++ clk_enable(clk); ++ ++ ast_writel(ast_regs, CLOCK, ++ AST_BF(CLOCK_CSSEL, clksel) | AST_BIT(CLOCK_CEN)); ++ ast_writel(ast_regs, CR, AST_BIT(CR_EN) | AST_BIT(CR_PCLR)); ++ ++ /* Using hardcoded divide-by-two prescaler */ ++ ast_hz = clk_get_rate(clk) / 2; ++ ast_clksrc.mult = clocksource_hz2mult(ast_hz, ast_clksrc.shift); ++ ++ ret = clocksource_register(&ast_clksrc); ++ if (ret) ++ pr_debug("AST: could not register clocksource: %d\n", ret); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ pr_debug("AST: No IRQ resource, won't setup clockevent\n"); ++ return; ++ } ++ ++ ast_clkevt.mult = div_sc(ast_hz, NSEC_PER_SEC, ast_clkevt.shift); ++ ast_clkevt.max_delta_ns = clockevent_delta2ns((u32)~0U, &ast_clkevt); ++ ast_clkevt.min_delta_ns = clockevent_delta2ns(2, &ast_clkevt) + 100; ++ ++ ast_clkevt_irqaction.dev_id = &ast_clkevt; ++ ++ ret = setup_irq(irq, &ast_clkevt_irqaction); ++ if (ret) { ++ pr_debug("AST: Could not request IRQ %d: %d\n", irq, ret); ++ return; ++ } ++ ++ clockevents_register_device(&ast_clkevt); ++ ++ pr_info("Using Asynchronous Timer %d @ %lu.%03lu Mhz" ++ " (regs 0x%p, irq %d)\n", ++ pdev->id, ((ast_hz + 500) / 1000) / 1000, ++ ((ast_hz + 500) / 1000) % 1000, ast_regs, irq); ++} +diff -urN linux-2.6.28.2-0rig//arch/avr32/mm/tlb.c linux-2.6.28.2/arch/avr32/mm/tlb.c +--- linux-2.6.28.2-0rig//arch/avr32/mm/tlb.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mm/tlb.c 2009-01-29 08:52:50.000000000 +0100 +@@ -12,7 +12,13 @@ + #include <asm/mmu_context.h> + + /* TODO: Get the correct number from the CONFIG1 system register */ +-#define NR_TLB_ENTRIES 32 ++#if defined(CONFIG_CPU_AT32AP700X) ++# define NR_TLB_ENTRIES 32 ++#elif defined(CONFIG_CPU_AT32AP720X) ++# define NR_TLB_ENTRIES 64 ++#else ++# error Unknown CPU type ++#endif + + static void show_dtlb_entry(unsigned int index) + { +@@ -85,9 +91,15 @@ + u32 tlbar = sysreg_read(TLBARLO); + + rp = 32 - fls(tlbar); +- if (rp == 32) { ++ if (NR_TLB_ENTRIES > 32 && rp >= 32) { ++ tlbar = sysreg_read(TLBARHI); ++ rp = 64 - fls(tlbar); ++ } ++ if (rp >= NR_TLB_ENTRIES) { + rp = 0; + sysreg_write(TLBARLO, -1L); ++ if (NR_TLB_ENTRIES > 32) ++ sysreg_write(TLBARHI, -1L); + } + + mmucr = SYSREG_BFINS(DRP, rp, mmucr); +@@ -131,16 +143,22 @@ + + if (!(mmucr & SYSREG_BIT(MMUCR_N))) { + unsigned int entry; +- u32 tlbarlo; ++ u32 tlbarlo, tlbarhi; + + /* Clear the "valid" bit */ + sysreg_write(TLBEHI, tlbehi); + + /* mark the entry as "not accessed" */ + entry = SYSREG_BFEXT(DRP, mmucr); +- tlbarlo = sysreg_read(TLBARLO); +- tlbarlo |= (0x80000000UL >> entry); +- sysreg_write(TLBARLO, tlbarlo); ++ if (NR_TLB_ENTRIES > 32 && entry > 32) { ++ tlbarhi = sysreg_read(TLBARHI); ++ tlbarhi |= (0x80000000UL >> (entry - 32)); ++ sysreg_write(TLBARHI, tlbarhi); ++ } else { ++ tlbarlo = sysreg_read(TLBARLO); ++ tlbarlo |= (0x80000000UL >> entry); ++ sysreg_write(TLBARLO, tlbarlo); ++ } + + /* update the entry with valid bit clear */ + __builtin_tlbw(); +@@ -179,9 +197,10 @@ + unsigned long flags; + int size; + +- local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + ++ local_irq_save(flags); ++ + if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */ + mm->context = NO_CONTEXT; + if (mm == current->mm) +diff -urN linux-2.6.28.2-0rig//drivers/dma/atmel_pdca.c linux-2.6.28.2/drivers/dma/atmel_pdca.c +--- linux-2.6.28.2-0rig//drivers/dma/atmel_pdca.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/drivers/dma/atmel_pdca.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,668 @@ ++/* ++ * Driver for the Atmel PDCA Peripheral DMA Controller ++ * ++ * Copyright (C) 2008 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. ++ */ ++#define DEBUG ++#include <linux/atmel_pdca.h> ++#include <linux/clk.h> ++#include <linux/dmaengine.h> ++#include <linux/dma-mapping.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/list.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/scatterlist.h> ++#include <linux/spinlock.h> ++ ++/* ++ * Since each descriptor can hold a whole scatterlist, we don't need ++ * many of them. ++ */ ++#define NR_DESCS_PER_CHANNEL 8 ++ ++static struct pdca_desc *pdca_desc_entry(struct list_head *node) ++{ ++ return list_entry(node, struct pdca_desc, desc_node); ++} ++ ++static struct pdca_desc *pdca_next_desc(struct pdca_chan *pch, ++ struct pdca_desc *desc) ++{ ++ if (desc->desc_node.next != &pch->queue) ++ return pdca_desc_entry(desc->desc_node.next); ++ return NULL; ++} ++ ++static struct pdca_desc *pdca_desc_get(struct pdca_chan *pch) ++{ ++ struct pdca_desc *desc = NULL; ++ ++ spin_lock_bh(&pch->lock); ++ if (likely(!list_empty(&pch->freelist))) { ++ desc = pdca_desc_entry(pch->freelist.next); ++ list_del(&desc->desc_node); ++ } ++ spin_unlock_bh(&pch->lock); ++ ++ return desc; ++} ++ ++static dma_cookie_t pdca_assign_cookie(struct pdca_chan *pch, ++ struct pdca_desc *desc) ++{ ++ dma_cookie_t cookie = pch->chan.cookie; ++ ++ if (++cookie < 0) ++ cookie = 1; ++ ++ pch->chan.cookie = cookie; ++ desc->txd.cookie = cookie; ++ ++ return cookie; ++} ++ ++static void pdca_desc_done(struct pdca_chan *pch, struct pdca_desc *desc) ++{ ++ struct dma_async_tx_descriptor *txd = &desc->txd; ++ dma_async_tx_callback callback; ++ void *param; ++ ++ pch->completed = txd->cookie; ++ callback = txd->callback; ++ param = txd->callback_param; ++ ++ dev_vdbg(&pch->chan.dev, " completed %u\n", txd->cookie); ++ ++ /* ++ * We can only handle scatterlists, so this is easy. No other ++ * drivers do the right thing with scatterlists though... ++ * ++ * Note that we ensure that at least one of these flags are ++ * set when the descriptor is prepared, as we never need to ++ * unmap the peripheral side. ++ */ ++ if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) ++ dma_unmap_sg(pch->chan.dev.parent, desc->sg, desc->sg_len, ++ DMA_FROM_DEVICE); ++ if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) ++ dma_unmap_sg(pch->chan.dev.parent, desc->sg, desc->sg_len, ++ DMA_TO_DEVICE); ++ ++ list_move(&desc->desc_node, &pch->freelist); ++ ++ if (callback) ++ callback(param); ++} ++ ++static void pdca_chan_tasklet(unsigned long param) ++{ ++ struct pdca_chan *pch = (struct pdca_chan *)param; ++ void __iomem *regs = pch->regs; ++ struct pdca_desc *cur; ++ struct pdca_desc *next; ++ struct scatterlist *cur_sg; ++ struct scatterlist *next_sg; ++ u32 intflags; ++ u32 status; ++ ++ spin_lock(&pch->lock); ++ ++ cur = pdca_desc_entry(pch->queue.next); ++ next = pdca_next_desc(pch, cur); ++ ++ cur_sg = pch->cur_sg; ++ next_sg = pch->next_sg; ++ ++ intflags = PDCA_TERR | PDCA_TRC | PDCA_RCZ; ++ ++ status = pdca_readl(regs, ISR); ++ dev_vdbg(&pch->chan.dev, "tasklet: status=%08x\n", status); ++ ++ if (status & PDCA_TRC) { ++ if (cur_sg) { ++ if (sg_is_last(cur_sg)) { ++ dev_vdbg(&pch->chan.dev, ++ " cur sg was last in %u\n", ++ cur->txd.cookie); ++ pdca_desc_done(pch, cur); ++ cur = next; ++ next = NULL; ++ } ++ if (next_sg && sg_is_last(next_sg)) { ++ dev_vdbg(&pch->chan.dev, ++ " next sg was last in %u\n", ++ cur->txd.cookie); ++ pdca_desc_done(pch, cur); ++ cur = next; ++ next = NULL; ++ } ++ if (!cur) { ++ dev_vdbg(&pch->chan.dev, " all done\n"); ++ pdca_writel(regs, CR, PDCA_CR_TDIS); ++ cur_sg = next_sg = NULL; ++ intflags = 0; ++ goto done; ++ } ++ cur_sg = next_sg ? sg_next(next_sg) : NULL; ++ } ++ ++ if (!cur_sg) { ++ dev_vdbg(&pch->chan.dev, " load sg from %u\n", ++ cur->txd.cookie); ++ cur_sg = cur->sg; ++ pdca_writel(regs, PSR, cur->periph_id); ++ pdca_writel(regs, MR, cur->reg_width); ++ } ++ dev_vdbg(&pch->chan.dev, " START: %08x count: %08x\n", ++ sg_dma_address(cur_sg), ++ sg_dma_len(cur_sg) >> cur->reg_width); ++ pdca_writel(regs, MAR, sg_dma_address(cur_sg)); ++ pdca_writel(regs, TCR, sg_dma_len(cur_sg) >> cur->reg_width); ++ ++ next_sg = sg_next(cur_sg); ++ if (!next_sg) { ++ next = pdca_next_desc(pch, cur); ++ if (next && next->reg_width == cur->reg_width ++ && next->periph_id == cur->periph_id) { ++ dev_vdbg(&pch->chan.dev, ++ "loading next_sg from %u\n", ++ next->txd.cookie); ++ next_sg = next->sg; ++ } ++ } ++ if (next_sg) { ++ dev_vdbg(&pch->chan.dev, " NEXT: %08x count: %08x\n", ++ sg_dma_address(next_sg), ++ sg_dma_len(next_sg) >> cur->reg_width); ++ pdca_writel(regs, MARR, sg_dma_address(next_sg)); ++ pdca_writel(regs, TCRR, ++ sg_dma_len(next_sg) >> cur->reg_width); ++ } else { ++ intflags &= ~PDCA_RCZ; ++ } ++ } else if (next_sg && (status & PDCA_RCZ)) { ++ if (sg_is_last(cur_sg)) { ++ dev_vdbg(&pch->chan.dev, " cur sg was last in %u\n", ++ cur->txd.cookie); ++ next = pdca_next_desc(pch, cur); ++ pdca_desc_done(pch, cur); ++ cur = next; ++ next = NULL; ++ } ++ ++ cur_sg = next_sg; ++ next_sg = sg_next(cur_sg); ++ if (!next_sg) { ++ next = pdca_next_desc(pch, cur); ++ if (next && next->reg_width == cur->reg_width ++ && next->periph_id == cur->periph_id) ++ next_sg = next->sg; ++ } ++ ++ if (next_sg) { ++ dev_vdbg(&pch->chan.dev, " NEXT: %08x count: %08x\n", ++ sg_dma_address(next_sg), ++ sg_dma_len(next_sg) >> cur->reg_width); ++ pdca_writel(regs, MARR, sg_dma_address(next_sg)); ++ pdca_writel(regs, TCRR, ++ sg_dma_len(next_sg) >> cur->reg_width); ++ } else { ++ dev_vdbg(&pch->chan.dev, " no next sg\n"); ++ intflags &= ~PDCA_RCZ; ++ } ++ } ++ ++done: ++ if (status & PDCA_TERR) { ++ /* ++ * Head of queue is busted. We must remove it, clear ++ * the error and restart the queue. ++ */ ++ pdca_writel(regs, TCRR, 0); ++ pdca_writel(regs, TCR, 0); ++ pdca_writel(regs, CR, PDCA_CR_ECLR); ++ cur_sg = next_sg = NULL; ++ ++ if (!cur) ++ dev_err(&pch->chan.dev, ++ "Transfer Error with empty queue\n"); ++ else { ++ dev_vdbg(&pch->chan.dev, ++ " %u is busted\n", cur->txd.cookie); ++ pdca_desc_done(pch, cur); ++ } ++ ++ if (list_empty(&pch->queue)) { ++ pdca_writel(regs, CR, PDCA_CR_TDIS); ++ intflags = 0; ++ } ++ } ++ ++ pch->cur_sg = cur_sg; ++ pch->next_sg = next_sg; ++ ++ dev_vdbg(&pch->chan.dev, " enabling interrupts: %08x\n", intflags); ++ pdca_writel(regs, IER, intflags); ++ pdca_readl(regs, SR); ++ ++ spin_unlock(&pch->lock); ++} ++ ++static irqreturn_t pdca_interrupt(int irq, void *dev_id) ++{ ++ struct pdca_dev *pdca = dev_id; ++ struct pdca_chan *pch; ++ void __iomem *regs; ++ unsigned long pending; ++ unsigned int chan; ++ ++ pending = intc_get_pending(irq); ++ if (unlikely(!pending)) ++ return IRQ_NONE; ++ ++ do { ++ chan = __ffs(pending); ++ pch = &pdca->chan[chan]; ++ regs = pch->regs; ++ pdca_writel(regs, IDR, ~0UL); ++ tasklet_schedule(&pch->tasklet); ++ pdca_readl(regs, IMR); ++ pending &= ~(1 << chan); ++ } while (pending); ++ ++ return IRQ_HANDLED; ++} ++ ++static dma_cookie_t pdca_tx_submit(struct dma_async_tx_descriptor *txd) ++{ ++ struct pdca_desc *desc = txd_to_pdca_desc(txd); ++ struct pdca_chan *pch = dma_to_pdca_chan(txd->chan); ++ void __iomem *regs = pch->regs; ++ dma_cookie_t cookie; ++ ++ spin_lock_bh(&pch->lock); ++ cookie = pdca_assign_cookie(pch, desc); ++ dev_vdbg(&pch->chan.dev, "submitted %u\n", cookie); ++ list_add_tail(&desc->desc_node, &pch->queue); ++ pdca_writel(regs, CR, PDCA_CR_TEN); ++ pdca_writel(regs, IER, PDCA_TERR | PDCA_RCZ); ++ /* The tasklet will kickstart the queue if necessary */ ++ spin_unlock_bh(&pch->lock); ++ ++ return cookie; ++} ++ ++static struct dma_async_tx_descriptor *pdca_prep_slave_sg(struct dma_chan *chan, ++ struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_data_direction direction, unsigned long flags) ++{ ++ struct pdca_chan *pch = dma_to_pdca_chan(chan); ++ struct pdca_slave *pslave = pch->pslave; ++ struct pdca_desc *desc; ++ unsigned int periph_id; ++ ++ dev_vdbg(&chan->dev, "prep_dma_slave: %s %u segments, flags: %lx\n", ++ direction == DMA_TO_DEVICE ? "OUT" : "IN", ++ sg_len, flags); ++ ++ switch (direction) { ++ case DMA_TO_DEVICE: ++ periph_id = pslave->tx_periph_id; ++ flags |= DMA_COMPL_SKIP_DEST_UNMAP; ++ break; ++ case DMA_FROM_DEVICE: ++ periph_id = pslave->rx_periph_id; ++ flags |= DMA_COMPL_SKIP_SRC_UNMAP; ++ break; ++ default: ++ return NULL; ++ } ++ ++ desc = pdca_desc_get(pch); ++ if (!desc) { ++ dev_err(&chan->dev, ++ "not enough descriptors available\n"); ++ return NULL; ++ } ++ desc->sg = sgl; ++ desc->sg_len = sg_len; ++ desc->periph_id = periph_id; ++ desc->reg_width = pslave->slave.reg_width; ++ desc->txd.flags = flags; ++ ++ return &desc->txd; ++} ++ ++static void pdca_terminate_all(struct dma_chan *chan) ++{ ++ struct pdca_chan *pch = dma_to_pdca_chan(chan); ++ struct pdca_desc *desc, *_desc; ++ void __iomem *regs = pch->regs; ++ ++ spin_lock_bh(&pch->lock); ++ pdca_writel(regs, CR, PDCA_CR_TDIS); ++ pdca_writel(regs, TCRR, 0); ++ pdca_writel(regs, TCR, 0); ++ while (pdca_readl(regs, SR) & PDCA_SR_TEN) ++ cpu_relax(); ++ ++ list_for_each_entry_safe(desc, _desc, &pch->queue, desc_node) ++ pdca_desc_done(pch, desc); ++ spin_unlock_bh(&pch->lock); ++} ++ ++static enum dma_status pdca_is_tx_complete(struct dma_chan *chan, ++ dma_cookie_t cookie, dma_cookie_t *done, dma_cookie_t *used) ++{ ++ struct pdca_chan *pch = dma_to_pdca_chan(chan); ++ dma_cookie_t last_used; ++ dma_cookie_t last_complete; ++ ++ last_complete = pch->completed; ++ last_used = chan->cookie; ++ ++ if (done) ++ *done = last_complete; ++ if (used) ++ *used = last_used; ++ ++ return dma_async_is_complete(cookie, last_complete, last_used); ++} ++ ++static void pdca_issue_pending(struct dma_chan *chan) ++{ ++ /* We always issue descriptors ASAP */ ++} ++ ++static int pdca_alloc_chan_resources(struct dma_chan *chan, ++ struct dma_client *client) ++{ ++ struct pdca_chan *pch = dma_to_pdca_chan(chan); ++ struct pdca_dev *pdca = dma_to_pdca_dev(chan->device); ++ struct dma_slave *slave = client->slave; ++ void __iomem *regs = pch->regs; ++ ++ /* ++ * Channels doing slave DMA can only handle one client. This ++ * controller can only do slave DMA. ++ */ ++ if (chan->client_count) ++ return -EBUSY; ++ if (!slave || !slave->dma_dev || slave->dma_dev != pdca->dma.dev) ++ return -EINVAL; ++ ++ if (pdca_readl(regs, SR) & PDCA_SR_TEN) ++ dev_err(&chan->dev, "DMA channel not idle!\n"); ++ ++ /* ++ * We may get called multiple times if a client rejects the ++ * channel... ++ */ ++ if (!pch->enabled) { ++ pch->enabled = true; ++ clk_enable(pdca->pclk); ++ clk_enable(pdca->hclk); ++ } ++ ++ pch->chan.cookie = pch->completed = 1; ++ pch->pslave = dma_to_pdca_slave(slave); ++ ++ while (pch->descs_allocated < NR_DESCS_PER_CHANNEL) { ++ struct pdca_desc *desc; ++ ++ desc = kzalloc(sizeof(struct pdca_desc), GFP_KERNEL); ++ if (!desc) { ++ dev_info(&chan->dev, "only allocated %d descriptors\n", ++ pch->descs_allocated); ++ break; ++ } ++ ++ dma_async_tx_descriptor_init(&desc->txd, chan); ++ desc->txd.tx_submit = pdca_tx_submit; ++ desc->txd.flags = DMA_CTRL_ACK; ++ INIT_LIST_HEAD(&desc->txd.tx_list); ++ list_add(&desc->desc_node, &pch->freelist); ++ pch->descs_allocated++; ++ } ++ ++ return pch->descs_allocated ? 0 : -ENOMEM; ++} ++ ++static void pdca_free_chan_resources(struct dma_chan *chan) ++{ ++ struct pdca_chan *pch = dma_to_pdca_chan(chan); ++ struct pdca_dev *pdca = dma_to_pdca_dev(chan->device); ++ struct pdca_desc *desc, *_desc; ++ ++ WARN_ON(!list_empty(&pch->queue)); ++ WARN_ON(pdca_readl(pch->regs, SR) & PDCA_SR_TEN); ++ WARN_ON(pdca_readl(pch->regs, IMR)); ++ ++ clk_disable(pdca->hclk); ++ clk_disable(pdca->pclk); ++ pch->enabled = false; ++ ++ list_for_each_entry_safe(desc, _desc, &pch->freelist, desc_node) { ++ list_del(&desc->desc_node); ++ kfree(desc); ++ } ++ ++ pch->descs_allocated = 0; ++} ++ ++static void pdca_suspend_channel(struct pdca_dev *pdca, struct pdca_chan *pch) ++{ ++ void __iomem *regs = pch->regs; ++ ++ /* ++ * REVISIT this whole business. ++ * ++ * The plan is to ensure that the PDCA doesn't do any bus ++ * transactions when we're suspended or shut down. Ideally, ++ * the client should make sure that all transfers have already ++ * been completed or terminated when we reach suspend_late(), ++ * but just in case that didn't happen, we should just stop ++ * the controller and turn it back on when resuming. Hopefully ++ * it will simply continue where it left off. ++ * ++ * We _probably_ need to save some sort of state to make this ++ * happen. Or we can just rely on interrupts being globally ++ * disabled at least until we reach resume_early. But that ++ * might not be the case for shutdown. ++ */ ++ tasklet_kill(&pch->tasklet); ++ spin_lock_bh(&pch->lock); ++ if (pdca_readl(regs, SR) & PDCA_SR_TEN) { ++ pdca_writel(regs, CR, PDCA_CR_TDIS); ++ while (pdca_readl(regs, SR) & PDCA_SR_TEN) ++ cpu_relax(); ++ ++ clk_disable(pdca->hclk); ++ clk_disable(pdca->pclk); ++ } ++ spin_unlock_bh(&pch->lock); ++} ++ ++static void __init pdca_init_channel(struct pdca_dev *pdca, unsigned int i) ++{ ++ struct pdca_chan *pch = &pdca->chan[i]; ++ ++ pch->chan.device = &pdca->dma; ++ pch->chan.chan_id = i; ++ pch->regs = pdca->regs + i * PDCA_CHAN_SIZE; ++ tasklet_init(&pch->tasklet, pdca_chan_tasklet, (unsigned long)pch); ++ spin_lock_init(&pch->lock); ++ INIT_LIST_HEAD(&pch->freelist); ++ INIT_LIST_HEAD(&pch->queue); ++ ++ list_add_tail(&pch->chan.device_node, &pdca->dma.channels); ++} ++ ++static int __init pdca_probe(struct platform_device *pdev) ++{ ++ struct pdca_pdata *pdata; ++ struct resource *mmio; ++ struct pdca_dev *pdca; ++ size_t mmio_len; ++ size_t size; ++ unsigned int i; ++ int irq; ++ int ret; ++ ++ pdata = pdev->dev.platform_data; ++ mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_irq(pdev, 0); ++ if (!pdata || pdata->nr_channels > 32 || !mmio || !irq) { ++ dev_dbg(&pdev->dev, "invalid params from platform code\n"); ++ return -EINVAL; ++ } ++ ++ mmio_len = mmio->end - mmio->start + 1; ++ if (!request_mem_region(mmio->start, mmio_len, "atmel_pdca")) { ++ dev_dbg(&pdev->dev, "mmio resource busy\n"); ++ return -EBUSY; ++ } ++ ++ size = sizeof(struct pdca_dev); ++ size += pdata->nr_channels * sizeof(struct pdca_chan); ++ pdca = kzalloc(size, GFP_KERNEL); ++ if (!pdca) { ++ dev_dbg(&pdev->dev, "insufficient memory\n"); ++ ret = -ENOMEM; ++ goto err_alloc_pdca; ++ } ++ ++ pdca->hclk = clk_get(&pdev->dev, "hclk"); ++ if (IS_ERR(pdca->hclk)) { ++ dev_dbg(&pdev->dev, "no HSB clock\n"); ++ ret = PTR_ERR(pdca->hclk); ++ goto err_get_hclk; ++ } ++ pdca->pclk = clk_get(&pdev->dev, "pclk"); ++ if (IS_ERR(pdca->pclk)) { ++ dev_dbg(&pdev->dev, "no PB clock\n"); ++ ret = PTR_ERR(pdca->pclk); ++ goto err_get_pclk; ++ } ++ ++ pdca->regs = ioremap(mmio->start, mmio_len); ++ if (!pdca->regs) { ++ dev_dbg(&pdev->dev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_ioremap; ++ } ++ ++ INIT_LIST_HEAD(&pdca->dma.channels); ++ for (i = 0; i < pdata->nr_channels; i++, pdca->dma.chancnt++) ++ pdca_init_channel(pdca, i); ++ ++ ret = request_irq(irq, pdca_interrupt, 0, pdev->dev.bus_id, pdca); ++ if (ret) { ++ dev_dbg(&pdev->dev, "request_irq failed\n"); ++ goto err_irq; ++ } ++ ++ dma_cap_set(DMA_SLAVE, pdca->dma.cap_mask); ++ pdca->dma.dev = &pdev->dev; ++ pdca->dma.device_alloc_chan_resources = pdca_alloc_chan_resources; ++ pdca->dma.device_free_chan_resources = pdca_free_chan_resources; ++ pdca->dma.device_prep_slave_sg = pdca_prep_slave_sg; ++ pdca->dma.device_terminate_all = pdca_terminate_all; ++ pdca->dma.device_is_tx_complete = pdca_is_tx_complete; ++ pdca->dma.device_issue_pending = pdca_issue_pending; ++ ++ platform_set_drvdata(pdev, pdca); ++ dma_async_device_register(&pdca->dma); ++ ++ dev_info(&pdev->dev, "Atmel PDCA at 0x%08lx (irq %d) %u channels\n", ++ (unsigned long)mmio->start, irq, pdca->dma.chancnt); ++ ++ return 0; ++ ++err_irq: ++ iounmap(pdca->regs); ++err_ioremap: ++ clk_put(pdca->pclk); ++err_get_pclk: ++ clk_put(pdca->hclk); ++err_get_hclk: ++ kfree(pdca); ++err_alloc_pdca: ++ release_resource(mmio); ++ return ret; ++} ++ ++static int __exit pdca_remove(struct platform_device *pdev) ++{ ++ struct pdca_dev *pdca = platform_get_drvdata(pdev); ++ struct pdca_chan *pch; ++ struct resource *mmio; ++ ++ list_for_each_entry(pch, &pdca->dma.channels, chan.device_node) ++ pdca_suspend_channel(pdca, pch); ++ ++ dma_async_device_unregister(&pdca->dma); ++ free_irq(platform_get_irq(pdev, 0), pdca); ++ clk_put(pdca->pclk); ++ clk_put(pdca->hclk); ++ iounmap(pdca->regs); ++ kfree(pdca); ++ ++ mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_resource(mmio); ++ ++ return 0; ++} ++ ++static void pdca_shutdown(struct platform_device *pdev) ++{ ++ struct pdca_dev *pdca = platform_get_drvdata(pdev); ++ struct pdca_chan *pch; ++ ++ list_for_each_entry(pch, &pdca->dma.channels, chan.device_node) ++ pdca_suspend_channel(pdca, pch); ++} ++ ++static int pdca_suspend_late(struct platform_device *pdev, pm_message_t state) ++{ ++ return 0; ++} ++ ++static int pdca_resume_early(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static struct platform_driver pdca_driver = { ++ .remove = __exit_p(pdca_remove), ++ .shutdown = pdca_shutdown, ++ .suspend_late = pdca_suspend_late, ++ .resume_early = pdca_resume_early, ++ .driver = { ++ .name = "atmel_pdca", ++ }, ++}; ++ ++static int __init pdca_init(void) ++{ ++ return platform_driver_probe(&pdca_driver, pdca_probe); ++} ++subsys_initcall(pdca_init); ++ ++static void __exit pdca_exit(void) ++{ ++ platform_driver_unregister(&pdca_driver); ++} ++module_exit(pdca_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Atmel PDCA DMA Controller driver"); ++MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>"); +diff -urN linux-2.6.28.2-0rig//drivers/dma/dw_dmac.c linux-2.6.28.2/drivers/dma/dw_dmac.c +--- linux-2.6.28.2-0rig//drivers/dma/dw_dmac.c 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/dma/dw_dmac.c 2009-01-29 08:52:50.000000000 +0100 +@@ -545,109 +545,51 @@ + return NULL; + } + +-static struct dma_async_tx_descriptor * +-dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, +- unsigned int sg_len, enum dma_data_direction direction, +- unsigned long flags) ++static struct dw_desc *dwc_init_slave_descs(struct dw_dma_chan *dwc, ++ struct scatterlist *sgl, unsigned int sg_len, ++ u32 ctllo, dma_addr_t src_reg, dma_addr_t dst_reg, ++ unsigned int reg_width, unsigned long flags) + { +- struct dw_dma_chan *dwc = to_dw_dma_chan(chan); +- struct dw_dma_slave *dws = dwc->dws; +- struct dw_desc *prev; +- struct dw_desc *first; +- u32 ctllo; +- dma_addr_t reg; +- unsigned int reg_width; +- unsigned int mem_width; +- unsigned int i; ++ struct dma_chan *chan = &dwc->chan; + struct scatterlist *sg; ++ struct dw_desc *desc; ++ struct dw_desc *first = NULL; ++ struct dw_desc *prev = NULL; ++ unsigned int align_mask; ++ unsigned int i; + size_t total_len = 0; + +- dev_vdbg(&chan->dev, "prep_dma_slave\n"); +- +- if (unlikely(!dws || !sg_len)) +- return NULL; +- +- reg_width = dws->slave.reg_width; +- prev = first = NULL; +- +- sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction); +- +- switch (direction) { +- case DMA_TO_DEVICE: +- ctllo = (DWC_DEFAULT_CTLLO +- | DWC_CTLL_DST_WIDTH(reg_width) +- | DWC_CTLL_DST_FIX +- | DWC_CTLL_SRC_INC +- | DWC_CTLL_FC_M2P); +- reg = dws->slave.tx_reg; +- for_each_sg(sgl, sg, sg_len, i) { +- struct dw_desc *desc; +- u32 len; +- u32 mem; ++ align_mask = (1 << reg_width) - 1; ++ for_each_sg(sgl, sg, sg_len, i) { ++ u32 len; ++ u32 desc_len; ++ u32 mem; ++ ++ mem = sg_phys(sg); ++ len = sg_dma_len(sg); ++ total_len += len; + ++ while (len) { ++ desc_len = min(len, DWC_MAX_COUNT << reg_width); + desc = dwc_desc_get(dwc); + if (!desc) { + dev_err(&chan->dev, + "not enough descriptors available\n"); + goto err_desc_get; + } ++ len -= desc_len; + +- mem = sg_phys(sg); +- len = sg_dma_len(sg); +- mem_width = 2; +- if (unlikely(mem & 3 || len & 3)) +- mem_width = 0; +- +- desc->lli.sar = mem; +- desc->lli.dar = reg; +- desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width); +- desc->lli.ctlhi = len >> mem_width; ++ if (unlikely((mem & align_mask) || (len & align_mask))) ++ goto err_align; + +- if (!first) { +- first = desc; +- } else { +- prev->lli.llp = desc->txd.phys; +- dma_sync_single_for_device(chan->dev.parent, +- prev->txd.phys, +- sizeof(prev->lli), +- DMA_TO_DEVICE); +- list_add_tail(&desc->desc_node, +- &first->txd.tx_list); +- } +- prev = desc; +- total_len += len; +- } +- break; +- case DMA_FROM_DEVICE: +- ctllo = (DWC_DEFAULT_CTLLO +- | DWC_CTLL_SRC_WIDTH(reg_width) +- | DWC_CTLL_DST_INC +- | DWC_CTLL_SRC_FIX +- | DWC_CTLL_FC_P2M); +- +- reg = dws->slave.rx_reg; +- for_each_sg(sgl, sg, sg_len, i) { +- struct dw_desc *desc; +- u32 len; +- u32 mem; +- +- desc = dwc_desc_get(dwc); +- if (!desc) { +- dev_err(&chan->dev, +- "not enough descriptors available\n"); +- goto err_desc_get; +- } +- +- mem = sg_phys(sg); +- len = sg_dma_len(sg); +- mem_width = 2; +- if (unlikely(mem & 3 || len & 3)) +- mem_width = 0; +- +- desc->lli.sar = reg; +- desc->lli.dar = mem; +- desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width); +- desc->lli.ctlhi = len >> reg_width; ++ desc->lli.sar = src_reg ? src_reg : mem; ++ desc->lli.dar = dst_reg ? dst_reg : mem; ++ desc->lli.ctllo = ctllo; ++ desc->lli.ctlhi = desc_len >> reg_width; ++ dev_vdbg(&dwc->chan.dev, ++ " s%08x d%08x c%08x:%08x\n", ++ desc->lli.sar, desc->lli.dar, ++ ctllo, desc_len >> reg_width); + + if (!first) { + first = desc; +@@ -661,11 +603,8 @@ + &first->txd.tx_list); + } + prev = desc; +- total_len += len; ++ mem += desc_len; + } +- break; +- default: +- return NULL; + } + + if (flags & DMA_PREP_INTERRUPT) +@@ -679,13 +618,69 @@ + + first->len = total_len; + +- return &first->txd; ++ return first; + ++err_align: ++ dwc_desc_put(dwc, desc); + err_desc_get: + dwc_desc_put(dwc, first); + return NULL; + } + ++static struct dma_async_tx_descriptor * ++dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_data_direction direction, ++ unsigned long flags) ++{ ++ struct dw_dma_chan *dwc = to_dw_dma_chan(chan); ++ struct dw_dma_slave *dws = dwc->dws; ++ struct dw_desc *first; ++ u32 ctllo; ++ unsigned int reg_width; ++ ++ dev_vdbg(&chan->dev, "prep_dma_slave: %s %u segments, flags: %lx\n", ++ direction == DMA_TO_DEVICE ? "OUT" : "IN", ++ sg_len, flags); ++ ++ if (unlikely(!dws || !sg_len)) ++ return NULL; ++ ++ reg_width = dws->slave.reg_width; ++ sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction); ++ ++ switch (direction) { ++ case DMA_TO_DEVICE: ++ ctllo = (DWC_DEFAULT_CTLLO ++ | DWC_CTLL_DST_WIDTH(reg_width) ++ | DWC_CTLL_SRC_WIDTH(reg_width) ++ | DWC_CTLL_DST_FIX ++ | DWC_CTLL_SRC_INC ++ | DWC_CTLL_FC_M2P); ++ first = dwc_init_slave_descs(dwc, sgl, sg_len, ctllo, ++ 0, dws->slave.tx_reg, reg_width, flags); ++ break; ++ case DMA_FROM_DEVICE: ++ ctllo = (DWC_DEFAULT_CTLLO ++ | DWC_CTLL_SRC_WIDTH(reg_width) ++ | DWC_CTLL_DST_WIDTH(reg_width) ++ | DWC_CTLL_DST_INC ++ | DWC_CTLL_SRC_FIX ++ | DWC_CTLL_FC_P2M); ++ first = dwc_init_slave_descs(dwc, sgl, sg_len, ctllo, ++ dws->slave.rx_reg, 0, reg_width, flags); ++ break; ++ default: ++ return NULL; ++ } ++ ++ if (unlikely(!first)) { ++ dma_unmap_sg(chan->dev.parent, sgl, sg_len, direction); ++ return NULL; ++ } ++ ++ return &first->txd; ++} ++ + static void dwc_terminate_all(struct dma_chan *chan) + { + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); +@@ -1109,7 +1104,7 @@ + { + return platform_driver_probe(&dw_driver, dw_probe); + } +-module_init(dw_init); ++subsys_initcall(dw_init); + + static void __exit dw_exit(void) + { +diff -urN linux-2.6.28.2-0rig//drivers/dma/Kconfig linux-2.6.28.2/drivers/dma/Kconfig +--- linux-2.6.28.2-0rig//drivers/dma/Kconfig 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/dma/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -38,6 +38,20 @@ + help + Enable support for the Intel(R) IOP Series RAID engines. + ++config ATMEL_PDCA ++ tristate "Atmel Peripheral DMA Controller A support" ++ depends on AVR32 ++ select DMA_ENGINE ++ default y if CPU_AT32AP7200 ++ help ++ Support the Atmel Peripheral DMA Controller found on AVR32 ++ UC3 chips as well as newer AP7 chips. This controller is ++ similar to the PDC found on AT32AP7000 and various AT91 ++ chips, but has its own register bank. ++ ++ This controller only supports peripheral (slave) transfers, ++ not memory-to-memory transfers. ++ + config DW_DMAC + tristate "Synopsys DesignWare AHB DMA support" + depends on AVR32 +diff -urN linux-2.6.28.2-0rig//drivers/dma/Makefile linux-2.6.28.2/drivers/dma/Makefile +--- linux-2.6.28.2-0rig//drivers/dma/Makefile 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/dma/Makefile 2009-01-29 08:52:50.000000000 +0100 +@@ -4,6 +4,7 @@ + obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o + ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o + obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o ++obj-$(CONFIG_ATMEL_PDCA) += atmel_pdca.o + obj-$(CONFIG_FSL_DMA) += fsldma.o + obj-$(CONFIG_MV_XOR) += mv_xor.o + obj-$(CONFIG_DW_DMAC) += dw_dmac.o +diff -urN linux-2.6.28.2-0rig//drivers/mmc/host/atmel-mci-regs.h linux-2.6.28.2/drivers/mmc/host/atmel-mci-regs.h +--- linux-2.6.28.2-0rig//drivers/mmc/host/atmel-mci-regs.h 2009-01-29 08:39:27.000000000 +0100 ++++ linux-2.6.28.2/drivers/mmc/host/atmel-mci-regs.h 2009-01-29 08:52:50.000000000 +0100 +@@ -10,13 +10,21 @@ + #ifndef __DRIVERS_MMC_ATMEL_MCI_H__ + #define __DRIVERS_MMC_ATMEL_MCI_H__ + +-/* MCI Register Definitions */ ++/* ++ * MCI Register Definitions. Registers and bitfields marked with [2] ++ * are only available in MCI2. ++ */ + #define MCI_CR 0x0000 /* Control */ + # define MCI_CR_MCIEN ( 1 << 0) /* MCI Enable */ + # define MCI_CR_MCIDIS ( 1 << 1) /* MCI Disable */ ++# define MCI_CR_PWSEN ( 1 << 2) /* Powersave Enable[2] */ ++# define MCI_CR_PWSDIS ( 1 << 3) /* Powersave Disable[2] */ ++# define MCI_CR_IOWAITEN ( 1 << 4) /* SDIO Read Wait Enable[2] */ ++# define MCI_CR_IOWAITDIS ( 1 << 5) /* SDIO Read Wait Disable[2] */ + # define MCI_CR_SWRST ( 1 << 7) /* Software Reset */ + #define MCI_MR 0x0004 /* Mode */ + # define MCI_MR_CLKDIV(x) ((x) << 0) /* Clock Divider */ ++# define MCI_MR_PWSDIV(x) ((x) << 8) /* Powersave Divider[2] */ + # define MCI_MR_RDPROOF ( 1 << 11) /* Read Proof */ + # define MCI_MR_WRPROOF ( 1 << 12) /* Write Proof */ + #define MCI_DTOR 0x0008 /* Data Timeout */ +@@ -56,6 +64,9 @@ + #define MCI_BLKR 0x0018 /* Block */ + # define MCI_BCNT(x) ((x) << 0) /* Data Block Count */ + # define MCI_BLKLEN(x) ((x) << 16) /* Data Block Length */ ++#define MCI_CSTOR 0x001c /* Completion Signal Timeout[2] */ ++# define MCI_CSTOCYC(x) ((x) << 0) /* CST cycles */ ++# define MCI_CSTOMUL(x) ((x) << 4) /* CST multiplier */ + #define MCI_RSPR 0x0020 /* Response 0 */ + #define MCI_RSPR1 0x0024 /* Response 1 */ + #define MCI_RSPR2 0x0028 /* Response 2 */ +@@ -66,24 +77,45 @@ + #define MCI_IER 0x0044 /* Interrupt Enable */ + #define MCI_IDR 0x0048 /* Interrupt Disable */ + #define MCI_IMR 0x004c /* Interrupt Mask */ +-# define MCI_CMDRDY ( 1 << 0) /* Command Ready */ +-# define MCI_RXRDY ( 1 << 1) /* Receiver Ready */ +-# define MCI_TXRDY ( 1 << 2) /* Transmitter Ready */ +-# define MCI_BLKE ( 1 << 3) /* Data Block Ended */ +-# define MCI_DTIP ( 1 << 4) /* Data Transfer In Progress */ +-# define MCI_NOTBUSY ( 1 << 5) /* Data Not Busy */ +-# define MCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */ +-# define MCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */ +-# define MCI_RINDE ( 1 << 16) /* Response Index Error */ +-# define MCI_RDIRE ( 1 << 17) /* Response Direction Error */ +-# define MCI_RCRCE ( 1 << 18) /* Response CRC Error */ +-# define MCI_RENDE ( 1 << 19) /* Response End Bit Error */ +-# define MCI_RTOE ( 1 << 20) /* Response Time-Out Error */ +-# define MCI_DCRCE ( 1 << 21) /* Data CRC Error */ +-# define MCI_DTOE ( 1 << 22) /* Data Time-Out Error */ +-# define MCI_OVRE ( 1 << 30) /* RX Overrun Error */ +-# define MCI_UNRE ( 1 << 31) /* TX Underrun Error */ ++# define MCI_CMDRDY ( 1 << 0) /* Command Ready */ ++# define MCI_RXRDY ( 1 << 1) /* Receiver Ready */ ++# define MCI_TXRDY ( 1 << 2) /* Transmitter Ready */ ++# define MCI_BLKE ( 1 << 3) /* Data Block Ended */ ++# define MCI_DTIP ( 1 << 4) /* Data Transfer In Progress */ ++# define MCI_NOTBUSY ( 1 << 5) /* Data Not Busy */ ++# define MCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */ ++# define MCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */ ++# define MCI_RINDE ( 1 << 16) /* Response Index Error */ ++# define MCI_RDIRE ( 1 << 17) /* Response Direction Error */ ++# define MCI_RCRCE ( 1 << 18) /* Response CRC Error */ ++# define MCI_RENDE ( 1 << 19) /* Response End Bit Error */ ++# define MCI_RTOE ( 1 << 20) /* Response Time-Out Error */ ++# define MCI_DCRCE ( 1 << 21) /* Data CRC Error */ ++# define MCI_DTOE ( 1 << 22) /* Data Time-Out Error */ ++# define MCI_OVRE ( 1 << 30) /* RX Overrun Error */ ++# define MCI_UNRE ( 1 << 31) /* TX Underrun Error */ ++#define MCI_DMA 0x0050 /* DMA Configuration[2] */ ++# define MCI_DMA_OFFSET(x) ((x) << 0) /* DMA write buffer offset */ ++# define MCI_DMA_CHKSIZE_1 ( 0 << 5) /* DMA chunk size */ ++# define MCI_DMA_CHKSIZE_4 ( 1 << 5) /* DMA chunk size */ ++# define MCI_DMA_CHKSIZE_8 ( 2 << 5) /* DMA chunk size */ ++# define MCI_DMA_CHKSIZE_16 ( 3 << 5) /* DMA chunk size */ ++# define MCI_DMAEN ( 1 << 8) /* DMA HW handshake enable */ ++#define MCI_CFG 0x0054 /* Configuration[2] */ ++# define MCI_CFG_FIFOMODE ( 1 << 0) /* Start transfer ASAP */ ++# define MCI_CFG_FERRCTRL ( 1 << 4) /* xrun flags clear-on-read */ ++# define MCI_CFG_HSMODE ( 1 << 8) /* Use high-speed signaling */ ++# define MCI_CFG_LSYNC ( 1 << 12) /* Synchronize on last block */ ++#define MCI_WPMR 0x00e4 /* Write Protect Mode[2] */ ++# define MCI_WP_EN ( 1 << 0) /* WP Enable */ ++# define MCI_WP_KEY (0x4d4349 << 8) /* WP Key */ ++#define MCI_WPSR 0x00e8 /* Write Protect Status[2] */ ++# define MCI_GET_WP_VS(x) ((x) & 0x0f) ++# define MCI_GET_WP_VSRC(x) (((x) >> 8) & 0xffff) ++#define MCI_VERSION 0x00fc /* MCI Core Version[2] */ ++#define MCI_FIFO_APERTURE 0x0200 /* FIFO Aperture[2] */ + ++/* This is not including the FIFO Aperture on MCI2 */ + #define MCI_REGS_SIZE 0x100 + + /* Register access macros */ +diff -urN linux-2.6.28.2-0rig//drivers/mmc/host/Kconfig linux-2.6.28.2/drivers/mmc/host/Kconfig +--- linux-2.6.28.2-0rig//drivers/mmc/host/Kconfig 2009-01-29 08:39:27.000000000 +0100 ++++ linux-2.6.28.2/drivers/mmc/host/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -125,6 +125,17 @@ + + If unsure, say N. + ++config MMC_ATMELMCI_DMA ++ bool "Atmel MCI DMA support (EXPERIMENTAL)" ++ depends on MMC_ATMELMCI && DMA_ENGINE && EXPERIMENTAL ++ help ++ Say Y here to have the Atmel MCI driver use a DMA engine to ++ do data transfers and thus increase the throughput and ++ reduce the CPU utilization. Note that this is highly ++ experimental and may cause the driver to lock up. ++ ++ If unsure, say N. ++ + config MMC_IMX + tristate "Motorola i.MX Multimedia Card Interface support" + depends on ARCH_IMX +diff -urN linux-2.6.28.2-0rig//drivers/mtd/nand/atmel_nand.c linux-2.6.28.2/drivers/mtd/nand/atmel_nand.c +--- linux-2.6.28.2-0rig//drivers/mtd/nand/atmel_nand.c 2009-01-29 08:39:27.000000000 +0100 ++++ linux-2.6.28.2/drivers/mtd/nand/atmel_nand.c 2009-01-29 08:52:50.000000000 +0100 +@@ -456,7 +456,7 @@ + platform_set_drvdata(pdev, host); + atmel_nand_enable(host); + +- if (host->board->det_pin) { ++ if (gpio_is_valid(host->board->det_pin)) { + if (gpio_get_value(host->board->det_pin)) { + printk("No SmartMedia card inserted.\n"); + res = ENXIO; +diff -urN linux-2.6.28.2-0rig//drivers/rtc/Kconfig linux-2.6.28.2/drivers/rtc/Kconfig +--- linux-2.6.28.2-0rig//drivers/rtc/Kconfig 2009-01-29 08:39:30.000000000 +0100 ++++ linux-2.6.28.2/drivers/rtc/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -633,6 +633,22 @@ + will be used. The default of zero is normally OK to use, but + on some systems other software needs to use that register. + ++config RTC_DRV_AVR32_AST ++ tristate "AVR32 Asynchronous Timer" ++ depends on AVR32 ++ help ++ RTC driver for the AVR32 Asynchronous Timers. The AST is a ++ simple and flexible timer that can be used both as a ++ high-resolution system timer and an RTC, depending on what ++ clock source it is running from. ++ ++ If you say yes here, and add one or more platform_device ++ called "rtc-ast", those devices will be clocked from a ++ 32.768 kHz crystal oscillator and used as RTCs. ++ ++ This driver can also be built as a module. If so, the module ++ will be called rtc-ast. ++ + config RTC_DRV_BFIN + tristate "Blackfin On-Chip RTC" + depends on BLACKFIN && !BF561 +diff -urN linux-2.6.28.2-0rig//drivers/rtc/Makefile linux-2.6.28.2/drivers/rtc/Makefile +--- linux-2.6.28.2-0rig//drivers/rtc/Makefile 2009-01-29 08:39:30.000000000 +0100 ++++ linux-2.6.28.2/drivers/rtc/Makefile 2009-01-29 08:52:50.000000000 +0100 +@@ -20,6 +20,7 @@ + obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o + obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o + obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o ++obj-$(CONFIG_RTC_DRV_AVR32_AST) += rtc-ast.o + obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o + obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o + obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o +diff -urN linux-2.6.28.2-0rig//drivers/rtc/rtc-ast.c linux-2.6.28.2/drivers/rtc/rtc-ast.c +--- linux-2.6.28.2-0rig//drivers/rtc/rtc-ast.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/drivers/rtc/rtc-ast.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,546 @@ ++/* ++ * An RTC driver for the AVR32 Asynchronous Timer ++ * ++ * Copyright (C) 2008 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 <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/rtc.h> ++ ++#include <asm/ast_regs.h> ++ ++/* ++ * The AST - ASynchronous Timer - is built around a simple cycle ++ * counter that can be driven from one of four selectable clocks with ++ * a selectable power-of-two prescaler. It also has two alarms (ALARM0 ++ * and ALARM1) and two periodic event generators (PER0 and PER1). The ++ * latter can be driven by different tappings of the same prescaler ++ * that drives the counter. ++ * ++ * This driver uses the 32.768 kHz crystal oscillator as a clock ++ * source and a prescaler that gives a 1 Hz counter frequency. It uses ++ * ALARM0 to support both "old-school" and "wake" alarms, PER0 to ++ * support periodic interrupts (PIE) up to 16.384 kHz (at power-of-two ++ * intervals), and PER1 to support a 1 Hz update interrupt (UIE). ++ * ++ * Watchdog interrupts seem to be undocumented and unsupported by ++ * everyone else, so those are not supported for now. ++ * ++ * The AST can wake the system from any sleep mode given that the ++ * source clock is running. On AT32AP720x, the 32.768 kHz crystal ++ * oscillator runs in all sleep modes except "static" and "shutdown". ++ */ ++ ++/* 32768 Hz means up to 60 us for synchronization + a bit of slack */ ++#define AST_SYNC_TIMEOUT_US 100 ++ ++#define AST_CLK_RATE 32768 ++#define AST_1S_PRESCALER 14 /* log2(32768) - 1 */ ++ ++struct rtc_ast { ++ /* Protects I/O registers */ ++ spinlock_t lock; ++ ++ struct rtc_device *rtc; ++ void __iomem *regs; ++ struct clk *osc32; ++ struct clk *pclk; ++}; ++ ++/* ++ * Because the AST is, well, asynchronous, we must make sure we don't ++ * write to certain registers while the previous write is being ++ * synchronized between clock domains. This affects writes to CR, CV, ++ * SCR, WER, PIRx and ARx. To keep the delays minimal, we always ++ * synchronize _before_ writes to these registers. ++ * ++ * This function is also used to synchronize when changing the clock ++ * source, using a different bit in the status register. ++ */ ++static int ast_wait_ready(void __iomem *regs, unsigned int busy_mask) ++{ ++ unsigned long timeout = AST_SYNC_TIMEOUT_US; ++ ++ while (ast_readl(regs, SR) & busy_mask) { ++ udelay(1); ++ if (--timeout == 0) ++ return -ETIMEDOUT; ++ cpu_relax(); ++ } ++ ++ return 0; ++} ++ ++static void rtc_ast_release(struct device *dev) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ ++ /* Disable all interrupts */ ++ clk_enable(ast->pclk); ++ ast_writel(ast->regs, IDR, ~0UL); ++ clk_disable(ast->pclk); ++} ++ ++static int rtc_ast_ioctl(struct device *dev, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ clk_enable(ast->pclk); ++ ++ switch (cmd) { ++ /* REVISIT: Should perhaps verify that irq_task is NULL */ ++ case RTC_AIE_ON: ++ ast_writel(ast->regs, IER, AST_BIT(ALARM0)); ++ break; ++ case RTC_AIE_OFF: ++ ast_writel(ast->regs, IDR, AST_BIT(ALARM0)); ++ break; ++ case RTC_UIE_ON: ++ spin_lock_irq(&ast->lock); ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (!ret) { ++ ast_writel(ast->regs, SCR, AST_BIT(PER1)); ++ ast_writel(ast->regs, IER, AST_BIT(PER1)); ++ } ++ spin_unlock_irq(&ast->lock); ++ ++ break; ++ case RTC_UIE_OFF: ++ ast_writel(ast->regs, IDR, AST_BIT(PER1)); ++ break; ++#if 0 ++ case RTC_PIE_ON: ++ spin_lock_irq(&ast->lock); ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (ret) ++ break; ++ ast_writel(ast->regs, SCR, AST_BIT(PER0)); ++ spin_unlock_irq(&ast->lock); ++ ++ ast_writel(ast->regs, IER, AST_BIT(PER0)); ++ break; ++ case RTC_PIE_OFF: ++ ast_writel(ast->regs, IDR, AST_BIT(PER1)); ++ break; ++#endif ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ ++ clk_disable(ast->pclk); ++ ++ return ret; ++} ++ ++static int rtc_ast_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ ++ clk_enable(ast->pclk); ++ rtc_time_to_tm(ast_readl(ast->regs, CV), tm); ++ clk_disable(ast->pclk); ++ ++ return 0; ++} ++ ++static int rtc_ast_set_mmss(struct device *dev, unsigned long secs) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ int ret; ++ ++ clk_enable(ast->pclk); ++ ++ spin_lock_irq(&ast->lock); ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (!ret) ++ ast_writel(ast->regs, CV, secs); ++ spin_unlock_irq(&ast->lock); ++ ++ clk_disable(ast->pclk); ++ ++ return ret; ++} ++ ++static int rtc_ast_set_time(struct device *dev, struct rtc_time *tm) ++{ ++ unsigned long secs; ++ int ret; ++ ++ ret = rtc_tm_to_time(tm, &secs); ++ if (!ret) ++ ret = rtc_ast_set_mmss(dev, secs); ++ ++ return ret; ++} ++ ++static int rtc_ast_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ ++ clk_enable(ast->pclk); ++ ++ spin_lock_irq(&ast->lock); ++ rtc_time_to_tm(ast_readl(ast->regs, AR0), &alrm->time); ++ alrm->enabled = !!(ast_readl(ast->regs, IMR) & AST_BIT(ALARM0)); ++ alrm->pending = !!(ast_readl(ast->regs, SR) & AST_BIT(ALARM0)); ++ spin_unlock_irq(&ast->lock); ++ ++ clk_disable(ast->pclk); ++ ++ return 0; ++} ++ ++static int rtc_ast_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ unsigned long seconds; ++ int ret; ++ ++ ret = rtc_tm_to_time(&alrm->time, &seconds); ++ if (ret) ++ return ret; ++ ++ clk_enable(ast->pclk); ++ ++ /* ++ * REVISIT: The alarm may trigger before we are done here. ++ * Who's responsible for handling that? ++ * ++ * We don't want to clear the ALARM0 flag before we update AR0 ++ * because the previous value of AR0 might trigger an alarm ++ * right after we clear the flag. ++ */ ++ spin_lock_irq(&ast->lock); ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (ret) ++ goto unlock; ++ ast_writel(ast->regs, AR0, seconds); ++ ++ /* Try to avoid synchronization penalty */ ++ if (ast_readl(ast->regs, SR) & AST_BIT(ALARM0)) { ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (ret) ++ goto unlock; ++ ast_writel(ast->regs, SCR, AST_BIT(ALARM0)); ++ } ++ ++ if (alrm->enabled) ++ ast_writel(ast->regs, IER, AST_BIT(ALARM0)); ++ ++unlock: ++ spin_unlock_irq(&ast->lock); ++ clk_disable(ast->pclk); ++ ++ return ret; ++} ++ ++static int rtc_ast_proc(struct device *dev, struct seq_file *seq) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ u32 imr; ++ ++ clk_enable(ast->pclk); ++ imr = ast_readl(ast->regs, IMR); ++ clk_disable(ast->pclk); ++ ++ return seq_printf(seq, ++ "periodic_IRQ\t: %s\n" ++ "update_IRQ\t: %s\n" ++ "periodic_freq\t: %d\n", ++ (imr & AST_BIT(PER0)) ? "yes" : "no", ++ (imr & AST_BIT(PER1)) ? "yes" : "no", ++ ast->rtc->irq_freq); ++} ++ ++static int rtc_ast_irq_set_freq(struct device *dev, int freq) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ unsigned int pres_bit; ++ int ret; ++ ++ /* RTC core currently ensures this. */ ++ BUG_ON(!freq); ++ ++ pres_bit = __ffs(freq); ++ if (pres_bit > AST_1S_PRESCALER) ++ return -EINVAL; ++ pres_bit = AST_1S_PRESCALER - pres_bit; ++ ++ clk_enable(ast->pclk); ++ ++ spin_lock_irq(&ast->lock); ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (ret) ++ goto unlock; ++ ++ ast_writel(ast->regs, PIR0, pres_bit); ++ ++unlock: ++ spin_unlock_irq(&ast->lock); ++ clk_disable(ast->pclk); ++ ++ return ret; ++} ++ ++static int rtc_ast_irq_set_state(struct device *dev, int enabled) ++{ ++ struct rtc_ast *ast = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ clk_enable(ast->pclk); ++ ++ if (enabled) { ++ spin_lock_irq(&ast->lock); ++ ret = ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ if (!ret) { ++ ast_writel(ast->regs, SCR, AST_BIT(PER0)); ++ ast_writel(ast->regs, IER, AST_BIT(PER0)); ++ } ++ spin_unlock_irq(&ast->lock); ++ } else { ++ ast_writel(ast->regs, IDR, AST_BIT(PER1)); ++ } ++ ++ clk_disable(ast->pclk); ++ ++ return ret; ++} ++ ++static const struct rtc_class_ops rtc_ast_ops = { ++ .release = rtc_ast_release, ++ .ioctl = rtc_ast_ioctl, ++ .read_time = rtc_ast_read_time, ++ .set_time = rtc_ast_set_time, ++ .read_alarm = rtc_ast_read_alarm, ++ .set_alarm = rtc_ast_set_alarm, ++ .proc = rtc_ast_proc, ++ .set_mmss = rtc_ast_set_mmss, ++ .irq_set_freq = rtc_ast_irq_set_freq, ++ .irq_set_state = rtc_ast_irq_set_state, ++}; ++ ++static irqreturn_t rtc_ast_interrupt(int irq, void *dev_id) ++{ ++ struct rtc_ast *ast = dev_id; ++ unsigned long events; ++ unsigned long num; ++ u32 status; ++ u32 pending; ++ irqreturn_t ret = IRQ_NONE; ++ ++ clk_enable(ast->pclk); ++ spin_lock(&ast->lock); ++ ++ status = ast_readl(ast->regs, SR); ++ pending = status & ast_readl(ast->regs, IMR); ++ if (unlikely(!pending)) ++ goto out; ++ ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ ast_writel(ast->regs, SCR, pending); ++ ++ events = RTC_IRQF; ++ num = 0; ++ if (pending & AST_BIT(ALARM0)) { ++ num++; ++ events |= RTC_AF; ++ } ++ if (pending & AST_BIT(PER0)) { ++ num++; ++ events |= RTC_PF; ++ } ++ if (pending & AST_BIT(PER1)) { ++ num++; ++ events |= RTC_UF; ++ } ++ ++ rtc_update_irq(ast->rtc, num, events); ++ ret = IRQ_HANDLED; ++ ++out: ++ spin_unlock(&ast->lock); ++ clk_disable(ast->pclk); ++ ++ return IRQ_HANDLED; ++} ++ ++static int __init rtc_ast_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ struct rtc_ast *ast; ++ int irq; ++ int ret; ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_dbg(&pdev->dev, "no mmio resource\n"); ++ return -ENXIO; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_dbg(&pdev->dev, "no irq\n"); ++ return -ENXIO; ++ } ++ ++ ast = kzalloc(sizeof(struct rtc_ast), GFP_KERNEL); ++ if (!ast) { ++ dev_dbg(&pdev->dev, "out of memory\n"); ++ return -ENOMEM; ++ } ++ ++ ast->osc32 = clk_get(NULL, "osc32k"); ++ if (IS_ERR(ast->osc32)) { ++ ret = PTR_ERR(ast->osc32); ++ dev_dbg(&pdev->dev, "no 32 kHz oscillator\n"); ++ goto err_osc32; ++ } ++ ++ ast->pclk = clk_get(&pdev->dev, "pclk"); ++ if (IS_ERR(ast->pclk)) { ++ ret = PTR_ERR(ast->pclk); ++ dev_dbg(&pdev->dev, "no peripheral clock\n"); ++ goto err_pclk; ++ } ++ ++ spin_lock_init(&ast->lock); ++ ++ ast->regs = ioremap(regs->start, regs->end - regs->start + 1); ++ if (!ast->regs) { ++ dev_dbg(&pdev->dev, "failed to map registers\n"); ++ ret = -ENOMEM; ++ goto err_ioremap; ++ } ++ ++ clk_enable(ast->osc32); ++ clk_enable(ast->pclk); ++ ++ /* Initialize the AST if it isn't running already */ ++ if (!(ast_readl(ast->regs, CR) & AST_BIT(CR_EN))) { ++ ast_wait_ready(ast->regs, AST_BIT(CLK_BUSY)); ++ ast_writel(ast->regs, CLOCK, ++ AST_BF(CLOCK_CSSEL, AST_CLOCK_OSC32) ++ | AST_BIT(CLOCK_CEN)); ++ ret = ast_wait_ready(ast->regs, AST_BIT(CLK_BUSY)); ++ if (ret) { ++ dev_dbg(&pdev->dev, ++ "timed out selecting clock source\n"); ++ goto err_clksel; ++ } ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ ast_writel(ast->regs, CV, 0); ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ ast_writel(ast->regs, CR, AST_BIT(CR_EN) | AST_BIT(CR_PCLR) ++ | AST_BF(CR_PSEL, AST_1S_PRESCALER)); ++ } ++ ++ ast_writel(ast->regs, IDR, ~0UL); ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ ast_writel(ast->regs, WER, 0); ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ ast_writel(ast->regs, PIR0, AST_1S_PRESCALER); ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ ast_writel(ast->regs, PIR1, AST_1S_PRESCALER); ++ ++ ret = request_irq(irq, rtc_ast_interrupt, 0, "rtc-ast", ast); ++ if (ret) { ++ dev_dbg(&pdev->dev, "could not request irq %d\n", irq); ++ goto err_request_irq; ++ } ++ ++ ast->rtc = rtc_device_register("rtc-ast", &pdev->dev, ++ &rtc_ast_ops, THIS_MODULE); ++ if (IS_ERR(ast->rtc)) { ++ dev_dbg(&pdev->dev, "could not register rtc device\n"); ++ ret = PTR_ERR(ast->rtc); ++ goto err_register; ++ } ++ ++ ast->rtc->max_user_freq = AST_CLK_RATE / 2; ++ ast->rtc->irq_freq = 1; ++ ++ ast_wait_ready(ast->regs, AST_BIT(BUSY)); ++ clk_disable(ast->pclk); ++ platform_set_drvdata(pdev, ast); ++ device_init_wakeup(&pdev->dev, 1); ++ ++ dev_info(&pdev->dev, "AVR32 Asynchronous Timer at %08lx irq %d\n", ++ (unsigned long)regs->start, irq); ++ ++ return 0; ++ ++err_register: ++ free_irq(irq, ast); ++err_request_irq: ++err_clksel: ++ clk_disable(ast->pclk); ++ clk_disable(ast->osc32); ++ iounmap(ast->regs); ++err_ioremap: ++ clk_put(ast->pclk); ++err_pclk: ++ clk_put(ast->osc32); ++err_osc32: ++ kfree(ast); ++ return ret; ++} ++ ++static int __exit rtc_ast_remove(struct platform_device *pdev) ++{ ++ struct rtc_ast *ast = platform_get_drvdata(pdev); ++ ++ device_init_wakeup(&pdev->dev, 0); ++ ++ clk_enable(ast->pclk); ++ ast_writel(ast->regs, IDR, ~0UL); ++ ast_readl(ast->regs, IMR); ++ clk_disable(ast->pclk); ++ ++ free_irq(platform_get_irq(pdev, 0), ast); ++ rtc_device_unregister(ast->rtc); ++ clk_disable(ast->osc32); ++ iounmap(ast->regs); ++ clk_put(ast->pclk); ++ clk_put(ast->osc32); ++ kfree(ast); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver rtc_ast_driver = { ++ .remove = __exit_p(rtc_ast_remove), ++ .driver = { ++ .name = "rtc-ast", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init rtc_ast_init(void) ++{ ++ return platform_driver_probe(&rtc_ast_driver, rtc_ast_probe); ++} ++module_init(rtc_ast_init); ++ ++static void __exit rtc_ast_exit(void) ++{ ++ platform_driver_unregister(&rtc_ast_driver); ++} ++module_exit(rtc_ast_exit); ++ ++MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>"); ++MODULE_DESCRIPTION("AVR32 Asynchronous Timer RTC"); ++MODULE_LICENSE("GPL"); +diff -urN linux-2.6.28.2-0rig//drivers/spi/atmel_spi.c linux-2.6.28.2/drivers/spi/atmel_spi.c +--- linux-2.6.28.2-0rig//drivers/spi/atmel_spi.c 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/spi/atmel_spi.c 2009-01-29 09:29:00.000000000 +0100 +@@ -1,306 +1,445 @@ + /* + * Driver for Atmel AT32 and AT91 SPI Controllers + * +- * Copyright (C) 2006 Atmel Corporation ++ * Copyright (C) 2006-2008 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 <linux/kernel.h> +-#include <linux/init.h> + #include <linux/clk.h> +-#include <linux/module.h> +-#include <linux/platform_device.h> + #include <linux/delay.h> + #include <linux/dma-mapping.h> ++#include <linux/dmaengine.h> + #include <linux/err.h> ++#include <linux/gpio.h> ++#include <linux/init.h> + #include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/wait.h> ++#include <linux/workqueue.h> ++#include <linux/spi/atmel_spi.h> + #include <linux/spi/spi.h> + +-#include <asm/io.h> +-#include <mach/board.h> +-#include <mach/gpio.h> + #include <mach/cpu.h> + + #include "atmel_spi.h" + +-/* +- * The core SPI transfer engine just talks to a register bank to set up +- * DMA transfers; transfer queue progress is driven by IRQs. The clock +- * framework provides the base clock, subdivided for each spi_device. +- * +- * Newer controllers, marked with "new_1" flag, have: +- * - CR.LASTXFER +- * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) +- * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs) +- * - SPI_CSRx.CSAAT +- * - SPI_CSRx.SBCR allows faster clocking ++#define BUFFER_SIZE PAGE_SIZE ++#define INVALID_DMA_ADDRESS 0xffffffff ++#define MAX_SG_SEGS 8 ++ ++/** ++ * struct atmel_spi - SPI master controller state ++ * @lock: Spinlock protecting the @queue, @stay and @stopping fields ++ * as well as the hardware registers. ++ * @regs: Base address of the hardware registers. ++ * @wait: Waitqueue used to wait for DMA completion or errors. ++ * @pending: Number of DMA transfers currently pending. ++ * @pending_bytes: Number of bytes submitted for DMA but not yet ++ * accounted for. ++ * @error: Data transfer error detected by interrupt handler. When this ++ * is set to a nonzero value, the DMA engine is stopped, @pending ++ * is set to 0 and @wait is triggered. ++ * @buffer: Scratch buffer for use when the upper layers didn't provide ++ * a TX or RX buffer. ++ * @buffer_dma: DMA address of @buffer. ++ * @buffer_size: Length of @buffer in bytes. ++ * @queue: SPI messages queued for transfer. ++ * @workqueue: Per-controller workqueue. ++ * @work: Queue processing work struct. ++ * @stay: If the last SPI message caused the SPI device to stay active, ++ * this points to the SPI device associated with that message. NULL ++ * otherwise. ++ * @clk: Bus clock connected to the controller. ++ * @base_hz: Base clock rate in Hz used for baud rate calculations. ++ * @stopping: Queue is being stopped. No new messages are started. ++ * @always_bounce: Always do transfers to/from bounce buffer. ++ * @pdev: Platform device associated with the controller. + */ + struct atmel_spi { + spinlock_t lock; +- + void __iomem *regs; +- int irq; +- struct clk *clk; +- struct platform_device *pdev; +- unsigned new_1:1; +- struct spi_device *stay; + +- u8 stopping; +- struct list_head queue; +- struct spi_transfer *current_transfer; +- unsigned long current_remaining_bytes; +- struct spi_transfer *next_transfer; +- unsigned long next_remaining_bytes; ++ wait_queue_head_t wait; ++ int pending; ++ size_t pending_bytes; ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ struct scatterlist tx_sg[MAX_SG_SEGS]; ++ struct scatterlist rx_sg[MAX_SG_SEGS]; ++ unsigned int sg_len; ++ struct dma_async_tx_descriptor *tx_desc; ++ struct dma_async_tx_descriptor *rx_desc; ++ struct dma_chan *tx_chan; ++ struct dma_chan *rx_chan; ++ struct dma_client rx_client; ++ struct dma_client tx_client; ++#endif ++ int error; + + void *buffer; + dma_addr_t buffer_dma; ++ size_t buffer_size; ++ ++ struct list_head queue; ++ struct workqueue_struct *workqueue; ++ struct work_struct work; ++ struct spi_device *stay; ++ struct clk *clk; ++ unsigned long base_hz; ++ bool stopping; ++ bool always_bounce; ++ ++ struct platform_device *pdev; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs_root; ++#endif + }; + +-#define BUFFER_SIZE PAGE_SIZE +-#define INVALID_DMA_ADDRESS 0xffffffff ++/** ++ * struct atmel_spi_device - Controller-specific per-slave state ++ * @npcs_pin: GPIO pin ID hooked up to this SPI slave. ++ * @csr: CSRn register value used when talking to this SPI slave. ++ */ ++struct atmel_spi_device { ++ unsigned int npcs_pin; ++ u32 csr; ++}; + + /* +- * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby +- * they assume that spi slave device state will not change on deselect, so +- * that automagic deselection is OK. ("NPCSx rises if no data is to be +- * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer +- * controllers have CSAAT and friends. +- * +- * Since the CSAAT functionality is a bit weird on newer controllers as +- * well, we use GPIO to control nCSx pins on all controllers, updating +- * MR.PCS to avoid confusing the controller. Using GPIOs also lets us +- * support active-high chipselects despite the controller's belief that +- * only active-low devices/systems exists. ++ * Version 2 of the SPI controller has ++ * - CR.LASTXFER ++ * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) ++ * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs) ++ * - SPI_CSRx.CSAAT ++ * - SPI_CSRx.SBCR allows faster clocking + * +- * However, at91rm9200 has a second erratum whereby nCS0 doesn't work +- * right when driven with GPIO. ("Mode Fault does not allow more than one +- * Master on Chip Select 0.") No workaround exists for that ... so for +- * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH, +- * and (c) will trigger that first erratum in some cases. ++ * We can determine the controller version by reading the VERSION ++ * register, but I haven't checked that it exists on all chips, and ++ * this is cheaper anyway. + */ ++static bool atmel_spi_is_v2(void) ++{ ++ return !cpu_is_at91rm9200(); ++} + +-static void cs_activate(struct atmel_spi *as, struct spi_device *spi) ++static bool atmel_spi_xfer_is_last(struct spi_message *msg, ++ struct spi_transfer *xfer) + { +- unsigned gpio = (unsigned) spi->controller_data; +- unsigned active = spi->mode & SPI_CS_HIGH; +- u32 mr; +- int i; +- u32 csr; +- u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; +- +- /* Make sure clock polarity is correct */ +- for (i = 0; i < spi->master->num_chipselect; i++) { +- csr = spi_readl(as, CSR0 + 4 * i); +- if ((csr ^ cpol) & SPI_BIT(CPOL)) +- spi_writel(as, CSR0 + 4 * i, csr ^ SPI_BIT(CPOL)); +- } ++ return &xfer->transfer_list == msg->transfers.prev; ++} + +- mr = spi_readl(as, MR); +- mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); ++/*-------------------------------------------------------------------------*/ + +- dev_dbg(&spi->dev, "activate %u%s, mr %08x\n", +- gpio, active ? " (high)" : "", +- mr); ++/* ++ * GCC doesn't eliminate _all_ the dead code, only some of it. In ++ * particular, the file operations appear to be difficult even if the ++ * file operations struct itself gets eliminated. ++ * ++ * So let's do the CPP dance. ++ */ ++#ifdef CONFIG_DEBUG_FS + +- if (!(cpu_is_at91rm9200() && spi->chip_select == 0)) +- gpio_set_value(gpio, active); +- spi_writel(as, MR, mr); +-} ++#include <linux/debugfs.h> ++#include <linux/seq_file.h> + +-static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) ++static int atmel_spi_queue_show(struct seq_file *s, void *v) + { +- unsigned gpio = (unsigned) spi->controller_data; +- unsigned active = spi->mode & SPI_CS_HIGH; +- u32 mr; ++ struct atmel_spi *as = s->private; ++ struct spi_message *msg; ++ struct spi_transfer *xfer; + +- /* only deactivate *this* device; sometimes transfers to +- * another device may be active when this routine is called. +- */ +- mr = spi_readl(as, MR); +- if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) { +- mr = SPI_BFINS(PCS, 0xf, mr); +- spi_writel(as, MR, mr); ++ spin_lock_irq(&as->lock); ++ list_for_each_entry(msg, &as->queue, queue) { ++ seq_printf(s, "msg to %s:%s DMA mapped, status %d actual %u\n", ++ msg->spi->dev.bus_id, ++ msg->is_dma_mapped ? "" : " Not", ++ msg->status, msg->actual_length); ++ list_for_each_entry(xfer, &msg->transfers, transfer_list) { ++ seq_printf(s, " t%p r%p l%u%s %u bits %u us %u Hz\n", ++ xfer->tx_buf, xfer->rx_buf, xfer->len, ++ xfer->cs_change ? "cs_change" : "", ++ xfer->bits_per_word, ++ xfer->delay_usecs, ++ xfer->speed_hz); ++ } + } ++ spin_unlock_irq(&as->lock); + +- dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n", +- gpio, active ? " (low)" : "", +- mr); +- +- if (!(cpu_is_at91rm9200() && spi->chip_select == 0)) +- gpio_set_value(gpio, !active); ++ return 0; + } + +-static inline int atmel_spi_xfer_is_last(struct spi_message *msg, +- struct spi_transfer *xfer) ++static int atmel_spi_queue_open(struct inode *inode, struct file *file) + { +- return msg->transfers.prev == &xfer->transfer_list; ++ return single_open(file, atmel_spi_queue_show, inode->i_private); + } + +-static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer) ++static const struct file_operations atmel_spi_queue_fops = { ++ .owner = THIS_MODULE, ++ .open = atmel_spi_queue_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void atmel_spi_show_status_reg(struct seq_file *s, ++ const char *regname, u32 value) + { +- return xfer->delay_usecs == 0 && !xfer->cs_change; ++ static const char *sr_bit[] = { ++ [0] = "RDRF", ++ [1] = "TDRE", ++ [2] = "MODF", ++ [3] = "OVRES", ++ [4] = "ENDRX", ++ [5] = "ENDTX", ++ [6] = "RXBUFF", ++ [7] = "TXBUFE", ++ [8] = "NSSR", ++ [9] = "TXEMPTY", ++ [16] = "SPIENS", ++ }; ++ unsigned int i; ++ ++ seq_printf(s, "%s:\t0x%08x", regname, value); ++ for (i = 0; i < ARRAY_SIZE(sr_bit); i++) { ++ if (value & (1 << i)) { ++ if (sr_bit[i]) ++ seq_printf(s, " %s", sr_bit[i]); ++ else ++ seq_printf(s, " UNKNOWN(%u)", i); ++ } ++ } ++ seq_putc(s, '\n'); + } + +-static void atmel_spi_next_xfer_data(struct spi_master *master, +- struct spi_transfer *xfer, +- dma_addr_t *tx_dma, +- dma_addr_t *rx_dma, +- u32 *plen) ++static int atmel_spi_regs_show(struct seq_file *s, void *v) + { +- struct atmel_spi *as = spi_master_get_devdata(master); +- u32 len = *plen; ++ struct atmel_spi *as = s->private; ++ unsigned int i; ++ u32 value; ++ u32 *buf; ++ ++ buf = kmalloc(0x200, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; + +- /* use scratch buffer only when rx or tx data is unspecified */ +- if (xfer->rx_buf) +- *rx_dma = xfer->rx_dma + xfer->len - len; +- else { +- *rx_dma = as->buffer_dma; +- if (len > BUFFER_SIZE) +- len = BUFFER_SIZE; +- } +- if (xfer->tx_buf) +- *tx_dma = xfer->tx_dma + xfer->len - len; +- else { +- *tx_dma = as->buffer_dma; +- if (len > BUFFER_SIZE) +- len = BUFFER_SIZE; +- memset(as->buffer, 0, len); +- dma_sync_single_for_device(&as->pdev->dev, +- as->buffer_dma, len, DMA_TO_DEVICE); ++ /* Grab a more or less consistent snapshot */ ++ spin_lock_irq(&as->lock); ++ memcpy_fromio(buf, as->regs, 0x200); ++ spin_unlock_irq(&as->lock); ++ ++ value = buf[SPI_MR / 4]; ++ seq_printf(s, "MR:\t0x%08x%s%s%s%s%s%s PCS=%x DLYBCS=%u\n", ++ value, ++ (value & SPI_BIT(MSTR)) ? " MSTR" : "", ++ (value & SPI_BIT(PS)) ? " PS" : "", ++ (value & SPI_BIT(PCSDEC)) ? " PCSDEC" : "", ++ (value & SPI_BIT(FDIV)) ? " FDIV" : "", ++ (value & SPI_BIT(MODFDIS)) ? " MODFDIS" : "", ++ (value & SPI_BIT(LLB)) ? " LLB" : "", ++ SPI_BFEXT(PCS, value), ++ SPI_BFEXT(DLYBCS, value)); ++ ++ atmel_spi_show_status_reg(s, "SR", buf[SPI_SR / 4]); ++ atmel_spi_show_status_reg(s, "IMR", buf[SPI_IMR / 4]); ++ ++ for (i = 0; i < 4; i++) { ++ value = buf[SPI_CSR0 / 4 + i]; ++ seq_printf(s, "CSR%u:\t0x%08x%s%s%s\n", ++ i, value, ++ (value & SPI_BIT(CPOL)) ? " CPOL" : "", ++ (value & SPI_BIT(NCPHA)) ? " NCPHA" : "", ++ (value & SPI_BIT(CSAAT)) ? " CSAAT" : ""); ++ seq_printf(s, "\t\tBITS=%u SCBR=%u DLYBS=%u DLYBCT=%u\n", ++ SPI_BFEXT(BITS, value) + 8, ++ SPI_BFEXT(SCBR, value), ++ SPI_BFEXT(DLYBS, value), ++ SPI_BFEXT(DLYBCT, value)); + } + +- *plen = len; ++ seq_printf(s, "RPR:\t0x%08x\n", buf[SPI_RPR / 4]); ++ seq_printf(s, "RCR:\t0x%08x\n", buf[SPI_RCR / 4]); ++ seq_printf(s, "TPR:\t0x%08x\n", buf[SPI_TPR / 4]); ++ seq_printf(s, "TCR:\t0x%08x\n", buf[SPI_TCR / 4]); ++ seq_printf(s, "RNPR:\t0x%08x\n", buf[SPI_RNPR / 4]); ++ seq_printf(s, "RNCR:\t0x%08x\n", buf[SPI_RNCR / 4]); ++ seq_printf(s, "TNPR:\t0x%08x\n", buf[SPI_TNPR / 4]); ++ seq_printf(s, "TNCR:\t0x%08x\n", buf[SPI_TNCR / 4]); ++ ++ value = buf[SPI_PTSR / 4]; ++ seq_printf(s, "PTSR:\t0x%08x%s%s\n", value, ++ (value & SPI_BIT(RXTEN)) ? " RXTEN" : "", ++ (value & SPI_BIT(TXTEN)) ? " TXTEN" : ""); ++ ++ kfree(buf); ++ ++ return 0; + } + +-/* +- * Submit next transfer for DMA. +- * lock is held, spi irq is blocked +- */ +-static void atmel_spi_next_xfer(struct spi_master *master, +- struct spi_message *msg) ++static int atmel_spi_regs_open(struct inode *inode, struct file *file) + { +- struct atmel_spi *as = spi_master_get_devdata(master); +- struct spi_transfer *xfer; +- u32 len, remaining; +- u32 ieval; +- dma_addr_t tx_dma, rx_dma; +- +- if (!as->current_transfer) +- xfer = list_entry(msg->transfers.next, +- struct spi_transfer, transfer_list); +- else if (!as->next_transfer) +- xfer = list_entry(as->current_transfer->transfer_list.next, +- struct spi_transfer, transfer_list); +- else +- xfer = NULL; +- +- if (xfer) { +- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); ++ return single_open(file, atmel_spi_regs_show, inode->i_private); ++} + +- len = xfer->len; +- atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); +- remaining = xfer->len - len; ++static const struct file_operations atmel_spi_regs_fops = { ++ .owner = THIS_MODULE, ++ .open = atmel_spi_regs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; + +- spi_writel(as, RPR, rx_dma); +- spi_writel(as, TPR, tx_dma); ++static void atmel_spi_init_debugfs(struct atmel_spi *as) ++{ ++ struct dentry *root; ++ struct dentry *node; + +- if (msg->spi->bits_per_word > 8) +- len >>= 1; +- spi_writel(as, RCR, len); +- spi_writel(as, TCR, len); ++ root = debugfs_create_dir(as->pdev->dev.bus_id, NULL); ++ if (IS_ERR(root)) ++ /* Debugfs not enabled */ ++ return; ++ if (!root) ++ /* Debugfs enabled, but failed to create directory */ ++ goto err_root; ++ ++ node = debugfs_create_file("regs", S_IRUSR, root, as, ++ &atmel_spi_regs_fops); ++ if (!node) ++ goto err; ++ node = debugfs_create_file("queue", S_IRUSR, root, as, ++ &atmel_spi_queue_fops); ++ if (!node) ++ goto err; ++ ++ as->debugfs_root = root; ++ return; ++ ++err: ++ debugfs_remove_recursive(root); ++err_root: ++ dev_err(&as->pdev->dev, "failed to initialize debugfs\n"); ++} + +- dev_dbg(&msg->spi->dev, +- " start xfer %p: len %u tx %p/%08x rx %p/%08x\n", +- xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, +- xfer->rx_buf, xfer->rx_dma); +- } else { +- xfer = as->next_transfer; +- remaining = as->next_remaining_bytes; +- } ++static void atmel_spi_cleanup_debugfs(struct atmel_spi *as) ++{ ++ debugfs_remove_recursive(as->debugfs_root); ++} + +- as->current_transfer = xfer; +- as->current_remaining_bytes = remaining; ++#else ++static void atmel_spi_init_debugfs(struct atmel_spi *as) ++{ + +- if (remaining > 0) +- len = remaining; +- else if (!atmel_spi_xfer_is_last(msg, xfer) +- && atmel_spi_xfer_can_be_chained(xfer)) { +- xfer = list_entry(xfer->transfer_list.next, +- struct spi_transfer, transfer_list); +- len = xfer->len; +- } else +- xfer = NULL; ++} ++static void atmel_spi_cleanup_debugfs(struct atmel_spi *as) ++{ + +- as->next_transfer = xfer; ++} ++#endif + +- if (xfer) { +- u32 total; ++/* ++ * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby ++ * they assume that spi slave device state will not change on deselect, so ++ * that automagic deselection is OK. ("NPCSx rises if no data is to be ++ * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer ++ * controllers have CSAAT and friends. ++ * ++ * Since the CSAAT functionality is a bit weird on newer controllers as ++ * well, we use GPIO to control nCSx pins on all controllers, updating ++ * MR.PCS to avoid confusing the controller. Using GPIOs also lets us ++ * support active-high chipselects despite the controller's belief that ++ * only active-low devices/systems exists. ++ * ++ * However, at91rm9200 has a second erratum whereby nCS0 doesn't work ++ * right when driven with GPIO. ("Mode Fault does not allow more than one ++ * Master on Chip Select 0.") No workaround exists for that ... so for ++ * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH, ++ * and (c) will trigger that first erratum in some cases. ++ * ++ * TODO: Test if the atmel_spi_is_v2() branch below works on ++ * AT91RM9200 if we use some other register than CSR0. However, don't ++ * do this unconditionally since AP7000 has an errata where the BITS ++ * field in CSR0 overrides all other CSRs. ++ */ + +- total = len; +- atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); +- as->next_remaining_bytes = total - len; ++static void atmel_spi_set_csr(struct atmel_spi *as, ++ struct spi_device *spi, u32 csr) ++{ ++ if (atmel_spi_is_v2()) ++ spi_writel(as, CSR0, csr); ++ else ++ spi_writel(as, CSR0 + 4 * spi->chip_select, csr); ++} + +- spi_writel(as, RNPR, rx_dma); +- spi_writel(as, TNPR, tx_dma); ++static void cs_activate(struct atmel_spi *as, struct spi_device *spi) ++{ ++ struct atmel_spi_device *asd = spi->controller_state; ++ unsigned active = spi->mode & SPI_CS_HIGH; + +- if (msg->spi->bits_per_word > 8) +- len >>= 1; +- spi_writel(as, RNCR, len); +- spi_writel(as, TNCR, len); ++ if (atmel_spi_is_v2()) { ++ /* ++ * Always use CSR0. This ensures that the clock ++ * switches to the correct idle polarity before we ++ * toggle the CS. ++ */ ++ atmel_spi_set_csr(as, spi, asd->csr); ++ spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS) ++ | SPI_BIT(MSTR)); ++ spi_readl(as, MR); ++ dev_vdbg(&spi->dev, "activate %u%s, csr0: %08x\n", ++ asd->npcs_pin, active ? " (low)" : "", ++ asd->csr); + +- dev_dbg(&msg->spi->dev, +- " next xfer %p: len %u tx %p/%08x rx %p/%08x\n", +- xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, +- xfer->rx_buf, xfer->rx_dma); +- ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES); ++ gpio_set_value(asd->npcs_pin, active); + } else { +- spi_writel(as, RNCR, 0); +- spi_writel(as, TNCR, 0); +- ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES); +- } ++ u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; ++ int i; ++ u32 mr; ++ u32 csr; ++ ++ /* Make sure clock polarity is correct */ ++ for (i = 0; i < spi->master->num_chipselect; i++) { ++ csr = spi_readl(as, CSR0 + 4 * i); ++ if ((csr ^ cpol) & SPI_BIT(CPOL)) ++ spi_writel(as, CSR0 + 4 * i, ++ csr ^ SPI_BIT(CPOL)); ++ } + +- /* REVISIT: We're waiting for ENDRX before we start the next +- * transfer because we need to handle some difficult timing +- * issues otherwise. If we wait for ENDTX in one transfer and +- * then starts waiting for ENDRX in the next, it's difficult +- * to tell the difference between the ENDRX interrupt we're +- * actually waiting for and the ENDRX interrupt of the +- * previous transfer. +- * +- * It should be doable, though. Just not now... +- */ +- spi_writel(as, IER, ieval); +- spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); ++ mr = spi_readl(as, MR); ++ mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); ++ dev_vdbg(&spi->dev, "activate %u%s, mr: %08x csr: %08x\n", ++ asd->npcs_pin, active ? " (low)" : "", ++ mr, csr); ++ if (spi->chip_select != 0) ++ gpio_set_value(asd->npcs_pin, active); ++ spi_writel(as, MR, mr); ++ } + } + +-static void atmel_spi_next_message(struct spi_master *master) ++static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) + { +- struct atmel_spi *as = spi_master_get_devdata(master); +- struct spi_message *msg; +- struct spi_device *spi; +- +- BUG_ON(as->current_transfer); +- +- msg = list_entry(as->queue.next, struct spi_message, queue); +- spi = msg->spi; ++ struct atmel_spi_device *asd = spi->controller_state; ++ unsigned active = spi->mode & SPI_CS_HIGH; ++ u32 mr; + +- dev_dbg(master->dev.parent, "start message %p for %s\n", +- msg, spi->dev.bus_id); ++ /* only deactivate *this* device; sometimes transfers to ++ * another device may be active when this routine is called. ++ */ ++ mr = spi_readl(as, MR); ++ if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) { ++ mr = SPI_BFINS(PCS, 0xf, mr); ++ spi_writel(as, MR, mr); ++ } + +- /* select chip if it's not still active */ +- if (as->stay) { +- if (as->stay != spi) { +- cs_deactivate(as, as->stay); +- cs_activate(as, spi); +- } +- as->stay = NULL; +- } else +- cs_activate(as, spi); ++ dev_vdbg(&spi->dev, "DEactivate %u%s, mr %08x\n", ++ asd->npcs_pin, active ? " (low)" : "", ++ mr); + +- atmel_spi_next_xfer(master, msg); ++ if (atmel_spi_is_v2() || spi->chip_select != 0) ++ gpio_set_value(asd->npcs_pin, !active); + } + + /* +@@ -338,162 +477,460 @@ + return 0; + } + +-static void atmel_spi_dma_unmap_xfer(struct spi_master *master, ++static void atmel_spi_dma_unmap_xfer(struct atmel_spi *as, + struct spi_transfer *xfer) + { + if (xfer->tx_dma != INVALID_DMA_ADDRESS) +- dma_unmap_single(master->dev.parent, xfer->tx_dma, ++ dma_unmap_single(&as->pdev->dev, xfer->tx_dma, + xfer->len, DMA_TO_DEVICE); + if (xfer->rx_dma != INVALID_DMA_ADDRESS) +- dma_unmap_single(master->dev.parent, xfer->rx_dma, ++ dma_unmap_single(&as->pdev->dev, xfer->rx_dma, + xfer->len, DMA_FROM_DEVICE); + } + +-static void +-atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as, +- struct spi_message *msg, int status, int stay) ++static void atmel_spi_dma_unmap_msg(struct atmel_spi *as, struct spi_message *msg) + { +- if (!stay || status < 0) +- cs_deactivate(as, msg->spi); +- else +- as->stay = msg->spi; ++ struct spi_transfer *xfer; + +- list_del(&msg->queue); +- msg->status = status; ++ if (!msg->is_dma_mapped) ++ list_for_each_entry(xfer, &msg->transfers, transfer_list) ++ atmel_spi_dma_unmap_xfer(as, xfer); ++} + +- dev_dbg(master->dev.parent, +- "xfer complete: %u bytes transferred\n", +- msg->actual_length); ++static void atmel_spi_handle_error(struct atmel_spi *as, ++ struct spi_message *msg, int err) ++{ ++ unsigned int timeout; + +- spin_unlock(&as->lock); +- msg->complete(msg->context); +- spin_lock(&as->lock); ++ /* Drain the buffers so that the hardware is ready for a new message */ ++ for (timeout = 1000; timeout; timeout--) ++ if (spi_readl(as, SR) & SPI_BIT(TXEMPTY)) ++ break; ++ if (!timeout) ++ dev_warn(&msg->spi->dev, ++ "timeout waiting for TXEMPTY"); ++ while (spi_readl(as, SR) & SPI_BIT(RDRF)) ++ spi_readl(as, RDR); + +- as->current_transfer = NULL; +- as->next_transfer = NULL; ++ /* Clear any overrun happening while cleaning up */ ++ spi_readl(as, SR); + +- /* continue if needed */ +- if (list_empty(&as->queue) || as->stopping) +- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); +- else +- atmel_spi_next_message(master); ++ msg->status = err; ++ as->error = 0; + } + +-static irqreturn_t +-atmel_spi_interrupt(int irq, void *dev_id) ++#ifdef CONFIG_SPI_ATMEL_HAVE_PDC ++static int atmel_spi_wait_idle(struct atmel_spi *as, struct spi_message *msg) + { +- struct spi_master *master = dev_id; +- struct atmel_spi *as = spi_master_get_devdata(master); +- struct spi_message *msg; +- struct spi_transfer *xfer; +- u32 status, pending, imr; +- int ret = IRQ_NONE; ++ int err; + +- spin_lock(&as->lock); ++ wait_event(as->wait, as->pending == 0); ++ err = as->error; ++ if (err) { ++ dev_warn(&msg->spi->dev, ++ "transfer error %d (%u/%u remaining)\n", ++ err, spi_readl(as, TCR), spi_readl(as, RCR)); + +- xfer = as->current_transfer; +- msg = list_entry(as->queue.next, struct spi_message, queue); ++ spi_writel(as, TNCR, 0); ++ spi_writel(as, RNCR, 0); ++ spi_writel(as, TCR, 0); ++ spi_writel(as, RCR, 0); + +- imr = spi_readl(as, IMR); +- status = spi_readl(as, SR); +- pending = status & imr; ++ atmel_spi_handle_error(as, msg, err); + +- if (pending & SPI_BIT(OVRES)) { +- int timeout; ++ return err; ++ } + +- ret = IRQ_HANDLED; ++ msg->actual_length += as->pending_bytes; ++ as->pending_bytes = 0; + +- spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) +- | SPI_BIT(OVRES))); ++ dev_vdbg(&msg->spi->dev, "controller idle, xfered so far: %u\n", ++ msg->actual_length); ++ ++ return 0; ++} ++ ++static int atmel_spi_submit_xfer(struct atmel_spi *as, struct spi_device *spi, ++ struct spi_message *msg, struct spi_transfer *xfer) ++{ ++ unsigned int bits = xfer->bits_per_word; ++ unsigned int speed_hz = xfer->speed_hz; ++ unsigned int submitted = 0; ++ dma_addr_t rx_dma; ++ dma_addr_t tx_dma; ++ ++ dev_vdbg(&spi->dev, "submit_xfer len %u rx %p tx %p\n", ++ xfer->len, xfer->rx_buf, xfer->tx_buf); ++ dev_vdbg(&spi->dev, " csc %u bpw %u delay %u speed %u\n", ++ xfer->cs_change, xfer->bits_per_word, ++ xfer->delay_usecs, xfer->speed_hz); ++ ++ if (bits || speed_hz) { ++ struct atmel_spi_device *asd; ++ u32 csr; ++ ++ if (atmel_spi_wait_idle(as, msg)) ++ return 0; ++ ++ asd = spi->controller_state; ++ csr = asd->csr; ++ ++ if (bits) ++ csr = SPI_BFINS(BITS, csr, bits - 8); ++ if (speed_hz) { ++ u32 scbr = DIV_ROUND_UP(as->base_hz, speed_hz); ++ csr = SPI_BFINS(SCBR, csr, scbr); ++ } ++ ++ atmel_spi_set_csr(as, spi, csr); ++ } ++ ++ if (!bits) ++ bits = spi->bits_per_word; ++ ++ /* PDC stuff starts here */ ++ while (submitted < xfer->len) { ++ unsigned long len; ++ ++ wait_event(as->wait, as->pending < 2); + + /* +- * When we get an overrun, we disregard the current +- * transfer. Data will not be copied back from any +- * bounce buffer and msg->actual_len will not be +- * updated with the last xfer. +- * +- * We will also not process any remaning transfers in +- * the message. +- * +- * First, stop the transfer and unmap the DMA buffers. ++ * This gives the RX side a slight advantage, making ++ * overruns less likely. + */ +- spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); +- if (!msg->is_dma_mapped) +- atmel_spi_dma_unmap_xfer(master, xfer); ++ spi_writel(as, PTCR, SPI_BIT(TXTDIS)); ++ ++ len = xfer->len - submitted; ++ if (xfer->rx_buf) { ++ rx_dma = xfer->rx_dma + submitted; ++ } else { ++ rx_dma = as->buffer_dma; ++ len = min(len, BUFFER_SIZE); ++ } ++ if (xfer->tx_buf) { ++ tx_dma = xfer->tx_dma + submitted; ++ } else { ++ tx_dma = as->buffer_dma; ++ len = min(len, BUFFER_SIZE); ++ memset(as->buffer, 0, len); ++ } ++ ++ submitted += len; ++ if (bits > 8) ++ len >>= 1; ++ ++ spin_lock_irq(&as->lock); ++ if (as->error) { ++ spin_unlock_irq(&as->lock); ++ atmel_spi_wait_idle(as, msg); ++ return 0; ++ } ++ ++ spi_writel(as, RNPR, rx_dma); ++ spi_writel(as, RNCR, len); ++ spi_writel(as, TNPR, tx_dma); ++ spi_writel(as, TNCR, len); ++ spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) ++ | SPI_BIT(OVRES)); ++ spi_writel(as, PTCR, SPI_BIT(RXTEN) | SPI_BIT(TXTEN)); ++ as->pending++; ++ spin_unlock_irq(&as->lock); ++ } + +- /* REVISIT: udelay in irq is unfriendly */ ++ as->pending_bytes += submitted; ++ ++ if (xfer->delay_usecs || xfer->cs_change || xfer->bits_per_word ++ || xfer->speed_hz) { ++ struct atmel_spi_device *asd = spi->controller_state; ++ int err; ++ ++ err = atmel_spi_wait_idle(as, msg); + if (xfer->delay_usecs) + udelay(xfer->delay_usecs); ++ atmel_spi_set_csr(as, spi, asd->csr); ++ if (err) ++ return 0; ++ ++ if (xfer->cs_change && !atmel_spi_xfer_is_last(msg, xfer)) { ++ cs_deactivate(as, spi); ++ udelay(1); ++ cs_activate(as, spi); ++ } ++ } + +- dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n", +- spi_readl(as, TCR), spi_readl(as, RCR)); ++ return xfer->cs_change; ++} + +- /* +- * Clean up DMA registers and make sure the data +- * registers are empty. +- */ +- spi_writel(as, RNCR, 0); +- spi_writel(as, TNCR, 0); +- spi_writel(as, RCR, 0); +- spi_writel(as, TCR, 0); +- for (timeout = 1000; timeout; timeout--) +- if (spi_readl(as, SR) & SPI_BIT(TXEMPTY)) +- break; +- if (!timeout) +- dev_warn(master->dev.parent, +- "timeout waiting for TXEMPTY"); +- while (spi_readl(as, SR) & SPI_BIT(RDRF)) +- spi_readl(as, RDR); +- +- /* Clear any overrun happening while cleaning up */ +- spi_readl(as, SR); +- +- atmel_spi_msg_done(master, as, msg, -EIO, 0); +- } else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) { +- ret = IRQ_HANDLED; ++#else /* Use DMA engine framework, not PDC */ + +- spi_writel(as, IDR, pending); ++static void atmel_spi_dma_complete(void *param) ++{ ++ struct atmel_spi *as = param; + +- if (as->current_remaining_bytes == 0) { +- msg->actual_length += xfer->len; ++ as->pending = 0; ++ as->sg_len = 0; ++ wake_up(&as->wait); ++} + +- if (!msg->is_dma_mapped) +- atmel_spi_dma_unmap_xfer(master, xfer); ++static int atmel_spi_wait_idle(struct atmel_spi *as, struct spi_message *msg) ++{ ++ struct dma_chan *tx_chan = as->tx_chan; ++ struct dma_chan *rx_chan = as->rx_chan; ++ struct dma_device *dma = rx_chan->device; ++ struct dma_async_tx_descriptor *tx_desc; ++ struct dma_async_tx_descriptor *rx_desc; ++ int err; ++ ++ dev_vdbg(&msg->spi->dev, "wait_idle: sg_len=%u\n", as->sg_len); ++ ++ if (!as->sg_len) ++ return 0; ++ ++ sg_mark_end(as->tx_sg + (as->sg_len - 1)); ++ sg_mark_end(as->rx_sg + (as->sg_len - 1)); ++ as->pending = 1; ++ smp_wmb(); ++ ++ tx_desc = dma->device_prep_slave_sg(tx_chan, ++ as->tx_sg, as->sg_len, DMA_TO_DEVICE, ++ DMA_COMPL_SKIP_SRC_UNMAP | DMA_CTRL_ACK); ++ rx_desc = dma->device_prep_slave_sg(rx_chan, ++ as->rx_sg, as->sg_len, DMA_FROM_DEVICE, ++ DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP ++ | DMA_CTRL_ACK); ++ rx_desc->callback = atmel_spi_dma_complete; ++ rx_desc->callback_param = as; ++ rx_desc->tx_submit(rx_desc); ++ tx_desc->tx_submit(tx_desc); ++ dma->device_issue_pending(rx_chan); ++ dma->device_issue_pending(tx_chan); ++ ++ spi_writel(as, IER, SPI_BIT(OVRES)); ++ wait_event(as->wait, !as->pending); ++ spi_writel(as, IDR, SPI_BIT(OVRES)); ++ err = as->error; ++ if (err) { ++ dev_warn(&msg->spi->dev, "transfer error %d\n", err); + +- /* REVISIT: udelay in irq is unfriendly */ +- if (xfer->delay_usecs) +- udelay(xfer->delay_usecs); +- +- if (atmel_spi_xfer_is_last(msg, xfer)) { +- /* report completed message */ +- atmel_spi_msg_done(master, as, msg, 0, +- xfer->cs_change); +- } else { +- if (xfer->cs_change) { +- cs_deactivate(as, msg->spi); +- udelay(1); +- cs_activate(as, msg->spi); +- } ++ dma->device_terminate_all(tx_chan); ++ dma->device_terminate_all(rx_chan); ++ ++ atmel_spi_handle_error(as, msg, err); ++ ++ return err; ++ } ++ ++ msg->actual_length += as->pending_bytes; ++ as->pending_bytes = 0; ++ sg_init_table(as->rx_sg, MAX_SG_SEGS); ++ sg_init_table(as->tx_sg, MAX_SG_SEGS); ++ ++ dev_vdbg(&msg->spi->dev, "controller idle, xfered so far: %u\n", ++ msg->actual_length); ++ ++ return 0; ++} ++ ++static int atmel_spi_submit_xfer(struct atmel_spi *as, struct spi_device *spi, ++ struct spi_message *msg, struct spi_transfer *xfer) ++{ ++ unsigned int bits = xfer->bits_per_word; ++ unsigned int speed_hz = xfer->speed_hz; ++ unsigned int submitted = 0; ++ unsigned int i; ++ ++ dev_vdbg(&spi->dev, "submit_xfer len %u rx %p tx %p\n", ++ xfer->len, xfer->rx_buf, xfer->tx_buf); ++ dev_vdbg(&spi->dev, " csc %u bpw %u delay %u speed %u\n", ++ xfer->cs_change, xfer->bits_per_word, ++ xfer->delay_usecs, xfer->speed_hz); ++ ++ if (bits || speed_hz) { ++ struct atmel_spi_device *asd; ++ u32 csr; ++ ++ if (atmel_spi_wait_idle(as, msg)) ++ return 0; ++ ++ asd = spi->controller_state; ++ csr = asd->csr; ++ ++ if (bits) ++ csr = SPI_BFINS(BITS, csr, bits - 8); ++ if (speed_hz) { ++ u32 scbr = DIV_ROUND_UP(as->base_hz, speed_hz); ++ csr = SPI_BFINS(SCBR, csr, scbr); ++ } ++ ++ atmel_spi_set_csr(as, spi, csr); ++ } ++ ++ if (!bits) ++ bits = spi->bits_per_word; ++ ++ i = as->sg_len; ++ while (submitted < xfer->len) { ++ unsigned long len; ++ ++ if (i == MAX_SG_SEGS) { ++ if (atmel_spi_wait_idle(as, msg)) ++ return 0; ++ i = 0; ++ } ++ ++ len = xfer->len - submitted; ++ if (!xfer->rx_buf || !xfer->tx_buf) ++ len = min(len, BUFFER_SIZE); ++ ++ if (xfer->rx_buf) { ++ sg_set_buf(&as->rx_sg[i], xfer->rx_buf + submitted, len); ++ as->rx_sg[i].dma_address = xfer->rx_dma + submitted; ++ } else { ++ sg_set_buf(&as->rx_sg[i], as->buffer, len); ++ as->rx_sg[i].dma_address = as->buffer_dma; ++ } ++ if (xfer->tx_buf) { ++ sg_set_buf(&as->tx_sg[i], xfer->tx_buf + submitted, len); ++ as->tx_sg[i].dma_address = xfer->tx_dma + submitted; ++ } else { ++ sg_set_buf(&as->tx_sg[i], as->buffer, len); ++ as->tx_sg[i].dma_address = as->buffer_dma; ++ memset(as->buffer, 0, len); ++ } ++ ++ submitted += len; ++ as->sg_len = ++i; ++ } ++ ++ as->pending_bytes += submitted; + +- /* +- * Not done yet. Submit the next transfer. +- * +- * FIXME handle protocol options for xfer +- */ +- atmel_spi_next_xfer(master, msg); ++ if (xfer->delay_usecs || xfer->cs_change || xfer->bits_per_word ++ || xfer->speed_hz) { ++ struct atmel_spi_device *asd = spi->controller_state; ++ int err; ++ ++ err = atmel_spi_wait_idle(as, msg); ++ if (xfer->delay_usecs) ++ udelay(xfer->delay_usecs); ++ atmel_spi_set_csr(as, spi, asd->csr); ++ if (err) ++ return 0; ++ ++ if (xfer->cs_change && !atmel_spi_xfer_is_last(msg, xfer)) { ++ cs_deactivate(as, spi); ++ udelay(1); ++ cs_activate(as, spi); ++ } ++ } ++ ++ return xfer->cs_change; ++} ++ ++#endif /* PDC vs. DMA engine */ ++ ++static void atmel_spi_work(struct work_struct *work) ++{ ++ struct atmel_spi *as; ++ ++ as = container_of(work, struct atmel_spi, work); ++ ++ spin_lock_irq(&as->lock); ++ while (!list_empty(&as->queue)) { ++ struct spi_message *msg; ++ struct spi_transfer *xfer; ++ struct spi_device *spi; ++ int cs_change = 0; ++ ++ if (as->stopping) ++ break; ++ ++ msg = list_entry(as->queue.next, struct spi_message, queue); ++ spin_unlock_irq(&as->lock); ++ ++ spi = msg->spi; ++ ++ if (as->stay) { ++ if (as->stay != spi) { ++ cs_deactivate(as, as->stay); ++ cs_activate(as, spi); + } ++ as->stay = NULL; + } else { +- /* +- * Keep going, we still have data to send in +- * the current transfer. +- */ +- atmel_spi_next_xfer(master, msg); ++ cs_activate(as, spi); ++ } ++ ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ sg_init_table(as->rx_sg, MAX_SG_SEGS); ++ sg_init_table(as->tx_sg, MAX_SG_SEGS); ++#endif ++ ++ list_for_each_entry(xfer, &msg->transfers, transfer_list) { ++ if (msg->status != -EINPROGRESS) ++ break; ++ cs_change = atmel_spi_submit_xfer(as, spi, msg, xfer); ++ } ++ ++ if (msg->status == -EINPROGRESS) { ++ if (atmel_spi_wait_idle(as, msg)) ++ cs_change = 1; ++ else ++ msg->status = 0; + } ++ if (!cs_change) ++ cs_deactivate(as, spi); ++ else ++ as->stay = spi; ++ ++ atmel_spi_dma_unmap_msg(as, msg); ++ ++ msg->complete(msg->context); ++ spin_lock_irq(&as->lock); ++ list_del(&msg->queue); + } ++ spin_unlock_irq(&as->lock); ++} ++ ++static irqreturn_t atmel_spi_interrupt(int irq, void *dev_id) ++{ ++ struct atmel_spi *as = dev_id; ++ u32 status; ++ u32 mask; ++ u32 pending; ++ ++ spin_lock(&as->lock); ++ ++ status = spi_readl(as, SR); ++ mask = spi_readl(as, IMR); ++ pending = status & mask; ++ ++ if (pending & SPI_BIT(OVRES)) { ++#ifdef CONFIG_SPI_ATMEL_HAVE_PDC ++ spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); ++#endif ++ spi_writel(as, IDR, ~0UL); ++ as->error = -EIO; ++ as->pending = 0; ++#ifdef CONFIG_SPI_ATMEL_HAVE_PDC ++ } else if (pending & SPI_BIT(RXBUFF)) { ++ spi_writel(as, IDR, ~0UL); ++ as->pending = 0; ++ } else if (pending & SPI_BIT(ENDRX)) { ++ spi_writel(as, IDR, SPI_BIT(ENDRX)); ++ as->pending--; ++#endif ++ } else { ++ dev_err(&as->pdev->dev, ++ "unexpected interrupt: SR=0x%08x MR=0x%08x\n", ++ status, mask); ++ spi_writel(as, IDR, pending); ++ } ++ ++ spi_readl(as, IMR); ++ wake_up(&as->wait); + + spin_unlock(&as->lock); + +- return ret; ++ return IRQ_HANDLED; + } + + /* the spi->mode bits understood by this driver: */ +@@ -502,6 +939,7 @@ + static int atmel_spi_setup(struct spi_device *spi) + { + struct atmel_spi *as; ++ struct atmel_spi_device *asd; + u32 scbr, csr; + unsigned int bits = spi->bits_per_word; + unsigned long bus_hz; +@@ -536,21 +974,14 @@ + } + + /* see notes above re chipselect */ +- if (cpu_is_at91rm9200() ++ if (!atmel_spi_is_v2() + && spi->chip_select == 0 + && (spi->mode & SPI_CS_HIGH)) { + dev_dbg(&spi->dev, "setup: can't be active-high\n"); + return -EINVAL; + } + +- /* +- * Pre-new_1 chips start out at half the peripheral +- * bus speed. +- */ +- bus_hz = clk_get_rate(as->clk); +- if (!as->new_1) +- bus_hz /= 2; +- ++ bus_hz = as->base_hz; + if (spi->max_speed_hz) { + /* + * Calculate the lowest divider that satisfies the +@@ -589,11 +1020,20 @@ + + /* chipselect must have been muxed as GPIO (e.g. in board setup) */ + npcs_pin = (unsigned int)spi->controller_data; +- if (!spi->controller_state) { ++ asd = spi->controller_state; ++ if (!asd) { ++ asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL); ++ if (!asd) ++ return -ENOMEM; ++ + ret = gpio_request(npcs_pin, spi->dev.bus_id); +- if (ret) ++ if (ret) { ++ kfree(asd); + return ret; +- spi->controller_state = (void *)npcs_pin; ++ } ++ ++ asd->npcs_pin = npcs_pin; ++ spi->controller_state = asd; + gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); + } else { + unsigned long flags; +@@ -605,11 +1045,14 @@ + spin_unlock_irqrestore(&as->lock, flags); + } + ++ asd->csr = csr; ++ + dev_dbg(&spi->dev, + "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n", + bus_hz / scbr, bits, spi->mode, spi->chip_select, csr); + +- spi_writel(as, CSR0 + 4 * spi->chip_select, csr); ++ if (!atmel_spi_is_v2()) ++ spi_writel(as, CSR0 + 4 * spi->chip_select, csr); + + return 0; + } +@@ -620,74 +1063,81 @@ + struct spi_transfer *xfer; + unsigned long flags; + struct device *controller = spi->master->dev.parent; ++ int ret; + + as = spi_master_get_devdata(spi->master); + +- dev_dbg(controller, "new message %p submitted for %s\n", ++ dev_vdbg(controller, "new message %p submitted for %s\n", + msg, spi->dev.bus_id); + + if (unlikely(list_empty(&msg->transfers) + || !spi->max_speed_hz)) + return -EINVAL; + +- if (as->stopping) +- return -ESHUTDOWN; +- + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) { + dev_dbg(&spi->dev, "missing rx or tx buf\n"); + return -EINVAL; + } + +- /* FIXME implement these protocol options!! */ +- if (xfer->bits_per_word || xfer->speed_hz) { +- dev_dbg(&spi->dev, "no protocol options yet\n"); +- return -ENOPROTOOPT; ++ if (xfer->bits_per_word && (xfer->bits_per_word < 8 ++ || xfer->bits_per_word > 16)) { ++ dev_dbg(&spi->dev, "unsupported bits_per_word\n"); ++ return -EINVAL; ++ } ++ if (xfer->speed_hz) { ++ unsigned long divider; ++ divider = DIV_ROUND_UP(as->base_hz, xfer->speed_hz); ++ ++ if (divider > 255) { ++ dev_dbg(&spi->dev, "speed_hz too low\n"); ++ return -EINVAL; ++ } + } + + /* + * DMA map early, for performance (empties dcache ASAP) and + * better fault reporting. This is a DMA-only driver. +- * +- * NOTE that if dma_unmap_single() ever starts to do work on +- * platforms supported by this driver, we would need to clean +- * up mappings for previously-mapped transfers. + */ + if (!msg->is_dma_mapped) { +- if (atmel_spi_dma_map_xfer(as, xfer) < 0) ++ if (atmel_spi_dma_map_xfer(as, xfer) < 0) { ++ /* Ick */ ++ while (xfer->transfer_list.prev != &msg->transfers) { ++ xfer = list_entry(xfer->transfer_list.prev, ++ struct spi_transfer, ++ transfer_list); ++ atmel_spi_dma_unmap_xfer(as, xfer); ++ } ++ + return -ENOMEM; ++ } + } + } + +-#ifdef VERBOSE +- list_for_each_entry(xfer, &msg->transfers, transfer_list) { +- dev_dbg(controller, +- " xfer %p: len %u tx %p/%08x rx %p/%08x\n", +- xfer, xfer->len, +- xfer->tx_buf, xfer->tx_dma, +- xfer->rx_buf, xfer->rx_dma); +- } +-#endif +- + msg->status = -EINPROGRESS; + msg->actual_length = 0; + + spin_lock_irqsave(&as->lock, flags); +- list_add_tail(&msg->queue, &as->queue); +- if (!as->current_transfer) +- atmel_spi_next_message(spi->master); ++ if (as->stopping) { ++ ret = -ESHUTDOWN; ++ } else { ++ list_add_tail(&msg->queue, &as->queue); ++ queue_work(as->workqueue, &as->work); ++ ret = 0; ++ } + spin_unlock_irqrestore(&as->lock, flags); + +- return 0; ++ return ret; + } + + static void atmel_spi_cleanup(struct spi_device *spi) + { + struct atmel_spi *as = spi_master_get_devdata(spi->master); ++ struct atmel_spi_device *asd = spi->controller_state; + unsigned gpio = (unsigned) spi->controller_data; + unsigned long flags; + +- if (!spi->controller_state) ++ if (!asd) + return; + + spin_lock_irqsave(&as->lock, flags); +@@ -697,14 +1147,131 @@ + } + spin_unlock_irqrestore(&as->lock, flags); + ++ spi->controller_state = NULL; + gpio_free(gpio); ++ kfree(asd); ++} ++ ++static void atmel_spi_stop_queue(struct atmel_spi *as) ++{ ++ struct spi_message *msg; ++ ++ /* ++ * Prevent any new messages from being submitted, cancel any ++ * submitted but not-yet-started messages, and wait for any ++ * ongoing messages to complete. ++ */ ++ as->stopping = true; ++ smp_wmb(); ++ cancel_work_sync(&as->work); ++ ++ /* Terminate anything that was left over */ ++ list_for_each_entry(msg, &as->queue, queue) { ++ atmel_spi_dma_unmap_msg(as, msg); ++ msg->status = -ESHUTDOWN; ++ msg->complete(msg->context); ++ } ++} ++ ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++static enum dma_state_client atmel_spi_dma_chan_avail(struct atmel_spi *as, ++ struct dma_chan *chan, struct dma_chan **pchan) ++{ ++ enum dma_state_client ret = DMA_NAK; ++ ++ if (!*pchan) { ++ as->stopping = false; ++ *pchan = chan; ++ ret = DMA_ACK; ++ } ++ ++ return ret; ++} ++ ++static enum dma_state_client atmel_spi_dma_chan_removed(struct atmel_spi *as, ++ struct dma_chan *chan, struct dma_chan **pchan) ++{ ++ enum dma_state_client ret = DMA_NAK; ++ ++ if (chan == *pchan) { ++ atmel_spi_stop_queue(as); ++ *pchan = NULL; ++ ret = DMA_ACK; ++ } ++ ++ return ret; ++} ++ ++static enum dma_state_client atmel_spi_dma_rx_event(struct dma_client *client, ++ struct dma_chan *chan, enum dma_state state) ++{ ++ struct atmel_spi *as; ++ enum dma_state_client ret = DMA_NAK; ++ ++ as = container_of(client, struct atmel_spi, rx_client); ++ ++ switch (state) { ++ case DMA_RESOURCE_AVAILABLE: ++ ret = atmel_spi_dma_chan_avail(as, chan, &as->rx_chan); ++ if (ret == DMA_ACK) ++ dev_info(&as->pdev->dev, ++ "Using %s for DMA RX transfers\n", ++ chan->dev.bus_id); ++ break; ++ ++ case DMA_RESOURCE_REMOVED: ++ ret = atmel_spi_dma_chan_removed(as, chan, &as->rx_chan); ++ if (ret == DMA_ACK) ++ dev_info(&as->pdev->dev, "Lost %s, queue stopped\n", ++ chan->dev.bus_id); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static enum dma_state_client atmel_spi_dma_tx_event(struct dma_client *client, ++ struct dma_chan *chan, enum dma_state state) ++{ ++ struct atmel_spi *as; ++ enum dma_state_client ret = DMA_NAK; ++ ++ as = container_of(client, struct atmel_spi, tx_client); ++ ++ switch (state) { ++ case DMA_RESOURCE_AVAILABLE: ++ ret = atmel_spi_dma_chan_avail(as, chan, &as->tx_chan); ++ if (ret == DMA_ACK) ++ dev_info(&as->pdev->dev, ++ "Using %s for DMA TX transfers\n", ++ chan->dev.bus_id); ++ break; ++ ++ case DMA_RESOURCE_REMOVED: ++ ret = atmel_spi_dma_chan_removed(as, chan, &as->tx_chan); ++ if (ret == DMA_ACK) ++ dev_info(&as->pdev->dev, "Lost %s, queue stopped\n", ++ chan->dev.bus_id); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return ret; + } ++#endif + + /*-------------------------------------------------------------------------*/ + + static int __init atmel_spi_probe(struct platform_device *pdev) + { + struct resource *regs; ++ struct resource *buf; ++ struct atmel_spi_pdata *pdata; + int irq; + struct clk *clk; + int ret; +@@ -719,6 +1286,14 @@ + if (irq < 0) + return irq; + ++ pdata = pdev->dev.platform_data; ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ if (!pdata) { ++ dev_dbg(&pdev->dev, "no platform data\n"); ++ return -ENXIO; ++ } ++#endif ++ + clk = clk_get(&pdev->dev, "spi_clk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); +@@ -738,31 +1313,65 @@ + + as = spi_master_get_devdata(master); + +- /* +- * Scratch buffer is used for throwaway rx and tx data. +- * It's coherent to minimize dcache pollution. +- */ +- as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE, +- &as->buffer_dma, GFP_KERNEL); +- if (!as->buffer) +- goto out_free; ++ buf = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (buf) { ++ as->buffer_dma = buf->start; ++ as->buffer_size ++ = rounddown_pow_of_two(buf->end - buf->start + 1); ++ if (as->buffer_size) { ++ as->buffer = (void __force *)ioremap(buf->start, ++ as->buffer_size); ++ if (as->buffer) ++ as->always_bounce = true; ++ } ++ } ++ ++ if (!as->buffer) { ++ /* ++ * Scratch buffer is used for throwaway rx and tx data. ++ * It's coherent to minimize dcache pollution. ++ */ ++ as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE, ++ &as->buffer_dma, GFP_KERNEL); ++ if (!as->buffer) ++ goto out_free; ++ } + + spin_lock_init(&as->lock); ++ init_waitqueue_head(&as->wait); + INIT_LIST_HEAD(&as->queue); ++ INIT_WORK(&as->work, atmel_spi_work); + as->pdev = pdev; ++ as->clk = clk; + as->regs = ioremap(regs->start, (regs->end - regs->start) + 1); + if (!as->regs) + goto out_free_buffer; +- as->irq = irq; +- as->clk = clk; +- if (!cpu_is_at91rm9200()) +- as->new_1 = 1; + +- ret = request_irq(irq, atmel_spi_interrupt, 0, +- pdev->dev.bus_id, master); ++ ret = request_irq(irq, atmel_spi_interrupt, 0, pdev->dev.bus_id, as); + if (ret) + goto out_unmap_regs; + ++ as->workqueue = create_singlethread_workqueue(pdev->dev.bus_id); ++ if (!as->workqueue) ++ goto out_free_irq; ++ ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ as->rx_client.event_callback = atmel_spi_dma_rx_event; ++ dma_cap_set(DMA_SLAVE, as->rx_client.cap_mask); ++ as->rx_client.slave = pdata->rx_dma_slave; ++ pdata->rx_dma_slave->rx_reg = regs->start + SPI_RDR + 3; ++ ++ as->tx_client.event_callback = atmel_spi_dma_tx_event; ++ dma_cap_set(DMA_SLAVE, as->tx_client.cap_mask); ++ as->tx_client.slave = pdata->tx_dma_slave; ++ pdata->tx_dma_slave->tx_reg = regs->start + SPI_TDR + 3; ++ ++ dma_async_client_register(&as->rx_client); ++ dma_async_client_register(&as->tx_client); ++ dma_async_client_chan_request(&as->rx_client); ++ dma_async_client_chan_request(&as->tx_client); ++#endif ++ + /* Initialize the hardware */ + clk_enable(clk); + spi_writel(as, CR, SPI_BIT(SWRST)); +@@ -771,9 +1380,19 @@ + spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); + spi_writel(as, CR, SPI_BIT(SPIEN)); + ++ /* v1 chips start out at half the peripheral bus speed. */ ++ as->base_hz = clk_get_rate(clk); ++ if (!atmel_spi_is_v2()) ++ as->base_hz /= 2; ++ + /* go! */ + dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", + (unsigned long)regs->start, irq); ++ if (as->always_bounce) ++ dev_info(&pdev->dev, "Using bounce buffer at 0x%08x len %zu\n", ++ as->buffer_dma, as->buffer_size); ++ ++ atmel_spi_init_debugfs(as); + + ret = spi_register_master(master); + if (ret) +@@ -782,10 +1401,17 @@ + return 0; + + out_reset_hw: ++ atmel_spi_cleanup_debugfs(as); + spi_writel(as, CR, SPI_BIT(SWRST)); + spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ + clk_disable(clk); +- free_irq(irq, master); ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ dma_async_client_unregister(&as->tx_client); ++ dma_async_client_unregister(&as->rx_client); ++#endif ++ destroy_workqueue(as->workqueue); ++out_free_irq: ++ free_irq(irq, as); + out_unmap_regs: + iounmap(as->regs); + out_free_buffer: +@@ -801,34 +1427,34 @@ + { + struct spi_master *master = platform_get_drvdata(pdev); + struct atmel_spi *as = spi_master_get_devdata(master); +- struct spi_message *msg; + +- /* reset the hardware and block queue progress */ +- spin_lock_irq(&as->lock); +- as->stopping = 1; +- spi_writel(as, CR, SPI_BIT(SWRST)); +- spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ +- spi_readl(as, SR); +- spin_unlock_irq(&as->lock); ++ /* Stop the queue */ ++ atmel_spi_stop_queue(as); + +- /* Terminate remaining queued transfers */ +- list_for_each_entry(msg, &as->queue, queue) { +- /* REVISIT unmapping the dma is a NOP on ARM and AVR32 +- * but we shouldn't depend on that... +- */ +- msg->status = -ESHUTDOWN; +- msg->complete(msg->context); +- } ++ atmel_spi_cleanup_debugfs(as); + +- dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, +- as->buffer_dma); ++ /* Shut down the hardware */ ++ spi_writel(as, CR, SPI_BIT(SWRST)); ++ spi_readl(as, SR); + ++ /* Clean up */ ++ spi_unregister_master(master); ++ free_irq(platform_get_irq(pdev, 0), as); ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ dma_async_client_unregister(&as->tx_client); ++ dma_async_client_unregister(&as->rx_client); ++#endif ++ destroy_workqueue(as->workqueue); ++ if (as->always_bounce) ++ iounmap((void __iomem __force *)as->buffer); ++ else ++ dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, ++ as->buffer_dma); ++ iounmap(as->regs); + clk_disable(as->clk); + clk_put(as->clk); +- free_irq(as->irq, master); +- iounmap(as->regs); + +- spi_unregister_master(master); ++ spi_master_put(master); + + return 0; + } +@@ -840,7 +1466,9 @@ + struct spi_master *master = platform_get_drvdata(pdev); + struct atmel_spi *as = spi_master_get_devdata(master); + ++ atmel_spi_stop_queue(as); + clk_disable(as->clk); ++ + return 0; + } + +@@ -850,6 +1478,9 @@ + struct atmel_spi *as = spi_master_get_devdata(master); + + clk_enable(as->clk); ++ as->stopping = false; ++ smp_wmb(); ++ + return 0; + } + +@@ -871,7 +1502,12 @@ + + static int __init atmel_spi_init(void) + { +- return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe); ++ int ret; ++ ++ ret = platform_driver_probe(&atmel_spi_driver, atmel_spi_probe); ++ if (ret) ++ pr_notice("atmel_spi probe failed: %d\n", ret); ++ return ret; + } + module_init(atmel_spi_init); + +@@ -882,6 +1518,6 @@ + module_exit(atmel_spi_exit); + + MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver"); +-MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); +-MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>"); ++MODULE_LICENSE("GPL v2"); + MODULE_ALIAS("platform:atmel_spi"); +diff -urN linux-2.6.28.2-0rig//drivers/spi/Kconfig linux-2.6.28.2/drivers/spi/Kconfig +--- linux-2.6.28.2-0rig//drivers/spi/Kconfig 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/spi/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -53,9 +53,14 @@ + + comment "SPI Master Controller Drivers" + ++config SPI_ATMEL_HAVE_PDC ++ def_bool y ++ depends on (ARCH_AT91 || CPU_AT32AP700X) ++ + config SPI_ATMEL + tristate "Atmel SPI Controller" + depends on (ARCH_AT91 || AVR32) ++ depends on SPI_ATMEL_HAVE_PDC || DMA_ENGINE + help + This selects a driver for the Atmel SPI Controller, present on + many AT32 (AVR32) and AT91 (ARM) chips. +diff -urN linux-2.6.28.2-0rig//drivers/usb/host/ehci-avr32.c linux-2.6.28.2/drivers/usb/host/ehci-avr32.c +--- linux-2.6.28.2-0rig//drivers/usb/host/ehci-avr32.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/host/ehci-avr32.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,213 @@ ++/* ++ * AVR32 EHCI bus and power management glue ++ * ++ * Copyright (C) 2008 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 <linux/clk.h> ++#include <linux/device.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/platform_device.h> ++ ++static struct clk *utmi_clk; ++static struct clk *hclk; ++ ++static void ehci_avr32_start_clocks(struct device *dev) ++{ ++ dev_vdbg(dev, "starting clocks...\n"); ++ ++ clk_enable(utmi_clk); ++ clk_enable(hclk); ++} ++ ++static void ehci_avr32_stop_clocks(struct device *dev) ++{ ++ dev_vdbg(dev, "stopping clocks...\n"); ++ ++ clk_disable(hclk); ++ clk_disable(utmi_clk); ++} ++ ++static int ehci_avr32_setup(struct usb_hcd *hcd) ++{ ++ struct device *dev = hcd->self.controller; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ int ret; ++ ++ ehci_avr32_start_clocks(dev); ++ ++ ehci->caps = hcd->regs; ++ ehci->regs = hcd->regs ++ + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ++ dbg_hcs_params(ehci, "reset"); ++ dbg_hcc_params(ehci, "reset"); ++ ++ /* cache this readonly data; minimize chip reads */ ++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ++ ++ ret = ehci_halt(ehci); ++ if (ret) ++ goto err; ++ ++ /* data structure init */ ++ ret = ehci_init(hcd); ++ if (ret) ++ goto err; ++ ++ ehci->sbrn = 0x20; ++ ehci_port_power(ehci, 0); ++ ++ return 0; ++ ++err: ++ ehci_avr32_stop_clocks(dev); ++ return ret; ++} ++ ++static void ehci_avr32_shutdown(struct usb_hcd *hcd) ++{ ++ ehci_shutdown(hcd); ++ ehci_avr32_stop_clocks(hcd->self.controller); ++} ++ ++static const struct hc_driver ehci_avr32_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "AVR32 USBH (EHCI)", ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ .irq = ehci_irq, ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ .reset = ehci_avr32_setup, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_avr32_shutdown, ++ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ ++ .get_frame_number = ehci_get_frame, ++ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++ .bus_suspend = ehci_bus_suspend, ++ .bus_resume = ehci_bus_resume, ++ .relinquish_port = ehci_relinquish_port, ++ .port_handed_over = ehci_port_handed_over, ++}; ++ ++static int ehci_avr32_probe(struct platform_device *pdev) ++{ ++ struct resource *reg_res; ++ struct usb_hcd *hcd; ++ struct ehci_hcd *ehci; ++ int irq; ++ int ret; ++ ++ reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!reg_res) { ++ dev_dbg(&pdev->dev, "no MMIO resource\n"); ++ return -ENXIO; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_dbg(&pdev->dev, "no IRQ resource\n"); ++ return -ENXIO; ++ } ++ ++ hclk = clk_get(&pdev->dev, "hclk"); ++ if (IS_ERR(hclk)) { ++ dev_dbg(&pdev->dev, "no HSB clock\n"); ++ return -ENXIO; ++ } ++ utmi_clk = clk_get(&pdev->dev, "utmi_clk"); ++ if (IS_ERR(utmi_clk)) { ++ dev_dbg(&pdev->dev, "no UTMI clock\n"); ++ ret = -ENXIO; ++ goto err_utmi_clk; ++ } ++ ++ if (!request_mem_region(reg_res->start, ++ reg_res->end - reg_res->start + 1, ++ hcd_name)) { ++ dev_dbg(&pdev->dev, "config regs busy\n"); ++ ret = -EBUSY; ++ goto err_request_mmio; ++ } ++ ++ ret = -ENOMEM; ++ ++ hcd = usb_create_hcd(&ehci_avr32_hc_driver, &pdev->dev, "ehci-avr32"); ++ if (!hcd) { ++ dev_dbg(&pdev->dev, "failed to create hcd\n"); ++ goto err_create_hcd; ++ } ++ ++ hcd->rsrc_start = reg_res->start; ++ hcd->rsrc_len = reg_res->end - reg_res->start + 1; ++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); ++ if (!hcd->regs) { ++ dev_dbg(&pdev->dev, "failed to map registers\n"); ++ goto err_ioremap; ++ } ++ ++ ehci = hcd_to_ehci(hcd); ++ ehci->big_endian_mmio = 1; ++ ehci->big_endian_desc = 1; ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); ++ if (ret) ++ goto err_add_hcd; ++ ++ return 0; ++ ++err_add_hcd: ++ iounmap(hcd->regs); ++err_ioremap: ++ usb_put_hcd(hcd); ++err_create_hcd: ++ release_mem_region(reg_res->start, reg_res->end - reg_res->start + 1); ++err_request_mmio: ++ clk_put(utmi_clk); ++err_utmi_clk: ++ clk_put(hclk); ++ ++ return ret; ++} ++ ++static int ehci_avr32_remove(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ usb_remove_hcd(hcd); ++ iounmap(hcd->regs); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ usb_put_hcd(hcd); ++ clk_put(utmi_clk); ++ clk_put(hclk); ++ ++ return 0; ++} ++ ++/* FIXME */ ++#define ehci_avr32_suspend NULL ++#define ehci_avr32_resume NULL ++ ++static struct platform_driver ehci_hcd_avr32_driver = { ++ .probe = ehci_avr32_probe, ++ .remove = ehci_avr32_remove, ++ .suspend = ehci_avr32_suspend, ++ .resume = ehci_avr32_resume, ++ .shutdown = usb_hcd_platform_shutdown, ++ .driver = { ++ .name = "ehci", ++ }, ++}; +diff -urN linux-2.6.28.2-0rig//drivers/usb/host/ehci-hcd.c linux-2.6.28.2/drivers/usb/host/ehci-hcd.c +--- linux-2.6.28.2-0rig//drivers/usb/host/ehci-hcd.c 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/host/ehci-hcd.c 2009-01-29 08:52:50.000000000 +0100 +@@ -1014,6 +1014,11 @@ + #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver + #endif + ++#ifdef CONFIG_AVR32 ++#include "ehci-avr32.c" ++#define PLATFORM_DRIVER ehci_hcd_avr32_driver ++#endif ++ + #ifdef CONFIG_PPC_PS3 + #include "ehci-ps3.c" + #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver +diff -urN linux-2.6.28.2-0rig//drivers/usb/host/Kconfig linux-2.6.28.2/drivers/usb/host/Kconfig +--- linux-2.6.28.2-0rig//drivers/usb/host/Kconfig 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/host/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -73,12 +73,12 @@ + + config USB_EHCI_BIG_ENDIAN_MMIO + bool +- depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX) ++ depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || AVR32) + default y + + config USB_EHCI_BIG_ENDIAN_DESC + bool +- depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) ++ depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || AVR32) + default y + + config USB_EHCI_FSL +@@ -196,17 +196,19 @@ + config USB_OHCI_BIG_ENDIAN_DESC + bool + depends on USB_OHCI_HCD ++ default y if AVR32 + default n + + config USB_OHCI_BIG_ENDIAN_MMIO + bool + depends on USB_OHCI_HCD ++ default y if AVR32 + default n + + config USB_OHCI_LITTLE_ENDIAN + bool + depends on USB_OHCI_HCD +- default n if STB03xxx || PPC_MPC52xx ++ default n if STB03xxx || PPC_MPC52xx || AVR32 + default y + + config USB_UHCI_HCD +diff -urN linux-2.6.28.2-0rig//drivers/usb/host/ohci-avr32.c linux-2.6.28.2/drivers/usb/host/ohci-avr32.c +--- linux-2.6.28.2-0rig//drivers/usb/host/ohci-avr32.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/host/ohci-avr32.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,208 @@ ++/* ++ * AVR32 OHCI bus and power management glue ++ * ++ * Copyright (C) 2008 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 <linux/clk.h> ++#include <linux/device.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/platform_device.h> ++ ++/* Grr! The core layer doesn't let us keep private data anywhere! */ ++static struct clk *ohci_clk; ++static struct clk *utmi_clk; ++static struct clk *hclk; ++ ++static void ohci_avr32_start_clocks(struct device *dev) ++{ ++ dev_vdbg(dev, "starting clocks...\n"); ++ ++ clk_enable(ohci_clk); ++ clk_enable(utmi_clk); ++ clk_enable(hclk); ++} ++ ++static void ohci_avr32_stop_clocks(struct device *dev) ++{ ++ dev_vdbg(dev, "stopping clocks...\n"); ++ ++ clk_disable(hclk); ++ clk_disable(utmi_clk); ++ clk_disable(ohci_clk); ++} ++ ++static int ohci_avr32_start(struct usb_hcd *hcd) ++{ ++ struct device *dev = hcd->self.controller; ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ int ret; ++ ++ ohci_avr32_start_clocks(dev); ++ ++ ret = ohci_init(ohci); ++ if (ret) ++ goto err_ohci_init; ++ ++ ret = ohci_run(ohci); ++ if (likely(!ret)) ++ return 0; ++ ++ ohci_stop(hcd); ++ ++err_ohci_init: ++ ohci_avr32_stop_clocks(dev); ++ return ret; ++} ++ ++static void ohci_avr32_stop(struct usb_hcd *hcd) ++{ ++ ohci_stop(hcd); ++ ohci_avr32_stop_clocks(hcd->self.controller); ++} ++ ++static const struct hc_driver ohci_avr32_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "AVR32 USBH (OHCI)", ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ .start = ohci_avr32_start, ++ .stop = ohci_avr32_stop, ++ .shutdown = ohci_shutdown, ++ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ .get_frame_number = ohci_get_frame, ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++#ifdef CONFIG_PM ++ .bus_suspend = ohci_bus_suspend, ++ .bus_resume = ohci_bus_resume, ++#endif ++ .start_port_reset = ohci_start_port_reset, ++}; ++ ++static int ohci_avr32_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ struct usb_hcd *hcd; ++ int irq; ++ int ret; ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_dbg(&pdev->dev, "no MMIO resource\n"); ++ return -ENXIO; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_dbg(&pdev->dev, "no IRQ resource\n"); ++ return -ENXIO; ++ } ++ ++ hclk = clk_get(&pdev->dev, "hclk"); ++ if (IS_ERR(hclk)) { ++ dev_dbg(&pdev->dev, "no HSB clock\n"); ++ return -ENXIO; ++ } ++ utmi_clk = clk_get(&pdev->dev, "utmi_clk"); ++ if (IS_ERR(utmi_clk)) { ++ dev_dbg(&pdev->dev, "no UTMI clock\n"); ++ ret = -ENXIO; ++ goto err_utmi_clk; ++ } ++ ohci_clk = clk_get(&pdev->dev, "ohci_clk"); ++ if (IS_ERR(ohci_clk)) { ++ dev_dbg(&pdev->dev, "no OHCI clock\n"); ++ ret = -ENXIO; ++ goto err_ohci_clk; ++ } ++ ++ if (!request_mem_region(regs->start, regs->end - regs->start + 1, ++ hcd_name)) { ++ dev_dbg(&pdev->dev, "config regs busy\n"); ++ ret = -EBUSY; ++ goto err_request_mmio; ++ } ++ ++ ret = -ENOMEM; ++ hcd = usb_create_hcd(&ohci_avr32_hc_driver, &pdev->dev, "ohci-avr32"); ++ if (!hcd) { ++ dev_dbg(&pdev->dev, "failed to create hcd\n"); ++ goto err_create_hcd; ++ } ++ ++ hcd->rsrc_start = regs->start; ++ hcd->rsrc_len = regs->end - regs->start + 1; ++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); ++ if (!hcd->regs) { ++ dev_dbg(&pdev->dev, "failed to map registers\n"); ++ goto err_ioremap; ++ } ++ ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); ++ if (ret) ++ goto err_add_hcd; ++ ++ return 0; ++ ++err_add_hcd: ++ iounmap(hcd->regs); ++err_ioremap: ++ usb_put_hcd(hcd); ++err_create_hcd: ++ release_mem_region(regs->start, regs->end - regs->start + 1); ++err_request_mmio: ++ clk_put(ohci_clk); ++err_ohci_clk: ++ clk_put(utmi_clk); ++err_utmi_clk: ++ clk_put(hclk); ++ ++ return ret; ++} ++ ++static int ohci_avr32_remove(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ usb_remove_hcd(hcd); ++ iounmap(hcd->regs); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ usb_put_hcd(hcd); ++ clk_put(utmi_clk); ++ clk_put(ohci_clk); ++ clk_put(hclk); ++ ++ return 0; ++} ++ ++/* FIXME */ ++#define ohci_avr32_suspend NULL ++#define ohci_avr32_resume NULL ++ ++static struct platform_driver ohci_hcd_avr32_driver = { ++ .probe = ohci_avr32_probe, ++ .remove = ohci_avr32_remove, ++ .shutdown = usb_hcd_platform_shutdown, ++ .suspend = ohci_avr32_suspend, ++ .resume = ohci_avr32_resume, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "ohci", ++ }, ++}; ++MODULE_ALIAS("platform:ohci"); +diff -urN linux-2.6.28.2-0rig//drivers/usb/host/ohci.h linux-2.6.28.2/drivers/usb/host/ohci.h +--- linux-2.6.28.2-0rig//drivers/usb/host/ohci.h 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/host/ohci.h 2009-01-29 08:52:50.000000000 +0100 +@@ -646,8 +646,10 @@ + * some big-endian SOC implementations. Same thing happens with PSW access. + */ + +-#ifdef CONFIG_PPC_MPC52xx ++#if defined(CONFIG_PPC_MPC52xx) + #define big_endian_frame_no_quirk(ohci) (ohci->flags & OHCI_QUIRK_FRAME_NO) ++#elif defined(CONFIG_AVR32) ++#define big_endian_frame_no_quirk(ohci) 1 + #else + #define big_endian_frame_no_quirk(ohci) 0 + #endif +diff -urN linux-2.6.28.2-0rig//drivers/usb/host/ohci-hcd.c linux-2.6.28.2/drivers/usb/host/ohci-hcd.c +--- linux-2.6.28.2-0rig//drivers/usb/host/ohci-hcd.c 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/host/ohci-hcd.c 2009-01-29 08:52:50.000000000 +0100 +@@ -1042,6 +1042,11 @@ + #define PLATFORM_DRIVER ohci_hcd_at91_driver + #endif + ++#ifdef CONFIG_AVR32 ++#include "ohci-avr32.c" ++#define PLATFORM_DRIVER ohci_hcd_avr32_driver ++#endif ++ + #ifdef CONFIG_ARCH_PNX4008 + #include "ohci-pnx4008.c" + #define PLATFORM_DRIVER usb_hcd_pnx4008_driver +diff -urN linux-2.6.28.2-0rig//drivers/usb/Kconfig linux-2.6.28.2/drivers/usb/Kconfig +--- linux-2.6.28.2-0rig//drivers/usb/Kconfig 2009-01-29 08:39:25.000000000 +0100 ++++ linux-2.6.28.2/drivers/usb/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -56,6 +56,7 @@ + default y if PPC_83xx + default y if SOC_AU1200 + default y if ARCH_IXP4XX ++ default y if AVR32 + default PCI + + # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. +diff -urN linux-2.6.28.2-0rig//drivers/watchdog/at32ap700x_wdt.c linux-2.6.28.2/drivers/watchdog/at32ap700x_wdt.c +--- linux-2.6.28.2-0rig//drivers/watchdog/at32ap700x_wdt.c 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/watchdog/at32ap700x_wdt.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,449 +0,0 @@ +-/* +- * Watchdog driver for Atmel AT32AP700X devices +- * +- * Copyright (C) 2005-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. +- * +- * +- * Errata: WDT Clear is blocked after WDT Reset +- * +- * A watchdog timer event will, after reset, block writes to the WDT_CLEAR +- * register, preventing the program to clear the next Watchdog Timer Reset. +- * +- * If you still want to use the WDT after a WDT reset a small code can be +- * insterted at the startup checking the AVR32_PM.rcause register for WDT reset +- * and use a GPIO pin to reset the system. This method requires that one of the +- * GPIO pins are available and connected externally to the RESET_N pin. After +- * the GPIO pin has pulled down the reset line the GPIO will be reset and leave +- * the pin tristated with pullup. +- */ +- +-#include <linux/init.h> +-#include <linux/kernel.h> +-#include <linux/module.h> +-#include <linux/moduleparam.h> +-#include <linux/miscdevice.h> +-#include <linux/fs.h> +-#include <linux/platform_device.h> +-#include <linux/watchdog.h> +-#include <linux/uaccess.h> +-#include <linux/io.h> +-#include <linux/spinlock.h> +- +-#define TIMEOUT_MIN 1 +-#define TIMEOUT_MAX 2 +-#define TIMEOUT_DEFAULT TIMEOUT_MAX +- +-/* module parameters */ +-static int timeout = TIMEOUT_DEFAULT; +-module_param(timeout, int, 0); +-MODULE_PARM_DESC(timeout, +- "Timeout value. Limited to be 1 or 2 seconds. (default=" +- __MODULE_STRING(TIMEOUT_DEFAULT) ")"); +- +-static int nowayout = WATCHDOG_NOWAYOUT; +-module_param(nowayout, int, 0); +-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" +- __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +- +-/* Watchdog registers and write/read macro */ +-#define WDT_CTRL 0x00 +-#define WDT_CTRL_EN 0 +-#define WDT_CTRL_PSEL 8 +-#define WDT_CTRL_KEY 24 +- +-#define WDT_CLR 0x04 +- +-#define WDT_RCAUSE 0x10 +-#define WDT_RCAUSE_POR 0 +-#define WDT_RCAUSE_EXT 2 +-#define WDT_RCAUSE_WDT 3 +-#define WDT_RCAUSE_JTAG 4 +-#define WDT_RCAUSE_SERP 5 +- +-#define WDT_BIT(name) (1 << WDT_##name) +-#define WDT_BF(name, value) ((value) << WDT_##name) +- +-#define wdt_readl(dev, reg) \ +- __raw_readl((dev)->regs + WDT_##reg) +-#define wdt_writel(dev, reg, value) \ +- __raw_writel((value), (dev)->regs + WDT_##reg) +- +-struct wdt_at32ap700x { +- void __iomem *regs; +- spinlock_t io_lock; +- int timeout; +- int boot_status; +- unsigned long users; +- struct miscdevice miscdev; +-}; +- +-static struct wdt_at32ap700x *wdt; +-static char expect_release; +- +-/* +- * Disable the watchdog. +- */ +-static inline void at32_wdt_stop(void) +-{ +- unsigned long psel; +- +- spin_lock(&wdt->io_lock); +- psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f); +- wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55)); +- wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa)); +- spin_unlock(&wdt->io_lock); +-} +- +-/* +- * Enable and reset the watchdog. +- */ +-static inline void at32_wdt_start(void) +-{ +- /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */ +- unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe; +- +- spin_lock(&wdt->io_lock); +- wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) +- | WDT_BF(CTRL_PSEL, psel) +- | WDT_BF(CTRL_KEY, 0x55)); +- wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) +- | WDT_BF(CTRL_PSEL, psel) +- | WDT_BF(CTRL_KEY, 0xaa)); +- spin_unlock(&wdt->io_lock); +-} +- +-/* +- * Pat the watchdog timer. +- */ +-static inline void at32_wdt_pat(void) +-{ +- spin_lock(&wdt->io_lock); +- wdt_writel(wdt, CLR, 0x42); +- spin_unlock(&wdt->io_lock); +-} +- +-/* +- * Watchdog device is opened, and watchdog starts running. +- */ +-static int at32_wdt_open(struct inode *inode, struct file *file) +-{ +- if (test_and_set_bit(1, &wdt->users)) +- return -EBUSY; +- +- at32_wdt_start(); +- return nonseekable_open(inode, file); +-} +- +-/* +- * Close the watchdog device. +- */ +-static int at32_wdt_close(struct inode *inode, struct file *file) +-{ +- if (expect_release == 42) { +- at32_wdt_stop(); +- } else { +- dev_dbg(wdt->miscdev.parent, +- "unexpected close, not stopping watchdog!\n"); +- at32_wdt_pat(); +- } +- clear_bit(1, &wdt->users); +- expect_release = 0; +- return 0; +-} +- +-/* +- * Change the watchdog time interval. +- */ +-static int at32_wdt_settimeout(int time) +-{ +- /* +- * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is +- * 2 ^ 16 allowing up to 2 seconds timeout. +- */ +- if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX)) +- return -EINVAL; +- +- /* +- * Set new watchdog time. It will be used when at32_wdt_start() is +- * called. +- */ +- wdt->timeout = time; +- return 0; +-} +- +-/* +- * Get the watchdog status. +- */ +-static int at32_wdt_get_status(void) +-{ +- int rcause; +- int status = 0; +- +- rcause = wdt_readl(wdt, RCAUSE); +- +- switch (rcause) { +- case WDT_BIT(RCAUSE_EXT): +- status = WDIOF_EXTERN1; +- break; +- case WDT_BIT(RCAUSE_WDT): +- status = WDIOF_CARDRESET; +- break; +- case WDT_BIT(RCAUSE_POR): /* fall through */ +- case WDT_BIT(RCAUSE_JTAG): /* fall through */ +- case WDT_BIT(RCAUSE_SERP): /* fall through */ +- default: +- break; +- } +- +- return status; +-} +- +-static struct watchdog_info at32_wdt_info = { +- .identity = "at32ap700x watchdog", +- .options = WDIOF_SETTIMEOUT | +- WDIOF_KEEPALIVEPING | +- WDIOF_MAGICCLOSE, +-}; +- +-/* +- * Handle commands from user-space. +- */ +-static long at32_wdt_ioctl(struct file *file, +- unsigned int cmd, unsigned long arg) +-{ +- int ret = -ENOTTY; +- int time; +- void __user *argp = (void __user *)arg; +- int __user *p = argp; +- +- switch (cmd) { +- case WDIOC_GETSUPPORT: +- ret = copy_to_user(argp, &at32_wdt_info, +- sizeof(at32_wdt_info)) ? -EFAULT : 0; +- break; +- case WDIOC_GETSTATUS: +- ret = put_user(0, p); +- break; +- case WDIOC_GETBOOTSTATUS: +- ret = put_user(wdt->boot_status, p); +- break; +- case WDIOC_SETOPTIONS: +- ret = get_user(time, p); +- if (ret) +- break; +- if (time & WDIOS_DISABLECARD) +- at32_wdt_stop(); +- if (time & WDIOS_ENABLECARD) +- at32_wdt_start(); +- ret = 0; +- break; +- case WDIOC_KEEPALIVE: +- at32_wdt_pat(); +- ret = 0; +- break; +- case WDIOC_SETTIMEOUT: +- ret = get_user(time, p); +- if (ret) +- break; +- ret = at32_wdt_settimeout(time); +- if (ret) +- break; +- /* Enable new time value */ +- at32_wdt_start(); +- /* fall through */ +- case WDIOC_GETTIMEOUT: +- ret = put_user(wdt->timeout, p); +- break; +- } +- +- return ret; +-} +- +-static ssize_t at32_wdt_write(struct file *file, const char __user *data, +- size_t len, loff_t *ppos) +-{ +- /* See if we got the magic character 'V' and reload the timer */ +- if (len) { +- if (!nowayout) { +- size_t i; +- +- /* +- * note: just in case someone wrote the magic +- * character five months ago... +- */ +- expect_release = 0; +- +- /* +- * scan to see whether or not we got the magic +- * character +- */ +- for (i = 0; i != len; i++) { +- char c; +- if (get_user(c, data + i)) +- return -EFAULT; +- if (c == 'V') +- expect_release = 42; +- } +- } +- /* someone wrote to us, we should pat the watchdog */ +- at32_wdt_pat(); +- } +- return len; +-} +- +-static const struct file_operations at32_wdt_fops = { +- .owner = THIS_MODULE, +- .llseek = no_llseek, +- .unlocked_ioctl = at32_wdt_ioctl, +- .open = at32_wdt_open, +- .release = at32_wdt_close, +- .write = at32_wdt_write, +-}; +- +-static int __init at32_wdt_probe(struct platform_device *pdev) +-{ +- struct resource *regs; +- int ret; +- +- if (wdt) { +- dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); +- return -EBUSY; +- } +- +- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!regs) { +- dev_dbg(&pdev->dev, "missing mmio resource\n"); +- return -ENXIO; +- } +- +- wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL); +- if (!wdt) { +- dev_dbg(&pdev->dev, "no memory for wdt structure\n"); +- return -ENOMEM; +- } +- +- wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); +- if (!wdt->regs) { +- ret = -ENOMEM; +- dev_dbg(&pdev->dev, "could not map I/O memory\n"); +- goto err_free; +- } +- +- spin_lock_init(&wdt->io_lock); +- wdt->boot_status = at32_wdt_get_status(); +- +- /* Work-around for watchdog silicon errata. */ +- if (wdt->boot_status & WDIOF_CARDRESET) { +- dev_info(&pdev->dev, "CPU must be reset with external " +- "reset or POR due to silicon errata.\n"); +- ret = -EIO; +- goto err_iounmap; +- } else { +- wdt->users = 0; +- } +- wdt->miscdev.minor = WATCHDOG_MINOR; +- wdt->miscdev.name = "watchdog"; +- wdt->miscdev.fops = &at32_wdt_fops; +- +- if (at32_wdt_settimeout(timeout)) { +- at32_wdt_settimeout(TIMEOUT_DEFAULT); +- dev_dbg(&pdev->dev, +- "default timeout invalid, set to %d sec.\n", +- TIMEOUT_DEFAULT); +- } +- +- ret = misc_register(&wdt->miscdev); +- if (ret) { +- dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); +- goto err_iounmap; +- } +- +- platform_set_drvdata(pdev, wdt); +- wdt->miscdev.parent = &pdev->dev; +- dev_info(&pdev->dev, +- "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n", +- wdt->regs, wdt->timeout, nowayout); +- +- return 0; +- +-err_iounmap: +- iounmap(wdt->regs); +-err_free: +- kfree(wdt); +- wdt = NULL; +- return ret; +-} +- +-static int __exit at32_wdt_remove(struct platform_device *pdev) +-{ +- if (wdt && platform_get_drvdata(pdev) == wdt) { +- /* Stop the timer before we leave */ +- if (!nowayout) +- at32_wdt_stop(); +- +- misc_deregister(&wdt->miscdev); +- iounmap(wdt->regs); +- kfree(wdt); +- wdt = NULL; +- platform_set_drvdata(pdev, NULL); +- } +- return 0; +-} +- +-static void at32_wdt_shutdown(struct platform_device *pdev) +-{ +- at32_wdt_stop(); +-} +- +-#ifdef CONFIG_PM +-static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message) +-{ +- at32_wdt_stop(); +- return 0; +-} +- +-static int at32_wdt_resume(struct platform_device *pdev) +-{ +- if (wdt->users) +- at32_wdt_start(); +- return 0; +-} +-#else +-#define at32_wdt_suspend NULL +-#define at32_wdt_resume NULL +-#endif +- +-/* work with hotplug and coldplug */ +-MODULE_ALIAS("platform:at32_wdt"); +- +-static struct platform_driver at32_wdt_driver = { +- .remove = __exit_p(at32_wdt_remove), +- .suspend = at32_wdt_suspend, +- .resume = at32_wdt_resume, +- .driver = { +- .name = "at32_wdt", +- .owner = THIS_MODULE, +- }, +- .shutdown = at32_wdt_shutdown, +-}; +- +-static int __init at32_wdt_init(void) +-{ +- return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe); +-} +-module_init(at32_wdt_init); +- +-static void __exit at32_wdt_exit(void) +-{ +- platform_driver_unregister(&at32_wdt_driver); +-} +-module_exit(at32_wdt_exit); +- +-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); +-MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); +-MODULE_LICENSE("GPL"); +-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff -urN linux-2.6.28.2-0rig//drivers/watchdog/at32_wdt.c linux-2.6.28.2/drivers/watchdog/at32_wdt.c +--- linux-2.6.28.2-0rig//drivers/watchdog/at32_wdt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/drivers/watchdog/at32_wdt.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,620 @@ ++/* ++ * Watchdog driver for Atmel AVR32 devices ++ * ++ * Copyright (C) 2005-2008 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. ++ * ++ * ++ * AT32AP700x Errata: WDT Clear is blocked after WDT Reset ++ * ++ * A watchdog timer event will, after reset, block writes to the WDT_CLEAR ++ * register, preventing the program to clear the next Watchdog Timer Reset. ++ * ++ * If you still want to use the WDT after a WDT reset a small code can be ++ * insterted at the startup checking the AVR32_PM.rcause register for WDT reset ++ * and use a GPIO pin to reset the system. This method requires that one of the ++ * GPIO pins are available and connected externally to the RESET_N pin. After ++ * the GPIO pin has pulled down the reset line the GPIO will be reset and leave ++ * the pin tristated with pullup. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/miscdevice.h> ++#include <linux/fs.h> ++#include <linux/platform_device.h> ++#include <linux/watchdog.h> ++#include <linux/uaccess.h> ++#include <linux/io.h> ++#include <linux/log2.h> ++#include <linux/spinlock.h> ++ ++#include <mach/cpu.h> ++#include <mach/pm.h> ++ ++/* ++ * AT32AP700x uses a 16-bit prescaler. This limits the timeout range ++ * somewhat. Later chips use a 32-bit prescaler. ++ */ ++#define TIMEOUT_MIN 1 ++#ifdef CONFIG_CPU_AT32AP700X ++# define TIMEOUT_MAX 2 ++# define TIMEOUT_DEFAULT TIMEOUT_MAX ++#else ++# define TIMEOUT_MAX 131072 ++# define TIMEOUT_DEFAULT 64 ++#endif ++ ++/* module parameters */ ++static int timeout = TIMEOUT_DEFAULT; ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout, ++ "Timeout value. Any power of two between 1 and " ++ __MODULE_STRING(TIMEOUT_MAX) " seconds. (default=" ++ __MODULE_STRING(TIMEOUT_DEFAULT) ")"); ++ ++static int nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++/* Watchdog registers and write/read macro */ ++#define WDT_CTRL 0x00 ++#define WDT_CTRL_EN 0 ++#define WDT_CTRL_PSEL 8 ++#define WDT_CTRL_CEN 16 ++#define WDT_CTRL_CSEL 17 ++#define WDT_CTRL_KEY 24 ++ ++#define WDT_CLR 0x04 ++ ++#define WDT_BIT(name) (1 << WDT_##name) ++#define WDT_BF(name, value) ((value) << WDT_##name) ++ ++#define wdt_readl(dev, reg) \ ++ __raw_readl((dev)->regs + WDT_##reg) ++#define wdt_writel(dev, reg, value) \ ++ __raw_writel((value), (dev)->regs + WDT_##reg) ++ ++struct wdt_at32 { ++ void __iomem *regs; ++ struct clk *pclk; ++ struct clk *src_clk; ++ spinlock_t io_lock; ++ int timeout; ++ int boot_status; ++ unsigned long users; ++ struct miscdevice miscdev; ++}; ++ ++static struct wdt_at32 *wdt; ++static char expect_release; ++ ++static inline void wdt_clk_enable(struct wdt_at32 *w) ++{ ++ if (!cpu_is_at32ap7000()) ++ clk_enable(w->pclk); ++} ++ ++static inline void wdt_clk_disable(struct wdt_at32 *w) ++{ ++ if (!cpu_is_at32ap7000()) ++ clk_disable(w->pclk); ++} ++ ++static inline int at32_wdt_version(void) ++{ ++ if (cpu_is_at32ap7000()) ++ return 1; ++ if (cpu_is_at32ap7200()) ++ return 3; ++ ++ BUG(); ++} ++ ++static unsigned long at32_wdt_calc_psel(int timeout) ++{ ++ if (at32_wdt_version() == 1) ++ /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */ ++ return (timeout > 1) ? 0xf : 0xe; ++ ++ return order_base_2(timeout) + 14; ++} ++ ++/* ++ * Disable the watchdog. ++ */ ++static inline void at32_wdt_stop(void) ++{ ++ unsigned long ctrl; ++ unsigned long ctrl_mask = 0; ++ ++ switch (at32_wdt_version()) { ++ case 3: ++ ctrl_mask |= (1 << WDT_CTRL_CEN) | (1 << WDT_CTRL_CSEL); ++ /* fall through */ ++ case 2: ++ ctrl_mask |= 0x1f << WDT_CTRL_PSEL; ++ break; ++ case 1: ++ ctrl_mask |= 0x0f << WDT_CTRL_PSEL; ++ break; ++ } ++ ++ wdt_clk_enable(wdt); ++ spin_lock(&wdt->io_lock); ++ ctrl = wdt_readl(wdt, CTRL); ++ ctrl &= ctrl_mask; ++ wdt_writel(wdt, CTRL, ctrl | WDT_BF(CTRL_KEY, 0x55)); ++ wdt_writel(wdt, CTRL, ctrl | WDT_BF(CTRL_KEY, 0xaa)); ++ spin_unlock(&wdt->io_lock); ++ wdt_clk_disable(wdt); ++} ++ ++/* ++ * Enable and reset the watchdog. ++ */ ++static inline void at32_wdt_start(void) ++{ ++ unsigned long psel; ++ unsigned long ctrl; ++ ++ psel = at32_wdt_calc_psel(wdt->timeout); ++ ctrl = WDT_BIT(CTRL_EN) | WDT_BF(CTRL_PSEL, psel); ++ ++ if (at32_wdt_version() >= 3) ++ ctrl |= wdt_readl(wdt, CTRL) ++ & (WDT_BIT(CTRL_CSEL) | WDT_BIT(CTRL_CEN)); ++ ++ wdt_clk_enable(wdt); ++ spin_lock(&wdt->io_lock); ++ wdt_writel(wdt, CTRL, ctrl | WDT_BF(CTRL_KEY, 0x55)); ++ wdt_writel(wdt, CTRL, ctrl | WDT_BF(CTRL_KEY, 0xaa)); ++ spin_unlock(&wdt->io_lock); ++ wdt_clk_disable(wdt); ++} ++ ++/* ++ * Pat the watchdog timer. ++ */ ++static inline void at32_wdt_pat(void) ++{ ++ wdt_clk_enable(wdt); ++ spin_lock(&wdt->io_lock); ++ wdt_writel(wdt, CLR, 0x42); ++ spin_unlock(&wdt->io_lock); ++ wdt_clk_disable(wdt); ++} ++ ++/* ++ * Watchdog device is opened, and watchdog starts running. ++ */ ++static int at32_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(1, &wdt->users)) ++ return -EBUSY; ++ ++ at32_wdt_start(); ++ return nonseekable_open(inode, file); ++} ++ ++/* ++ * Close the watchdog device. ++ */ ++static int at32_wdt_close(struct inode *inode, struct file *file) ++{ ++ if (expect_release == 42) { ++ at32_wdt_stop(); ++ } else { ++ dev_dbg(wdt->miscdev.parent, ++ "unexpected close, not stopping watchdog!\n"); ++ at32_wdt_pat(); ++ } ++ clear_bit(1, &wdt->users); ++ expect_release = 0; ++ return 0; ++} ++ ++/* ++ * Change the watchdog time interval. ++ */ ++static int at32_wdt_settimeout(int time) ++{ ++ /* ++ * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max ++ * prescaler is 2 ^ 16 (or 2 ^ 32) allowing up to TIMEOUT_MAX ++ * seconds timeout. ++ */ ++ if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX) ++ || !is_power_of_2(time)) ++ return -EINVAL; ++ ++ /* ++ * Set new watchdog time. It will be used when at32_wdt_start() is ++ * called. ++ */ ++ wdt->timeout = time; ++ return 0; ++} ++ ++/* ++ * Get the watchdog status. ++ */ ++static int at32_wdt_get_status(void) ++{ ++ int rcause; ++ int status = 0; ++ ++ rcause = at32_get_reset_cause(); ++ ++ switch (rcause) { ++ case AT32_RCAUSE_BOD: ++ status = WDIOF_POWERUNDER; ++ break; ++ case AT32_RCAUSE_EXT: ++ status = WDIOF_EXTERN1; ++ break; ++ case AT32_RCAUSE_JTAG: ++ case AT32_RCAUSE_JTAGHARD: ++ case AT32_RCAUSE_OCDRST: ++ status = WDIOF_EXTERN2; ++ break; ++ case AT32_RCAUSE_WDT: ++ status = WDIOF_CARDRESET; ++ break; ++ case AT32_RCAUSE_POR: ++ case AT32_RCAUSE_NTAE: ++ case AT32_RCAUSE_SLEEP: ++ case AT32_RCAUSE_CPUERR: ++ default: ++ break; ++ } ++ ++ return status; ++} ++ ++static struct watchdog_info at32_wdt_info = { ++ .identity = "at32 watchdog", ++ .options = WDIOF_SETTIMEOUT | ++ WDIOF_KEEPALIVEPING | ++ WDIOF_MAGICCLOSE, ++}; ++ ++/* ++ * Handle commands from user-space. ++ */ ++static long at32_wdt_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret = -ENOTTY; ++ int time; ++ void __user *argp = (void __user *)arg; ++ int __user *p = argp; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user(argp, &at32_wdt_info, ++ sizeof(at32_wdt_info)) ? -EFAULT : 0; ++ break; ++ case WDIOC_GETSTATUS: ++ ret = put_user(0, p); ++ break; ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(wdt->boot_status, p); ++ break; ++ case WDIOC_SETOPTIONS: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ if (time & WDIOS_DISABLECARD) ++ at32_wdt_stop(); ++ if (time & WDIOS_ENABLECARD) ++ at32_wdt_start(); ++ ret = 0; ++ break; ++ case WDIOC_KEEPALIVE: ++ at32_wdt_pat(); ++ ret = 0; ++ break; ++ case WDIOC_SETTIMEOUT: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ ret = at32_wdt_settimeout(time); ++ if (ret) ++ break; ++ /* Enable new time value */ ++ at32_wdt_start(); ++ /* fall through */ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(wdt->timeout, p); ++ break; ++ } ++ ++ return ret; ++} ++ ++static ssize_t at32_wdt_write(struct file *file, const char __user *data, ++ size_t len, loff_t *ppos) ++{ ++ /* See if we got the magic character 'V' and reload the timer */ ++ if (len) { ++ if (!nowayout) { ++ size_t i; ++ ++ /* ++ * note: just in case someone wrote the magic ++ * character five months ago... ++ */ ++ expect_release = 0; ++ ++ /* ++ * scan to see whether or not we got the magic ++ * character ++ */ ++ for (i = 0; i != len; i++) { ++ char c; ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ if (c == 'V') ++ expect_release = 42; ++ } ++ } ++ /* someone wrote to us, we should pat the watchdog */ ++ at32_wdt_pat(); ++ } ++ return len; ++} ++ ++static const struct file_operations at32_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = at32_wdt_ioctl, ++ .open = at32_wdt_open, ++ .release = at32_wdt_close, ++ .write = at32_wdt_write, ++}; ++ ++static int __init at32_wdt_enable_source_clock(struct platform_device *pdev) ++{ ++ struct clk *clk; ++ unsigned int csel; ++ u32 ctrl; ++ ++ /* Only v3+ have selectable source clock */ ++ if (at32_wdt_version() < 3) ++ return 0; ++ ++ csel = 1; ++ ++ /* ++ * Prefer the much more accurate crystal oscillator in favor ++ * of the RC oscillator. ++ */ ++ clk = clk_get(NULL, "osc32"); ++ if (IS_ERR(clk)) { ++ csel = 0; ++ clk = clk_get(NULL, "rcosc"); ++ } ++ if (IS_ERR(clk)) { ++ dev_dbg(&pdev->dev, "No source clock\n"); ++ return -ENXIO; ++ } ++ ++ clk_enable(clk); ++ ++ dev_info(&pdev->dev, "Using 32 kHz %s oscillator\n", ++ csel ? "crystal" : "RC"); ++ ++ wdt_clk_enable(wdt); ++ ctrl = (csel << WDT_CTRL_CSEL) | (1 << WDT_CTRL_CEN); ++ ++ /* ++ * Make sure the WDT is disabled, and disable any clocks that ++ * may have been selected earlier. ++ */ ++ wdt_writel(wdt, CTRL, 0x55 << WDT_CTRL_KEY); ++ wdt_writel(wdt, CTRL, 0xaa << WDT_CTRL_KEY); ++ ++ /* Wait for the clock to become properly deselected */ ++ while (wdt_readl(wdt, CTRL) & (1 << WDT_CTRL_CEN)) ++ cpu_relax(); ++ ++ /* Select the new clock */ ++ wdt_writel(wdt, CTRL, ctrl | (0x55 << WDT_CTRL_KEY)); ++ wdt_writel(wdt, CTRL, ctrl | (0xaa << WDT_CTRL_KEY)); ++ ++ /* Wait for the new clock to become usable */ ++ while (!(wdt_readl(wdt, CTRL) & (1 << WDT_CTRL_CEN))) ++ cpu_relax(); ++ ++ wdt_clk_disable(wdt); ++ return 0; ++} ++ ++static void at32_wdt_disable_source_clock(void) ++{ ++ wdt_clk_enable(wdt); ++ ++ wdt_writel(wdt, CTRL, 0x55 << WDT_CTRL_KEY); ++ wdt_writel(wdt, CTRL, 0xaa << WDT_CTRL_KEY); ++ ++ /* Wait for the clock to become properly deselected */ ++ while (wdt_readl(wdt, CTRL) & (1 << WDT_CTRL_CEN)) ++ cpu_relax(); ++ ++ wdt_clk_disable(wdt); ++} ++ ++static int __init at32_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ int ret; ++ ++ if (wdt) { ++ dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); ++ return -EBUSY; ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_dbg(&pdev->dev, "missing mmio resource\n"); ++ return -ENXIO; ++ } ++ ++ wdt = kzalloc(sizeof(struct wdt_at32), GFP_KERNEL); ++ if (!wdt) { ++ dev_dbg(&pdev->dev, "no memory for wdt structure\n"); ++ return -ENOMEM; ++ } ++ ++ wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); ++ if (!wdt->regs) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "could not map I/O memory\n"); ++ goto err_free; ++ } ++ ++ if (!cpu_is_at32ap7000()) { ++ wdt->pclk = clk_get(&pdev->dev, "pclk"); ++ if (IS_ERR(wdt->pclk)) { ++ dev_dbg(&pdev->dev, "no peripheral clock\n"); ++ ret = -ENXIO; ++ goto err_iounmap; ++ } ++ } ++ ++ ret = at32_wdt_enable_source_clock(pdev); ++ if (ret) ++ goto err_put_clk; ++ ++ spin_lock_init(&wdt->io_lock); ++ wdt->boot_status = at32_wdt_get_status(); ++ ++ /* Work-around for watchdog silicon errata. */ ++ if (cpu_is_at32ap7000() ++ && (wdt->boot_status & WDIOF_CARDRESET)) { ++ dev_info(&pdev->dev, "CPU must be reset with external " ++ "reset or POR due to silicon errata.\n"); ++ ret = -EIO; ++ goto err_disable_source_clock; ++ } else { ++ wdt->users = 0; ++ } ++ wdt->miscdev.minor = WATCHDOG_MINOR; ++ wdt->miscdev.name = "watchdog"; ++ wdt->miscdev.fops = &at32_wdt_fops; ++ ++ if (at32_wdt_settimeout(timeout)) { ++ at32_wdt_settimeout(TIMEOUT_DEFAULT); ++ dev_dbg(&pdev->dev, ++ "default timeout invalid, set to %d sec.\n", ++ TIMEOUT_DEFAULT); ++ } ++ ++ ret = misc_register(&wdt->miscdev); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); ++ goto err_iounmap; ++ } ++ ++ platform_set_drvdata(pdev, wdt); ++ wdt->miscdev.parent = &pdev->dev; ++ dev_info(&pdev->dev, ++ "AT32 WDT at 0x%p, timeout %d sec (nowayout=%d)\n", ++ wdt->regs, wdt->timeout, nowayout); ++ ++ return 0; ++ ++err_disable_source_clock: ++ at32_wdt_disable_source_clock(); ++err_put_clk: ++ if (!cpu_is_at32ap7000()) ++ clk_put(wdt->pclk); ++err_iounmap: ++ iounmap(wdt->regs); ++err_free: ++ kfree(wdt); ++ wdt = NULL; ++ return ret; ++} ++ ++static int __exit at32_wdt_remove(struct platform_device *pdev) ++{ ++ if (wdt && platform_get_drvdata(pdev) == wdt) { ++ /* Stop the timer before we leave */ ++ if (!nowayout) { ++ at32_wdt_stop(); ++ at32_wdt_disable_source_clock(); ++ } ++ ++ misc_deregister(&wdt->miscdev); ++ if (!cpu_is_at32ap7000()) ++ clk_put(wdt->pclk); ++ iounmap(wdt->regs); ++ kfree(wdt); ++ wdt = NULL; ++ platform_set_drvdata(pdev, NULL); ++ } ++ return 0; ++} ++ ++static void at32_wdt_shutdown(struct platform_device *pdev) ++{ ++ at32_wdt_stop(); ++} ++ ++#ifdef CONFIG_PM ++static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ at32_wdt_stop(); ++ return 0; ++} ++ ++static int at32_wdt_resume(struct platform_device *pdev) ++{ ++ if (wdt->users) ++ at32_wdt_start(); ++ return 0; ++} ++#else ++#define at32_wdt_suspend NULL ++#define at32_wdt_resume NULL ++#endif ++ ++/* work with hotplug and coldplug */ ++MODULE_ALIAS("platform:at32_wdt"); ++ ++static struct platform_driver at32_wdt_driver = { ++ .remove = __exit_p(at32_wdt_remove), ++ .suspend = at32_wdt_suspend, ++ .resume = at32_wdt_resume, ++ .driver = { ++ .name = "at32_wdt", ++ .owner = THIS_MODULE, ++ }, ++ .shutdown = at32_wdt_shutdown, ++}; ++ ++static int __init at32_wdt_init(void) ++{ ++ return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe); ++} ++module_init(at32_wdt_init); ++ ++static void __exit at32_wdt_exit(void) ++{ ++ platform_driver_unregister(&at32_wdt_driver); ++} ++module_exit(at32_wdt_exit); ++ ++MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); ++MODULE_DESCRIPTION("Watchdog driver for Atmel AVR32 devices"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff -urN linux-2.6.28.2-0rig//drivers/watchdog/Kconfig linux-2.6.28.2/drivers/watchdog/Kconfig +--- linux-2.6.28.2-0rig//drivers/watchdog/Kconfig 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/watchdog/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -237,12 +237,12 @@ + + # AVR32 Architecture + +-config AT32AP700X_WDT +- tristate "AT32AP700x watchdog" +- depends on CPU_AT32AP700X ++config AT32_WDT ++ tristate "AVR32 On-Chip Watchdog Timer" ++ depends on AVR32 + help +- Watchdog timer embedded into AT32AP700x devices. This will reboot +- your system when the timeout is reached. ++ Watchdog timer embedded into AT32AP700x and similar devices. ++ This will reboot your system when the timeout is reached. + + # BLACKFIN Architecture + +diff -urN linux-2.6.28.2-0rig//drivers/watchdog/Makefile linux-2.6.28.2/drivers/watchdog/Makefile +--- linux-2.6.28.2-0rig//drivers/watchdog/Makefile 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/watchdog/Makefile 2009-01-29 08:52:50.000000000 +0100 +@@ -45,7 +45,7 @@ + # ARM26 Architecture + + # AVR32 Architecture +-obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o ++obj-$(CONFIG_AT32_WDT) += at32_wdt.o + + # BLACKFIN Architecture + obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o +diff -urN linux-2.6.28.2-0rig//drivers/video/atmel_lcdfb.c linux-2.6.28.2/drivers/video/atmel_lcdfb.c +--- linux-2.6.28.2-0rig//drivers/video/atmel_lcdfb.c 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/video/atmel_lcdfb.c 2009-01-29 08:52:50.000000000 +0100 +@@ -178,7 +178,7 @@ + static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, +- .xpanstep = 0, ++ .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +@@ -239,7 +239,7 @@ + } + + static void atmel_lcdfb_update_dma(struct fb_info *info, +- struct fb_var_screeninfo *var) ++ struct fb_var_screeninfo *var) + { + struct atmel_lcdfb_info *sinfo = info->par; + struct fb_fix_screeninfo *fix = &info->fix; +@@ -251,6 +251,8 @@ + dma_addr &= ~3UL; + + /* Set framebuffer DMA base address and pixel offset */ ++ dev_dbg(info->device, "%s:\n", __func__); ++ dev_dbg(info->device, " *setting dma addr: 0x%lx \n", dma_addr); + lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); + + atmel_lcdfb_update_dma2d(sinfo, var); +@@ -493,6 +495,7 @@ + dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", + info->var.xres, info->var.yres, + info->var.xres_virtual, info->var.yres_virtual); ++ dev_dbg(info->device, " * bpp: %u\n", info->var.bits_per_pixel); + + atmel_lcdfb_stop_nowait(sinfo); + +@@ -594,7 +597,12 @@ + lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); + /* Enable FIFO & DMA errors */ + lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); +- ++ ++ /* !!!HACK for logging end of frame and underruns ++ when connected to MPOP. */ ++ if( info->var.bits_per_pixel == 32 ) ++ lcdc_writel(sinfo, ATMEL_LCDC_IER, 0x70); ++ + /* ...wait for DMA engine to become idle... */ + while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) + msleep(10); +@@ -695,7 +703,7 @@ + } + + static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, +- struct fb_info *info) ++ struct fb_info *info) + { + dev_dbg(info->device, "%s\n", __func__); + +@@ -827,7 +835,8 @@ + info->fix = atmel_lcdfb_fix; + + /* Enable LCDC Clocks */ +- if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { ++ if (cpu_is_at91sam9261() || cpu_is_at32ap7000() ++ || cpu_is_at32ap7200()) { + sinfo->bus_clk = clk_get(dev, "hck1"); + if (IS_ERR(sinfo->bus_clk)) { + ret = PTR_ERR(sinfo->bus_clk); +diff -urN linux-2.6.28.2-0rig//drivers/video/atmel_mpopfb.c linux-2.6.28.2/drivers/video/atmel_mpopfb.c +--- linux-2.6.28.2-0rig//drivers/video/atmel_mpopfb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/drivers/video/atmel_mpopfb.c 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,1127 @@ ++/* ++ * Driver for AT91/AT32 LCD Controller ++ * ++ * Copyright (C) 2007 Atmel Corporation ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#define DEBUG ++ ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/fb.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/platform_device.h> ++#include <linux/uaccess.h> ++ ++#include <mach/board.h> ++#include <mach/cpu.h> ++ ++#include <video/atmel_lcdc.h> ++#include <video/atmel_mpop.h> ++ ++#define mpop_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg)) ++#define mpop_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg)) ++ ++#define ATMEL_MPOPFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ ++ | FBINFO_PARTIAL_PAN_OK \ ++ | FBINFO_HWACCEL_XPAN \ ++ | FBINFO_HWACCEL_YPAN) ++ ++static struct atmel_mpopfb_rgbconv_coeffs atmel_mpop_ycrcb2rgb_coeffs = { ++ .r1 = 298, ++ .r2 = 0, ++ .r3 = 409, ++ .r4 = -56992, ++ .g1 = 298, ++ .g2 = -100, ++ .g3 = -208, ++ .g4 = 34784, ++ .b1 = 298, ++ .b2 = 516, ++ .b3 = 0, ++ .b4 = -70688, ++}; ++ ++static struct fb_fix_screeninfo atmel_mpopfb_fix __initdata = { ++ .type = FB_TYPE_PLANES, ++ .visual = FB_VISUAL_TRUECOLOR, ++ .xpanstep = 16, ++ .ypanstep = 1, ++ .ywrapstep = 1, ++ .accel = FB_ACCEL_NONE, ++}; ++ ++static void atmel_mpopfb_update_sar(struct fb_info *info, ++ struct fb_var_screeninfo *var) ++{ ++ struct atmel_mpopfb_info *sinfo = info->par; ++ struct fb_fix_screeninfo *fix = &info->fix; ++ u32 y_sar, u_sar, v_sar, o1_sar, o2_sar, cursor_sar, next_sar; ++ ++ u32 chroma_xres_virtual; ++ u32 chroma_yres_virtual; ++ u32 chroma_xres; ++ u32 chroma_yres; ++ u32 chroma_xoffset; ++ u32 chroma_yoffset; ++ ++ switch (var->bits_per_pixel) { ++ default: ++ case 12: ++ chroma_xres_virtual = var->xres_virtual / 2; ++ chroma_yres_virtual = var->yres_virtual / 2; ++ chroma_xres = var->xres / 2; ++ chroma_yres = var->yres / 2; ++ chroma_xoffset = var->xoffset / 2; ++ chroma_yoffset = var->yoffset / 2; ++ break; ++ case 16: ++ chroma_xres_virtual = var->xres_virtual / 2; ++ chroma_yres_virtual = var->yres_virtual; ++ chroma_xres = var->xres / 2; ++ chroma_yres = var->yres; ++ chroma_xoffset = var->xoffset / 2; ++ chroma_yoffset = var->yoffset; ++ break; ++ case 24: ++ chroma_xres_virtual = var->xres_virtual; ++ chroma_yres_virtual = var->yres_virtual; ++ chroma_xres = var->xres; ++ chroma_yres = var->yres; ++ chroma_xoffset = var->xoffset; ++ chroma_yoffset = var->yoffset; ++ break; ++ } ++ ++ /* Setup pointer to YUV planes in YUV framebuffer. */ ++ y_sar = fix->smem_start + var->xoffset ++ + var->yoffset * var->xres_virtual; ++ u_sar = fix->smem_start + var->xres_virtual * var->yres_virtual ++ + chroma_xoffset + chroma_yoffset * chroma_xres_virtual; ++ v_sar = u_sar + chroma_xres_virtual * chroma_yres_virtual; ++ next_sar = fix->smem_start + var->xres_virtual * var->yres_virtual ++ + 2 * chroma_xres_virtual * chroma_yres_virtual; ++ o1_sar = next_sar; ++ if (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].enabled) ++ next_sar += sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].xsize ++ * sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].ysize; ++ o2_sar = next_sar; ++ if (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].enabled) ++ next_sar += sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].xsize ++ * sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].ysize; ++ cursor_sar = next_sar; ++ ++ if (sinfo->baseimg_info.flip) { ++ /* If we flip we must start with the last line in the frame. */ ++ y_sar += var->xres_virtual * (var->yres - 1); ++ u_sar += chroma_xres_virtual * (chroma_yres - 1); ++ v_sar += chroma_xres_virtual * (chroma_yres - 1); ++ } ++ ++ dev_dbg(info->device, "%s:\n", __func__); ++ dev_dbg(info->device, " * y_sar = 0x%x\n", y_sar); ++ dev_dbg(info->device, " * u_sar = 0x%x\n", u_sar); ++ dev_dbg(info->device, " * v_sar = 0x%x\n", v_sar); ++ dev_dbg(info->device, " * o1_sar = 0x%x\n", o1_sar); ++ dev_dbg(info->device, " * o2_sar = 0x%x\n", o2_sar); ++ dev_dbg(info->device, " * cursor_sar = 0x%x\n", cursor_sar); ++ ++ mpop_writel(sinfo, ATMEL_MPOP_Y_SAR, y_sar); ++ mpop_writel(sinfo, ATMEL_MPOP_U_SAR, u_sar); ++ mpop_writel(sinfo, ATMEL_MPOP_V_SAR, v_sar); ++ mpop_writel(sinfo, ATMEL_MPOP_O1_SAR, o1_sar); ++ mpop_writel(sinfo, ATMEL_MPOP_O2_SAR, o2_sar); ++ mpop_writel(sinfo, ATMEL_MPOP_CURSOR_SAR, cursor_sar); ++} ++ ++static void atmel_mpopfb_free_video_memory(struct atmel_mpopfb_info *sinfo) ++{ ++ struct fb_info *info = sinfo->info; ++ ++ dma_free_writecombine(info->device, info->fix.smem_len, ++ (void __force *)info->screen_base, ++ info->fix.smem_start); ++} ++ ++/** ++ * atmel_mpopfb_alloc_video_memory - Allocate framebuffer memory ++ * @sinfo: the frame buffer to allocate memory for ++ */ ++static int atmel_mpopfb_alloc_video_memory(struct atmel_mpopfb_info *sinfo) ++{ ++ struct fb_info *info = sinfo->info; ++ struct fb_var_screeninfo *var = &info->var; ++ ++ info->fix.smem_len = (var->xres_virtual * var->yres_virtual ++ * ((var->bits_per_pixel + 7) / 8)); ++ ++ info->screen_base ++ = (void __iomem __force *)dma_alloc_writecombine(info->device, ++ info->fix.smem_len, ++ (dma_addr_t *)&info->fix.smem_start, ++ GFP_KERNEL); ++ ++ if (!info->screen_base) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++/** ++ * atmel_mpopfb_check_var - Validates a var passed in. ++ * @var: frame buffer variable screen structure ++ * @info: frame buffer structure that represents a single frame buffer ++ * ++ * Checks to see if the hardware supports the state requested by ++ * var passed in. This function does not alter the hardware ++ * state!!! This means the data stored in struct fb_info and ++ * struct atmel_mpopfb_info do not change. This includes the var ++ * inside of struct fb_info. Do NOT change these. This function ++ * can be called on its own if we intent to only test a mode and ++ * not actually set it. The stuff in modedb.c is a example of ++ * this. If the var passed in is slightly off by what the ++ * hardware can support then we alter the var PASSED in to what ++ * we can do. If the hardware doesn't support mode change a ++ * -EINVAL will be returned by the upper layers. You don't need ++ * to implement this function then. If you hardware doesn't ++ * support changing the resolution then this function is not ++ * needed. In this case the driver would just provide a var that ++ * represents the static state the screen is in. ++ * ++ * Returns negative errno on error, or zero on success. ++ */ ++static int atmel_mpopfb_check_var(struct fb_var_screeninfo *var, ++ struct fb_info *info) ++{ ++ struct device *dev = info->device; ++ struct atmel_mpopfb_info *sinfo = info->par; ++ struct fb_info *lcdc_info = platform_get_drvdata(sinfo->lcdc_pdev); ++ ++ dev_dbg(dev, "%s:\n", __func__); ++ dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); ++ dev_dbg(dev, " offset: (%u,%u)\n", var->xoffset, var->yoffset); ++ dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); ++ ++ /* ++ * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal! ++ * as FB_VMODE_SMOOTH_XPAN is only used internally ++ */ ++ ++ if (var->vmode & FB_VMODE_CONUPDATE) { ++ var->vmode |= FB_VMODE_YWRAP; ++ var->xoffset = info->var.xoffset; ++ var->yoffset = info->var.yoffset; ++ } ++ ++ /* Horizontal size must be a multiple of 16 pixels */ ++ ++ /* ++ * Some very basic checks ++ */ ++ if (!var->xres) ++ var->xres = 1; ++ if (!var->yres) ++ var->yres = 1; ++ if (var->xres > var->xres_virtual) ++ var->xres_virtual = var->xres; ++ if (var->yres > var->yres_virtual) ++ var->yres_virtual = var->yres; ++ if (var->bits_per_pixel > 16) ++ var->bits_per_pixel = 24; ++ else if (var->bits_per_pixel > 12) ++ var->bits_per_pixel = 16; ++ else ++ var->bits_per_pixel = 12; ++ ++ /* Horizontal size and offset must be a multiple of 16 pixels */ ++ var->xres = (var->xres + 15) & ~15UL; ++ var->xres_virtual = (var->xres_virtual + 15) & ~15UL; ++ var->xoffset = (var->xoffset + 15) & ~15UL; ++ ++ if (var->xres_virtual < var->xoffset + var->xres) ++ var->xres_virtual = var->xoffset + var->xres; ++ if (var->yres_virtual < var->yoffset + var->yres) ++ var->yres_virtual = var->yoffset + var->yres; ++ ++ /* Check that the scaled image will fit into the LCD display. */ ++ if (sinfo->baseimg_info.xsize > lcdc_info->var.xres) { ++ dev_err(dev, "baseimage is wider than screen: %d > %d\n", ++ sinfo->baseimg_info.xsize, lcdc_info->var.xres); ++ return -EINVAL; ++ } ++ ++ if (sinfo->baseimg_info.ysize > lcdc_info->var.yres) { ++ dev_err(dev, "baseimage is higher than screen: %d > %d\n", ++ sinfo->baseimg_info.ysize, lcdc_info->var.yres); ++ return -EINVAL; ++ } ++ ++ /* Check that it is possible to scale to given size. */ ++ if (ATMEL_MPOP_CALC_SCALE(var->xres, sinfo->baseimg_info.xsize) == 0 ++ || (ATMEL_MPOP_CALC_SCALE(var->xres, ++ sinfo->baseimg_info.xsize) ++ > (4 << ATMEL_MPOP_RESIZE_FRAC_BITS))) { ++ dev_err(dev, "cannot scale from width %d to %d Max %s\n", ++ var->xres, sinfo->baseimg_info.xsize, ++ ATMEL_MPOP_CALC_SCALE(var->xres, ++ sinfo->baseimg_info.xsize) ++ ? "downscale factor is 4!" ++ : "upscale factor is 32"); ++ return -EINVAL; ++ } ++ ++ if (ATMEL_MPOP_CALC_SCALE(var->yres, sinfo->baseimg_info.ysize) == 0 ++ || (ATMEL_MPOP_CALC_SCALE(var->yres, ++ sinfo->baseimg_info.ysize) ++ > (4 << ATMEL_MPOP_RESIZE_FRAC_BITS))) { ++ dev_err(dev, "cannot scale from height %d to %d Max %s\n", ++ var->yres, sinfo->baseimg_info.ysize, ++ ATMEL_MPOP_CALC_SCALE(var->yres, ++ sinfo->baseimg_info.ysize) ++ ? "downscale factor is 4!" ++ : "upscale factor is 32"); ++ return -EINVAL; ++ } ++ ++ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; ++ var->transp.msb_right = 0; ++ var->transp.offset = var->transp.length = 0; ++ ++ switch (var->bits_per_pixel) { ++ case 12: ++ case 16: ++ case 24: ++ var->red.offset = 0; ++ var->green.offset = 8; ++ var->blue.offset = 16; ++ var->red.length = var->green.length = var->blue.length = 8; ++ break; ++ default: ++ dev_err(dev, "color depth %d not supported\n", ++ var->bits_per_pixel); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void atmel_mpopfb_start(struct atmel_mpopfb_info *sinfo) ++{ ++ if (!sinfo->running) { ++ dev_dbg(sinfo->info->device, " * Starting MPOP.\n"); ++ ++ /* Enable all error interrupts. */ ++ mpop_writel(sinfo, ATMEL_MPOP_INTEN, 0x7); ++ ++ /* ++ * Enable the MPOP. When the LCD controller starts ++ * reading from the slave interface it will start ++ * generating a frame. ++ */ ++ mpop_writel(sinfo, ATMEL_MPOP_CR, ++ ATMEL_MPOP_CR_EN_MASK ++ /*| ATMEL_MPOP_CR_OUT_BGR_MASK */ ); ++ ++ sinfo->running = 1; ++ } ++} ++ ++static void atmel_mpopfb_stop(struct atmel_mpopfb_info *sinfo) ++{ ++ if (!sinfo->running) ++ /* Not running. Already stopped. */ ++ return; ++ ++ dev_dbg(sinfo->info->device, "Stopping MPOP.\n"); ++ ++ /* Disable the MPOP. This will force the MPOP to be reset. */ ++ mpop_writel(sinfo, ATMEL_MPOP_CR, 0); ++ ++ /* Disable all interrupts. */ ++ mpop_writel(sinfo, ATMEL_MPOP_INTDIS, ~0UL); ++ ++ /* Looks like we stopped the MPOP... */ ++ dev_dbg(sinfo->info->device, "MPOP stopped.\n"); ++ ++ sinfo->running = 0; ++} ++ ++static void atmel_mpopfb_connect_to_lcdc(struct atmel_mpopfb_info *sinfo) ++{ ++ struct fb_info *lcdc_info = platform_get_drvdata(sinfo->lcdc_pdev); ++ ++ dev_dbg(sinfo->info->device, "Connecting MPOP to LCDC:\n"); ++ ++ /* Start the mpop if it is not running. */ ++ atmel_mpopfb_start(sinfo); ++ ++ if (sinfo->connected_to_lcdc) ++ /* Already connected. */ ++ return; ++ ++ /* ++ * Set framebuffer pointer in LCDC to point to the slave ++ * interface of the MPOP. ++ */ ++ dev_dbg(sinfo->info->device, " * Attaching to LCDC.\n"); ++ sinfo->lcdc_old_smem_start = lcdc_info->fix.smem_start; ++ lcdc_info->fix.smem_start = (unsigned long)sinfo->slave_base; ++ sinfo->lcdc_old_bits_per_pixel = lcdc_info->var.bits_per_pixel; ++ lcdc_info->var.bits_per_pixel = 32; ++ ++ /* Force the LCDC to change the configuration. */ ++ lcdc_info->fbops->fb_set_par(lcdc_info); ++ ++ sinfo->connected_to_lcdc = 1; ++} ++ ++static void atmel_mpopfb_disconnect_from_lcdc(struct atmel_mpopfb_info *sinfo) ++{ ++ struct fb_info *lcdc_info = platform_get_drvdata(sinfo->lcdc_pdev); ++ ++ dev_dbg(sinfo->info->device, "Disconnecting MPOP from LCDC:\n"); ++ ++ if (!sinfo->connected_to_lcdc) ++ /* Already disconnected. */ ++ return; ++ ++ /* Restore lcdc's old framebuffer pointer and pixel-format. */ ++ lcdc_info->fix.smem_start = sinfo->lcdc_old_smem_start; ++ lcdc_info->var.bits_per_pixel = sinfo->lcdc_old_bits_per_pixel; ++ ++ /* Force the LCDC to change the configuration. */ ++ lcdc_info->fbops->fb_set_par(lcdc_info); ++ ++ sinfo->connected_to_lcdc = 0; ++ ++ /* We must stop the mpop to reset it. */ ++ atmel_mpopfb_stop(sinfo); ++} ++ ++static void atmel_mpopfb_put_overlay_palette(struct atmel_mpopfb_info *sinfo, ++ struct atmel_mpopfb_overlay_palette *palette) ++{ ++ int i; ++ ++ dev_dbg(sinfo->info->device, "Overlay palette = :\n"); ++ for (i = 0; i < 256; i++) { ++ dev_dbg(sinfo->info->device, "%d -> 0x%x\n", i, ++ *((int *)&palette->entry[i])); ++ mpop_writel(sinfo, ATMEL_MPOP_PALETTEDATA + 4 * i, ++ *((int *)&palette->entry[i])); ++ } ++} ++ ++static void atmel_mpopfb_get_overlay_palette(struct atmel_mpopfb_info *sinfo, ++ struct atmel_mpopfb_overlay_palette *palette) ++{ ++ int i; ++ ++ for (i = 0; i < 256; i++) ++ *((int *)&palette->entry[i]) = ++ mpop_readl(sinfo, ATMEL_MPOP_PALETTEDATA + 4 * i); ++} ++ ++static void atmel_mpopfb_put_cursor_palette(struct atmel_mpopfb_info *sinfo, ++ struct atmel_mpopfb_cursor_palette *palette) ++{ ++ int i; ++ for (i = 0; i < 4; i++) ++ mpop_writel(sinfo, ATMEL_MPOP_CURSOR_P0 + 4 * i, ++ *((int *)&palette->entry[i])); ++} ++ ++static void atmel_mpopfb_get_cursor_palette(struct atmel_mpopfb_info *sinfo, ++ struct atmel_mpopfb_cursor_palette *palette) ++{ ++ int i; ++ for (i = 0; i < 4; i++) ++ *((int *)&palette->entry[i]) ++ = mpop_readl(sinfo, ATMEL_MPOP_CURSOR_P0 + 4 * i); ++} ++ ++/** ++ * atmel_mpopfb_set_par - Alters the hardware state. ++ * @info: frame buffer structure that represents a single frame buffer ++ * ++ * Using the fb_var_screeninfo in fb_info we set the resolution ++ * of the this particular framebuffer. This function alters the ++ * par AND the fb_fix_screeninfo stored in fb_info. It doesn't ++ * not alter var in fb_info since we are using that data. This ++ * means we depend on the data in var inside fb_info to be ++ * supported by the hardware. atmel_lcdfb_check_var is always called ++ * before atmel_lcdfb_set_par to ensure this. Again if you can't ++ * change the resolution you don't need this function. ++ * ++ */ ++static int atmel_mpopfb_set_par(struct fb_info *info) ++{ ++ struct atmel_mpopfb_info *sinfo = info->par; ++ struct fb_info *lcdc_info = platform_get_drvdata(sinfo->lcdc_pdev); ++ struct fb_var_screeninfo *var = &info->var; ++ ++ u32 yuv_format; ++ u32 xscale, yscale; ++ ++ dev_dbg(info->device, "%s:\n", __func__); ++ dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", ++ info->var.xres, info->var.yres, ++ info->var.xres_virtual, info->var.yres_virtual); ++ dev_dbg(info->device, " * offset: (%u,%u)\n", ++ info->var.xoffset, info->var.yoffset); ++ dev_dbg(info->device, " * bpp: %u\n", info->var.bits_per_pixel); ++ ++ /* Setup the output picture size. We must use the size of the lcdcfb. */ ++ dev_dbg(info->device, " * output frame resolution: %ux%u \n", ++ lcdc_info->var.xres, lcdc_info->var.yres); ++ mpop_writel(sinfo, ATMEL_MPOP_DISP_MAX_COORD, ++ ((lcdc_info->var.xres - 1) << ATMEL_MPOP_DISP_MAX_COORD_X_OFFSET) ++ | ((lcdc_info->var.yres - 1) << ATMEL_MPOP_DISP_MAX_COORD_Y_OFFSET)); ++ ++ /* Setup base picture. */ ++ ++ switch (var->bits_per_pixel) { ++ default: ++ case 12: ++ yuv_format = ATMEL_MPOP_YUVFORMAT_420; ++ break; ++ case 16: ++ yuv_format = ATMEL_MPOP_YUVFORMAT_422; ++ break; ++ case 24: ++ yuv_format = ATMEL_MPOP_YUVFORMAT_444; ++ break; ++ } ++ ++ xscale = ATMEL_MPOP_CALC_SCALE(info->var.xres, sinfo->baseimg_info.xsize); ++ yscale = ATMEL_MPOP_CALC_SCALE(info->var.yres, sinfo->baseimg_info.ysize); ++ ++ dev_dbg(info->device, " * baseimg output size = %ux%u \n", ++ sinfo->baseimg_info.xsize, sinfo->baseimg_info.ysize); ++ dev_dbg(info->device, " * resize scales = %ux%u \n", xscale, yscale); ++ dev_dbg(info->device, " * yuv format = %u \n", yuv_format); ++ mpop_writel(sinfo, ATMEL_MPOP_YCR, ++ yuv_format << ATMEL_MPOP_YCR_YUVFORMAT_OFFSET ++ | xscale << ATMEL_MPOP_YCR_XRESIZE_OFFSET ++ | yscale << ATMEL_MPOP_YCR_YRESIZE_OFFSET); ++ ++ /* Setup conversion coefficients. */ ++ mpop_writel(sinfo, ATMEL_MPOP_R2R1, ++ ((sinfo->rgbconv_coeffs.r1 << ATMEL_MPOP_R1_OFFSET) & ATMEL_MPOP_R1_MASK) ++ | ((sinfo->rgbconv_coeffs.r2 << ATMEL_MPOP_R2_OFFSET) & ATMEL_MPOP_R2_MASK)); ++ mpop_writel(sinfo, ATMEL_MPOP_R4R3, ++ ((sinfo->rgbconv_coeffs.r3 << ATMEL_MPOP_R3_OFFSET) & ATMEL_MPOP_R3_MASK) ++ | ((sinfo->rgbconv_coeffs.r4 << ATMEL_MPOP_R4_OFFSET) & ATMEL_MPOP_R4_MASK)); ++ mpop_writel(sinfo, ATMEL_MPOP_G2G1, ++ ((sinfo->rgbconv_coeffs.g1 << ATMEL_MPOP_G1_OFFSET) & ATMEL_MPOP_G1_MASK) ++ | ((sinfo->rgbconv_coeffs.g2 << ATMEL_MPOP_G2_OFFSET) & ATMEL_MPOP_G2_MASK)); ++ mpop_writel(sinfo, ATMEL_MPOP_G4G3, ++ ((sinfo->rgbconv_coeffs.g3 << ATMEL_MPOP_G3_OFFSET) & ATMEL_MPOP_G3_MASK) ++ | ((sinfo->rgbconv_coeffs.g4 << ATMEL_MPOP_G4_OFFSET) & ATMEL_MPOP_G4_MASK)); ++ mpop_writel(sinfo, ATMEL_MPOP_B2B1, ++ ((sinfo->rgbconv_coeffs.b1 << ATMEL_MPOP_B1_OFFSET) & ATMEL_MPOP_B1_MASK) ++ | ((sinfo->rgbconv_coeffs.b2 << ATMEL_MPOP_B2_OFFSET) & ATMEL_MPOP_B2_MASK)); ++ mpop_writel(sinfo, ATMEL_MPOP_B4B3, ++ ((sinfo->rgbconv_coeffs.b3 << ATMEL_MPOP_B3_OFFSET) & ATMEL_MPOP_B3_MASK) ++ | ((sinfo->rgbconv_coeffs.b4 << ATMEL_MPOP_B4_OFFSET) & ATMEL_MPOP_B4_MASK)); ++ ++ info->fix.line_length = info->var.xres_virtual; ++ info->fix.visual = FB_VISUAL_TRUECOLOR; ++ ++ /* Setup stride. We can flip the image by negating the ++ stride, but we must then set the SAR registers to point ++ to the last line in the image. */ ++ if (sinfo->baseimg_info.flip) { ++ dev_dbg(info->device, " * flip \n"); ++ mpop_writel(sinfo, ATMEL_MPOP_STRIDE, -info->var.xres_virtual); ++ } else ++ mpop_writel(sinfo, ATMEL_MPOP_STRIDE, info->var.xres_virtual); ++ ++ /* Setup input image size. */ ++ mpop_writel(sinfo, ATMEL_MPOP_YUV_MAX_COORD, ++ ((info->var.xres - 1) << ATMEL_MPOP_YUV_MAX_COORD_X_OFFSET) ++ | ((info->var.yres - 1) << ATMEL_MPOP_YUV_MAX_COORD_Y_OFFSET)); ++ ++ /* Setup size and position of output base image after scaling. */ ++ mpop_writel(sinfo, ATMEL_MPOP_RGB_SIZE, ++ sinfo->baseimg_info.xsize << ATMEL_MPOP_RGB_SIZE_X_OFFSET ++ | sinfo->baseimg_info.ysize << ATMEL_MPOP_RGB_SIZE_Y_OFFSET); ++ ++ mpop_writel(sinfo, ATMEL_MPOP_RGB_POS, ++ (sinfo->baseimg_info.xpos << ATMEL_MPOP_RGB_POS_X_OFFSET) ++ | (sinfo->baseimg_info.ypos << ATMEL_MPOP_RGB_POS_Y_OFFSET)); ++ ++ dev_dbg(info->device, " * baseimg pos: (%u,%u) \n", ++ sinfo->baseimg_info.xpos, sinfo->baseimg_info.ypos); ++ ++ /* Setup Word Transfer Count. */ ++ mpop_writel(sinfo, ATMEL_MPOP_RGB_WTC, ++ DIV_ROUND_UP(info->var.xres * info->var.yres ++ * var->bits_per_pixel, 32)); ++ ++ /* Set overlay parameters. */ ++ mpop_writel(sinfo, ATMEL_MPOP_O1_POS, ++ (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].xpos << ATMEL_MPOP_O1_POS_O1_POS_X) ++ | (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].ypos << ATMEL_MPOP_O1_POS_O1_POS_Y)); ++ mpop_writel(sinfo, ATMEL_MPOP_O1_SIZE, ++ (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].xsize << ATMEL_MPOP_O1_SIZE_O1_SIZE_X) ++ | (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].ysize << ATMEL_MPOP_O1_SIZE_O1_SIZE_Y)); ++ mpop_writel(sinfo, ATMEL_MPOP_O1_WTC, ++ DIV_ROUND_UP(sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].xsize ++ * sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].ysize, 4)); ++ ++ mpop_writel(sinfo, ATMEL_MPOP_O2_POS, ++ (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].xpos << ATMEL_MPOP_O2_POS_O2_POS_X) ++ | (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].ypos << ATMEL_MPOP_O2_POS_O2_POS_Y)); ++ mpop_writel(sinfo, ATMEL_MPOP_O2_SIZE, ++ (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].xsize << ATMEL_MPOP_O2_SIZE_O2_SIZE_X) ++ | (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].ysize << ATMEL_MPOP_O2_SIZE_O2_SIZE_Y)); ++ mpop_writel(sinfo, ATMEL_MPOP_O2_WTC, ++ DIV_ROUND_UP(sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].xsize * ++ sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].ysize, 4)); ++ ++ mpop_writel(sinfo, ATMEL_MPOP_CURSOR_POS, ++ (sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].xpos << ATMEL_MPOP_CURSOR_POS_CURSOR_POS_X) ++ | (sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].ypos << ATMEL_MPOP_CURSOR_POS_CURSOR_POS_Y)); ++ mpop_writel(sinfo, ATMEL_MPOP_CURSOR_SIZE, ++ (sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].xsize << ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_X) ++ | (sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].ysize << ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_Y)); ++ mpop_writel(sinfo, ATMEL_MPOP_CURSOR_WTC, ++ DIV_ROUND_UP(sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].xsize ++ * sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].ysize, 16)); ++ ++ /* Enable base overlay + any other enabled overlays. */ ++ mpop_writel(sinfo, ATMEL_MPOP_OCR, ATMEL_MPOP_OCR_RGBEN_MASK); ++ ++ if (sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].enabled) ++ mpop_writel(sinfo, ATMEL_MPOP_OCR, ++ mpop_readl(sinfo, ATMEL_MPOP_OCR) ++ | ATMEL_MPOP_OCR_CURSOREN_MASK); ++ if (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].enabled) ++ mpop_writel(sinfo, ATMEL_MPOP_OCR, ++ mpop_readl(sinfo, ATMEL_MPOP_OCR) ++ | ATMEL_MPOP_OCR_O1EN_MASK); ++ if (sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].enabled) ++ mpop_writel(sinfo, ATMEL_MPOP_OCR, ++ mpop_readl(sinfo, ATMEL_MPOP_OCR) ++ | ATMEL_MPOP_OCR_O2EN_MASK); ++ ++ /* Set background to black. */ ++ mpop_writel(sinfo, ATMEL_MPOP_BGCOLOR, 0); ++ ++ /* Setup source address registers */ ++ atmel_mpopfb_update_sar(info, &info->var); ++ ++ dev_dbg(info->device, " * DONE\n"); ++ ++ return 0; ++} ++ ++static int atmel_mpopfb_pan_display(struct fb_var_screeninfo *var, ++ struct fb_info *info) ++{ ++ dev_dbg(info->device, "%s\n", __func__); ++ ++ /* Change source address registers to reflect the panning. */ ++ atmel_mpopfb_update_sar(info, var); ++ ++ return 0; ++} ++ ++static void atmel_mpopfb_put_overlay_info(struct fb_info *info, ++ struct atmel_mpopfb_overlay_info overlay_info) ++{ ++ struct atmel_mpopfb_info *sinfo = info->par; ++ ++ /* We can update the position now since it is double buffered. */ ++ switch (overlay_info.overlay) { ++ case ATMEL_MPOPFB_OVERLAY1: ++ mpop_writel(sinfo, ATMEL_MPOP_O1_POS, ++ (overlay_info.xpos << ATMEL_MPOP_O1_POS_O1_POS_X) ++ | (overlay_info.ypos << ATMEL_MPOP_O1_POS_O1_POS_Y)); ++ break; ++ case ATMEL_MPOPFB_OVERLAY2: ++ mpop_writel(sinfo, ATMEL_MPOP_O2_POS, ++ (overlay_info.xpos << ATMEL_MPOP_O2_POS_O2_POS_X) ++ | (overlay_info.ypos << ATMEL_MPOP_O2_POS_O2_POS_Y)); ++ break; ++ case ATMEL_MPOPFB_CURSOR: ++ mpop_writel(sinfo, ATMEL_MPOP_CURSOR_POS, ++ (overlay_info.xpos << ATMEL_MPOP_CURSOR_POS_CURSOR_POS_X) ++ | (overlay_info.ypos << ATMEL_MPOP_CURSOR_POS_CURSOR_POS_Y)); ++ break; ++ default: ++ dev_warn(info->device, "Unknown overlay type: %d\n", ++ overlay_info.overlay); ++ return; ++ } ++ ++ /* Copy the overlay info to the mpopfb info structure. */ ++ sinfo->overlay_info[overlay_info.overlay] = overlay_info; ++} ++ ++static int atmel_mpopfb_ioctl(struct fb_info *info, ++ unsigned int cmd, unsigned long arg) ++{ ++ void __user *argp = (void __user *)arg; ++ struct atmel_mpopfb_info *sinfo = info->par; ++ struct atmel_mpopfb_overlay_info overlay_info; ++ ++ switch (cmd) { ++ case ATMEL_MPOP_FBIOPUT_OVERLAY_PALETTE:{ ++ struct atmel_mpopfb_overlay_palette palette; ++ if (copy_from_user(&palette, argp, sizeof(palette))) ++ return -EFAULT; ++ atmel_mpopfb_put_overlay_palette(sinfo, &palette); ++ return 0; ++ } ++ case ATMEL_MPOP_FBIOGET_OVERLAY_PALETTE:{ ++ struct atmel_mpopfb_overlay_palette palette; ++ atmel_mpopfb_get_overlay_palette(sinfo, &palette); ++ if (copy_to_user(argp, &palette, sizeof(palette))) ++ return -EFAULT; ++ return 0; ++ } ++ case ATMEL_MPOP_FBIOPUT_CURSOR_PALETTE:{ ++ struct atmel_mpopfb_cursor_palette palette; ++ if (copy_from_user(&palette, argp, sizeof(palette))) ++ return -EFAULT; ++ atmel_mpopfb_put_cursor_palette(sinfo, &palette); ++ return 0; ++ } ++ case ATMEL_MPOP_FBIOGET_CURSOR_PALETTE:{ ++ struct atmel_mpopfb_cursor_palette palette; ++ atmel_mpopfb_get_cursor_palette(sinfo, &palette); ++ if (copy_to_user(argp, &palette, sizeof(palette))) ++ return -EFAULT; ++ return 0; ++ } ++ case ATMEL_MPOP_FBIOPUT_OVERLAY_INFO: ++ if (copy_from_user(&overlay_info, argp, sizeof(overlay_info))) ++ return -EFAULT; ++ atmel_mpopfb_put_overlay_info(info, overlay_info); ++ return 0; ++ case ATMEL_MPOP_FBIOPUT_BASEIMG_INFO: ++ if (copy_from_user(&sinfo->baseimg_info, argp, ++ sizeof(sinfo->baseimg_info))) ++ return -EFAULT; ++ ++ /* Check that new baseimg parameters are sane. */ ++ if (atmel_mpopfb_check_var(&info->var, info)) ++ return -EFAULT; ++ ++ /* Update hardware configuration. */ ++ atmel_mpopfb_set_par(info); ++ return 0; ++ case ATMEL_MPOP_FBIOGET_BASEIMG_INFO: ++ return copy_to_user(argp, &sinfo->baseimg_info, ++ sizeof(sinfo->baseimg_info)) ? -EFAULT : 0; ++ case ATMEL_MPOP_FBIOPUT_RGBCONV_COEFFS: ++ if (copy_from_user(&sinfo->rgbconv_coeffs, argp, ++ sizeof(sinfo->rgbconv_coeffs))) ++ return -EFAULT; ++ ++ /* Update hardware configuration. */ ++ if (atmel_mpopfb_set_par(info)) ++ return -EFAULT; ++ ++ return 0; ++ case ATMEL_MPOP_FBIOGET_RGBCONV_COEFFS: ++ return copy_to_user(argp, &sinfo->rgbconv_coeffs, ++ sizeof(sinfo->rgbconv_coeffs)) ? -EFAULT : 0; ++ case ATMEL_MPOP_FBIO_CONNECT_TO_LCDC: ++ atmel_mpopfb_connect_to_lcdc(sinfo); ++ return 0; ++ case ATMEL_MPOP_FBIO_DISCONNECT_FROM_LCDC: ++ atmel_mpopfb_disconnect_from_lcdc(sinfo); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Force MPOP to be updated with any new parameters. */ ++ atmel_mpopfb_set_par(info); ++} ++ ++static int atmel_mpopfb_setcolreg(unsigned int regno, unsigned int red, ++ unsigned int green, unsigned int blue, ++ unsigned int transp, struct fb_info *info) ++{ ++ return 0; ++} ++ ++static struct fb_ops atmel_mpopfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_check_var = atmel_mpopfb_check_var, ++ .fb_set_par = atmel_mpopfb_set_par, ++ .fb_setcolreg = atmel_mpopfb_setcolreg, ++ .fb_pan_display = atmel_mpopfb_pan_display, ++ .fb_imageblit = cfb_imageblit, ++ .fb_ioctl = atmel_mpopfb_ioctl, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++}; ++ ++static irqreturn_t atmel_mpopfb_interrupt(int irq, void *dev_id) ++{ ++ struct fb_info *info = dev_id; ++ struct atmel_mpopfb_info *sinfo = info->par; ++ u32 status; ++ ++ /* Check which interrupt we have. */ ++ status = mpop_readl(sinfo, ATMEL_MPOP_INTSTATUS); ++ ++ /* Clear interrupts. */ ++ mpop_writel(sinfo, ATMEL_MPOP_INTCLEAR, status); ++ ++ if (status & ATMEL_MPOP_EOP) { ++ /* End Of Picture. Start new picture. */ ++ mpop_writel(sinfo, ATMEL_MPOP_CR, ++ ATMEL_MPOP_CR_START_MASK ++ | mpop_readl(sinfo, ATMEL_MPOP_CR)); ++ } else if (status & ATMEL_MPOP_OUT) { ++ dev_err(info->dev, ++ "MPOP Output DMA interface Bus Error (address=0x%x)!\n", ++ mpop_readl(sinfo, ATMEL_MPOP_OUT_BEAR)); ++ } else if (status & ATMEL_MPOP_YUV) { ++ dev_err(info->dev, ++ "MPOP YUV Picture Fetch DMA interface Bus Error (address=0x%x)!\n", ++ mpop_readl(sinfo, ATMEL_MPOP_YUV_BEAR)); ++ } else if (status & ATMEL_MPOP_OVERLAY) { ++ dev_err(info->dev, ++ "MPOP Overlay Picture Fetch DMA interface Bus Error (address=0x%x)!\n", ++ mpop_readl(sinfo, ATMEL_MPOP_OVERLAY_BEAR)); ++ } ++ ++ dev_dbg(info->device, "%s\n", __func__); ++ dev_dbg(info->device, " * status: 0x%x \n", status); ++ ++ return IRQ_HANDLED; ++} ++ ++static int __init atmel_mpopfb_init_fbinfo(struct atmel_mpopfb_info *sinfo) ++{ ++ struct fb_info *info = sinfo->info; ++ int ret = 0; ++ ++ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; ++ ++ dev_info(info->device, ++ "%luKiB frame buffer at %08lx (mapped at %p)\n", ++ (unsigned long)info->fix.smem_len / 1024, ++ (unsigned long)info->fix.smem_start, info->screen_base); ++ ++ return ret; ++} ++ ++static void atmel_mpopfb_start_clock(struct atmel_mpopfb_info *sinfo) ++{ ++ clk_enable(sinfo->mpop_hclk); ++ clk_enable(sinfo->mpop_pclk); ++} ++ ++static void atmel_mpopfb_stop_clock(struct atmel_mpopfb_info *sinfo) ++{ ++ clk_disable(sinfo->mpop_hclk); ++ clk_disable(sinfo->mpop_pclk); ++} ++ ++static int __init atmel_mpopfb_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct fb_info *info; ++ struct fb_info *lcdc_info; ++ struct atmel_mpopfb_info *sinfo; ++ struct atmel_mpopfb_info *pdata_sinfo; ++ struct resource *regs = NULL; ++ struct resource *slave = NULL; ++ struct resource *map = NULL; ++ int ret; ++ ++ dev_dbg(dev, "%s BEGIN\n", __func__); ++ ++ ret = -ENOMEM; ++ info = framebuffer_alloc(sizeof(struct atmel_mpopfb_info), dev); ++ if (!info) { ++ dev_err(dev, "cannot allocate memory\n"); ++ goto out; ++ } ++ ++ sinfo = info->par; ++ ++ if (dev->platform_data) { ++ pdata_sinfo = dev->platform_data; ++ sinfo->lcdc_pdev = pdata_sinfo->lcdc_pdev; ++ if (!sinfo->lcdc_pdev) { ++ dev_err(dev, "cannot get hold of lcdcfb device\n"); ++ goto free_info; ++ } ++ } else { ++ dev_err(dev, "cannot get default configuration\n"); ++ goto free_info; ++ } ++ ++ sinfo->info = info; ++ sinfo->pdev = pdev; ++ sinfo->running = 0; ++ sinfo->connected_to_lcdc = 0; ++ sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY1].enabled = 0; ++ sinfo->overlay_info[ATMEL_MPOPFB_OVERLAY2].enabled = 0; ++ sinfo->overlay_info[ATMEL_MPOPFB_CURSOR].enabled = 0; ++ ++ /* Setup default info */ ++ ++ /* Set fb_var_screeninfo equal to that of the lcdcfb driver. */ ++ lcdc_info = (struct fb_info *)platform_get_drvdata(sinfo->lcdc_pdev); ++ memcpy(&info->var, &lcdc_info->var, sizeof(struct fb_var_screeninfo)); ++ ++ /* Set default position of the image on the screen to (0,0) and ++ no scaling */ ++ sinfo->baseimg_info.xpos = 0; ++ sinfo->baseimg_info.ypos = 0; ++ sinfo->baseimg_info.xsize = info->var.xres; ++ sinfo->baseimg_info.ysize = info->var.yres; ++ ++ /* Use YCbCr --> RGB converion per default. */ ++ memcpy(&sinfo->rgbconv_coeffs, &atmel_mpop_ycrcb2rgb_coeffs, ++ sizeof(struct atmel_mpopfb_rgbconv_coeffs)); ++ ++ strcpy(info->fix.id, sinfo->pdev->name); ++ info->flags = ATMEL_MPOPFB_FBINFO_DEFAULT; ++ info->fbops = &atmel_mpopfb_ops; ++ ++ //memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); ++ info->fix = atmel_mpopfb_fix; ++ ++ /* Enable MPOP Clocks */ ++ sinfo->mpop_hclk = clk_get(dev, "hclk"); ++ sinfo->mpop_pclk = clk_get(dev, "pclk"); ++ if (IS_ERR(sinfo->mpop_hclk)) { ++ ret = PTR_ERR(sinfo->mpop_hclk); ++ goto put_bus_clk; ++ } ++ if (IS_ERR(sinfo->mpop_pclk)) { ++ ret = PTR_ERR(sinfo->mpop_pclk); ++ goto stop_clk; ++ } ++ atmel_mpopfb_start_clock(sinfo); ++ ++ //ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, ++ // info->monspecs.modedb_len, info->monspecs.modedb, ++ // sinfo->default_bpp); ++ //if (!ret) { ++ // dev_err(dev, "no suitable video mode found\n"); ++ // goto stop_clk; ++ //} ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_err(dev, "resources unusable\n"); ++ ret = -ENXIO; ++ goto stop_clk; ++ } ++ ++ slave = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!slave) { ++ dev_err(dev, "slave interface memory resource unusable\n"); ++ ret = -ENXIO; ++ goto stop_clk; ++ } ++ sinfo->slave_base = (void *)slave->start; ++ ++ sinfo->irq_base = platform_get_irq(pdev, 0); ++ if (sinfo->irq_base < 0) { ++ dev_err(dev, "unable to get irq\n"); ++ ret = sinfo->irq_base; ++ goto stop_clk; ++ } ++ ++ /* Initialize video memory */ ++ map = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (map) { ++ /* use a pre-allocated memory buffer */ ++ info->fix.smem_start = map->start; ++ info->fix.smem_len = map->end - map->start + 1; ++ if (!request_mem_region(info->fix.smem_start, ++ info->fix.smem_len, pdev->name)) { ++ //ret = -EBUSY; ++ //goto stop_clk; ++ /* Probably in use by LCD controller. */ ++ info->screen_base = lcdc_info->screen_base; ++ } else { ++ info->screen_base = ++ ioremap(info->fix.smem_start, info->fix.smem_len); ++ if (!info->screen_base) ++ goto release_intmem; ++ } ++ } else { ++ /* alocate memory buffer */ ++ ret = atmel_mpopfb_alloc_video_memory(sinfo); ++ if (ret < 0) { ++ dev_err(dev, "cannot allocate mpop framebuffer: %d\n", ++ ret); ++ goto stop_clk; ++ } ++ } ++ ++ /* MPOP registers */ ++ info->fix.mmio_start = regs->start; ++ info->fix.mmio_len = regs->end - regs->start + 1; ++ ++ if (!request_mem_region(info->fix.mmio_start, ++ info->fix.mmio_len, pdev->name)) { ++ ret = -EBUSY; ++ goto free_fb; ++ } ++ ++ sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); ++ if (!sinfo->mmio) { ++ dev_err(dev, "cannot map MPOP registers\n"); ++ goto release_mem; ++ } ++ ++ /* MPOP slave interface */ ++ if (!request_mem_region(slave->start, ++ slave->end - slave->start + 1, pdev->name)) { ++ dev_err(dev, ++ "error requesting memory region for MPOP slave interface\n"); ++ ret = -EBUSY; ++ goto unmap_mmio; ++ } ++ ++ /* interrupt */ ++ ret = ++ request_irq(sinfo->irq_base, atmel_mpopfb_interrupt, 0, pdev->name, ++ info); ++ if (ret) { ++ dev_err(dev, "request_irq failed: %d\n", ret); ++ goto release_mem_slave; ++ } ++ ++ ret = atmel_mpopfb_init_fbinfo(sinfo); ++ if (ret < 0) { ++ dev_err(dev, "init fbinfo failed: %d\n", ret); ++ goto unregister_irqs; ++ } ++ ++ /* ++ * This makes sure that our colour bitfield ++ * descriptors are correctly initialised. ++ */ ++ atmel_mpopfb_check_var(&info->var, info); ++ ++ ret = fb_set_var(info, &info->var); ++ if (ret) { ++ dev_warn(dev, "unable to set display parameters\n"); ++ goto free_cmap; ++ } ++ ++ dev_set_drvdata(dev, info); ++ ++ /* ++ * Tell the world that we're ready to go ++ */ ++ ret = register_framebuffer(info); ++ if (ret < 0) { ++ dev_err(dev, "failed to register framebuffer device: %d\n", ++ ret); ++ goto free_cmap; ++ } ++ ++ dev_info(dev, "fb%d: Atmel MPOP at 0x%08lx (mapped at %p), irq %lu\n", ++ info->node, info->fix.mmio_start, sinfo->mmio, ++ sinfo->irq_base); ++ ++ return 0; ++ ++free_cmap: ++ fb_dealloc_cmap(&info->cmap); ++unregister_irqs: ++ free_irq(sinfo->irq_base, info); ++release_mem_slave: ++ release_mem_region(slave->start, slave->end - slave->start + 1); ++unmap_mmio: ++ iounmap(sinfo->mmio); ++release_mem: ++ release_mem_region(info->fix.mmio_start, info->fix.mmio_len); ++free_fb: ++ if (map) ++ iounmap(info->screen_base); ++ else ++ atmel_mpopfb_free_video_memory(sinfo); ++ ++release_intmem: ++ if (map) ++ release_mem_region(info->fix.smem_start, info->fix.smem_len); ++stop_clk: ++ atmel_mpopfb_stop_clock(sinfo); ++ clk_put(sinfo->mpop_hclk); ++put_bus_clk: ++ if (sinfo->mpop_pclk) ++ clk_put(sinfo->mpop_pclk); ++free_info: ++ framebuffer_release(info); ++out: ++ dev_dbg(dev, "%s FAILED\n", __func__); ++ return ret; ++} ++ ++static int __exit atmel_mpopfb_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct atmel_mpopfb_info *sinfo = info->par; ++ ++ if (!sinfo) ++ return 0; ++ ++ unregister_framebuffer(info); ++ atmel_mpopfb_stop_clock(sinfo); ++ clk_put(sinfo->mpop_hclk); ++ clk_put(sinfo->mpop_pclk); ++ fb_dealloc_cmap(&info->cmap); ++ free_irq(sinfo->irq_base, info); ++ iounmap(sinfo->mmio); ++ release_mem_region(info->fix.mmio_start, info->fix.mmio_len); ++ if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { ++ iounmap(info->screen_base); ++ release_mem_region(info->fix.smem_start, info->fix.smem_len); ++ } else { ++ atmel_mpopfb_free_video_memory(sinfo); ++ } ++ ++ dev_set_drvdata(dev, NULL); ++ framebuffer_release(info); ++ ++ return 0; ++} ++ ++static struct platform_driver atmel_mpopfb_driver = { ++ .remove = __exit_p(atmel_mpopfb_remove), ++ .driver.name = "atmel_mpopfb", ++ .driver.owner = THIS_MODULE, ++}; ++ ++static int __init atmel_mpopfb_init(void) ++{ ++ return platform_driver_probe(&atmel_mpopfb_driver, atmel_mpopfb_probe); ++} ++ ++static void __exit atmel_mpopfb_exit(void) ++{ ++ platform_driver_unregister(&atmel_mpopfb_driver); ++} ++ ++module_init(atmel_mpopfb_init); ++module_exit(atmel_mpopfb_exit); ++ ++MODULE_DESCRIPTION("AT32 MPOP framebuffer driver"); ++MODULE_AUTHOR("Ronny Pedersen <rpedersen@atmel.com>"); ++MODULE_LICENSE("GPL"); +diff -urN linux-2.6.28.2-0rig//drivers/video/Kconfig linux-2.6.28.2/drivers/video/Kconfig +--- linux-2.6.28.2-0rig//drivers/video/Kconfig 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/video/Kconfig 2009-01-29 08:52:50.000000000 +0100 +@@ -940,6 +940,15 @@ + help + This enables support for the AT91/AT32 LCD Controller. + ++config FB_ATMEL_MPOP ++ tristate "AT32 MPOP support" ++ depends on FB && AVR32 && FB_ATMEL ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT ++ help ++ This enables support for the AT32 MPOP module. ++ + config FB_INTSRAM + bool "Frame Buffer in internal SRAM" + depends on FB_ATMEL && ARCH_AT91SAM9261 +diff -urN linux-2.6.28.2-0rig//drivers/video/Makefile linux-2.6.28.2/drivers/video/Makefile +--- linux-2.6.28.2-0rig//drivers/video/Makefile 2009-01-29 08:39:31.000000000 +0100 ++++ linux-2.6.28.2/drivers/video/Makefile 2009-01-29 08:52:50.000000000 +0100 +@@ -89,6 +89,7 @@ + obj-$(CONFIG_FB_HIT) += hitfb.o + obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o + obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o ++obj-$(CONFIG_FB_ATMEL_MPOP) += atmel_mpopfb.o + obj-$(CONFIG_FB_PVR2) += pvr2fb.o + obj-$(CONFIG_FB_VOODOO1) += sstfb.o + obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o +diff -urN linux-2.6.28.2-0rig//include/linux/atmel_mpopfb.h linux-2.6.28.2/include/linux/atmel_mpopfb.h +--- linux-2.6.28.2-0rig//include/linux/atmel_mpopfb.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/include/linux/atmel_mpopfb.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,112 @@ ++/* ++ * Header file for AT32 MPOP FB Driver ++ * ++ * Data structure and register user interface ++ * ++ * Copyright (C) 2007 Atmel Corporation ++ * ++ * 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 ++ */ ++#ifndef __ATMEL_MPOPFB_H__ ++#define __ATMEL_MPOPFB_H__ ++ ++#include <linux/fb.h> ++#include <linux/ioctl.h> ++ ++/* Coefficients for conversion to rgb. */ ++struct atmel_mpopfb_rgbconv_coeffs { ++ int r1, r2, r3, r4; ++ int g1, g2, g3, g4; ++ int b1, b2, b3, b4; ++}; ++ ++struct atmel_mpopfb_baseimg_info { ++ /* Position of the mpop base image ++ in the image sent to the LCD. */ ++ unsigned xpos; ++ unsigned ypos; ++ ++ /* The size of the base image after scaling. */ ++ unsigned xsize; ++ unsigned ysize; ++ ++ /* Signal that we should flip the video. */ ++ int flip; ++ ++}; ++ ++enum atmel_mpopfb_overlay_type { ++ ATMEL_MPOPFB_OVERLAY1 = 0, ++ ATMEL_MPOPFB_OVERLAY2 = 1, ++ ATMEL_MPOPFB_CURSOR = 2 ++}; ++ ++struct atmel_mpopfb_overlay_info { ++ /* Position of the mpop overlay image ++ in the image sent to the LCD. */ ++ unsigned xpos; ++ unsigned ypos; ++ /* The size of the overlay image. */ ++ unsigned xsize; ++ unsigned ysize; ++ /* Signal which overlay this info is for. */ ++ enum atmel_mpopfb_overlay_type overlay; ++ /* Signal if the overlay is enabled. */ ++ unsigned enabled; ++}; ++ ++struct atmel_mpopfb_overlay_palette_entry { ++ unsigned char alpha; ++ unsigned char red; ++ unsigned char green; ++ unsigned char blue; ++}; ++ ++struct atmel_mpopfb_cursor_palette_entry { ++ unsigned char:6; ++ unsigned char invert:1; ++ unsigned char visible:1; ++ unsigned char red; ++ unsigned char green; ++ unsigned char blue; ++}; ++ ++struct atmel_mpopfb_overlay_palette { ++ struct atmel_mpopfb_overlay_palette_entry entry[256]; ++}; ++ ++struct atmel_mpopfb_cursor_palette { ++ struct atmel_mpopfb_cursor_palette_entry entry[4]; ++}; ++ ++#define ATMEL_MPOP_FBIOPUT_BASEIMG_INFO _IOW('x',0,struct atmel_mpopfb_baseimg_info) ++#define ATMEL_MPOP_FBIOGET_BASEIMG_INFO _IOR('x',1,struct atmel_mpopfb_baseimg_info) ++#define ATMEL_MPOP_FBIOPUT_OVERLAY_INFO _IOW('x',2,struct atmel_mpopfb_overlay_info) ++#define ATMEL_MPOP_FBIO_CONNECT_TO_LCDC _IO( 'x',4) ++#define ATMEL_MPOP_FBIO_DISCONNECT_FROM_LCDC _IO( 'x',5) ++#define ATMEL_MPOP_FBIOPUT_RGBCONV_COEFFS _IOW('x',6,struct atmel_mpopfb_rgbconv_coeffs) ++#define ATMEL_MPOP_FBIOGET_RGBCONV_COEFFS _IOR('x',7,struct atmel_mpopfb_rgbconv_coeffs) ++#define ATMEL_MPOP_FBIOPUT_OVERLAY_PALETTE _IOW('x',8,struct atmel_mpopfb_overlay_palette) ++#define ATMEL_MPOP_FBIOGET_OVERLAY_PALETTE _IOR('x',9,struct atmel_mpopfb_overlay_palette) ++#define ATMEL_MPOP_FBIOPUT_CURSOR_PALETTE _IOW('x',10,struct atmel_mpopfb_cursor_palette) ++#define ATMEL_MPOP_FBIOGET_CURSOR_PALETTE _IOR('x',11,struct atmel_mpopfb_cursor_palette) ++ ++#define ATMEL_MPOP_RESIZE_FRAC_BITS 5 ++#define ATMEL_MPOP_SCALE_FRAC_DIV(a,b) ((((a) << ATMEL_MPOP_RESIZE_FRAC_BITS))/(b)) ++#define ATMEL_MPOP_CALC_SCALE(from_res,to_res) ATMEL_MPOP_SCALE_FRAC_DIV(from_res, to_res) ++ ++#define ATMEL_MPOP_COEFF_FRAC_BITS 8 ++ ++#endif +diff -urN linux-2.6.28.2-0rig//include/linux/atmel_pdca.h linux-2.6.28.2/include/linux/atmel_pdca.h +--- linux-2.6.28.2-0rig//include/linux/atmel_pdca.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/include/linux/atmel_pdca.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,120 @@ ++/* ++ * Driver for the Atmel PDCA Peripheral DMA Controller ++ * ++ * Copyright (C) 2008 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. ++ */ ++#ifndef __ATMEL_PDCA_H ++#define __ATMEL_PDCA_H ++ ++#include <linux/dmaengine.h> ++#include <linux/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/list.h> ++ ++struct pdca_pdata { ++ unsigned int nr_channels; ++}; ++ ++struct pdca_slave { ++ struct dma_slave slave; ++ u8 tx_periph_id; ++ u8 rx_periph_id; ++}; ++ ++struct pdca_desc { ++ /* This controller does not support hardware descriptors */ ++ struct scatterlist *sg; ++ int sg_len; ++ u8 reg_width; ++ u8 periph_id; ++ ++ struct list_head desc_node; ++ struct dma_async_tx_descriptor txd; ++}; ++ ++struct pdca_chan { ++ struct list_head freelist; ++ struct list_head queue; ++ ++ spinlock_t lock; ++ void __iomem *regs; ++ ++ struct scatterlist *cur_sg; ++ struct scatterlist *next_sg; ++ ++ struct tasklet_struct tasklet; ++ ++ dma_cookie_t completed; ++ struct dma_chan chan; ++ struct pdca_slave *pslave; ++ unsigned int descs_allocated; ++ bool enabled; ++}; ++ ++struct pdca_dev { ++ struct clk *hclk; ++ struct clk *pclk; ++ struct dma_device dma; ++ void __iomem *regs; ++ ++ struct pdca_chan chan[]; ++}; ++ ++static inline struct pdca_slave *dma_to_pdca_slave(struct dma_slave *slave) ++{ ++ return container_of(slave, struct pdca_slave, slave); ++} ++ ++static inline struct pdca_desc *txd_to_pdca_desc( ++ struct dma_async_tx_descriptor *txd) ++{ ++ return container_of(txd, struct pdca_desc, txd); ++} ++ ++static inline struct pdca_chan *dma_to_pdca_chan(struct dma_chan *chan) ++{ ++ return container_of(chan, struct pdca_chan, chan); ++} ++ ++static inline struct pdca_dev *dma_to_pdca_dev(struct dma_device *dma) ++{ ++ return container_of(dma, struct pdca_dev, dma); ++} ++ ++/* PDCA per-channel register definitions */ ++#define PDCA_MAR 0x0000 /* Memory Address */ ++#define PDCA_PSR 0x0004 /* Peripheral Select */ ++#define PDCA_TCR 0x0008 /* Transfer Counter */ ++#define PDCA_MARR 0x000c /* Memory Address Reload */ ++#define PDCA_TCRR 0x0010 /* Transfer Counter Reload */ ++#define PDCA_CR 0x0014 /* Control */ ++# define PDCA_CR_TEN ( 1 << 0) /* Transfer Enable */ ++# define PDCA_CR_TDIS ( 1 << 1) /* Transfer Disable */ ++# define PDCA_CR_ECLR ( 1 << 8) /* Error Clear */ ++#define PDCA_MR 0x0018 /* Mode */ ++# define PDCA_SIZE_BYTE ( 0 << 0) /* 8 bits per transfer */ ++# define PDCA_SIZE_HWORD ( 1 << 0) /* 16 bits per transfer */ ++# define PDCA_SIZE_WORD ( 2 << 0) /* 32 bits per transfer */ ++#define PDCA_SR 0x001c /* Status */ ++# define PDCA_SR_TEN ( 1 << 0) /* Transfer Enabled */ ++#define PDCA_IER 0x0020 /* Interrupt Enable */ ++#define PDCA_IDR 0x0024 /* Interrupt Disable */ ++#define PDCA_IMR 0x0028 /* Interrupt Mask */ ++#define PDCA_ISR 0x002c /* Interrupt Status */ ++# define PDCA_RCZ ( 1 << 0) /* Reload Counter Zero */ ++# define PDCA_TRC ( 1 << 1) /* Transfer Complete */ ++# define PDCA_TERR ( 1 << 2) /* Transfer Error */ ++ ++/* Address space occupied by one channel */ ++#define PDCA_CHAN_SIZE 0x40 ++ ++#define pdca_readl(base, reg) \ ++ __raw_readl((base) + PDCA_##reg) ++#define pdca_writel(base, reg, value) \ ++ __raw_writel((value), (base) + PDCA_##reg) ++ ++#endif /* __ATMEL_PDCA_H */ +diff -urN linux-2.6.28.2-0rig//include/linux/Kbuild linux-2.6.28.2/include/linux/Kbuild +--- linux-2.6.28.2-0rig//include/linux/Kbuild 2009-01-29 08:39:39.000000000 +0100 ++++ linux-2.6.28.2/include/linux/Kbuild 2009-01-29 08:52:50.000000000 +0100 +@@ -23,6 +23,7 @@ + header-y += atmarp.h + header-y += atmbr2684.h + header-y += atmclip.h ++header-y += atmel_mpopfb.h + header-y += atm_eni.h + header-y += atm_he.h + header-y += atm_idt77105.h +diff -urN linux-2.6.28.2-0rig//include/linux/spi/atmel_spi.h linux-2.6.28.2/include/linux/spi/atmel_spi.h +--- linux-2.6.28.2-0rig//include/linux/spi/atmel_spi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/include/linux/spi/atmel_spi.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,20 @@ ++/* ++ * Driver for Atmel AT32 and AT91 SPI Controllers ++ * ++ * Copyright (C) 2008 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. ++ */ ++#ifndef __LINUX_SPI_ATMEL_SPI_H ++#define __LINUX_SPI_ATMEL_SPI_H ++ ++struct atmel_spi_pdata { ++#ifndef CONFIG_SPI_ATMEL_HAVE_PDC ++ struct dma_slave *rx_dma_slave; ++ struct dma_slave *tx_dma_slave; ++#endif ++}; ++ ++#endif /* __LINUX_SPI_ATMEL_SPI_H */ +diff -urN linux-2.6.28.2-0rig//include/video/atmel_mpop.h linux-2.6.28.2/include/video/atmel_mpop.h +--- linux-2.6.28.2-0rig//include/video/atmel_mpop.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.28.2/include/video/atmel_mpop.h 2009-01-29 08:52:50.000000000 +0100 +@@ -0,0 +1,820 @@ ++/* ++ * Header file for AT32 MPOP Controller ++ * ++ * Data structure and register user interface ++ * ++ * Copyright (C) 2007 Atmel Corporation ++ * ++ * 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 ++ */ ++#ifndef __ATMEL_MPOP_H__ ++#define __ATMEL_MPOP_H__ ++ ++#include <linux/atmel_mpopfb.h> ++ ++/* MPOP Controller info data structure */ ++struct atmel_mpopfb_info { ++ spinlock_t lock; ++ struct fb_info *info; ++ void __iomem *mmio; ++ unsigned long irq_base; ++ void *slave_base; ++ ++ struct platform_device *pdev; ++ struct platform_device *lcdc_pdev; ++ struct clk *mpop_hclk; ++ struct clk *mpop_pclk; ++ unsigned int running; ++ unsigned int connected_to_lcdc; ++ unsigned long lcdc_old_smem_start; ++ unsigned long lcdc_old_bits_per_pixel; ++ struct atmel_mpopfb_baseimg_info baseimg_info; ++ struct atmel_mpopfb_overlay_info overlay_info[3]; ++ struct atmel_mpopfb_rgbconv_coeffs rgbconv_coeffs; ++}; ++ ++/* TODO! Clean up these defines.... */ ++#define ATMEL_MPOP_B 0 ++#define ATMEL_MPOP_B1 0 ++#define ATMEL_MPOP_B1_MASK 0x00000fff ++#define ATMEL_MPOP_B1_OFFSET 0 ++#define ATMEL_MPOP_B1_SIZE 12 ++#define ATMEL_MPOP_B2 12 ++#define ATMEL_MPOP_B2B1 0x00000024 ++#define ATMEL_MPOP_B2B1_B1 0 ++#define ATMEL_MPOP_B2B1_B1_MASK 0x00000fff ++#define ATMEL_MPOP_B2B1_B1_OFFSET 0 ++#define ATMEL_MPOP_B2B1_B1_SIZE 12 ++#define ATMEL_MPOP_B2B1_B2 12 ++#define ATMEL_MPOP_B2B1_B2_MASK 0x00fff000 ++#define ATMEL_MPOP_B2B1_B2_OFFSET 12 ++#define ATMEL_MPOP_B2B1_B2_SIZE 12 ++#define ATMEL_MPOP_B2_MASK 0x00fff000 ++#define ATMEL_MPOP_B2_OFFSET 12 ++#define ATMEL_MPOP_B2_SIZE 12 ++#define ATMEL_MPOP_B3 0 ++#define ATMEL_MPOP_B3_MASK 0x00000fff ++#define ATMEL_MPOP_B3_OFFSET 0 ++#define ATMEL_MPOP_B3_SIZE 12 ++#define ATMEL_MPOP_B4 12 ++#define ATMEL_MPOP_B4B3 0x00000028 ++#define ATMEL_MPOP_B4B3_B3 0 ++#define ATMEL_MPOP_B4B3_B3_MASK 0x00000fff ++#define ATMEL_MPOP_B4B3_B3_OFFSET 0 ++#define ATMEL_MPOP_B4B3_B3_SIZE 12 ++#define ATMEL_MPOP_B4B3_B4 12 ++#define ATMEL_MPOP_B4B3_B4_MASK 0xfffff000 ++#define ATMEL_MPOP_B4B3_B4_OFFSET 12 ++#define ATMEL_MPOP_B4B3_B4_SIZE 20 ++#define ATMEL_MPOP_B4_MASK 0xfffff000 ++#define ATMEL_MPOP_B4_OFFSET 12 ++#define ATMEL_MPOP_B4_SIZE 20 ++#define ATMEL_MPOP_BGCOLOR 0x00000090 ++#define ATMEL_MPOP_BGCOLOR_BGCOLOR 0 ++#define ATMEL_MPOP_BGCOLOR_BGCOLOR_MASK 0xffffffff ++#define ATMEL_MPOP_BGCOLOR_BGCOLOR_OFFSET 0 ++#define ATMEL_MPOP_BGCOLOR_BGCOLOR_SIZE 32 ++#define ATMEL_MPOP_BGCOLOR_MASK 0xffffffff ++#define ATMEL_MPOP_BGCOLOR_OFFSET 0 ++#define ATMEL_MPOP_BGCOLOR_SIZE 32 ++#define ATMEL_MPOP_BGR 6 ++#define ATMEL_MPOP_BGR_MASK 0x00000040 ++#define ATMEL_MPOP_BGR_OFFSET 6 ++#define ATMEL_MPOP_BGR_SIZE 1 ++#define ATMEL_MPOP_B_MASK 0x000000ff ++#define ATMEL_MPOP_B_OFFSET 0 ++#define ATMEL_MPOP_B_SIZE 8 ++#define ATMEL_MPOP_CACHEDIS 8 ++#define ATMEL_MPOP_CACHEDIS_MASK 0x00000100 ++#define ATMEL_MPOP_CACHEDIS_OFFSET 8 ++#define ATMEL_MPOP_CACHEDIS_SIZE 1 ++#define ATMEL_MPOP_CR 0x00000000 ++#define ATMEL_MPOP_CR_CACHEDIS 8 ++#define ATMEL_MPOP_CR_CACHEDIS_MASK 0x00000100 ++#define ATMEL_MPOP_CR_CACHEDIS_OFFSET 8 ++#define ATMEL_MPOP_CR_CACHEDIS_SIZE 1 ++#define ATMEL_MPOP_CR_EN 0 ++#define ATMEL_MPOP_CR_EN_MASK 0x00000001 ++#define ATMEL_MPOP_CR_EN_OFFSET 0 ++#define ATMEL_MPOP_CR_EN_SIZE 1 ++#define ATMEL_MPOP_CR_OUT_BGR 3 ++#define ATMEL_MPOP_CR_OUT_BGR_MASK 0x00000008 ++#define ATMEL_MPOP_CR_OUT_BGR_OFFSET 3 ++#define ATMEL_MPOP_CR_OUT_BGR_SIZE 1 ++#define ATMEL_MPOP_CR_OUT_CTRL 2 ++#define ATMEL_MPOP_CR_OUT_CTRL_MASK 0x00000004 ++#define ATMEL_MPOP_CR_OUT_CTRL_OFFSET 2 ++#define ATMEL_MPOP_CR_OUT_CTRL_SIZE 1 ++#define ATMEL_MPOP_CR_START 1 ++#define ATMEL_MPOP_CR_START_MASK 0x00000002 ++#define ATMEL_MPOP_CR_START_OFFSET 1 ++#define ATMEL_MPOP_CR_START_SIZE 1 ++#define ATMEL_MPOP_CURSOREN 0 ++#define ATMEL_MPOP_CURSOREN_MASK 0x00000001 ++#define ATMEL_MPOP_CURSOREN_OFFSET 0 ++#define ATMEL_MPOP_CURSOREN_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P0 0x00000080 ++#define ATMEL_MPOP_CURSOR_P0_B 0 ++#define ATMEL_MPOP_CURSOR_P0_B_MASK 0x000000ff ++#define ATMEL_MPOP_CURSOR_P0_B_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_P0_B_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P0_G 8 ++#define ATMEL_MPOP_CURSOR_P0_G_MASK 0x0000ff00 ++#define ATMEL_MPOP_CURSOR_P0_G_OFFSET 8 ++#define ATMEL_MPOP_CURSOR_P0_G_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P0_INVERT 25 ++#define ATMEL_MPOP_CURSOR_P0_INVERT_MASK 0x02000000 ++#define ATMEL_MPOP_CURSOR_P0_INVERT_OFFSET 25 ++#define ATMEL_MPOP_CURSOR_P0_INVERT_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P0_R 16 ++#define ATMEL_MPOP_CURSOR_P0_R_MASK 0x00ff0000 ++#define ATMEL_MPOP_CURSOR_P0_R_OFFSET 16 ++#define ATMEL_MPOP_CURSOR_P0_R_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P0_VISIBLE 24 ++#define ATMEL_MPOP_CURSOR_P0_VISIBLE_MASK 0x01000000 ++#define ATMEL_MPOP_CURSOR_P0_VISIBLE_OFFSET 24 ++#define ATMEL_MPOP_CURSOR_P0_VISIBLE_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P1 0x00000084 ++#define ATMEL_MPOP_CURSOR_P1_B 0 ++#define ATMEL_MPOP_CURSOR_P1_B_MASK 0x000000ff ++#define ATMEL_MPOP_CURSOR_P1_B_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_P1_B_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P1_G 8 ++#define ATMEL_MPOP_CURSOR_P1_G_MASK 0x0000ff00 ++#define ATMEL_MPOP_CURSOR_P1_G_OFFSET 8 ++#define ATMEL_MPOP_CURSOR_P1_G_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P1_INVERT 25 ++#define ATMEL_MPOP_CURSOR_P1_INVERT_MASK 0x02000000 ++#define ATMEL_MPOP_CURSOR_P1_INVERT_OFFSET 25 ++#define ATMEL_MPOP_CURSOR_P1_INVERT_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P1_R 16 ++#define ATMEL_MPOP_CURSOR_P1_R_MASK 0x00ff0000 ++#define ATMEL_MPOP_CURSOR_P1_R_OFFSET 16 ++#define ATMEL_MPOP_CURSOR_P1_R_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P1_VISIBLE 24 ++#define ATMEL_MPOP_CURSOR_P1_VISIBLE_MASK 0x01000000 ++#define ATMEL_MPOP_CURSOR_P1_VISIBLE_OFFSET 24 ++#define ATMEL_MPOP_CURSOR_P1_VISIBLE_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P2 0x00000088 ++#define ATMEL_MPOP_CURSOR_P2_B 0 ++#define ATMEL_MPOP_CURSOR_P2_B_MASK 0x000000ff ++#define ATMEL_MPOP_CURSOR_P2_B_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_P2_B_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P2_G 8 ++#define ATMEL_MPOP_CURSOR_P2_G_MASK 0x0000ff00 ++#define ATMEL_MPOP_CURSOR_P2_G_OFFSET 8 ++#define ATMEL_MPOP_CURSOR_P2_G_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P2_INVERT 25 ++#define ATMEL_MPOP_CURSOR_P2_INVERT_MASK 0x02000000 ++#define ATMEL_MPOP_CURSOR_P2_INVERT_OFFSET 25 ++#define ATMEL_MPOP_CURSOR_P2_INVERT_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P2_R 16 ++#define ATMEL_MPOP_CURSOR_P2_R_MASK 0x00ff0000 ++#define ATMEL_MPOP_CURSOR_P2_R_OFFSET 16 ++#define ATMEL_MPOP_CURSOR_P2_R_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P2_VISIBLE 24 ++#define ATMEL_MPOP_CURSOR_P2_VISIBLE_MASK 0x01000000 ++#define ATMEL_MPOP_CURSOR_P2_VISIBLE_OFFSET 24 ++#define ATMEL_MPOP_CURSOR_P2_VISIBLE_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P3 0x0000008c ++#define ATMEL_MPOP_CURSOR_P3_B 0 ++#define ATMEL_MPOP_CURSOR_P3_B_MASK 0x000000ff ++#define ATMEL_MPOP_CURSOR_P3_B_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_P3_B_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P3_G 8 ++#define ATMEL_MPOP_CURSOR_P3_G_MASK 0x0000ff00 ++#define ATMEL_MPOP_CURSOR_P3_G_OFFSET 8 ++#define ATMEL_MPOP_CURSOR_P3_G_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P3_INVERT 25 ++#define ATMEL_MPOP_CURSOR_P3_INVERT_MASK 0x02000000 ++#define ATMEL_MPOP_CURSOR_P3_INVERT_OFFSET 25 ++#define ATMEL_MPOP_CURSOR_P3_INVERT_SIZE 1 ++#define ATMEL_MPOP_CURSOR_P3_R 16 ++#define ATMEL_MPOP_CURSOR_P3_R_MASK 0x00ff0000 ++#define ATMEL_MPOP_CURSOR_P3_R_OFFSET 16 ++#define ATMEL_MPOP_CURSOR_P3_R_SIZE 8 ++#define ATMEL_MPOP_CURSOR_P3_VISIBLE 24 ++#define ATMEL_MPOP_CURSOR_P3_VISIBLE_MASK 0x01000000 ++#define ATMEL_MPOP_CURSOR_P3_VISIBLE_OFFSET 24 ++#define ATMEL_MPOP_CURSOR_P3_VISIBLE_SIZE 1 ++#define ATMEL_MPOP_CURSOR_POS 0x00000058 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_X 11 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_X_OFFSET 11 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_X_SIZE 11 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_Y 0 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_POS_CURSOR_POS_Y_SIZE 11 ++#define ATMEL_MPOP_CURSOR_POS_X 11 ++#define ATMEL_MPOP_CURSOR_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_CURSOR_POS_X_OFFSET 11 ++#define ATMEL_MPOP_CURSOR_POS_X_SIZE 11 ++#define ATMEL_MPOP_CURSOR_POS_Y 0 ++#define ATMEL_MPOP_CURSOR_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_CURSOR_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_POS_Y_SIZE 11 ++#define ATMEL_MPOP_CURSOR_SAR 0x00000048 ++#define ATMEL_MPOP_CURSOR_SAR_CURSOR_SAR 0 ++#define ATMEL_MPOP_CURSOR_SAR_CURSOR_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_CURSOR_SAR_CURSOR_SAR_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_SAR_CURSOR_SAR_SIZE 32 ++#define ATMEL_MPOP_CURSOR_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_CURSOR_SAR_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_SAR_SIZE 32 ++#define ATMEL_MPOP_CURSOR_SIZE 0x0000006c ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_X 11 ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_Y 0 ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_SIZE_CURSOR_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_CURSOR_SIZE_X 11 ++#define ATMEL_MPOP_CURSOR_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_CURSOR_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_CURSOR_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_CURSOR_SIZE_Y 0 ++#define ATMEL_MPOP_CURSOR_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_CURSOR_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_CURSOR_WTC 0x0000007c ++#define ATMEL_MPOP_CURSOR_WTC_CURSOR_WTC 0 ++#define ATMEL_MPOP_CURSOR_WTC_CURSOR_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_CURSOR_WTC_CURSOR_WTC_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_WTC_CURSOR_WTC_SIZE 32 ++#define ATMEL_MPOP_CURSOR_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_CURSOR_WTC_OFFSET 0 ++#define ATMEL_MPOP_CURSOR_WTC_SIZE 32 ++#define ATMEL_MPOP_DISP_MAX_COORD 0x00000010 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_X 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_X_MASK 0x003ff800 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_X_OFFSET 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_X_SIZE 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_Y 0 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_Y_MASK 0x000007ff ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_Y_OFFSET 0 ++#define ATMEL_MPOP_DISP_MAX_COORD_DISP_MAX_COORD_Y_SIZE 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_X 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_X_MASK 0x003ff800 ++#define ATMEL_MPOP_DISP_MAX_COORD_X_OFFSET 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_X_SIZE 11 ++#define ATMEL_MPOP_DISP_MAX_COORD_Y 0 ++#define ATMEL_MPOP_DISP_MAX_COORD_Y_MASK 0x000007ff ++#define ATMEL_MPOP_DISP_MAX_COORD_Y_OFFSET 0 ++#define ATMEL_MPOP_DISP_MAX_COORD_Y_SIZE 11 ++#define ATMEL_MPOP_EN 0 ++#define ATMEL_MPOP_EN_MASK 0x00000001 ++#define ATMEL_MPOP_EN_OFFSET 0 ++#define ATMEL_MPOP_EN_SIZE 1 ++#define ATMEL_MPOP_EOP 3 ++#define ATMEL_MPOP_EOP_MASK 0x00000008 ++#define ATMEL_MPOP_EOP_OFFSET 3 ++#define ATMEL_MPOP_EOP_SIZE 1 ++#define ATMEL_MPOP_G 8 ++#define ATMEL_MPOP_G1 0 ++#define ATMEL_MPOP_G1_MASK 0x00000fff ++#define ATMEL_MPOP_G1_OFFSET 0 ++#define ATMEL_MPOP_G1_SIZE 12 ++#define ATMEL_MPOP_G2 12 ++#define ATMEL_MPOP_G2G1 0x0000001c ++#define ATMEL_MPOP_G2G1_G1 0 ++#define ATMEL_MPOP_G2G1_G1_MASK 0x00000fff ++#define ATMEL_MPOP_G2G1_G1_OFFSET 0 ++#define ATMEL_MPOP_G2G1_G1_SIZE 12 ++#define ATMEL_MPOP_G2G1_G2 12 ++#define ATMEL_MPOP_G2G1_G2_MASK 0x00fff000 ++#define ATMEL_MPOP_G2G1_G2_OFFSET 12 ++#define ATMEL_MPOP_G2G1_G2_SIZE 12 ++#define ATMEL_MPOP_G2_MASK 0x00fff000 ++#define ATMEL_MPOP_G2_OFFSET 12 ++#define ATMEL_MPOP_G2_SIZE 12 ++#define ATMEL_MPOP_G3 0 ++#define ATMEL_MPOP_G3_MASK 0x00000fff ++#define ATMEL_MPOP_G3_OFFSET 0 ++#define ATMEL_MPOP_G3_SIZE 12 ++#define ATMEL_MPOP_G4 12 ++#define ATMEL_MPOP_G4G3 0x00000020 ++#define ATMEL_MPOP_G4G3_G3 0 ++#define ATMEL_MPOP_G4G3_G3_MASK 0x00000fff ++#define ATMEL_MPOP_G4G3_G3_OFFSET 0 ++#define ATMEL_MPOP_G4G3_G3_SIZE 12 ++#define ATMEL_MPOP_G4G3_G4 12 ++#define ATMEL_MPOP_G4G3_G4_MASK 0xfffff000 ++#define ATMEL_MPOP_G4G3_G4_OFFSET 12 ++#define ATMEL_MPOP_G4G3_G4_SIZE 20 ++#define ATMEL_MPOP_G4_MASK 0xfffff000 ++#define ATMEL_MPOP_G4_OFFSET 12 ++#define ATMEL_MPOP_G4_SIZE 20 ++#define ATMEL_MPOP_G_MASK 0x0000ff00 ++#define ATMEL_MPOP_G_OFFSET 8 ++#define ATMEL_MPOP_G_SIZE 8 ++#define ATMEL_MPOP_INTCLEAR 0x000000b0 ++#define ATMEL_MPOP_INTCLEAR_EOP 3 ++#define ATMEL_MPOP_INTCLEAR_EOP_MASK 0x00000008 ++#define ATMEL_MPOP_INTCLEAR_EOP_OFFSET 3 ++#define ATMEL_MPOP_INTCLEAR_EOP_SIZE 1 ++#define ATMEL_MPOP_INTCLEAR_OUT 2 ++#define ATMEL_MPOP_INTCLEAR_OUT_MASK 0x00000004 ++#define ATMEL_MPOP_INTCLEAR_OUT_OFFSET 2 ++#define ATMEL_MPOP_INTCLEAR_OUT_SIZE 1 ++#define ATMEL_MPOP_INTCLEAR_OVERLAY 1 ++#define ATMEL_MPOP_INTCLEAR_OVERLAY_MASK 0x00000002 ++#define ATMEL_MPOP_INTCLEAR_OVERLAY_OFFSET 1 ++#define ATMEL_MPOP_INTCLEAR_OVERLAY_SIZE 1 ++#define ATMEL_MPOP_INTCLEAR_SOP 4 ++#define ATMEL_MPOP_INTCLEAR_SOP_MASK 0x00000010 ++#define ATMEL_MPOP_INTCLEAR_SOP_OFFSET 4 ++#define ATMEL_MPOP_INTCLEAR_SOP_SIZE 1 ++#define ATMEL_MPOP_INTCLEAR_YUV 0 ++#define ATMEL_MPOP_INTCLEAR_YUV_MASK 0x00000001 ++#define ATMEL_MPOP_INTCLEAR_YUV_OFFSET 0 ++#define ATMEL_MPOP_INTCLEAR_YUV_SIZE 1 ++#define ATMEL_MPOP_INTDIS 0x000000a4 ++#define ATMEL_MPOP_INTDIS_EOP 3 ++#define ATMEL_MPOP_INTDIS_EOP_MASK 0x00000008 ++#define ATMEL_MPOP_INTDIS_EOP_OFFSET 3 ++#define ATMEL_MPOP_INTDIS_EOP_SIZE 1 ++#define ATMEL_MPOP_INTDIS_OUT 2 ++#define ATMEL_MPOP_INTDIS_OUT_MASK 0x00000004 ++#define ATMEL_MPOP_INTDIS_OUT_OFFSET 2 ++#define ATMEL_MPOP_INTDIS_OUT_SIZE 1 ++#define ATMEL_MPOP_INTDIS_OVERLAY 1 ++#define ATMEL_MPOP_INTDIS_OVERLAY_MASK 0x00000002 ++#define ATMEL_MPOP_INTDIS_OVERLAY_OFFSET 1 ++#define ATMEL_MPOP_INTDIS_OVERLAY_SIZE 1 ++#define ATMEL_MPOP_INTDIS_SOP 4 ++#define ATMEL_MPOP_INTDIS_SOP_MASK 0x00000010 ++#define ATMEL_MPOP_INTDIS_SOP_OFFSET 4 ++#define ATMEL_MPOP_INTDIS_SOP_SIZE 1 ++#define ATMEL_MPOP_INTDIS_YUV 0 ++#define ATMEL_MPOP_INTDIS_YUV_MASK 0x00000001 ++#define ATMEL_MPOP_INTDIS_YUV_OFFSET 0 ++#define ATMEL_MPOP_INTDIS_YUV_SIZE 1 ++#define ATMEL_MPOP_INTEN 0x000000a0 ++#define ATMEL_MPOP_INTEN_EOP 3 ++#define ATMEL_MPOP_INTEN_EOP_MASK 0x00000008 ++#define ATMEL_MPOP_INTEN_EOP_OFFSET 3 ++#define ATMEL_MPOP_INTEN_EOP_SIZE 1 ++#define ATMEL_MPOP_INTEN_OUT 2 ++#define ATMEL_MPOP_INTEN_OUT_MASK 0x00000004 ++#define ATMEL_MPOP_INTEN_OUT_OFFSET 2 ++#define ATMEL_MPOP_INTEN_OUT_SIZE 1 ++#define ATMEL_MPOP_INTEN_OVERLAY 1 ++#define ATMEL_MPOP_INTEN_OVERLAY_MASK 0x00000002 ++#define ATMEL_MPOP_INTEN_OVERLAY_OFFSET 1 ++#define ATMEL_MPOP_INTEN_OVERLAY_SIZE 1 ++#define ATMEL_MPOP_INTEN_SOP 4 ++#define ATMEL_MPOP_INTEN_SOP_MASK 0x00000010 ++#define ATMEL_MPOP_INTEN_SOP_OFFSET 4 ++#define ATMEL_MPOP_INTEN_SOP_SIZE 1 ++#define ATMEL_MPOP_INTEN_YUV 0 ++#define ATMEL_MPOP_INTEN_YUV_MASK 0x00000001 ++#define ATMEL_MPOP_INTEN_YUV_OFFSET 0 ++#define ATMEL_MPOP_INTEN_YUV_SIZE 1 ++#define ATMEL_MPOP_INTMASK 0x000000a8 ++#define ATMEL_MPOP_INTMASK_EOP 3 ++#define ATMEL_MPOP_INTMASK_EOP_MASK 0x00000008 ++#define ATMEL_MPOP_INTMASK_EOP_OFFSET 3 ++#define ATMEL_MPOP_INTMASK_EOP_SIZE 1 ++#define ATMEL_MPOP_INTMASK_OUT 2 ++#define ATMEL_MPOP_INTMASK_OUT_MASK 0x00000004 ++#define ATMEL_MPOP_INTMASK_OUT_OFFSET 2 ++#define ATMEL_MPOP_INTMASK_OUT_SIZE 1 ++#define ATMEL_MPOP_INTMASK_OVERLAY 1 ++#define ATMEL_MPOP_INTMASK_OVERLAY_MASK 0x00000002 ++#define ATMEL_MPOP_INTMASK_OVERLAY_OFFSET 1 ++#define ATMEL_MPOP_INTMASK_OVERLAY_SIZE 1 ++#define ATMEL_MPOP_INTMASK_SOP 4 ++#define ATMEL_MPOP_INTMASK_SOP_MASK 0x00000010 ++#define ATMEL_MPOP_INTMASK_SOP_OFFSET 4 ++#define ATMEL_MPOP_INTMASK_SOP_SIZE 1 ++#define ATMEL_MPOP_INTMASK_YUV 0 ++#define ATMEL_MPOP_INTMASK_YUV_MASK 0x00000001 ++#define ATMEL_MPOP_INTMASK_YUV_OFFSET 0 ++#define ATMEL_MPOP_INTMASK_YUV_SIZE 1 ++#define ATMEL_MPOP_INTSTATUS 0x000000ac ++#define ATMEL_MPOP_INTSTATUS_EOP 3 ++#define ATMEL_MPOP_INTSTATUS_EOP_MASK 0x00000008 ++#define ATMEL_MPOP_INTSTATUS_EOP_OFFSET 3 ++#define ATMEL_MPOP_INTSTATUS_EOP_SIZE 1 ++#define ATMEL_MPOP_INTSTATUS_OUT 2 ++#define ATMEL_MPOP_INTSTATUS_OUT_MASK 0x00000004 ++#define ATMEL_MPOP_INTSTATUS_OUT_OFFSET 2 ++#define ATMEL_MPOP_INTSTATUS_OUT_SIZE 1 ++#define ATMEL_MPOP_INTSTATUS_OVERLAY 1 ++#define ATMEL_MPOP_INTSTATUS_OVERLAY_MASK 0x00000002 ++#define ATMEL_MPOP_INTSTATUS_OVERLAY_OFFSET 1 ++#define ATMEL_MPOP_INTSTATUS_OVERLAY_SIZE 1 ++#define ATMEL_MPOP_INTSTATUS_SOP 4 ++#define ATMEL_MPOP_INTSTATUS_SOP_MASK 0x00000010 ++#define ATMEL_MPOP_INTSTATUS_SOP_OFFSET 4 ++#define ATMEL_MPOP_INTSTATUS_SOP_SIZE 1 ++#define ATMEL_MPOP_INTSTATUS_YUV 0 ++#define ATMEL_MPOP_INTSTATUS_YUV_MASK 0x00000001 ++#define ATMEL_MPOP_INTSTATUS_YUV_OFFSET 0 ++#define ATMEL_MPOP_INTSTATUS_YUV_SIZE 1 ++#define ATMEL_MPOP_INVERT 25 ++#define ATMEL_MPOP_INVERT_MASK 0x02000000 ++#define ATMEL_MPOP_INVERT_OFFSET 25 ++#define ATMEL_MPOP_INVERT_SIZE 1 ++#define ATMEL_MPOP_MSTR_PTR 0x0000000c ++#define ATMEL_MPOP_MSTR_PTR_MASK 0xffffffff ++#define ATMEL_MPOP_MSTR_PTR_MSTR_PTR 0 ++#define ATMEL_MPOP_MSTR_PTR_MSTR_PTR_MASK 0xffffffff ++#define ATMEL_MPOP_MSTR_PTR_MSTR_PTR_OFFSET 0 ++#define ATMEL_MPOP_MSTR_PTR_MSTR_PTR_SIZE 32 ++#define ATMEL_MPOP_MSTR_PTR_OFFSET 0 ++#define ATMEL_MPOP_MSTR_PTR_SIZE 32 ++#define ATMEL_MPOP_O1EN 1 ++#define ATMEL_MPOP_O1EN_MASK 0x00000002 ++#define ATMEL_MPOP_O1EN_OFFSET 1 ++#define ATMEL_MPOP_O1EN_SIZE 1 ++#define ATMEL_MPOP_O1_POS 0x00000050 ++#define ATMEL_MPOP_O1_POS_O1_POS_X 11 ++#define ATMEL_MPOP_O1_POS_O1_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O1_POS_O1_POS_X_OFFSET 11 ++#define ATMEL_MPOP_O1_POS_O1_POS_X_SIZE 11 ++#define ATMEL_MPOP_O1_POS_O1_POS_Y 0 ++#define ATMEL_MPOP_O1_POS_O1_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O1_POS_O1_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_O1_POS_O1_POS_Y_SIZE 11 ++#define ATMEL_MPOP_O1_POS_X 11 ++#define ATMEL_MPOP_O1_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O1_POS_X_OFFSET 11 ++#define ATMEL_MPOP_O1_POS_X_SIZE 11 ++#define ATMEL_MPOP_O1_POS_Y 0 ++#define ATMEL_MPOP_O1_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O1_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_O1_POS_Y_SIZE 11 ++#define ATMEL_MPOP_O1_SAR 0x00000040 ++#define ATMEL_MPOP_O1_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_O1_SAR_O1_SAR 0 ++#define ATMEL_MPOP_O1_SAR_O1_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_O1_SAR_O1_SAR_OFFSET 0 ++#define ATMEL_MPOP_O1_SAR_O1_SAR_SIZE 32 ++#define ATMEL_MPOP_O1_SAR_OFFSET 0 ++#define ATMEL_MPOP_O1_SAR_SIZE 32 ++#define ATMEL_MPOP_O1_SIZE 0x00000064 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_X 11 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_Y 0 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_O1_SIZE_O1_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_O1_SIZE_X 11 ++#define ATMEL_MPOP_O1_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O1_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_O1_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_O1_SIZE_Y 0 ++#define ATMEL_MPOP_O1_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O1_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_O1_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_O1_WTC 0x00000074 ++#define ATMEL_MPOP_O1_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_O1_WTC_O1_WTC 0 ++#define ATMEL_MPOP_O1_WTC_O1_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_O1_WTC_O1_WTC_OFFSET 0 ++#define ATMEL_MPOP_O1_WTC_O1_WTC_SIZE 32 ++#define ATMEL_MPOP_O1_WTC_OFFSET 0 ++#define ATMEL_MPOP_O1_WTC_SIZE 32 ++#define ATMEL_MPOP_O2EN 2 ++#define ATMEL_MPOP_O2EN_MASK 0x00000004 ++#define ATMEL_MPOP_O2EN_OFFSET 2 ++#define ATMEL_MPOP_O2EN_SIZE 1 ++#define ATMEL_MPOP_O2_POS 0x00000054 ++#define ATMEL_MPOP_O2_POS_O2_POS_X 11 ++#define ATMEL_MPOP_O2_POS_O2_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O2_POS_O2_POS_X_OFFSET 11 ++#define ATMEL_MPOP_O2_POS_O2_POS_X_SIZE 11 ++#define ATMEL_MPOP_O2_POS_O2_POS_Y 0 ++#define ATMEL_MPOP_O2_POS_O2_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O2_POS_O2_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_O2_POS_O2_POS_Y_SIZE 11 ++#define ATMEL_MPOP_O2_POS_X 11 ++#define ATMEL_MPOP_O2_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O2_POS_X_OFFSET 11 ++#define ATMEL_MPOP_O2_POS_X_SIZE 11 ++#define ATMEL_MPOP_O2_POS_Y 0 ++#define ATMEL_MPOP_O2_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O2_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_O2_POS_Y_SIZE 11 ++#define ATMEL_MPOP_O2_SAR 0x00000044 ++#define ATMEL_MPOP_O2_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_O2_SAR_O2_SAR 0 ++#define ATMEL_MPOP_O2_SAR_O2_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_O2_SAR_O2_SAR_OFFSET 0 ++#define ATMEL_MPOP_O2_SAR_O2_SAR_SIZE 32 ++#define ATMEL_MPOP_O2_SAR_OFFSET 0 ++#define ATMEL_MPOP_O2_SAR_SIZE 32 ++#define ATMEL_MPOP_O2_SIZE 0x00000068 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_X 11 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_Y 0 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_O2_SIZE_O2_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_O2_SIZE_X 11 ++#define ATMEL_MPOP_O2_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_O2_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_O2_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_O2_SIZE_Y 0 ++#define ATMEL_MPOP_O2_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_O2_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_O2_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_O2_WTC 0x00000078 ++#define ATMEL_MPOP_O2_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_O2_WTC_O2_WTC 0 ++#define ATMEL_MPOP_O2_WTC_O2_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_O2_WTC_O2_WTC_OFFSET 0 ++#define ATMEL_MPOP_O2_WTC_O2_WTC_SIZE 32 ++#define ATMEL_MPOP_O2_WTC_OFFSET 0 ++#define ATMEL_MPOP_O2_WTC_SIZE 32 ++#define ATMEL_MPOP_OCR 0x00000008 ++#define ATMEL_MPOP_OCR_BGR 6 ++#define ATMEL_MPOP_OCR_BGR_MASK 0x00000040 ++#define ATMEL_MPOP_OCR_BGR_OFFSET 6 ++#define ATMEL_MPOP_OCR_BGR_SIZE 1 ++#define ATMEL_MPOP_OCR_CURSOREN 0 ++#define ATMEL_MPOP_OCR_CURSOREN_MASK 0x00000001 ++#define ATMEL_MPOP_OCR_CURSOREN_OFFSET 0 ++#define ATMEL_MPOP_OCR_CURSOREN_SIZE 1 ++#define ATMEL_MPOP_OCR_O1EN 1 ++#define ATMEL_MPOP_OCR_O1EN_MASK 0x00000002 ++#define ATMEL_MPOP_OCR_O1EN_OFFSET 1 ++#define ATMEL_MPOP_OCR_O1EN_SIZE 1 ++#define ATMEL_MPOP_OCR_O2EN 2 ++#define ATMEL_MPOP_OCR_O2EN_MASK 0x00000004 ++#define ATMEL_MPOP_OCR_O2EN_OFFSET 2 ++#define ATMEL_MPOP_OCR_O2EN_SIZE 1 ++#define ATMEL_MPOP_OCR_RGBEN 3 ++#define ATMEL_MPOP_OCR_RGBEN_MASK 0x00000008 ++#define ATMEL_MPOP_OCR_RGBEN_OFFSET 3 ++#define ATMEL_MPOP_OCR_RGBEN_SIZE 1 ++#define ATMEL_MPOP_OCR_RGBFORM 5 ++#define ATMEL_MPOP_OCR_RGBFORM_MASK 0x00000020 ++#define ATMEL_MPOP_OCR_RGBFORM_OFFSET 5 ++#define ATMEL_MPOP_OCR_RGBFORM_SIZE 1 ++#define ATMEL_MPOP_OCR_RGBSRC 4 ++#define ATMEL_MPOP_OCR_RGBSRC_MASK 0x00000010 ++#define ATMEL_MPOP_OCR_RGBSRC_OFFSET 4 ++#define ATMEL_MPOP_OCR_RGBSRC_SIZE 1 ++#define ATMEL_MPOP_OUT 2 ++#define ATMEL_MPOP_OUT_BEAR 0x0000009c ++#define ATMEL_MPOP_OUT_BEAR_MASK 0xffffffff ++#define ATMEL_MPOP_OUT_BEAR_OFFSET 0 ++#define ATMEL_MPOP_OUT_BEAR_OUT_BEAR 0 ++#define ATMEL_MPOP_OUT_BEAR_OUT_BEAR_MASK 0xffffffff ++#define ATMEL_MPOP_OUT_BEAR_OUT_BEAR_OFFSET 0 ++#define ATMEL_MPOP_OUT_BEAR_OUT_BEAR_SIZE 32 ++#define ATMEL_MPOP_OUT_BEAR_SIZE 32 ++#define ATMEL_MPOP_OUT_BGR 3 ++#define ATMEL_MPOP_OUT_BGR_MASK 0x00000008 ++#define ATMEL_MPOP_OUT_BGR_OFFSET 3 ++#define ATMEL_MPOP_OUT_BGR_SIZE 1 ++#define ATMEL_MPOP_OUT_CTRL 2 ++#define ATMEL_MPOP_OUT_CTRL_MASK 0x00000004 ++#define ATMEL_MPOP_OUT_CTRL_OFFSET 2 ++#define ATMEL_MPOP_OUT_CTRL_SIZE 1 ++#define ATMEL_MPOP_OUT_MASK 0x00000004 ++#define ATMEL_MPOP_OUT_OFFSET 2 ++#define ATMEL_MPOP_OUT_SIZE 1 ++#define ATMEL_MPOP_OVERLAY 1 ++#define ATMEL_MPOP_OVERLAY_BEAR 0x00000098 ++#define ATMEL_MPOP_OVERLAY_BEAR_MASK 0xffffffff ++#define ATMEL_MPOP_OVERLAY_BEAR_OFFSET 0 ++#define ATMEL_MPOP_OVERLAY_BEAR_OVERLAY_BEAR 0 ++#define ATMEL_MPOP_OVERLAY_BEAR_OVERLAY_BEAR_MASK 0xffffffff ++#define ATMEL_MPOP_OVERLAY_BEAR_OVERLAY_BEAR_OFFSET 0 ++#define ATMEL_MPOP_OVERLAY_BEAR_OVERLAY_BEAR_SIZE 32 ++#define ATMEL_MPOP_OVERLAY_BEAR_SIZE 32 ++#define ATMEL_MPOP_OVERLAY_MASK 0x00000002 ++#define ATMEL_MPOP_OVERLAY_OFFSET 1 ++#define ATMEL_MPOP_OVERLAY_SIZE 1 ++#define ATMEL_MPOP_PALETTEDATA 0x00000400 ++#define ATMEL_MPOP_R 16 ++#define ATMEL_MPOP_R1 0 ++#define ATMEL_MPOP_R1_MASK 0x00000fff ++#define ATMEL_MPOP_R1_OFFSET 0 ++#define ATMEL_MPOP_R1_SIZE 12 ++#define ATMEL_MPOP_R2 12 ++#define ATMEL_MPOP_R2R1 0x00000014 ++#define ATMEL_MPOP_R2R1_R1 0 ++#define ATMEL_MPOP_R2R1_R1_MASK 0x00000fff ++#define ATMEL_MPOP_R2R1_R1_OFFSET 0 ++#define ATMEL_MPOP_R2R1_R1_SIZE 12 ++#define ATMEL_MPOP_R2R1_R2 12 ++#define ATMEL_MPOP_R2R1_R2_MASK 0x00fff000 ++#define ATMEL_MPOP_R2R1_R2_OFFSET 12 ++#define ATMEL_MPOP_R2R1_R2_SIZE 12 ++#define ATMEL_MPOP_R2_MASK 0x00fff000 ++#define ATMEL_MPOP_R2_OFFSET 12 ++#define ATMEL_MPOP_R2_SIZE 12 ++#define ATMEL_MPOP_R3 0 ++#define ATMEL_MPOP_R3_MASK 0x00000fff ++#define ATMEL_MPOP_R3_OFFSET 0 ++#define ATMEL_MPOP_R3_SIZE 12 ++#define ATMEL_MPOP_R4 12 ++#define ATMEL_MPOP_R4R3 0x00000018 ++#define ATMEL_MPOP_R4R3_R3 0 ++#define ATMEL_MPOP_R4R3_R3_MASK 0x00000fff ++#define ATMEL_MPOP_R4R3_R3_OFFSET 0 ++#define ATMEL_MPOP_R4R3_R3_SIZE 12 ++#define ATMEL_MPOP_R4R3_R4 12 ++#define ATMEL_MPOP_R4R3_R4_MASK 0xfffff000 ++#define ATMEL_MPOP_R4R3_R4_OFFSET 12 ++#define ATMEL_MPOP_R4R3_R4_SIZE 20 ++#define ATMEL_MPOP_R4_MASK 0xfffff000 ++#define ATMEL_MPOP_R4_OFFSET 12 ++#define ATMEL_MPOP_R4_SIZE 20 ++#define ATMEL_MPOP_RGBEN 3 ++#define ATMEL_MPOP_RGBEN_MASK 0x00000008 ++#define ATMEL_MPOP_RGBEN_OFFSET 3 ++#define ATMEL_MPOP_RGBEN_SIZE 1 ++#define ATMEL_MPOP_RGBFORM 5 ++#define ATMEL_MPOP_RGBFORM_MASK 0x00000020 ++#define ATMEL_MPOP_RGBFORM_OFFSET 5 ++#define ATMEL_MPOP_RGBFORM_SIZE 1 ++#define ATMEL_MPOP_RGBSRC 4 ++#define ATMEL_MPOP_RGBSRC_MASK 0x00000010 ++#define ATMEL_MPOP_RGBSRC_OFFSET 4 ++#define ATMEL_MPOP_RGBSRC_SIZE 1 ++#define ATMEL_MPOP_RGB_POS 0x0000004c ++#define ATMEL_MPOP_RGB_POS_RGB_POS_X 11 ++#define ATMEL_MPOP_RGB_POS_RGB_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_RGB_POS_RGB_POS_X_OFFSET 11 ++#define ATMEL_MPOP_RGB_POS_RGB_POS_X_SIZE 11 ++#define ATMEL_MPOP_RGB_POS_RGB_POS_Y 0 ++#define ATMEL_MPOP_RGB_POS_RGB_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_RGB_POS_RGB_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_RGB_POS_RGB_POS_Y_SIZE 11 ++#define ATMEL_MPOP_RGB_POS_X 11 ++#define ATMEL_MPOP_RGB_POS_X_MASK 0x003ff800 ++#define ATMEL_MPOP_RGB_POS_X_OFFSET 11 ++#define ATMEL_MPOP_RGB_POS_X_SIZE 11 ++#define ATMEL_MPOP_RGB_POS_Y 0 ++#define ATMEL_MPOP_RGB_POS_Y_MASK 0x000007ff ++#define ATMEL_MPOP_RGB_POS_Y_OFFSET 0 ++#define ATMEL_MPOP_RGB_POS_Y_SIZE 11 ++#define ATMEL_MPOP_RGB_SAR 0x0000003c ++#define ATMEL_MPOP_RGB_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_RGB_SAR_OFFSET 0 ++#define ATMEL_MPOP_RGB_SAR_RGB_SAR 0 ++#define ATMEL_MPOP_RGB_SAR_RGB_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_RGB_SAR_RGB_SAR_OFFSET 0 ++#define ATMEL_MPOP_RGB_SAR_RGB_SAR_SIZE 32 ++#define ATMEL_MPOP_RGB_SAR_SIZE 32 ++#define ATMEL_MPOP_RGB_SIZE 0x00000060 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_X 11 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_Y 0 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_RGB_SIZE_RGB_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_RGB_SIZE_X 11 ++#define ATMEL_MPOP_RGB_SIZE_X_MASK 0x003ff800 ++#define ATMEL_MPOP_RGB_SIZE_X_OFFSET 11 ++#define ATMEL_MPOP_RGB_SIZE_X_SIZE 11 ++#define ATMEL_MPOP_RGB_SIZE_Y 0 ++#define ATMEL_MPOP_RGB_SIZE_Y_MASK 0x000007ff ++#define ATMEL_MPOP_RGB_SIZE_Y_OFFSET 0 ++#define ATMEL_MPOP_RGB_SIZE_Y_SIZE 11 ++#define ATMEL_MPOP_RGB_WTC 0x00000070 ++#define ATMEL_MPOP_RGB_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_RGB_WTC_OFFSET 0 ++#define ATMEL_MPOP_RGB_WTC_RGB_WTC 0 ++#define ATMEL_MPOP_RGB_WTC_RGB_WTC_MASK 0xffffffff ++#define ATMEL_MPOP_RGB_WTC_RGB_WTC_OFFSET 0 ++#define ATMEL_MPOP_RGB_WTC_RGB_WTC_SIZE 32 ++#define ATMEL_MPOP_RGB_WTC_SIZE 32 ++#define ATMEL_MPOP_R_MASK 0x00ff0000 ++#define ATMEL_MPOP_R_OFFSET 16 ++#define ATMEL_MPOP_R_SIZE 8 ++#define ATMEL_MPOP_SOP 4 ++#define ATMEL_MPOP_SOP_MASK 0x00000010 ++#define ATMEL_MPOP_SOP_OFFSET 4 ++#define ATMEL_MPOP_SOP_SIZE 1 ++#define ATMEL_MPOP_START 1 ++#define ATMEL_MPOP_START_MASK 0x00000002 ++#define ATMEL_MPOP_START_OFFSET 1 ++#define ATMEL_MPOP_START_SIZE 1 ++#define ATMEL_MPOP_STRIDE 0x0000002c ++#define ATMEL_MPOP_STRIDE_MASK 0xffffffff ++#define ATMEL_MPOP_STRIDE_OFFSET 0 ++#define ATMEL_MPOP_STRIDE_SIZE 32 ++#define ATMEL_MPOP_STRIDE_STRIDE 0 ++#define ATMEL_MPOP_STRIDE_STRIDE_MASK 0xffffffff ++#define ATMEL_MPOP_STRIDE_STRIDE_OFFSET 0 ++#define ATMEL_MPOP_STRIDE_STRIDE_SIZE 32 ++#define ATMEL_MPOP_U_SAR 0x00000034 ++#define ATMEL_MPOP_U_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_U_SAR_OFFSET 0 ++#define ATMEL_MPOP_U_SAR_SIZE 32 ++#define ATMEL_MPOP_U_SAR_U_SAR 0 ++#define ATMEL_MPOP_U_SAR_U_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_U_SAR_U_SAR_OFFSET 0 ++#define ATMEL_MPOP_U_SAR_U_SAR_SIZE 32 ++#define ATMEL_MPOP_VISIBLE 24 ++#define ATMEL_MPOP_VISIBLE_MASK 0x01000000 ++#define ATMEL_MPOP_VISIBLE_OFFSET 24 ++#define ATMEL_MPOP_VISIBLE_SIZE 1 ++#define ATMEL_MPOP_V_SAR 0x00000038 ++#define ATMEL_MPOP_V_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_V_SAR_OFFSET 0 ++#define ATMEL_MPOP_V_SAR_SIZE 32 ++#define ATMEL_MPOP_V_SAR_V_SAR 0 ++#define ATMEL_MPOP_V_SAR_V_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_V_SAR_V_SAR_OFFSET 0 ++#define ATMEL_MPOP_V_SAR_V_SAR_SIZE 32 ++#define ATMEL_MPOP_XRESIZE 16 ++#define ATMEL_MPOP_XRESIZE_MASK 0x00ff0000 ++#define ATMEL_MPOP_XRESIZE_OFFSET 16 ++#define ATMEL_MPOP_XRESIZE_SIZE 8 ++#define ATMEL_MPOP_YCR 0x00000004 ++#define ATMEL_MPOP_YCR_XRESIZE 16 ++#define ATMEL_MPOP_YCR_XRESIZE_MASK 0x00ff0000 ++#define ATMEL_MPOP_YCR_XRESIZE_OFFSET 16 ++#define ATMEL_MPOP_YCR_XRESIZE_SIZE 8 ++#define ATMEL_MPOP_YCR_YRESIZE 8 ++#define ATMEL_MPOP_YCR_YRESIZE_MASK 0x0000ff00 ++#define ATMEL_MPOP_YCR_YRESIZE_OFFSET 8 ++#define ATMEL_MPOP_YCR_YRESIZE_SIZE 8 ++#define ATMEL_MPOP_YCR_YUVFORMAT 0 ++#define ATMEL_MPOP_YCR_YUVFORMAT_MASK 0x00000003 ++#define ATMEL_MPOP_YCR_YUVFORMAT_OFFSET 0 ++#define ATMEL_MPOP_YCR_YUVFORMAT_SIZE 2 ++#define ATMEL_MPOP_YCR_YUVFORMAT_YUVFORMAT_420 0x00000002 ++#define ATMEL_MPOP_YCR_YUVFORMAT_YUVFORMAT_422 0x00000001 ++#define ATMEL_MPOP_YCR_YUVFORMAT_YUVFORMAT_444 0x00000000 ++#define ATMEL_MPOP_YRESIZE 8 ++#define ATMEL_MPOP_YRESIZE_MASK 0x0000ff00 ++#define ATMEL_MPOP_YRESIZE_OFFSET 8 ++#define ATMEL_MPOP_YRESIZE_SIZE 8 ++#define ATMEL_MPOP_YUV 0 ++#define ATMEL_MPOP_YUVFORMAT 0 ++#define ATMEL_MPOP_YUVFORMAT_420 0x00000002 ++#define ATMEL_MPOP_YUVFORMAT_422 0x00000001 ++#define ATMEL_MPOP_YUVFORMAT_444 0x00000000 ++#define ATMEL_MPOP_YUVFORMAT_MASK 0x00000003 ++#define ATMEL_MPOP_YUVFORMAT_OFFSET 0 ++#define ATMEL_MPOP_YUVFORMAT_SIZE 2 ++#define ATMEL_MPOP_YUVFORMAT_YUVFORMAT_420 0x00000002 ++#define ATMEL_MPOP_YUVFORMAT_YUVFORMAT_422 0x00000001 ++#define ATMEL_MPOP_YUVFORMAT_YUVFORMAT_444 0x00000000 ++#define ATMEL_MPOP_YUV_BEAR 0x00000094 ++#define ATMEL_MPOP_YUV_BEAR_MASK 0xffffffff ++#define ATMEL_MPOP_YUV_BEAR_OFFSET 0 ++#define ATMEL_MPOP_YUV_BEAR_SIZE 32 ++#define ATMEL_MPOP_YUV_BEAR_YUV_BEAR 0 ++#define ATMEL_MPOP_YUV_BEAR_YUV_BEAR_MASK 0xffffffff ++#define ATMEL_MPOP_YUV_BEAR_YUV_BEAR_OFFSET 0 ++#define ATMEL_MPOP_YUV_BEAR_YUV_BEAR_SIZE 32 ++#define ATMEL_MPOP_YUV_MASK 0x00000001 ++#define ATMEL_MPOP_YUV_MAX_COORD 0x0000005c ++#define ATMEL_MPOP_YUV_MAX_COORD_X 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_X_MASK 0x003ff800 ++#define ATMEL_MPOP_YUV_MAX_COORD_X_OFFSET 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_X_SIZE 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_Y 0 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_X 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_X_MASK 0x003ff800 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_X_OFFSET 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_X_SIZE 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_Y 0 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_Y_MASK 0x000007ff ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_Y_OFFSET 0 ++#define ATMEL_MPOP_YUV_MAX_COORD_YUV_MAX_COORD_Y_SIZE 11 ++#define ATMEL_MPOP_YUV_MAX_COORD_Y_MASK 0x000007ff ++#define ATMEL_MPOP_YUV_MAX_COORD_Y_OFFSET 0 ++#define ATMEL_MPOP_YUV_MAX_COORD_Y_SIZE 11 ++#define ATMEL_MPOP_YUV_OFFSET 0 ++#define ATMEL_MPOP_YUV_SIZE 1 ++#define ATMEL_MPOP_Y_SAR 0x00000030 ++#define ATMEL_MPOP_Y_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_Y_SAR_OFFSET 0 ++#define ATMEL_MPOP_Y_SAR_SIZE 32 ++#define ATMEL_MPOP_Y_SAR_Y_SAR 0 ++#define ATMEL_MPOP_Y_SAR_Y_SAR_MASK 0xffffffff ++#define ATMEL_MPOP_Y_SAR_Y_SAR_OFFSET 0 ++#define ATMEL_MPOP_Y_SAR_Y_SAR_SIZE 32 ++ ++#endif /* __ATMEL_MPOP_H__ */ +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/clock.c linux-2.6.28.2/arch/avr32/mach-at32ap/clock.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/clock.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/clock.c 2009-01-29 10:16:11.000000000 +0100 +@@ -178,7 +178,11 @@ + #include <linux/io.h> + #include <linux/debugfs.h> + #include <linux/seq_file.h> +-#include "pm.h" ++#if defined(CONFIG_CPU_AT32AP700X) ++# include "pm-v1.h" ++#elif defined(CONFIG_CPU_AT32AP720X) ++# include "pm-v3.h" ++#endif + + + #define NEST_DELTA 2 +@@ -234,19 +238,40 @@ + struct clk *clk; + + /* show all the power manager registers */ +- seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL)); +- seq_printf(s, "CKSEL = %8x\n", pm_readl(CKSEL)); +- seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPU_MASK)); +- seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSB_MASK)); +- seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBA_MASK)); +- seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBB_MASK)); +- seq_printf(s, "PLL0 = %8x\n", pm_readl(PLL0)); +- seq_printf(s, "PLL1 = %8x\n", pm_readl(PLL1)); +- seq_printf(s, "IMR = %8x\n", pm_readl(IMR)); ++ seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL)); ++ seq_printf(s, "CKSEL = %8x\n", pm_readl(CKSEL)); ++#ifdef CONFIG_CPU_AT32AP700X ++ seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPU_MASK)); ++ seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSB_MASK)); ++ seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBA_MASK)); ++ seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBB_MASK)); ++ seq_printf(s, "PLL0 = %8x\n", pm_readl(PLL0)); ++ seq_printf(s, "PLL1 = %8x\n", pm_readl(PLL1)); ++#else ++ seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPUMASK)); ++ seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSBMASK)); ++ seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBAMASK)); ++ seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBBMASK)); ++ seq_printf(s, "PBADIVMASK = %8x\n", pm_readl(PBADIVMASK)); ++ seq_printf(s, "PBBDIVMASK = %8x\n", pm_readl(PBBDIVMASK)); ++ seq_printf(s, "PLL0 = %8x\n", pm_readl(PLL[0])); ++ seq_printf(s, "PLL1 = %8x\n", pm_readl(PLL[1])); ++ seq_printf(s, "PLL2 = %8x\n", pm_readl(PLL[2])); ++ seq_printf(s, "OSCCTRL0 = %8x\n", pm_readl(OSCCTRL[0])); ++ seq_printf(s, "OSCCTRL1 = %8x\n", pm_readl(OSCCTRL[1])); ++ seq_printf(s, "OSCCTRL2 = %8x\n", pm_readl(OSCCTRL[2])); ++ seq_printf(s, "POSCSR = %8x\n", pm_readl(POSCSR)); ++ seq_printf(s, "PPCR = %8x\n", pm_readl(PPCR)); ++#endif ++ seq_printf(s, "IMR = %8x\n", pm_readl(IMR)); + for (i = 0; i < 8; i++) { + if (i == 5) + continue; +- seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i))); ++#ifdef CONFIG_CPU_AT32AP700X ++ seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i))); ++#else ++ seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL[i])); ++#endif + } + + seq_printf(s, "\n"); +@@ -269,6 +294,16 @@ + dump_clock(clk, &r); + clk_put(clk); + ++#ifdef CONFIG_CPU_AT32AP720X ++ clk = clk_get(NULL, "osc2"); ++ dump_clock(clk, &r); ++ clk_put(clk); ++ ++ clk = clk_get(NULL, "rcosc"); ++ dump_clock(clk, &r); ++ clk_put(clk); ++#endif ++ + spin_unlock(&clk_list_lock); + + return 0; + diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-201-avr32-atmel_mpopfb-disable-debug.patch b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-201-avr32-atmel_mpopfb-disable-debug.patch new file mode 100644 index 000000000..6cc4b679a --- /dev/null +++ b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-201-avr32-atmel_mpopfb-disable-debug.patch @@ -0,0 +1,23 @@ +From f26e2224d46430ac4f6c0ddeb518f5766ba62b16 Mon Sep 17 00:00:00 2001 +From: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> +Date: Wed, 26 Nov 2008 14:10:45 +0100 +Subject: [PATCH 2/3] atmel_mpopfb: remove define DEBUG to disable debug output + +Signed-off-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> + +diff --git a/drivers/video/atmel_mpopfb.c b/drivers/video/atmel_mpopfb.c +index 0a07f7b..3b4b668 100644 +--- a/drivers/video/atmel_mpopfb.c ++++ b/drivers/video/atmel_mpopfb.c +@@ -8,8 +8,6 @@ + * more details. + */ + +-#define DEBUG +- + #include <linux/clk.h> + #include <linux/delay.h> + #include <linux/dma-mapping.h> +-- +1.5.6.3 + diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-202-avr32-atmel_mpopfb-add-signal-to-disable-line-caching.patch b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-202-avr32-atmel_mpopfb-add-signal-to-disable-line-caching.patch new file mode 100644 index 000000000..2163c92c7 --- /dev/null +++ b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-202-avr32-atmel_mpopfb-add-signal-to-disable-line-caching.patch @@ -0,0 +1,43 @@ +diff -urN linux-2.6.28.2-0rig//drivers/video/atmel_mpopfb.c linux-2.6.28.2/drivers/video/atmel_mpopfb.c +--- linux-2.6.28.2-0rig//drivers/video/atmel_mpopfb.c 2009-01-29 09:41:04.000000000 +0100 ++++ linux-2.6.28.2/drivers/video/atmel_mpopfb.c 2009-01-29 09:43:46.000000000 +0100 +@@ -315,6 +315,10 @@ + static void atmel_mpopfb_start(struct atmel_mpopfb_info *sinfo) + { + if (!sinfo->running) { ++ unsigned int line_cache_disable = ++ sinfo->baseimg_info.line_cache_disable ? ++ ATMEL_MPOP_CR_CACHEDIS_MASK : 0; ++ + dev_dbg(sinfo->info->device, " * Starting MPOP.\n"); + + /* Enable all error interrupts. */ +@@ -325,9 +329,9 @@ + * reading from the slave interface it will start + * generating a frame. + */ +- mpop_writel(sinfo, ATMEL_MPOP_CR, +- ATMEL_MPOP_CR_EN_MASK +- /*| ATMEL_MPOP_CR_OUT_BGR_MASK */ ); ++ mpop_writel(sinfo, ATMEL_MPOP_CR, ATMEL_MPOP_CR_EN_MASK ++ | line_cache_disable ++ | ATMEL_MPOP_CR_OUT_BGR_MASK); + + sinfo->running = 1; + } +diff -urN linux-2.6.28.2-0rig//include/linux/atmel_mpopfb.h linux-2.6.28.2/include/linux/atmel_mpopfb.h +--- linux-2.6.28.2-0rig//include/linux/atmel_mpopfb.h 2009-01-29 09:41:04.000000000 +0100 ++++ linux-2.6.28.2/include/linux/atmel_mpopfb.h 2009-01-29 09:43:46.000000000 +0100 +@@ -42,9 +42,11 @@ + unsigned xsize; + unsigned ysize; + +- /* Signal that we should flip the video. */ ++ /* Signal for flipping the video. */ + int flip; + ++ /* Signal for disabling the line cache. */ ++ int line_cache_disable; + }; + + enum atmel_mpopfb_overlay_type { diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-203-avr32-fix-arch-header-byteorder.patch b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-203-avr32-fix-arch-header-byteorder.patch new file mode 100644 index 000000000..ac990f9cd --- /dev/null +++ b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-203-avr32-fix-arch-header-byteorder.patch @@ -0,0 +1,35 @@ +Index: linux-2.6.27.6/arch/avr32/include/asm/byteorder.h +=================================================================== +--- linux-2.6.27.6.orig/arch/avr32/include/asm/byteorder.h 2008-11-28 16:47:15.000000000 +0100 ++++ linux-2.6.27.6/arch/avr32/include/asm/byteorder.h 2008-11-28 16:47:31.000000000 +0100 +@@ -7,8 +7,9 @@ + #include <asm/types.h> + #include <linux/compiler.h> + +-#define __BIG_ENDIAN ++#define __BIG_ENDIAN 4321 + #define __SWAB_64_THRU_32__ ++#define __BYTEORDER_HAS_U64__ + + #ifdef __CHECKER__ + extern unsigned long __builtin_bswap_32(unsigned long x); +@@ -33,5 +34,5 @@ + #define __arch_swab32 __arch_swab32 + #endif + +-#include <linux/byteorder.h> ++#include <linux/byteorder/big_endian.h> + #endif /* __ASM_AVR32_BYTEORDER_H */ +Index: linux-2.6.27.6/arch/avr32/mach-at32ap/include/mach/io.h +=================================================================== +--- linux-2.6.27.6.orig/arch/avr32/mach-at32ap/include/mach/io.h 2008-11-28 16:47:58.000000000 +0100 ++++ linux-2.6.27.6/arch/avr32/mach-at32ap/include/mach/io.h 2008-11-28 16:48:15.000000000 +0100 +@@ -1,7 +1,7 @@ + #ifndef __ASM_AVR32_ARCH_AT32AP_IO_H + #define __ASM_AVR32_ARCH_AT32AP_IO_H + +-#include <linux/swab.h> ++#include <linux/byteorder/swabb.h> + + #if defined(CONFIG_AP700X_32_BIT_SMC) + # define __swizzle_addr_b(addr) (addr ^ 3UL) diff --git a/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-204-avr32-ap700x-fix-det_pin-for-nand-flash.patch b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-204-avr32-ap700x-fix-det_pin-for-nand-flash.patch new file mode 100644 index 000000000..05522da5b --- /dev/null +++ b/target/device/Atmel/arch-avr32/kernel-patches-2.6.28.2/linux-2.6.28.2-204-avr32-ap700x-fix-det_pin-for-nand-flash.patch @@ -0,0 +1,33 @@ +diff -urN linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/atstk1002.c linux-2.6.28.2/arch/avr32/boards/atstk1000/atstk1002.c +--- linux-2.6.28.2-0rig//arch/avr32/boards/atstk1000/atstk1002.c 2009-01-29 08:39:35.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/boards/atstk1000/atstk1002.c 2009-01-29 09:50:56.000000000 +0100 +@@ -99,6 +99,7 @@ + static struct atmel_nand_data atstk1006_nand_data __initdata = { + .cle = 21, + .ale = 22, ++ .det_pin = GPIO_PIN_NONE, + .rdy_pin = GPIO_PIN_PB(30), + .enable_pin = GPIO_PIN_PB(29), + .partition_info = nand_part_info, +diff -urN linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/at32ap700x.c linux-2.6.28.2/arch/avr32/mach-at32ap/at32ap700x.c +--- linux-2.6.28.2-0rig//arch/avr32/mach-at32ap/at32ap700x.c 2009-01-29 09:41:04.000000000 +0100 ++++ linux-2.6.28.2/arch/avr32/mach-at32ap/at32ap700x.c 2009-01-29 09:50:56.000000000 +0100 +@@ -1972,13 +1972,14 @@ + goto fail; + + hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_NAND_ENABLE); +- if (data->enable_pin) ++ ++ if (gpio_is_valid(data->enable_pin)) + at32_select_gpio(data->enable_pin, + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); +- if (data->rdy_pin) +- at32_select_gpio(data->rdy_pin, 0); +- if (data->det_pin) ++ if (gpio_is_valid(data->det_pin)) + at32_select_gpio(data->det_pin, 0); ++ if (gpio_is_valid(data->rdy_pin)) ++ at32_select_gpio(data->rdy_pin, 0); + + platform_device_add(pdev); + return pdev; |