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;